1 diff -uprN linux-2.6.27./fs/afs/dir.c linux-2.6.27/fs/afs/dir.c
2 --- linux-2.6.27./fs/afs/dir.c 2008-10-10 00:13:53.000000000 +0200
3 +++ linux-2.6.27/fs/afs/dir.c 2008-10-29 02:02:01.686215981 +0100
4 @@ -45,6 +45,7 @@ const struct file_operations afs_dir_fil
5 .release = afs_release,
6 .readdir = afs_readdir,
8 + .fsetattr = afs_fsetattr,
11 const struct inode_operations afs_dir_inode_operations = {
12 diff -uprN linux-2.6.27./fs/afs/file.c linux-2.6.27/fs/afs/file.c
13 --- linux-2.6.27./fs/afs/file.c 2008-10-10 00:13:53.000000000 +0200
14 +++ linux-2.6.27/fs/afs/file.c 2008-10-29 02:02:01.718012026 +0100
15 @@ -36,6 +36,7 @@ const struct file_operations afs_file_op
19 + .fsetattr = afs_fsetattr,
22 const struct inode_operations afs_file_inode_operations = {
23 diff -uprN linux-2.6.27./fs/afs/inode.c linux-2.6.27/fs/afs/inode.c
24 --- linux-2.6.27./fs/afs/inode.c 2008-10-10 00:13:53.000000000 +0200
25 +++ linux-2.6.27/fs/afs/inode.c 2008-10-29 02:02:01.732673766 +0100
26 @@ -358,7 +358,8 @@ void afs_clear_inode(struct inode *inode
28 * set the attributes of an inode
30 -int afs_setattr(struct dentry *dentry, struct iattr *attr)
31 +static int afs_do_setattr(struct dentry *dentry, struct iattr *attr,
34 struct afs_vnode *vnode = AFS_FS_I(dentry->d_inode);
36 @@ -380,8 +381,8 @@ int afs_setattr(struct dentry *dentry, s
37 afs_writeback_all(vnode);
40 - if (attr->ia_valid & ATTR_FILE) {
41 - key = attr->ia_file->private_data;
43 + key = file->private_data;
45 key = afs_request_key(vnode->volume->cell);
47 @@ -391,10 +392,20 @@ int afs_setattr(struct dentry *dentry, s
50 ret = afs_vnode_setattr(vnode, key, attr);
51 - if (!(attr->ia_valid & ATTR_FILE))
60 +int afs_setattr(struct dentry *dentry, struct iattr *attr)
62 + return afs_do_setattr(dentry, attr, NULL);
65 +int afs_fsetattr(struct file *file, struct iattr *attr)
67 + return afs_do_setattr(file->f_path.dentry, attr, file);
69 diff -uprN linux-2.6.27./fs/afs/internal.h linux-2.6.27/fs/afs/internal.h
70 --- linux-2.6.27./fs/afs/internal.h 2008-10-10 00:13:53.000000000 +0200
71 +++ linux-2.6.27/fs/afs/internal.h 2008-10-29 02:02:01.752698408 +0100
72 @@ -548,6 +548,7 @@ extern void afs_zap_data(struct afs_vnod
73 extern int afs_validate(struct afs_vnode *, struct key *);
74 extern int afs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
75 extern int afs_setattr(struct dentry *, struct iattr *);
76 +extern int afs_fsetattr(struct file *, struct iattr *);
77 extern void afs_clear_inode(struct inode *);
80 diff -uprN linux-2.6.27./fs/attr.c linux-2.6.27/fs/attr.c
81 --- linux-2.6.27./fs/attr.c 2008-10-10 00:13:53.000000000 +0200
82 +++ linux-2.6.27/fs/attr.c 2008-10-29 02:02:01.899339282 +0100
83 @@ -100,7 +100,8 @@ int inode_setattr(struct inode * inode,
85 EXPORT_SYMBOL(inode_setattr);
87 -int notify_change(struct dentry * dentry, struct iattr * attr)
88 +int fnotify_change(struct dentry *dentry, struct vfsmount *mnt,
89 + struct iattr *attr, struct file *file)
91 struct inode *inode = dentry->d_inode;
92 mode_t mode = inode->i_mode;
93 @@ -163,13 +164,28 @@ int notify_change(struct dentry * dentry
94 down_write(&dentry->d_inode->i_alloc_sem);
96 if (inode->i_op && inode->i_op->setattr) {
97 - error = security_inode_setattr(dentry, attr);
99 - error = inode->i_op->setattr(dentry, attr);
100 + error = security_inode_setattr(dentry, mnt, attr);
102 + if (file && file->f_op && file->f_op->fsetattr)
103 + error = file->f_op->fsetattr(file, attr);
105 + /* External file system still expect to be
106 + * passed a file pointer via ia_file and
107 + * have it announced via ATTR_FILE. This
108 + * just makes it so they don't need to
109 + * change their API just for us. External
110 + * callers will have set these themselves. */
112 + attr->ia_valid |= ATTR_FILE;
113 + attr->ia_file = file;
115 + error = inode->i_op->setattr(dentry, attr);
119 error = inode_change_ok(inode, attr);
121 - error = security_inode_setattr(dentry, attr);
122 + error = security_inode_setattr(dentry, mnt, attr);
124 if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) ||
125 (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid))
126 @@ -187,5 +203,12 @@ int notify_change(struct dentry * dentry
130 +EXPORT_SYMBOL_GPL(fnotify_change);
132 +int notify_change(struct dentry *dentry, struct vfsmount *mnt,
133 + struct iattr *attr)
135 + return fnotify_change(dentry, mnt, attr, NULL);
138 EXPORT_SYMBOL(notify_change);
139 diff -uprN linux-2.6.27./fs/dcache.c linux-2.6.27/fs/dcache.c
140 --- linux-2.6.27./fs/dcache.c 2008-10-10 00:13:53.000000000 +0200
141 +++ linux-2.6.27/fs/dcache.c 2008-10-29 02:02:01.602672110 +0100
142 @@ -1897,44 +1897,46 @@ static int prepend_name(char **buffer, i
143 * @root: root vfsmnt/dentry (may be modified by this function)
144 * @buffer: buffer to return value in
145 * @buflen: buffer length
146 + * @flags: flags controling behavior of d_path
148 - * Convert a dentry into an ASCII path name. If the entry has been deleted
149 - * the string " (deleted)" is appended. Note that this is ambiguous.
151 - * Returns the buffer or an error code if the path was too long.
153 - * "buflen" should be positive. Caller holds the dcache_lock.
154 + * Convert a dentry into an ASCII path name. If the entry has been deleted,
155 + * then if @flags has D_PATH_FAIL_DELETED set, ERR_PTR(-ENOENT) is returned.
156 + * Otherwise, the string " (deleted)" is appended. Note that this is ambiguous.
158 * If path is not reachable from the supplied root, then the value of
159 - * root is changed (without modifying refcounts).
160 + * root is changed (without modifying refcounts). The path returned in this
161 + * case will be relative (i.e., it will not start with a slash).
163 + * Returns the buffer or an error code if the path was too long.
165 char *__d_path(const struct path *path, struct path *root,
166 - char *buffer, int buflen)
167 + char *buffer, int buflen, int flags)
169 struct dentry *dentry = path->dentry;
170 struct vfsmount *vfsmnt = path->mnt;
171 - char *end = buffer + buflen;
173 + const unsigned char *name;
177 + prepend(&buffer, &buflen, "\0", 1);
179 spin_lock(&vfsmount_lock);
180 - prepend(&end, &buflen, "\0", 1);
181 - if (!IS_ROOT(dentry) && d_unhashed(dentry) &&
182 - (prepend(&end, &buflen, " (deleted)", 10) != 0))
183 + spin_lock(&dcache_lock);
184 + if (!IS_ROOT(dentry) && d_unhashed(dentry)) {
185 + if (flags & D_PATH_FAIL_DELETED) {
186 + buffer = ERR_PTR(-ENOENT);
189 + if (prepend(&buffer, &buflen, " (deleted)", 10) != 0)
195 - /* Get '/' right */
200 + while (dentry != root->dentry || vfsmnt != root->mnt) {
201 struct dentry * parent;
203 - if (dentry == root->dentry && vfsmnt == root->mnt)
205 if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
207 if (vfsmnt->mnt_parent == vfsmnt) {
210 @@ -1944,27 +1946,51 @@ char *__d_path(const struct path *path,
212 parent = dentry->d_parent;
214 - if ((prepend_name(&end, &buflen, &dentry->d_name) != 0) ||
215 - (prepend(&end, &buflen, "/", 1) != 0))
216 + if ((prepend_name(&buffer, &buflen, &dentry->d_name) != 0) ||
217 + (prepend(&buffer, &buflen, "/", 1) != 0))
222 + /* Get '/' right. */
223 + if (*buffer != '/' && prepend(&buffer, &buflen, "/", 1))
227 + spin_unlock(&dcache_lock);
228 spin_unlock(&vfsmount_lock);
233 - retval += 1; /* hit the slash */
234 - if (prepend_name(&retval, &buflen, &dentry->d_name) != 0)
236 + * We went past the (vfsmount, dentry) we were looking for and have
237 + * either hit a root dentry, a lazily unmounted dentry, an
238 + * unconnected dentry, or the file is on a pseudo filesystem.
240 + namelen = dentry->d_name.len;
241 + name = dentry->d_name.name;
244 + * If this is a root dentry, then overwrite the slash. This
245 + * will also DTRT with pseudo filesystems which have root
246 + * dentries named "foo:".
248 + if (IS_ROOT(dentry) && *buffer == '/') {
252 + if ((flags & D_PATH_DISCONNECT) && *name == '/') {
253 + /* Make sure we won't return a pathname starting with '/' */
257 + if (prepend(&buffer, &buflen, name, namelen))
260 root->dentry = dentry;
264 - retval = ERR_PTR(-ENAMETOOLONG);
265 + buffer = ERR_PTR(-ENAMETOOLONG);
269 @@ -2001,10 +2027,8 @@ char *d_path(const struct path *path, ch
270 root = current->fs->root;
272 read_unlock(¤t->fs->lock);
273 - spin_lock(&dcache_lock);
275 - res = __d_path(path, &tmp, buf, buflen);
276 - spin_unlock(&dcache_lock);
277 + res = __d_path(path, &tmp, buf, buflen, 0);
281 @@ -2087,9 +2111,9 @@ Elong:
283 asmlinkage long sys_getcwd(char __user *buf, unsigned long size)
286 - struct path pwd, root;
287 - char *page = (char *) __get_free_page(GFP_USER);
289 + struct path pwd, root, tmp;
290 + char *page = (char *) __get_free_page(GFP_USER), *cwd;
294 @@ -2101,30 +2125,20 @@ asmlinkage long sys_getcwd(char __user *
296 read_unlock(¤t->fs->lock);
299 - /* Has the current directory has been unlinked? */
300 - spin_lock(&dcache_lock);
301 - if (IS_ROOT(pwd.dentry) || !d_unhashed(pwd.dentry)) {
303 - struct path tmp = root;
306 - cwd = __d_path(&pwd, &tmp, page, PAGE_SIZE);
307 - spin_unlock(&dcache_lock);
310 + cwd = __d_path(&pwd, &tmp, page, PAGE_SIZE, D_PATH_FAIL_DELETED);
312 error = PTR_ERR(cwd);
319 - len = PAGE_SIZE + page - cwd;
322 - if (copy_to_user(buf, cwd, len))
326 - spin_unlock(&dcache_lock);
328 + len = PAGE_SIZE + page - cwd;
331 + if (copy_to_user(buf, cwd, len))
337 diff -uprN linux-2.6.27./fs/ecryptfs/inode.c linux-2.6.27/fs/ecryptfs/inode.c
338 --- linux-2.6.27./fs/ecryptfs/inode.c 2008-10-10 00:13:53.000000000 +0200
339 +++ linux-2.6.27/fs/ecryptfs/inode.c 2008-10-29 02:02:00.779549727 +0100
340 @@ -403,19 +403,24 @@ static int ecryptfs_link(struct dentry *
341 struct dentry *new_dentry)
343 struct dentry *lower_old_dentry;
344 + struct vfsmount *lower_old_mnt;
345 struct dentry *lower_new_dentry;
346 + struct vfsmount *lower_new_mnt;
347 struct dentry *lower_dir_dentry;
351 file_size_save = i_size_read(old_dentry->d_inode);
352 lower_old_dentry = ecryptfs_dentry_to_lower(old_dentry);
353 + lower_old_mnt = ecryptfs_dentry_to_lower_mnt(old_dentry);
354 lower_new_dentry = ecryptfs_dentry_to_lower(new_dentry);
355 + lower_new_mnt = ecryptfs_dentry_to_lower_mnt(new_dentry);
356 dget(lower_old_dentry);
357 dget(lower_new_dentry);
358 lower_dir_dentry = lock_parent(lower_new_dentry);
359 - rc = vfs_link(lower_old_dentry, lower_dir_dentry->d_inode,
361 + rc = vfs_link(lower_old_dentry, lower_old_mnt,
362 + lower_dir_dentry->d_inode, lower_new_dentry,
364 if (rc || !lower_new_dentry->d_inode)
366 rc = ecryptfs_interpose(lower_new_dentry, new_dentry, dir->i_sb, 0);
367 @@ -440,11 +445,12 @@ static int ecryptfs_unlink(struct inode
370 struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
371 + struct vfsmount *lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
372 struct inode *lower_dir_inode = ecryptfs_inode_to_lower(dir);
373 struct dentry *lower_dir_dentry;
375 lower_dir_dentry = lock_parent(lower_dentry);
376 - rc = vfs_unlink(lower_dir_inode, lower_dentry);
377 + rc = vfs_unlink(lower_dir_inode, lower_dentry, lower_mnt);
379 printk(KERN_ERR "Error in vfs_unlink; rc = [%d]\n", rc);
381 @@ -464,6 +470,7 @@ static int ecryptfs_symlink(struct inode
384 struct dentry *lower_dentry;
385 + struct vfsmount *lower_mnt;
386 struct dentry *lower_dir_dentry;
387 char *encoded_symname;
389 @@ -471,6 +478,7 @@ static int ecryptfs_symlink(struct inode
391 lower_dentry = ecryptfs_dentry_to_lower(dentry);
393 + lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
394 lower_dir_dentry = lock_parent(lower_dentry);
395 encoded_symlen = ecryptfs_encode_filename(crypt_stat, symname,
397 @@ -479,7 +487,7 @@ static int ecryptfs_symlink(struct inode
401 - rc = vfs_symlink(lower_dir_dentry->d_inode, lower_dentry,
402 + rc = vfs_symlink(lower_dir_dentry->d_inode, lower_dentry, lower_mnt,
404 kfree(encoded_symname);
405 if (rc || !lower_dentry->d_inode)
406 @@ -501,11 +509,14 @@ static int ecryptfs_mkdir(struct inode *
409 struct dentry *lower_dentry;
410 + struct vfsmount *lower_mnt;
411 struct dentry *lower_dir_dentry;
413 lower_dentry = ecryptfs_dentry_to_lower(dentry);
414 + lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
415 lower_dir_dentry = lock_parent(lower_dentry);
416 - rc = vfs_mkdir(lower_dir_dentry->d_inode, lower_dentry, mode);
417 + rc = vfs_mkdir(lower_dir_dentry->d_inode, lower_dentry, lower_mnt,
419 if (rc || !lower_dentry->d_inode)
421 rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb, 0);
422 @@ -524,14 +535,16 @@ out:
423 static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry)
425 struct dentry *lower_dentry;
426 + struct vfsmount *lower_mnt;
427 struct dentry *lower_dir_dentry;
430 lower_dentry = ecryptfs_dentry_to_lower(dentry);
431 + lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
433 lower_dir_dentry = lock_parent(lower_dentry);
435 - rc = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry);
436 + rc = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry, lower_mnt);
439 d_delete(lower_dentry);
440 @@ -549,11 +562,14 @@ ecryptfs_mknod(struct inode *dir, struct
443 struct dentry *lower_dentry;
444 + struct vfsmount *lower_mnt;
445 struct dentry *lower_dir_dentry;
447 lower_dentry = ecryptfs_dentry_to_lower(dentry);
448 + lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
449 lower_dir_dentry = lock_parent(lower_dentry);
450 - rc = vfs_mknod(lower_dir_dentry->d_inode, lower_dentry, mode, dev);
451 + rc = vfs_mknod(lower_dir_dentry->d_inode, lower_dentry, lower_mnt, mode,
453 if (rc || !lower_dentry->d_inode)
455 rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb, 0);
456 @@ -574,19 +590,24 @@ ecryptfs_rename(struct inode *old_dir, s
459 struct dentry *lower_old_dentry;
460 + struct vfsmount *lower_old_mnt;
461 struct dentry *lower_new_dentry;
462 + struct vfsmount *lower_new_mnt;
463 struct dentry *lower_old_dir_dentry;
464 struct dentry *lower_new_dir_dentry;
466 lower_old_dentry = ecryptfs_dentry_to_lower(old_dentry);
467 + lower_old_mnt = ecryptfs_dentry_to_lower_mnt(old_dentry);
468 lower_new_dentry = ecryptfs_dentry_to_lower(new_dentry);
469 + lower_new_mnt = ecryptfs_dentry_to_lower_mnt(new_dentry);
470 dget(lower_old_dentry);
471 dget(lower_new_dentry);
472 lower_old_dir_dentry = dget_parent(lower_old_dentry);
473 lower_new_dir_dentry = dget_parent(lower_new_dentry);
474 lock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
475 rc = vfs_rename(lower_old_dir_dentry->d_inode, lower_old_dentry,
476 - lower_new_dir_dentry->d_inode, lower_new_dentry);
477 + lower_old_mnt, lower_new_dir_dentry->d_inode,
478 + lower_new_dentry, lower_new_mnt);
481 fsstack_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode, NULL);
482 @@ -849,6 +870,7 @@ static int ecryptfs_setattr(struct dentr
485 struct dentry *lower_dentry;
486 + struct vfsmount *lower_mnt;
488 struct inode *lower_inode;
489 struct ecryptfs_crypt_stat *crypt_stat;
490 @@ -859,6 +881,7 @@ static int ecryptfs_setattr(struct dentr
491 inode = dentry->d_inode;
492 lower_inode = ecryptfs_inode_to_lower(inode);
493 lower_dentry = ecryptfs_dentry_to_lower(dentry);
494 + lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
495 mutex_lock(&crypt_stat->cs_mutex);
496 if (S_ISDIR(dentry->d_inode->i_mode))
497 crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
498 @@ -910,7 +933,7 @@ static int ecryptfs_setattr(struct dentr
499 ia->ia_valid &= ~ATTR_MODE;
501 mutex_lock(&lower_dentry->d_inode->i_mutex);
502 - rc = notify_change(lower_dentry, ia);
503 + rc = notify_change(lower_dentry, lower_mnt, ia);
504 mutex_unlock(&lower_dentry->d_inode->i_mutex);
506 fsstack_copy_attr_all(inode, lower_inode, NULL);
507 diff -uprN linux-2.6.27./fs/exec.c linux-2.6.27/fs/exec.c
508 --- linux-2.6.27./fs/exec.c 2008-10-10 00:13:53.000000000 +0200
509 +++ linux-2.6.27/fs/exec.c 2008-10-29 02:01:59.319416030 +0100
510 @@ -1827,7 +1827,8 @@ int do_coredump(long signr, int exit_cod
512 if (!file->f_op->write)
514 - if (!ispipe && do_truncate(file->f_path.dentry, 0, 0, file) != 0)
516 + do_truncate(file->f_path.dentry, file->f_path.mnt, 0, 0, file) != 0)
519 retval = binfmt->core_dump(signr, regs, file, core_limit);
520 diff -uprN linux-2.6.27./fs/fat/file.c linux-2.6.27/fs/fat/file.c
521 --- linux-2.6.27./fs/fat/file.c 2008-10-10 00:13:53.000000000 +0200
522 +++ linux-2.6.27/fs/fat/file.c 2008-10-29 02:01:59.500590545 +0100
523 @@ -98,7 +98,7 @@ int fat_generic_ioctl(struct inode *inod
524 * out the RO attribute for checking by the security
525 * module, just because it maps to a file mode.
527 - err = security_inode_setattr(filp->f_path.dentry, &ia);
528 + err = security_inode_setattr(filp->f_path.dentry, filp->f_path.mnt, &ia);
532 diff -uprN linux-2.6.27./fs/fuse/dir.c linux-2.6.27/fs/fuse/dir.c
533 --- linux-2.6.27./fs/fuse/dir.c 2008-10-10 00:13:53.000000000 +0200
534 +++ linux-2.6.27/fs/fuse/dir.c 2008-10-29 02:02:01.786146390 +0100
535 @@ -1105,21 +1105,22 @@ static int fuse_dir_fsync(struct file *f
536 return file ? fuse_fsync_common(file, de, datasync, 1) : 0;
539 -static bool update_mtime(unsigned ivalid)
540 +static bool update_mtime(unsigned ivalid, bool have_file)
542 /* Always update if mtime is explicitly set */
543 if (ivalid & ATTR_MTIME_SET)
546 /* If it's an open(O_TRUNC) or an ftruncate(), don't update */
547 - if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE)))
548 + if ((ivalid & ATTR_SIZE) && ((ivalid & ATTR_OPEN) || have_file))
551 /* In all other cases update */
555 -static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg)
556 +static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg,
559 unsigned ivalid = iattr->ia_valid;
561 @@ -1138,7 +1139,7 @@ static void iattr_to_fattr(struct iattr
562 if (!(ivalid & ATTR_ATIME_SET))
563 arg->valid |= FATTR_ATIME_NOW;
565 - if ((ivalid & ATTR_MTIME) && update_mtime(ivalid)) {
566 + if ((ivalid & ATTR_MTIME) && update_mtime(ivalid, have_file)) {
567 arg->valid |= FATTR_MTIME;
568 arg->mtime = iattr->ia_mtime.tv_sec;
569 arg->mtimensec = iattr->ia_mtime.tv_nsec;
570 @@ -1199,8 +1200,8 @@ void fuse_release_nowrite(struct inode *
571 * vmtruncate() doesn't allow for this case, so do the rlimit checking
572 * and the actual truncation by hand.
574 -static int fuse_do_setattr(struct dentry *entry, struct iattr *attr,
576 +int fuse_do_setattr(struct dentry *entry, struct iattr *attr,
579 struct inode *inode = entry->d_inode;
580 struct fuse_conn *fc = get_fuse_conn(inode);
581 @@ -1244,7 +1245,7 @@ static int fuse_do_setattr(struct dentry
583 memset(&inarg, 0, sizeof(inarg));
584 memset(&outarg, 0, sizeof(outarg));
585 - iattr_to_fattr(attr, &inarg);
586 + iattr_to_fattr(attr, &inarg, file != NULL);
588 struct fuse_file *ff = file->private_data;
589 inarg.valid |= FATTR_FH;
590 @@ -1314,10 +1315,7 @@ error:
592 static int fuse_setattr(struct dentry *entry, struct iattr *attr)
594 - if (attr->ia_valid & ATTR_FILE)
595 - return fuse_do_setattr(entry, attr, attr->ia_file);
597 - return fuse_do_setattr(entry, attr, NULL);
598 + return fuse_do_setattr(entry, attr, NULL);
601 static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
602 diff -uprN linux-2.6.27./fs/fuse/file.c linux-2.6.27/fs/fuse/file.c
603 --- linux-2.6.27./fs/fuse/file.c 2008-10-10 00:13:53.000000000 +0200
604 +++ linux-2.6.27/fs/fuse/file.c 2008-10-29 02:02:01.819442233 +0100
605 @@ -1465,6 +1465,11 @@ static loff_t fuse_file_llseek(struct fi
609 +static int fuse_fsetattr(struct file *file, struct iattr *attr)
611 + return fuse_do_setattr(file->f_path.dentry, attr, file);
614 static const struct file_operations fuse_file_operations = {
615 .llseek = fuse_file_llseek,
616 .read = do_sync_read,
617 @@ -1478,6 +1483,7 @@ static const struct file_operations fuse
619 .lock = fuse_file_lock,
620 .flock = fuse_file_flock,
621 + .fsetattr = fuse_fsetattr,
622 .splice_read = generic_file_splice_read,
625 @@ -1491,6 +1497,7 @@ static const struct file_operations fuse
627 .lock = fuse_file_lock,
628 .flock = fuse_file_flock,
629 + .fsetattr = fuse_fsetattr,
630 /* no mmap and splice_read */
633 diff -uprN linux-2.6.27./fs/fuse/fuse_i.h linux-2.6.27/fs/fuse/fuse_i.h
634 --- linux-2.6.27./fs/fuse/fuse_i.h 2008-10-10 00:13:53.000000000 +0200
635 +++ linux-2.6.27/fs/fuse/fuse_i.h 2008-10-29 02:02:01.849340465 +0100
636 @@ -551,6 +551,10 @@ void fuse_truncate(struct address_space
638 int fuse_dev_init(void);
641 +int fuse_do_setattr(struct dentry *entry, struct iattr *attr,
642 + struct file *file);
645 * Cleanup the client device
647 diff -uprN linux-2.6.27./fs/hpfs/namei.c linux-2.6.27/fs/hpfs/namei.c
648 --- linux-2.6.27./fs/hpfs/namei.c 2008-10-10 00:13:53.000000000 +0200
649 +++ linux-2.6.27/fs/hpfs/namei.c 2008-10-29 02:01:59.336012786 +0100
650 @@ -426,7 +426,7 @@ again:
651 /*printk("HPFS: truncating file before delete.\n");*/
652 newattrs.ia_size = 0;
653 newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
654 - err = notify_change(dentry, &newattrs);
655 + err = notify_change(dentry, NULL, &newattrs);
656 put_write_access(inode);
659 diff -uprN linux-2.6.27./fs/inotify_user.c linux-2.6.27/fs/inotify_user.c
660 --- linux-2.6.27./fs/inotify_user.c 2008-10-10 00:13:53.000000000 +0200
661 +++ linux-2.6.27/fs/inotify_user.c 2008-10-29 02:02:02.186081701 +0100
662 @@ -372,7 +372,7 @@ static int find_inode(const char __user
665 /* you can only watch an inode if you have read permissions on it */
666 - error = inode_permission(path->dentry->d_inode, MAY_READ);
667 + error = path_permission(path, MAY_READ);
671 diff -uprN linux-2.6.27./fs/namei.c linux-2.6.27/fs/namei.c
672 --- linux-2.6.27./fs/namei.c 2008-10-10 00:13:53.000000000 +0200
673 +++ linux-2.6.27/fs/namei.c 2008-10-29 02:02:02.266214852 +0100
674 @@ -227,7 +227,7 @@ int generic_permission(struct inode *ino
678 -int inode_permission(struct inode *inode, int mask)
679 +static int __inode_permission(struct inode *inode, int mask)
683 @@ -269,7 +269,12 @@ int inode_permission(struct inode *inode
687 - retval = devcgroup_inode_permission(inode, mask);
688 + return devcgroup_inode_permission(inode, mask);
691 +int inode_permission(struct inode *inode, int mask)
693 + int retval = __inode_permission(inode, mask);
697 @@ -277,6 +282,15 @@ int inode_permission(struct inode *inode
698 mask & (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND));
701 +int path_permission(struct path *path, int mask)
703 + int retval = __inode_permission(path->dentry->d_inode, mask);
706 + return security_path_permission(path,
707 + mask & (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND));
711 * vfs_permission - check for access rights to a given path
712 * @nd: lookup result that describes the path
713 @@ -289,7 +303,7 @@ int inode_permission(struct inode *inode
715 int vfs_permission(struct nameidata *nd, int mask)
717 - return inode_permission(nd->path.dentry->d_inode, mask);
718 + return path_permission(&nd->path, mask);
722 @@ -306,7 +320,7 @@ int vfs_permission(struct nameidata *nd,
724 int file_permission(struct file *file, int mask)
726 - return inode_permission(file->f_path.dentry->d_inode, mask);
727 + return path_permission(&file->f_path, mask);
731 @@ -447,8 +461,9 @@ static struct dentry * cached_lookup(str
732 * short-cut DAC fails, then call permission() to do more
733 * complete permission check.
735 -static int exec_permission_lite(struct inode *inode)
736 +static int exec_permission_lite(struct path *path)
738 + struct inode *inode = path->dentry->d_inode;
739 umode_t mode = inode->i_mode;
741 if (inode->i_op && inode->i_op->permission)
742 @@ -473,7 +488,7 @@ static int exec_permission_lite(struct i
746 - return security_inode_permission(inode, MAY_EXEC);
747 + return security_path_permission(path, MAY_EXEC);
751 @@ -870,7 +885,7 @@ static int __link_path_walk(const char *
754 nd->flags |= LOOKUP_CONTINUE;
755 - err = exec_permission_lite(inode);
756 + err = exec_permission_lite(&nd->path);
758 err = vfs_permission(nd, MAY_EXEC);
760 @@ -1065,24 +1080,21 @@ static int do_path_lookup(int dfd, const
762 read_unlock(&fs->lock);
764 - struct dentry *dentry;
766 file = fget_light(dfd, &fput_needed);
771 - dentry = file->f_path.dentry;
772 + nd->path = file->f_path;
775 - if (!S_ISDIR(dentry->d_inode->i_mode))
776 + if (!S_ISDIR(nd->path.dentry->d_inode->i_mode))
779 retval = file_permission(file, MAY_EXEC);
783 - nd->path = file->f_path;
784 path_get(&file->f_path);
786 fput_light(file, fput_needed);
787 @@ -1245,7 +1257,7 @@ static struct dentry *lookup_hash(struct
791 - err = inode_permission(nd->path.dentry->d_inode, MAY_EXEC);
792 + err = path_permission(&nd->path, MAY_EXEC);
795 return __lookup_hash(&nd->last, nd->path.dentry, nd);
796 @@ -1512,7 +1524,7 @@ int vfs_create(struct inode *dir, struct
797 return -EACCES; /* shouldn't it be ENOSYS? */
800 - error = security_inode_create(dir, dentry, mode);
801 + error = security_inode_create(dir, dentry, nd ? nd->path.mnt : NULL, mode);
805 @@ -1588,7 +1600,7 @@ int may_open(struct nameidata *nd, int a
809 - error = do_truncate(dentry, 0,
810 + error = do_truncate(dentry, nd->path.mnt, 0,
811 ATTR_MTIME|ATTR_CTIME|ATTR_OPEN,
814 @@ -1945,7 +1957,8 @@ fail:
816 EXPORT_SYMBOL_GPL(lookup_create);
818 -int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
819 +int vfs_mknod(struct inode *dir, struct dentry *dentry, struct vfsmount *mnt,
820 + int mode, dev_t dev)
822 int error = may_create(dir, dentry);
824 @@ -1962,7 +1975,7 @@ int vfs_mknod(struct inode *dir, struct
828 - error = security_inode_mknod(dir, dentry, mode, dev);
829 + error = security_inode_mknod(dir, dentry, mnt, mode, dev);
833 @@ -2023,11 +2036,12 @@ asmlinkage long sys_mknodat(int dfd, con
834 error = vfs_create(nd.path.dentry->d_inode,dentry,mode,&nd);
836 case S_IFCHR: case S_IFBLK:
837 - error = vfs_mknod(nd.path.dentry->d_inode,dentry,mode,
838 - new_decode_dev(dev));
839 + error = vfs_mknod(nd.path.dentry->d_inode, dentry,
840 + nd.path.mnt, mode, new_decode_dev(dev));
842 case S_IFIFO: case S_IFSOCK:
843 - error = vfs_mknod(nd.path.dentry->d_inode,dentry,mode,0);
844 + error = vfs_mknod(nd.path.dentry->d_inode, dentry,
845 + nd.path.mnt, mode, 0);
848 mnt_drop_write(nd.path.mnt);
849 @@ -2046,7 +2060,8 @@ asmlinkage long sys_mknod(const char __u
850 return sys_mknodat(AT_FDCWD, filename, mode, dev);
853 -int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
854 +int vfs_mkdir(struct inode *dir, struct dentry *dentry, struct vfsmount *mnt,
857 int error = may_create(dir, dentry);
859 @@ -2057,7 +2072,7 @@ int vfs_mkdir(struct inode *dir, struct
862 mode &= (S_IRWXUGO|S_ISVTX);
863 - error = security_inode_mkdir(dir, dentry, mode);
864 + error = security_inode_mkdir(dir, dentry, mnt, mode);
868 @@ -2089,7 +2104,7 @@ asmlinkage long sys_mkdirat(int dfd, con
869 error = mnt_want_write(nd.path.mnt);
872 - error = vfs_mkdir(nd.path.dentry->d_inode, dentry, mode);
873 + error = vfs_mkdir(nd.path.dentry->d_inode, dentry, nd.path.mnt, mode);
874 mnt_drop_write(nd.path.mnt);
877 @@ -2133,7 +2148,7 @@ void dentry_unhash(struct dentry *dentry
878 spin_unlock(&dcache_lock);
881 -int vfs_rmdir(struct inode *dir, struct dentry *dentry)
882 +int vfs_rmdir(struct inode *dir, struct dentry *dentry,struct vfsmount *mnt)
884 int error = may_delete(dir, dentry, 1);
886 @@ -2143,6 +2158,10 @@ int vfs_rmdir(struct inode *dir, struct
887 if (!dir->i_op || !dir->i_op->rmdir)
890 + error = security_inode_rmdir(dir, dentry, mnt);
896 mutex_lock(&dentry->d_inode->i_mutex);
897 @@ -2150,12 +2169,9 @@ int vfs_rmdir(struct inode *dir, struct
898 if (d_mountpoint(dentry))
901 - error = security_inode_rmdir(dir, dentry);
903 - error = dir->i_op->rmdir(dir, dentry);
905 - dentry->d_inode->i_flags |= S_DEAD;
907 + error = dir->i_op->rmdir(dir, dentry);
909 + dentry->d_inode->i_flags |= S_DEAD;
911 mutex_unlock(&dentry->d_inode->i_mutex);
913 @@ -2196,7 +2212,7 @@ static long do_rmdir(int dfd, const char
914 error = mnt_want_write(nd.path.mnt);
917 - error = vfs_rmdir(nd.path.dentry->d_inode, dentry);
918 + error = vfs_rmdir(nd.path.dentry->d_inode, dentry, nd.path.mnt);
919 mnt_drop_write(nd.path.mnt);
922 @@ -2213,7 +2229,7 @@ asmlinkage long sys_rmdir(const char __u
923 return do_rmdir(AT_FDCWD, pathname);
926 -int vfs_unlink(struct inode *dir, struct dentry *dentry)
927 +int vfs_unlink(struct inode *dir, struct dentry *dentry, struct vfsmount *mnt)
929 int error = may_delete(dir, dentry, 0);
931 @@ -2229,7 +2245,7 @@ int vfs_unlink(struct inode *dir, struct
932 if (d_mountpoint(dentry))
935 - error = security_inode_unlink(dir, dentry);
936 + error = security_inode_unlink(dir, dentry, mnt);
938 error = dir->i_op->unlink(dir, dentry);
940 @@ -2278,7 +2294,7 @@ static long do_unlinkat(int dfd, const c
941 error = mnt_want_write(nd.path.mnt);
944 - error = vfs_unlink(nd.path.dentry->d_inode, dentry);
945 + error = vfs_unlink(nd.path.dentry->d_inode, dentry, nd.path.mnt);
946 if (!error && (saved_ino || saved_dev))
947 gr_handle_delete(saved_ino, saved_dev);
948 mnt_drop_write(nd.path.mnt);
949 @@ -2313,7 +2329,8 @@ asmlinkage long sys_unlink(const char __
950 return do_unlinkat(AT_FDCWD, pathname);
953 -int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname)
954 +int vfs_symlink(struct inode *dir, struct dentry *dentry, struct vfsmount *mnt,
955 + const char *oldname)
957 int error = may_create(dir, dentry);
959 @@ -2323,7 +2340,7 @@ int vfs_symlink(struct inode *dir, struc
960 if (!dir->i_op || !dir->i_op->symlink)
963 - error = security_inode_symlink(dir, dentry, oldname);
964 + error = security_inode_symlink(dir, dentry, mnt, oldname);
968 @@ -2359,7 +2376,7 @@ asmlinkage long sys_symlinkat(const char
969 error = mnt_want_write(nd.path.mnt);
972 - error = vfs_symlink(nd.path.dentry->d_inode, dentry, from);
973 + error = vfs_symlink(nd.path.dentry->d_inode, dentry, nd.path.mnt, from);
975 gr_handle_create(dentry, nd.path.mnt);
976 mnt_drop_write(nd.path.mnt);
977 @@ -2377,7 +2394,7 @@ asmlinkage long sys_symlink(const char _
978 return sys_symlinkat(oldname, AT_FDCWD, newname);
981 -int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
982 +int vfs_link(struct dentry *old_dentry, struct vfsmount *old_mnt, struct inode *dir, struct dentry *new_dentry, struct vfsmount *new_mnt)
984 struct inode *inode = old_dentry->d_inode;
986 @@ -2402,7 +2419,8 @@ int vfs_link(struct dentry *old_dentry,
987 if (S_ISDIR(inode->i_mode))
990 - error = security_inode_link(old_dentry, dir, new_dentry);
991 + error = security_inode_link(old_dentry, old_mnt, dir, new_dentry,
996 @@ -2456,7 +2474,9 @@ asmlinkage long sys_linkat(int olddfd, c
997 error = mnt_want_write(nd.path.mnt);
1000 - error = vfs_link(old_path.dentry, nd.path.dentry->d_inode, new_dentry);
1001 + error = vfs_link(old_path.dentry, old_path.mnt,
1002 + nd.path.dentry->d_inode,
1003 + new_dentry, nd.path.mnt);
1005 gr_handle_create(new_dentry, nd.path.mnt);
1006 mnt_drop_write(nd.path.mnt);
1007 @@ -2509,7 +2529,8 @@ asmlinkage long sys_link(const char __us
1010 static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
1011 - struct inode *new_dir, struct dentry *new_dentry)
1012 + struct vfsmount *old_mnt, struct inode *new_dir,
1013 + struct dentry *new_dentry, struct vfsmount *new_mnt)
1016 struct inode *target;
1017 @@ -2524,7 +2545,8 @@ static int vfs_rename_dir(struct inode *
1021 - error = security_inode_rename(old_dir, old_dentry, new_dir, new_dentry);
1022 + error = security_inode_rename(old_dir, old_dentry, old_mnt,
1023 + new_dir, new_dentry, new_mnt);
1027 @@ -2552,12 +2574,14 @@ static int vfs_rename_dir(struct inode *
1030 static int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
1031 - struct inode *new_dir, struct dentry *new_dentry)
1032 + struct vfsmount *old_mnt, struct inode *new_dir,
1033 + struct dentry *new_dentry, struct vfsmount *new_mnt)
1035 struct inode *target;
1038 - error = security_inode_rename(old_dir, old_dentry, new_dir, new_dentry);
1039 + error = security_inode_rename(old_dir, old_dentry, old_mnt,
1040 + new_dir, new_dentry, new_mnt);
1044 @@ -2580,7 +2604,8 @@ static int vfs_rename_other(struct inode
1047 int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
1048 - struct inode *new_dir, struct dentry *new_dentry)
1049 + struct vfsmount *old_mnt, struct inode *new_dir,
1050 + struct dentry *new_dentry, struct vfsmount *new_mnt)
1053 int is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
1054 @@ -2609,9 +2634,11 @@ int vfs_rename(struct inode *old_dir, st
1055 old_name = fsnotify_oldname_init(old_dentry->d_name.name);
1058 - error = vfs_rename_dir(old_dir,old_dentry,new_dir,new_dentry);
1059 + error = vfs_rename_dir(old_dir, old_dentry, old_mnt,
1060 + new_dir, new_dentry, new_mnt);
1062 - error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry);
1063 + error = vfs_rename_other(old_dir, old_dentry, old_mnt,
1064 + new_dir, new_dentry, new_mnt);
1067 const char *new_name = old_dentry->d_name.name;
1068 @@ -2688,8 +2715,8 @@ asmlinkage long sys_renameat(int olddfd,
1069 error = mnt_want_write(oldnd.path.mnt);
1072 - error = vfs_rename(old_dir->d_inode, old_dentry,
1073 - new_dir->d_inode, new_dentry);
1074 + error = vfs_rename(old_dir->d_inode, old_dentry, oldnd.path.mnt,
1075 + new_dir->d_inode, new_dentry, newnd.path.mnt);
1077 gr_handle_rename(old_dir->d_inode, newnd.path.dentry->d_inode, old_dentry,
1078 new_dentry, oldnd.path.mnt, new_dentry->d_inode ? 1 : 0);
1079 @@ -2857,6 +2884,7 @@ EXPORT_SYMBOL(page_symlink_inode_operati
1080 EXPORT_SYMBOL(path_lookup);
1081 EXPORT_SYMBOL(vfs_path_lookup);
1082 EXPORT_SYMBOL(inode_permission);
1083 +EXPORT_SYMBOL(path_permission);
1084 EXPORT_SYMBOL(vfs_permission);
1085 EXPORT_SYMBOL(file_permission);
1086 EXPORT_SYMBOL(unlock_rename);
1087 diff -uprN linux-2.6.27./fs/namespace.c linux-2.6.27/fs/namespace.c
1088 --- linux-2.6.27./fs/namespace.c 2008-10-10 00:13:53.000000000 +0200
1089 +++ linux-2.6.27/fs/namespace.c 2008-10-29 02:02:01.636213710 +0100
1090 @@ -2352,3 +2352,33 @@ void __put_mnt_ns(struct mnt_namespace *
1091 release_mounts(&umount_list);
1095 +char *d_namespace_path(struct dentry *dentry, struct vfsmount *vfsmnt,
1096 + char *buf, int buflen)
1098 + struct path root, tmp, ns_root = { };
1099 + struct path path = { .mnt = vfsmnt, .dentry = dentry };
1102 + read_lock(¤t->fs->lock);
1103 + root = current->fs->root;
1104 + path_get(¤t->fs->root);
1105 + read_unlock(¤t->fs->lock);
1106 + spin_lock(&vfsmount_lock);
1108 + ns_root.mnt = mntget(root.mnt->mnt_ns->root);
1110 + ns_root.dentry = dget(ns_root.mnt->mnt_root);
1111 + spin_unlock(&vfsmount_lock);
1113 + res = __d_path(&path, &tmp, buf, buflen,
1114 + D_PATH_FAIL_DELETED | D_PATH_DISCONNECT);
1116 + path_put(&ns_root);
1118 + /* Prevent empty path for lazily unmounted filesystems. */
1119 + if (!IS_ERR(res) && *res == '\0')
1123 +EXPORT_SYMBOL(d_namespace_path);
1124 diff -uprN linux-2.6.27./fs/nfsd/nfs4recover.c linux-2.6.27/fs/nfsd/nfs4recover.c
1125 --- linux-2.6.27./fs/nfsd/nfs4recover.c 2008-10-10 00:13:53.000000000 +0200
1126 +++ linux-2.6.27/fs/nfsd/nfs4recover.c 2008-10-29 02:02:00.593071537 +0100
1127 @@ -158,7 +158,8 @@ nfsd4_create_clid_dir(struct nfs4_client
1128 status = mnt_want_write(rec_dir.path.mnt);
1131 - status = vfs_mkdir(rec_dir.path.dentry->d_inode, dentry, S_IRWXU);
1132 + status = vfs_mkdir(rec_dir.path.dentry->d_inode, dentry,
1133 + rec_dir.path.mnt, S_IRWXU);
1134 mnt_drop_write(rec_dir.path.mnt);
1137 @@ -263,7 +264,7 @@ nfsd4_remove_clid_file(struct dentry *di
1140 mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
1141 - status = vfs_unlink(dir->d_inode, dentry);
1142 + status = vfs_unlink(dir->d_inode, dentry, rec_dir.path.mnt);
1143 mutex_unlock(&dir->d_inode->i_mutex);
1146 @@ -278,7 +279,7 @@ nfsd4_clear_clid_dir(struct dentry *dir,
1147 * a kernel from the future.... */
1148 nfsd4_list_rec_dir(dentry, nfsd4_remove_clid_file);
1149 mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
1150 - status = vfs_rmdir(dir->d_inode, dentry);
1151 + status = vfs_rmdir(dir->d_inode, dentry, rec_dir.path.mnt);
1152 mutex_unlock(&dir->d_inode->i_mutex);
1155 diff -uprN linux-2.6.27./fs/nfsd/nfs4xdr.c linux-2.6.27/fs/nfsd/nfs4xdr.c
1156 --- linux-2.6.27./fs/nfsd/nfs4xdr.c 2008-10-10 00:13:53.000000000 +0200
1157 +++ linux-2.6.27/fs/nfsd/nfs4xdr.c 2008-10-29 02:02:01.146006994 +0100
1158 @@ -1446,7 +1446,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, s
1160 if (bmval0 & (FATTR4_WORD0_ACL | FATTR4_WORD0_ACLSUPPORT
1161 | FATTR4_WORD0_SUPPORTED_ATTRS)) {
1162 - err = nfsd4_get_nfs4_acl(rqstp, dentry, &acl);
1163 + err = nfsd4_get_nfs4_acl(rqstp, dentry, exp->ex_path.mnt, &acl);
1164 aclsupport = (err == 0);
1165 if (bmval0 & FATTR4_WORD0_ACL) {
1166 if (err == -EOPNOTSUPP)
1167 diff -uprN linux-2.6.27./fs/nfsd/vfs.c linux-2.6.27/fs/nfsd/vfs.c
1168 --- linux-2.6.27./fs/nfsd/vfs.c 2008-10-10 00:13:53.000000000 +0200
1169 +++ linux-2.6.27/fs/nfsd/vfs.c 2008-10-29 02:02:01.949479311 +0100
1170 @@ -388,7 +388,7 @@ nfsd_setattr(struct svc_rqst *rqstp, str
1171 err = nfserr_notsync;
1172 if (!check_guard || guardtime == inode->i_ctime.tv_sec) {
1174 - host_err = notify_change(dentry, iap);
1175 + host_err = notify_change(dentry, fhp->fh_export->ex_path.mnt, iap);
1176 err = nfserrno(host_err);
1179 @@ -408,11 +408,12 @@ out_nfserr:
1180 #if defined(CONFIG_NFSD_V2_ACL) || \
1181 defined(CONFIG_NFSD_V3_ACL) || \
1182 defined(CONFIG_NFSD_V4)
1183 -static ssize_t nfsd_getxattr(struct dentry *dentry, char *key, void **buf)
1184 +static ssize_t nfsd_getxattr(struct dentry *dentry, struct vfsmount *mnt,
1185 + char *key, void **buf)
1189 - buflen = vfs_getxattr(dentry, key, NULL, 0);
1190 + buflen = vfs_getxattr(dentry, mnt, key, NULL, 0, NULL);
1194 @@ -420,13 +421,14 @@ static ssize_t nfsd_getxattr(struct dent
1198 - return vfs_getxattr(dentry, key, *buf, buflen);
1199 + return vfs_getxattr(dentry, mnt, key, *buf, buflen, NULL);
1203 #if defined(CONFIG_NFSD_V4)
1205 -set_nfsv4_acl_one(struct dentry *dentry, struct posix_acl *pacl, char *key)
1206 +set_nfsv4_acl_one(struct dentry *dentry, struct vfsmount *mnt,
1207 + struct posix_acl *pacl, char *key)
1211 @@ -445,7 +447,7 @@ set_nfsv4_acl_one(struct dentry *dentry,
1215 - error = vfs_setxattr(dentry, key, buf, len, 0);
1216 + error = vfs_setxattr(dentry, mnt, key, buf, len, 0, NULL);
1220 @@ -458,6 +460,7 @@ nfsd4_set_nfs4_acl(struct svc_rqst *rqst
1223 struct dentry *dentry;
1224 + struct vfsmount *mnt;
1225 struct inode *inode;
1226 struct posix_acl *pacl = NULL, *dpacl = NULL;
1227 unsigned int flags = 0;
1228 @@ -468,6 +471,7 @@ nfsd4_set_nfs4_acl(struct svc_rqst *rqst
1231 dentry = fhp->fh_dentry;
1232 + mnt = fhp->fh_export->ex_path.mnt;
1233 inode = dentry->d_inode;
1234 if (S_ISDIR(inode->i_mode))
1235 flags = NFS4_ACL_DIR;
1236 @@ -478,12 +482,14 @@ nfsd4_set_nfs4_acl(struct svc_rqst *rqst
1237 } else if (host_error < 0)
1240 - host_error = set_nfsv4_acl_one(dentry, pacl, POSIX_ACL_XATTR_ACCESS);
1241 + host_error = set_nfsv4_acl_one(dentry, mnt, pacl,
1242 + POSIX_ACL_XATTR_ACCESS);
1246 if (S_ISDIR(inode->i_mode))
1247 - host_error = set_nfsv4_acl_one(dentry, dpacl, POSIX_ACL_XATTR_DEFAULT);
1248 + host_error = set_nfsv4_acl_one(dentry, mnt, dpacl,
1249 + POSIX_ACL_XATTR_DEFAULT);
1252 posix_acl_release(pacl);
1253 @@ -496,13 +502,13 @@ out_nfserr:
1256 static struct posix_acl *
1257 -_get_posix_acl(struct dentry *dentry, char *key)
1258 +_get_posix_acl(struct dentry *dentry, struct vfsmount *mnt, char *key)
1261 struct posix_acl *pacl = NULL;
1264 - buflen = nfsd_getxattr(dentry, key, &buf);
1265 + buflen = nfsd_getxattr(dentry, mnt, key, &buf);
1269 @@ -514,14 +520,15 @@ _get_posix_acl(struct dentry *dentry, ch
1273 -nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry, struct nfs4_acl **acl)
1274 +nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry,
1275 + struct vfsmount *mnt, struct nfs4_acl **acl)
1277 struct inode *inode = dentry->d_inode;
1279 struct posix_acl *pacl = NULL, *dpacl = NULL;
1280 unsigned int flags = 0;
1282 - pacl = _get_posix_acl(dentry, POSIX_ACL_XATTR_ACCESS);
1283 + pacl = _get_posix_acl(dentry, mnt, POSIX_ACL_XATTR_ACCESS);
1284 if (IS_ERR(pacl) && PTR_ERR(pacl) == -ENODATA)
1285 pacl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
1287 @@ -531,7 +538,7 @@ nfsd4_get_nfs4_acl(struct svc_rqst *rqst
1290 if (S_ISDIR(inode->i_mode)) {
1291 - dpacl = _get_posix_acl(dentry, POSIX_ACL_XATTR_DEFAULT);
1292 + dpacl = _get_posix_acl(dentry, mnt, POSIX_ACL_XATTR_DEFAULT);
1293 if (IS_ERR(dpacl) && PTR_ERR(dpacl) == -ENODATA)
1295 else if (IS_ERR(dpacl)) {
1296 @@ -944,13 +951,13 @@ out:
1300 -static void kill_suid(struct dentry *dentry)
1301 +static void kill_suid(struct dentry *dentry, struct vfsmount *mnt)
1304 ia.ia_valid = ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;
1306 mutex_lock(&dentry->d_inode->i_mutex);
1307 - notify_change(dentry, &ia);
1308 + notify_change(dentry, mnt, &ia);
1309 mutex_unlock(&dentry->d_inode->i_mutex);
1312 @@ -1009,7 +1016,7 @@ nfsd_vfs_write(struct svc_rqst *rqstp, s
1314 /* clear setuid/setgid flag after write */
1315 if (host_err >= 0 && (inode->i_mode & (S_ISUID | S_ISGID)))
1316 - kill_suid(dentry);
1317 + kill_suid(dentry, exp->ex_path.mnt);
1319 if (host_err >= 0 && stable) {
1320 static ino_t last_ino;
1321 @@ -1187,6 +1194,7 @@ nfsd_create(struct svc_rqst *rqstp, stru
1322 int type, dev_t rdev, struct svc_fh *resfhp)
1324 struct dentry *dentry, *dchild = NULL;
1325 + struct svc_export *exp;
1329 @@ -1204,6 +1212,7 @@ nfsd_create(struct svc_rqst *rqstp, stru
1332 dentry = fhp->fh_dentry;
1333 + exp = fhp->fh_export;
1334 dirp = dentry->d_inode;
1336 err = nfserr_notdir;
1337 @@ -1220,7 +1229,7 @@ nfsd_create(struct svc_rqst *rqstp, stru
1338 host_err = PTR_ERR(dchild);
1341 - err = fh_compose(resfhp, fhp->fh_export, dchild, fhp);
1342 + err = fh_compose(resfhp, exp, dchild, fhp);
1346 @@ -1270,13 +1279,14 @@ nfsd_create(struct svc_rqst *rqstp, stru
1347 host_err = vfs_create(dirp, dchild, iap->ia_mode, NULL);
1350 - host_err = vfs_mkdir(dirp, dchild, iap->ia_mode);
1351 + host_err = vfs_mkdir(dirp, dchild, exp->ex_path.mnt, iap->ia_mode);
1357 - host_err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev);
1358 + host_err = vfs_mknod(dirp, dchild, exp->ex_path.mnt,
1359 + iap->ia_mode, rdev);
1363 @@ -1284,7 +1294,7 @@ nfsd_create(struct svc_rqst *rqstp, stru
1367 - if (EX_ISSYNC(fhp->fh_export)) {
1368 + if (EX_ISSYNC(exp)) {
1369 err = nfserrno(nfsd_sync_dir(dentry));
1370 write_inode_now(dchild->d_inode, 1);
1372 @@ -1514,6 +1524,7 @@ nfsd_symlink(struct svc_rqst *rqstp, str
1375 struct dentry *dentry, *dnew;
1376 + struct svc_export *exp;
1380 @@ -1538,6 +1549,7 @@ nfsd_symlink(struct svc_rqst *rqstp, str
1384 + exp = fhp->fh_export;
1385 if (unlikely(path[plen] != 0)) {
1386 char *path_alloced = kmalloc(plen+1, GFP_KERNEL);
1387 if (path_alloced == NULL)
1388 @@ -1545,14 +1557,16 @@ nfsd_symlink(struct svc_rqst *rqstp, str
1390 strncpy(path_alloced, path, plen);
1391 path_alloced[plen] = 0;
1392 - host_err = vfs_symlink(dentry->d_inode, dnew, path_alloced);
1393 + host_err = vfs_symlink(dentry->d_inode, dnew,
1394 + exp->ex_path.mnt, path_alloced);
1395 kfree(path_alloced);
1398 - host_err = vfs_symlink(dentry->d_inode, dnew, path);
1399 + host_err = vfs_symlink(dentry->d_inode, dnew, exp->ex_path.mnt,
1403 - if (EX_ISSYNC(fhp->fh_export))
1404 + if (EX_ISSYNC(exp))
1405 host_err = nfsd_sync_dir(dentry);
1407 err = nfserrno(host_err);
1408 @@ -1560,7 +1574,7 @@ nfsd_symlink(struct svc_rqst *rqstp, str
1410 mnt_drop_write(fhp->fh_export->ex_path.mnt);
1412 - cerr = fh_compose(resfhp, fhp->fh_export, dnew, fhp);
1413 + cerr = fh_compose(resfhp, exp, dnew, fhp);
1415 if (err==0) err = cerr;
1417 @@ -1615,7 +1629,8 @@ nfsd_link(struct svc_rqst *rqstp, struct
1418 err = nfserrno(host_err);
1421 - host_err = vfs_link(dold, dirp, dnew);
1422 + host_err = vfs_link(dold, tfhp->fh_export->ex_path.mnt, dirp,
1423 + dnew, ffhp->fh_export->ex_path.mnt);
1425 if (EX_ISSYNC(ffhp->fh_export)) {
1426 err = nfserrno(nfsd_sync_dir(ddir));
1427 @@ -1716,7 +1731,8 @@ nfsd_rename(struct svc_rqst *rqstp, stru
1431 - host_err = vfs_rename(fdir, odentry, tdir, ndentry);
1432 + host_err = vfs_rename(fdir, odentry, ffhp->fh_export->ex_path.mnt,
1433 + tdir, ndentry, tfhp->fh_export->ex_path.mnt);
1434 if (!host_err && EX_ISSYNC(tfhp->fh_export)) {
1435 host_err = nfsd_sync_dir(tdentry);
1437 @@ -1754,6 +1770,7 @@ nfsd_unlink(struct svc_rqst *rqstp, stru
1438 char *fname, int flen)
1440 struct dentry *dentry, *rdentry;
1441 + struct svc_export *exp;
1445 @@ -1768,6 +1785,7 @@ nfsd_unlink(struct svc_rqst *rqstp, stru
1446 fh_lock_nested(fhp, I_MUTEX_PARENT);
1447 dentry = fhp->fh_dentry;
1448 dirp = dentry->d_inode;
1449 + exp = fhp->fh_export;
1451 rdentry = lookup_one_len(fname, dentry, flen);
1452 host_err = PTR_ERR(rdentry);
1453 @@ -1789,21 +1807,21 @@ nfsd_unlink(struct svc_rqst *rqstp, stru
1455 if (type != S_IFDIR) { /* It's UNLINK */
1457 - if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
1458 + if ((exp->ex_flags & NFSEXP_MSNFS) &&
1459 (atomic_read(&rdentry->d_count) > 1)) {
1463 - host_err = vfs_unlink(dirp, rdentry);
1464 + host_err = vfs_unlink(dirp, rdentry, exp->ex_path.mnt);
1465 } else { /* It's RMDIR */
1466 - host_err = vfs_rmdir(dirp, rdentry);
1467 + host_err = vfs_rmdir(dirp, rdentry, exp->ex_path.mnt);
1474 - if (EX_ISSYNC(fhp->fh_export))
1475 + if (EX_ISSYNC(exp))
1476 host_err = nfsd_sync_dir(dentry);
1479 @@ -2036,7 +2054,8 @@ nfsd_get_posix_acl(struct svc_fh *fhp, i
1480 return ERR_PTR(-EOPNOTSUPP);
1483 - size = nfsd_getxattr(fhp->fh_dentry, name, &value);
1484 + size = nfsd_getxattr(fhp->fh_dentry, fhp->fh_export->ex_path.mnt, name,
1487 return ERR_PTR(size);
1489 @@ -2048,6 +2067,7 @@ nfsd_get_posix_acl(struct svc_fh *fhp, i
1491 nfsd_set_posix_acl(struct svc_fh *fhp, int type, struct posix_acl *acl)
1493 + struct vfsmount *mnt;
1494 struct inode *inode = fhp->fh_dentry->d_inode;
1497 @@ -2080,21 +2100,24 @@ nfsd_set_posix_acl(struct svc_fh *fhp, i
1501 - error = mnt_want_write(fhp->fh_export->ex_path.mnt);
1502 + mnt = fhp->fh_export->ex_path.mnt;
1503 + error = mnt_want_write(mnt);
1507 - error = vfs_setxattr(fhp->fh_dentry, name, value, size, 0);
1508 + error = vfs_setxattr(fhp->fh_dentry, mnt, name, value, size, 0,
1511 if (!S_ISDIR(inode->i_mode) && type == ACL_TYPE_DEFAULT)
1514 - error = vfs_removexattr(fhp->fh_dentry, name);
1515 + error = vfs_removexattr(fhp->fh_dentry, mnt, name,
1517 if (error == -ENODATA)
1521 - mnt_drop_write(fhp->fh_export->ex_path.mnt);
1522 + mnt_drop_write(mnt);
1526 diff -uprN linux-2.6.27./fs/open.c linux-2.6.27/fs/open.c
1527 --- linux-2.6.27./fs/open.c 2008-10-10 00:13:53.000000000 +0200
1528 +++ linux-2.6.27/fs/open.c 2008-10-29 02:02:02.243218277 +0100
1529 @@ -197,8 +197,8 @@ out:
1533 -int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
1534 - struct file *filp)
1535 +int do_truncate(struct dentry *dentry, struct vfsmount *mnt, loff_t length,
1536 + unsigned int time_attrs, struct file *filp)
1539 struct iattr newattrs;
1540 @@ -209,16 +209,15 @@ int do_truncate(struct dentry *dentry, l
1542 newattrs.ia_size = length;
1543 newattrs.ia_valid = ATTR_SIZE | time_attrs;
1545 - newattrs.ia_file = filp;
1548 newattrs.ia_valid |= ATTR_FILE;
1551 /* Remove suid/sgid on truncate too */
1552 newattrs.ia_valid |= should_remove_suid(dentry);
1554 mutex_lock(&dentry->d_inode->i_mutex);
1555 - err = notify_change(dentry, &newattrs);
1556 + err = fnotify_change(dentry, mnt, &newattrs, filp);
1557 mutex_unlock(&dentry->d_inode->i_mutex);
1560 @@ -251,7 +250,7 @@ static long do_sys_truncate(const char _
1564 - error = inode_permission(inode, MAY_WRITE);
1565 + error = path_permission(&path, MAY_WRITE);
1567 goto mnt_drop_write_and_out;
1569 @@ -274,7 +273,7 @@ static long do_sys_truncate(const char _
1570 error = locks_verify_truncate(inode, NULL, length);
1573 - error = do_truncate(path.dentry, length, 0, NULL);
1574 + error = do_truncate(path.dentry, path.mnt, length, 0, NULL);
1578 @@ -329,7 +328,8 @@ static long do_sys_ftruncate(unsigned in
1580 error = locks_verify_truncate(inode, file, length);
1582 - error = do_truncate(dentry, length, ATTR_MTIME|ATTR_CTIME, file);
1583 + error = do_truncate(dentry, file->f_path.mnt, length,
1584 + ATTR_MTIME|ATTR_CTIME, file);
1588 @@ -474,7 +474,7 @@ asmlinkage long sys_faccessat(int dfd, c
1589 goto out_path_release;
1592 - res = inode_permission(inode, mode | MAY_ACCESS);
1593 + res = path_permission(&path, mode | MAY_ACCESS);
1594 /* SuS v2 requires we report a read only fs too */
1595 if (res || !(mode & S_IWOTH) || special_file(inode->i_mode))
1596 goto out_path_release;
1597 @@ -517,7 +517,7 @@ asmlinkage long sys_chdir(const char __u
1601 - error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_ACCESS);
1602 + error = path_permission(&path, MAY_EXEC | MAY_ACCESS);
1606 @@ -546,7 +546,7 @@ asmlinkage long sys_fchdir(unsigned int
1607 if (!S_ISDIR(inode->i_mode))
1610 - error = inode_permission(inode, MAY_EXEC | MAY_ACCESS);
1611 + error = path_permission(&file->f_path, MAY_EXEC | MAY_ACCESS);
1613 if (!error && !gr_chroot_fchdir(file->f_path.dentry, file->f_path.mnt))
1615 @@ -564,7 +564,7 @@ asmlinkage long sys_chroot(const char __
1619 - error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_ACCESS);
1620 + error = path_permission(&path, MAY_EXEC | MAY_ACCESS);
1624 @@ -604,8 +604,8 @@ asmlinkage long sys_fchmod(unsigned int
1625 if (mode == (mode_t) -1)
1626 mode = inode->i_mode;
1627 newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
1628 - newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
1629 - err = notify_change(dentry, &newattrs);
1630 + newattrs.ia_valid = ATTR_MODE | ATTR_CTIME | ATTR_FILE;
1631 + err = fnotify_change(dentry, file->f_path.mnt, &newattrs, file);
1632 mutex_unlock(&inode->i_mutex);
1633 mnt_drop_write(file->f_path.mnt);
1635 @@ -635,7 +635,7 @@ asmlinkage long sys_fchmodat(int dfd, co
1636 mode = inode->i_mode;
1637 newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
1638 newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
1639 - error = notify_change(path.dentry, &newattrs);
1640 + error = notify_change(path.dentry, path.mnt, &newattrs);
1641 mutex_unlock(&inode->i_mutex);
1642 mnt_drop_write(path.mnt);
1644 @@ -649,7 +649,8 @@ asmlinkage long sys_chmod(const char __u
1645 return sys_fchmodat(AT_FDCWD, filename, mode);
1648 -static int chown_common(struct dentry * dentry, uid_t user, gid_t group, struct vfsmount *mnt)
1649 +static int chown_common(struct dentry * dentry, struct vfsmount *mnt,
1650 + uid_t user, gid_t group, struct file *file)
1652 struct inode *inode = dentry->d_inode;
1654 @@ -667,8 +668,11 @@ static int chown_common(struct dentry *
1655 if (!S_ISDIR(inode->i_mode))
1656 newattrs.ia_valid |=
1657 ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;
1659 + newattrs.ia_valid |= ATTR_FILE;
1661 mutex_lock(&inode->i_mutex);
1662 - error = notify_change(dentry, &newattrs);
1663 + error = fnotify_change(dentry, mnt, &newattrs, file);
1664 mutex_unlock(&inode->i_mutex);
1667 @@ -685,7 +689,7 @@ asmlinkage long sys_chown(const char __u
1668 error = cow_check_and_break(&path);
1671 - error = chown_common(path.dentry, user, group, path.mnt);
1672 + error = chown_common(path.dentry, path.mnt, user, group, NULL);
1673 mnt_drop_write(path.mnt);
1676 @@ -710,7 +714,7 @@ asmlinkage long sys_fchownat(int dfd, co
1677 error = cow_check_and_break(&path);
1680 - error = chown_common(path.dentry, user, group, path.mnt);
1681 + error = chown_common(path.dentry, path.mnt, user, group, NULL);
1682 mnt_drop_write(path.mnt);
1685 @@ -729,7 +733,7 @@ asmlinkage long sys_lchown(const char __
1686 error = cow_check_and_break(&path);
1689 - error = chown_common(path.dentry, user, group, path.mnt);
1690 + error = chown_common(path.dentry, path.mnt, user, group, NULL);
1691 mnt_drop_write(path.mnt);
1694 @@ -753,7 +757,7 @@ asmlinkage long sys_fchown(unsigned int
1696 dentry = file->f_path.dentry;
1697 audit_inode(NULL, dentry);
1698 - error = chown_common(dentry, user, group, file->f_path.mnt);
1699 + error = chown_common(dentry, file->f_path.mnt, user, group, file);
1700 mnt_drop_write(file->f_path.mnt);
1703 diff -uprN linux-2.6.27./fs/reiserfs/xattr.c linux-2.6.27/fs/reiserfs/xattr.c
1704 --- linux-2.6.27./fs/reiserfs/xattr.c 2008-10-10 00:13:53.000000000 +0200
1705 +++ linux-2.6.27/fs/reiserfs/xattr.c 2008-10-29 02:02:00.436006183 +0100
1706 @@ -459,7 +459,7 @@ reiserfs_xattr_set(struct inode *inode,
1707 newattrs.ia_size = buffer_size;
1708 newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
1709 mutex_lock_nested(&xinode->i_mutex, I_MUTEX_XATTR);
1710 - err = notify_change(dentry, &newattrs);
1711 + err = notify_change(dentry, NULL, &newattrs);
1715 @@ -746,7 +746,7 @@ int reiserfs_delete_xattrs(struct inode
1716 if (dir->d_inode->i_nlink <= 2) {
1717 root = get_xa_root(inode->i_sb, XATTR_REPLACE);
1718 reiserfs_write_lock_xattrs(inode->i_sb);
1719 - err = vfs_rmdir(root->d_inode, dir);
1720 + err = vfs_rmdir(root->d_inode, dir, NULL);
1721 reiserfs_write_unlock_xattrs(inode->i_sb);
1724 @@ -790,7 +790,7 @@ reiserfs_chown_xattrs_filler(void *buf,
1727 if (!S_ISDIR(xafile->d_inode->i_mode))
1728 - err = notify_change(xafile, attrs);
1729 + err = notify_change(xafile, NULL, attrs);
1733 @@ -834,7 +834,7 @@ int reiserfs_chown_xattrs(struct inode *
1737 - err = notify_change(dir, attrs);
1738 + err = notify_change(dir, NULL, attrs);
1742 diff -uprN linux-2.6.27./fs/seq_file.c linux-2.6.27/fs/seq_file.c
1743 --- linux-2.6.27./fs/seq_file.c 2008-10-10 00:13:53.000000000 +0200
1744 +++ linux-2.6.27/fs/seq_file.c 2008-10-29 02:02:01.616216002 +0100
1745 @@ -412,9 +412,7 @@ int seq_path_root(struct seq_file *m, st
1746 char *s = m->buf + m->count;
1749 - spin_lock(&dcache_lock);
1750 - p = __d_path(path, root, s, m->size - m->count);
1751 - spin_unlock(&dcache_lock);
1752 + p = __d_path(path, root, s, m->size - m->count, 0);
1755 s = mangle_path(s, p, esc);
1756 diff -uprN linux-2.6.27./fs/stat.c linux-2.6.27/fs/stat.c
1757 --- linux-2.6.27./fs/stat.c 2008-10-10 00:13:53.000000000 +0200
1758 +++ linux-2.6.27/fs/stat.c 2008-10-29 02:02:00.123187352 +0100
1759 @@ -306,7 +306,7 @@ asmlinkage long sys_readlinkat(int dfd,
1762 if (inode->i_op && inode->i_op->readlink) {
1763 - error = security_inode_readlink(path.dentry);
1764 + error = security_inode_readlink(path.dentry, path.mnt);
1766 touch_atime(path.mnt, path.dentry);
1767 error = inode->i_op->readlink(path.dentry,
1768 diff -uprN linux-2.6.27./fs/utimes.c linux-2.6.27/fs/utimes.c
1769 --- linux-2.6.27./fs/utimes.c 2008-10-10 00:13:53.000000000 +0200
1770 +++ linux-2.6.27/fs/utimes.c 2008-10-29 02:02:01.893015871 +0100
1771 @@ -48,7 +48,8 @@ static bool nsec_valid(long nsec)
1772 return nsec >= 0 && nsec <= 999999999;
1775 -static int utimes_common(struct path *path, struct timespec *times)
1776 +static int utimes_common(struct path *path, struct timespec *times,
1780 struct iattr newattrs;
1781 @@ -102,7 +103,7 @@ static int utimes_common(struct path *pa
1784 mutex_lock(&inode->i_mutex);
1785 - error = notify_change(path->dentry, &newattrs);
1786 + error = fnotify_change(path->dentry, path->mnt, &newattrs, f);
1787 mutex_unlock(&inode->i_mutex);
1789 mnt_drop_write_and_out:
1790 @@ -149,7 +150,7 @@ long do_utimes(int dfd, char __user *fil
1794 - error = utimes_common(&file->f_path, times);
1795 + error = utimes_common(&file->f_path, times, file);
1799 @@ -162,7 +163,7 @@ long do_utimes(int dfd, char __user *fil
1803 - error = utimes_common(&path, times);
1804 + error = utimes_common(&path, times, NULL);
1808 diff -uprN linux-2.6.27./fs/xattr.c linux-2.6.27/fs/xattr.c
1809 --- linux-2.6.27./fs/xattr.c 2008-10-10 00:13:53.000000000 +0200
1810 +++ linux-2.6.27/fs/xattr.c 2008-10-29 02:02:01.962882939 +0100
1811 @@ -67,8 +67,8 @@ xattr_permission(struct inode *inode, co
1815 -vfs_setxattr(struct dentry *dentry, const char *name, const void *value,
1816 - size_t size, int flags)
1817 +vfs_setxattr(struct dentry *dentry, struct vfsmount *mnt, const char *name,
1818 + const void *value, size_t size, int flags, struct file *file)
1820 struct inode *inode = dentry->d_inode;
1822 @@ -78,7 +78,7 @@ vfs_setxattr(struct dentry *dentry, cons
1825 mutex_lock(&inode->i_mutex);
1826 - error = security_inode_setxattr(dentry, name, value, size, flags);
1827 + error = security_inode_setxattr(dentry, mnt, name, value, size, flags, file);
1830 error = -EOPNOTSUPP;
1831 @@ -86,7 +86,7 @@ vfs_setxattr(struct dentry *dentry, cons
1832 error = inode->i_op->setxattr(dentry, name, value, size, flags);
1834 fsnotify_xattr(dentry);
1835 - security_inode_post_setxattr(dentry, name, value,
1836 + security_inode_post_setxattr(dentry, mnt, name, value,
1839 } else if (!strncmp(name, XATTR_SECURITY_PREFIX,
1840 @@ -131,7 +131,8 @@ out_noalloc:
1841 EXPORT_SYMBOL_GPL(xattr_getsecurity);
1844 -vfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size)
1845 +vfs_getxattr(struct dentry *dentry, struct vfsmount *mnt, const char *name,
1846 + void *value, size_t size, struct file *file)
1848 struct inode *inode = dentry->d_inode;
1850 @@ -140,7 +141,7 @@ vfs_getxattr(struct dentry *dentry, cons
1854 - error = security_inode_getxattr(dentry, name);
1855 + error = security_inode_getxattr(dentry, mnt, name, file);
1859 @@ -167,18 +168,20 @@ nolsm:
1860 EXPORT_SYMBOL_GPL(vfs_getxattr);
1863 -vfs_listxattr(struct dentry *d, char *list, size_t size)
1864 +vfs_listxattr(struct dentry *dentry, struct vfsmount *mnt, char *list,
1865 + size_t size, struct file *file)
1867 + struct inode *inode = dentry->d_inode;
1870 - error = security_inode_listxattr(d);
1871 + error = security_inode_listxattr(dentry, mnt, file);
1874 error = -EOPNOTSUPP;
1875 - if (d->d_inode->i_op && d->d_inode->i_op->listxattr) {
1876 - error = d->d_inode->i_op->listxattr(d, list, size);
1878 - error = security_inode_listsecurity(d->d_inode, list, size);
1879 + if (inode->i_op && inode->i_op->listxattr)
1880 + error = inode->i_op->listxattr(dentry, list, size);
1882 + error = security_inode_listsecurity(inode, list, size);
1883 if (size && error > size)
1886 @@ -187,7 +190,8 @@ vfs_listxattr(struct dentry *d, char *li
1887 EXPORT_SYMBOL_GPL(vfs_listxattr);
1890 -vfs_removexattr(struct dentry *dentry, const char *name)
1891 +vfs_removexattr(struct dentry *dentry, struct vfsmount *mnt, const char *name,
1892 + struct file *file)
1894 struct inode *inode = dentry->d_inode;
1896 @@ -199,7 +203,7 @@ vfs_removexattr(struct dentry *dentry, c
1900 - error = security_inode_removexattr(dentry, name);
1901 + error = security_inode_removexattr(dentry, mnt, name, file);
1905 @@ -218,8 +222,8 @@ EXPORT_SYMBOL_GPL(vfs_removexattr);
1906 * Extended attribute SET operations
1909 -setxattr(struct dentry *d, const char __user *name, const void __user *value,
1910 - size_t size, int flags)
1911 +setxattr(struct dentry *dentry, struct vfsmount *mnt, const char __user *name,
1912 + const void __user *value, size_t size, int flags, struct file *file)
1915 void *kvalue = NULL;
1916 @@ -246,7 +250,7 @@ setxattr(struct dentry *d, const char __
1920 - error = vfs_setxattr(d, kname, kvalue, size, flags);
1921 + error = vfs_setxattr(dentry, mnt, kname, kvalue, size, flags, file);
1925 @@ -263,7 +267,7 @@ sys_setxattr(const char __user *pathname
1927 error = mnt_want_write(path.mnt);
1929 - error = setxattr(path.dentry, name, value, size, flags);
1930 + error = setxattr(path.dentry, path.mnt, name, value, size, flags, NULL);
1931 mnt_drop_write(path.mnt);
1934 @@ -282,7 +286,7 @@ sys_lsetxattr(const char __user *pathnam
1936 error = mnt_want_write(path.mnt);
1938 - error = setxattr(path.dentry, name, value, size, flags);
1939 + error = setxattr(path.dentry, path.mnt, name, value, size, flags, NULL);
1940 mnt_drop_write(path.mnt);
1943 @@ -304,7 +308,8 @@ sys_fsetxattr(int fd, const char __user
1944 audit_inode(NULL, dentry);
1945 error = mnt_want_write(f->f_path.mnt);
1947 - error = setxattr(dentry, name, value, size, flags);
1948 + error = setxattr(dentry, f->f_vfsmnt, name, value, size, flags,
1950 mnt_drop_write(f->f_path.mnt);
1953 @@ -315,8 +320,8 @@ sys_fsetxattr(int fd, const char __user
1954 * Extended attribute GET operations
1957 -getxattr(struct dentry *d, const char __user *name, void __user *value,
1959 +getxattr(struct dentry *dentry, struct vfsmount *mnt, const char __user *name,
1960 + void __user *value, size_t size, struct file *file)
1963 void *kvalue = NULL;
1964 @@ -336,7 +341,7 @@ getxattr(struct dentry *d, const char __
1968 - error = vfs_getxattr(d, kname, kvalue, size);
1969 + error = vfs_getxattr(dentry, mnt, kname, kvalue, size, file);
1971 if (size && copy_to_user(value, kvalue, error))
1973 @@ -359,7 +364,7 @@ sys_getxattr(const char __user *pathname
1974 error = user_path(pathname, &path);
1977 - error = getxattr(path.dentry, name, value, size);
1978 + error = getxattr(path.dentry, path.mnt, name, value, size, NULL);
1982 @@ -374,7 +379,7 @@ sys_lgetxattr(const char __user *pathnam
1983 error = user_lpath(pathname, &path);
1986 - error = getxattr(path.dentry, name, value, size);
1987 + error = getxattr(path.dentry, path.mnt, name, value, size, NULL);
1991 @@ -389,7 +394,7 @@ sys_fgetxattr(int fd, const char __user
1994 audit_inode(NULL, f->f_path.dentry);
1995 - error = getxattr(f->f_path.dentry, name, value, size);
1996 + error = getxattr(f->f_path.dentry, f->f_path.mnt, name, value, size, f);
2000 @@ -398,7 +403,8 @@ sys_fgetxattr(int fd, const char __user
2001 * Extended attribute LIST operations
2004 -listxattr(struct dentry *d, char __user *list, size_t size)
2005 +listxattr(struct dentry *dentry, struct vfsmount *mnt, char __user *list,
2006 + size_t size, struct file *file)
2010 @@ -411,7 +417,7 @@ listxattr(struct dentry *d, char __user
2014 - error = vfs_listxattr(d, klist, size);
2015 + error = vfs_listxattr(dentry, mnt, klist, size, file);
2017 if (size && copy_to_user(list, klist, error))
2019 @@ -433,7 +439,7 @@ sys_listxattr(const char __user *pathnam
2020 error = user_path(pathname, &path);
2023 - error = listxattr(path.dentry, list, size);
2024 + error = listxattr(path.dentry, path.mnt, list, size, NULL);
2028 @@ -447,7 +453,7 @@ sys_llistxattr(const char __user *pathna
2029 error = user_lpath(pathname, &path);
2032 - error = listxattr(path.dentry, list, size);
2033 + error = listxattr(path.dentry, path.mnt, list, size, NULL);
2037 @@ -462,7 +468,7 @@ sys_flistxattr(int fd, char __user *list
2040 audit_inode(NULL, f->f_path.dentry);
2041 - error = listxattr(f->f_path.dentry, list, size);
2042 + error = listxattr(f->f_path.dentry, f->f_path.mnt, list, size, f);
2046 @@ -471,7 +477,8 @@ sys_flistxattr(int fd, char __user *list
2047 * Extended attribute REMOVE operations
2050 -removexattr(struct dentry *d, const char __user *name)
2051 +removexattr(struct dentry *dentry, struct vfsmount *mnt,
2052 + const char __user *name, struct file *file)
2055 char kname[XATTR_NAME_MAX + 1];
2056 @@ -482,7 +489,7 @@ removexattr(struct dentry *d, const char
2060 - return vfs_removexattr(d, kname);
2061 + return vfs_removexattr(dentry, mnt, kname, file);
2065 @@ -496,7 +503,7 @@ sys_removexattr(const char __user *pathn
2067 error = mnt_want_write(path.mnt);
2069 - error = removexattr(path.dentry, name);
2070 + error = removexattr(path.dentry, path.mnt, name, NULL);
2071 mnt_drop_write(path.mnt);
2074 @@ -514,7 +521,7 @@ sys_lremovexattr(const char __user *path
2076 error = mnt_want_write(path.mnt);
2078 - error = removexattr(path.dentry, name);
2079 + error = removexattr(path.dentry, path.mnt, name, NULL);
2080 mnt_drop_write(path.mnt);
2083 @@ -535,7 +542,7 @@ sys_fremovexattr(int fd, const char __us
2084 audit_inode(NULL, dentry);
2085 error = mnt_want_write(f->f_path.mnt);
2087 - error = removexattr(dentry, name);
2088 + error = removexattr(dentry, f->f_path.mnt, name, f);
2089 mnt_drop_write(f->f_path.mnt);
2092 diff -uprN linux-2.6.27./include/linux/audit.h linux-2.6.27/include/linux/audit.h
2093 --- linux-2.6.27./include/linux/audit.h 2008-10-10 00:13:53.000000000 +0200
2094 +++ linux-2.6.27/include/linux/audit.h 2008-10-29 02:02:02.266214852 +0100
2096 * 1200 - 1299 messages internal to the audit daemon
2097 * 1300 - 1399 audit event messages
2098 * 1400 - 1499 SE Linux use
2099 - * 1500 - 1599 kernel LSPP events
2100 + * 1500 - 1599 AppArmor use
2101 * 1600 - 1699 kernel crypto events
2102 * 1700 - 1799 kernel anomaly records
2103 * 1800 - 1999 future kernel use (maybe integrity labels and related events)
2104 @@ -119,6 +119,13 @@
2105 #define AUDIT_MAC_UNLBL_STCADD 1416 /* NetLabel: add a static label */
2106 #define AUDIT_MAC_UNLBL_STCDEL 1417 /* NetLabel: del a static label */
2108 +#define AUDIT_APPARMOR_AUDIT 1501 /* AppArmor audited grants */
2109 +#define AUDIT_APPARMOR_ALLOWED 1502 /* Allowed Access for learning */
2110 +#define AUDIT_APPARMOR_DENIED 1503
2111 +#define AUDIT_APPARMOR_HINT 1504 /* Process Tracking information */
2112 +#define AUDIT_APPARMOR_STATUS 1505 /* Changes in config */
2113 +#define AUDIT_APPARMOR_ERROR 1506 /* Internal AppArmor Errors */
2115 #define AUDIT_FIRST_KERN_ANOM_MSG 1700
2116 #define AUDIT_LAST_KERN_ANOM_MSG 1799
2117 #define AUDIT_ANOM_PROMISCUOUS 1700 /* Device changed promiscuous mode */
2118 @@ -545,6 +552,9 @@ extern void audit_log(struct audit_
2119 __attribute__((format(printf,4,5)));
2121 extern struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, int type);
2122 +extern void audit_log_vformat(struct audit_buffer *ab,
2123 + const char *fmt, va_list args)
2124 + __attribute__((format(printf,2,0)));
2125 extern void audit_log_format(struct audit_buffer *ab,
2126 const char *fmt, ...)
2127 __attribute__((format(printf,2,3)));
2128 diff -uprN linux-2.6.27./include/linux/dcache.h linux-2.6.27/include/linux/dcache.h
2129 --- linux-2.6.27./include/linux/dcache.h 2008-10-10 00:13:53.000000000 +0200
2130 +++ linux-2.6.27/include/linux/dcache.h 2008-10-29 02:02:01.634722088 +0100
2131 @@ -299,9 +299,12 @@ extern int d_validate(struct dentry *, s
2133 * helper function for dentry_operations.d_dname() members
2135 +#define D_PATH_FAIL_DELETED 1
2136 +#define D_PATH_DISCONNECT 2
2137 extern char *dynamic_dname(struct dentry *, char *, int, const char *, ...);
2139 -extern char *__d_path(const struct path *path, struct path *root, char *, int);
2140 +extern char *__d_path(const struct path *path, struct path *root, char *, int,
2142 extern char *d_path(const struct path *, char *, int);
2143 extern char *dentry_path(struct dentry *, char *, int);
2145 diff -uprN linux-2.6.27./include/linux/fs.h linux-2.6.27/include/linux/fs.h
2146 --- linux-2.6.27./include/linux/fs.h 2008-10-10 00:13:53.000000000 +0200
2147 +++ linux-2.6.27/include/linux/fs.h 2008-10-29 02:02:02.264908196 +0100
2148 @@ -361,6 +361,10 @@ struct iattr {
2149 * Not an attribute, but an auxilary info for filesystems wanting to
2150 * implement an ftruncate() like method. NOTE: filesystem should
2151 * check for (ia_valid & ATTR_FILE), and not for (ia_file != NULL).
2153 + * NOTE: With patches.apparmor/fsetattr.diff applied, this is
2154 + * for compatibility with external file system modules only. There
2155 + * should not be any in-kernel users left.
2157 struct file *ia_file;
2159 @@ -1160,13 +1164,13 @@ extern void unlock_super(struct super_bl
2161 extern int vfs_permission(struct nameidata *, int);
2162 extern int vfs_create(struct inode *, struct dentry *, int, struct nameidata *);
2163 -extern int vfs_mkdir(struct inode *, struct dentry *, int);
2164 -extern int vfs_mknod(struct inode *, struct dentry *, int, dev_t);
2165 -extern int vfs_symlink(struct inode *, struct dentry *, const char *);
2166 -extern int vfs_link(struct dentry *, struct inode *, struct dentry *);
2167 -extern int vfs_rmdir(struct inode *, struct dentry *);
2168 -extern int vfs_unlink(struct inode *, struct dentry *);
2169 -extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
2170 +extern int vfs_mkdir(struct inode *, struct dentry *, struct vfsmount *, int);
2171 +extern int vfs_mknod(struct inode *, struct dentry *, struct vfsmount *, int, dev_t);
2172 +extern int vfs_symlink(struct inode *, struct dentry *, struct vfsmount *, const char *);
2173 +extern int vfs_link(struct dentry *, struct vfsmount *, struct inode *, struct dentry *, struct vfsmount *);
2174 +extern int vfs_rmdir(struct inode *, struct dentry *, struct vfsmount *);
2175 +extern int vfs_unlink(struct inode *, struct dentry *, struct vfsmount *);
2176 +extern int vfs_rename(struct inode *, struct dentry *, struct vfsmount *, struct inode *, struct dentry *, struct vfsmount *);
2179 * VFS dentry helper functions.
2180 @@ -1179,6 +1183,11 @@ extern void dentry_unhash(struct dentry
2181 extern int file_permission(struct file *, int);
2184 + * VFS path helper functions.
2186 +extern int path_permission(struct path *, int);
2191 * NOTE! These match bits 12..15 of stat.st_mode
2192 @@ -1260,6 +1269,7 @@ struct file_operations {
2193 ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
2194 ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
2195 int (*setlease)(struct file *, long, struct file_lock **);
2196 + int (*fsetattr)(struct file *, struct iattr *);
2199 struct inode_operations {
2200 @@ -1612,8 +1622,8 @@ static inline int break_lease(struct ino
2204 -extern int do_truncate(struct dentry *, loff_t start, unsigned int time_attrs,
2205 - struct file *filp);
2206 +extern int do_truncate(struct dentry *, struct vfsmount *, loff_t start,
2207 + unsigned int time_attrs, struct file *filp);
2208 extern long do_sys_open(int dfd, const char __user *filename, int flags,
2210 extern struct file *filp_open(const char *, int, int);
2211 @@ -1771,7 +1781,8 @@ extern int do_remount_sb(struct super_bl
2213 extern sector_t bmap(struct inode *, sector_t);
2215 -extern int notify_change(struct dentry *, struct iattr *);
2216 +extern int notify_change(struct dentry *, struct vfsmount *, struct iattr *);
2217 +extern int fnotify_change(struct dentry *, struct vfsmount *, struct iattr *, struct file *);
2218 extern int inode_permission(struct inode *, int);
2219 extern int generic_permission(struct inode *, int,
2220 int (*check_acl)(struct inode *, int));
2221 diff -uprN linux-2.6.27./include/linux/mount.h linux-2.6.27/include/linux/mount.h
2222 --- linux-2.6.27./include/linux/mount.h 2008-10-10 00:13:53.000000000 +0200
2223 +++ linux-2.6.27/include/linux/mount.h 2008-10-29 02:02:01.674077632 +0100
2224 @@ -114,4 +114,6 @@ extern void mark_mounts_for_expiry(struc
2225 extern spinlock_t vfsmount_lock;
2226 extern dev_t name_to_dev_t(char *name);
2228 +extern char *d_namespace_path(struct dentry *, struct vfsmount *, char *, int);
2230 #endif /* _LINUX_MOUNT_H */
2231 diff -uprN linux-2.6.27./include/linux/nfsd/nfsd.h linux-2.6.27/include/linux/nfsd/nfsd.h
2232 --- linux-2.6.27./include/linux/nfsd/nfsd.h 2008-10-10 00:13:53.000000000 +0200
2233 +++ linux-2.6.27/include/linux/nfsd/nfsd.h 2008-10-29 02:02:01.216214540 +0100
2234 @@ -85,7 +85,8 @@ __be32 nfsd_setattr(struct svc_rqst *,
2235 #ifdef CONFIG_NFSD_V4
2236 __be32 nfsd4_set_nfs4_acl(struct svc_rqst *, struct svc_fh *,
2238 -int nfsd4_get_nfs4_acl(struct svc_rqst *, struct dentry *, struct nfs4_acl **);
2239 +int nfsd4_get_nfs4_acl(struct svc_rqst *, struct dentry *,
2240 + struct vfsmount *mnt, struct nfs4_acl **);
2241 #endif /* CONFIG_NFSD_V4 */
2242 __be32 nfsd_create(struct svc_rqst *, struct svc_fh *,
2243 char *name, int len, struct iattr *attrs,
2244 diff -uprN linux-2.6.27./include/linux/security.h linux-2.6.27/include/linux/security.h
2245 --- linux-2.6.27./include/linux/security.h 2008-10-10 00:13:53.000000000 +0200
2246 +++ linux-2.6.27/include/linux/security.h 2008-10-29 02:02:02.149345476 +0100
2247 @@ -54,9 +54,11 @@ extern void cap_capset_set(struct task_s
2248 extern int cap_bprm_set_security(struct linux_binprm *bprm);
2249 extern void cap_bprm_apply_creds(struct linux_binprm *bprm, int unsafe);
2250 extern int cap_bprm_secureexec(struct linux_binprm *bprm);
2251 -extern int cap_inode_setxattr(struct dentry *dentry, const char *name,
2252 - const void *value, size_t size, int flags);
2253 -extern int cap_inode_removexattr(struct dentry *dentry, const char *name);
2254 +extern int cap_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
2255 + const char *name, const void *value, size_t size,
2256 + int flags, struct file *file);
2257 +extern int cap_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
2258 + const char *name, struct file *file);
2259 extern int cap_inode_need_killpriv(struct dentry *dentry);
2260 extern int cap_inode_killpriv(struct dentry *dentry);
2261 extern int cap_task_post_setuid(uid_t old_ruid, uid_t old_euid, uid_t old_suid, int flags);
2262 @@ -337,23 +339,28 @@ static inline void security_free_mnt_opt
2263 * Check permission to create a regular file.
2264 * @dir contains inode structure of the parent of the new file.
2265 * @dentry contains the dentry structure for the file to be created.
2266 + * @mnt is the vfsmount corresponding to @dentry (may be NULL).
2267 * @mode contains the file mode of the file to be created.
2268 * Return 0 if permission is granted.
2270 * Check permission before creating a new hard link to a file.
2271 * @old_dentry contains the dentry structure for an existing link to the file.
2272 + * @old_mnt is the vfsmount corresponding to @old_dentry (may be NULL).
2273 * @dir contains the inode structure of the parent directory of the new link.
2274 * @new_dentry contains the dentry structure for the new link.
2275 + * @new_mnt is the vfsmount corresponding to @new_dentry (may be NULL).
2276 * Return 0 if permission is granted.
2278 * Check the permission to remove a hard link to a file.
2279 * @dir contains the inode structure of parent directory of the file.
2280 * @dentry contains the dentry structure for file to be unlinked.
2281 + * @mnt is the vfsmount corresponding to @dentry (may be NULL).
2282 * Return 0 if permission is granted.
2284 * Check the permission to create a symbolic link to a file.
2285 * @dir contains the inode structure of parent directory of the symbolic link.
2286 * @dentry contains the dentry structure of the symbolic link.
2287 + * @mnt is the vfsmount corresponding to @dentry (may be NULL).
2288 * @old_name contains the pathname of file.
2289 * Return 0 if permission is granted.
2291 @@ -361,12 +368,14 @@ static inline void security_free_mnt_opt
2292 * associated with inode strcture @dir.
2293 * @dir containst the inode structure of parent of the directory to be created.
2294 * @dentry contains the dentry structure of new directory.
2295 + * @mnt is the vfsmount corresponding to @dentry (may be NULL).
2296 * @mode contains the mode of new directory.
2297 * Return 0 if permission is granted.
2299 * Check the permission to remove a directory.
2300 * @dir contains the inode structure of parent of the directory to be removed.
2301 * @dentry contains the dentry structure of directory to be removed.
2302 + * @mnt is the vfsmount corresponding to @dentry (may be NULL).
2303 * Return 0 if permission is granted.
2305 * Check permissions when creating a special file (or a socket or a fifo
2306 @@ -375,6 +384,7 @@ static inline void security_free_mnt_opt
2307 * and not this hook.
2308 * @dir contains the inode structure of parent of the new file.
2309 * @dentry contains the dentry structure of the new file.
2310 + * @mnt is the vfsmount corresponding to @dentry (may be NULL).
2311 * @mode contains the mode of the new file.
2312 * @dev contains the device number.
2313 * Return 0 if permission is granted.
2314 @@ -382,12 +392,15 @@ static inline void security_free_mnt_opt
2315 * Check for permission to rename a file or directory.
2316 * @old_dir contains the inode structure for parent of the old link.
2317 * @old_dentry contains the dentry structure of the old link.
2318 + * @old_mnt is the vfsmount corresponding to @old_dentry (may be NULL).
2319 * @new_dir contains the inode structure for parent of the new link.
2320 * @new_dentry contains the dentry structure of the new link.
2321 + * @new_mnt is the vfsmount corresponding to @new_dentry (may be NULL).
2322 * Return 0 if permission is granted.
2324 * Check the permission to read the symbolic link.
2325 * @dentry contains the dentry structure for the file link.
2326 + * @mnt is the vfsmount corresponding to @dentry (may be NULL).
2327 * Return 0 if permission is granted.
2328 * @inode_follow_link:
2329 * Check permission to follow a symbolic link when looking up a pathname.
2330 @@ -411,6 +424,7 @@ static inline void security_free_mnt_opt
2331 * file attributes change (such as when a file is truncated, chown/chmod
2332 * operations, transferring disk quotas, etc).
2333 * @dentry contains the dentry structure for the file.
2334 + * @mnt is the vfsmount corresponding to @dentry (may be NULL).
2335 * @attr is the iattr structure containing the new file attributes.
2336 * Return 0 if permission is granted.
2338 @@ -426,18 +440,18 @@ static inline void security_free_mnt_opt
2341 * Check permission before setting the extended attributes
2342 - * @value identified by @name for @dentry.
2343 + * @value identified by @name for @dentry and @mnt.
2344 * Return 0 if permission is granted.
2345 * @inode_post_setxattr:
2346 * Update inode security field after successful setxattr operation.
2347 - * @value identified by @name for @dentry.
2348 + * @value identified by @name for @dentry and @mnt.
2350 * Check permission before obtaining the extended attributes
2351 - * identified by @name for @dentry.
2352 + * identified by @name for @dentry and @mnt.
2353 * Return 0 if permission is granted.
2355 * Check permission before obtaining the list of extended attribute
2356 - * names for @dentry.
2357 + * names for @dentry and @mnt.
2358 * Return 0 if permission is granted.
2359 * @inode_removexattr:
2360 * Check permission before removing the extended attribute
2361 @@ -578,6 +592,20 @@ static inline void security_free_mnt_opt
2362 * file_permission, and recheck access if anything has changed
2363 * since inode_permission.
2365 + * Security hook for path
2367 + * @path_permission:
2368 + * Check permission before accessing a path. This hook is called by the
2369 + * existing Linux permission function, so a security module can use it to
2370 + * provide additional checking for existing Linux permission checks.
2371 + * Notice that this hook is called when a file is opened (as well as many
2372 + * other operations), whereas the file_security_ops permission hook is
2373 + * called when the actual read/write operations are performed. This
2374 + * hook is optional and if absent, inode_permission will be substituted.
2375 + * @path contains the path structure to check.
2376 + * @mask contains the permission mask.
2377 + * Return 0 if permission is granted.
2379 * Security hooks for task operations.
2382 @@ -1354,32 +1382,45 @@ struct security_operations {
2383 void (*inode_free_security) (struct inode *inode);
2384 int (*inode_init_security) (struct inode *inode, struct inode *dir,
2385 char **name, void **value, size_t *len);
2386 - int (*inode_create) (struct inode *dir,
2387 - struct dentry *dentry, int mode);
2388 - int (*inode_link) (struct dentry *old_dentry,
2389 - struct inode *dir, struct dentry *new_dentry);
2390 - int (*inode_unlink) (struct inode *dir, struct dentry *dentry);
2391 - int (*inode_symlink) (struct inode *dir,
2392 - struct dentry *dentry, const char *old_name);
2393 - int (*inode_mkdir) (struct inode *dir, struct dentry *dentry, int mode);
2394 - int (*inode_rmdir) (struct inode *dir, struct dentry *dentry);
2395 + int (*inode_create) (struct inode *dir, struct dentry *dentry,
2396 + struct vfsmount *mnt, int mode);
2397 + int (*inode_link) (struct dentry *old_dentry, struct vfsmount *old_mnt,
2398 + struct inode *dir, struct dentry *new_dentry,
2399 + struct vfsmount *new_mnt);
2400 + int (*inode_unlink) (struct inode *dir, struct dentry *dentry,
2401 + struct vfsmount *mnt);
2402 + int (*inode_symlink) (struct inode *dir, struct dentry *dentry,
2403 + struct vfsmount *mnt, const char *old_name);
2404 + int (*inode_mkdir) (struct inode *dir, struct dentry *dentry,
2405 + struct vfsmount *mnt, int mode);
2406 + int (*inode_rmdir) (struct inode *dir, struct dentry *dentry,
2407 + struct vfsmount *mnt);
2408 int (*inode_mknod) (struct inode *dir, struct dentry *dentry,
2409 - int mode, dev_t dev);
2410 + struct vfsmount *mnt, int mode, dev_t dev);
2411 int (*inode_rename) (struct inode *old_dir, struct dentry *old_dentry,
2412 - struct inode *new_dir, struct dentry *new_dentry);
2413 - int (*inode_readlink) (struct dentry *dentry);
2414 + struct vfsmount *old_mnt,
2415 + struct inode *new_dir, struct dentry *new_dentry,
2416 + struct vfsmount *new_mnt);
2417 + int (*inode_readlink) (struct dentry *dentry, struct vfsmount *mnt);
2418 int (*inode_follow_link) (struct dentry *dentry, struct nameidata *nd);
2419 int (*inode_permission) (struct inode *inode, int mask);
2420 - int (*inode_setattr) (struct dentry *dentry, struct iattr *attr);
2421 + int (*inode_setattr) (struct dentry *dentry, struct vfsmount *,
2422 + struct iattr *attr);
2423 int (*inode_getattr) (struct vfsmount *mnt, struct dentry *dentry);
2424 void (*inode_delete) (struct inode *inode);
2425 - int (*inode_setxattr) (struct dentry *dentry, const char *name,
2426 - const void *value, size_t size, int flags);
2427 - void (*inode_post_setxattr) (struct dentry *dentry, const char *name,
2428 - const void *value, size_t size, int flags);
2429 - int (*inode_getxattr) (struct dentry *dentry, const char *name);
2430 - int (*inode_listxattr) (struct dentry *dentry);
2431 - int (*inode_removexattr) (struct dentry *dentry, const char *name);
2432 + int (*inode_setxattr) (struct dentry *dentry, struct vfsmount *mnt,
2433 + const char *name, const void *value, size_t size,
2434 + int flags, struct file *file);
2435 + void (*inode_post_setxattr) (struct dentry *dentry,
2436 + struct vfsmount *mnt,
2437 + const char *name, const void *value,
2438 + size_t size, int flags);
2439 + int (*inode_getxattr) (struct dentry *dentry, struct vfsmount *mnt,
2440 + const char *name, struct file *file);
2441 + int (*inode_listxattr) (struct dentry *dentry, struct vfsmount *mnt,
2442 + struct file *file);
2443 + int (*inode_removexattr) (struct dentry *dentry, struct vfsmount *mnt,
2444 + const char *name, struct file *file);
2445 int (*inode_need_killpriv) (struct dentry *dentry);
2446 int (*inode_killpriv) (struct dentry *dentry);
2447 int (*inode_getsecurity) (const struct inode *inode, const char *name, void **buffer, bool alloc);
2448 @@ -1407,6 +1448,7 @@ struct security_operations {
2449 struct fown_struct *fown, int sig);
2450 int (*file_receive) (struct file *file);
2451 int (*dentry_open) (struct file *file);
2452 + int (*path_permission) (struct path *path, int mask);
2454 int (*task_create) (unsigned long clone_flags);
2455 int (*task_alloc_security) (struct task_struct *p);
2456 @@ -1622,30 +1664,43 @@ int security_inode_alloc(struct inode *i
2457 void security_inode_free(struct inode *inode);
2458 int security_inode_init_security(struct inode *inode, struct inode *dir,
2459 char **name, void **value, size_t *len);
2460 -int security_inode_create(struct inode *dir, struct dentry *dentry, int mode);
2461 -int security_inode_link(struct dentry *old_dentry, struct inode *dir,
2462 - struct dentry *new_dentry);
2463 -int security_inode_unlink(struct inode *dir, struct dentry *dentry);
2464 +int security_inode_create(struct inode *dir, struct dentry *dentry,
2465 + struct vfsmount *mnt, int mode);
2466 +int security_inode_link(struct dentry *old_dentry, struct vfsmount *old_mnt,
2467 + struct inode *dir, struct dentry *new_dentry,
2468 + struct vfsmount *new_mnt);
2469 +int security_inode_unlink(struct inode *dir, struct dentry *dentry,
2470 + struct vfsmount *mnt);
2471 int security_inode_symlink(struct inode *dir, struct dentry *dentry,
2472 - const char *old_name);
2473 -int security_inode_mkdir(struct inode *dir, struct dentry *dentry, int mode);
2474 -int security_inode_rmdir(struct inode *dir, struct dentry *dentry);
2475 -int security_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev);
2476 + struct vfsmount *mnt, const char *old_name);
2477 +int security_inode_mkdir(struct inode *dir, struct dentry *dentry,
2478 + struct vfsmount *mnt, int mode);
2479 +int security_inode_rmdir(struct inode *dir, struct dentry *dentry,
2480 + struct vfsmount *mnt);
2481 +int security_inode_mknod(struct inode *dir, struct dentry *dentry,
2482 + struct vfsmount *mnt, int mode, dev_t dev);
2483 int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
2484 - struct inode *new_dir, struct dentry *new_dentry);
2485 -int security_inode_readlink(struct dentry *dentry);
2486 + struct vfsmount *old_mnt, struct inode *new_dir,
2487 + struct dentry *new_dentry, struct vfsmount *new_mnt);
2488 +int security_inode_readlink(struct dentry *dentry, struct vfsmount *mnt);
2489 int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd);
2490 int security_inode_permission(struct inode *inode, int mask);
2491 -int security_inode_setattr(struct dentry *dentry, struct iattr *attr);
2492 +int security_inode_setattr(struct dentry *dentry, struct vfsmount *mnt,
2493 + struct iattr *attr);
2494 int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry);
2495 void security_inode_delete(struct inode *inode);
2496 -int security_inode_setxattr(struct dentry *dentry, const char *name,
2497 - const void *value, size_t size, int flags);
2498 -void security_inode_post_setxattr(struct dentry *dentry, const char *name,
2499 - const void *value, size_t size, int flags);
2500 -int security_inode_getxattr(struct dentry *dentry, const char *name);
2501 -int security_inode_listxattr(struct dentry *dentry);
2502 -int security_inode_removexattr(struct dentry *dentry, const char *name);
2503 +int security_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
2504 + const char *name, const void *value,
2505 + size_t size, int flags, struct file *file);
2506 +void security_inode_post_setxattr(struct dentry *dentry, struct vfsmount *mnt,
2507 + const char *name, const void *value,
2508 + size_t size, int flags);
2509 +int security_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
2510 + const char *name, struct file *file);
2511 +int security_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt,
2512 + struct file *file);
2513 +int security_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
2514 + const char *name, struct file *file);
2515 int security_inode_need_killpriv(struct dentry *dentry);
2516 int security_inode_killpriv(struct dentry *dentry);
2517 int security_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc);
2518 @@ -1668,6 +1723,7 @@ int security_file_send_sigiotask(struct
2519 struct fown_struct *fown, int sig);
2520 int security_file_receive(struct file *file);
2521 int security_dentry_open(struct file *file);
2522 +int security_path_permission(struct path *path, int mask);
2523 int security_task_create(unsigned long clone_flags);
2524 int security_task_alloc(struct task_struct *p);
2525 void security_task_free(struct task_struct *p);
2526 @@ -1968,26 +2024,31 @@ static inline int security_inode_init_se
2528 static inline int security_inode_create(struct inode *dir,
2529 struct dentry *dentry,
2530 + struct vfsmount *mnt,
2536 static inline int security_inode_link(struct dentry *old_dentry,
2537 - struct inode *dir,
2538 - struct dentry *new_dentry)
2539 + struct vfsmount *old_mnt,
2540 + struct inode *dir,
2541 + struct dentry *new_dentry,
2542 + struct vfsmount *new_mnt)
2547 static inline int security_inode_unlink(struct inode *dir,
2548 - struct dentry *dentry)
2549 + struct dentry *dentry,
2550 + struct vfsmount *mnt)
2555 static inline int security_inode_symlink(struct inode *dir,
2556 struct dentry *dentry,
2557 + struct vfsmount *mnt,
2558 const char *old_name)
2561 @@ -1995,19 +2056,22 @@ static inline int security_inode_symlink
2563 static inline int security_inode_mkdir(struct inode *dir,
2564 struct dentry *dentry,
2565 + struct vfsmount *mnt,
2571 static inline int security_inode_rmdir(struct inode *dir,
2572 - struct dentry *dentry)
2573 + struct dentry *dentry,
2574 + struct vfsmount *mnt)
2579 static inline int security_inode_mknod(struct inode *dir,
2580 struct dentry *dentry,
2581 + struct vfsmount *mnt,
2582 int mode, dev_t dev)
2585 @@ -2015,13 +2079,16 @@ static inline int security_inode_mknod(s
2587 static inline int security_inode_rename(struct inode *old_dir,
2588 struct dentry *old_dentry,
2589 + struct vfsmount *old_mnt,
2590 struct inode *new_dir,
2591 - struct dentry *new_dentry)
2592 + struct dentry *new_dentry,
2593 + struct vfsmount *new_mnt)
2598 -static inline int security_inode_readlink(struct dentry *dentry)
2599 +static inline int security_inode_readlink(struct dentry *dentry,
2600 + struct vfsmount *mnt)
2604 @@ -2038,7 +2105,8 @@ static inline int security_inode_permiss
2607 static inline int security_inode_setattr(struct dentry *dentry,
2608 - struct iattr *attr)
2609 + struct vfsmount *mnt,
2610 + struct iattr *attr)
2614 @@ -2053,30 +2121,42 @@ static inline void security_inode_delete
2617 static inline int security_inode_setxattr(struct dentry *dentry,
2618 - const char *name, const void *value, size_t size, int flags)
2619 + struct vfsmount *mnt,
2620 + const char *name, const void *value,
2621 + size_t size, int flags,
2622 + struct file *file)
2624 - return cap_inode_setxattr(dentry, name, value, size, flags);
2625 + return cap_inode_setxattr(dentry, mnt, name, value, size, flags, file);
2628 static inline void security_inode_post_setxattr(struct dentry *dentry,
2629 - const char *name, const void *value, size_t size, int flags)
2630 + struct vfsmount *mnt,
2632 + const void *value,
2633 + size_t size, int flags)
2636 static inline int security_inode_getxattr(struct dentry *dentry,
2638 + struct vfsmount *mnt,
2640 + struct file *file)
2645 -static inline int security_inode_listxattr(struct dentry *dentry)
2646 +static inline int security_inode_listxattr(struct dentry *dentry,
2647 + struct vfsmount *mnt,
2648 + struct file *file)
2653 static inline int security_inode_removexattr(struct dentry *dentry,
2655 + struct vfsmount *mnt,
2657 + struct file *file)
2659 - return cap_inode_removexattr(dentry, name);
2660 + return cap_inode_removexattr(dentry, mnt, name, file);
2663 static inline int security_inode_need_killpriv(struct dentry *dentry)
2664 @@ -2177,6 +2257,11 @@ static inline int security_dentry_open(s
2668 +static inline int security_path_permission(struct path *path, int mask)
2673 static inline int security_task_create(unsigned long clone_flags)
2676 diff -uprN linux-2.6.27./include/linux/sysctl.h linux-2.6.27/include/linux/sysctl.h
2677 --- linux-2.6.27./include/linux/sysctl.h 2008-10-10 00:13:53.000000000 +0200
2678 +++ linux-2.6.27/include/linux/sysctl.h 2008-10-29 02:02:02.110260164 +0100
2679 @@ -996,6 +996,8 @@ extern int proc_doulongvec_minmax(struct
2680 extern int proc_doulongvec_ms_jiffies_minmax(struct ctl_table *table, int,
2681 struct file *, void __user *, size_t *, loff_t *);
2683 +extern char *sysctl_pathname(ctl_table *, char *, int);
2685 extern int do_sysctl (int __user *name, int nlen,
2686 void __user *oldval, size_t __user *oldlenp,
2687 void __user *newval, size_t newlen);
2688 diff -uprN linux-2.6.27./include/linux/xattr.h linux-2.6.27/include/linux/xattr.h
2689 --- linux-2.6.27./include/linux/xattr.h 2008-10-10 00:13:53.000000000 +0200
2690 +++ linux-2.6.27/include/linux/xattr.h 2008-10-29 02:02:01.996215347 +0100
2694 #include <linux/types.h>
2695 +#include <linux/mount.h>
2696 +#include <linux/fs.h>
2699 #define XATTR_OS2_PREFIX "os2."
2700 @@ -47,10 +49,10 @@ struct xattr_handler {
2703 ssize_t xattr_getsecurity(struct inode *, const char *, void *, size_t);
2704 -ssize_t vfs_getxattr(struct dentry *, const char *, void *, size_t);
2705 -ssize_t vfs_listxattr(struct dentry *d, char *list, size_t size);
2706 -int vfs_setxattr(struct dentry *, const char *, const void *, size_t, int);
2707 -int vfs_removexattr(struct dentry *, const char *);
2708 +ssize_t vfs_getxattr(struct dentry *, struct vfsmount *, const char *, void *, size_t, struct file *file);
2709 +ssize_t vfs_listxattr(struct dentry *d, struct vfsmount *, char *list, size_t size, struct file *file);
2710 +int vfs_setxattr(struct dentry *, struct vfsmount *, const char *, const void *, size_t, int, struct file *file);
2711 +int vfs_removexattr(struct dentry *, struct vfsmount *mnt, const char *, struct file *file);
2713 ssize_t generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size);
2714 ssize_t generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size);
2715 diff -uprN linux-2.6.27./ipc/mqueue.c linux-2.6.27/ipc/mqueue.c
2716 --- linux-2.6.27./ipc/mqueue.c 2008-10-10 00:13:53.000000000 +0200
2717 +++ linux-2.6.27/ipc/mqueue.c 2008-10-29 02:02:00.652678045 +0100
2718 @@ -745,7 +745,7 @@ asmlinkage long sys_mq_unlink(const char
2719 err = mnt_want_write(mqueue_mnt);
2722 - err = vfs_unlink(dentry->d_parent->d_inode, dentry);
2723 + err = vfs_unlink(dentry->d_parent->d_inode, dentry, mqueue_mnt);
2724 mnt_drop_write(mqueue_mnt);
2727 diff -uprN linux-2.6.27./kernel/audit.c linux-2.6.27/kernel/audit.c
2728 --- linux-2.6.27./kernel/audit.c 2008-10-10 00:13:53.000000000 +0200
2729 +++ linux-2.6.27/kernel/audit.c 2008-10-29 02:02:02.282882034 +0100
2730 @@ -1231,8 +1231,7 @@ static inline int audit_expand(struct au
2731 * will be called a second time. Currently, we assume that a printk
2732 * can't format message larger than 1024 bytes, so we don't either.
2734 -static void audit_log_vformat(struct audit_buffer *ab, const char *fmt,
2736 +void audit_log_vformat(struct audit_buffer *ab, const char *fmt, va_list args)
2739 struct sk_buff *skb;
2740 @@ -1506,3 +1505,6 @@ EXPORT_SYMBOL(audit_log_start);
2741 EXPORT_SYMBOL(audit_log_end);
2742 EXPORT_SYMBOL(audit_log_format);
2743 EXPORT_SYMBOL(audit_log);
2744 +EXPORT_SYMBOL_GPL(audit_log_vformat);
2745 +EXPORT_SYMBOL_GPL(audit_log_untrustedstring);
2746 +EXPORT_SYMBOL_GPL(audit_log_d_path);
2747 diff -uprN linux-2.6.27./kernel/cgroup.c linux-2.6.27/kernel/cgroup.c
2748 --- linux-2.6.27./kernel/cgroup.c 2008-10-10 00:13:53.000000000 +0200
2749 +++ linux-2.6.27/kernel/cgroup.c 2008-10-29 02:01:59.706048714 +0100
2750 @@ -2905,7 +2905,7 @@ int cgroup_clone(struct task_struct *tsk
2753 /* Create the cgroup directory, which also creates the cgroup */
2754 - ret = vfs_mkdir(inode, dentry, S_IFDIR | 0755);
2755 + ret = vfs_mkdir(inode, dentry, NULL, S_IFDIR | 0755);
2756 child = __d_cgrp(dentry);
2759 diff -uprN linux-2.6.27./kernel/sysctl.c linux-2.6.27/kernel/sysctl.c
2760 --- linux-2.6.27./kernel/sysctl.c 2008-10-10 00:13:53.000000000 +0200
2761 +++ linux-2.6.27/kernel/sysctl.c 2008-10-29 02:02:02.130590271 +0100
2762 @@ -1506,6 +1506,33 @@ void register_sysctl_root(struct ctl_tab
2763 spin_unlock(&sysctl_lock);
2766 +char *sysctl_pathname(struct ctl_table *table, char *buffer, int buflen)
2770 + buffer += --buflen;
2774 + int namelen = strlen(table->procname);
2776 + if (buflen < namelen + 1)
2778 + buflen -= namelen + 1;
2779 + buffer -= namelen;
2780 + memcpy(buffer, table->procname, namelen);
2782 + table = table->parent;
2787 + memcpy(buffer, "/sys", 4);
2791 +EXPORT_SYMBOL_GPL(sysctl_pathname);
2793 #ifdef CONFIG_SYSCTL_SYSCALL
2794 /* Perform the actual read/write of a sysctl table entry. */
2795 static int do_sysctl_strategy(struct ctl_table_root *root,
2796 diff -uprN linux-2.6.27./mm/filemap.c linux-2.6.27/mm/filemap.c
2797 --- linux-2.6.27./mm/filemap.c 2008-10-10 00:13:53.000000000 +0200
2798 +++ linux-2.6.27/mm/filemap.c 2008-10-29 02:01:59.480174096 +0100
2799 @@ -1760,12 +1760,12 @@ int should_remove_suid(struct dentry *de
2801 EXPORT_SYMBOL(should_remove_suid);
2803 -static int __remove_suid(struct dentry *dentry, int kill)
2804 +static int __remove_suid(struct path *path, int kill)
2806 struct iattr newattrs;
2808 newattrs.ia_valid = ATTR_FORCE | kill;
2809 - return notify_change(dentry, &newattrs);
2810 + return notify_change(path->dentry, path->mnt, &newattrs);
2813 int file_remove_suid(struct file *file)
2814 @@ -1780,7 +1780,7 @@ int file_remove_suid(struct file *file)
2816 error = security_inode_killpriv(dentry);
2817 if (!error && killsuid)
2818 - error = __remove_suid(dentry, killsuid);
2819 + error = __remove_suid(&file->f_path, killsuid);
2823 diff -uprN linux-2.6.27./net/unix/af_unix.c linux-2.6.27/net/unix/af_unix.c
2824 --- linux-2.6.27./net/unix/af_unix.c 2008-10-10 00:13:53.000000000 +0200
2825 +++ linux-2.6.27/net/unix/af_unix.c 2008-10-29 02:01:59.886248280 +0100
2826 @@ -827,7 +827,8 @@ static int unix_bind(struct socket *sock
2827 goto out_mknod_dput;
2830 - err = vfs_mknod(nd.path.dentry->d_inode, dentry, mode, 0);
2831 + err = vfs_mknod(nd.path.dentry->d_inode, dentry, nd.path.mnt,
2833 mnt_drop_write(nd.path.mnt);
2835 goto out_mknod_dput;
2836 diff -uprN linux-2.6.27./security/Kconfig linux-2.6.27/security/Kconfig
2837 --- linux-2.6.27./security/Kconfig 2008-10-10 00:13:53.000000000 +0200
2838 +++ linux-2.6.27/security/Kconfig 2008-10-29 02:02:02.502672932 +0100
2839 @@ -117,6 +117,7 @@ config SECURITY_DEFAULT_MMAP_MIN_ADDR
2841 source security/selinux/Kconfig
2842 source security/smack/Kconfig
2843 +source security/apparmor/Kconfig
2847 diff -uprN linux-2.6.27./security/Makefile linux-2.6.27/security/Makefile
2848 --- linux-2.6.27./security/Makefile 2008-10-10 00:13:53.000000000 +0200
2849 +++ linux-2.6.27/security/Makefile 2008-10-29 02:02:02.512881631 +0100
2850 @@ -14,5 +14,6 @@ obj-$(CONFIG_SECURITY) += security.o c
2851 # Must precede capability.o in order to stack properly.
2852 obj-$(CONFIG_SECURITY_SELINUX) += selinux/built-in.o
2853 obj-$(CONFIG_SECURITY_SMACK) += smack/built-in.o
2854 -obj-$(CONFIG_SECURITY_ROOTPLUG) += root_plug.o
2855 +obj-$(CONFIG_SECURITY_APPARMOR) += commoncap.o apparmor/
2856 + obj-$(CONFIG_SECURITY_ROOTPLUG) += root_plug.o
2857 obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o
2858 diff -uprN linux-2.6.27./security/apparmor/Kconfig linux-2.6.27/security/apparmor/Kconfig
2859 --- linux-2.6.27./security/apparmor/Kconfig 1970-01-01 01:00:00.000000000 +0100
2860 +++ linux-2.6.27/security/apparmor/Kconfig 2008-10-29 14:28:53.319441671 +0100
2862 +config SECURITY_APPARMOR
2863 + bool "AppArmor support"
2864 + depends on SECURITY
2867 + This enables the AppArmor security module.
2868 + Required userspace tools (if they are not included in your
2869 + distribution) and further information may be found at
2870 + <http://forge.novell.com/modules/xfmod/project/?apparmor>
2872 + If you are unsure how to answer this question, answer N.
2874 +config SECURITY_APPARMOR_BOOTPARAM_VALUE
2875 + int "AppArmor boot parameter default value"
2876 + depends on SECURITY_APPARMOR
2880 + This option sets the default value for the kernel parameter
2881 + 'apparmor', which allows AppArmor to be enabled or disabled
2882 + at boot. If this option is set to 0 (zero), the AppArmor
2883 + kernel parameter will default to 0, disabling AppArmor at
2884 + bootup. If this option is set to 1 (one), the AppArmor
2885 + kernel parameter will default to 1, enabling AppArmor at
2888 + If you are unsure how to answer this question, answer 1.
2890 +config SECURITY_APPARMOR_DISABLE
2891 + bool "AppArmor runtime disable"
2892 + depends on SECURITY_APPARMOR
2895 + This option enables writing to a apparmorfs node 'disable', which
2896 + allows AppArmor to be disabled at runtime prior to the policy load.
2897 + AppArmor will then remain disabled until the next boot.
2898 + This option is similar to the apparmor.enabled=0 boot parameter,
2899 + but is to support runtime disabling of AppArmor, e.g. from
2900 + /sbin/init, for portability across platforms where boot
2901 + parameters are difficult to employ.
2903 + If you are unsure how to answer this question, answer N.
2904 diff -uprN linux-2.6.27./security/apparmor/Makefile linux-2.6.27/security/apparmor/Makefile
2905 --- linux-2.6.27./security/apparmor/Makefile 1970-01-01 01:00:00.000000000 +0100
2906 +++ linux-2.6.27/security/apparmor/Makefile 2008-10-29 14:28:53.322775050 +0100
2908 +# Makefile for AppArmor Linux Security Module
2910 +obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
2912 +apparmor-y := main.o list.o procattr.o lsm.o apparmorfs.o \
2913 + module_interface.o match.o
2915 +quiet_cmd_make-caps = GEN $@
2916 +cmd_make-caps = sed -n -e "/CAP_FS_MASK/d" -e "s/^\#define[ \\t]\\+CAP_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\$$/[\\2] = \"\\1\",/p" $< | tr A-Z a-z > $@
2918 +quiet_cmd_make-af = GEN $@
2919 +cmd_make-af = sed -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e "s/^\#define[ \\t]\\+AF_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\\(.*\\)\$$/[\\2] = \"\\1\",/p" $< | tr A-Z a-z > $@
2921 +$(obj)/main.o : $(obj)/capability_names.h $(obj)/af_names.h
2922 +$(obj)/capability_names.h : $(srctree)/include/linux/capability.h
2923 + $(call cmd,make-caps)
2924 +$(obj)/af_names.h : $(srctree)/include/linux/socket.h
2925 + $(call cmd,make-af)
2926 diff -uprN linux-2.6.27./security/apparmor/apparmor.h linux-2.6.27/security/apparmor/apparmor.h
2927 --- linux-2.6.27./security/apparmor/apparmor.h 1970-01-01 01:00:00.000000000 +0100
2928 +++ linux-2.6.27/security/apparmor/apparmor.h 2008-10-29 14:28:53.326113825 +0100
2931 + * Copyright (C) 1998-2007 Novell/SUSE
2933 + * This program is free software; you can redistribute it and/or
2934 + * modify it under the terms of the GNU General Public License as
2935 + * published by the Free Software Foundation, version 2 of the
2938 + * AppArmor internal prototypes
2941 +#ifndef __APPARMOR_H
2942 +#define __APPARMOR_H
2944 +#include <linux/sched.h>
2945 +#include <linux/fs.h>
2946 +#include <linux/binfmts.h>
2947 +#include <linux/rcupdate.h>
2948 +#include <linux/resource.h>
2949 +#include <linux/socket.h>
2950 +#include <net/sock.h>
2953 + * We use MAY_READ, MAY_WRITE, MAY_EXEC, MAY_APPEND and the following flags
2954 + * for profile permissions
2956 +#define AA_MAY_LINK 0x0010
2957 +#define AA_MAY_LOCK 0x0020
2958 +#define AA_EXEC_MMAP 0x0040
2959 +#define AA_MAY_MOUNT 0x0080 /* no direct audit mapping */
2960 +#define AA_EXEC_UNSAFE 0x0100
2961 +#define AA_EXEC_INHERIT 0x0200
2962 +#define AA_EXEC_MOD_0 0x0400
2963 +#define AA_EXEC_MOD_1 0x0800
2964 +#define AA_EXEC_MOD_2 0x1000
2965 +#define AA_EXEC_MOD_3 0x2000
2967 +#define AA_BASE_PERMS (MAY_READ | MAY_WRITE | MAY_EXEC | \
2968 + MAY_APPEND | AA_MAY_LINK | \
2969 + AA_MAY_LOCK | AA_EXEC_MMAP | \
2970 + AA_MAY_MOUNT | AA_EXEC_UNSAFE | \
2971 + AA_EXEC_INHERIT | AA_EXEC_MOD_0 | \
2972 + AA_EXEC_MOD_1 | AA_EXEC_MOD_2 | \
2975 +#define AA_EXEC_MODIFIERS (AA_EXEC_MOD_0 | AA_EXEC_MOD_1 | \
2976 + AA_EXEC_MOD_2 | AA_EXEC_MOD_3)
2978 +#define AA_EXEC_TYPE (AA_EXEC_UNSAFE | AA_EXEC_INHERIT | \
2979 + AA_EXEC_MODIFIERS)
2981 +#define AA_EXEC_UNCONFINED AA_EXEC_MOD_0
2982 +#define AA_EXEC_PROFILE AA_EXEC_MOD_1
2983 +#define AA_EXEC_CHILD (AA_EXEC_MOD_0 | AA_EXEC_MOD_1)
2984 +/* remaining exec modes are index into profile name table */
2985 +#define AA_EXEC_INDEX(mode) ((mode & AA_EXEC_MODIFIERS) >> 10)
2987 +#define AA_USER_SHIFT 0
2988 +#define AA_OTHER_SHIFT 14
2990 +#define AA_USER_PERMS (AA_BASE_PERMS << AA_USER_SHIFT)
2991 +#define AA_OTHER_PERMS (AA_BASE_PERMS << AA_OTHER_SHIFT)
2993 +#define AA_FILE_PERMS (AA_USER_PERMS | AA_OTHER_PERMS)
2995 +#define AA_LINK_BITS ((AA_MAY_LINK << AA_USER_SHIFT) | \
2996 + (AA_MAY_LINK << AA_OTHER_SHIFT))
2998 +#define AA_USER_EXEC (MAY_EXEC << AA_USER_SHIFT)
2999 +#define AA_OTHER_EXEC (MAY_EXEC << AA_OTHER_SHIFT)
3001 +#define AA_USER_EXEC_TYPE (AA_EXEC_TYPE << AA_USER_SHIFT)
3002 +#define AA_OTHER_EXEC_TYPE (AA_EXEC_TYPE << AA_OTHER_SHIFT)
3004 +#define AA_EXEC_BITS (AA_USER_EXEC | AA_OTHER_EXEC)
3006 +#define ALL_AA_EXEC_UNSAFE ((AA_EXEC_UNSAFE << AA_USER_SHIFT) | \
3007 + (AA_EXEC_UNSAFE << AA_OTHER_SHIFT))
3009 +#define ALL_AA_EXEC_TYPE (AA_USER_EXEC_TYPE | AA_OTHER_EXEC_TYPE)
3011 +/* overloaded permissions for link pairs */
3012 +#define AA_LINK_SUBSET_TEST 0x0020
3014 +#define AA_USER_PTRACE 0x10000000
3015 +#define AA_OTHER_PTRACE 0x20000000
3016 +#define AA_PTRACE_PERMS (AA_USER_PTRACE | AA_OTHER_PTRACE)
3018 +/* shared permissions that are not duplicated in user::other */
3019 +#define AA_CHANGE_HAT 0x40000000
3020 +#define AA_CHANGE_PROFILE 0x80000000
3022 +#define AA_SHARED_PERMS (AA_CHANGE_HAT | AA_CHANGE_PROFILE)
3024 +#define AA_VALID_PERM_MASK (AA_FILE_PERMS | AA_PTRACE_PERMS | \
3027 +/* audit bits for the second accept field */
3028 +#define AUDIT_FILE_MASK 0x1fc07f
3029 +#define AUDIT_QUIET_MASK(mask) ((mask >> 7) & AUDIT_FILE_MASK)
3030 +#define AA_VALID_PERM2_MASK 0x0fffffff
3032 +#define AA_SECURE_EXEC_NEEDED 1
3034 +/* Control parameters (0 or 1), settable thru module/boot flags or
3035 + * via /sys/kernel/security/apparmor/control */
3036 +extern int apparmor_complain;
3037 +extern int apparmor_debug;
3038 +extern int apparmor_audit;
3039 +extern int apparmor_logsyscall;
3040 +extern unsigned int apparmor_path_max;
3042 +#define PROFILE_COMPLAIN(_profile) \
3043 + (apparmor_complain == 1 || ((_profile) && (_profile)->flags.complain))
3045 +#define APPARMOR_COMPLAIN(_cxt) \
3046 + (apparmor_complain == 1 || \
3047 + ((_cxt) && (_cxt)->profile && (_cxt)->profile->flags.complain))
3049 +#define PROFILE_AUDIT(_profile) \
3050 + (apparmor_audit == 1 || ((_profile) && (_profile)->flags.audit))
3052 +#define APPARMOR_AUDIT(_cxt) \
3053 + (apparmor_audit == 1 || \
3054 + ((_cxt) && (_cxt)->profile && (_cxt)->profile->flags.audit))
3056 +#define PROFILE_IS_HAT(_profile) \
3057 + ((_profile) && (_profile)->flags.hat)
3060 + * DEBUG remains global (no per profile flag) since it is mostly used in sysctl
3061 + * which is not related to profile accesses.
3064 +#define AA_DEBUG(fmt, args...) \
3066 + if (apparmor_debug) \
3067 + printk(KERN_DEBUG "AppArmor: " fmt, ##args); \
3070 +#define AA_ERROR(fmt, args...) printk(KERN_ERR "AppArmor: " fmt, ##args)
3072 +/* struct aa_rlimit - rlimits settings for the profile
3073 + * @mask: which hard limits to set
3074 + * @limits: rlimit values that override task limits
3076 + * AppArmor rlimits are used to set confined task rlimits. Only the
3077 + * limits specified in @mask will be controlled by apparmor.
3080 + unsigned int mask;
3081 + struct rlimit limits[RLIM_NLIMITS];
3086 +/* struct aa_namespace - namespace for a set of profiles
3087 + * @name: the name of the namespace
3088 + * @list: list the namespace is on
3089 + * @profiles: list of profile in the namespace
3090 + * @profile_count: the number of profiles in the namespace
3091 + * @null_complain_profile: special profile used for learning in this namespace
3092 + * @count: reference count on the namespace
3093 + * @lock: lock for adding/removing profile to the namespace
3095 +struct aa_namespace {
3097 + struct list_head list;
3098 + struct list_head profiles;
3099 + int profile_count;
3100 + struct aa_profile *null_complain_profile;
3102 + struct kref count;
3106 +/* struct aa_profile - basic confinement data
3107 + * @name: the profiles name
3108 + * @list: list this profile is on
3109 + * @ns: namespace the profile is in
3110 + * @file_rules: dfa containing the profiles file rules
3111 + * @flags: flags controlling profile behavior
3112 + * @isstale: flag indicating if profile is stale
3113 + * @set_caps: capabilities that are being set
3114 + * @capabilities: capabilities mask
3115 + * @audit_caps: caps that are to be audited
3116 + * @quiet_caps: caps that should not be audited
3117 + * @capabilities: capabilities granted by the process
3118 + * @rlimits: rlimits for the profile
3119 + * @task_count: how many tasks the profile is attached to
3120 + * @count: reference count of the profile
3121 + * @task_contexts: list of tasks confined by profile
3122 + * @lock: lock for the task_contexts list
3123 + * @network_families: basic network permissions
3124 + * @audit_network: which network permissions to force audit
3125 + * @quiet_network: which network permissions to quiet rejects
3127 + * The AppArmor profile contains the basic confinement data. Each profile
3128 + * has a name, and all nonstale profile are in a profile namespace.
3130 + * The task_contexts list and the isstale flag are protected by the
3133 + * If a task context is moved between two profiles, we first need to grab
3134 + * both profile locks. lock_both_profiles() does that in a deadlock-safe
3137 +struct aa_profile {
3139 + struct list_head list;
3140 + struct aa_namespace *ns;
3142 + int exec_table_size;
3143 + char **exec_table;
3144 + struct aa_dfa *file_rules;
3152 + kernel_cap_t set_caps;
3153 + kernel_cap_t capabilities;
3154 + kernel_cap_t audit_caps;
3155 + kernel_cap_t quiet_caps;
3157 + struct aa_rlimit rlimits;
3158 + unsigned int task_count;
3160 + struct kref count;
3161 + struct list_head task_contexts;
3163 + unsigned long int_flags;
3164 + u16 network_families[AF_MAX];
3165 + u16 audit_network[AF_MAX];
3166 + u16 quiet_network[AF_MAX];
3169 +extern struct list_head profile_ns_list;
3170 +extern rwlock_t profile_ns_list_lock;
3171 +extern struct mutex aa_interface_lock;
3174 + * struct aa_task_context - primary label for confined tasks
3175 + * @profile: the current profile
3176 + * @previous_profile: profile the task may return to
3177 + * @cookie: magic value the task must know for returning to @previous_profile
3178 + * @list: list this aa_task_context is on
3179 + * @task: task that the aa_task_context confines
3180 + * @rcu: rcu head used when freeing the aa_task_context
3181 + * @caps_logged: caps that have previously generated log entries
3183 + * Contains the task's current profile (which could change due to
3184 + * change_hat). Plus the hat_magic needed during change_hat.
3186 +struct aa_task_context {
3187 + struct aa_profile *profile;
3188 + struct aa_profile *previous_profile;
3190 + struct list_head list;
3191 + struct task_struct *task;
3192 + struct rcu_head rcu;
3193 + kernel_cap_t caps_logged;
3196 +extern struct aa_namespace *default_namespace;
3198 +/* aa_audit - AppArmor auditing structure
3199 + * Structure is populated by access control code and passed to aa_audit which
3200 + * provides for a single point of logging.
3204 + const char *operation;
3208 + const char *name2;
3209 + const char *name3;
3210 + int request_mask, denied_mask, audit_mask;
3212 + struct iattr *iattr;
3213 + pid_t task, parent;
3214 + int family, type, protocol;
3218 +/* Flags for the permission check functions */
3219 +#define AA_CHECK_FD 1 /* coming from a file descriptor */
3220 +#define AA_CHECK_DIR 2 /* file type is directory */
3222 +/* lock subtypes so lockdep does not raise false dependencies */
3223 +enum aa_lock_class {
3226 + aa_lock_task_release
3230 +extern int alloc_default_namespace(void);
3231 +extern void free_default_namespace(void);
3232 +extern int aa_audit_message(struct aa_profile *profile, struct aa_audit *sa,
3234 +void aa_audit_hint(struct aa_profile *profile, struct aa_audit *sa);
3235 +void aa_audit_status(struct aa_profile *profile, struct aa_audit *sa);
3236 +int aa_audit_reject(struct aa_profile *profile, struct aa_audit *sa);
3237 +extern int aa_audit_syscallreject(struct aa_profile *profile, gfp_t gfp,
3239 +extern int aa_audit(struct aa_profile *profile, struct aa_audit *);
3241 +extern int aa_attr(struct aa_profile *profile, struct dentry *dentry,
3242 + struct vfsmount *mnt, struct iattr *iattr);
3243 +extern int aa_perm_xattr(struct aa_profile *profile, const char *operation,
3244 + struct dentry *dentry, struct vfsmount *mnt,
3245 + int mask, int check);
3246 +extern int aa_capability(struct aa_task_context *cxt, int cap);
3247 +extern int aa_perm(struct aa_profile *profile, const char *operation,
3248 + struct dentry *dentry, struct vfsmount *mnt, int mask,
3250 +extern int aa_perm_dir(struct aa_profile *profile, const char *operation,
3251 + struct dentry *dentry, struct vfsmount *mnt,
3253 +extern int aa_perm_path(struct aa_profile *, const char *operation,
3254 + const char *name, int mask, uid_t uid);
3255 +extern int aa_link(struct aa_profile *profile,
3256 + struct dentry *link, struct vfsmount *link_mnt,
3257 + struct dentry *target, struct vfsmount *target_mnt);
3258 +extern int aa_clone(struct task_struct *task);
3259 +extern int aa_register(struct linux_binprm *bprm);
3260 +extern void aa_release(struct task_struct *task);
3261 +extern int aa_change_hat(const char *id, u64 hat_magic);
3262 +extern int aa_change_profile(const char *ns_name, const char *name);
3263 +extern struct aa_profile *__aa_replace_profile(struct task_struct *task,
3264 + struct aa_profile *profile);
3265 +extern struct aa_task_context *lock_task_and_profiles(struct task_struct *task,
3266 + struct aa_profile *profile);
3267 +extern void unlock_task_and_profiles(struct task_struct *task,
3268 + struct aa_task_context *cxt,
3269 + struct aa_profile *profile);
3270 +extern void aa_change_task_context(struct task_struct *task,
3271 + struct aa_task_context *new_cxt,
3272 + struct aa_profile *profile, u64 cookie,
3273 + struct aa_profile *previous_profile);
3274 +extern int aa_may_ptrace(struct aa_task_context *cxt,
3275 + struct aa_profile *tracee);
3276 +extern int aa_net_perm(struct aa_profile *profile, char *operation,
3277 + int family, int type, int protocol);
3278 +extern int aa_revalidate_sk(struct sock *sk, char *operation);
3279 +extern int aa_task_setrlimit(struct aa_profile *profile, unsigned int resource,
3280 + struct rlimit *new_rlim);
3281 +extern void aa_set_rlimits(struct task_struct *task, struct aa_profile *profile);
3285 +extern int apparmor_initialized;
3286 +extern void info_message(const char *str);
3287 +extern void apparmor_disable(void);
3290 +extern struct aa_namespace *__aa_find_namespace(const char *name,
3291 + struct list_head *list);
3292 +extern struct aa_profile *__aa_find_profile(const char *name,
3293 + struct list_head *list);
3294 +extern void aa_profile_ns_list_release(void);
3296 +/* module_interface.c */
3297 +extern ssize_t aa_add_profile(void *, size_t);
3298 +extern ssize_t aa_replace_profile(void *, size_t);
3299 +extern ssize_t aa_remove_profile(char *, size_t);
3300 +extern struct aa_namespace *alloc_aa_namespace(char *name);
3301 +extern void free_aa_namespace(struct aa_namespace *ns);
3302 +extern void free_aa_namespace_kref(struct kref *kref);
3303 +extern struct aa_profile *alloc_aa_profile(void);
3304 +extern void free_aa_profile(struct aa_profile *profile);
3305 +extern void free_aa_profile_kref(struct kref *kref);
3306 +extern void aa_unconfine_tasks(struct aa_profile *profile);
3309 +extern int aa_getprocattr(struct aa_profile *profile, char **string,
3311 +extern int aa_setprocattr_changehat(char *args);
3312 +extern int aa_setprocattr_changeprofile(char *args);
3313 +extern int aa_setprocattr_setprofile(struct task_struct *task, char *args);
3316 +extern int create_apparmorfs(void);
3317 +extern void destroy_apparmorfs(void);
3320 +extern struct aa_dfa *aa_match_alloc(void);
3321 +extern void aa_match_free(struct aa_dfa *dfa);
3322 +extern int unpack_dfa(struct aa_dfa *dfa, void *blob, size_t size);
3323 +extern int verify_dfa(struct aa_dfa *dfa);
3324 +extern unsigned int aa_dfa_match(struct aa_dfa *dfa, const char *str, int *);
3325 +extern unsigned int aa_dfa_next_state(struct aa_dfa *dfa, unsigned int start,
3327 +extern unsigned int aa_match_state(struct aa_dfa *dfa, unsigned int start,
3328 + const char *str, unsigned int *final);
3329 +extern unsigned int aa_dfa_null_transition(struct aa_dfa *dfa,
3330 + unsigned int start);
3332 +#endif /* __APPARMOR_H */
3333 diff -uprN linux-2.6.27./security/apparmor/apparmorfs.c linux-2.6.27/security/apparmor/apparmorfs.c
3334 --- linux-2.6.27./security/apparmor/apparmorfs.c 1970-01-01 01:00:00.000000000 +0100
3335 +++ linux-2.6.27/security/apparmor/apparmorfs.c 2008-10-29 14:28:53.326113825 +0100
3338 + * Copyright (C) 1998-2007 Novell/SUSE
3340 + * This program is free software; you can redistribute it and/or
3341 + * modify it under the terms of the GNU General Public License as
3342 + * published by the Free Software Foundation, version 2 of the
3345 + * AppArmor filesystem (part of securityfs)
3348 +#include <linux/security.h>
3349 +#include <linux/vmalloc.h>
3350 +#include <linux/module.h>
3351 +#include <linux/seq_file.h>
3352 +#include <asm/uaccess.h>
3353 +#include <linux/namei.h>
3355 +#include "apparmor.h"
3356 +#include "inline.h"
3358 +static char *aa_simple_write_to_buffer(const char __user *userbuf,
3359 + size_t alloc_size, size_t copy_size,
3360 + loff_t *pos, const char *operation)
3362 + struct aa_profile *profile;
3366 + /* only writes from pos 0, that is complete writes */
3367 + data = ERR_PTR(-ESPIPE);
3372 + * Don't allow confined processes to load/replace/remove profiles.
3373 + * No sane person would add rules allowing this to a profile
3374 + * but we enforce the restriction anyways.
3376 + profile = aa_get_profile(current);
3378 + struct aa_audit sa;
3379 + memset(&sa, 0, sizeof(sa));
3380 + sa.operation = operation;
3381 + sa.gfp_mask = GFP_KERNEL;
3382 + sa.error_code = -EACCES;
3383 + data = ERR_PTR(aa_audit_reject(profile, &sa));
3384 + aa_put_profile(profile);
3388 + data = vmalloc(alloc_size);
3389 + if (data == NULL) {
3390 + data = ERR_PTR(-ENOMEM);
3394 + if (copy_from_user(data, userbuf, copy_size)) {
3396 + data = ERR_PTR(-EFAULT);
3404 +/* apparmor/profiles */
3405 +extern struct seq_operations apparmorfs_profiles_op;
3407 +static int aa_profiles_open(struct inode *inode, struct file *file)
3409 + return seq_open(file, &apparmorfs_profiles_op);
3413 +static int aa_profiles_release(struct inode *inode, struct file *file)
3415 + return seq_release(inode, file);
3418 +static struct file_operations apparmorfs_profiles_fops = {
3419 + .open = aa_profiles_open,
3421 + .llseek = seq_lseek,
3422 + .release = aa_profiles_release,
3425 +/* apparmor/matching */
3426 +static ssize_t aa_matching_read(struct file *file, char __user *buf,
3427 + size_t size, loff_t *ppos)
3429 + const char *matching = "pattern=aadfa audit perms=rwxamlk/ user::other";
3431 + return simple_read_from_buffer(buf, size, ppos, matching,
3432 + strlen(matching));
3435 +static struct file_operations apparmorfs_matching_fops = {
3436 + .read = aa_matching_read,
3439 +/* apparmor/features */
3440 +static ssize_t aa_features_read(struct file *file, char __user *buf,
3441 + size_t size, loff_t *ppos)
3443 + const char *features = "file=3.0 capability=2.0 network=1.0 "
3444 + "change_hat=1.5 change_profile=1.0 "
3445 + "aanamespaces=1.0 rlimit=1.0";
3447 + return simple_read_from_buffer(buf, size, ppos, features,
3448 + strlen(features));
3451 +static struct file_operations apparmorfs_features_fops = {
3452 + .read = aa_features_read,
3455 +/* apparmor/.load */
3456 +static ssize_t aa_profile_load(struct file *f, const char __user *buf,
3457 + size_t size, loff_t *pos)
3462 + data = aa_simple_write_to_buffer(buf, size, size, pos, "profile_load");
3464 + error = PTR_ERR(data);
3465 + if (!IS_ERR(data)) {
3466 + error = aa_add_profile(data, size);
3474 +static struct file_operations apparmorfs_profile_load = {
3475 + .write = aa_profile_load
3478 +/* apparmor/.replace */
3479 +static ssize_t aa_profile_replace(struct file *f, const char __user *buf,
3480 + size_t size, loff_t *pos)
3485 + data = aa_simple_write_to_buffer(buf, size, size, pos,
3486 + "profile_replace");
3488 + error = PTR_ERR(data);
3489 + if (!IS_ERR(data)) {
3490 + error = aa_replace_profile(data, size);
3498 +static struct file_operations apparmorfs_profile_replace = {
3499 + .write = aa_profile_replace
3502 +/* apparmor/.remove */
3503 +static ssize_t aa_profile_remove(struct file *f, const char __user *buf,
3504 + size_t size, loff_t *pos)
3510 + * aa_remove_profile needs a null terminated string so 1 extra
3511 + * byte is allocated and the copied data is null terminated.
3513 + data = aa_simple_write_to_buffer(buf, size + 1, size, pos,
3514 + "profile_remove");
3516 + error = PTR_ERR(data);
3517 + if (!IS_ERR(data)) {
3519 + error = aa_remove_profile(data, size);
3526 +static struct file_operations apparmorfs_profile_remove = {
3527 + .write = aa_profile_remove
3530 +static struct dentry *apparmor_dentry;
3532 +static void aafs_remove(const char *name)
3534 + struct dentry *dentry;
3536 + dentry = lookup_one_len(name, apparmor_dentry, strlen(name));
3537 + if (!IS_ERR(dentry)) {
3538 + securityfs_remove(dentry);
3543 +static int aafs_create(const char *name, int mask, struct file_operations *fops)
3545 + struct dentry *dentry;
3547 + dentry = securityfs_create_file(name, S_IFREG | mask, apparmor_dentry,
3550 + return IS_ERR(dentry) ? PTR_ERR(dentry) : 0;
3553 +void destroy_apparmorfs(void)
3555 + if (apparmor_dentry) {
3556 + aafs_remove(".remove");
3557 + aafs_remove(".replace");
3558 + aafs_remove(".load");
3559 + aafs_remove("matching");
3560 + aafs_remove("features");
3561 + aafs_remove("profiles");
3562 + securityfs_remove(apparmor_dentry);
3563 + apparmor_dentry = NULL;
3567 +int create_apparmorfs(void)
3571 + if (!apparmor_initialized)
3574 + if (apparmor_dentry) {
3575 + AA_ERROR("%s: AppArmor securityfs already exists\n",
3580 + apparmor_dentry = securityfs_create_dir("apparmor", NULL);
3581 + if (IS_ERR(apparmor_dentry)) {
3582 + error = PTR_ERR(apparmor_dentry);
3583 + apparmor_dentry = NULL;
3586 + error = aafs_create("profiles", 0440, &apparmorfs_profiles_fops);
3589 + error = aafs_create("matching", 0444, &apparmorfs_matching_fops);
3592 + error = aafs_create("features", 0444, &apparmorfs_features_fops);
3595 + error = aafs_create(".load", 0640, &apparmorfs_profile_load);
3598 + error = aafs_create(".replace", 0640, &apparmorfs_profile_replace);
3601 + error = aafs_create(".remove", 0640, &apparmorfs_profile_remove);
3605 + /* Report that AppArmor fs is enabled */
3606 + info_message("AppArmor Filesystem Enabled");
3610 + destroy_apparmorfs();
3611 + AA_ERROR("Error creating AppArmor securityfs\n");
3612 + apparmor_disable();
3616 +fs_initcall(create_apparmorfs);
3618 diff -uprN linux-2.6.27./security/apparmor/inline.h linux-2.6.27/security/apparmor/inline.h
3619 --- linux-2.6.27./security/apparmor/inline.h 1970-01-01 01:00:00.000000000 +0100
3620 +++ linux-2.6.27/security/apparmor/inline.h 2008-10-29 14:28:53.319441671 +0100
3623 + * Copyright (C) 1998-2007 Novell/SUSE
3625 + * This program is free software; you can redistribute it and/or
3626 + * modify it under the terms of the GNU General Public License as
3627 + * published by the Free Software Foundation, version 2 of the
3634 +#include <linux/sched.h>
3638 +static inline int mediated_filesystem(struct inode *inode)
3640 + return !(inode->i_sb->s_flags & MS_NOUSER);
3643 +static inline struct aa_task_context *aa_task_context(struct task_struct *task)
3645 + return (struct aa_task_context *) rcu_dereference(task->security);
3648 +static inline struct aa_namespace *aa_get_namespace(struct aa_namespace *ns)
3651 + kref_get(&(ns->count));
3656 +static inline void aa_put_namespace(struct aa_namespace *ns)
3659 + kref_put(&ns->count, free_aa_namespace_kref);
3663 +static inline struct aa_namespace *aa_find_namespace(const char *name)
3665 + struct aa_namespace *ns = NULL;
3667 + read_lock(&profile_ns_list_lock);
3668 + ns = aa_get_namespace(__aa_find_namespace(name, &profile_ns_list));
3669 + read_unlock(&profile_ns_list_lock);
3675 + * aa_dup_profile - increment refcount on profile @p
3678 +static inline struct aa_profile *aa_dup_profile(struct aa_profile *p)
3681 + kref_get(&(p->count));
3687 + * aa_put_profile - decrement refcount on profile @p
3690 +static inline void aa_put_profile(struct aa_profile *p)
3693 + kref_put(&p->count, free_aa_profile_kref);
3696 +static inline struct aa_profile *aa_get_profile(struct task_struct *task)
3698 + struct aa_task_context *cxt;
3699 + struct aa_profile *profile = NULL;
3702 + cxt = aa_task_context(task);
3704 + profile = cxt->profile;
3705 + aa_dup_profile(profile);
3707 + rcu_read_unlock();
3712 +static inline struct aa_profile *aa_find_profile(struct aa_namespace *ns,
3715 + struct aa_profile *profile = NULL;
3717 + read_lock(&ns->lock);
3718 + profile = aa_dup_profile(__aa_find_profile(name, &ns->profiles));
3719 + read_unlock(&ns->lock);
3724 +static inline struct aa_task_context *aa_alloc_task_context(gfp_t flags)
3726 + struct aa_task_context *cxt;
3728 + cxt = kzalloc(sizeof(*cxt), flags);
3730 + INIT_LIST_HEAD(&cxt->list);
3731 + INIT_RCU_HEAD(&cxt->rcu);
3737 +static inline void aa_free_task_context(struct aa_task_context *cxt)
3740 + aa_put_profile(cxt->profile);
3741 + aa_put_profile(cxt->previous_profile);
3747 + * lock_profile - lock a profile
3748 + * @profile: the profile to lock
3750 + * While the profile is locked, local interrupts are disabled. This also
3751 + * gives us RCU reader safety.
3753 +static inline void lock_profile_nested(struct aa_profile *profile,
3754 + enum aa_lock_class lock_class)
3757 + * Lock the profile.
3759 + * Need to disable interrupts here because this lock is used in
3760 + * the task_free_security hook, which may run in RCU context.
3763 + spin_lock_irqsave_nested(&profile->lock, profile->int_flags,
3767 +static inline void lock_profile(struct aa_profile *profile)
3769 + lock_profile_nested(profile, aa_lock_normal);
3773 + * unlock_profile - unlock a profile
3774 + * @profile: the profile to unlock
3776 +static inline void unlock_profile(struct aa_profile *profile)
3778 + /* Unlock the profile. */
3780 + spin_unlock_irqrestore(&profile->lock, profile->int_flags);
3784 + * lock_both_profiles - lock two profiles in a deadlock-free way
3785 + * @profile1: profile to lock (may be NULL)
3786 + * @profile2: profile to lock (may be NULL)
3788 + * The order in which profiles are passed into lock_both_profiles() /
3789 + * unlock_both_profiles() does not matter.
3790 + * While the profile is locked, local interrupts are disabled. This also
3791 + * gives us RCU reader safety.
3793 +static inline void lock_both_profiles(struct aa_profile *profile1,
3794 + struct aa_profile *profile2)
3797 + * Lock the two profiles.
3799 + * We need to disable interrupts because the profile locks are
3800 + * used in the task_free_security hook, which may run in RCU
3803 + * Do not nest spin_lock_irqsave()/spin_unlock_irqresore():
3804 + * interrupts only need to be turned off once.
3806 + if (!profile1 || profile1 == profile2) {
3808 + spin_lock_irqsave_nested(&profile2->lock,
3809 + profile2->int_flags,
3811 + } else if (profile1 > profile2) {
3812 + /* profile1 cannot be NULL here. */
3813 + spin_lock_irqsave_nested(&profile1->lock, profile1->int_flags,
3816 + spin_lock_nested(&profile2->lock, aa_lock_nested);
3819 + /* profile2 cannot be NULL here. */
3820 + spin_lock_irqsave_nested(&profile2->lock, profile2->int_flags,
3822 + spin_lock_nested(&profile1->lock, aa_lock_nested);
3827 + * unlock_both_profiles - unlock two profiles in a deadlock-free way
3828 + * @profile1: profile to unlock (may be NULL)
3829 + * @profile2: profile to unlock (may be NULL)
3831 + * The order in which profiles are passed into lock_both_profiles() /
3832 + * unlock_both_profiles() does not matter.
3833 + * While the profile is locked, local interrupts are disabled. This also
3834 + * gives us RCU reader safety.
3836 +static inline void unlock_both_profiles(struct aa_profile *profile1,
3837 + struct aa_profile *profile2)
3839 + /* Unlock the two profiles. */
3840 + if (!profile1 || profile1 == profile2) {
3842 + spin_unlock_irqrestore(&profile2->lock,
3843 + profile2->int_flags);
3844 + } else if (profile1 > profile2) {
3845 + /* profile1 cannot be NULL here. */
3847 + spin_unlock(&profile2->lock);
3848 + spin_unlock_irqrestore(&profile1->lock, profile1->int_flags);
3850 + /* profile2 cannot be NULL here. */
3851 + spin_unlock(&profile1->lock);
3852 + spin_unlock_irqrestore(&profile2->lock, profile2->int_flags);
3856 +static inline unsigned int aa_match(struct aa_dfa *dfa, const char *pathname,
3860 + return aa_dfa_match(dfa, pathname, audit_mask);
3866 +static inline int dfa_audit_mask(struct aa_dfa *dfa, unsigned int state)
3868 + return ACCEPT_TABLE2(dfa)[state];
3871 +#endif /* __INLINE_H__ */
3872 diff -uprN linux-2.6.27./security/apparmor/list.c linux-2.6.27/security/apparmor/list.c
3873 --- linux-2.6.27./security/apparmor/list.c 1970-01-01 01:00:00.000000000 +0100
3874 +++ linux-2.6.27/security/apparmor/list.c 2008-10-29 14:28:53.319441671 +0100
3877 + * Copyright (C) 1998-2007 Novell/SUSE
3879 + * This program is free software; you can redistribute it and/or
3880 + * modify it under the terms of the GNU General Public License as
3881 + * published by the Free Software Foundation, version 2 of the
3884 + * AppArmor Profile List Management
3887 +#include <linux/seq_file.h>
3888 +#include "apparmor.h"
3889 +#include "inline.h"
3891 +/* list of profile namespaces and lock */
3892 +LIST_HEAD(profile_ns_list);
3893 +rwlock_t profile_ns_list_lock = RW_LOCK_UNLOCKED;
3896 + * __aa_find_namespace - look up a profile namespace on the namespace list
3897 + * @name: name of namespace to find
3898 + * @head: list to search
3900 + * Returns a pointer to the namespace on the list, or NULL if no namespace
3901 + * called @name exists. The caller must hold the profile_ns_list_lock.
3903 +struct aa_namespace *__aa_find_namespace(const char *name,
3904 + struct list_head *head)
3906 + struct aa_namespace *ns;
3908 + list_for_each_entry(ns, head, list) {
3909 + if (!strcmp(ns->name, name))
3917 + * __aa_find_profile - look up a profile on the profile list
3918 + * @name: name of profile to find
3919 + * @head: list to search
3921 + * Returns a pointer to the profile on the list, or NULL if no profile
3922 + * called @name exists. The caller must hold the profile_list_lock.
3924 +struct aa_profile *__aa_find_profile(const char *name, struct list_head *head)
3926 + struct aa_profile *profile;
3928 + list_for_each_entry(profile, head, list) {
3929 + if (!strcmp(profile->name, name))
3936 +static void aa_profile_list_release(struct list_head *head)
3938 + struct aa_profile *profile, *tmp;
3939 + list_for_each_entry_safe(profile, tmp, head, list) {
3940 + /* Remove the profile from each task context it is on. */
3941 + lock_profile(profile);
3942 + profile->isstale = 1;
3943 + aa_unconfine_tasks(profile);
3944 + list_del_init(&profile->list);
3945 + unlock_profile(profile);
3946 + aa_put_profile(profile);
3951 + * aa_profilelist_release - Remove all profiles from profile_list
3953 +void aa_profile_ns_list_release(void)
3955 + struct aa_namespace *ns, *tmp;
3957 + /* Remove and release all the profiles on namespace profile lists. */
3958 + write_lock(&profile_ns_list_lock);
3959 + list_for_each_entry_safe(ns, tmp, &profile_ns_list, list) {
3960 + write_lock(&ns->lock);
3961 + aa_profile_list_release(&ns->profiles);
3962 + list_del_init(&ns->list);
3963 + write_unlock(&ns->lock);
3964 + aa_put_namespace(ns);
3966 + write_unlock(&profile_ns_list_lock);
3970 +static struct aa_profile *next_profile(struct aa_profile *profile)
3972 + struct aa_profile *next = profile;
3973 + struct aa_namespace *ns;
3975 + list_for_each_entry_continue(next, &profile->ns->profiles, list)
3979 + read_unlock(&ns->lock);
3980 + list_for_each_entry_continue(ns, &profile_ns_list, list) {
3981 + read_lock(&ns->lock);
3982 + list_for_each_entry(profile, &ns->profiles, list)
3984 + read_unlock(&ns->lock);
3989 +static void *p_start(struct seq_file *f, loff_t *pos)
3991 + struct aa_namespace *ns;
3994 + read_lock(&profile_ns_list_lock);
3995 + if (!list_empty(&profile_ns_list)) {
3996 + struct aa_profile *profile = NULL;
3997 + ns = list_first_entry(&profile_ns_list, typeof(*ns), list);
3998 + read_lock(&ns->lock);
3999 + if (!list_empty(&ns->profiles))
4000 + profile = list_first_entry(&ns->profiles,
4001 + typeof(*profile), list);
4003 + read_unlock(&ns->lock);
4004 + for ( ; profile && l > 0; l--)
4005 + profile = next_profile(profile);
4011 +static void *p_next(struct seq_file *f, void *p, loff_t *pos)
4013 + struct aa_profile *profile = (struct aa_profile *) p;
4016 + profile = next_profile(profile);
4021 +static void p_stop(struct seq_file *f, void *p)
4023 + struct aa_profile *profile = (struct aa_profile *) p;
4026 + read_unlock(&profile->ns->lock);
4027 + read_unlock(&profile_ns_list_lock);
4030 +static int seq_show_profile(struct seq_file *f, void *p)
4032 + struct aa_profile *profile = (struct aa_profile *)p;
4034 + if (profile->ns == default_namespace)
4035 + seq_printf(f, "%s (%s)\n", profile->name,
4036 + PROFILE_COMPLAIN(profile) ? "complain" : "enforce");
4038 + seq_printf(f, ":%s:%s (%s)\n", profile->ns->name, profile->name,
4039 + PROFILE_COMPLAIN(profile) ? "complain" : "enforce");
4043 +/* Used in apparmorfs.c */
4044 +struct seq_operations apparmorfs_profiles_op = {
4048 + .show = seq_show_profile,
4050 diff -uprN linux-2.6.27./security/apparmor/locking.txt linux-2.6.27/security/apparmor/locking.txt
4051 --- linux-2.6.27./security/apparmor/locking.txt 1970-01-01 01:00:00.000000000 +0100
4052 +++ linux-2.6.27/security/apparmor/locking.txt 2008-10-29 14:28:53.319441671 +0100
4054 +Locking in AppArmor
4055 +===================
4065 +Which lock protects what?
4067 + /-----------------------+-------------------------------\
4068 + | Variable | Lock |
4069 + >-----------------------+-------------------------------<
4070 + | profile_list | profile_list_lock |
4071 + +-----------------------+-------------------------------+
4072 + | aa_profile | (reference count) |
4073 + +-----------------------+-------------------------------+
4074 + | aa_profile-> | aa_profile->lock |
4076 + | task_contexts | |
4077 + +-----------------------+-------------------------------+
4078 + | task_struct->security | read: RCU |
4079 + | | write: task_lock() |
4080 + +-----------------------+-------------------------------+
4081 + | aa_profile->sub | handle on the profile (list |
4082 + | | is never modified) |
4083 + \-----------------------+-------------------------------/
4085 +(Obviously, the list_heads embedded in data structures are always
4086 +protected with the lock that also protects the list.)
4088 +When moving a task context from one profile to another, we grab both
4089 +profile locks with lock_both_profiles(). This ensures that both locks
4090 +are always taken in the same order, and so we won't deadlock.
4092 +Since task_struct->security is RCU protected the aa_task_struct it
4093 +references is only guarenteed to exist for the rcu cycle. Where
4094 +aa_task_context->profile is needed in blocking operations the
4095 +profile's reference count is incremented and the profile reference
4098 +Profiles on profile_list are never stale: when a profile becomes stale,
4099 +it is removed from profile_list at the same time (under profile_list_lock
4100 +and aa_profile->lock).
4102 +The aa_interface_lock is taken whenever user-space modifies the profile
4103 +list, and can sleep. This ensures that profile loading/replacement/removal
4104 +won't race with itself. We release the profile_list_lock as soon as
4105 +possible to avoid stalling exec during profile loading/replacement/removal.
4107 +AppArmor uses lock subtyping to avoid false positives from lockdep. The
4108 +profile lock is often taken nested, but it is guaranteed to be in a lock
4109 +safe order and not the same lock when done, so it is safe.
4111 +A third lock type (aa_lock_task_release) is given to the profile lock
4112 +when it is taken in soft irq context during task release (aa_release).
4113 +This is to avoid a false positive between the task lock and the profile
4114 +lock. In task context the profile lock wraps the task lock with irqs
4115 +off, but the kernel takes the task lock with irqs enabled. This won't
4116 +result in a deadlock because for a deadlock to occur the kernel must
4117 +take dead task A's lock (irqs on), the rcu callback hook freeing
4118 +dead task A must be run and AppArmor must be changing the profile on
4119 +dead task A. The kernel should not be taking a dead task's task_lock
4120 +at the same time the task is being freed by task rcu cleanup other wise
4121 +the task would not be out of its quiescent period.
4122 diff -uprN linux-2.6.27./security/apparmor/lsm.c linux-2.6.27/security/apparmor/lsm.c
4123 --- linux-2.6.27./security/apparmor/lsm.c 1970-01-01 01:00:00.000000000 +0100
4124 +++ linux-2.6.27/security/apparmor/lsm.c 2008-10-29 14:28:53.329440939 +0100
4127 + * Copyright (C) 1998-2007 Novell/SUSE
4129 + * This program is free software; you can redistribute it and/or
4130 + * modify it under the terms of the GNU General Public License as
4131 + * published by the Free Software Foundation, version 2 of the
4134 + * AppArmor LSM interface
4137 +#include <linux/security.h>
4138 +#include <linux/module.h>
4139 +#include <linux/mm.h>
4140 +#include <linux/mman.h>
4141 +#include <linux/mount.h>
4142 +#include <linux/namei.h>
4143 +#include <linux/ctype.h>
4144 +#include <linux/sysctl.h>
4145 +#include <linux/audit.h>
4146 +#include <net/sock.h>
4148 +#include "apparmor.h"
4149 +#include "inline.h"
4151 +/* Flag indicating whether initialization completed */
4152 +int apparmor_initialized = 0;
4154 +static int param_set_aabool(const char *val, struct kernel_param *kp);
4155 +static int param_get_aabool(char *buffer, struct kernel_param *kp);
4156 +#define param_check_aabool(name, p) __param_check(name, p, int)
4158 +static int param_set_aauint(const char *val, struct kernel_param *kp);
4159 +static int param_get_aauint(char *buffer, struct kernel_param *kp);
4160 +#define param_check_aauint(name, p) __param_check(name, p, int)
4162 +/* Flag values, also controllable via /sys/module/apparmor/parameters
4163 + * We define special types as we want to do additional mediation.
4165 + * Complain mode -- in complain mode access failures result in auditing only
4166 + * and task is allowed access. audit events are processed by userspace to
4167 + * generate policy. Default is 'enforce' (0).
4168 + * Value is also togglable per profile and referenced when global value is
4171 +int apparmor_complain = 0;
4172 +module_param_named(complain, apparmor_complain, aabool, S_IRUSR | S_IWUSR);
4173 +MODULE_PARM_DESC(apparmor_complain, "Toggle AppArmor complain mode");
4176 +int apparmor_debug = 0;
4177 +module_param_named(debug, apparmor_debug, aabool, S_IRUSR | S_IWUSR);
4178 +MODULE_PARM_DESC(apparmor_debug, "Toggle AppArmor debug mode");
4181 +int apparmor_audit = 0;
4182 +module_param_named(audit, apparmor_audit, aabool, S_IRUSR | S_IWUSR);
4183 +MODULE_PARM_DESC(apparmor_audit, "Toggle AppArmor audit mode");
4185 +/* Syscall logging mode */
4186 +int apparmor_logsyscall = 0;
4187 +module_param_named(logsyscall, apparmor_logsyscall, aabool, S_IRUSR | S_IWUSR);
4188 +MODULE_PARM_DESC(apparmor_logsyscall, "Toggle AppArmor logsyscall mode");
4190 +/* Maximum pathname length before accesses will start getting rejected */
4191 +unsigned int apparmor_path_max = 2 * PATH_MAX;
4192 +module_param_named(path_max, apparmor_path_max, aauint, S_IRUSR | S_IWUSR);
4193 +MODULE_PARM_DESC(apparmor_path_max, "Maximum pathname length allowed");
4195 +/* Boot time disable flag */
4196 +#ifdef CONFIG_SECURITY_APPARMOR_DISABLE
4197 +#define AA_ENABLED_PERMS 0600
4199 +#define AA_ENABLED_PERMS 0400
4201 +static int param_set_aa_enabled(const char *val, struct kernel_param *kp);
4202 +unsigned int apparmor_enabled = CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE;
4203 +module_param_call(enabled, param_set_aa_enabled, param_get_aauint,
4204 + &apparmor_enabled, AA_ENABLED_PERMS);
4205 +MODULE_PARM_DESC(apparmor_enabled, "Enable/Disable Apparmor on boot");
4207 +static int __init apparmor_enabled_setup(char *str)
4209 + apparmor_enabled = simple_strtol(str, NULL, 0);
4212 +__setup("apparmor=", apparmor_enabled_setup);
4214 +static int param_set_aabool(const char *val, struct kernel_param *kp)
4216 + if (aa_task_context(current))
4218 + return param_set_bool(val, kp);
4221 +static int param_get_aabool(char *buffer, struct kernel_param *kp)
4223 + if (aa_task_context(current))
4225 + return param_get_bool(buffer, kp);
4228 +static int param_set_aauint(const char *val, struct kernel_param *kp)
4230 + if (aa_task_context(current))
4232 + return param_set_uint(val, kp);
4235 +static int param_get_aauint(char *buffer, struct kernel_param *kp)
4237 + if (aa_task_context(current))
4239 + return param_get_uint(buffer, kp);
4242 +/* allow run time disabling of apparmor */
4243 +static int param_set_aa_enabled(const char *val, struct kernel_param *kp)
4248 + if (!apparmor_initialized) {
4249 + apparmor_enabled = 0;
4253 + if (aa_task_context(current))
4256 + if (!apparmor_enabled)
4262 + l = simple_strtoul(val, &endp, 0);
4263 + if (endp == val || l != 0)
4266 + apparmor_enabled = 0;
4267 + apparmor_disable();
4271 +static int aa_reject_syscall(struct task_struct *task, gfp_t flags,
4274 + struct aa_profile *profile = aa_get_profile(task);
4278 + error = aa_audit_syscallreject(profile, flags, name);
4279 + aa_put_profile(profile);
4285 +static int apparmor_ptrace(struct task_struct *tracer,
4286 + struct task_struct *tracee)
4288 + struct aa_task_context *cxt;
4292 + * tracer can ptrace tracee when
4293 + * - tracer is unconfined
4294 + * - tracer & tracee are in the same namespace &&
4295 + * - tracer is in complain mode
4296 + * - tracer and tracee are confined by the same profile
4297 + * - tracer profile has CAP_SYS_PTRACE
4301 + cxt = aa_task_context(tracer);
4303 + if (tracer->nsproxy != tracee->nsproxy) {
4304 + struct aa_audit sa;
4305 + memset(&sa, 0, sizeof(sa));
4306 + sa.operation = "ptrace";
4307 + sa.gfp_mask = GFP_ATOMIC;
4308 + sa.parent = tracer->pid;
4309 + sa.task = tracee->pid;
4310 + sa.info = "different namespaces";
4311 + aa_audit_reject(cxt->profile, &sa);
4314 + struct aa_task_context *tracee_cxt =
4315 + aa_task_context(tracee);
4317 + error = aa_may_ptrace(cxt, tracee_cxt ?
4318 + tracee_cxt->profile : NULL);
4319 + if (error && PROFILE_COMPLAIN(cxt->profile)) {
4320 + struct aa_audit sa;
4321 + memset(&sa, 0, sizeof(sa));
4322 + sa.operation = "ptrace";
4323 + sa.gfp_mask = GFP_ATOMIC;
4324 + sa.parent = tracer->pid;
4325 + sa.task = tracee->pid;
4326 + aa_audit_hint(cxt->profile, &sa);
4330 + rcu_read_unlock();
4335 +static int apparmor_ptrace_may_access(struct task_struct *child,
4336 + unsigned int mode)
4338 + return apparmor_ptrace(current, child);
4342 +static int apparmor_ptrace_traceme(struct task_struct *parent)
4344 + return apparmor_ptrace(parent, current);
4347 +static int apparmor_capable(struct task_struct *task, int cap)
4350 + struct aa_task_context *cxt;
4352 + /* cap_capable returns 0 on success, else -EPERM */
4353 + error = cap_capable(task, cap);
4356 + cxt = aa_task_context(task);
4357 + if (cxt && (!error || cap_raised(cxt->profile->set_caps, cap)))
4358 + error = aa_capability(cxt, cap);
4359 + rcu_read_unlock();
4364 +static int apparmor_sysctl(struct ctl_table *table, int op)
4366 + struct aa_profile *profile = aa_get_profile(current);
4370 + char *buffer, *name;
4377 + mask |= MAY_WRITE;
4380 + buffer = (char*)__get_free_page(GFP_KERNEL);
4383 + name = sysctl_pathname(table, buffer, PAGE_SIZE);
4384 + if (name && name - buffer >= 5) {
4386 + memcpy(name, "/proc", 5);
4387 + error = aa_perm_path(profile, "sysctl", name, mask, 0);
4389 + free_page((unsigned long)buffer);
4393 + aa_put_profile(profile);
4397 +static int apparmor_bprm_set_security(struct linux_binprm *bprm)
4399 + /* handle capability bits with setuid, etc */
4400 + cap_bprm_set_security(bprm);
4401 + /* already set based on script name */
4402 + if (bprm->sh_bang)
4404 + return aa_register(bprm);
4407 +static int apparmor_bprm_secureexec(struct linux_binprm *bprm)
4409 + int ret = cap_bprm_secureexec(bprm);
4411 + if (!ret && (unsigned long)bprm->security & AA_SECURE_EXEC_NEEDED) {
4412 + AA_DEBUG("%s: secureexec required for %s\n",
4413 + __FUNCTION__, bprm->filename);
4420 +static int apparmor_sb_mount(char *dev_name, struct path *path, char *type,
4421 + unsigned long flags, void *data)
4423 + return aa_reject_syscall(current, GFP_KERNEL, "mount");
4426 +static int apparmor_umount(struct vfsmount *mnt, int flags)
4428 + return aa_reject_syscall(current, GFP_KERNEL, "umount");
4431 +static int apparmor_inode_mkdir(struct inode *dir, struct dentry *dentry,
4432 + struct vfsmount *mnt, int mask)
4434 + struct aa_profile *profile;
4437 + if (!mnt || !mediated_filesystem(dir))
4440 + profile = aa_get_profile(current);
4443 + error = aa_perm_dir(profile, "inode_mkdir", dentry, mnt,
4446 + aa_put_profile(profile);
4452 +static int apparmor_inode_rmdir(struct inode *dir, struct dentry *dentry,
4453 + struct vfsmount *mnt)
4455 + struct aa_profile *profile;
4458 + if (!mnt || !mediated_filesystem(dir))
4461 + profile = aa_get_profile(current);
4464 + error = aa_perm_dir(profile, "inode_rmdir", dentry, mnt,
4467 + aa_put_profile(profile);
4473 +static int aa_permission(const char *operation, struct inode *inode,
4474 + struct dentry *dentry, struct vfsmount *mnt,
4475 + int mask, int check)
4479 + if (mnt && mediated_filesystem(inode)) {
4480 + struct aa_profile *profile;
4482 + profile = aa_get_profile(current);
4484 + error = aa_perm(profile, operation, dentry, mnt, mask,
4486 + aa_put_profile(profile);
4491 +static inline int aa_mask_permissions(int mask)
4493 + if (mask & MAY_APPEND)
4494 + mask &= (MAY_READ | MAY_APPEND | MAY_EXEC);
4496 + mask &= (MAY_READ | MAY_WRITE | MAY_EXEC);
4500 +static int apparmor_inode_create(struct inode *dir, struct dentry *dentry,
4501 + struct vfsmount *mnt, int mask)
4503 + return aa_permission("inode_create", dir, dentry, mnt, MAY_APPEND, 0);
4506 +static int apparmor_inode_link(struct dentry *old_dentry,
4507 + struct vfsmount *old_mnt, struct inode *dir,
4508 + struct dentry *new_dentry,
4509 + struct vfsmount *new_mnt)
4512 + struct aa_profile *profile;
4514 + if (!old_mnt || !new_mnt || !mediated_filesystem(dir))
4517 + profile = aa_get_profile(current);
4520 + error = aa_link(profile, new_dentry, new_mnt,
4521 + old_dentry, old_mnt);
4523 + aa_put_profile(profile);
4529 +static int apparmor_inode_unlink(struct inode *dir, struct dentry *dentry,
4530 + struct vfsmount *mnt)
4534 + if (S_ISDIR(dentry->d_inode->i_mode))
4535 + check |= AA_CHECK_DIR;
4536 + return aa_permission("inode_unlink", dir, dentry, mnt, MAY_WRITE,
4540 +static int apparmor_inode_symlink(struct inode *dir, struct dentry *dentry,
4541 + struct vfsmount *mnt, const char *old_name)
4543 + return aa_permission("inode_symlink", dir, dentry, mnt, MAY_WRITE, 0);
4546 +static int apparmor_inode_mknod(struct inode *dir, struct dentry *dentry,
4547 + struct vfsmount *mnt, int mode, dev_t dev)
4549 + return aa_permission("inode_mknod", dir, dentry, mnt, MAY_WRITE, 0);
4552 +static int apparmor_inode_rename(struct inode *old_dir,
4553 + struct dentry *old_dentry,
4554 + struct vfsmount *old_mnt,
4555 + struct inode *new_dir,
4556 + struct dentry *new_dentry,
4557 + struct vfsmount *new_mnt)
4559 + struct aa_profile *profile;
4562 + if ((!old_mnt && !new_mnt) || !mediated_filesystem(old_dir))
4565 + profile = aa_get_profile(current);
4568 + struct inode *inode = old_dentry->d_inode;
4571 + if (inode && S_ISDIR(inode->i_mode))
4572 + check |= AA_CHECK_DIR;
4574 + error = aa_perm(profile, "inode_rename", old_dentry,
4575 + old_mnt, MAY_READ | MAY_WRITE, check);
4577 + if (!error && new_mnt) {
4578 + error = aa_perm(profile, "inode_rename", new_dentry,
4579 + new_mnt, MAY_WRITE, check);
4583 + aa_put_profile(profile);
4589 +static int apparmor_inode_permission(struct inode *inode, int mask)
4594 +static int apparmor_inode_setattr(struct dentry *dentry, struct vfsmount *mnt,
4595 + struct iattr *iattr)
4602 + if (mediated_filesystem(dentry->d_inode)) {
4603 + struct aa_profile *profile;
4605 + profile = aa_get_profile(current);
4607 + * Mediate any attempt to change attributes of a file
4608 + * (chmod, chown, chgrp, etc)
4611 + error = aa_attr(profile, dentry, mnt, iattr);
4613 + aa_put_profile(profile);
4620 +static int aa_xattr_permission(struct dentry *dentry, struct vfsmount *mnt,
4621 + const char *operation, int mask,
4622 + struct file *file)
4626 + if (mnt && mediated_filesystem(dentry->d_inode)) {
4627 + struct aa_profile *profile = aa_get_profile(current);
4628 + int check = file ? AA_CHECK_FD : 0;
4631 + error = aa_perm_xattr(profile, operation, dentry, mnt,
4633 + aa_put_profile(profile);
4639 +static int apparmor_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
4640 + const char *name, const void *value,
4641 + size_t size, int flags, struct file *file)
4643 + int error = cap_inode_setxattr(dentry, mnt, name, value, size, flags,
4647 + error = aa_xattr_permission(dentry, mnt, "xattr set",
4652 +static int apparmor_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
4653 + const char *name, struct file *file)
4655 + return aa_xattr_permission(dentry, mnt, "xattr get", MAY_READ, file);
4658 +static int apparmor_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt,
4659 + struct file *file)
4661 + return aa_xattr_permission(dentry, mnt, "xattr list", MAY_READ, file);
4664 +static int apparmor_inode_removexattr(struct dentry *dentry,
4665 + struct vfsmount *mnt, const char *name,
4666 + struct file *file)
4668 + return aa_xattr_permission(dentry, mnt, "xattr remove", MAY_WRITE,
4672 +static int aa_file_permission(const char *op, struct file *file, int mask)
4674 + struct aa_profile *profile;
4675 + struct aa_profile *file_profile = (struct aa_profile*)file->f_security;
4678 + if (!file_profile)
4682 + * If this file was opened under a different profile, we
4683 + * revalidate the access against the current profile.
4685 + profile = aa_get_profile(current);
4686 + if (profile && (file_profile != profile || mask & AA_MAY_LOCK)) {
4687 + struct dentry *dentry = file->f_dentry;
4688 + struct vfsmount *mnt = file->f_vfsmnt;
4689 + struct inode *inode = dentry->d_inode;
4690 + int check = AA_CHECK_FD;
4693 + * FIXME: We should remember which profiles we revalidated
4696 + if (S_ISDIR(inode->i_mode))
4697 + check |= AA_CHECK_DIR;
4698 + error = aa_permission(op, inode, dentry, mnt, mask, check);
4700 + aa_put_profile(profile);
4706 +static int apparmor_file_permission(struct file *file, int mask)
4708 + return aa_file_permission("file_permission", file,
4709 + aa_mask_permissions(mask));
4712 +static inline int apparmor_file_lock (struct file *file, unsigned int cmd)
4714 + int mask = AA_MAY_LOCK;
4715 + if (cmd == F_WRLCK)
4716 + mask |= MAY_WRITE;
4717 + return aa_file_permission("file_lock", file, mask);
4720 +static int apparmor_file_alloc_security(struct file *file)
4722 + struct aa_profile *profile;
4724 + profile = aa_get_profile(current);
4726 + file->f_security = profile;
4731 +static void apparmor_file_free_security(struct file *file)
4733 + struct aa_profile *file_profile = (struct aa_profile*)file->f_security;
4735 + aa_put_profile(file_profile);
4738 +static inline int aa_mmap(struct file *file, const char *operation,
4739 + unsigned long prot, unsigned long flags)
4741 + struct dentry *dentry;
4744 + if (!file || !file->f_security)
4747 + if (prot & PROT_READ)
4749 + /* Private mappings don't require write perms since they don't
4750 + * write back to the files */
4751 + if ((prot & PROT_WRITE) && !(flags & MAP_PRIVATE))
4752 + mask |= MAY_WRITE;
4753 + if (prot & PROT_EXEC)
4754 + mask |= AA_EXEC_MMAP;
4756 + dentry = file->f_dentry;
4757 + return aa_permission(operation, dentry->d_inode, dentry,
4758 + file->f_vfsmnt, mask, AA_CHECK_FD);
4761 +static int apparmor_file_mmap(struct file *file, unsigned long reqprot,
4762 + unsigned long prot, unsigned long flags,
4763 + unsigned long addr, unsigned long addr_only)
4765 + if ((addr < mmap_min_addr) && !capable(CAP_SYS_RAWIO)) {
4766 + struct aa_profile *profile = aa_get_profile(current);
4768 + /* future control check here */
4772 + aa_put_profile(profile);
4775 + return aa_mmap(file, "file_mmap", prot, flags);
4778 +static int apparmor_file_mprotect(struct vm_area_struct *vma,
4779 + unsigned long reqprot, unsigned long prot)
4781 + return aa_mmap(vma->vm_file, "file_mprotect", prot,
4782 + !(vma->vm_flags & VM_SHARED) ? MAP_PRIVATE : 0);
4785 +static int apparmor_path_permission(struct path *path, int mask)
4787 + struct inode *inode;
4793 + inode = path->dentry->d_inode;
4795 + mask = aa_mask_permissions(mask);
4796 + if (S_ISDIR(inode->i_mode)) {
4797 + check |= AA_CHECK_DIR;
4798 + /* allow traverse accesses to directories */
4799 + mask &= ~MAY_EXEC;
4804 + return aa_permission("inode_permission", inode, path->dentry,
4805 + path->mnt, mask, check);
4808 +static int apparmor_task_alloc_security(struct task_struct *task)
4810 + return aa_clone(task);
4814 + * Called from IRQ context from RCU callback.
4816 +static void apparmor_task_free_security(struct task_struct *task)
4821 +static int apparmor_socket_create(int family, int type, int protocol, int kern)
4823 + struct aa_profile *profile;
4829 + profile = aa_get_profile(current);
4831 + error = aa_net_perm(profile, "socket_create", family,
4833 + aa_put_profile(profile);
4838 +static int apparmor_socket_post_create(struct socket *sock, int family,
4839 + int type, int protocol, int kern)
4841 + struct sock *sk = sock->sk;
4846 + return aa_revalidate_sk(sk, "socket_post_create");
4849 +static int apparmor_socket_bind(struct socket *sock,
4850 + struct sockaddr *address, int addrlen)
4852 + struct sock *sk = sock->sk;
4854 + return aa_revalidate_sk(sk, "socket_bind");
4857 +static int apparmor_socket_connect(struct socket *sock,
4858 + struct sockaddr *address, int addrlen)
4860 + struct sock *sk = sock->sk;
4862 + return aa_revalidate_sk(sk, "socket_connect");
4865 +static int apparmor_socket_listen(struct socket *sock, int backlog)
4867 + struct sock *sk = sock->sk;
4869 + return aa_revalidate_sk(sk, "socket_listen");
4872 +static int apparmor_socket_accept(struct socket *sock, struct socket *newsock)
4874 + struct sock *sk = sock->sk;
4876 + return aa_revalidate_sk(sk, "socket_accept");
4879 +static int apparmor_socket_sendmsg(struct socket *sock,
4880 + struct msghdr *msg, int size)
4882 + struct sock *sk = sock->sk;
4884 + return aa_revalidate_sk(sk, "socket_sendmsg");
4887 +static int apparmor_socket_recvmsg(struct socket *sock,
4888 + struct msghdr *msg, int size, int flags)
4890 + struct sock *sk = sock->sk;
4892 + return aa_revalidate_sk(sk, "socket_recvmsg");
4895 +static int apparmor_socket_getsockname(struct socket *sock)
4897 + struct sock *sk = sock->sk;
4899 + return aa_revalidate_sk(sk, "socket_getsockname");
4902 +static int apparmor_socket_getpeername(struct socket *sock)
4904 + struct sock *sk = sock->sk;
4906 + return aa_revalidate_sk(sk, "socket_getpeername");
4909 +static int apparmor_socket_getsockopt(struct socket *sock, int level,
4912 + struct sock *sk = sock->sk;
4914 + return aa_revalidate_sk(sk, "socket_getsockopt");
4917 +static int apparmor_socket_setsockopt(struct socket *sock, int level,
4920 + struct sock *sk = sock->sk;
4922 + return aa_revalidate_sk(sk, "socket_setsockopt");
4925 +static int apparmor_socket_shutdown(struct socket *sock, int how)
4927 + struct sock *sk = sock->sk;
4929 + return aa_revalidate_sk(sk, "socket_shutdown");
4932 +static int apparmor_getprocattr(struct task_struct *task, char *name,
4937 + struct aa_profile *profile;
4939 + /* AppArmor only supports the "current" process attribute */
4940 + if (strcmp(name, "current") != 0)
4943 + /* must be task querying itself or admin */
4944 + if (current != task && !capable(CAP_SYS_ADMIN))
4947 + profile = aa_get_profile(task);
4948 + error = aa_getprocattr(profile, value, &len);
4949 + aa_put_profile(profile);
4956 +static int apparmor_setprocattr(struct task_struct *task, char *name,
4957 + void *value, size_t size)
4959 + char *command, *args;
4962 + if (strcmp(name, "current") != 0 || size == 0 || size >= PAGE_SIZE)
4965 + args[size] = '\0';
4966 + args = strstrip(args);
4967 + command = strsep(&args, " ");
4970 + while (isspace(*args))
4975 + if (strcmp(command, "changehat") == 0) {
4976 + if (current != task)
4978 + error = aa_setprocattr_changehat(args);
4979 + } else if (strcmp(command, "changeprofile") == 0) {
4980 + if (current != task)
4982 + error = aa_setprocattr_changeprofile(args);
4983 + } else if (strcmp(command, "setprofile") == 0) {
4984 + struct aa_profile *profile;
4986 + /* Only an unconfined process with admin capabilities
4987 + * may change the profile of another task.
4990 + if (!capable(CAP_SYS_ADMIN))
4993 + profile = aa_get_profile(current);
4995 + struct aa_audit sa;
4996 + memset(&sa, 0, sizeof(sa));
4997 + sa.operation = "profile_set";
4998 + sa.gfp_mask = GFP_KERNEL;
4999 + sa.task = task->pid;
5000 + sa.info = "from confined process";
5001 + aa_audit_reject(profile, &sa);
5002 + aa_put_profile(profile);
5005 + error = aa_setprocattr_setprofile(task, args);
5007 + struct aa_audit sa;
5008 + memset(&sa, 0, sizeof(sa));
5009 + sa.operation = "setprocattr";
5010 + sa.gfp_mask = GFP_KERNEL;
5011 + sa.info = "invalid command";
5012 + sa.name = command;
5013 + sa.task = task->pid;
5014 + aa_audit_reject(NULL, &sa);
5023 +static int apparmor_task_setrlimit(unsigned int resource,
5024 + struct rlimit *new_rlim)
5026 + struct aa_profile *profile;
5029 + profile = aa_get_profile(current);
5031 + error = aa_task_setrlimit(profile, resource, new_rlim);
5033 + aa_put_profile(profile);
5038 +struct security_operations apparmor_ops = {
5039 + .ptrace_may_access = apparmor_ptrace_may_access,
5040 + .ptrace_traceme = apparmor_ptrace_traceme,
5041 + .capget = cap_capget,
5042 + .capset_check = cap_capset_check,
5043 + .capset_set = cap_capset_set,
5044 + .sysctl = apparmor_sysctl,
5045 + .capable = apparmor_capable,
5046 + .syslog = cap_syslog,
5048 + .bprm_apply_creds = cap_bprm_apply_creds,
5049 + .bprm_set_security = apparmor_bprm_set_security,
5050 + .bprm_secureexec = apparmor_bprm_secureexec,
5052 + .sb_mount = apparmor_sb_mount,
5053 + .sb_umount = apparmor_umount,
5055 + .inode_mkdir = apparmor_inode_mkdir,
5056 + .inode_rmdir = apparmor_inode_rmdir,
5057 + .inode_create = apparmor_inode_create,
5058 + .inode_link = apparmor_inode_link,
5059 + .inode_unlink = apparmor_inode_unlink,
5060 + .inode_symlink = apparmor_inode_symlink,
5061 + .inode_mknod = apparmor_inode_mknod,
5062 + .inode_rename = apparmor_inode_rename,
5063 + .inode_permission = apparmor_inode_permission,
5064 + .inode_setattr = apparmor_inode_setattr,
5065 + .inode_setxattr = apparmor_inode_setxattr,
5066 + .inode_getxattr = apparmor_inode_getxattr,
5067 + .inode_listxattr = apparmor_inode_listxattr,
5068 + .inode_removexattr = apparmor_inode_removexattr,
5069 + .file_permission = apparmor_file_permission,
5070 + .file_alloc_security = apparmor_file_alloc_security,
5071 + .file_free_security = apparmor_file_free_security,
5072 + .file_mmap = apparmor_file_mmap,
5073 + .file_mprotect = apparmor_file_mprotect,
5074 + .file_lock = apparmor_file_lock,
5076 + .path_permission = apparmor_path_permission,
5078 + .task_alloc_security = apparmor_task_alloc_security,
5079 + .task_free_security = apparmor_task_free_security,
5080 + .task_post_setuid = cap_task_post_setuid,
5081 + .task_reparent_to_init = cap_task_reparent_to_init,
5082 + .task_setrlimit = apparmor_task_setrlimit,
5084 + .getprocattr = apparmor_getprocattr,
5085 + .setprocattr = apparmor_setprocattr,
5087 + .socket_create = apparmor_socket_create,
5088 + .socket_post_create = apparmor_socket_post_create,
5089 + .socket_bind = apparmor_socket_bind,
5090 + .socket_connect = apparmor_socket_connect,
5091 + .socket_listen = apparmor_socket_listen,
5092 + .socket_accept = apparmor_socket_accept,
5093 + .socket_sendmsg = apparmor_socket_sendmsg,
5094 + .socket_recvmsg = apparmor_socket_recvmsg,
5095 + .socket_getsockname = apparmor_socket_getsockname,
5096 + .socket_getpeername = apparmor_socket_getpeername,
5097 + .socket_getsockopt = apparmor_socket_getsockopt,
5098 + .socket_setsockopt = apparmor_socket_setsockopt,
5099 + .socket_shutdown = apparmor_socket_shutdown,
5102 +void info_message(const char *str)
5104 + struct aa_audit sa;
5105 + memset(&sa, 0, sizeof(sa));
5106 + sa.gfp_mask = GFP_KERNEL;
5108 + printk(KERN_INFO "AppArmor: %s\n", str);
5109 + if (audit_enabled)
5110 + aa_audit_message(NULL, &sa, AUDIT_APPARMOR_STATUS);
5113 +static int __init apparmor_init(void)
5117 + if (!apparmor_enabled) {
5118 + info_message("AppArmor disabled by boottime parameter\n");
5122 + if ((error = create_apparmorfs())) {
5123 + AA_ERROR("Unable to activate AppArmor filesystem\n");
5124 + goto createfs_out;
5127 + if ((error = alloc_default_namespace())){
5128 + AA_ERROR("Unable to allocate default profile namespace\n");
5132 + if ((error = register_security(&apparmor_ops))) {
5133 + AA_ERROR("Unable to register AppArmor\n");
5134 + goto register_security_out;
5137 + /* Report that AppArmor successfully initialized */
5138 + apparmor_initialized = 1;
5139 + if (apparmor_complain)
5140 + info_message("AppArmor initialized: complainmode enabled");
5142 + info_message("AppArmor initialized");
5146 +register_security_out:
5147 + free_default_namespace();
5150 + destroy_apparmorfs();
5157 +security_initcall(apparmor_init);
5159 +void apparmor_disable(void)
5161 + /* Remove and release all the profiles on the profile list. */
5162 + mutex_lock(&aa_interface_lock);
5163 + aa_profile_ns_list_release();
5165 + /* FIXME: cleanup profiles references on files */
5166 + free_default_namespace();
5169 + * Delay for an rcu cycle to make sure that all active task
5170 + * context readers have finished, and all profiles have been
5171 + * freed by their rcu callbacks.
5173 + synchronize_rcu();
5175 + destroy_apparmorfs();
5176 + mutex_unlock(&aa_interface_lock);
5178 + apparmor_initialized = 0;
5180 + info_message("AppArmor protection removed");
5183 +MODULE_DESCRIPTION("AppArmor process confinement");
5184 +MODULE_AUTHOR("Novell/Immunix, http://bugs.opensuse.org");
5185 +MODULE_LICENSE("GPL");
5186 diff -uprN linux-2.6.27./security/apparmor/main.c linux-2.6.27/security/apparmor/main.c
5187 --- linux-2.6.27./security/apparmor/main.c 1970-01-01 01:00:00.000000000 +0100
5188 +++ linux-2.6.27/security/apparmor/main.c 2008-10-29 14:28:53.326113825 +0100
5191 + * Copyright (C) 2002-2007 Novell/SUSE
5193 + * This program is free software; you can redistribute it and/or
5194 + * modify it under the terms of the GNU General Public License as
5195 + * published by the Free Software Foundation, version 2 of the
5201 +#include <linux/security.h>
5202 +#include <linux/namei.h>
5203 +#include <linux/audit.h>
5204 +#include <linux/mount.h>
5205 +#include <linux/ptrace.h>
5206 +#include <linux/socket.h>
5207 +#include <linux/net.h>
5208 +#include <net/sock.h>
5210 +#include "apparmor.h"
5212 +#include "inline.h"
5215 + * Table of capability names: we generate it from capabilities.h.
5217 +static const char *capability_names[] = {
5218 +#include "capability_names.h"
5221 +struct aa_namespace *default_namespace;
5223 +static int aa_inode_mode(struct inode *inode)
5225 + /* if the inode doesn't exist the user is creating it */
5226 + if (!inode || current->fsuid == inode->i_uid)
5227 + return AA_USER_SHIFT;
5228 + return AA_OTHER_SHIFT;
5231 +int alloc_default_namespace(void)
5233 + struct aa_namespace *ns;
5234 + char *name = kstrdup("default", GFP_KERNEL);
5237 + ns = alloc_aa_namespace(name);
5243 + write_lock(&profile_ns_list_lock);
5244 + default_namespace = ns;
5245 + aa_get_namespace(ns);
5246 + list_add(&ns->list, &profile_ns_list);
5247 + write_unlock(&profile_ns_list_lock);
5252 +void free_default_namespace(void)
5254 + write_lock(&profile_ns_list_lock);
5255 + list_del_init(&default_namespace->list);
5256 + write_unlock(&profile_ns_list_lock);
5257 + aa_put_namespace(default_namespace);
5258 + default_namespace = NULL;
5261 +static void aa_audit_file_sub_mask(struct audit_buffer *ab, char *buffer,
5264 + const char unsafex[] = "upcn";
5265 + const char safex[] = "UPCN";
5268 + if (mask & AA_EXEC_MMAP)
5270 + if (mask & MAY_READ)
5272 + if (mask & MAY_WRITE)
5274 + else if (mask & MAY_APPEND)
5276 + if (mask & MAY_EXEC) {
5277 + int index = AA_EXEC_INDEX(mask);
5278 + /* all indexes > 4 are also named transitions */
5282 + if (mask & AA_EXEC_UNSAFE)
5283 + *m++ = unsafex[index - 1];
5285 + *m++ = safex[index - 1];
5287 + if (mask & AA_EXEC_INHERIT)
5291 + if (mask & AA_MAY_LINK)
5293 + if (mask & AA_MAY_LOCK)
5298 +static void aa_audit_file_mask(struct audit_buffer *ab, const char *name,
5301 + char user[10], other[10];
5303 + aa_audit_file_sub_mask(ab, user,
5304 + (mask & AA_USER_PERMS) >> AA_USER_SHIFT);
5305 + aa_audit_file_sub_mask(ab, other,
5306 + (mask & AA_OTHER_PERMS) >> AA_OTHER_SHIFT);
5308 + audit_log_format(ab, " %s=\"%s::%s\"", name, user, other);
5311 +static const char *address_families[] = {
5312 +#include "af_names.h"
5315 +static const char *sock_types[] = {
5330 + * aa_audit - Log an audit event to the audit subsystem
5331 + * @profile: profile to check against
5332 + * @sa: audit event
5333 + * @audit_cxt: audit context to log message to
5334 + * @type: audit event number
5336 +static int aa_audit_base(struct aa_profile *profile, struct aa_audit *sa,
5337 + struct audit_context *audit_cxt, int type)
5339 + struct audit_buffer *ab = NULL;
5341 + ab = audit_log_start(audit_cxt, sa->gfp_mask, type);
5344 + AA_ERROR("Unable to log event (%d) to audit subsys\n",
5346 + /* don't fail operations in complain mode even if logging
5348 + return type == AUDIT_APPARMOR_ALLOWED ? 0 : -ENOMEM;
5351 + if (sa->operation)
5352 + audit_log_format(ab, "operation=\"%s\"", sa->operation);
5355 + audit_log_format(ab, " info=\"%s\"", sa->info);
5356 + if (sa->error_code)
5357 + audit_log_format(ab, " error=%d", sa->error_code);
5360 + if (sa->request_mask)
5361 + aa_audit_file_mask(ab, "requested_mask", sa->request_mask);
5363 + if (sa->denied_mask)
5364 + aa_audit_file_mask(ab, "denied_mask", sa->denied_mask);
5366 + if (sa->request_mask)
5367 + audit_log_format(ab, " fsuid=%d", current->fsuid);
5370 + audit_log_format(ab, " rlimit=%d", sa->rlimit - 1);
5373 + struct iattr *iattr = sa->iattr;
5375 + audit_log_format(ab, " attribute=\"%s%s%s%s%s%s%s\"",
5376 + iattr->ia_valid & ATTR_MODE ? "mode," : "",
5377 + iattr->ia_valid & ATTR_UID ? "uid," : "",
5378 + iattr->ia_valid & ATTR_GID ? "gid," : "",
5379 + iattr->ia_valid & ATTR_SIZE ? "size," : "",
5380 + iattr->ia_valid & (ATTR_ATIME | ATTR_ATIME_SET) ?
5382 + iattr->ia_valid & (ATTR_MTIME | ATTR_MTIME_SET) ?
5384 + iattr->ia_valid & ATTR_CTIME ? "ctime," : "");
5388 + audit_log_format(ab, " task=%d", sa->task);
5391 + audit_log_format(ab, " parent=%d", sa->parent);
5394 + audit_log_format(ab, " name=");
5395 + audit_log_untrustedstring(ab, sa->name);
5399 + audit_log_format(ab, " name2=");
5400 + audit_log_untrustedstring(ab, sa->name2);
5403 + if (sa->family || sa->type) {
5404 + if (address_families[sa->family])
5405 + audit_log_format(ab, " family=\"%s\"",
5406 + address_families[sa->family]);
5408 + audit_log_format(ab, " family=\"unknown(%d)\"",
5411 + if (sock_types[sa->type])
5412 + audit_log_format(ab, " sock_type=\"%s\"",
5413 + sock_types[sa->type]);
5415 + audit_log_format(ab, " sock_type=\"unknown(%d)\"",
5418 + audit_log_format(ab, " protocol=%d", sa->protocol);
5421 + audit_log_format(ab, " pid=%d", current->pid);
5424 + audit_log_format(ab, " profile=");
5425 + audit_log_untrustedstring(ab, profile->name);
5427 + if (profile->ns != default_namespace) {
5428 + audit_log_format(ab, " namespace=");
5429 + audit_log_untrustedstring(ab, profile->ns->name);
5433 + audit_log_end(ab);
5435 + return type == AUDIT_APPARMOR_ALLOWED ? 0 : sa->error_code;
5439 + * aa_audit_syscallreject - Log a syscall rejection to the audit subsystem
5440 + * @profile: profile to check against
5441 + * @gfp: memory allocation flags
5442 + * @msg: string describing syscall being rejected
5444 +int aa_audit_syscallreject(struct aa_profile *profile, gfp_t gfp,
5447 + struct aa_audit sa;
5448 + memset(&sa, 0, sizeof(sa));
5449 + sa.operation = "syscall";
5451 + sa.gfp_mask = gfp;
5452 + sa.error_code = -EPERM;
5454 + return aa_audit_base(profile, &sa, current->audit_context,
5455 + AUDIT_APPARMOR_DENIED);
5458 +int aa_audit_message(struct aa_profile *profile, struct aa_audit *sa,
5461 + struct audit_context *audit_cxt;
5463 + audit_cxt = apparmor_logsyscall ? current->audit_context : NULL;
5464 + return aa_audit_base(profile, sa, audit_cxt, type);
5467 +void aa_audit_hint(struct aa_profile *profile, struct aa_audit *sa)
5469 + aa_audit_message(profile, sa, AUDIT_APPARMOR_HINT);
5472 +void aa_audit_status(struct aa_profile *profile, struct aa_audit *sa)
5474 + aa_audit_message(profile, sa, AUDIT_APPARMOR_STATUS);
5477 +int aa_audit_reject(struct aa_profile *profile, struct aa_audit *sa)
5479 + return aa_audit_message(profile, sa, AUDIT_APPARMOR_DENIED);
5483 + * aa_audit - Log an audit event to the audit subsystem
5484 + * @profile: profile to check against
5485 + * @sa: audit event
5487 +int aa_audit(struct aa_profile *profile, struct aa_audit *sa)
5489 + int type = AUDIT_APPARMOR_DENIED;
5490 + struct audit_context *audit_cxt;
5492 + if (likely(!sa->error_code))
5493 + type = AUDIT_APPARMOR_AUDIT;
5494 + else if (PROFILE_COMPLAIN(profile))
5495 + type = AUDIT_APPARMOR_ALLOWED;
5497 + audit_cxt = apparmor_logsyscall ? current->audit_context : NULL;
5498 + return aa_audit_base(profile, sa, audit_cxt, type);
5501 +static int aa_audit_file(struct aa_profile *profile, struct aa_audit *sa)
5503 + if (likely(!sa->error_code)) {
5504 + int mask = sa->audit_mask & AUDIT_FILE_MASK;
5506 + if (unlikely(PROFILE_AUDIT(profile)))
5507 + mask |= AUDIT_FILE_MASK;
5509 + if (likely(!(sa->request_mask & mask)))
5512 + /* mask off perms that are not being force audited */
5513 + sa->request_mask &= mask | ALL_AA_EXEC_TYPE;
5515 + int mask = AUDIT_QUIET_MASK(sa->audit_mask);
5517 + if (!(sa->denied_mask & ~mask))
5518 + return sa->error_code;
5520 + /* mask off perms whose denial is being silenced */
5521 + if (!PROFILE_COMPLAIN(profile))
5522 + sa->denied_mask &= (~mask) | ALL_AA_EXEC_TYPE;
5525 + return aa_audit(profile, sa);
5528 +static int aa_audit_caps(struct aa_profile *profile, struct aa_audit *sa,
5531 + if (likely(!sa->error_code)) {
5532 + if (likely(!PROFILE_AUDIT(profile) &&
5533 + !cap_raised(profile->audit_caps, cap)))
5537 + /* quieting of capabilities is handled the caps_logged cache */
5538 + return aa_audit(profile, sa);
5542 + * aa_file_denied - check for @mask access on a file
5543 + * @profile: profile to check against
5544 + * @name: pathname of file
5545 + * @mask: permission mask requested for file
5546 + * @audit_mask: return audit mask for the match
5548 + * Return %0 on success, or else the permissions in @mask that the
5551 +static int aa_file_denied(struct aa_profile *profile, const char *name,
5552 + int mask, int *audit_mask)
5554 + return (mask & ~aa_match(profile->file_rules, name, audit_mask));
5558 + * aa_link_denied - check for permission to link a file
5559 + * @profile: profile to check against
5560 + * @link: pathname of link being created
5561 + * @target: pathname of target to be linked to
5562 + * @target_mode: UGO shift for target inode
5563 + * @request_mask: the permissions subset valid only if link succeeds
5564 + * @audit_mask: return the audit_mask for the link permission
5565 + * Return %0 on success, or else the permissions that the profile denies.
5567 +static int aa_link_denied(struct aa_profile *profile, const char *link,
5568 + const char *target, int target_mode,
5569 + int *request_mask, int *audit_mask)
5571 + unsigned int state;
5572 + int l_mode, t_mode, l_x, t_x, denied_mask = 0;
5573 + int link_mask = AA_MAY_LINK << target_mode;
5575 + *request_mask = link_mask;
5577 + l_mode = aa_match_state(profile->file_rules, DFA_START, link, &state);
5579 + if (l_mode & link_mask) {
5581 + /* test to see if target can be paired with link */
5582 + state = aa_dfa_null_transition(profile->file_rules, state);
5583 + mode = aa_match_state(profile->file_rules, state, target,
5586 + if (!(mode & link_mask))
5587 + denied_mask |= link_mask;
5589 + *audit_mask = dfa_audit_mask(profile->file_rules, state);
5591 + /* return if link subset test is not required */
5592 + if (!(mode & (AA_LINK_SUBSET_TEST << target_mode)))
5593 + return denied_mask;
5596 + /* Do link perm subset test requiring permission on link are a
5597 + * subset of the permissions on target.
5598 + * If a subset test is required a permission subset test of the
5599 + * perms for the link are done against the user::other of the
5600 + * target's 'r', 'w', 'x', 'a', 'k', and 'm' permissions.
5602 + * If the link has 'x', an exact match of all the execute flags
5605 + denied_mask |= ~l_mode & link_mask;
5607 + t_mode = aa_match(profile->file_rules, target, NULL);
5609 + l_x = l_mode & (ALL_AA_EXEC_TYPE | AA_EXEC_BITS);
5610 + t_x = t_mode & (ALL_AA_EXEC_TYPE | AA_EXEC_BITS);
5612 + /* For actual subset test ignore valid-profile-transition flags,
5615 + l_mode &= AA_FILE_PERMS & ~AA_LINK_BITS;
5616 + t_mode &= AA_FILE_PERMS & ~AA_LINK_BITS;
5618 + *request_mask = l_mode | link_mask;
5621 + int x = l_x | (t_x & ALL_AA_EXEC_UNSAFE);
5622 + denied_mask |= l_mode & ~t_mode;
5623 + /* mask off x modes not used by link */
5625 + /* handle exec subset
5626 + * - link safe exec issubset of unsafe exec
5627 + * - no link x perm is subset of target having x perm
5629 + if ((l_mode & AA_USER_EXEC) &&
5630 + (x & AA_USER_EXEC_TYPE) != (t_x & AA_USER_EXEC_TYPE))
5631 + denied_mask = AA_USER_EXEC | (l_x & AA_USER_EXEC_TYPE);
5632 + if ((l_mode & AA_OTHER_EXEC) &&
5633 + (x & AA_OTHER_EXEC_TYPE) != (t_x & AA_OTHER_EXEC_TYPE))
5634 + denied_mask = AA_OTHER_EXEC | (l_x & AA_OTHER_EXEC_TYPE);
5637 + return denied_mask;
5641 + * aa_get_name - compute the pathname of a file
5642 + * @dentry: dentry of the file
5643 + * @mnt: vfsmount of the file
5644 + * @buffer: buffer that aa_get_name() allocated
5645 + * @check: AA_CHECK_DIR is set if the file is a directory
5647 + * Returns a pointer to the beginning of the pathname (which usually differs
5648 + * from the beginning of the buffer), or an error code.
5650 + * We need @check to indicate whether the file is a directory or not because
5651 + * the file may not yet exist, and so we cannot check the inode's file type.
5653 +static char *aa_get_name(struct dentry *dentry, struct vfsmount *mnt,
5654 + char **buffer, int check)
5657 + int is_dir, size = 256;
5659 + is_dir = (check & AA_CHECK_DIR) ? 1 : 0;
5662 + char *buf = kmalloc(size, GFP_KERNEL);
5664 + return ERR_PTR(-ENOMEM);
5666 + name = d_namespace_path(dentry, mnt, buf, size - is_dir);
5667 + if (!IS_ERR(name)) {
5668 + if (name[0] != '/') {
5670 + * This dentry is not connected to the
5671 + * namespace root -- reject access.
5674 + return ERR_PTR(-ENOENT);
5676 + if (is_dir && name[1] != '\0') {
5678 + * Append "/" to the pathname. The root
5679 + * directory is a special case; it already
5682 + buf[size - 2] = '/';
5683 + buf[size - 1] = '\0';
5689 + if (PTR_ERR(name) != -ENAMETOOLONG)
5694 + if (size > apparmor_path_max)
5695 + return ERR_PTR(-ENAMETOOLONG);
5699 +static char *new_compound_name(const char *n1, const char *n2)
5701 + char *name = kmalloc(strlen(n1) + strlen(n2) + 3, GFP_KERNEL);
5703 + sprintf(name, "%s//%s", n1, n2);
5706 +static inline void aa_put_name_buffer(char *buffer)
5712 + * aa_perm_dentry - check if @profile allows @mask for a file
5713 + * @profile: profile to check against
5714 + * @dentry: dentry of the file
5715 + * @mnt: vfsmount o the file
5716 + * @sa: audit context
5717 + * @mask: requested profile permissions
5718 + * @check: kind of check to perform
5720 + * Returns 0 upon success, or else an error code.
5722 + * @check indicates the file type, and whether the file was accessed through
5723 + * an open file descriptor (AA_CHECK_FD) or not.
5725 +static int aa_perm_dentry(struct aa_profile *profile, struct dentry *dentry,
5726 + struct vfsmount *mnt, struct aa_audit *sa, int check)
5729 + char *buffer = NULL;
5731 + sa->name = aa_get_name(dentry, mnt, &buffer, check);
5732 + sa->request_mask <<= aa_inode_mode(dentry->d_inode);
5733 + if (IS_ERR(sa->name)) {
5735 + * deleted files are given a pass on permission checks when
5736 + * accessed through a file descriptor.
5738 + if (PTR_ERR(sa->name) == -ENOENT && (check & AA_CHECK_FD))
5739 + sa->denied_mask = 0;
5741 + sa->denied_mask = sa->request_mask;
5742 + sa->error_code = PTR_ERR(sa->name);
5743 + if (sa->error_code == -ENOENT)
5744 + sa->info = "Failed name resolution - object not a valid entry";
5745 + else if (sa->error_code == -ENAMETOOLONG)
5746 + sa->info = "Failed name resolution - name too long";
5748 + sa->info = "Failed name resolution";
5752 + sa->denied_mask = aa_file_denied(profile, sa->name,
5756 + if (!sa->denied_mask)
5757 + sa->error_code = 0;
5759 + error = aa_audit_file(profile, sa);
5760 + aa_put_name_buffer(buffer);
5766 + * aa_attr - check if attribute change is allowed
5767 + * @profile: profile to check against
5768 + * @dentry: dentry of the file to check
5769 + * @mnt: vfsmount of the file to check
5770 + * @iattr: attribute changes requested
5772 +int aa_attr(struct aa_profile *profile, struct dentry *dentry,
5773 + struct vfsmount *mnt, struct iattr *iattr)
5775 + struct inode *inode = dentry->d_inode;
5777 + struct aa_audit sa;
5779 + memset(&sa, 0, sizeof(sa));
5780 + sa.operation = "setattr";
5781 + sa.gfp_mask = GFP_KERNEL;
5783 + sa.request_mask = MAY_WRITE;
5784 + sa.error_code = -EACCES;
5787 + if (inode && S_ISDIR(inode->i_mode))
5788 + check |= AA_CHECK_DIR;
5789 + if (iattr->ia_valid & ATTR_FILE)
5790 + check |= AA_CHECK_FD;
5792 + error = aa_perm_dentry(profile, dentry, mnt, &sa, check);
5798 + * aa_perm_xattr - check if xattr attribute change is allowed
5799 + * @profile: profile to check against
5800 + * @dentry: dentry of the file to check
5801 + * @mnt: vfsmount of the file to check
5802 + * @operation: xattr operation being done
5803 + * @mask: access mode requested
5804 + * @check: kind of check to perform
5806 +int aa_perm_xattr(struct aa_profile *profile, const char *operation,
5807 + struct dentry *dentry, struct vfsmount *mnt, int mask,
5810 + struct inode *inode = dentry->d_inode;
5812 + struct aa_audit sa;
5814 + memset(&sa, 0, sizeof(sa));
5815 + sa.operation = operation;
5816 + sa.gfp_mask = GFP_KERNEL;
5817 + sa.request_mask = mask;
5818 + sa.error_code = -EACCES;
5820 + if (inode && S_ISDIR(inode->i_mode))
5821 + check |= AA_CHECK_DIR;
5823 + error = aa_perm_dentry(profile, dentry, mnt, &sa, check);
5829 + * aa_perm - basic apparmor permissions check
5830 + * @profile: profile to check against
5831 + * @dentry: dentry of the file to check
5832 + * @mnt: vfsmount of the file to check
5833 + * @mask: access mode requested
5834 + * @check: kind of check to perform
5836 + * Determine if access @mask for the file is authorized by @profile.
5837 + * Returns 0 on success, or else an error code.
5839 +int aa_perm(struct aa_profile *profile, const char *operation,
5840 + struct dentry *dentry, struct vfsmount *mnt, int mask, int check)
5842 + struct aa_audit sa;
5848 + memset(&sa, 0, sizeof(sa));
5849 + sa.operation = operation;
5850 + sa.gfp_mask = GFP_KERNEL;
5851 + sa.request_mask = mask;
5852 + sa.error_code = -EACCES;
5854 + error = aa_perm_dentry(profile, dentry, mnt, &sa, check);
5862 + * @profile: profile to check against
5863 + * @dentry: dentry of directory to check
5864 + * @mnt: vfsmount of directory to check
5865 + * @operation: directory operation being performed
5866 + * @mask: access mode requested
5868 + * Determine if directory operation (make/remove) for dentry is authorized
5870 + * Returns 0 on success, or else an error code.
5872 +int aa_perm_dir(struct aa_profile *profile, const char *operation,
5873 + struct dentry *dentry, struct vfsmount *mnt, int mask)
5875 + struct aa_audit sa;
5877 + memset(&sa, 0, sizeof(sa));
5878 + sa.operation = operation;
5879 + sa.gfp_mask = GFP_KERNEL;
5880 + sa.request_mask = mask;
5881 + sa.error_code = -EACCES;
5883 + return aa_perm_dentry(profile, dentry, mnt, &sa, AA_CHECK_DIR);
5886 +int aa_perm_path(struct aa_profile *profile, const char *operation,
5887 + const char *name, int mask, uid_t uid)
5889 + struct aa_audit sa;
5891 + memset(&sa, 0, sizeof(sa));
5892 + sa.operation = operation;
5893 + sa.gfp_mask = GFP_KERNEL;
5894 + sa.request_mask = mask;
5896 + if (current->fsuid == uid)
5897 + sa.request_mask = mask << AA_USER_SHIFT;
5899 + sa.request_mask = mask << AA_OTHER_SHIFT;
5901 + sa.denied_mask = aa_file_denied(profile, name, sa.request_mask,
5903 + sa.error_code = sa.denied_mask ? -EACCES : 0;
5905 + return aa_audit_file(profile, &sa);
5909 + * aa_capability - test permission to use capability
5910 + * @cxt: aa_task_context with profile to check against
5911 + * @cap: capability to be tested
5913 + * Look up capability in profile capability set.
5914 + * Returns 0 on success, or else an error code.
5916 +int aa_capability(struct aa_task_context *cxt, int cap)
5918 + int error = cap_raised(cxt->profile->capabilities, cap) ? 0 : -EPERM;
5919 + struct aa_audit sa;
5921 + /* test if cap has alread been logged */
5922 + if (cap_raised(cxt->caps_logged, cap)) {
5923 + if (PROFILE_COMPLAIN(cxt->profile))
5927 + /* don't worry about rcu replacement of the cxt here.
5928 + * caps_logged is a cache to reduce the occurence of
5929 + * duplicate messages in the log. The worst that can
5930 + * happen is duplicate capability messages shows up in
5933 + cap_raise(cxt->caps_logged, cap);
5935 + memset(&sa, 0, sizeof(sa));
5936 + sa.operation = "capable";
5937 + sa.gfp_mask = GFP_ATOMIC;
5938 + sa.name = capability_names[cap];
5939 + sa.error_code = error;
5941 + error = aa_audit_caps(cxt->profile, &sa, cap);
5946 +/* must be used inside rcu_read_lock or task_lock */
5947 +int aa_may_ptrace(struct aa_task_context *cxt, struct aa_profile *tracee)
5949 + if (!cxt || cxt->profile == tracee)
5951 + return aa_capability(cxt, CAP_SYS_PTRACE);
5955 + * aa_link - hard link check
5956 + * @profile: profile to check against
5957 + * @link: dentry of link being created
5958 + * @link_mnt: vfsmount of link being created
5959 + * @target: dentry of link target
5960 + * @target_mnt: vfsmunt of link target
5962 + * Returns 0 on success, or else an error code.
5964 +int aa_link(struct aa_profile *profile,
5965 + struct dentry *link, struct vfsmount *link_mnt,
5966 + struct dentry *target, struct vfsmount *target_mnt)
5969 + struct aa_audit sa;
5970 + char *buffer = NULL, *buffer2 = NULL;
5972 + memset(&sa, 0, sizeof(sa));
5973 + sa.operation = "inode_link";
5974 + sa.gfp_mask = GFP_KERNEL;
5975 + sa.name = aa_get_name(link, link_mnt, &buffer, 0);
5976 + sa.name2 = aa_get_name(target, target_mnt, &buffer2, 0);
5978 + if (IS_ERR(sa.name)) {
5979 + sa.error_code = PTR_ERR(sa.name);
5982 + if (IS_ERR(sa.name2)) {
5983 + sa.error_code = PTR_ERR(sa.name2);
5987 + if (sa.name && sa.name2) {
5988 + sa.denied_mask = aa_link_denied(profile, sa.name, sa.name2,
5989 + aa_inode_mode(target->d_inode),
5992 + sa.error_code = sa.denied_mask ? -EACCES : 0;
5995 + error = aa_audit_file(profile, &sa);
5997 + aa_put_name_buffer(buffer);
5998 + aa_put_name_buffer(buffer2);
6003 +int aa_net_perm(struct aa_profile *profile, char *operation,
6004 + int family, int type, int protocol)
6006 + struct aa_audit sa;
6008 + u16 family_mask, audit_mask, quiet_mask;
6010 + if ((family < 0) || (family >= AF_MAX))
6013 + if ((type < 0) || (type >= SOCK_MAX))
6016 + /* unix domain and netlink sockets are handled by ipc */
6017 + if (family == AF_UNIX || family == AF_NETLINK)
6020 + family_mask = profile->network_families[family];
6021 + audit_mask = profile->audit_network[family];
6022 + quiet_mask = profile->quiet_network[family];
6024 + error = (family_mask & (1 << type)) ? 0 : -EACCES;
6026 + memset(&sa, 0, sizeof(sa));
6027 + sa.operation = operation;
6028 + sa.gfp_mask = GFP_KERNEL;
6029 + sa.family = family;
6031 + sa.protocol = protocol;
6032 + sa.error_code = error;
6034 + if (likely(!error)) {
6035 + if (!PROFILE_AUDIT(profile) && !(family_mask & audit_mask))
6037 + } else if (!((1 << type) & ~quiet_mask)) {
6041 + error = aa_audit(profile, &sa);
6046 +int aa_revalidate_sk(struct sock *sk, char *operation)
6048 + struct aa_profile *profile;
6051 + /* this is some debugging code to flush out the network hooks that
6052 + that are called in interrupt context */
6053 + if (in_interrupt()) {
6054 + printk("AppArmor Debug: Hook being called from interrupt context\n");
6059 + profile = aa_get_profile(current);
6061 + error = aa_net_perm(profile, operation,
6062 + sk->sk_family, sk->sk_type,
6064 + aa_put_profile(profile);
6069 + * aa_task_setrlimit - test permission to set an rlimit
6070 + * @profile - profile confining the task
6071 + * @resource - the resource being set
6072 + * @new_rlim - the new resource limit
6074 + * Control raising the processes hard limit.
6076 +int aa_task_setrlimit(struct aa_profile *profile, unsigned int resource,
6077 + struct rlimit *new_rlim)
6079 + struct aa_audit sa;
6082 + memset(&sa, 0, sizeof(sa));
6083 + sa.operation = "setrlimit";
6084 + sa.gfp_mask = GFP_KERNEL;
6085 + sa.rlimit = resource + 1;
6087 + if (profile->rlimits.mask & (1 << resource) &&
6088 + new_rlim->rlim_max > profile->rlimits.limits[resource].rlim_max) {
6089 + sa.error_code = -EACCES;
6091 + error = aa_audit(profile, &sa);
6097 +static int aa_rlimit_nproc(struct aa_profile *profile) {
6098 + if (profile && (profile->rlimits.mask & (1 << RLIMIT_NPROC)) &&
6099 + profile->task_count >= profile->rlimits.limits[RLIMIT_NPROC].rlim_max)
6104 +void aa_set_rlimits(struct task_struct *task, struct aa_profile *profile)
6111 + if (!profile->rlimits.mask)
6114 + task_lock(task->group_leader);
6116 + for (i = 0; i < RLIM_NLIMITS; i++, mask <<= 1) {
6117 + struct rlimit new_rlim, *old_rlim;
6119 + /* check to see if NPROC which is per profile and handled
6120 + * in clone/exec or whether this is a limit to be set
6121 + * can't set cpu limit either right now
6123 + if (i == RLIMIT_NPROC || i == RLIMIT_CPU)
6126 + old_rlim = task->signal->rlim + i;
6127 + new_rlim = *old_rlim;
6129 + if (mask & profile->rlimits.mask &&
6130 + profile->rlimits.limits[i].rlim_max < new_rlim.rlim_max) {
6131 + new_rlim.rlim_max = profile->rlimits.limits[i].rlim_max;
6132 + /* soft limit should not exceed hard limit */
6133 + if (new_rlim.rlim_cur > new_rlim.rlim_max)
6134 + new_rlim.rlim_cur = new_rlim.rlim_max;
6137 + *old_rlim = new_rlim;
6139 + task_unlock(task->group_leader);
6142 +/*******************************
6143 + * Global task related functions
6144 + *******************************/
6147 + * aa_clone - initialize the task context for a new task
6148 + * @child: task that is being created
6150 + * Returns 0 on success, or else an error code.
6152 +int aa_clone(struct task_struct *child)
6154 + struct aa_audit sa;
6155 + struct aa_task_context *cxt, *child_cxt;
6156 + struct aa_profile *profile;
6158 + if (!aa_task_context(current))
6160 + child_cxt = aa_alloc_task_context(GFP_KERNEL);
6164 + memset(&sa, 0, sizeof(sa));
6165 + sa.operation = "clone";
6166 + sa.task = child->pid;
6167 + sa.gfp_mask = GFP_KERNEL;
6170 + profile = aa_get_profile(current);
6172 + lock_profile(profile);
6173 + cxt = aa_task_context(current);
6174 + if (unlikely(profile->isstale || !cxt ||
6175 + cxt->profile != profile)) {
6177 + * Race with profile replacement or removal, or with
6178 + * task context removal.
6180 + unlock_profile(profile);
6181 + aa_put_profile(profile);
6185 + if (aa_rlimit_nproc(profile)) {
6186 + sa.info = "rlimit nproc limit exceeded";
6187 + unlock_profile(profile);
6188 + aa_audit_reject(profile, &sa);
6189 + aa_put_profile(profile);
6193 + /* No need to grab the child's task lock here. */
6194 + aa_change_task_context(child, child_cxt, profile,
6195 + cxt->cookie, cxt->previous_profile);
6197 + unlock_profile(profile);
6199 + if (APPARMOR_COMPLAIN(child_cxt) &&
6200 + profile == profile->ns->null_complain_profile) {
6201 + aa_audit_hint(profile, &sa);
6203 + aa_put_profile(profile);
6205 + aa_free_task_context(child_cxt);
6210 +static struct aa_profile *
6211 +aa_register_find(struct aa_profile *profile, const char* ns_name,
6212 + const char *name, int mandatory, int complain,
6213 + struct aa_audit *sa)
6215 + struct aa_namespace *ns;
6216 + struct aa_profile *new_profile;
6222 + ns = default_namespace;
6225 + /* locate the profile namespace */
6226 + ns = aa_find_namespace(ns_name);
6229 + sa->info = "profile namespace not found";
6230 + sa->denied_mask = sa->request_mask;
6231 + sa->error_code = -ENOENT;
6232 + return ERR_PTR(-ENOENT);
6240 + /* Locate new profile */
6241 + new_profile = aa_find_profile(ns, name);
6243 + if (new_profile) {
6244 + AA_DEBUG("%s: setting profile %s\n",
6245 + __FUNCTION__, new_profile->name);
6246 + } else if (mandatory && profile) {
6247 + sa->info = "mandatory profile missing";
6248 + sa->denied_mask = sa->request_mask; /* shifted MAY_EXEC */
6250 + aa_audit_hint(profile, sa);
6252 + aa_dup_profile(profile->ns->null_complain_profile);
6254 + sa->error_code = -EACCES;
6256 + aa_put_namespace(ns);
6257 + return ERR_PTR(-EACCES);
6260 + /* Only way we can get into this code is if task
6261 + * is unconfined, pix, nix.
6263 + AA_DEBUG("%s: No profile found for exec image '%s'\n",
6268 + aa_put_namespace(ns);
6269 + return new_profile;
6272 +static struct aa_profile *
6273 +aa_x_to_profile(struct aa_profile *profile, const char *filename, int xmode,
6274 + struct aa_audit *sa, char **child)
6276 + struct aa_profile *new_profile = NULL;
6277 + int ix = xmode & AA_EXEC_INHERIT;
6278 + int complain = PROFILE_COMPLAIN(profile);
6282 + switch (xmode & AA_EXEC_MODIFIERS) {
6284 + /* only valid with ix flag */
6287 + case AA_EXEC_UNCONFINED:
6288 + /* only valid without ix flag */
6291 + case AA_EXEC_PROFILE:
6292 + new_profile = aa_register_find(profile, NULL, filename, !ix,
6295 + case AA_EXEC_CHILD:
6296 + *child = new_compound_name(profile->name, filename);
6297 + sa->name2 = *child;
6299 + sa->info = "Failed name resolution - exec failed";
6300 + sa->error_code = -ENOMEM;
6301 + new_profile = ERR_PTR(-ENOMEM);
6303 + new_profile = aa_register_find(profile, NULL, *child,
6304 + !ix, complain, sa);
6308 + /* all other indexes are named transitions */
6309 + index = AA_EXEC_INDEX(xmode);
6310 + if (index - 4 > profile->exec_table_size) {
6311 + sa->info = "invalid named transition - exec failed";
6312 + sa->error_code = -EACCES;
6313 + new_profile = ERR_PTR(-EACCES);
6315 + char *ns_name = NULL;
6316 + char *name = profile->exec_table[index - 4];
6317 + if (*name == ':') {
6318 + ns_name = name + 1;
6319 + name = ns_name + strlen(ns_name) + 1;
6322 + sa->name3 = ns_name;
6324 + aa_register_find(profile, ns_name, name,
6325 + !ix, complain, sa);
6328 + if (IS_ERR(new_profile))
6329 + /* all these failures must be audited - no quieting */
6330 + return ERR_PTR(aa_audit_reject(profile, sa));
6331 + return new_profile;
6335 + * aa_register - register a new program
6336 + * @bprm: binprm of program being registered
6338 + * Try to register a new program during execve(). This should give the
6339 + * new program a valid aa_task_context if confined.
6341 +int aa_register(struct linux_binprm *bprm)
6343 + const char *filename;
6344 + char *buffer = NULL, *child = NULL;
6345 + struct file *filp = bprm->file;
6346 + struct aa_profile *profile, *old_profile, *new_profile = NULL;
6347 + int exec_mode, complain = 0, shift;
6348 + struct aa_audit sa;
6350 + AA_DEBUG("%s\n", __FUNCTION__);
6352 + profile = aa_get_profile(current);
6354 + shift = aa_inode_mode(filp->f_dentry->d_inode);
6355 + memset(&sa, 0, sizeof(sa));
6356 + sa.operation = "exec";
6357 + sa.gfp_mask = GFP_KERNEL;
6358 + sa.request_mask = MAY_EXEC << shift;
6360 + filename = aa_get_name(filp->f_dentry, filp->f_vfsmnt, &buffer, 0);
6361 + if (IS_ERR(filename)) {
6363 + sa.info = "Failed name resolution - exec failed";
6364 + sa.error_code = PTR_ERR(filename);
6365 + aa_audit_file(profile, &sa);
6366 + return sa.error_code;
6370 + sa.name = filename;
6372 + exec_mode = AA_EXEC_UNSAFE << shift;
6376 + complain = PROFILE_COMPLAIN(profile);
6378 + /* Confined task, determine what mode inherit, unconfined or
6379 + * mandatory to load new profile
6381 + exec_mode = aa_match(profile->file_rules, filename,
6385 + if (exec_mode & sa.request_mask) {
6386 + int xm = exec_mode >> shift;
6387 + new_profile = aa_x_to_profile(profile, filename,
6390 + if (!new_profile && (xm & AA_EXEC_INHERIT))
6391 + /* (p|c|n|)ix - don't change profile */
6393 + /* error case caught below */
6395 + } else if (sa.request_mask & AUDIT_QUIET_MASK(sa.audit_mask)) {
6396 + /* quiet failed exit */
6397 + new_profile = ERR_PTR(-EACCES);
6398 + } else if (complain) {
6399 + /* There was no entry in calling profile
6400 + * describing mode to execute image in.
6401 + * Drop into null-profile (disabling secure exec).
6404 + aa_dup_profile(profile->ns->null_complain_profile);
6405 + exec_mode |= AA_EXEC_UNSAFE << shift;
6407 + sa.denied_mask = sa.request_mask;
6408 + sa.error_code = -EACCES;
6409 + new_profile = ERR_PTR(aa_audit_file(profile, &sa));
6412 + /* Unconfined task, load profile if it exists */
6413 + new_profile = aa_register_find(NULL, NULL, filename, 0, 0, &sa);
6414 + if (new_profile == NULL)
6418 + if (IS_ERR(new_profile))
6421 + old_profile = __aa_replace_profile(current, new_profile);
6422 + if (IS_ERR(old_profile)) {
6423 + aa_put_profile(new_profile);
6424 + aa_put_profile(profile);
6425 + if (PTR_ERR(old_profile) == -ESTALE) {
6426 + profile = aa_get_profile(current);
6429 + if (PTR_ERR(old_profile) == -EPERM) {
6430 + sa.denied_mask = sa.request_mask;
6431 + sa.info = "unable to set profile due to ptrace";
6432 + sa.task = current->parent->pid;
6433 + aa_audit_reject(profile, &sa);
6435 + if (PTR_ERR(old_profile) == -EAGAIN) {
6436 + sa.info = "rlimit nproc limit exceeded";
6437 + aa_audit_reject(profile, &sa);
6439 + new_profile = old_profile;
6442 + aa_put_profile(old_profile);
6443 + aa_put_profile(profile);
6445 + /* Handle confined exec.
6446 + * Can be at this point for the following reasons:
6447 + * 1. unconfined switching to confined
6448 + * 2. confined switching to different confinement
6449 + * 3. confined switching to unconfined
6451 + * Cases 2 and 3 are marked as requiring secure exec
6452 + * (unless policy specified "unsafe exec")
6454 + if (!(exec_mode & (AA_EXEC_UNSAFE << shift))) {
6455 + unsigned long bprm_flags;
6457 + bprm_flags = AA_SECURE_EXEC_NEEDED;
6458 + bprm->security = (void*)
6459 + ((unsigned long)bprm->security | bprm_flags);
6462 + if (complain && new_profile &&
6463 + new_profile == new_profile->ns->null_complain_profile) {
6464 + sa.request_mask = 0;
6466 + sa.info = "set profile";
6467 + aa_audit_hint(new_profile, &sa);
6471 + aa_put_name_buffer(child);
6472 + aa_put_name_buffer(buffer);
6473 + if (IS_ERR(new_profile))
6474 + return PTR_ERR(new_profile);
6475 + aa_put_profile(new_profile);
6480 + * aa_release - release a task context
6481 + * @task: task being released
6483 + * This is called after a task has exited and the parent has reaped it.
6485 +void aa_release(struct task_struct *task)
6487 + struct aa_task_context *cxt;
6488 + struct aa_profile *profile;
6490 + * While the task context is still on a profile's task context
6491 + * list, another process could replace the profile under us,
6492 + * leaving us with a locked profile that is no longer attached
6493 + * to this task. So after locking the profile, we check that
6494 + * the profile is still attached. The profile lock is
6495 + * sufficient to prevent the replacement race so we do not lock
6498 + * Use lock subtyping to avoid lockdep reporting a false irq
6499 + * possible inversion between the task_lock and profile_lock
6501 + * We also avoid taking the task_lock here because lock_dep
6502 + * would report another false {softirq-on-W} potential irq_lock
6505 + * If the task does not have a profile attached we are safe;
6506 + * nothing can race with us at this point.
6510 + profile = aa_get_profile(task);
6512 + lock_profile_nested(profile, aa_lock_task_release);
6513 + cxt = aa_task_context(task);
6514 + if (unlikely(!cxt || cxt->profile != profile)) {
6515 + unlock_profile(profile);
6516 + aa_put_profile(profile);
6519 + aa_change_task_context(task, NULL, NULL, 0, NULL);
6520 + unlock_profile(profile);
6521 + aa_put_profile(profile);
6525 +static int do_change_profile(struct aa_profile *expected,
6526 + struct aa_namespace *ns, const char *name,
6527 + u64 cookie, int restore, int hat,
6528 + struct aa_audit *sa)
6530 + struct aa_profile *new_profile = NULL, *old_profile = NULL,
6531 + *previous_profile = NULL;
6532 + struct aa_task_context *new_cxt, *cxt;
6537 + new_cxt = aa_alloc_task_context(GFP_KERNEL);
6541 + new_profile = aa_find_profile(ns, name);
6542 + if (!new_profile && !restore) {
6543 + if (!PROFILE_COMPLAIN(expected)) {
6544 + aa_free_task_context(new_cxt);
6547 + new_profile = aa_dup_profile(ns->null_complain_profile);
6548 + } else if (new_profile && hat && !PROFILE_IS_HAT(new_profile)) {
6549 + aa_free_task_context(new_cxt);
6550 + aa_put_profile(new_profile);
6554 + cxt = lock_task_and_profiles(current, new_profile);
6559 + old_profile = cxt->profile;
6561 + if (cxt->profile != expected || (new_profile && new_profile->isstale)) {
6566 + if (cxt->previous_profile) {
6567 + if (cxt->cookie != cookie) {
6569 + sa->info = "killing process";
6570 + aa_audit_reject(cxt->profile, sa);
6571 + /* terminate process */
6572 + (void)send_sig_info(SIGKILL, NULL, current);
6577 + previous_profile = cxt->previous_profile;
6579 + previous_profile = cxt->profile;
6581 + if ((current->ptrace & PT_PTRACED) && aa_may_ptrace(cxt, new_profile)) {
6586 + if ((error = aa_rlimit_nproc(new_profile))) {
6587 + sa->info = "rlimit nproc limit exceeded";
6588 + aa_audit_reject(cxt->profile, sa);
6592 + if (new_profile == ns->null_complain_profile)
6593 + aa_audit_hint(cxt->profile, sa);
6595 + if (APPARMOR_AUDIT(cxt))
6596 + aa_audit_message(cxt->profile, sa, AUDIT_APPARMOR_AUDIT);
6598 + if (!restore && cookie)
6599 + aa_change_task_context(current, new_cxt, new_profile, cookie,
6600 + previous_profile);
6602 + /* either return to previous_profile, or a permanent change */
6603 + aa_change_task_context(current, new_cxt, new_profile, 0, NULL);
6606 + if (aa_task_context(current) != new_cxt)
6607 + aa_free_task_context(new_cxt);
6608 + task_unlock(current);
6609 + unlock_both_profiles(old_profile, new_profile);
6610 + aa_put_profile(new_profile);
6615 + * aa_change_profile - perform a one-way profile transition
6616 + * @ns_name: name of the profile namespace to change to
6617 + * @name: name of profile to change to
6618 + * Change to new profile @name. Unlike with hats, there is no way
6621 + * Returns %0 on success, error otherwise.
6623 +int aa_change_profile(const char *ns_name, const char *name)
6625 + struct aa_task_context *cxt;
6626 + struct aa_profile *profile = NULL;
6627 + struct aa_namespace *ns = NULL;
6628 + struct aa_audit sa;
6629 + unsigned int state;
6630 + int error = -EINVAL;
6635 + memset(&sa, 0, sizeof(sa));
6636 + sa.gfp_mask = GFP_ATOMIC;
6637 + sa.operation = "change_profile";
6640 + task_lock(current);
6641 + cxt = aa_task_context(current);
6643 + profile = aa_dup_profile(cxt->profile);
6644 + task_unlock(current);
6647 + ns = aa_find_namespace(ns_name);
6649 + ns = aa_get_namespace(profile->ns);
6651 + ns = aa_get_namespace(default_namespace);
6654 + aa_put_profile(profile);
6658 + if (!profile || PROFILE_COMPLAIN(profile) ||
6659 + (ns == profile->ns &&
6660 + (aa_match(profile->file_rules, name, NULL) & AA_CHANGE_PROFILE)))
6661 + error = do_change_profile(profile, ns, name, 0, 0, 0, &sa);
6663 + /* check for a rule with a namespace prepended */
6664 + aa_match_state(profile->file_rules, DFA_START, ns->name,
6666 + state = aa_dfa_null_transition(profile->file_rules, state);
6667 + if ((aa_match_state(profile->file_rules, state, name, NULL) &
6668 + AA_CHANGE_PROFILE))
6669 + error = do_change_profile(profile, ns, name, 0, 0, 0,
6672 + /* no permission to transition to profile @name */
6676 + aa_put_namespace(ns);
6677 + aa_put_profile(profile);
6678 + if (error == -ESTALE)
6685 + * aa_change_hat - change hat to/from subprofile
6686 + * @hat_name: hat to change to
6687 + * @cookie: magic value to validate the hat change
6689 + * Change to new @hat_name, and store the @hat_magic in the current task
6690 + * context. If the new @hat_name is %NULL and the @cookie matches that
6691 + * stored in the current task context and is not 0, return to the top level
6693 + * Returns %0 on success, error otherwise.
6695 +int aa_change_hat(const char *hat_name, u64 cookie)
6697 + struct aa_task_context *cxt;
6698 + struct aa_profile *profile, *previous_profile;
6699 + struct aa_audit sa;
6702 + memset(&sa, 0, sizeof(sa));
6703 + sa.gfp_mask = GFP_ATOMIC;
6704 + sa.operation = "change_hat";
6707 + task_lock(current);
6708 + cxt = aa_task_context(current);
6710 + task_unlock(current);
6713 + profile = aa_dup_profile(cxt->profile);
6714 + previous_profile = aa_dup_profile(cxt->previous_profile);
6715 + task_unlock(current);
6718 + char *name, *profile_name;
6720 + if (previous_profile)
6721 + profile_name = previous_profile->name;
6723 + profile_name = profile->name;
6725 + name = new_compound_name(profile_name, hat_name);
6730 + error = do_change_profile(profile, profile->ns, name, cookie,
6732 + aa_put_name_buffer(name);
6733 + } else if (previous_profile)
6734 + error = do_change_profile(profile, profile->ns,
6735 + previous_profile->name, cookie, 1, 0,
6737 + /* else ignore restores when there is no saved profile */
6740 + aa_put_profile(previous_profile);
6741 + aa_put_profile(profile);
6742 + if (error == -ESTALE)
6749 + * __aa_replace_profile - replace a task's profile
6750 + * @task: task to switch the profile of
6751 + * @profile: profile to switch to
6753 + * Returns a handle to the previous profile upon success, or else an
6756 +struct aa_profile *__aa_replace_profile(struct task_struct *task,
6757 + struct aa_profile *profile)
6759 + struct aa_task_context *cxt, *new_cxt = NULL;
6760 + struct aa_profile *old_profile = NULL;
6763 + new_cxt = aa_alloc_task_context(GFP_KERNEL);
6765 + return ERR_PTR(-ENOMEM);
6768 + cxt = lock_task_and_profiles(task, profile);
6769 + if (unlikely(profile && profile->isstale)) {
6770 + old_profile = ERR_PTR(-ESTALE);
6774 + if ((current->ptrace & PT_PTRACED) && aa_may_ptrace(cxt, profile)) {
6775 + old_profile = ERR_PTR(-EPERM);
6779 + if (aa_rlimit_nproc(profile)) {
6780 + old_profile = ERR_PTR(-EAGAIN);
6785 + old_profile = aa_dup_profile(cxt->profile);
6786 + aa_change_task_context(task, new_cxt, profile, 0, NULL);
6788 + task_unlock(task);
6789 + aa_set_rlimits(task, profile);
6790 + unlock_both_profiles(profile, old_profile);
6791 + return old_profile;
6794 + task_unlock(task);
6795 + unlock_both_profiles(profile, cxt ? cxt->profile : NULL);
6796 + aa_free_task_context(new_cxt);
6797 + return old_profile;
6801 + * lock_task_and_profiles - lock the task and confining profiles and @profile
6802 + * @task: task to lock
6803 + * @profile: extra profile to lock in addition to the current profile
6805 + * Handle the spinning on locking to make sure the task context and
6806 + * profile are consistent once all locks are aquired.
6808 + * return the aa_task_context currently confining the task. The task lock
6809 + * will be held whether or not the task is confined.
6811 +struct aa_task_context *
6812 +lock_task_and_profiles(struct task_struct *task, struct aa_profile *profile)
6814 + struct aa_task_context *cxt;
6815 + struct aa_profile *old_profile = NULL;
6819 + cxt = aa_task_context(task);
6821 + old_profile = cxt->profile;
6823 + lock_both_profiles(profile, old_profile);
6826 + /* check for race with profile transition, replacement or removal */
6827 + if (unlikely(cxt != aa_task_context(task))) {
6828 + task_unlock(task);
6829 + unlock_both_profiles(profile, old_profile);
6830 + old_profile = NULL;
6833 + rcu_read_unlock();
6837 +static void free_aa_task_context_rcu_callback(struct rcu_head *head)
6839 + struct aa_task_context *cxt;
6841 + cxt = container_of(head, struct aa_task_context, rcu);
6842 + aa_free_task_context(cxt);
6846 + * aa_change_task_context - switch a task to use a new context and profile
6847 + * @task: task that is having its task context changed
6848 + * @new_cxt: new task context to use after the switch
6849 + * @profile: new profile to use after the switch
6850 + * @cookie: magic value to switch to
6851 + * @previous_profile: profile the task can return to
6853 +void aa_change_task_context(struct task_struct *task,
6854 + struct aa_task_context *new_cxt,
6855 + struct aa_profile *profile, u64 cookie,
6856 + struct aa_profile *previous_profile)
6858 + struct aa_task_context *old_cxt = aa_task_context(task);
6861 + list_del_init(&old_cxt->list);
6862 + old_cxt->profile->task_count--;
6863 + call_rcu(&old_cxt->rcu, free_aa_task_context_rcu_callback);
6866 + /* set the caps_logged cache to the quiet_caps mask
6867 + * this has the effect of quieting caps that are not
6868 + * supposed to be logged
6870 + new_cxt->caps_logged = profile->quiet_caps;
6871 + new_cxt->cookie = cookie;
6872 + new_cxt->task = task;
6873 + new_cxt->profile = aa_dup_profile(profile);
6874 + profile->task_count++;
6875 + new_cxt->previous_profile = aa_dup_profile(previous_profile);
6876 + list_move(&new_cxt->list, &profile->task_contexts);
6878 + rcu_assign_pointer(task->security, new_cxt);
6880 diff -uprN linux-2.6.27./security/apparmor/match.c linux-2.6.27/security/apparmor/match.c
6881 --- linux-2.6.27./security/apparmor/match.c 1970-01-01 01:00:00.000000000 +0100
6882 +++ linux-2.6.27/security/apparmor/match.c 2008-10-29 14:28:53.316113441 +0100
6885 + * Copyright (C) 2007 Novell/SUSE
6887 + * This program is free software; you can redistribute it and/or
6888 + * modify it under the terms of the GNU General Public License as
6889 + * published by the Free Software Foundation, version 2 of the
6892 + * Regular expression transition table matching
6895 +#include <linux/kernel.h>
6896 +#include <linux/slab.h>
6897 +#include <linux/errno.h>
6898 +#include "apparmor.h"
6900 +#include "inline.h"
6902 +static struct table_header *unpack_table(void *blob, size_t bsize)
6904 + struct table_header *table = NULL;
6905 + struct table_header th;
6908 + if (bsize < sizeof(struct table_header))
6911 + th.td_id = be16_to_cpu(*(u16 *) (blob));
6912 + th.td_flags = be16_to_cpu(*(u16 *) (blob + 2));
6913 + th.td_lolen = be32_to_cpu(*(u32 *) (blob + 8));
6914 + blob += sizeof(struct table_header);
6916 + if (!(th.td_flags == YYTD_DATA16 || th.td_flags == YYTD_DATA32 ||
6917 + th.td_flags == YYTD_DATA8))
6920 + tsize = table_size(th.td_lolen, th.td_flags);
6921 + if (bsize < tsize)
6924 + table = kmalloc(tsize, GFP_KERNEL);
6927 + if (th.td_flags == YYTD_DATA8)
6928 + UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
6929 + u8, byte_to_byte);
6930 + else if (th.td_flags == YYTD_DATA16)
6931 + UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
6932 + u16, be16_to_cpu);
6934 + UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
6935 + u32, be32_to_cpu);
6942 +int unpack_dfa(struct aa_dfa *dfa, void *blob, size_t size)
6945 + int error = -ENOMEM;
6947 + /* get dfa table set header */
6948 + if (size < sizeof(struct table_set_header))
6951 + if (ntohl(*(u32 *)blob) != YYTH_MAGIC)
6954 + hsize = ntohl(*(u32 *)(blob + 4));
6962 + while (size > 0) {
6963 + struct table_header *table;
6964 + table = unpack_table(blob, size);
6968 + switch(table->td_id) {
6969 + case YYTD_ID_ACCEPT:
6970 + case YYTD_ID_ACCEPT2:
6971 + case YYTD_ID_BASE:
6972 + dfa->tables[table->td_id - 1] = table;
6973 + if (table->td_flags != YYTD_DATA32)
6979 + dfa->tables[table->td_id - 1] = table;
6980 + if (table->td_flags != YYTD_DATA16)
6984 + dfa->tables[table->td_id - 1] = table;
6985 + if (table->td_flags != YYTD_DATA8)
6993 + blob += table_size(table->td_lolen, table->td_flags);
6994 + size -= table_size(table->td_lolen, table->td_flags);
7000 + for (i = 0; i < ARRAY_SIZE(dfa->tables); i++) {
7001 + if (dfa->tables[i]) {
7002 + kfree(dfa->tables[i]);
7003 + dfa->tables[i] = NULL;
7010 + * verify_dfa - verify that all the transitions and states in the dfa tables
7012 + * @dfa: dfa to test
7014 + * assumes dfa has gone through the verification done by unpacking
7016 +int verify_dfa(struct aa_dfa *dfa)
7018 + size_t i, state_count, trans_count;
7019 + int error = -EPROTO;
7021 + /* check that required tables exist */
7022 + if (!(dfa->tables[YYTD_ID_ACCEPT - 1] &&
7023 + dfa->tables[YYTD_ID_ACCEPT2 - 1] &&
7024 + dfa->tables[YYTD_ID_DEF - 1] &&
7025 + dfa->tables[YYTD_ID_BASE - 1] &&
7026 + dfa->tables[YYTD_ID_NXT - 1] &&
7027 + dfa->tables[YYTD_ID_CHK - 1]))
7030 + /* accept.size == default.size == base.size */
7031 + state_count = dfa->tables[YYTD_ID_BASE - 1]->td_lolen;
7032 + if (!(state_count == dfa->tables[YYTD_ID_DEF - 1]->td_lolen &&
7033 + state_count == dfa->tables[YYTD_ID_ACCEPT - 1]->td_lolen &&
7034 + state_count == dfa->tables[YYTD_ID_ACCEPT2 - 1]->td_lolen))
7037 + /* next.size == chk.size */
7038 + trans_count = dfa->tables[YYTD_ID_NXT - 1]->td_lolen;
7039 + if (trans_count != dfa->tables[YYTD_ID_CHK - 1]->td_lolen)
7042 + /* if equivalence classes then its table size must be 256 */
7043 + if (dfa->tables[YYTD_ID_EC - 1] &&
7044 + dfa->tables[YYTD_ID_EC - 1]->td_lolen != 256)
7047 + for (i = 0; i < state_count; i++) {
7048 + if (DEFAULT_TABLE(dfa)[i] >= state_count)
7050 + if (BASE_TABLE(dfa)[i] >= trans_count + 256)
7054 + for (i = 0; i < trans_count ; i++) {
7055 + if (NEXT_TABLE(dfa)[i] >= state_count)
7057 + if (CHECK_TABLE(dfa)[i] >= state_count)
7061 + /* verify accept permissions */
7062 + for (i = 0; i < state_count; i++) {
7063 + int mode = ACCEPT_TABLE(dfa)[i];
7065 + if (mode & ~AA_VALID_PERM_MASK)
7067 + if (ACCEPT_TABLE2(dfa)[i] & ~AA_VALID_PERM2_MASK)
7070 + /* if any exec modifier is set MAY_EXEC must be set */
7071 + if ((mode & AA_USER_EXEC_TYPE) && !(mode & AA_USER_EXEC))
7073 + if ((mode & AA_OTHER_EXEC_TYPE) && !(mode & AA_OTHER_EXEC))
7082 +struct aa_dfa *aa_match_alloc(void)
7084 + return kzalloc(sizeof(struct aa_dfa), GFP_KERNEL);
7087 +void aa_match_free(struct aa_dfa *dfa)
7092 + for (i = 0; i < ARRAY_SIZE(dfa->tables); i++)
7093 + kfree(dfa->tables[i]);
7099 + * aa_dfa_next_state_len - traverse @dfa to find state @str stops at
7100 + * @dfa: the dfa to match @str against
7101 + * @start: the state of the dfa to start matching in
7102 + * @str: the string of bytes to match against the dfa
7103 + * @len: length of the string of bytes to match
7105 + * aa_dfa_next_state will match @str against the dfa and return the state it
7106 + * finished matching in. The final state can be used to look up the accepting
7107 + * label, or as the start state of a continuing match.
7109 + * aa_dfa_next_state could be implement using this function by doing
7110 + * return aa_dfa_next_state_len(dfa, start, str, strlen(str));
7111 + * but that would require traversing the string twice and be slightly
7114 +unsigned int aa_dfa_next_state_len(struct aa_dfa *dfa, unsigned int start,
7115 + const char *str, int len)
7117 + u16 *def = DEFAULT_TABLE(dfa);
7118 + u32 *base = BASE_TABLE(dfa);
7119 + u16 *next = NEXT_TABLE(dfa);
7120 + u16 *check = CHECK_TABLE(dfa);
7121 + unsigned int state = start, pos;
7126 + /* current state is <state>, matching character *str */
7127 + if (dfa->tables[YYTD_ID_EC - 1]) {
7128 + u8 *equiv = EQUIV_TABLE(dfa);
7129 + for (; len; len--) {
7130 + pos = base[state] + equiv[(u8)*str++];
7131 + if (check[pos] == state)
7132 + state = next[pos];
7134 + state = def[state];
7137 + for (; len; len--) {
7138 + pos = base[state] + (u8)*str++;
7139 + if (check[pos] == state)
7140 + state = next[pos];
7142 + state = def[state];
7149 + * aa_dfa_next_state - traverse @dfa to find state @str stops at
7150 + * @dfa: the dfa to match @str against
7151 + * @start: the state of the dfa to start matching in
7152 + * @str: the null terminated string of bytes to match against the dfa
7154 + * aa_dfa_next_state will match @str against the dfa and return the state it
7155 + * finished matching in. The final state can be used to look up the accepting
7156 + * label, or as the start state of a continuing match.
7158 +unsigned int aa_dfa_next_state(struct aa_dfa *dfa, unsigned int start,
7161 + u16 *def = DEFAULT_TABLE(dfa);
7162 + u32 *base = BASE_TABLE(dfa);
7163 + u16 *next = NEXT_TABLE(dfa);
7164 + u16 *check = CHECK_TABLE(dfa);
7165 + unsigned int state = start, pos;
7170 + /* current state is <state>, matching character *str */
7171 + if (dfa->tables[YYTD_ID_EC - 1]) {
7172 + u8 *equiv = EQUIV_TABLE(dfa);
7174 + pos = base[state] + equiv[(u8)*str++];
7175 + if (check[pos] == state)
7176 + state = next[pos];
7178 + state = def[state];
7182 + pos = base[state] + (u8)*str++;
7183 + if (check[pos] == state)
7184 + state = next[pos];
7186 + state = def[state];
7193 + * aa_dfa_null_transition - step to next state after null character
7194 + * @dfa: the dfa to match against
7195 + * @start: the state of the dfa to start matching in
7197 + * aa_dfa_null_transition transitions to the next state after a null
7198 + * character which is not used in standard matching and is only
7199 + * used to seperate pairs.
7201 +unsigned int aa_dfa_null_transition(struct aa_dfa *dfa, unsigned int start)
7203 + return aa_dfa_next_state_len(dfa, start, "", 1);
7207 + * aa_dfa_match - find accept perm for @str in @dfa
7208 + * @dfa: the dfa to match @str against
7209 + * @str: the string to match against the dfa
7210 + * @audit_mask: the audit_mask for the final state
7212 + * aa_dfa_match will match @str and return the accept perms for the
7215 +unsigned int aa_dfa_match(struct aa_dfa *dfa, const char *str, int *audit_mask)
7217 + int state = aa_dfa_next_state(dfa, DFA_START, str);
7219 + *audit_mask = dfa_audit_mask(dfa, state);
7220 + return ACCEPT_TABLE(dfa)[state];
7224 + * aa_match_state - find accept perm and state for @str in @dfa
7225 + * @dfa: the dfa to match @str against
7226 + * @start: the state to start the match from
7227 + * @str: the string to match against the dfa
7228 + * @final: the state that the match finished in
7230 + * aa_match_state will match @str and return the accept perms, and @final
7231 + * state, the match occured in.
7233 +unsigned int aa_match_state(struct aa_dfa *dfa, unsigned int start,
7234 + const char *str, unsigned int *final)
7236 + unsigned int state;
7238 + state = aa_dfa_next_state(dfa, start, str);
7241 + return ACCEPT_TABLE(dfa)[state];
7248 diff -uprN linux-2.6.27./security/apparmor/match.h linux-2.6.27/security/apparmor/match.h
7249 --- linux-2.6.27./security/apparmor/match.h 1970-01-01 01:00:00.000000000 +0100
7250 +++ linux-2.6.27/security/apparmor/match.h 2008-10-29 14:28:53.316113441 +0100
7253 + * Copyright (C) 2007 Novell/SUSE
7255 + * This program is free software; you can redistribute it and/or
7256 + * modify it under the terms of the GNU General Public License as
7257 + * published by the Free Software Foundation, version 2 of the
7260 + * AppArmor submodule (match) prototypes
7266 +#define DFA_START 1
7269 + * The format used for transition tables is based on the GNU flex table
7270 + * file format (--tables-file option; see Table File Format in the flex
7271 + * info pages and the flex sources for documentation). The magic number
7272 + * used in the header is 0x1B5E783D insted of 0xF13C57B1 though, because
7273 + * the YY_ID_CHK (check) and YY_ID_DEF (default) tables are used
7274 + * slightly differently (see the apparmor-parser package).
7277 +#define YYTH_MAGIC 0x1B5E783D
7279 +struct table_set_header {
7280 + u32 th_magic; /* YYTH_MAGIC */
7284 + char th_version[];
7287 +#define YYTD_ID_ACCEPT 1
7288 +#define YYTD_ID_BASE 2
7289 +#define YYTD_ID_CHK 3
7290 +#define YYTD_ID_DEF 4
7291 +#define YYTD_ID_EC 5
7292 +#define YYTD_ID_META 6
7293 +#define YYTD_ID_ACCEPT2 7
7294 +#define YYTD_ID_NXT 8
7297 +#define YYTD_DATA8 1
7298 +#define YYTD_DATA16 2
7299 +#define YYTD_DATA32 4
7301 +struct table_header {
7309 +#define DEFAULT_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_DEF - 1]->td_data))
7310 +#define BASE_TABLE(DFA) ((u32 *)((DFA)->tables[YYTD_ID_BASE - 1]->td_data))
7311 +#define NEXT_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_NXT - 1]->td_data))
7312 +#define CHECK_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_CHK - 1]->td_data))
7313 +#define EQUIV_TABLE(DFA) ((u8 *)((DFA)->tables[YYTD_ID_EC - 1]->td_data))
7314 +#define ACCEPT_TABLE(DFA) ((u32 *)((DFA)->tables[YYTD_ID_ACCEPT - 1]->td_data))
7315 +#define ACCEPT_TABLE2(DFA) ((u32 *)((DFA)->tables[YYTD_ID_ACCEPT2 -1]->td_data))
7318 + struct table_header *tables[YYTD_ID_NXT];
7321 +#define byte_to_byte(X) (X)
7323 +#define UNPACK_ARRAY(TABLE, BLOB, LEN, TYPE, NTOHX) \
7325 + typeof(LEN) __i; \
7326 + TYPE *__t = (TYPE *) TABLE; \
7327 + TYPE *__b = (TYPE *) BLOB; \
7328 + for (__i = 0; __i < LEN; __i++) { \
7329 + __t[__i] = NTOHX(__b[__i]); \
7333 +static inline size_t table_size(size_t len, size_t el_size)
7335 + return ALIGN(sizeof(struct table_header) + len * el_size, 8);
7338 +#endif /* __MATCH_H */
7339 diff -uprN linux-2.6.27./security/apparmor/module_interface.c linux-2.6.27/security/apparmor/module_interface.c
7340 --- linux-2.6.27./security/apparmor/module_interface.c 1970-01-01 01:00:00.000000000 +0100
7341 +++ linux-2.6.27/security/apparmor/module_interface.c 2008-10-29 14:28:53.329440939 +0100
7344 + * Copyright (C) 1998-2007 Novell/SUSE
7346 + * This program is free software; you can redistribute it and/or
7347 + * modify it under the terms of the GNU General Public License as
7348 + * published by the Free Software Foundation, version 2 of the
7351 + * AppArmor userspace policy interface
7354 +#include <asm/unaligned.h>
7356 +#include "apparmor.h"
7357 +#include "inline.h"
7360 + * This mutex is used to synchronize profile adds, replacements, and
7361 + * removals: we only allow one of these operations at a time.
7362 + * We do not use the profile list lock here in order to avoid blocking
7363 + * exec during those operations. (Exec involves a profile list lookup
7364 + * for named-profile transitions.)
7366 +DEFINE_MUTEX(aa_interface_lock);
7369 + * The AppArmor interface treats data as a type byte followed by the
7370 + * actual data. The interface has the notion of a a named entry
7371 + * which has a name (AA_NAME typecode followed by name string) followed by
7372 + * the entries typecode and data. Named types allow for optional
7373 + * elements and extensions to be added and tested for without breaking
7374 + * backwards compatability.
7382 + AA_NAME, /* same as string except it is items name */
7394 + * aa_ext is the read of the buffer containing the serialized profile. The
7395 + * data is copied into a kernel buffer in apparmorfs and then handed off to
7396 + * the unpack routines.
7401 + void *pos; /* pointer to current position in the buffer */
7406 +static inline int aa_inbounds(struct aa_ext *e, size_t size)
7408 + return (size <= e->end - e->pos);
7412 + * aa_u16_chunck - test and do bounds checking for a u16 size based chunk
7413 + * @e: serialized data read head
7414 + * @chunk: start address for chunk of data
7416 + * return the size of chunk found with the read head at the end of
7419 +static size_t aa_is_u16_chunk(struct aa_ext *e, char **chunk)
7421 + void *pos = e->pos;
7424 + if (!aa_inbounds(e, sizeof(u16)))
7426 + size = le16_to_cpu(get_unaligned((u16 *)e->pos));
7427 + e->pos += sizeof(u16);
7428 + if (!aa_inbounds(e, size))
7439 +static inline int aa_is_X(struct aa_ext *e, enum aa_code code)
7441 + if (!aa_inbounds(e, 1))
7443 + if (*(u8 *) e->pos != code)
7450 + * aa_is_nameX - check is the next element is of type X with a name of @name
7451 + * @e: serialized data extent information
7452 + * @code: type code
7453 + * @name: name to match to the serialized element.
7455 + * check that the next serialized data element is of type X and has a tag
7456 + * name @name. If @name is specified then there must be a matching
7457 + * name element in the stream. If @name is NULL any name element will be
7458 + * skipped and only the typecode will be tested.
7459 + * returns 1 on success (both type code and name tests match) and the read
7460 + * head is advanced past the headers
7461 + * returns %0 if either match failes, the read head does not move
7463 +static int aa_is_nameX(struct aa_ext *e, enum aa_code code, const char *name)
7465 + void *pos = e->pos;
7467 + * Check for presence of a tagname, and if present name size
7468 + * AA_NAME tag value is a u16.
7470 + if (aa_is_X(e, AA_NAME)) {
7472 + size_t size = aa_is_u16_chunk(e, &tag);
7473 + /* if a name is specified it must match. otherwise skip tag */
7474 + if (name && (!size || strcmp(name, tag)))
7476 + } else if (name) {
7477 + /* if a name is specified and there is no name tag fail */
7481 + /* now check if type code matches */
7482 + if (aa_is_X(e, code))
7490 +static int aa_is_u16(struct aa_ext *e, u16 *data, const char *name)
7492 + void *pos = e->pos;
7493 + if (aa_is_nameX(e, AA_U16, name)) {
7494 + if (!aa_inbounds(e, sizeof(u16)))
7497 + *data = le16_to_cpu(get_unaligned((u16 *)e->pos));
7498 + e->pos += sizeof(u16);
7506 +static int aa_is_u32(struct aa_ext *e, u32 *data, const char *name)
7508 + void *pos = e->pos;
7509 + if (aa_is_nameX(e, AA_U32, name)) {
7510 + if (!aa_inbounds(e, sizeof(u32)))
7513 + *data = le32_to_cpu(get_unaligned((u32 *)e->pos));
7514 + e->pos += sizeof(u32);
7522 +static int aa_is_u64(struct aa_ext *e, u64 *data, const char *name)
7524 + void *pos = e->pos;
7525 + if (aa_is_nameX(e, AA_U64, name)) {
7526 + if (!aa_inbounds(e, sizeof(u64)))
7529 + *data = le64_to_cpu(get_unaligned((u64 *)e->pos));
7530 + e->pos += sizeof(u64);
7538 +static size_t aa_is_array(struct aa_ext *e, const char *name)
7540 + void *pos = e->pos;
7541 + if (aa_is_nameX(e, AA_ARRAY, name)) {
7543 + if (!aa_inbounds(e, sizeof(u16)))
7545 + size = (int) le16_to_cpu(get_unaligned((u16 *)e->pos));
7546 + e->pos += sizeof(u16);
7554 +static size_t aa_is_blob(struct aa_ext *e, char **blob, const char *name)
7556 + void *pos = e->pos;
7557 + if (aa_is_nameX(e, AA_BLOB, name)) {
7559 + if (!aa_inbounds(e, sizeof(u32)))
7561 + size = le32_to_cpu(get_unaligned((u32 *)e->pos));
7562 + e->pos += sizeof(u32);
7563 + if (aa_inbounds(e, (size_t) size)) {
7574 +static int aa_is_dynstring(struct aa_ext *e, char **string, const char *name)
7578 + void *pos = e->pos;
7580 + if (aa_is_nameX(e, AA_STRING, name) &&
7581 + (size = aa_is_u16_chunk(e, &src_str))) {
7583 + if (!(str = kmalloc(size, GFP_KERNEL)))
7585 + memcpy(str, src_str, size);
7597 + * aa_unpack_dfa - unpack a file rule dfa
7598 + * @e: serialized data extent information
7600 + * returns dfa or ERR_PTR
7602 +static struct aa_dfa *aa_unpack_dfa(struct aa_ext *e)
7604 + char *blob = NULL;
7605 + size_t size, error = 0;
7606 + struct aa_dfa *dfa = NULL;
7608 + size = aa_is_blob(e, &blob, "aadfa");
7610 + dfa = aa_match_alloc();
7613 + * The dfa is aligned with in the blob to 8 bytes
7614 + * from the beginning of the stream.
7616 + size_t sz = blob - (char *) e->start;
7617 + size_t pad = ALIGN(sz, 8) - sz;
7618 + error = unpack_dfa(dfa, blob + pad, size - pad);
7620 + error = verify_dfa(dfa);
7626 + aa_match_free(dfa);
7627 + dfa = ERR_PTR(error);
7634 +static int aa_unpack_exec_table(struct aa_ext *e, struct aa_profile *profile)
7636 + void *pos = e->pos;
7638 + /* exec table is optional */
7639 + if (aa_is_nameX(e, AA_STRUCT, "xtable")) {
7642 + size = aa_is_array(e, NULL);
7643 + /* currently 4 exec bits and entries 0-3 are reserved iupcx */
7644 + if (size > 16 - 4)
7646 + profile->exec_table = kzalloc(sizeof(char *) * size,
7648 + if (!profile->exec_table)
7651 + for (i = 0; i < size; i++) {
7653 + if (!aa_is_dynstring(e, &tmp, NULL))
7655 + /* note: strings beginning with a : have an embedded
7656 + \0 seperating the profile ns name from the profile
7658 + profile->exec_table[i] = tmp;
7660 + if (!aa_is_nameX(e, AA_ARRAYEND, NULL))
7662 + if (!aa_is_nameX(e, AA_STRUCTEND, NULL))
7664 + profile->exec_table_size = size;
7673 +int aa_unpack_rlimits(struct aa_ext *e, struct aa_profile *profile)
7675 + void *pos = e->pos;
7677 + /* rlimits are optional */
7678 + if (aa_is_nameX(e, AA_STRUCT, "rlimits")) {
7681 + if (!aa_is_u32(e, &tmp, NULL))
7683 + profile->rlimits.mask = tmp;
7685 + size = aa_is_array(e, NULL);
7686 + if (size > RLIM_NLIMITS)
7688 + for (i = 0; i < size; i++) {
7690 + if (!aa_is_u64(e, &tmp, NULL))
7692 + profile->rlimits.limits[i].rlim_max = tmp;
7694 + if (!aa_is_nameX(e, AA_ARRAYEND, NULL))
7696 + if (!aa_is_nameX(e, AA_STRUCTEND, NULL))
7707 + * aa_unpack_profile - unpack a serialized profile
7708 + * @e: serialized data extent information
7709 + * @sa: audit struct for the operation
7711 +static struct aa_profile *aa_unpack_profile(struct aa_ext *e,
7712 + struct aa_audit *sa)
7714 + struct aa_profile *profile = NULL;
7716 + int i, error = -EPROTO;
7718 + profile = alloc_aa_profile();
7720 + return ERR_PTR(-ENOMEM);
7722 + /* check that we have the right struct being passed */
7723 + if (!aa_is_nameX(e, AA_STRUCT, "profile"))
7725 + if (!aa_is_dynstring(e, &profile->name, NULL))
7728 + /* per profile debug flags (complain, audit) */
7729 + if (!aa_is_nameX(e, AA_STRUCT, "flags"))
7731 + if (!aa_is_u32(e, &(profile->flags.hat), NULL))
7733 + if (!aa_is_u32(e, &(profile->flags.complain), NULL))
7735 + if (!aa_is_u32(e, &(profile->flags.audit), NULL))
7737 + if (!aa_is_nameX(e, AA_STRUCTEND, NULL))
7740 + if (!aa_is_u32(e, &(profile->capabilities.cap[0]), NULL))
7742 + if (!aa_is_u32(e, &(profile->audit_caps.cap[0]), NULL))
7744 + if (!aa_is_u32(e, &(profile->quiet_caps.cap[0]), NULL))
7746 + if (!aa_is_u32(e, &(profile->set_caps.cap[0]), NULL))
7749 + if (aa_is_nameX(e, AA_STRUCT, "caps64")) {
7750 + /* optional upper half of 64 bit caps */
7751 + if (!aa_is_u32(e, &(profile->capabilities.cap[1]), NULL))
7753 + if (!aa_is_u32(e, &(profile->audit_caps.cap[1]), NULL))
7755 + if (!aa_is_u32(e, &(profile->quiet_caps.cap[1]), NULL))
7757 + if (!aa_is_u32(e, &(profile->set_caps.cap[1]), NULL))
7759 + if (!aa_is_nameX(e, AA_STRUCTEND, NULL))
7763 + if (!aa_unpack_rlimits(e, profile))
7766 + size = aa_is_array(e, "net_allowed_af");
7768 + if (size > AF_MAX)
7771 + for (i = 0; i < size; i++) {
7772 + if (!aa_is_u16(e, &profile->network_families[i], NULL))
7774 + if (!aa_is_u16(e, &profile->audit_network[i], NULL))
7776 + if (!aa_is_u16(e, &profile->quiet_network[i], NULL))
7779 + if (!aa_is_nameX(e, AA_ARRAYEND, NULL))
7781 + /* allow unix domain and netlink sockets they are handled
7785 + profile->network_families[AF_UNIX] = 0xffff;
7786 + profile->network_families[AF_NETLINK] = 0xffff;
7788 + /* get file rules */
7789 + profile->file_rules = aa_unpack_dfa(e);
7790 + if (IS_ERR(profile->file_rules)) {
7791 + error = PTR_ERR(profile->file_rules);
7792 + profile->file_rules = NULL;
7796 + if (!aa_unpack_exec_table(e, profile))
7799 + if (!aa_is_nameX(e, AA_STRUCTEND, NULL))
7805 + sa->name = profile && profile->name ? profile->name : "unknown";
7807 + sa->info = "failed to unpack profile";
7808 + aa_audit_status(NULL, sa);
7811 + free_aa_profile(profile);
7813 + return ERR_PTR(error);
7817 + * aa_verify_head - unpack serialized stream header
7818 + * @e: serialized data read head
7819 + * @operation: operation header is being verified for
7821 + * returns error or 0 if header is good
7823 +static int aa_verify_header(struct aa_ext *e, struct aa_audit *sa)
7825 + /* get the interface version */
7826 + if (!aa_is_u32(e, &e->version, "version")) {
7827 + sa->info = "invalid profile format";
7828 + aa_audit_status(NULL, sa);
7829 + return -EPROTONOSUPPORT;
7832 + /* check that the interface version is currently supported */
7833 + if (e->version != 5) {
7834 + sa->info = "unsupported interface version";
7835 + aa_audit_status(NULL, sa);
7836 + return -EPROTONOSUPPORT;
7839 + /* read the namespace if present */
7840 + if (!aa_is_dynstring(e, &e->ns_name, "namespace")) {
7841 + e->ns_name = NULL;
7848 + * aa_add_profile - Unpack and add a new profile to the profile list
7849 + * @data: serialized data stream
7850 + * @size: size of the serialized data stream
7852 +ssize_t aa_add_profile(void *data, size_t size)
7854 + struct aa_profile *profile = NULL;
7855 + struct aa_namespace *ns = NULL;
7856 + struct aa_ext e = {
7858 + .end = data + size,
7863 + struct aa_audit sa;
7864 + memset(&sa, 0, sizeof(sa));
7865 + sa.operation = "profile_load";
7866 + sa.gfp_mask = GFP_KERNEL;
7868 + error = aa_verify_header(&e, &sa);
7872 + profile = aa_unpack_profile(&e, &sa);
7873 + if (IS_ERR(profile))
7874 + return PTR_ERR(profile);
7876 + mutex_lock(&aa_interface_lock);
7877 + write_lock(&profile_ns_list_lock);
7879 + ns = __aa_find_namespace(e.ns_name, &profile_ns_list);
7881 + ns = default_namespace;
7883 + struct aa_namespace *new_ns;
7884 + write_unlock(&profile_ns_list_lock);
7885 + new_ns = alloc_aa_namespace(e.ns_name);
7887 + mutex_unlock(&aa_interface_lock);
7890 + write_lock(&profile_ns_list_lock);
7891 + ns = __aa_find_namespace(e.ns_name, &profile_ns_list);
7893 + list_add(&new_ns->list, &profile_ns_list);
7896 + free_aa_namespace(new_ns);
7899 + write_lock(&ns->lock);
7900 + if (__aa_find_profile(profile->name, &ns->profiles)) {
7901 + /* A profile with this name exists already. */
7902 + write_unlock(&ns->lock);
7903 + write_unlock(&profile_ns_list_lock);
7904 + sa.name = profile->name;
7905 + sa.name2 = ns->name;
7906 + sa.info = "failed: profile already loaded";
7907 + aa_audit_status(NULL, &sa);
7908 + mutex_unlock(&aa_interface_lock);
7909 + aa_put_profile(profile);
7912 + profile->ns = aa_get_namespace(ns);
7913 + ns->profile_count++;
7914 + list_add(&profile->list, &ns->profiles);
7915 + write_unlock(&ns->lock);
7916 + write_unlock(&profile_ns_list_lock);
7918 + sa.name = profile->name;
7919 + sa.name2 = ns->name;
7920 + aa_audit_status(NULL, &sa);
7921 + mutex_unlock(&aa_interface_lock);
7926 + * task_replace - replace a task's profile
7927 + * @task: task to replace profile on
7928 + * @new_cxt: new aa_task_context to do replacement with
7929 + * @new_profile: new profile
7931 +static inline void task_replace(struct task_struct *task,
7932 + struct aa_task_context *new_cxt,
7933 + struct aa_profile *new_profile)
7935 + struct aa_task_context *cxt = aa_task_context(task);
7937 + AA_DEBUG("%s: replacing profile for task %d "
7938 + "profile=%s (%p)\n",
7941 + cxt->profile->name, cxt->profile);
7943 + aa_change_task_context(task, new_cxt, new_profile, cxt->cookie,
7944 + cxt->previous_profile);
7948 + * aa_replace_profile - replace a profile on the profile list
7949 + * @udata: serialized data stream
7950 + * @size: size of the serialized data stream
7952 + * unpack and replace a profile on the profile list and uses of that profile
7953 + * by any aa_task_context. If the profile does not exist on the profile list
7954 + * it is added. Return %0 or error.
7956 +ssize_t aa_replace_profile(void *udata, size_t size)
7958 + struct aa_profile *old_profile, *new_profile;
7959 + struct aa_namespace *ns;
7960 + struct aa_task_context *new_cxt;
7961 + struct aa_ext e = {
7963 + .end = udata + size,
7968 + struct aa_audit sa;
7969 + memset(&sa, 0, sizeof(sa));
7970 + sa.operation = "profile_replace";
7971 + sa.gfp_mask = GFP_KERNEL;
7973 + error = aa_verify_header(&e, &sa);
7977 + new_profile = aa_unpack_profile(&e, &sa);
7978 + if (IS_ERR(new_profile))
7979 + return PTR_ERR(new_profile);
7981 + mutex_lock(&aa_interface_lock);
7982 + write_lock(&profile_ns_list_lock);
7984 + ns = __aa_find_namespace(e.ns_name, &profile_ns_list);
7986 + ns = default_namespace;
7988 + struct aa_namespace *new_ns;
7989 + write_unlock(&profile_ns_list_lock);
7990 + new_ns = alloc_aa_namespace(e.ns_name);
7992 + mutex_unlock(&aa_interface_lock);
7995 + write_lock(&profile_ns_list_lock);
7996 + ns = __aa_find_namespace(e.ns_name, &profile_ns_list);
7998 + list_add(&new_ns->list, &profile_ns_list);
8001 + free_aa_namespace(new_ns);
8004 + write_lock(&ns->lock);
8005 + old_profile = __aa_find_profile(new_profile->name, &ns->profiles);
8006 + if (old_profile) {
8007 + lock_profile(old_profile);
8008 + old_profile->isstale = 1;
8009 + list_del_init(&old_profile->list);
8010 + unlock_profile(old_profile);
8011 + ns->profile_count--;
8013 + new_profile->ns = aa_get_namespace(ns);
8014 + ns->profile_count++;
8015 + /* not don't need an extra ref count to keep new_profile as
8016 + * it is protect by the interface mutex */
8017 + list_add(&new_profile->list, &ns->profiles);
8018 + write_unlock(&ns->lock);
8019 + write_unlock(&profile_ns_list_lock);
8021 + if (!old_profile) {
8022 + sa.operation = "profile_load";
8025 + /* do not fail replacement based off of profile's NPROC rlimit */
8028 + * Replacement needs to allocate a new aa_task_context for each
8029 + * task confined by old_profile. To do this the profile locks
8030 + * are only held when the actual switch is done per task. While
8031 + * looping to allocate a new aa_task_context the old_task list
8032 + * may get shorter if tasks exit/change their profile but will
8033 + * not get longer as new task will not use old_profile detecting
8037 + new_cxt = aa_alloc_task_context(GFP_KERNEL | __GFP_NOFAIL);
8039 + lock_both_profiles(old_profile, new_profile);
8040 + if (!list_empty(&old_profile->task_contexts)) {
8041 + struct task_struct *task =
8042 + list_entry(old_profile->task_contexts.next,
8043 + struct aa_task_context, list)->task;
8045 + task_replace(task, new_cxt, new_profile);
8046 + task_unlock(task);
8047 + aa_set_rlimits(task, new_profile);
8050 + unlock_both_profiles(old_profile, new_profile);
8051 + } while (!new_cxt);
8052 + aa_free_task_context(new_cxt);
8053 + aa_put_profile(old_profile);
8056 + sa.name = new_profile->name;
8057 + sa.name2 = ns->name;
8058 + aa_audit_status(NULL, &sa);
8059 + mutex_unlock(&aa_interface_lock);
8064 + * aa_remove_profile - remove a profile from the system
8065 + * @name: name of the profile to remove
8066 + * @size: size of the name
8068 + * remove a profile from the profile list and all aa_task_context references
8069 + * to said profile.
8070 + * NOTE: removing confinement does not restore rlimits to preconfinemnet values
8072 +ssize_t aa_remove_profile(char *name, size_t size)
8074 + struct aa_namespace *ns;
8075 + struct aa_profile *profile;
8076 + struct aa_audit sa;
8077 + memset(&sa, 0, sizeof(sa));
8078 + sa.operation = "profile_remove";
8079 + sa.gfp_mask = GFP_KERNEL;
8081 + mutex_lock(&aa_interface_lock);
8082 + write_lock(&profile_ns_list_lock);
8084 + if (name[0] == ':') {
8085 + char *split = strchr(name + 1, ':');
8089 + ns = __aa_find_namespace(name + 1, &profile_ns_list);
8092 + ns = default_namespace;
8097 + sa.name2 = ns->name;
8098 + write_lock(&ns->lock);
8099 + profile = __aa_find_profile(name, &ns->profiles);
8101 + write_unlock(&ns->lock);
8104 + sa.name = profile->name;
8106 + /* Remove the profile from each task context it is on. */
8107 + lock_profile(profile);
8108 + profile->isstale = 1;
8109 + aa_unconfine_tasks(profile);
8110 + list_del_init(&profile->list);
8111 + ns->profile_count--;
8112 + unlock_profile(profile);
8113 + /* Release the profile itself. */
8114 + write_unlock(&ns->lock);
8115 + /* check to see if the namespace has become stale */
8116 + if (ns != default_namespace && ns->profile_count == 0) {
8117 + list_del_init(&ns->list);
8118 + aa_put_namespace(ns);
8120 + write_unlock(&profile_ns_list_lock);
8122 + aa_audit_status(NULL, &sa);
8123 + mutex_unlock(&aa_interface_lock);
8124 + aa_put_profile(profile);
8129 + write_unlock(&profile_ns_list_lock);
8130 + sa.info = "failed: profile does not exist";
8131 + aa_audit_status(NULL, &sa);
8132 + mutex_unlock(&aa_interface_lock);
8137 + * free_aa_namespace_kref - free aa_namespace by kref (see aa_put_namespace)
8138 + * @kr: kref callback for freeing of a namespace
8140 +void free_aa_namespace_kref(struct kref *kref)
8142 + struct aa_namespace *ns=container_of(kref, struct aa_namespace, count);
8144 + free_aa_namespace(ns);
8148 + * alloc_aa_namespace - allocate, initialize and return a new namespace
8149 + * @name: a preallocated name
8150 + * Returns NULL on failure.
8152 +struct aa_namespace *alloc_aa_namespace(char *name)
8154 + struct aa_namespace *ns;
8156 + ns = kzalloc(sizeof(*ns), GFP_KERNEL);
8157 + AA_DEBUG("%s(%p)\n", __FUNCTION__, ns);
8160 + INIT_LIST_HEAD(&ns->list);
8161 + INIT_LIST_HEAD(&ns->profiles);
8162 + kref_init(&ns->count);
8163 + rwlock_init(&ns->lock);
8165 + ns->null_complain_profile = alloc_aa_profile();
8166 + if (!ns->null_complain_profile) {
8172 + ns->null_complain_profile->name =
8173 + kstrdup("null-complain-profile", GFP_KERNEL);
8174 + if (!ns->null_complain_profile->name) {
8175 + free_aa_profile(ns->null_complain_profile);
8181 + ns->null_complain_profile->flags.complain = 1;
8182 + /* null_complain_profile doesn't contribute to ns ref count */
8183 + ns->null_complain_profile->ns = ns;
8189 + * free_aa_namespace - free a profile namespace
8190 + * @namespace: the namespace to free
8192 + * Free a namespace. All references to the namespace must have been put.
8193 + * If the namespace was referenced by a profile confining a task,
8194 + * free_aa_namespace will be called indirectly (through free_aa_profile)
8195 + * from an rcu callback routine, so we must not sleep here.
8197 +void free_aa_namespace(struct aa_namespace *ns)
8199 + AA_DEBUG("%s(%p)\n", __FUNCTION__, ns);
8204 + /* namespace still contains profiles -- invalid */
8205 + if (!list_empty(&ns->profiles)) {
8206 + AA_ERROR("%s: internal error, "
8207 + "namespace '%s' still contains profiles\n",
8212 + if (!list_empty(&ns->list)) {
8213 + AA_ERROR("%s: internal error, "
8214 + "namespace '%s' still on list\n",
8219 + /* null_complain_profile doesn't contribute to ns ref counting */
8220 + ns->null_complain_profile->ns = NULL;
8221 + aa_put_profile(ns->null_complain_profile);
8227 + * free_aa_profile_kref - free aa_profile by kref (called by aa_put_profile)
8228 + * @kr: kref callback for freeing of a profile
8230 +void free_aa_profile_kref(struct kref *kref)
8232 + struct aa_profile *p=container_of(kref, struct aa_profile, count);
8234 + free_aa_profile(p);
8238 + * alloc_aa_profile - allocate, initialize and return a new profile
8239 + * Returns NULL on failure.
8241 +struct aa_profile *alloc_aa_profile(void)
8243 + struct aa_profile *profile;
8245 + profile = kzalloc(sizeof(*profile), GFP_KERNEL);
8246 + AA_DEBUG("%s(%p)\n", __FUNCTION__, profile);
8248 + INIT_LIST_HEAD(&profile->list);
8249 + kref_init(&profile->count);
8250 + INIT_LIST_HEAD(&profile->task_contexts);
8251 + spin_lock_init(&profile->lock);
8257 + * free_aa_profile - free a profile
8258 + * @profile: the profile to free
8260 + * Free a profile, its hats and null_profile. All references to the profile,
8261 + * its hats and null_profile must have been put.
8263 + * If the profile was referenced from a task context, free_aa_profile() will
8264 + * be called from an rcu callback routine, so we must not sleep here.
8266 +void free_aa_profile(struct aa_profile *profile)
8268 + AA_DEBUG("%s(%p)\n", __FUNCTION__, profile);
8273 + /* profile is still on profile namespace list -- invalid */
8274 + if (!list_empty(&profile->list)) {
8275 + AA_ERROR("%s: internal error, "
8276 + "profile '%s' still on global list\n",
8281 + aa_put_namespace(profile->ns);
8283 + aa_match_free(profile->file_rules);
8285 + if (profile->name) {
8286 + AA_DEBUG("%s: %s\n", __FUNCTION__, profile->name);
8287 + kfree(profile->name);
8294 + * aa_unconfine_tasks - remove tasks on a profile's task context list
8295 + * @profile: profile to remove tasks from
8297 + * Assumes that @profile lock is held.
8299 +void aa_unconfine_tasks(struct aa_profile *profile)
8301 + while (!list_empty(&profile->task_contexts)) {
8302 + struct task_struct *task =
8303 + list_entry(profile->task_contexts.next,
8304 + struct aa_task_context, list)->task;
8306 + aa_change_task_context(task, NULL, NULL, 0, NULL);
8307 + task_unlock(task);
8310 diff -uprN linux-2.6.27./security/apparmor/procattr.c linux-2.6.27/security/apparmor/procattr.c
8311 --- linux-2.6.27./security/apparmor/procattr.c 1970-01-01 01:00:00.000000000 +0100
8312 +++ linux-2.6.27/security/apparmor/procattr.c 2008-10-29 14:28:53.319441671 +0100
8315 + * Copyright (C) 1998-2007 Novell/SUSE
8317 + * This program is free software; you can redistribute it and/or
8318 + * modify it under the terms of the GNU General Public License as
8319 + * published by the Free Software Foundation, version 2 of the
8322 + * AppArmor /proc/pid/attr handling
8325 +#include "apparmor.h"
8326 +#include "inline.h"
8328 +int aa_getprocattr(struct aa_profile *profile, char **string, unsigned *len)
8333 + const char *mode_str = PROFILE_COMPLAIN(profile) ?
8334 + " (complain)" : " (enforce)";
8335 + int mode_len, name_len, ns_len = 0;
8337 + mode_len = strlen(mode_str);
8338 + name_len = strlen(profile->name);
8339 + if (profile->ns != default_namespace)
8340 + ns_len = strlen(profile->ns->name) + 2;
8341 + *len = mode_len + ns_len + name_len + 1;
8342 + str = kmalloc(*len, GFP_ATOMIC);
8348 + memcpy(str, profile->ns->name, ns_len - 2);
8349 + str += ns_len - 2;
8352 + memcpy(str, profile->name, name_len);
8354 + memcpy(str, mode_str, mode_len);
8359 + const char *unconfined_str = "unconfined\n";
8361 + *len = strlen(unconfined_str);
8362 + str = kmalloc(*len, GFP_ATOMIC);
8366 + memcpy(str, unconfined_str, *len);
8373 +static char *split_token_from_name(const char *op, char *args, u64 *cookie)
8377 + *cookie = simple_strtoull(args, &name, 16);
8378 + if ((name == args) || *name != '^') {
8379 + AA_ERROR("%s: Invalid input '%s'", op, args);
8380 + return ERR_PTR(-EINVAL);
8383 + name++; /* skip ^ */
8389 +int aa_setprocattr_changehat(char *args)
8394 + hat = split_token_from_name("change_hat", args, &cookie);
8396 + return PTR_ERR(hat);
8398 + if (!hat && !cookie) {
8399 + AA_ERROR("change_hat: Invalid input, NULL hat and NULL magic");
8403 + AA_DEBUG("%s: Magic 0x%llx Hat '%s'\n",
8404 + __FUNCTION__, cookie, hat ? hat : NULL);
8406 + return aa_change_hat(hat, cookie);
8409 +int aa_setprocattr_changeprofile(char *args)
8411 + char *name = args, *ns_name = NULL;
8413 + if (name[0] == ':') {
8414 + char *split = strchr(&name[1], ':');
8417 + ns_name = &name[1];
8422 + return aa_change_profile(ns_name, name);
8425 +int aa_setprocattr_setprofile(struct task_struct *task, char *args)
8427 + struct aa_profile *old_profile, *new_profile;
8428 + struct aa_namespace *ns;
8429 + struct aa_audit sa;
8430 + char *name, *ns_name = NULL;
8432 + memset(&sa, 0, sizeof(sa));
8433 + sa.operation = "profile_set";
8434 + sa.gfp_mask = GFP_KERNEL;
8435 + sa.task = task->pid;
8437 + AA_DEBUG("%s: current %d\n",
8438 + __FUNCTION__, current->pid);
8441 + if (args[0] != '/') {
8442 + char *split = strchr(args, ':');
8450 + ns = aa_find_namespace(ns_name);
8452 + ns = aa_get_namespace(default_namespace);
8454 + sa.name = ns_name;
8455 + sa.info = "unknown namespace";
8456 + aa_audit_reject(NULL, &sa);
8457 + aa_put_namespace(ns);
8462 + if (strcmp(name, "unconfined") == 0)
8463 + new_profile = NULL;
8465 + new_profile = aa_find_profile(ns, name);
8466 + if (!new_profile) {
8467 + sa.name = ns_name;
8469 + sa.info = "unknown profile";
8470 + aa_audit_reject(NULL, &sa);
8471 + aa_put_namespace(ns);
8476 + old_profile = __aa_replace_profile(task, new_profile);
8477 + if (IS_ERR(old_profile)) {
8480 + aa_put_profile(new_profile);
8481 + error = PTR_ERR(old_profile);
8482 + if (error == -ESTALE)
8484 + aa_put_namespace(ns);
8488 + if (new_profile) {
8489 + sa.name = ns_name;
8491 + sa.name3 = old_profile ? old_profile->name :
8493 + aa_audit_status(NULL, &sa);
8495 + if (old_profile) {
8496 + sa.name = "unconfined";
8497 + sa.name2 = old_profile->name;
8498 + aa_audit_status(NULL, &sa);
8500 + sa.info = "task is unconfined";
8501 + aa_audit_status(NULL, &sa);
8504 + aa_put_namespace(ns);
8505 + aa_put_profile(old_profile);
8506 + aa_put_profile(new_profile);
8509 diff -uprN linux-2.6.27./security/capability.c linux-2.6.27/security/capability.c
8510 --- linux-2.6.27./security/capability.c 2008-10-10 00:13:53.000000000 +0200
8511 +++ linux-2.6.27/security/capability.c 2008-10-29 02:02:02.169338920 +0100
8512 @@ -155,52 +155,56 @@ static int cap_inode_init_security(struc
8515 static int cap_inode_create(struct inode *inode, struct dentry *dentry,
8517 + struct vfsmount *mnt, int mask)
8522 -static int cap_inode_link(struct dentry *old_dentry, struct inode *inode,
8523 - struct dentry *new_dentry)
8524 +static int cap_inode_link(struct dentry *old_dentry, struct vfsmount *old_mnt,
8525 + struct inode *inode,
8526 + struct dentry *new_dentry, struct vfsmount *new_mnt)
8531 -static int cap_inode_unlink(struct inode *inode, struct dentry *dentry)
8532 +static int cap_inode_unlink(struct inode *inode, struct dentry *dentry,
8533 + struct vfsmount *mnt)
8538 static int cap_inode_symlink(struct inode *inode, struct dentry *dentry,
8540 + struct vfsmount *mnt, const char *name)
8545 static int cap_inode_mkdir(struct inode *inode, struct dentry *dentry,
8547 + struct vfsmount *mnt, int mask)
8552 -static int cap_inode_rmdir(struct inode *inode, struct dentry *dentry)
8553 +static int cap_inode_rmdir(struct inode *inode, struct dentry *dentry,
8554 + struct vfsmount *mnt)
8559 static int cap_inode_mknod(struct inode *inode, struct dentry *dentry,
8560 - int mode, dev_t dev)
8561 + struct vfsmount *mnt, int mode, dev_t dev)
8566 static int cap_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
8567 - struct inode *new_inode, struct dentry *new_dentry)
8568 + struct vfsmount *old_mnt, struct inode *new_inode,
8569 + struct dentry *new_dentry, struct vfsmount *new_mnt)
8574 -static int cap_inode_readlink(struct dentry *dentry)
8575 +static int cap_inode_readlink(struct dentry *dentry, struct vfsmount *mnt)
8579 @@ -216,7 +220,8 @@ static int cap_inode_permission(struct i
8583 -static int cap_inode_setattr(struct dentry *dentry, struct iattr *iattr)
8584 +static int cap_inode_setattr(struct dentry *dentry, struct vfsmount *mnt,
8585 + struct iattr *iattr)
8589 @@ -230,17 +235,20 @@ static void cap_inode_delete(struct inod
8593 -static void cap_inode_post_setxattr(struct dentry *dentry, const char *name,
8594 +static void cap_inode_post_setxattr(struct dentry *dentry, struct vfsmount *mnt,
8596 const void *value, size_t size, int flags)
8600 -static int cap_inode_getxattr(struct dentry *dentry, const char *name)
8601 +static int cap_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
8602 + const char *name, struct file *f)
8607 -static int cap_inode_listxattr(struct dentry *dentry)
8608 +static int cap_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt,
8613 @@ -335,6 +343,11 @@ static int cap_dentry_open(struct file *
8617 +static int cap_path_permission(struct path *path, int mask)
8619 + return security_inode_permission(path->dentry->d_inode, mask);
8622 static int cap_task_create(unsigned long clone_flags)
8625 @@ -889,6 +902,7 @@ void security_fixup_ops(struct security_
8626 set_to_cap_if_null(ops, file_send_sigiotask);
8627 set_to_cap_if_null(ops, file_receive);
8628 set_to_cap_if_null(ops, dentry_open);
8629 + set_to_cap_if_null(ops, path_permission);
8630 set_to_cap_if_null(ops, task_create);
8631 set_to_cap_if_null(ops, task_alloc_security);
8632 set_to_cap_if_null(ops, task_free_security);
8633 diff -uprN linux-2.6.27./security/commoncap.c linux-2.6.27/security/commoncap.c
8634 --- linux-2.6.27./security/commoncap.c 2008-10-10 00:13:53.000000000 +0200
8635 +++ linux-2.6.27/security/commoncap.c 2008-10-29 02:02:02.043175933 +0100
8636 @@ -411,8 +411,9 @@ int cap_bprm_secureexec (struct linux_bi
8637 current->egid != current->gid);
8640 -int cap_inode_setxattr(struct dentry *dentry, const char *name,
8641 - const void *value, size_t size, int flags)
8642 +int cap_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
8643 + const char *name, const void *value, size_t size,
8644 + int flags, struct file *file)
8646 if (!strcmp(name, XATTR_NAME_CAPS)) {
8647 if (!capable(CAP_SETFCAP))
8648 @@ -425,7 +426,8 @@ int cap_inode_setxattr(struct dentry *de
8652 -int cap_inode_removexattr(struct dentry *dentry, const char *name)
8653 +int cap_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
8654 + const char *name, struct file *file)
8656 if (!strcmp(name, XATTR_NAME_CAPS)) {
8657 if (!capable(CAP_SETFCAP))
8658 diff -uprN linux-2.6.27./security/security.c linux-2.6.27/security/security.c
8659 --- linux-2.6.27./security/security.c 2008-10-10 00:13:53.000000000 +0200
8660 +++ linux-2.6.27/security/security.c 2008-10-29 02:02:02.706853503 +0100
8661 @@ -358,72 +358,81 @@ int security_inode_init_security(struct
8663 EXPORT_SYMBOL(security_inode_init_security);
8665 -int security_inode_create(struct inode *dir, struct dentry *dentry, int mode)
8666 +int security_inode_create(struct inode *dir, struct dentry *dentry,
8667 + struct vfsmount *mnt, int mode)
8669 if (unlikely(IS_PRIVATE(dir)))
8671 - return security_ops->inode_create(dir, dentry, mode);
8672 + return security_ops->inode_create(dir, dentry, mnt, mode);
8675 -int security_inode_link(struct dentry *old_dentry, struct inode *dir,
8676 - struct dentry *new_dentry)
8677 +int security_inode_link(struct dentry *old_dentry, struct vfsmount *old_mnt,
8678 + struct inode *dir, struct dentry *new_dentry,
8679 + struct vfsmount *new_mnt)
8681 if (unlikely(IS_PRIVATE(old_dentry->d_inode)))
8683 - return security_ops->inode_link(old_dentry, dir, new_dentry);
8684 + return security_ops->inode_link(old_dentry, old_mnt, dir,
8685 + new_dentry, new_mnt);
8688 -int security_inode_unlink(struct inode *dir, struct dentry *dentry)
8689 +int security_inode_unlink(struct inode *dir, struct dentry *dentry,
8690 + struct vfsmount *mnt)
8692 if (unlikely(IS_PRIVATE(dentry->d_inode)))
8694 - return security_ops->inode_unlink(dir, dentry);
8695 + return security_ops->inode_unlink(dir, dentry, mnt);
8698 int security_inode_symlink(struct inode *dir, struct dentry *dentry,
8699 - const char *old_name)
8700 + struct vfsmount *mnt, const char *old_name)
8702 if (unlikely(IS_PRIVATE(dir)))
8704 - return security_ops->inode_symlink(dir, dentry, old_name);
8705 + return security_ops->inode_symlink(dir, dentry, mnt, old_name);
8708 -int security_inode_mkdir(struct inode *dir, struct dentry *dentry, int mode)
8709 +int security_inode_mkdir(struct inode *dir, struct dentry *dentry,
8710 + struct vfsmount *mnt, int mode)
8712 if (unlikely(IS_PRIVATE(dir)))
8714 - return security_ops->inode_mkdir(dir, dentry, mode);
8715 + return security_ops->inode_mkdir(dir, dentry, mnt, mode);
8718 -int security_inode_rmdir(struct inode *dir, struct dentry *dentry)
8719 +int security_inode_rmdir(struct inode *dir, struct dentry *dentry,
8720 + struct vfsmount *mnt)
8722 if (unlikely(IS_PRIVATE(dentry->d_inode)))
8724 - return security_ops->inode_rmdir(dir, dentry);
8725 + return security_ops->inode_rmdir(dir, dentry, mnt);
8728 -int security_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
8729 +int security_inode_mknod(struct inode *dir, struct dentry *dentry,
8730 + struct vfsmount *mnt, int mode, dev_t dev)
8732 if (unlikely(IS_PRIVATE(dir)))
8734 - return security_ops->inode_mknod(dir, dentry, mode, dev);
8735 + return security_ops->inode_mknod(dir, dentry, mnt, mode, dev);
8737 +EXPORT_SYMBOL_GPL(security_inode_permission);
8739 int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
8740 - struct inode *new_dir, struct dentry *new_dentry)
8741 + struct vfsmount *old_mnt, struct inode *new_dir,
8742 + struct dentry *new_dentry, struct vfsmount *new_mnt)
8744 if (unlikely(IS_PRIVATE(old_dentry->d_inode) ||
8745 (new_dentry->d_inode && IS_PRIVATE(new_dentry->d_inode))))
8747 - return security_ops->inode_rename(old_dir, old_dentry,
8748 - new_dir, new_dentry);
8749 + return security_ops->inode_rename(old_dir, old_dentry, old_mnt,
8750 + new_dir, new_dentry, new_mnt);
8753 -int security_inode_readlink(struct dentry *dentry)
8754 +int security_inode_readlink(struct dentry *dentry, struct vfsmount *mnt)
8756 if (unlikely(IS_PRIVATE(dentry->d_inode)))
8758 - return security_ops->inode_readlink(dentry);
8759 + return security_ops->inode_readlink(dentry, mnt);
8762 int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd)
8763 @@ -440,11 +449,12 @@ int security_inode_permission(struct ino
8764 return security_ops->inode_permission(inode, mask);
8767 -int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
8768 +int security_inode_setattr(struct dentry *dentry, struct vfsmount *mnt,
8769 + struct iattr *attr)
8771 if (unlikely(IS_PRIVATE(dentry->d_inode)))
8773 - return security_ops->inode_setattr(dentry, attr);
8774 + return security_ops->inode_setattr(dentry, mnt, attr);
8776 EXPORT_SYMBOL_GPL(security_inode_setattr);
8778 @@ -462,41 +472,48 @@ void security_inode_delete(struct inode
8779 security_ops->inode_delete(inode);
8782 -int security_inode_setxattr(struct dentry *dentry, const char *name,
8783 - const void *value, size_t size, int flags)
8784 +int security_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
8785 + const char *name, const void *value, size_t size,
8786 + int flags, struct file *file)
8788 if (unlikely(IS_PRIVATE(dentry->d_inode)))
8790 - return security_ops->inode_setxattr(dentry, name, value, size, flags);
8791 + return security_ops->inode_setxattr(dentry, mnt, name, value, size,
8795 -void security_inode_post_setxattr(struct dentry *dentry, const char *name,
8796 - const void *value, size_t size, int flags)
8797 +void security_inode_post_setxattr(struct dentry *dentry, struct vfsmount *mnt,
8798 + const char *name, const void *value,
8799 + size_t size, int flags)
8801 if (unlikely(IS_PRIVATE(dentry->d_inode)))
8803 - security_ops->inode_post_setxattr(dentry, name, value, size, flags);
8804 + security_ops->inode_post_setxattr(dentry, mnt, name, value, size,
8808 -int security_inode_getxattr(struct dentry *dentry, const char *name)
8809 +int security_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
8810 + const char *name, struct file *file)
8812 if (unlikely(IS_PRIVATE(dentry->d_inode)))
8814 - return security_ops->inode_getxattr(dentry, name);
8815 + return security_ops->inode_getxattr(dentry, mnt, name, file);
8818 -int security_inode_listxattr(struct dentry *dentry)
8819 +int security_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt,
8820 + struct file *file)
8822 if (unlikely(IS_PRIVATE(dentry->d_inode)))
8824 - return security_ops->inode_listxattr(dentry);
8825 + return security_ops->inode_listxattr(dentry, mnt, file);
8828 -int security_inode_removexattr(struct dentry *dentry, const char *name)
8829 +int security_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
8830 + const char *name, struct file *file)
8832 if (unlikely(IS_PRIVATE(dentry->d_inode)))
8834 - return security_ops->inode_removexattr(dentry, name);
8835 + return security_ops->inode_removexattr(dentry, mnt, name, file);
8838 int security_inode_need_killpriv(struct dentry *dentry)
8839 @@ -599,6 +616,15 @@ int security_dentry_open(struct file *fi
8840 return security_ops->dentry_open(file);
8843 +int security_path_permission(struct path *path, int mask)
8845 + struct inode *inode = path->dentry->d_inode;
8846 + if (unlikely(IS_PRIVATE(inode)))
8849 + return security_ops->path_permission(path, mask);
8852 int security_task_create(unsigned long clone_flags)
8854 return security_ops->task_create(clone_flags);
8855 diff -uprN linux-2.6.27./security/selinux/hooks.c linux-2.6.27/security/selinux/hooks.c
8856 --- linux-2.6.27./security/selinux/hooks.c 2008-10-10 00:13:53.000000000 +0200
8857 +++ linux-2.6.27/security/selinux/hooks.c 2008-10-29 02:02:02.147048695 +0100
8858 @@ -1811,40 +1811,16 @@ static int selinux_capable(struct task_s
8860 static int selinux_sysctl_get_sid(ctl_table *table, u16 tclass, u32 *sid)
8863 - char *buffer, *path, *end;
8864 + char *buffer, *path;
8868 buffer = (char *)__get_free_page(GFP_KERNEL);
8872 - buflen = PAGE_SIZE;
8873 - end = buffer+buflen;
8879 - const char *name = table->procname;
8880 - size_t namelen = strlen(name);
8881 - buflen -= namelen + 1;
8885 - memcpy(end, name, namelen);
8888 - table = table->parent;
8894 - memcpy(end, "/sys", 4);
8896 - rc = security_genfs_sid("proc", path, tclass, sid);
8898 + path = sysctl_pathname(table, buffer, PAGE_SIZE);
8900 + rc = security_genfs_sid("proc", path, tclass, sid);
8901 free_page((unsigned long)buffer);
8904 @@ -2566,64 +2542,79 @@ static int selinux_inode_init_security(s
8908 -static int selinux_inode_create(struct inode *dir, struct dentry *dentry, int mask)
8909 +static int selinux_inode_create(struct inode *dir, struct dentry *dentry,
8910 + struct vfsmount *mnt, int mask)
8912 return may_create(dir, dentry, SECCLASS_FILE);
8915 -static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
8916 +static int selinux_inode_link(struct dentry *old_dentry,
8917 + struct vfsmount *old_mnt,
8918 + struct inode *dir,
8919 + struct dentry *new_dentry,
8920 + struct vfsmount *new_mnt)
8924 - rc = secondary_ops->inode_link(old_dentry, dir, new_dentry);
8925 + rc = secondary_ops->inode_link(old_dentry, old_mnt, dir, new_dentry,
8929 return may_link(dir, old_dentry, MAY_LINK);
8932 -static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry)
8933 +static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry,
8934 + struct vfsmount *mnt)
8938 - rc = secondary_ops->inode_unlink(dir, dentry);
8939 + rc = secondary_ops->inode_unlink(dir, dentry, mnt);
8942 return may_link(dir, dentry, MAY_UNLINK);
8945 -static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name)
8946 +static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry,
8947 + struct vfsmount *mnt, const char *name)
8949 return may_create(dir, dentry, SECCLASS_LNK_FILE);
8952 -static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, int mask)
8953 +static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry,
8954 + struct vfsmount *mnt, int mask)
8956 return may_create(dir, dentry, SECCLASS_DIR);
8959 -static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry)
8960 +static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry,
8961 + struct vfsmount *mnt)
8963 return may_link(dir, dentry, MAY_RMDIR);
8966 -static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
8967 +static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry,
8968 + struct vfsmount *mnt, int mode, dev_t dev)
8972 - rc = secondary_ops->inode_mknod(dir, dentry, mode, dev);
8973 + rc = secondary_ops->inode_mknod(dir, dentry, mnt, mode, dev);
8977 return may_create(dir, dentry, inode_mode_to_security_class(mode));
8980 -static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
8981 - struct inode *new_inode, struct dentry *new_dentry)
8982 +static int selinux_inode_rename(struct inode *old_inode,
8983 + struct dentry *old_dentry,
8984 + struct vfsmount *old_mnt,
8985 + struct inode *new_inode,
8986 + struct dentry *new_dentry,
8987 + struct vfsmount *new_mnt)
8989 return may_rename(old_inode, old_dentry, new_inode, new_dentry);
8992 -static int selinux_inode_readlink(struct dentry *dentry)
8993 +static int selinux_inode_readlink(struct dentry *dentry, struct vfsmount *mnt)
8995 return dentry_has_perm(current, NULL, dentry, FILE__READ);
8997 @@ -2655,11 +2646,12 @@ static int selinux_inode_permission(stru
8998 open_file_mask_to_av(inode->i_mode, mask), NULL);
9001 -static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
9002 +static int selinux_inode_setattr(struct dentry *dentry, struct vfsmount *mnt,
9003 + struct iattr *iattr)
9007 - rc = secondary_ops->inode_setattr(dentry, iattr);
9008 + rc = secondary_ops->inode_setattr(dentry, mnt, iattr);
9012 @@ -2697,8 +2689,9 @@ static int selinux_inode_setotherxattr(s
9013 return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
9016 -static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
9017 - const void *value, size_t size, int flags)
9018 +static int selinux_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
9019 + const char *name, const void *value,
9020 + size_t size, int flags, struct file *file)
9022 struct task_security_struct *tsec = current->security;
9023 struct inode *inode = dentry->d_inode;
9024 @@ -2752,7 +2745,8 @@ static int selinux_inode_setxattr(struct
9028 -static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
9029 +static void selinux_inode_post_setxattr(struct dentry *dentry,
9030 + struct vfsmount *mnt, const char *name,
9031 const void *value, size_t size,
9034 @@ -2778,17 +2772,21 @@ static void selinux_inode_post_setxattr(
9038 -static int selinux_inode_getxattr(struct dentry *dentry, const char *name)
9039 +static int selinux_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
9040 + const char *name, struct file *file)
9042 return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
9045 -static int selinux_inode_listxattr(struct dentry *dentry)
9046 +static int selinux_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt,
9047 + struct file *file)
9049 return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
9052 -static int selinux_inode_removexattr(struct dentry *dentry, const char *name)
9053 +static int selinux_inode_removexattr(struct dentry *dentry,
9054 + struct vfsmount *mnt, const char *name,
9055 + struct file *file)
9057 if (strcmp(name, XATTR_NAME_SELINUX))
9058 return selinux_inode_setotherxattr(dentry, name);
9059 diff -uprN linux-2.6.27./security/smack/smack_lsm.c linux-2.6.27/security/smack/smack_lsm.c
9060 --- linux-2.6.27./security/smack/smack_lsm.c 2008-10-10 00:13:53.000000000 +0200
9061 +++ linux-2.6.27/security/smack/smack_lsm.c 2008-10-29 02:02:02.110260164 +0100
9062 @@ -432,8 +432,9 @@ static int smack_inode_init_security(str
9064 * Returns 0 if access is permitted, an error code otherwise
9066 -static int smack_inode_link(struct dentry *old_dentry, struct inode *dir,
9067 - struct dentry *new_dentry)
9068 +static int smack_inode_link(struct dentry *old_dentry, struct vfsmount *old_mnt,
9069 + struct inode *dir,
9070 + struct dentry *new_dentry, struct vfsmount *new_mnt)
9074 @@ -453,11 +454,13 @@ static int smack_inode_link(struct dentr
9075 * smack_inode_unlink - Smack check on inode deletion
9076 * @dir: containing directory object
9077 * @dentry: file to unlink
9078 + * @mnt: vfsmount of file to unlink
9080 * Returns 0 if current can write the containing directory
9081 * and the object, error code otherwise
9083 -static int smack_inode_unlink(struct inode *dir, struct dentry *dentry)
9084 +static int smack_inode_unlink(struct inode *dir, struct dentry *dentry,
9085 + struct vfsmount *mnt)
9087 struct inode *ip = dentry->d_inode;
9089 @@ -479,11 +482,13 @@ static int smack_inode_unlink(struct ino
9090 * smack_inode_rmdir - Smack check on directory deletion
9091 * @dir: containing directory object
9092 * @dentry: directory to unlink
9093 + * @mnt: vfsmount @dentry to unlink
9095 * Returns 0 if current can write the containing directory
9096 * and the directory, error code otherwise
9098 -static int smack_inode_rmdir(struct inode *dir, struct dentry *dentry)
9099 +static int smack_inode_rmdir(struct inode *dir, struct dentry *dentry,
9100 + struct vfsmount *mnt)
9104 @@ -504,8 +509,10 @@ static int smack_inode_rmdir(struct inod
9105 * smack_inode_rename - Smack check on rename
9106 * @old_inode: the old directory
9107 * @old_dentry: unused
9108 + * @old_mnt: unused
9109 * @new_inode: the new directory
9110 * @new_dentry: unused
9111 + * @new_mnt: unused
9113 * Read and write access is required on both the old and
9115 @@ -514,8 +521,10 @@ static int smack_inode_rmdir(struct inod
9117 static int smack_inode_rename(struct inode *old_inode,
9118 struct dentry *old_dentry,
9119 + struct vfsmount *old_mnt,
9120 struct inode *new_inode,
9121 - struct dentry *new_dentry)
9122 + struct dentry *new_dentry,
9123 + struct vfsmount *new_mnt)
9127 @@ -559,7 +568,8 @@ static int smack_inode_permission(struct
9129 * Returns 0 if access is permitted, an error code otherwise
9131 -static int smack_inode_setattr(struct dentry *dentry, struct iattr *iattr)
9132 +static int smack_inode_setattr(struct dentry *dentry, struct vfsmount *mnt,
9133 + struct iattr *iattr)
9136 * Need to allow for clearing the setuid bit.
9137 @@ -585,17 +595,20 @@ static int smack_inode_getattr(struct vf
9139 * smack_inode_setxattr - Smack check for setting xattrs
9140 * @dentry: the object
9142 * @name: name of the attribute
9148 * This protects the Smack attribute explicitly.
9150 * Returns 0 if access is permitted, an error code otherwise
9152 -static int smack_inode_setxattr(struct dentry *dentry, const char *name,
9153 - const void *value, size_t size, int flags)
9154 +static int smack_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
9155 + const char *name, const void *value,
9156 + size_t size, int flags, struct file *file)
9160 @@ -605,7 +618,8 @@ static int smack_inode_setxattr(struct d
9161 if (!capable(CAP_MAC_ADMIN))
9164 - rc = cap_inode_setxattr(dentry, name, value, size, flags);
9165 + rc = cap_inode_setxattr(dentry, mnt, name, value, size, flags,
9169 rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE);
9170 @@ -616,6 +630,7 @@ static int smack_inode_setxattr(struct d
9172 * smack_inode_post_setxattr - Apply the Smack update approved above
9175 * @name: attribute name
9176 * @value: attribute value
9177 * @size: attribute size
9178 @@ -624,7 +639,8 @@ static int smack_inode_setxattr(struct d
9179 * Set the pointer in the inode blob to the entry found
9180 * in the master label list.
9182 -static void smack_inode_post_setxattr(struct dentry *dentry, const char *name,
9183 +static void smack_inode_post_setxattr(struct dentry *dentry,
9184 + struct vfsmount *mnt, const char *name,
9185 const void *value, size_t size, int flags)
9187 struct inode_smack *isp;
9188 @@ -657,11 +673,14 @@ static void smack_inode_post_setxattr(st
9190 * smack_inode_getxattr - Smack check on getxattr
9191 * @dentry: the object
9196 * Returns 0 if access is permitted, an error code otherwise
9198 -static int smack_inode_getxattr(struct dentry *dentry, const char *name)
9199 +static int smack_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
9200 + const char *name, struct file *file)
9202 return smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ);
9204 @@ -669,13 +688,16 @@ static int smack_inode_getxattr(struct d
9206 * smack_inode_removexattr - Smack check on removexattr
9207 * @dentry: the object
9209 * @name: name of the attribute
9212 * Removing the Smack attribute requires CAP_MAC_ADMIN
9214 * Returns 0 if access is permitted, an error code otherwise
9216 -static int smack_inode_removexattr(struct dentry *dentry, const char *name)
9217 +static int smack_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
9218 + const char *name, struct file *file)
9222 @@ -685,7 +707,7 @@ static int smack_inode_removexattr(struc
9223 if (!capable(CAP_MAC_ADMIN))
9226 - rc = cap_inode_removexattr(dentry, name);
9227 + rc = cap_inode_removexattr(dentry, mnt, name, file);
9230 rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE);