]> git.pld-linux.org Git - packages/kernel.git/blob - kernel-apparmor.patch
- revert
[packages/kernel.git] / kernel-apparmor.patch
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,
7         .lock           = afs_lock,
8 +       .fsetattr       = afs_fsetattr,
9  };
10  
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
16         .fsync          = afs_fsync,
17         .lock           = afs_lock,
18         .flock          = afs_flock,
19 +       .fsetattr       = afs_fsetattr,
20  };
21  
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
27  /*
28   * set the attributes of an inode
29   */
30 -int afs_setattr(struct dentry *dentry, struct iattr *attr)
31 +static int afs_do_setattr(struct dentry *dentry, struct iattr *attr,
32 +                  struct file *file)
33  {
34         struct afs_vnode *vnode = AFS_FS_I(dentry->d_inode);
35         struct key *key;
36 @@ -380,8 +381,8 @@ int afs_setattr(struct dentry *dentry, s
37                 afs_writeback_all(vnode);
38         }
39  
40 -       if (attr->ia_valid & ATTR_FILE) {
41 -               key = attr->ia_file->private_data;
42 +       if (file) {
43 +               key = file->private_data;
44         } else {
45                 key = afs_request_key(vnode->volume->cell);
46                 if (IS_ERR(key)) {
47 @@ -391,10 +392,20 @@ int afs_setattr(struct dentry *dentry, s
48         }
49  
50         ret = afs_vnode_setattr(vnode, key, attr);
51 -       if (!(attr->ia_valid & ATTR_FILE))
52 +       if (!file)
53                 key_put(key);
54  
55  error:
56         _leave(" = %d", ret);
57         return ret;
58  }
59 +
60 +int afs_setattr(struct dentry *dentry, struct iattr *attr)
61 +{
62 +       return afs_do_setattr(dentry, attr, NULL);
63 +}
64 +
65 +int afs_fsetattr(struct file *file, struct iattr *attr)
66 +{
67 +       return afs_do_setattr(file->f_path.dentry, attr, file);
68 +}
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 *);
78  
79  /*
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, 
84  }
85  EXPORT_SYMBOL(inode_setattr);
86  
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)
90  {
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);
95  
96         if (inode->i_op && inode->i_op->setattr) {
97 -               error = security_inode_setattr(dentry, attr);
98 -               if (!error)
99 -                       error = inode->i_op->setattr(dentry, attr);
100 +               error = security_inode_setattr(dentry, mnt, attr);
101 +               if (!error) {
102 +                       if (file && file->f_op && file->f_op->fsetattr)
103 +                               error = file->f_op->fsetattr(file, attr);
104 +                       else
105 +                               error = inode->i_op->setattr(dentry, attr);
106 +               }
107         } else {
108                 error = inode_change_ok(inode, attr);
109                 if (!error)
110 -                       error = security_inode_setattr(dentry, attr);
111 +                       error = security_inode_setattr(dentry, mnt, attr);
112                 if (!error) {
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
116  
117         return error;
118  }
119 +EXPORT_SYMBOL_GPL(fnotify_change);
120 +
121 +int notify_change(struct dentry *dentry, struct vfsmount *mnt,
122 +                 struct iattr *attr)
123 +{
124 +       return fnotify_change(dentry, mnt, attr, NULL);
125 +}
126  
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:
132  }
133  
134  /**
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
139   * @root: root dentry
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
145   *
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.
150   *
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).
154   *
155 - * "buflen" should be positive. Caller holds the dcache_lock.
156 + * Returns the buffer or an error code.
157   */
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)
163  {
164 -       char * end = buffer+buflen;
165 -       char * retval;
166 -       int namelen;
167 +       int namelen, vfsmount_locked = 0;
168 +       const unsigned char *name;
169 +
170 +       if (buflen < 2)
171 +               return ERR_PTR(-ENAMETOOLONG);
172 +       buffer += --buflen;
173 +       *buffer = '\0';
174  
175 -       *--end = '\0';
176 -       buflen--;
177 +       spin_lock(&dcache_lock);
178         if (!IS_ROOT(dentry) && d_unhashed(dentry)) {
179 -               buflen -= 10;
180 -               end -= 10;
181 -               if (buflen < 0)
182 +               if (fail_deleted) {
183 +                       buffer = ERR_PTR(-ENOENT);
184 +                       goto out;
185 +               }
186 +               if (buflen < 10)
187                         goto Elong;
188 -               memcpy(end, " (deleted)", 10);
189 +               buflen -= 10;
190 +               buffer -= 10;
191 +               memcpy(buffer, " (deleted)", 10);
192         }
193  
194 -       if (buflen < 1)
195 -               goto Elong;
196 -       /* Get '/' right */
197 -       retval = end-1;
198 -       *retval = '/';
199 -
200 -       for (;;) {
201 +       while (dentry != root->dentry || vfsmnt != root->mnt) {
202                 struct dentry * parent;
203  
204 -               if (dentry == root->dentry && vfsmnt == root->mnt)
205 -                       break;
206                 if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
207 -                       /* Global root? */
208 -                       spin_lock(&vfsmount_lock);
209 -                       if (vfsmnt->mnt_parent == vfsmnt) {
210 -                               spin_unlock(&vfsmount_lock);
211 -                               goto global_root;
212 +                       if (!vfsmount_locked) {
213 +                               spin_lock(&vfsmount_lock);
214 +                               vfsmount_locked = 1;
215                         }
216 +                       if (vfsmnt->mnt_parent == vfsmnt)
217 +                               goto global_root;
218                         dentry = vfsmnt->mnt_mountpoint;
219                         vfsmnt = vfsmnt->mnt_parent;
220 -                       spin_unlock(&vfsmount_lock);
221                         continue;
222                 }
223                 parent = dentry->d_parent;
224                 prefetch(parent);
225                 namelen = dentry->d_name.len;
226 -               buflen -= namelen + 1;
227 -               if (buflen < 0)
228 +               if (buflen < namelen + 1)
229                         goto Elong;
230 -               end -= namelen;
231 -               memcpy(end, dentry->d_name.name, namelen);
232 -               *--end = '/';
233 -               retval = end;
234 +               buflen -= namelen + 1;
235 +               buffer -= namelen;
236 +               memcpy(buffer, dentry->d_name.name, namelen);
237 +               *--buffer = '/';
238                 dentry = parent;
239         }
240 +       /* Get '/' right. */
241 +       if (*buffer != '/')
242 +               *--buffer = '/';
243  
244 -       return retval;
245 +out:
246 +       if (vfsmount_locked)
247 +               spin_unlock(&vfsmount_lock);
248 +       spin_unlock(&dcache_lock);
249 +       return buffer;
250  
251  global_root:
252 +       /*
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.
256 +        */
257         namelen = dentry->d_name.len;
258 -       buflen -= namelen;
259 -       if (buflen < 0)
260 +       name = dentry->d_name.name;
261 +
262 +       /*
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:".
266 +        */
267 +       if (IS_ROOT(dentry)) {
268 +               buffer++;
269 +               buflen++;
270 +       }
271 +       if (disconnect && *name == '/') {
272 +           /* Make sure we won't return a pathname starting with '/' */
273 +               name++;
274 +               namelen--;
275 +       }
276 +       if (buflen < namelen)
277                 goto Elong;
278 -       retval -= namelen-1;    /* hit the slash */
279 -       memcpy(retval, dentry->d_name.name, namelen);
280 -       return retval;
281 +       buffer -= namelen;
282 +       memcpy(buffer, dentry->d_name.name, namelen);
283 +       goto out;
284 +
285  Elong:
286 -       return ERR_PTR(-ENAMETOOLONG);
287 +       buffer = ERR_PTR(-ENAMETOOLONG);
288 +       goto out;
289  }
290  
291  /**
292 @@ -1861,9 +1893,7 @@ char *d_path(struct path *path, char *bu
293         root = current->fs->root;
294         path_get(&current->fs->root);
295         read_unlock(&current->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);
300         path_put(&root);
301         return res;
302  }
303 @@ -1909,9 +1939,9 @@ char *dynamic_dname(struct dentry *dentr
304   */
305  asmlinkage long sys_getcwd(char __user *buf, unsigned long size)
306  {
307 -       int error;
308 +       int error, len;
309         struct path pwd, root;
310 -       char *page = (char *) __get_free_page(GFP_USER);
311 +       char *page = (char *) __get_free_page(GFP_USER), *cwd;
312  
313         if (!page)
314                 return -ENOMEM;
315 @@ -1923,29 +1953,18 @@ asmlinkage long sys_getcwd(char __user *
316         path_get(&current->fs->root);
317         read_unlock(&current->fs->lock);
318  
319 -       error = -ENOENT;
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)) {
323 -               unsigned long len;
324 -               char * cwd;
325 -
326 -               cwd = __d_path(pwd.dentry, pwd.mnt, &root, page, PAGE_SIZE);
327 -               spin_unlock(&dcache_lock);
328 -
329 -               error = PTR_ERR(cwd);
330 -               if (IS_ERR(cwd))
331 -                       goto out;
332 -
333 -               error = -ERANGE;
334 -               len = PAGE_SIZE + page - cwd;
335 -               if (len <= size) {
336 -                       error = len;
337 -                       if (copy_to_user(buf, cwd, len))
338 -                               error = -EFAULT;
339 -               }
340 -       } else
341 -               spin_unlock(&dcache_lock);
342 +       cwd = __d_path(pwd.dentry, pwd.mnt, &root, page, PAGE_SIZE, 1, 0);
343 +       error = PTR_ERR(cwd);
344 +       if (IS_ERR(cwd))
345 +               goto out;
346 +
347 +       error = -ERANGE;
348 +       len = PAGE_SIZE + page - cwd;
349 +       if (len <= size) {
350 +               error = len;
351 +               if (copy_to_user(buf, cwd, len))
352 +                       error = -EFAULT;
353 +       }
354  
355  out:
356         path_put(&pwd);
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)
362  {
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;
368         u64 file_size_save;
369         int rc;
370  
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)
385                 goto out_lock;
386         rc = ecryptfs_interpose(lower_new_dentry, new_dentry, dir->i_sb, 0);
387 @@ -425,10 +430,11 @@ static int ecryptfs_unlink(struct inode 
388         int rc = 0;
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;
393  
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);
397         if (rc) {
398                 printk(KERN_ERR "Error in vfs_unlink; rc = [%d]\n", rc);
399                 goto out_unlock;
400 @@ -448,6 +454,7 @@ static int ecryptfs_symlink(struct inode
401  {
402         int rc;
403         struct dentry *lower_dentry;
404 +       struct vfsmount *lower_mnt;
405         struct dentry *lower_dir_dentry;
406         umode_t mode;
407         char *encoded_symname;
408 @@ -456,6 +463,7 @@ static int ecryptfs_symlink(struct inode
409  
410         lower_dentry = ecryptfs_dentry_to_lower(dentry);
411         dget(lower_dentry);
412 +       lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
413         lower_dir_dentry = lock_parent(lower_dentry);
414         mode = S_IALLUGO;
415         encoded_symlen = ecryptfs_encode_filename(crypt_stat, symname,
416 @@ -465,7 +473,7 @@ static int ecryptfs_symlink(struct inode
417                 rc = encoded_symlen;
418                 goto out_lock;
419         }
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 *
426  {
427         int rc;
428         struct dentry *lower_dentry;
429 +       struct vfsmount *lower_mnt;
430         struct dentry *lower_dir_dentry;
431  
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,
437 +                      mode, NULL);
438         if (rc || !lower_dentry->d_inode)
439                 goto out;
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)
443  {
444         struct dentry *lower_dentry;
445 +       struct vfsmount *lower_mnt;
446         struct dentry *lower_dir_dentry;
447         int rc;
448  
449         lower_dentry = ecryptfs_dentry_to_lower(dentry);
450 +       lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
451         dget(dentry);
452         lower_dir_dentry = lock_parent(lower_dentry);
453         dget(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);
456         dput(lower_dentry);
457         if (!rc)
458                 d_delete(lower_dentry);
459 @@ -535,11 +548,14 @@ ecryptfs_mknod(struct inode *dir, struct
460  {
461         int rc;
462         struct dentry *lower_dentry;
463 +       struct vfsmount *lower_mnt;
464         struct dentry *lower_dir_dentry;
465  
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,
471 +                      dev, NULL);
472         if (rc || !lower_dentry->d_inode)
473                 goto out;
474         rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb, 0);
475 @@ -560,19 +576,24 @@ ecryptfs_rename(struct inode *old_dir, s
476  {
477         int rc;
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;
484  
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);
498         if (rc)
499                 goto out_lock;
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
502  {
503         int rc = 0;
504         struct dentry *lower_dentry;
505 +       struct vfsmount *lower_mnt;
506         struct inode *inode;
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);
517 @@ -927,7 +927,7 @@
518                 ia->ia_valid &= ~ATTR_MODE;
519  
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);
524  out:
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
530                 goto close_fail;
531         if (!file->f_op->write)
532                 goto close_fail;
533 -       if (!ispipe && do_truncate(file->f_path.dentry, 0, 0, file) != 0)
534 +       if (!ispipe &&
535 +           do_truncate(file->f_path.dentry, file->f_path.mnt, 0, 0, file) != 0)
536                 goto close_fail;
537  
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
543                 }
544  
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);
548                 if (err)
549                         goto up;
550  
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;
556  }
557  
558 -static bool update_mtime(unsigned ivalid)
559 +static bool update_mtime(unsigned ivalid, bool have_file)
560  {
561         /* Always update if mtime is explicitly set  */
562         if (ivalid & ATTR_MTIME_SET)
563                 return true;
564  
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))
568                 return false;
569  
570         /* In all other cases update */
571         return true;
572  }
573  
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,
576 +                          bool have_file)
577  {
578         unsigned ivalid = iattr->ia_valid;
579  
580 @@ -1097,7 +1098,7 @@ static void iattr_to_fattr(struct iattr 
581                 if (!(ivalid & ATTR_ATIME_SET))
582                         arg->valid |= FATTR_ATIME_NOW;
583         }
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.
592   */
593 -static int fuse_do_setattr(struct dentry *entry, struct iattr *attr,
594 -                          struct file *file)
595 +int fuse_do_setattr(struct dentry *entry, struct iattr *attr,
596 +                   struct file *file)
597  {
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
601  
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);
606         if (file) {
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
610  
611  static int fuse_setattr(struct dentry *entry, struct iattr *attr)
612  {
613 -       if (attr->ia_valid & ATTR_FILE)
614 -               return fuse_do_setattr(entry, attr, attr->ia_file);
615 -       else
616 -               return fuse_do_setattr(entry, attr, NULL);
617 +       return fuse_do_setattr(entry, attr, NULL);
618  }
619  
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;
626  }
627  
628 +static int fuse_fsetattr(struct file *file, struct iattr *attr)
629 +{
630 +       return fuse_do_setattr(file->f_path.dentry, attr, file);
631 +}
632 +
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
637         .fsync          = fuse_fsync,
638         .lock           = fuse_file_lock,
639         .flock          = fuse_file_flock,
640 +       .fsetattr       = fuse_fsetattr,
641         .splice_read    = generic_file_splice_read,
642  };
643  
644 @@ -935,6 +941,7 @@ static const struct file_operations fuse
645         .fsync          = fuse_fsync,
646         .lock           = fuse_file_lock,
647         .flock          = fuse_file_flock,
648 +       .fsetattr       = fuse_fsetattr,
649         /* no mmap and splice_read */
650  };
651  
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
656   */
657  int fuse_dev_init(void);
658  
659 +
660 +int fuse_do_setattr(struct dentry *entry, struct iattr *attr,
661 +                   struct file *file);
662 +
663  /**
664   * Cleanup the client device
665   */
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);
676                         if (!err)
677                                 goto again;
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,
682   */
683  int file_permission(struct file *file, int mask)
684  {
685 -       return permission(file->f_path.dentry->d_inode, mask, NULL);
686 +       struct nameidata nd;
687 +
688 +       nd.path = file->f_path;
689 +       nd.flags = LOOKUP_ACCESS;
690 +
691 +       return permission(nd.path.dentry->d_inode, mask, &nd);
692  }
693  
694  /*
695 @@ -1150,24 +1155,21 @@ static int do_path_lookup(int dfd, const
696                 path_get(&fs->pwd);
697                 read_unlock(&fs->lock);
698         } else {
699 -               struct dentry *dentry;
700 -
701                 file = fget_light(dfd, &fput_needed);
702                 retval = -EBADF;
703                 if (!file)
704                         goto out_fail;
705  
706 -               dentry = file->f_path.dentry;
707 +               nd->path = file->f_path;
708  
709                 retval = -ENOTDIR;
710 -               if (!S_ISDIR(dentry->d_inode->i_mode))
711 +               if (!S_ISDIR(nd->path.dentry->d_inode->i_mode))
712                         goto fput_fail;
713  
714                 retval = file_permission(file, MAY_EXEC);
715                 if (retval)
716                         goto fput_fail;
717  
718 -               nd->path = file->f_path;
719                 path_get(&file->f_path);
720  
721                 fput_light(file, fput_needed);
722 @@ -1511,6 +1513,8 @@ static inline int may_create(struct inod
723                 return -EEXIST;
724         if (IS_DEADDIR(dir))
725                 return -ENOENT;
726 +       if (nd)
727 +               nd->flags |= LOOKUP_CONTINUE;
728         return permission(dir,MAY_WRITE | MAY_EXEC, nd);
729  }
730  
731 @@ -1586,7 +1590,7 @@ int vfs_create(struct inode *dir, struct
732                 return -EACCES; /* shouldn't it be ENOSYS? */
733         mode &= S_IALLUGO;
734         mode |= S_IFREG;
735 -       error = security_inode_create(dir, dentry, mode);
736 +       error = security_inode_create(dir, dentry, nd ? nd->path.mnt : NULL, mode);
737         if (error)
738                 return error;
739         DQUOT_INIT(dir);
740 @@ -1663,7 +1667,7 @@ int may_open(struct nameidata *nd, int a
741                 if (!error) {
742                         DQUOT_INIT(inode);
743  
744 -                       error = do_truncate(dentry, 0,
745 +                       error = do_truncate(dentry, nd->path.mnt, 0,
746                                             ATTR_MTIME|ATTR_CTIME|ATTR_OPEN,
747                                             NULL);
748                 }
749 @@ -1921,8 +1925,8 @@ fail:
750  }
751  EXPORT_SYMBOL_GPL(lookup_create);
752  
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)
757  {
758         int error = may_create(dir, dentry, NULL);
759  
760 @@ -1934,7 +1939,7 @@ int vfs_mknod(struct inode *dir, struct 
761         if (!dir->i_op || !dir->i_op->mknod)
762                 return -EPERM;
763  
764 -       error = security_inode_mknod(dir, dentry, mode, dev);
765 +       error = security_inode_mknod(dir, dentry, mnt, mode, dev);
766         if (error)
767                 return error;
768  
769 @@ -1973,12 +1978,12 @@ asmlinkage long sys_mknodat(int dfd, con
770                         error = vfs_create(nd.path.dentry->d_inode,dentry,mode,&nd);
771                         break;
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);
777                         break;
778                 case S_IFIFO: case S_IFSOCK:
779 -                       error = vfs_mknod(nd.path.dentry->d_inode, dentry, mode,
780 -                                       0, &nd);
781 +                       error = vfs_mknod(nd.path.dentry->d_inode, dentry,
782 +                                         nd.path.mnt, mode, 0, &nd);
783                         break;
784                 case S_IFDIR:
785                         error = -EPERM;
786 @@ -2000,8 +2006,8 @@ asmlinkage long sys_mknod(const char __u
787         return sys_mknodat(AT_FDCWD, filename, mode, dev);
788  }
789  
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)
794  {
795         int error = may_create(dir, dentry, nd);
796  
797 @@ -2011,7 +2018,7 @@ int vfs_mkdir(struct inode *dir, struct 
798                 return -EPERM;
799  
800         mode &= (S_IRWXUGO|S_ISVTX);
801 -       error = security_inode_mkdir(dir, dentry, mode);
802 +       error = security_inode_mkdir(dir, dentry, mnt, mode);
803         if (error)
804                 return error;
805  
806 @@ -2044,7 +2051,7 @@ asmlinkage long sys_mkdirat(int dfd, con
807  
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);
812         dput(dentry);
813  out_unlock:
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);
817  }
818  
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)
823  {
824         int error = may_delete(dir, dentry, 1);
825  
826 @@ -2097,6 +2104,10 @@ int vfs_rmdir(struct inode *dir, struct 
827         if (!dir->i_op || !dir->i_op->rmdir)
828                 return -EPERM;
829  
830 +       error = security_inode_rmdir(dir, dentry, mnt);
831 +       if (error)
832 +               return error;
833 +
834         DQUOT_INIT(dir);
835  
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))
839                 error = -EBUSY;
840         else {
841 -               error = security_inode_rmdir(dir, dentry);
842 -               if (!error) {
843 -                       error = dir->i_op->rmdir(dir, dentry);
844 -                       if (!error)
845 -                               dentry->d_inode->i_flags |= S_DEAD;
846 -               }
847 +               error = dir->i_op->rmdir(dir, dentry);
848 +               if (!error)
849 +                       dentry->d_inode->i_flags |= S_DEAD;
850         }
851         mutex_unlock(&dentry->d_inode->i_mutex);
852         if (!error) {
853 @@ -2151,7 +2159,7 @@ static long do_rmdir(int dfd, const char
854         error = PTR_ERR(dentry);
855         if (IS_ERR(dentry))
856                 goto exit2;
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);
859         dput(dentry);
860  exit2:
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);
864  }
865  
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)
870  {
871         int error = may_delete(dir, dentry, 0, nd);
872  
873 @@ -2183,7 +2191,7 @@ int vfs_unlink(struct inode *dir, struct
874         if (d_mountpoint(dentry))
875                 error = -EBUSY;
876         else {
877 -               error = security_inode_unlink(dir, dentry);
878 +               error = security_inode_unlink(dir, dentry, mnt);
879                 if (!error)
880                         error = dir->i_op->unlink(dir, dentry);
881         }
882 @@ -2232,7 +2240,7 @@ static long do_unlinkat(int dfd, const c
883                 inode = dentry->d_inode;
884                 if (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);
888         exit2:
889                 dput(dentry);
890         }
891 @@ -2267,7 +2275,7 @@ asmlinkage long sys_unlink(const char __
892         return do_unlinkat(AT_FDCWD, pathname);
893  }
894  
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)
899  {
900 @@ -2277,7 +2286,7 @@ int vfs_symlink(struct inode *dir, struc
901         if (!dir->i_op || !dir->i_op->symlink)
902                 return -EPERM;
903  
904 -       error = security_inode_symlink(dir, dentry, oldname);
905 +       error = security_inode_symlink(dir, dentry, mnt, oldname);
906         if (error)
907                 return error;
908  
909 @@ -2313,8 +2322,8 @@ asmlinkage long sys_symlinkat(const char
910         if (IS_ERR(dentry))
911                 goto out_unlock;
912  
913 -       error = vfs_symlink(nd.path.dentry->d_inode, dentry, from,
914 -               S_IALLUGO, &nd);
915 +       error = vfs_symlink(nd.path.dentry->d_inode, dentry, nd.path.mnt, from,
916 +                           S_IALLUGO, &nd);
917         dput(dentry);
918  out_unlock:
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);
922  }
923  
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)
928  {
929         struct inode *inode = old_dentry->d_inode;
930         int error;
931 @@ -2355,7 +2365,8 @@ int vfs_link(struct dentry *old_dentry, 
932         if (S_ISDIR(old_dentry->d_inode->i_mode))
933                 return -EPERM;
934  
935 -       error = security_inode_link(old_dentry, dir, new_dentry);
936 +       error = security_inode_link(old_dentry, old_mnt, dir, new_dentry,
937 +                                   new_mnt);
938         if (error)
939                 return error;
940  
941 @@ -2408,8 +2419,8 @@ asmlinkage long sys_linkat(int olddfd, c
942                 goto out_unlock_dput;
943         }
944  
945 -       error = vfs_link(old_nd.path.dentry, nd.path.dentry->d_inode,
946 -               new_dentry, &nd);
947 +       error = vfs_link(old_nd.path.dentry, old_nd.path.mnt, nd.path.dentry->d_inode,
948 +                        new_dentry, nd.path.mnt, &nd);
949  out_unlock_dput:
950         dput(new_dentry);
951  out_unlock:
952 @@ -2460,7 +2472,8 @@ asmlinkage long sys_link(const char __us
953   *        locking].
954   */
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)
959  {
960         int error = 0;
961         struct inode *target;
962 @@ -2475,7 +2488,8 @@ static int vfs_rename_dir(struct inode *
963                         return error;
964         }
965  
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);
969         if (error)
970                 return error;
971  
972 @@ -2503,12 +2517,14 @@ static int vfs_rename_dir(struct inode *
973  }
974  
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)
979  {
980         struct inode *target;
981         int error;
982  
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);
986         if (error)
987                 return error;
988  
989 @@ -2531,7 +2547,8 @@ static int vfs_rename_other(struct inode
990  }
991  
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)
996  {
997         int error;
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);
1001  
1002         if (is_dir)
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);
1006         else
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);
1010         if (!error) {
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)
1015                 goto exit5;
1016  
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);
1021  exit5:
1022         dput(new_dentry);
1023  exit4:
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);
1029         kfree(ns);
1030  }
1031 +
1032 +char *d_namespace_path(struct dentry *dentry, struct vfsmount *vfsmnt,
1033 +                      char *buf, int buflen)
1034 +{
1035 +       struct path root, ns_root = { };
1036 +       char *res;
1037 +
1038 +       read_lock(&current->fs->lock);
1039 +       root = current->fs->root;
1040 +       path_get(&current->fs->root);
1041 +       read_unlock(&current->fs->lock);
1042 +       spin_lock(&vfsmount_lock);
1043 +       if (root.mnt)
1044 +               ns_root.mnt = mntget(root.mnt->mnt_ns->root);
1045 +       if (ns_root.mnt)
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);
1049 +       path_put(&root);
1050 +       path_put(&ns_root);
1051 +
1052 +       /* Prevent empty path for lazily unmounted filesystems. */
1053 +       if (!IS_ERR(res) && *res == '\0')
1054 +               *--res = '.';
1055 +       return res;
1056 +}
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");
1063                 goto out_put;
1064         }
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);
1068  out_put:
1069         dput(dentry);
1070  out_unlock:
1071 @@ -258,7 +259,7 @@ nfsd4_remove_clid_file(struct dentry *di
1072                 return -EINVAL;
1073         }
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);
1078         return status;
1079  }
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);
1087         return status;
1088  }
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
1093         }
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) {
1107                 fh_lock(fhp);
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);
1111                 fh_unlock(fhp);
1112         }
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)
1120  {
1121         ssize_t buflen;
1122  
1123 -       buflen = vfs_getxattr(dentry, key, NULL, 0);
1124 +       buflen = vfs_getxattr(dentry, mnt, key, NULL, 0, NULL);
1125         if (buflen <= 0)
1126                 return buflen;
1127  
1128 @@ -420,13 +421,14 @@ static ssize_t nfsd_getxattr(struct dent
1129         if (!*buf)
1130                 return -ENOMEM;
1131  
1132 -       return vfs_getxattr(dentry, key, *buf, buflen);
1133 +       return vfs_getxattr(dentry, mnt, key, *buf, buflen, NULL);
1134  }
1135  #endif
1136  
1137  #if defined(CONFIG_NFSD_V4)
1138  static int
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)
1142  {
1143         int len;
1144         size_t buflen;
1145 @@ -445,7 +447,7 @@ set_nfsv4_acl_one(struct dentry *dentry,
1146                 goto out;
1147         }
1148  
1149 -       error = vfs_setxattr(dentry, key, buf, len, 0);
1150 +       error = vfs_setxattr(dentry, mnt, key, buf, len, 0, NULL);
1151  out:
1152         kfree(buf);
1153         return error;
1154 @@ -458,6 +460,7 @@ nfsd4_set_nfs4_acl(struct svc_rqst *rqst
1155         __be32 error;
1156         int host_error;
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
1163                 return error;
1164  
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)
1172                 goto out_nfserr;
1173  
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);
1177         if (host_error < 0)
1178                 goto out_release;
1179  
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);
1184  
1185  out_release:
1186         posix_acl_release(pacl);
1187 @@ -496,13 +502,13 @@ out_nfserr:
1188  }
1189  
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)
1193  {
1194         void *buf = NULL;
1195         struct posix_acl *pacl = NULL;
1196         int buflen;
1197  
1198 -       buflen = nfsd_getxattr(dentry, key, &buf);
1199 +       buflen = nfsd_getxattr(dentry, mnt, key, &buf);
1200         if (!buflen)
1201                 buflen = -ENODATA;
1202         if (buflen <= 0)
1203 @@ -514,14 +520,15 @@ _get_posix_acl(struct dentry *dentry, ch
1204  }
1205  
1206  int
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)
1210  {
1211         struct inode *inode = dentry->d_inode;
1212         int error = 0;
1213         struct posix_acl *pacl = NULL, *dpacl = NULL;
1214         unsigned int flags = 0;
1215  
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);
1220         if (IS_ERR(pacl)) {
1221 @@ -531,7 +538,7 @@ nfsd4_get_nfs4_acl(struct svc_rqst *rqst
1222         }
1223  
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)
1228                         dpacl = NULL;
1229                 else if (IS_ERR(dpacl)) {
1230 @@ -944,13 +951,13 @@ out:
1231         return err;
1232  }
1233  
1234 -static void kill_suid(struct dentry *dentry)
1235 +static void kill_suid(struct dentry *dentry, struct vfsmount *mnt)
1236  {
1237         struct iattr    ia;
1238         ia.ia_valid = ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;
1239  
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);
1244  }
1245  
1246 @@ -1009,7 +1016,7 @@ nfsd_vfs_write(struct svc_rqst *rqstp, s
1247  
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);
1252  
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)
1257  {
1258         struct dentry   *dentry, *dchild = NULL;
1259 +       struct svc_export *exp;
1260         struct inode    *dirp;
1261         __be32          err;
1262         __be32          err2;
1263 @@ -1203,6 +1211,7 @@ nfsd_create(struct svc_rqst *rqstp, stru
1264                 goto out;
1265  
1266         dentry = fhp->fh_dentry;
1267 +       exp = fhp->fh_export;
1268         dirp = dentry->d_inode;
1269  
1270         err = nfserr_notdir;
1271 @@ -1219,7 +1228,7 @@ nfsd_create(struct svc_rqst *rqstp, stru
1272                 host_err = PTR_ERR(dchild);
1273                 if (IS_ERR(dchild))
1274                         goto out_nfserr;
1275 -               err = fh_compose(resfhp, fhp->fh_export, dchild, fhp);
1276 +               err = fh_compose(resfhp, exp, dchild, fhp);
1277                 if (err)
1278                         goto out;
1279         } else {
1280 @@ -1258,13 +1267,14 @@ nfsd_create(struct svc_rqst *rqstp, stru
1281                 host_err = vfs_create(dirp, dchild, iap->ia_mode, NULL);
1282                 break;
1283         case S_IFDIR:
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);
1286                 break;
1287         case S_IFCHR:
1288         case S_IFBLK:
1289         case S_IFIFO:
1290         case S_IFSOCK:
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);
1294                 break;
1295         default:
1296                 printk("nfsd: bad file type %o in nfsd_create\n", type);
1297 @@ -1273,7 +1283,7 @@ nfsd_create(struct svc_rqst *rqstp, stru
1298         if (host_err < 0)
1299                 goto out_nfserr;
1300  
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);
1305         }
1306 @@ -1496,6 +1506,7 @@ nfsd_symlink(struct svc_rqst *rqstp, str
1307                                 struct iattr *iap)
1308  {
1309         struct dentry   *dentry, *dnew;
1310 +       struct svc_export *exp;
1311         __be32          err, cerr;
1312         int             host_err;
1313         umode_t         mode;
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;
1317  
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);
1329                 }
1330         } else
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);
1335  
1336         if (!host_err) {
1337 -               if (EX_ISSYNC(fhp->fh_export))
1338 +               if (EX_ISSYNC(exp))
1339                         host_err = nfsd_sync_dir(dentry);
1340         }
1341         err = nfserrno(host_err);
1342         fh_unlock(fhp);
1343  
1344 -       cerr = fh_compose(resfhp, fhp->fh_export, dnew, fhp);
1345 +       cerr = fh_compose(resfhp, exp, dnew, fhp);
1346         dput(dnew);
1347         if (err==0) err = cerr;
1348  out:
1349 @@ -1592,7 +1606,8 @@ nfsd_link(struct svc_rqst *rqstp, struct
1350         dold = tfhp->fh_dentry;
1351         dest = dold->d_inode;
1352  
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);
1356         if (!host_err) {
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
1360                         host_err = -EPERM;
1361         } else
1362  #endif
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);
1368                 if (!host_err)
1369 @@ -1721,6 +1737,7 @@ nfsd_unlink(struct svc_rqst *rqstp, stru
1370                                 char *fname, int flen)
1371  {
1372         struct dentry   *dentry, *rdentry;
1373 +       struct svc_export *exp;
1374         struct inode    *dirp;
1375         __be32          err;
1376         int             host_err;
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;
1382  
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
1386  
1387         if (type != S_IFDIR) { /* It's UNLINK */
1388  #ifdef MSNFS
1389 -               if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
1390 +               if ((exp->ex_flags & NFSEXP_MSNFS) &&
1391                         (atomic_read(&rdentry->d_count) > 1)) {
1392                         host_err = -EPERM;
1393                 } else
1394  #endif
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);
1400         }
1401  
1402         dput(rdentry);
1403  
1404         if (host_err)
1405                 goto out_nfserr;
1406 -       if (EX_ISSYNC(fhp->fh_export))
1407 +       if (EX_ISSYNC(exp))
1408                 host_err = nfsd_sync_dir(dentry);
1409  
1410  out_nfserr:
1411 @@ -1995,7 +2013,8 @@ nfsd_get_posix_acl(struct svc_fh *fhp, i
1412                 return ERR_PTR(-EOPNOTSUPP);
1413         }
1414  
1415 -       size = nfsd_getxattr(fhp->fh_dentry, name, &value);
1416 +       size = nfsd_getxattr(fhp->fh_dentry, fhp->fh_export->ex_path.mnt, name,
1417 +                            &value);
1418         if (size < 0)
1419                 return ERR_PTR(size);
1420  
1421 @@ -2007,6 +2026,7 @@ nfsd_get_posix_acl(struct svc_fh *fhp, i
1422  int
1423  nfsd_set_posix_acl(struct svc_fh *fhp, int type, struct posix_acl *acl)
1424  {
1425 +       struct vfsmount *mnt;
1426         struct inode *inode = fhp->fh_dentry->d_inode;
1427         char *name;
1428         void *value = NULL;
1429 @@ -2039,13 +2059,16 @@ nfsd_set_posix_acl(struct svc_fh *fhp, i
1430         } else
1431                 size = 0;
1432  
1433 +       mnt = fhp->fh_export->ex_path.mnt;
1434         if (size)
1435 -               error = vfs_setxattr(fhp->fh_dentry, name, value, size, 0);
1436 +               error = vfs_setxattr(fhp->fh_dentry, mnt, name, value, size, 0,
1437 +                                    NULL);
1438         else {
1439                 if (!S_ISDIR(inode->i_mode) && type == ACL_TYPE_DEFAULT)
1440                         error = 0;
1441                 else {
1442 -                       error = vfs_removexattr(fhp->fh_dentry, name);
1443 +                       error = vfs_removexattr(fhp->fh_dentry, mnt, name,
1444 +                                               NULL);
1445                         if (error == -ENODATA)
1446                                 error = 0;
1447                 }
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
1452                 goto out;
1453         if (!count)
1454                 goto out;
1455 -       err = remove_suid(file->f_path.dentry);
1456 +       err = remove_suid(&file->f_path);
1457         if (err)
1458                 goto out;
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:
1464         return error;
1465  }
1466  
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)
1471  {
1472         int err;
1473         struct iattr newattrs;
1474 @@ -206,16 +206,15 @@ int do_truncate(struct dentry *dentry, l
1475  
1476         newattrs.ia_size = length;
1477         newattrs.ia_valid = ATTR_SIZE | time_attrs;
1478 -       if (filp) {
1479 -               newattrs.ia_file = filp;
1480 +
1481 +       if (filp)
1482                 newattrs.ia_valid |= ATTR_FILE;
1483 -       }
1484  
1485         /* Remove suid/sgid on truncate too */
1486         newattrs.ia_valid |= should_remove_suid(dentry);
1487  
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);
1492         return err;
1493  }
1494 @@ -271,7 +270,7 @@ static long do_sys_truncate(const char _
1495         error = locks_verify_truncate(inode, NULL, length);
1496         if (!error) {
1497                 DQUOT_INIT(inode);
1498 -               error = do_truncate(nd.path.dentry, length, 0, NULL);
1499 +               error = do_truncate(nd.path.dentry, nd.path.mnt, length, 0, NULL);
1500         }
1501  
1502  put_write_and_out:
1503 @@ -324,7 +323,8 @@ static long do_sys_ftruncate(unsigned in
1504  
1505         error = locks_verify_truncate(inode, file, length);
1506         if (!error)
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);
1510  out_putf:
1511         fput(file);
1512  out:
1513 @@ -500,8 +500,8 @@ out:
1514  
1515  asmlinkage long sys_fchdir(unsigned int fd)
1516  {
1517 +       struct nameidata nd = { .flags = 0 };
1518         struct file *file;
1519 -       struct inode *inode;
1520         int error;
1521  
1522         error = -EBADF;
1523 @@ -509,12 +509,11 @@ asmlinkage long sys_fchdir(unsigned int 
1524         if (!file)
1525                 goto out;
1526  
1527 -       inode = file->f_path.dentry->d_inode;
1528 -
1529         error = -ENOTDIR;
1530 -       if (!S_ISDIR(inode->i_mode))
1531 +       if (!S_ISDIR(file->f_path.dentry->d_inode->i_mode))
1532                 goto out_putf;
1533  
1534 +       nd.path = file->f_path;
1535         error = file_permission(file, MAY_EXEC);
1536         if (!error)
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);
1547  
1548  out_putf:
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);
1556  
1557  dput_and_out:
1558 @@ -627,7 +626,7 @@ asmlinkage long sys_chmod(const char __u
1559  }
1560  
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)
1564  {
1565         struct inode * inode;
1566         int error;
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;
1571 +       if (file)
1572 +               newattrs.ia_valid |= ATTR_FILE;
1573 +
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);
1578  out:
1579         return error;
1580 @@ -671,7 +686,7 @@ asmlinkage long sys_chown(const char __u
1581         error = cow_check_and_break(&nd);
1582         if (!error)
1583  #endif
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);
1586         path_put(&nd.path);
1587  out:
1588         return error;
1589 @@ -691,7 +710,7 @@ asmlinkage long sys_fchownat(int dfd, co
1590         error = __user_walk_fd(dfd, filename, follow, &nd);
1591         if (!error)
1592  #endif
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);
1595         path_put(&nd.path);
1596  out:
1597         return error;
1598 @@ -705,7 +708,7 @@ asmlinkage long sys_lchown(const char __
1599         error = cow_check_and_break(&nd);
1600         if (!error)
1601  #endif
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);
1604         path_put(&nd.path);
1605  out:
1606         return error;
1607 @@ -724,7 +727,7 @@ asmlinkage long sys_fchown(unsigned int 
1608  
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);
1613         fput(file);
1614  out:
1615         return error;
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);
1625         if (err)
1626                 goto out_filp;
1627  
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);
1635                 dput(root);
1636         } else {
1637 @@ -791,7 +791,7 @@ reiserfs_chown_xattrs_filler(void *buf, 
1638         }
1639  
1640         if (!S_ISDIR(xafile->d_inode->i_mode))
1641 -               err = notify_change(xafile, attrs);
1642 +               err = notify_change(xafile, NULL, attrs);
1643         dput(xafile);
1644  
1645         return err;
1646 @@ -835,7 +835,7 @@ int reiserfs_chown_xattrs(struct inode *
1647                 goto out_dir;
1648         }
1649  
1650 -       err = notify_change(dir, attrs);
1651 +       err = notify_change(dir, NULL, attrs);
1652         unlock_kernel();
1653  
1654        out_dir:
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 
1659         ssize_t ret;
1660         int err;
1661  
1662 -       err = remove_suid(out->f_path.dentry);
1663 +       err = remove_suid(&out->f_path);
1664         if (unlikely(err))
1665                 return err;
1666  
1667 @@ -822,7 +822,7 @@ generic_file_splice_write(struct pipe_in
1668                 if (killpriv)
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);
1674                 if (err)
1675                         return err;
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, 
1680  
1681                 error = -EINVAL;
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);
1685                         if (!error) {
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
1692  
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);
1697  
1698         if (rc == 0) {
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
1704  {
1705         int error;
1706         struct nameidata nd;
1707 -       struct dentry *dentry;
1708 +       struct path path;
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
1713                 f = fget(dfd);
1714                 if (!f)
1715                         goto out;
1716 -               dentry = f->f_path.dentry;
1717 +               path = f->f_path;
1718         } else {
1719                 error = __user_walk_fd(dfd, filename, (flags & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW, &nd);
1720                 if (error)
1721                         goto out;
1722  
1723                 error = cow_check_and_break(&nd);
1724                 if (error)
1725                         goto dput_and_out;
1726 -               dentry = nd.path.dentry;
1727 +               path = nd.path;
1728         }
1729  
1730 -       inode = dentry->d_inode;
1731 +       inode = path.dentry->d_inode;
1732  
1733         error = -EROFS;
1734         if (IS_RDONLY(inode))
1735 @@ -145,7 +145,7 @@ long do_utimes(int dfd, char __user *fil
1736                 }
1737         }
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);
1742  dput_and_out:
1743         if (f)
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
1748  }
1749  
1750  int
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)
1755  {
1756         struct inode *inode = dentry->d_inode;
1757         int error;
1758 @@ -79,7 +79,7 @@ vfs_setxattr(struct dentry *dentry, char
1759                 return error;
1760  
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);
1764         if (error)
1765                 goto out;
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);
1769                 if (!error) {
1770                         fsnotify_xattr(dentry);
1771 -                       security_inode_post_setxattr(dentry, name, value,
1772 +                       security_inode_post_setxattr(dentry, mnt, name, value,
1773                                                      size, flags);
1774                 }
1775         } else if (!strncmp(name, XATTR_SECURITY_PREFIX,
1776 @@ -132,7 +132,8 @@ out_noalloc:
1777  EXPORT_SYMBOL_GPL(xattr_getsecurity);
1778  
1779  ssize_t
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)
1783  {
1784         struct inode *inode = dentry->d_inode;
1785         int error;
1786 @@ -141,7 +142,7 @@ vfs_getxattr(struct dentry *dentry, char
1787         if (error)
1788                 return error;
1789  
1790 -       error = security_inode_getxattr(dentry, name);
1791 +       error = security_inode_getxattr(dentry, mnt, name, file);
1792         if (error)
1793                 return error;
1794  
1795 @@ -168,18 +169,20 @@ nolsm:
1796  EXPORT_SYMBOL_GPL(vfs_getxattr);
1797  
1798  ssize_t
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)
1802  {
1803 +       struct inode *inode = dentry->d_inode;
1804         ssize_t error;
1805  
1806 -       error = security_inode_listxattr(d);
1807 +       error = security_inode_listxattr(dentry, mnt, file);
1808         if (error)
1809                 return error;
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);
1813 -       } else {
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);
1817 +       else {
1818 +               error = security_inode_listsecurity(inode, list, size);
1819                 if (size && error > size)
1820                         error = -ERANGE;
1821         }
1822 @@ -188,7 +191,8 @@ vfs_listxattr(struct dentry *d, char *li
1823  EXPORT_SYMBOL_GPL(vfs_listxattr);
1824  
1825  int
1826 -vfs_removexattr(struct dentry *dentry, char *name)
1827 +vfs_removexattr(struct dentry *dentry, struct vfsmount *mnt, char *name,
1828 +               struct file *file)
1829  {
1830         struct inode *inode = dentry->d_inode;
1831         int error;
1832 @@ -200,7 +204,7 @@ vfs_removexattr(struct dentry *dentry, c
1833         if (error)
1834                 return error;
1835  
1836 -       error = security_inode_removexattr(dentry, name);
1837 +       error = security_inode_removexattr(dentry, mnt, name, file);
1838         if (error)
1839                 return error;
1840  
1841 @@ -219,7 +223,7 @@ EXPORT_SYMBOL_GPL(vfs_removexattr);
1842   */
1843  static long
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)
1847  {
1848         int error;
1849         void *kvalue = NULL;
1850 @@ -247,7 +251,7 @@ setxattr(struct dentry *d, char __user *
1851                 }
1852         }
1853  
1854 -       error = vfs_setxattr(d, kname, kvalue, size, flags);
1855 +       error = vfs_setxattr(d, mnt, kname, kvalue, size, flags, file);
1856         kfree(kvalue);
1857         return error;
1858  }
1859 @@ -262,7 +266,7 @@ sys_setxattr(char __user *path, char __u
1860         error = user_path_walk(path, &nd);
1861         if (error)
1862                 return error;
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);
1865         path_put(&nd.path);
1866         return error;
1867  }
1868 @@ -277,7 +281,7 @@ sys_lsetxattr(char __user *path, char __
1869         error = user_path_walk_link(path, &nd);
1870         if (error)
1871                 return error;
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);
1874         path_put(&nd.path);
1875         return error;
1876  }
1877 @@ -295,7 +299,7 @@ sys_fsetxattr(int fd, char __user *name,
1878                 return error;
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);
1883         fput(f);
1884         return error;
1885  }
1886 @@ -304,7 +308,8 @@ sys_fsetxattr(int fd, char __user *name,
1887   * Extended attribute GET operations
1888   */
1889  static ssize_t
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)
1893  {
1894         ssize_t error;
1895         void *kvalue = NULL;
1896 @@ -324,7 +329,7 @@ getxattr(struct dentry *d, char __user *
1897                         return -ENOMEM;
1898         }
1899  
1900 -       error = vfs_getxattr(d, kname, kvalue, size);
1901 +       error = vfs_getxattr(dentry, mnt, kname, kvalue, size, file);
1902         if (error > 0) {
1903                 if (size && copy_to_user(value, kvalue, error))
1904                         error = -EFAULT;
1905 @@ -347,7 +352,7 @@ sys_getxattr(char __user *path, char __u
1906         error = user_path_walk(path, &nd);
1907         if (error)
1908                 return error;
1909 -       error = getxattr(nd.path.dentry, name, value, size);
1910 +       error = getxattr(nd.path.dentry, nd.path.mnt, name, value, size, NULL);
1911         path_put(&nd.path);
1912         return error;
1913  }
1914 @@ -362,7 +367,7 @@ sys_lgetxattr(char __user *path, char __
1915         error = user_path_walk_link(path, &nd);
1916         if (error)
1917                 return error;
1918 -       error = getxattr(nd.path.dentry, name, value, size);
1919 +       error = getxattr(nd.path.dentry, nd.path.mnt, name, value, size, NULL);
1920         path_put(&nd.path);
1921         return error;
1922  }
1923 @@ -377,7 +382,7 @@ sys_fgetxattr(int fd, char __user *name,
1924         if (!f)
1925                 return error;
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);
1929         fput(f);
1930         return error;
1931  }
1932 @@ -386,7 +391,8 @@ sys_fgetxattr(int fd, char __user *name,
1933   * Extended attribute LIST operations
1934   */
1935  static ssize_t
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)
1939  {
1940         ssize_t error;
1941         char *klist = NULL;
1942 @@ -399,7 +405,7 @@ listxattr(struct dentry *d, char __user 
1943                         return -ENOMEM;
1944         }
1945  
1946 -       error = vfs_listxattr(d, klist, size);
1947 +       error = vfs_listxattr(dentry, mnt, klist, size, file);
1948         if (error > 0) {
1949                 if (size && copy_to_user(list, klist, error))
1950                         error = -EFAULT;
1951 @@ -421,7 +427,7 @@ sys_listxattr(char __user *path, char __
1952         error = user_path_walk(path, &nd);
1953         if (error)
1954                 return error;
1955 -       error = listxattr(nd.path.dentry, list, size);
1956 +       error = listxattr(nd.path.dentry, nd.path.mnt, list, size, NULL);
1957         path_put(&nd.path);
1958         return error;
1959  }
1960 @@ -435,7 +441,7 @@ sys_llistxattr(char __user *path, char _
1961         error = user_path_walk_link(path, &nd);
1962         if (error)
1963                 return error;
1964 -       error = listxattr(nd.path.dentry, list, size);
1965 +       error = listxattr(nd.path.dentry, nd.path.mnt, list, size, NULL);
1966         path_put(&nd.path);
1967         return error;
1968  }
1969 @@ -450,7 +456,7 @@ sys_flistxattr(int fd, char __user *list
1970         if (!f)
1971                 return error;
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);
1975         fput(f);
1976         return error;
1977  }
1978 @@ -459,7 +465,8 @@ sys_flistxattr(int fd, char __user *list
1979   * Extended attribute REMOVE operations
1980   */
1981  static long
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)
1985  {
1986         int error;
1987         char kname[XATTR_NAME_MAX + 1];
1988 @@ -470,7 +477,7 @@ removexattr(struct dentry *d, char __use
1989         if (error < 0)
1990                 return error;
1991  
1992 -       return vfs_removexattr(d, kname);
1993 +       return vfs_removexattr(dentry, mnt, kname, file);
1994  }
1995  
1996  asmlinkage long
1997 @@ -482,7 +489,7 @@ sys_removexattr(char __user *path, char 
1998         error = user_path_walk(path, &nd);
1999         if (error)
2000                 return error;
2001 -       error = removexattr(nd.path.dentry, name, nd.path.mnt);
2002 +       error = removexattr(nd.path.dentry, name, nd.path.mnt, NULL);
2003         path_put(&nd.path);
2004         return error;
2005  }
2006 @@ -496,7 +503,7 @@ sys_lremovexattr(char __user *path, char
2007         error = user_path_walk_link(path, &nd);
2008         if (error)
2009                 return error;
2010 -       error = removexattr(nd.path.dentry, name, nd.path.mnt);
2011 +       error = removexattr(nd.path.dentry, name, nd.path.mnt, NULL);
2012         path_put(&nd.path);
2013         return error;
2014  }
2015 @@ -513,7 +520,7 @@ sys_fremovexattr(int fd, char __user *na
2016                 return error;
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);
2021         fput(f);
2022         return error;
2023  }
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);
2030                 if (likely(!error))
2031 -                       error = -remove_suid(file->f_path.dentry);
2032 +                       error = -remove_suid(&file->f_path);
2033                 if (unlikely(error)) {
2034                         goto out_unlock_internal;
2035                 }
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
2039 @@ -33,7 +33,7 @@
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 */
2051  
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 */
2058 +
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)));
2064  
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
2077   */
2078  extern char *dynamic_dname(struct dentry *, char *, int, const char *, ...);
2079 -
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);
2083  
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;
2092 -
2093 -       /*
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).
2097 -        */
2098 -       struct file     *ia_file;
2099  };
2100  
2101  /*
2102 @@ -1076,13 +1069,13 @@ extern void unlock_super(struct super_bl
2103   */
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 *);
2120  
2121  /*
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 *);
2128  };
2129  
2130  struct inode_operations {
2131 @@ -1559,8 +1553,8 @@ static inline int break_lease(struct ino
2132  
2133  /* fs/open.c */
2134  
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,
2140                         int mode);
2141  extern struct file *filp_open(const char *, int, int);
2142 @@ -1714,7 +1708,8 @@ extern int do_remount_sb(struct super_bl
2143  #ifdef CONFIG_BLOCK
2144  extern sector_t bmap(struct inode *, sector_t);
2145  #endif
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 *);
2161  
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);
2170  
2171 +extern char *d_namespace_path(struct dentry *, struct vfsmount *, char *, int);
2172 +
2173  #endif
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 *,
2181                      struct nfs4_acl *);
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.
2209   * @inode_link:
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.
2217   * @inode_unlink:
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.
2223   * @inode_symlink:
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.
2230   * @inode_mkdir:
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.
2238   * @inode_rmdir:
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.
2244   * @inode_mknod:
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.
2263   * @inode_readlink:
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.
2277   * @inode_getattr:
2278 @@ -419,18 +431,18 @@ static inline void security_free_mnt_opt
2279   *     inode.
2280   * @inode_setxattr:
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.
2289   * @inode_getxattr:
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.
2294   * @inode_listxattr:
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,
2418 +                                 int flags);
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
2429         
2430  static inline int security_inode_create (struct inode *dir,
2431                                          struct dentry *dentry,
2432 +                                        struct vfsmount *mnt,
2433                                          int mode)
2434  {
2435         return 0;
2436  }
2437  
2438  static inline int security_inode_link (struct dentry *old_dentry,
2439 +                                      struct vfsmount *old_mnt,
2440                                        struct inode *dir,
2441 -                                      struct dentry *new_dentry)
2442 +                                      struct dentry *new_dentry,
2443 +                                      struct vfsmount *new_mnt)
2444  {
2445         return 0;
2446  }
2447  
2448  static inline int security_inode_unlink (struct inode *dir,
2449 -                                        struct dentry *dentry)
2450 +                                        struct dentry *dentry,
2451 +                                        struct vfsmount *mnt)
2452  {
2453         return 0;
2454  }
2455  
2456  static inline int security_inode_symlink (struct inode *dir,
2457                                           struct dentry *dentry,
2458 +                                         struct vfsmount *mnt,
2459                                           const char *old_name)
2460  {
2461         return 0;
2462 @@ -1914,19 +1957,22 @@ static inline int security_inode_symlink
2463  
2464  static inline int security_inode_mkdir (struct inode *dir,
2465                                         struct dentry *dentry,
2466 +                                       struct vfsmount *mnt,
2467                                         int mode)
2468  {
2469         return 0;
2470  }
2471  
2472  static inline int security_inode_rmdir (struct inode *dir,
2473 -                                       struct dentry *dentry)
2474 +                                       struct dentry *dentry,
2475 +                                       struct vfsmount *mnt)
2476  {
2477         return 0;
2478  }
2479  
2480  static inline int security_inode_mknod (struct inode *dir,
2481                                         struct dentry *dentry,
2482 +                                       struct vfsmount *mnt,
2483                                         int mode, dev_t dev)
2484  {
2485         return 0;
2486 @@ -1934,13 +1980,16 @@ static inline int security_inode_mknod (
2487  
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)
2495  {
2496         return 0;
2497  }
2498  
2499 -static inline int security_inode_readlink (struct dentry *dentry)
2500 +static inline int security_inode_readlink(struct dentry *dentry,
2501 +                                          struct vfsmount *mnt)
2502  {
2503         return 0;
2504  }
2505 @@ -1958,6 +2007,7 @@ static inline int security_inode_permiss
2506  }
2507  
2508  static inline int security_inode_setattr (struct dentry *dentry,
2509 +                                         struct vfsmount *mnt,
2510                                           struct iattr *attr)
2511  {
2512         return 0;
2513 @@ -1972,29 +2022,40 @@ static inline int security_inode_getattr
2514  static inline void security_inode_delete (struct inode *inode)
2515  { }
2516  
2517 -static inline int security_inode_setxattr (struct dentry *dentry, char *name,
2518 -                                          void *value, size_t size, int flags)
2519 -{
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)
2525 +{
2526 +       return cap_inode_setxattr(dentry, mnt, name, value, size, flags, file);
2527  }
2528  
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,
2533 +                                                char *name,
2534 +                                                void *value, size_t size,
2535 +                                                int flags)
2536  { }
2537  
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)
2542  {
2543         return 0;
2544  }
2545  
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)
2550  {
2551         return 0;
2552  }
2553  
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)
2558  {
2559 -       return cap_inode_removexattr(dentry, name);
2560 +       return cap_inode_removexattr(dentry, mnt, name, file);
2561  }
2562  
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 *);
2570  
2571 +extern char *sysctl_pathname(ctl_table *, char *, int);
2572 +
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 {
2580  };
2581  
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 *);
2594  
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
2601         if (inode)
2602                 atomic_inc(&inode->i_count);
2603  
2604 -       err = vfs_unlink(dentry->d_parent->d_inode, dentry, NULL);
2605 +       err = vfs_unlink(dentry->d_parent->d_inode, dentry, NULL, mqueue_mnt);
2606  out_err:
2607         dput(dentry);
2608  
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.
2615   */
2616 -static void audit_log_vformat(struct audit_buffer *ab, const char *fmt,
2617 -                             va_list args)
2618 +void audit_log_vformat(struct audit_buffer *ab, const char *fmt, va_list args)
2619  {
2620         int len, avail;
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
2633         }
2634  
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);
2639         dput(dentry);
2640         if (ret) {
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);
2646  }
2647  
2648 +char *sysctl_pathname(struct ctl_table *table, char *buffer, int buflen)
2649 +{
2650 +       if (buflen < 1)
2651 +               return NULL;
2652 +       buffer += --buflen;
2653 +       *buffer = '\0';
2654 +
2655 +       while (table) {
2656 +               int namelen = strlen(table->procname);
2657 +
2658 +               if (buflen < namelen + 1)
2659 +                       return NULL;
2660 +               buflen -= namelen + 1;
2661 +               buffer -= namelen;
2662 +               memcpy(buffer, table->procname, namelen);
2663 +               *--buffer = '/';
2664 +               table = table->parent;
2665 +       }
2666 +       if (buflen < 4)
2667 +               return NULL;
2668 +       buffer -= 4;
2669 +       memcpy(buffer, "/sys", 4);
2670 +
2671 +       return buffer;
2672 +}
2673 +EXPORT_SYMBOL_GPL(sysctl_pathname);
2674 +
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
2682  }
2683  EXPORT_SYMBOL(should_remove_suid);
2684  
2685 -int __remove_suid(struct dentry *dentry, int kill)
2686 +int __remove_suid(struct path *path, int kill)
2687  {
2688         struct iattr newattrs;
2689  
2690         newattrs.ia_valid = ATTR_FORCE | kill;
2691 -       return notify_change(dentry, &newattrs);
2692 +       return notify_change(path->dentry, path->mnt, &newattrs);
2693  }
2694  
2695 -int remove_suid(struct dentry *dentry)
2696 +int remove_suid(struct path *path)
2697  {
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);
2702         int error = 0;
2703  
2704         if (killpriv < 0)
2705                 return killpriv;
2706         if (killpriv)
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);
2712  
2713         return error;
2714  }
2715 @@ -2387,7 +2387,7 @@ __generic_file_aio_write_nolock(struct k
2716         if (count == 0)
2717                 goto out;
2718  
2719 -       err = remove_suid(file->f_path.dentry);
2720 +       err = remove_suid(&file->f_path);
2721         if (err)
2722                 goto out;
2723  
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 
2728         if (count == 0)
2729                 goto out_backing;
2730  
2731 -       ret = remove_suid(filp->f_path.dentry);
2732 +       ret = remove_suid(&filp->f_path);
2733         if (ret)
2734                 goto out_backing;
2735  
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 */
2741  
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);
2745         if (error < 0)
2746                 goto close_file;
2747  
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
2752                  */
2753                 mode = S_IFSOCK |
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,
2757 +                               mode, 0, NULL);
2758                 if (err)
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
2765  
2766  source security/selinux/Kconfig
2767  source security/smack/Kconfig
2768 +source security/apparmor/Kconfig
2769  
2770  endmenu
2771  
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
2785 @@ -0,0 +1,42 @@
2786 +config SECURITY_APPARMOR
2787 +       bool "AppArmor support"
2788 +       depends on SECURITY
2789 +       select AUDIT
2790 +       help
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>
2795 +
2796 +         If you are unsure how to answer this question, answer N.
2797 +
2798 +config SECURITY_APPARMOR_BOOTPARAM_VALUE
2799 +       int "AppArmor boot parameter default value"
2800 +       depends on SECURITY_APPARMOR
2801 +       range 0 1
2802 +       default 1
2803 +       help
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
2810 +         bootup.
2811 +
2812 +         If you are unsure how to answer this question, answer 1.
2813 +
2814 +config SECURITY_APPARMOR_DISABLE
2815 +       bool "AppArmor runtime disable"
2816 +       depends on SECURITY_APPARMOR
2817 +       default n
2818 +       help
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.
2826 +
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
2831 @@ -0,0 +1,18 @@
2832 +# Makefile for AppArmor Linux Security Module
2833 +#
2834 +obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
2835 +
2836 +apparmor-y := main.o list.o procattr.o lsm.o apparmorfs.o \
2837 +             module_interface.o match.o
2838 +
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 > $@
2841 +
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 > $@
2844 +
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
2853 @@ -0,0 +1,403 @@
2854 +/*
2855 + *     Copyright (C) 1998-2007 Novell/SUSE
2856 + *
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
2860 + *     License.
2861 + *
2862 + *     AppArmor internal prototypes
2863 + */
2864 +
2865 +#ifndef __APPARMOR_H
2866 +#define __APPARMOR_H
2867 +
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>
2875 +
2876 +/*
2877 + * We use MAY_READ, MAY_WRITE, MAY_EXEC, MAY_APPEND and the following flags
2878 + * for profile permissions
2879 + */
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
2890 +
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 | \
2897 +                                        AA_EXEC_MOD_3)
2898 +
2899 +#define AA_EXEC_MODIFIERS              (AA_EXEC_MOD_0 | AA_EXEC_MOD_1 | \
2900 +                                        AA_EXEC_MOD_2 | AA_EXEC_MOD_3)
2901 +
2902 +#define AA_EXEC_TYPE                   (AA_EXEC_UNSAFE | AA_EXEC_INHERIT | \
2903 +                                        AA_EXEC_MODIFIERS)
2904 +
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)
2910 +
2911 +#define AA_USER_SHIFT                  0
2912 +#define AA_OTHER_SHIFT                 14
2913 +
2914 +#define AA_USER_PERMS                  (AA_BASE_PERMS << AA_USER_SHIFT)
2915 +#define AA_OTHER_PERMS                 (AA_BASE_PERMS << AA_OTHER_SHIFT)
2916 +
2917 +#define AA_FILE_PERMS                  (AA_USER_PERMS | AA_OTHER_PERMS)
2918 +
2919 +#define AA_LINK_BITS                   ((AA_MAY_LINK << AA_USER_SHIFT) | \
2920 +                                        (AA_MAY_LINK << AA_OTHER_SHIFT))
2921 +
2922 +#define AA_USER_EXEC                   (MAY_EXEC << AA_USER_SHIFT)
2923 +#define AA_OTHER_EXEC                  (MAY_EXEC << AA_OTHER_SHIFT)
2924 +
2925 +#define AA_USER_EXEC_TYPE              (AA_EXEC_TYPE << AA_USER_SHIFT)
2926 +#define AA_OTHER_EXEC_TYPE             (AA_EXEC_TYPE << AA_OTHER_SHIFT)
2927 +
2928 +#define AA_EXEC_BITS                   (AA_USER_EXEC | AA_OTHER_EXEC)
2929 +
2930 +#define ALL_AA_EXEC_UNSAFE             ((AA_EXEC_UNSAFE << AA_USER_SHIFT) | \
2931 +                                        (AA_EXEC_UNSAFE << AA_OTHER_SHIFT))
2932 +
2933 +#define ALL_AA_EXEC_TYPE               (AA_USER_EXEC_TYPE | AA_OTHER_EXEC_TYPE)
2934 +
2935 +/* overloaded permissions for link pairs */
2936 +#define AA_LINK_SUBSET_TEST            0x0020
2937 +
2938 +#define AA_USER_PTRACE                 0x10000000
2939 +#define AA_OTHER_PTRACE                        0x20000000
2940 +#define AA_PTRACE_PERMS                        (AA_USER_PTRACE | AA_OTHER_PTRACE)
2941 +
2942 +/* shared permissions that are not duplicated in user::other */
2943 +#define AA_CHANGE_HAT                  0x40000000
2944 +#define AA_CHANGE_PROFILE              0x80000000
2945 +
2946 +#define AA_SHARED_PERMS                        (AA_CHANGE_HAT | AA_CHANGE_PROFILE)
2947 +
2948 +#define AA_VALID_PERM_MASK             (AA_FILE_PERMS | AA_PTRACE_PERMS | \
2949 +                                        AA_SHARED_PERMS)
2950 +
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
2955 +
2956 +#define AA_SECURE_EXEC_NEEDED          1
2957 +
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;
2965 +
2966 +#define PROFILE_COMPLAIN(_profile) \
2967 +       (apparmor_complain == 1 || ((_profile) && (_profile)->flags.complain))
2968 +
2969 +#define APPARMOR_COMPLAIN(_cxt) \
2970 +       (apparmor_complain == 1 || \
2971 +        ((_cxt) && (_cxt)->profile && (_cxt)->profile->flags.complain))
2972 +
2973 +#define PROFILE_AUDIT(_profile) \
2974 +       (apparmor_audit == 1 || ((_profile) && (_profile)->flags.audit))
2975 +
2976 +#define APPARMOR_AUDIT(_cxt) \
2977 +       (apparmor_audit == 1 || \
2978 +        ((_cxt) && (_cxt)->profile && (_cxt)->profile->flags.audit))
2979 +
2980 +#define PROFILE_IS_HAT(_profile) \
2981 +      ((_profile) && (_profile)->flags.hat)
2982 +
2983 +/*
2984 + * DEBUG remains global (no per profile flag) since it is mostly used in sysctl
2985 + * which is not related to profile accesses.
2986 + */
2987 +
2988 +#define AA_DEBUG(fmt, args...)                                         \
2989 +       do {                                                            \
2990 +               if (apparmor_debug)                                     \
2991 +                       printk(KERN_DEBUG "AppArmor: " fmt, ##args);    \
2992 +       } while (0)
2993 +
2994 +#define AA_ERROR(fmt, args...) printk(KERN_ERR "AppArmor: " fmt, ##args)
2995 +
2996 +/* struct aa_rlimit - rlimits settings for the profile
2997 + * @mask: which hard limits to set
2998 + * @limits: rlimit values that override task limits
2999 + *
3000 + * AppArmor rlimits are used to set confined task rlimits.  Only the
3001 + * limits specified in @mask will be controlled by apparmor.
3002 + */
3003 +struct aa_rlimit {
3004 +       unsigned int mask;
3005 +       struct rlimit limits[RLIM_NLIMITS];
3006 +};
3007 +
3008 +struct aa_profile;
3009 +
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
3018 + */
3019 +struct aa_namespace {
3020 +       char *name;
3021 +       struct list_head list;
3022 +       struct list_head profiles;
3023 +       int profile_count;
3024 +       struct aa_profile *null_complain_profile;
3025 +
3026 +       struct kref count;
3027 +       rwlock_t lock;
3028 +};
3029 +
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
3050 + *
3051 + * The AppArmor profile contains the basic confinement data.  Each profile
3052 + * has a name, and all nonstale profile are in a profile namespace.
3053 + *
3054 + * The task_contexts list and the isstale flag are protected by the
3055 + * profile lock.
3056 + *
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
3059 + * way.
3060 + */
3061 +struct aa_profile {
3062 +       char *name;
3063 +       struct list_head list;
3064 +       struct aa_namespace *ns;
3065 +
3066 +       int exec_table_size;
3067 +       char **exec_table;
3068 +       struct aa_dfa *file_rules;
3069 +       struct {
3070 +               int hat;
3071 +               int complain;
3072 +               int audit;
3073 +       } flags;
3074 +       int isstale;
3075 +
3076 +       kernel_cap_t set_caps;
3077 +       kernel_cap_t capabilities;
3078 +       kernel_cap_t audit_caps;
3079 +       kernel_cap_t quiet_caps;
3080 +
3081 +       struct aa_rlimit rlimits;
3082 +       unsigned int task_count;
3083 +
3084 +       struct kref count;
3085 +       struct list_head task_contexts;
3086 +       spinlock_t lock;
3087 +       unsigned long int_flags;
3088 +       u16 network_families[AF_MAX];
3089 +       u16 audit_network[AF_MAX];
3090 +       u16 quiet_network[AF_MAX];
3091 +};
3092 +
3093 +extern struct list_head profile_ns_list;
3094 +extern rwlock_t profile_ns_list_lock;
3095 +extern struct mutex aa_interface_lock;
3096 +
3097 +/**
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
3106 + *
3107 + * Contains the task's current profile (which could change due to
3108 + * change_hat).  Plus the hat_magic needed during change_hat.
3109 + */
3110 +struct aa_task_context {
3111 +       struct aa_profile *profile;
3112 +       struct aa_profile *previous_profile;
3113 +       u64 cookie;
3114 +       struct list_head list;
3115 +       struct task_struct *task;
3116 +       struct rcu_head rcu;
3117 +       kernel_cap_t caps_logged;
3118 +};
3119 +
3120 +extern struct aa_namespace *default_namespace;
3121 +
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.
3125 + */
3126 +
3127 +struct aa_audit {
3128 +       const char *operation;
3129 +       gfp_t gfp_mask;
3130 +       const char *info;
3131 +       const char *name;
3132 +       const char *name2;
3133 +       const char *name3;
3134 +       int request_mask, denied_mask, audit_mask;
3135 +       int rlimit;
3136 +       struct iattr *iattr;
3137 +       pid_t task, parent;
3138 +       int family, type, protocol;
3139 +       int error_code;
3140 +};
3141 +
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 */
3145 +
3146 +/* lock subtypes so lockdep does not raise false dependencies */
3147 +enum aa_lock_class {
3148 +       aa_lock_normal,
3149 +       aa_lock_nested,
3150 +       aa_lock_task_release
3151 +};
3152 +
3153 +/* main.c */
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,
3157 +                           int type);
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,
3162 +                                 const char *);
3163 +extern int aa_audit(struct aa_profile *profile, struct aa_audit *);
3164 +
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,
3173 +                  int check);
3174 +extern int aa_perm_dir(struct aa_profile *profile, const char *operation,
3175 +                      struct dentry *dentry, struct vfsmount *mnt,
3176 +                      int mask);
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);
3206 +
3207 +
3208 +/* lsm.c */
3209 +extern int apparmor_initialized;
3210 +extern void info_message(const char *str, const char *name);
3211 +extern void apparmor_disable(void);
3212 +
3213 +/* list.c */
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);
3219 +
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);
3231 +
3232 +/* procattr.c */
3233 +extern int aa_getprocattr(struct aa_profile *profile, char **string,
3234 +                         unsigned *len);
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);
3238 +
3239 +/* apparmorfs.c */
3240 +extern int create_apparmorfs(void);
3241 +extern void destroy_apparmorfs(void);
3242 +
3243 +/* match.c */
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,
3250 +                                     const char *str);
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);
3255 +
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
3260 @@ -0,0 +1,279 @@
3261 +/*
3262 + *     Copyright (C) 1998-2007 Novell/SUSE
3263 + *
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
3267 + *
3268 + *     AppArmor filesystem (part of securityfs)
3269 + */
3270 +
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>
3276 +
3277 +#include "apparmor.h"
3278 +#include "inline.h"
3279 +
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)
3283 +{
3284 +       struct aa_profile *profile;
3285 +       char *data;
3286 +
3287 +       if (*pos != 0) {
3288 +               /* only writes from pos 0, that is complete writes */
3289 +               data = ERR_PTR(-ESPIPE);
3290 +               goto out;
3291 +       }
3292 +
3293 +       /*
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.
3297 +        */
3298 +       profile = aa_get_profile(current);
3299 +       if (profile) {
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);
3307 +               goto out;
3308 +       }
3309 +
3310 +       data = vmalloc(alloc_size);
3311 +       if (data == NULL) {
3312 +               data = ERR_PTR(-ENOMEM);
3313 +               goto out;
3314 +       }
3315 +
3316 +       if (copy_from_user(data, userbuf, copy_size)) {
3317 +               vfree(data);
3318 +               data = ERR_PTR(-EFAULT);
3319 +               goto out;
3320 +       }
3321 +
3322 +out:
3323 +       return data;
3324 +}
3325 +
3326 +/* apparmor/profiles */
3327 +extern struct seq_operations apparmorfs_profiles_op;
3328 +
3329 +static int aa_profiles_open(struct inode *inode, struct file *file)
3330 +{
3331 +       return seq_open(file, &apparmorfs_profiles_op);
3332 +}
3333 +
3334 +
3335 +static int aa_profiles_release(struct inode *inode, struct file *file)
3336 +{
3337 +       return seq_release(inode, file);
3338 +}
3339 +
3340 +static struct file_operations apparmorfs_profiles_fops = {
3341 +       .open =         aa_profiles_open,
3342 +       .read =         seq_read,
3343 +       .llseek =       seq_lseek,
3344 +       .release =      aa_profiles_release,
3345 +};
3346 +
3347 +/* apparmor/matching */
3348 +static ssize_t aa_matching_read(struct file *file, char __user *buf,
3349 +                              size_t size, loff_t *ppos)
3350 +{
3351 +       const char *matching = "pattern=aadfa audit perms=rwxamlk/ user::other";
3352 +
3353 +       return simple_read_from_buffer(buf, size, ppos, matching,
3354 +                                      strlen(matching));
3355 +}
3356 +
3357 +static struct file_operations apparmorfs_matching_fops = {
3358 +       .read =         aa_matching_read,
3359 +};
3360 +
3361 +/* apparmor/features */
3362 +static ssize_t aa_features_read(struct file *file, char __user *buf,
3363 +                               size_t size, loff_t *ppos)
3364 +{
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";
3368 +
3369 +       return simple_read_from_buffer(buf, size, ppos, features,
3370 +                                      strlen(features));
3371 +}
3372 +
3373 +static struct file_operations apparmorfs_features_fops = {
3374 +       .read =         aa_features_read,
3375 +};
3376 +
3377 +/* apparmor/.load */
3378 +static ssize_t aa_profile_load(struct file *f, const char __user *buf,
3379 +                              size_t size, loff_t *pos)
3380 +{
3381 +       char *data;
3382 +       ssize_t error;
3383 +
3384 +       data = aa_simple_write_to_buffer(buf, size, size, pos, "profile_load");
3385 +
3386 +       error = PTR_ERR(data);
3387 +       if (!IS_ERR(data)) {
3388 +               error = aa_add_profile(data, size);
3389 +               vfree(data);
3390 +       }
3391 +
3392 +       return error;
3393 +}
3394 +
3395 +
3396 +static struct file_operations apparmorfs_profile_load = {
3397 +       .write = aa_profile_load
3398 +};
3399 +
3400 +/* apparmor/.replace */
3401 +static ssize_t aa_profile_replace(struct file *f, const char __user *buf,
3402 +                                 size_t size, loff_t *pos)
3403 +{
3404 +       char *data;
3405 +       ssize_t error;
3406 +
3407 +       data = aa_simple_write_to_buffer(buf, size, size, pos,
3408 +                                        "profile_replace");
3409 +
3410 +       error = PTR_ERR(data);
3411 +       if (!IS_ERR(data)) {
3412 +               error = aa_replace_profile(data, size);
3413 +               vfree(data);
3414 +       }
3415 +
3416 +       return error;
3417 +}
3418 +
3419 +
3420 +static struct file_operations apparmorfs_profile_replace = {
3421 +       .write = aa_profile_replace
3422 +};
3423 +
3424 +/* apparmor/.remove */
3425 +static ssize_t aa_profile_remove(struct file *f, const char __user *buf,
3426 +                                 size_t size, loff_t *pos)
3427 +{
3428 +       char *data;
3429 +       ssize_t error;
3430 +
3431 +       /*
3432 +        * aa_remove_profile needs a null terminated string so 1 extra
3433 +        * byte is allocated and the copied data is null terminated.
3434 +        */
3435 +       data = aa_simple_write_to_buffer(buf, size + 1, size, pos,
3436 +                                        "profile_remove");
3437 +
3438 +       error = PTR_ERR(data);
3439 +       if (!IS_ERR(data)) {
3440 +               data[size] = 0;
3441 +               error = aa_remove_profile(data, size);
3442 +               vfree(data);
3443 +       }
3444 +
3445 +       return error;
3446 +}
3447 +
3448 +static struct file_operations apparmorfs_profile_remove = {
3449 +       .write = aa_profile_remove
3450 +};
3451 +
3452 +static struct dentry *apparmor_dentry;
3453 +
3454 +static void aafs_remove(const char *name)
3455 +{
3456 +       struct dentry *dentry;
3457 +
3458 +       dentry = lookup_one_len(name, apparmor_dentry, strlen(name));
3459 +       if (!IS_ERR(dentry)) {
3460 +               securityfs_remove(dentry);
3461 +               dput(dentry);
3462 +       }
3463 +}
3464 +
3465 +static int aafs_create(const char *name, int mask, struct file_operations *fops)
3466 +{
3467 +       struct dentry *dentry;
3468 +
3469 +       dentry = securityfs_create_file(name, S_IFREG | mask, apparmor_dentry,
3470 +                                       NULL, fops);
3471 +
3472 +       return IS_ERR(dentry) ? PTR_ERR(dentry) : 0;
3473 +}
3474 +
3475 +void destroy_apparmorfs(void)
3476 +{
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;
3486 +       }
3487 +}
3488 +
3489 +int create_apparmorfs(void)
3490 +{
3491 +       int error;
3492 +
3493 +       if (!apparmor_initialized)
3494 +               return 0;
3495 +
3496 +       if (apparmor_dentry) {
3497 +               AA_ERROR("%s: AppArmor securityfs already exists\n",
3498 +                       __FUNCTION__);
3499 +               return -EEXIST;
3500 +       }
3501 +
3502 +       apparmor_dentry = securityfs_create_dir("apparmor", NULL);
3503 +       if (IS_ERR(apparmor_dentry)) {
3504 +               error = PTR_ERR(apparmor_dentry);
3505 +               apparmor_dentry = NULL;
3506 +               goto error;
3507 +       }
3508 +       error = aafs_create("profiles", 0440, &apparmorfs_profiles_fops);
3509 +       if (error)
3510 +               goto error;
3511 +       error = aafs_create("matching", 0444, &apparmorfs_matching_fops);
3512 +       if (error)
3513 +               goto error;
3514 +       error = aafs_create("features", 0444, &apparmorfs_features_fops);
3515 +       if (error)
3516 +               goto error;
3517 +       error = aafs_create(".load", 0640, &apparmorfs_profile_load);
3518 +       if (error)
3519 +               goto error;
3520 +       error = aafs_create(".replace", 0640, &apparmorfs_profile_replace);
3521 +       if (error)
3522 +               goto error;
3523 +       error = aafs_create(".remove", 0640, &apparmorfs_profile_remove);
3524 +       if (error)
3525 +               goto error;
3526 +
3527 +       /* Report that AppArmor fs is enabled */
3528 +       info_message("AppArmor Filesystem Enabled", "");
3529 +       return 0;
3530 +
3531 +error:
3532 +       destroy_apparmorfs();
3533 +       AA_ERROR("Error creating AppArmor securityfs\n");
3534 +       apparmor_disable();
3535 +       return error;
3536 +}
3537 +
3538 +fs_initcall(create_apparmorfs);
3539 +
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
3543 @@ -0,0 +1,250 @@
3544 +/*
3545 + *     Copyright (C) 1998-2007 Novell/SUSE
3546 + *
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
3550 + *     License.
3551 + */
3552 +
3553 +#ifndef __INLINE_H
3554 +#define __INLINE_H
3555 +
3556 +#include <linux/sched.h>
3557 +
3558 +#include "match.h"
3559 +
3560 +static inline int mediated_filesystem(struct inode *inode)
3561 +{
3562 +       return !(inode->i_sb->s_flags & MS_NOUSER);
3563 +}
3564 +
3565 +static inline struct aa_task_context *aa_task_context(struct task_struct *task)
3566 +{
3567 +       return (struct aa_task_context *) rcu_dereference(task->security);
3568 +}
3569 +
3570 +static inline struct aa_namespace *aa_get_namespace(struct aa_namespace *ns)
3571 +{
3572 +       if (ns)
3573 +               kref_get(&(ns->count));
3574 +
3575 +       return ns;
3576 +}
3577 +
3578 +static inline void aa_put_namespace(struct aa_namespace *ns)
3579 +{
3580 +       if (ns)
3581 +               kref_put(&ns->count, free_aa_namespace_kref);
3582 +}
3583 +
3584 +
3585 +static inline struct aa_namespace *aa_find_namespace(const char *name)
3586 +{
3587 +       struct aa_namespace *ns = NULL;
3588 +
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);
3592 +
3593 +       return ns;
3594 +}
3595 +
3596 +/**
3597 + * aa_dup_profile - increment refcount on profile @p
3598 + * @p: profile
3599 + */
3600 +static inline struct aa_profile *aa_dup_profile(struct aa_profile *p)
3601 +{
3602 +       if (p)
3603 +               kref_get(&(p->count));
3604 +
3605 +       return p;
3606 +}
3607 +
3608 +/**
3609 + * aa_put_profile - decrement refcount on profile @p
3610 + * @p: profile
3611 + */
3612 +static inline void aa_put_profile(struct aa_profile *p)
3613 +{
3614 +       if (p)
3615 +               kref_put(&p->count, free_aa_profile_kref);
3616 +}
3617 +
3618 +static inline struct aa_profile *aa_get_profile(struct task_struct *task)
3619 +{
3620 +       struct aa_task_context *cxt;
3621 +       struct aa_profile *profile = NULL;
3622 +
3623 +       rcu_read_lock();
3624 +       cxt = aa_task_context(task);
3625 +       if (cxt) {
3626 +               profile = cxt->profile;
3627 +               aa_dup_profile(profile);
3628 +       }
3629 +       rcu_read_unlock();
3630 +
3631 +       return profile;
3632 +}
3633 +
3634 +static inline struct aa_profile *aa_find_profile(struct aa_namespace *ns,
3635 +                                                const char *name)
3636 +{
3637 +       struct aa_profile *profile = NULL;
3638 +
3639 +       read_lock(&ns->lock);
3640 +       profile = aa_dup_profile(__aa_find_profile(name, &ns->profiles));
3641 +       read_unlock(&ns->lock);
3642 +
3643 +       return profile;
3644 +}
3645 +
3646 +static inline struct aa_task_context *aa_alloc_task_context(gfp_t flags)
3647 +{
3648 +       struct aa_task_context *cxt;
3649 +
3650 +       cxt = kzalloc(sizeof(*cxt), flags);
3651 +       if (cxt) {
3652 +               INIT_LIST_HEAD(&cxt->list);
3653 +               INIT_RCU_HEAD(&cxt->rcu);
3654 +       }
3655 +
3656 +       return cxt;
3657 +}
3658 +
3659 +static inline void aa_free_task_context(struct aa_task_context *cxt)
3660 +{
3661 +       if (cxt) {
3662 +               aa_put_profile(cxt->profile);
3663 +               aa_put_profile(cxt->previous_profile);
3664 +               kfree(cxt);
3665 +       }
3666 +}
3667 +
3668 +/**
3669 + * lock_profile - lock a profile
3670 + * @profile: the profile to lock
3671 + *
3672 + * While the profile is locked, local interrupts are disabled. This also
3673 + * gives us RCU reader safety.
3674 + */
3675 +static inline void lock_profile_nested(struct aa_profile *profile,
3676 +                                      enum aa_lock_class lock_class)
3677 +{
3678 +       /*
3679 +        * Lock the profile.
3680 +        *
3681 +        * Need to disable interrupts here because this lock is used in
3682 +        * the task_free_security hook, which may run in RCU context.
3683 +        */
3684 +       if (profile)
3685 +               spin_lock_irqsave_nested(&profile->lock, profile->int_flags,
3686 +                                        lock_class);
3687 +}
3688 +
3689 +static inline void lock_profile(struct aa_profile *profile)
3690 +{
3691 +       lock_profile_nested(profile, aa_lock_normal);
3692 +}
3693 +
3694 +/**
3695 + * unlock_profile - unlock a profile
3696 + * @profile: the profile to unlock
3697 + */
3698 +static inline void unlock_profile(struct aa_profile *profile)
3699 +{
3700 +       /* Unlock the profile. */
3701 +       if (profile)
3702 +               spin_unlock_irqrestore(&profile->lock, profile->int_flags);
3703 +}
3704 +
3705 +/**
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)
3709 + *
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.
3714 + */
3715 +static inline void lock_both_profiles(struct aa_profile *profile1,
3716 +                                     struct aa_profile *profile2)
3717 +{
3718 +       /*
3719 +        * Lock the two profiles.
3720 +        *
3721 +        * We need to disable interrupts because the profile locks are
3722 +        * used in the task_free_security hook, which may run in RCU
3723 +        * context.
3724 +        *
3725 +        * Do not nest spin_lock_irqsave()/spin_unlock_irqresore():
3726 +        * interrupts only need to be turned off once.
3727 +        */
3728 +       if (!profile1 || profile1 == profile2) {
3729 +               if (profile2)
3730 +                       spin_lock_irqsave_nested(&profile2->lock,
3731 +                                                profile2->int_flags,
3732 +                                                aa_lock_normal);
3733 +       } else if (profile1 > profile2) {
3734 +               /* profile1 cannot be NULL here. */
3735 +               spin_lock_irqsave_nested(&profile1->lock, profile1->int_flags,
3736 +                                        aa_lock_normal);
3737 +               if (profile2)
3738 +                       spin_lock_nested(&profile2->lock, aa_lock_nested);
3739 +
3740 +       } else {
3741 +               /* profile2 cannot be NULL here. */
3742 +               spin_lock_irqsave_nested(&profile2->lock, profile2->int_flags,
3743 +                                        aa_lock_normal);
3744 +               spin_lock_nested(&profile1->lock, aa_lock_nested);
3745 +       }
3746 +}
3747 +
3748 +/**
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)
3752 + *
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.
3757 + */
3758 +static inline void unlock_both_profiles(struct aa_profile *profile1,
3759 +                                       struct aa_profile *profile2)
3760 +{
3761 +       /* Unlock the two profiles. */
3762 +       if (!profile1 || profile1 == profile2) {
3763 +               if (profile2)
3764 +                       spin_unlock_irqrestore(&profile2->lock,
3765 +                                              profile2->int_flags);
3766 +       } else if (profile1 > profile2) {
3767 +               /* profile1 cannot be NULL here. */
3768 +               if (profile2)
3769 +                       spin_unlock(&profile2->lock);
3770 +               spin_unlock_irqrestore(&profile1->lock, profile1->int_flags);
3771 +       } else {
3772 +               /* profile2 cannot be NULL here. */
3773 +               spin_unlock(&profile1->lock);
3774 +               spin_unlock_irqrestore(&profile2->lock, profile2->int_flags);
3775 +       }
3776 +}
3777 +
3778 +static inline unsigned int aa_match(struct aa_dfa *dfa, const char *pathname,
3779 +                                   int *audit_mask)
3780 +{
3781 +       if (dfa)
3782 +               return aa_dfa_match(dfa, pathname, audit_mask);
3783 +       if (audit_mask)
3784 +               *audit_mask = 0;
3785 +       return 0;
3786 +}
3787 +
3788 +static inline int dfa_audit_mask(struct aa_dfa *dfa, unsigned int state)
3789 +{
3790 +       return  ACCEPT_TABLE2(dfa)[state];
3791 +}
3792 +
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
3797 @@ -0,0 +1,172 @@
3798 +/*
3799 + *     Copyright (C) 1998-2007 Novell/SUSE
3800 + *
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
3804 + *     License.
3805 + *
3806 + *     AppArmor Profile List Management
3807 + */
3808 +
3809 +#include <linux/seq_file.h>
3810 +#include "apparmor.h"
3811 +#include "inline.h"
3812 +
3813 +/* list of profile namespaces and lock */
3814 +LIST_HEAD(profile_ns_list);
3815 +rwlock_t profile_ns_list_lock = RW_LOCK_UNLOCKED;
3816 +
3817 +/**
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
3821 + *
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.
3824 + */
3825 +struct aa_namespace *__aa_find_namespace(const char *name,
3826 +                                      struct list_head *head)
3827 +{
3828 +       struct aa_namespace *ns;
3829 +
3830 +       list_for_each_entry(ns, head, list) {
3831 +               if (!strcmp(ns->name, name))
3832 +                       return ns;
3833 +       }
3834 +
3835 +       return NULL;
3836 +}
3837 +
3838 +/**
3839 + * __aa_find_profile  -  look up a profile on the profile list
3840 + * @name: name of profile to find
3841 + * @head: list to search
3842 + *
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.
3845 + */
3846 +struct aa_profile *__aa_find_profile(const char *name, struct list_head *head)
3847 +{
3848 +       struct aa_profile *profile;
3849 +
3850 +       list_for_each_entry(profile, head, list) {
3851 +               if (!strcmp(profile->name, name))
3852 +                       return profile;
3853 +       }
3854 +
3855 +       return NULL;
3856 +}
3857 +
3858 +static void aa_profile_list_release(struct list_head *head)
3859 +{
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);
3869 +       }
3870 +}
3871 +
3872 +/**
3873 + * aa_profilelist_release - Remove all profiles from profile_list
3874 + */
3875 +void aa_profile_ns_list_release(void)
3876 +{
3877 +       struct aa_namespace *ns, *tmp;
3878 +
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);
3887 +       }
3888 +       write_unlock(&profile_ns_list_lock);
3889 +}
3890 +
3891 +static struct aa_profile *next_profile(struct aa_profile *profile)
3892 +{
3893 +       struct aa_profile *next = profile;
3894 +       struct aa_namespace *ns;
3895 +
3896 +       list_for_each_entry_continue(next, &profile->ns->profiles, list)
3897 +               return next;
3898 +
3899 +       ns = profile->ns;
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)
3904 +                       return profile;
3905 +               read_unlock(&ns->lock);
3906 +       }
3907 +       return NULL;
3908 +}
3909 +
3910 +static void *p_start(struct seq_file *f, loff_t *pos)
3911 +{
3912 +       struct aa_namespace *ns;
3913 +       loff_t l = *pos;
3914 +
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);
3923 +               else
3924 +                       read_unlock(&ns->lock);
3925 +               for ( ; profile && l > 0; l--)
3926 +                       profile = next_profile(profile);
3927 +               return profile;
3928 +       }
3929 +       return NULL;
3930 +}
3931 +
3932 +static void *p_next(struct seq_file *f, void *p, loff_t *pos)
3933 +{
3934 +       struct aa_profile *profile = (struct aa_profile *) p;
3935 +
3936 +       (*pos)++;
3937 +       profile = next_profile(profile);
3938 +
3939 +       return profile;
3940 +}
3941 +
3942 +static void p_stop(struct seq_file *f, void *p)
3943 +{
3944 +       struct aa_profile *profile = (struct aa_profile *) p;
3945 +
3946 +       if (profile)
3947 +               read_unlock(&profile->ns->lock);
3948 +       read_unlock(&profile_ns_list_lock);
3949 +}
3950 +
3951 +static int seq_show_profile(struct seq_file *f, void *p)
3952 +{
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");
3957 +       else
3958 +           seq_printf(f, ":%s:%s (%s)\n", profile->ns->name, profile->name,
3959 +                      PROFILE_COMPLAIN(profile) ? "complain" : "enforce");
3960 +       return 0;
3961 +}
3962 +
3963 +/* Used in apparmorfs.c */
3964 +struct seq_operations apparmorfs_profiles_op = {
3965 +       .start =        p_start,
3966 +       .next =         p_next,
3967 +       .stop =         p_stop,
3968 +       .show =         seq_show_profile,
3969 +};
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
3973 @@ -0,0 +1,68 @@
3974 +Locking in AppArmor
3975 +===================
3976 +
3977 +Lock hierarchy:
3978 +
3979 +       aa_interface_lock
3980 +         profile_list_lock
3981 +           aa_profile->lock
3982 +             task_lock()
3983 +
3984 +
3985 +Which lock protects what?
3986 +
3987 +       /-----------------------+-------------------------------\
3988 +       | Variable              | Lock                          |
3989 +       >-----------------------+-------------------------------<
3990 +       | profile_list          | profile_list_lock             |
3991 +       +-----------------------+-------------------------------+
3992 +       | aa_profile            | (reference count)             |
3993 +       +-----------------------+-------------------------------+
3994 +       | aa_profile->          | aa_profile->lock              |
3995 +       |   isstale,            |                               |
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 +       \-----------------------+-------------------------------/
4004 +
4005 +(Obviously, the list_heads embedded in data structures are always
4006 +protected with the lock that also protects the list.)
4007 +
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.
4011 +
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
4016 +is used.
4017 +
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).
4021 +
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.
4026 +
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.
4030 +
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
4045 @@ -0,0 +1,1108 @@
4046 +/*
4047 + *     Copyright (C) 1998-2007 Novell/SUSE
4048 + *
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
4052 + *     License.
4053 + *
4054 + *     AppArmor LSM interface
4055 + */
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>
4066 +
4067 +#include "apparmor.h"
4068 +#include "inline.h"
4069 +
4070 +/* Flag indicating whether initialization completed */
4071 +int apparmor_initialized = 0;
4072 +
4073 +/* point to the apparmor module */
4074 +struct module *aa_module = NULL;
4075 +
4076 +/* secondary ops if apparmor is stacked */
4077 +static struct security_operations *aa_secondary_ops = NULL;
4078 +static DEFINE_MUTEX(aa_secondary_lock);
4079 +
4080 +#define AA_SECONDARY(FN, ARGS...) \
4081 +       ({ \
4082 +               struct security_operations *__f1; \
4083 +               __f1 = rcu_dereference(aa_secondary_ops); \
4084 +               (unlikely(__f1) && __f1->FN) ? __f1->FN(ARGS) : 0; \
4085 +       })
4086 +
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)
4090 +
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)
4094 +
4095 +/* Flag values, also controllable via /sys/module/apparmor/parameters
4096 + * We define special types as we want to do additional mediation.
4097 + *
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
4102 + * enforce.
4103 + */
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");
4107 +
4108 +/* Debug 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");
4112 +
4113 +/* Audit 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");
4117 +
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");
4122 +
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");
4127 +
4128 +/* Boot time disable flag */
4129 +#ifdef CONFIG_SECURITY_APPARMOR_DISABLE
4130 +#define AA_ENABLED_PERMS 0600
4131 +#else
4132 +#define AA_ENABLED_PERMS 0400
4133 +#endif
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");
4139 +
4140 +static int __init apparmor_enabled_setup(char *str)
4141 +{
4142 +       apparmor_enabled = simple_strtol(str, NULL, 0);
4143 +       return 1;
4144 +}
4145 +__setup("apparmor=", apparmor_enabled_setup);
4146 +
4147 +static int param_set_aabool(const char *val, struct kernel_param *kp)
4148 +{
4149 +       if (aa_task_context(current))
4150 +               return -EPERM;
4151 +       return param_set_bool(val, kp);
4152 +}
4153 +
4154 +static int param_get_aabool(char *buffer, struct kernel_param *kp)
4155 +{
4156 +       if (aa_task_context(current))
4157 +               return -EPERM;
4158 +       return param_get_bool(buffer, kp);
4159 +}
4160 +
4161 +static int param_set_aauint(const char *val, struct kernel_param *kp)
4162 +{
4163 +       if (aa_task_context(current))
4164 +               return -EPERM;
4165 +       return param_set_uint(val, kp);
4166 +}
4167 +
4168 +static int param_get_aauint(char *buffer, struct kernel_param *kp)
4169 +{
4170 +       if (aa_task_context(current))
4171 +               return -EPERM;
4172 +       return param_get_uint(buffer, kp);
4173 +}
4174 +
4175 +/* allow run time disabling of apparmor */
4176 +static int param_set_aa_enabled(const char *val, struct kernel_param *kp)
4177 +{
4178 +       char *endp;
4179 +       unsigned long l;
4180 +
4181 +       if (!apparmor_initialized) {
4182 +               apparmor_enabled = 0;
4183 +               return 0;
4184 +       }
4185 +
4186 +       if (aa_task_context(current))
4187 +               return -EPERM;
4188 +
4189 +       if (!apparmor_enabled)
4190 +               return -EINVAL;
4191 +
4192 +       if (!val)
4193 +               return -EINVAL;
4194 +
4195 +       l = simple_strtoul(val, &endp, 0);
4196 +       if (endp == val || l != 0)
4197 +               return -EINVAL;
4198 +
4199 +       apparmor_enabled = 0;
4200 +       apparmor_disable();
4201 +       return 0;
4202 +}
4203 +
4204 +static int aa_reject_syscall(struct task_struct *task, gfp_t flags,
4205 +                            const char *name)
4206 +{
4207 +       struct aa_profile *profile = aa_get_profile(task);
4208 +       int error = 0;
4209 +
4210 +       if (profile) {
4211 +               error = aa_audit_syscallreject(profile, flags, name);
4212 +               aa_put_profile(profile);
4213 +       }
4214 +
4215 +       return error;
4216 +}
4217 +
4218 +static int apparmor_ptrace(struct task_struct *parent,
4219 +                          struct task_struct *child)
4220 +{
4221 +       struct aa_task_context *cxt;
4222 +       int error = 0;
4223 +
4224 +       /*
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
4231 +        */
4232 +
4233 +       rcu_read_lock();
4234 +       cxt = aa_task_context(parent);
4235 +       if (cxt) {
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);
4245 +                       error = -EPERM;
4246 +               } else {
4247 +                       struct aa_task_context *child_cxt =
4248 +                               aa_task_context(child);
4249 +
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);
4260 +                       }
4261 +               }
4262 +       }
4263 +       rcu_read_unlock();
4264 +
4265 +       return error;
4266 +}
4267 +
4268 +static int apparmor_capable(struct task_struct *task, int cap)
4269 +{
4270 +       int error;
4271 +       struct aa_task_context *cxt;
4272 +
4273 +       /* cap_capable returns 0 on success, else -EPERM */
4274 +       error = cap_capable(task, cap);
4275 +
4276 +       rcu_read_lock();
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();
4281 +
4282 +       return error;
4283 +}
4284 +
4285 +static int apparmor_sysctl(struct ctl_table *table, int op)
4286 +{
4287 +       struct aa_profile *profile = aa_get_profile(current);
4288 +       int error = 0;
4289 +
4290 +       if (profile) {
4291 +               char *buffer, *name;
4292 +               int mask;
4293 +
4294 +               mask = 0;
4295 +               if (op & 4)
4296 +                       mask |= MAY_READ;
4297 +               if (op & 2)
4298 +                       mask |= MAY_WRITE;
4299 +
4300 +               error = -ENOMEM;
4301 +               buffer = (char*)__get_free_page(GFP_KERNEL);
4302 +               if (!buffer)
4303 +                       goto out;
4304 +               name = sysctl_pathname(table, buffer, PAGE_SIZE);
4305 +               if (name && name - buffer >= 5) {
4306 +                       name -= 5;
4307 +                       memcpy(name, "/proc", 5);
4308 +                       error = aa_perm_path(profile, "sysctl", name, mask, 0);
4309 +               }
4310 +               free_page((unsigned long)buffer);
4311 +       }
4312 +
4313 +out:
4314 +       aa_put_profile(profile);
4315 +       return error;
4316 +}
4317 +
4318 +static int apparmor_bprm_set_security(struct linux_binprm *bprm)
4319 +{
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)
4324 +               return 0;
4325 +       return aa_register(bprm);
4326 +}
4327 +
4328 +static int apparmor_bprm_secureexec(struct linux_binprm *bprm)
4329 +{
4330 +       int ret = cap_bprm_secureexec(bprm);
4331 +
4332 +       if (!ret && (unsigned long)bprm->security & AA_SECURE_EXEC_NEEDED) {
4333 +               AA_DEBUG("%s: secureexec required for %s\n",
4334 +                        __FUNCTION__, bprm->filename);
4335 +               ret = 1;
4336 +       }
4337 +
4338 +       return ret;
4339 +}
4340 +
4341 +static int apparmor_sb_mount(char *dev_name, struct nameidata *nd, char *type,
4342 +                             unsigned long flags, void *data)
4343 +{
4344 +       return aa_reject_syscall(current, GFP_KERNEL, "mount");
4345 +}
4346 +
4347 +static int apparmor_umount(struct vfsmount *mnt, int flags)
4348 +{
4349 +       return aa_reject_syscall(current, GFP_KERNEL, "umount");
4350 +}
4351 +
4352 +static int apparmor_inode_mkdir(struct inode *dir, struct dentry *dentry,
4353 +                               struct vfsmount *mnt, int mask)
4354 +{
4355 +       struct aa_profile *profile;
4356 +       int error = 0;
4357 +
4358 +       if (!mnt || !mediated_filesystem(dir))
4359 +               goto out;
4360 +
4361 +       profile = aa_get_profile(current);
4362 +
4363 +       if (profile)
4364 +               error = aa_perm_dir(profile, "inode_mkdir", dentry, mnt,
4365 +                                   MAY_WRITE);
4366 +
4367 +       aa_put_profile(profile);
4368 +
4369 +out:
4370 +       return error;
4371 +}
4372 +
4373 +static int apparmor_inode_rmdir(struct inode *dir, struct dentry *dentry,
4374 +                               struct vfsmount *mnt)
4375 +{
4376 +       struct aa_profile *profile;
4377 +       int error = 0;
4378 +
4379 +       if (!mnt || !mediated_filesystem(dir))
4380 +               goto out;
4381 +
4382 +       profile = aa_get_profile(current);
4383 +
4384 +       if (profile)
4385 +               error = aa_perm_dir(profile, "inode_rmdir", dentry, mnt,
4386 +                                   MAY_WRITE);
4387 +
4388 +       aa_put_profile(profile);
4389 +
4390 +out:
4391 +       return error;
4392 +}
4393 +
4394 +static int aa_permission(const char *operation, struct inode *inode,
4395 +                        struct dentry *dentry, struct vfsmount *mnt,
4396 +                        int mask, int check)
4397 +{
4398 +       int error = 0;
4399 +
4400 +       if (mnt && mediated_filesystem(inode)) {
4401 +               struct aa_profile *profile;
4402 +
4403 +               profile = aa_get_profile(current);
4404 +               if (profile)
4405 +                       error = aa_perm(profile, operation, dentry, mnt, mask,
4406 +                                       check);
4407 +               aa_put_profile(profile);
4408 +       }
4409 +       return error;
4410 +}
4411 +
4412 +static inline int aa_mask_permissions(int mask)
4413 +{
4414 +       if (mask & MAY_APPEND)
4415 +               mask &= (MAY_READ | MAY_APPEND | MAY_EXEC);
4416 +       else
4417 +               mask &= (MAY_READ | MAY_WRITE | MAY_EXEC);
4418 +       return mask;
4419 +}
4420 +
4421 +static int apparmor_inode_create(struct inode *dir, struct dentry *dentry,
4422 +                                struct vfsmount *mnt, int mask)
4423 +{
4424 +       return aa_permission("inode_create", dir, dentry, mnt, MAY_APPEND, 0);
4425 +}
4426 +
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)
4431 +{
4432 +       int error = 0;
4433 +       struct aa_profile *profile;
4434 +
4435 +       if (!old_mnt || !new_mnt || !mediated_filesystem(dir))
4436 +               goto out;
4437 +
4438 +       profile = aa_get_profile(current);
4439 +
4440 +       if (profile)
4441 +               error = aa_link(profile, new_dentry, new_mnt,
4442 +                               old_dentry, old_mnt);
4443 +
4444 +       aa_put_profile(profile);
4445 +
4446 +out:
4447 +       return error;
4448 +}
4449 +
4450 +static int apparmor_inode_unlink(struct inode *dir, struct dentry *dentry,
4451 +                                struct vfsmount *mnt)
4452 +{
4453 +       int check = 0;
4454 +
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,
4458 +                            check);
4459 +}
4460 +
4461 +static int apparmor_inode_symlink(struct inode *dir, struct dentry *dentry,
4462 +                                 struct vfsmount *mnt, const char *old_name)
4463 +{
4464 +       return aa_permission("inode_symlink", dir, dentry, mnt, MAY_WRITE, 0);
4465 +}
4466 +
4467 +static int apparmor_inode_mknod(struct inode *dir, struct dentry *dentry,
4468 +                               struct vfsmount *mnt, int mode, dev_t dev)
4469 +{
4470 +       return aa_permission("inode_mknod", dir, dentry, mnt, MAY_WRITE, 0);
4471 +}
4472 +
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)
4479 +{
4480 +       struct aa_profile *profile;
4481 +       int error = 0;
4482 +
4483 +       if ((!old_mnt && !new_mnt) || !mediated_filesystem(old_dir))
4484 +               goto out;
4485 +
4486 +       profile = aa_get_profile(current);
4487 +
4488 +       if (profile) {
4489 +               struct inode *inode = old_dentry->d_inode;
4490 +               int check = 0;
4491 +
4492 +               if (inode && S_ISDIR(inode->i_mode))
4493 +                       check |= AA_CHECK_DIR;
4494 +               if (old_mnt)
4495 +                       error = aa_perm(profile, "inode_rename", old_dentry,
4496 +                                       old_mnt, MAY_READ | MAY_WRITE, check);
4497 +
4498 +               if (!error && new_mnt) {
4499 +                       error = aa_perm(profile, "inode_rename", new_dentry,
4500 +                                       new_mnt, MAY_WRITE, check);
4501 +               }
4502 +       }
4503 +
4504 +       aa_put_profile(profile);
4505 +
4506 +out:
4507 +       return error;
4508 +}
4509 +
4510 +static int apparmor_inode_permission(struct inode *inode, int mask,
4511 +                                    struct nameidata *nd)
4512 +{
4513 +       int check = 0, error = 0;
4514 +
4515 +       if (!nd || nd->flags & (LOOKUP_PARENT | LOOKUP_CONTINUE))
4516 +               goto out;
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;
4522 +       }
4523 +       error = aa_permission("inode_permission", inode, nd->path.dentry,
4524 +                             nd->path.mnt,
4525 +                             mask, check);
4526 +
4527 +out:
4528 +       if (!error)
4529 +               error = AA_SECONDARY(inode_permission, inode, mask, nd);
4530 +
4531 +       return error;
4532 +}
4533 +
4534 +static int apparmor_inode_setattr(struct dentry *dentry, struct vfsmount *mnt,
4535 +                                 struct iattr *iattr)
4536 +{
4537 +       int error = 0;
4538 +
4539 +       if (!mnt)
4540 +               goto out;
4541 +
4542 +       if (mediated_filesystem(dentry->d_inode)) {
4543 +               struct aa_profile *profile;
4544 +
4545 +               profile = aa_get_profile(current);
4546 +               /*
4547 +                * Mediate any attempt to change attributes of a file
4548 +                * (chmod, chown, chgrp, etc)
4549 +                */
4550 +               if (profile)
4551 +                       error = aa_attr(profile, dentry, mnt, iattr);
4552 +
4553 +               aa_put_profile(profile);
4554 +       }
4555 +
4556 +out:
4557 +       return error;
4558 +}
4559 +
4560 +static int aa_xattr_permission(struct dentry *dentry, struct vfsmount *mnt,
4561 +                              const char *operation, int mask,
4562 +                              struct file *file)
4563 +{
4564 +       int error = 0;
4565 +
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;
4569 +
4570 +               if (profile)
4571 +                       error = aa_perm_xattr(profile, operation, dentry, mnt,
4572 +                                             mask, check);
4573 +               aa_put_profile(profile);
4574 +       }
4575 +
4576 +       return error;
4577 +}
4578 +
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)
4582 +{
4583 +       return aa_xattr_permission(dentry, mnt, "xattr set", MAY_WRITE, file);
4584 +}
4585 +
4586 +static int apparmor_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
4587 +                                  char *name, struct file *file)
4588 +{
4589 +       return aa_xattr_permission(dentry, mnt, "xattr get", MAY_READ, file);
4590 +}
4591 +
4592 +static int apparmor_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt,
4593 +                                   struct file *file)
4594 +{
4595 +       return aa_xattr_permission(dentry, mnt, "xattr list", MAY_READ, file);
4596 +}
4597 +
4598 +static int apparmor_inode_removexattr(struct dentry *dentry,
4599 +                                     struct vfsmount *mnt, char *name,
4600 +                                     struct file *file)
4601 +{
4602 +       return aa_xattr_permission(dentry, mnt, "xattr remove", MAY_WRITE,
4603 +                                  file);
4604 +}
4605 +
4606 +static int aa_file_permission(const char *op, struct file *file, int mask)
4607 +{
4608 +       struct aa_profile *profile;
4609 +       struct aa_profile *file_profile = (struct aa_profile*)file->f_security;
4610 +       int error = 0;
4611 +
4612 +       if (!file_profile)
4613 +               goto out;
4614 +
4615 +       /*
4616 +        * If this file was opened under a different profile, we
4617 +        * revalidate the access against the current profile.
4618 +        */
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;
4625 +
4626 +               /*
4627 +                * FIXME: We should remember which profiles we revalidated
4628 +                *        against.
4629 +                */
4630 +               if (S_ISDIR(inode->i_mode))
4631 +                       check |= AA_CHECK_DIR;
4632 +               error = aa_permission(op, inode, dentry, mnt, mask, check);
4633 +       }
4634 +       aa_put_profile(profile);
4635 +
4636 +out:
4637 +       return error;
4638 +}
4639 +
4640 +static int apparmor_file_permission(struct file *file, int mask)
4641 +{
4642 +       return aa_file_permission("file_permission", file,
4643 +                                 aa_mask_permissions(mask));
4644 +}
4645 +
4646 +static inline int apparmor_file_lock (struct file *file, unsigned int cmd)
4647 +{
4648 +       int mask = AA_MAY_LOCK;
4649 +       if (cmd == F_WRLCK)
4650 +               mask |= MAY_WRITE;
4651 +       return aa_file_permission("file_lock", file, mask);
4652 +}
4653 +
4654 +static int apparmor_file_alloc_security(struct file *file)
4655 +{
4656 +       struct aa_profile *profile;
4657 +
4658 +       profile = aa_get_profile(current);
4659 +       if (profile)
4660 +               file->f_security = profile;
4661 +
4662 +       return 0;
4663 +}
4664 +
4665 +static void apparmor_file_free_security(struct file *file)
4666 +{
4667 +       struct aa_profile *file_profile = (struct aa_profile*)file->f_security;
4668 +
4669 +       aa_put_profile(file_profile);
4670 +}
4671 +
4672 +static inline int aa_mmap(struct file *file, const char *operation,
4673 +                         unsigned long prot, unsigned long flags)
4674 +{
4675 +       struct dentry *dentry;
4676 +       int mask = 0;
4677 +
4678 +       if (!file || !file->f_security)
4679 +               return 0;
4680 +
4681 +       if (prot & PROT_READ)
4682 +               mask |= MAY_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;
4689 +
4690 +       dentry = file->f_dentry;
4691 +       return aa_permission(operation, dentry->d_inode, dentry,
4692 +                            file->f_vfsmnt, mask, AA_CHECK_FD);
4693 +}
4694 +
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)
4698 +{
4699 +       if ((addr < mmap_min_addr) && !capable(CAP_SYS_RAWIO)) {
4700 +               struct aa_profile *profile = aa_get_profile(current);
4701 +               if (profile)
4702 +                       /* future control check here */
4703 +                       return -EACCES;
4704 +               else
4705 +                       return -EACCES;
4706 +               aa_put_profile(profile);
4707 +       }
4708 +
4709 +       return aa_mmap(file, "file_mmap", prot, flags);
4710 +}
4711 +
4712 +static int apparmor_file_mprotect(struct vm_area_struct *vma,
4713 +                                 unsigned long reqprot, unsigned long prot)
4714 +{
4715 +       return aa_mmap(vma->vm_file, "file_mprotect", prot,
4716 +                      !(vma->vm_flags & VM_SHARED) ? MAP_PRIVATE : 0);
4717 +}
4718 +
4719 +static int apparmor_task_alloc_security(struct task_struct *task)
4720 +{
4721 +       return aa_clone(task);
4722 +}
4723 +
4724 +/*
4725 + * Called from IRQ context from RCU callback.
4726 + */
4727 +static void apparmor_task_free_security(struct task_struct *task)
4728 +{
4729 +       aa_release(task);
4730 +}
4731 +
4732 +static int apparmor_socket_create(int family, int type, int protocol, int kern)
4733 +{
4734 +       struct aa_profile *profile;
4735 +       int error = 0;
4736 +
4737 +       if (kern)
4738 +               return 0;
4739 +
4740 +       profile = aa_get_profile(current);
4741 +       if (profile)
4742 +               error = aa_net_perm(profile, "socket_create", family,
4743 +                                                       type, protocol);
4744 +       aa_put_profile(profile);
4745 +
4746 +       return error;
4747 +}
4748 +
4749 +static int apparmor_socket_post_create(struct socket *sock, int family,
4750 +                                       int type, int protocol, int kern)
4751 +{
4752 +       struct sock *sk = sock->sk;
4753 +
4754 +       if (kern)
4755 +               return 0;
4756 +
4757 +       return aa_revalidate_sk(sk, "socket_post_create");
4758 +}
4759 +
4760 +static int apparmor_socket_bind(struct socket *sock,
4761 +                               struct sockaddr *address, int addrlen)
4762 +{
4763 +       struct sock *sk = sock->sk;
4764 +
4765 +       return aa_revalidate_sk(sk, "socket_bind");
4766 +}
4767 +
4768 +static int apparmor_socket_connect(struct socket *sock,
4769 +                                       struct sockaddr *address, int addrlen)
4770 +{
4771 +       struct sock *sk = sock->sk;
4772 +
4773 +       return aa_revalidate_sk(sk, "socket_connect");
4774 +}
4775 +
4776 +static int apparmor_socket_listen(struct socket *sock, int backlog)
4777 +{
4778 +       struct sock *sk = sock->sk;
4779 +
4780 +       return aa_revalidate_sk(sk, "socket_listen");
4781 +}
4782 +
4783 +static int apparmor_socket_accept(struct socket *sock, struct socket *newsock)
4784 +{
4785 +       struct sock *sk = sock->sk;
4786 +
4787 +       return aa_revalidate_sk(sk, "socket_accept");
4788 +}
4789 +
4790 +static int apparmor_socket_sendmsg(struct socket *sock,
4791 +                                       struct msghdr *msg, int size)
4792 +{
4793 +       struct sock *sk = sock->sk;
4794 +
4795 +       return aa_revalidate_sk(sk, "socket_sendmsg");
4796 +}
4797 +
4798 +static int apparmor_socket_recvmsg(struct socket *sock,
4799 +                                  struct msghdr *msg, int size, int flags)
4800 +{
4801 +       struct sock *sk = sock->sk;
4802 +
4803 +       return aa_revalidate_sk(sk, "socket_recvmsg");
4804 +}
4805 +
4806 +static int apparmor_socket_getsockname(struct socket *sock)
4807 +{
4808 +       struct sock *sk = sock->sk;
4809 +
4810 +       return aa_revalidate_sk(sk, "socket_getsockname");
4811 +}
4812 +
4813 +static int apparmor_socket_getpeername(struct socket *sock)
4814 +{
4815 +       struct sock *sk = sock->sk;
4816 +
4817 +       return aa_revalidate_sk(sk, "socket_getpeername");
4818 +}
4819 +
4820 +static int apparmor_socket_getsockopt(struct socket *sock, int level,
4821 +                                       int optname)
4822 +{
4823 +       struct sock *sk = sock->sk;
4824 +
4825 +       return aa_revalidate_sk(sk, "socket_getsockopt");
4826 +}
4827 +
4828 +static int apparmor_socket_setsockopt(struct socket *sock, int level,
4829 +                                       int optname)
4830 +{
4831 +       struct sock *sk = sock->sk;
4832 +
4833 +       return aa_revalidate_sk(sk, "socket_setsockopt");
4834 +}
4835 +
4836 +static int apparmor_socket_shutdown(struct socket *sock, int how)
4837 +{
4838 +       struct sock *sk = sock->sk;
4839 +
4840 +       return aa_revalidate_sk(sk, "socket_shutdown");
4841 +}
4842 +
4843 +static int apparmor_getprocattr(struct task_struct *task, char *name,
4844 +                               char **value)
4845 +{
4846 +       unsigned len;
4847 +       int error;
4848 +       struct aa_profile *profile;
4849 +
4850 +       /* AppArmor only supports the "current" process attribute */
4851 +       if (strcmp(name, "current") != 0)
4852 +               return -EINVAL;
4853 +
4854 +       /* must be task querying itself or admin */
4855 +       if (current != task && !capable(CAP_SYS_ADMIN))
4856 +               return -EPERM;
4857 +
4858 +       profile = aa_get_profile(task);
4859 +       error = aa_getprocattr(profile, value, &len);
4860 +       aa_put_profile(profile);
4861 +       if (!error)
4862 +               error = len;
4863 +
4864 +       return error;
4865 +}
4866 +
4867 +static int apparmor_setprocattr(struct task_struct *task, char *name,
4868 +                               void *value, size_t size)
4869 +{
4870 +       char *command, *args;
4871 +       int error;
4872 +
4873 +       if (strcmp(name, "current") != 0 || size == 0 || size >= PAGE_SIZE)
4874 +               return -EINVAL;
4875 +       args = value;
4876 +       args[size] = '\0';
4877 +       args = strstrip(args);
4878 +       command = strsep(&args, " ");
4879 +       if (!args)
4880 +               return -EINVAL;
4881 +       while (isspace(*args))
4882 +               args++;
4883 +       if (!*args)
4884 +               return -EINVAL;
4885 +
4886 +       if (strcmp(command, "changehat") == 0) {
4887 +               if (current != task)
4888 +                       return -EACCES;
4889 +               error = aa_setprocattr_changehat(args);
4890 +       } else if (strcmp(command, "changeprofile") == 0) {
4891 +               if (current != task)
4892 +                       return -EACCES;
4893 +               error = aa_setprocattr_changeprofile(args);
4894 +       } else if (strcmp(command, "setprofile") == 0) {
4895 +               struct aa_profile *profile;
4896 +
4897 +               /* Only an unconfined process with admin capabilities
4898 +                * may change the profile of another task.
4899 +                */
4900 +
4901 +               if (!capable(CAP_SYS_ADMIN))
4902 +                       return -EACCES;
4903 +
4904 +               profile = aa_get_profile(current);
4905 +               if (profile) {
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);
4914 +                       return -EACCES;
4915 +               }
4916 +               error = aa_setprocattr_setprofile(task, args);
4917 +       } else {
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);
4926 +               return -EINVAL;
4927 +       }
4928 +
4929 +       if (!error)
4930 +               error = size;
4931 +       return error;
4932 +}
4933 +
4934 +static int apparmor_task_setrlimit(unsigned int resource,
4935 +                                  struct rlimit *new_rlim)
4936 +{
4937 +       struct aa_profile *profile;
4938 +       int error = 0;
4939 +
4940 +       profile = aa_get_profile(current);
4941 +       if (profile) {
4942 +               error = aa_task_setrlimit(profile, resource, new_rlim);
4943 +       }
4944 +       aa_put_profile(profile);
4945 +
4946 +       return error;
4947 +}
4948 +
4949 +int apparmor_register_subsecurity(const char *name,
4950 +                                 struct security_operations *ops)
4951 +{
4952 +       int error = 0;
4953 +
4954 +       if (mutex_lock_interruptible(&aa_secondary_lock))
4955 +               return -ERESTARTSYS;
4956 +
4957 +       /* allow dazuko and capability to stack.  The stacking with
4958 +        * capability is not needed since apparmor already composes
4959 +        * capability using common cap.
4960 +        */
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
4964 +                * registered
4965 +                */
4966 +               if (try_module_get(aa_module)) {
4967 +                       aa_secondary_ops = ops;
4968 +                       info_message("Registered secondary security module",
4969 +                                    name);
4970 +               } else {
4971 +                       error = -EINVAL;
4972 +               }
4973 +       } else {
4974 +               info_message("Unable to register %s as a secondary security "
4975 +                            "module", name);
4976 +               error = -EPERM;
4977 +       }
4978 +       mutex_unlock(&aa_secondary_lock);
4979 +       return error;
4980 +}
4981 +
4982 +int apparmor_unregister_subsecurity(const char *name,
4983 +                                   struct security_operations *ops)
4984 +{
4985 +       int error = 0;
4986 +
4987 +       if (mutex_lock_interruptible(&aa_secondary_lock))
4988 +               return -ERESTARTSYS;
4989 +
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);
4995 +       } else {
4996 +               info_message("Unable to unregister secondary security module",
4997 +                            name);
4998 +               error = -EPERM;
4999 +       }
5000 +       mutex_unlock(&aa_secondary_lock);
5001 +       return error;
5002 +}
5003 +
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,
5013 +
5014 +       .bprm_apply_creds =             cap_bprm_apply_creds,
5015 +       .bprm_set_security =            apparmor_bprm_set_security,
5016 +       .bprm_secureexec =              apparmor_bprm_secureexec,
5017 +
5018 +       .sb_mount =                     apparmor_sb_mount,
5019 +       .sb_umount =                    apparmor_umount,
5020 +
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,
5041 +
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,
5047 +
5048 +       .getprocattr =                  apparmor_getprocattr,
5049 +       .setprocattr =                  apparmor_setprocattr,
5050 +
5051 +       .register_security =            apparmor_register_subsecurity,
5052 +
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,
5066 +};
5067 +
5068 +void info_message(const char *str, const char *name)
5069 +{
5070 +       struct aa_audit sa;
5071 +       memset(&sa, 0, sizeof(sa));
5072 +       sa.gfp_mask = GFP_KERNEL;
5073 +       sa.info = str;
5074 +       sa.name = name;
5075 +       printk(KERN_INFO "AppArmor: %s %s\n", str, name);
5076 +       if (audit_enabled)
5077 +               aa_audit_message(NULL, &sa, AUDIT_APPARMOR_STATUS);
5078 +}
5079 +
5080 +static int __init apparmor_init(void)
5081 +{
5082 +       int error;
5083 +
5084 +       if (!apparmor_enabled) {
5085 +               info_message("AppArmor disabled by boottime parameter", "");
5086 +               return 0;
5087 +       }
5088 +
5089 +       if ((error = create_apparmorfs())) {
5090 +               AA_ERROR("Unable to activate AppArmor filesystem\n");
5091 +               goto createfs_out;
5092 +       }
5093 +
5094 +       if ((error = alloc_default_namespace())){
5095 +               AA_ERROR("Unable to allocate default profile namespace\n");
5096 +               goto alloc_out;
5097 +       }
5098 +
5099 +       if ((error = register_security(&apparmor_ops))) {
5100 +               AA_ERROR("Unable to register AppArmor\n");
5101 +               goto register_security_out;
5102 +       }
5103 +
5104 +       /* Report that AppArmor successfully initialized */
5105 +       apparmor_initialized = 1;
5106 +       if (apparmor_complain)
5107 +               info_message("AppArmor initialized: complainmode enabled",
5108 +                            NULL);
5109 +       else
5110 +               info_message("AppArmor initialized", NULL);
5111 +
5112 +       return error;
5113 +
5114 +register_security_out:
5115 +       free_default_namespace();
5116 +
5117 +alloc_out:
5118 +       destroy_apparmorfs();
5119 +
5120 +createfs_out:
5121 +       return error;
5122 +
5123 +}
5124 +
5125 +security_initcall(apparmor_init);
5126 +
5127 +void apparmor_disable(void)
5128 +{
5129 +       /* Remove and release all the profiles on the profile list. */
5130 +       mutex_lock(&aa_interface_lock);
5131 +       aa_profile_ns_list_release();
5132 +
5133 +       /* FIXME: cleanup profiles references on files */
5134 +       free_default_namespace();
5135 +
5136 +       /*
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.
5140 +        */
5141 +       synchronize_rcu();
5142 +
5143 +       destroy_apparmorfs();
5144 +       mutex_unlock(&aa_interface_lock);
5145 +
5146 +       apparmor_initialized = 0;
5147 +
5148 +       info_message("AppArmor protection removed", NULL);
5149 +}
5150 +
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
5157 @@ -0,0 +1,1689 @@
5158 +/*
5159 + *     Copyright (C) 2002-2007 Novell/SUSE
5160 + *
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
5164 + *     License.
5165 + *
5166 + *     AppArmor Core
5167 + */
5168 +
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>
5177 +
5178 +#include "apparmor.h"
5179 +
5180 +#include "inline.h"
5181 +
5182 +/*
5183 + * Table of capability names: we generate it from capabilities.h.
5184 + */
5185 +static const char *capability_names[] = {
5186 +#include "capability_names.h"
5187 +};
5188 +
5189 +struct aa_namespace *default_namespace;
5190 +
5191 +static int aa_inode_mode(struct inode *inode)
5192 +{
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;
5197 +}
5198 +
5199 +int alloc_default_namespace(void)
5200 +{
5201 +       struct aa_namespace *ns;
5202 +       char *name = kstrdup("default", GFP_KERNEL);
5203 +       if (!name)
5204 +               return -ENOMEM;
5205 +       ns = alloc_aa_namespace(name);
5206 +       if (!ns) {
5207 +               kfree(name);
5208 +               return -ENOMEM;
5209 +       }
5210 +
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);
5216 +
5217 +       return 0;
5218 +}
5219 +
5220 +void free_default_namespace(void)
5221 +{
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;
5227 +}
5228 +
5229 +static void aa_audit_file_sub_mask(struct audit_buffer *ab, char *buffer,
5230 +                                  int mask)
5231 +{
5232 +       const char unsafex[] = "upcn";
5233 +       const char safex[] = "UPCN";
5234 +       char *m = buffer;
5235 +
5236 +       if (mask & AA_EXEC_MMAP)
5237 +               *m++ = 'm';
5238 +       if (mask & MAY_READ)
5239 +               *m++ = 'r';
5240 +       if (mask & MAY_WRITE)
5241 +               *m++ = 'w';
5242 +       else if (mask & MAY_APPEND)
5243 +               *m++ = 'a';
5244 +       if (mask & MAY_EXEC) {
5245 +               int index = AA_EXEC_INDEX(mask);
5246 +               /* all indexes > 4 are also named transitions */
5247 +               if (index > 4)
5248 +                       index = 4;
5249 +               if (index > 0) {
5250 +                       if (mask & AA_EXEC_UNSAFE)
5251 +                               *m++ = unsafex[index - 1];
5252 +                       else
5253 +                               *m++ = safex[index - 1];
5254 +               }
5255 +               if (mask & AA_EXEC_INHERIT)
5256 +                       *m++ = 'i';
5257 +               *m++ = 'x';
5258 +       }
5259 +       if (mask & AA_MAY_LINK)
5260 +               *m++ = 'l';
5261 +       if (mask & AA_MAY_LOCK)
5262 +               *m++ = 'k';
5263 +       *m++ = '\0';
5264 +}
5265 +
5266 +static void aa_audit_file_mask(struct audit_buffer *ab, const char *name,
5267 +                              int mask)
5268 +{
5269 +       char user[10], other[10];
5270 +
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);
5275 +
5276 +       audit_log_format(ab, " %s=\"%s::%s\"", name, user, other);
5277 +}
5278 +
5279 +static const char *address_families[] = {
5280 +#include "af_names.h"
5281 +};
5282 +
5283 +static const char *sock_types[] = {
5284 +       "unknown(0)",
5285 +       "stream",
5286 +       "dgram",
5287 +       "raw",
5288 +       "rdm",
5289 +       "seqpacket",
5290 +       "dccp",
5291 +       "unknown(7)",
5292 +       "unknown(8)",
5293 +       "unknown(9)",
5294 +       "packet",
5295 +};
5296 +
5297 +/**
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
5303 + */
5304 +static int aa_audit_base(struct aa_profile *profile, struct aa_audit *sa,
5305 +                        struct audit_context *audit_cxt, int type)
5306 +{
5307 +       struct audit_buffer *ab = NULL;
5308 +
5309 +       ab = audit_log_start(audit_cxt, sa->gfp_mask, type);
5310 +
5311 +       if (!ab) {
5312 +               AA_ERROR("Unable to log event (%d) to audit subsys\n",
5313 +                        type);
5314 +                /* don't fail operations in complain mode even if logging
5315 +                 * fails */
5316 +               return type == AUDIT_APPARMOR_ALLOWED ? 0 : -ENOMEM;
5317 +       }
5318 +
5319 +       if (sa->operation)
5320 +               audit_log_format(ab, "operation=\"%s\"", sa->operation);
5321 +
5322 +       if (sa->info) {
5323 +               audit_log_format(ab, " info=\"%s\"", sa->info);
5324 +               if (sa->error_code)
5325 +                       audit_log_format(ab, " error=%d", sa->error_code);
5326 +       }
5327 +
5328 +       if (sa->request_mask)
5329 +               aa_audit_file_mask(ab, "requested_mask", sa->request_mask);
5330 +
5331 +       if (sa->denied_mask)
5332 +               aa_audit_file_mask(ab, "denied_mask", sa->denied_mask);
5333 +
5334 +       if (sa->request_mask)
5335 +               audit_log_format(ab, " fsuid=%d", current->fsuid);
5336 +
5337 +       if (sa->rlimit)
5338 +               audit_log_format(ab, " rlimit=%d", sa->rlimit - 1);
5339 +
5340 +       if (sa->iattr) {
5341 +               struct iattr *iattr = sa->iattr;
5342 +
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) ?
5349 +                               "atime," : "",
5350 +                       iattr->ia_valid & (ATTR_MTIME | ATTR_MTIME_SET) ?
5351 +                               "mtime," : "",
5352 +                       iattr->ia_valid & ATTR_CTIME ? "ctime," : "");
5353 +       }
5354 +
5355 +       if (sa->task)
5356 +               audit_log_format(ab, " task=%d", sa->task);
5357 +
5358 +       if (sa->parent)
5359 +               audit_log_format(ab, " parent=%d", sa->parent);
5360 +
5361 +       if (sa->name) {
5362 +               audit_log_format(ab, " name=");
5363 +               audit_log_untrustedstring(ab, sa->name);
5364 +       }
5365 +
5366 +       if (sa->name2) {
5367 +               audit_log_format(ab, " name2=");
5368 +               audit_log_untrustedstring(ab, sa->name2);
5369 +       }
5370 +
5371 +       if (sa->family || sa->type) {
5372 +               if (address_families[sa->family])
5373 +                       audit_log_format(ab, " family=\"%s\"",
5374 +                                        address_families[sa->family]);
5375 +               else
5376 +                       audit_log_format(ab, " family=\"unknown(%d)\"",
5377 +                                        sa->family);
5378 +
5379 +               if (sock_types[sa->type])
5380 +                       audit_log_format(ab, " sock_type=\"%s\"",
5381 +                                        sock_types[sa->type]);
5382 +               else
5383 +                       audit_log_format(ab, " sock_type=\"unknown(%d)\"",
5384 +                                        sa->type);
5385 +
5386 +               audit_log_format(ab, " protocol=%d", sa->protocol);
5387 +       }
5388 +
5389 +        audit_log_format(ab, " pid=%d", current->pid);
5390 +
5391 +       if (profile) {
5392 +               audit_log_format(ab, " profile=");
5393 +               audit_log_untrustedstring(ab, profile->name);
5394 +
5395 +               if (profile->ns != default_namespace) {
5396 +                       audit_log_format(ab, " namespace=");
5397 +                       audit_log_untrustedstring(ab, profile->ns->name);
5398 +               }
5399 +       }
5400 +
5401 +       audit_log_end(ab);
5402 +
5403 +       return type == AUDIT_APPARMOR_ALLOWED ? 0 : sa->error_code;
5404 +}
5405 +
5406 +/**
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
5411 + */
5412 +int aa_audit_syscallreject(struct aa_profile *profile, gfp_t gfp,
5413 +                          const char *msg)
5414 +{
5415 +       struct aa_audit sa;
5416 +       memset(&sa, 0, sizeof(sa));
5417 +       sa.operation = "syscall";
5418 +       sa.name = msg;
5419 +       sa.gfp_mask = gfp;
5420 +       sa.error_code = -EPERM;
5421 +
5422 +       return aa_audit_base(profile, &sa, current->audit_context,
5423 +                            AUDIT_APPARMOR_DENIED);
5424 +}
5425 +
5426 +int aa_audit_message(struct aa_profile *profile, struct aa_audit *sa,
5427 +                     int type)
5428 +{
5429 +       struct audit_context *audit_cxt;
5430 +
5431 +       audit_cxt = apparmor_logsyscall ? current->audit_context : NULL;
5432 +       return aa_audit_base(profile, sa, audit_cxt, type);
5433 +}
5434 +
5435 +void aa_audit_hint(struct aa_profile *profile, struct aa_audit *sa)
5436 +{
5437 +       aa_audit_message(profile, sa, AUDIT_APPARMOR_HINT);
5438 +}
5439 +
5440 +void aa_audit_status(struct aa_profile *profile, struct aa_audit *sa)
5441 +{
5442 +       aa_audit_message(profile, sa, AUDIT_APPARMOR_STATUS);
5443 +}
5444 +
5445 +int aa_audit_reject(struct aa_profile *profile, struct aa_audit *sa)
5446 +{
5447 +       return aa_audit_message(profile, sa, AUDIT_APPARMOR_DENIED);
5448 +}
5449 +
5450 +/**
5451 + * aa_audit - Log an audit event to the audit subsystem
5452 + * @profile: profile to check against
5453 + * @sa: audit event
5454 + */
5455 +int aa_audit(struct aa_profile *profile, struct aa_audit *sa)
5456 +{
5457 +       int type = AUDIT_APPARMOR_DENIED;
5458 +       struct audit_context *audit_cxt;
5459 +
5460 +       if (likely(!sa->error_code))
5461 +               type = AUDIT_APPARMOR_AUDIT;
5462 +       else if (PROFILE_COMPLAIN(profile))
5463 +               type = AUDIT_APPARMOR_ALLOWED;
5464 +
5465 +       audit_cxt = apparmor_logsyscall ? current->audit_context : NULL;
5466 +       return aa_audit_base(profile, sa, audit_cxt, type);
5467 +}
5468 +
5469 +static int aa_audit_file(struct aa_profile *profile, struct aa_audit *sa)
5470 +{
5471 +       if (likely(!sa->error_code)) {
5472 +               int mask = sa->audit_mask & AUDIT_FILE_MASK;
5473 +
5474 +               if (unlikely(PROFILE_AUDIT(profile)))
5475 +                       mask |= AUDIT_FILE_MASK;
5476 +
5477 +               if (likely(!(sa->request_mask & mask)))
5478 +                       return 0;
5479 +
5480 +               /* mask off perms that are not being force audited */
5481 +               sa->request_mask &= mask | ALL_AA_EXEC_TYPE;
5482 +       } else {
5483 +               int mask = AUDIT_QUIET_MASK(sa->audit_mask);
5484 +
5485 +               if (!(sa->denied_mask & ~mask))
5486 +                       return sa->error_code;
5487 +
5488 +               /* mask off perms whose denial is being silenced */
5489 +               sa->denied_mask &= (~mask) | ALL_AA_EXEC_TYPE;
5490 +       }
5491 +
5492 +       return aa_audit(profile, sa);
5493 +}
5494 +
5495 +static int aa_audit_caps(struct aa_profile *profile, struct aa_audit *sa,
5496 +                        int cap)
5497 +{
5498 +       if (likely(!sa->error_code)) {
5499 +               if (likely(!PROFILE_AUDIT(profile) &&
5500 +                          !cap_raised(profile->audit_caps, cap)))
5501 +                       return 0;
5502 +       }
5503 +
5504 +       /* quieting of capabilities is handled the caps_logged cache */
5505 +       return aa_audit(profile, sa);
5506 +}
5507 +
5508 +/**
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
5514 + *
5515 + * Return %0 on success, or else the permissions in @mask that the
5516 + * profile denies.
5517 + */
5518 +static int aa_file_denied(struct aa_profile *profile, const char *name,
5519 +                         int mask, int *audit_mask)
5520 +{
5521 +       return (mask & ~aa_match(profile->file_rules, name, audit_mask));
5522 +}
5523 +
5524 +/**
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.
5533 + */
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)
5537 +{
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;
5541 +
5542 +       *request_mask = link_mask;
5543 +
5544 +       l_mode = aa_match_state(profile->file_rules, DFA_START, link, &state);
5545 +
5546 +       if (l_mode & link_mask) {
5547 +               int mode;
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,
5551 +                                     &state);
5552 +
5553 +               if (!(mode & link_mask))
5554 +                       denied_mask |= link_mask;
5555 +
5556 +               *audit_mask = dfa_audit_mask(profile->file_rules, state);
5557 +
5558 +               /* return if link subset test is not required */
5559 +               if (!(mode & (AA_LINK_SUBSET_TEST << target_mode)))
5560 +                       return denied_mask;
5561 +       }
5562 +
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.
5568 +        *
5569 +        * If the link has 'x', an exact match of all the execute flags
5570 +        * must match.
5571 +        */
5572 +       denied_mask |= ~l_mode & link_mask;
5573 +
5574 +       t_mode = aa_match(profile->file_rules, target, NULL);
5575 +
5576 +       l_x = l_mode & (ALL_AA_EXEC_TYPE | AA_EXEC_BITS);
5577 +       t_x = t_mode & (ALL_AA_EXEC_TYPE | AA_EXEC_BITS);
5578 +
5579 +       /* For actual subset test ignore valid-profile-transition flags,
5580 +        * and link bits
5581 +        */
5582 +       l_mode &= AA_FILE_PERMS & ~AA_LINK_BITS;
5583 +       t_mode &= AA_FILE_PERMS & ~AA_LINK_BITS;
5584 +
5585 +       *request_mask = l_mode | link_mask;
5586 +
5587 +       if (l_mode) {
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 */
5591 +
5592 +               /* handle exec subset
5593 +                * - link safe exec issubset of unsafe exec
5594 +                * - no link x perm is subset of target having x perm
5595 +                */
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);
5602 +       }
5603 +
5604 +       return denied_mask;
5605 +}
5606 +
5607 +/**
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
5613 + *
5614 + * Returns a pointer to the beginning of the pathname (which usually differs
5615 + * from the beginning of the buffer), or an error code.
5616 + *
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.
5619 + */
5620 +static char *aa_get_name(struct dentry *dentry, struct vfsmount *mnt,
5621 +                        char **buffer, int check)
5622 +{
5623 +       char *name;
5624 +       int is_dir, size = 256;
5625 +
5626 +       is_dir = (check & AA_CHECK_DIR) ? 1 : 0;
5627 +
5628 +       for (;;) {
5629 +               char *buf = kmalloc(size, GFP_KERNEL);
5630 +               if (!buf)
5631 +                       return ERR_PTR(-ENOMEM);
5632 +
5633 +               name = d_namespace_path(dentry, mnt, buf, size - is_dir);
5634 +               if (!IS_ERR(name)) {
5635 +                       if (name[0] != '/') {
5636 +                               /*
5637 +                                * This dentry is not connected to the
5638 +                                * namespace root -- reject access.
5639 +                                */
5640 +                               kfree(buf);
5641 +                               return ERR_PTR(-ENOENT);
5642 +                       }
5643 +                       if (is_dir && name[1] != '\0') {
5644 +                               /*
5645 +                                * Append "/" to the pathname. The root
5646 +                                * directory is a special case; it already
5647 +                                * ends in slash.
5648 +                                */
5649 +                               buf[size - 2] = '/';
5650 +                               buf[size - 1] = '\0';
5651 +                       }
5652 +
5653 +                       *buffer = buf;
5654 +                       return name;
5655 +               }
5656 +               if (PTR_ERR(name) != -ENAMETOOLONG)
5657 +                       return name;
5658 +
5659 +               kfree(buf);
5660 +               size <<= 1;
5661 +               if (size > apparmor_path_max)
5662 +                       return ERR_PTR(-ENAMETOOLONG);
5663 +       }
5664 +}
5665 +
5666 +static char *new_compound_name(const char *n1, const char *n2)
5667 +{
5668 +       char *name = kmalloc(strlen(n1) + strlen(n2) + 3, GFP_KERNEL);
5669 +       if (name)
5670 +               sprintf(name, "%s//%s", n1, n2);
5671 +       return name;
5672 +}
5673 +static inline void aa_put_name_buffer(char *buffer)
5674 +{
5675 +       kfree(buffer);
5676 +}
5677 +
5678 +/**
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
5686 + *
5687 + * Returns 0 upon success, or else an error code.
5688 + *
5689 + * @check indicates the file type, and whether the file was accessed through
5690 + * an open file descriptor (AA_CHECK_FD) or not.
5691 + */
5692 +static int aa_perm_dentry(struct aa_profile *profile, struct dentry *dentry,
5693 +                         struct vfsmount *mnt, struct aa_audit *sa, int check)
5694 +{
5695 +       int error;
5696 +       char *buffer = NULL;
5697 +
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)) {
5701 +               /*
5702 +                * deleted files are given a pass on permission checks when
5703 +                * accessed through a file descriptor.
5704 +                */
5705 +               if (PTR_ERR(sa->name) == -ENOENT && (check & AA_CHECK_FD))
5706 +                       sa->denied_mask = 0;
5707 +               else {
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";
5714 +                       else
5715 +                               sa->info = "Failed name resolution";
5716 +               }
5717 +               sa->name = NULL;
5718 +       } else
5719 +               sa->denied_mask = aa_file_denied(profile, sa->name,
5720 +                                                sa->request_mask,
5721 +                                                &sa->audit_mask);
5722 +
5723 +       if (!sa->denied_mask)
5724 +               sa->error_code = 0;
5725 +
5726 +       error = aa_audit_file(profile, sa);
5727 +       aa_put_name_buffer(buffer);
5728 +
5729 +       return error;
5730 +}
5731 +
5732 +/**
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
5738 + */
5739 +int aa_attr(struct aa_profile *profile, struct dentry *dentry,
5740 +           struct vfsmount *mnt, struct iattr *iattr)
5741 +{
5742 +       struct inode *inode = dentry->d_inode;
5743 +       int error, check;
5744 +       struct aa_audit sa;
5745 +
5746 +       memset(&sa, 0, sizeof(sa));
5747 +       sa.operation = "setattr";
5748 +       sa.gfp_mask = GFP_KERNEL;
5749 +       sa.iattr = iattr;
5750 +       sa.request_mask = MAY_WRITE;
5751 +       sa.error_code = -EACCES;
5752 +
5753 +       check = 0;
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;
5758 +
5759 +       error = aa_perm_dentry(profile, dentry, mnt, &sa, check);
5760 +
5761 +       return error;
5762 +}
5763 +
5764 +/**
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
5772 + */
5773 +int aa_perm_xattr(struct aa_profile *profile, const char *operation,
5774 +                 struct dentry *dentry, struct vfsmount *mnt, int mask,
5775 +                 int check)
5776 +{
5777 +       struct inode *inode = dentry->d_inode;
5778 +       int error;
5779 +       struct aa_audit sa;
5780 +
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;
5786 +
5787 +       if (inode && S_ISDIR(inode->i_mode))
5788 +               check |= AA_CHECK_DIR;
5789 +
5790 +       error = aa_perm_dentry(profile, dentry, mnt, &sa, check);
5791 +
5792 +       return error;
5793 +}
5794 +
5795 +/**
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
5802 + *
5803 + * Determine if access @mask for the file is authorized by @profile.
5804 + * Returns 0 on success, or else an error code.
5805 + */
5806 +int aa_perm(struct aa_profile *profile, const char *operation,
5807 +           struct dentry *dentry, struct vfsmount *mnt, int mask, int check)
5808 +{
5809 +       struct aa_audit sa;
5810 +       int error = 0;
5811 +
5812 +       if (mask == 0)
5813 +               goto out;
5814 +
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;
5820 +
5821 +       error = aa_perm_dentry(profile, dentry, mnt, &sa, check);
5822 +
5823 +out:
5824 +       return error;
5825 +}
5826 +
5827 +/**
5828 + * aa_perm_dir
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
5834 + *
5835 + * Determine if directory operation (make/remove) for dentry is authorized
5836 + * by @profile.
5837 + * Returns 0 on success, or else an error code.
5838 + */
5839 +int aa_perm_dir(struct aa_profile *profile, const char *operation,
5840 +               struct dentry *dentry, struct vfsmount *mnt, int mask)
5841 +{
5842 +       struct aa_audit sa;
5843 +
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;
5849 +
5850 +       return aa_perm_dentry(profile, dentry, mnt, &sa, AA_CHECK_DIR);
5851 +}
5852 +
5853 +int aa_perm_path(struct aa_profile *profile, const char *operation,
5854 +                const char *name, int mask, uid_t uid)
5855 +{
5856 +       struct aa_audit sa;
5857 +
5858 +       memset(&sa, 0, sizeof(sa));
5859 +       sa.operation = operation;
5860 +       sa.gfp_mask = GFP_KERNEL;
5861 +       sa.request_mask = mask;
5862 +       sa.name = name;
5863 +       if (current->fsuid == uid)
5864 +               sa.request_mask = mask << AA_USER_SHIFT;
5865 +       else
5866 +               sa.request_mask = mask << AA_OTHER_SHIFT;
5867 +
5868 +       sa.denied_mask = aa_file_denied(profile, name, sa.request_mask,
5869 +                                       &sa.audit_mask) ;
5870 +       sa.error_code = sa.denied_mask ? -EACCES : 0;
5871 +
5872 +       return aa_audit_file(profile, &sa);
5873 +}
5874 +
5875 +/**
5876 + * aa_capability - test permission to use capability
5877 + * @cxt: aa_task_context with profile to check against
5878 + * @cap: capability to be tested
5879 + *
5880 + * Look up capability in profile capability set.
5881 + * Returns 0 on success, or else an error code.
5882 + */
5883 +int aa_capability(struct aa_task_context *cxt, int cap)
5884 +{
5885 +       int error = cap_raised(cxt->profile->capabilities, cap) ? 0 : -EPERM;
5886 +       struct aa_audit sa;
5887 +
5888 +       /* test if cap has alread been logged */
5889 +       if (cap_raised(cxt->caps_logged, cap)) {
5890 +               if (PROFILE_COMPLAIN(cxt->profile))
5891 +                       error = 0;
5892 +               return error;
5893 +       } else
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
5898 +                * the audit log
5899 +                */
5900 +               cap_raise(cxt->caps_logged, cap);
5901 +
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;
5907 +
5908 +       error = aa_audit_caps(cxt->profile, &sa, cap);
5909 +
5910 +       return error;
5911 +}
5912 +
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)
5915 +{
5916 +       if (!cxt || cxt->profile == tracee)
5917 +               return 0;
5918 +       return aa_capability(cxt, CAP_SYS_PTRACE);
5919 +}
5920 +
5921 +/**
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
5928 + *
5929 + * Returns 0 on success, or else an error code.
5930 + */
5931 +int aa_link(struct aa_profile *profile,
5932 +           struct dentry *link, struct vfsmount *link_mnt,
5933 +           struct dentry *target, struct vfsmount *target_mnt)
5934 +{
5935 +       int error;
5936 +       struct aa_audit sa;
5937 +       char *buffer = NULL, *buffer2 = NULL;
5938 +
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);
5944 +
5945 +       if (IS_ERR(sa.name)) {
5946 +               sa.error_code = PTR_ERR(sa.name);
5947 +               sa.name = NULL;
5948 +       }
5949 +       if (IS_ERR(sa.name2)) {
5950 +               sa.error_code = PTR_ERR(sa.name2);
5951 +               sa.name2 = NULL;
5952 +       }
5953 +
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),
5957 +                                               &sa.request_mask,
5958 +                                               &sa.audit_mask);
5959 +               sa.error_code = sa.denied_mask ? -EACCES : 0;
5960 +       }
5961 +
5962 +       error = aa_audit_file(profile, &sa);
5963 +
5964 +       aa_put_name_buffer(buffer);
5965 +       aa_put_name_buffer(buffer2);
5966 +
5967 +       return error;
5968 +}
5969 +
5970 +int aa_net_perm(struct aa_profile *profile, char *operation,
5971 +               int family, int type, int protocol)
5972 +{
5973 +       struct aa_audit sa;
5974 +       int error = 0;
5975 +       u16 family_mask, audit_mask, quiet_mask;
5976 +
5977 +       if ((family < 0) || (family >= AF_MAX))
5978 +               return -EINVAL;
5979 +
5980 +       if ((type < 0) || (type >= SOCK_MAX))
5981 +               return -EINVAL;
5982 +
5983 +       /* unix domain and netlink sockets are handled by ipc */
5984 +       if (family == AF_UNIX || family == AF_NETLINK)
5985 +               return 0;
5986 +
5987 +       family_mask = profile->network_families[family];
5988 +       audit_mask = profile->audit_network[family];
5989 +       quiet_mask = profile->quiet_network[family];
5990 +
5991 +       error = (family_mask & (1 << type)) ? 0 : -EACCES;
5992 +
5993 +       memset(&sa, 0, sizeof(sa));
5994 +       sa.operation = operation;
5995 +       sa.gfp_mask = GFP_KERNEL;
5996 +       sa.family = family;
5997 +       sa.type = type;
5998 +       sa.protocol = protocol;
5999 +       sa.error_code = error;
6000 +
6001 +       if (likely(!error)) {
6002 +               if (!PROFILE_AUDIT(profile) && !(family_mask & audit_mask))
6003 +                       return 0;
6004 +       } else if (!((1 << type) & ~quiet_mask)) {
6005 +               return error;
6006 +       }
6007 +
6008 +       error = aa_audit(profile, &sa);
6009 +
6010 +       return error;
6011 +}
6012 +
6013 +int aa_revalidate_sk(struct sock *sk, char *operation)
6014 +{
6015 +       struct aa_profile *profile;
6016 +       int error = 0;
6017 +
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");
6022 +               dump_stack();
6023 +               return 0;
6024 +       }
6025 +
6026 +       profile = aa_get_profile(current);
6027 +       if (profile)
6028 +               error = aa_net_perm(profile, operation,
6029 +                                   sk->sk_family, sk->sk_type,
6030 +                                   sk->sk_protocol);
6031 +       aa_put_profile(profile);
6032 +
6033 +       return error;
6034 +}
6035 +/**
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
6040 + *
6041 + * Control raising the processes hard limit.
6042 + */
6043 +int aa_task_setrlimit(struct aa_profile *profile, unsigned int resource,
6044 +                     struct rlimit *new_rlim)
6045 +{
6046 +       struct aa_audit sa;
6047 +       int error = 0;
6048 +
6049 +       memset(&sa, 0, sizeof(sa));
6050 +       sa.operation = "setrlimit";
6051 +       sa.gfp_mask = GFP_KERNEL;
6052 +       sa.rlimit = resource + 1;
6053 +
6054 +       if (profile->rlimits.mask & (1 << resource) &&
6055 +           new_rlim->rlim_max > profile->rlimits.limits[resource].rlim_max) {
6056 +               sa.error_code = -EACCES;
6057 +
6058 +               error = aa_audit(profile, &sa);
6059 +       }
6060 +
6061 +       return error;
6062 +}
6063 +
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)
6067 +               return -EAGAIN;
6068 +       return 0;
6069 +}
6070 +
6071 +void aa_set_rlimits(struct task_struct *task, struct aa_profile *profile)
6072 +{
6073 +       int i, mask;
6074 +
6075 +       if (!profile)
6076 +               return;
6077 +
6078 +       if (!profile->rlimits.mask)
6079 +               return;
6080 +
6081 +       task_lock(task->group_leader);
6082 +       mask = 1;
6083 +       for (i = 0; i < RLIM_NLIMITS; i++, mask <<= 1) {
6084 +               struct rlimit new_rlim, *old_rlim;
6085 +
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
6089 +                */
6090 +               if (i == RLIMIT_NPROC || i == RLIMIT_CPU)
6091 +                       continue;
6092 +
6093 +               old_rlim = task->signal->rlim + i;
6094 +               new_rlim = *old_rlim;
6095 +
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;
6102 +               }
6103 +
6104 +               *old_rlim = new_rlim;
6105 +       }
6106 +       task_unlock(task->group_leader);
6107 +}
6108 +
6109 +/*******************************
6110 + * Global task related functions
6111 + *******************************/
6112 +
6113 +/**
6114 + * aa_clone - initialize the task context for a new task
6115 + * @child: task that is being created
6116 + *
6117 + * Returns 0 on success, or else an error code.
6118 + */
6119 +int aa_clone(struct task_struct *child)
6120 +{
6121 +       struct aa_audit sa;
6122 +       struct aa_task_context *cxt, *child_cxt;
6123 +       struct aa_profile *profile;
6124 +
6125 +       if (!aa_task_context(current))
6126 +               return 0;
6127 +       child_cxt = aa_alloc_task_context(GFP_KERNEL);
6128 +       if (!child_cxt)
6129 +               return -ENOMEM;
6130 +
6131 +       memset(&sa, 0, sizeof(sa));
6132 +       sa.operation = "clone";
6133 +       sa.task = child->pid;
6134 +       sa.gfp_mask = GFP_KERNEL;
6135 +
6136 +repeat:
6137 +       profile = aa_get_profile(current);
6138 +       if (profile) {
6139 +               lock_profile(profile);
6140 +               cxt = aa_task_context(current);
6141 +               if (unlikely(profile->isstale || !cxt ||
6142 +                            cxt->profile != profile)) {
6143 +                       /**
6144 +                        * Race with profile replacement or removal, or with
6145 +                        * task context removal.
6146 +                        */
6147 +                       unlock_profile(profile);
6148 +                       aa_put_profile(profile);
6149 +                       goto repeat;
6150 +               }
6151 +
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);
6157 +                       return -EAGAIN;
6158 +               }
6159 +
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);
6163 +
6164 +               unlock_profile(profile);
6165 +
6166 +               if (APPARMOR_COMPLAIN(child_cxt) &&
6167 +                   profile == profile->ns->null_complain_profile) {
6168 +                       aa_audit_hint(profile, &sa);
6169 +               }
6170 +               aa_put_profile(profile);
6171 +       } else
6172 +               aa_free_task_context(child_cxt);
6173 +
6174 +       return 0;
6175 +}
6176 +
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)
6181 +{
6182 +       struct aa_namespace *ns;
6183 +       struct aa_profile *new_profile;
6184 +       int ns_ref = 0;
6185 +
6186 +       if (profile)
6187 +               ns = profile->ns;
6188 +       else
6189 +               ns = default_namespace;
6190 +
6191 +       if (ns_name) {
6192 +               /* locate the profile namespace */
6193 +               ns = aa_find_namespace(ns_name);
6194 +               if (!ns) {
6195 +                       if (mandatory) {
6196 +                               sa->info = "profile namespace not found";
6197 +                               sa->denied_mask = sa->request_mask;
6198 +                               sa->error_code = -ENOENT;
6199 +                               return ERR_PTR(-ENOENT);
6200 +                       } else {
6201 +                               return NULL;
6202 +                       }
6203 +               }
6204 +               ns_ref++;
6205 +       }
6206 +
6207 +       /* Locate new profile */
6208 +       new_profile = aa_find_profile(ns, name);
6209 +
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 */
6216 +               if (complain) {
6217 +                       aa_audit_hint(profile, sa);
6218 +                       new_profile =
6219 +                           aa_dup_profile(profile->ns->null_complain_profile);
6220 +               } else {
6221 +                       sa->error_code = -EACCES;
6222 +                       if (ns_ref)
6223 +                               aa_put_namespace(ns);
6224 +                       return ERR_PTR(-EACCES);
6225 +               }
6226 +       } else {
6227 +               /* Only way we can get into this code is if task
6228 +                * is unconfined, pix, nix.
6229 +                */
6230 +               AA_DEBUG("%s: No profile found for exec image '%s'\n",
6231 +                        __FUNCTION__,
6232 +                        name);
6233 +       }
6234 +       if (ns_ref)
6235 +               aa_put_namespace(ns);
6236 +       return new_profile;
6237 +}
6238 +
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)
6242 +{
6243 +       struct aa_profile *new_profile = NULL;
6244 +       int ix = xmode & AA_EXEC_INHERIT;
6245 +       int complain = PROFILE_COMPLAIN(profile);
6246 +       int index;
6247 +
6248 +       *child = NULL;
6249 +       switch (xmode & AA_EXEC_MODIFIERS) {
6250 +       case 0:
6251 +               /* only valid with ix flag */
6252 +               ix = 1;
6253 +               break;
6254 +       case AA_EXEC_UNCONFINED:
6255 +               /* only valid without ix flag */
6256 +               ix = 0;
6257 +               break;
6258 +       case AA_EXEC_PROFILE:
6259 +               new_profile = aa_register_find(profile, NULL, filename, !ix,
6260 +                                              complain, sa);
6261 +               break;
6262 +       case AA_EXEC_CHILD:
6263 +               *child = new_compound_name(profile->name, filename);
6264 +               sa->name2 = *child;
6265 +               if (!*child) {
6266 +                       sa->info = "Failed name resolution - exec failed";
6267 +                       sa->error_code = -ENOMEM;
6268 +                       new_profile = ERR_PTR(-ENOMEM);
6269 +               } else {
6270 +                       new_profile = aa_register_find(profile, NULL, *child,
6271 +                                                      !ix, complain, sa);
6272 +               }
6273 +               break;
6274 +       default:
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);
6281 +               } else {
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;
6287 +                       }
6288 +                       sa->name2 = name;
6289 +                       sa->name3 = ns_name;
6290 +                       new_profile =
6291 +                               aa_register_find(profile, ns_name, name,
6292 +                                                !ix, complain, sa);
6293 +               }
6294 +       }
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;
6299 +}
6300 +
6301 +/**
6302 + * aa_register - register a new program
6303 + * @bprm: binprm of program being registered
6304 + *
6305 + * Try to register a new program during execve().  This should give the
6306 + * new program a valid aa_task_context if confined.
6307 + */
6308 +int aa_register(struct linux_binprm *bprm)
6309 +{
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;
6316 +
6317 +       AA_DEBUG("%s\n", __FUNCTION__);
6318 +
6319 +       profile = aa_get_profile(current);
6320 +
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;
6326 +
6327 +       filename = aa_get_name(filp->f_dentry, filp->f_vfsmnt, &buffer, 0);
6328 +       if (IS_ERR(filename)) {
6329 +               if (profile) {
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;
6334 +               } else
6335 +                       return 0;
6336 +       }
6337 +       sa.name = filename;
6338 +
6339 +       exec_mode = AA_EXEC_UNSAFE << shift;
6340 +
6341 +repeat:
6342 +       if (profile) {
6343 +               complain = PROFILE_COMPLAIN(profile);
6344 +
6345 +               /* Confined task, determine what mode inherit, unconfined or
6346 +                * mandatory to load new profile
6347 +                */
6348 +               exec_mode = aa_match(profile->file_rules, filename,
6349 +                                    &sa.audit_mask);
6350 +
6351 +
6352 +               if (exec_mode & sa.request_mask) {
6353 +                       int xm = exec_mode >> shift;
6354 +                       new_profile = aa_x_to_profile(profile, filename,
6355 +                                                     xm, &sa, &child);
6356 +
6357 +                       if (!new_profile && (xm & AA_EXEC_INHERIT))
6358 +                               /* (p|c|n|)ix - don't change profile */
6359 +                               goto cleanup;
6360 +                       /* error case caught below */
6361 +
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).
6369 +                        */
6370 +                       new_profile =
6371 +                           aa_dup_profile(profile->ns->null_complain_profile);
6372 +                       exec_mode |= AA_EXEC_UNSAFE << shift;
6373 +               } else {
6374 +                       sa.denied_mask = sa.request_mask;
6375 +                       sa.error_code = -EACCES;
6376 +                       new_profile = ERR_PTR(aa_audit_file(profile, &sa));
6377 +               }
6378 +       } else {
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)
6382 +                       goto cleanup;
6383 +       }
6384 +
6385 +       if (IS_ERR(new_profile))
6386 +               goto cleanup;
6387 +
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);
6394 +                       goto repeat;
6395 +               }
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);
6401 +               }
6402 +               if (PTR_ERR(old_profile) == -EAGAIN) {
6403 +                       sa.info = "rlimit nproc limit exceeded";
6404 +                       aa_audit_reject(profile, &sa);
6405 +               }
6406 +               new_profile = old_profile;
6407 +               goto cleanup;
6408 +       }
6409 +       aa_put_profile(old_profile);
6410 +       aa_put_profile(profile);
6411 +
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
6417 +        *
6418 +        * Cases 2 and 3 are marked as requiring secure exec
6419 +        * (unless policy specified "unsafe exec")
6420 +        */
6421 +       if (!(exec_mode & (AA_EXEC_UNSAFE << shift))) {
6422 +               unsigned long bprm_flags;
6423 +
6424 +               bprm_flags = AA_SECURE_EXEC_NEEDED;
6425 +               bprm->security = (void*)
6426 +                       ((unsigned long)bprm->security | bprm_flags);
6427 +       }
6428 +
6429 +       if (complain && new_profile &&
6430 +           new_profile == new_profile->ns->null_complain_profile) {
6431 +               sa.request_mask = 0;
6432 +               sa.name = NULL;
6433 +               sa.info = "set profile";
6434 +               aa_audit_hint(new_profile, &sa);
6435 +       }
6436 +
6437 +cleanup:
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);
6443 +       return 0;
6444 +}
6445 +
6446 +/**
6447 + * aa_release - release a task context
6448 + * @task: task being released
6449 + *
6450 + * This is called after a task has exited and the parent has reaped it.
6451 + */
6452 +void aa_release(struct task_struct *task)
6453 +{
6454 +       struct aa_task_context *cxt;
6455 +       struct aa_profile *profile;
6456 +       /*
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
6463 +        * the task.
6464 +        *
6465 +        * Use lock subtyping to avoid lockdep reporting a false irq
6466 +        * possible inversion between the task_lock and profile_lock
6467 +        *
6468 +        * We also avoid taking the task_lock here because lock_dep
6469 +        * would report another false {softirq-on-W} potential irq_lock
6470 +        * inversion.
6471 +        *
6472 +        * If the task does not have a profile attached we are safe;
6473 +        * nothing can race with us at this point.
6474 +        */
6475 +
6476 +repeat:
6477 +       profile = aa_get_profile(task);
6478 +       if (profile) {
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);
6484 +                       goto repeat;
6485 +               }
6486 +               aa_change_task_context(task, NULL, NULL, 0, NULL);
6487 +               unlock_profile(profile);
6488 +               aa_put_profile(profile);
6489 +       }
6490 +}
6491 +
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)
6496 +{
6497 +       struct aa_profile *new_profile = NULL, *old_profile = NULL,
6498 +               *previous_profile = NULL;
6499 +       struct aa_task_context *new_cxt, *cxt;
6500 +       int error = 0;
6501 +
6502 +       sa->name = name;
6503 +
6504 +       new_cxt = aa_alloc_task_context(GFP_KERNEL);
6505 +       if (!new_cxt)
6506 +               return -ENOMEM;
6507 +
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);
6512 +                       return -ENOENT;
6513 +               }
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);
6518 +               return error;
6519 +       }
6520 +
6521 +       cxt = lock_task_and_profiles(current, new_profile);
6522 +       if (!cxt) {
6523 +               error = -EPERM;
6524 +               goto out;
6525 +       }
6526 +       old_profile = cxt->profile;
6527 +
6528 +       if (cxt->profile != expected || (new_profile && new_profile->isstale)) {
6529 +               error = -ESTALE;
6530 +               goto out;
6531 +       }
6532 +
6533 +       if (cxt->previous_profile) {
6534 +               if (cxt->cookie != cookie) {
6535 +                       error = -EACCES;
6536 +                       sa->info = "killing process";
6537 +                       aa_audit_reject(cxt->profile, sa);
6538 +                       /* terminate process */
6539 +                       (void)send_sig_info(SIGKILL, NULL, current);
6540 +                       goto out;
6541 +               }
6542 +
6543 +               if (!restore)
6544 +                       previous_profile = cxt->previous_profile;
6545 +       } else
6546 +               previous_profile = cxt->profile;
6547 +
6548 +       if ((current->ptrace & PT_PTRACED) && aa_may_ptrace(cxt, new_profile)) {
6549 +               error = -EACCES;
6550 +               goto out;
6551 +       }
6552 +
6553 +       if ((error = aa_rlimit_nproc(new_profile))) {
6554 +               sa->info = "rlimit nproc limit exceeded";
6555 +               aa_audit_reject(cxt->profile, sa);
6556 +               goto out;
6557 +       }
6558 +
6559 +       if (new_profile == ns->null_complain_profile)
6560 +               aa_audit_hint(cxt->profile, sa);
6561 +
6562 +       if (APPARMOR_AUDIT(cxt))
6563 +               aa_audit_message(cxt->profile, sa, AUDIT_APPARMOR_AUDIT);
6564 +
6565 +       if (!restore && cookie)
6566 +               aa_change_task_context(current, new_cxt, new_profile, cookie,
6567 +                                      previous_profile);
6568 +       else
6569 +               /* either return to previous_profile, or a permanent change */
6570 +               aa_change_task_context(current, new_cxt, new_profile, 0, NULL);
6571 +
6572 +out:
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);
6578 +       return error;
6579 +}
6580 +
6581 +/**
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
6586 + * to change back.
6587 + *
6588 + * Returns %0 on success, error otherwise.
6589 + */
6590 +int aa_change_profile(const char *ns_name, const char *name)
6591 +{
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;
6598 +
6599 +       if (!name)
6600 +               return -EINVAL;
6601 +
6602 +       memset(&sa, 0, sizeof(sa));
6603 +       sa.gfp_mask = GFP_ATOMIC;
6604 +       sa.operation = "change_profile";
6605 +
6606 +repeat:
6607 +       task_lock(current);
6608 +       cxt = aa_task_context(current);
6609 +       if (cxt)
6610 +               profile = aa_dup_profile(cxt->profile);
6611 +       task_unlock(current);
6612 +
6613 +       if (ns_name)
6614 +               ns = aa_find_namespace(ns_name);
6615 +       else if (profile)
6616 +               ns = aa_get_namespace(profile->ns);
6617 +       else
6618 +               ns = aa_get_namespace(default_namespace);
6619 +
6620 +       if (!ns) {
6621 +               aa_put_profile(profile);
6622 +               return -ENOENT;
6623 +       }
6624 +
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);
6629 +       else {
6630 +               /* check for a rule with a namespace prepended */
6631 +               aa_match_state(profile->file_rules, DFA_START, ns->name,
6632 +                              &state);
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,
6637 +                                                 &sa);
6638 +               else
6639 +                       /* no permission to transition to profile @name */
6640 +                       error = -EACCES;
6641 +       }
6642 +
6643 +       aa_put_namespace(ns);
6644 +       aa_put_profile(profile);
6645 +       if (error == -ESTALE)
6646 +               goto repeat;
6647 +
6648 +       return error;
6649 +}
6650 +
6651 +/**
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
6655 + *
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
6659 + * profile.
6660 + * Returns %0 on success, error otherwise.
6661 + */
6662 +int aa_change_hat(const char *hat_name, u64 cookie)
6663 +{
6664 +       struct aa_task_context *cxt;
6665 +       struct aa_profile *profile, *previous_profile;
6666 +       struct aa_audit sa;
6667 +       int error = 0;
6668 +
6669 +       memset(&sa, 0, sizeof(sa));
6670 +       sa.gfp_mask = GFP_ATOMIC;
6671 +       sa.operation = "change_hat";
6672 +
6673 +repeat:
6674 +       task_lock(current);
6675 +       cxt = aa_task_context(current);
6676 +       if (!cxt) {
6677 +               task_unlock(current);
6678 +               return -EPERM;
6679 +       }
6680 +       profile = aa_dup_profile(cxt->profile);
6681 +       previous_profile = aa_dup_profile(cxt->previous_profile);
6682 +       task_unlock(current);
6683 +
6684 +       if (hat_name) {
6685 +               char *name, *profile_name;
6686 +
6687 +               if (previous_profile)
6688 +                       profile_name = previous_profile->name;
6689 +               else
6690 +                       profile_name = profile->name;
6691 +
6692 +               name = new_compound_name(profile_name, hat_name);
6693 +               if (!name) {
6694 +                       error = -ENOMEM;
6695 +                       goto out;
6696 +               }
6697 +               error = do_change_profile(profile, profile->ns, name, cookie,
6698 +                                         0, 1, &sa);
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,
6703 +                                         &sa);
6704 +       /* else ignore restores when there is no saved profile */
6705 +
6706 +out:
6707 +       aa_put_profile(previous_profile);
6708 +       aa_put_profile(profile);
6709 +       if (error == -ESTALE)
6710 +               goto repeat;
6711 +
6712 +       return error;
6713 +}
6714 +
6715 +/**
6716 + * __aa_replace_profile - replace a task's profile
6717 + * @task: task to switch the profile of
6718 + * @profile: profile to switch to
6719 + *
6720 + * Returns a handle to the previous profile upon success, or else an
6721 + * error code.
6722 + */
6723 +struct aa_profile *__aa_replace_profile(struct task_struct *task,
6724 +                                       struct aa_profile *profile)
6725 +{
6726 +       struct aa_task_context *cxt, *new_cxt = NULL;
6727 +       struct aa_profile *old_profile = NULL;
6728 +
6729 +       if (profile) {
6730 +               new_cxt = aa_alloc_task_context(GFP_KERNEL);
6731 +               if (!new_cxt)
6732 +                       return ERR_PTR(-ENOMEM);
6733 +       }
6734 +
6735 +       cxt = lock_task_and_profiles(task, profile);
6736 +       if (unlikely(profile && profile->isstale)) {
6737 +               old_profile = ERR_PTR(-ESTALE);
6738 +               goto error;
6739 +       }
6740 +
6741 +       if ((current->ptrace & PT_PTRACED) && aa_may_ptrace(cxt, profile)) {
6742 +               old_profile = ERR_PTR(-EPERM);
6743 +               goto error;
6744 +       }
6745 +
6746 +       if (aa_rlimit_nproc(profile)) {
6747 +               old_profile = ERR_PTR(-EAGAIN);
6748 +               goto error;
6749 +       }
6750 +
6751 +       if (cxt)
6752 +               old_profile = aa_dup_profile(cxt->profile);
6753 +       aa_change_task_context(task, new_cxt, profile, 0, NULL);
6754 +
6755 +       task_unlock(task);
6756 +       aa_set_rlimits(task, profile);
6757 +       unlock_both_profiles(profile, old_profile);
6758 +       return old_profile;
6759 +
6760 +error:
6761 +       task_unlock(task);
6762 +       unlock_both_profiles(profile, cxt ? cxt->profile : NULL);
6763 +       aa_free_task_context(new_cxt);
6764 +       return old_profile;
6765 +}
6766 +
6767 +/**
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
6771 + *
6772 + * Handle the spinning on locking to make sure the task context and
6773 + * profile are consistent once all locks are aquired.
6774 + *
6775 + * return the aa_task_context currently confining the task.  The task lock
6776 + * will be held whether or not the task is confined.
6777 + */
6778 +struct aa_task_context *
6779 +lock_task_and_profiles(struct task_struct *task, struct aa_profile *profile)
6780 +{
6781 +       struct aa_task_context *cxt;
6782 +       struct aa_profile *old_profile = NULL;
6783 +
6784 +       rcu_read_lock();
6785 +repeat:
6786 +       cxt = aa_task_context(task);
6787 +       if (cxt)
6788 +               old_profile = cxt->profile;
6789 +
6790 +       lock_both_profiles(profile, old_profile);
6791 +       task_lock(task);
6792 +
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;
6798 +               goto repeat;
6799 +       }
6800 +       rcu_read_unlock();
6801 +       return cxt;
6802 +}
6803 +
6804 +static void free_aa_task_context_rcu_callback(struct rcu_head *head)
6805 +{
6806 +       struct aa_task_context *cxt;
6807 +
6808 +       cxt = container_of(head, struct aa_task_context, rcu);
6809 +       aa_free_task_context(cxt);
6810 +}
6811 +
6812 +/**
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
6819 + */
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)
6824 +{
6825 +       struct aa_task_context *old_cxt = aa_task_context(task);
6826 +
6827 +       if (old_cxt) {
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);
6831 +       }
6832 +       if (new_cxt) {
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
6836 +                */
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);
6844 +       }
6845 +       rcu_assign_pointer(task->security, new_cxt);
6846 +}
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
6850 @@ -0,0 +1,364 @@
6851 +/*
6852 + *     Copyright (C) 2007 Novell/SUSE
6853 + *
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
6857 + *     License.
6858 + *
6859 + *     Regular expression transition table matching
6860 + */
6861 +
6862 +#include <linux/kernel.h>
6863 +#include <linux/slab.h>
6864 +#include <linux/errno.h>
6865 +#include "apparmor.h"
6866 +#include "match.h"
6867 +#include "inline.h"
6868 +
6869 +static struct table_header *unpack_table(void *blob, size_t bsize)
6870 +{
6871 +       struct table_header *table = NULL;
6872 +       struct table_header th;
6873 +       size_t tsize;
6874 +
6875 +       if (bsize < sizeof(struct table_header))
6876 +               goto out;
6877 +
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);
6882 +
6883 +       if (!(th.td_flags == YYTD_DATA16 || th.td_flags == YYTD_DATA32 ||
6884 +               th.td_flags == YYTD_DATA8))
6885 +               goto out;
6886 +
6887 +       tsize = table_size(th.td_lolen, th.td_flags);
6888 +       if (bsize < tsize)
6889 +               goto out;
6890 +
6891 +       table = kmalloc(tsize, GFP_KERNEL);
6892 +       if (table) {
6893 +               *table = th;
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);
6900 +               else
6901 +                       UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
6902 +                                    u32, be32_to_cpu);
6903 +       }
6904 +
6905 +out:
6906 +       return table;
6907 +}
6908 +
6909 +int unpack_dfa(struct aa_dfa *dfa, void *blob, size_t size)
6910 +{
6911 +       int hsize, i;
6912 +       int error = -ENOMEM;
6913 +
6914 +       /* get dfa table set header */
6915 +       if (size < sizeof(struct table_set_header))
6916 +               goto fail;
6917 +
6918 +       if (ntohl(*(u32 *)blob) != YYTH_MAGIC)
6919 +               goto fail;
6920 +
6921 +       hsize = ntohl(*(u32 *)(blob + 4));
6922 +       if (size < hsize)
6923 +               goto fail;
6924 +
6925 +       blob += hsize;
6926 +       size -= hsize;
6927 +
6928 +       error = -EPROTO;
6929 +       while (size > 0) {
6930 +               struct table_header *table;
6931 +               table = unpack_table(blob, size);
6932 +               if (!table)
6933 +                       goto fail;
6934 +
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)
6941 +                               goto fail;
6942 +                       break;
6943 +               case YYTD_ID_DEF:
6944 +               case YYTD_ID_NXT:
6945 +               case YYTD_ID_CHK:
6946 +                       dfa->tables[table->td_id - 1] = table;
6947 +                       if (table->td_flags != YYTD_DATA16)
6948 +                               goto fail;
6949 +                       break;
6950 +               case YYTD_ID_EC:
6951 +                       dfa->tables[table->td_id - 1] = table;
6952 +                       if (table->td_flags != YYTD_DATA8)
6953 +                               goto fail;
6954 +                       break;
6955 +               default:
6956 +                       kfree(table);
6957 +                       goto fail;
6958 +               }
6959 +
6960 +               blob += table_size(table->td_lolen, table->td_flags);
6961 +               size -= table_size(table->td_lolen, table->td_flags);
6962 +       }
6963 +
6964 +       return 0;
6965 +
6966 +fail:
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;
6971 +               }
6972 +       }
6973 +       return error;
6974 +}
6975 +
6976 +/**
6977 + * verify_dfa - verify that all the transitions and states in the dfa tables
6978 + *              are in bounds.
6979 + * @dfa: dfa to test
6980 + *
6981 + * assumes dfa has gone through the verification done by unpacking
6982 + */
6983 +int verify_dfa(struct aa_dfa *dfa)
6984 +{
6985 +       size_t i, state_count, trans_count;
6986 +       int error = -EPROTO;
6987 +
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]))
6995 +               goto out;
6996 +
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))
7002 +               goto out;
7003 +
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)
7007 +               goto out;
7008 +
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)
7012 +               goto out;
7013 +
7014 +       for (i = 0; i < state_count; i++) {
7015 +               if (DEFAULT_TABLE(dfa)[i] >= state_count)
7016 +                       goto out;
7017 +               if (BASE_TABLE(dfa)[i] >= trans_count + 256)
7018 +                       goto out;
7019 +       }
7020 +
7021 +       for (i = 0; i < trans_count ; i++) {
7022 +               if (NEXT_TABLE(dfa)[i] >= state_count)
7023 +                       goto out;
7024 +               if (CHECK_TABLE(dfa)[i] >= state_count)
7025 +                       goto out;
7026 +       }
7027 +
7028 +       /* verify accept permissions */
7029 +       for (i = 0; i < state_count; i++) {
7030 +               int mode = ACCEPT_TABLE(dfa)[i];
7031 +
7032 +               if (mode & ~AA_VALID_PERM_MASK)
7033 +                       goto out;
7034 +               if (ACCEPT_TABLE2(dfa)[i] & ~AA_VALID_PERM2_MASK)
7035 +                       goto out;
7036 +
7037 +               /* if any exec modifier is set MAY_EXEC must be set */
7038 +               if ((mode & AA_USER_EXEC_TYPE) && !(mode & AA_USER_EXEC))
7039 +                       goto out;
7040 +               if ((mode & AA_OTHER_EXEC_TYPE) && !(mode & AA_OTHER_EXEC))
7041 +                       goto out;
7042 +       }
7043 +
7044 +       error = 0;
7045 +out:
7046 +       return error;
7047 +}
7048 +
7049 +struct aa_dfa *aa_match_alloc(void)
7050 +{
7051 +       return kzalloc(sizeof(struct aa_dfa), GFP_KERNEL);
7052 +}
7053 +
7054 +void aa_match_free(struct aa_dfa *dfa)
7055 +{
7056 +       if (dfa) {
7057 +               int i;
7058 +
7059 +               for (i = 0; i < ARRAY_SIZE(dfa->tables); i++)
7060 +                       kfree(dfa->tables[i]);
7061 +       }
7062 +       kfree(dfa);
7063 +}
7064 +
7065 +/**
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
7071 + *
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.
7075 + *
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
7079 + * slower.
7080 + */
7081 +unsigned int aa_dfa_next_state_len(struct aa_dfa *dfa, unsigned int start,
7082 +                                  const char *str, int len)
7083 +{
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;
7089 +
7090 +       if (state == 0)
7091 +               return 0;
7092 +
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];
7100 +                       else
7101 +                               state = def[state];
7102 +               }
7103 +       } else {
7104 +               for (; len; len--) {
7105 +                       pos = base[state] + (u8)*str++;
7106 +                       if (check[pos] == state)
7107 +                               state = next[pos];
7108 +                       else
7109 +                               state = def[state];
7110 +               }
7111 +       }
7112 +       return state;
7113 +}
7114 +
7115 +/**
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
7120 + *
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.
7124 + */
7125 +unsigned int aa_dfa_next_state(struct aa_dfa *dfa, unsigned int start,
7126 +                              const char *str)
7127 +{
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;
7133 +
7134 +       if (state == 0)
7135 +               return 0;
7136 +
7137 +       /* current state is <state>, matching character *str */
7138 +       if (dfa->tables[YYTD_ID_EC - 1]) {
7139 +               u8 *equiv = EQUIV_TABLE(dfa);
7140 +               while (*str) {
7141 +                       pos = base[state] + equiv[(u8)*str++];
7142 +                       if (check[pos] == state)
7143 +                               state = next[pos];
7144 +                       else
7145 +                               state = def[state];
7146 +               }
7147 +       } else {
7148 +               while (*str) {
7149 +                       pos = base[state] + (u8)*str++;
7150 +                       if (check[pos] == state)
7151 +                               state = next[pos];
7152 +                       else
7153 +                               state = def[state];
7154 +               }
7155 +       }
7156 +       return state;
7157 +}
7158 +
7159 +/**
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
7163 + *
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.
7167 + */
7168 +unsigned int aa_dfa_null_transition(struct aa_dfa *dfa, unsigned int start)
7169 +{
7170 +       return aa_dfa_next_state_len(dfa, start, "", 1);
7171 +}
7172 +
7173 +/**
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
7178 + *
7179 + * aa_dfa_match will match @str and return the accept perms for the
7180 + * final state.
7181 + */
7182 +unsigned int aa_dfa_match(struct aa_dfa *dfa, const char *str, int *audit_mask)
7183 +{
7184 +       int state = aa_dfa_next_state(dfa, DFA_START, str);
7185 +       if (audit_mask)
7186 +               *audit_mask = dfa_audit_mask(dfa, state);
7187 +       return ACCEPT_TABLE(dfa)[state];
7188 +}
7189 +
7190 +/**
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
7196 + *
7197 + * aa_match_state will match @str and return the accept perms, and @final
7198 + * state, the match occured in.
7199 + */
7200 +unsigned int aa_match_state(struct aa_dfa *dfa, unsigned int start,
7201 +                           const char *str, unsigned int *final)
7202 +{
7203 +       unsigned int state;
7204 +       if (dfa) {
7205 +               state = aa_dfa_next_state(dfa, start, str);
7206 +               if (final)
7207 +                       *final = state;
7208 +               return ACCEPT_TABLE(dfa)[state];
7209 +       }
7210 +       if (final)
7211 +               *final = 0;
7212 +       return 0;
7213 +}
7214 +
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
7218 @@ -0,0 +1,87 @@
7219 +/*
7220 + *     Copyright (C) 2007 Novell/SUSE
7221 + *
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
7225 + *     License.
7226 + *
7227 + *     AppArmor submodule (match) prototypes
7228 + */
7229 +
7230 +#ifndef __MATCH_H
7231 +#define __MATCH_H
7232 +
7233 +#define DFA_START                      1
7234 +
7235 +/**
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).
7242 + */
7243 +
7244 +#define YYTH_MAGIC     0x1B5E783D
7245 +
7246 +struct table_set_header {
7247 +       u32             th_magic;       /* YYTH_MAGIC */
7248 +       u32             th_hsize;
7249 +       u32             th_ssize;
7250 +       u16             th_flags;
7251 +       char            th_version[];
7252 +};
7253 +
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
7262 +
7263 +
7264 +#define YYTD_DATA8     1
7265 +#define YYTD_DATA16    2
7266 +#define YYTD_DATA32    4
7267 +
7268 +struct table_header {
7269 +       u16             td_id;
7270 +       u16             td_flags;
7271 +       u32             td_hilen;
7272 +       u32             td_lolen;
7273 +       char            td_data[];
7274 +};
7275 +
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))
7283 +
7284 +struct aa_dfa {
7285 +       struct table_header *tables[YYTD_ID_NXT];
7286 +};
7287 +
7288 +#define byte_to_byte(X) (X)
7289 +
7290 +#define UNPACK_ARRAY(TABLE, BLOB, LEN, TYPE, NTOHX) \
7291 +       do { \
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]); \
7297 +               } \
7298 +       } while (0)
7299 +
7300 +static inline size_t table_size(size_t len, size_t el_size)
7301 +{
7302 +       return ALIGN(sizeof(struct table_header) + len * el_size, 8);
7303 +}
7304 +
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
7309 @@ -0,0 +1,966 @@
7310 +/*
7311 + *     Copyright (C) 1998-2007 Novell/SUSE
7312 + *
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
7316 + *     License.
7317 + *
7318 + *     AppArmor userspace policy interface
7319 + */
7320 +
7321 +#include <asm/unaligned.h>
7322 +
7323 +#include "apparmor.h"
7324 +#include "inline.h"
7325 +
7326 +/*
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.)
7332 + */
7333 +DEFINE_MUTEX(aa_interface_lock);
7334 +
7335 +/*
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.
7342 + */
7343 +
7344 +enum aa_code {
7345 +       AA_U8,
7346 +       AA_U16,
7347 +       AA_U32,
7348 +       AA_U64,
7349 +       AA_NAME,        /* same as string except it is items name */
7350 +       AA_STRING,
7351 +       AA_BLOB,
7352 +       AA_STRUCT,
7353 +       AA_STRUCTEND,
7354 +       AA_LIST,
7355 +       AA_LISTEND,
7356 +       AA_ARRAY,
7357 +       AA_ARRAYEND,
7358 +};
7359 +
7360 +/*
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.
7364 + */
7365 +struct aa_ext {
7366 +       void *start;
7367 +       void *end;
7368 +       void *pos;      /* pointer to current position in the buffer */
7369 +       u32 version;
7370 +       char *ns_name;
7371 +};
7372 +
7373 +static inline int aa_inbounds(struct aa_ext *e, size_t size)
7374 +{
7375 +       return (size <= e->end - e->pos);
7376 +}
7377 +
7378 +/**
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
7382 + *
7383 + * return the size of chunk found with the read head at the end of
7384 + * the chunk.
7385 + */
7386 +static size_t aa_is_u16_chunk(struct aa_ext *e, char **chunk)
7387 +{
7388 +       void *pos = e->pos;
7389 +       size_t size = 0;
7390 +
7391 +       if (!aa_inbounds(e, sizeof(u16)))
7392 +               goto fail;
7393 +       size = le16_to_cpu(get_unaligned((u16 *)e->pos));
7394 +       e->pos += sizeof(u16);
7395 +       if (!aa_inbounds(e, size))
7396 +               goto fail;
7397 +       *chunk = e->pos;
7398 +       e->pos += size;
7399 +       return size;
7400 +
7401 +fail:
7402 +       e->pos = pos;
7403 +       return 0;
7404 +}
7405 +
7406 +static inline int aa_is_X(struct aa_ext *e, enum aa_code code)
7407 +{
7408 +       if (!aa_inbounds(e, 1))
7409 +               return 0;
7410 +       if (*(u8 *) e->pos != code)
7411 +               return 0;
7412 +       e->pos++;
7413 +       return 1;
7414 +}
7415 +
7416 +/**
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.
7421 + *
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
7429 + */
7430 +static int aa_is_nameX(struct aa_ext *e, enum aa_code code, const char *name)
7431 +{
7432 +       void *pos = e->pos;
7433 +       /*
7434 +        * Check for presence of a tagname, and if present name size
7435 +        * AA_NAME tag value is a u16.
7436 +        */
7437 +       if (aa_is_X(e, AA_NAME)) {
7438 +               char *tag;
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)))
7442 +                       goto fail;
7443 +       } else if (name) {
7444 +               /* if a name is specified and there is no name tag fail */
7445 +               goto fail;
7446 +       }
7447 +
7448 +       /* now check if type code matches */
7449 +       if (aa_is_X(e, code))
7450 +               return 1;
7451 +
7452 +fail:
7453 +       e->pos = pos;
7454 +       return 0;
7455 +}
7456 +
7457 +static int aa_is_u16(struct aa_ext *e, u16 *data, const char *name)
7458 +{
7459 +       void *pos = e->pos;
7460 +       if (aa_is_nameX(e, AA_U16, name)) {
7461 +               if (!aa_inbounds(e, sizeof(u16)))
7462 +                       goto fail;
7463 +               if (data)
7464 +                       *data = le16_to_cpu(get_unaligned((u16 *)e->pos));
7465 +               e->pos += sizeof(u16);
7466 +               return 1;
7467 +       }
7468 +fail:
7469 +       e->pos = pos;
7470 +       return 0;
7471 +}
7472 +
7473 +static int aa_is_u32(struct aa_ext *e, u32 *data, const char *name)
7474 +{
7475 +       void *pos = e->pos;
7476 +       if (aa_is_nameX(e, AA_U32, name)) {
7477 +               if (!aa_inbounds(e, sizeof(u32)))
7478 +                       goto fail;
7479 +               if (data)
7480 +                       *data = le32_to_cpu(get_unaligned((u32 *)e->pos));
7481 +               e->pos += sizeof(u32);
7482 +               return 1;
7483 +       }
7484 +fail:
7485 +       e->pos = pos;
7486 +       return 0;
7487 +}
7488 +
7489 +static int aa_is_u64(struct aa_ext *e, u64 *data, const char *name)
7490 +{
7491 +       void *pos = e->pos;
7492 +       if (aa_is_nameX(e, AA_U64, name)) {
7493 +               if (!aa_inbounds(e, sizeof(u64)))
7494 +                       goto fail;
7495 +               if (data)
7496 +                       *data = le64_to_cpu(get_unaligned((u64 *)e->pos));
7497 +               e->pos += sizeof(u64);
7498 +               return 1;
7499 +       }
7500 +fail:
7501 +       e->pos = pos;
7502 +       return 0;
7503 +}
7504 +
7505 +static size_t aa_is_array(struct aa_ext *e, const char *name)
7506 +{
7507 +       void *pos = e->pos;
7508 +       if (aa_is_nameX(e, AA_ARRAY, name)) {
7509 +               int size;
7510 +               if (!aa_inbounds(e, sizeof(u16)))
7511 +                       goto fail;
7512 +               size = (int) le16_to_cpu(get_unaligned((u16 *)e->pos));
7513 +               e->pos += sizeof(u16);
7514 +               return size;
7515 +       }
7516 +fail:
7517 +       e->pos = pos;
7518 +       return 0;
7519 +}
7520 +
7521 +static size_t aa_is_blob(struct aa_ext *e, char **blob, const char *name)
7522 +{
7523 +       void *pos = e->pos;
7524 +       if (aa_is_nameX(e, AA_BLOB, name)) {
7525 +               u32 size;
7526 +               if (!aa_inbounds(e, sizeof(u32)))
7527 +                       goto fail;
7528 +               size = le32_to_cpu(get_unaligned((u32 *)e->pos));
7529 +               e->pos += sizeof(u32);
7530 +               if (aa_inbounds(e, (size_t) size)) {
7531 +                       * blob = e->pos;
7532 +                       e->pos += size;
7533 +                       return size;
7534 +               }
7535 +       }
7536 +fail:
7537 +       e->pos = pos;
7538 +       return 0;
7539 +}
7540 +
7541 +static int aa_is_dynstring(struct aa_ext *e, char **string, const char *name)
7542 +{
7543 +       char *src_str;
7544 +       size_t size = 0;
7545 +       void *pos = e->pos;
7546 +       *string = NULL;
7547 +       if (aa_is_nameX(e, AA_STRING, name) &&
7548 +           (size = aa_is_u16_chunk(e, &src_str))) {
7549 +               char *str;
7550 +               if (!(str = kmalloc(size, GFP_KERNEL)))
7551 +                       goto fail;
7552 +               memcpy(str, src_str, size);
7553 +               *string = str;
7554 +       }
7555 +
7556 +       return size;
7557 +
7558 +fail:
7559 +       e->pos = pos;
7560 +       return 0;
7561 +}
7562 +
7563 +/**
7564 + * aa_unpack_dfa - unpack a file rule dfa
7565 + * @e: serialized data extent information
7566 + *
7567 + * returns dfa or ERR_PTR
7568 + */
7569 +static struct aa_dfa *aa_unpack_dfa(struct aa_ext *e)
7570 +{
7571 +       char *blob = NULL;
7572 +       size_t size, error = 0;
7573 +       struct aa_dfa *dfa = NULL;
7574 +
7575 +       size = aa_is_blob(e, &blob, "aadfa");
7576 +       if (size) {
7577 +               dfa = aa_match_alloc();
7578 +               if (dfa) {
7579 +                       /*
7580 +                        * The dfa is aligned with in the blob to 8 bytes
7581 +                        * from the beginning of the stream.
7582 +                        */
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);
7586 +                       if (!error)
7587 +                               error = verify_dfa(dfa);
7588 +               } else {
7589 +                       error = -ENOMEM;
7590 +               }
7591 +
7592 +               if (error) {
7593 +                       aa_match_free(dfa);
7594 +                       dfa = ERR_PTR(error);
7595 +               }
7596 +       }
7597 +
7598 +       return dfa;
7599 +}
7600 +
7601 +static int aa_unpack_exec_table(struct aa_ext *e, struct aa_profile *profile)
7602 +{
7603 +       void *pos = e->pos;
7604 +
7605 +       /* exec table is optional */
7606 +       if (aa_is_nameX(e, AA_STRUCT, "xtable")) {
7607 +               int i, size;
7608 +
7609 +               size = aa_is_array(e, NULL);
7610 +               /* currently 4 exec bits and entries 0-3 are reserved iupcx */
7611 +               if (size > 16 - 4)
7612 +                       goto fail;
7613 +               profile->exec_table = kzalloc(sizeof(char *) * size,
7614 +                                             GFP_KERNEL);
7615 +               if (!profile->exec_table)
7616 +                       goto fail;
7617 +
7618 +               for (i = 0; i < size; i++) {
7619 +                   char *tmp;
7620 +                       if (!aa_is_dynstring(e, &tmp, NULL))
7621 +                               goto fail;
7622 +                       /* note: strings beginning with a : have an embedded
7623 +                          \0 seperating the profile ns name from the profile
7624 +                          name */
7625 +                       profile->exec_table[i] = tmp;
7626 +               }
7627 +               if (!aa_is_nameX(e, AA_ARRAYEND, NULL))
7628 +                       goto fail;
7629 +               if (!aa_is_nameX(e, AA_STRUCTEND, NULL))
7630 +                       goto fail;
7631 +       }
7632 +       return 1;
7633 +
7634 +fail:
7635 +       e->pos = pos;
7636 +       return 0;
7637 +}
7638 +
7639 +int aa_unpack_rlimits(struct aa_ext *e, struct aa_profile *profile)
7640 +{
7641 +       void *pos = e->pos;
7642 +
7643 +       /* rlimits are optional */
7644 +       if (aa_is_nameX(e, AA_STRUCT, "rlimits")) {
7645 +               int i, size;
7646 +               u32 tmp = 0;
7647 +               if (!aa_is_u32(e, &tmp, NULL))
7648 +                       goto fail;
7649 +               profile->rlimits.mask = tmp;
7650 +
7651 +               size = aa_is_array(e, NULL);
7652 +               if (size > RLIM_NLIMITS)
7653 +                       goto fail;
7654 +               for (i = 0; i < size; i++) {
7655 +                       u64 tmp = 0;
7656 +                       if (!aa_is_u64(e, &tmp, NULL))
7657 +                               goto fail;
7658 +                       profile->rlimits.limits[i].rlim_max = tmp;
7659 +               }
7660 +               if (!aa_is_nameX(e, AA_ARRAYEND, NULL))
7661 +                       goto fail;
7662 +               if (!aa_is_nameX(e, AA_STRUCTEND, NULL))
7663 +                       goto fail;
7664 +       }
7665 +       return 1;
7666 +
7667 +fail:
7668 +       e->pos = pos;
7669 +       return 0;
7670 +}
7671 +
7672 +/**
7673 + * aa_unpack_profile - unpack a serialized profile
7674 + * @e: serialized data extent information
7675 + * @sa: audit struct for the operation
7676 + */
7677 +static struct aa_profile *aa_unpack_profile(struct aa_ext *e,
7678 +                                           struct aa_audit *sa)
7679 +{
7680 +       struct aa_profile *profile = NULL;
7681 +       size_t size = 0;
7682 +       int i, error = -EPROTO;
7683 +
7684 +       profile = alloc_aa_profile();
7685 +       if (!profile)
7686 +               return ERR_PTR(-ENOMEM);
7687 +
7688 +       /* check that we have the right struct being passed */
7689 +       if (!aa_is_nameX(e, AA_STRUCT, "profile"))
7690 +               goto fail;
7691 +       if (!aa_is_dynstring(e, &profile->name, NULL))
7692 +               goto fail;
7693 +
7694 +       /* per profile debug flags (complain, audit) */
7695 +       if (!aa_is_nameX(e, AA_STRUCT, "flags"))
7696 +               goto fail;
7697 +       if (!aa_is_u32(e, &(profile->flags.hat), NULL))
7698 +               goto fail;
7699 +       if (!aa_is_u32(e, &(profile->flags.complain), NULL))
7700 +               goto fail;
7701 +       if (!aa_is_u32(e, &(profile->flags.audit), NULL))
7702 +               goto fail;
7703 +       if (!aa_is_nameX(e, AA_STRUCTEND, NULL))
7704 +               goto fail;
7705 +
7706 +       if (!aa_is_u32(e, &(profile->capabilities.cap[0]), NULL))
7707 +               goto fail;
7708 +       if (!aa_is_u32(e, &(profile->audit_caps.cap[0]), NULL))
7709 +               goto fail;
7710 +       if (!aa_is_u32(e, &(profile->quiet_caps.cap[0]), NULL))
7711 +               goto fail;
7712 +       if (!aa_is_u32(e, &(profile->set_caps.cap[0]), NULL))
7713 +               goto fail;
7714 +
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))
7718 +                       goto fail;
7719 +               if (!aa_is_u32(e, &(profile->audit_caps.cap[1]), NULL))
7720 +                       goto fail;
7721 +               if (!aa_is_u32(e, &(profile->quiet_caps.cap[1]), NULL))
7722 +                       goto fail;
7723 +               if (!aa_is_u32(e, &(profile->set_caps.cap[1]), NULL))
7724 +                       goto fail;
7725 +               if (!aa_is_nameX(e, AA_STRUCTEND, NULL))
7726 +                       goto fail;
7727 +       }
7728 +
7729 +       if (!aa_unpack_rlimits(e, profile))
7730 +               goto fail;
7731 +
7732 +       size = aa_is_array(e, "net_allowed_af");
7733 +       if (size) {
7734 +               if (size > AF_MAX)
7735 +                       goto fail;
7736 +
7737 +               for (i = 0; i < size; i++) {
7738 +                       if (!aa_is_u16(e, &profile->network_families[i], NULL))
7739 +                               goto fail;
7740 +                       if (!aa_is_u16(e, &profile->audit_network[i], NULL))
7741 +                               goto fail;
7742 +                       if (!aa_is_u16(e, &profile->quiet_network[i], NULL))
7743 +                               goto fail;
7744 +               }
7745 +               if (!aa_is_nameX(e, AA_ARRAYEND, NULL))
7746 +                       goto fail;
7747 +               /* allow unix domain and netlink sockets they are handled
7748 +                * by IPC
7749 +                */
7750 +       }
7751 +       profile->network_families[AF_UNIX] = 0xffff;
7752 +       profile->network_families[AF_NETLINK] = 0xffff;
7753 +
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;
7759 +               goto fail;
7760 +       }
7761 +
7762 +       if (!aa_unpack_exec_table(e, profile))
7763 +               goto fail;
7764 +
7765 +       if (!aa_is_nameX(e, AA_STRUCTEND, NULL))
7766 +               goto fail;
7767 +
7768 +       return profile;
7769 +
7770 +fail:
7771 +       sa->name = profile && profile->name ? profile->name : "unknown";
7772 +       if (!sa->info)
7773 +               sa->info = "failed to unpack profile";
7774 +       aa_audit_status(NULL, sa);
7775 +
7776 +       if (profile)
7777 +               free_aa_profile(profile);
7778 +
7779 +       return ERR_PTR(error);
7780 +}
7781 +
7782 +/**
7783 + * aa_verify_head - unpack serialized stream header
7784 + * @e: serialized data read head
7785 + * @operation: operation header is being verified for
7786 + *
7787 + * returns error or 0 if header is good
7788 + */
7789 +static int aa_verify_header(struct aa_ext *e, struct aa_audit *sa)
7790 +{
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;
7796 +       }
7797 +
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;
7803 +       }
7804 +
7805 +       /* read the namespace if present */
7806 +       if (!aa_is_dynstring(e, &e->ns_name, "namespace")) {
7807 +               e->ns_name = NULL;
7808 +       }
7809 +
7810 +       return 0;
7811 +}
7812 +
7813 +/**
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
7817 + */
7818 +ssize_t aa_add_profile(void *data, size_t size)
7819 +{
7820 +       struct aa_profile *profile = NULL;
7821 +       struct aa_namespace *ns = NULL;
7822 +       struct aa_ext e = {
7823 +               .start = data,
7824 +               .end = data + size,
7825 +               .pos = data,
7826 +               .ns_name = NULL
7827 +       };
7828 +       ssize_t error;
7829 +       struct aa_audit sa;
7830 +       memset(&sa, 0, sizeof(sa));
7831 +       sa.operation = "profile_load";
7832 +       sa.gfp_mask = GFP_KERNEL;
7833 +
7834 +       error = aa_verify_header(&e, &sa);
7835 +       if (error)
7836 +               return error;
7837 +
7838 +       profile = aa_unpack_profile(&e, &sa);
7839 +       if (IS_ERR(profile))
7840 +               return PTR_ERR(profile);
7841 +
7842 +       mutex_lock(&aa_interface_lock);
7843 +       write_lock(&profile_ns_list_lock);
7844 +       if (e.ns_name)
7845 +               ns = __aa_find_namespace(e.ns_name, &profile_ns_list);
7846 +       else
7847 +               ns = default_namespace;
7848 +       if (!ns) {
7849 +               struct aa_namespace *new_ns;
7850 +               write_unlock(&profile_ns_list_lock);
7851 +               new_ns = alloc_aa_namespace(e.ns_name);
7852 +               if (!new_ns) {
7853 +                       mutex_unlock(&aa_interface_lock);
7854 +                       return -ENOMEM;
7855 +               }
7856 +               write_lock(&profile_ns_list_lock);
7857 +               ns = __aa_find_namespace(e.ns_name, &profile_ns_list);
7858 +               if (!ns) {
7859 +                       list_add(&new_ns->list, &profile_ns_list);
7860 +                       ns = new_ns;
7861 +               } else
7862 +                       free_aa_namespace(new_ns);
7863 +       }
7864 +
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);
7876 +               return -EEXIST;
7877 +       }
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);
7883 +
7884 +       sa.name = profile->name;
7885 +       sa.name2 = ns->name;
7886 +       aa_audit_status(NULL, &sa);
7887 +       mutex_unlock(&aa_interface_lock);
7888 +       return size;
7889 +}
7890 +
7891 +/**
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
7896 + */
7897 +static inline void task_replace(struct task_struct *task,
7898 +                               struct aa_task_context *new_cxt,
7899 +                               struct aa_profile *new_profile)
7900 +{
7901 +       struct aa_task_context *cxt = aa_task_context(task);
7902 +
7903 +       AA_DEBUG("%s: replacing profile for task %d "
7904 +                "profile=%s (%p)\n",
7905 +                __FUNCTION__,
7906 +                cxt->task->pid,
7907 +                cxt->profile->name, cxt->profile);
7908 +
7909 +       aa_change_task_context(task, new_cxt, new_profile, cxt->cookie,
7910 +                              cxt->previous_profile);
7911 +}
7912 +
7913 +/**
7914 + * aa_replace_profile - replace a profile on the profile list
7915 + * @udata: serialized data stream
7916 + * @size: size of the serialized data stream
7917 + *
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.
7921 + */
7922 +ssize_t aa_replace_profile(void *udata, size_t size)
7923 +{
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 = {
7928 +               .start = udata,
7929 +               .end = udata + size,
7930 +               .pos = udata,
7931 +               .ns_name = NULL
7932 +       };
7933 +       ssize_t error;
7934 +       struct aa_audit sa;
7935 +       memset(&sa, 0, sizeof(sa));
7936 +       sa.operation = "profile_replace";
7937 +       sa.gfp_mask = GFP_KERNEL;
7938 +
7939 +       error = aa_verify_header(&e, &sa);
7940 +       if (error)
7941 +               return error;
7942 +
7943 +       new_profile = aa_unpack_profile(&e, &sa);
7944 +       if (IS_ERR(new_profile))
7945 +               return PTR_ERR(new_profile);
7946 +
7947 +       mutex_lock(&aa_interface_lock);
7948 +       write_lock(&profile_ns_list_lock);
7949 +       if (e.ns_name)
7950 +               ns = __aa_find_namespace(e.ns_name, &profile_ns_list);
7951 +       else
7952 +               ns = default_namespace;
7953 +       if (!ns) {
7954 +               struct aa_namespace *new_ns;
7955 +               write_unlock(&profile_ns_list_lock);
7956 +               new_ns = alloc_aa_namespace(e.ns_name);
7957 +               if (!new_ns) {
7958 +                       mutex_unlock(&aa_interface_lock);
7959 +                       return -ENOMEM;
7960 +               }
7961 +               write_lock(&profile_ns_list_lock);
7962 +               ns = __aa_find_namespace(e.ns_name, &profile_ns_list);
7963 +               if (!ns) {
7964 +                       list_add(&new_ns->list, &profile_ns_list);
7965 +                       ns = new_ns;
7966 +               } else
7967 +                       free_aa_namespace(new_ns);
7968 +       }
7969 +
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--;
7978 +       }
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);
7986 +
7987 +       if (!old_profile) {
7988 +               sa.operation = "profile_load";
7989 +               goto out;
7990 +       }
7991 +       /* do not fail replacement based off of profile's NPROC rlimit */
7992 +
7993 +       /*
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
8000 +        * that is stale.
8001 +        */
8002 +       do {
8003 +               new_cxt = aa_alloc_task_context(GFP_KERNEL | __GFP_NOFAIL);
8004 +
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;
8010 +                       task_lock(task);
8011 +                       task_replace(task, new_cxt, new_profile);
8012 +                       task_unlock(task);
8013 +                       aa_set_rlimits(task, new_profile);
8014 +                       new_cxt = NULL;
8015 +               }
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);
8020 +
8021 +out:
8022 +       sa.name = new_profile->name;
8023 +       sa.name2 = ns->name;
8024 +       aa_audit_status(NULL, &sa);
8025 +       mutex_unlock(&aa_interface_lock);
8026 +       return size;
8027 +}
8028 +
8029 +/**
8030 + * aa_remove_profile - remove a profile from the system
8031 + * @name: name of the profile to remove
8032 + * @size: size of the name
8033 + *
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
8037 + */
8038 +ssize_t aa_remove_profile(char *name, size_t size)
8039 +{
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;
8046 +
8047 +       mutex_lock(&aa_interface_lock);
8048 +       write_lock(&profile_ns_list_lock);
8049 +
8050 +       if (name[0] == ':') {
8051 +               char *split = strchr(name + 1, ':');
8052 +               if (!split)
8053 +                       goto noent;
8054 +               *split = 0;
8055 +               ns = __aa_find_namespace(name + 1, &profile_ns_list);
8056 +               name = split + 1;
8057 +       } else {
8058 +               ns = default_namespace;
8059 +       }
8060 +
8061 +       if (!ns)
8062 +               goto noent;
8063 +       sa.name2 = ns->name;
8064 +       write_lock(&ns->lock);
8065 +       profile = __aa_find_profile(name, &ns->profiles);
8066 +       if (!profile) {
8067 +               write_unlock(&ns->lock);
8068 +               goto noent;
8069 +       }
8070 +       sa.name = profile->name;
8071 +
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);
8085 +       }
8086 +       write_unlock(&profile_ns_list_lock);
8087 +
8088 +       aa_audit_status(NULL, &sa);
8089 +       mutex_unlock(&aa_interface_lock);
8090 +       aa_put_profile(profile);
8091 +
8092 +       return size;
8093 +
8094 +noent:
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);
8099 +       return -ENOENT;
8100 +}
8101 +
8102 +/**
8103 + * free_aa_namespace_kref - free aa_namespace by kref (see aa_put_namespace)
8104 + * @kr: kref callback for freeing of a namespace
8105 + */
8106 +void free_aa_namespace_kref(struct kref *kref)
8107 +{
8108 +       struct aa_namespace *ns=container_of(kref, struct aa_namespace, count);
8109 +
8110 +       free_aa_namespace(ns);
8111 +}
8112 +
8113 +/**
8114 + * alloc_aa_namespace - allocate, initialize and return a new namespace
8115 + * @name: a preallocated name
8116 + * Returns NULL on failure.
8117 + */
8118 +struct aa_namespace *alloc_aa_namespace(char *name)
8119 +{
8120 +       struct aa_namespace *ns;
8121 +
8122 +       ns = kzalloc(sizeof(*ns), GFP_KERNEL);
8123 +       AA_DEBUG("%s(%p)\n", __FUNCTION__, ns);
8124 +       if (ns) {
8125 +               ns->name = name;
8126 +               INIT_LIST_HEAD(&ns->list);
8127 +               INIT_LIST_HEAD(&ns->profiles);
8128 +               kref_init(&ns->count);
8129 +               rwlock_init(&ns->lock);
8130 +
8131 +               ns->null_complain_profile = alloc_aa_profile();
8132 +               if (!ns->null_complain_profile) {
8133 +                       if (!name)
8134 +                               kfree(ns->name);
8135 +                       kfree(ns);
8136 +                       return NULL;
8137 +               }
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);
8142 +                       if (!name)
8143 +                               kfree(ns->name);
8144 +                       kfree(ns);
8145 +                       return NULL;
8146 +               }
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;
8150 +       }
8151 +       return ns;
8152 +}
8153 +
8154 +/**
8155 + * free_aa_namespace - free a profile namespace
8156 + * @namespace: the namespace to free
8157 + *
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.
8162 + */
8163 +void free_aa_namespace(struct aa_namespace *ns)
8164 +{
8165 +       AA_DEBUG("%s(%p)\n", __FUNCTION__, ns);
8166 +
8167 +       if (!ns)
8168 +               return;
8169 +
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",
8174 +                        __FUNCTION__,
8175 +                        ns->name);
8176 +               BUG();
8177 +       }
8178 +       if (!list_empty(&ns->list)) {
8179 +               AA_ERROR("%s: internal error, "
8180 +                        "namespace '%s' still on list\n",
8181 +                        __FUNCTION__,
8182 +                        ns->name);
8183 +               BUG();
8184 +       }
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);
8188 +       kfree(ns->name);
8189 +       kfree(ns);
8190 +}
8191 +
8192 +/**
8193 + * free_aa_profile_kref - free aa_profile by kref (called by aa_put_profile)
8194 + * @kr: kref callback for freeing of a profile
8195 + */
8196 +void free_aa_profile_kref(struct kref *kref)
8197 +{
8198 +       struct aa_profile *p=container_of(kref, struct aa_profile, count);
8199 +
8200 +       free_aa_profile(p);
8201 +}
8202 +
8203 +/**
8204 + * alloc_aa_profile - allocate, initialize and return a new profile
8205 + * Returns NULL on failure.
8206 + */
8207 +struct aa_profile *alloc_aa_profile(void)
8208 +{
8209 +       struct aa_profile *profile;
8210 +
8211 +       profile = kzalloc(sizeof(*profile), GFP_KERNEL);
8212 +       AA_DEBUG("%s(%p)\n", __FUNCTION__, profile);
8213 +       if (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);
8218 +       }
8219 +       return profile;
8220 +}
8221 +
8222 +/**
8223 + * free_aa_profile - free a profile
8224 + * @profile: the profile to free
8225 + *
8226 + * Free a profile, its hats and null_profile. All references to the profile,
8227 + * its hats and null_profile must have been put.
8228 + *
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.
8231 + */
8232 +void free_aa_profile(struct aa_profile *profile)
8233 +{
8234 +       AA_DEBUG("%s(%p)\n", __FUNCTION__, profile);
8235 +
8236 +       if (!profile)
8237 +               return;
8238 +
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",
8243 +                        __FUNCTION__,
8244 +                        profile->name);
8245 +               BUG();
8246 +       }
8247 +       aa_put_namespace(profile->ns);
8248 +
8249 +       aa_match_free(profile->file_rules);
8250 +
8251 +       if (profile->name) {
8252 +               AA_DEBUG("%s: %s\n", __FUNCTION__, profile->name);
8253 +               kfree(profile->name);
8254 +       }
8255 +
8256 +       kfree(profile);
8257 +}
8258 +
8259 +/**
8260 + * aa_unconfine_tasks - remove tasks on a profile's task context list
8261 + * @profile: profile to remove tasks from
8262 + *
8263 + * Assumes that @profile lock is held.
8264 + */
8265 +void aa_unconfine_tasks(struct aa_profile *profile)
8266 +{
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;
8271 +               task_lock(task);
8272 +               aa_change_task_context(task, NULL, NULL, 0, NULL);
8273 +               task_unlock(task);
8274 +       }
8275 +}
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
8279 @@ -0,0 +1,195 @@
8280 +/*
8281 + *     Copyright (C) 1998-2007 Novell/SUSE
8282 + *
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
8286 + *     License.
8287 + *
8288 + *     AppArmor /proc/pid/attr handling
8289 + */
8290 +
8291 +#include "apparmor.h"
8292 +#include "inline.h"
8293 +
8294 +int aa_getprocattr(struct aa_profile *profile, char **string, unsigned *len)
8295 +{
8296 +       char *str;
8297 +
8298 +       if (profile) {
8299 +               const char *mode_str = PROFILE_COMPLAIN(profile) ?
8300 +                       " (complain)" : " (enforce)";
8301 +               int mode_len, name_len, ns_len = 0;
8302 +
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);
8309 +               if (!str)
8310 +                       return -ENOMEM;
8311 +
8312 +               if (ns_len) {
8313 +                       *str++ = ':';
8314 +                       memcpy(str, profile->ns->name, ns_len - 2);
8315 +                       str += ns_len - 2;
8316 +                       *str++ = ':';
8317 +               }
8318 +               memcpy(str, profile->name, name_len);
8319 +               str += name_len;
8320 +               memcpy(str, mode_str, mode_len);
8321 +               str += mode_len;
8322 +               *str++ = '\n';
8323 +               str -= *len;
8324 +       } else {
8325 +               const char *unconfined_str = "unconfined\n";
8326 +
8327 +               *len = strlen(unconfined_str);
8328 +               str = kmalloc(*len, GFP_ATOMIC);
8329 +               if (!str)
8330 +                       return -ENOMEM;
8331 +
8332 +               memcpy(str, unconfined_str, *len);
8333 +       }
8334 +       *string = str;
8335 +
8336 +       return 0;
8337 +}
8338 +
8339 +static char *split_token_from_name(const char *op, char *args, u64 *cookie)
8340 +{
8341 +       char *name;
8342 +
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);
8347 +       }
8348 +
8349 +       name++;  /* skip ^ */
8350 +       if (!*name)
8351 +               name = NULL;
8352 +       return name;
8353 +}
8354 +
8355 +int aa_setprocattr_changehat(char *args)
8356 +{
8357 +       char *hat;
8358 +       u64 cookie;
8359 +
8360 +       hat = split_token_from_name("change_hat", args, &cookie);
8361 +       if (IS_ERR(hat))
8362 +               return PTR_ERR(hat);
8363 +
8364 +       if (!hat && !cookie) {
8365 +               AA_ERROR("change_hat: Invalid input, NULL hat and NULL magic");
8366 +               return -EINVAL;
8367 +       }
8368 +
8369 +       AA_DEBUG("%s: Magic 0x%llx Hat '%s'\n",
8370 +                __FUNCTION__, cookie, hat ? hat : NULL);
8371 +
8372 +       return aa_change_hat(hat, cookie);
8373 +}
8374 +
8375 +int aa_setprocattr_changeprofile(char *args)
8376 +{
8377 +       char *name = args, *ns_name = NULL;
8378 +
8379 +       if (name[0] == ':') {
8380 +               char *split = strchr(&name[1], ':');
8381 +               if (split) {
8382 +                       *split = 0;
8383 +                       ns_name = &name[1];
8384 +                       name = split + 1;
8385 +               }
8386 +       }
8387 +
8388 +       return aa_change_profile(ns_name, name);
8389 +}
8390 +
8391 +int aa_setprocattr_setprofile(struct task_struct *task, char *args)
8392 +{
8393 +       struct aa_profile *old_profile, *new_profile;
8394 +       struct aa_namespace *ns;
8395 +       struct aa_audit sa;
8396 +       char *name, *ns_name = NULL;
8397 +
8398 +       memset(&sa, 0, sizeof(sa));
8399 +       sa.operation = "profile_set";
8400 +       sa.gfp_mask = GFP_KERNEL;
8401 +       sa.task = task->pid;
8402 +
8403 +       AA_DEBUG("%s: current %d\n",
8404 +                __FUNCTION__, current->pid);
8405 +
8406 +       name = args;
8407 +       if (args[0] != '/') {
8408 +               char *split = strchr(args, ':');
8409 +               if (split) {
8410 +                       *split = 0;
8411 +                       ns_name = args;
8412 +                       name = split + 1;
8413 +               }
8414 +       }
8415 +       if (ns_name)
8416 +               ns = aa_find_namespace(ns_name);
8417 +       else
8418 +               ns = aa_get_namespace(default_namespace);
8419 +       if (!ns) {
8420 +               sa.name = ns_name;
8421 +               sa.info = "unknown namespace";
8422 +               aa_audit_reject(NULL, &sa);
8423 +               aa_put_namespace(ns);
8424 +               return -EINVAL;
8425 +       }
8426 +
8427 +repeat:
8428 +       if (strcmp(name, "unconfined") == 0)
8429 +               new_profile = NULL;
8430 +       else {
8431 +               new_profile = aa_find_profile(ns, name);
8432 +               if (!new_profile) {
8433 +                       sa.name = ns_name;
8434 +                       sa.name2 = name;
8435 +                       sa.info = "unknown profile";
8436 +                       aa_audit_reject(NULL, &sa);
8437 +                       aa_put_namespace(ns);
8438 +                       return -EINVAL;
8439 +               }
8440 +       }
8441 +
8442 +       old_profile = __aa_replace_profile(task, new_profile);
8443 +       if (IS_ERR(old_profile)) {
8444 +               int error;
8445 +
8446 +               aa_put_profile(new_profile);
8447 +               error = PTR_ERR(old_profile);
8448 +               if (error == -ESTALE)
8449 +                       goto repeat;
8450 +               aa_put_namespace(ns);
8451 +               return error;
8452 +       }
8453 +
8454 +       if (new_profile) {
8455 +               sa.name = ns_name;
8456 +               sa.name2 = name;
8457 +               sa.name3 = old_profile ? old_profile->name :
8458 +                       "unconfined";
8459 +               aa_audit_status(NULL, &sa);
8460 +       } else {
8461 +               if (old_profile) {
8462 +                       sa.name = "unconfined";
8463 +                       sa.name2 = old_profile->name;
8464 +                       aa_audit_status(NULL, &sa);
8465 +               } else {
8466 +                       sa.info = "task is unconfined";
8467 +                       aa_audit_status(NULL, &sa);
8468 +               }
8469 +       }
8470 +       aa_put_namespace(ns);
8471 +       aa_put_profile(old_profile);
8472 +       aa_put_profile(new_profile);
8473 +       return 0;
8474 +}
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);
8480  }
8481  
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)
8486  {
8487         if (!strcmp(name, XATTR_NAME_CAPS)) {
8488                 if (!capable(CAP_SETFCAP))
8489 @@ -400,7 +400,8 @@ int cap_inode_setxattr(struct dentry *de
8490         return 0;
8491  }
8492  
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)
8496  {
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
8503  }
8504  
8505  static int dummy_inode_create (struct inode *inode, struct dentry *dentry,
8506 -                              int mask)
8507 +                              struct vfsmount *mnt, int mask)
8508  {
8509         return 0;
8510  }
8511  
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)
8518  {
8519         return 0;
8520  }
8521  
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)
8525  {
8526         return 0;
8527  }
8528  
8529  static int dummy_inode_symlink (struct inode *inode, struct dentry *dentry,
8530 -                               const char *name)
8531 +                               struct vfsmount *mnt, const char *name)
8532  {
8533         return 0;
8534  }
8535  
8536  static int dummy_inode_mkdir (struct inode *inode, struct dentry *dentry,
8537 -                             int mask)
8538 +                             struct vfsmount *mnt, int mask)
8539  {
8540         return 0;
8541  }
8542  
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)
8546  {
8547         return 0;
8548  }
8549  
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)
8553  {
8554         return 0;
8555  }
8556  
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)
8564  {
8565         return 0;
8566  }
8567  
8568 -static int dummy_inode_readlink (struct dentry *dentry)
8569 +static int dummy_inode_readlink (struct dentry *dentry, struct vfsmount *mnt)
8570  {
8571         return 0;
8572  }
8573 @@ -350,7 +356,8 @@ static int dummy_inode_permission (struc
8574         return 0;
8575  }
8576  
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)
8580  {
8581         return 0;
8582  }
8583 @@ -365,8 +372,9 @@ static void dummy_inode_delete (struct i
8584         return;
8585  }
8586  
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)
8592  {
8593         if (!strncmp(name, XATTR_SECURITY_PREFIX,
8594                      sizeof(XATTR_SECURITY_PREFIX) - 1) &&
8595 @@ -375,22 +383,28 @@ static int dummy_inode_setxattr (struct 
8596         return 0;
8597  }
8598  
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)
8604  {
8605  }
8606  
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)
8611  {
8612         return 0;
8613  }
8614  
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)
8618  {
8619         return 0;
8620  }
8621  
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)
8625  {
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 
8632  }
8633  EXPORT_SYMBOL(security_inode_init_security);
8634  
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)
8638  {
8639         if (unlikely(IS_PRIVATE(dir)))
8640                 return 0;
8641 -       return security_ops->inode_create(dir, dentry, mode);
8642 +       return security_ops->inode_create(dir, dentry, mnt, mode);
8643  }
8644  
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)
8650  {
8651         if (unlikely(IS_PRIVATE(old_dentry->d_inode)))
8652                 return 0;
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);
8656  }
8657  
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)
8661  {
8662         if (unlikely(IS_PRIVATE(dentry->d_inode)))
8663                 return 0;
8664 -       return security_ops->inode_unlink(dir, dentry);
8665 +       return security_ops->inode_unlink(dir, dentry, mnt);
8666  }
8667  
8668  int security_inode_symlink(struct inode *dir, struct dentry *dentry,
8669 -                           const char *old_name)
8670 +                          struct vfsmount *mnt, const char *old_name)
8671  {
8672         if (unlikely(IS_PRIVATE(dir)))
8673                 return 0;
8674 -       return security_ops->inode_symlink(dir, dentry, old_name);
8675 +       return security_ops->inode_symlink(dir, dentry, mnt, old_name);
8676  }
8677  
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)
8681  {
8682         if (unlikely(IS_PRIVATE(dir)))
8683                 return 0;
8684 -       return security_ops->inode_mkdir(dir, dentry, mode);
8685 +       return security_ops->inode_mkdir(dir, dentry, mnt, mode);
8686  }
8687  
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)
8691  {
8692         if (unlikely(IS_PRIVATE(dentry->d_inode)))
8693                 return 0;
8694 -       return security_ops->inode_rmdir(dir, dentry);
8695 +       return security_ops->inode_rmdir(dir, dentry, mnt);
8696  }
8697  
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)
8701  {
8702         if (unlikely(IS_PRIVATE(dir)))
8703                 return 0;
8704 -       return security_ops->inode_mknod(dir, dentry, mode, dev);
8705 +       return security_ops->inode_mknod(dir, dentry, mnt, mode, dev);
8706  }
8707  
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)
8712  {
8713          if (unlikely(IS_PRIVATE(old_dentry->d_inode) ||
8714              (new_dentry->d_inode && IS_PRIVATE(new_dentry->d_inode))))
8715                 return 0;
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);
8720  }
8721  
8722 -int security_inode_readlink(struct dentry *dentry)
8723 +int security_inode_readlink(struct dentry *dentry, struct vfsmount *mnt)
8724  {
8725         if (unlikely(IS_PRIVATE(dentry->d_inode)))
8726                 return 0;
8727 -       return security_ops->inode_readlink(dentry);
8728 +       return security_ops->inode_readlink(dentry, mnt);
8729  }
8730  
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);
8734  }
8735  
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)
8739  {
8740         if (unlikely(IS_PRIVATE(dentry->d_inode)))
8741                 return 0;
8742 -       return security_ops->inode_setattr(dentry, attr);
8743 +       return security_ops->inode_setattr(dentry, mnt, attr);
8744  }
8745  
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);
8749  }
8750  
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)
8756  {
8757         if (unlikely(IS_PRIVATE(dentry->d_inode)))
8758                 return 0;
8759 -       return security_ops->inode_setxattr(dentry, name, value, size, flags);
8760 +       return security_ops->inode_setxattr(dentry, mnt, name, value, size,
8761 +                                           flags, file);
8762  }
8763  
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,
8768 +                                 int flags)
8769  {
8770         if (unlikely(IS_PRIVATE(dentry->d_inode)))
8771                 return;
8772 -       security_ops->inode_post_setxattr(dentry, name, value, size, flags);
8773 +       security_ops->inode_post_setxattr(dentry, mnt, name, value, size,
8774 +                                        flags);
8775  }
8776  
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)
8780  {
8781         if (unlikely(IS_PRIVATE(dentry->d_inode)))
8782                 return 0;
8783 -       return security_ops->inode_getxattr(dentry, name);
8784 +       return security_ops->inode_getxattr(dentry, mnt, name, file);
8785  }
8786  
8787 -int security_inode_listxattr(struct dentry *dentry)
8788 +int security_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt,
8789 +                            struct file *file)
8790  {
8791         if (unlikely(IS_PRIVATE(dentry->d_inode)))
8792                 return 0;
8793 -       return security_ops->inode_listxattr(dentry);
8794 +       return security_ops->inode_listxattr(dentry, mnt, file);
8795  }
8796  
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)
8800  {
8801         if (unlikely(IS_PRIVATE(dentry->d_inode)))
8802                 return 0;
8803 -       return security_ops->inode_removexattr(dentry, name);
8804 +       return security_ops->inode_removexattr(dentry, mnt, name, file);
8805  }
8806  
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
8812  
8813  static int selinux_sysctl_get_sid(ctl_table *table, u16 tclass, u32 *sid)
8814  {
8815 -       int buflen, rc;
8816 -       char *buffer, *path, *end;
8817 +       char *buffer, *path;
8818 +       int rc = -ENOMEM;
8819  
8820 -       rc = -ENOMEM;
8821         buffer = (char*)__get_free_page(GFP_KERNEL);
8822         if (!buffer)
8823                 goto out;
8824 -
8825 -       buflen = PAGE_SIZE;
8826 -       end = buffer+buflen;
8827 -       *--end = '\0';
8828 -       buflen--;
8829 -       path = end-1;
8830 -       *path = '/';
8831 -       while (table) {
8832 -               const char *name = table->procname;
8833 -               size_t namelen = strlen(name);
8834 -               buflen -= namelen + 1;
8835 -               if (buflen < 0)
8836 -                       goto out_free;
8837 -               end -= namelen;
8838 -               memcpy(end, name, namelen);
8839 -               *--end = '/';
8840 -               path = end;
8841 -               table = table->parent;
8842 -       }
8843 -       buflen -= 4;
8844 -       if (buflen < 0)
8845 -               goto out_free;
8846 -       end -= 4;
8847 -       memcpy(end, "/sys", 4);
8848 -       path = end;
8849 -       rc = security_genfs_sid("proc", path, tclass, sid);
8850 -out_free:
8851 +       path = sysctl_pathname(table, buffer, PAGE_SIZE);
8852 +       if (path)
8853 +               rc = security_genfs_sid("proc", path, tclass, sid);
8854         free_page((unsigned long)buffer);
8855  out:
8856         return rc;
8857 @@ -2458,64 +2433,79 @@ static int selinux_inode_init_security(s
8858         return 0;
8859  }
8860  
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)
8864  {
8865         return may_create(dir, dentry, SECCLASS_FILE);
8866  }
8867  
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)
8874  {
8875         int rc;
8876  
8877 -       rc = secondary_ops->inode_link(old_dentry,dir,new_dentry);
8878 +       rc = secondary_ops->inode_link(old_dentry, old_mnt, dir, new_dentry,
8879 +                                      new_mnt);
8880         if (rc)
8881                 return rc;
8882         return may_link(dir, old_dentry, MAY_LINK);
8883  }
8884  
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)
8888  {
8889         int rc;
8890  
8891 -       rc = secondary_ops->inode_unlink(dir, dentry);
8892 +       rc = secondary_ops->inode_unlink(dir, dentry, mnt);
8893         if (rc)
8894                 return rc;
8895         return may_link(dir, dentry, MAY_UNLINK);
8896  }
8897  
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)
8901  {
8902         return may_create(dir, dentry, SECCLASS_LNK_FILE);
8903  }
8904  
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)
8908  {
8909         return may_create(dir, dentry, SECCLASS_DIR);
8910  }
8911  
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)
8915  {
8916         return may_link(dir, dentry, MAY_RMDIR);
8917  }
8918  
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)
8922  {
8923         int rc;
8924  
8925 -       rc = secondary_ops->inode_mknod(dir, dentry, mode, dev);
8926 +       rc = secondary_ops->inode_mknod(dir, dentry, mnt, mode, dev);
8927         if (rc)
8928                 return rc;
8929  
8930         return may_create(dir, dentry, inode_mode_to_security_class(mode));
8931  }
8932  
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)
8941  {
8942         return may_rename(old_inode, old_dentry, new_inode, new_dentry);
8943  }
8944  
8945 -static int selinux_inode_readlink(struct dentry *dentry)
8946 +static int selinux_inode_readlink(struct dentry *dentry, struct vfsmount *mnt)
8947  {
8948         return dentry_has_perm(current, NULL, dentry, FILE__READ);
8949  }
8950 @@ -2548,11 +2538,12 @@ static int selinux_inode_permission(stru
8951                                file_mask_to_av(inode->i_mode, mask), NULL);
8952  }
8953  
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)
8957  {
8958         int rc;
8959  
8960 -       rc = secondary_ops->inode_setattr(dentry, iattr);
8961 +       rc = secondary_ops->inode_setattr(dentry, mnt, iattr);
8962         if (rc)
8963                 return rc;
8964  
8965 @@ -2590,7 +2581,9 @@ static int selinux_inode_setotherxattr(s
8966         return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
8967  }
8968  
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)
8973  {
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
8977                             &ad);
8978  }
8979  
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,
8983 +                                       char *name,
8984                                          void *value, size_t size, int flags)
8985  {
8986         struct inode *inode = dentry->d_inode;
8987 @@ -2663,17 +2658,21 @@ static void selinux_inode_post_setxattr(
8988         return;
8989  }
8990  
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)
8994  {
8995         return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
8996  }
8997  
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)
9001  {
9002         return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
9003  }
9004  
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)
9009  {
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;
9024  
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 @@
9028                 goto out_redo;
9029  
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);
9034  
9035  out_redo:
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
9038 @@ -16,6 +16,7 @@
9039  #ifdef  __KERNEL__
9040  
9041  #include <linux/types.h>
9042 +#include <linux/fs.h>
9043  
9044  /* Namespaces */
9045  #define XATTR_OS2_PREFIX "os2."
This page took 2.626315 seconds and 3 git commands to generate.