1 diff -uprN e/fs/afs/dir.c f/fs/afs/dir.c
2 --- e/fs/afs/dir.c 2008-04-17 02:49:44.000000000 +0000
3 +++ f/fs/afs/dir.c 2008-05-28 20:29:29.410207000 +0000
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 e/fs/afs/file.c f/fs/afs/file.c
13 --- e/fs/afs/file.c 2008-04-17 02:49:44.000000000 +0000
14 +++ f/fs/afs/file.c 2008-05-28 20:29:29.410207000 +0000
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 e/fs/afs/inode.c f/fs/afs/inode.c
24 --- e/fs/afs/inode.c 2008-04-17 02:49:44.000000000 +0000
25 +++ f/fs/afs/inode.c 2008-05-28 20:29:29.410207000 +0000
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 e/fs/afs/internal.h f/fs/afs/internal.h
70 --- e/fs/afs/internal.h 2008-04-17 02:49:44.000000000 +0000
71 +++ f/fs/afs/internal.h 2008-05-28 20:29:29.410207000 +0000
72 @@ -550,6 +550,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 e/fs/attr.c f/fs/attr.c
81 --- e/fs/attr.c 2008-04-17 02:49:44.000000000 +0000
82 +++ f/fs/attr.c 2008-05-28 20:29:29.410207000 +0000
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 @@ -158,13 +159,17 @@ 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 + error = inode->i_op->setattr(dentry, attr);
108 error = inode_change_ok(inode, attr);
110 - error = security_inode_setattr(dentry, attr);
111 + error = security_inode_setattr(dentry, mnt, attr);
113 if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) ||
114 (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid))
115 @@ -182,5 +187,12 @@ int notify_change(struct dentry * dentry
119 +EXPORT_SYMBOL_GPL(fnotify_change);
121 +int notify_change(struct dentry *dentry, struct vfsmount *mnt,
122 + struct iattr *attr)
124 + return fnotify_change(dentry, mnt, attr, NULL);
127 EXPORT_SYMBOL(notify_change);
128 diff -uprN e/fs/dcache.c f/fs/dcache.c
129 --- e/fs/dcache.c 2008-04-17 02:49:44.000000000 +0000
130 +++ f/fs/dcache.c 2008-05-28 20:29:29.410207000 +0000
131 @@ -1747,86 +1747,118 @@ shouldnt_be_hashed:
135 - * d_path - return the path of a dentry
136 + * __d_path - return the path of a dentry
137 * @dentry: dentry to report
138 * @vfsmnt: vfsmnt to which the dentry belongs
140 * @rootmnt: vfsmnt to which the root dentry belongs
141 * @buffer: buffer to return value in
142 * @buflen: buffer length
143 + * @fail_deleted: what to return for deleted files
144 + * @disconnect: don't return a path starting with / when disconnected
146 - * Convert a dentry into an ASCII path name. If the entry has been deleted
147 + * Convert a dentry into an ASCII path name. If the entry has been deleted,
148 + * then if @fail_deleted is true, ERR_PTR(-ENOENT) is returned. Otherwise,
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.
152 + * If @dentry is not connected to @root, the path returned will be relative
153 + * (i.e., it will not start with a slash).
155 - * "buflen" should be positive. Caller holds the dcache_lock.
156 + * Returns the buffer or an error code.
158 -static char *__d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
159 - struct path *root, char *buffer, int buflen)
160 +char *__d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
161 + struct path *root, char *buffer, int buflen,
162 + int fail_deleted, int disconnect)
164 - char * end = buffer+buflen;
167 + int namelen, vfsmount_locked = 0;
168 + const unsigned char *name;
171 + return ERR_PTR(-ENAMETOOLONG);
172 + buffer += --buflen;
177 + spin_lock(&dcache_lock);
178 if (!IS_ROOT(dentry) && d_unhashed(dentry)) {
182 + if (fail_deleted) {
183 + buffer = ERR_PTR(-ENOENT);
188 - memcpy(end, " (deleted)", 10);
191 + memcpy(buffer, " (deleted)", 10);
196 - /* Get '/' right */
201 + while (dentry != root->dentry || vfsmnt != root->mnt) {
202 struct dentry * parent;
204 - if (dentry == root->dentry && vfsmnt == root->mnt)
206 if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
208 - spin_lock(&vfsmount_lock);
209 - if (vfsmnt->mnt_parent == vfsmnt) {
210 - spin_unlock(&vfsmount_lock);
212 + if (!vfsmount_locked) {
213 + spin_lock(&vfsmount_lock);
214 + vfsmount_locked = 1;
216 + if (vfsmnt->mnt_parent == vfsmnt)
218 dentry = vfsmnt->mnt_mountpoint;
219 vfsmnt = vfsmnt->mnt_parent;
220 - spin_unlock(&vfsmount_lock);
223 parent = dentry->d_parent;
225 namelen = dentry->d_name.len;
226 - buflen -= namelen + 1;
228 + if (buflen < namelen + 1)
231 - memcpy(end, dentry->d_name.name, namelen);
234 + buflen -= namelen + 1;
236 + memcpy(buffer, dentry->d_name.name, namelen);
240 + /* Get '/' right. */
241 + if (*buffer != '/')
246 + if (vfsmount_locked)
247 + spin_unlock(&vfsmount_lock);
248 + spin_unlock(&dcache_lock);
253 + * We went past the (vfsmount, dentry) we were looking for and have
254 + * either hit a root dentry, a lazily unmounted dentry, an
255 + * unconnected dentry, or the file is on a pseudo filesystem.
257 namelen = dentry->d_name.len;
260 + name = dentry->d_name.name;
263 + * If this is a root dentry, then overwrite the slash. This
264 + * will also DTRT with pseudo filesystems which have root
265 + * dentries named "foo:".
267 + if (IS_ROOT(dentry)) {
271 + if (disconnect && *name == '/') {
272 + /* Make sure we won't return a pathname starting with '/' */
276 + if (buflen < namelen)
278 - retval -= namelen-1; /* hit the slash */
279 - memcpy(retval, dentry->d_name.name, namelen);
282 + memcpy(buffer, dentry->d_name.name, namelen);
286 - return ERR_PTR(-ENAMETOOLONG);
287 + buffer = ERR_PTR(-ENAMETOOLONG);
292 @@ -1861,9 +1893,7 @@ char *d_path(struct path *path, char *bu
293 root = current->fs->root;
294 path_get(¤t->fs->root);
295 read_unlock(¤t->fs->lock);
296 - spin_lock(&dcache_lock);
297 - res = __d_path(path->dentry, path->mnt, &root, buf, buflen);
298 - spin_unlock(&dcache_lock);
299 + res = __d_path(path->dentry, path->mnt, &root, buf, buflen, 0, 0);
303 @@ -1909,9 +1939,9 @@ char *dynamic_dname(struct dentry *dentr
305 asmlinkage long sys_getcwd(char __user *buf, unsigned long size)
309 struct path pwd, root;
310 - char *page = (char *) __get_free_page(GFP_USER);
311 + char *page = (char *) __get_free_page(GFP_USER), *cwd;
315 @@ -1923,29 +1953,18 @@ asmlinkage long sys_getcwd(char __user *
316 path_get(¤t->fs->root);
317 read_unlock(¤t->fs->lock);
320 - /* Has the current directory has been unlinked? */
321 - spin_lock(&dcache_lock);
322 - if (pwd.dentry->d_parent == pwd.dentry || !d_unhashed(pwd.dentry)) {
326 - cwd = __d_path(pwd.dentry, pwd.mnt, &root, page, PAGE_SIZE);
327 - spin_unlock(&dcache_lock);
329 - error = PTR_ERR(cwd);
334 - len = PAGE_SIZE + page - cwd;
337 - if (copy_to_user(buf, cwd, len))
341 - spin_unlock(&dcache_lock);
342 + cwd = __d_path(pwd.dentry, pwd.mnt, &root, page, PAGE_SIZE, 1, 0);
343 + error = PTR_ERR(cwd);
348 + len = PAGE_SIZE + page - cwd;
351 + if (copy_to_user(buf, cwd, len))
357 diff -uprN e/fs/ecryptfs/inode.c f/fs/ecryptfs/inode.c
358 --- e/fs/ecryptfs/inode.c 2008-04-17 02:49:44.000000000 +0000
359 +++ f/fs/ecryptfs/inode.c 2008-05-28 20:29:28.910241000 +0000
360 @@ -388,19 +388,24 @@ static int ecryptfs_link(struct dentry *
361 struct dentry *new_dentry)
363 struct dentry *lower_old_dentry;
364 + struct vfsmount *lower_old_mnt;
365 struct dentry *lower_new_dentry;
366 + struct vfsmount *lower_new_mnt;
367 struct dentry *lower_dir_dentry;
371 file_size_save = i_size_read(old_dentry->d_inode);
372 lower_old_dentry = ecryptfs_dentry_to_lower(old_dentry);
373 + lower_old_mnt = ecryptfs_dentry_to_lower_mnt(old_dentry);
374 lower_new_dentry = ecryptfs_dentry_to_lower(new_dentry);
375 + lower_new_mnt = ecryptfs_dentry_to_lower_mnt(new_dentry);
376 dget(lower_old_dentry);
377 dget(lower_new_dentry);
378 lower_dir_dentry = lock_parent(lower_new_dentry);
379 - rc = vfs_link(lower_old_dentry, lower_dir_dentry->d_inode,
380 - lower_new_dentry, NULL);
381 + rc = vfs_link(lower_old_dentry, lower_old_mnt,
382 + lower_dir_dentry->d_inode, lower_new_dentry,
383 + lower_new_mnt, NULL);
384 if (rc || !lower_new_dentry->d_inode)
386 rc = ecryptfs_interpose(lower_new_dentry, new_dentry, dir->i_sb, 0);
387 @@ -425,10 +430,11 @@ static int ecryptfs_unlink(struct inode
389 struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
390 + struct vfsmount *lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
391 struct inode *lower_dir_inode = ecryptfs_inode_to_lower(dir);
392 struct dentry *lower_dir_dentry;
394 lower_dir_dentry = lock_parent(lower_dentry);
395 - rc = vfs_unlink(lower_dir_inode, lower_dentry, NULL);
396 + rc = vfs_unlink(lower_dir_inode, lower_dentry, NULL, lower_mnt);
398 printk(KERN_ERR "Error in vfs_unlink; rc = [%d]\n", rc);
400 @@ -448,6 +454,7 @@ static int ecryptfs_symlink(struct inode
403 struct dentry *lower_dentry;
404 + struct vfsmount *lower_mnt;
405 struct dentry *lower_dir_dentry;
407 char *encoded_symname;
408 @@ -456,6 +463,7 @@ static int ecryptfs_symlink(struct inode
410 lower_dentry = ecryptfs_dentry_to_lower(dentry);
412 + lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
413 lower_dir_dentry = lock_parent(lower_dentry);
415 encoded_symlen = ecryptfs_encode_filename(crypt_stat, symname,
416 @@ -465,7 +473,7 @@ static int ecryptfs_symlink(struct inode
420 - rc = vfs_symlink(lower_dir_dentry->d_inode, lower_dentry,
421 + rc = vfs_symlink(lower_dir_dentry->d_inode, lower_dentry, lower_mnt,
422 encoded_symname, mode, NULL);
423 kfree(encoded_symname);
424 if (rc || !lower_dentry->d_inode)
425 @@ -487,11 +495,14 @@ static int ecryptfs_mkdir(struct inode *
428 struct dentry *lower_dentry;
429 + struct vfsmount *lower_mnt;
430 struct dentry *lower_dir_dentry;
432 lower_dentry = ecryptfs_dentry_to_lower(dentry);
433 + lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
434 lower_dir_dentry = lock_parent(lower_dentry);
435 - rc = vfs_mkdir(lower_dir_dentry->d_inode, lower_dentry, mode, NULL);
436 + rc = vfs_mkdir(lower_dir_dentry->d_inode, lower_dentry, lower_mnt,
438 if (rc || !lower_dentry->d_inode)
440 rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb, 0);
441 @@ -510,14 +521,16 @@ out:
442 static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry)
444 struct dentry *lower_dentry;
445 + struct vfsmount *lower_mnt;
446 struct dentry *lower_dir_dentry;
449 lower_dentry = ecryptfs_dentry_to_lower(dentry);
450 + lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
452 lower_dir_dentry = lock_parent(lower_dentry);
454 - rc = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry, NULL);
455 + rc = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry, NULL, lower_mnt);
458 d_delete(lower_dentry);
459 @@ -535,11 +548,14 @@ ecryptfs_mknod(struct inode *dir, struct
462 struct dentry *lower_dentry;
463 + struct vfsmount *lower_mnt;
464 struct dentry *lower_dir_dentry;
466 lower_dentry = ecryptfs_dentry_to_lower(dentry);
467 + lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
468 lower_dir_dentry = lock_parent(lower_dentry);
469 - rc = vfs_mknod(lower_dir_dentry->d_inode, lower_dentry, mode, dev, NULL);
470 + rc = vfs_mknod(lower_dir_dentry->d_inode, lower_dentry, lower_mnt, mode,
472 if (rc || !lower_dentry->d_inode)
474 rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb, 0);
475 @@ -560,19 +576,24 @@ ecryptfs_rename(struct inode *old_dir, s
478 struct dentry *lower_old_dentry;
479 + struct vfsmount *lower_old_mnt;
480 struct dentry *lower_new_dentry;
481 + struct vfsmount *lower_new_mnt;
482 struct dentry *lower_old_dir_dentry;
483 struct dentry *lower_new_dir_dentry;
485 lower_old_dentry = ecryptfs_dentry_to_lower(old_dentry);
486 + lower_old_mnt = ecryptfs_dentry_to_lower_mnt(old_dentry);
487 lower_new_dentry = ecryptfs_dentry_to_lower(new_dentry);
488 + lower_new_mnt = ecryptfs_dentry_to_lower_mnt(new_dentry);
489 dget(lower_old_dentry);
490 dget(lower_new_dentry);
491 lower_old_dir_dentry = dget_parent(lower_old_dentry);
492 lower_new_dir_dentry = dget_parent(lower_new_dentry);
493 lock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
494 rc = vfs_rename(lower_old_dir_dentry->d_inode, lower_old_dentry,
495 - lower_new_dir_dentry->d_inode, lower_new_dentry);
496 + lower_old_mnt, lower_new_dir_dentry->d_inode,
497 + lower_new_dentry, lower_new_mnt);
500 fsstack_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode, NULL);
501 @@ -848,6 +869,7 @@ static int ecryptfs_setattr(struct dentr
504 struct dentry *lower_dentry;
505 + struct vfsmount *lower_mnt;
507 struct inode *lower_inode;
508 struct ecryptfs_crypt_stat *crypt_stat;
509 @@ -858,6 +880,7 @@ static int ecryptfs_setattr(struct dentr
510 inode = dentry->d_inode;
511 lower_inode = ecryptfs_inode_to_lower(inode);
512 lower_dentry = ecryptfs_dentry_to_lower(dentry);
513 + lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
514 mutex_lock(&crypt_stat->cs_mutex);
515 if (S_ISDIR(dentry->d_inode->i_mode))
516 crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
518 ia->ia_valid &= ~ATTR_MODE;
520 mutex_lock(&lower_dentry->d_inode->i_mutex);
521 - rc = notify_change(lower_dentry, ia);
522 + rc = notify_change(lower_dentry, lower_mnt, ia);
523 mutex_unlock(&lower_dentry->d_inode->i_mutex);
525 fsstack_copy_attr_all(inode, lower_inode);
526 diff -uprN e/fs/exec.c f/fs/exec.c
527 --- e/fs/exec.c 2008-04-17 02:49:44.000000000 +0000
528 +++ f/fs/exec.c 2008-05-28 20:29:28.910241000 +0000
529 @@ -1777,7 +1777,8 @@ int do_coredump(long signr, int exit_cod
531 if (!file->f_op->write)
533 - if (!ispipe && do_truncate(file->f_path.dentry, 0, 0, file) != 0)
535 + do_truncate(file->f_path.dentry, file->f_path.mnt, 0, 0, file) != 0)
538 retval = binfmt->core_dump(signr, regs, file, core_limit);
539 diff -uprN e/fs/fat/file.c f/fs/fat/file.c
540 --- e/fs/fat/file.c 2008-04-17 02:49:44.000000000 +0000
541 +++ f/fs/fat/file.c 2008-05-28 20:29:28.910241000 +0000
542 @@ -92,7 +92,7 @@ int fat_generic_ioctl(struct inode *inod
545 /* This MUST be done before doing anything irreversible... */
546 - err = notify_change(filp->f_path.dentry, &ia);
547 + err = notify_change(filp->f_path.dentry, filp->f_path.mnt, &ia);
551 diff -uprN e/fs/fuse/dir.c f/fs/fuse/dir.c
552 --- e/fs/fuse/dir.c 2008-04-17 02:49:44.000000000 +0000
553 +++ f/fs/fuse/dir.c 2008-05-28 20:29:29.410207000 +0000
554 @@ -1064,21 +1064,22 @@ static int fuse_dir_fsync(struct file *f
555 return file ? fuse_fsync_common(file, de, datasync, 1) : 0;
558 -static bool update_mtime(unsigned ivalid)
559 +static bool update_mtime(unsigned ivalid, bool have_file)
561 /* Always update if mtime is explicitly set */
562 if (ivalid & ATTR_MTIME_SET)
565 /* If it's an open(O_TRUNC) or an ftruncate(), don't update */
566 - if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE)))
567 + if ((ivalid & ATTR_SIZE) && ((ivalid & ATTR_OPEN) || have_file))
570 /* In all other cases update */
574 -static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg)
575 +static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg,
578 unsigned ivalid = iattr->ia_valid;
580 @@ -1097,7 +1098,7 @@ static void iattr_to_fattr(struct iattr
581 if (!(ivalid & ATTR_ATIME_SET))
582 arg->valid |= FATTR_ATIME_NOW;
584 - if ((ivalid & ATTR_MTIME) && update_mtime(ivalid)) {
585 + if ((ivalid & ATTR_MTIME) && update_mtime(ivalid, have_file)) {
586 arg->valid |= FATTR_MTIME;
587 arg->mtime = iattr->ia_mtime.tv_sec;
588 arg->mtimensec = iattr->ia_mtime.tv_nsec;
589 @@ -1114,8 +1115,8 @@ static void iattr_to_fattr(struct iattr
590 * vmtruncate() doesn't allow for this case, so do the rlimit checking
591 * and the actual truncation by hand.
593 -static int fuse_do_setattr(struct dentry *entry, struct iattr *attr,
595 +int fuse_do_setattr(struct dentry *entry, struct iattr *attr,
598 struct inode *inode = entry->d_inode;
599 struct fuse_conn *fc = get_fuse_conn(inode);
600 @@ -1153,7 +1154,7 @@ static int fuse_do_setattr(struct dentry
602 memset(&inarg, 0, sizeof(inarg));
603 memset(&outarg, 0, sizeof(outarg));
604 - iattr_to_fattr(attr, &inarg);
605 + iattr_to_fattr(attr, &inarg, file != NULL);
607 struct fuse_file *ff = file->private_data;
608 inarg.valid |= FATTR_FH;
609 @@ -1195,10 +1196,7 @@ static int fuse_do_setattr(struct dentry
611 static int fuse_setattr(struct dentry *entry, struct iattr *attr)
613 - if (attr->ia_valid & ATTR_FILE)
614 - return fuse_do_setattr(entry, attr, attr->ia_file);
616 - return fuse_do_setattr(entry, attr, NULL);
617 + return fuse_do_setattr(entry, attr, NULL);
620 static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
621 diff -uprN e/fs/fuse/file.c f/fs/fuse/file.c
622 --- e/fs/fuse/file.c 2008-04-17 02:49:44.000000000 +0000
623 +++ f/fs/fuse/file.c 2008-05-28 20:29:29.410207000 +0000
624 @@ -909,6 +909,11 @@ static sector_t fuse_bmap(struct address
625 return err ? 0 : outarg.block;
628 +static int fuse_fsetattr(struct file *file, struct iattr *attr)
630 + return fuse_do_setattr(file->f_path.dentry, attr, file);
633 static const struct file_operations fuse_file_operations = {
634 .llseek = generic_file_llseek,
635 .read = do_sync_read,
636 @@ -922,6 +927,7 @@ static const struct file_operations fuse
638 .lock = fuse_file_lock,
639 .flock = fuse_file_flock,
640 + .fsetattr = fuse_fsetattr,
641 .splice_read = generic_file_splice_read,
644 @@ -935,6 +941,7 @@ static const struct file_operations fuse
646 .lock = fuse_file_lock,
647 .flock = fuse_file_flock,
648 + .fsetattr = fuse_fsetattr,
649 /* no mmap and splice_read */
652 diff -uprN e/fs/fuse/fuse_i.h f/fs/fuse/fuse_i.h
653 --- e/fs/fuse/fuse_i.h 2008-04-17 02:49:44.000000000 +0000
654 +++ f/fs/fuse/fuse_i.h 2008-05-28 20:29:29.410207000 +0000
655 @@ -509,6 +509,10 @@ void fuse_change_attributes(struct inode
657 int fuse_dev_init(void);
660 +int fuse_do_setattr(struct dentry *entry, struct iattr *attr,
661 + struct file *file);
664 * Cleanup the client device
666 diff -uprN e/fs/hpfs/namei.c f/fs/hpfs/namei.c
667 --- e/fs/hpfs/namei.c 2008-04-17 02:49:44.000000000 +0000
668 +++ f/fs/hpfs/namei.c 2008-05-28 20:29:28.910241000 +0000
669 @@ -426,7 +426,7 @@ again:
670 /*printk("HPFS: truncating file before delete.\n");*/
671 newattrs.ia_size = 0;
672 newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
673 - err = notify_change(dentry, &newattrs);
674 + err = notify_change(dentry, NULL, &newattrs);
675 put_write_access(inode);
678 diff -uprN e/fs/namei.c f/fs/namei.c
679 --- e/fs/namei.c 2008-04-17 02:49:44.000000000 +0000
680 +++ f/fs/namei.c 2008-05-28 20:29:29.410207000 +0000
681 @@ -313,7 +313,12 @@ int vfs_permission(struct nameidata *nd,
683 int file_permission(struct file *file, int mask)
685 - return permission(file->f_path.dentry->d_inode, mask, NULL);
686 + struct nameidata nd;
688 + nd.path = file->f_path;
689 + nd.flags = LOOKUP_ACCESS;
691 + return permission(nd.path.dentry->d_inode, mask, &nd);
695 @@ -1150,24 +1155,21 @@ static int do_path_lookup(int dfd, const
697 read_unlock(&fs->lock);
699 - struct dentry *dentry;
701 file = fget_light(dfd, &fput_needed);
706 - dentry = file->f_path.dentry;
707 + nd->path = file->f_path;
710 - if (!S_ISDIR(dentry->d_inode->i_mode))
711 + if (!S_ISDIR(nd->path.dentry->d_inode->i_mode))
714 retval = file_permission(file, MAY_EXEC);
718 - nd->path = file->f_path;
719 path_get(&file->f_path);
721 fput_light(file, fput_needed);
722 @@ -1511,6 +1513,8 @@ static inline int may_create(struct inod
727 + nd->flags |= LOOKUP_CONTINUE;
728 return permission(dir,MAY_WRITE | MAY_EXEC, nd);
731 @@ -1586,7 +1590,7 @@ int vfs_create(struct inode *dir, struct
732 return -EACCES; /* shouldn't it be ENOSYS? */
735 - error = security_inode_create(dir, dentry, mode);
736 + error = security_inode_create(dir, dentry, nd ? nd->path.mnt : NULL, mode);
740 @@ -1663,7 +1667,7 @@ int may_open(struct nameidata *nd, int a
744 - error = do_truncate(dentry, 0,
745 + error = do_truncate(dentry, nd->path.mnt, 0,
746 ATTR_MTIME|ATTR_CTIME|ATTR_OPEN,
749 @@ -1921,8 +1925,8 @@ fail:
751 EXPORT_SYMBOL_GPL(lookup_create);
753 -int vfs_mknod(struct inode *dir, struct dentry *dentry,
754 - int mode, dev_t dev, struct nameidata *nd)
755 +int vfs_mknod(struct inode *dir, struct dentry *dentry, struct vfsmount *mnt,
756 + int mode, dev_t dev, struct nameidata *nd)
758 int error = may_create(dir, dentry, NULL);
760 @@ -1934,7 +1939,7 @@ int vfs_mknod(struct inode *dir, struct
761 if (!dir->i_op || !dir->i_op->mknod)
764 - error = security_inode_mknod(dir, dentry, mode, dev);
765 + error = security_inode_mknod(dir, dentry, mnt, mode, dev);
769 @@ -1973,12 +1978,12 @@ asmlinkage long sys_mknodat(int dfd, con
770 error = vfs_create(nd.path.dentry->d_inode,dentry,mode,&nd);
772 case S_IFCHR: case S_IFBLK:
773 - error = vfs_mknod(nd.path.dentry->d_inode, dentry, mode,
774 - new_decode_dev(dev), &nd);
775 + error = vfs_mknod(nd.path.dentry->d_inode, dentry,
776 + nd.path.mnt, mode, new_decode_dev(dev), &nd);
778 case S_IFIFO: case S_IFSOCK:
779 - error = vfs_mknod(nd.path.dentry->d_inode, dentry, mode,
781 + error = vfs_mknod(nd.path.dentry->d_inode, dentry,
782 + nd.path.mnt, mode, 0, &nd);
786 @@ -2000,8 +2006,8 @@ asmlinkage long sys_mknod(const char __u
787 return sys_mknodat(AT_FDCWD, filename, mode, dev);
790 -int vfs_mkdir(struct inode *dir, struct dentry *dentry,
791 - int mode, struct nameidata *nd)
792 +int vfs_mkdir(struct inode *dir, struct dentry *dentry, struct vfsmount *mnt,
793 + int mode, struct nameidata *nd)
795 int error = may_create(dir, dentry, nd);
797 @@ -2011,7 +2018,7 @@ int vfs_mkdir(struct inode *dir, struct
800 mode &= (S_IRWXUGO|S_ISVTX);
801 - error = security_inode_mkdir(dir, dentry, mode);
802 + error = security_inode_mkdir(dir, dentry, mnt, mode);
806 @@ -2044,7 +2051,7 @@ asmlinkage long sys_mkdirat(int dfd, con
808 if (!IS_POSIXACL(nd.path.dentry->d_inode))
809 mode &= ~current->fs->umask;
810 - error = vfs_mkdir(nd.path.dentry->d_inode, dentry, mode, &nd);
811 + error = vfs_mkdir(nd.path.dentry->d_inode, dentry, nd.path.mnt, mode, &nd);
814 mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
815 @@ -2087,8 +2094,8 @@ void dentry_unhash(struct dentry *dentry
816 spin_unlock(&dcache_lock);
819 -int vfs_rmdir(struct inode *dir, struct dentry *dentry,
820 - struct nameidata *nd)
821 +int vfs_rmdir(struct inode *dir, struct dentry *dentry,
822 + struct nameidata *nd, struct vfsmount *mnt)
824 int error = may_delete(dir, dentry, 1);
826 @@ -2097,6 +2104,10 @@ int vfs_rmdir(struct inode *dir, struct
827 if (!dir->i_op || !dir->i_op->rmdir)
830 + error = security_inode_rmdir(dir, dentry, mnt);
836 mutex_lock(&dentry->d_inode->i_mutex);
837 @@ -2104,12 +2115,9 @@ int vfs_rmdir(struct inode *dir, struct
838 if (d_mountpoint(dentry))
841 - error = security_inode_rmdir(dir, dentry);
843 - error = dir->i_op->rmdir(dir, dentry);
845 - dentry->d_inode->i_flags |= S_DEAD;
847 + error = dir->i_op->rmdir(dir, dentry);
849 + dentry->d_inode->i_flags |= S_DEAD;
851 mutex_unlock(&dentry->d_inode->i_mutex);
853 @@ -2151,7 +2159,7 @@ static long do_rmdir(int dfd, const char
854 error = PTR_ERR(dentry);
857 - error = vfs_rmdir(nd.path.dentry->d_inode, dentry, &nd);
858 + error = vfs_rmdir(nd.path.dentry->d_inode, dentry, &nd, nd.path.mnt);
861 mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
862 @@ -2167,8 +2175,8 @@ asmlinkage long sys_rmdir(const char __u
863 return do_rmdir(AT_FDCWD, pathname);
866 -int vfs_unlink(struct inode *dir, struct dentry *dentry,
867 - struct nameidata *nd)
868 +int vfs_unlink(struct inode *dir, struct dentry *dentry,
869 + struct nameidata *nd, struct vfsmount *mnt)
871 int error = may_delete(dir, dentry, 0, nd);
873 @@ -2183,7 +2191,7 @@ int vfs_unlink(struct inode *dir, struct
874 if (d_mountpoint(dentry))
877 - error = security_inode_unlink(dir, dentry);
878 + error = security_inode_unlink(dir, dentry, mnt);
880 error = dir->i_op->unlink(dir, dentry);
882 @@ -2232,7 +2240,7 @@ static long do_unlinkat(int dfd, const c
883 inode = dentry->d_inode;
885 atomic_inc(&inode->i_count);
886 - error = vfs_unlink(nd.path.dentry->d_inode, dentry, &nd);
887 + error = vfs_unlink(nd.path.dentry->d_inode, dentry, &nd, nd.path.mnt);
891 @@ -2267,7 +2275,7 @@ asmlinkage long sys_unlink(const char __
892 return do_unlinkat(AT_FDCWD, pathname);
895 -int vfs_symlink(struct inode *dir, struct dentry *dentry,
896 +int vfs_symlink(struct inode *dir, struct dentry *dentry, struct vfsmount *mnt,
897 const char *oldname, int mode, struct nameidata *nd)
898 const char *oldname, int mode, struct nameidata *nd)
900 @@ -2277,7 +2286,7 @@ int vfs_symlink(struct inode *dir, struc
901 if (!dir->i_op || !dir->i_op->symlink)
904 - error = security_inode_symlink(dir, dentry, oldname);
905 + error = security_inode_symlink(dir, dentry, mnt, oldname);
909 @@ -2313,8 +2322,8 @@ asmlinkage long sys_symlinkat(const char
913 - error = vfs_symlink(nd.path.dentry->d_inode, dentry, from,
915 + error = vfs_symlink(nd.path.dentry->d_inode, dentry, nd.path.mnt, from,
919 mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
920 @@ -2330,8 +2340,8 @@ asmlinkage long sys_symlink(const char _
921 return sys_symlinkat(oldname, AT_FDCWD, newname);
924 -int vfs_link(struct dentry *old_dentry, struct inode *dir,
925 - struct dentry *new_dentry, struct nameidata *nd)
926 +int vfs_link(struct dentry *old_dentry, struct vfsmount *old_mnt, struct inode *dir,
927 + struct dentry *new_dentry, struct vfsmount *new_mnt, struct nameidata *nd)
929 struct inode *inode = old_dentry->d_inode;
931 @@ -2355,7 +2365,8 @@ int vfs_link(struct dentry *old_dentry,
932 if (S_ISDIR(old_dentry->d_inode->i_mode))
935 - error = security_inode_link(old_dentry, dir, new_dentry);
936 + error = security_inode_link(old_dentry, old_mnt, dir, new_dentry,
941 @@ -2408,8 +2419,8 @@ asmlinkage long sys_linkat(int olddfd, c
942 goto out_unlock_dput;
945 - error = vfs_link(old_nd.path.dentry, nd.path.dentry->d_inode,
947 + error = vfs_link(old_nd.path.dentry, old_nd.path.mnt, nd.path.dentry->d_inode,
948 + new_dentry, nd.path.mnt, &nd);
952 @@ -2460,7 +2472,8 @@ asmlinkage long sys_link(const char __us
955 static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
956 - struct inode *new_dir, struct dentry *new_dentry)
957 + struct vfsmount *old_mnt, struct inode *new_dir,
958 + struct dentry *new_dentry, struct vfsmount *new_mnt)
961 struct inode *target;
962 @@ -2475,7 +2488,8 @@ static int vfs_rename_dir(struct inode *
966 - error = security_inode_rename(old_dir, old_dentry, new_dir, new_dentry);
967 + error = security_inode_rename(old_dir, old_dentry, old_mnt,
968 + new_dir, new_dentry, new_mnt);
972 @@ -2503,12 +2517,14 @@ static int vfs_rename_dir(struct inode *
975 static int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
976 - struct inode *new_dir, struct dentry *new_dentry)
977 + struct vfsmount *old_mnt, struct inode *new_dir,
978 + struct dentry *new_dentry, struct vfsmount *new_mnt)
980 struct inode *target;
983 - error = security_inode_rename(old_dir, old_dentry, new_dir, new_dentry);
984 + error = security_inode_rename(old_dir, old_dentry, old_mnt,
985 + new_dir, new_dentry, new_mnt);
989 @@ -2531,7 +2547,8 @@ static int vfs_rename_other(struct inode
992 int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
993 - struct inode *new_dir, struct dentry *new_dentry)
994 + struct vfsmount *old_mnt, struct inode *new_dir,
995 + struct dentry *new_dentry, struct vfsmount *new_mnt)
998 int is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
999 @@ -2560,9 +2577,11 @@ int vfs_rename(struct inode *old_dir, st
1000 old_name = fsnotify_oldname_init(old_dentry->d_name.name);
1003 - error = vfs_rename_dir(old_dir,old_dentry,new_dir,new_dentry);
1004 + error = vfs_rename_dir(old_dir, old_dentry, old_mnt,
1005 + new_dir, new_dentry, new_mnt);
1007 - error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry);
1008 + error = vfs_rename_other(old_dir, old_dentry, old_mnt,
1009 + new_dir, new_dentry, new_mnt);
1011 const char *new_name = old_dentry->d_name.name;
1012 fsnotify_move(old_dir, new_dir, old_name, new_name, is_dir,
1013 @@ -2634,8 +2653,8 @@ static int do_rename(int olddfd, const c
1014 if (new_dentry == trap)
1017 - error = vfs_rename(old_dir->d_inode, old_dentry,
1018 - new_dir->d_inode, new_dentry);
1019 + error = vfs_rename(old_dir->d_inode, old_dentry, oldnd.path.mnt,
1020 + new_dir->d_inode, new_dentry, newnd.path.mnt);
1024 diff -uprN e/fs/namespace.c f/fs/namespace.c
1025 --- e/fs/namespace.c 2008-04-17 02:49:44.000000000 +0000
1026 +++ f/fs/namespace.c 2008-05-28 20:29:29.410207000 +0000
1027 @@ -1852,3 +1852,30 @@ void __put_mnt_ns(struct mnt_namespace *
1028 release_mounts(&umount_list);
1032 +char *d_namespace_path(struct dentry *dentry, struct vfsmount *vfsmnt,
1033 + char *buf, int buflen)
1035 + struct path root, ns_root = { };
1038 + read_lock(¤t->fs->lock);
1039 + root = current->fs->root;
1040 + path_get(¤t->fs->root);
1041 + read_unlock(¤t->fs->lock);
1042 + spin_lock(&vfsmount_lock);
1044 + ns_root.mnt = mntget(root.mnt->mnt_ns->root);
1046 + ns_root.dentry = dget(ns_root.mnt->mnt_root);
1047 + spin_unlock(&vfsmount_lock);
1048 + res = __d_path(dentry, vfsmnt, &ns_root, buf, buflen, 1, 1);
1050 + path_put(&ns_root);
1052 + /* Prevent empty path for lazily unmounted filesystems. */
1053 + if (!IS_ERR(res) && *res == '\0')
1057 +EXPORT_SYMBOL(d_namespace_path);
1058 diff -uprN e/fs/nfsd/nfs4recover.c f/fs/nfsd/nfs4recover.c
1059 --- e/fs/nfsd/nfs4recover.c 2008-04-17 02:49:44.000000000 +0000
1060 +++ f/fs/nfsd/nfs4recover.c 2008-05-28 20:29:28.910241000 +0000
1061 @@ -154,7 +154,8 @@ nfsd4_create_clid_dir(struct nfs4_client
1062 dprintk("NFSD: nfsd4_create_clid_dir: DIRECTORY EXISTS\n");
1065 - status = vfs_mkdir(rec_dir.path.dentry->d_inode, dentry, S_IRWXU, NULL);
1066 + status = vfs_mkdir(rec_dir.path.dentry->d_inode, dentry,
1067 + rec_dir.path.mnt, S_IRWXU, NULL);
1071 @@ -258,7 +259,7 @@ nfsd4_remove_clid_file(struct dentry *di
1074 mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
1075 - status = vfs_unlink(dir->d_inode, dentry, NULL);
1076 + status = vfs_unlink(dir->d_inode, dentry, NULL, rec_dir.path.mnt);
1077 mutex_unlock(&dir->d_inode->i_mutex);
1080 @@ -273,7 +274,7 @@ nfsd4_clear_clid_dir(struct dentry *dir,
1081 * a kernel from the future.... */
1082 nfsd4_list_rec_dir(dentry, nfsd4_remove_clid_file);
1083 mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
1084 - status = vfs_rmdir(dir->d_inode, dentry, NULL);
1085 + status = vfs_rmdir(dir->d_inode, dentry, NULL, rec_dir.path.mnt);
1086 mutex_unlock(&dir->d_inode->i_mutex);
1089 diff -uprN e/fs/nfsd/nfs4xdr.c f/fs/nfsd/nfs4xdr.c
1090 --- e/fs/nfsd/nfs4xdr.c 2008-04-17 02:49:44.000000000 +0000
1091 +++ f/fs/nfsd/nfs4xdr.c 2008-05-28 20:29:28.910241000 +0000
1092 @@ -1501,7 +1501,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, s
1094 if (bmval0 & (FATTR4_WORD0_ACL | FATTR4_WORD0_ACLSUPPORT
1095 | FATTR4_WORD0_SUPPORTED_ATTRS)) {
1096 - err = nfsd4_get_nfs4_acl(rqstp, dentry, &acl);
1097 + err = nfsd4_get_nfs4_acl(rqstp, dentry, exp->ex_path.mnt, &acl);
1098 aclsupport = (err == 0);
1099 if (bmval0 & FATTR4_WORD0_ACL) {
1100 if (err == -EOPNOTSUPP)
1101 diff -uprN e/fs/nfsd/vfs.c f/fs/nfsd/vfs.c
1102 --- e/fs/nfsd/vfs.c 2008-04-17 02:49:44.000000000 +0000
1103 +++ f/fs/nfsd/vfs.c 2008-05-28 20:29:29.410207000 +0000
1104 @@ -388,7 +388,7 @@ nfsd_setattr(struct svc_rqst *rqstp, str
1105 err = nfserr_notsync;
1106 if (!check_guard || guardtime == inode->i_ctime.tv_sec) {
1108 - host_err = notify_change(dentry, iap);
1109 + host_err = notify_change(dentry, fhp->fh_export->ex_path.mnt, iap);
1110 err = nfserrno(host_err);
1113 @@ -408,11 +408,12 @@ out_nfserr:
1114 #if defined(CONFIG_NFSD_V2_ACL) || \
1115 defined(CONFIG_NFSD_V3_ACL) || \
1116 defined(CONFIG_NFSD_V4)
1117 -static ssize_t nfsd_getxattr(struct dentry *dentry, char *key, void **buf)
1118 +static ssize_t nfsd_getxattr(struct dentry *dentry, struct vfsmount *mnt,
1119 + char *key, void **buf)
1123 - buflen = vfs_getxattr(dentry, key, NULL, 0);
1124 + buflen = vfs_getxattr(dentry, mnt, key, NULL, 0, NULL);
1128 @@ -420,13 +421,14 @@ static ssize_t nfsd_getxattr(struct dent
1132 - return vfs_getxattr(dentry, key, *buf, buflen);
1133 + return vfs_getxattr(dentry, mnt, key, *buf, buflen, NULL);
1137 #if defined(CONFIG_NFSD_V4)
1139 -set_nfsv4_acl_one(struct dentry *dentry, struct posix_acl *pacl, char *key)
1140 +set_nfsv4_acl_one(struct dentry *dentry, struct vfsmount *mnt,
1141 + struct posix_acl *pacl, char *key)
1145 @@ -445,7 +447,7 @@ set_nfsv4_acl_one(struct dentry *dentry,
1149 - error = vfs_setxattr(dentry, key, buf, len, 0);
1150 + error = vfs_setxattr(dentry, mnt, key, buf, len, 0, NULL);
1154 @@ -458,6 +460,7 @@ nfsd4_set_nfs4_acl(struct svc_rqst *rqst
1157 struct dentry *dentry;
1158 + struct vfsmount *mnt;
1159 struct inode *inode;
1160 struct posix_acl *pacl = NULL, *dpacl = NULL;
1161 unsigned int flags = 0;
1162 @@ -468,6 +471,7 @@ nfsd4_set_nfs4_acl(struct svc_rqst *rqst
1165 dentry = fhp->fh_dentry;
1166 + mnt = fhp->fh_export->ex_path.mnt;
1167 inode = dentry->d_inode;
1168 if (S_ISDIR(inode->i_mode))
1169 flags = NFS4_ACL_DIR;
1170 @@ -478,12 +482,14 @@ nfsd4_set_nfs4_acl(struct svc_rqst *rqst
1171 } else if (host_error < 0)
1174 - host_error = set_nfsv4_acl_one(dentry, pacl, POSIX_ACL_XATTR_ACCESS);
1175 + host_error = set_nfsv4_acl_one(dentry, mnt, pacl,
1176 + POSIX_ACL_XATTR_ACCESS);
1180 if (S_ISDIR(inode->i_mode))
1181 - host_error = set_nfsv4_acl_one(dentry, dpacl, POSIX_ACL_XATTR_DEFAULT);
1182 + host_error = set_nfsv4_acl_one(dentry, mnt, dpacl,
1183 + POSIX_ACL_XATTR_DEFAULT);
1186 posix_acl_release(pacl);
1187 @@ -496,13 +502,13 @@ out_nfserr:
1190 static struct posix_acl *
1191 -_get_posix_acl(struct dentry *dentry, char *key)
1192 +_get_posix_acl(struct dentry *dentry, struct vfsmount *mnt, char *key)
1195 struct posix_acl *pacl = NULL;
1198 - buflen = nfsd_getxattr(dentry, key, &buf);
1199 + buflen = nfsd_getxattr(dentry, mnt, key, &buf);
1203 @@ -514,14 +520,15 @@ _get_posix_acl(struct dentry *dentry, ch
1207 -nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry, struct nfs4_acl **acl)
1208 +nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry,
1209 + struct vfsmount *mnt, struct nfs4_acl **acl)
1211 struct inode *inode = dentry->d_inode;
1213 struct posix_acl *pacl = NULL, *dpacl = NULL;
1214 unsigned int flags = 0;
1216 - pacl = _get_posix_acl(dentry, POSIX_ACL_XATTR_ACCESS);
1217 + pacl = _get_posix_acl(dentry, mnt, POSIX_ACL_XATTR_ACCESS);
1218 if (IS_ERR(pacl) && PTR_ERR(pacl) == -ENODATA)
1219 pacl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
1221 @@ -531,7 +538,7 @@ nfsd4_get_nfs4_acl(struct svc_rqst *rqst
1224 if (S_ISDIR(inode->i_mode)) {
1225 - dpacl = _get_posix_acl(dentry, POSIX_ACL_XATTR_DEFAULT);
1226 + dpacl = _get_posix_acl(dentry, mnt, POSIX_ACL_XATTR_DEFAULT);
1227 if (IS_ERR(dpacl) && PTR_ERR(dpacl) == -ENODATA)
1229 else if (IS_ERR(dpacl)) {
1230 @@ -944,13 +951,13 @@ out:
1234 -static void kill_suid(struct dentry *dentry)
1235 +static void kill_suid(struct dentry *dentry, struct vfsmount *mnt)
1238 ia.ia_valid = ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;
1240 mutex_lock(&dentry->d_inode->i_mutex);
1241 - notify_change(dentry, &ia);
1242 + notify_change(dentry, mnt, &ia);
1243 mutex_unlock(&dentry->d_inode->i_mutex);
1246 @@ -1009,7 +1016,7 @@ nfsd_vfs_write(struct svc_rqst *rqstp, s
1248 /* clear setuid/setgid flag after write */
1249 if (host_err >= 0 && (inode->i_mode & (S_ISUID | S_ISGID)))
1250 - kill_suid(dentry);
1251 + kill_suid(dentry, exp->ex_path.mnt);
1253 if (host_err >= 0 && stable) {
1254 static ino_t last_ino;
1255 @@ -1186,6 +1193,7 @@ nfsd_create(struct svc_rqst *rqstp, stru
1256 int type, dev_t rdev, struct svc_fh *resfhp)
1258 struct dentry *dentry, *dchild = NULL;
1259 + struct svc_export *exp;
1263 @@ -1203,6 +1211,7 @@ nfsd_create(struct svc_rqst *rqstp, stru
1266 dentry = fhp->fh_dentry;
1267 + exp = fhp->fh_export;
1268 dirp = dentry->d_inode;
1270 err = nfserr_notdir;
1271 @@ -1219,7 +1228,7 @@ nfsd_create(struct svc_rqst *rqstp, stru
1272 host_err = PTR_ERR(dchild);
1275 - err = fh_compose(resfhp, fhp->fh_export, dchild, fhp);
1276 + err = fh_compose(resfhp, exp, dchild, fhp);
1280 @@ -1258,13 +1267,14 @@ nfsd_create(struct svc_rqst *rqstp, stru
1281 host_err = vfs_create(dirp, dchild, iap->ia_mode, NULL);
1284 - host_err = vfs_mkdir(dirp, dchild, iap->ia_mode, NULL);
1285 + host_err = vfs_mkdir(dirp, dchild, exp->ex_path.mnt, iap->ia_mode, NULL);
1291 - host_err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev, NULL);
1292 + host_err = vfs_mknod(dirp, dchild, exp->ex_path.mnt,
1293 + iap->ia_mode, rdev, NULL);
1296 printk("nfsd: bad file type %o in nfsd_create\n", type);
1297 @@ -1273,7 +1283,7 @@ nfsd_create(struct svc_rqst *rqstp, stru
1301 - if (EX_ISSYNC(fhp->fh_export)) {
1302 + if (EX_ISSYNC(exp)) {
1303 err = nfserrno(nfsd_sync_dir(dentry));
1304 write_inode_now(dchild->d_inode, 1);
1306 @@ -1496,6 +1506,7 @@ nfsd_symlink(struct svc_rqst *rqstp, str
1309 struct dentry *dentry, *dnew;
1310 + struct svc_export *exp;
1314 @@ -1522,6 +1533,7 @@ nfsd_symlink(struct svc_rqst *rqstp, str
1315 if (iap && (iap->ia_valid & ATTR_MODE))
1316 mode = iap->ia_mode & S_IALLUGO;
1318 + exp = fhp->fh_export;
1319 if (unlikely(path[plen] != 0)) {
1320 char *path_alloced = kmalloc(plen+1, GFP_KERNEL);
1321 if (path_alloced == NULL)
1322 @@ -1529,21 +1541,21 @@ nfsd_symlink(struct svc_rqst *rqstp, str
1323 strncpy(path_alloced, path, plen);
1324 path_alloced[plen] = 0;
1325 host_err = vfs_symlink(dentry->d_inode, dnew,
1326 - path_alloced, mode, NULL);
1327 + exp->ex_path.mnt, path_alloced, mode, NULL);
1328 kfree(path_alloced);
1331 - host_err = vfs_symlink(dentry->d_inode, dnew,
1332 - path, mode, NULL);
1333 + host_err = vfs_symlink(dentry->d_inode, dnew, exp->ex_path.mnt,
1334 + path, mode, NULL);
1337 - if (EX_ISSYNC(fhp->fh_export))
1338 + if (EX_ISSYNC(exp))
1339 host_err = nfsd_sync_dir(dentry);
1341 err = nfserrno(host_err);
1344 - cerr = fh_compose(resfhp, fhp->fh_export, dnew, fhp);
1345 + cerr = fh_compose(resfhp, exp, dnew, fhp);
1347 if (err==0) err = cerr;
1349 @@ -1592,7 +1606,8 @@ nfsd_link(struct svc_rqst *rqstp, struct
1350 dold = tfhp->fh_dentry;
1351 dest = dold->d_inode;
1353 - host_err = vfs_link(dold, dirp, dnew, NULL);
1354 + host_err = vfs_link(dold, tfhp->fh_export->ex_path.mnt, dirp,
1355 + dnew, ffhp->fh_export->ex_path.mnt, NULL);
1357 if (EX_ISSYNC(ffhp->fh_export)) {
1358 err = nfserrno(nfsd_sync_dir(ddir));
1359 @@ -1685,7 +1700,8 @@ nfsd_rename(struct svc_rqst *rqstp, stru
1363 - host_err = vfs_rename(fdir, odentry, tdir, ndentry);
1364 + host_err = vfs_rename(fdir, odentry, ffhp->fh_export->ex_path.mnt,
1365 + tdir, ndentry, tfhp->fh_export->ex_path.mnt);
1366 if (!host_err && EX_ISSYNC(tfhp->fh_export)) {
1367 host_err = nfsd_sync_dir(tdentry);
1369 @@ -1721,6 +1737,7 @@ nfsd_unlink(struct svc_rqst *rqstp, stru
1370 char *fname, int flen)
1372 struct dentry *dentry, *rdentry;
1373 + struct svc_export *exp;
1377 @@ -1735,6 +1752,7 @@ nfsd_unlink(struct svc_rqst *rqstp, stru
1378 fh_lock_nested(fhp, I_MUTEX_PARENT);
1379 dentry = fhp->fh_dentry;
1380 dirp = dentry->d_inode;
1381 + exp = fhp->fh_export;
1383 rdentry = lookup_one_len(fname, dentry, flen);
1384 host_err = PTR_ERR(rdentry);
1385 @@ -1752,21 +1770,21 @@ nfsd_unlink(struct svc_rqst *rqstp, stru
1387 if (type != S_IFDIR) { /* It's UNLINK */
1389 - if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
1390 + if ((exp->ex_flags & NFSEXP_MSNFS) &&
1391 (atomic_read(&rdentry->d_count) > 1)) {
1395 - host_err = vfs_unlink(dirp, rdentry, NULL);
1396 + host_err = vfs_unlink(dirp, rdentry, NULL, exp->ex_path.mnt);
1397 } else { /* It's RMDIR */
1398 - host_err = vfs_rmdir(dirp, rdentry, NULL);
1399 + host_err = vfs_rmdir(dirp, rdentry, NULL, exp->ex_path.mnt);
1406 - if (EX_ISSYNC(fhp->fh_export))
1407 + if (EX_ISSYNC(exp))
1408 host_err = nfsd_sync_dir(dentry);
1411 @@ -1995,7 +2013,8 @@ nfsd_get_posix_acl(struct svc_fh *fhp, i
1412 return ERR_PTR(-EOPNOTSUPP);
1415 - size = nfsd_getxattr(fhp->fh_dentry, name, &value);
1416 + size = nfsd_getxattr(fhp->fh_dentry, fhp->fh_export->ex_path.mnt, name,
1419 return ERR_PTR(size);
1421 @@ -2007,6 +2026,7 @@ nfsd_get_posix_acl(struct svc_fh *fhp, i
1423 nfsd_set_posix_acl(struct svc_fh *fhp, int type, struct posix_acl *acl)
1425 + struct vfsmount *mnt;
1426 struct inode *inode = fhp->fh_dentry->d_inode;
1429 @@ -2039,13 +2059,16 @@ nfsd_set_posix_acl(struct svc_fh *fhp, i
1433 + mnt = fhp->fh_export->ex_path.mnt;
1435 - error = vfs_setxattr(fhp->fh_dentry, name, value, size, 0);
1436 + error = vfs_setxattr(fhp->fh_dentry, mnt, name, value, size, 0,
1439 if (!S_ISDIR(inode->i_mode) && type == ACL_TYPE_DEFAULT)
1442 - error = vfs_removexattr(fhp->fh_dentry, name);
1443 + error = vfs_removexattr(fhp->fh_dentry, mnt, name,
1445 if (error == -ENODATA)
1448 diff -uprN e/fs/ntfs/file.c f/fs/ntfs/file.c
1449 --- e/fs/ntfs/file.c 2008-04-17 02:49:44.000000000 +0000
1450 +++ f/fs/ntfs/file.c 2008-05-28 20:29:28.910241000 +0000
1451 @@ -2118,7 +2118,7 @@ static ssize_t ntfs_file_aio_write_noloc
1455 - err = remove_suid(file->f_path.dentry);
1456 + err = remove_suid(&file->f_path);
1459 file_update_time(file);
1460 diff -uprN e/fs/open.c f/fs/open.c
1461 --- e/fs/open.c 2008-04-17 02:49:44.000000000 +0000
1462 +++ f/fs/open.c 2008-05-28 20:29:29.410207000 +0000
1463 @@ -194,8 +194,8 @@ out:
1467 -int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
1468 - struct file *filp)
1469 +int do_truncate(struct dentry *dentry, struct vfsmount *mnt, loff_t length,
1470 + unsigned int time_attrs, struct file *filp)
1473 struct iattr newattrs;
1474 @@ -206,16 +206,15 @@ int do_truncate(struct dentry *dentry, l
1476 newattrs.ia_size = length;
1477 newattrs.ia_valid = ATTR_SIZE | time_attrs;
1479 - newattrs.ia_file = filp;
1482 newattrs.ia_valid |= ATTR_FILE;
1485 /* Remove suid/sgid on truncate too */
1486 newattrs.ia_valid |= should_remove_suid(dentry);
1488 mutex_lock(&dentry->d_inode->i_mutex);
1489 - err = notify_change(dentry, &newattrs);
1490 + err = fnotify_change(dentry, mnt, &newattrs, filp);
1491 mutex_unlock(&dentry->d_inode->i_mutex);
1494 @@ -271,7 +270,7 @@ static long do_sys_truncate(const char _
1495 error = locks_verify_truncate(inode, NULL, length);
1498 - error = do_truncate(nd.path.dentry, length, 0, NULL);
1499 + error = do_truncate(nd.path.dentry, nd.path.mnt, length, 0, NULL);
1503 @@ -324,7 +323,8 @@ static long do_sys_ftruncate(unsigned in
1505 error = locks_verify_truncate(inode, file, length);
1507 - error = do_truncate(dentry, length, ATTR_MTIME|ATTR_CTIME, file);
1508 + error = do_truncate(dentry, file->f_path.mnt, length,
1509 + ATTR_MTIME|ATTR_CTIME, file);
1513 @@ -500,8 +500,8 @@ out:
1515 asmlinkage long sys_fchdir(unsigned int fd)
1517 + struct nameidata nd = { .flags = 0 };
1519 - struct inode *inode;
1523 @@ -509,12 +509,11 @@ asmlinkage long sys_fchdir(unsigned int
1527 - inode = file->f_path.dentry->d_inode;
1530 - if (!S_ISDIR(inode->i_mode))
1531 + if (!S_ISDIR(file->f_path.dentry->d_inode->i_mode))
1534 + nd.path = file->f_path;
1535 error = file_permission(file, MAY_EXEC);
1537 set_fs_pwd(current->fs, &file->f_path);
1538 @@ -577,8 +576,8 @@ asmlinkage long sys_fchmod(unsigned int
1539 if (mode == (mode_t) -1)
1540 mode = inode->i_mode;
1541 newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
1542 - newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
1543 - err = notify_change(dentry, &newattrs);
1544 + newattrs.ia_valid = ATTR_MODE | ATTR_CTIME | ATTR_FILE;
1545 + err = fnotify_change(dentry, file->f_path.mnt, &newattrs, file);
1546 mutex_unlock(&inode->i_mutex);
1549 @@ -613,7 +612,7 @@ asmlinkage long sys_fchmodat(int dfd, co
1550 mode = inode->i_mode;
1551 newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
1552 newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
1553 - error = notify_change(nd.path.dentry, &newattrs);
1554 + error = notify_change(nd.path.dentry, nd.path.mnt, &newattrs);
1555 mutex_unlock(&inode->i_mutex);
1558 @@ -627,7 +626,7 @@ asmlinkage long sys_chmod(const char __u
1561 static int chown_common(struct dentry *dentry, struct vfsmount *mnt,
1562 - uid_t user, gid_t group)
1563 + uid_t user, gid_t group, struct file *file)
1565 struct inode * inode;
1567 @@ -666,8 +666,11 @@ static int chown_common(struct dentry *
1568 if (!S_ISDIR(inode->i_mode))
1569 newattrs.ia_valid |=
1570 ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;
1572 + newattrs.ia_valid |= ATTR_FILE;
1574 mutex_lock(&inode->i_mutex);
1575 - error = notify_change(dentry, &newattrs);
1576 + error = fnotify_change(dentry, mnt, &newattrs, file);
1577 mutex_unlock(&inode->i_mutex);
1580 @@ -671,7 +686,7 @@ asmlinkage long sys_chown(const char __u
1581 error = cow_check_and_break(&nd);
1584 - error = chown_common(nd.path.dentry, nd.path.mnt, user, group);
1585 + error = chown_common(nd.path.dentry, nd.path.mnt, user, group, NULL);
1589 @@ -691,7 +710,7 @@ asmlinkage long sys_fchownat(int dfd, co
1590 error = __user_walk_fd(dfd, filename, follow, &nd);
1593 - error = chown_common(nd.path.dentry, nd.path.mnt, user, group);
1594 + error = chown_common(nd.path.dentry, nd.path.mnt, user, group, NULL);
1598 @@ -705,7 +708,7 @@ asmlinkage long sys_lchown(const char __
1599 error = cow_check_and_break(&nd);
1602 - error = chown_common(nd.path.dentry, nd.path.mnt, user, group);
1603 + error = chown_common(nd.path.dentry, nd.path.mnt, user, group, NULL);
1607 @@ -724,7 +727,7 @@ asmlinkage long sys_fchown(unsigned int
1609 dentry = file->f_path.dentry;
1610 audit_inode(NULL, dentry);
1611 - error = chown_common(dentry, file->f_vfsmnt, user, group);
1612 + error = chown_common(dentry, file->f_path.mnt, user, group, file);
1616 diff -uprN e/fs/reiserfs/xattr.c f/fs/reiserfs/xattr.c
1617 --- e/fs/reiserfs/xattr.c 2008-04-17 02:49:44.000000000 +0000
1618 +++ f/fs/reiserfs/xattr.c 2008-05-28 20:29:28.910241000 +0000
1619 @@ -460,7 +460,7 @@ reiserfs_xattr_set(struct inode *inode,
1620 newattrs.ia_size = buffer_size;
1621 newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
1622 mutex_lock_nested(&xinode->i_mutex, I_MUTEX_XATTR);
1623 - err = notify_change(dentry, &newattrs);
1624 + err = notify_change(dentry, NULL, &newattrs);
1628 @@ -747,7 +747,7 @@ int reiserfs_delete_xattrs(struct inode
1629 if (dir->d_inode->i_nlink <= 2) {
1630 root = get_xa_root(inode->i_sb, XATTR_REPLACE);
1631 reiserfs_write_lock_xattrs(inode->i_sb);
1632 - err = vfs_rmdir(root->d_inode, dir, NULL);
1633 + err = vfs_rmdir(root->d_inode, dir, NULL, NULL);
1634 reiserfs_write_unlock_xattrs(inode->i_sb);
1637 @@ -791,7 +791,7 @@ reiserfs_chown_xattrs_filler(void *buf,
1640 if (!S_ISDIR(xafile->d_inode->i_mode))
1641 - err = notify_change(xafile, attrs);
1642 + err = notify_change(xafile, NULL, attrs);
1646 @@ -835,7 +835,7 @@ int reiserfs_chown_xattrs(struct inode *
1650 - err = notify_change(dir, attrs);
1651 + err = notify_change(dir, NULL, attrs);
1655 diff -uprN e/fs/splice.c f/fs/splice.c
1656 --- e/fs/splice.c 2008-04-17 02:49:44.000000000 +0000
1657 +++ f/fs/splice.c 2008-05-28 20:29:28.910241000 +0000
1658 @@ -762,7 +762,7 @@ generic_file_splice_write_nolock(struct
1662 - err = remove_suid(out->f_path.dentry);
1663 + err = remove_suid(&out->f_path);
1667 @@ -822,7 +822,7 @@ generic_file_splice_write(struct pipe_in
1669 err = security_inode_killpriv(out->f_path.dentry);
1670 if (!err && killsuid)
1671 - err = __remove_suid(out->f_path.dentry, killsuid);
1672 + err = __remove_suid(&out->f_path, killsuid);
1673 mutex_unlock(&inode->i_mutex);
1676 diff -uprN e/fs/stat.c f/fs/stat.c
1677 --- e/fs/stat.c 2008-04-17 02:49:44.000000000 +0000
1678 +++ f/fs/stat.c 2008-05-28 20:29:28.910241000 +0000
1679 @@ -306,7 +306,7 @@ asmlinkage long sys_readlinkat(int dfd,
1682 if (inode->i_op && inode->i_op->readlink) {
1683 - error = security_inode_readlink(nd.path.dentry);
1684 + error = security_inode_readlink(nd.path.dentry, nd.path.mnt);
1686 touch_atime(nd.path.mnt, nd.path.dentry);
1687 error = inode->i_op->readlink(nd.path.dentry,
1688 diff -uprN e/fs/sysfs/file.c f/fs/sysfs/file.c
1689 --- e/fs/sysfs/file.c 2008-04-17 02:49:44.000000000 +0000
1690 +++ f/fs/sysfs/file.c 2008-05-28 20:29:28.910241000 +0000
1691 @@ -579,7 +579,7 @@ int sysfs_chmod_file(struct kobject *kob
1693 newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
1694 newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
1695 - rc = notify_change(victim, &newattrs);
1696 + rc = notify_change(victim, NULL, &newattrs);
1699 mutex_lock(&sysfs_mutex);
1700 diff -uprN e/fs/utimes.c f/fs/utimes.c
1701 --- e/fs/utimes.c 2008-05-28 20:32:27.897940261 +0000
1702 +++ f/fs/utimes.c 2008-05-28 20:29:29.410207000 +0000
1703 @@ -60,7 +60,7 @@ long do_utimes(int dfd, char __user *fil
1706 struct nameidata nd;
1707 - struct dentry *dentry;
1709 struct inode *inode;
1710 struct iattr newattrs;
1711 struct file *f = NULL;
1712 @@ -83,19 +83,19 @@ long do_utimes(int dfd, char __user *fil
1716 - dentry = f->f_path.dentry;
1719 error = __user_walk_fd(dfd, filename, (flags & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW, &nd);
1723 error = cow_check_and_break(&nd);
1726 - dentry = nd.path.dentry;
1730 - inode = dentry->d_inode;
1731 + inode = path.dentry->d_inode;
1734 if (IS_RDONLY(inode))
1735 @@ -145,7 +145,7 @@ long do_utimes(int dfd, char __user *fil
1738 mutex_lock(&inode->i_mutex);
1739 - error = notify_change(dentry, &newattrs);
1740 + error = fnotify_change(path.dentry, path.mnt, &newattrs, f);
1741 mutex_unlock(&inode->i_mutex);
1744 diff -uprN e/fs/xattr.c f/fs/xattr.c
1745 --- e/fs/xattr.c 2008-04-17 02:49:44.000000000 +0000
1746 +++ f/fs/xattr.c 2008-05-28 20:29:29.410207000 +0000
1747 @@ -68,8 +68,8 @@ xattr_permission(struct inode *inode, co
1751 -vfs_setxattr(struct dentry *dentry, char *name, void *value,
1752 - size_t size, int flags)
1753 +vfs_setxattr(struct dentry *dentry, struct vfsmount *mnt, char *name,
1754 + void *value, size_t size, int flags, struct file *file)
1756 struct inode *inode = dentry->d_inode;
1758 @@ -79,7 +79,7 @@ vfs_setxattr(struct dentry *dentry, char
1761 mutex_lock(&inode->i_mutex);
1762 - error = security_inode_setxattr(dentry, name, value, size, flags);
1763 + error = security_inode_setxattr(dentry, mnt, name, value, size, flags, file);
1766 error = -EOPNOTSUPP;
1767 @@ -87,7 +87,7 @@ vfs_setxattr(struct dentry *dentry, char
1768 error = inode->i_op->setxattr(dentry, name, value, size, flags);
1770 fsnotify_xattr(dentry);
1771 - security_inode_post_setxattr(dentry, name, value,
1772 + security_inode_post_setxattr(dentry, mnt, name, value,
1775 } else if (!strncmp(name, XATTR_SECURITY_PREFIX,
1776 @@ -132,7 +132,8 @@ out_noalloc:
1777 EXPORT_SYMBOL_GPL(xattr_getsecurity);
1780 -vfs_getxattr(struct dentry *dentry, char *name, void *value, size_t size)
1781 +vfs_getxattr(struct dentry *dentry, struct vfsmount *mnt, char *name,
1782 + void *value, size_t size, struct file *file)
1784 struct inode *inode = dentry->d_inode;
1786 @@ -141,7 +142,7 @@ vfs_getxattr(struct dentry *dentry, char
1790 - error = security_inode_getxattr(dentry, name);
1791 + error = security_inode_getxattr(dentry, mnt, name, file);
1795 @@ -168,18 +169,20 @@ nolsm:
1796 EXPORT_SYMBOL_GPL(vfs_getxattr);
1799 -vfs_listxattr(struct dentry *d, char *list, size_t size)
1800 +vfs_listxattr(struct dentry *dentry, struct vfsmount *mnt, char *list,
1801 + size_t size, struct file *file)
1803 + struct inode *inode = dentry->d_inode;
1806 - error = security_inode_listxattr(d);
1807 + error = security_inode_listxattr(dentry, mnt, file);
1810 error = -EOPNOTSUPP;
1811 - if (d->d_inode->i_op && d->d_inode->i_op->listxattr) {
1812 - error = d->d_inode->i_op->listxattr(d, list, size);
1814 - error = security_inode_listsecurity(d->d_inode, list, size);
1815 + if (inode->i_op && inode->i_op->listxattr)
1816 + error = inode->i_op->listxattr(dentry, list, size);
1818 + error = security_inode_listsecurity(inode, list, size);
1819 if (size && error > size)
1822 @@ -188,7 +191,8 @@ vfs_listxattr(struct dentry *d, char *li
1823 EXPORT_SYMBOL_GPL(vfs_listxattr);
1826 -vfs_removexattr(struct dentry *dentry, char *name)
1827 +vfs_removexattr(struct dentry *dentry, struct vfsmount *mnt, char *name,
1828 + struct file *file)
1830 struct inode *inode = dentry->d_inode;
1832 @@ -200,7 +204,7 @@ vfs_removexattr(struct dentry *dentry, c
1836 - error = security_inode_removexattr(dentry, name);
1837 + error = security_inode_removexattr(dentry, mnt, name, file);
1841 @@ -219,7 +223,7 @@ EXPORT_SYMBOL_GPL(vfs_removexattr);
1844 setxattr(struct dentry *d, char __user *name, void __user *value,
1845 - size_t size, int flags, struct vfsmount *mnt)
1846 + size_t size, int flags, struct vfsmount *mnt, struct file *file)
1849 void *kvalue = NULL;
1850 @@ -247,7 +251,7 @@ setxattr(struct dentry *d, char __user *
1854 - error = vfs_setxattr(d, kname, kvalue, size, flags);
1855 + error = vfs_setxattr(d, mnt, kname, kvalue, size, flags, file);
1859 @@ -262,7 +266,7 @@ sys_setxattr(char __user *path, char __u
1860 error = user_path_walk(path, &nd);
1863 - error = setxattr(nd.path.dentry, name, value, size, flags, nd.path.mnt);
1864 + error = setxattr(nd.path.dentry, name, value, size, flags, nd.path.mnt, NULL);
1868 @@ -277,7 +281,7 @@ sys_lsetxattr(char __user *path, char __
1869 error = user_path_walk_link(path, &nd);
1872 - error = setxattr(nd.path.dentry, name, value, size, flags, nd.path.mnt);
1873 + error = setxattr(nd.path.dentry, name, value, size, flags, nd.path.mnt, NULL);
1877 @@ -295,7 +299,7 @@ sys_fsetxattr(int fd, char __user *name,
1879 dentry = f->f_path.dentry;
1880 audit_inode(NULL, dentry);
1881 - error = setxattr(dentry, name, value, size, flags, f->f_vfsmnt);
1882 + error = setxattr(dentry, name, value, size, flags, f->f_vfsmnt, f);
1886 @@ -304,7 +308,8 @@ sys_fsetxattr(int fd, char __user *name,
1887 * Extended attribute GET operations
1890 -getxattr(struct dentry *d, char __user *name, void __user *value, size_t size)
1891 +getxattr(struct dentry *dentry, struct vfsmount *mnt, char __user *name,
1892 + void __user *value, size_t size, struct file *file)
1895 void *kvalue = NULL;
1896 @@ -324,7 +329,7 @@ getxattr(struct dentry *d, char __user *
1900 - error = vfs_getxattr(d, kname, kvalue, size);
1901 + error = vfs_getxattr(dentry, mnt, kname, kvalue, size, file);
1903 if (size && copy_to_user(value, kvalue, error))
1905 @@ -347,7 +352,7 @@ sys_getxattr(char __user *path, char __u
1906 error = user_path_walk(path, &nd);
1909 - error = getxattr(nd.path.dentry, name, value, size);
1910 + error = getxattr(nd.path.dentry, nd.path.mnt, name, value, size, NULL);
1914 @@ -362,7 +367,7 @@ sys_lgetxattr(char __user *path, char __
1915 error = user_path_walk_link(path, &nd);
1918 - error = getxattr(nd.path.dentry, name, value, size);
1919 + error = getxattr(nd.path.dentry, nd.path.mnt, name, value, size, NULL);
1923 @@ -377,7 +382,7 @@ sys_fgetxattr(int fd, char __user *name,
1926 audit_inode(NULL, f->f_path.dentry);
1927 - error = getxattr(f->f_path.dentry, name, value, size);
1928 + error = getxattr(f->f_path.dentry, f->f_path.mnt, name, value, size, f);
1932 @@ -386,7 +391,8 @@ sys_fgetxattr(int fd, char __user *name,
1933 * Extended attribute LIST operations
1936 -listxattr(struct dentry *d, char __user *list, size_t size)
1937 +listxattr(struct dentry *dentry, struct vfsmount *mnt, char __user *list,
1938 + size_t size, struct file *file)
1942 @@ -399,7 +405,7 @@ listxattr(struct dentry *d, char __user
1946 - error = vfs_listxattr(d, klist, size);
1947 + error = vfs_listxattr(dentry, mnt, klist, size, file);
1949 if (size && copy_to_user(list, klist, error))
1951 @@ -421,7 +427,7 @@ sys_listxattr(char __user *path, char __
1952 error = user_path_walk(path, &nd);
1955 - error = listxattr(nd.path.dentry, list, size);
1956 + error = listxattr(nd.path.dentry, nd.path.mnt, list, size, NULL);
1960 @@ -435,7 +441,7 @@ sys_llistxattr(char __user *path, char _
1961 error = user_path_walk_link(path, &nd);
1964 - error = listxattr(nd.path.dentry, list, size);
1965 + error = listxattr(nd.path.dentry, nd.path.mnt, list, size, NULL);
1969 @@ -450,7 +456,7 @@ sys_flistxattr(int fd, char __user *list
1972 audit_inode(NULL, f->f_path.dentry);
1973 - error = listxattr(f->f_path.dentry, list, size);
1974 + error = listxattr(f->f_path.dentry, f->f_path.mnt, list, size, f);
1978 @@ -459,7 +465,8 @@ sys_flistxattr(int fd, char __user *list
1979 * Extended attribute REMOVE operations
1982 -removexattr(struct dentry *d, char __user *name, struct vfsmount *mnt)
1983 +removexattr(struct dentry *dentry, char __user *name, struct vfsmount *mnt,
1984 + struct file *file)
1987 char kname[XATTR_NAME_MAX + 1];
1988 @@ -470,7 +477,7 @@ removexattr(struct dentry *d, char __use
1992 - return vfs_removexattr(d, kname);
1993 + return vfs_removexattr(dentry, mnt, kname, file);
1997 @@ -482,7 +489,7 @@ sys_removexattr(char __user *path, char
1998 error = user_path_walk(path, &nd);
2001 - error = removexattr(nd.path.dentry, name, nd.path.mnt);
2002 + error = removexattr(nd.path.dentry, name, nd.path.mnt, NULL);
2006 @@ -496,7 +503,7 @@ sys_lremovexattr(char __user *path, char
2007 error = user_path_walk_link(path, &nd);
2010 - error = removexattr(nd.path.dentry, name, nd.path.mnt);
2011 + error = removexattr(nd.path.dentry, name, nd.path.mnt, NULL);
2015 @@ -513,7 +520,7 @@ sys_fremovexattr(int fd, char __user *na
2017 dentry = f->f_path.dentry;
2018 audit_inode(NULL, dentry);
2019 - error = removexattr(dentry, name, f->f_vfsmnt);
2020 + error = removexattr(dentry, name, f->f_path.mnt, f);
2024 diff -uprN e/fs/xfs/linux-2.6/xfs_lrw.c f/fs/xfs/linux-2.6/xfs_lrw.c
2025 --- e/fs/xfs/linux-2.6/xfs_lrw.c 2008-04-17 02:49:44.000000000 +0000
2026 +++ f/fs/xfs/linux-2.6/xfs_lrw.c 2008-05-28 20:29:28.910241000 +0000
2027 @@ -716,7 +716,7 @@ start:
2028 !capable(CAP_FSETID)) {
2029 error = xfs_write_clear_setuid(xip);
2031 - error = -remove_suid(file->f_path.dentry);
2032 + error = -remove_suid(&file->f_path);
2033 if (unlikely(error)) {
2034 goto out_unlock_internal;
2036 diff -uprN e/include/linux/audit.h f/include/linux/audit.h
2037 --- e/include/linux/audit.h 2008-04-17 02:49:44.000000000 +0000
2038 +++ f/include/linux/audit.h 2008-05-28 20:29:29.410207000 +0000
2040 * 1200 - 1299 messages internal to the audit daemon
2041 * 1300 - 1399 audit event messages
2042 * 1400 - 1499 SE Linux use
2043 - * 1500 - 1599 kernel LSPP events
2044 + * 1500 - 1599 AppArmor use
2045 * 1600 - 1699 kernel crypto events
2046 * 1700 - 1799 kernel anomaly records
2047 * 1800 - 1999 future kernel use (maybe integrity labels and related events)
2048 @@ -119,6 +119,13 @@
2049 #define AUDIT_MAC_UNLBL_STCADD 1416 /* NetLabel: add a static label */
2050 #define AUDIT_MAC_UNLBL_STCDEL 1417 /* NetLabel: del a static label */
2052 +#define AUDIT_APPARMOR_AUDIT 1501 /* AppArmor audited grants */
2053 +#define AUDIT_APPARMOR_ALLOWED 1502 /* Allowed Access for learning */
2054 +#define AUDIT_APPARMOR_DENIED 1503
2055 +#define AUDIT_APPARMOR_HINT 1504 /* Process Tracking information */
2056 +#define AUDIT_APPARMOR_STATUS 1505 /* Changes in config */
2057 +#define AUDIT_APPARMOR_ERROR 1506 /* Internal AppArmor Errors */
2059 #define AUDIT_FIRST_KERN_ANOM_MSG 1700
2060 #define AUDIT_LAST_KERN_ANOM_MSG 1799
2061 #define AUDIT_ANOM_PROMISCUOUS 1700 /* Device changed promiscuous mode */
2062 @@ -518,6 +525,9 @@ extern void audit_log(struct audit_
2063 __attribute__((format(printf,4,5)));
2065 extern struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, int type);
2066 +extern void audit_log_vformat(struct audit_buffer *ab,
2067 + const char *fmt, va_list args)
2068 + __attribute__((format(printf,2,0)));
2069 extern void audit_log_format(struct audit_buffer *ab,
2070 const char *fmt, ...)
2071 __attribute__((format(printf,2,3)));
2072 diff -uprN e/include/linux/dcache.h f/include/linux/dcache.h
2073 --- e/include/linux/dcache.h 2008-04-17 02:49:44.000000000 +0000
2074 +++ f/include/linux/dcache.h 2008-05-28 20:29:29.410207000 +0000
2075 @@ -300,7 +300,8 @@ extern int d_validate(struct dentry *, s
2076 * helper function for dentry_operations.d_dname() members
2078 extern char *dynamic_dname(struct dentry *, char *, int, const char *, ...);
2080 +extern char *__d_path(struct dentry *, struct vfsmount *, struct path *,
2081 + char *, int, int, int);
2082 extern char *d_path(struct path *, char *, int);
2084 /* Allocation counts.. */
2085 diff -uprN e/include/linux/fs.h f/include/linux/fs.h
2086 --- e/include/linux/fs.h 2008-04-17 02:49:44.000000000 +0000
2087 +++ f/include/linux/fs.h 2008-05-28 20:29:29.410207000 +0000
2088 @@ -353,13 +353,6 @@ struct iattr {
2089 struct timespec ia_atime;
2090 struct timespec ia_mtime;
2091 struct timespec ia_ctime;
2094 - * Not an attribute, but an auxilary info for filesystems wanting to
2095 - * implement an ftruncate() like method. NOTE: filesystem should
2096 - * check for (ia_valid & ATTR_FILE), and not for (ia_file != NULL).
2098 - struct file *ia_file;
2102 @@ -1076,13 +1069,13 @@ extern void unlock_super(struct super_bl
2104 extern int vfs_permission(struct nameidata *, int);
2105 extern int vfs_create(struct inode *, struct dentry *, int, struct nameidata *);
2106 -extern int vfs_mkdir(struct inode *, struct dentry *, int, struct nameidata *);
2107 -extern int vfs_mknod(struct inode *, struct dentry *, int, dev_t, struct nameidata *);
2108 -extern int vfs_symlink(struct inode *, struct dentry *, const char *, int, struct nameidata *);
2109 -extern int vfs_link(struct dentry *, struct inode *, struct dentry *, struct nameidata *);
2110 -extern int vfs_rmdir(struct inode *, struct dentry *, struct nameidata *);
2111 -extern int vfs_unlink(struct inode *, struct dentry *, struct nameidata *);
2112 -extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
2113 +extern int vfs_mkdir(struct inode *, struct dentry *, struct vfsmount *, int, struct nameidata *);
2114 +extern int vfs_mknod(struct inode *, struct dentry *, struct vfsmount *, int, dev_t, struct nameidata *);
2115 +extern int vfs_symlink(struct inode *, struct dentry *, struct vfsmount *, const char *, int, struct nameidata *);
2116 +extern int vfs_link(struct dentry *, struct vfsmount *, struct inode *, struct dentry *, struct vfsmount *, struct nameidata *);
2117 +extern int vfs_rmdir(struct inode *, struct dentry *, struct nameidata *, struct vfsmount *);
2118 +extern int vfs_unlink(struct inode *, struct dentry *, struct nameidata *, struct vfsmount *);
2119 +extern int vfs_rename(struct inode *, struct dentry *, struct vfsmount *, struct inode *, struct dentry *, struct vfsmount *);
2122 * VFS dentry helper functions.
2123 @@ -1196,6 +1189,7 @@ struct file_operations {
2124 ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
2125 ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
2126 int (*setlease)(struct file *, long, struct file_lock **);
2127 + int (*fsetattr)(struct file *, struct iattr *);
2130 struct inode_operations {
2131 @@ -1559,8 +1553,8 @@ static inline int break_lease(struct ino
2135 -extern int do_truncate(struct dentry *, loff_t start, unsigned int time_attrs,
2136 - struct file *filp);
2137 +extern int do_truncate(struct dentry *, struct vfsmount *, loff_t start,
2138 + unsigned int time_attrs, struct file *filp);
2139 extern long do_sys_open(int dfd, const char __user *filename, int flags,
2141 extern struct file *filp_open(const char *, int, int);
2142 @@ -1714,7 +1708,8 @@ extern int do_remount_sb(struct super_bl
2144 extern sector_t bmap(struct inode *, sector_t);
2146 -extern int notify_change(struct dentry *, struct iattr *);
2147 +extern int notify_change(struct dentry *, struct vfsmount *, struct iattr *);
2148 +extern int fnotify_change(struct dentry *, struct vfsmount *, struct iattr *, struct file *);
2149 extern int permission(struct inode *, int, struct nameidata *);
2150 extern int generic_permission(struct inode *, int,
2151 int (*check_acl)(struct inode *, int));
2152 @@ -1776,9 +1771,9 @@ extern void iget_failed(struct inode *);
2153 extern void clear_inode(struct inode *);
2154 extern void destroy_inode(struct inode *);
2155 extern struct inode *new_inode(struct super_block *);
2156 -extern int __remove_suid(struct dentry *, int);
2157 +extern int __remove_suid(struct path *, int);
2158 extern int should_remove_suid(struct dentry *);
2159 -extern int remove_suid(struct dentry *);
2160 +extern int remove_suid(struct path *);
2162 extern void __insert_inode_hash(struct inode *, unsigned long hashval);
2163 extern void remove_inode_hash(struct inode *);
2164 diff -uprN e/include/linux/mount.h f/include/linux/mount.h
2165 --- e/include/linux/mount.h 2008-04-17 02:49:44.000000000 +0000
2166 +++ f/include/linux/mount.h 2008-05-28 20:29:29.410207000 +0000
2167 @@ -103,5 +103,7 @@ extern void mark_mounts_for_expiry(struc
2168 extern spinlock_t vfsmount_lock;
2169 extern dev_t name_to_dev_t(char *name);
2171 +extern char *d_namespace_path(struct dentry *, struct vfsmount *, char *, int);
2174 #endif /* _LINUX_MOUNT_H */
2175 diff -uprN e/include/linux/nfsd/nfsd.h f/include/linux/nfsd/nfsd.h
2176 --- e/include/linux/nfsd/nfsd.h 2008-04-17 02:49:44.000000000 +0000
2177 +++ f/include/linux/nfsd/nfsd.h 2008-05-28 20:29:28.910241000 +0000
2178 @@ -78,7 +78,8 @@ __be32 nfsd_setattr(struct svc_rqst *,
2179 #ifdef CONFIG_NFSD_V4
2180 __be32 nfsd4_set_nfs4_acl(struct svc_rqst *, struct svc_fh *,
2182 -int nfsd4_get_nfs4_acl(struct svc_rqst *, struct dentry *, struct nfs4_acl **);
2183 +int nfsd4_get_nfs4_acl(struct svc_rqst *, struct dentry *,
2184 + struct vfsmount *mnt, struct nfs4_acl **);
2185 #endif /* CONFIG_NFSD_V4 */
2186 __be32 nfsd_create(struct svc_rqst *, struct svc_fh *,
2187 char *name, int len, struct iattr *attrs,
2188 diff -uprN e/include/linux/security.h f/include/linux/security.h
2189 --- e/include/linux/security.h 2008-04-17 02:49:44.000000000 +0000
2190 +++ f/include/linux/security.h 2008-05-28 20:29:29.410207000 +0000
2191 @@ -51,8 +51,8 @@ extern void cap_capset_set (struct task_
2192 extern int cap_bprm_set_security (struct linux_binprm *bprm);
2193 extern void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe);
2194 extern int cap_bprm_secureexec(struct linux_binprm *bprm);
2195 -extern int cap_inode_setxattr(struct dentry *dentry, char *name, void *value, size_t size, int flags);
2196 -extern int cap_inode_removexattr(struct dentry *dentry, char *name);
2197 +extern int cap_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt, char *name, void *value, size_t size, int flags, struct file *file);
2198 +extern int cap_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt, char *name, struct file *file);
2199 extern int cap_inode_need_killpriv(struct dentry *dentry);
2200 extern int cap_inode_killpriv(struct dentry *dentry);
2201 extern int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid, int flags);
2202 @@ -330,23 +330,28 @@ static inline void security_free_mnt_opt
2203 * Check permission to create a regular file.
2204 * @dir contains inode structure of the parent of the new file.
2205 * @dentry contains the dentry structure for the file to be created.
2206 + * @mnt is the vfsmount corresponding to @dentry (may be NULL).
2207 * @mode contains the file mode of the file to be created.
2208 * Return 0 if permission is granted.
2210 * Check permission before creating a new hard link to a file.
2211 * @old_dentry contains the dentry structure for an existing link to the file.
2212 + * @old_mnt is the vfsmount corresponding to @old_dentry (may be NULL).
2213 * @dir contains the inode structure of the parent directory of the new link.
2214 * @new_dentry contains the dentry structure for the new link.
2215 + * @new_mnt is the vfsmount corresponding to @new_dentry (may be NULL).
2216 * Return 0 if permission is granted.
2218 * Check the permission to remove a hard link to a file.
2219 * @dir contains the inode structure of parent directory of the file.
2220 * @dentry contains the dentry structure for file to be unlinked.
2221 + * @mnt is the vfsmount corresponding to @dentry (may be NULL).
2222 * Return 0 if permission is granted.
2224 * Check the permission to create a symbolic link to a file.
2225 * @dir contains the inode structure of parent directory of the symbolic link.
2226 * @dentry contains the dentry structure of the symbolic link.
2227 + * @mnt is the vfsmount corresponding to @dentry (may be NULL).
2228 * @old_name contains the pathname of file.
2229 * Return 0 if permission is granted.
2231 @@ -354,12 +359,14 @@ static inline void security_free_mnt_opt
2232 * associated with inode strcture @dir.
2233 * @dir containst the inode structure of parent of the directory to be created.
2234 * @dentry contains the dentry structure of new directory.
2235 + * @mnt is the vfsmount corresponding to @dentry (may be NULL).
2236 * @mode contains the mode of new directory.
2237 * Return 0 if permission is granted.
2239 * Check the permission to remove a directory.
2240 * @dir contains the inode structure of parent of the directory to be removed.
2241 * @dentry contains the dentry structure of directory to be removed.
2242 + * @mnt is the vfsmount corresponding to @dentry (may be NULL).
2243 * Return 0 if permission is granted.
2245 * Check permissions when creating a special file (or a socket or a fifo
2246 @@ -368,6 +375,7 @@ static inline void security_free_mnt_opt
2247 * and not this hook.
2248 * @dir contains the inode structure of parent of the new file.
2249 * @dentry contains the dentry structure of the new file.
2250 + * @mnt is the vfsmount corresponding to @dentry (may be NULL).
2251 * @mode contains the mode of the new file.
2252 * @dev contains the device number.
2253 * Return 0 if permission is granted.
2254 @@ -375,12 +383,15 @@ static inline void security_free_mnt_opt
2255 * Check for permission to rename a file or directory.
2256 * @old_dir contains the inode structure for parent of the old link.
2257 * @old_dentry contains the dentry structure of the old link.
2258 + * @old_mnt is the vfsmount corresponding to @old_dentry (may be NULL).
2259 * @new_dir contains the inode structure for parent of the new link.
2260 * @new_dentry contains the dentry structure of the new link.
2261 + * @new_mnt is the vfsmount corresponding to @new_dentry (may be NULL).
2262 * Return 0 if permission is granted.
2264 * Check the permission to read the symbolic link.
2265 * @dentry contains the dentry structure for the file link.
2266 + * @mnt is the vfsmount corresponding to @dentry (may be NULL).
2267 * Return 0 if permission is granted.
2268 * @inode_follow_link:
2269 * Check permission to follow a symbolic link when looking up a pathname.
2270 @@ -404,6 +415,7 @@ static inline void security_free_mnt_opt
2271 * file attributes change (such as when a file is truncated, chown/chmod
2272 * operations, transferring disk quotas, etc).
2273 * @dentry contains the dentry structure for the file.
2274 + * @mnt is the vfsmount corresponding to @dentry (may be NULL).
2275 * @attr is the iattr structure containing the new file attributes.
2276 * Return 0 if permission is granted.
2278 @@ -419,18 +431,18 @@ static inline void security_free_mnt_opt
2281 * Check permission before setting the extended attributes
2282 - * @value identified by @name for @dentry.
2283 + * @value identified by @name for @dentry and @mnt.
2284 * Return 0 if permission is granted.
2285 * @inode_post_setxattr:
2286 * Update inode security field after successful setxattr operation.
2287 - * @value identified by @name for @dentry.
2288 + * @value identified by @name for @dentry and @mnt.
2290 * Check permission before obtaining the extended attributes
2291 - * identified by @name for @dentry.
2292 + * identified by @name for @dentry and @mnt.
2293 * Return 0 if permission is granted.
2295 * Check permission before obtaining the list of extended attribute
2296 - * names for @dentry.
2297 + * names for @dentry and @mnt.
2298 * Return 0 if permission is granted.
2299 * @inode_removexattr:
2300 * Check permission before removing the extended attribute
2301 @@ -1286,32 +1298,45 @@ struct security_operations {
2302 void (*inode_free_security) (struct inode *inode);
2303 int (*inode_init_security) (struct inode *inode, struct inode *dir,
2304 char **name, void **value, size_t *len);
2305 - int (*inode_create) (struct inode *dir,
2306 - struct dentry *dentry, int mode);
2307 - int (*inode_link) (struct dentry *old_dentry,
2308 - struct inode *dir, struct dentry *new_dentry);
2309 - int (*inode_unlink) (struct inode *dir, struct dentry *dentry);
2310 - int (*inode_symlink) (struct inode *dir,
2311 - struct dentry *dentry, const char *old_name);
2312 - int (*inode_mkdir) (struct inode *dir, struct dentry *dentry, int mode);
2313 - int (*inode_rmdir) (struct inode *dir, struct dentry *dentry);
2314 + int (*inode_create) (struct inode *dir, struct dentry *dentry,
2315 + struct vfsmount *mnt, int mode);
2316 + int (*inode_link) (struct dentry *old_dentry, struct vfsmount *old_mnt,
2317 + struct inode *dir, struct dentry *new_dentry,
2318 + struct vfsmount *new_mnt);
2319 + int (*inode_unlink) (struct inode *dir, struct dentry *dentry,
2320 + struct vfsmount *mnt);
2321 + int (*inode_symlink) (struct inode *dir, struct dentry *dentry,
2322 + struct vfsmount *mnt, const char *old_name);
2323 + int (*inode_mkdir) (struct inode *dir, struct dentry *dentry,
2324 + struct vfsmount *mnt, int mode);
2325 + int (*inode_rmdir) (struct inode *dir, struct dentry *dentry,
2326 + struct vfsmount *mnt);
2327 int (*inode_mknod) (struct inode *dir, struct dentry *dentry,
2328 - int mode, dev_t dev);
2329 + struct vfsmount *mnt, int mode, dev_t dev);
2330 int (*inode_rename) (struct inode *old_dir, struct dentry *old_dentry,
2331 - struct inode *new_dir, struct dentry *new_dentry);
2332 - int (*inode_readlink) (struct dentry *dentry);
2333 + struct vfsmount *old_mnt,
2334 + struct inode *new_dir, struct dentry *new_dentry,
2335 + struct vfsmount *new_mnt);
2336 + int (*inode_readlink) (struct dentry *dentry, struct vfsmount *mnt);
2337 int (*inode_follow_link) (struct dentry *dentry, struct nameidata *nd);
2338 int (*inode_permission) (struct inode *inode, int mask, struct nameidata *nd);
2339 - int (*inode_setattr) (struct dentry *dentry, struct iattr *attr);
2340 + int (*inode_setattr) (struct dentry *dentry, struct vfsmount *mnt,
2341 + struct iattr *attr);
2342 int (*inode_getattr) (struct vfsmount *mnt, struct dentry *dentry);
2343 void (*inode_delete) (struct inode *inode);
2344 - int (*inode_setxattr) (struct dentry *dentry, char *name, void *value,
2345 - size_t size, int flags);
2346 - void (*inode_post_setxattr) (struct dentry *dentry, char *name, void *value,
2347 + int (*inode_setxattr) (struct dentry *dentry, struct vfsmount *mnt,
2348 + char *name, void *value, size_t size, int flags,
2349 + struct file *file);
2350 + void (*inode_post_setxattr) (struct dentry *dentry,
2351 + struct vfsmount *mnt,
2352 + char *name, void *value,
2353 size_t size, int flags);
2354 - int (*inode_getxattr) (struct dentry *dentry, char *name);
2355 - int (*inode_listxattr) (struct dentry *dentry);
2356 - int (*inode_removexattr) (struct dentry *dentry, char *name);
2357 + int (*inode_getxattr) (struct dentry *dentry, struct vfsmount *mnt,
2358 + char *name, struct file *file);
2359 + int (*inode_listxattr) (struct dentry *dentry, struct vfsmount *mnt,
2360 + struct file *file);
2361 + int (*inode_removexattr) (struct dentry *dentry, struct vfsmount *mnt,
2362 + char *name, struct file *file);
2363 int (*inode_need_killpriv) (struct dentry *dentry);
2364 int (*inode_killpriv) (struct dentry *dentry);
2365 int (*inode_getsecurity)(const struct inode *inode, const char *name, void **buffer, bool alloc);
2366 @@ -1549,30 +1574,43 @@ int security_inode_alloc(struct inode *i
2367 void security_inode_free(struct inode *inode);
2368 int security_inode_init_security(struct inode *inode, struct inode *dir,
2369 char **name, void **value, size_t *len);
2370 -int security_inode_create(struct inode *dir, struct dentry *dentry, int mode);
2371 -int security_inode_link(struct dentry *old_dentry, struct inode *dir,
2372 - struct dentry *new_dentry);
2373 -int security_inode_unlink(struct inode *dir, struct dentry *dentry);
2374 +int security_inode_create(struct inode *dir, struct dentry *dentry,
2375 + struct vfsmount *mnt, int mode);
2376 +int security_inode_link(struct dentry *old_dentry, struct vfsmount *old_mnt,
2377 + struct inode *dir, struct dentry *new_dentry,
2378 + struct vfsmount *new_mnt);
2379 +int security_inode_unlink(struct inode *dir, struct dentry *dentry,
2380 + struct vfsmount *mnt);
2381 int security_inode_symlink(struct inode *dir, struct dentry *dentry,
2382 - const char *old_name);
2383 -int security_inode_mkdir(struct inode *dir, struct dentry *dentry, int mode);
2384 -int security_inode_rmdir(struct inode *dir, struct dentry *dentry);
2385 -int security_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev);
2386 + struct vfsmount *mnt, const char *old_name);
2387 +int security_inode_mkdir(struct inode *dir, struct dentry *dentry,
2388 + struct vfsmount *mnt, int mode);
2389 +int security_inode_rmdir(struct inode *dir, struct dentry *dentry,
2390 + struct vfsmount *mnt);
2391 +int security_inode_mknod(struct inode *dir, struct dentry *dentry,
2392 + struct vfsmount *mnt, int mode, dev_t dev);
2393 int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
2394 - struct inode *new_dir, struct dentry *new_dentry);
2395 -int security_inode_readlink(struct dentry *dentry);
2396 + struct vfsmount *old_mnt, struct inode *new_dir,
2397 + struct dentry *new_dentry, struct vfsmount *new_mnt);
2398 +int security_inode_readlink(struct dentry *dentry, struct vfsmount *mnt);
2399 int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd);
2400 int security_inode_permission(struct inode *inode, int mask, struct nameidata *nd);
2401 -int security_inode_setattr(struct dentry *dentry, struct iattr *attr);
2402 +int security_inode_setattr(struct dentry *dentry, struct vfsmount *mnt,
2403 + struct iattr *attr);
2404 int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry);
2405 void security_inode_delete(struct inode *inode);
2406 -int security_inode_setxattr(struct dentry *dentry, char *name,
2407 - void *value, size_t size, int flags);
2408 -void security_inode_post_setxattr(struct dentry *dentry, char *name,
2409 - void *value, size_t size, int flags);
2410 -int security_inode_getxattr(struct dentry *dentry, char *name);
2411 -int security_inode_listxattr(struct dentry *dentry);
2412 -int security_inode_removexattr(struct dentry *dentry, char *name);
2413 +int security_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
2414 + char *name, void *value, size_t size, int flags,
2415 + struct file *file);
2416 +void security_inode_post_setxattr(struct dentry *dentry, struct vfsmount *mnt,
2417 + char *name, void *value, size_t size,
2419 +int security_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
2420 + char *name, struct file *file);
2421 +int security_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt,
2422 + struct file *file);
2423 +int security_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
2424 + char *name, struct file *file);
2425 int security_inode_need_killpriv(struct dentry *dentry);
2426 int security_inode_killpriv(struct dentry *dentry);
2427 int security_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc);
2428 @@ -1887,26 +1925,31 @@ static inline int security_inode_init_se
2430 static inline int security_inode_create (struct inode *dir,
2431 struct dentry *dentry,
2432 + struct vfsmount *mnt,
2438 static inline int security_inode_link (struct dentry *old_dentry,
2439 + struct vfsmount *old_mnt,
2441 - struct dentry *new_dentry)
2442 + struct dentry *new_dentry,
2443 + struct vfsmount *new_mnt)
2448 static inline int security_inode_unlink (struct inode *dir,
2449 - struct dentry *dentry)
2450 + struct dentry *dentry,
2451 + struct vfsmount *mnt)
2456 static inline int security_inode_symlink (struct inode *dir,
2457 struct dentry *dentry,
2458 + struct vfsmount *mnt,
2459 const char *old_name)
2462 @@ -1914,19 +1957,22 @@ static inline int security_inode_symlink
2464 static inline int security_inode_mkdir (struct inode *dir,
2465 struct dentry *dentry,
2466 + struct vfsmount *mnt,
2472 static inline int security_inode_rmdir (struct inode *dir,
2473 - struct dentry *dentry)
2474 + struct dentry *dentry,
2475 + struct vfsmount *mnt)
2480 static inline int security_inode_mknod (struct inode *dir,
2481 struct dentry *dentry,
2482 + struct vfsmount *mnt,
2483 int mode, dev_t dev)
2486 @@ -1934,13 +1980,16 @@ static inline int security_inode_mknod (
2488 static inline int security_inode_rename (struct inode *old_dir,
2489 struct dentry *old_dentry,
2490 + struct vfsmount *old_mnt,
2491 struct inode *new_dir,
2492 - struct dentry *new_dentry)
2493 + struct dentry *new_dentry,
2494 + struct vfsmount *new_mnt)
2499 -static inline int security_inode_readlink (struct dentry *dentry)
2500 +static inline int security_inode_readlink(struct dentry *dentry,
2501 + struct vfsmount *mnt)
2505 @@ -1958,6 +2007,7 @@ static inline int security_inode_permiss
2508 static inline int security_inode_setattr (struct dentry *dentry,
2509 + struct vfsmount *mnt,
2513 @@ -1972,29 +2022,40 @@ static inline int security_inode_getattr
2514 static inline void security_inode_delete (struct inode *inode)
2517 -static inline int security_inode_setxattr (struct dentry *dentry, char *name,
2518 - void *value, size_t size, int flags)
2520 - return cap_inode_setxattr(dentry, name, value, size, flags);
2521 +static inline int security_inode_setxattr (struct dentry *dentry,
2522 + struct vfsmount *mnt, char *name,
2523 + void *value, size_t size, int flags,
2524 + struct file *file)
2526 + return cap_inode_setxattr(dentry, mnt, name, value, size, flags, file);
2529 -static inline void security_inode_post_setxattr (struct dentry *dentry, char *name,
2530 - void *value, size_t size, int flags)
2531 +static inline void security_inode_post_setxattr (struct dentry *dentry,
2532 + struct vfsmount *mnt,
2534 + void *value, size_t size,
2538 -static inline int security_inode_getxattr (struct dentry *dentry, char *name)
2539 +static inline int security_inode_getxattr (struct dentry *dentry,
2540 + struct vfsmount *mnt, char *name,
2541 + struct file *file)
2546 -static inline int security_inode_listxattr (struct dentry *dentry)
2547 +static inline int security_inode_listxattr (struct dentry *dentry,
2548 + struct vfsmount *mnt,
2549 + struct file *file)
2554 -static inline int security_inode_removexattr (struct dentry *dentry, char *name)
2555 +static inline int security_inode_removexattr (struct dentry *dentry,
2556 + struct vfsmount *mnt, char *name,
2557 + struct file *file)
2559 - return cap_inode_removexattr(dentry, name);
2560 + return cap_inode_removexattr(dentry, mnt, name, file);
2563 static inline int security_inode_need_killpriv(struct dentry *dentry)
2564 diff -uprN e/include/linux/sysctl.h f/include/linux/sysctl.h
2565 --- e/include/linux/sysctl.h 2008-04-17 02:49:44.000000000 +0000
2566 +++ f/include/linux/sysctl.h 2008-05-28 20:29:29.410207000 +0000
2567 @@ -977,6 +977,8 @@ extern int proc_doulongvec_minmax(struct
2568 extern int proc_doulongvec_ms_jiffies_minmax(struct ctl_table *table, int,
2569 struct file *, void __user *, size_t *, loff_t *);
2571 +extern char *sysctl_pathname(ctl_table *, char *, int);
2573 extern int do_sysctl (int __user *name, int nlen,
2574 void __user *oldval, size_t __user *oldlenp,
2575 void __user *newval, size_t newlen);
2576 diff -uprN e/include/linux/xattr.h f/include/linux/xattr.h
2577 --- e/include/linux/xattr.h 2008-04-17 02:49:44.000000000 +0000
2578 +++ f/include/linux/xattr.h 2008-05-28 20:29:29.410207000 +0000
2579 @@ -47,10 +47,13 @@ struct xattr_handler {
2582 ssize_t xattr_getsecurity(struct inode *, const char *, void *, size_t);
2583 -ssize_t vfs_getxattr(struct dentry *, char *, void *, size_t);
2584 -ssize_t vfs_listxattr(struct dentry *d, char *list, size_t size);
2585 -int vfs_setxattr(struct dentry *, char *, void *, size_t, int);
2586 -int vfs_removexattr(struct dentry *, char *);
2587 +ssize_t vfs_getxattr(struct dentry *, struct vfsmount *, char *, void *,
2588 + size_t, struct file *);
2589 +ssize_t vfs_listxattr(struct dentry *d, struct vfsmount *, char *list,
2590 + size_t size, struct file *);
2591 +int vfs_setxattr(struct dentry *, struct vfsmount *, char *, void *, size_t,
2592 + int, struct file *);
2593 +int vfs_removexattr(struct dentry *, struct vfsmount *, char *, struct file *);
2595 ssize_t generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size);
2596 ssize_t generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size);
2597 diff -uprN e/ipc/mqueue.c f/ipc/mqueue.c
2598 --- e/ipc/mqueue.c 2008-04-17 02:49:44.000000000 +0000
2599 +++ f/ipc/mqueue.c 2008-05-28 20:29:28.910241000 +0000
2600 @@ -743,7 +743,7 @@ asmlinkage long sys_mq_unlink(const char
2602 atomic_inc(&inode->i_count);
2604 - err = vfs_unlink(dentry->d_parent->d_inode, dentry, NULL);
2605 + err = vfs_unlink(dentry->d_parent->d_inode, dentry, NULL, mqueue_mnt);
2609 diff -uprN e/kernel/audit.c f/kernel/audit.c
2610 --- e/kernel/audit.c 2008-04-17 02:49:44.000000000 +0000
2611 +++ f/kernel/audit.c 2008-05-28 20:29:29.410207000 +0000
2612 @@ -1136,8 +1136,7 @@ static inline int audit_expand(struct au
2613 * will be called a second time. Currently, we assume that a printk
2614 * can't format message larger than 1024 bytes, so we don't either.
2616 -static void audit_log_vformat(struct audit_buffer *ab, const char *fmt,
2618 +void audit_log_vformat(struct audit_buffer *ab, const char *fmt, va_list args)
2621 struct sk_buff *skb;
2622 @@ -1407,3 +1406,6 @@ EXPORT_SYMBOL(audit_log_start);
2623 EXPORT_SYMBOL(audit_log_end);
2624 EXPORT_SYMBOL(audit_log_format);
2625 EXPORT_SYMBOL(audit_log);
2626 +EXPORT_SYMBOL_GPL(audit_log_vformat);
2627 +EXPORT_SYMBOL_GPL(audit_log_untrustedstring);
2628 +EXPORT_SYMBOL_GPL(audit_log_d_path);
2629 diff -uprN e/kernel/cgroup.c f/kernel/cgroup.c
2630 --- e/kernel/cgroup.c 2008-05-28 20:32:27.897940261 +0000
2631 +++ f/kernel/cgroup.c 2008-05-28 20:29:28.910241000 +0000
2632 @@ -2833,7 +2833,7 @@ int cgroup_clone(struct task_struct *tsk
2635 /* Create the cgroup directory, which also creates the cgroup */
2636 - ret = vfs_mkdir(inode, dentry, S_IFDIR | 0755, NULL);
2637 + ret = vfs_mkdir(inode, dentry, NULL, S_IFDIR | 0755, NULL);
2638 child = __d_cgrp(dentry);
2641 diff -uprN e/kernel/sysctl.c f/kernel/sysctl.c
2642 --- e/kernel/sysctl.c 2008-04-17 02:49:44.000000000 +0000
2643 +++ f/kernel/sysctl.c 2008-05-28 20:29:29.410207000 +0000
2644 @@ -1440,6 +1440,33 @@ void register_sysctl_root(struct ctl_tab
2645 spin_unlock(&sysctl_lock);
2648 +char *sysctl_pathname(struct ctl_table *table, char *buffer, int buflen)
2652 + buffer += --buflen;
2656 + int namelen = strlen(table->procname);
2658 + if (buflen < namelen + 1)
2660 + buflen -= namelen + 1;
2661 + buffer -= namelen;
2662 + memcpy(buffer, table->procname, namelen);
2664 + table = table->parent;
2669 + memcpy(buffer, "/sys", 4);
2673 +EXPORT_SYMBOL_GPL(sysctl_pathname);
2675 #ifdef CONFIG_SYSCTL_SYSCALL
2676 int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *oldlenp,
2677 void __user *newval, size_t newlen)
2678 diff -uprN e/mm/filemap.c f/mm/filemap.c
2679 --- e/mm/filemap.c 2008-04-17 02:49:44.000000000 +0000
2680 +++ f/mm/filemap.c 2008-05-28 20:29:28.910241000 +0000
2681 @@ -1653,26 +1653,26 @@ int should_remove_suid(struct dentry *de
2683 EXPORT_SYMBOL(should_remove_suid);
2685 -int __remove_suid(struct dentry *dentry, int kill)
2686 +int __remove_suid(struct path *path, int kill)
2688 struct iattr newattrs;
2690 newattrs.ia_valid = ATTR_FORCE | kill;
2691 - return notify_change(dentry, &newattrs);
2692 + return notify_change(path->dentry, path->mnt, &newattrs);
2695 -int remove_suid(struct dentry *dentry)
2696 +int remove_suid(struct path *path)
2698 - int killsuid = should_remove_suid(dentry);
2699 - int killpriv = security_inode_need_killpriv(dentry);
2700 + int killsuid = should_remove_suid(path->dentry);
2701 + int killpriv = security_inode_need_killpriv(path->dentry);
2707 - error = security_inode_killpriv(dentry);
2708 + error = security_inode_killpriv(path->dentry);
2709 if (!error && killsuid)
2710 - error = __remove_suid(dentry, killsuid);
2711 + error = __remove_suid(path, killsuid);
2715 @@ -2387,7 +2387,7 @@ __generic_file_aio_write_nolock(struct k
2719 - err = remove_suid(file->f_path.dentry);
2720 + err = remove_suid(&file->f_path);
2724 diff -uprN e/mm/filemap_xip.c f/mm/filemap_xip.c
2725 --- e/mm/filemap_xip.c 2008-04-17 02:49:44.000000000 +0000
2726 +++ f/mm/filemap_xip.c 2008-05-28 20:29:28.910241000 +0000
2727 @@ -380,7 +380,7 @@ xip_file_write(struct file *filp, const
2731 - ret = remove_suid(filp->f_path.dentry);
2732 + ret = remove_suid(&filp->f_path);
2736 diff -uprN e/mm/tiny-shmem.c f/mm/tiny-shmem.c
2737 --- e/mm/tiny-shmem.c 2008-04-17 02:49:44.000000000 +0000
2738 +++ f/mm/tiny-shmem.c 2008-05-28 20:29:28.910241000 +0000
2739 @@ -80,7 +80,7 @@ struct file *shmem_file_setup(char *name
2740 inode->i_nlink = 0; /* It is unlinked */
2742 /* notify everyone as to the change of file size */
2743 - error = do_truncate(dentry, size, 0, file);
2744 + error = do_truncate(dentry, file->f_path.mnt, size, 0, file);
2748 diff -uprN e/net/unix/af_unix.c f/net/unix/af_unix.c
2749 --- e/net/unix/af_unix.c 2008-04-17 02:49:44.000000000 +0000
2750 +++ f/net/unix/af_unix.c 2008-05-28 20:29:28.910241000 +0000
2751 @@ -819,7 +819,8 @@ static int unix_bind(struct socket *sock
2754 (SOCK_INODE(sock)->i_mode & ~current->fs->umask);
2755 - err = vfs_mknod(nd.path.dentry->d_inode, dentry, mode, 0, NULL);
2756 + err = vfs_mknod(nd.path.dentry->d_inode, dentry, nd.path.mnt,
2759 goto out_mknod_dput;
2760 mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
2761 diff -uprN e/security/Kconfig f/security/Kconfig
2762 --- e/security/Kconfig 2008-04-17 02:49:44.000000000 +0000
2763 +++ f/security/Kconfig 2008-05-28 20:29:29.410207000 +0000
2764 @@ -124,6 +124,7 @@ config SECURITY_DEFAULT_MMAP_MIN_ADDR
2766 source security/selinux/Kconfig
2767 source security/smack/Kconfig
2768 +source security/apparmor/Kconfig
2772 diff -uprN e/security/Makefile f/security/Makefile
2773 --- e/security/Makefile 2008-04-17 02:49:44.000000000 +0000
2774 +++ f/security/Makefile 2008-05-28 20:29:29.410207000 +0000
2775 @@ -16,5 +16,6 @@ obj-$(CONFIG_SECURITY) += security.o d
2776 # Must precede capability.o in order to stack properly.
2777 obj-$(CONFIG_SECURITY_SELINUX) += selinux/built-in.o
2778 obj-$(CONFIG_SECURITY_SMACK) += commoncap.o smack/built-in.o
2779 +obj-$(CONFIG_SECURITY_APPARMOR) += commoncap.o apparmor/
2780 obj-$(CONFIG_SECURITY_CAPABILITIES) += commoncap.o capability.o
2781 obj-$(CONFIG_SECURITY_ROOTPLUG) += commoncap.o root_plug.o
2782 diff -uprN e/security/apparmor/Kconfig f/security/apparmor/Kconfig
2783 --- e/security/apparmor/Kconfig 1970-01-01 00:00:00.000000000 +0000
2784 +++ f/security/apparmor/Kconfig 2008-05-28 20:29:29.410207000 +0000
2786 +config SECURITY_APPARMOR
2787 + bool "AppArmor support"
2788 + depends on SECURITY
2791 + This enables the AppArmor security module.
2792 + Required userspace tools (if they are not included in your
2793 + distribution) and further information may be found at
2794 + <http://forge.novell.com/modules/xfmod/project/?apparmor>
2796 + If you are unsure how to answer this question, answer N.
2798 +config SECURITY_APPARMOR_BOOTPARAM_VALUE
2799 + int "AppArmor boot parameter default value"
2800 + depends on SECURITY_APPARMOR
2804 + This option sets the default value for the kernel parameter
2805 + 'apparmor', which allows AppArmor to be enabled or disabled
2806 + at boot. If this option is set to 0 (zero), the AppArmor
2807 + kernel parameter will default to 0, disabling AppArmor at
2808 + bootup. If this option is set to 1 (one), the AppArmor
2809 + kernel parameter will default to 1, enabling AppArmor at
2812 + If you are unsure how to answer this question, answer 1.
2814 +config SECURITY_APPARMOR_DISABLE
2815 + bool "AppArmor runtime disable"
2816 + depends on SECURITY_APPARMOR
2819 + This option enables writing to a apparmorfs node 'disable', which
2820 + allows AppArmor to be disabled at runtime prior to the policy load.
2821 + AppArmor will then remain disabled until the next boot.
2822 + This option is similar to the apparmor.enabled=0 boot parameter,
2823 + but is to support runtime disabling of AppArmor, e.g. from
2824 + /sbin/init, for portability across platforms where boot
2825 + parameters are difficult to employ.
2827 + If you are unsure how to answer this question, answer N.
2828 diff -uprN e/security/apparmor/Makefile f/security/apparmor/Makefile
2829 --- e/security/apparmor/Makefile 1970-01-01 00:00:00.000000000 +0000
2830 +++ f/security/apparmor/Makefile 2008-05-28 20:29:29.410207000 +0000
2832 +# Makefile for AppArmor Linux Security Module
2834 +obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
2836 +apparmor-y := main.o list.o procattr.o lsm.o apparmorfs.o \
2837 + module_interface.o match.o
2839 +quiet_cmd_make-caps = GEN $@
2840 +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 > $@
2842 +quiet_cmd_make-af = GEN $@
2843 +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 > $@
2845 +$(obj)/main.o : $(obj)/capability_names.h $(obj)/af_names.h
2846 +$(obj)/capability_names.h : $(srctree)/include/linux/capability.h
2847 + $(call cmd,make-caps)
2848 +$(obj)/af_names.h : $(srctree)/include/linux/socket.h
2849 + $(call cmd,make-af)
2850 diff -uprN e/security/apparmor/apparmor.h f/security/apparmor/apparmor.h
2851 --- e/security/apparmor/apparmor.h 1970-01-01 00:00:00.000000000 +0000
2852 +++ f/security/apparmor/apparmor.h 2008-05-28 20:29:29.410207000 +0000
2855 + * Copyright (C) 1998-2007 Novell/SUSE
2857 + * This program is free software; you can redistribute it and/or
2858 + * modify it under the terms of the GNU General Public License as
2859 + * published by the Free Software Foundation, version 2 of the
2862 + * AppArmor internal prototypes
2865 +#ifndef __APPARMOR_H
2866 +#define __APPARMOR_H
2868 +#include <linux/sched.h>
2869 +#include <linux/fs.h>
2870 +#include <linux/binfmts.h>
2871 +#include <linux/rcupdate.h>
2872 +#include <linux/resource.h>
2873 +#include <linux/socket.h>
2874 +#include <net/sock.h>
2877 + * We use MAY_READ, MAY_WRITE, MAY_EXEC, MAY_APPEND and the following flags
2878 + * for profile permissions
2880 +#define AA_MAY_LINK 0x0010
2881 +#define AA_MAY_LOCK 0x0020
2882 +#define AA_EXEC_MMAP 0x0040
2883 +#define AA_MAY_MOUNT 0x0080 /* no direct audit mapping */
2884 +#define AA_EXEC_UNSAFE 0x0100
2885 +#define AA_EXEC_INHERIT 0x0200
2886 +#define AA_EXEC_MOD_0 0x0400
2887 +#define AA_EXEC_MOD_1 0x0800
2888 +#define AA_EXEC_MOD_2 0x1000
2889 +#define AA_EXEC_MOD_3 0x2000
2891 +#define AA_BASE_PERMS (MAY_READ | MAY_WRITE | MAY_EXEC | \
2892 + MAY_APPEND | AA_MAY_LINK | \
2893 + AA_MAY_LOCK | AA_EXEC_MMAP | \
2894 + AA_MAY_MOUNT | AA_EXEC_UNSAFE | \
2895 + AA_EXEC_INHERIT | AA_EXEC_MOD_0 | \
2896 + AA_EXEC_MOD_1 | AA_EXEC_MOD_2 | \
2899 +#define AA_EXEC_MODIFIERS (AA_EXEC_MOD_0 | AA_EXEC_MOD_1 | \
2900 + AA_EXEC_MOD_2 | AA_EXEC_MOD_3)
2902 +#define AA_EXEC_TYPE (AA_EXEC_UNSAFE | AA_EXEC_INHERIT | \
2903 + AA_EXEC_MODIFIERS)
2905 +#define AA_EXEC_UNCONFINED AA_EXEC_MOD_0
2906 +#define AA_EXEC_PROFILE AA_EXEC_MOD_1
2907 +#define AA_EXEC_CHILD (AA_EXEC_MOD_0 | AA_EXEC_MOD_1)
2908 +/* remaining exec modes are index into profile name table */
2909 +#define AA_EXEC_INDEX(mode) ((mode & AA_EXEC_MODIFIERS) >> 10)
2911 +#define AA_USER_SHIFT 0
2912 +#define AA_OTHER_SHIFT 14
2914 +#define AA_USER_PERMS (AA_BASE_PERMS << AA_USER_SHIFT)
2915 +#define AA_OTHER_PERMS (AA_BASE_PERMS << AA_OTHER_SHIFT)
2917 +#define AA_FILE_PERMS (AA_USER_PERMS | AA_OTHER_PERMS)
2919 +#define AA_LINK_BITS ((AA_MAY_LINK << AA_USER_SHIFT) | \
2920 + (AA_MAY_LINK << AA_OTHER_SHIFT))
2922 +#define AA_USER_EXEC (MAY_EXEC << AA_USER_SHIFT)
2923 +#define AA_OTHER_EXEC (MAY_EXEC << AA_OTHER_SHIFT)
2925 +#define AA_USER_EXEC_TYPE (AA_EXEC_TYPE << AA_USER_SHIFT)
2926 +#define AA_OTHER_EXEC_TYPE (AA_EXEC_TYPE << AA_OTHER_SHIFT)
2928 +#define AA_EXEC_BITS (AA_USER_EXEC | AA_OTHER_EXEC)
2930 +#define ALL_AA_EXEC_UNSAFE ((AA_EXEC_UNSAFE << AA_USER_SHIFT) | \
2931 + (AA_EXEC_UNSAFE << AA_OTHER_SHIFT))
2933 +#define ALL_AA_EXEC_TYPE (AA_USER_EXEC_TYPE | AA_OTHER_EXEC_TYPE)
2935 +/* overloaded permissions for link pairs */
2936 +#define AA_LINK_SUBSET_TEST 0x0020
2938 +#define AA_USER_PTRACE 0x10000000
2939 +#define AA_OTHER_PTRACE 0x20000000
2940 +#define AA_PTRACE_PERMS (AA_USER_PTRACE | AA_OTHER_PTRACE)
2942 +/* shared permissions that are not duplicated in user::other */
2943 +#define AA_CHANGE_HAT 0x40000000
2944 +#define AA_CHANGE_PROFILE 0x80000000
2946 +#define AA_SHARED_PERMS (AA_CHANGE_HAT | AA_CHANGE_PROFILE)
2948 +#define AA_VALID_PERM_MASK (AA_FILE_PERMS | AA_PTRACE_PERMS | \
2951 +/* audit bits for the second accept field */
2952 +#define AUDIT_FILE_MASK 0x1fc07f
2953 +#define AUDIT_QUIET_MASK(mask) ((mask >> 7) & AUDIT_FILE_MASK)
2954 +#define AA_VALID_PERM2_MASK 0x0fffffff
2956 +#define AA_SECURE_EXEC_NEEDED 1
2958 +/* Control parameters (0 or 1), settable thru module/boot flags or
2959 + * via /sys/kernel/security/apparmor/control */
2960 +extern int apparmor_complain;
2961 +extern int apparmor_debug;
2962 +extern int apparmor_audit;
2963 +extern int apparmor_logsyscall;
2964 +extern unsigned int apparmor_path_max;
2966 +#define PROFILE_COMPLAIN(_profile) \
2967 + (apparmor_complain == 1 || ((_profile) && (_profile)->flags.complain))
2969 +#define APPARMOR_COMPLAIN(_cxt) \
2970 + (apparmor_complain == 1 || \
2971 + ((_cxt) && (_cxt)->profile && (_cxt)->profile->flags.complain))
2973 +#define PROFILE_AUDIT(_profile) \
2974 + (apparmor_audit == 1 || ((_profile) && (_profile)->flags.audit))
2976 +#define APPARMOR_AUDIT(_cxt) \
2977 + (apparmor_audit == 1 || \
2978 + ((_cxt) && (_cxt)->profile && (_cxt)->profile->flags.audit))
2980 +#define PROFILE_IS_HAT(_profile) \
2981 + ((_profile) && (_profile)->flags.hat)
2984 + * DEBUG remains global (no per profile flag) since it is mostly used in sysctl
2985 + * which is not related to profile accesses.
2988 +#define AA_DEBUG(fmt, args...) \
2990 + if (apparmor_debug) \
2991 + printk(KERN_DEBUG "AppArmor: " fmt, ##args); \
2994 +#define AA_ERROR(fmt, args...) printk(KERN_ERR "AppArmor: " fmt, ##args)
2996 +/* struct aa_rlimit - rlimits settings for the profile
2997 + * @mask: which hard limits to set
2998 + * @limits: rlimit values that override task limits
3000 + * AppArmor rlimits are used to set confined task rlimits. Only the
3001 + * limits specified in @mask will be controlled by apparmor.
3004 + unsigned int mask;
3005 + struct rlimit limits[RLIM_NLIMITS];
3010 +/* struct aa_namespace - namespace for a set of profiles
3011 + * @name: the name of the namespace
3012 + * @list: list the namespace is on
3013 + * @profiles: list of profile in the namespace
3014 + * @profile_count: the number of profiles in the namespace
3015 + * @null_complain_profile: special profile used for learning in this namespace
3016 + * @count: reference count on the namespace
3017 + * @lock: lock for adding/removing profile to the namespace
3019 +struct aa_namespace {
3021 + struct list_head list;
3022 + struct list_head profiles;
3023 + int profile_count;
3024 + struct aa_profile *null_complain_profile;
3026 + struct kref count;
3030 +/* struct aa_profile - basic confinement data
3031 + * @name: the profiles name
3032 + * @list: list this profile is on
3033 + * @ns: namespace the profile is in
3034 + * @file_rules: dfa containing the profiles file rules
3035 + * @flags: flags controlling profile behavior
3036 + * @isstale: flag indicating if profile is stale
3037 + * @set_caps: capabilities that are being set
3038 + * @capabilities: capabilities mask
3039 + * @audit_caps: caps that are to be audited
3040 + * @quiet_caps: caps that should not be audited
3041 + * @capabilities: capabilities granted by the process
3042 + * @rlimits: rlimits for the profile
3043 + * @task_count: how many tasks the profile is attached to
3044 + * @count: reference count of the profile
3045 + * @task_contexts: list of tasks confined by profile
3046 + * @lock: lock for the task_contexts list
3047 + * @network_families: basic network permissions
3048 + * @audit_network: which network permissions to force audit
3049 + * @quiet_network: which network permissions to quiet rejects
3051 + * The AppArmor profile contains the basic confinement data. Each profile
3052 + * has a name, and all nonstale profile are in a profile namespace.
3054 + * The task_contexts list and the isstale flag are protected by the
3057 + * If a task context is moved between two profiles, we first need to grab
3058 + * both profile locks. lock_both_profiles() does that in a deadlock-safe
3061 +struct aa_profile {
3063 + struct list_head list;
3064 + struct aa_namespace *ns;
3066 + int exec_table_size;
3067 + char **exec_table;
3068 + struct aa_dfa *file_rules;
3076 + kernel_cap_t set_caps;
3077 + kernel_cap_t capabilities;
3078 + kernel_cap_t audit_caps;
3079 + kernel_cap_t quiet_caps;
3081 + struct aa_rlimit rlimits;
3082 + unsigned int task_count;
3084 + struct kref count;
3085 + struct list_head task_contexts;
3087 + unsigned long int_flags;
3088 + u16 network_families[AF_MAX];
3089 + u16 audit_network[AF_MAX];
3090 + u16 quiet_network[AF_MAX];
3093 +extern struct list_head profile_ns_list;
3094 +extern rwlock_t profile_ns_list_lock;
3095 +extern struct mutex aa_interface_lock;
3098 + * struct aa_task_context - primary label for confined tasks
3099 + * @profile: the current profile
3100 + * @previous_profile: profile the task may return to
3101 + * @cookie: magic value the task must know for returning to @previous_profile
3102 + * @list: list this aa_task_context is on
3103 + * @task: task that the aa_task_context confines
3104 + * @rcu: rcu head used when freeing the aa_task_context
3105 + * @caps_logged: caps that have previously generated log entries
3107 + * Contains the task's current profile (which could change due to
3108 + * change_hat). Plus the hat_magic needed during change_hat.
3110 +struct aa_task_context {
3111 + struct aa_profile *profile;
3112 + struct aa_profile *previous_profile;
3114 + struct list_head list;
3115 + struct task_struct *task;
3116 + struct rcu_head rcu;
3117 + kernel_cap_t caps_logged;
3120 +extern struct aa_namespace *default_namespace;
3122 +/* aa_audit - AppArmor auditing structure
3123 + * Structure is populated by access control code and passed to aa_audit which
3124 + * provides for a single point of logging.
3128 + const char *operation;
3132 + const char *name2;
3133 + const char *name3;
3134 + int request_mask, denied_mask, audit_mask;
3136 + struct iattr *iattr;
3137 + pid_t task, parent;
3138 + int family, type, protocol;
3142 +/* Flags for the permission check functions */
3143 +#define AA_CHECK_FD 1 /* coming from a file descriptor */
3144 +#define AA_CHECK_DIR 2 /* file type is directory */
3146 +/* lock subtypes so lockdep does not raise false dependencies */
3147 +enum aa_lock_class {
3150 + aa_lock_task_release
3154 +extern int alloc_default_namespace(void);
3155 +extern void free_default_namespace(void);
3156 +extern int aa_audit_message(struct aa_profile *profile, struct aa_audit *sa,
3158 +void aa_audit_hint(struct aa_profile *profile, struct aa_audit *sa);
3159 +void aa_audit_status(struct aa_profile *profile, struct aa_audit *sa);
3160 +int aa_audit_reject(struct aa_profile *profile, struct aa_audit *sa);
3161 +extern int aa_audit_syscallreject(struct aa_profile *profile, gfp_t gfp,
3163 +extern int aa_audit(struct aa_profile *profile, struct aa_audit *);
3165 +extern int aa_attr(struct aa_profile *profile, struct dentry *dentry,
3166 + struct vfsmount *mnt, struct iattr *iattr);
3167 +extern int aa_perm_xattr(struct aa_profile *profile, const char *operation,
3168 + struct dentry *dentry, struct vfsmount *mnt,
3169 + int mask, int check);
3170 +extern int aa_capability(struct aa_task_context *cxt, int cap);
3171 +extern int aa_perm(struct aa_profile *profile, const char *operation,
3172 + struct dentry *dentry, struct vfsmount *mnt, int mask,
3174 +extern int aa_perm_dir(struct aa_profile *profile, const char *operation,
3175 + struct dentry *dentry, struct vfsmount *mnt,
3177 +extern int aa_perm_path(struct aa_profile *, const char *operation,
3178 + const char *name, int mask, uid_t uid);
3179 +extern int aa_link(struct aa_profile *profile,
3180 + struct dentry *link, struct vfsmount *link_mnt,
3181 + struct dentry *target, struct vfsmount *target_mnt);
3182 +extern int aa_clone(struct task_struct *task);
3183 +extern int aa_register(struct linux_binprm *bprm);
3184 +extern void aa_release(struct task_struct *task);
3185 +extern int aa_change_hat(const char *id, u64 hat_magic);
3186 +extern int aa_change_profile(const char *ns_name, const char *name);
3187 +extern struct aa_profile *__aa_replace_profile(struct task_struct *task,
3188 + struct aa_profile *profile);
3189 +extern struct aa_task_context *lock_task_and_profiles(struct task_struct *task,
3190 + struct aa_profile *profile);
3191 +extern void unlock_task_and_profiles(struct task_struct *task,
3192 + struct aa_task_context *cxt,
3193 + struct aa_profile *profile);
3194 +extern void aa_change_task_context(struct task_struct *task,
3195 + struct aa_task_context *new_cxt,
3196 + struct aa_profile *profile, u64 cookie,
3197 + struct aa_profile *previous_profile);
3198 +extern int aa_may_ptrace(struct aa_task_context *cxt,
3199 + struct aa_profile *tracee);
3200 +extern int aa_net_perm(struct aa_profile *profile, char *operation,
3201 + int family, int type, int protocol);
3202 +extern int aa_revalidate_sk(struct sock *sk, char *operation);
3203 +extern int aa_task_setrlimit(struct aa_profile *profile, unsigned int resource,
3204 + struct rlimit *new_rlim);
3205 +extern void aa_set_rlimits(struct task_struct *task, struct aa_profile *profile);
3209 +extern int apparmor_initialized;
3210 +extern void info_message(const char *str, const char *name);
3211 +extern void apparmor_disable(void);
3214 +extern struct aa_namespace *__aa_find_namespace(const char *name,
3215 + struct list_head *list);
3216 +extern struct aa_profile *__aa_find_profile(const char *name,
3217 + struct list_head *list);
3218 +extern void aa_profile_ns_list_release(void);
3220 +/* module_interface.c */
3221 +extern ssize_t aa_add_profile(void *, size_t);
3222 +extern ssize_t aa_replace_profile(void *, size_t);
3223 +extern ssize_t aa_remove_profile(char *, size_t);
3224 +extern struct aa_namespace *alloc_aa_namespace(char *name);
3225 +extern void free_aa_namespace(struct aa_namespace *ns);
3226 +extern void free_aa_namespace_kref(struct kref *kref);
3227 +extern struct aa_profile *alloc_aa_profile(void);
3228 +extern void free_aa_profile(struct aa_profile *profile);
3229 +extern void free_aa_profile_kref(struct kref *kref);
3230 +extern void aa_unconfine_tasks(struct aa_profile *profile);
3233 +extern int aa_getprocattr(struct aa_profile *profile, char **string,
3235 +extern int aa_setprocattr_changehat(char *args);
3236 +extern int aa_setprocattr_changeprofile(char *args);
3237 +extern int aa_setprocattr_setprofile(struct task_struct *task, char *args);
3240 +extern int create_apparmorfs(void);
3241 +extern void destroy_apparmorfs(void);
3244 +extern struct aa_dfa *aa_match_alloc(void);
3245 +extern void aa_match_free(struct aa_dfa *dfa);
3246 +extern int unpack_dfa(struct aa_dfa *dfa, void *blob, size_t size);
3247 +extern int verify_dfa(struct aa_dfa *dfa);
3248 +extern unsigned int aa_dfa_match(struct aa_dfa *dfa, const char *str, int *);
3249 +extern unsigned int aa_dfa_next_state(struct aa_dfa *dfa, unsigned int start,
3251 +extern unsigned int aa_match_state(struct aa_dfa *dfa, unsigned int start,
3252 + const char *str, unsigned int *final);
3253 +extern unsigned int aa_dfa_null_transition(struct aa_dfa *dfa,
3254 + unsigned int start);
3256 +#endif /* __APPARMOR_H */
3257 diff -uprN e/security/apparmor/apparmorfs.c f/security/apparmor/apparmorfs.c
3258 --- e/security/apparmor/apparmorfs.c 1970-01-01 00:00:00.000000000 +0000
3259 +++ f/security/apparmor/apparmorfs.c 2008-05-28 20:29:29.410207000 +0000
3262 + * Copyright (C) 1998-2007 Novell/SUSE
3264 + * This program is free software; you can redistribute it and/or
3265 + * modify it under the terms of the GNU General Public License as
3266 + * published by the Free Software Foundation, version 2 of the
3268 + * AppArmor filesystem (part of securityfs)
3271 +#include <linux/security.h>
3272 +#include <linux/vmalloc.h>
3273 +#include <linux/module.h>
3274 +#include <linux/seq_file.h>
3275 +#include <asm/uaccess.h>
3277 +#include "apparmor.h"
3278 +#include "inline.h"
3280 +static char *aa_simple_write_to_buffer(const char __user *userbuf,
3281 + size_t alloc_size, size_t copy_size,
3282 + loff_t *pos, const char *operation)
3284 + struct aa_profile *profile;
3288 + /* only writes from pos 0, that is complete writes */
3289 + data = ERR_PTR(-ESPIPE);
3294 + * Don't allow confined processes to load/replace/remove profiles.
3295 + * No sane person would add rules allowing this to a profile
3296 + * but we enforce the restriction anyways.
3298 + profile = aa_get_profile(current);
3300 + struct aa_audit sa;
3301 + memset(&sa, 0, sizeof(sa));
3302 + sa.operation = operation;
3303 + sa.gfp_mask = GFP_KERNEL;
3304 + sa.error_code = -EACCES;
3305 + data = ERR_PTR(aa_audit_reject(profile, &sa));
3306 + aa_put_profile(profile);
3310 + data = vmalloc(alloc_size);
3311 + if (data == NULL) {
3312 + data = ERR_PTR(-ENOMEM);
3316 + if (copy_from_user(data, userbuf, copy_size)) {
3318 + data = ERR_PTR(-EFAULT);
3326 +/* apparmor/profiles */
3327 +extern struct seq_operations apparmorfs_profiles_op;
3329 +static int aa_profiles_open(struct inode *inode, struct file *file)
3331 + return seq_open(file, &apparmorfs_profiles_op);
3335 +static int aa_profiles_release(struct inode *inode, struct file *file)
3337 + return seq_release(inode, file);
3340 +static struct file_operations apparmorfs_profiles_fops = {
3341 + .open = aa_profiles_open,
3343 + .llseek = seq_lseek,
3344 + .release = aa_profiles_release,
3347 +/* apparmor/matching */
3348 +static ssize_t aa_matching_read(struct file *file, char __user *buf,
3349 + size_t size, loff_t *ppos)
3351 + const char *matching = "pattern=aadfa audit perms=rwxamlk/ user::other";
3353 + return simple_read_from_buffer(buf, size, ppos, matching,
3354 + strlen(matching));
3357 +static struct file_operations apparmorfs_matching_fops = {
3358 + .read = aa_matching_read,
3361 +/* apparmor/features */
3362 +static ssize_t aa_features_read(struct file *file, char __user *buf,
3363 + size_t size, loff_t *ppos)
3365 + const char *features = "file=3.0 capability=2.0 network=1.0 "
3366 + "change_hat=1.4 change_profile=1.0 "
3367 + "aanamespaces=1.0 rlimit=1.0";
3369 + return simple_read_from_buffer(buf, size, ppos, features,
3370 + strlen(features));
3373 +static struct file_operations apparmorfs_features_fops = {
3374 + .read = aa_features_read,
3377 +/* apparmor/.load */
3378 +static ssize_t aa_profile_load(struct file *f, const char __user *buf,
3379 + size_t size, loff_t *pos)
3384 + data = aa_simple_write_to_buffer(buf, size, size, pos, "profile_load");
3386 + error = PTR_ERR(data);
3387 + if (!IS_ERR(data)) {
3388 + error = aa_add_profile(data, size);
3396 +static struct file_operations apparmorfs_profile_load = {
3397 + .write = aa_profile_load
3400 +/* apparmor/.replace */
3401 +static ssize_t aa_profile_replace(struct file *f, const char __user *buf,
3402 + size_t size, loff_t *pos)
3407 + data = aa_simple_write_to_buffer(buf, size, size, pos,
3408 + "profile_replace");
3410 + error = PTR_ERR(data);
3411 + if (!IS_ERR(data)) {
3412 + error = aa_replace_profile(data, size);
3420 +static struct file_operations apparmorfs_profile_replace = {
3421 + .write = aa_profile_replace
3424 +/* apparmor/.remove */
3425 +static ssize_t aa_profile_remove(struct file *f, const char __user *buf,
3426 + size_t size, loff_t *pos)
3432 + * aa_remove_profile needs a null terminated string so 1 extra
3433 + * byte is allocated and the copied data is null terminated.
3435 + data = aa_simple_write_to_buffer(buf, size + 1, size, pos,
3436 + "profile_remove");
3438 + error = PTR_ERR(data);
3439 + if (!IS_ERR(data)) {
3441 + error = aa_remove_profile(data, size);
3448 +static struct file_operations apparmorfs_profile_remove = {
3449 + .write = aa_profile_remove
3452 +static struct dentry *apparmor_dentry;
3454 +static void aafs_remove(const char *name)
3456 + struct dentry *dentry;
3458 + dentry = lookup_one_len(name, apparmor_dentry, strlen(name));
3459 + if (!IS_ERR(dentry)) {
3460 + securityfs_remove(dentry);
3465 +static int aafs_create(const char *name, int mask, struct file_operations *fops)
3467 + struct dentry *dentry;
3469 + dentry = securityfs_create_file(name, S_IFREG | mask, apparmor_dentry,
3472 + return IS_ERR(dentry) ? PTR_ERR(dentry) : 0;
3475 +void destroy_apparmorfs(void)
3477 + if (apparmor_dentry) {
3478 + aafs_remove(".remove");
3479 + aafs_remove(".replace");
3480 + aafs_remove(".load");
3481 + aafs_remove("matching");
3482 + aafs_remove("features");
3483 + aafs_remove("profiles");
3484 + securityfs_remove(apparmor_dentry);
3485 + apparmor_dentry = NULL;
3489 +int create_apparmorfs(void)
3493 + if (!apparmor_initialized)
3496 + if (apparmor_dentry) {
3497 + AA_ERROR("%s: AppArmor securityfs already exists\n",
3502 + apparmor_dentry = securityfs_create_dir("apparmor", NULL);
3503 + if (IS_ERR(apparmor_dentry)) {
3504 + error = PTR_ERR(apparmor_dentry);
3505 + apparmor_dentry = NULL;
3508 + error = aafs_create("profiles", 0440, &apparmorfs_profiles_fops);
3511 + error = aafs_create("matching", 0444, &apparmorfs_matching_fops);
3514 + error = aafs_create("features", 0444, &apparmorfs_features_fops);
3517 + error = aafs_create(".load", 0640, &apparmorfs_profile_load);
3520 + error = aafs_create(".replace", 0640, &apparmorfs_profile_replace);
3523 + error = aafs_create(".remove", 0640, &apparmorfs_profile_remove);
3527 + /* Report that AppArmor fs is enabled */
3528 + info_message("AppArmor Filesystem Enabled", "");
3532 + destroy_apparmorfs();
3533 + AA_ERROR("Error creating AppArmor securityfs\n");
3534 + apparmor_disable();
3538 +fs_initcall(create_apparmorfs);
3540 diff -uprN e/security/apparmor/inline.h f/security/apparmor/inline.h
3541 --- e/security/apparmor/inline.h 1970-01-01 00:00:00.000000000 +0000
3542 +++ f/security/apparmor/inline.h 2008-05-28 20:29:29.410207000 +0000
3545 + * Copyright (C) 1998-2007 Novell/SUSE
3547 + * This program is free software; you can redistribute it and/or
3548 + * modify it under the terms of the GNU General Public License as
3549 + * published by the Free Software Foundation, version 2 of the
3556 +#include <linux/sched.h>
3560 +static inline int mediated_filesystem(struct inode *inode)
3562 + return !(inode->i_sb->s_flags & MS_NOUSER);
3565 +static inline struct aa_task_context *aa_task_context(struct task_struct *task)
3567 + return (struct aa_task_context *) rcu_dereference(task->security);
3570 +static inline struct aa_namespace *aa_get_namespace(struct aa_namespace *ns)
3573 + kref_get(&(ns->count));
3578 +static inline void aa_put_namespace(struct aa_namespace *ns)
3581 + kref_put(&ns->count, free_aa_namespace_kref);
3585 +static inline struct aa_namespace *aa_find_namespace(const char *name)
3587 + struct aa_namespace *ns = NULL;
3589 + read_lock(&profile_ns_list_lock);
3590 + ns = aa_get_namespace(__aa_find_namespace(name, &profile_ns_list));
3591 + read_unlock(&profile_ns_list_lock);
3597 + * aa_dup_profile - increment refcount on profile @p
3600 +static inline struct aa_profile *aa_dup_profile(struct aa_profile *p)
3603 + kref_get(&(p->count));
3609 + * aa_put_profile - decrement refcount on profile @p
3612 +static inline void aa_put_profile(struct aa_profile *p)
3615 + kref_put(&p->count, free_aa_profile_kref);
3618 +static inline struct aa_profile *aa_get_profile(struct task_struct *task)
3620 + struct aa_task_context *cxt;
3621 + struct aa_profile *profile = NULL;
3624 + cxt = aa_task_context(task);
3626 + profile = cxt->profile;
3627 + aa_dup_profile(profile);
3629 + rcu_read_unlock();
3634 +static inline struct aa_profile *aa_find_profile(struct aa_namespace *ns,
3637 + struct aa_profile *profile = NULL;
3639 + read_lock(&ns->lock);
3640 + profile = aa_dup_profile(__aa_find_profile(name, &ns->profiles));
3641 + read_unlock(&ns->lock);
3646 +static inline struct aa_task_context *aa_alloc_task_context(gfp_t flags)
3648 + struct aa_task_context *cxt;
3650 + cxt = kzalloc(sizeof(*cxt), flags);
3652 + INIT_LIST_HEAD(&cxt->list);
3653 + INIT_RCU_HEAD(&cxt->rcu);
3659 +static inline void aa_free_task_context(struct aa_task_context *cxt)
3662 + aa_put_profile(cxt->profile);
3663 + aa_put_profile(cxt->previous_profile);
3669 + * lock_profile - lock a profile
3670 + * @profile: the profile to lock
3672 + * While the profile is locked, local interrupts are disabled. This also
3673 + * gives us RCU reader safety.
3675 +static inline void lock_profile_nested(struct aa_profile *profile,
3676 + enum aa_lock_class lock_class)
3679 + * Lock the profile.
3681 + * Need to disable interrupts here because this lock is used in
3682 + * the task_free_security hook, which may run in RCU context.
3685 + spin_lock_irqsave_nested(&profile->lock, profile->int_flags,
3689 +static inline void lock_profile(struct aa_profile *profile)
3691 + lock_profile_nested(profile, aa_lock_normal);
3695 + * unlock_profile - unlock a profile
3696 + * @profile: the profile to unlock
3698 +static inline void unlock_profile(struct aa_profile *profile)
3700 + /* Unlock the profile. */
3702 + spin_unlock_irqrestore(&profile->lock, profile->int_flags);
3706 + * lock_both_profiles - lock two profiles in a deadlock-free way
3707 + * @profile1: profile to lock (may be NULL)
3708 + * @profile2: profile to lock (may be NULL)
3710 + * The order in which profiles are passed into lock_both_profiles() /
3711 + * unlock_both_profiles() does not matter.
3712 + * While the profile is locked, local interrupts are disabled. This also
3713 + * gives us RCU reader safety.
3715 +static inline void lock_both_profiles(struct aa_profile *profile1,
3716 + struct aa_profile *profile2)
3719 + * Lock the two profiles.
3721 + * We need to disable interrupts because the profile locks are
3722 + * used in the task_free_security hook, which may run in RCU
3725 + * Do not nest spin_lock_irqsave()/spin_unlock_irqresore():
3726 + * interrupts only need to be turned off once.
3728 + if (!profile1 || profile1 == profile2) {
3730 + spin_lock_irqsave_nested(&profile2->lock,
3731 + profile2->int_flags,
3733 + } else if (profile1 > profile2) {
3734 + /* profile1 cannot be NULL here. */
3735 + spin_lock_irqsave_nested(&profile1->lock, profile1->int_flags,
3738 + spin_lock_nested(&profile2->lock, aa_lock_nested);
3741 + /* profile2 cannot be NULL here. */
3742 + spin_lock_irqsave_nested(&profile2->lock, profile2->int_flags,
3744 + spin_lock_nested(&profile1->lock, aa_lock_nested);
3749 + * unlock_both_profiles - unlock two profiles in a deadlock-free way
3750 + * @profile1: profile to unlock (may be NULL)
3751 + * @profile2: profile to unlock (may be NULL)
3753 + * The order in which profiles are passed into lock_both_profiles() /
3754 + * unlock_both_profiles() does not matter.
3755 + * While the profile is locked, local interrupts are disabled. This also
3756 + * gives us RCU reader safety.
3758 +static inline void unlock_both_profiles(struct aa_profile *profile1,
3759 + struct aa_profile *profile2)
3761 + /* Unlock the two profiles. */
3762 + if (!profile1 || profile1 == profile2) {
3764 + spin_unlock_irqrestore(&profile2->lock,
3765 + profile2->int_flags);
3766 + } else if (profile1 > profile2) {
3767 + /* profile1 cannot be NULL here. */
3769 + spin_unlock(&profile2->lock);
3770 + spin_unlock_irqrestore(&profile1->lock, profile1->int_flags);
3772 + /* profile2 cannot be NULL here. */
3773 + spin_unlock(&profile1->lock);
3774 + spin_unlock_irqrestore(&profile2->lock, profile2->int_flags);
3778 +static inline unsigned int aa_match(struct aa_dfa *dfa, const char *pathname,
3782 + return aa_dfa_match(dfa, pathname, audit_mask);
3788 +static inline int dfa_audit_mask(struct aa_dfa *dfa, unsigned int state)
3790 + return ACCEPT_TABLE2(dfa)[state];
3793 +#endif /* __INLINE_H__ */
3794 diff -uprN e/security/apparmor/list.c f/security/apparmor/list.c
3795 --- e/security/apparmor/list.c 1970-01-01 00:00:00.000000000 +0000
3796 +++ f/security/apparmor/list.c 2008-05-28 20:29:29.410207000 +0000
3799 + * Copyright (C) 1998-2007 Novell/SUSE
3801 + * This program is free software; you can redistribute it and/or
3802 + * modify it under the terms of the GNU General Public License as
3803 + * published by the Free Software Foundation, version 2 of the
3806 + * AppArmor Profile List Management
3809 +#include <linux/seq_file.h>
3810 +#include "apparmor.h"
3811 +#include "inline.h"
3813 +/* list of profile namespaces and lock */
3814 +LIST_HEAD(profile_ns_list);
3815 +rwlock_t profile_ns_list_lock = RW_LOCK_UNLOCKED;
3818 + * __aa_find_namespace - look up a profile namespace on the namespace list
3819 + * @name: name of namespace to find
3820 + * @head: list to search
3822 + * Returns a pointer to the namespace on the list, or NULL if no namespace
3823 + * called @name exists. The caller must hold the profile_ns_list_lock.
3825 +struct aa_namespace *__aa_find_namespace(const char *name,
3826 + struct list_head *head)
3828 + struct aa_namespace *ns;
3830 + list_for_each_entry(ns, head, list) {
3831 + if (!strcmp(ns->name, name))
3839 + * __aa_find_profile - look up a profile on the profile list
3840 + * @name: name of profile to find
3841 + * @head: list to search
3843 + * Returns a pointer to the profile on the list, or NULL if no profile
3844 + * called @name exists. The caller must hold the profile_list_lock.
3846 +struct aa_profile *__aa_find_profile(const char *name, struct list_head *head)
3848 + struct aa_profile *profile;
3850 + list_for_each_entry(profile, head, list) {
3851 + if (!strcmp(profile->name, name))
3858 +static void aa_profile_list_release(struct list_head *head)
3860 + struct aa_profile *profile, *tmp;
3861 + list_for_each_entry_safe(profile, tmp, head, list) {
3862 + /* Remove the profile from each task context it is on. */
3863 + lock_profile(profile);
3864 + profile->isstale = 1;
3865 + aa_unconfine_tasks(profile);
3866 + list_del_init(&profile->list);
3867 + unlock_profile(profile);
3868 + aa_put_profile(profile);
3873 + * aa_profilelist_release - Remove all profiles from profile_list
3875 +void aa_profile_ns_list_release(void)
3877 + struct aa_namespace *ns, *tmp;
3879 + /* Remove and release all the profiles on namespace profile lists. */
3880 + write_lock(&profile_ns_list_lock);
3881 + list_for_each_entry_safe(ns, tmp, &profile_ns_list, list) {
3882 + write_lock(&ns->lock);
3883 + aa_profile_list_release(&ns->profiles);
3884 + list_del_init(&ns->list);
3885 + write_unlock(&ns->lock);
3886 + aa_put_namespace(ns);
3888 + write_unlock(&profile_ns_list_lock);
3891 +static struct aa_profile *next_profile(struct aa_profile *profile)
3893 + struct aa_profile *next = profile;
3894 + struct aa_namespace *ns;
3896 + list_for_each_entry_continue(next, &profile->ns->profiles, list)
3900 + read_unlock(&ns->lock);
3901 + list_for_each_entry_continue(ns, &profile_ns_list, list) {
3902 + read_lock(&ns->lock);
3903 + list_for_each_entry(profile, &ns->profiles, list)
3905 + read_unlock(&ns->lock);
3910 +static void *p_start(struct seq_file *f, loff_t *pos)
3912 + struct aa_namespace *ns;
3915 + read_lock(&profile_ns_list_lock);
3916 + if (!list_empty(&profile_ns_list)) {
3917 + struct aa_profile *profile = NULL;
3918 + ns = list_first_entry(&profile_ns_list, typeof(*ns), list);
3919 + read_lock(&ns->lock);
3920 + if (!list_empty(&ns->profiles))
3921 + profile = list_first_entry(&ns->profiles,
3922 + typeof(*profile), list);
3924 + read_unlock(&ns->lock);
3925 + for ( ; profile && l > 0; l--)
3926 + profile = next_profile(profile);
3932 +static void *p_next(struct seq_file *f, void *p, loff_t *pos)
3934 + struct aa_profile *profile = (struct aa_profile *) p;
3937 + profile = next_profile(profile);
3942 +static void p_stop(struct seq_file *f, void *p)
3944 + struct aa_profile *profile = (struct aa_profile *) p;
3947 + read_unlock(&profile->ns->lock);
3948 + read_unlock(&profile_ns_list_lock);
3951 +static int seq_show_profile(struct seq_file *f, void *p)
3953 + struct aa_profile *profile = (struct aa_profile *)p;
3954 + if (profile->ns == default_namespace)
3955 + seq_printf(f, "%s (%s)\n", profile->name,
3956 + PROFILE_COMPLAIN(profile) ? "complain" : "enforce");
3958 + seq_printf(f, ":%s:%s (%s)\n", profile->ns->name, profile->name,
3959 + PROFILE_COMPLAIN(profile) ? "complain" : "enforce");
3963 +/* Used in apparmorfs.c */
3964 +struct seq_operations apparmorfs_profiles_op = {
3968 + .show = seq_show_profile,
3970 diff -uprN e/security/apparmor/locking.txt f/security/apparmor/locking.txt
3971 --- e/security/apparmor/locking.txt 1970-01-01 00:00:00.000000000 +0000
3972 +++ f/security/apparmor/locking.txt 2008-05-28 20:29:29.410207000 +0000
3974 +Locking in AppArmor
3975 +===================
3985 +Which lock protects what?
3987 + /-----------------------+-------------------------------\
3988 + | Variable | Lock |
3989 + >-----------------------+-------------------------------<
3990 + | profile_list | profile_list_lock |
3991 + +-----------------------+-------------------------------+
3992 + | aa_profile | (reference count) |
3993 + +-----------------------+-------------------------------+
3994 + | aa_profile-> | aa_profile->lock |
3996 + | task_contexts | |
3997 + +-----------------------+-------------------------------+
3998 + | task_struct->security | read: RCU |
3999 + | | write: task_lock() |
4000 + +-----------------------+-------------------------------+
4001 + | aa_profile->sub | handle on the profile (list |
4002 + | | is never modified) |
4003 + \-----------------------+-------------------------------/
4005 +(Obviously, the list_heads embedded in data structures are always
4006 +protected with the lock that also protects the list.)
4008 +When moving a task context from one profile to another, we grab both
4009 +profile locks with lock_both_profiles(). This ensures that both locks
4010 +are always taken in the same order, and so we won't deadlock.
4012 +Since task_struct->security is RCU protected the aa_task_struct it
4013 +references is only guarenteed to exist for the rcu cycle. Where
4014 +aa_task_context->profile is needed in blocking operations the
4015 +profile's reference count is incremented and the profile reference
4018 +Profiles on profile_list are never stale: when a profile becomes stale,
4019 +it is removed from profile_list at the same time (under profile_list_lock
4020 +and aa_profile->lock).
4022 +The aa_interface_lock is taken whenever user-space modifies the profile
4023 +list, and can sleep. This ensures that profile loading/replacement/removal
4024 +won't race with itself. We release the profile_list_lock as soon as
4025 +possible to avoid stalling exec during profile loading/replacement/removal.
4027 +AppArmor uses lock subtyping to avoid false positives from lockdep. The
4028 +profile lock is often taken nested, but it is guaranteed to be in a lock
4029 +safe order and not the same lock when done, so it is safe.
4031 +A third lock type (aa_lock_task_release) is given to the profile lock
4032 +when it is taken in soft irq context during task release (aa_release).
4033 +This is to avoid a false positive between the task lock and the profile
4034 +lock. In task context the profile lock wraps the task lock with irqs
4035 +off, but the kernel takes the task lock with irqs enabled. This won't
4036 +result in a deadlock because for a deadlock to occur the kernel must
4037 +take dead task A's lock (irqs on), the rcu callback hook freeing
4038 +dead task A must be run and AppArmor must be changing the profile on
4039 +dead task A. The kernel should not be taking a dead task's task_lock
4040 +at the same time the task is being freed by task rcu cleanup other wise
4041 +the task would not be out of its quiescent period.
4042 diff -uprN e/security/apparmor/lsm.c f/security/apparmor/lsm.c
4043 --- e/security/apparmor/lsm.c 1970-01-01 00:00:00.000000000 +0000
4044 +++ f/security/apparmor/lsm.c 2008-05-28 20:29:29.410207000 +0000
4047 + * Copyright (C) 1998-2007 Novell/SUSE
4049 + * This program is free software; you can redistribute it and/or
4050 + * modify it under the terms of the GNU General Public License as
4051 + * published by the Free Software Foundation, version 2 of the
4054 + * AppArmor LSM interface
4056 +#include <linux/security.h>
4057 +#include <linux/module.h>
4058 +#include <linux/mm.h>
4059 +#include <linux/mman.h>
4060 +#include <linux/mount.h>
4061 +#include <linux/namei.h>
4062 +#include <linux/ctype.h>
4063 +#include <linux/sysctl.h>
4064 +#include <linux/audit.h>
4065 +#include <net/sock.h>
4067 +#include "apparmor.h"
4068 +#include "inline.h"
4070 +/* Flag indicating whether initialization completed */
4071 +int apparmor_initialized = 0;
4073 +/* point to the apparmor module */
4074 +struct module *aa_module = NULL;
4076 +/* secondary ops if apparmor is stacked */
4077 +static struct security_operations *aa_secondary_ops = NULL;
4078 +static DEFINE_MUTEX(aa_secondary_lock);
4080 +#define AA_SECONDARY(FN, ARGS...) \
4082 + struct security_operations *__f1; \
4083 + __f1 = rcu_dereference(aa_secondary_ops); \
4084 + (unlikely(__f1) && __f1->FN) ? __f1->FN(ARGS) : 0; \
4087 +static int param_set_aabool(const char *val, struct kernel_param *kp);
4088 +static int param_get_aabool(char *buffer, struct kernel_param *kp);
4089 +#define param_check_aabool(name, p) __param_check(name, p, int)
4091 +static int param_set_aauint(const char *val, struct kernel_param *kp);
4092 +static int param_get_aauint(char *buffer, struct kernel_param *kp);
4093 +#define param_check_aauint(name, p) __param_check(name, p, int)
4095 +/* Flag values, also controllable via /sys/module/apparmor/parameters
4096 + * We define special types as we want to do additional mediation.
4098 + * Complain mode -- in complain mode access failures result in auditing only
4099 + * and task is allowed access. audit events are processed by userspace to
4100 + * generate policy. Default is 'enforce' (0).
4101 + * Value is also togglable per profile and referenced when global value is
4104 +int apparmor_complain = 0;
4105 +module_param_named(complain, apparmor_complain, aabool, S_IRUSR | S_IWUSR);
4106 +MODULE_PARM_DESC(apparmor_complain, "Toggle AppArmor complain mode");
4109 +int apparmor_debug = 0;
4110 +module_param_named(debug, apparmor_debug, aabool, S_IRUSR | S_IWUSR);
4111 +MODULE_PARM_DESC(apparmor_debug, "Toggle AppArmor debug mode");
4114 +int apparmor_audit = 0;
4115 +module_param_named(audit, apparmor_audit, aabool, S_IRUSR | S_IWUSR);
4116 +MODULE_PARM_DESC(apparmor_audit, "Toggle AppArmor audit mode");
4118 +/* Syscall logging mode */
4119 +int apparmor_logsyscall = 0;
4120 +module_param_named(logsyscall, apparmor_logsyscall, aabool, S_IRUSR | S_IWUSR);
4121 +MODULE_PARM_DESC(apparmor_logsyscall, "Toggle AppArmor logsyscall mode");
4123 +/* Maximum pathname length before accesses will start getting rejected */
4124 +unsigned int apparmor_path_max = 2 * PATH_MAX;
4125 +module_param_named(path_max, apparmor_path_max, aauint, S_IRUSR | S_IWUSR);
4126 +MODULE_PARM_DESC(apparmor_path_max, "Maximum pathname length allowed");
4128 +/* Boot time disable flag */
4129 +#ifdef CONFIG_SECURITY_APPARMOR_DISABLE
4130 +#define AA_ENABLED_PERMS 0600
4132 +#define AA_ENABLED_PERMS 0400
4134 +static int param_set_aa_enabled(const char *val, struct kernel_param *kp);
4135 +unsigned int apparmor_enabled = CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE;
4136 +module_param_call(enabled, param_set_aa_enabled, param_get_aauint,
4137 + &apparmor_enabled, AA_ENABLED_PERMS);
4138 +MODULE_PARM_DESC(apparmor_enabled, "Enable/Disable Apparmor on boot");
4140 +static int __init apparmor_enabled_setup(char *str)
4142 + apparmor_enabled = simple_strtol(str, NULL, 0);
4145 +__setup("apparmor=", apparmor_enabled_setup);
4147 +static int param_set_aabool(const char *val, struct kernel_param *kp)
4149 + if (aa_task_context(current))
4151 + return param_set_bool(val, kp);
4154 +static int param_get_aabool(char *buffer, struct kernel_param *kp)
4156 + if (aa_task_context(current))
4158 + return param_get_bool(buffer, kp);
4161 +static int param_set_aauint(const char *val, struct kernel_param *kp)
4163 + if (aa_task_context(current))
4165 + return param_set_uint(val, kp);
4168 +static int param_get_aauint(char *buffer, struct kernel_param *kp)
4170 + if (aa_task_context(current))
4172 + return param_get_uint(buffer, kp);
4175 +/* allow run time disabling of apparmor */
4176 +static int param_set_aa_enabled(const char *val, struct kernel_param *kp)
4181 + if (!apparmor_initialized) {
4182 + apparmor_enabled = 0;
4186 + if (aa_task_context(current))
4189 + if (!apparmor_enabled)
4195 + l = simple_strtoul(val, &endp, 0);
4196 + if (endp == val || l != 0)
4199 + apparmor_enabled = 0;
4200 + apparmor_disable();
4204 +static int aa_reject_syscall(struct task_struct *task, gfp_t flags,
4207 + struct aa_profile *profile = aa_get_profile(task);
4211 + error = aa_audit_syscallreject(profile, flags, name);
4212 + aa_put_profile(profile);
4218 +static int apparmor_ptrace(struct task_struct *parent,
4219 + struct task_struct *child)
4221 + struct aa_task_context *cxt;
4225 + * parent can ptrace child when
4226 + * - parent is unconfined
4227 + * - parent & child are in the same namespace &&
4228 + * - parent is in complain mode
4229 + * - parent and child are confined by the same profile
4230 + * - parent profile has CAP_SYS_PTRACE
4234 + cxt = aa_task_context(parent);
4236 + if (parent->nsproxy != child->nsproxy) {
4237 + struct aa_audit sa;
4238 + memset(&sa, 0, sizeof(sa));
4239 + sa.operation = "ptrace";
4240 + sa.gfp_mask = GFP_ATOMIC;
4241 + sa.parent = parent->pid;
4242 + sa.task = child->pid;
4243 + sa.info = "different namespaces";
4244 + aa_audit_reject(cxt->profile, &sa);
4247 + struct aa_task_context *child_cxt =
4248 + aa_task_context(child);
4250 + error = aa_may_ptrace(cxt, child_cxt ?
4251 + child_cxt->profile : NULL);
4252 + if (PROFILE_COMPLAIN(cxt->profile)) {
4253 + struct aa_audit sa;
4254 + memset(&sa, 0, sizeof(sa));
4255 + sa.operation = "ptrace";
4256 + sa.gfp_mask = GFP_ATOMIC;
4257 + sa.parent = parent->pid;
4258 + sa.task = child->pid;
4259 + aa_audit_hint(cxt->profile, &sa);
4263 + rcu_read_unlock();
4268 +static int apparmor_capable(struct task_struct *task, int cap)
4271 + struct aa_task_context *cxt;
4273 + /* cap_capable returns 0 on success, else -EPERM */
4274 + error = cap_capable(task, cap);
4277 + cxt = aa_task_context(task);
4278 + if (cxt && (!error || cap_raised(cxt->profile->set_caps, cap)))
4279 + error = aa_capability(cxt, cap);
4280 + rcu_read_unlock();
4285 +static int apparmor_sysctl(struct ctl_table *table, int op)
4287 + struct aa_profile *profile = aa_get_profile(current);
4291 + char *buffer, *name;
4298 + mask |= MAY_WRITE;
4301 + buffer = (char*)__get_free_page(GFP_KERNEL);
4304 + name = sysctl_pathname(table, buffer, PAGE_SIZE);
4305 + if (name && name - buffer >= 5) {
4307 + memcpy(name, "/proc", 5);
4308 + error = aa_perm_path(profile, "sysctl", name, mask, 0);
4310 + free_page((unsigned long)buffer);
4314 + aa_put_profile(profile);
4318 +static int apparmor_bprm_set_security(struct linux_binprm *bprm)
4320 + /* handle capability bits with setuid, etc */
4321 + cap_bprm_set_security(bprm);
4322 + /* already set based on script name */
4323 + if (bprm->sh_bang)
4325 + return aa_register(bprm);
4328 +static int apparmor_bprm_secureexec(struct linux_binprm *bprm)
4330 + int ret = cap_bprm_secureexec(bprm);
4332 + if (!ret && (unsigned long)bprm->security & AA_SECURE_EXEC_NEEDED) {
4333 + AA_DEBUG("%s: secureexec required for %s\n",
4334 + __FUNCTION__, bprm->filename);
4341 +static int apparmor_sb_mount(char *dev_name, struct nameidata *nd, char *type,
4342 + unsigned long flags, void *data)
4344 + return aa_reject_syscall(current, GFP_KERNEL, "mount");
4347 +static int apparmor_umount(struct vfsmount *mnt, int flags)
4349 + return aa_reject_syscall(current, GFP_KERNEL, "umount");
4352 +static int apparmor_inode_mkdir(struct inode *dir, struct dentry *dentry,
4353 + struct vfsmount *mnt, int mask)
4355 + struct aa_profile *profile;
4358 + if (!mnt || !mediated_filesystem(dir))
4361 + profile = aa_get_profile(current);
4364 + error = aa_perm_dir(profile, "inode_mkdir", dentry, mnt,
4367 + aa_put_profile(profile);
4373 +static int apparmor_inode_rmdir(struct inode *dir, struct dentry *dentry,
4374 + struct vfsmount *mnt)
4376 + struct aa_profile *profile;
4379 + if (!mnt || !mediated_filesystem(dir))
4382 + profile = aa_get_profile(current);
4385 + error = aa_perm_dir(profile, "inode_rmdir", dentry, mnt,
4388 + aa_put_profile(profile);
4394 +static int aa_permission(const char *operation, struct inode *inode,
4395 + struct dentry *dentry, struct vfsmount *mnt,
4396 + int mask, int check)
4400 + if (mnt && mediated_filesystem(inode)) {
4401 + struct aa_profile *profile;
4403 + profile = aa_get_profile(current);
4405 + error = aa_perm(profile, operation, dentry, mnt, mask,
4407 + aa_put_profile(profile);
4412 +static inline int aa_mask_permissions(int mask)
4414 + if (mask & MAY_APPEND)
4415 + mask &= (MAY_READ | MAY_APPEND | MAY_EXEC);
4417 + mask &= (MAY_READ | MAY_WRITE | MAY_EXEC);
4421 +static int apparmor_inode_create(struct inode *dir, struct dentry *dentry,
4422 + struct vfsmount *mnt, int mask)
4424 + return aa_permission("inode_create", dir, dentry, mnt, MAY_APPEND, 0);
4427 +static int apparmor_inode_link(struct dentry *old_dentry,
4428 + struct vfsmount *old_mnt, struct inode *dir,
4429 + struct dentry *new_dentry,
4430 + struct vfsmount *new_mnt)
4433 + struct aa_profile *profile;
4435 + if (!old_mnt || !new_mnt || !mediated_filesystem(dir))
4438 + profile = aa_get_profile(current);
4441 + error = aa_link(profile, new_dentry, new_mnt,
4442 + old_dentry, old_mnt);
4444 + aa_put_profile(profile);
4450 +static int apparmor_inode_unlink(struct inode *dir, struct dentry *dentry,
4451 + struct vfsmount *mnt)
4455 + if (S_ISDIR(dentry->d_inode->i_mode))
4456 + check |= AA_CHECK_DIR;
4457 + return aa_permission("inode_unlink", dir, dentry, mnt, MAY_WRITE,
4461 +static int apparmor_inode_symlink(struct inode *dir, struct dentry *dentry,
4462 + struct vfsmount *mnt, const char *old_name)
4464 + return aa_permission("inode_symlink", dir, dentry, mnt, MAY_WRITE, 0);
4467 +static int apparmor_inode_mknod(struct inode *dir, struct dentry *dentry,
4468 + struct vfsmount *mnt, int mode, dev_t dev)
4470 + return aa_permission("inode_mknod", dir, dentry, mnt, MAY_WRITE, 0);
4473 +static int apparmor_inode_rename(struct inode *old_dir,
4474 + struct dentry *old_dentry,
4475 + struct vfsmount *old_mnt,
4476 + struct inode *new_dir,
4477 + struct dentry *new_dentry,
4478 + struct vfsmount *new_mnt)
4480 + struct aa_profile *profile;
4483 + if ((!old_mnt && !new_mnt) || !mediated_filesystem(old_dir))
4486 + profile = aa_get_profile(current);
4489 + struct inode *inode = old_dentry->d_inode;
4492 + if (inode && S_ISDIR(inode->i_mode))
4493 + check |= AA_CHECK_DIR;
4495 + error = aa_perm(profile, "inode_rename", old_dentry,
4496 + old_mnt, MAY_READ | MAY_WRITE, check);
4498 + if (!error && new_mnt) {
4499 + error = aa_perm(profile, "inode_rename", new_dentry,
4500 + new_mnt, MAY_WRITE, check);
4504 + aa_put_profile(profile);
4510 +static int apparmor_inode_permission(struct inode *inode, int mask,
4511 + struct nameidata *nd)
4513 + int check = 0, error = 0;
4515 + if (!nd || nd->flags & (LOOKUP_PARENT | LOOKUP_CONTINUE))
4517 + mask = aa_mask_permissions(mask);
4518 + if (S_ISDIR(inode->i_mode)) {
4519 + check |= AA_CHECK_DIR;
4520 + /* allow traverse accesses to directories */
4521 + mask &= ~MAY_EXEC;
4523 + error = aa_permission("inode_permission", inode, nd->path.dentry,
4529 + error = AA_SECONDARY(inode_permission, inode, mask, nd);
4534 +static int apparmor_inode_setattr(struct dentry *dentry, struct vfsmount *mnt,
4535 + struct iattr *iattr)
4542 + if (mediated_filesystem(dentry->d_inode)) {
4543 + struct aa_profile *profile;
4545 + profile = aa_get_profile(current);
4547 + * Mediate any attempt to change attributes of a file
4548 + * (chmod, chown, chgrp, etc)
4551 + error = aa_attr(profile, dentry, mnt, iattr);
4553 + aa_put_profile(profile);
4560 +static int aa_xattr_permission(struct dentry *dentry, struct vfsmount *mnt,
4561 + const char *operation, int mask,
4562 + struct file *file)
4566 + if (mnt && mediated_filesystem(dentry->d_inode)) {
4567 + struct aa_profile *profile = aa_get_profile(current);
4568 + int check = file ? AA_CHECK_FD : 0;
4571 + error = aa_perm_xattr(profile, operation, dentry, mnt,
4573 + aa_put_profile(profile);
4579 +static int apparmor_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
4580 + char *name, void *value, size_t size,
4581 + int flags, struct file *file)
4583 + return aa_xattr_permission(dentry, mnt, "xattr set", MAY_WRITE, file);
4586 +static int apparmor_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
4587 + char *name, struct file *file)
4589 + return aa_xattr_permission(dentry, mnt, "xattr get", MAY_READ, file);
4592 +static int apparmor_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt,
4593 + struct file *file)
4595 + return aa_xattr_permission(dentry, mnt, "xattr list", MAY_READ, file);
4598 +static int apparmor_inode_removexattr(struct dentry *dentry,
4599 + struct vfsmount *mnt, char *name,
4600 + struct file *file)
4602 + return aa_xattr_permission(dentry, mnt, "xattr remove", MAY_WRITE,
4606 +static int aa_file_permission(const char *op, struct file *file, int mask)
4608 + struct aa_profile *profile;
4609 + struct aa_profile *file_profile = (struct aa_profile*)file->f_security;
4612 + if (!file_profile)
4616 + * If this file was opened under a different profile, we
4617 + * revalidate the access against the current profile.
4619 + profile = aa_get_profile(current);
4620 + if (profile && (file_profile != profile || mask & AA_MAY_LOCK)) {
4621 + struct dentry *dentry = file->f_dentry;
4622 + struct vfsmount *mnt = file->f_vfsmnt;
4623 + struct inode *inode = dentry->d_inode;
4624 + int check = AA_CHECK_FD;
4627 + * FIXME: We should remember which profiles we revalidated
4630 + if (S_ISDIR(inode->i_mode))
4631 + check |= AA_CHECK_DIR;
4632 + error = aa_permission(op, inode, dentry, mnt, mask, check);
4634 + aa_put_profile(profile);
4640 +static int apparmor_file_permission(struct file *file, int mask)
4642 + return aa_file_permission("file_permission", file,
4643 + aa_mask_permissions(mask));
4646 +static inline int apparmor_file_lock (struct file *file, unsigned int cmd)
4648 + int mask = AA_MAY_LOCK;
4649 + if (cmd == F_WRLCK)
4650 + mask |= MAY_WRITE;
4651 + return aa_file_permission("file_lock", file, mask);
4654 +static int apparmor_file_alloc_security(struct file *file)
4656 + struct aa_profile *profile;
4658 + profile = aa_get_profile(current);
4660 + file->f_security = profile;
4665 +static void apparmor_file_free_security(struct file *file)
4667 + struct aa_profile *file_profile = (struct aa_profile*)file->f_security;
4669 + aa_put_profile(file_profile);
4672 +static inline int aa_mmap(struct file *file, const char *operation,
4673 + unsigned long prot, unsigned long flags)
4675 + struct dentry *dentry;
4678 + if (!file || !file->f_security)
4681 + if (prot & PROT_READ)
4683 + /* Private mappings don't require write perms since they don't
4684 + * write back to the files */
4685 + if ((prot & PROT_WRITE) && !(flags & MAP_PRIVATE))
4686 + mask |= MAY_WRITE;
4687 + if (prot & PROT_EXEC)
4688 + mask |= AA_EXEC_MMAP;
4690 + dentry = file->f_dentry;
4691 + return aa_permission(operation, dentry->d_inode, dentry,
4692 + file->f_vfsmnt, mask, AA_CHECK_FD);
4695 +static int apparmor_file_mmap(struct file *file, unsigned long reqprot,
4696 + unsigned long prot, unsigned long flags,
4697 + unsigned long addr, unsigned long addr_only)
4699 + if ((addr < mmap_min_addr) && !capable(CAP_SYS_RAWIO)) {
4700 + struct aa_profile *profile = aa_get_profile(current);
4702 + /* future control check here */
4706 + aa_put_profile(profile);
4709 + return aa_mmap(file, "file_mmap", prot, flags);
4712 +static int apparmor_file_mprotect(struct vm_area_struct *vma,
4713 + unsigned long reqprot, unsigned long prot)
4715 + return aa_mmap(vma->vm_file, "file_mprotect", prot,
4716 + !(vma->vm_flags & VM_SHARED) ? MAP_PRIVATE : 0);
4719 +static int apparmor_task_alloc_security(struct task_struct *task)
4721 + return aa_clone(task);
4725 + * Called from IRQ context from RCU callback.
4727 +static void apparmor_task_free_security(struct task_struct *task)
4732 +static int apparmor_socket_create(int family, int type, int protocol, int kern)
4734 + struct aa_profile *profile;
4740 + profile = aa_get_profile(current);
4742 + error = aa_net_perm(profile, "socket_create", family,
4744 + aa_put_profile(profile);
4749 +static int apparmor_socket_post_create(struct socket *sock, int family,
4750 + int type, int protocol, int kern)
4752 + struct sock *sk = sock->sk;
4757 + return aa_revalidate_sk(sk, "socket_post_create");
4760 +static int apparmor_socket_bind(struct socket *sock,
4761 + struct sockaddr *address, int addrlen)
4763 + struct sock *sk = sock->sk;
4765 + return aa_revalidate_sk(sk, "socket_bind");
4768 +static int apparmor_socket_connect(struct socket *sock,
4769 + struct sockaddr *address, int addrlen)
4771 + struct sock *sk = sock->sk;
4773 + return aa_revalidate_sk(sk, "socket_connect");
4776 +static int apparmor_socket_listen(struct socket *sock, int backlog)
4778 + struct sock *sk = sock->sk;
4780 + return aa_revalidate_sk(sk, "socket_listen");
4783 +static int apparmor_socket_accept(struct socket *sock, struct socket *newsock)
4785 + struct sock *sk = sock->sk;
4787 + return aa_revalidate_sk(sk, "socket_accept");
4790 +static int apparmor_socket_sendmsg(struct socket *sock,
4791 + struct msghdr *msg, int size)
4793 + struct sock *sk = sock->sk;
4795 + return aa_revalidate_sk(sk, "socket_sendmsg");
4798 +static int apparmor_socket_recvmsg(struct socket *sock,
4799 + struct msghdr *msg, int size, int flags)
4801 + struct sock *sk = sock->sk;
4803 + return aa_revalidate_sk(sk, "socket_recvmsg");
4806 +static int apparmor_socket_getsockname(struct socket *sock)
4808 + struct sock *sk = sock->sk;
4810 + return aa_revalidate_sk(sk, "socket_getsockname");
4813 +static int apparmor_socket_getpeername(struct socket *sock)
4815 + struct sock *sk = sock->sk;
4817 + return aa_revalidate_sk(sk, "socket_getpeername");
4820 +static int apparmor_socket_getsockopt(struct socket *sock, int level,
4823 + struct sock *sk = sock->sk;
4825 + return aa_revalidate_sk(sk, "socket_getsockopt");
4828 +static int apparmor_socket_setsockopt(struct socket *sock, int level,
4831 + struct sock *sk = sock->sk;
4833 + return aa_revalidate_sk(sk, "socket_setsockopt");
4836 +static int apparmor_socket_shutdown(struct socket *sock, int how)
4838 + struct sock *sk = sock->sk;
4840 + return aa_revalidate_sk(sk, "socket_shutdown");
4843 +static int apparmor_getprocattr(struct task_struct *task, char *name,
4848 + struct aa_profile *profile;
4850 + /* AppArmor only supports the "current" process attribute */
4851 + if (strcmp(name, "current") != 0)
4854 + /* must be task querying itself or admin */
4855 + if (current != task && !capable(CAP_SYS_ADMIN))
4858 + profile = aa_get_profile(task);
4859 + error = aa_getprocattr(profile, value, &len);
4860 + aa_put_profile(profile);
4867 +static int apparmor_setprocattr(struct task_struct *task, char *name,
4868 + void *value, size_t size)
4870 + char *command, *args;
4873 + if (strcmp(name, "current") != 0 || size == 0 || size >= PAGE_SIZE)
4876 + args[size] = '\0';
4877 + args = strstrip(args);
4878 + command = strsep(&args, " ");
4881 + while (isspace(*args))
4886 + if (strcmp(command, "changehat") == 0) {
4887 + if (current != task)
4889 + error = aa_setprocattr_changehat(args);
4890 + } else if (strcmp(command, "changeprofile") == 0) {
4891 + if (current != task)
4893 + error = aa_setprocattr_changeprofile(args);
4894 + } else if (strcmp(command, "setprofile") == 0) {
4895 + struct aa_profile *profile;
4897 + /* Only an unconfined process with admin capabilities
4898 + * may change the profile of another task.
4901 + if (!capable(CAP_SYS_ADMIN))
4904 + profile = aa_get_profile(current);
4906 + struct aa_audit sa;
4907 + memset(&sa, 0, sizeof(sa));
4908 + sa.operation = "profile_set";
4909 + sa.gfp_mask = GFP_KERNEL;
4910 + sa.task = task->pid;
4911 + sa.info = "from confined process";
4912 + aa_audit_reject(profile, &sa);
4913 + aa_put_profile(profile);
4916 + error = aa_setprocattr_setprofile(task, args);
4918 + struct aa_audit sa;
4919 + memset(&sa, 0, sizeof(sa));
4920 + sa.operation = "setprocattr";
4921 + sa.gfp_mask = GFP_KERNEL;
4922 + sa.info = "invalid command";
4923 + sa.name = command;
4924 + sa.task = task->pid;
4925 + aa_audit_reject(NULL, &sa);
4934 +static int apparmor_task_setrlimit(unsigned int resource,
4935 + struct rlimit *new_rlim)
4937 + struct aa_profile *profile;
4940 + profile = aa_get_profile(current);
4942 + error = aa_task_setrlimit(profile, resource, new_rlim);
4944 + aa_put_profile(profile);
4949 +int apparmor_register_subsecurity(const char *name,
4950 + struct security_operations *ops)
4954 + if (mutex_lock_interruptible(&aa_secondary_lock))
4955 + return -ERESTARTSYS;
4957 + /* allow dazuko and capability to stack. The stacking with
4958 + * capability is not needed since apparmor already composes
4959 + * capability using common cap.
4961 + if (!aa_secondary_ops && (strcmp(name, "dazuko") == 0 ||
4962 + strcmp(name, "capability") == 0)){
4963 + /* The apparmor module needs to be pinned while a secondary is
4966 + if (try_module_get(aa_module)) {
4967 + aa_secondary_ops = ops;
4968 + info_message("Registered secondary security module",
4974 + info_message("Unable to register %s as a secondary security "
4978 + mutex_unlock(&aa_secondary_lock);
4982 +int apparmor_unregister_subsecurity(const char *name,
4983 + struct security_operations *ops)
4987 + if (mutex_lock_interruptible(&aa_secondary_lock))
4988 + return -ERESTARTSYS;
4990 + if (aa_secondary_ops && aa_secondary_ops == ops) {
4991 + rcu_assign_pointer(aa_secondary_ops, NULL);
4992 + synchronize_rcu();
4993 + module_put(aa_module);
4994 + info_message("Unregistered secondary security module", name);
4996 + info_message("Unable to unregister secondary security module",
5000 + mutex_unlock(&aa_secondary_lock);
5004 +struct security_operations apparmor_ops = {
5005 + .name = "apparmor",
5006 + .ptrace = apparmor_ptrace,
5007 + .capget = cap_capget,
5008 + .capset_check = cap_capset_check,
5009 + .capset_set = cap_capset_set,
5010 + .sysctl = apparmor_sysctl,
5011 + .capable = apparmor_capable,
5012 + .syslog = cap_syslog,
5014 + .bprm_apply_creds = cap_bprm_apply_creds,
5015 + .bprm_set_security = apparmor_bprm_set_security,
5016 + .bprm_secureexec = apparmor_bprm_secureexec,
5018 + .sb_mount = apparmor_sb_mount,
5019 + .sb_umount = apparmor_umount,
5021 + .inode_mkdir = apparmor_inode_mkdir,
5022 + .inode_rmdir = apparmor_inode_rmdir,
5023 + .inode_create = apparmor_inode_create,
5024 + .inode_link = apparmor_inode_link,
5025 + .inode_unlink = apparmor_inode_unlink,
5026 + .inode_symlink = apparmor_inode_symlink,
5027 + .inode_mknod = apparmor_inode_mknod,
5028 + .inode_rename = apparmor_inode_rename,
5029 + .inode_permission = apparmor_inode_permission,
5030 + .inode_setattr = apparmor_inode_setattr,
5031 + .inode_setxattr = apparmor_inode_setxattr,
5032 + .inode_getxattr = apparmor_inode_getxattr,
5033 + .inode_listxattr = apparmor_inode_listxattr,
5034 + .inode_removexattr = apparmor_inode_removexattr,
5035 + .file_permission = apparmor_file_permission,
5036 + .file_alloc_security = apparmor_file_alloc_security,
5037 + .file_free_security = apparmor_file_free_security,
5038 + .file_mmap = apparmor_file_mmap,
5039 + .file_mprotect = apparmor_file_mprotect,
5040 + .file_lock = apparmor_file_lock,
5042 + .task_alloc_security = apparmor_task_alloc_security,
5043 + .task_free_security = apparmor_task_free_security,
5044 + .task_post_setuid = cap_task_post_setuid,
5045 + .task_reparent_to_init = cap_task_reparent_to_init,
5046 + .task_setrlimit = apparmor_task_setrlimit,
5048 + .getprocattr = apparmor_getprocattr,
5049 + .setprocattr = apparmor_setprocattr,
5051 + .register_security = apparmor_register_subsecurity,
5053 + .socket_create = apparmor_socket_create,
5054 + .socket_post_create = apparmor_socket_post_create,
5055 + .socket_bind = apparmor_socket_bind,
5056 + .socket_connect = apparmor_socket_connect,
5057 + .socket_listen = apparmor_socket_listen,
5058 + .socket_accept = apparmor_socket_accept,
5059 + .socket_sendmsg = apparmor_socket_sendmsg,
5060 + .socket_recvmsg = apparmor_socket_recvmsg,
5061 + .socket_getsockname = apparmor_socket_getsockname,
5062 + .socket_getpeername = apparmor_socket_getpeername,
5063 + .socket_getsockopt = apparmor_socket_getsockopt,
5064 + .socket_setsockopt = apparmor_socket_setsockopt,
5065 + .socket_shutdown = apparmor_socket_shutdown,
5068 +void info_message(const char *str, const char *name)
5070 + struct aa_audit sa;
5071 + memset(&sa, 0, sizeof(sa));
5072 + sa.gfp_mask = GFP_KERNEL;
5075 + printk(KERN_INFO "AppArmor: %s %s\n", str, name);
5076 + if (audit_enabled)
5077 + aa_audit_message(NULL, &sa, AUDIT_APPARMOR_STATUS);
5080 +static int __init apparmor_init(void)
5084 + if (!apparmor_enabled) {
5085 + info_message("AppArmor disabled by boottime parameter", "");
5089 + if ((error = create_apparmorfs())) {
5090 + AA_ERROR("Unable to activate AppArmor filesystem\n");
5091 + goto createfs_out;
5094 + if ((error = alloc_default_namespace())){
5095 + AA_ERROR("Unable to allocate default profile namespace\n");
5099 + if ((error = register_security(&apparmor_ops))) {
5100 + AA_ERROR("Unable to register AppArmor\n");
5101 + goto register_security_out;
5104 + /* Report that AppArmor successfully initialized */
5105 + apparmor_initialized = 1;
5106 + if (apparmor_complain)
5107 + info_message("AppArmor initialized: complainmode enabled",
5110 + info_message("AppArmor initialized", NULL);
5114 +register_security_out:
5115 + free_default_namespace();
5118 + destroy_apparmorfs();
5125 +security_initcall(apparmor_init);
5127 +void apparmor_disable(void)
5129 + /* Remove and release all the profiles on the profile list. */
5130 + mutex_lock(&aa_interface_lock);
5131 + aa_profile_ns_list_release();
5133 + /* FIXME: cleanup profiles references on files */
5134 + free_default_namespace();
5137 + * Delay for an rcu cycle to make sure that all active task
5138 + * context readers have finished, and all profiles have been
5139 + * freed by their rcu callbacks.
5141 + synchronize_rcu();
5143 + destroy_apparmorfs();
5144 + mutex_unlock(&aa_interface_lock);
5146 + apparmor_initialized = 0;
5148 + info_message("AppArmor protection removed", NULL);
5151 +MODULE_DESCRIPTION("AppArmor process confinement");
5152 +MODULE_AUTHOR("Novell/Immunix, http://bugs.opensuse.org");
5153 +MODULE_LICENSE("GPL");
5154 diff -uprN e/security/apparmor/main.c f/security/apparmor/main.c
5155 --- e/security/apparmor/main.c 1970-01-01 00:00:00.000000000 +0000
5156 +++ f/security/apparmor/main.c 2008-05-28 20:29:29.410207000 +0000
5159 + * Copyright (C) 2002-2007 Novell/SUSE
5161 + * This program is free software; you can redistribute it and/or
5162 + * modify it under the terms of the GNU General Public License as
5163 + * published by the Free Software Foundation, version 2 of the
5169 +#include <linux/security.h>
5170 +#include <linux/namei.h>
5171 +#include <linux/audit.h>
5172 +#include <linux/mount.h>
5173 +#include <linux/ptrace.h>
5174 +#include <linux/socket.h>
5175 +#include <linux/net.h>
5176 +#include <net/sock.h>
5178 +#include "apparmor.h"
5180 +#include "inline.h"
5183 + * Table of capability names: we generate it from capabilities.h.
5185 +static const char *capability_names[] = {
5186 +#include "capability_names.h"
5189 +struct aa_namespace *default_namespace;
5191 +static int aa_inode_mode(struct inode *inode)
5193 + /* if the inode doesn't exist the user is creating it */
5194 + if (!inode || current->fsuid == inode->i_uid)
5195 + return AA_USER_SHIFT;
5196 + return AA_OTHER_SHIFT;
5199 +int alloc_default_namespace(void)
5201 + struct aa_namespace *ns;
5202 + char *name = kstrdup("default", GFP_KERNEL);
5205 + ns = alloc_aa_namespace(name);
5211 + write_lock(&profile_ns_list_lock);
5212 + default_namespace = ns;
5213 + aa_get_namespace(ns);
5214 + list_add(&ns->list, &profile_ns_list);
5215 + write_unlock(&profile_ns_list_lock);
5220 +void free_default_namespace(void)
5222 + write_lock(&profile_ns_list_lock);
5223 + list_del_init(&default_namespace->list);
5224 + write_unlock(&profile_ns_list_lock);
5225 + aa_put_namespace(default_namespace);
5226 + default_namespace = NULL;
5229 +static void aa_audit_file_sub_mask(struct audit_buffer *ab, char *buffer,
5232 + const char unsafex[] = "upcn";
5233 + const char safex[] = "UPCN";
5236 + if (mask & AA_EXEC_MMAP)
5238 + if (mask & MAY_READ)
5240 + if (mask & MAY_WRITE)
5242 + else if (mask & MAY_APPEND)
5244 + if (mask & MAY_EXEC) {
5245 + int index = AA_EXEC_INDEX(mask);
5246 + /* all indexes > 4 are also named transitions */
5250 + if (mask & AA_EXEC_UNSAFE)
5251 + *m++ = unsafex[index - 1];
5253 + *m++ = safex[index - 1];
5255 + if (mask & AA_EXEC_INHERIT)
5259 + if (mask & AA_MAY_LINK)
5261 + if (mask & AA_MAY_LOCK)
5266 +static void aa_audit_file_mask(struct audit_buffer *ab, const char *name,
5269 + char user[10], other[10];
5271 + aa_audit_file_sub_mask(ab, user,
5272 + (mask & AA_USER_PERMS) >> AA_USER_SHIFT);
5273 + aa_audit_file_sub_mask(ab, other,
5274 + (mask & AA_OTHER_PERMS) >> AA_OTHER_SHIFT);
5276 + audit_log_format(ab, " %s=\"%s::%s\"", name, user, other);
5279 +static const char *address_families[] = {
5280 +#include "af_names.h"
5283 +static const char *sock_types[] = {
5298 + * aa_audit - Log an audit event to the audit subsystem
5299 + * @profile: profile to check against
5300 + * @sa: audit event
5301 + * @audit_cxt: audit context to log message to
5302 + * @type: audit event number
5304 +static int aa_audit_base(struct aa_profile *profile, struct aa_audit *sa,
5305 + struct audit_context *audit_cxt, int type)
5307 + struct audit_buffer *ab = NULL;
5309 + ab = audit_log_start(audit_cxt, sa->gfp_mask, type);
5312 + AA_ERROR("Unable to log event (%d) to audit subsys\n",
5314 + /* don't fail operations in complain mode even if logging
5316 + return type == AUDIT_APPARMOR_ALLOWED ? 0 : -ENOMEM;
5319 + if (sa->operation)
5320 + audit_log_format(ab, "operation=\"%s\"", sa->operation);
5323 + audit_log_format(ab, " info=\"%s\"", sa->info);
5324 + if (sa->error_code)
5325 + audit_log_format(ab, " error=%d", sa->error_code);
5328 + if (sa->request_mask)
5329 + aa_audit_file_mask(ab, "requested_mask", sa->request_mask);
5331 + if (sa->denied_mask)
5332 + aa_audit_file_mask(ab, "denied_mask", sa->denied_mask);
5334 + if (sa->request_mask)
5335 + audit_log_format(ab, " fsuid=%d", current->fsuid);
5338 + audit_log_format(ab, " rlimit=%d", sa->rlimit - 1);
5341 + struct iattr *iattr = sa->iattr;
5343 + audit_log_format(ab, " attribute=\"%s%s%s%s%s%s%s\"",
5344 + iattr->ia_valid & ATTR_MODE ? "mode," : "",
5345 + iattr->ia_valid & ATTR_UID ? "uid," : "",
5346 + iattr->ia_valid & ATTR_GID ? "gid," : "",
5347 + iattr->ia_valid & ATTR_SIZE ? "size," : "",
5348 + iattr->ia_valid & (ATTR_ATIME | ATTR_ATIME_SET) ?
5350 + iattr->ia_valid & (ATTR_MTIME | ATTR_MTIME_SET) ?
5352 + iattr->ia_valid & ATTR_CTIME ? "ctime," : "");
5356 + audit_log_format(ab, " task=%d", sa->task);
5359 + audit_log_format(ab, " parent=%d", sa->parent);
5362 + audit_log_format(ab, " name=");
5363 + audit_log_untrustedstring(ab, sa->name);
5367 + audit_log_format(ab, " name2=");
5368 + audit_log_untrustedstring(ab, sa->name2);
5371 + if (sa->family || sa->type) {
5372 + if (address_families[sa->family])
5373 + audit_log_format(ab, " family=\"%s\"",
5374 + address_families[sa->family]);
5376 + audit_log_format(ab, " family=\"unknown(%d)\"",
5379 + if (sock_types[sa->type])
5380 + audit_log_format(ab, " sock_type=\"%s\"",
5381 + sock_types[sa->type]);
5383 + audit_log_format(ab, " sock_type=\"unknown(%d)\"",
5386 + audit_log_format(ab, " protocol=%d", sa->protocol);
5389 + audit_log_format(ab, " pid=%d", current->pid);
5392 + audit_log_format(ab, " profile=");
5393 + audit_log_untrustedstring(ab, profile->name);
5395 + if (profile->ns != default_namespace) {
5396 + audit_log_format(ab, " namespace=");
5397 + audit_log_untrustedstring(ab, profile->ns->name);
5401 + audit_log_end(ab);
5403 + return type == AUDIT_APPARMOR_ALLOWED ? 0 : sa->error_code;
5407 + * aa_audit_syscallreject - Log a syscall rejection to the audit subsystem
5408 + * @profile: profile to check against
5409 + * @gfp: memory allocation flags
5410 + * @msg: string describing syscall being rejected
5412 +int aa_audit_syscallreject(struct aa_profile *profile, gfp_t gfp,
5415 + struct aa_audit sa;
5416 + memset(&sa, 0, sizeof(sa));
5417 + sa.operation = "syscall";
5419 + sa.gfp_mask = gfp;
5420 + sa.error_code = -EPERM;
5422 + return aa_audit_base(profile, &sa, current->audit_context,
5423 + AUDIT_APPARMOR_DENIED);
5426 +int aa_audit_message(struct aa_profile *profile, struct aa_audit *sa,
5429 + struct audit_context *audit_cxt;
5431 + audit_cxt = apparmor_logsyscall ? current->audit_context : NULL;
5432 + return aa_audit_base(profile, sa, audit_cxt, type);
5435 +void aa_audit_hint(struct aa_profile *profile, struct aa_audit *sa)
5437 + aa_audit_message(profile, sa, AUDIT_APPARMOR_HINT);
5440 +void aa_audit_status(struct aa_profile *profile, struct aa_audit *sa)
5442 + aa_audit_message(profile, sa, AUDIT_APPARMOR_STATUS);
5445 +int aa_audit_reject(struct aa_profile *profile, struct aa_audit *sa)
5447 + return aa_audit_message(profile, sa, AUDIT_APPARMOR_DENIED);
5451 + * aa_audit - Log an audit event to the audit subsystem
5452 + * @profile: profile to check against
5453 + * @sa: audit event
5455 +int aa_audit(struct aa_profile *profile, struct aa_audit *sa)
5457 + int type = AUDIT_APPARMOR_DENIED;
5458 + struct audit_context *audit_cxt;
5460 + if (likely(!sa->error_code))
5461 + type = AUDIT_APPARMOR_AUDIT;
5462 + else if (PROFILE_COMPLAIN(profile))
5463 + type = AUDIT_APPARMOR_ALLOWED;
5465 + audit_cxt = apparmor_logsyscall ? current->audit_context : NULL;
5466 + return aa_audit_base(profile, sa, audit_cxt, type);
5469 +static int aa_audit_file(struct aa_profile *profile, struct aa_audit *sa)
5471 + if (likely(!sa->error_code)) {
5472 + int mask = sa->audit_mask & AUDIT_FILE_MASK;
5474 + if (unlikely(PROFILE_AUDIT(profile)))
5475 + mask |= AUDIT_FILE_MASK;
5477 + if (likely(!(sa->request_mask & mask)))
5480 + /* mask off perms that are not being force audited */
5481 + sa->request_mask &= mask | ALL_AA_EXEC_TYPE;
5483 + int mask = AUDIT_QUIET_MASK(sa->audit_mask);
5485 + if (!(sa->denied_mask & ~mask))
5486 + return sa->error_code;
5488 + /* mask off perms whose denial is being silenced */
5489 + sa->denied_mask &= (~mask) | ALL_AA_EXEC_TYPE;
5492 + return aa_audit(profile, sa);
5495 +static int aa_audit_caps(struct aa_profile *profile, struct aa_audit *sa,
5498 + if (likely(!sa->error_code)) {
5499 + if (likely(!PROFILE_AUDIT(profile) &&
5500 + !cap_raised(profile->audit_caps, cap)))
5504 + /* quieting of capabilities is handled the caps_logged cache */
5505 + return aa_audit(profile, sa);
5509 + * aa_file_denied - check for @mask access on a file
5510 + * @profile: profile to check against
5511 + * @name: pathname of file
5512 + * @mask: permission mask requested for file
5513 + * @audit_mask: return audit mask for the match
5515 + * Return %0 on success, or else the permissions in @mask that the
5518 +static int aa_file_denied(struct aa_profile *profile, const char *name,
5519 + int mask, int *audit_mask)
5521 + return (mask & ~aa_match(profile->file_rules, name, audit_mask));
5525 + * aa_link_denied - check for permission to link a file
5526 + * @profile: profile to check against
5527 + * @link: pathname of link being created
5528 + * @target: pathname of target to be linked to
5529 + * @target_mode: UGO shift for target inode
5530 + * @request_mask: the permissions subset valid only if link succeeds
5531 + * @audit_mask: return the audit_mask for the link permission
5532 + * Return %0 on success, or else the permissions that the profile denies.
5534 +static int aa_link_denied(struct aa_profile *profile, const char *link,
5535 + const char *target, int target_mode,
5536 + int *request_mask, int *audit_mask)
5538 + unsigned int state;
5539 + int l_mode, t_mode, l_x, t_x, denied_mask = 0;
5540 + int link_mask = AA_MAY_LINK << target_mode;
5542 + *request_mask = link_mask;
5544 + l_mode = aa_match_state(profile->file_rules, DFA_START, link, &state);
5546 + if (l_mode & link_mask) {
5548 + /* test to see if target can be paired with link */
5549 + state = aa_dfa_null_transition(profile->file_rules, state);
5550 + mode = aa_match_state(profile->file_rules, state, target,
5553 + if (!(mode & link_mask))
5554 + denied_mask |= link_mask;
5556 + *audit_mask = dfa_audit_mask(profile->file_rules, state);
5558 + /* return if link subset test is not required */
5559 + if (!(mode & (AA_LINK_SUBSET_TEST << target_mode)))
5560 + return denied_mask;
5563 + /* Do link perm subset test requiring permission on link are a
5564 + * subset of the permissions on target.
5565 + * If a subset test is required a permission subset test of the
5566 + * perms for the link are done against the user::other of the
5567 + * target's 'r', 'w', 'x', 'a', 'k', and 'm' permissions.
5569 + * If the link has 'x', an exact match of all the execute flags
5572 + denied_mask |= ~l_mode & link_mask;
5574 + t_mode = aa_match(profile->file_rules, target, NULL);
5576 + l_x = l_mode & (ALL_AA_EXEC_TYPE | AA_EXEC_BITS);
5577 + t_x = t_mode & (ALL_AA_EXEC_TYPE | AA_EXEC_BITS);
5579 + /* For actual subset test ignore valid-profile-transition flags,
5582 + l_mode &= AA_FILE_PERMS & ~AA_LINK_BITS;
5583 + t_mode &= AA_FILE_PERMS & ~AA_LINK_BITS;
5585 + *request_mask = l_mode | link_mask;
5588 + int x = l_x | (t_x & ALL_AA_EXEC_UNSAFE);
5589 + denied_mask |= l_mode & ~t_mode;
5590 + /* mask off x modes not used by link */
5592 + /* handle exec subset
5593 + * - link safe exec issubset of unsafe exec
5594 + * - no link x perm is subset of target having x perm
5596 + if ((l_mode & AA_USER_EXEC) &&
5597 + (x & AA_USER_EXEC_TYPE) != (t_x & AA_USER_EXEC_TYPE))
5598 + denied_mask = AA_USER_EXEC | (l_x & AA_USER_EXEC_TYPE);
5599 + if ((l_mode & AA_OTHER_EXEC) &&
5600 + (x & AA_OTHER_EXEC_TYPE) != (t_x & AA_OTHER_EXEC_TYPE))
5601 + denied_mask = AA_OTHER_EXEC | (l_x & AA_OTHER_EXEC_TYPE);
5604 + return denied_mask;
5608 + * aa_get_name - compute the pathname of a file
5609 + * @dentry: dentry of the file
5610 + * @mnt: vfsmount of the file
5611 + * @buffer: buffer that aa_get_name() allocated
5612 + * @check: AA_CHECK_DIR is set if the file is a directory
5614 + * Returns a pointer to the beginning of the pathname (which usually differs
5615 + * from the beginning of the buffer), or an error code.
5617 + * We need @check to indicate whether the file is a directory or not because
5618 + * the file may not yet exist, and so we cannot check the inode's file type.
5620 +static char *aa_get_name(struct dentry *dentry, struct vfsmount *mnt,
5621 + char **buffer, int check)
5624 + int is_dir, size = 256;
5626 + is_dir = (check & AA_CHECK_DIR) ? 1 : 0;
5629 + char *buf = kmalloc(size, GFP_KERNEL);
5631 + return ERR_PTR(-ENOMEM);
5633 + name = d_namespace_path(dentry, mnt, buf, size - is_dir);
5634 + if (!IS_ERR(name)) {
5635 + if (name[0] != '/') {
5637 + * This dentry is not connected to the
5638 + * namespace root -- reject access.
5641 + return ERR_PTR(-ENOENT);
5643 + if (is_dir && name[1] != '\0') {
5645 + * Append "/" to the pathname. The root
5646 + * directory is a special case; it already
5649 + buf[size - 2] = '/';
5650 + buf[size - 1] = '\0';
5656 + if (PTR_ERR(name) != -ENAMETOOLONG)
5661 + if (size > apparmor_path_max)
5662 + return ERR_PTR(-ENAMETOOLONG);
5666 +static char *new_compound_name(const char *n1, const char *n2)
5668 + char *name = kmalloc(strlen(n1) + strlen(n2) + 3, GFP_KERNEL);
5670 + sprintf(name, "%s//%s", n1, n2);
5673 +static inline void aa_put_name_buffer(char *buffer)
5679 + * aa_perm_dentry - check if @profile allows @mask for a file
5680 + * @profile: profile to check against
5681 + * @dentry: dentry of the file
5682 + * @mnt: vfsmount o the file
5683 + * @sa: audit context
5684 + * @mask: requested profile permissions
5685 + * @check: kind of check to perform
5687 + * Returns 0 upon success, or else an error code.
5689 + * @check indicates the file type, and whether the file was accessed through
5690 + * an open file descriptor (AA_CHECK_FD) or not.
5692 +static int aa_perm_dentry(struct aa_profile *profile, struct dentry *dentry,
5693 + struct vfsmount *mnt, struct aa_audit *sa, int check)
5696 + char *buffer = NULL;
5698 + sa->name = aa_get_name(dentry, mnt, &buffer, check);
5699 + sa->request_mask <<= aa_inode_mode(dentry->d_inode);
5700 + if (IS_ERR(sa->name)) {
5702 + * deleted files are given a pass on permission checks when
5703 + * accessed through a file descriptor.
5705 + if (PTR_ERR(sa->name) == -ENOENT && (check & AA_CHECK_FD))
5706 + sa->denied_mask = 0;
5708 + sa->denied_mask = sa->request_mask;
5709 + sa->error_code = PTR_ERR(sa->name);
5710 + if (sa->error_code == -ENOENT)
5711 + sa->info = "Failed name resolution - object not a valid entry";
5712 + else if (sa->error_code == -ENAMETOOLONG)
5713 + sa->info = "Failed name resolution - name too long";
5715 + sa->info = "Failed name resolution";
5719 + sa->denied_mask = aa_file_denied(profile, sa->name,
5723 + if (!sa->denied_mask)
5724 + sa->error_code = 0;
5726 + error = aa_audit_file(profile, sa);
5727 + aa_put_name_buffer(buffer);
5733 + * aa_attr - check if attribute change is allowed
5734 + * @profile: profile to check against
5735 + * @dentry: dentry of the file to check
5736 + * @mnt: vfsmount of the file to check
5737 + * @iattr: attribute changes requested
5739 +int aa_attr(struct aa_profile *profile, struct dentry *dentry,
5740 + struct vfsmount *mnt, struct iattr *iattr)
5742 + struct inode *inode = dentry->d_inode;
5744 + struct aa_audit sa;
5746 + memset(&sa, 0, sizeof(sa));
5747 + sa.operation = "setattr";
5748 + sa.gfp_mask = GFP_KERNEL;
5750 + sa.request_mask = MAY_WRITE;
5751 + sa.error_code = -EACCES;
5754 + if (inode && S_ISDIR(inode->i_mode))
5755 + check |= AA_CHECK_DIR;
5756 + if (iattr->ia_valid & ATTR_FILE)
5757 + check |= AA_CHECK_FD;
5759 + error = aa_perm_dentry(profile, dentry, mnt, &sa, check);
5765 + * aa_perm_xattr - check if xattr attribute change is allowed
5766 + * @profile: profile to check against
5767 + * @dentry: dentry of the file to check
5768 + * @mnt: vfsmount of the file to check
5769 + * @operation: xattr operation being done
5770 + * @mask: access mode requested
5771 + * @check: kind of check to perform
5773 +int aa_perm_xattr(struct aa_profile *profile, const char *operation,
5774 + struct dentry *dentry, struct vfsmount *mnt, int mask,
5777 + struct inode *inode = dentry->d_inode;
5779 + struct aa_audit sa;
5781 + memset(&sa, 0, sizeof(sa));
5782 + sa.operation = operation;
5783 + sa.gfp_mask = GFP_KERNEL;
5784 + sa.request_mask = mask;
5785 + sa.error_code = -EACCES;
5787 + if (inode && S_ISDIR(inode->i_mode))
5788 + check |= AA_CHECK_DIR;
5790 + error = aa_perm_dentry(profile, dentry, mnt, &sa, check);
5796 + * aa_perm - basic apparmor permissions check
5797 + * @profile: profile to check against
5798 + * @dentry: dentry of the file to check
5799 + * @mnt: vfsmount of the file to check
5800 + * @mask: access mode requested
5801 + * @check: kind of check to perform
5803 + * Determine if access @mask for the file is authorized by @profile.
5804 + * Returns 0 on success, or else an error code.
5806 +int aa_perm(struct aa_profile *profile, const char *operation,
5807 + struct dentry *dentry, struct vfsmount *mnt, int mask, int check)
5809 + struct aa_audit sa;
5815 + memset(&sa, 0, sizeof(sa));
5816 + sa.operation = operation;
5817 + sa.gfp_mask = GFP_KERNEL;
5818 + sa.request_mask = mask;
5819 + sa.error_code = -EACCES;
5821 + error = aa_perm_dentry(profile, dentry, mnt, &sa, check);
5829 + * @profile: profile to check against
5830 + * @dentry: dentry of directory to check
5831 + * @mnt: vfsmount of directory to check
5832 + * @operation: directory operation being performed
5833 + * @mask: access mode requested
5835 + * Determine if directory operation (make/remove) for dentry is authorized
5837 + * Returns 0 on success, or else an error code.
5839 +int aa_perm_dir(struct aa_profile *profile, const char *operation,
5840 + struct dentry *dentry, struct vfsmount *mnt, int mask)
5842 + struct aa_audit sa;
5844 + memset(&sa, 0, sizeof(sa));
5845 + sa.operation = operation;
5846 + sa.gfp_mask = GFP_KERNEL;
5847 + sa.request_mask = mask;
5848 + sa.error_code = -EACCES;
5850 + return aa_perm_dentry(profile, dentry, mnt, &sa, AA_CHECK_DIR);
5853 +int aa_perm_path(struct aa_profile *profile, const char *operation,
5854 + const char *name, int mask, uid_t uid)
5856 + struct aa_audit sa;
5858 + memset(&sa, 0, sizeof(sa));
5859 + sa.operation = operation;
5860 + sa.gfp_mask = GFP_KERNEL;
5861 + sa.request_mask = mask;
5863 + if (current->fsuid == uid)
5864 + sa.request_mask = mask << AA_USER_SHIFT;
5866 + sa.request_mask = mask << AA_OTHER_SHIFT;
5868 + sa.denied_mask = aa_file_denied(profile, name, sa.request_mask,
5870 + sa.error_code = sa.denied_mask ? -EACCES : 0;
5872 + return aa_audit_file(profile, &sa);
5876 + * aa_capability - test permission to use capability
5877 + * @cxt: aa_task_context with profile to check against
5878 + * @cap: capability to be tested
5880 + * Look up capability in profile capability set.
5881 + * Returns 0 on success, or else an error code.
5883 +int aa_capability(struct aa_task_context *cxt, int cap)
5885 + int error = cap_raised(cxt->profile->capabilities, cap) ? 0 : -EPERM;
5886 + struct aa_audit sa;
5888 + /* test if cap has alread been logged */
5889 + if (cap_raised(cxt->caps_logged, cap)) {
5890 + if (PROFILE_COMPLAIN(cxt->profile))
5894 + /* don't worry about rcu replacement of the cxt here.
5895 + * caps_logged is a cache to reduce the occurence of
5896 + * duplicate messages in the log. The worst that can
5897 + * happen is duplicate capability messages shows up in
5900 + cap_raise(cxt->caps_logged, cap);
5902 + memset(&sa, 0, sizeof(sa));
5903 + sa.operation = "capable";
5904 + sa.gfp_mask = GFP_ATOMIC;
5905 + sa.name = capability_names[cap];
5906 + sa.error_code = error;
5908 + error = aa_audit_caps(cxt->profile, &sa, cap);
5913 +/* must be used inside rcu_read_lock or task_lock */
5914 +int aa_may_ptrace(struct aa_task_context *cxt, struct aa_profile *tracee)
5916 + if (!cxt || cxt->profile == tracee)
5918 + return aa_capability(cxt, CAP_SYS_PTRACE);
5922 + * aa_link - hard link check
5923 + * @profile: profile to check against
5924 + * @link: dentry of link being created
5925 + * @link_mnt: vfsmount of link being created
5926 + * @target: dentry of link target
5927 + * @target_mnt: vfsmunt of link target
5929 + * Returns 0 on success, or else an error code.
5931 +int aa_link(struct aa_profile *profile,
5932 + struct dentry *link, struct vfsmount *link_mnt,
5933 + struct dentry *target, struct vfsmount *target_mnt)
5936 + struct aa_audit sa;
5937 + char *buffer = NULL, *buffer2 = NULL;
5939 + memset(&sa, 0, sizeof(sa));
5940 + sa.operation = "inode_link";
5941 + sa.gfp_mask = GFP_KERNEL;
5942 + sa.name = aa_get_name(link, link_mnt, &buffer, 0);
5943 + sa.name2 = aa_get_name(target, target_mnt, &buffer2, 0);
5945 + if (IS_ERR(sa.name)) {
5946 + sa.error_code = PTR_ERR(sa.name);
5949 + if (IS_ERR(sa.name2)) {
5950 + sa.error_code = PTR_ERR(sa.name2);
5954 + if (sa.name && sa.name2) {
5955 + sa.denied_mask = aa_link_denied(profile, sa.name, sa.name2,
5956 + aa_inode_mode(target->d_inode),
5959 + sa.error_code = sa.denied_mask ? -EACCES : 0;
5962 + error = aa_audit_file(profile, &sa);
5964 + aa_put_name_buffer(buffer);
5965 + aa_put_name_buffer(buffer2);
5970 +int aa_net_perm(struct aa_profile *profile, char *operation,
5971 + int family, int type, int protocol)
5973 + struct aa_audit sa;
5975 + u16 family_mask, audit_mask, quiet_mask;
5977 + if ((family < 0) || (family >= AF_MAX))
5980 + if ((type < 0) || (type >= SOCK_MAX))
5983 + /* unix domain and netlink sockets are handled by ipc */
5984 + if (family == AF_UNIX || family == AF_NETLINK)
5987 + family_mask = profile->network_families[family];
5988 + audit_mask = profile->audit_network[family];
5989 + quiet_mask = profile->quiet_network[family];
5991 + error = (family_mask & (1 << type)) ? 0 : -EACCES;
5993 + memset(&sa, 0, sizeof(sa));
5994 + sa.operation = operation;
5995 + sa.gfp_mask = GFP_KERNEL;
5996 + sa.family = family;
5998 + sa.protocol = protocol;
5999 + sa.error_code = error;
6001 + if (likely(!error)) {
6002 + if (!PROFILE_AUDIT(profile) && !(family_mask & audit_mask))
6004 + } else if (!((1 << type) & ~quiet_mask)) {
6008 + error = aa_audit(profile, &sa);
6013 +int aa_revalidate_sk(struct sock *sk, char *operation)
6015 + struct aa_profile *profile;
6018 + /* this is some debugging code to flush out the network hooks that
6019 + that are called in interrupt context */
6020 + if (in_interrupt()) {
6021 + printk("AppArmor Debug: Hook being called from interrupt context\n");
6026 + profile = aa_get_profile(current);
6028 + error = aa_net_perm(profile, operation,
6029 + sk->sk_family, sk->sk_type,
6031 + aa_put_profile(profile);
6036 + * aa_task_setrlimit - test permission to set an rlimit
6037 + * @profile - profile confining the task
6038 + * @resource - the resource being set
6039 + * @new_rlim - the new resource limit
6041 + * Control raising the processes hard limit.
6043 +int aa_task_setrlimit(struct aa_profile *profile, unsigned int resource,
6044 + struct rlimit *new_rlim)
6046 + struct aa_audit sa;
6049 + memset(&sa, 0, sizeof(sa));
6050 + sa.operation = "setrlimit";
6051 + sa.gfp_mask = GFP_KERNEL;
6052 + sa.rlimit = resource + 1;
6054 + if (profile->rlimits.mask & (1 << resource) &&
6055 + new_rlim->rlim_max > profile->rlimits.limits[resource].rlim_max) {
6056 + sa.error_code = -EACCES;
6058 + error = aa_audit(profile, &sa);
6064 +static int aa_rlimit_nproc(struct aa_profile *profile) {
6065 + if (profile && (profile->rlimits.mask & (1 << RLIMIT_NPROC)) &&
6066 + profile->task_count >= profile->rlimits.limits[RLIMIT_NPROC].rlim_max)
6071 +void aa_set_rlimits(struct task_struct *task, struct aa_profile *profile)
6078 + if (!profile->rlimits.mask)
6081 + task_lock(task->group_leader);
6083 + for (i = 0; i < RLIM_NLIMITS; i++, mask <<= 1) {
6084 + struct rlimit new_rlim, *old_rlim;
6086 + /* check to see if NPROC which is per profile and handled
6087 + * in clone/exec or whether this is a limit to be set
6088 + * can't set cpu limit either right now
6090 + if (i == RLIMIT_NPROC || i == RLIMIT_CPU)
6093 + old_rlim = task->signal->rlim + i;
6094 + new_rlim = *old_rlim;
6096 + if (mask & profile->rlimits.mask &&
6097 + profile->rlimits.limits[i].rlim_max < new_rlim.rlim_max) {
6098 + new_rlim.rlim_max = profile->rlimits.limits[i].rlim_max;
6099 + /* soft limit should not exceed hard limit */
6100 + if (new_rlim.rlim_cur > new_rlim.rlim_max)
6101 + new_rlim.rlim_cur = new_rlim.rlim_max;
6104 + *old_rlim = new_rlim;
6106 + task_unlock(task->group_leader);
6109 +/*******************************
6110 + * Global task related functions
6111 + *******************************/
6114 + * aa_clone - initialize the task context for a new task
6115 + * @child: task that is being created
6117 + * Returns 0 on success, or else an error code.
6119 +int aa_clone(struct task_struct *child)
6121 + struct aa_audit sa;
6122 + struct aa_task_context *cxt, *child_cxt;
6123 + struct aa_profile *profile;
6125 + if (!aa_task_context(current))
6127 + child_cxt = aa_alloc_task_context(GFP_KERNEL);
6131 + memset(&sa, 0, sizeof(sa));
6132 + sa.operation = "clone";
6133 + sa.task = child->pid;
6134 + sa.gfp_mask = GFP_KERNEL;
6137 + profile = aa_get_profile(current);
6139 + lock_profile(profile);
6140 + cxt = aa_task_context(current);
6141 + if (unlikely(profile->isstale || !cxt ||
6142 + cxt->profile != profile)) {
6144 + * Race with profile replacement or removal, or with
6145 + * task context removal.
6147 + unlock_profile(profile);
6148 + aa_put_profile(profile);
6152 + if (aa_rlimit_nproc(profile)) {
6153 + sa.info = "rlimit nproc limit exceeded";
6154 + unlock_profile(profile);
6155 + aa_audit_reject(profile, &sa);
6156 + aa_put_profile(profile);
6160 + /* No need to grab the child's task lock here. */
6161 + aa_change_task_context(child, child_cxt, profile,
6162 + cxt->cookie, cxt->previous_profile);
6164 + unlock_profile(profile);
6166 + if (APPARMOR_COMPLAIN(child_cxt) &&
6167 + profile == profile->ns->null_complain_profile) {
6168 + aa_audit_hint(profile, &sa);
6170 + aa_put_profile(profile);
6172 + aa_free_task_context(child_cxt);
6177 +static struct aa_profile *
6178 +aa_register_find(struct aa_profile *profile, const char* ns_name,
6179 + const char *name, int mandatory, int complain,
6180 + struct aa_audit *sa)
6182 + struct aa_namespace *ns;
6183 + struct aa_profile *new_profile;
6189 + ns = default_namespace;
6192 + /* locate the profile namespace */
6193 + ns = aa_find_namespace(ns_name);
6196 + sa->info = "profile namespace not found";
6197 + sa->denied_mask = sa->request_mask;
6198 + sa->error_code = -ENOENT;
6199 + return ERR_PTR(-ENOENT);
6207 + /* Locate new profile */
6208 + new_profile = aa_find_profile(ns, name);
6210 + if (new_profile) {
6211 + AA_DEBUG("%s: setting profile %s\n",
6212 + __FUNCTION__, new_profile->name);
6213 + } else if (mandatory && profile) {
6214 + sa->info = "mandatory profile missing";
6215 + sa->denied_mask = sa->request_mask; /* shifted MAY_EXEC */
6217 + aa_audit_hint(profile, sa);
6219 + aa_dup_profile(profile->ns->null_complain_profile);
6221 + sa->error_code = -EACCES;
6223 + aa_put_namespace(ns);
6224 + return ERR_PTR(-EACCES);
6227 + /* Only way we can get into this code is if task
6228 + * is unconfined, pix, nix.
6230 + AA_DEBUG("%s: No profile found for exec image '%s'\n",
6235 + aa_put_namespace(ns);
6236 + return new_profile;
6239 +static struct aa_profile *
6240 +aa_x_to_profile(struct aa_profile *profile, const char *filename, int xmode,
6241 + struct aa_audit *sa, char **child)
6243 + struct aa_profile *new_profile = NULL;
6244 + int ix = xmode & AA_EXEC_INHERIT;
6245 + int complain = PROFILE_COMPLAIN(profile);
6249 + switch (xmode & AA_EXEC_MODIFIERS) {
6251 + /* only valid with ix flag */
6254 + case AA_EXEC_UNCONFINED:
6255 + /* only valid without ix flag */
6258 + case AA_EXEC_PROFILE:
6259 + new_profile = aa_register_find(profile, NULL, filename, !ix,
6262 + case AA_EXEC_CHILD:
6263 + *child = new_compound_name(profile->name, filename);
6264 + sa->name2 = *child;
6266 + sa->info = "Failed name resolution - exec failed";
6267 + sa->error_code = -ENOMEM;
6268 + new_profile = ERR_PTR(-ENOMEM);
6270 + new_profile = aa_register_find(profile, NULL, *child,
6271 + !ix, complain, sa);
6275 + /* all other indexes are named transitions */
6276 + index = AA_EXEC_INDEX(xmode);
6277 + if (index - 4 > profile->exec_table_size) {
6278 + sa->info = "invalid named transition - exec failed";
6279 + sa->error_code = -EACCES;
6280 + new_profile = ERR_PTR(-EACCES);
6282 + char *ns_name = NULL;
6283 + char *name = profile->exec_table[index - 4];
6284 + if (*name == ':') {
6285 + ns_name = name + 1;
6286 + name = ns_name + strlen(ns_name) + 1;
6289 + sa->name3 = ns_name;
6291 + aa_register_find(profile, ns_name, name,
6292 + !ix, complain, sa);
6295 + if (IS_ERR(new_profile))
6296 + /* all these failures must be audited - no quieting */
6297 + return ERR_PTR(aa_audit_reject(profile, sa));
6298 + return new_profile;
6302 + * aa_register - register a new program
6303 + * @bprm: binprm of program being registered
6305 + * Try to register a new program during execve(). This should give the
6306 + * new program a valid aa_task_context if confined.
6308 +int aa_register(struct linux_binprm *bprm)
6310 + const char *filename;
6311 + char *buffer = NULL, *child = NULL;
6312 + struct file *filp = bprm->file;
6313 + struct aa_profile *profile, *old_profile, *new_profile = NULL;
6314 + int exec_mode, complain = 0, shift;
6315 + struct aa_audit sa;
6317 + AA_DEBUG("%s\n", __FUNCTION__);
6319 + profile = aa_get_profile(current);
6321 + shift = aa_inode_mode(filp->f_dentry->d_inode);
6322 + memset(&sa, 0, sizeof(sa));
6323 + sa.operation = "exec";
6324 + sa.gfp_mask = GFP_KERNEL;
6325 + sa.request_mask = MAY_EXEC << shift;
6327 + filename = aa_get_name(filp->f_dentry, filp->f_vfsmnt, &buffer, 0);
6328 + if (IS_ERR(filename)) {
6330 + sa.info = "Failed name resolution - exec failed";
6331 + sa.error_code = PTR_ERR(filename);
6332 + aa_audit_file(profile, &sa);
6333 + return sa.error_code;
6337 + sa.name = filename;
6339 + exec_mode = AA_EXEC_UNSAFE << shift;
6343 + complain = PROFILE_COMPLAIN(profile);
6345 + /* Confined task, determine what mode inherit, unconfined or
6346 + * mandatory to load new profile
6348 + exec_mode = aa_match(profile->file_rules, filename,
6352 + if (exec_mode & sa.request_mask) {
6353 + int xm = exec_mode >> shift;
6354 + new_profile = aa_x_to_profile(profile, filename,
6357 + if (!new_profile && (xm & AA_EXEC_INHERIT))
6358 + /* (p|c|n|)ix - don't change profile */
6360 + /* error case caught below */
6362 + } else if (sa.request_mask & AUDIT_QUIET_MASK(sa.audit_mask)) {
6363 + /* quiet failed exit */
6364 + new_profile = ERR_PTR(-EACCES);
6365 + } else if (complain) {
6366 + /* There was no entry in calling profile
6367 + * describing mode to execute image in.
6368 + * Drop into null-profile (disabling secure exec).
6371 + aa_dup_profile(profile->ns->null_complain_profile);
6372 + exec_mode |= AA_EXEC_UNSAFE << shift;
6374 + sa.denied_mask = sa.request_mask;
6375 + sa.error_code = -EACCES;
6376 + new_profile = ERR_PTR(aa_audit_file(profile, &sa));
6379 + /* Unconfined task, load profile if it exists */
6380 + new_profile = aa_register_find(NULL, NULL, filename, 0, 0, &sa);
6381 + if (new_profile == NULL)
6385 + if (IS_ERR(new_profile))
6388 + old_profile = __aa_replace_profile(current, new_profile);
6389 + if (IS_ERR(old_profile)) {
6390 + aa_put_profile(new_profile);
6391 + aa_put_profile(profile);
6392 + if (PTR_ERR(old_profile) == -ESTALE) {
6393 + profile = aa_get_profile(current);
6396 + if (PTR_ERR(old_profile) == -EPERM) {
6397 + sa.denied_mask = sa.request_mask;
6398 + sa.info = "unable to set profile due to ptrace";
6399 + sa.task = current->parent->pid;
6400 + aa_audit_reject(profile, &sa);
6402 + if (PTR_ERR(old_profile) == -EAGAIN) {
6403 + sa.info = "rlimit nproc limit exceeded";
6404 + aa_audit_reject(profile, &sa);
6406 + new_profile = old_profile;
6409 + aa_put_profile(old_profile);
6410 + aa_put_profile(profile);
6412 + /* Handle confined exec.
6413 + * Can be at this point for the following reasons:
6414 + * 1. unconfined switching to confined
6415 + * 2. confined switching to different confinement
6416 + * 3. confined switching to unconfined
6418 + * Cases 2 and 3 are marked as requiring secure exec
6419 + * (unless policy specified "unsafe exec")
6421 + if (!(exec_mode & (AA_EXEC_UNSAFE << shift))) {
6422 + unsigned long bprm_flags;
6424 + bprm_flags = AA_SECURE_EXEC_NEEDED;
6425 + bprm->security = (void*)
6426 + ((unsigned long)bprm->security | bprm_flags);
6429 + if (complain && new_profile &&
6430 + new_profile == new_profile->ns->null_complain_profile) {
6431 + sa.request_mask = 0;
6433 + sa.info = "set profile";
6434 + aa_audit_hint(new_profile, &sa);
6438 + aa_put_name_buffer(child);
6439 + aa_put_name_buffer(buffer);
6440 + if (IS_ERR(new_profile))
6441 + return PTR_ERR(new_profile);
6442 + aa_put_profile(new_profile);
6447 + * aa_release - release a task context
6448 + * @task: task being released
6450 + * This is called after a task has exited and the parent has reaped it.
6452 +void aa_release(struct task_struct *task)
6454 + struct aa_task_context *cxt;
6455 + struct aa_profile *profile;
6457 + * While the task context is still on a profile's task context
6458 + * list, another process could replace the profile under us,
6459 + * leaving us with a locked profile that is no longer attached
6460 + * to this task. So after locking the profile, we check that
6461 + * the profile is still attached. The profile lock is
6462 + * sufficient to prevent the replacement race so we do not lock
6465 + * Use lock subtyping to avoid lockdep reporting a false irq
6466 + * possible inversion between the task_lock and profile_lock
6468 + * We also avoid taking the task_lock here because lock_dep
6469 + * would report another false {softirq-on-W} potential irq_lock
6472 + * If the task does not have a profile attached we are safe;
6473 + * nothing can race with us at this point.
6477 + profile = aa_get_profile(task);
6479 + lock_profile_nested(profile, aa_lock_task_release);
6480 + cxt = aa_task_context(task);
6481 + if (unlikely(!cxt || cxt->profile != profile)) {
6482 + unlock_profile(profile);
6483 + aa_put_profile(profile);
6486 + aa_change_task_context(task, NULL, NULL, 0, NULL);
6487 + unlock_profile(profile);
6488 + aa_put_profile(profile);
6492 +static int do_change_profile(struct aa_profile *expected,
6493 + struct aa_namespace *ns, const char *name,
6494 + u64 cookie, int restore, int hat,
6495 + struct aa_audit *sa)
6497 + struct aa_profile *new_profile = NULL, *old_profile = NULL,
6498 + *previous_profile = NULL;
6499 + struct aa_task_context *new_cxt, *cxt;
6504 + new_cxt = aa_alloc_task_context(GFP_KERNEL);
6508 + new_profile = aa_find_profile(ns, name);
6509 + if (!new_profile && !restore) {
6510 + if (!PROFILE_COMPLAIN(expected)) {
6511 + aa_free_task_context(new_cxt);
6514 + new_profile = aa_dup_profile(ns->null_complain_profile);
6515 + } else if (new_profile && hat && !PROFILE_IS_HAT(new_profile)) {
6516 + aa_free_task_context(new_cxt);
6517 + aa_put_profile(new_profile);
6521 + cxt = lock_task_and_profiles(current, new_profile);
6526 + old_profile = cxt->profile;
6528 + if (cxt->profile != expected || (new_profile && new_profile->isstale)) {
6533 + if (cxt->previous_profile) {
6534 + if (cxt->cookie != cookie) {
6536 + sa->info = "killing process";
6537 + aa_audit_reject(cxt->profile, sa);
6538 + /* terminate process */
6539 + (void)send_sig_info(SIGKILL, NULL, current);
6544 + previous_profile = cxt->previous_profile;
6546 + previous_profile = cxt->profile;
6548 + if ((current->ptrace & PT_PTRACED) && aa_may_ptrace(cxt, new_profile)) {
6553 + if ((error = aa_rlimit_nproc(new_profile))) {
6554 + sa->info = "rlimit nproc limit exceeded";
6555 + aa_audit_reject(cxt->profile, sa);
6559 + if (new_profile == ns->null_complain_profile)
6560 + aa_audit_hint(cxt->profile, sa);
6562 + if (APPARMOR_AUDIT(cxt))
6563 + aa_audit_message(cxt->profile, sa, AUDIT_APPARMOR_AUDIT);
6565 + if (!restore && cookie)
6566 + aa_change_task_context(current, new_cxt, new_profile, cookie,
6567 + previous_profile);
6569 + /* either return to previous_profile, or a permanent change */
6570 + aa_change_task_context(current, new_cxt, new_profile, 0, NULL);
6573 + if (aa_task_context(current) != new_cxt)
6574 + aa_free_task_context(new_cxt);
6575 + task_unlock(current);
6576 + unlock_both_profiles(old_profile, new_profile);
6577 + aa_put_profile(new_profile);
6582 + * aa_change_profile - perform a one-way profile transition
6583 + * @ns_name: name of the profile namespace to change to
6584 + * @name: name of profile to change to
6585 + * Change to new profile @name. Unlike with hats, there is no way
6588 + * Returns %0 on success, error otherwise.
6590 +int aa_change_profile(const char *ns_name, const char *name)
6592 + struct aa_task_context *cxt;
6593 + struct aa_profile *profile = NULL;
6594 + struct aa_namespace *ns = NULL;
6595 + struct aa_audit sa;
6596 + unsigned int state;
6597 + int error = -EINVAL;
6602 + memset(&sa, 0, sizeof(sa));
6603 + sa.gfp_mask = GFP_ATOMIC;
6604 + sa.operation = "change_profile";
6607 + task_lock(current);
6608 + cxt = aa_task_context(current);
6610 + profile = aa_dup_profile(cxt->profile);
6611 + task_unlock(current);
6614 + ns = aa_find_namespace(ns_name);
6616 + ns = aa_get_namespace(profile->ns);
6618 + ns = aa_get_namespace(default_namespace);
6621 + aa_put_profile(profile);
6625 + if (!profile || PROFILE_COMPLAIN(profile) ||
6626 + (ns == profile->ns &&
6627 + (aa_match(profile->file_rules, name, NULL) & AA_CHANGE_PROFILE)))
6628 + error = do_change_profile(profile, ns, name, 0, 0, 0, &sa);
6630 + /* check for a rule with a namespace prepended */
6631 + aa_match_state(profile->file_rules, DFA_START, ns->name,
6633 + state = aa_dfa_null_transition(profile->file_rules, state);
6634 + if ((aa_match_state(profile->file_rules, state, name, NULL) &
6635 + AA_CHANGE_PROFILE))
6636 + error = do_change_profile(profile, ns, name, 0, 0, 0,
6639 + /* no permission to transition to profile @name */
6643 + aa_put_namespace(ns);
6644 + aa_put_profile(profile);
6645 + if (error == -ESTALE)
6652 + * aa_change_hat - change hat to/from subprofile
6653 + * @hat_name: hat to change to
6654 + * @cookie: magic value to validate the hat change
6656 + * Change to new @hat_name, and store the @hat_magic in the current task
6657 + * context. If the new @hat_name is %NULL and the @cookie matches that
6658 + * stored in the current task context and is not 0, return to the top level
6660 + * Returns %0 on success, error otherwise.
6662 +int aa_change_hat(const char *hat_name, u64 cookie)
6664 + struct aa_task_context *cxt;
6665 + struct aa_profile *profile, *previous_profile;
6666 + struct aa_audit sa;
6669 + memset(&sa, 0, sizeof(sa));
6670 + sa.gfp_mask = GFP_ATOMIC;
6671 + sa.operation = "change_hat";
6674 + task_lock(current);
6675 + cxt = aa_task_context(current);
6677 + task_unlock(current);
6680 + profile = aa_dup_profile(cxt->profile);
6681 + previous_profile = aa_dup_profile(cxt->previous_profile);
6682 + task_unlock(current);
6685 + char *name, *profile_name;
6687 + if (previous_profile)
6688 + profile_name = previous_profile->name;
6690 + profile_name = profile->name;
6692 + name = new_compound_name(profile_name, hat_name);
6697 + error = do_change_profile(profile, profile->ns, name, cookie,
6699 + aa_put_name_buffer(name);
6700 + } else if (previous_profile)
6701 + error = do_change_profile(profile, profile->ns,
6702 + previous_profile->name, cookie, 1, 0,
6704 + /* else ignore restores when there is no saved profile */
6707 + aa_put_profile(previous_profile);
6708 + aa_put_profile(profile);
6709 + if (error == -ESTALE)
6716 + * __aa_replace_profile - replace a task's profile
6717 + * @task: task to switch the profile of
6718 + * @profile: profile to switch to
6720 + * Returns a handle to the previous profile upon success, or else an
6723 +struct aa_profile *__aa_replace_profile(struct task_struct *task,
6724 + struct aa_profile *profile)
6726 + struct aa_task_context *cxt, *new_cxt = NULL;
6727 + struct aa_profile *old_profile = NULL;
6730 + new_cxt = aa_alloc_task_context(GFP_KERNEL);
6732 + return ERR_PTR(-ENOMEM);
6735 + cxt = lock_task_and_profiles(task, profile);
6736 + if (unlikely(profile && profile->isstale)) {
6737 + old_profile = ERR_PTR(-ESTALE);
6741 + if ((current->ptrace & PT_PTRACED) && aa_may_ptrace(cxt, profile)) {
6742 + old_profile = ERR_PTR(-EPERM);
6746 + if (aa_rlimit_nproc(profile)) {
6747 + old_profile = ERR_PTR(-EAGAIN);
6752 + old_profile = aa_dup_profile(cxt->profile);
6753 + aa_change_task_context(task, new_cxt, profile, 0, NULL);
6755 + task_unlock(task);
6756 + aa_set_rlimits(task, profile);
6757 + unlock_both_profiles(profile, old_profile);
6758 + return old_profile;
6761 + task_unlock(task);
6762 + unlock_both_profiles(profile, cxt ? cxt->profile : NULL);
6763 + aa_free_task_context(new_cxt);
6764 + return old_profile;
6768 + * lock_task_and_profiles - lock the task and confining profiles and @profile
6769 + * @task: task to lock
6770 + * @profile: extra profile to lock in addition to the current profile
6772 + * Handle the spinning on locking to make sure the task context and
6773 + * profile are consistent once all locks are aquired.
6775 + * return the aa_task_context currently confining the task. The task lock
6776 + * will be held whether or not the task is confined.
6778 +struct aa_task_context *
6779 +lock_task_and_profiles(struct task_struct *task, struct aa_profile *profile)
6781 + struct aa_task_context *cxt;
6782 + struct aa_profile *old_profile = NULL;
6786 + cxt = aa_task_context(task);
6788 + old_profile = cxt->profile;
6790 + lock_both_profiles(profile, old_profile);
6793 + /* check for race with profile transition, replacement or removal */
6794 + if (unlikely(cxt != aa_task_context(task))) {
6795 + task_unlock(task);
6796 + unlock_both_profiles(profile, old_profile);
6797 + old_profile = NULL;
6800 + rcu_read_unlock();
6804 +static void free_aa_task_context_rcu_callback(struct rcu_head *head)
6806 + struct aa_task_context *cxt;
6808 + cxt = container_of(head, struct aa_task_context, rcu);
6809 + aa_free_task_context(cxt);
6813 + * aa_change_task_context - switch a task to use a new context and profile
6814 + * @task: task that is having its task context changed
6815 + * @new_cxt: new task context to use after the switch
6816 + * @profile: new profile to use after the switch
6817 + * @cookie: magic value to switch to
6818 + * @previous_profile: profile the task can return to
6820 +void aa_change_task_context(struct task_struct *task,
6821 + struct aa_task_context *new_cxt,
6822 + struct aa_profile *profile, u64 cookie,
6823 + struct aa_profile *previous_profile)
6825 + struct aa_task_context *old_cxt = aa_task_context(task);
6828 + list_del_init(&old_cxt->list);
6829 + old_cxt->profile->task_count--;
6830 + call_rcu(&old_cxt->rcu, free_aa_task_context_rcu_callback);
6833 + /* set the caps_logged cache to the quiet_caps mask
6834 + * this has the effect of quieting caps that are not
6835 + * supposed to be logged
6837 + new_cxt->caps_logged = profile->quiet_caps;
6838 + new_cxt->cookie = cookie;
6839 + new_cxt->task = task;
6840 + new_cxt->profile = aa_dup_profile(profile);
6841 + profile->task_count++;
6842 + new_cxt->previous_profile = aa_dup_profile(previous_profile);
6843 + list_move(&new_cxt->list, &profile->task_contexts);
6845 + rcu_assign_pointer(task->security, new_cxt);
6847 diff -uprN e/security/apparmor/match.c f/security/apparmor/match.c
6848 --- e/security/apparmor/match.c 1970-01-01 00:00:00.000000000 +0000
6849 +++ f/security/apparmor/match.c 2008-05-28 20:29:29.410207000 +0000
6852 + * Copyright (C) 2007 Novell/SUSE
6854 + * This program is free software; you can redistribute it and/or
6855 + * modify it under the terms of the GNU General Public License as
6856 + * published by the Free Software Foundation, version 2 of the
6859 + * Regular expression transition table matching
6862 +#include <linux/kernel.h>
6863 +#include <linux/slab.h>
6864 +#include <linux/errno.h>
6865 +#include "apparmor.h"
6867 +#include "inline.h"
6869 +static struct table_header *unpack_table(void *blob, size_t bsize)
6871 + struct table_header *table = NULL;
6872 + struct table_header th;
6875 + if (bsize < sizeof(struct table_header))
6878 + th.td_id = be16_to_cpu(*(u16 *) (blob));
6879 + th.td_flags = be16_to_cpu(*(u16 *) (blob + 2));
6880 + th.td_lolen = be32_to_cpu(*(u32 *) (blob + 8));
6881 + blob += sizeof(struct table_header);
6883 + if (!(th.td_flags == YYTD_DATA16 || th.td_flags == YYTD_DATA32 ||
6884 + th.td_flags == YYTD_DATA8))
6887 + tsize = table_size(th.td_lolen, th.td_flags);
6888 + if (bsize < tsize)
6891 + table = kmalloc(tsize, GFP_KERNEL);
6894 + if (th.td_flags == YYTD_DATA8)
6895 + UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
6896 + u8, byte_to_byte);
6897 + else if (th.td_flags == YYTD_DATA16)
6898 + UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
6899 + u16, be16_to_cpu);
6901 + UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
6902 + u32, be32_to_cpu);
6909 +int unpack_dfa(struct aa_dfa *dfa, void *blob, size_t size)
6912 + int error = -ENOMEM;
6914 + /* get dfa table set header */
6915 + if (size < sizeof(struct table_set_header))
6918 + if (ntohl(*(u32 *)blob) != YYTH_MAGIC)
6921 + hsize = ntohl(*(u32 *)(blob + 4));
6929 + while (size > 0) {
6930 + struct table_header *table;
6931 + table = unpack_table(blob, size);
6935 + switch(table->td_id) {
6936 + case YYTD_ID_ACCEPT:
6937 + case YYTD_ID_ACCEPT2:
6938 + case YYTD_ID_BASE:
6939 + dfa->tables[table->td_id - 1] = table;
6940 + if (table->td_flags != YYTD_DATA32)
6946 + dfa->tables[table->td_id - 1] = table;
6947 + if (table->td_flags != YYTD_DATA16)
6951 + dfa->tables[table->td_id - 1] = table;
6952 + if (table->td_flags != YYTD_DATA8)
6960 + blob += table_size(table->td_lolen, table->td_flags);
6961 + size -= table_size(table->td_lolen, table->td_flags);
6967 + for (i = 0; i < ARRAY_SIZE(dfa->tables); i++) {
6968 + if (dfa->tables[i]) {
6969 + kfree(dfa->tables[i]);
6970 + dfa->tables[i] = NULL;
6977 + * verify_dfa - verify that all the transitions and states in the dfa tables
6979 + * @dfa: dfa to test
6981 + * assumes dfa has gone through the verification done by unpacking
6983 +int verify_dfa(struct aa_dfa *dfa)
6985 + size_t i, state_count, trans_count;
6986 + int error = -EPROTO;
6988 + /* check that required tables exist */
6989 + if (!(dfa->tables[YYTD_ID_ACCEPT - 1] &&
6990 + dfa->tables[YYTD_ID_ACCEPT2 - 1] &&
6991 + dfa->tables[YYTD_ID_DEF - 1] &&
6992 + dfa->tables[YYTD_ID_BASE - 1] &&
6993 + dfa->tables[YYTD_ID_NXT - 1] &&
6994 + dfa->tables[YYTD_ID_CHK - 1]))
6997 + /* accept.size == default.size == base.size */
6998 + state_count = dfa->tables[YYTD_ID_BASE - 1]->td_lolen;
6999 + if (!(state_count == dfa->tables[YYTD_ID_DEF - 1]->td_lolen &&
7000 + state_count == dfa->tables[YYTD_ID_ACCEPT - 1]->td_lolen &&
7001 + state_count == dfa->tables[YYTD_ID_ACCEPT2 - 1]->td_lolen))
7004 + /* next.size == chk.size */
7005 + trans_count = dfa->tables[YYTD_ID_NXT - 1]->td_lolen;
7006 + if (trans_count != dfa->tables[YYTD_ID_CHK - 1]->td_lolen)
7009 + /* if equivalence classes then its table size must be 256 */
7010 + if (dfa->tables[YYTD_ID_EC - 1] &&
7011 + dfa->tables[YYTD_ID_EC - 1]->td_lolen != 256)
7014 + for (i = 0; i < state_count; i++) {
7015 + if (DEFAULT_TABLE(dfa)[i] >= state_count)
7017 + if (BASE_TABLE(dfa)[i] >= trans_count + 256)
7021 + for (i = 0; i < trans_count ; i++) {
7022 + if (NEXT_TABLE(dfa)[i] >= state_count)
7024 + if (CHECK_TABLE(dfa)[i] >= state_count)
7028 + /* verify accept permissions */
7029 + for (i = 0; i < state_count; i++) {
7030 + int mode = ACCEPT_TABLE(dfa)[i];
7032 + if (mode & ~AA_VALID_PERM_MASK)
7034 + if (ACCEPT_TABLE2(dfa)[i] & ~AA_VALID_PERM2_MASK)
7037 + /* if any exec modifier is set MAY_EXEC must be set */
7038 + if ((mode & AA_USER_EXEC_TYPE) && !(mode & AA_USER_EXEC))
7040 + if ((mode & AA_OTHER_EXEC_TYPE) && !(mode & AA_OTHER_EXEC))
7049 +struct aa_dfa *aa_match_alloc(void)
7051 + return kzalloc(sizeof(struct aa_dfa), GFP_KERNEL);
7054 +void aa_match_free(struct aa_dfa *dfa)
7059 + for (i = 0; i < ARRAY_SIZE(dfa->tables); i++)
7060 + kfree(dfa->tables[i]);
7066 + * aa_dfa_next_state_len - traverse @dfa to find state @str stops at
7067 + * @dfa: the dfa to match @str against
7068 + * @start: the state of the dfa to start matching in
7069 + * @str: the string of bytes to match against the dfa
7070 + * @len: length of the string of bytes to match
7072 + * aa_dfa_next_state will match @str against the dfa and return the state it
7073 + * finished matching in. The final state can be used to look up the accepting
7074 + * label, or as the start state of a continuing match.
7076 + * aa_dfa_next_state could be implement using this function by doing
7077 + * return aa_dfa_next_state_len(dfa, start, str, strlen(str));
7078 + * but that would require traversing the string twice and be slightly
7081 +unsigned int aa_dfa_next_state_len(struct aa_dfa *dfa, unsigned int start,
7082 + const char *str, int len)
7084 + u16 *def = DEFAULT_TABLE(dfa);
7085 + u32 *base = BASE_TABLE(dfa);
7086 + u16 *next = NEXT_TABLE(dfa);
7087 + u16 *check = CHECK_TABLE(dfa);
7088 + unsigned int state = start, pos;
7093 + /* current state is <state>, matching character *str */
7094 + if (dfa->tables[YYTD_ID_EC - 1]) {
7095 + u8 *equiv = EQUIV_TABLE(dfa);
7096 + for (; len; len--) {
7097 + pos = base[state] + equiv[(u8)*str++];
7098 + if (check[pos] == state)
7099 + state = next[pos];
7101 + state = def[state];
7104 + for (; len; len--) {
7105 + pos = base[state] + (u8)*str++;
7106 + if (check[pos] == state)
7107 + state = next[pos];
7109 + state = def[state];
7116 + * aa_dfa_next_state - traverse @dfa to find state @str stops at
7117 + * @dfa: the dfa to match @str against
7118 + * @start: the state of the dfa to start matching in
7119 + * @str: the null terminated string of bytes to match against the dfa
7121 + * aa_dfa_next_state will match @str against the dfa and return the state it
7122 + * finished matching in. The final state can be used to look up the accepting
7123 + * label, or as the start state of a continuing match.
7125 +unsigned int aa_dfa_next_state(struct aa_dfa *dfa, unsigned int start,
7128 + u16 *def = DEFAULT_TABLE(dfa);
7129 + u32 *base = BASE_TABLE(dfa);
7130 + u16 *next = NEXT_TABLE(dfa);
7131 + u16 *check = CHECK_TABLE(dfa);
7132 + unsigned int state = start, pos;
7137 + /* current state is <state>, matching character *str */
7138 + if (dfa->tables[YYTD_ID_EC - 1]) {
7139 + u8 *equiv = EQUIV_TABLE(dfa);
7141 + pos = base[state] + equiv[(u8)*str++];
7142 + if (check[pos] == state)
7143 + state = next[pos];
7145 + state = def[state];
7149 + pos = base[state] + (u8)*str++;
7150 + if (check[pos] == state)
7151 + state = next[pos];
7153 + state = def[state];
7160 + * aa_dfa_null_transition - step to next state after null character
7161 + * @dfa: the dfa to match against
7162 + * @start: the state of the dfa to start matching in
7164 + * aa_dfa_null_transition transitions to the next state after a null
7165 + * character which is not used in standard matching and is only
7166 + * used to seperate pairs.
7168 +unsigned int aa_dfa_null_transition(struct aa_dfa *dfa, unsigned int start)
7170 + return aa_dfa_next_state_len(dfa, start, "", 1);
7174 + * aa_dfa_match - find accept perm for @str in @dfa
7175 + * @dfa: the dfa to match @str against
7176 + * @str: the string to match against the dfa
7177 + * @audit_mask: the audit_mask for the final state
7179 + * aa_dfa_match will match @str and return the accept perms for the
7182 +unsigned int aa_dfa_match(struct aa_dfa *dfa, const char *str, int *audit_mask)
7184 + int state = aa_dfa_next_state(dfa, DFA_START, str);
7186 + *audit_mask = dfa_audit_mask(dfa, state);
7187 + return ACCEPT_TABLE(dfa)[state];
7191 + * aa_match_state - find accept perm and state for @str in @dfa
7192 + * @dfa: the dfa to match @str against
7193 + * @start: the state to start the match from
7194 + * @str: the string to match against the dfa
7195 + * @final: the state that the match finished in
7197 + * aa_match_state will match @str and return the accept perms, and @final
7198 + * state, the match occured in.
7200 +unsigned int aa_match_state(struct aa_dfa *dfa, unsigned int start,
7201 + const char *str, unsigned int *final)
7203 + unsigned int state;
7205 + state = aa_dfa_next_state(dfa, start, str);
7208 + return ACCEPT_TABLE(dfa)[state];
7215 diff -uprN e/security/apparmor/match.h f/security/apparmor/match.h
7216 --- e/security/apparmor/match.h 1970-01-01 00:00:00.000000000 +0000
7217 +++ f/security/apparmor/match.h 2008-05-28 20:29:29.410207000 +0000
7220 + * Copyright (C) 2007 Novell/SUSE
7222 + * This program is free software; you can redistribute it and/or
7223 + * modify it under the terms of the GNU General Public License as
7224 + * published by the Free Software Foundation, version 2 of the
7227 + * AppArmor submodule (match) prototypes
7233 +#define DFA_START 1
7236 + * The format used for transition tables is based on the GNU flex table
7237 + * file format (--tables-file option; see Table File Format in the flex
7238 + * info pages and the flex sources for documentation). The magic number
7239 + * used in the header is 0x1B5E783D insted of 0xF13C57B1 though, because
7240 + * the YY_ID_CHK (check) and YY_ID_DEF (default) tables are used
7241 + * slightly differently (see the apparmor-parser package).
7244 +#define YYTH_MAGIC 0x1B5E783D
7246 +struct table_set_header {
7247 + u32 th_magic; /* YYTH_MAGIC */
7251 + char th_version[];
7254 +#define YYTD_ID_ACCEPT 1
7255 +#define YYTD_ID_BASE 2
7256 +#define YYTD_ID_CHK 3
7257 +#define YYTD_ID_DEF 4
7258 +#define YYTD_ID_EC 5
7259 +#define YYTD_ID_META 6
7260 +#define YYTD_ID_ACCEPT2 7
7261 +#define YYTD_ID_NXT 8
7264 +#define YYTD_DATA8 1
7265 +#define YYTD_DATA16 2
7266 +#define YYTD_DATA32 4
7268 +struct table_header {
7276 +#define DEFAULT_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_DEF - 1]->td_data))
7277 +#define BASE_TABLE(DFA) ((u32 *)((DFA)->tables[YYTD_ID_BASE - 1]->td_data))
7278 +#define NEXT_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_NXT - 1]->td_data))
7279 +#define CHECK_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_CHK - 1]->td_data))
7280 +#define EQUIV_TABLE(DFA) ((u8 *)((DFA)->tables[YYTD_ID_EC - 1]->td_data))
7281 +#define ACCEPT_TABLE(DFA) ((u32 *)((DFA)->tables[YYTD_ID_ACCEPT - 1]->td_data))
7282 +#define ACCEPT_TABLE2(DFA) ((u32 *)((DFA)->tables[YYTD_ID_ACCEPT2 -1]->td_data))
7285 + struct table_header *tables[YYTD_ID_NXT];
7288 +#define byte_to_byte(X) (X)
7290 +#define UNPACK_ARRAY(TABLE, BLOB, LEN, TYPE, NTOHX) \
7292 + typeof(LEN) __i; \
7293 + TYPE *__t = (TYPE *) TABLE; \
7294 + TYPE *__b = (TYPE *) BLOB; \
7295 + for (__i = 0; __i < LEN; __i++) { \
7296 + __t[__i] = NTOHX(__b[__i]); \
7300 +static inline size_t table_size(size_t len, size_t el_size)
7302 + return ALIGN(sizeof(struct table_header) + len * el_size, 8);
7305 +#endif /* __MATCH_H */
7306 diff -uprN e/security/apparmor/module_interface.c f/security/apparmor/module_interface.c
7307 --- e/security/apparmor/module_interface.c 1970-01-01 00:00:00.000000000 +0000
7308 +++ f/security/apparmor/module_interface.c 2008-05-28 20:29:29.410207000 +0000
7311 + * Copyright (C) 1998-2007 Novell/SUSE
7313 + * This program is free software; you can redistribute it and/or
7314 + * modify it under the terms of the GNU General Public License as
7315 + * published by the Free Software Foundation, version 2 of the
7318 + * AppArmor userspace policy interface
7321 +#include <asm/unaligned.h>
7323 +#include "apparmor.h"
7324 +#include "inline.h"
7327 + * This mutex is used to synchronize profile adds, replacements, and
7328 + * removals: we only allow one of these operations at a time.
7329 + * We do not use the profile list lock here in order to avoid blocking
7330 + * exec during those operations. (Exec involves a profile list lookup
7331 + * for named-profile transitions.)
7333 +DEFINE_MUTEX(aa_interface_lock);
7336 + * The AppArmor interface treats data as a type byte followed by the
7337 + * actual data. The interface has the notion of a a named entry
7338 + * which has a name (AA_NAME typecode followed by name string) followed by
7339 + * the entries typecode and data. Named types allow for optional
7340 + * elements and extensions to be added and tested for without breaking
7341 + * backwards compatability.
7349 + AA_NAME, /* same as string except it is items name */
7361 + * aa_ext is the read of the buffer containing the serialized profile. The
7362 + * data is copied into a kernel buffer in apparmorfs and then handed off to
7363 + * the unpack routines.
7368 + void *pos; /* pointer to current position in the buffer */
7373 +static inline int aa_inbounds(struct aa_ext *e, size_t size)
7375 + return (size <= e->end - e->pos);
7379 + * aa_u16_chunck - test and do bounds checking for a u16 size based chunk
7380 + * @e: serialized data read head
7381 + * @chunk: start address for chunk of data
7383 + * return the size of chunk found with the read head at the end of
7386 +static size_t aa_is_u16_chunk(struct aa_ext *e, char **chunk)
7388 + void *pos = e->pos;
7391 + if (!aa_inbounds(e, sizeof(u16)))
7393 + size = le16_to_cpu(get_unaligned((u16 *)e->pos));
7394 + e->pos += sizeof(u16);
7395 + if (!aa_inbounds(e, size))
7406 +static inline int aa_is_X(struct aa_ext *e, enum aa_code code)
7408 + if (!aa_inbounds(e, 1))
7410 + if (*(u8 *) e->pos != code)
7417 + * aa_is_nameX - check is the next element is of type X with a name of @name
7418 + * @e: serialized data extent information
7419 + * @code: type code
7420 + * @name: name to match to the serialized element.
7422 + * check that the next serialized data element is of type X and has a tag
7423 + * name @name. If @name is specified then there must be a matching
7424 + * name element in the stream. If @name is NULL any name element will be
7425 + * skipped and only the typecode will be tested.
7426 + * returns 1 on success (both type code and name tests match) and the read
7427 + * head is advanced past the headers
7428 + * returns %0 if either match failes, the read head does not move
7430 +static int aa_is_nameX(struct aa_ext *e, enum aa_code code, const char *name)
7432 + void *pos = e->pos;
7434 + * Check for presence of a tagname, and if present name size
7435 + * AA_NAME tag value is a u16.
7437 + if (aa_is_X(e, AA_NAME)) {
7439 + size_t size = aa_is_u16_chunk(e, &tag);
7440 + /* if a name is specified it must match. otherwise skip tag */
7441 + if (name && (!size || strcmp(name, tag)))
7443 + } else if (name) {
7444 + /* if a name is specified and there is no name tag fail */
7448 + /* now check if type code matches */
7449 + if (aa_is_X(e, code))
7457 +static int aa_is_u16(struct aa_ext *e, u16 *data, const char *name)
7459 + void *pos = e->pos;
7460 + if (aa_is_nameX(e, AA_U16, name)) {
7461 + if (!aa_inbounds(e, sizeof(u16)))
7464 + *data = le16_to_cpu(get_unaligned((u16 *)e->pos));
7465 + e->pos += sizeof(u16);
7473 +static int aa_is_u32(struct aa_ext *e, u32 *data, const char *name)
7475 + void *pos = e->pos;
7476 + if (aa_is_nameX(e, AA_U32, name)) {
7477 + if (!aa_inbounds(e, sizeof(u32)))
7480 + *data = le32_to_cpu(get_unaligned((u32 *)e->pos));
7481 + e->pos += sizeof(u32);
7489 +static int aa_is_u64(struct aa_ext *e, u64 *data, const char *name)
7491 + void *pos = e->pos;
7492 + if (aa_is_nameX(e, AA_U64, name)) {
7493 + if (!aa_inbounds(e, sizeof(u64)))
7496 + *data = le64_to_cpu(get_unaligned((u64 *)e->pos));
7497 + e->pos += sizeof(u64);
7505 +static size_t aa_is_array(struct aa_ext *e, const char *name)
7507 + void *pos = e->pos;
7508 + if (aa_is_nameX(e, AA_ARRAY, name)) {
7510 + if (!aa_inbounds(e, sizeof(u16)))
7512 + size = (int) le16_to_cpu(get_unaligned((u16 *)e->pos));
7513 + e->pos += sizeof(u16);
7521 +static size_t aa_is_blob(struct aa_ext *e, char **blob, const char *name)
7523 + void *pos = e->pos;
7524 + if (aa_is_nameX(e, AA_BLOB, name)) {
7526 + if (!aa_inbounds(e, sizeof(u32)))
7528 + size = le32_to_cpu(get_unaligned((u32 *)e->pos));
7529 + e->pos += sizeof(u32);
7530 + if (aa_inbounds(e, (size_t) size)) {
7541 +static int aa_is_dynstring(struct aa_ext *e, char **string, const char *name)
7545 + void *pos = e->pos;
7547 + if (aa_is_nameX(e, AA_STRING, name) &&
7548 + (size = aa_is_u16_chunk(e, &src_str))) {
7550 + if (!(str = kmalloc(size, GFP_KERNEL)))
7552 + memcpy(str, src_str, size);
7564 + * aa_unpack_dfa - unpack a file rule dfa
7565 + * @e: serialized data extent information
7567 + * returns dfa or ERR_PTR
7569 +static struct aa_dfa *aa_unpack_dfa(struct aa_ext *e)
7571 + char *blob = NULL;
7572 + size_t size, error = 0;
7573 + struct aa_dfa *dfa = NULL;
7575 + size = aa_is_blob(e, &blob, "aadfa");
7577 + dfa = aa_match_alloc();
7580 + * The dfa is aligned with in the blob to 8 bytes
7581 + * from the beginning of the stream.
7583 + size_t sz = blob - (char *) e->start;
7584 + size_t pad = ALIGN(sz, 8) - sz;
7585 + error = unpack_dfa(dfa, blob + pad, size - pad);
7587 + error = verify_dfa(dfa);
7593 + aa_match_free(dfa);
7594 + dfa = ERR_PTR(error);
7601 +static int aa_unpack_exec_table(struct aa_ext *e, struct aa_profile *profile)
7603 + void *pos = e->pos;
7605 + /* exec table is optional */
7606 + if (aa_is_nameX(e, AA_STRUCT, "xtable")) {
7609 + size = aa_is_array(e, NULL);
7610 + /* currently 4 exec bits and entries 0-3 are reserved iupcx */
7611 + if (size > 16 - 4)
7613 + profile->exec_table = kzalloc(sizeof(char *) * size,
7615 + if (!profile->exec_table)
7618 + for (i = 0; i < size; i++) {
7620 + if (!aa_is_dynstring(e, &tmp, NULL))
7622 + /* note: strings beginning with a : have an embedded
7623 + \0 seperating the profile ns name from the profile
7625 + profile->exec_table[i] = tmp;
7627 + if (!aa_is_nameX(e, AA_ARRAYEND, NULL))
7629 + if (!aa_is_nameX(e, AA_STRUCTEND, NULL))
7639 +int aa_unpack_rlimits(struct aa_ext *e, struct aa_profile *profile)
7641 + void *pos = e->pos;
7643 + /* rlimits are optional */
7644 + if (aa_is_nameX(e, AA_STRUCT, "rlimits")) {
7647 + if (!aa_is_u32(e, &tmp, NULL))
7649 + profile->rlimits.mask = tmp;
7651 + size = aa_is_array(e, NULL);
7652 + if (size > RLIM_NLIMITS)
7654 + for (i = 0; i < size; i++) {
7656 + if (!aa_is_u64(e, &tmp, NULL))
7658 + profile->rlimits.limits[i].rlim_max = tmp;
7660 + if (!aa_is_nameX(e, AA_ARRAYEND, NULL))
7662 + if (!aa_is_nameX(e, AA_STRUCTEND, NULL))
7673 + * aa_unpack_profile - unpack a serialized profile
7674 + * @e: serialized data extent information
7675 + * @sa: audit struct for the operation
7677 +static struct aa_profile *aa_unpack_profile(struct aa_ext *e,
7678 + struct aa_audit *sa)
7680 + struct aa_profile *profile = NULL;
7682 + int i, error = -EPROTO;
7684 + profile = alloc_aa_profile();
7686 + return ERR_PTR(-ENOMEM);
7688 + /* check that we have the right struct being passed */
7689 + if (!aa_is_nameX(e, AA_STRUCT, "profile"))
7691 + if (!aa_is_dynstring(e, &profile->name, NULL))
7694 + /* per profile debug flags (complain, audit) */
7695 + if (!aa_is_nameX(e, AA_STRUCT, "flags"))
7697 + if (!aa_is_u32(e, &(profile->flags.hat), NULL))
7699 + if (!aa_is_u32(e, &(profile->flags.complain), NULL))
7701 + if (!aa_is_u32(e, &(profile->flags.audit), NULL))
7703 + if (!aa_is_nameX(e, AA_STRUCTEND, NULL))
7706 + if (!aa_is_u32(e, &(profile->capabilities.cap[0]), NULL))
7708 + if (!aa_is_u32(e, &(profile->audit_caps.cap[0]), NULL))
7710 + if (!aa_is_u32(e, &(profile->quiet_caps.cap[0]), NULL))
7712 + if (!aa_is_u32(e, &(profile->set_caps.cap[0]), NULL))
7715 + if (aa_is_nameX(e, AA_STRUCT, "caps64")) {
7716 + /* optional upper half of 64 bit caps */
7717 + if (!aa_is_u32(e, &(profile->capabilities.cap[1]), NULL))
7719 + if (!aa_is_u32(e, &(profile->audit_caps.cap[1]), NULL))
7721 + if (!aa_is_u32(e, &(profile->quiet_caps.cap[1]), NULL))
7723 + if (!aa_is_u32(e, &(profile->set_caps.cap[1]), NULL))
7725 + if (!aa_is_nameX(e, AA_STRUCTEND, NULL))
7729 + if (!aa_unpack_rlimits(e, profile))
7732 + size = aa_is_array(e, "net_allowed_af");
7734 + if (size > AF_MAX)
7737 + for (i = 0; i < size; i++) {
7738 + if (!aa_is_u16(e, &profile->network_families[i], NULL))
7740 + if (!aa_is_u16(e, &profile->audit_network[i], NULL))
7742 + if (!aa_is_u16(e, &profile->quiet_network[i], NULL))
7745 + if (!aa_is_nameX(e, AA_ARRAYEND, NULL))
7747 + /* allow unix domain and netlink sockets they are handled
7751 + profile->network_families[AF_UNIX] = 0xffff;
7752 + profile->network_families[AF_NETLINK] = 0xffff;
7754 + /* get file rules */
7755 + profile->file_rules = aa_unpack_dfa(e);
7756 + if (IS_ERR(profile->file_rules)) {
7757 + error = PTR_ERR(profile->file_rules);
7758 + profile->file_rules = NULL;
7762 + if (!aa_unpack_exec_table(e, profile))
7765 + if (!aa_is_nameX(e, AA_STRUCTEND, NULL))
7771 + sa->name = profile && profile->name ? profile->name : "unknown";
7773 + sa->info = "failed to unpack profile";
7774 + aa_audit_status(NULL, sa);
7777 + free_aa_profile(profile);
7779 + return ERR_PTR(error);
7783 + * aa_verify_head - unpack serialized stream header
7784 + * @e: serialized data read head
7785 + * @operation: operation header is being verified for
7787 + * returns error or 0 if header is good
7789 +static int aa_verify_header(struct aa_ext *e, struct aa_audit *sa)
7791 + /* get the interface version */
7792 + if (!aa_is_u32(e, &e->version, "version")) {
7793 + sa->info = "invalid profile format";
7794 + aa_audit_status(NULL, sa);
7795 + return -EPROTONOSUPPORT;
7798 + /* check that the interface version is currently supported */
7799 + if (e->version != 5) {
7800 + sa->info = "unsupported interface version";
7801 + aa_audit_status(NULL, sa);
7802 + return -EPROTONOSUPPORT;
7805 + /* read the namespace if present */
7806 + if (!aa_is_dynstring(e, &e->ns_name, "namespace")) {
7807 + e->ns_name = NULL;
7814 + * aa_add_profile - Unpack and add a new profile to the profile list
7815 + * @data: serialized data stream
7816 + * @size: size of the serialized data stream
7818 +ssize_t aa_add_profile(void *data, size_t size)
7820 + struct aa_profile *profile = NULL;
7821 + struct aa_namespace *ns = NULL;
7822 + struct aa_ext e = {
7824 + .end = data + size,
7829 + struct aa_audit sa;
7830 + memset(&sa, 0, sizeof(sa));
7831 + sa.operation = "profile_load";
7832 + sa.gfp_mask = GFP_KERNEL;
7834 + error = aa_verify_header(&e, &sa);
7838 + profile = aa_unpack_profile(&e, &sa);
7839 + if (IS_ERR(profile))
7840 + return PTR_ERR(profile);
7842 + mutex_lock(&aa_interface_lock);
7843 + write_lock(&profile_ns_list_lock);
7845 + ns = __aa_find_namespace(e.ns_name, &profile_ns_list);
7847 + ns = default_namespace;
7849 + struct aa_namespace *new_ns;
7850 + write_unlock(&profile_ns_list_lock);
7851 + new_ns = alloc_aa_namespace(e.ns_name);
7853 + mutex_unlock(&aa_interface_lock);
7856 + write_lock(&profile_ns_list_lock);
7857 + ns = __aa_find_namespace(e.ns_name, &profile_ns_list);
7859 + list_add(&new_ns->list, &profile_ns_list);
7862 + free_aa_namespace(new_ns);
7865 + write_lock(&ns->lock);
7866 + if (__aa_find_profile(profile->name, &ns->profiles)) {
7867 + /* A profile with this name exists already. */
7868 + write_unlock(&ns->lock);
7869 + write_unlock(&profile_ns_list_lock);
7870 + sa.name = profile->name;
7871 + sa.name2 = ns->name;
7872 + sa.info = "failed: profile already loaded";
7873 + aa_audit_status(NULL, &sa);
7874 + mutex_unlock(&aa_interface_lock);
7875 + aa_put_profile(profile);
7878 + profile->ns = aa_get_namespace(ns);
7879 + ns->profile_count++;
7880 + list_add(&profile->list, &ns->profiles);
7881 + write_unlock(&ns->lock);
7882 + write_unlock(&profile_ns_list_lock);
7884 + sa.name = profile->name;
7885 + sa.name2 = ns->name;
7886 + aa_audit_status(NULL, &sa);
7887 + mutex_unlock(&aa_interface_lock);
7892 + * task_replace - replace a task's profile
7893 + * @task: task to replace profile on
7894 + * @new_cxt: new aa_task_context to do replacement with
7895 + * @new_profile: new profile
7897 +static inline void task_replace(struct task_struct *task,
7898 + struct aa_task_context *new_cxt,
7899 + struct aa_profile *new_profile)
7901 + struct aa_task_context *cxt = aa_task_context(task);
7903 + AA_DEBUG("%s: replacing profile for task %d "
7904 + "profile=%s (%p)\n",
7907 + cxt->profile->name, cxt->profile);
7909 + aa_change_task_context(task, new_cxt, new_profile, cxt->cookie,
7910 + cxt->previous_profile);
7914 + * aa_replace_profile - replace a profile on the profile list
7915 + * @udata: serialized data stream
7916 + * @size: size of the serialized data stream
7918 + * unpack and replace a profile on the profile list and uses of that profile
7919 + * by any aa_task_context. If the profile does not exist on the profile list
7920 + * it is added. Return %0 or error.
7922 +ssize_t aa_replace_profile(void *udata, size_t size)
7924 + struct aa_profile *old_profile, *new_profile;
7925 + struct aa_namespace *ns;
7926 + struct aa_task_context *new_cxt;
7927 + struct aa_ext e = {
7929 + .end = udata + size,
7934 + struct aa_audit sa;
7935 + memset(&sa, 0, sizeof(sa));
7936 + sa.operation = "profile_replace";
7937 + sa.gfp_mask = GFP_KERNEL;
7939 + error = aa_verify_header(&e, &sa);
7943 + new_profile = aa_unpack_profile(&e, &sa);
7944 + if (IS_ERR(new_profile))
7945 + return PTR_ERR(new_profile);
7947 + mutex_lock(&aa_interface_lock);
7948 + write_lock(&profile_ns_list_lock);
7950 + ns = __aa_find_namespace(e.ns_name, &profile_ns_list);
7952 + ns = default_namespace;
7954 + struct aa_namespace *new_ns;
7955 + write_unlock(&profile_ns_list_lock);
7956 + new_ns = alloc_aa_namespace(e.ns_name);
7958 + mutex_unlock(&aa_interface_lock);
7961 + write_lock(&profile_ns_list_lock);
7962 + ns = __aa_find_namespace(e.ns_name, &profile_ns_list);
7964 + list_add(&new_ns->list, &profile_ns_list);
7967 + free_aa_namespace(new_ns);
7970 + write_lock(&ns->lock);
7971 + old_profile = __aa_find_profile(new_profile->name, &ns->profiles);
7972 + if (old_profile) {
7973 + lock_profile(old_profile);
7974 + old_profile->isstale = 1;
7975 + list_del_init(&old_profile->list);
7976 + unlock_profile(old_profile);
7977 + ns->profile_count--;
7979 + new_profile->ns = aa_get_namespace(ns);
7980 + ns->profile_count++;
7981 + /* not don't need an extra ref count to keep new_profile as
7982 + * it is protect by the interface mutex */
7983 + list_add(&new_profile->list, &ns->profiles);
7984 + write_unlock(&ns->lock);
7985 + write_unlock(&profile_ns_list_lock);
7987 + if (!old_profile) {
7988 + sa.operation = "profile_load";
7991 + /* do not fail replacement based off of profile's NPROC rlimit */
7994 + * Replacement needs to allocate a new aa_task_context for each
7995 + * task confined by old_profile. To do this the profile locks
7996 + * are only held when the actual switch is done per task. While
7997 + * looping to allocate a new aa_task_context the old_task list
7998 + * may get shorter if tasks exit/change their profile but will
7999 + * not get longer as new task will not use old_profile detecting
8003 + new_cxt = aa_alloc_task_context(GFP_KERNEL | __GFP_NOFAIL);
8005 + lock_both_profiles(old_profile, new_profile);
8006 + if (!list_empty(&old_profile->task_contexts)) {
8007 + struct task_struct *task =
8008 + list_entry(old_profile->task_contexts.next,
8009 + struct aa_task_context, list)->task;
8011 + task_replace(task, new_cxt, new_profile);
8012 + task_unlock(task);
8013 + aa_set_rlimits(task, new_profile);
8016 + unlock_both_profiles(old_profile, new_profile);
8017 + } while (!new_cxt);
8018 + aa_free_task_context(new_cxt);
8019 + aa_put_profile(old_profile);
8022 + sa.name = new_profile->name;
8023 + sa.name2 = ns->name;
8024 + aa_audit_status(NULL, &sa);
8025 + mutex_unlock(&aa_interface_lock);
8030 + * aa_remove_profile - remove a profile from the system
8031 + * @name: name of the profile to remove
8032 + * @size: size of the name
8034 + * remove a profile from the profile list and all aa_task_context references
8035 + * to said profile.
8036 + * NOTE: removing confinement does not restore rlimits to preconfinemnet values
8038 +ssize_t aa_remove_profile(char *name, size_t size)
8040 + struct aa_namespace *ns;
8041 + struct aa_profile *profile;
8042 + struct aa_audit sa;
8043 + memset(&sa, 0, sizeof(sa));
8044 + sa.operation = "profile_remove";
8045 + sa.gfp_mask = GFP_KERNEL;
8047 + mutex_lock(&aa_interface_lock);
8048 + write_lock(&profile_ns_list_lock);
8050 + if (name[0] == ':') {
8051 + char *split = strchr(name + 1, ':');
8055 + ns = __aa_find_namespace(name + 1, &profile_ns_list);
8058 + ns = default_namespace;
8063 + sa.name2 = ns->name;
8064 + write_lock(&ns->lock);
8065 + profile = __aa_find_profile(name, &ns->profiles);
8067 + write_unlock(&ns->lock);
8070 + sa.name = profile->name;
8072 + /* Remove the profile from each task context it is on. */
8073 + lock_profile(profile);
8074 + profile->isstale = 1;
8075 + aa_unconfine_tasks(profile);
8076 + list_del_init(&profile->list);
8077 + ns->profile_count--;
8078 + unlock_profile(profile);
8079 + /* Release the profile itself. */
8080 + write_unlock(&ns->lock);
8081 + /* check to see if the namespace has become stale */
8082 + if (ns != default_namespace && ns->profile_count == 0) {
8083 + list_del_init(&ns->list);
8084 + aa_put_namespace(ns);
8086 + write_unlock(&profile_ns_list_lock);
8088 + aa_audit_status(NULL, &sa);
8089 + mutex_unlock(&aa_interface_lock);
8090 + aa_put_profile(profile);
8095 + write_unlock(&profile_ns_list_lock);
8096 + sa.info = "failed: profile does not exist";
8097 + aa_audit_status(NULL, &sa);
8098 + mutex_unlock(&aa_interface_lock);
8103 + * free_aa_namespace_kref - free aa_namespace by kref (see aa_put_namespace)
8104 + * @kr: kref callback for freeing of a namespace
8106 +void free_aa_namespace_kref(struct kref *kref)
8108 + struct aa_namespace *ns=container_of(kref, struct aa_namespace, count);
8110 + free_aa_namespace(ns);
8114 + * alloc_aa_namespace - allocate, initialize and return a new namespace
8115 + * @name: a preallocated name
8116 + * Returns NULL on failure.
8118 +struct aa_namespace *alloc_aa_namespace(char *name)
8120 + struct aa_namespace *ns;
8122 + ns = kzalloc(sizeof(*ns), GFP_KERNEL);
8123 + AA_DEBUG("%s(%p)\n", __FUNCTION__, ns);
8126 + INIT_LIST_HEAD(&ns->list);
8127 + INIT_LIST_HEAD(&ns->profiles);
8128 + kref_init(&ns->count);
8129 + rwlock_init(&ns->lock);
8131 + ns->null_complain_profile = alloc_aa_profile();
8132 + if (!ns->null_complain_profile) {
8138 + ns->null_complain_profile->name =
8139 + kstrdup("null-complain-profile", GFP_KERNEL);
8140 + if (!ns->null_complain_profile->name) {
8141 + free_aa_profile(ns->null_complain_profile);
8147 + ns->null_complain_profile->flags.complain = 1;
8148 + /* null_complain_profile doesn't contribute to ns ref count */
8149 + ns->null_complain_profile->ns = ns;
8155 + * free_aa_namespace - free a profile namespace
8156 + * @namespace: the namespace to free
8158 + * Free a namespace. All references to the namespace must have been put.
8159 + * If the namespace was referenced by a profile confining a task,
8160 + * free_aa_namespace will be called indirectly (through free_aa_profile)
8161 + * from an rcu callback routine, so we must not sleep here.
8163 +void free_aa_namespace(struct aa_namespace *ns)
8165 + AA_DEBUG("%s(%p)\n", __FUNCTION__, ns);
8170 + /* namespace still contains profiles -- invalid */
8171 + if (!list_empty(&ns->profiles)) {
8172 + AA_ERROR("%s: internal error, "
8173 + "namespace '%s' still contains profiles\n",
8178 + if (!list_empty(&ns->list)) {
8179 + AA_ERROR("%s: internal error, "
8180 + "namespace '%s' still on list\n",
8185 + /* null_complain_profile doesn't contribute to ns ref counting */
8186 + ns->null_complain_profile->ns = NULL;
8187 + aa_put_profile(ns->null_complain_profile);
8193 + * free_aa_profile_kref - free aa_profile by kref (called by aa_put_profile)
8194 + * @kr: kref callback for freeing of a profile
8196 +void free_aa_profile_kref(struct kref *kref)
8198 + struct aa_profile *p=container_of(kref, struct aa_profile, count);
8200 + free_aa_profile(p);
8204 + * alloc_aa_profile - allocate, initialize and return a new profile
8205 + * Returns NULL on failure.
8207 +struct aa_profile *alloc_aa_profile(void)
8209 + struct aa_profile *profile;
8211 + profile = kzalloc(sizeof(*profile), GFP_KERNEL);
8212 + AA_DEBUG("%s(%p)\n", __FUNCTION__, profile);
8214 + INIT_LIST_HEAD(&profile->list);
8215 + kref_init(&profile->count);
8216 + INIT_LIST_HEAD(&profile->task_contexts);
8217 + spin_lock_init(&profile->lock);
8223 + * free_aa_profile - free a profile
8224 + * @profile: the profile to free
8226 + * Free a profile, its hats and null_profile. All references to the profile,
8227 + * its hats and null_profile must have been put.
8229 + * If the profile was referenced from a task context, free_aa_profile() will
8230 + * be called from an rcu callback routine, so we must not sleep here.
8232 +void free_aa_profile(struct aa_profile *profile)
8234 + AA_DEBUG("%s(%p)\n", __FUNCTION__, profile);
8239 + /* profile is still on profile namespace list -- invalid */
8240 + if (!list_empty(&profile->list)) {
8241 + AA_ERROR("%s: internal error, "
8242 + "profile '%s' still on global list\n",
8247 + aa_put_namespace(profile->ns);
8249 + aa_match_free(profile->file_rules);
8251 + if (profile->name) {
8252 + AA_DEBUG("%s: %s\n", __FUNCTION__, profile->name);
8253 + kfree(profile->name);
8260 + * aa_unconfine_tasks - remove tasks on a profile's task context list
8261 + * @profile: profile to remove tasks from
8263 + * Assumes that @profile lock is held.
8265 +void aa_unconfine_tasks(struct aa_profile *profile)
8267 + while (!list_empty(&profile->task_contexts)) {
8268 + struct task_struct *task =
8269 + list_entry(profile->task_contexts.next,
8270 + struct aa_task_context, list)->task;
8272 + aa_change_task_context(task, NULL, NULL, 0, NULL);
8273 + task_unlock(task);
8276 diff -uprN e/security/apparmor/procattr.c f/security/apparmor/procattr.c
8277 --- e/security/apparmor/procattr.c 1970-01-01 00:00:00.000000000 +0000
8278 +++ f/security/apparmor/procattr.c 2008-05-28 20:29:29.410207000 +0000
8281 + * Copyright (C) 1998-2007 Novell/SUSE
8283 + * This program is free software; you can redistribute it and/or
8284 + * modify it under the terms of the GNU General Public License as
8285 + * published by the Free Software Foundation, version 2 of the
8288 + * AppArmor /proc/pid/attr handling
8291 +#include "apparmor.h"
8292 +#include "inline.h"
8294 +int aa_getprocattr(struct aa_profile *profile, char **string, unsigned *len)
8299 + const char *mode_str = PROFILE_COMPLAIN(profile) ?
8300 + " (complain)" : " (enforce)";
8301 + int mode_len, name_len, ns_len = 0;
8303 + mode_len = strlen(mode_str);
8304 + name_len = strlen(profile->name);
8305 + if (profile->ns != default_namespace)
8306 + ns_len = strlen(profile->ns->name) + 2;
8307 + *len = mode_len + ns_len + name_len + 1;
8308 + str = kmalloc(*len, GFP_ATOMIC);
8314 + memcpy(str, profile->ns->name, ns_len - 2);
8315 + str += ns_len - 2;
8318 + memcpy(str, profile->name, name_len);
8320 + memcpy(str, mode_str, mode_len);
8325 + const char *unconfined_str = "unconfined\n";
8327 + *len = strlen(unconfined_str);
8328 + str = kmalloc(*len, GFP_ATOMIC);
8332 + memcpy(str, unconfined_str, *len);
8339 +static char *split_token_from_name(const char *op, char *args, u64 *cookie)
8343 + *cookie = simple_strtoull(args, &name, 16);
8344 + if ((name == args) || *name != '^') {
8345 + AA_ERROR("%s: Invalid input '%s'", op, args);
8346 + return ERR_PTR(-EINVAL);
8349 + name++; /* skip ^ */
8355 +int aa_setprocattr_changehat(char *args)
8360 + hat = split_token_from_name("change_hat", args, &cookie);
8362 + return PTR_ERR(hat);
8364 + if (!hat && !cookie) {
8365 + AA_ERROR("change_hat: Invalid input, NULL hat and NULL magic");
8369 + AA_DEBUG("%s: Magic 0x%llx Hat '%s'\n",
8370 + __FUNCTION__, cookie, hat ? hat : NULL);
8372 + return aa_change_hat(hat, cookie);
8375 +int aa_setprocattr_changeprofile(char *args)
8377 + char *name = args, *ns_name = NULL;
8379 + if (name[0] == ':') {
8380 + char *split = strchr(&name[1], ':');
8383 + ns_name = &name[1];
8388 + return aa_change_profile(ns_name, name);
8391 +int aa_setprocattr_setprofile(struct task_struct *task, char *args)
8393 + struct aa_profile *old_profile, *new_profile;
8394 + struct aa_namespace *ns;
8395 + struct aa_audit sa;
8396 + char *name, *ns_name = NULL;
8398 + memset(&sa, 0, sizeof(sa));
8399 + sa.operation = "profile_set";
8400 + sa.gfp_mask = GFP_KERNEL;
8401 + sa.task = task->pid;
8403 + AA_DEBUG("%s: current %d\n",
8404 + __FUNCTION__, current->pid);
8407 + if (args[0] != '/') {
8408 + char *split = strchr(args, ':');
8416 + ns = aa_find_namespace(ns_name);
8418 + ns = aa_get_namespace(default_namespace);
8420 + sa.name = ns_name;
8421 + sa.info = "unknown namespace";
8422 + aa_audit_reject(NULL, &sa);
8423 + aa_put_namespace(ns);
8428 + if (strcmp(name, "unconfined") == 0)
8429 + new_profile = NULL;
8431 + new_profile = aa_find_profile(ns, name);
8432 + if (!new_profile) {
8433 + sa.name = ns_name;
8435 + sa.info = "unknown profile";
8436 + aa_audit_reject(NULL, &sa);
8437 + aa_put_namespace(ns);
8442 + old_profile = __aa_replace_profile(task, new_profile);
8443 + if (IS_ERR(old_profile)) {
8446 + aa_put_profile(new_profile);
8447 + error = PTR_ERR(old_profile);
8448 + if (error == -ESTALE)
8450 + aa_put_namespace(ns);
8454 + if (new_profile) {
8455 + sa.name = ns_name;
8457 + sa.name3 = old_profile ? old_profile->name :
8459 + aa_audit_status(NULL, &sa);
8461 + if (old_profile) {
8462 + sa.name = "unconfined";
8463 + sa.name2 = old_profile->name;
8464 + aa_audit_status(NULL, &sa);
8466 + sa.info = "task is unconfined";
8467 + aa_audit_status(NULL, &sa);
8470 + aa_put_namespace(ns);
8471 + aa_put_profile(old_profile);
8472 + aa_put_profile(new_profile);
8475 diff -uprN e/security/commoncap.c f/security/commoncap.c
8476 --- e/security/commoncap.c 2008-04-17 02:49:44.000000000 +0000
8477 +++ f/security/commoncap.c 2008-05-28 20:29:29.410207000 +0000
8478 @@ -386,8 +386,8 @@ int cap_bprm_secureexec (struct linux_bi
8479 current->egid != current->gid);
8482 -int cap_inode_setxattr(struct dentry *dentry, char *name, void *value,
8483 - size_t size, int flags)
8484 +int cap_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt, char *name,
8485 + void *value, size_t size, int flags, struct file *file)
8487 if (!strcmp(name, XATTR_NAME_CAPS)) {
8488 if (!capable(CAP_SETFCAP))
8489 @@ -400,7 +400,8 @@ int cap_inode_setxattr(struct dentry *de
8493 -int cap_inode_removexattr(struct dentry *dentry, char *name)
8494 +int cap_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
8495 + char *name, struct file *file)
8497 if (!strcmp(name, XATTR_NAME_CAPS)) {
8498 if (!capable(CAP_SETFCAP))
8499 diff -uprN e/security/dummy.c f/security/dummy.c
8500 --- e/security/dummy.c 2008-04-17 02:49:44.000000000 +0000
8501 +++ f/security/dummy.c 2008-05-28 20:29:29.410207000 +0000
8502 @@ -287,54 +287,60 @@ static int dummy_inode_init_security (st
8505 static int dummy_inode_create (struct inode *inode, struct dentry *dentry,
8507 + struct vfsmount *mnt, int mask)
8512 -static int dummy_inode_link (struct dentry *old_dentry, struct inode *inode,
8513 - struct dentry *new_dentry)
8514 +static int dummy_inode_link (struct dentry *old_dentry,
8515 + struct vfsmount *old_mnt, struct inode *inode,
8516 + struct dentry *new_dentry,
8517 + struct vfsmount *new_mnt)
8522 -static int dummy_inode_unlink (struct inode *inode, struct dentry *dentry)
8523 +static int dummy_inode_unlink (struct inode *inode, struct dentry *dentry,
8524 + struct vfsmount *mnt)
8529 static int dummy_inode_symlink (struct inode *inode, struct dentry *dentry,
8531 + struct vfsmount *mnt, const char *name)
8536 static int dummy_inode_mkdir (struct inode *inode, struct dentry *dentry,
8538 + struct vfsmount *mnt, int mask)
8543 -static int dummy_inode_rmdir (struct inode *inode, struct dentry *dentry)
8544 +static int dummy_inode_rmdir (struct inode *inode, struct dentry *dentry,
8545 + struct vfsmount *mnt)
8550 static int dummy_inode_mknod (struct inode *inode, struct dentry *dentry,
8551 - int mode, dev_t dev)
8552 + struct vfsmount *mnt, int mode, dev_t dev)
8557 static int dummy_inode_rename (struct inode *old_inode,
8558 struct dentry *old_dentry,
8559 + struct vfsmount *old_mnt,
8560 struct inode *new_inode,
8561 - struct dentry *new_dentry)
8562 + struct dentry *new_dentry,
8563 + struct vfsmount *new_mnt)
8568 -static int dummy_inode_readlink (struct dentry *dentry)
8569 +static int dummy_inode_readlink (struct dentry *dentry, struct vfsmount *mnt)
8573 @@ -350,7 +356,8 @@ static int dummy_inode_permission (struc
8577 -static int dummy_inode_setattr (struct dentry *dentry, struct iattr *iattr)
8578 +static int dummy_inode_setattr (struct dentry *dentry, struct vfsmount *mnt,
8579 + struct iattr *iattr)
8583 @@ -365,8 +372,9 @@ static void dummy_inode_delete (struct i
8587 -static int dummy_inode_setxattr (struct dentry *dentry, char *name, void *value,
8588 - size_t size, int flags)
8589 +static int dummy_inode_setxattr (struct dentry *dentry, struct vfsmount *mnt,
8590 + char *name, void *value, size_t size,
8591 + int flags, struct file *file)
8593 if (!strncmp(name, XATTR_SECURITY_PREFIX,
8594 sizeof(XATTR_SECURITY_PREFIX) - 1) &&
8595 @@ -375,22 +383,28 @@ static int dummy_inode_setxattr (struct
8599 -static void dummy_inode_post_setxattr (struct dentry *dentry, char *name, void *value,
8600 +static void dummy_inode_post_setxattr (struct dentry *dentry,
8601 + struct vfsmount *mnt,
8602 + char *name, void *value,
8603 size_t size, int flags)
8607 -static int dummy_inode_getxattr (struct dentry *dentry, char *name)
8608 +static int dummy_inode_getxattr (struct dentry *dentry,
8609 + struct vfsmount *mnt, char *name,
8610 + struct file *file)
8615 -static int dummy_inode_listxattr (struct dentry *dentry)
8616 +static int dummy_inode_listxattr (struct dentry *dentry, struct vfsmount *mnt,
8617 + struct file *file)
8622 -static int dummy_inode_removexattr (struct dentry *dentry, char *name)
8623 +static int dummy_inode_removexattr (struct dentry *dentry, struct vfsmount *mnt,
8624 + char *name, struct file *file)
8626 if (!strncmp(name, XATTR_SECURITY_PREFIX,
8627 sizeof(XATTR_SECURITY_PREFIX) - 1) &&
8628 diff -uprN e/security/security.c f/security/security.c
8629 --- e/security/security.c 2008-04-17 02:49:44.000000000 +0000
8630 +++ f/security/security.c 2008-05-28 20:29:29.410207000 +0000
8631 @@ -352,72 +352,80 @@ int security_inode_init_security(struct
8633 EXPORT_SYMBOL(security_inode_init_security);
8635 -int security_inode_create(struct inode *dir, struct dentry *dentry, int mode)
8636 +int security_inode_create(struct inode *dir, struct dentry *dentry,
8637 + struct vfsmount *mnt, int mode)
8639 if (unlikely(IS_PRIVATE(dir)))
8641 - return security_ops->inode_create(dir, dentry, mode);
8642 + return security_ops->inode_create(dir, dentry, mnt, mode);
8645 -int security_inode_link(struct dentry *old_dentry, struct inode *dir,
8646 - struct dentry *new_dentry)
8647 +int security_inode_link(struct dentry *old_dentry, struct vfsmount *old_mnt,
8648 + struct inode *dir, struct dentry *new_dentry,
8649 + struct vfsmount *new_mnt)
8651 if (unlikely(IS_PRIVATE(old_dentry->d_inode)))
8653 - return security_ops->inode_link(old_dentry, dir, new_dentry);
8654 + return security_ops->inode_link(old_dentry, old_mnt, dir,
8655 + new_dentry, new_mnt);
8658 -int security_inode_unlink(struct inode *dir, struct dentry *dentry)
8659 +int security_inode_unlink(struct inode *dir, struct dentry *dentry,
8660 + struct vfsmount *mnt)
8662 if (unlikely(IS_PRIVATE(dentry->d_inode)))
8664 - return security_ops->inode_unlink(dir, dentry);
8665 + return security_ops->inode_unlink(dir, dentry, mnt);
8668 int security_inode_symlink(struct inode *dir, struct dentry *dentry,
8669 - const char *old_name)
8670 + struct vfsmount *mnt, const char *old_name)
8672 if (unlikely(IS_PRIVATE(dir)))
8674 - return security_ops->inode_symlink(dir, dentry, old_name);
8675 + return security_ops->inode_symlink(dir, dentry, mnt, old_name);
8678 -int security_inode_mkdir(struct inode *dir, struct dentry *dentry, int mode)
8679 +int security_inode_mkdir(struct inode *dir, struct dentry *dentry,
8680 + struct vfsmount *mnt, int mode)
8682 if (unlikely(IS_PRIVATE(dir)))
8684 - return security_ops->inode_mkdir(dir, dentry, mode);
8685 + return security_ops->inode_mkdir(dir, dentry, mnt, mode);
8688 -int security_inode_rmdir(struct inode *dir, struct dentry *dentry)
8689 +int security_inode_rmdir(struct inode *dir, struct dentry *dentry,
8690 + struct vfsmount *mnt)
8692 if (unlikely(IS_PRIVATE(dentry->d_inode)))
8694 - return security_ops->inode_rmdir(dir, dentry);
8695 + return security_ops->inode_rmdir(dir, dentry, mnt);
8698 -int security_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
8699 +int security_inode_mknod(struct inode *dir, struct dentry *dentry,
8700 + struct vfsmount *mnt, int mode, dev_t dev)
8702 if (unlikely(IS_PRIVATE(dir)))
8704 - return security_ops->inode_mknod(dir, dentry, mode, dev);
8705 + return security_ops->inode_mknod(dir, dentry, mnt, mode, dev);
8708 int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
8709 - struct inode *new_dir, struct dentry *new_dentry)
8710 + struct vfsmount *old_mnt, struct inode *new_dir,
8711 + struct dentry *new_dentry, struct vfsmount *new_mnt)
8713 if (unlikely(IS_PRIVATE(old_dentry->d_inode) ||
8714 (new_dentry->d_inode && IS_PRIVATE(new_dentry->d_inode))))
8716 - return security_ops->inode_rename(old_dir, old_dentry,
8717 - new_dir, new_dentry);
8718 + return security_ops->inode_rename(old_dir, old_dentry, old_mnt,
8719 + new_dir, new_dentry, new_mnt);
8722 -int security_inode_readlink(struct dentry *dentry)
8723 +int security_inode_readlink(struct dentry *dentry, struct vfsmount *mnt)
8725 if (unlikely(IS_PRIVATE(dentry->d_inode)))
8727 - return security_ops->inode_readlink(dentry);
8728 + return security_ops->inode_readlink(dentry, mnt);
8731 int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd)
8732 @@ -434,11 +442,12 @@ int security_inode_permission(struct ino
8733 return security_ops->inode_permission(inode, mask, nd);
8736 -int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
8737 +int security_inode_setattr(struct dentry *dentry, struct vfsmount *mnt,
8738 + struct iattr *attr)
8740 if (unlikely(IS_PRIVATE(dentry->d_inode)))
8742 - return security_ops->inode_setattr(dentry, attr);
8743 + return security_ops->inode_setattr(dentry, mnt, attr);
8746 int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
8747 @@ -455,41 +464,48 @@ void security_inode_delete(struct inode
8748 security_ops->inode_delete(inode);
8751 -int security_inode_setxattr(struct dentry *dentry, char *name,
8752 - void *value, size_t size, int flags)
8753 +int security_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
8754 + char *name, void *value, size_t size, int flags,
8755 + struct file *file)
8757 if (unlikely(IS_PRIVATE(dentry->d_inode)))
8759 - return security_ops->inode_setxattr(dentry, name, value, size, flags);
8760 + return security_ops->inode_setxattr(dentry, mnt, name, value, size,
8764 -void security_inode_post_setxattr(struct dentry *dentry, char *name,
8765 - void *value, size_t size, int flags)
8766 +void security_inode_post_setxattr(struct dentry *dentry, struct vfsmount *mnt,
8767 + char *name, void *value, size_t size,
8770 if (unlikely(IS_PRIVATE(dentry->d_inode)))
8772 - security_ops->inode_post_setxattr(dentry, name, value, size, flags);
8773 + security_ops->inode_post_setxattr(dentry, mnt, name, value, size,
8777 -int security_inode_getxattr(struct dentry *dentry, char *name)
8778 +int security_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
8779 + char *name, struct file *file)
8781 if (unlikely(IS_PRIVATE(dentry->d_inode)))
8783 - return security_ops->inode_getxattr(dentry, name);
8784 + return security_ops->inode_getxattr(dentry, mnt, name, file);
8787 -int security_inode_listxattr(struct dentry *dentry)
8788 +int security_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt,
8789 + struct file *file)
8791 if (unlikely(IS_PRIVATE(dentry->d_inode)))
8793 - return security_ops->inode_listxattr(dentry);
8794 + return security_ops->inode_listxattr(dentry, mnt, file);
8797 -int security_inode_removexattr(struct dentry *dentry, char *name)
8798 +int security_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
8799 + char *name, struct file *file)
8801 if (unlikely(IS_PRIVATE(dentry->d_inode)))
8803 - return security_ops->inode_removexattr(dentry, name);
8804 + return security_ops->inode_removexattr(dentry, mnt, name, file);
8807 int security_inode_need_killpriv(struct dentry *dentry)
8808 diff -uprN e/security/selinux/hooks.c f/security/selinux/hooks.c
8809 --- e/security/selinux/hooks.c 2008-05-28 20:32:27.897940261 +0000
8810 +++ f/security/selinux/hooks.c 2008-05-28 20:29:29.410207000 +0000
8811 @@ -1712,40 +1712,15 @@ static int selinux_capable(struct task_s
8813 static int selinux_sysctl_get_sid(ctl_table *table, u16 tclass, u32 *sid)
8816 - char *buffer, *path, *end;
8817 + char *buffer, *path;
8821 buffer = (char*)__get_free_page(GFP_KERNEL);
8825 - buflen = PAGE_SIZE;
8826 - end = buffer+buflen;
8832 - const char *name = table->procname;
8833 - size_t namelen = strlen(name);
8834 - buflen -= namelen + 1;
8838 - memcpy(end, name, namelen);
8841 - table = table->parent;
8847 - memcpy(end, "/sys", 4);
8849 - rc = security_genfs_sid("proc", path, tclass, sid);
8851 + path = sysctl_pathname(table, buffer, PAGE_SIZE);
8853 + rc = security_genfs_sid("proc", path, tclass, sid);
8854 free_page((unsigned long)buffer);
8857 @@ -2458,64 +2433,79 @@ static int selinux_inode_init_security(s
8861 -static int selinux_inode_create(struct inode *dir, struct dentry *dentry, int mask)
8862 +static int selinux_inode_create(struct inode *dir, struct dentry *dentry,
8863 + struct vfsmount *mnt, int mask)
8865 return may_create(dir, dentry, SECCLASS_FILE);
8868 -static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
8869 +static int selinux_inode_link(struct dentry *old_dentry,
8870 + struct vfsmount *old_mnt,
8871 + struct inode *dir,
8872 + struct dentry *new_dentry,
8873 + struct vfsmount *new_mnt)
8877 - rc = secondary_ops->inode_link(old_dentry,dir,new_dentry);
8878 + rc = secondary_ops->inode_link(old_dentry, old_mnt, dir, new_dentry,
8882 return may_link(dir, old_dentry, MAY_LINK);
8885 -static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry)
8886 +static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry,
8887 + struct vfsmount *mnt)
8891 - rc = secondary_ops->inode_unlink(dir, dentry);
8892 + rc = secondary_ops->inode_unlink(dir, dentry, mnt);
8895 return may_link(dir, dentry, MAY_UNLINK);
8898 -static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name)
8899 +static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry,
8900 + struct vfsmount *mnt, const char *name)
8902 return may_create(dir, dentry, SECCLASS_LNK_FILE);
8905 -static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, int mask)
8906 +static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry,
8907 + struct vfsmount *mnt, int mask)
8909 return may_create(dir, dentry, SECCLASS_DIR);
8912 -static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry)
8913 +static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry,
8914 + struct vfsmount *mnt)
8916 return may_link(dir, dentry, MAY_RMDIR);
8919 -static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
8920 +static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry,
8921 + struct vfsmount *mnt, int mode, dev_t dev)
8925 - rc = secondary_ops->inode_mknod(dir, dentry, mode, dev);
8926 + rc = secondary_ops->inode_mknod(dir, dentry, mnt, mode, dev);
8930 return may_create(dir, dentry, inode_mode_to_security_class(mode));
8933 -static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
8934 - struct inode *new_inode, struct dentry *new_dentry)
8935 +static int selinux_inode_rename(struct inode *old_inode,
8936 + struct dentry *old_dentry,
8937 + struct vfsmount *old_mnt,
8938 + struct inode *new_inode,
8939 + struct dentry *new_dentry,
8940 + struct vfsmount *new_mnt)
8942 return may_rename(old_inode, old_dentry, new_inode, new_dentry);
8945 -static int selinux_inode_readlink(struct dentry *dentry)
8946 +static int selinux_inode_readlink(struct dentry *dentry, struct vfsmount *mnt)
8948 return dentry_has_perm(current, NULL, dentry, FILE__READ);
8950 @@ -2548,11 +2538,12 @@ static int selinux_inode_permission(stru
8951 file_mask_to_av(inode->i_mode, mask), NULL);
8954 -static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
8955 +static int selinux_inode_setattr(struct dentry *dentry, struct vfsmount *mnt,
8956 + struct iattr *iattr)
8960 - rc = secondary_ops->inode_setattr(dentry, iattr);
8961 + rc = secondary_ops->inode_setattr(dentry, mnt, iattr);
8965 @@ -2590,7 +2581,9 @@ static int selinux_inode_setotherxattr(s
8966 return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
8969 -static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value, size_t size, int flags)
8970 +static int selinux_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
8971 + char *name, void *value, size_t size,
8972 + int flags, struct file *file)
8974 struct task_security_struct *tsec = current->security;
8975 struct inode *inode = dentry->d_inode;
8976 @@ -2639,7 +2632,9 @@ static int selinux_inode_setxattr(struct
8980 -static void selinux_inode_post_setxattr(struct dentry *dentry, char *name,
8981 +static void selinux_inode_post_setxattr(struct dentry *dentry,
8982 + struct vfsmount *mnt,
8984 void *value, size_t size, int flags)
8986 struct inode *inode = dentry->d_inode;
8987 @@ -2663,17 +2658,21 @@ static void selinux_inode_post_setxattr(
8991 -static int selinux_inode_getxattr (struct dentry *dentry, char *name)
8992 +static int selinux_inode_getxattr (struct dentry *dentry, struct vfsmount *mnt,
8993 + char *name, struct file *file)
8995 return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
8998 -static int selinux_inode_listxattr (struct dentry *dentry)
8999 +static int selinux_inode_listxattr (struct dentry *dentry, struct vfsmount *mnt,
9000 + struct file *file)
9002 return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
9005 -static int selinux_inode_removexattr (struct dentry *dentry, char *name)
9006 +static int selinux_inode_removexattr (struct dentry *dentry,
9007 + struct vfsmount *mnt, char *name,
9008 + struct file *file)
9010 if (strcmp(name, XATTR_NAME_SELINUX))
9011 return selinux_inode_setotherxattr(dentry, name);
9012 --- s/fs/namei.c~ 2008-05-29 00:47:22.000000000 +0200
9013 +++ s/fs/namei.c 2008-05-29 00:53:55.814585231 +0200
9014 @@ -3022,8 +3022,8 @@
9015 new_path.dentry->d_name.len,
9016 old_path.dentry->d_name.len, old_path.dentry->d_name.name,
9017 old_path.dentry->d_name.len);
9018 - ret = vfs_rename(dir_nd.path.dentry->d_inode, new_path.dentry,
9019 - old_nd.path.dentry->d_parent->d_inode, old_path.dentry);
9020 + ret = vfs_rename(dir_nd.path.dentry->d_inode, new_path.dentry, new_path.mnt,
9021 + old_nd.path.dentry->d_parent->d_inode, old_path.dentry, old_path.mnt);
9022 vxdprintk(VXD_CBIT(misc, 2), "vfs_rename: %d", ret);
9023 res = new_path.dentry;
9025 --- s/fs/namei.c~ 2008-05-29 00:59:12.000000000 +0200
9026 +++ s/fs/namei.c 2008-05-29 00:59:40.790875766 +0200
9027 @@ -3048,7 +3048,7 @@
9030 /* error path cleanup */
9031 - vfs_unlink(dir->d_inode, new_path.dentry, &dir_nd);
9032 + vfs_unlink(dir->d_inode, new_path.dentry, &dir_nd, new_path.mnt);
9033 dput(new_path.dentry);
9036 --- s/include/linux/xattr.h~ 2008-05-29 01:40:01.000000000 +0200
9037 +++ s/include/linux/xattr.h 2008-05-29 01:40:06.624153911 +0200
9041 #include <linux/types.h>
9042 +#include <linux/fs.h>
9045 #define XATTR_OS2_PREFIX "os2."