]> git.pld-linux.org Git - packages/kernel.git/blob - kernel-apparmor-after-grsec_full.patch
- update SECURITY_DEFAULT_MMAP_MIN_ADDR to match upstream settings
[packages/kernel.git] / kernel-apparmor-after-grsec_full.patch
1 diff -uprN linux-2.6.27./fs/afs/dir.c linux-2.6.27/fs/afs/dir.c
2 --- linux-2.6.27./fs/afs/dir.c  2008-10-10 00:13:53.000000000 +0200
3 +++ linux-2.6.27/fs/afs/dir.c   2008-10-29 02:02:01.686215981 +0100
4 @@ -45,6 +45,7 @@ const struct file_operations afs_dir_fil
5         .release        = afs_release,
6         .readdir        = afs_readdir,
7         .lock           = afs_lock,
8 +       .fsetattr       = afs_fsetattr,
9  };
10  
11  const struct inode_operations afs_dir_inode_operations = {
12 diff -uprN linux-2.6.27./fs/afs/file.c linux-2.6.27/fs/afs/file.c
13 --- linux-2.6.27./fs/afs/file.c 2008-10-10 00:13:53.000000000 +0200
14 +++ linux-2.6.27/fs/afs/file.c  2008-10-29 02:02:01.718012026 +0100
15 @@ -36,6 +36,7 @@ const struct file_operations afs_file_op
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 linux-2.6.27./fs/afs/inode.c linux-2.6.27/fs/afs/inode.c
24 --- linux-2.6.27./fs/afs/inode.c        2008-10-10 00:13:53.000000000 +0200
25 +++ linux-2.6.27/fs/afs/inode.c 2008-10-29 02:02:01.732673766 +0100
26 @@ -358,7 +358,8 @@ void afs_clear_inode(struct inode *inode
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 linux-2.6.27./fs/afs/internal.h linux-2.6.27/fs/afs/internal.h
70 --- linux-2.6.27./fs/afs/internal.h     2008-10-10 00:13:53.000000000 +0200
71 +++ linux-2.6.27/fs/afs/internal.h      2008-10-29 02:02:01.752698408 +0100
72 @@ -548,6 +548,7 @@ extern void afs_zap_data(struct afs_vnod
73  extern int afs_validate(struct afs_vnode *, struct key *);
74  extern int afs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
75  extern int afs_setattr(struct dentry *, struct iattr *);
76 +extern int afs_fsetattr(struct file *, struct iattr *);
77  extern void afs_clear_inode(struct inode *);
78  
79  /*
80 diff -uprN linux-2.6.27./fs/attr.c linux-2.6.27/fs/attr.c
81 --- linux-2.6.27./fs/attr.c     2008-10-10 00:13:53.000000000 +0200
82 +++ linux-2.6.27/fs/attr.c      2008-10-29 02:02:01.899339282 +0100
83 @@ -100,7 +100,8 @@ int inode_setattr(struct inode * inode, 
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 @@ -163,13 +164,28 @@ 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 +                               /* External file system still expect to be
106 +                                * passed a file pointer via ia_file and
107 +                                * have it announced via ATTR_FILE. This
108 +                                * just makes it so they don't need to
109 +                                * change their API just for us. External
110 +                                * callers will have set these themselves. */
111 +                               if (file) {
112 +                                       attr->ia_valid |= ATTR_FILE;
113 +                                       attr->ia_file = file;
114 +                               }
115 +                               error = inode->i_op->setattr(dentry, attr);
116 +                       }
117 +               }
118         } else {
119                 error = inode_change_ok(inode, attr);
120                 if (!error)
121 -                       error = security_inode_setattr(dentry, attr);
122 +                       error = security_inode_setattr(dentry, mnt, attr);
123                 if (!error) {
124                         if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) ||
125                             (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid))
126 @@ -187,5 +203,12 @@ int notify_change(struct dentry * dentry
127  
128         return error;
129  }
130 +EXPORT_SYMBOL_GPL(fnotify_change);
131 +
132 +int notify_change(struct dentry *dentry, struct vfsmount *mnt,
133 +                 struct iattr *attr)
134 +{
135 +       return fnotify_change(dentry, mnt, attr, NULL);
136 +}
137  
138  EXPORT_SYMBOL(notify_change);
139 diff -uprN linux-2.6.27./fs/dcache.c linux-2.6.27/fs/dcache.c
140 --- linux-2.6.27./fs/dcache.c   2008-10-10 00:13:53.000000000 +0200
141 +++ linux-2.6.27/fs/dcache.c    2008-10-29 02:02:01.602672110 +0100
142 @@ -1897,44 +1897,46 @@ static int prepend_name(char **buffer, i
143   * @root: root vfsmnt/dentry (may be modified by this function)
144   * @buffer: buffer to return value in
145   * @buflen: buffer length
146 + * @flags: flags controling behavior of d_path
147   *
148 - * Convert a dentry into an ASCII path name. If the entry has been deleted
149 - * the string " (deleted)" is appended. Note that this is ambiguous.
150 - *
151 - * Returns the buffer or an error code if the path was too long.
152 - *
153 - * "buflen" should be positive. Caller holds the dcache_lock.
154 + * Convert a dentry into an ASCII path name. If the entry has been deleted,
155 + * then if @flags has D_PATH_FAIL_DELETED set, ERR_PTR(-ENOENT) is returned.
156 + * Otherwise, the string " (deleted)" is appended. Note that this is ambiguous.
157   *
158   * If path is not reachable from the supplied root, then the value of
159 - * root is changed (without modifying refcounts).
160 + * root is changed (without modifying refcounts).  The path returned in this
161 + * case will be relative (i.e., it will not start with a slash).
162 + *
163 + * Returns the buffer or an error code if the path was too long.
164   */
165  char *__d_path(const struct path *path, struct path *root,
166 -              char *buffer, int buflen)
167 +              char *buffer, int buflen, int flags)
168  {
169         struct dentry *dentry = path->dentry;
170         struct vfsmount *vfsmnt = path->mnt;
171 -       char *end = buffer + buflen;
172 -       char *retval;
173 +       const unsigned char *name;
174 +       int namelen;
175 +
176 +       buffer += buflen;
177 +       prepend(&buffer, &buflen, "\0", 1);
178  
179         spin_lock(&vfsmount_lock);
180 -       prepend(&end, &buflen, "\0", 1);
181 -       if (!IS_ROOT(dentry) && d_unhashed(dentry) &&
182 -               (prepend(&end, &buflen, " (deleted)", 10) != 0))
183 +       spin_lock(&dcache_lock);
184 +       if (!IS_ROOT(dentry) && d_unhashed(dentry)) {
185 +               if (flags & D_PATH_FAIL_DELETED) {
186 +                       buffer = ERR_PTR(-ENOENT);
187 +                       goto out;
188 +               }
189 +               if (prepend(&buffer, &buflen, " (deleted)", 10) != 0)
190                         goto Elong;
191 -
192 +       }
193         if (buflen < 1)
194                 goto Elong;
195 -       /* Get '/' right */
196 -       retval = end-1;
197 -       *retval = '/';
198  
199 -       for (;;) {
200 +       while (dentry != root->dentry || vfsmnt != root->mnt) {
201                 struct dentry * parent;
202  
203 -               if (dentry == root->dentry && vfsmnt == root->mnt)
204 -                       break;
205                 if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
206 -                       /* Global root? */
207                         if (vfsmnt->mnt_parent == vfsmnt) {
208                                 goto global_root;
209                         }
210 @@ -1944,27 +1946,51 @@ char *__d_path(const struct path *path, 
211                 }
212                 parent = dentry->d_parent;
213                 prefetch(parent);
214 -               if ((prepend_name(&end, &buflen, &dentry->d_name) != 0) ||
215 -                   (prepend(&end, &buflen, "/", 1) != 0))
216 +               if ((prepend_name(&buffer, &buflen, &dentry->d_name) != 0) ||
217 +                   (prepend(&buffer, &buflen, "/", 1) != 0))
218                         goto Elong;
219 -               retval = end;
220                 dentry = parent;
221         }
222 +       /* Get '/' right. */
223 +       if (*buffer != '/' && prepend(&buffer, &buflen, "/", 1))
224 +               goto Elong;
225  
226  out:
227 +       spin_unlock(&dcache_lock);
228         spin_unlock(&vfsmount_lock);
229 -       return retval;
230 +       return buffer;
231  
232  global_root:
233 -       retval += 1;    /* hit the slash */
234 -       if (prepend_name(&retval, &buflen, &dentry->d_name) != 0)
235 +       /*
236 +        * We went past the (vfsmount, dentry) we were looking for and have
237 +        * either hit a root dentry, a lazily unmounted dentry, an
238 +        * unconnected dentry, or the file is on a pseudo filesystem.
239 +        */
240 +        namelen = dentry->d_name.len;
241 +       name = dentry->d_name.name;
242 +
243 +       /*
244 +        * If this is a root dentry, then overwrite the slash.  This
245 +        * will also DTRT with pseudo filesystems which have root
246 +        * dentries named "foo:".
247 +        */
248 +       if (IS_ROOT(dentry) && *buffer == '/') {
249 +               buffer++;
250 +               buflen++;
251 +       }
252 +       if ((flags & D_PATH_DISCONNECT) && *name == '/') {
253 +               /* Make sure we won't return a pathname starting with '/' */
254 +               name++;
255 +               namelen--;
256 +       }
257 +       if (prepend(&buffer, &buflen, name, namelen))
258                 goto Elong;
259         root->mnt = vfsmnt;
260         root->dentry = dentry;
261         goto out;
262  
263  Elong:
264 -       retval = ERR_PTR(-ENAMETOOLONG);
265 +       buffer = ERR_PTR(-ENAMETOOLONG);
266         goto out;
267  }
268  
269 @@ -2001,10 +2027,8 @@ char *d_path(const struct path *path, ch
270         root = current->fs->root;
271         path_get(&root);
272         read_unlock(&current->fs->lock);
273 -       spin_lock(&dcache_lock);
274         tmp = root;
275 -       res = __d_path(path, &tmp, buf, buflen);
276 -       spin_unlock(&dcache_lock);
277 +       res = __d_path(path, &tmp, buf, buflen, 0);
278         path_put(&root);
279         return res;
280  }
281 @@ -2087,9 +2111,9 @@ Elong:
282   */
283  asmlinkage long sys_getcwd(char __user *buf, unsigned long size)
284  {
285 -       int error;
286 -       struct path pwd, root;
287 -       char *page = (char *) __get_free_page(GFP_USER);
288 +       int error, len;
289 +       struct path pwd, root, tmp;
290 +       char *page = (char *) __get_free_page(GFP_USER), *cwd;
291  
292         if (!page)
293                 return -ENOMEM;
294 @@ -2101,30 +2125,20 @@ asmlinkage long sys_getcwd(char __user *
295         path_get(&root);
296         read_unlock(&current->fs->lock);
297  
298 -       error = -ENOENT;
299 -       /* Has the current directory has been unlinked? */
300 -       spin_lock(&dcache_lock);
301 -       if (IS_ROOT(pwd.dentry) || !d_unhashed(pwd.dentry)) {
302 -               unsigned long len;
303 -               struct path tmp = root;
304 -               char * cwd;
305 -
306 -               cwd = __d_path(&pwd, &tmp, page, PAGE_SIZE);
307 -               spin_unlock(&dcache_lock);
308 -
309 +       tmp = root;
310 +       cwd = __d_path(&pwd, &tmp, page, PAGE_SIZE, D_PATH_FAIL_DELETED);
311 +       if (IS_ERR(cwd)) {
312                 error = PTR_ERR(cwd);
313 -               if (IS_ERR(cwd))
314 -                       goto out;
315 +               goto out;
316 +       }
317  
318 -               error = -ERANGE;
319 -               len = PAGE_SIZE + page - cwd;
320 -               if (len <= size) {
321 -                       error = len;
322 -                       if (copy_to_user(buf, cwd, len))
323 -                               error = -EFAULT;
324 -               }
325 -       } else
326 -               spin_unlock(&dcache_lock);
327 +       error = -ERANGE;
328 +       len = PAGE_SIZE + page - cwd;
329 +       if (len <= size) {
330 +               error = len;
331 +               if (copy_to_user(buf, cwd, len))
332 +                       error = -EFAULT;
333 +       }
334  
335  out:
336         path_put(&pwd);
337 diff -uprN linux-2.6.27./fs/ecryptfs/inode.c linux-2.6.27/fs/ecryptfs/inode.c
338 --- linux-2.6.27./fs/ecryptfs/inode.c   2008-10-10 00:13:53.000000000 +0200
339 +++ linux-2.6.27/fs/ecryptfs/inode.c    2008-10-29 02:02:00.779549727 +0100
340 @@ -403,19 +403,24 @@ static int ecryptfs_link(struct dentry *
341                          struct dentry *new_dentry)
342  {
343         struct dentry *lower_old_dentry;
344 +       struct vfsmount *lower_old_mnt;
345         struct dentry *lower_new_dentry;
346 +       struct vfsmount *lower_new_mnt;
347         struct dentry *lower_dir_dentry;
348         u64 file_size_save;
349         int rc;
350  
351         file_size_save = i_size_read(old_dentry->d_inode);
352         lower_old_dentry = ecryptfs_dentry_to_lower(old_dentry);
353 +       lower_old_mnt = ecryptfs_dentry_to_lower_mnt(old_dentry);
354         lower_new_dentry = ecryptfs_dentry_to_lower(new_dentry);
355 +       lower_new_mnt = ecryptfs_dentry_to_lower_mnt(new_dentry);
356         dget(lower_old_dentry);
357         dget(lower_new_dentry);
358         lower_dir_dentry = lock_parent(lower_new_dentry);
359 -       rc = vfs_link(lower_old_dentry, lower_dir_dentry->d_inode,
360 -                     lower_new_dentry);
361 +       rc = vfs_link(lower_old_dentry, lower_old_mnt,
362 +                     lower_dir_dentry->d_inode, lower_new_dentry,
363 +                     lower_new_mnt);
364         if (rc || !lower_new_dentry->d_inode)
365                 goto out_lock;
366         rc = ecryptfs_interpose(lower_new_dentry, new_dentry, dir->i_sb, 0);
367 @@ -440,11 +445,12 @@ static int ecryptfs_unlink(struct inode 
368  {
369         int rc = 0;
370         struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
371 +       struct vfsmount *lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
372         struct inode *lower_dir_inode = ecryptfs_inode_to_lower(dir);
373         struct dentry *lower_dir_dentry;
374  
375         lower_dir_dentry = lock_parent(lower_dentry);
376 -       rc = vfs_unlink(lower_dir_inode, lower_dentry);
377 +       rc = vfs_unlink(lower_dir_inode, lower_dentry, lower_mnt);
378         if (rc) {
379                 printk(KERN_ERR "Error in vfs_unlink; rc = [%d]\n", rc);
380                 goto out_unlock;
381 @@ -464,6 +470,7 @@ static int ecryptfs_symlink(struct inode
382  {
383         int rc;
384         struct dentry *lower_dentry;
385 +       struct vfsmount *lower_mnt;
386         struct dentry *lower_dir_dentry;
387         char *encoded_symname;
388         int encoded_symlen;
389 @@ -471,6 +478,7 @@ static int ecryptfs_symlink(struct inode
390  
391         lower_dentry = ecryptfs_dentry_to_lower(dentry);
392         dget(lower_dentry);
393 +       lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
394         lower_dir_dentry = lock_parent(lower_dentry);
395         encoded_symlen = ecryptfs_encode_filename(crypt_stat, symname,
396                                                   strlen(symname),
397 @@ -479,7 +487,7 @@ static int ecryptfs_symlink(struct inode
398                 rc = encoded_symlen;
399                 goto out_lock;
400         }
401 -       rc = vfs_symlink(lower_dir_dentry->d_inode, lower_dentry,
402 +       rc = vfs_symlink(lower_dir_dentry->d_inode, lower_dentry, lower_mnt,
403                          encoded_symname);
404         kfree(encoded_symname);
405         if (rc || !lower_dentry->d_inode)
406 @@ -501,11 +509,14 @@ static int ecryptfs_mkdir(struct inode *
407  {
408         int rc;
409         struct dentry *lower_dentry;
410 +       struct vfsmount *lower_mnt;
411         struct dentry *lower_dir_dentry;
412  
413         lower_dentry = ecryptfs_dentry_to_lower(dentry);
414 +       lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
415         lower_dir_dentry = lock_parent(lower_dentry);
416 -       rc = vfs_mkdir(lower_dir_dentry->d_inode, lower_dentry, mode);
417 +       rc = vfs_mkdir(lower_dir_dentry->d_inode, lower_dentry, lower_mnt,
418 +                      mode);
419         if (rc || !lower_dentry->d_inode)
420                 goto out;
421         rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb, 0);
422 @@ -524,14 +535,16 @@ out:
423  static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry)
424  {
425         struct dentry *lower_dentry;
426 +       struct vfsmount *lower_mnt;
427         struct dentry *lower_dir_dentry;
428         int rc;
429  
430         lower_dentry = ecryptfs_dentry_to_lower(dentry);
431 +       lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
432         dget(dentry);
433         lower_dir_dentry = lock_parent(lower_dentry);
434         dget(lower_dentry);
435 -       rc = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry);
436 +       rc = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry, lower_mnt);
437         dput(lower_dentry);
438         if (!rc)
439                 d_delete(lower_dentry);
440 @@ -549,11 +562,14 @@ ecryptfs_mknod(struct inode *dir, struct
441  {
442         int rc;
443         struct dentry *lower_dentry;
444 +       struct vfsmount *lower_mnt;
445         struct dentry *lower_dir_dentry;
446  
447         lower_dentry = ecryptfs_dentry_to_lower(dentry);
448 +       lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
449         lower_dir_dentry = lock_parent(lower_dentry);
450 -       rc = vfs_mknod(lower_dir_dentry->d_inode, lower_dentry, mode, dev);
451 +       rc = vfs_mknod(lower_dir_dentry->d_inode, lower_dentry, lower_mnt, mode,
452 +                      dev);
453         if (rc || !lower_dentry->d_inode)
454                 goto out;
455         rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb, 0);
456 @@ -574,19 +590,24 @@ ecryptfs_rename(struct inode *old_dir, s
457  {
458         int rc;
459         struct dentry *lower_old_dentry;
460 +       struct vfsmount *lower_old_mnt;
461         struct dentry *lower_new_dentry;
462 +       struct vfsmount *lower_new_mnt;
463         struct dentry *lower_old_dir_dentry;
464         struct dentry *lower_new_dir_dentry;
465  
466         lower_old_dentry = ecryptfs_dentry_to_lower(old_dentry);
467 +       lower_old_mnt = ecryptfs_dentry_to_lower_mnt(old_dentry);
468         lower_new_dentry = ecryptfs_dentry_to_lower(new_dentry);
469 +       lower_new_mnt = ecryptfs_dentry_to_lower_mnt(new_dentry);
470         dget(lower_old_dentry);
471         dget(lower_new_dentry);
472         lower_old_dir_dentry = dget_parent(lower_old_dentry);
473         lower_new_dir_dentry = dget_parent(lower_new_dentry);
474         lock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
475         rc = vfs_rename(lower_old_dir_dentry->d_inode, lower_old_dentry,
476 -                       lower_new_dir_dentry->d_inode, lower_new_dentry);
477 +                       lower_old_mnt, lower_new_dir_dentry->d_inode,
478 +                       lower_new_dentry, lower_new_mnt);
479         if (rc)
480                 goto out_lock;
481         fsstack_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode, NULL);
482 @@ -849,6 +870,7 @@ static int ecryptfs_setattr(struct dentr
483  {
484         int rc = 0;
485         struct dentry *lower_dentry;
486 +       struct vfsmount *lower_mnt;
487         struct inode *inode;
488         struct inode *lower_inode;
489         struct ecryptfs_crypt_stat *crypt_stat;
490 @@ -859,6 +881,7 @@ static int ecryptfs_setattr(struct dentr
491         inode = dentry->d_inode;
492         lower_inode = ecryptfs_inode_to_lower(inode);
493         lower_dentry = ecryptfs_dentry_to_lower(dentry);
494 +       lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
495         mutex_lock(&crypt_stat->cs_mutex);
496         if (S_ISDIR(dentry->d_inode->i_mode))
497                 crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
498 @@ -910,7 +933,7 @@ static int ecryptfs_setattr(struct dentr
499                 ia->ia_valid &= ~ATTR_MODE;
500  
501         mutex_lock(&lower_dentry->d_inode->i_mutex);
502 -       rc = notify_change(lower_dentry, ia);
503 +       rc = notify_change(lower_dentry, lower_mnt, ia);
504         mutex_unlock(&lower_dentry->d_inode->i_mutex);
505  out:
506         fsstack_copy_attr_all(inode, lower_inode, NULL);
507 diff -uprN linux-2.6.27./fs/exec.c linux-2.6.27/fs/exec.c
508 --- linux-2.6.27./fs/exec.c     2008-10-10 00:13:53.000000000 +0200
509 +++ linux-2.6.27/fs/exec.c      2008-10-29 02:01:59.319416030 +0100
510 @@ -1827,7 +1827,8 @@ int do_coredump(long signr, int exit_cod
511                 goto close_fail;
512         if (!file->f_op->write)
513                 goto close_fail;
514 -       if (!ispipe && do_truncate(file->f_path.dentry, 0, 0, file) != 0)
515 +       if (!ispipe &&
516 +           do_truncate(file->f_path.dentry, file->f_path.mnt, 0, 0, file) != 0)
517                 goto close_fail;
518  
519         retval = binfmt->core_dump(signr, regs, file, core_limit);
520 diff -uprN linux-2.6.27./fs/fat/file.c linux-2.6.27/fs/fat/file.c
521 --- linux-2.6.27./fs/fat/file.c 2008-10-10 00:13:53.000000000 +0200
522 +++ linux-2.6.27/fs/fat/file.c  2008-10-29 02:01:59.500590545 +0100
523 @@ -98,7 +98,7 @@ int fat_generic_ioctl(struct inode *inod
524                  * out the RO attribute for checking by the security
525                  * module, just because it maps to a file mode.
526                  */
527 -               err = security_inode_setattr(filp->f_path.dentry, &ia);
528 +               err = security_inode_setattr(filp->f_path.dentry, filp->f_path.mnt, &ia);
529                 if (err)
530                         goto up;
531  
532 diff -uprN linux-2.6.27./fs/fuse/dir.c linux-2.6.27/fs/fuse/dir.c
533 --- linux-2.6.27./fs/fuse/dir.c 2008-10-10 00:13:53.000000000 +0200
534 +++ linux-2.6.27/fs/fuse/dir.c  2008-10-29 02:02:01.786146390 +0100
535 @@ -1105,21 +1105,22 @@ static int fuse_dir_fsync(struct file *f
536         return file ? fuse_fsync_common(file, de, datasync, 1) : 0;
537  }
538  
539 -static bool update_mtime(unsigned ivalid)
540 +static bool update_mtime(unsigned ivalid, bool have_file)
541  {
542         /* Always update if mtime is explicitly set  */
543         if (ivalid & ATTR_MTIME_SET)
544                 return true;
545  
546         /* If it's an open(O_TRUNC) or an ftruncate(), don't update */
547 -       if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE)))
548 +       if ((ivalid & ATTR_SIZE) && ((ivalid & ATTR_OPEN) || have_file))
549                 return false;
550  
551         /* In all other cases update */
552         return true;
553  }
554  
555 -static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg)
556 +static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg,
557 +                          bool have_file)
558  {
559         unsigned ivalid = iattr->ia_valid;
560  
561 @@ -1138,7 +1139,7 @@ static void iattr_to_fattr(struct iattr 
562                 if (!(ivalid & ATTR_ATIME_SET))
563                         arg->valid |= FATTR_ATIME_NOW;
564         }
565 -       if ((ivalid & ATTR_MTIME) && update_mtime(ivalid)) {
566 +       if ((ivalid & ATTR_MTIME) && update_mtime(ivalid, have_file)) {
567                 arg->valid |= FATTR_MTIME;
568                 arg->mtime = iattr->ia_mtime.tv_sec;
569                 arg->mtimensec = iattr->ia_mtime.tv_nsec;
570 @@ -1199,8 +1200,8 @@ void fuse_release_nowrite(struct inode *
571   * vmtruncate() doesn't allow for this case, so do the rlimit checking
572   * and the actual truncation by hand.
573   */
574 -static int fuse_do_setattr(struct dentry *entry, struct iattr *attr,
575 -                          struct file *file)
576 +int fuse_do_setattr(struct dentry *entry, struct iattr *attr,
577 +                   struct file *file)
578  {
579         struct inode *inode = entry->d_inode;
580         struct fuse_conn *fc = get_fuse_conn(inode);
581 @@ -1244,7 +1245,7 @@ static int fuse_do_setattr(struct dentry
582  
583         memset(&inarg, 0, sizeof(inarg));
584         memset(&outarg, 0, sizeof(outarg));
585 -       iattr_to_fattr(attr, &inarg);
586 +       iattr_to_fattr(attr, &inarg, file != NULL);
587         if (file) {
588                 struct fuse_file *ff = file->private_data;
589                 inarg.valid |= FATTR_FH;
590 @@ -1314,10 +1315,7 @@ error:
591  
592  static int fuse_setattr(struct dentry *entry, struct iattr *attr)
593  {
594 -       if (attr->ia_valid & ATTR_FILE)
595 -               return fuse_do_setattr(entry, attr, attr->ia_file);
596 -       else
597 -               return fuse_do_setattr(entry, attr, NULL);
598 +       return fuse_do_setattr(entry, attr, NULL);
599  }
600  
601  static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
602 diff -uprN linux-2.6.27./fs/fuse/file.c linux-2.6.27/fs/fuse/file.c
603 --- linux-2.6.27./fs/fuse/file.c        2008-10-10 00:13:53.000000000 +0200
604 +++ linux-2.6.27/fs/fuse/file.c 2008-10-29 02:02:01.819442233 +0100
605 @@ -1465,6 +1465,11 @@ static loff_t fuse_file_llseek(struct fi
606         return retval;
607  }
608  
609 +static int fuse_fsetattr(struct file *file, struct iattr *attr)
610 +{
611 +       return fuse_do_setattr(file->f_path.dentry, attr, file);
612 +}
613 +
614  static const struct file_operations fuse_file_operations = {
615         .llseek         = fuse_file_llseek,
616         .read           = do_sync_read,
617 @@ -1478,6 +1483,7 @@ static const struct file_operations fuse
618         .fsync          = fuse_fsync,
619         .lock           = fuse_file_lock,
620         .flock          = fuse_file_flock,
621 +       .fsetattr       = fuse_fsetattr,
622         .splice_read    = generic_file_splice_read,
623  };
624  
625 @@ -1491,6 +1497,7 @@ static const struct file_operations fuse
626         .fsync          = fuse_fsync,
627         .lock           = fuse_file_lock,
628         .flock          = fuse_file_flock,
629 +       .fsetattr       = fuse_fsetattr,
630         /* no mmap and splice_read */
631  };
632  
633 diff -uprN linux-2.6.27./fs/fuse/fuse_i.h linux-2.6.27/fs/fuse/fuse_i.h
634 --- linux-2.6.27./fs/fuse/fuse_i.h      2008-10-10 00:13:53.000000000 +0200
635 +++ linux-2.6.27/fs/fuse/fuse_i.h       2008-10-29 02:02:01.849340465 +0100
636 @@ -551,6 +551,10 @@ void fuse_truncate(struct address_space 
637   */
638  int fuse_dev_init(void);
639  
640 +
641 +int fuse_do_setattr(struct dentry *entry, struct iattr *attr,
642 +                   struct file *file);
643 +
644  /**
645   * Cleanup the client device
646   */
647 diff -uprN linux-2.6.27./fs/hpfs/namei.c linux-2.6.27/fs/hpfs/namei.c
648 --- linux-2.6.27./fs/hpfs/namei.c       2008-10-10 00:13:53.000000000 +0200
649 +++ linux-2.6.27/fs/hpfs/namei.c        2008-10-29 02:01:59.336012786 +0100
650 @@ -426,7 +426,7 @@ again:
651                         /*printk("HPFS: truncating file before delete.\n");*/
652                         newattrs.ia_size = 0;
653                         newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
654 -                       err = notify_change(dentry, &newattrs);
655 +                       err = notify_change(dentry, NULL, &newattrs);
656                         put_write_access(inode);
657                         if (!err)
658                                 goto again;
659 diff -uprN linux-2.6.27./fs/inotify_user.c linux-2.6.27/fs/inotify_user.c
660 --- linux-2.6.27./fs/inotify_user.c     2008-10-10 00:13:53.000000000 +0200
661 +++ linux-2.6.27/fs/inotify_user.c      2008-10-29 02:02:02.186081701 +0100
662 @@ -372,7 +372,7 @@ static int find_inode(const char __user 
663         if (error)
664                 return error;
665         /* you can only watch an inode if you have read permissions on it */
666 -       error = inode_permission(path->dentry->d_inode, MAY_READ);
667 +       error = path_permission(path, MAY_READ);
668         if (error)
669                 path_put(path);
670         return error;
671 diff -uprN linux-2.6.27./fs/namei.c linux-2.6.27/fs/namei.c
672 --- linux-2.6.27./fs/namei.c    2008-10-10 00:13:53.000000000 +0200
673 +++ linux-2.6.27/fs/namei.c     2008-10-29 02:02:02.266214852 +0100
674 @@ -227,7 +227,7 @@ int generic_permission(struct inode *ino
675         return -EACCES;
676  }
677  
678 -int inode_permission(struct inode *inode, int mask)
679 +static int __inode_permission(struct inode *inode, int mask)
680  {
681         int retval;
682  
683 @@ -269,7 +269,12 @@ int inode_permission(struct inode *inode
684         if (retval)
685                 return retval;
686  
687 -       retval = devcgroup_inode_permission(inode, mask);
688 +       return devcgroup_inode_permission(inode, mask);
689 +}
690 +
691 +int inode_permission(struct inode *inode, int mask)
692 +{
693 +       int retval = __inode_permission(inode, mask);
694         if (retval)
695                 return retval;
696  
697 @@ -277,6 +282,15 @@ int inode_permission(struct inode *inode
698                         mask & (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND));
699  }
700  
701 +int path_permission(struct path *path, int mask)
702 +{
703 +       int retval = __inode_permission(path->dentry->d_inode, mask);
704 +       if (retval)
705 +               return retval;
706 +       return security_path_permission(path,
707 +                       mask & (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND));
708 +}
709 +
710  /**
711   * vfs_permission  -  check for access rights to a given path
712   * @nd:                lookup result that describes the path
713 @@ -289,7 +303,7 @@ int inode_permission(struct inode *inode
714   */
715  int vfs_permission(struct nameidata *nd, int mask)
716  {
717 -       return inode_permission(nd->path.dentry->d_inode, mask);
718 +       return path_permission(&nd->path, mask);
719  }
720  
721  /**
722 @@ -306,7 +320,7 @@ int vfs_permission(struct nameidata *nd,
723   */
724  int file_permission(struct file *file, int mask)
725  {
726 -       return inode_permission(file->f_path.dentry->d_inode, mask);
727 +       return path_permission(&file->f_path, mask);
728  }
729  
730  /*
731 @@ -447,8 +461,9 @@ static struct dentry * cached_lookup(str
732   * short-cut DAC fails, then call permission() to do more
733   * complete permission check.
734   */
735 -static int exec_permission_lite(struct inode *inode)
736 +static int exec_permission_lite(struct path *path)
737  {
738 +       struct inode *inode = path->dentry->d_inode;
739         umode_t mode = inode->i_mode;
740  
741         if (inode->i_op && inode->i_op->permission)
742 @@ -473,7 +488,7 @@ static int exec_permission_lite(struct i
743  
744         return -EACCES;
745  ok:
746 -       return security_inode_permission(inode, MAY_EXEC);
747 +       return security_path_permission(path, MAY_EXEC);
748  }
749  
750  /*
751 @@ -870,7 +885,7 @@ static int __link_path_walk(const char *
752                 unsigned int c;
753  
754                 nd->flags |= LOOKUP_CONTINUE;
755 -               err = exec_permission_lite(inode);
756 +               err = exec_permission_lite(&nd->path);
757                 if (err == -EAGAIN)
758                         err = vfs_permission(nd, MAY_EXEC);
759                 if (err)
760 @@ -1065,24 +1080,21 @@ static int do_path_lookup(int dfd, const
761                 path_get(&fs->pwd);
762                 read_unlock(&fs->lock);
763         } else {
764 -               struct dentry *dentry;
765 -
766                 file = fget_light(dfd, &fput_needed);
767                 retval = -EBADF;
768                 if (!file)
769                         goto out_fail;
770  
771 -               dentry = file->f_path.dentry;
772 +               nd->path = file->f_path;
773  
774                 retval = -ENOTDIR;
775 -               if (!S_ISDIR(dentry->d_inode->i_mode))
776 +               if (!S_ISDIR(nd->path.dentry->d_inode->i_mode))
777                         goto fput_fail;
778  
779                 retval = file_permission(file, MAY_EXEC);
780                 if (retval)
781                         goto fput_fail;
782  
783 -               nd->path = file->f_path;
784                 path_get(&file->f_path);
785  
786                 fput_light(file, fput_needed);
787 @@ -1245,7 +1257,7 @@ static struct dentry *lookup_hash(struct
788  {
789         int err;
790  
791 -       err = inode_permission(nd->path.dentry->d_inode, MAY_EXEC);
792 +       err = path_permission(&nd->path, MAY_EXEC);
793         if (err)
794                 return ERR_PTR(err);
795         return __lookup_hash(&nd->last, nd->path.dentry, nd);
796 @@ -1512,7 +1524,7 @@ int vfs_create(struct inode *dir, struct
797                 return -EACCES; /* shouldn't it be ENOSYS? */
798         mode &= S_IALLUGO;
799         mode |= S_IFREG;
800 -       error = security_inode_create(dir, dentry, mode);
801 +       error = security_inode_create(dir, dentry, nd ? nd->path.mnt : NULL, mode);
802         if (error)
803                 return error;
804         DQUOT_INIT(dir);
805 @@ -1588,7 +1600,7 @@ int may_open(struct nameidata *nd, int a
806                 if (!error) {
807                         DQUOT_INIT(inode);
808  
809 -                       error = do_truncate(dentry, 0,
810 +                       error = do_truncate(dentry, nd->path.mnt, 0,
811                                             ATTR_MTIME|ATTR_CTIME|ATTR_OPEN,
812                                             NULL);
813                 }
814 @@ -1945,7 +1957,8 @@ fail:
815  }
816  EXPORT_SYMBOL_GPL(lookup_create);
817  
818 -int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
819 +int vfs_mknod(struct inode *dir, struct dentry *dentry, struct vfsmount *mnt,
820 +             int mode, dev_t dev)
821  {
822         int error = may_create(dir, dentry);
823  
824 @@ -1962,7 +1975,7 @@ int vfs_mknod(struct inode *dir, struct 
825         if (error)
826                 return error;
827  
828 -       error = security_inode_mknod(dir, dentry, mode, dev);
829 +       error = security_inode_mknod(dir, dentry, mnt, mode, dev);
830         if (error)
831                 return error;
832  
833 @@ -2023,11 +2036,12 @@ asmlinkage long sys_mknodat(int dfd, con
834                         error = vfs_create(nd.path.dentry->d_inode,dentry,mode,&nd);
835                         break;
836                 case S_IFCHR: case S_IFBLK:
837 -                       error = vfs_mknod(nd.path.dentry->d_inode,dentry,mode,
838 -                                       new_decode_dev(dev));
839 +                       error = vfs_mknod(nd.path.dentry->d_inode, dentry,
840 +                                         nd.path.mnt, mode, new_decode_dev(dev));
841                         break;
842                 case S_IFIFO: case S_IFSOCK:
843 -                       error = vfs_mknod(nd.path.dentry->d_inode,dentry,mode,0);
844 +                       error = vfs_mknod(nd.path.dentry->d_inode, dentry,
845 +                                         nd.path.mnt, mode, 0);
846                         break;
847         }
848         mnt_drop_write(nd.path.mnt);
849 @@ -2046,7 +2060,8 @@ asmlinkage long sys_mknod(const char __u
850         return sys_mknodat(AT_FDCWD, filename, mode, dev);
851  }
852  
853 -int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
854 +int vfs_mkdir(struct inode *dir, struct dentry *dentry, struct vfsmount *mnt,
855 +             int mode)
856  {
857         int error = may_create(dir, dentry);
858  
859 @@ -2057,7 +2072,7 @@ int vfs_mkdir(struct inode *dir, struct 
860                 return -EPERM;
861  
862         mode &= (S_IRWXUGO|S_ISVTX);
863 -       error = security_inode_mkdir(dir, dentry, mode);
864 +       error = security_inode_mkdir(dir, dentry, mnt, mode);
865         if (error)
866                 return error;
867  
868 @@ -2089,7 +2104,7 @@ asmlinkage long sys_mkdirat(int dfd, con
869         error = mnt_want_write(nd.path.mnt);
870         if (error)
871                 goto out_dput;
872 -       error = vfs_mkdir(nd.path.dentry->d_inode, dentry, mode);
873 +       error = vfs_mkdir(nd.path.dentry->d_inode, dentry, nd.path.mnt, mode);
874         mnt_drop_write(nd.path.mnt);
875  out_dput:
876         dput(dentry);
877 @@ -2133,7 +2148,7 @@ void dentry_unhash(struct dentry *dentry
878         spin_unlock(&dcache_lock);
879  }
880  
881 -int vfs_rmdir(struct inode *dir, struct dentry *dentry)
882 +int vfs_rmdir(struct inode *dir, struct dentry *dentry,struct vfsmount *mnt)
883  {
884         int error = may_delete(dir, dentry, 1);
885  
886 @@ -2143,6 +2158,10 @@ int vfs_rmdir(struct inode *dir, struct 
887         if (!dir->i_op || !dir->i_op->rmdir)
888                 return -EPERM;
889  
890 +       error = security_inode_rmdir(dir, dentry, mnt);
891 +       if (error)
892 +               return error;
893 +
894         DQUOT_INIT(dir);
895  
896         mutex_lock(&dentry->d_inode->i_mutex);
897 @@ -2150,12 +2169,9 @@ int vfs_rmdir(struct inode *dir, struct 
898         if (d_mountpoint(dentry))
899                 error = -EBUSY;
900         else {
901 -               error = security_inode_rmdir(dir, dentry);
902 -               if (!error) {
903 -                       error = dir->i_op->rmdir(dir, dentry);
904 -                       if (!error)
905 -                               dentry->d_inode->i_flags |= S_DEAD;
906 -               }
907 +               error = dir->i_op->rmdir(dir, dentry);
908 +               if (!error)
909 +                       dentry->d_inode->i_flags |= S_DEAD;
910         }
911         mutex_unlock(&dentry->d_inode->i_mutex);
912         if (!error) {
913 @@ -2196,7 +2212,7 @@ static long do_rmdir(int dfd, const char
914         error = mnt_want_write(nd.path.mnt);
915         if (error)
916                 goto exit3;
917 -       error = vfs_rmdir(nd.path.dentry->d_inode, dentry);
918 +       error = vfs_rmdir(nd.path.dentry->d_inode, dentry, nd.path.mnt);
919         mnt_drop_write(nd.path.mnt);
920  exit3:
921         dput(dentry);
922 @@ -2213,7 +2229,7 @@ asmlinkage long sys_rmdir(const char __u
923         return do_rmdir(AT_FDCWD, pathname);
924  }
925  
926 -int vfs_unlink(struct inode *dir, struct dentry *dentry)
927 +int vfs_unlink(struct inode *dir, struct dentry *dentry, struct vfsmount *mnt)
928  {
929         int error = may_delete(dir, dentry, 0);
930  
931 @@ -2229,7 +2245,7 @@ int vfs_unlink(struct inode *dir, struct
932         if (d_mountpoint(dentry))
933                 error = -EBUSY;
934         else {
935 -               error = security_inode_unlink(dir, dentry);
936 +               error = security_inode_unlink(dir, dentry, mnt);
937                 if (!error)
938                         error = dir->i_op->unlink(dir, dentry);
939         }
940 @@ -2278,7 +2294,7 @@ static long do_unlinkat(int dfd, const c
941                 error = mnt_want_write(nd.path.mnt);
942                 if (error)
943                         goto exit2;
944 -               error = vfs_unlink(nd.path.dentry->d_inode, dentry);
945 +               error = vfs_unlink(nd.path.dentry->d_inode, dentry, nd.path.mnt);
946                 if (!error && (saved_ino || saved_dev))
947                         gr_handle_delete(saved_ino, saved_dev);
948                 mnt_drop_write(nd.path.mnt);
949 @@ -2313,7 +2329,8 @@ asmlinkage long sys_unlink(const char __
950         return do_unlinkat(AT_FDCWD, pathname);
951  }
952  
953 -int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname)
954 +int vfs_symlink(struct inode *dir, struct dentry *dentry, struct vfsmount *mnt,
955 +               const char *oldname)
956  {
957         int error = may_create(dir, dentry);
958  
959 @@ -2323,7 +2340,7 @@ int vfs_symlink(struct inode *dir, struc
960         if (!dir->i_op || !dir->i_op->symlink)
961                 return -EPERM;
962  
963 -       error = security_inode_symlink(dir, dentry, oldname);
964 +       error = security_inode_symlink(dir, dentry, mnt, oldname);
965         if (error)
966                 return error;
967  
968 @@ -2359,7 +2376,7 @@ asmlinkage long sys_symlinkat(const char
969         error = mnt_want_write(nd.path.mnt);
970         if (error)
971                 goto out_dput;
972 -       error = vfs_symlink(nd.path.dentry->d_inode, dentry, from);
973 +       error = vfs_symlink(nd.path.dentry->d_inode, dentry, nd.path.mnt, from);
974         if (!error)
975                 gr_handle_create(dentry, nd.path.mnt);
976         mnt_drop_write(nd.path.mnt);
977 @@ -2377,7 +2394,7 @@ asmlinkage long sys_symlink(const char _
978         return sys_symlinkat(oldname, AT_FDCWD, newname);
979  }
980  
981 -int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
982 +int vfs_link(struct dentry *old_dentry, struct vfsmount *old_mnt, struct inode *dir, struct dentry *new_dentry, struct vfsmount *new_mnt)
983  {
984         struct inode *inode = old_dentry->d_inode;
985         int error;
986 @@ -2402,7 +2419,8 @@ int vfs_link(struct dentry *old_dentry, 
987         if (S_ISDIR(inode->i_mode))
988                 return -EPERM;
989  
990 -       error = security_inode_link(old_dentry, dir, new_dentry);
991 +       error = security_inode_link(old_dentry, old_mnt, dir, new_dentry,
992 +                                   new_mnt);
993         if (error)
994                 return error;
995  
996 @@ -2456,7 +2474,9 @@ asmlinkage long sys_linkat(int olddfd, c
997         error = mnt_want_write(nd.path.mnt);
998         if (error)
999                 goto out_dput;
1000 -       error = vfs_link(old_path.dentry, nd.path.dentry->d_inode, new_dentry);
1001 +       error = vfs_link(old_path.dentry, old_path.mnt,
1002 +                        nd.path.dentry->d_inode,
1003 +                        new_dentry, nd.path.mnt);
1004         if (!error)
1005                 gr_handle_create(new_dentry, nd.path.mnt);
1006         mnt_drop_write(nd.path.mnt);
1007 @@ -2509,7 +2529,8 @@ asmlinkage long sys_link(const char __us
1008   *        locking].
1009   */
1010  static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
1011 -                         struct inode *new_dir, struct dentry *new_dentry)
1012 +                         struct vfsmount *old_mnt, struct inode *new_dir,
1013 +                         struct dentry *new_dentry, struct vfsmount *new_mnt)
1014  {
1015         int error = 0;
1016         struct inode *target;
1017 @@ -2524,7 +2545,8 @@ static int vfs_rename_dir(struct inode *
1018                         return error;
1019         }
1020  
1021 -       error = security_inode_rename(old_dir, old_dentry, new_dir, new_dentry);
1022 +       error = security_inode_rename(old_dir, old_dentry, old_mnt,
1023 +                                     new_dir, new_dentry, new_mnt);
1024         if (error)
1025                 return error;
1026  
1027 @@ -2552,12 +2574,14 @@ static int vfs_rename_dir(struct inode *
1028  }
1029  
1030  static int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
1031 -                           struct inode *new_dir, struct dentry *new_dentry)
1032 +                           struct vfsmount *old_mnt, struct inode *new_dir,
1033 +                           struct dentry *new_dentry, struct vfsmount *new_mnt)
1034  {
1035         struct inode *target;
1036         int error;
1037  
1038 -       error = security_inode_rename(old_dir, old_dentry, new_dir, new_dentry);
1039 +       error = security_inode_rename(old_dir, old_dentry, old_mnt,
1040 +                                     new_dir, new_dentry, new_mnt);
1041         if (error)
1042                 return error;
1043  
1044 @@ -2580,7 +2604,8 @@ static int vfs_rename_other(struct inode
1045  }
1046  
1047  int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
1048 -              struct inode *new_dir, struct dentry *new_dentry)
1049 +               struct vfsmount *old_mnt, struct inode *new_dir,
1050 +               struct dentry *new_dentry, struct vfsmount *new_mnt)
1051  {
1052         int error;
1053         int is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
1054 @@ -2609,9 +2634,11 @@ int vfs_rename(struct inode *old_dir, st
1055         old_name = fsnotify_oldname_init(old_dentry->d_name.name);
1056  
1057         if (is_dir)
1058 -               error = vfs_rename_dir(old_dir,old_dentry,new_dir,new_dentry);
1059 +               error = vfs_rename_dir(old_dir, old_dentry, old_mnt,
1060 +                                      new_dir, new_dentry, new_mnt);
1061         else
1062 -               error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry);
1063 +               error = vfs_rename_other(old_dir, old_dentry, old_mnt,
1064 +                                        new_dir, new_dentry, new_mnt);
1065  
1066         if (!error) {
1067                 const char *new_name = old_dentry->d_name.name;
1068 @@ -2688,8 +2715,8 @@ asmlinkage long sys_renameat(int olddfd,
1069         error = mnt_want_write(oldnd.path.mnt);
1070         if (error)
1071                 goto exit5;
1072 -       error = vfs_rename(old_dir->d_inode, old_dentry,
1073 -                                  new_dir->d_inode, new_dentry);
1074 +       error = vfs_rename(old_dir->d_inode, old_dentry, oldnd.path.mnt,
1075 +                          new_dir->d_inode, new_dentry, newnd.path.mnt);
1076         if (!error)
1077                 gr_handle_rename(old_dir->d_inode, newnd.path.dentry->d_inode, old_dentry,
1078                                  new_dentry, oldnd.path.mnt, new_dentry->d_inode ? 1 : 0);
1079 @@ -2857,6 +2884,7 @@ EXPORT_SYMBOL(page_symlink_inode_operati
1080  EXPORT_SYMBOL(path_lookup);
1081  EXPORT_SYMBOL(vfs_path_lookup);
1082  EXPORT_SYMBOL(inode_permission);
1083 +EXPORT_SYMBOL(path_permission);
1084  EXPORT_SYMBOL(vfs_permission);
1085  EXPORT_SYMBOL(file_permission);
1086  EXPORT_SYMBOL(unlock_rename);
1087 diff -uprN linux-2.6.27./fs/namespace.c linux-2.6.27/fs/namespace.c
1088 --- linux-2.6.27./fs/namespace.c        2008-10-10 00:13:53.000000000 +0200
1089 +++ linux-2.6.27/fs/namespace.c 2008-10-29 02:02:01.636213710 +0100
1090 @@ -2352,3 +2352,33 @@ void __put_mnt_ns(struct mnt_namespace *
1091         release_mounts(&umount_list);
1092         kfree(ns);
1093  }
1094 +
1095 +char *d_namespace_path(struct dentry *dentry, struct vfsmount *vfsmnt,
1096 +                      char *buf, int buflen)
1097 +{
1098 +       struct path root, tmp, ns_root = { };
1099 +       struct path path = { .mnt = vfsmnt, .dentry = dentry };
1100 +       char *res;
1101 +
1102 +       read_lock(&current->fs->lock);
1103 +       root = current->fs->root;
1104 +       path_get(&current->fs->root);
1105 +       read_unlock(&current->fs->lock);
1106 +       spin_lock(&vfsmount_lock);
1107 +       if (root.mnt)
1108 +               ns_root.mnt = mntget(root.mnt->mnt_ns->root);
1109 +       if (ns_root.mnt)
1110 +               ns_root.dentry = dget(ns_root.mnt->mnt_root);
1111 +       spin_unlock(&vfsmount_lock);
1112 +       tmp = ns_root;
1113 +       res = __d_path(&path, &tmp, buf, buflen,
1114 +                      D_PATH_FAIL_DELETED | D_PATH_DISCONNECT);
1115 +       path_put(&root);
1116 +       path_put(&ns_root);
1117 +
1118 +       /* Prevent empty path for lazily unmounted filesystems. */
1119 +       if (!IS_ERR(res) && *res == '\0')
1120 +               *--res = '.';
1121 +       return res;
1122 +}
1123 +EXPORT_SYMBOL(d_namespace_path);
1124 diff -uprN linux-2.6.27./fs/nfsd/nfs4recover.c linux-2.6.27/fs/nfsd/nfs4recover.c
1125 --- linux-2.6.27./fs/nfsd/nfs4recover.c 2008-10-10 00:13:53.000000000 +0200
1126 +++ linux-2.6.27/fs/nfsd/nfs4recover.c  2008-10-29 02:02:00.593071537 +0100
1127 @@ -158,7 +158,8 @@ nfsd4_create_clid_dir(struct nfs4_client
1128         status = mnt_want_write(rec_dir.path.mnt);
1129         if (status)
1130                 goto out_put;
1131 -       status = vfs_mkdir(rec_dir.path.dentry->d_inode, dentry, S_IRWXU);
1132 +       status = vfs_mkdir(rec_dir.path.dentry->d_inode, dentry,
1133 +                          rec_dir.path.mnt, S_IRWXU);
1134         mnt_drop_write(rec_dir.path.mnt);
1135  out_put:
1136         dput(dentry);
1137 @@ -263,7 +264,7 @@ nfsd4_remove_clid_file(struct dentry *di
1138                 return -EINVAL;
1139         }
1140         mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
1141 -       status = vfs_unlink(dir->d_inode, dentry);
1142 +       status = vfs_unlink(dir->d_inode, dentry, rec_dir.path.mnt);
1143         mutex_unlock(&dir->d_inode->i_mutex);
1144         return status;
1145  }
1146 @@ -278,7 +279,7 @@ nfsd4_clear_clid_dir(struct dentry *dir,
1147          * a kernel from the future.... */
1148         nfsd4_list_rec_dir(dentry, nfsd4_remove_clid_file);
1149         mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
1150 -       status = vfs_rmdir(dir->d_inode, dentry);
1151 +       status = vfs_rmdir(dir->d_inode, dentry, rec_dir.path.mnt);
1152         mutex_unlock(&dir->d_inode->i_mutex);
1153         return status;
1154  }
1155 diff -uprN linux-2.6.27./fs/nfsd/nfs4xdr.c linux-2.6.27/fs/nfsd/nfs4xdr.c
1156 --- linux-2.6.27./fs/nfsd/nfs4xdr.c     2008-10-10 00:13:53.000000000 +0200
1157 +++ linux-2.6.27/fs/nfsd/nfs4xdr.c      2008-10-29 02:02:01.146006994 +0100
1158 @@ -1446,7 +1446,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, s
1159         }
1160         if (bmval0 & (FATTR4_WORD0_ACL | FATTR4_WORD0_ACLSUPPORT
1161                         | FATTR4_WORD0_SUPPORTED_ATTRS)) {
1162 -               err = nfsd4_get_nfs4_acl(rqstp, dentry, &acl);
1163 +               err = nfsd4_get_nfs4_acl(rqstp, dentry, exp->ex_path.mnt, &acl);
1164                 aclsupport = (err == 0);
1165                 if (bmval0 & FATTR4_WORD0_ACL) {
1166                         if (err == -EOPNOTSUPP)
1167 diff -uprN linux-2.6.27./fs/nfsd/vfs.c linux-2.6.27/fs/nfsd/vfs.c
1168 --- linux-2.6.27./fs/nfsd/vfs.c 2008-10-10 00:13:53.000000000 +0200
1169 +++ linux-2.6.27/fs/nfsd/vfs.c  2008-10-29 02:02:01.949479311 +0100
1170 @@ -388,7 +388,7 @@ nfsd_setattr(struct svc_rqst *rqstp, str
1171         err = nfserr_notsync;
1172         if (!check_guard || guardtime == inode->i_ctime.tv_sec) {
1173                 fh_lock(fhp);
1174 -               host_err = notify_change(dentry, iap);
1175 +               host_err = notify_change(dentry, fhp->fh_export->ex_path.mnt, iap);
1176                 err = nfserrno(host_err);
1177                 fh_unlock(fhp);
1178         }
1179 @@ -408,11 +408,12 @@ out_nfserr:
1180  #if defined(CONFIG_NFSD_V2_ACL) || \
1181      defined(CONFIG_NFSD_V3_ACL) || \
1182      defined(CONFIG_NFSD_V4)
1183 -static ssize_t nfsd_getxattr(struct dentry *dentry, char *key, void **buf)
1184 +static ssize_t nfsd_getxattr(struct dentry *dentry, struct vfsmount *mnt,
1185 +                            char *key, void **buf)
1186  {
1187         ssize_t buflen;
1188  
1189 -       buflen = vfs_getxattr(dentry, key, NULL, 0);
1190 +       buflen = vfs_getxattr(dentry, mnt, key, NULL, 0, NULL);
1191         if (buflen <= 0)
1192                 return buflen;
1193  
1194 @@ -420,13 +421,14 @@ static ssize_t nfsd_getxattr(struct dent
1195         if (!*buf)
1196                 return -ENOMEM;
1197  
1198 -       return vfs_getxattr(dentry, key, *buf, buflen);
1199 +       return vfs_getxattr(dentry, mnt, key, *buf, buflen, NULL);
1200  }
1201  #endif
1202  
1203  #if defined(CONFIG_NFSD_V4)
1204  static int
1205 -set_nfsv4_acl_one(struct dentry *dentry, struct posix_acl *pacl, char *key)
1206 +set_nfsv4_acl_one(struct dentry *dentry, struct vfsmount *mnt,
1207 +                 struct posix_acl *pacl, char *key)
1208  {
1209         int len;
1210         size_t buflen;
1211 @@ -445,7 +447,7 @@ set_nfsv4_acl_one(struct dentry *dentry,
1212                 goto out;
1213         }
1214  
1215 -       error = vfs_setxattr(dentry, key, buf, len, 0);
1216 +       error = vfs_setxattr(dentry, mnt, key, buf, len, 0, NULL);
1217  out:
1218         kfree(buf);
1219         return error;
1220 @@ -458,6 +460,7 @@ nfsd4_set_nfs4_acl(struct svc_rqst *rqst
1221         __be32 error;
1222         int host_error;
1223         struct dentry *dentry;
1224 +       struct vfsmount *mnt;
1225         struct inode *inode;
1226         struct posix_acl *pacl = NULL, *dpacl = NULL;
1227         unsigned int flags = 0;
1228 @@ -468,6 +471,7 @@ nfsd4_set_nfs4_acl(struct svc_rqst *rqst
1229                 return error;
1230  
1231         dentry = fhp->fh_dentry;
1232 +       mnt = fhp->fh_export->ex_path.mnt;
1233         inode = dentry->d_inode;
1234         if (S_ISDIR(inode->i_mode))
1235                 flags = NFS4_ACL_DIR;
1236 @@ -478,12 +482,14 @@ nfsd4_set_nfs4_acl(struct svc_rqst *rqst
1237         } else if (host_error < 0)
1238                 goto out_nfserr;
1239  
1240 -       host_error = set_nfsv4_acl_one(dentry, pacl, POSIX_ACL_XATTR_ACCESS);
1241 +       host_error = set_nfsv4_acl_one(dentry, mnt, pacl,
1242 +                                      POSIX_ACL_XATTR_ACCESS);
1243         if (host_error < 0)
1244                 goto out_release;
1245  
1246         if (S_ISDIR(inode->i_mode))
1247 -               host_error = set_nfsv4_acl_one(dentry, dpacl, POSIX_ACL_XATTR_DEFAULT);
1248 +               host_error = set_nfsv4_acl_one(dentry, mnt, dpacl,
1249 +                                              POSIX_ACL_XATTR_DEFAULT);
1250  
1251  out_release:
1252         posix_acl_release(pacl);
1253 @@ -496,13 +502,13 @@ out_nfserr:
1254  }
1255  
1256  static struct posix_acl *
1257 -_get_posix_acl(struct dentry *dentry, char *key)
1258 +_get_posix_acl(struct dentry *dentry, struct vfsmount *mnt, char *key)
1259  {
1260         void *buf = NULL;
1261         struct posix_acl *pacl = NULL;
1262         int buflen;
1263  
1264 -       buflen = nfsd_getxattr(dentry, key, &buf);
1265 +       buflen = nfsd_getxattr(dentry, mnt, key, &buf);
1266         if (!buflen)
1267                 buflen = -ENODATA;
1268         if (buflen <= 0)
1269 @@ -514,14 +520,15 @@ _get_posix_acl(struct dentry *dentry, ch
1270  }
1271  
1272  int
1273 -nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry, struct nfs4_acl **acl)
1274 +nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry,
1275 +                  struct vfsmount *mnt, struct nfs4_acl **acl)
1276  {
1277         struct inode *inode = dentry->d_inode;
1278         int error = 0;
1279         struct posix_acl *pacl = NULL, *dpacl = NULL;
1280         unsigned int flags = 0;
1281  
1282 -       pacl = _get_posix_acl(dentry, POSIX_ACL_XATTR_ACCESS);
1283 +       pacl = _get_posix_acl(dentry, mnt, POSIX_ACL_XATTR_ACCESS);
1284         if (IS_ERR(pacl) && PTR_ERR(pacl) == -ENODATA)
1285                 pacl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
1286         if (IS_ERR(pacl)) {
1287 @@ -531,7 +538,7 @@ nfsd4_get_nfs4_acl(struct svc_rqst *rqst
1288         }
1289  
1290         if (S_ISDIR(inode->i_mode)) {
1291 -               dpacl = _get_posix_acl(dentry, POSIX_ACL_XATTR_DEFAULT);
1292 +               dpacl = _get_posix_acl(dentry, mnt, POSIX_ACL_XATTR_DEFAULT);
1293                 if (IS_ERR(dpacl) && PTR_ERR(dpacl) == -ENODATA)
1294                         dpacl = NULL;
1295                 else if (IS_ERR(dpacl)) {
1296 @@ -944,13 +951,13 @@ out:
1297         return err;
1298  }
1299  
1300 -static void kill_suid(struct dentry *dentry)
1301 +static void kill_suid(struct dentry *dentry, struct vfsmount *mnt)
1302  {
1303         struct iattr    ia;
1304         ia.ia_valid = ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;
1305  
1306         mutex_lock(&dentry->d_inode->i_mutex);
1307 -       notify_change(dentry, &ia);
1308 +       notify_change(dentry, mnt, &ia);
1309         mutex_unlock(&dentry->d_inode->i_mutex);
1310  }
1311  
1312 @@ -1009,7 +1016,7 @@ nfsd_vfs_write(struct svc_rqst *rqstp, s
1313  
1314         /* clear setuid/setgid flag after write */
1315         if (host_err >= 0 && (inode->i_mode & (S_ISUID | S_ISGID)))
1316 -               kill_suid(dentry);
1317 +               kill_suid(dentry, exp->ex_path.mnt);
1318  
1319         if (host_err >= 0 && stable) {
1320                 static ino_t    last_ino;
1321 @@ -1187,6 +1194,7 @@ nfsd_create(struct svc_rqst *rqstp, stru
1322                 int type, dev_t rdev, struct svc_fh *resfhp)
1323  {
1324         struct dentry   *dentry, *dchild = NULL;
1325 +       struct svc_export *exp;
1326         struct inode    *dirp;
1327         __be32          err;
1328         __be32          err2;
1329 @@ -1204,6 +1212,7 @@ nfsd_create(struct svc_rqst *rqstp, stru
1330                 goto out;
1331  
1332         dentry = fhp->fh_dentry;
1333 +       exp = fhp->fh_export;
1334         dirp = dentry->d_inode;
1335  
1336         err = nfserr_notdir;
1337 @@ -1220,7 +1229,7 @@ nfsd_create(struct svc_rqst *rqstp, stru
1338                 host_err = PTR_ERR(dchild);
1339                 if (IS_ERR(dchild))
1340                         goto out_nfserr;
1341 -               err = fh_compose(resfhp, fhp->fh_export, dchild, fhp);
1342 +               err = fh_compose(resfhp, exp, dchild, fhp);
1343                 if (err)
1344                         goto out;
1345         } else {
1346 @@ -1270,13 +1279,14 @@ nfsd_create(struct svc_rqst *rqstp, stru
1347                 host_err = vfs_create(dirp, dchild, iap->ia_mode, NULL);
1348                 break;
1349         case S_IFDIR:
1350 -               host_err = vfs_mkdir(dirp, dchild, iap->ia_mode);
1351 +               host_err = vfs_mkdir(dirp, dchild, exp->ex_path.mnt, iap->ia_mode);
1352                 break;
1353         case S_IFCHR:
1354         case S_IFBLK:
1355         case S_IFIFO:
1356         case S_IFSOCK:
1357 -               host_err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev);
1358 +               host_err = vfs_mknod(dirp, dchild, exp->ex_path.mnt,
1359 +                                    iap->ia_mode, rdev);
1360                 break;
1361         }
1362         if (host_err < 0) {
1363 @@ -1284,7 +1294,7 @@ nfsd_create(struct svc_rqst *rqstp, stru
1364                 goto out_nfserr;
1365         }
1366  
1367 -       if (EX_ISSYNC(fhp->fh_export)) {
1368 +       if (EX_ISSYNC(exp)) {
1369                 err = nfserrno(nfsd_sync_dir(dentry));
1370                 write_inode_now(dchild->d_inode, 1);
1371         }
1372 @@ -1514,6 +1524,7 @@ nfsd_symlink(struct svc_rqst *rqstp, str
1373                                 struct iattr *iap)
1374  {
1375         struct dentry   *dentry, *dnew;
1376 +       struct svc_export *exp;
1377         __be32          err, cerr;
1378         int             host_err;
1379  
1380 @@ -1538,6 +1549,7 @@ nfsd_symlink(struct svc_rqst *rqstp, str
1381         if (host_err)
1382                 goto out_nfserr;
1383  
1384 +       exp = fhp->fh_export;
1385         if (unlikely(path[plen] != 0)) {
1386                 char *path_alloced = kmalloc(plen+1, GFP_KERNEL);
1387                 if (path_alloced == NULL)
1388 @@ -1545,14 +1557,16 @@ nfsd_symlink(struct svc_rqst *rqstp, str
1389                 else {
1390                         strncpy(path_alloced, path, plen);
1391                         path_alloced[plen] = 0;
1392 -                       host_err = vfs_symlink(dentry->d_inode, dnew, path_alloced);
1393 +                       host_err = vfs_symlink(dentry->d_inode, dnew,
1394 +                                              exp->ex_path.mnt, path_alloced);
1395                         kfree(path_alloced);
1396                 }
1397         } else
1398 -               host_err = vfs_symlink(dentry->d_inode, dnew, path);
1399 +               host_err = vfs_symlink(dentry->d_inode, dnew, exp->ex_path.mnt,
1400 +                                      path);
1401  
1402         if (!host_err) {
1403 -               if (EX_ISSYNC(fhp->fh_export))
1404 +               if (EX_ISSYNC(exp))
1405                         host_err = nfsd_sync_dir(dentry);
1406         }
1407         err = nfserrno(host_err);
1408 @@ -1560,7 +1574,7 @@ nfsd_symlink(struct svc_rqst *rqstp, str
1409  
1410         mnt_drop_write(fhp->fh_export->ex_path.mnt);
1411  
1412 -       cerr = fh_compose(resfhp, fhp->fh_export, dnew, fhp);
1413 +       cerr = fh_compose(resfhp, exp, dnew, fhp);
1414         dput(dnew);
1415         if (err==0) err = cerr;
1416  out:
1417 @@ -1615,7 +1629,8 @@ nfsd_link(struct svc_rqst *rqstp, struct
1418                 err = nfserrno(host_err);
1419                 goto out_dput;
1420         }
1421 -       host_err = vfs_link(dold, dirp, dnew);
1422 +       host_err = vfs_link(dold, tfhp->fh_export->ex_path.mnt, dirp,
1423 +                           dnew, ffhp->fh_export->ex_path.mnt);
1424         if (!host_err) {
1425                 if (EX_ISSYNC(ffhp->fh_export)) {
1426                         err = nfserrno(nfsd_sync_dir(ddir));
1427 @@ -1716,7 +1731,8 @@ nfsd_rename(struct svc_rqst *rqstp, stru
1428         if (host_err)
1429                 goto out_dput_new;
1430  
1431 -       host_err = vfs_rename(fdir, odentry, tdir, ndentry);
1432 +       host_err = vfs_rename(fdir, odentry, ffhp->fh_export->ex_path.mnt,
1433 +                             tdir, ndentry, tfhp->fh_export->ex_path.mnt);
1434         if (!host_err && EX_ISSYNC(tfhp->fh_export)) {
1435                 host_err = nfsd_sync_dir(tdentry);
1436                 if (!host_err)
1437 @@ -1754,6 +1770,7 @@ nfsd_unlink(struct svc_rqst *rqstp, stru
1438                                 char *fname, int flen)
1439  {
1440         struct dentry   *dentry, *rdentry;
1441 +       struct svc_export *exp;
1442         struct inode    *dirp;
1443         __be32          err;
1444         int             host_err;
1445 @@ -1768,6 +1785,7 @@ nfsd_unlink(struct svc_rqst *rqstp, stru
1446         fh_lock_nested(fhp, I_MUTEX_PARENT);
1447         dentry = fhp->fh_dentry;
1448         dirp = dentry->d_inode;
1449 +       exp = fhp->fh_export;
1450  
1451         rdentry = lookup_one_len(fname, dentry, flen);
1452         host_err = PTR_ERR(rdentry);
1453 @@ -1789,21 +1807,21 @@ nfsd_unlink(struct svc_rqst *rqstp, stru
1454  
1455         if (type != S_IFDIR) { /* It's UNLINK */
1456  #ifdef MSNFS
1457 -               if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
1458 +               if ((exp->ex_flags & NFSEXP_MSNFS) &&
1459                         (atomic_read(&rdentry->d_count) > 1)) {
1460                         host_err = -EPERM;
1461                 } else
1462  #endif
1463 -               host_err = vfs_unlink(dirp, rdentry);
1464 +               host_err = vfs_unlink(dirp, rdentry, exp->ex_path.mnt);
1465         } else { /* It's RMDIR */
1466 -               host_err = vfs_rmdir(dirp, rdentry);
1467 +               host_err = vfs_rmdir(dirp, rdentry, exp->ex_path.mnt);
1468         }
1469  
1470         dput(rdentry);
1471  
1472         if (host_err)
1473                 goto out_drop;
1474 -       if (EX_ISSYNC(fhp->fh_export))
1475 +       if (EX_ISSYNC(exp))
1476                 host_err = nfsd_sync_dir(dentry);
1477  
1478  out_drop:
1479 @@ -2036,7 +2054,8 @@ nfsd_get_posix_acl(struct svc_fh *fhp, i
1480                 return ERR_PTR(-EOPNOTSUPP);
1481         }
1482  
1483 -       size = nfsd_getxattr(fhp->fh_dentry, name, &value);
1484 +       size = nfsd_getxattr(fhp->fh_dentry, fhp->fh_export->ex_path.mnt, name,
1485 +                            &value);
1486         if (size < 0)
1487                 return ERR_PTR(size);
1488  
1489 @@ -2048,6 +2067,7 @@ nfsd_get_posix_acl(struct svc_fh *fhp, i
1490  int
1491  nfsd_set_posix_acl(struct svc_fh *fhp, int type, struct posix_acl *acl)
1492  {
1493 +       struct vfsmount *mnt;
1494         struct inode *inode = fhp->fh_dentry->d_inode;
1495         char *name;
1496         void *value = NULL;
1497 @@ -2080,21 +2100,24 @@ nfsd_set_posix_acl(struct svc_fh *fhp, i
1498         } else
1499                 size = 0;
1500  
1501 -       error = mnt_want_write(fhp->fh_export->ex_path.mnt);
1502 +       mnt = fhp->fh_export->ex_path.mnt;
1503 +       error = mnt_want_write(mnt);
1504         if (error)
1505                 goto getout;
1506         if (size)
1507 -               error = vfs_setxattr(fhp->fh_dentry, name, value, size, 0);
1508 +               error = vfs_setxattr(fhp->fh_dentry, mnt, name, value, size, 0,
1509 +                                    NULL);
1510         else {
1511                 if (!S_ISDIR(inode->i_mode) && type == ACL_TYPE_DEFAULT)
1512                         error = 0;
1513                 else {
1514 -                       error = vfs_removexattr(fhp->fh_dentry, name);
1515 +                       error = vfs_removexattr(fhp->fh_dentry, mnt, name,
1516 +                                               NULL);
1517                         if (error == -ENODATA)
1518                                 error = 0;
1519                 }
1520         }
1521 -       mnt_drop_write(fhp->fh_export->ex_path.mnt);
1522 +       mnt_drop_write(mnt);
1523  
1524  getout:
1525         kfree(value);
1526 diff -uprN linux-2.6.27./fs/open.c linux-2.6.27/fs/open.c
1527 --- linux-2.6.27./fs/open.c     2008-10-10 00:13:53.000000000 +0200
1528 +++ linux-2.6.27/fs/open.c      2008-10-29 02:02:02.243218277 +0100
1529 @@ -197,8 +197,8 @@ out:
1530         return error;
1531  }
1532  
1533 -int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
1534 -       struct file *filp)
1535 +int do_truncate(struct dentry *dentry, struct vfsmount *mnt, loff_t length,
1536 +               unsigned int time_attrs, struct file *filp)
1537  {
1538         int err;
1539         struct iattr newattrs;
1540 @@ -209,16 +209,15 @@ int do_truncate(struct dentry *dentry, l
1541  
1542         newattrs.ia_size = length;
1543         newattrs.ia_valid = ATTR_SIZE | time_attrs;
1544 -       if (filp) {
1545 -               newattrs.ia_file = filp;
1546 +
1547 +       if (filp)
1548                 newattrs.ia_valid |= ATTR_FILE;
1549 -       }
1550  
1551         /* Remove suid/sgid on truncate too */
1552         newattrs.ia_valid |= should_remove_suid(dentry);
1553  
1554         mutex_lock(&dentry->d_inode->i_mutex);
1555 -       err = notify_change(dentry, &newattrs);
1556 +       err = fnotify_change(dentry, mnt, &newattrs, filp);
1557         mutex_unlock(&dentry->d_inode->i_mutex);
1558         return err;
1559  }
1560 @@ -251,7 +250,7 @@ static long do_sys_truncate(const char _
1561         if (error)
1562                 goto dput_and_out;
1563  
1564 -       error = inode_permission(inode, MAY_WRITE);
1565 +       error = path_permission(&path, MAY_WRITE);
1566         if (error)
1567                 goto mnt_drop_write_and_out;
1568  
1569 @@ -274,7 +273,7 @@ static long do_sys_truncate(const char _
1570         error = locks_verify_truncate(inode, NULL, length);
1571         if (!error) {
1572                 DQUOT_INIT(inode);
1573 -               error = do_truncate(path.dentry, length, 0, NULL);
1574 +               error = do_truncate(path.dentry, path.mnt, length, 0, NULL);
1575         }
1576  
1577  put_write_and_out:
1578 @@ -329,7 +328,8 @@ static long do_sys_ftruncate(unsigned in
1579  
1580         error = locks_verify_truncate(inode, file, length);
1581         if (!error)
1582 -               error = do_truncate(dentry, length, ATTR_MTIME|ATTR_CTIME, file);
1583 +               error = do_truncate(dentry, file->f_path.mnt, length,
1584 +                                   ATTR_MTIME|ATTR_CTIME, file);
1585  out_putf:
1586         fput(file);
1587  out:
1588 @@ -474,7 +474,7 @@ asmlinkage long sys_faccessat(int dfd, c
1589                         goto out_path_release;
1590         }
1591  
1592 -       res = inode_permission(inode, mode | MAY_ACCESS);
1593 +       res = path_permission(&path, mode | MAY_ACCESS);
1594         /* SuS v2 requires we report a read only fs too */
1595         if (res || !(mode & S_IWOTH) || special_file(inode->i_mode))
1596                 goto out_path_release;
1597 @@ -517,7 +517,7 @@ asmlinkage long sys_chdir(const char __u
1598         if (error)
1599                 goto out;
1600  
1601 -       error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_ACCESS);
1602 +       error = path_permission(&path, MAY_EXEC | MAY_ACCESS);
1603         if (error)
1604                 goto dput_and_out;
1605  
1606 @@ -546,7 +546,7 @@ asmlinkage long sys_fchdir(unsigned int 
1607         if (!S_ISDIR(inode->i_mode))
1608                 goto out_putf;
1609  
1610 -       error = inode_permission(inode, MAY_EXEC | MAY_ACCESS);
1611 +       error = path_permission(&file->f_path, MAY_EXEC | MAY_ACCESS);
1612  
1613         if (!error && !gr_chroot_fchdir(file->f_path.dentry, file->f_path.mnt))
1614                 error = -EPERM;
1615 @@ -564,7 +564,7 @@ asmlinkage long sys_chroot(const char __
1616         if (error)
1617                 goto out;
1618  
1619 -       error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_ACCESS);
1620 +       error = path_permission(&path, MAY_EXEC | MAY_ACCESS);
1621         if (error)
1622                 goto dput_and_out;
1623  
1624 @@ -604,8 +604,8 @@ asmlinkage long sys_fchmod(unsigned int 
1625         if (mode == (mode_t) -1)
1626                 mode = inode->i_mode;
1627         newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
1628 -       newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
1629 -       err = notify_change(dentry, &newattrs);
1630 +       newattrs.ia_valid = ATTR_MODE | ATTR_CTIME | ATTR_FILE;
1631 +       err = fnotify_change(dentry, file->f_path.mnt, &newattrs, file);
1632         mutex_unlock(&inode->i_mutex);
1633         mnt_drop_write(file->f_path.mnt);
1634  out_putf:
1635 @@ -635,7 +635,7 @@ asmlinkage long sys_fchmodat(int dfd, co
1636                 mode = inode->i_mode;
1637         newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
1638         newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
1639 -       error = notify_change(path.dentry, &newattrs);
1640 +       error = notify_change(path.dentry, path.mnt, &newattrs);
1641         mutex_unlock(&inode->i_mutex);
1642         mnt_drop_write(path.mnt);
1643  dput_and_out:
1644 @@ -649,7 +649,8 @@ asmlinkage long sys_chmod(const char __u
1645         return sys_fchmodat(AT_FDCWD, filename, mode);
1646  }
1647  
1648 -static int chown_common(struct dentry * dentry, uid_t user, gid_t group, struct vfsmount *mnt)
1649 +static int chown_common(struct dentry * dentry, struct vfsmount *mnt,
1650 +                       uid_t user, gid_t group, struct file *file)
1651  {
1652         struct inode *inode = dentry->d_inode;
1653         int error;
1654 @@ -667,8 +668,11 @@ static int chown_common(struct dentry * 
1655         if (!S_ISDIR(inode->i_mode))
1656                 newattrs.ia_valid |=
1657                         ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;
1658 +       if (file)
1659 +               newattrs.ia_valid |= ATTR_FILE;
1660 +
1661         mutex_lock(&inode->i_mutex);
1662 -       error = notify_change(dentry, &newattrs);
1663 +       error = fnotify_change(dentry, mnt, &newattrs, file);
1664         mutex_unlock(&inode->i_mutex);
1665  
1666         return error;
1667 @@ -685,7 +689,7 @@ asmlinkage long sys_chown(const char __u
1668         error = cow_check_and_break(&path);
1669         if (!error)
1670  #endif
1671 -               error = chown_common(path.dentry, user, group, path.mnt);
1672 +               error = chown_common(path.dentry, path.mnt, user, group, NULL);
1673         mnt_drop_write(path.mnt);
1674  out_release:
1675         path_put(&path);
1676 @@ -710,7 +714,7 @@ asmlinkage long sys_fchownat(int dfd, co
1677         error = cow_check_and_break(&path);
1678         if (!error)
1679  #endif
1680 -               error = chown_common(path.dentry, user, group, path.mnt);
1681 +               error = chown_common(path.dentry, path.mnt, user, group, NULL);
1682         mnt_drop_write(path.mnt);
1683  out_release:
1684         path_put(&path);
1685 @@ -729,7 +733,7 @@ asmlinkage long sys_lchown(const char __
1686         error = cow_check_and_break(&path);
1687         if (!error)
1688  #endif
1689 -               error = chown_common(path.dentry, user, group, path.mnt);
1690 +               error = chown_common(path.dentry, path.mnt, user, group, NULL);
1691         mnt_drop_write(path.mnt);
1692  out_release:
1693         path_put(&path);
1694 @@ -753,7 +757,7 @@ asmlinkage long sys_fchown(unsigned int 
1695                 goto out_fput;
1696         dentry = file->f_path.dentry;
1697         audit_inode(NULL, dentry);
1698 -       error = chown_common(dentry, user, group, file->f_path.mnt);
1699 +       error = chown_common(dentry, file->f_path.mnt, user, group, file);
1700         mnt_drop_write(file->f_path.mnt);
1701  out_fput:
1702         fput(file);
1703 diff -uprN linux-2.6.27./fs/reiserfs/xattr.c linux-2.6.27/fs/reiserfs/xattr.c
1704 --- linux-2.6.27./fs/reiserfs/xattr.c   2008-10-10 00:13:53.000000000 +0200
1705 +++ linux-2.6.27/fs/reiserfs/xattr.c    2008-10-29 02:02:00.436006183 +0100
1706 @@ -459,7 +459,7 @@ reiserfs_xattr_set(struct inode *inode, 
1707         newattrs.ia_size = buffer_size;
1708         newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
1709         mutex_lock_nested(&xinode->i_mutex, I_MUTEX_XATTR);
1710 -       err = notify_change(dentry, &newattrs);
1711 +       err = notify_change(dentry, NULL, &newattrs);
1712         if (err)
1713                 goto out_filp;
1714  
1715 @@ -746,7 +746,7 @@ int reiserfs_delete_xattrs(struct inode 
1716         if (dir->d_inode->i_nlink <= 2) {
1717                 root = get_xa_root(inode->i_sb, XATTR_REPLACE);
1718                 reiserfs_write_lock_xattrs(inode->i_sb);
1719 -               err = vfs_rmdir(root->d_inode, dir);
1720 +               err = vfs_rmdir(root->d_inode, dir, NULL);
1721                 reiserfs_write_unlock_xattrs(inode->i_sb);
1722                 dput(root);
1723         } else {
1724 @@ -790,7 +790,7 @@ reiserfs_chown_xattrs_filler(void *buf, 
1725         }
1726  
1727         if (!S_ISDIR(xafile->d_inode->i_mode))
1728 -               err = notify_change(xafile, attrs);
1729 +           err = notify_change(xafile, NULL, attrs);
1730         dput(xafile);
1731  
1732         return err;
1733 @@ -834,7 +834,7 @@ int reiserfs_chown_xattrs(struct inode *
1734                 goto out_dir;
1735         }
1736  
1737 -       err = notify_change(dir, attrs);
1738 +       err = notify_change(dir, NULL, attrs);
1739         unlock_kernel();
1740  
1741        out_dir:
1742 diff -uprN linux-2.6.27./fs/seq_file.c linux-2.6.27/fs/seq_file.c
1743 --- linux-2.6.27./fs/seq_file.c 2008-10-10 00:13:53.000000000 +0200
1744 +++ linux-2.6.27/fs/seq_file.c  2008-10-29 02:02:01.616216002 +0100
1745 @@ -412,9 +412,7 @@ int seq_path_root(struct seq_file *m, st
1746                 char *s = m->buf + m->count;
1747                 char *p;
1748  
1749 -               spin_lock(&dcache_lock);
1750 -               p = __d_path(path, root, s, m->size - m->count);
1751 -               spin_unlock(&dcache_lock);
1752 +               p = __d_path(path, root, s, m->size - m->count, 0);
1753                 err = PTR_ERR(p);
1754                 if (!IS_ERR(p)) {
1755                         s = mangle_path(s, p, esc);
1756 diff -uprN linux-2.6.27./fs/stat.c linux-2.6.27/fs/stat.c
1757 --- linux-2.6.27./fs/stat.c     2008-10-10 00:13:53.000000000 +0200
1758 +++ linux-2.6.27/fs/stat.c      2008-10-29 02:02:00.123187352 +0100
1759 @@ -306,7 +306,7 @@ asmlinkage long sys_readlinkat(int dfd, 
1760  
1761                 error = -EINVAL;
1762                 if (inode->i_op && inode->i_op->readlink) {
1763 -                       error = security_inode_readlink(path.dentry);
1764 +                       error = security_inode_readlink(path.dentry, path.mnt);
1765                         if (!error) {
1766                                 touch_atime(path.mnt, path.dentry);
1767                                 error = inode->i_op->readlink(path.dentry,
1768 diff -uprN linux-2.6.27./fs/utimes.c linux-2.6.27/fs/utimes.c
1769 --- linux-2.6.27./fs/utimes.c   2008-10-10 00:13:53.000000000 +0200
1770 +++ linux-2.6.27/fs/utimes.c    2008-10-29 02:02:01.893015871 +0100
1771 @@ -48,7 +48,8 @@ static bool nsec_valid(long nsec)
1772         return nsec >= 0 && nsec <= 999999999;
1773  }
1774  
1775 -static int utimes_common(struct path *path, struct timespec *times)
1776 +static int utimes_common(struct path *path, struct timespec *times,
1777 +                        struct file *f)
1778  {
1779         int error;
1780         struct iattr newattrs;
1781 @@ -102,7 +103,7 @@ static int utimes_common(struct path *pa
1782                 }
1783         }
1784         mutex_lock(&inode->i_mutex);
1785 -       error = notify_change(path->dentry, &newattrs);
1786 +       error = fnotify_change(path->dentry, path->mnt, &newattrs, f);
1787         mutex_unlock(&inode->i_mutex);
1788  
1789  mnt_drop_write_and_out:
1790 @@ -149,7 +150,7 @@ long do_utimes(int dfd, char __user *fil
1791                 if (!file)
1792                         goto out;
1793  
1794 -               error = utimes_common(&file->f_path, times);
1795 +               error = utimes_common(&file->f_path, times, file);
1796                 fput(file);
1797         } else {
1798                 struct path path;
1799 @@ -162,7 +163,7 @@ long do_utimes(int dfd, char __user *fil
1800                 if (error)
1801                         goto out;
1802  
1803 -               error = utimes_common(&path, times);
1804 +               error = utimes_common(&path, times, NULL);
1805                 path_put(&path);
1806         }
1807  
1808 diff -uprN linux-2.6.27./fs/xattr.c linux-2.6.27/fs/xattr.c
1809 --- linux-2.6.27./fs/xattr.c    2008-10-10 00:13:53.000000000 +0200
1810 +++ linux-2.6.27/fs/xattr.c     2008-10-29 02:02:01.962882939 +0100
1811 @@ -67,8 +67,8 @@ xattr_permission(struct inode *inode, co
1812  }
1813  
1814  int
1815 -vfs_setxattr(struct dentry *dentry, const char *name, const void *value,
1816 -               size_t size, int flags)
1817 +vfs_setxattr(struct dentry *dentry, struct vfsmount *mnt, const char *name,
1818 +            const void *value, size_t size, int flags, struct file *file)
1819  {
1820         struct inode *inode = dentry->d_inode;
1821         int error;
1822 @@ -78,7 +78,7 @@ vfs_setxattr(struct dentry *dentry, cons
1823                 return error;
1824  
1825         mutex_lock(&inode->i_mutex);
1826 -       error = security_inode_setxattr(dentry, name, value, size, flags);
1827 +       error = security_inode_setxattr(dentry, mnt, name, value, size, flags,                                          file);
1828         if (error)
1829                 goto out;
1830         error = -EOPNOTSUPP;
1831 @@ -86,7 +86,7 @@ vfs_setxattr(struct dentry *dentry, cons
1832                 error = inode->i_op->setxattr(dentry, name, value, size, flags);
1833                 if (!error) {
1834                         fsnotify_xattr(dentry);
1835 -                       security_inode_post_setxattr(dentry, name, value,
1836 +                       security_inode_post_setxattr(dentry, mnt, name, value,
1837                                                      size, flags);
1838                 }
1839         } else if (!strncmp(name, XATTR_SECURITY_PREFIX,
1840 @@ -131,7 +131,8 @@ out_noalloc:
1841  EXPORT_SYMBOL_GPL(xattr_getsecurity);
1842  
1843  ssize_t
1844 -vfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size)
1845 +vfs_getxattr(struct dentry *dentry, struct vfsmount *mnt, const char *name,
1846 +            void *value, size_t size, struct file *file)
1847  {
1848         struct inode *inode = dentry->d_inode;
1849         int error;
1850 @@ -140,7 +141,7 @@ vfs_getxattr(struct dentry *dentry, cons
1851         if (error)
1852                 return error;
1853  
1854 -       error = security_inode_getxattr(dentry, name);
1855 +       error = security_inode_getxattr(dentry, mnt, name, file);
1856         if (error)
1857                 return error;
1858  
1859 @@ -167,18 +168,20 @@ nolsm:
1860  EXPORT_SYMBOL_GPL(vfs_getxattr);
1861  
1862  ssize_t
1863 -vfs_listxattr(struct dentry *d, char *list, size_t size)
1864 +vfs_listxattr(struct dentry *dentry, struct vfsmount *mnt, char *list,
1865 +             size_t size, struct file *file)
1866  {
1867 +       struct inode *inode = dentry->d_inode;
1868         ssize_t error;
1869  
1870 -       error = security_inode_listxattr(d);
1871 +       error = security_inode_listxattr(dentry, mnt, file);
1872         if (error)
1873                 return error;
1874         error = -EOPNOTSUPP;
1875 -       if (d->d_inode->i_op && d->d_inode->i_op->listxattr) {
1876 -               error = d->d_inode->i_op->listxattr(d, list, size);
1877 -       } else {
1878 -               error = security_inode_listsecurity(d->d_inode, list, size);
1879 +       if (inode->i_op && inode->i_op->listxattr)
1880 +               error = inode->i_op->listxattr(dentry, list, size);
1881 +       else {
1882 +               error = security_inode_listsecurity(inode, list, size);
1883                 if (size && error > size)
1884                         error = -ERANGE;
1885         }
1886 @@ -187,7 +190,8 @@ vfs_listxattr(struct dentry *d, char *li
1887  EXPORT_SYMBOL_GPL(vfs_listxattr);
1888  
1889  int
1890 -vfs_removexattr(struct dentry *dentry, const char *name)
1891 +vfs_removexattr(struct dentry *dentry, struct vfsmount *mnt, const char *name,
1892 +               struct file *file)
1893  {
1894         struct inode *inode = dentry->d_inode;
1895         int error;
1896 @@ -199,7 +203,7 @@ vfs_removexattr(struct dentry *dentry, c
1897         if (error)
1898                 return error;
1899  
1900 -       error = security_inode_removexattr(dentry, name);
1901 +       error = security_inode_removexattr(dentry, mnt, name, file);
1902         if (error)
1903                 return error;
1904  
1905 @@ -218,8 +222,8 @@ EXPORT_SYMBOL_GPL(vfs_removexattr);
1906   * Extended attribute SET operations
1907   */
1908  static long
1909 -setxattr(struct dentry *d, const char __user *name, const void __user *value,
1910 -        size_t size, int flags)
1911 +setxattr(struct dentry *dentry, struct vfsmount *mnt, const char __user *name,
1912 +        const void __user *value, size_t size, int flags, struct file *file)
1913  {
1914         int error;
1915         void *kvalue = NULL;
1916 @@ -246,7 +250,7 @@ setxattr(struct dentry *d, const char __
1917                 }
1918         }
1919  
1920 -       error = vfs_setxattr(d, kname, kvalue, size, flags);
1921 +       error = vfs_setxattr(dentry, mnt, kname, kvalue, size, flags, file);
1922         kfree(kvalue);
1923         return error;
1924  }
1925 @@ -263,7 +267,7 @@ sys_setxattr(const char __user *pathname
1926                 return error;
1927         error = mnt_want_write(path.mnt);
1928         if (!error) {
1929 -               error = setxattr(path.dentry, name, value, size, flags);
1930 +               error = setxattr(path.dentry, path.mnt, name, value, size, flags, NULL);
1931                 mnt_drop_write(path.mnt);
1932         }
1933         path_put(&path);
1934 @@ -282,7 +286,7 @@ sys_lsetxattr(const char __user *pathnam
1935                 return error;
1936         error = mnt_want_write(path.mnt);
1937         if (!error) {
1938 -               error = setxattr(path.dentry, name, value, size, flags);
1939 +               error = setxattr(path.dentry, path.mnt, name, value, size, flags, NULL);
1940                 mnt_drop_write(path.mnt);
1941         }
1942         path_put(&path);
1943 @@ -304,7 +308,8 @@ sys_fsetxattr(int fd, const char __user 
1944         audit_inode(NULL, dentry);
1945         error = mnt_want_write(f->f_path.mnt);
1946         if (!error) {
1947 -               error = setxattr(dentry, name, value, size, flags);
1948 +               error = setxattr(dentry, f->f_vfsmnt, name, value, size, flags,
1949 +                                f);
1950                 mnt_drop_write(f->f_path.mnt);
1951         }
1952         fput(f);
1953 @@ -315,8 +320,8 @@ sys_fsetxattr(int fd, const char __user 
1954   * Extended attribute GET operations
1955   */
1956  static ssize_t
1957 -getxattr(struct dentry *d, const char __user *name, void __user *value,
1958 -        size_t size)
1959 +getxattr(struct dentry *dentry, struct vfsmount *mnt, const char __user *name,
1960 +        void __user *value, size_t size, struct file *file)
1961  {
1962         ssize_t error;
1963         void *kvalue = NULL;
1964 @@ -336,7 +341,7 @@ getxattr(struct dentry *d, const char __
1965                         return -ENOMEM;
1966         }
1967  
1968 -       error = vfs_getxattr(d, kname, kvalue, size);
1969 +       error = vfs_getxattr(dentry, mnt, kname, kvalue, size, file);
1970         if (error > 0) {
1971                 if (size && copy_to_user(value, kvalue, error))
1972                         error = -EFAULT;
1973 @@ -359,7 +364,7 @@ sys_getxattr(const char __user *pathname
1974         error = user_path(pathname, &path);
1975         if (error)
1976                 return error;
1977 -       error = getxattr(path.dentry, name, value, size);
1978 +       error = getxattr(path.dentry, path.mnt, name, value, size, NULL);
1979         path_put(&path);
1980         return error;
1981  }
1982 @@ -374,7 +379,7 @@ sys_lgetxattr(const char __user *pathnam
1983         error = user_lpath(pathname, &path);
1984         if (error)
1985                 return error;
1986 -       error = getxattr(path.dentry, name, value, size);
1987 +       error = getxattr(path.dentry, path.mnt, name, value, size, NULL);
1988         path_put(&path);
1989         return error;
1990  }
1991 @@ -389,7 +394,7 @@ sys_fgetxattr(int fd, const char __user 
1992         if (!f)
1993                 return error;
1994         audit_inode(NULL, f->f_path.dentry);
1995 -       error = getxattr(f->f_path.dentry, name, value, size);
1996 +       error = getxattr(f->f_path.dentry, f->f_path.mnt, name, value, size, f);
1997         fput(f);
1998         return error;
1999  }
2000 @@ -398,7 +403,8 @@ sys_fgetxattr(int fd, const char __user 
2001   * Extended attribute LIST operations
2002   */
2003  static ssize_t
2004 -listxattr(struct dentry *d, char __user *list, size_t size)
2005 +listxattr(struct dentry *dentry, struct vfsmount *mnt, char __user *list,
2006 +         size_t size, struct file *file)
2007  {
2008         ssize_t error;
2009         char *klist = NULL;
2010 @@ -411,7 +417,7 @@ listxattr(struct dentry *d, char __user 
2011                         return -ENOMEM;
2012         }
2013  
2014 -       error = vfs_listxattr(d, klist, size);
2015 +       error = vfs_listxattr(dentry, mnt, klist, size, file);
2016         if (error > 0) {
2017                 if (size && copy_to_user(list, klist, error))
2018                         error = -EFAULT;
2019 @@ -433,7 +439,7 @@ sys_listxattr(const char __user *pathnam
2020         error = user_path(pathname, &path);
2021         if (error)
2022                 return error;
2023 -       error = listxattr(path.dentry, list, size);
2024 +       error = listxattr(path.dentry, path.mnt, list, size, NULL);
2025         path_put(&path);
2026         return error;
2027  }
2028 @@ -447,7 +453,7 @@ sys_llistxattr(const char __user *pathna
2029         error = user_lpath(pathname, &path);
2030         if (error)
2031                 return error;
2032 -       error = listxattr(path.dentry, list, size);
2033 +       error = listxattr(path.dentry, path.mnt, list, size, NULL);
2034         path_put(&path);
2035         return error;
2036  }
2037 @@ -462,7 +468,7 @@ sys_flistxattr(int fd, char __user *list
2038         if (!f)
2039                 return error;
2040         audit_inode(NULL, f->f_path.dentry);
2041 -       error = listxattr(f->f_path.dentry, list, size);
2042 +       error = listxattr(f->f_path.dentry, f->f_path.mnt, list, size, f);
2043         fput(f);
2044         return error;
2045  }
2046 @@ -471,7 +477,8 @@ sys_flistxattr(int fd, char __user *list
2047   * Extended attribute REMOVE operations
2048   */
2049  static long
2050 -removexattr(struct dentry *d, const char __user *name)
2051 +removexattr(struct dentry *dentry, struct vfsmount *mnt,
2052 +           const char __user *name, struct file *file)
2053  {
2054         int error;
2055         char kname[XATTR_NAME_MAX + 1];
2056 @@ -482,7 +489,7 @@ removexattr(struct dentry *d, const char
2057         if (error < 0)
2058                 return error;
2059  
2060 -       return vfs_removexattr(d, kname);
2061 +       return vfs_removexattr(dentry, mnt, kname, file);
2062  }
2063  
2064  asmlinkage long
2065 @@ -496,7 +503,7 @@ sys_removexattr(const char __user *pathn
2066                 return error;
2067         error = mnt_want_write(path.mnt);
2068         if (!error) {
2069 -               error = removexattr(path.dentry, name);
2070 +               error = removexattr(path.dentry, path.mnt, name, NULL);
2071                 mnt_drop_write(path.mnt);
2072         }
2073         path_put(&path);
2074 @@ -514,7 +521,7 @@ sys_lremovexattr(const char __user *path
2075                 return error;
2076         error = mnt_want_write(path.mnt);
2077         if (!error) {
2078 -               error = removexattr(path.dentry, name);
2079 +               error = removexattr(path.dentry, path.mnt, name, NULL);
2080                 mnt_drop_write(path.mnt);
2081         }
2082         path_put(&path);
2083 @@ -535,7 +542,7 @@ sys_fremovexattr(int fd, const char __us
2084         audit_inode(NULL, dentry);
2085         error = mnt_want_write(f->f_path.mnt);
2086         if (!error) {
2087 -               error = removexattr(dentry, name);
2088 +               error = removexattr(dentry, f->f_path.mnt, name, f);
2089                 mnt_drop_write(f->f_path.mnt);
2090         }
2091         fput(f);
2092 diff -uprN linux-2.6.27./include/linux/audit.h linux-2.6.27/include/linux/audit.h
2093 --- linux-2.6.27./include/linux/audit.h 2008-10-10 00:13:53.000000000 +0200
2094 +++ linux-2.6.27/include/linux/audit.h  2008-10-29 02:02:02.266214852 +0100
2095 @@ -33,7 +33,7 @@
2096   * 1200 - 1299 messages internal to the audit daemon
2097   * 1300 - 1399 audit event messages
2098   * 1400 - 1499 SE Linux use
2099 - * 1500 - 1599 kernel LSPP events
2100 + * 1500 - 1599 AppArmor use
2101   * 1600 - 1699 kernel crypto events
2102   * 1700 - 1799 kernel anomaly records
2103   * 1800 - 1999 future kernel use (maybe integrity labels and related events)
2104 @@ -119,6 +119,13 @@
2105  #define AUDIT_MAC_UNLBL_STCADD 1416    /* NetLabel: add a static label */
2106  #define AUDIT_MAC_UNLBL_STCDEL 1417    /* NetLabel: del a static label */
2107  
2108 +#define AUDIT_APPARMOR_AUDIT   1501    /* AppArmor audited grants */
2109 +#define AUDIT_APPARMOR_ALLOWED 1502    /* Allowed Access for learning */
2110 +#define AUDIT_APPARMOR_DENIED  1503
2111 +#define AUDIT_APPARMOR_HINT    1504    /* Process Tracking information */
2112 +#define AUDIT_APPARMOR_STATUS  1505    /* Changes in config */
2113 +#define AUDIT_APPARMOR_ERROR   1506    /* Internal AppArmor Errors */
2114 +
2115  #define AUDIT_FIRST_KERN_ANOM_MSG   1700
2116  #define AUDIT_LAST_KERN_ANOM_MSG    1799
2117  #define AUDIT_ANOM_PROMISCUOUS      1700 /* Device changed promiscuous mode */
2118 @@ -545,6 +552,9 @@ extern void             audit_log(struct audit_
2119                                       __attribute__((format(printf,4,5)));
2120  
2121  extern struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, int type);
2122 +extern void                audit_log_vformat(struct audit_buffer *ab,
2123 +                                             const char *fmt, va_list args)
2124 +                           __attribute__((format(printf,2,0)));
2125  extern void                audit_log_format(struct audit_buffer *ab,
2126                                              const char *fmt, ...)
2127                             __attribute__((format(printf,2,3)));
2128 diff -uprN linux-2.6.27./include/linux/dcache.h linux-2.6.27/include/linux/dcache.h
2129 --- linux-2.6.27./include/linux/dcache.h        2008-10-10 00:13:53.000000000 +0200
2130 +++ linux-2.6.27/include/linux/dcache.h 2008-10-29 02:02:01.634722088 +0100
2131 @@ -299,9 +299,12 @@ extern int d_validate(struct dentry *, s
2132  /*
2133   * helper function for dentry_operations.d_dname() members
2134   */
2135 +#define D_PATH_FAIL_DELETED 1
2136 +#define D_PATH_DISCONNECT   2
2137  extern char *dynamic_dname(struct dentry *, char *, int, const char *, ...);
2138  
2139 -extern char *__d_path(const struct path *path, struct path *root, char *, int);
2140 +extern char *__d_path(const struct path *path, struct path *root, char *, int,
2141 +                     int);
2142  extern char *d_path(const struct path *, char *, int);
2143  extern char *dentry_path(struct dentry *, char *, int);
2144  
2145 diff -uprN linux-2.6.27./include/linux/fs.h linux-2.6.27/include/linux/fs.h
2146 --- linux-2.6.27./include/linux/fs.h    2008-10-10 00:13:53.000000000 +0200
2147 +++ linux-2.6.27/include/linux/fs.h     2008-10-29 02:02:02.264908196 +0100
2148 @@ -361,6 +361,10 @@ struct iattr {
2149          * Not an attribute, but an auxilary info for filesystems wanting to
2150          * implement an ftruncate() like method.  NOTE: filesystem should
2151          * check for (ia_valid & ATTR_FILE), and not for (ia_file != NULL).
2152 +        *
2153 +        * NOTE: With patches.apparmor/fsetattr.diff applied, this is
2154 +        * for compatibility with external file system modules only. There
2155 +        * should not be any in-kernel users left.
2156          */
2157         struct file     *ia_file;
2158  };
2159 @@ -1160,13 +1164,13 @@ extern void unlock_super(struct super_bl
2160   */
2161  extern int vfs_permission(struct nameidata *, int);
2162  extern int vfs_create(struct inode *, struct dentry *, int, struct nameidata *);
2163 -extern int vfs_mkdir(struct inode *, struct dentry *, int);
2164 -extern int vfs_mknod(struct inode *, struct dentry *, int, dev_t);
2165 -extern int vfs_symlink(struct inode *, struct dentry *, const char *);
2166 -extern int vfs_link(struct dentry *, struct inode *, struct dentry *);
2167 -extern int vfs_rmdir(struct inode *, struct dentry *);
2168 -extern int vfs_unlink(struct inode *, struct dentry *);
2169 -extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
2170 +extern int vfs_mkdir(struct inode *, struct dentry *, struct vfsmount *, int);
2171 +extern int vfs_mknod(struct inode *, struct dentry *, struct vfsmount *, int, dev_t);
2172 +extern int vfs_symlink(struct inode *, struct dentry *, struct vfsmount *, const char *);
2173 +extern int vfs_link(struct dentry *, struct vfsmount *, struct inode *, struct dentry *, struct vfsmount *);
2174 +extern int vfs_rmdir(struct inode *, struct dentry *, struct vfsmount *);
2175 +extern int vfs_unlink(struct inode *, struct dentry *, struct vfsmount *);
2176 +extern int vfs_rename(struct inode *, struct dentry *, struct vfsmount *, struct inode *, struct dentry *, struct vfsmount *);
2177  
2178  /*
2179   * VFS dentry helper functions.
2180 @@ -1179,6 +1183,11 @@ extern void dentry_unhash(struct dentry 
2181  extern int file_permission(struct file *, int);
2182  
2183  /*
2184 + * VFS path helper functions.
2185 + */
2186 +extern int path_permission(struct path *, int);
2187 +
2188 +/*
2189   * File types
2190   *
2191   * NOTE! These match bits 12..15 of stat.st_mode
2192 @@ -1260,6 +1269,7 @@ struct file_operations {
2193         ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
2194         ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
2195         int (*setlease)(struct file *, long, struct file_lock **);
2196 +       int (*fsetattr)(struct file *, struct iattr *);
2197  };
2198  
2199  struct inode_operations {
2200 @@ -1612,8 +1622,8 @@ static inline int break_lease(struct ino
2201  
2202  /* fs/open.c */
2203  
2204 -extern int do_truncate(struct dentry *, loff_t start, unsigned int time_attrs,
2205 -                      struct file *filp);
2206 +extern int do_truncate(struct dentry *, struct vfsmount *, loff_t start,
2207 +                      unsigned int time_attrs, struct file *filp);
2208  extern long do_sys_open(int dfd, const char __user *filename, int flags,
2209                         int mode);
2210  extern struct file *filp_open(const char *, int, int);
2211 @@ -1771,7 +1781,8 @@ extern int do_remount_sb(struct super_bl
2212  #ifdef CONFIG_BLOCK
2213  extern sector_t bmap(struct inode *, sector_t);
2214  #endif
2215 -extern int notify_change(struct dentry *, struct iattr *);
2216 +extern int notify_change(struct dentry *, struct vfsmount *, struct iattr *);
2217 +extern int fnotify_change(struct dentry *, struct vfsmount *, struct iattr *, struct file *);
2218  extern int inode_permission(struct inode *, int);
2219  extern int generic_permission(struct inode *, int,
2220                 int (*check_acl)(struct inode *, int));
2221 diff -uprN linux-2.6.27./include/linux/mount.h linux-2.6.27/include/linux/mount.h
2222 --- linux-2.6.27./include/linux/mount.h 2008-10-10 00:13:53.000000000 +0200
2223 +++ linux-2.6.27/include/linux/mount.h  2008-10-29 02:02:01.674077632 +0100
2224 @@ -114,4 +114,6 @@ extern void mark_mounts_for_expiry(struc
2225  extern spinlock_t vfsmount_lock;
2226  extern dev_t name_to_dev_t(char *name);
2227  
2228 +extern char *d_namespace_path(struct dentry *, struct vfsmount *, char *, int);
2229 +
2230  #endif /* _LINUX_MOUNT_H */
2231 diff -uprN linux-2.6.27./include/linux/nfsd/nfsd.h linux-2.6.27/include/linux/nfsd/nfsd.h
2232 --- linux-2.6.27./include/linux/nfsd/nfsd.h     2008-10-10 00:13:53.000000000 +0200
2233 +++ linux-2.6.27/include/linux/nfsd/nfsd.h      2008-10-29 02:02:01.216214540 +0100
2234 @@ -85,7 +85,8 @@ __be32                nfsd_setattr(struct svc_rqst *, 
2235  #ifdef CONFIG_NFSD_V4
2236  __be32          nfsd4_set_nfs4_acl(struct svc_rqst *, struct svc_fh *,
2237                      struct nfs4_acl *);
2238 -int             nfsd4_get_nfs4_acl(struct svc_rqst *, struct dentry *, struct nfs4_acl **);
2239 +int             nfsd4_get_nfs4_acl(struct svc_rqst *, struct dentry *,
2240 +                               struct vfsmount *mnt, struct nfs4_acl **);
2241  #endif /* CONFIG_NFSD_V4 */
2242  __be32         nfsd_create(struct svc_rqst *, struct svc_fh *,
2243                                 char *name, int len, struct iattr *attrs,
2244 diff -uprN linux-2.6.27./include/linux/security.h linux-2.6.27/include/linux/security.h
2245 --- linux-2.6.27./include/linux/security.h      2008-10-10 00:13:53.000000000 +0200
2246 +++ linux-2.6.27/include/linux/security.h       2008-10-29 02:02:02.149345476 +0100
2247 @@ -54,9 +54,11 @@ extern void cap_capset_set(struct task_s
2248  extern int cap_bprm_set_security(struct linux_binprm *bprm);
2249  extern void cap_bprm_apply_creds(struct linux_binprm *bprm, int unsafe);
2250  extern int cap_bprm_secureexec(struct linux_binprm *bprm);
2251 -extern int cap_inode_setxattr(struct dentry *dentry, const char *name,
2252 -                             const void *value, size_t size, int flags);
2253 -extern int cap_inode_removexattr(struct dentry *dentry, const char *name);
2254 +extern int cap_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
2255 +                             const char *name, const void *value, size_t size,
2256 +                             int flags, struct file *file);
2257 +extern int cap_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
2258 +                                const char *name, struct file *file);
2259  extern int cap_inode_need_killpriv(struct dentry *dentry);
2260  extern int cap_inode_killpriv(struct dentry *dentry);
2261  extern int cap_task_post_setuid(uid_t old_ruid, uid_t old_euid, uid_t old_suid, int flags);
2262 @@ -337,23 +339,28 @@ static inline void security_free_mnt_opt
2263   *     Check permission to create a regular file.
2264   *     @dir contains inode structure of the parent of the new file.
2265   *     @dentry contains the dentry structure for the file to be created.
2266 + *     @mnt is the vfsmount corresponding to @dentry (may be NULL).
2267   *     @mode contains the file mode of the file to be created.
2268   *     Return 0 if permission is granted.
2269   * @inode_link:
2270   *     Check permission before creating a new hard link to a file.
2271   *     @old_dentry contains the dentry structure for an existing link to the file.
2272 + *     @old_mnt is the vfsmount corresponding to @old_dentry (may be NULL).
2273   *     @dir contains the inode structure of the parent directory of the new link.
2274   *     @new_dentry contains the dentry structure for the new link.
2275 + *     @new_mnt is the vfsmount corresponding to @new_dentry (may be NULL).
2276   *     Return 0 if permission is granted.
2277   * @inode_unlink:
2278   *     Check the permission to remove a hard link to a file.
2279   *     @dir contains the inode structure of parent directory of the file.
2280   *     @dentry contains the dentry structure for file to be unlinked.
2281 + *     @mnt is the vfsmount corresponding to @dentry (may be NULL).
2282   *     Return 0 if permission is granted.
2283   * @inode_symlink:
2284   *     Check the permission to create a symbolic link to a file.
2285   *     @dir contains the inode structure of parent directory of the symbolic link.
2286   *     @dentry contains the dentry structure of the symbolic link.
2287 + *     @mnt is the vfsmount corresponding to @dentry (may be NULL).
2288   *     @old_name contains the pathname of file.
2289   *     Return 0 if permission is granted.
2290   * @inode_mkdir:
2291 @@ -361,12 +368,14 @@ static inline void security_free_mnt_opt
2292   *     associated with inode strcture @dir.
2293   *     @dir containst the inode structure of parent of the directory to be created.
2294   *     @dentry contains the dentry structure of new directory.
2295 + *     @mnt is the vfsmount corresponding to @dentry (may be NULL).
2296   *     @mode contains the mode of new directory.
2297   *     Return 0 if permission is granted.
2298   * @inode_rmdir:
2299   *     Check the permission to remove a directory.
2300   *     @dir contains the inode structure of parent of the directory to be removed.
2301   *     @dentry contains the dentry structure of directory to be removed.
2302 + *     @mnt is the vfsmount corresponding to @dentry (may be NULL).
2303   *     Return 0 if permission is granted.
2304   * @inode_mknod:
2305   *     Check permissions when creating a special file (or a socket or a fifo
2306 @@ -375,6 +384,7 @@ static inline void security_free_mnt_opt
2307   *     and not this hook.
2308   *     @dir contains the inode structure of parent of the new file.
2309   *     @dentry contains the dentry structure of the new file.
2310 + *     @mnt is the vfsmount corresponding to @dentry (may be NULL).
2311   *     @mode contains the mode of the new file.
2312   *     @dev contains the device number.
2313   *     Return 0 if permission is granted.
2314 @@ -382,12 +392,15 @@ static inline void security_free_mnt_opt
2315   *     Check for permission to rename a file or directory.
2316   *     @old_dir contains the inode structure for parent of the old link.
2317   *     @old_dentry contains the dentry structure of the old link.
2318 + *     @old_mnt is the vfsmount corresponding to @old_dentry (may be NULL).
2319   *     @new_dir contains the inode structure for parent of the new link.
2320   *     @new_dentry contains the dentry structure of the new link.
2321 + *     @new_mnt is the vfsmount corresponding to @new_dentry (may be NULL).
2322   *     Return 0 if permission is granted.
2323   * @inode_readlink:
2324   *     Check the permission to read the symbolic link.
2325   *     @dentry contains the dentry structure for the file link.
2326 + *     @mnt is the vfsmount corresponding to @dentry (may be NULL).
2327   *     Return 0 if permission is granted.
2328   * @inode_follow_link:
2329   *     Check permission to follow a symbolic link when looking up a pathname.
2330 @@ -411,6 +424,7 @@ static inline void security_free_mnt_opt
2331   *     file attributes change (such as when a file is truncated, chown/chmod
2332   *     operations, transferring disk quotas, etc).
2333   *     @dentry contains the dentry structure for the file.
2334 + *     @mnt is the vfsmount corresponding to @dentry (may be NULL).
2335   *     @attr is the iattr structure containing the new file attributes.
2336   *     Return 0 if permission is granted.
2337   * @inode_getattr:
2338 @@ -426,18 +440,18 @@ static inline void security_free_mnt_opt
2339   *     inode.
2340   * @inode_setxattr:
2341   *     Check permission before setting the extended attributes
2342 - *     @value identified by @name for @dentry.
2343 + *     @value identified by @name for @dentry and @mnt.
2344   *     Return 0 if permission is granted.
2345   * @inode_post_setxattr:
2346   *     Update inode security field after successful setxattr operation.
2347 - *     @value identified by @name for @dentry.
2348 + *     @value identified by @name for @dentry and @mnt.
2349   * @inode_getxattr:
2350   *     Check permission before obtaining the extended attributes
2351 - *     identified by @name for @dentry.
2352 + *     identified by @name for @dentry and @mnt.
2353   *     Return 0 if permission is granted.
2354   * @inode_listxattr:
2355   *     Check permission before obtaining the list of extended attribute
2356 - *     names for @dentry.
2357 + *     names for @dentry and @mnt.
2358   *     Return 0 if permission is granted.
2359   * @inode_removexattr:
2360   *     Check permission before removing the extended attribute
2361 @@ -578,6 +592,20 @@ static inline void security_free_mnt_opt
2362   *     file_permission, and recheck access if anything has changed
2363   *     since inode_permission.
2364   *
2365 + * Security hook for path
2366 + *
2367 + * @path_permission:
2368 + *     Check permission before accessing a path.  This hook is called by the
2369 + *     existing Linux permission function, so a security module can use it to
2370 + *     provide additional checking for existing Linux permission checks.
2371 + *     Notice that this hook is called when a file is opened (as well as many
2372 + *     other operations), whereas the file_security_ops permission hook is
2373 + *     called when the actual read/write operations are performed. This
2374 + *     hook is optional and if absent, inode_permission will be substituted.
2375 + *     @path contains the path structure to check.
2376 + *     @mask contains the permission mask.
2377 + *     Return 0 if permission is granted.
2378 +
2379   * Security hooks for task operations.
2380   *
2381   * @task_create:
2382 @@ -1354,32 +1382,45 @@ struct security_operations {
2383         void (*inode_free_security) (struct inode *inode);
2384         int (*inode_init_security) (struct inode *inode, struct inode *dir,
2385                                     char **name, void **value, size_t *len);
2386 -       int (*inode_create) (struct inode *dir,
2387 -                            struct dentry *dentry, int mode);
2388 -       int (*inode_link) (struct dentry *old_dentry,
2389 -                          struct inode *dir, struct dentry *new_dentry);
2390 -       int (*inode_unlink) (struct inode *dir, struct dentry *dentry);
2391 -       int (*inode_symlink) (struct inode *dir,
2392 -                             struct dentry *dentry, const char *old_name);
2393 -       int (*inode_mkdir) (struct inode *dir, struct dentry *dentry, int mode);
2394 -       int (*inode_rmdir) (struct inode *dir, struct dentry *dentry);
2395 +       int (*inode_create) (struct inode *dir, struct dentry *dentry,
2396 +                            struct vfsmount *mnt, int mode);
2397 +       int (*inode_link) (struct dentry *old_dentry, struct vfsmount *old_mnt,
2398 +                          struct inode *dir, struct dentry *new_dentry,
2399 +                          struct vfsmount *new_mnt);
2400 +       int (*inode_unlink) (struct inode *dir, struct dentry *dentry,
2401 +                            struct vfsmount *mnt);
2402 +       int (*inode_symlink) (struct inode *dir, struct dentry *dentry,
2403 +                             struct vfsmount *mnt, const char *old_name);
2404 +       int (*inode_mkdir) (struct inode *dir, struct dentry *dentry,
2405 +                           struct vfsmount *mnt, int mode);
2406 +       int (*inode_rmdir) (struct inode *dir, struct dentry *dentry,
2407 +                           struct vfsmount *mnt);
2408         int (*inode_mknod) (struct inode *dir, struct dentry *dentry,
2409 -                           int mode, dev_t dev);
2410 +                           struct vfsmount *mnt, int mode, dev_t dev);
2411         int (*inode_rename) (struct inode *old_dir, struct dentry *old_dentry,
2412 -                            struct inode *new_dir, struct dentry *new_dentry);
2413 -       int (*inode_readlink) (struct dentry *dentry);
2414 +                            struct vfsmount *old_mnt,
2415 +                            struct inode *new_dir, struct dentry *new_dentry,
2416 +                            struct vfsmount *new_mnt);
2417 +       int (*inode_readlink) (struct dentry *dentry, struct vfsmount *mnt);
2418         int (*inode_follow_link) (struct dentry *dentry, struct nameidata *nd);
2419         int (*inode_permission) (struct inode *inode, int mask);
2420 -       int (*inode_setattr)    (struct dentry *dentry, struct iattr *attr);
2421 +       int (*inode_setattr)    (struct dentry *dentry, struct vfsmount *,
2422 +                                struct iattr *attr);
2423         int (*inode_getattr) (struct vfsmount *mnt, struct dentry *dentry);
2424         void (*inode_delete) (struct inode *inode);
2425 -       int (*inode_setxattr) (struct dentry *dentry, const char *name,
2426 -                              const void *value, size_t size, int flags);
2427 -       void (*inode_post_setxattr) (struct dentry *dentry, const char *name,
2428 -                                    const void *value, size_t size, int flags);
2429 -       int (*inode_getxattr) (struct dentry *dentry, const char *name);
2430 -       int (*inode_listxattr) (struct dentry *dentry);
2431 -       int (*inode_removexattr) (struct dentry *dentry, const char *name);
2432 +       int (*inode_setxattr) (struct dentry *dentry, struct vfsmount *mnt,
2433 +                              const char *name, const void *value, size_t size,
2434 +                              int flags, struct file *file);
2435 +       void (*inode_post_setxattr) (struct dentry *dentry,
2436 +                                    struct vfsmount *mnt,
2437 +                                    const char *name, const void *value,
2438 +                                    size_t size, int flags);
2439 +       int (*inode_getxattr) (struct dentry *dentry, struct vfsmount *mnt,
2440 +                              const char *name, struct file *file);
2441 +       int (*inode_listxattr) (struct dentry *dentry, struct vfsmount *mnt,
2442 +                               struct file *file);
2443 +       int (*inode_removexattr) (struct dentry *dentry, struct vfsmount *mnt,
2444 +                                 const char *name, struct file *file);
2445         int (*inode_need_killpriv) (struct dentry *dentry);
2446         int (*inode_killpriv) (struct dentry *dentry);
2447         int (*inode_getsecurity) (const struct inode *inode, const char *name, void **buffer, bool alloc);
2448 @@ -1407,6 +1448,7 @@ struct security_operations {
2449                                     struct fown_struct *fown, int sig);
2450         int (*file_receive) (struct file *file);
2451         int (*dentry_open) (struct file *file);
2452 +       int (*path_permission) (struct path *path, int mask);
2453  
2454         int (*task_create) (unsigned long clone_flags);
2455         int (*task_alloc_security) (struct task_struct *p);
2456 @@ -1622,30 +1664,43 @@ int security_inode_alloc(struct inode *i
2457  void security_inode_free(struct inode *inode);
2458  int security_inode_init_security(struct inode *inode, struct inode *dir,
2459                                   char **name, void **value, size_t *len);
2460 -int security_inode_create(struct inode *dir, struct dentry *dentry, int mode);
2461 -int security_inode_link(struct dentry *old_dentry, struct inode *dir,
2462 -                        struct dentry *new_dentry);
2463 -int security_inode_unlink(struct inode *dir, struct dentry *dentry);
2464 +int security_inode_create(struct inode *dir, struct dentry *dentry,
2465 +                         struct vfsmount *mnt, int mode);
2466 +int security_inode_link(struct dentry *old_dentry, struct vfsmount *old_mnt,
2467 +                       struct inode *dir, struct dentry *new_dentry,
2468 +                       struct vfsmount *new_mnt);
2469 +int security_inode_unlink(struct inode *dir, struct dentry *dentry,
2470 +                         struct vfsmount *mnt);
2471  int security_inode_symlink(struct inode *dir, struct dentry *dentry,
2472 -                          const char *old_name);
2473 -int security_inode_mkdir(struct inode *dir, struct dentry *dentry, int mode);
2474 -int security_inode_rmdir(struct inode *dir, struct dentry *dentry);
2475 -int security_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev);
2476 +                          struct vfsmount *mnt, const char *old_name);
2477 +int security_inode_mkdir(struct inode *dir, struct dentry *dentry,
2478 +                        struct vfsmount *mnt, int mode);
2479 +int security_inode_rmdir(struct inode *dir, struct dentry *dentry,
2480 +                        struct vfsmount *mnt);
2481 +int security_inode_mknod(struct inode *dir, struct dentry *dentry,
2482 +                        struct vfsmount *mnt, int mode, dev_t dev);
2483  int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
2484 -                         struct inode *new_dir, struct dentry *new_dentry);
2485 -int security_inode_readlink(struct dentry *dentry);
2486 +                         struct vfsmount *old_mnt, struct inode *new_dir,
2487 +                         struct dentry *new_dentry, struct vfsmount *new_mnt);
2488 +int security_inode_readlink(struct dentry *dentry, struct vfsmount *mnt);
2489  int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd);
2490  int security_inode_permission(struct inode *inode, int mask);
2491 -int security_inode_setattr(struct dentry *dentry, struct iattr *attr);
2492 +int security_inode_setattr(struct dentry *dentry, struct vfsmount *mnt,
2493 +                          struct iattr *attr);
2494  int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry);
2495  void security_inode_delete(struct inode *inode);
2496 -int security_inode_setxattr(struct dentry *dentry, const char *name,
2497 -                           const void *value, size_t size, int flags);
2498 -void security_inode_post_setxattr(struct dentry *dentry, const char *name,
2499 -                                 const void *value, size_t size, int flags);
2500 -int security_inode_getxattr(struct dentry *dentry, const char *name);
2501 -int security_inode_listxattr(struct dentry *dentry);
2502 -int security_inode_removexattr(struct dentry *dentry, const char *name);
2503 +int security_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
2504 +                           const char *name, const void *value,
2505 +                           size_t size, int flags, struct file *file);
2506 +void security_inode_post_setxattr(struct dentry *dentry, struct vfsmount *mnt,
2507 +                                 const char *name, const void *value,
2508 +                                 size_t size, int flags);
2509 +int security_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
2510 +                           const char *name, struct file *file);
2511 +int security_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt,
2512 +                            struct file *file);
2513 +int security_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
2514 +                              const char *name, struct file *file);
2515  int security_inode_need_killpriv(struct dentry *dentry);
2516  int security_inode_killpriv(struct dentry *dentry);
2517  int security_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc);
2518 @@ -1668,6 +1723,7 @@ int security_file_send_sigiotask(struct 
2519                                  struct fown_struct *fown, int sig);
2520  int security_file_receive(struct file *file);
2521  int security_dentry_open(struct file *file);
2522 +int security_path_permission(struct path *path, int mask);
2523  int security_task_create(unsigned long clone_flags);
2524  int security_task_alloc(struct task_struct *p);
2525  void security_task_free(struct task_struct *p);
2526 @@ -1968,26 +2024,31 @@ static inline int security_inode_init_se
2527  
2528  static inline int security_inode_create(struct inode *dir,
2529                                          struct dentry *dentry,
2530 +                                        struct vfsmount *mnt,
2531                                          int mode)
2532  {
2533         return 0;
2534  }
2535  
2536  static inline int security_inode_link(struct dentry *old_dentry,
2537 -                                      struct inode *dir,
2538 -                                      struct dentry *new_dentry)
2539 +                                     struct vfsmount *old_mnt,
2540 +                                     struct inode *dir,
2541 +                                     struct dentry *new_dentry,
2542 +                                     struct vfsmount *new_mnt)
2543  {
2544         return 0;
2545  }
2546  
2547  static inline int security_inode_unlink(struct inode *dir,
2548 -                                        struct dentry *dentry)
2549 +                                       struct dentry *dentry,
2550 +                                       struct vfsmount *mnt)
2551  {
2552         return 0;
2553  }
2554  
2555  static inline int security_inode_symlink(struct inode *dir,
2556                                           struct dentry *dentry,
2557 +                                         struct vfsmount *mnt,
2558                                           const char *old_name)
2559  {
2560         return 0;
2561 @@ -1995,19 +2056,22 @@ static inline int security_inode_symlink
2562  
2563  static inline int security_inode_mkdir(struct inode *dir,
2564                                         struct dentry *dentry,
2565 +                                       struct vfsmount *mnt,
2566                                         int mode)
2567  {
2568         return 0;
2569  }
2570  
2571  static inline int security_inode_rmdir(struct inode *dir,
2572 -                                       struct dentry *dentry)
2573 +                                      struct dentry *dentry,
2574 +                                      struct vfsmount *mnt)
2575  {
2576         return 0;
2577  }
2578  
2579  static inline int security_inode_mknod(struct inode *dir,
2580                                         struct dentry *dentry,
2581 +                                       struct vfsmount *mnt,
2582                                         int mode, dev_t dev)
2583  {
2584         return 0;
2585 @@ -2015,13 +2079,16 @@ static inline int security_inode_mknod(s
2586  
2587  static inline int security_inode_rename(struct inode *old_dir,
2588                                          struct dentry *old_dentry,
2589 +                                        struct vfsmount *old_mnt,
2590                                          struct inode *new_dir,
2591 -                                        struct dentry *new_dentry)
2592 +                                        struct dentry *new_dentry,
2593 +                                        struct vfsmount *new_mnt)
2594  {
2595         return 0;
2596  }
2597  
2598 -static inline int security_inode_readlink(struct dentry *dentry)
2599 +static inline int security_inode_readlink(struct dentry *dentry,
2600 +                                         struct vfsmount *mnt)
2601  {
2602         return 0;
2603  }
2604 @@ -2038,7 +2105,8 @@ static inline int security_inode_permiss
2605  }
2606  
2607  static inline int security_inode_setattr(struct dentry *dentry,
2608 -                                         struct iattr *attr)
2609 +                                        struct vfsmount *mnt,
2610 +                                        struct iattr *attr)
2611  {
2612         return 0;
2613  }
2614 @@ -2053,30 +2121,42 @@ static inline void security_inode_delete
2615  { }
2616  
2617  static inline int security_inode_setxattr(struct dentry *dentry,
2618 -               const char *name, const void *value, size_t size, int flags)
2619 +                                         struct vfsmount *mnt,
2620 +                                         const char *name, const void *value,
2621 +                                         size_t size, int flags,
2622 +                                         struct file *file)
2623  {
2624 -       return cap_inode_setxattr(dentry, name, value, size, flags);
2625 +       return cap_inode_setxattr(dentry, mnt, name, value, size, flags, file);
2626  }
2627  
2628  static inline void security_inode_post_setxattr(struct dentry *dentry,
2629 -               const char *name, const void *value, size_t size, int flags)
2630 +                                               struct vfsmount *mnt,
2631 +                                               const char *name,
2632 +                                               const void *value,
2633 +                                               size_t size, int flags)
2634  { }
2635  
2636  static inline int security_inode_getxattr(struct dentry *dentry,
2637 -                       const char *name)
2638 +                                         struct vfsmount *mnt,
2639 +                                         const char *name,
2640 +                                         struct file *file)
2641  {
2642         return 0;
2643  }
2644  
2645 -static inline int security_inode_listxattr(struct dentry *dentry)
2646 +static inline int security_inode_listxattr(struct dentry *dentry,
2647 +                                          struct vfsmount *mnt,
2648 +                                          struct file *file)
2649  {
2650         return 0;
2651  }
2652  
2653  static inline int security_inode_removexattr(struct dentry *dentry,
2654 -                       const char *name)
2655 +                                            struct vfsmount *mnt,
2656 +                                            const char *name,
2657 +                                            struct file *file)
2658  {
2659 -       return cap_inode_removexattr(dentry, name);
2660 +       return cap_inode_removexattr(dentry, mnt, name, file);
2661  }
2662  
2663  static inline int security_inode_need_killpriv(struct dentry *dentry)
2664 @@ -2177,6 +2257,11 @@ static inline int security_dentry_open(s
2665         return 0;
2666  }
2667  
2668 +static inline int security_path_permission(struct path *path, int mask)
2669 +{
2670 +       return 0;
2671 +}
2672 +
2673  static inline int security_task_create(unsigned long clone_flags)
2674  {
2675         return 0;
2676 diff -uprN linux-2.6.27./include/linux/sysctl.h linux-2.6.27/include/linux/sysctl.h
2677 --- linux-2.6.27./include/linux/sysctl.h        2008-10-10 00:13:53.000000000 +0200
2678 +++ linux-2.6.27/include/linux/sysctl.h 2008-10-29 02:02:02.110260164 +0100
2679 @@ -996,6 +996,8 @@ extern int proc_doulongvec_minmax(struct
2680  extern int proc_doulongvec_ms_jiffies_minmax(struct ctl_table *table, int,
2681                                       struct file *, void __user *, size_t *, loff_t *);
2682  
2683 +extern char *sysctl_pathname(ctl_table *, char *, int);
2684 +
2685  extern int do_sysctl (int __user *name, int nlen,
2686                       void __user *oldval, size_t __user *oldlenp,
2687                       void __user *newval, size_t newlen);
2688 diff -uprN linux-2.6.27./include/linux/xattr.h linux-2.6.27/include/linux/xattr.h
2689 --- linux-2.6.27./include/linux/xattr.h 2008-10-10 00:13:53.000000000 +0200
2690 +++ linux-2.6.27/include/linux/xattr.h  2008-10-29 02:02:01.996215347 +0100
2691 @@ -16,6 +16,8 @@
2692  #ifdef  __KERNEL__
2693  
2694  #include <linux/types.h>
2695 +#include <linux/mount.h>
2696 +#include <linux/fs.h>
2697  
2698  /* Namespaces */
2699  #define XATTR_OS2_PREFIX "os2."
2700 @@ -47,10 +49,10 @@ struct xattr_handler {
2701  };
2702  
2703  ssize_t xattr_getsecurity(struct inode *, const char *, void *, size_t);
2704 -ssize_t vfs_getxattr(struct dentry *, const char *, void *, size_t);
2705 -ssize_t vfs_listxattr(struct dentry *d, char *list, size_t size);
2706 -int vfs_setxattr(struct dentry *, const char *, const void *, size_t, int);
2707 -int vfs_removexattr(struct dentry *, const char *);
2708 +ssize_t vfs_getxattr(struct dentry *, struct vfsmount *, const char *, void *, size_t, struct file *file);
2709 +ssize_t vfs_listxattr(struct dentry *d, struct vfsmount *, char *list, size_t size, struct file *file);
2710 +int vfs_setxattr(struct dentry *, struct vfsmount *, const char *, const void *, size_t, int, struct file *file);
2711 +int vfs_removexattr(struct dentry *, struct vfsmount *mnt, const char *, struct file *file);
2712  
2713  ssize_t generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size);
2714  ssize_t generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size);
2715 diff -uprN linux-2.6.27./ipc/mqueue.c linux-2.6.27/ipc/mqueue.c
2716 --- linux-2.6.27./ipc/mqueue.c  2008-10-10 00:13:53.000000000 +0200
2717 +++ linux-2.6.27/ipc/mqueue.c   2008-10-29 02:02:00.652678045 +0100
2718 @@ -745,7 +745,7 @@ asmlinkage long sys_mq_unlink(const char
2719         err = mnt_want_write(mqueue_mnt);
2720         if (err)
2721                 goto out_err;
2722 -       err = vfs_unlink(dentry->d_parent->d_inode, dentry);
2723 +       err = vfs_unlink(dentry->d_parent->d_inode, dentry, mqueue_mnt);
2724         mnt_drop_write(mqueue_mnt);
2725  out_err:
2726         dput(dentry);
2727 diff -uprN linux-2.6.27./kernel/audit.c linux-2.6.27/kernel/audit.c
2728 --- linux-2.6.27./kernel/audit.c        2008-10-10 00:13:53.000000000 +0200
2729 +++ linux-2.6.27/kernel/audit.c 2008-10-29 02:02:02.282882034 +0100
2730 @@ -1231,8 +1231,7 @@ static inline int audit_expand(struct au
2731   * will be called a second time.  Currently, we assume that a printk
2732   * can't format message larger than 1024 bytes, so we don't either.
2733   */
2734 -static void audit_log_vformat(struct audit_buffer *ab, const char *fmt,
2735 -                             va_list args)
2736 +void audit_log_vformat(struct audit_buffer *ab, const char *fmt, va_list args)
2737  {
2738         int len, avail;
2739         struct sk_buff *skb;
2740 @@ -1506,3 +1505,6 @@ EXPORT_SYMBOL(audit_log_start);
2741  EXPORT_SYMBOL(audit_log_end);
2742  EXPORT_SYMBOL(audit_log_format);
2743  EXPORT_SYMBOL(audit_log);
2744 +EXPORT_SYMBOL_GPL(audit_log_vformat);
2745 +EXPORT_SYMBOL_GPL(audit_log_untrustedstring);
2746 +EXPORT_SYMBOL_GPL(audit_log_d_path);
2747 diff -uprN linux-2.6.27./kernel/cgroup.c linux-2.6.27/kernel/cgroup.c
2748 --- linux-2.6.27./kernel/cgroup.c       2008-10-10 00:13:53.000000000 +0200
2749 +++ linux-2.6.27/kernel/cgroup.c        2008-10-29 02:01:59.706048714 +0100
2750 @@ -2905,7 +2905,7 @@ int cgroup_clone(struct task_struct *tsk
2751         }
2752  
2753         /* Create the cgroup directory, which also creates the cgroup */
2754 -       ret = vfs_mkdir(inode, dentry, S_IFDIR | 0755);
2755 +       ret = vfs_mkdir(inode, dentry, NULL, S_IFDIR | 0755);
2756         child = __d_cgrp(dentry);
2757         dput(dentry);
2758         if (ret) {
2759 diff -uprN linux-2.6.27./kernel/sysctl.c linux-2.6.27/kernel/sysctl.c
2760 --- linux-2.6.27./kernel/sysctl.c       2008-10-10 00:13:53.000000000 +0200
2761 +++ linux-2.6.27/kernel/sysctl.c        2008-10-29 02:02:02.130590271 +0100
2762 @@ -1506,6 +1506,33 @@ void register_sysctl_root(struct ctl_tab
2763         spin_unlock(&sysctl_lock);
2764  }
2765  
2766 +char *sysctl_pathname(struct ctl_table *table, char *buffer, int buflen)
2767 +{
2768 +       if (buflen < 1)
2769 +               return NULL;
2770 +       buffer += --buflen;
2771 +       *buffer = '\0';
2772 +
2773 +       while (table) {
2774 +               int namelen = strlen(table->procname);
2775 +
2776 +               if (buflen < namelen + 1)
2777 +                       return NULL;
2778 +               buflen -= namelen + 1;
2779 +               buffer -= namelen;
2780 +               memcpy(buffer, table->procname, namelen);
2781 +               *--buffer = '/';
2782 +               table = table->parent;
2783 +       }
2784 +       if (buflen < 4)
2785 +               return NULL;
2786 +       buffer -= 4;
2787 +       memcpy(buffer, "/sys", 4);
2788 +
2789 +       return buffer;
2790 +}
2791 +EXPORT_SYMBOL_GPL(sysctl_pathname);
2792 +
2793  #ifdef CONFIG_SYSCTL_SYSCALL
2794  /* Perform the actual read/write of a sysctl table entry. */
2795  static int do_sysctl_strategy(struct ctl_table_root *root,
2796 diff -uprN linux-2.6.27./mm/filemap.c linux-2.6.27/mm/filemap.c
2797 --- linux-2.6.27./mm/filemap.c  2008-10-10 00:13:53.000000000 +0200
2798 +++ linux-2.6.27/mm/filemap.c   2008-10-29 02:01:59.480174096 +0100
2799 @@ -1760,12 +1760,12 @@ int should_remove_suid(struct dentry *de
2800  }
2801  EXPORT_SYMBOL(should_remove_suid);
2802  
2803 -static int __remove_suid(struct dentry *dentry, int kill)
2804 +static int __remove_suid(struct path *path, int kill)
2805  {
2806         struct iattr newattrs;
2807  
2808         newattrs.ia_valid = ATTR_FORCE | kill;
2809 -       return notify_change(dentry, &newattrs);
2810 +       return notify_change(path->dentry, path->mnt, &newattrs);
2811  }
2812  
2813  int file_remove_suid(struct file *file)
2814 @@ -1780,7 +1780,7 @@ int file_remove_suid(struct file *file)
2815         if (killpriv)
2816                 error = security_inode_killpriv(dentry);
2817         if (!error && killsuid)
2818 -               error = __remove_suid(dentry, killsuid);
2819 +               error = __remove_suid(&file->f_path, killsuid);
2820  
2821         return error;
2822  }
2823 diff -uprN linux-2.6.27./net/unix/af_unix.c linux-2.6.27/net/unix/af_unix.c
2824 --- linux-2.6.27./net/unix/af_unix.c    2008-10-10 00:13:53.000000000 +0200
2825 +++ linux-2.6.27/net/unix/af_unix.c     2008-10-29 02:01:59.886248280 +0100
2826 @@ -827,7 +827,8 @@ static int unix_bind(struct socket *sock
2827                         goto out_mknod_dput;
2828                 }
2829  
2830 -               err = vfs_mknod(nd.path.dentry->d_inode, dentry, mode, 0);
2831 +               err = vfs_mknod(nd.path.dentry->d_inode, dentry, nd.path.mnt,
2832 +                               mode, 0);
2833                 mnt_drop_write(nd.path.mnt);
2834                 if (err)
2835                         goto out_mknod_dput;
2836 diff -uprN linux-2.6.27./security/Kconfig linux-2.6.27/security/Kconfig
2837 --- linux-2.6.27./security/Kconfig      2008-10-10 00:13:53.000000000 +0200
2838 +++ linux-2.6.27/security/Kconfig       2008-10-29 02:02:02.502672932 +0100
2839 @@ -117,6 +117,7 @@ config SECURITY_DEFAULT_MMAP_MIN_ADDR
2840  
2841  source security/selinux/Kconfig
2842  source security/smack/Kconfig
2843 +source security/apparmor/Kconfig
2844  
2845  endmenu
2846  
2847 diff -uprN linux-2.6.27./security/Makefile linux-2.6.27/security/Makefile
2848 --- linux-2.6.27./security/Makefile     2008-10-10 00:13:53.000000000 +0200
2849 +++ linux-2.6.27/security/Makefile      2008-10-29 02:02:02.512881631 +0100
2850 @@ -14,5 +14,6 @@ obj-$(CONFIG_SECURITY)                        += security.o c
2851  # Must precede capability.o in order to stack properly.
2852  obj-$(CONFIG_SECURITY_SELINUX)         += selinux/built-in.o
2853  obj-$(CONFIG_SECURITY_SMACK)           += smack/built-in.o
2854 -obj-$(CONFIG_SECURITY_ROOTPLUG)                += root_plug.o
2855 +obj-$(CONFIG_SECURITY_APPARMOR)         += commoncap.o apparmor/
2856 + obj-$(CONFIG_SECURITY_ROOTPLUG)               += root_plug.o
2857  obj-$(CONFIG_CGROUP_DEVICE)            += device_cgroup.o
2858 diff -uprN linux-2.6.27./security/apparmor/Kconfig linux-2.6.27/security/apparmor/Kconfig
2859 --- linux-2.6.27./security/apparmor/Kconfig     1970-01-01 01:00:00.000000000 +0100
2860 +++ linux-2.6.27/security/apparmor/Kconfig      2008-10-29 14:28:53.319441671 +0100
2861 @@ -0,0 +1,42 @@
2862 +config SECURITY_APPARMOR
2863 +       bool "AppArmor support"
2864 +       depends on SECURITY
2865 +       select AUDIT
2866 +       help
2867 +         This enables the AppArmor security module.
2868 +         Required userspace tools (if they are not included in your
2869 +         distribution) and further information may be found at
2870 +         <http://forge.novell.com/modules/xfmod/project/?apparmor>
2871 +
2872 +         If you are unsure how to answer this question, answer N.
2873 +
2874 +config SECURITY_APPARMOR_BOOTPARAM_VALUE
2875 +       int "AppArmor boot parameter default value"
2876 +       depends on SECURITY_APPARMOR
2877 +       range 0 1
2878 +       default 1
2879 +       help
2880 +         This option sets the default value for the kernel parameter
2881 +         'apparmor', which allows AppArmor to be enabled or disabled
2882 +          at boot.  If this option is set to 0 (zero), the AppArmor
2883 +         kernel parameter will default to 0, disabling AppArmor at
2884 +         bootup.  If this option is set to 1 (one), the AppArmor
2885 +         kernel parameter will default to 1, enabling AppArmor at
2886 +         bootup.
2887 +
2888 +         If you are unsure how to answer this question, answer 1.
2889 +
2890 +config SECURITY_APPARMOR_DISABLE
2891 +       bool "AppArmor runtime disable"
2892 +       depends on SECURITY_APPARMOR
2893 +       default n
2894 +       help
2895 +         This option enables writing to a apparmorfs node 'disable', which
2896 +         allows AppArmor to be disabled at runtime prior to the policy load.
2897 +         AppArmor will then remain disabled until the next boot.
2898 +         This option is similar to the apparmor.enabled=0 boot parameter,
2899 +         but is to support runtime disabling of AppArmor, e.g. from
2900 +         /sbin/init, for portability across platforms where boot
2901 +         parameters are difficult to employ.
2902 +
2903 +         If you are unsure how to answer this question, answer N.
2904 diff -uprN linux-2.6.27./security/apparmor/Makefile linux-2.6.27/security/apparmor/Makefile
2905 --- linux-2.6.27./security/apparmor/Makefile    1970-01-01 01:00:00.000000000 +0100
2906 +++ linux-2.6.27/security/apparmor/Makefile     2008-10-29 14:28:53.322775050 +0100
2907 @@ -0,0 +1,18 @@
2908 +# Makefile for AppArmor Linux Security Module
2909 +#
2910 +obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
2911 +
2912 +apparmor-y := main.o list.o procattr.o lsm.o apparmorfs.o \
2913 +             module_interface.o match.o
2914 +
2915 +quiet_cmd_make-caps = GEN     $@
2916 +cmd_make-caps = sed -n -e "/CAP_FS_MASK/d" -e "s/^\#define[ \\t]\\+CAP_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\$$/[\\2]  = \"\\1\",/p" $< | tr A-Z a-z > $@
2917 +
2918 +quiet_cmd_make-af = GEN     $@
2919 +cmd_make-af = sed -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e "s/^\#define[ \\t]\\+AF_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\\(.*\\)\$$/[\\2]  = \"\\1\",/p" $< | tr A-Z a-z > $@
2920 +
2921 +$(obj)/main.o : $(obj)/capability_names.h $(obj)/af_names.h
2922 +$(obj)/capability_names.h : $(srctree)/include/linux/capability.h
2923 +       $(call cmd,make-caps)
2924 +$(obj)/af_names.h : $(srctree)/include/linux/socket.h
2925 +       $(call cmd,make-af)
2926 diff -uprN linux-2.6.27./security/apparmor/apparmor.h linux-2.6.27/security/apparmor/apparmor.h
2927 --- linux-2.6.27./security/apparmor/apparmor.h  1970-01-01 01:00:00.000000000 +0100
2928 +++ linux-2.6.27/security/apparmor/apparmor.h   2008-10-29 14:28:53.326113825 +0100
2929 @@ -0,0 +1,403 @@
2930 +/*
2931 + *     Copyright (C) 1998-2007 Novell/SUSE
2932 + *
2933 + *     This program is free software; you can redistribute it and/or
2934 + *     modify it under the terms of the GNU General Public License as
2935 + *     published by the Free Software Foundation, version 2 of the
2936 + *     License.
2937 + *
2938 + *     AppArmor internal prototypes
2939 + */
2940 +
2941 +#ifndef __APPARMOR_H
2942 +#define __APPARMOR_H
2943 +
2944 +#include <linux/sched.h>
2945 +#include <linux/fs.h>
2946 +#include <linux/binfmts.h>
2947 +#include <linux/rcupdate.h>
2948 +#include <linux/resource.h>
2949 +#include <linux/socket.h>
2950 +#include <net/sock.h>
2951 +
2952 +/*
2953 + * We use MAY_READ, MAY_WRITE, MAY_EXEC, MAY_APPEND and the following flags
2954 + * for profile permissions
2955 + */
2956 +#define AA_MAY_LINK                    0x0010
2957 +#define AA_MAY_LOCK                    0x0020
2958 +#define AA_EXEC_MMAP                   0x0040
2959 +#define AA_MAY_MOUNT                   0x0080  /* no direct audit mapping */
2960 +#define AA_EXEC_UNSAFE                 0x0100
2961 +#define AA_EXEC_INHERIT                        0x0200
2962 +#define AA_EXEC_MOD_0                  0x0400
2963 +#define AA_EXEC_MOD_1                  0x0800
2964 +#define AA_EXEC_MOD_2                  0x1000
2965 +#define AA_EXEC_MOD_3                  0x2000
2966 +
2967 +#define AA_BASE_PERMS                  (MAY_READ | MAY_WRITE | MAY_EXEC | \
2968 +                                        MAY_APPEND | AA_MAY_LINK | \
2969 +                                        AA_MAY_LOCK | AA_EXEC_MMAP | \
2970 +                                        AA_MAY_MOUNT | AA_EXEC_UNSAFE | \
2971 +                                        AA_EXEC_INHERIT | AA_EXEC_MOD_0 | \
2972 +                                        AA_EXEC_MOD_1 | AA_EXEC_MOD_2 | \
2973 +                                        AA_EXEC_MOD_3)
2974 +
2975 +#define AA_EXEC_MODIFIERS              (AA_EXEC_MOD_0 | AA_EXEC_MOD_1 | \
2976 +                                        AA_EXEC_MOD_2 | AA_EXEC_MOD_3)
2977 +
2978 +#define AA_EXEC_TYPE                   (AA_EXEC_UNSAFE | AA_EXEC_INHERIT | \
2979 +                                        AA_EXEC_MODIFIERS)
2980 +
2981 +#define AA_EXEC_UNCONFINED             AA_EXEC_MOD_0
2982 +#define AA_EXEC_PROFILE                        AA_EXEC_MOD_1
2983 +#define AA_EXEC_CHILD                  (AA_EXEC_MOD_0 | AA_EXEC_MOD_1)
2984 +/* remaining exec modes are index into profile name table */
2985 +#define AA_EXEC_INDEX(mode)            ((mode & AA_EXEC_MODIFIERS) >> 10)
2986 +
2987 +#define AA_USER_SHIFT                  0
2988 +#define AA_OTHER_SHIFT                 14
2989 +
2990 +#define AA_USER_PERMS                  (AA_BASE_PERMS << AA_USER_SHIFT)
2991 +#define AA_OTHER_PERMS                 (AA_BASE_PERMS << AA_OTHER_SHIFT)
2992 +
2993 +#define AA_FILE_PERMS                  (AA_USER_PERMS | AA_OTHER_PERMS)
2994 +
2995 +#define AA_LINK_BITS                   ((AA_MAY_LINK << AA_USER_SHIFT) | \
2996 +                                        (AA_MAY_LINK << AA_OTHER_SHIFT))
2997 +
2998 +#define AA_USER_EXEC                   (MAY_EXEC << AA_USER_SHIFT)
2999 +#define AA_OTHER_EXEC                  (MAY_EXEC << AA_OTHER_SHIFT)
3000 +
3001 +#define AA_USER_EXEC_TYPE              (AA_EXEC_TYPE << AA_USER_SHIFT)
3002 +#define AA_OTHER_EXEC_TYPE             (AA_EXEC_TYPE << AA_OTHER_SHIFT)
3003 +
3004 +#define AA_EXEC_BITS                   (AA_USER_EXEC | AA_OTHER_EXEC)
3005 +
3006 +#define ALL_AA_EXEC_UNSAFE             ((AA_EXEC_UNSAFE << AA_USER_SHIFT) | \
3007 +                                        (AA_EXEC_UNSAFE << AA_OTHER_SHIFT))
3008 +
3009 +#define ALL_AA_EXEC_TYPE               (AA_USER_EXEC_TYPE | AA_OTHER_EXEC_TYPE)
3010 +
3011 +/* overloaded permissions for link pairs */
3012 +#define AA_LINK_SUBSET_TEST            0x0020
3013 +
3014 +#define AA_USER_PTRACE                 0x10000000
3015 +#define AA_OTHER_PTRACE                        0x20000000
3016 +#define AA_PTRACE_PERMS                        (AA_USER_PTRACE | AA_OTHER_PTRACE)
3017 +
3018 +/* shared permissions that are not duplicated in user::other */
3019 +#define AA_CHANGE_HAT                  0x40000000
3020 +#define AA_CHANGE_PROFILE              0x80000000
3021 +
3022 +#define AA_SHARED_PERMS                        (AA_CHANGE_HAT | AA_CHANGE_PROFILE)
3023 +
3024 +#define AA_VALID_PERM_MASK             (AA_FILE_PERMS | AA_PTRACE_PERMS | \
3025 +                                        AA_SHARED_PERMS)
3026 +
3027 +/* audit bits for the second accept field */
3028 +#define AUDIT_FILE_MASK 0x1fc07f
3029 +#define AUDIT_QUIET_MASK(mask)         ((mask >> 7) & AUDIT_FILE_MASK)
3030 +#define AA_VALID_PERM2_MASK            0x0fffffff
3031 +
3032 +#define AA_SECURE_EXEC_NEEDED          1
3033 +
3034 +/* Control parameters (0 or 1), settable thru module/boot flags or
3035 + * via /sys/kernel/security/apparmor/control */
3036 +extern int apparmor_complain;
3037 +extern int apparmor_debug;
3038 +extern int apparmor_audit;
3039 +extern int apparmor_logsyscall;
3040 +extern unsigned int apparmor_path_max;
3041 +
3042 +#define PROFILE_COMPLAIN(_profile) \
3043 +       (apparmor_complain == 1 || ((_profile) && (_profile)->flags.complain))
3044 +
3045 +#define APPARMOR_COMPLAIN(_cxt) \
3046 +       (apparmor_complain == 1 || \
3047 +        ((_cxt) && (_cxt)->profile && (_cxt)->profile->flags.complain))
3048 +
3049 +#define PROFILE_AUDIT(_profile) \
3050 +       (apparmor_audit == 1 || ((_profile) && (_profile)->flags.audit))
3051 +
3052 +#define APPARMOR_AUDIT(_cxt) \
3053 +       (apparmor_audit == 1 || \
3054 +        ((_cxt) && (_cxt)->profile && (_cxt)->profile->flags.audit))
3055 +
3056 +#define PROFILE_IS_HAT(_profile) \
3057 +       ((_profile) && (_profile)->flags.hat)
3058 +
3059 +/*
3060 + * DEBUG remains global (no per profile flag) since it is mostly used in sysctl
3061 + * which is not related to profile accesses.
3062 + */
3063 +
3064 +#define AA_DEBUG(fmt, args...)                                         \
3065 +       do {                                                            \
3066 +               if (apparmor_debug)                                     \
3067 +                       printk(KERN_DEBUG "AppArmor: " fmt, ##args);    \
3068 +       } while (0)
3069 +
3070 +#define AA_ERROR(fmt, args...) do { if (printk_ratelimit()) printk(KERN_ERR "AppArmor: " fmt, ##args); } while (0)
3071 +
3072 +/* struct aa_rlimit - rlimits settings for the profile
3073 + * @mask: which hard limits to set
3074 + * @limits: rlimit values that override task limits
3075 + *
3076 + * AppArmor rlimits are used to set confined task rlimits.  Only the
3077 + * limits specified in @mask will be controlled by apparmor.
3078 + */
3079 +struct aa_rlimit {
3080 +       unsigned int mask;
3081 +       struct rlimit limits[RLIM_NLIMITS];
3082 +};
3083 +
3084 +struct aa_profile;
3085 +
3086 +/* struct aa_namespace - namespace for a set of profiles
3087 + * @name: the name of the namespace
3088 + * @list: list the namespace is on
3089 + * @profiles: list of profile in the namespace
3090 + * @profile_count: the number of profiles in the namespace
3091 + * @null_complain_profile: special profile used for learning in this namespace
3092 + * @count: reference count on the namespace
3093 + * @lock: lock for adding/removing profile to the namespace
3094 + */
3095 +struct aa_namespace {
3096 +       char *name;
3097 +       struct list_head list;
3098 +       struct list_head profiles;
3099 +       int profile_count;
3100 +       struct aa_profile *null_complain_profile;
3101 +
3102 +       struct kref count;
3103 +       rwlock_t lock;
3104 +};
3105 +
3106 +/* struct aa_profile - basic confinement data
3107 + * @name: the profiles name
3108 + * @list: list this profile is on
3109 + * @ns: namespace the profile is in
3110 + * @file_rules: dfa containing the profiles file rules
3111 + * @flags: flags controlling profile behavior
3112 + * @isstale: flag indicating if profile is stale
3113 + * @set_caps: capabilities that are being set
3114 + * @capabilities: capabilities mask
3115 + * @audit_caps: caps that are to be audited
3116 + * @quiet_caps: caps that should not be audited
3117 + * @capabilities: capabilities granted by the process
3118 + * @rlimits: rlimits for the profile
3119 + * @task_count: how many tasks the profile is attached to
3120 + * @count: reference count of the profile
3121 + * @task_contexts: list of tasks confined by profile
3122 + * @lock: lock for the task_contexts list
3123 + * @network_families: basic network permissions
3124 + * @audit_network: which network permissions to force audit
3125 + * @quiet_network: which network permissions to quiet rejects
3126 + *
3127 + * The AppArmor profile contains the basic confinement data.  Each profile
3128 + * has a name, and all nonstale profile are in a profile namespace.
3129 + *
3130 + * The task_contexts list and the isstale flag are protected by the
3131 + * profile lock.
3132 + *
3133 + * If a task context is moved between two profiles, we first need to grab
3134 + * both profile locks. lock_both_profiles() does that in a deadlock-safe
3135 + * way.
3136 + */
3137 +struct aa_profile {
3138 +       char *name;
3139 +       struct list_head list;
3140 +       struct aa_namespace *ns;
3141 +
3142 +       int exec_table_size;
3143 +       char **exec_table;
3144 +       struct aa_dfa *file_rules;
3145 +       struct {
3146 +               int hat;
3147 +               int complain;
3148 +               int audit;
3149 +       } flags;
3150 +       int isstale;
3151 +
3152 +       kernel_cap_t set_caps;
3153 +       kernel_cap_t capabilities;
3154 +       kernel_cap_t audit_caps;
3155 +       kernel_cap_t quiet_caps;
3156 +
3157 +       struct aa_rlimit rlimits;
3158 +       unsigned int task_count;
3159 +
3160 +       struct kref count;
3161 +       struct list_head task_contexts;
3162 +       spinlock_t lock;
3163 +       unsigned long int_flags;
3164 +       u16 network_families[AF_MAX];
3165 +       u16 audit_network[AF_MAX];
3166 +       u16 quiet_network[AF_MAX];
3167 +};
3168 +
3169 +extern struct list_head profile_ns_list;
3170 +extern rwlock_t profile_ns_list_lock;
3171 +extern struct mutex aa_interface_lock;
3172 +
3173 +/**
3174 + * struct aa_task_context - primary label for confined tasks
3175 + * @profile: the current profile
3176 + * @previous_profile: profile the task may return to
3177 + * @cookie: magic value the task must know for returning to @previous_profile
3178 + * @list: list this aa_task_context is on
3179 + * @task: task that the aa_task_context confines
3180 + * @rcu: rcu head used when freeing the aa_task_context
3181 + * @caps_logged: caps that have previously generated log entries
3182 + *
3183 + * Contains the task's current profile (which could change due to
3184 + * change_hat).  Plus the hat_magic needed during change_hat.
3185 + */
3186 +struct aa_task_context {
3187 +       struct aa_profile *profile;
3188 +       struct aa_profile *previous_profile;
3189 +       u64 cookie;
3190 +       struct list_head list;
3191 +       struct task_struct *task;
3192 +       struct rcu_head rcu;
3193 +       kernel_cap_t caps_logged;
3194 +};
3195 +
3196 +extern struct aa_namespace *default_namespace;
3197 +
3198 +/* aa_audit - AppArmor auditing structure
3199 + * Structure is populated by access control code and passed to aa_audit which
3200 + * provides for a single point of logging.
3201 + */
3202 +
3203 +struct aa_audit {
3204 +       const char *operation;
3205 +       gfp_t gfp_mask;
3206 +       const char *info;
3207 +       const char *name;
3208 +       const char *name2;
3209 +       const char *name3;
3210 +       int request_mask, denied_mask, audit_mask;
3211 +       int rlimit;
3212 +       struct iattr *iattr;
3213 +       pid_t task, parent;
3214 +       int family, type, protocol;
3215 +       int error_code;
3216 +};
3217 +
3218 +/* Flags for the permission check functions */
3219 +#define AA_CHECK_FD    1  /* coming from a file descriptor */
3220 +#define AA_CHECK_DIR   2  /* file type is directory */
3221 +
3222 +/* lock subtypes so lockdep does not raise false dependencies */
3223 +enum aa_lock_class {
3224 +       aa_lock_normal,
3225 +       aa_lock_nested,
3226 +       aa_lock_task_release
3227 +};
3228 +
3229 +/* main.c */
3230 +extern int alloc_default_namespace(void);
3231 +extern void free_default_namespace(void);
3232 +extern int aa_audit_message(struct aa_profile *profile, struct aa_audit *sa,
3233 +                           int type);
3234 +void aa_audit_hint(struct aa_profile *profile, struct aa_audit *sa);
3235 +void aa_audit_status(struct aa_profile *profile, struct aa_audit *sa);
3236 +int aa_audit_reject(struct aa_profile *profile, struct aa_audit *sa);
3237 +extern int aa_audit_syscallreject(struct aa_profile *profile, gfp_t gfp,
3238 +                                 const char *);
3239 +extern int aa_audit(struct aa_profile *profile, struct aa_audit *);
3240 +
3241 +extern int aa_attr(struct aa_profile *profile, struct dentry *dentry,
3242 +                  struct vfsmount *mnt, struct iattr *iattr);
3243 +extern int aa_perm_xattr(struct aa_profile *profile, const char *operation,
3244 +                        struct dentry *dentry, struct vfsmount *mnt,
3245 +                        int mask, int check);
3246 +extern int aa_capability(struct aa_task_context *cxt, int cap);
3247 +extern int aa_perm(struct aa_profile *profile, const char *operation,
3248 +                  struct dentry *dentry, struct vfsmount *mnt, int mask,
3249 +                  int check);
3250 +extern int aa_perm_dir(struct aa_profile *profile, const char *operation,
3251 +                      struct dentry *dentry, struct vfsmount *mnt,
3252 +                      int mask);
3253 +extern int aa_perm_path(struct aa_profile *, const char *operation,
3254 +                       const char *name, int mask, uid_t uid);
3255 +extern int aa_link(struct aa_profile *profile,
3256 +                  struct dentry *link, struct vfsmount *link_mnt,
3257 +                  struct dentry *target, struct vfsmount *target_mnt);
3258 +extern int aa_clone(struct task_struct *task);
3259 +extern int aa_register(struct linux_binprm *bprm);
3260 +extern void aa_release(struct task_struct *task);
3261 +extern int aa_change_hat(const char *id, u64 hat_magic);
3262 +extern int aa_change_profile(const char *ns_name, const char *name);
3263 +extern struct aa_profile *__aa_replace_profile(struct task_struct *task,
3264 +                                              struct aa_profile *profile);
3265 +extern struct aa_task_context *lock_task_and_profiles(struct task_struct *task,
3266 +                                                     struct aa_profile *profile);
3267 +extern void unlock_task_and_profiles(struct task_struct *task,
3268 +                                    struct aa_task_context *cxt,
3269 +                                    struct aa_profile *profile);
3270 +extern void aa_change_task_context(struct task_struct *task,
3271 +                                  struct aa_task_context *new_cxt,
3272 +                                  struct aa_profile *profile, u64 cookie,
3273 +                                  struct aa_profile *previous_profile);
3274 +extern int aa_may_ptrace(struct aa_task_context *cxt,
3275 +                        struct aa_profile *tracee);
3276 +extern int aa_net_perm(struct aa_profile *profile, char *operation,
3277 +                       int family, int type, int protocol);
3278 +extern int aa_revalidate_sk(struct sock *sk, char *operation);
3279 +extern int aa_task_setrlimit(struct aa_profile *profile, unsigned int resource,
3280 +                            struct rlimit *new_rlim);
3281 +extern void aa_set_rlimits(struct task_struct *task, struct aa_profile *profile);
3282 +
3283 +
3284 +/* lsm.c */
3285 +extern int apparmor_initialized;
3286 +extern void info_message(const char *str);
3287 +extern void apparmor_disable(void);
3288 +
3289 +/* list.c */
3290 +extern struct aa_namespace *__aa_find_namespace(const char *name,
3291 +                                               struct list_head *list);
3292 +extern struct aa_profile *__aa_find_profile(const char *name,
3293 +                                           struct list_head *list);
3294 +extern void aa_profile_ns_list_release(void);
3295 +
3296 +/* module_interface.c */
3297 +extern ssize_t aa_add_profile(void *, size_t);
3298 +extern ssize_t aa_replace_profile(void *, size_t);
3299 +extern ssize_t aa_remove_profile(char *, size_t);
3300 +extern struct aa_namespace *alloc_aa_namespace(char *name);
3301 +extern void free_aa_namespace(struct aa_namespace *ns);
3302 +extern void free_aa_namespace_kref(struct kref *kref);
3303 +extern struct aa_profile *alloc_aa_profile(void);
3304 +extern void free_aa_profile(struct aa_profile *profile);
3305 +extern void free_aa_profile_kref(struct kref *kref);
3306 +extern void aa_unconfine_tasks(struct aa_profile *profile);
3307 +
3308 +/* procattr.c */
3309 +extern int aa_getprocattr(struct aa_profile *profile, char **string,
3310 +                         unsigned *len);
3311 +extern int aa_setprocattr_changehat(char *args);
3312 +extern int aa_setprocattr_changeprofile(char *args);
3313 +extern int aa_setprocattr_setprofile(struct task_struct *task, char *args);
3314 +
3315 +/* apparmorfs.c */
3316 +extern int create_apparmorfs(void);
3317 +extern void destroy_apparmorfs(void);
3318 +
3319 +/* match.c */
3320 +extern struct aa_dfa *aa_match_alloc(void);
3321 +extern void aa_match_free(struct aa_dfa *dfa);
3322 +extern int unpack_dfa(struct aa_dfa *dfa, void *blob, size_t size);
3323 +extern int verify_dfa(struct aa_dfa *dfa);
3324 +extern unsigned int aa_dfa_match(struct aa_dfa *dfa, const char *str, int *);
3325 +extern unsigned int aa_dfa_next_state(struct aa_dfa *dfa, unsigned int start,
3326 +                                     const char *str);
3327 +extern unsigned int aa_match_state(struct aa_dfa *dfa, unsigned int start,
3328 +                                  const char *str, unsigned int *final);
3329 +extern unsigned int aa_dfa_null_transition(struct aa_dfa *dfa,
3330 +                                          unsigned int start);
3331 +
3332 +#endif  /* __APPARMOR_H */
3333 diff -uprN linux-2.6.27./security/apparmor/apparmorfs.c linux-2.6.27/security/apparmor/apparmorfs.c
3334 --- linux-2.6.27./security/apparmor/apparmorfs.c        1970-01-01 01:00:00.000000000 +0100
3335 +++ linux-2.6.27/security/apparmor/apparmorfs.c 2008-10-29 14:28:53.326113825 +0100
3336 @@ -0,0 +1,281 @@
3337 +/*
3338 + *     Copyright (C) 1998-2007 Novell/SUSE
3339 + *
3340 + *     This program is free software; you can redistribute it and/or
3341 + *     modify it under the terms of the GNU General Public License as
3342 + *     published by the Free Software Foundation, version 2 of the
3343 + *     License.
3344 + *
3345 + *     AppArmor filesystem (part of securityfs)
3346 + */
3347 +
3348 +#include <linux/security.h>
3349 +#include <linux/vmalloc.h>
3350 +#include <linux/module.h>
3351 +#include <linux/seq_file.h>
3352 +#include <asm/uaccess.h>
3353 +#include <linux/namei.h>
3354 +
3355 +#include "apparmor.h"
3356 +#include "inline.h"
3357 +
3358 +static char *aa_simple_write_to_buffer(const char __user *userbuf,
3359 +                                      size_t alloc_size, size_t copy_size,
3360 +                                      loff_t *pos, const char *operation)
3361 +{
3362 +       struct aa_profile *profile;
3363 +       char *data;
3364 +
3365 +       if (*pos != 0) {
3366 +               /* only writes from pos 0, that is complete writes */
3367 +               data = ERR_PTR(-ESPIPE);
3368 +               goto out;
3369 +       }
3370 +
3371 +       /*
3372 +        * Don't allow confined processes to load/replace/remove profiles.
3373 +        * No sane person would add rules allowing this to a profile
3374 +        * but we enforce the restriction anyways.
3375 +        */
3376 +       profile = aa_get_profile(current);
3377 +       if (profile) {
3378 +               struct aa_audit sa;
3379 +               memset(&sa, 0, sizeof(sa));
3380 +               sa.operation = operation;
3381 +               sa.gfp_mask = GFP_KERNEL;
3382 +               sa.error_code = -EACCES;
3383 +               data = ERR_PTR(aa_audit_reject(profile, &sa));
3384 +               aa_put_profile(profile);
3385 +               goto out;
3386 +       }
3387 +
3388 +       data = vmalloc(alloc_size);
3389 +       if (data == NULL) {
3390 +               data = ERR_PTR(-ENOMEM);
3391 +               goto out;
3392 +       }
3393 +
3394 +       if (copy_from_user(data, userbuf, copy_size)) {
3395 +               vfree(data);
3396 +               data = ERR_PTR(-EFAULT);
3397 +               goto out;
3398 +       }
3399 +
3400 +out:
3401 +       return data;
3402 +}
3403 +
3404 +/* apparmor/profiles */
3405 +extern struct seq_operations apparmorfs_profiles_op;
3406 +
3407 +static int aa_profiles_open(struct inode *inode, struct file *file)
3408 +{
3409 +       return seq_open(file, &apparmorfs_profiles_op);
3410 +}
3411 +
3412 +
3413 +static int aa_profiles_release(struct inode *inode, struct file *file)
3414 +{
3415 +       return seq_release(inode, file);
3416 +}
3417 +
3418 +static struct file_operations apparmorfs_profiles_fops = {
3419 +       .open =         aa_profiles_open,
3420 +       .read =         seq_read,
3421 +       .llseek =       seq_lseek,
3422 +       .release =      aa_profiles_release,
3423 +};
3424 +
3425 +/* apparmor/matching */
3426 +static ssize_t aa_matching_read(struct file *file, char __user *buf,
3427 +                              size_t size, loff_t *ppos)
3428 +{
3429 +       const char *matching = "pattern=aadfa audit perms=rwxamlk/ user::other";
3430 +
3431 +       return simple_read_from_buffer(buf, size, ppos, matching,
3432 +                                      strlen(matching));
3433 +}
3434 +
3435 +static struct file_operations apparmorfs_matching_fops = {
3436 +       .read =         aa_matching_read,
3437 +};
3438 +
3439 +/* apparmor/features */
3440 +static ssize_t aa_features_read(struct file *file, char __user *buf,
3441 +                               size_t size, loff_t *ppos)
3442 +{
3443 +       const char *features = "file=3.0 capability=2.0 network=1.0 "
3444 +                              "change_hat=1.5 change_profile=1.0 "
3445 +                              "aanamespaces=1.0 rlimit=1.0";
3446 +
3447 +       return simple_read_from_buffer(buf, size, ppos, features,
3448 +                                      strlen(features));
3449 +}
3450 +
3451 +static struct file_operations apparmorfs_features_fops = {
3452 +       .read =         aa_features_read,
3453 +};
3454 +
3455 +/* apparmor/.load */
3456 +static ssize_t aa_profile_load(struct file *f, const char __user *buf,
3457 +                              size_t size, loff_t *pos)
3458 +{
3459 +       char *data;
3460 +       ssize_t error;
3461 +
3462 +       data = aa_simple_write_to_buffer(buf, size, size, pos, "profile_load");
3463 +
3464 +       error = PTR_ERR(data);
3465 +       if (!IS_ERR(data)) {
3466 +               error = aa_add_profile(data, size);
3467 +               vfree(data);
3468 +       }
3469 +
3470 +       return error;
3471 +}
3472 +
3473 +
3474 +static struct file_operations apparmorfs_profile_load = {
3475 +       .write = aa_profile_load
3476 +};
3477 +
3478 +/* apparmor/.replace */
3479 +static ssize_t aa_profile_replace(struct file *f, const char __user *buf,
3480 +                                 size_t size, loff_t *pos)
3481 +{
3482 +       char *data;
3483 +       ssize_t error;
3484 +
3485 +       data = aa_simple_write_to_buffer(buf, size, size, pos,
3486 +                                        "profile_replace");
3487 +
3488 +       error = PTR_ERR(data);
3489 +       if (!IS_ERR(data)) {
3490 +               error = aa_replace_profile(data, size);
3491 +               vfree(data);
3492 +       }
3493 +
3494 +       return error;
3495 +}
3496 +
3497 +
3498 +static struct file_operations apparmorfs_profile_replace = {
3499 +       .write = aa_profile_replace
3500 +};
3501 +
3502 +/* apparmor/.remove */
3503 +static ssize_t aa_profile_remove(struct file *f, const char __user *buf,
3504 +                                 size_t size, loff_t *pos)
3505 +{
3506 +       char *data;
3507 +       ssize_t error;
3508 +
3509 +       /*
3510 +        * aa_remove_profile needs a null terminated string so 1 extra
3511 +        * byte is allocated and the copied data is null terminated.
3512 +        */
3513 +       data = aa_simple_write_to_buffer(buf, size + 1, size, pos,
3514 +                                        "profile_remove");
3515 +
3516 +       error = PTR_ERR(data);
3517 +       if (!IS_ERR(data)) {
3518 +               data[size] = 0;
3519 +               error = aa_remove_profile(data, size);
3520 +               vfree(data);
3521 +       }
3522 +
3523 +       return error;
3524 +}
3525 +
3526 +static struct file_operations apparmorfs_profile_remove = {
3527 +       .write = aa_profile_remove
3528 +};
3529 +
3530 +static struct dentry *apparmor_dentry;
3531 +
3532 +static void aafs_remove(const char *name)
3533 +{
3534 +       struct dentry *dentry;
3535 +
3536 +       dentry = lookup_one_len(name, apparmor_dentry, strlen(name));
3537 +       if (!IS_ERR(dentry)) {
3538 +               securityfs_remove(dentry);
3539 +               dput(dentry);
3540 +       }
3541 +}
3542 +
3543 +static int aafs_create(const char *name, int mask, struct file_operations *fops)
3544 +{
3545 +       struct dentry *dentry;
3546 +
3547 +       dentry = securityfs_create_file(name, S_IFREG | mask, apparmor_dentry,
3548 +                                       NULL, fops);
3549 +
3550 +       return IS_ERR(dentry) ? PTR_ERR(dentry) : 0;
3551 +}
3552 +
3553 +void destroy_apparmorfs(void)
3554 +{
3555 +       if (apparmor_dentry) {
3556 +               aafs_remove(".remove");
3557 +               aafs_remove(".replace");
3558 +               aafs_remove(".load");
3559 +               aafs_remove("matching");
3560 +               aafs_remove("features");
3561 +               aafs_remove("profiles");
3562 +               securityfs_remove(apparmor_dentry);
3563 +               apparmor_dentry = NULL;
3564 +       }
3565 +}
3566 +
3567 +int create_apparmorfs(void)
3568 +{
3569 +       int error;
3570 +
3571 +       if (!apparmor_initialized)
3572 +               return 0;
3573 +
3574 +       if (apparmor_dentry) {
3575 +               AA_ERROR("%s: AppArmor securityfs already exists\n",
3576 +                       __FUNCTION__);
3577 +               return -EEXIST;
3578 +       }
3579 +
3580 +       apparmor_dentry = securityfs_create_dir("apparmor", NULL);
3581 +       if (IS_ERR(apparmor_dentry)) {
3582 +               error = PTR_ERR(apparmor_dentry);
3583 +               apparmor_dentry = NULL;
3584 +               goto error;
3585 +       }
3586 +       error = aafs_create("profiles", 0440, &apparmorfs_profiles_fops);
3587 +       if (error)
3588 +               goto error;
3589 +       error = aafs_create("matching", 0444, &apparmorfs_matching_fops);
3590 +       if (error)
3591 +               goto error;
3592 +       error = aafs_create("features", 0444, &apparmorfs_features_fops);
3593 +       if (error)
3594 +               goto error;
3595 +       error = aafs_create(".load", 0640, &apparmorfs_profile_load);
3596 +       if (error)
3597 +               goto error;
3598 +       error = aafs_create(".replace", 0640, &apparmorfs_profile_replace);
3599 +       if (error)
3600 +               goto error;
3601 +       error = aafs_create(".remove", 0640, &apparmorfs_profile_remove);
3602 +       if (error)
3603 +               goto error;
3604 +
3605 +       /* Report that AppArmor fs is enabled */
3606 +       info_message("AppArmor Filesystem Enabled");
3607 +       return 0;
3608 +
3609 +error:
3610 +       destroy_apparmorfs();
3611 +       AA_ERROR("Error creating AppArmor securityfs\n");
3612 +       apparmor_disable();
3613 +       return error;
3614 +}
3615 +
3616 +fs_initcall(create_apparmorfs);
3617 +
3618 diff -uprN linux-2.6.27./security/apparmor/inline.h linux-2.6.27/security/apparmor/inline.h
3619 --- linux-2.6.27./security/apparmor/inline.h    1970-01-01 01:00:00.000000000 +0100
3620 +++ linux-2.6.27/security/apparmor/inline.h     2008-10-29 14:28:53.319441671 +0100
3621 @@ -0,0 +1,250 @@
3622 +/*
3623 + *     Copyright (C) 1998-2007 Novell/SUSE
3624 + *
3625 + *     This program is free software; you can redistribute it and/or
3626 + *     modify it under the terms of the GNU General Public License as
3627 + *     published by the Free Software Foundation, version 2 of the
3628 + *     License.
3629 + */
3630 +
3631 +#ifndef __INLINE_H
3632 +#define __INLINE_H
3633 +
3634 +#include <linux/sched.h>
3635 +
3636 +#include "match.h"
3637 +
3638 +static inline int mediated_filesystem(struct inode *inode)
3639 +{
3640 +       return !(inode->i_sb->s_flags & MS_NOUSER);
3641 +}
3642 +
3643 +static inline struct aa_task_context *aa_task_context(struct task_struct *task)
3644 +{
3645 +       return (struct aa_task_context *) rcu_dereference(task->security);
3646 +}
3647 +
3648 +static inline struct aa_namespace *aa_get_namespace(struct aa_namespace *ns)
3649 +{
3650 +       if (ns)
3651 +               kref_get(&(ns->count));
3652 +
3653 +       return ns;
3654 +}
3655 +
3656 +static inline void aa_put_namespace(struct aa_namespace *ns)
3657 +{
3658 +       if (ns)
3659 +               kref_put(&ns->count, free_aa_namespace_kref);
3660 +}
3661 +
3662 +
3663 +static inline struct aa_namespace *aa_find_namespace(const char *name)
3664 +{
3665 +       struct aa_namespace *ns = NULL;
3666 +
3667 +       read_lock(&profile_ns_list_lock);
3668 +       ns = aa_get_namespace(__aa_find_namespace(name, &profile_ns_list));
3669 +       read_unlock(&profile_ns_list_lock);
3670 +
3671 +       return ns;
3672 +}
3673 +
3674 +/**
3675 + * aa_dup_profile - increment refcount on profile @p
3676 + * @p: profile
3677 + */
3678 +static inline struct aa_profile *aa_dup_profile(struct aa_profile *p)
3679 +{
3680 +       if (p)
3681 +               kref_get(&(p->count));
3682 +
3683 +       return p;
3684 +}
3685 +
3686 +/**
3687 + * aa_put_profile - decrement refcount on profile @p
3688 + * @p: profile
3689 + */
3690 +static inline void aa_put_profile(struct aa_profile *p)
3691 +{
3692 +       if (p)
3693 +               kref_put(&p->count, free_aa_profile_kref);
3694 +}
3695 +
3696 +static inline struct aa_profile *aa_get_profile(struct task_struct *task)
3697 +{
3698 +       struct aa_task_context *cxt;
3699 +       struct aa_profile *profile = NULL;
3700 +
3701 +       rcu_read_lock();
3702 +       cxt = aa_task_context(task);
3703 +       if (cxt) {
3704 +               profile = cxt->profile;
3705 +               aa_dup_profile(profile);
3706 +       }
3707 +       rcu_read_unlock();
3708 +
3709 +       return profile;
3710 +}
3711 +
3712 +static inline struct aa_profile *aa_find_profile(struct aa_namespace *ns,
3713 +                                                const char *name)
3714 +{
3715 +       struct aa_profile *profile = NULL;
3716 +
3717 +       read_lock(&ns->lock);
3718 +       profile = aa_dup_profile(__aa_find_profile(name, &ns->profiles));
3719 +       read_unlock(&ns->lock);
3720 +
3721 +       return profile;
3722 +}
3723 +
3724 +static inline struct aa_task_context *aa_alloc_task_context(gfp_t flags)
3725 +{
3726 +       struct aa_task_context *cxt;
3727 +
3728 +       cxt = kzalloc(sizeof(*cxt), flags);
3729 +       if (cxt) {
3730 +               INIT_LIST_HEAD(&cxt->list);
3731 +               INIT_RCU_HEAD(&cxt->rcu);
3732 +       }
3733 +
3734 +       return cxt;
3735 +}
3736 +
3737 +static inline void aa_free_task_context(struct aa_task_context *cxt)
3738 +{
3739 +       if (cxt) {
3740 +               aa_put_profile(cxt->profile);
3741 +               aa_put_profile(cxt->previous_profile);
3742 +               kfree(cxt);
3743 +       }
3744 +}
3745 +
3746 +/**
3747 + * lock_profile - lock a profile
3748 + * @profile: the profile to lock
3749 + *
3750 + * While the profile is locked, local interrupts are disabled. This also
3751 + * gives us RCU reader safety.
3752 + */
3753 +static inline void lock_profile_nested(struct aa_profile *profile,
3754 +                                      enum aa_lock_class lock_class)
3755 +{
3756 +       /*
3757 +        * Lock the profile.
3758 +        *
3759 +        * Need to disable interrupts here because this lock is used in
3760 +        * the task_free_security hook, which may run in RCU context.
3761 +        */
3762 +       if (profile)
3763 +               spin_lock_irqsave_nested(&profile->lock, profile->int_flags,
3764 +                                        lock_class);
3765 +}
3766 +
3767 +static inline void lock_profile(struct aa_profile *profile)
3768 +{
3769 +       lock_profile_nested(profile, aa_lock_normal);
3770 +}
3771 +
3772 +/**
3773 + * unlock_profile - unlock a profile
3774 + * @profile: the profile to unlock
3775 + */
3776 +static inline void unlock_profile(struct aa_profile *profile)
3777 +{
3778 +       /* Unlock the profile. */
3779 +       if (profile)
3780 +               spin_unlock_irqrestore(&profile->lock, profile->int_flags);
3781 +}
3782 +
3783 +/**
3784 + * lock_both_profiles  -  lock two profiles in a deadlock-free way
3785 + * @profile1:  profile to lock (may be NULL)
3786 + * @profile2:  profile to lock (may be NULL)
3787 + *
3788 + * The order in which profiles are passed into lock_both_profiles() /
3789 + * unlock_both_profiles() does not matter.
3790 + * While the profile is locked, local interrupts are disabled. This also
3791 + * gives us RCU reader safety.
3792 + */
3793 +static inline void lock_both_profiles(struct aa_profile *profile1,
3794 +                                     struct aa_profile *profile2)
3795 +{
3796 +       /*
3797 +        * Lock the two profiles.
3798 +        *
3799 +        * We need to disable interrupts because the profile locks are
3800 +        * used in the task_free_security hook, which may run in RCU
3801 +        * context.
3802 +        *
3803 +        * Do not nest spin_lock_irqsave()/spin_unlock_irqresore():
3804 +        * interrupts only need to be turned off once.
3805 +        */
3806 +       if (!profile1 || profile1 == profile2) {
3807 +               if (profile2)
3808 +                       spin_lock_irqsave_nested(&profile2->lock,
3809 +                                                profile2->int_flags,
3810 +                                                aa_lock_normal);
3811 +       } else if (profile1 > profile2) {
3812 +               /* profile1 cannot be NULL here. */
3813 +               spin_lock_irqsave_nested(&profile1->lock, profile1->int_flags,
3814 +                                        aa_lock_normal);
3815 +               if (profile2)
3816 +                       spin_lock_nested(&profile2->lock, aa_lock_nested);
3817 +
3818 +       } else {
3819 +               /* profile2 cannot be NULL here. */
3820 +               spin_lock_irqsave_nested(&profile2->lock, profile2->int_flags,
3821 +                                        aa_lock_normal);
3822 +               spin_lock_nested(&profile1->lock, aa_lock_nested);
3823 +       }
3824 +}
3825 +
3826 +/**
3827 + * unlock_both_profiles  -  unlock two profiles in a deadlock-free way
3828 + * @profile1:  profile to unlock (may be NULL)
3829 + * @profile2:  profile to unlock (may be NULL)
3830 + *
3831 + * The order in which profiles are passed into lock_both_profiles() /
3832 + * unlock_both_profiles() does not matter.
3833 + * While the profile is locked, local interrupts are disabled. This also
3834 + * gives us RCU reader safety.
3835 + */
3836 +static inline void unlock_both_profiles(struct aa_profile *profile1,
3837 +                                       struct aa_profile *profile2)
3838 +{
3839 +       /* Unlock the two profiles. */
3840 +       if (!profile1 || profile1 == profile2) {
3841 +               if (profile2)
3842 +                       spin_unlock_irqrestore(&profile2->lock,
3843 +                                              profile2->int_flags);
3844 +       } else if (profile1 > profile2) {
3845 +               /* profile1 cannot be NULL here. */
3846 +               if (profile2)
3847 +                       spin_unlock(&profile2->lock);
3848 +               spin_unlock_irqrestore(&profile1->lock, profile1->int_flags);
3849 +       } else {
3850 +               /* profile2 cannot be NULL here. */
3851 +               spin_unlock(&profile1->lock);
3852 +               spin_unlock_irqrestore(&profile2->lock, profile2->int_flags);
3853 +       }
3854 +}
3855 +
3856 +static inline unsigned int aa_match(struct aa_dfa *dfa, const char *pathname,
3857 +                                   int *audit_mask)
3858 +{
3859 +       if (dfa)
3860 +               return aa_dfa_match(dfa, pathname, audit_mask);
3861 +       if (audit_mask)
3862 +               *audit_mask = 0;
3863 +       return 0;
3864 +}
3865 +
3866 +static inline int dfa_audit_mask(struct aa_dfa *dfa, unsigned int state)
3867 +{
3868 +       return  ACCEPT_TABLE2(dfa)[state];
3869 +}
3870 +
3871 +#endif /* __INLINE_H__ */
3872 diff -uprN linux-2.6.27./security/apparmor/list.c linux-2.6.27/security/apparmor/list.c
3873 --- linux-2.6.27./security/apparmor/list.c      1970-01-01 01:00:00.000000000 +0100
3874 +++ linux-2.6.27/security/apparmor/list.c       2008-10-29 14:28:53.319441671 +0100
3875 @@ -0,0 +1,174 @@
3876 +/*
3877 + *     Copyright (C) 1998-2007 Novell/SUSE
3878 + *
3879 + *     This program is free software; you can redistribute it and/or
3880 + *     modify it under the terms of the GNU General Public License as
3881 + *     published by the Free Software Foundation, version 2 of the
3882 + *     License.
3883 + *
3884 + *     AppArmor Profile List Management
3885 + */
3886 +
3887 +#include <linux/seq_file.h>
3888 +#include "apparmor.h"
3889 +#include "inline.h"
3890 +
3891 +/* list of profile namespaces and lock */
3892 +LIST_HEAD(profile_ns_list);
3893 +rwlock_t profile_ns_list_lock = RW_LOCK_UNLOCKED;
3894 +
3895 +/**
3896 + * __aa_find_namespace  -  look up a profile namespace on the namespace list
3897 + * @name: name of namespace to find
3898 + * @head: list to search
3899 + *
3900 + * Returns a pointer to the namespace on the list, or NULL if no namespace
3901 + * called @name exists. The caller must hold the profile_ns_list_lock.
3902 + */
3903 +struct aa_namespace *__aa_find_namespace(const char *name,
3904 +                                      struct list_head *head)
3905 +{
3906 +       struct aa_namespace *ns;
3907 +
3908 +       list_for_each_entry(ns, head, list) {
3909 +               if (!strcmp(ns->name, name))
3910 +                       return ns;
3911 +       }
3912 +
3913 +       return NULL;
3914 +}
3915 +
3916 +/**
3917 + * __aa_find_profile  -  look up a profile on the profile list
3918 + * @name: name of profile to find
3919 + * @head: list to search
3920 + *
3921 + * Returns a pointer to the profile on the list, or NULL if no profile
3922 + * called @name exists. The caller must hold the profile_list_lock.
3923 + */
3924 +struct aa_profile *__aa_find_profile(const char *name, struct list_head *head)
3925 +{
3926 +       struct aa_profile *profile;
3927 +
3928 +       list_for_each_entry(profile, head, list) {
3929 +               if (!strcmp(profile->name, name))
3930 +                       return profile;
3931 +       }
3932 +
3933 +       return NULL;
3934 +}
3935 +
3936 +static void aa_profile_list_release(struct list_head *head)
3937 +{
3938 +       struct aa_profile *profile, *tmp;
3939 +       list_for_each_entry_safe(profile, tmp, head, list) {
3940 +               /* Remove the profile from each task context it is on. */
3941 +               lock_profile(profile);
3942 +               profile->isstale = 1;
3943 +               aa_unconfine_tasks(profile);
3944 +               list_del_init(&profile->list);
3945 +               unlock_profile(profile);
3946 +               aa_put_profile(profile);
3947 +       }
3948 +}
3949 +
3950 +/**
3951 + * aa_profilelist_release - Remove all profiles from profile_list
3952 + */
3953 +void aa_profile_ns_list_release(void)
3954 +{
3955 +       struct aa_namespace *ns, *tmp;
3956 +
3957 +       /* Remove and release all the profiles on namespace profile lists. */
3958 +       write_lock(&profile_ns_list_lock);
3959 +       list_for_each_entry_safe(ns, tmp, &profile_ns_list, list) {
3960 +               write_lock(&ns->lock);
3961 +               aa_profile_list_release(&ns->profiles);
3962 +               list_del_init(&ns->list);
3963 +               write_unlock(&ns->lock);
3964 +               aa_put_namespace(ns);
3965 +       }
3966 +       write_unlock(&profile_ns_list_lock);
3967 +}
3968 +
3969 +
3970 +static struct aa_profile *next_profile(struct aa_profile *profile)
3971 +{
3972 +       struct aa_profile *next = profile;
3973 +       struct aa_namespace *ns;
3974 +
3975 +       list_for_each_entry_continue(next, &profile->ns->profiles, list)
3976 +               return next;
3977 +
3978 +       ns = profile->ns;
3979 +       read_unlock(&ns->lock);
3980 +       list_for_each_entry_continue(ns, &profile_ns_list, list) {
3981 +               read_lock(&ns->lock);
3982 +               list_for_each_entry(profile, &ns->profiles, list)
3983 +                       return profile;
3984 +               read_unlock(&ns->lock);
3985 +       }
3986 +       return NULL;
3987 +}
3988 +
3989 +static void *p_start(struct seq_file *f, loff_t *pos)
3990 +{
3991 +       struct aa_namespace *ns;
3992 +       loff_t l = *pos;
3993 +
3994 +       read_lock(&profile_ns_list_lock);
3995 +       if (!list_empty(&profile_ns_list)) {
3996 +               struct aa_profile *profile = NULL;
3997 +               ns = list_first_entry(&profile_ns_list, typeof(*ns), list);
3998 +               read_lock(&ns->lock);
3999 +               if (!list_empty(&ns->profiles))
4000 +                       profile = list_first_entry(&ns->profiles,
4001 +                                                  typeof(*profile), list);
4002 +               else
4003 +                       read_unlock(&ns->lock);
4004 +               for ( ; profile && l > 0; l--)
4005 +                       profile = next_profile(profile);
4006 +               return profile;
4007 +       }
4008 +       return NULL;
4009 +}
4010 +
4011 +static void *p_next(struct seq_file *f, void *p, loff_t *pos)
4012 +{
4013 +       struct aa_profile *profile = (struct aa_profile *) p;
4014 +
4015 +       (*pos)++;
4016 +       profile = next_profile(profile);
4017 +
4018 +       return profile;
4019 +}
4020 +
4021 +static void p_stop(struct seq_file *f, void *p)
4022 +{
4023 +       struct aa_profile *profile = (struct aa_profile *) p;
4024 +
4025 +       if (profile)
4026 +               read_unlock(&profile->ns->lock);
4027 +       read_unlock(&profile_ns_list_lock);
4028 +}
4029 +
4030 +static int seq_show_profile(struct seq_file *f, void *p)
4031 +{
4032 +       struct aa_profile *profile = (struct aa_profile *)p;
4033 +
4034 +       if (profile->ns == default_namespace)
4035 +           seq_printf(f, "%s (%s)\n", profile->name,
4036 +                      PROFILE_COMPLAIN(profile) ? "complain" : "enforce");
4037 +       else
4038 +           seq_printf(f, ":%s:%s (%s)\n", profile->ns->name, profile->name,
4039 +                      PROFILE_COMPLAIN(profile) ? "complain" : "enforce");
4040 +       return 0;
4041 +}
4042 +
4043 +/* Used in apparmorfs.c */
4044 +struct seq_operations apparmorfs_profiles_op = {
4045 +       .start =        p_start,
4046 +       .next =         p_next,
4047 +       .stop =         p_stop,
4048 +       .show =         seq_show_profile,
4049 +};
4050 diff -uprN linux-2.6.27./security/apparmor/locking.txt linux-2.6.27/security/apparmor/locking.txt
4051 --- linux-2.6.27./security/apparmor/locking.txt 1970-01-01 01:00:00.000000000 +0100
4052 +++ linux-2.6.27/security/apparmor/locking.txt  2008-10-29 14:28:53.319441671 +0100
4053 @@ -0,0 +1,68 @@
4054 +Locking in AppArmor
4055 +===================
4056 +
4057 +Lock hierarchy:
4058 +
4059 +       aa_interface_lock
4060 +         profile_list_lock
4061 +           aa_profile->lock
4062 +             task_lock()
4063 +
4064 +
4065 +Which lock protects what?
4066 +
4067 +       /-----------------------+-------------------------------\
4068 +       | Variable              | Lock                          |
4069 +       >-----------------------+-------------------------------<
4070 +       | profile_list          | profile_list_lock             |
4071 +       +-----------------------+-------------------------------+
4072 +       | aa_profile            | (reference count)             |
4073 +       +-----------------------+-------------------------------+
4074 +       | aa_profile->          | aa_profile->lock              |
4075 +       |   isstale,            |                               |
4076 +       |   task_contexts       |                               |
4077 +       +-----------------------+-------------------------------+
4078 +       | task_struct->security | read: RCU                     |
4079 +       |                       | write: task_lock()            |
4080 +       +-----------------------+-------------------------------+
4081 +       | aa_profile->sub       | handle on the profile (list   |
4082 +       |                       | is never modified)            |
4083 +       \-----------------------+-------------------------------/
4084 +
4085 +(Obviously, the list_heads embedded in data structures are always
4086 +protected with the lock that also protects the list.)
4087 +
4088 +When moving a task context from one profile to another, we grab both
4089 +profile locks with lock_both_profiles(). This ensures that both locks
4090 +are always taken in the same order, and so we won't deadlock.
4091 +
4092 +Since task_struct->security is RCU protected the aa_task_struct it
4093 +references is only guarenteed to exist for the rcu cycle.  Where
4094 +aa_task_context->profile is needed in blocking operations the
4095 +profile's reference count is incremented and the profile reference
4096 +is used.
4097 +
4098 +Profiles on profile_list are never stale: when a profile becomes stale,
4099 +it is removed from profile_list at the same time (under profile_list_lock
4100 +and aa_profile->lock).
4101 +
4102 +The aa_interface_lock is taken whenever user-space modifies the profile
4103 +list, and can sleep. This ensures that profile loading/replacement/removal
4104 +won't race with itself. We release the profile_list_lock as soon as
4105 +possible to avoid stalling exec during profile loading/replacement/removal.
4106 +
4107 +AppArmor uses lock subtyping to avoid false positives from lockdep.  The
4108 +profile lock is often taken nested, but it is guaranteed to be in a lock
4109 +safe order and not the same lock when done, so it is safe.
4110 +
4111 +A third lock type (aa_lock_task_release) is given to the profile lock
4112 +when it is taken in soft irq context during task release (aa_release).
4113 +This is to avoid a false positive between the task lock and the profile
4114 +lock.  In task context the profile lock wraps the task lock with irqs
4115 +off, but the kernel takes the task lock with irqs enabled.  This won't
4116 +result in a deadlock because for a deadlock to occur the kernel must
4117 +take dead task A's lock (irqs on), the rcu callback hook freeing
4118 +dead task A must be run and AppArmor must be changing the profile on
4119 +dead task A.  The kernel should not be taking a dead task's task_lock
4120 +at the same time the task is being freed by task rcu cleanup other wise
4121 +the task would not be out of its quiescent period.
4122 diff -uprN linux-2.6.27./security/apparmor/lsm.c linux-2.6.27/security/apparmor/lsm.c
4123 --- linux-2.6.27./security/apparmor/lsm.c       1970-01-01 01:00:00.000000000 +0100
4124 +++ linux-2.6.27/security/apparmor/lsm.c        2008-10-29 14:28:53.329440939 +0100
4125 @@ -0,0 +1,1060 @@
4126 +/*
4127 + *     Copyright (C) 1998-2007 Novell/SUSE
4128 + *
4129 + *     This program is free software; you can redistribute it and/or
4130 + *     modify it under the terms of the GNU General Public License as
4131 + *     published by the Free Software Foundation, version 2 of the
4132 + *     License.
4133 + *
4134 + *     AppArmor LSM interface
4135 + */
4136 +#include <linux/security.h>
4137 +#include <linux/module.h>
4138 +#include <linux/mm.h>
4139 +#include <linux/mman.h>
4140 +#include <linux/mount.h>
4141 +#include <linux/namei.h>
4142 +#include <linux/ctype.h>
4143 +#include <linux/sysctl.h>
4144 +#include <linux/audit.h>
4145 +#include <net/sock.h>
4146 +
4147 +#include "apparmor.h"
4148 +#include "inline.h"
4149 +
4150 +/* Flag indicating whether initialization completed */
4151 +int apparmor_initialized = 0;
4152 +
4153 +static int param_set_aabool(const char *val, struct kernel_param *kp);
4154 +static int param_get_aabool(char *buffer, struct kernel_param *kp);
4155 +#define param_check_aabool(name, p) __param_check(name, p, int)
4156 +
4157 +static int param_set_aauint(const char *val, struct kernel_param *kp);
4158 +static int param_get_aauint(char *buffer, struct kernel_param *kp);
4159 +#define param_check_aauint(name, p) __param_check(name, p, int)
4160 +
4161 +/* Flag values, also controllable via /sys/module/apparmor/parameters
4162 + * We define special types as we want to do additional mediation.
4163 + *
4164 + * Complain mode -- in complain mode access failures result in auditing only
4165 + * and task is allowed access.  audit events are processed by userspace to
4166 + * generate policy.  Default is 'enforce' (0).
4167 + * Value is also togglable per profile and referenced when global value is
4168 + * enforce.
4169 + */
4170 +int apparmor_complain = 0;
4171 +module_param_named(complain, apparmor_complain, aabool, S_IRUSR | S_IWUSR);
4172 +MODULE_PARM_DESC(apparmor_complain, "Toggle AppArmor complain mode");
4173 +
4174 +/* Debug mode */
4175 +int apparmor_debug = 0;
4176 +module_param_named(debug, apparmor_debug, aabool, S_IRUSR | S_IWUSR);
4177 +MODULE_PARM_DESC(apparmor_debug, "Toggle AppArmor debug mode");
4178 +
4179 +/* Audit mode */
4180 +int apparmor_audit = 0;
4181 +module_param_named(audit, apparmor_audit, aabool, S_IRUSR | S_IWUSR);
4182 +MODULE_PARM_DESC(apparmor_audit, "Toggle AppArmor audit mode");
4183 +
4184 +/* Syscall logging mode */
4185 +int apparmor_logsyscall = 0;
4186 +module_param_named(logsyscall, apparmor_logsyscall, aabool, S_IRUSR | S_IWUSR);
4187 +MODULE_PARM_DESC(apparmor_logsyscall, "Toggle AppArmor logsyscall mode");
4188 +
4189 +/* Maximum pathname length before accesses will start getting rejected */
4190 +unsigned int apparmor_path_max = 2 * PATH_MAX;
4191 +module_param_named(path_max, apparmor_path_max, aauint, S_IRUSR | S_IWUSR);
4192 +MODULE_PARM_DESC(apparmor_path_max, "Maximum pathname length allowed");
4193 +
4194 +/* Boot time disable flag */
4195 +#ifdef CONFIG_SECURITY_APPARMOR_DISABLE
4196 +#define AA_ENABLED_PERMS 0600
4197 +#else
4198 +#define AA_ENABLED_PERMS 0400
4199 +#endif
4200 +static int param_set_aa_enabled(const char *val, struct kernel_param *kp);
4201 +unsigned int apparmor_enabled = CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE;
4202 +module_param_call(enabled, param_set_aa_enabled, param_get_aauint,
4203 +                 &apparmor_enabled, AA_ENABLED_PERMS);
4204 +MODULE_PARM_DESC(apparmor_enabled, "Enable/Disable Apparmor on boot");
4205 +
4206 +static int __init apparmor_enabled_setup(char *str)
4207 +{
4208 +       apparmor_enabled = simple_strtol(str, NULL, 0);
4209 +       return 1;
4210 +}
4211 +__setup("apparmor=", apparmor_enabled_setup);
4212 +
4213 +static int param_set_aabool(const char *val, struct kernel_param *kp)
4214 +{
4215 +       if (aa_task_context(current))
4216 +               return -EPERM;
4217 +       return param_set_bool(val, kp);
4218 +}
4219 +
4220 +static int param_get_aabool(char *buffer, struct kernel_param *kp)
4221 +{
4222 +       if (aa_task_context(current))
4223 +               return -EPERM;
4224 +       return param_get_bool(buffer, kp);
4225 +}
4226 +
4227 +static int param_set_aauint(const char *val, struct kernel_param *kp)
4228 +{
4229 +       if (aa_task_context(current))
4230 +               return -EPERM;
4231 +       return param_set_uint(val, kp);
4232 +}
4233 +
4234 +static int param_get_aauint(char *buffer, struct kernel_param *kp)
4235 +{
4236 +       if (aa_task_context(current))
4237 +               return -EPERM;
4238 +       return param_get_uint(buffer, kp);
4239 +}
4240 +
4241 +/* allow run time disabling of apparmor */
4242 +static int param_set_aa_enabled(const char *val, struct kernel_param *kp)
4243 +{
4244 +       char *endp;
4245 +       unsigned long l;
4246 +
4247 +       if (!apparmor_initialized) {
4248 +               apparmor_enabled = 0;
4249 +               return 0;
4250 +       }
4251 +
4252 +       if (aa_task_context(current))
4253 +               return -EPERM;
4254 +
4255 +       if (!apparmor_enabled)
4256 +               return -EINVAL;
4257 +
4258 +       if (!val)
4259 +               return -EINVAL;
4260 +
4261 +       l = simple_strtoul(val, &endp, 0);
4262 +       if (endp == val || l != 0)
4263 +               return -EINVAL;
4264 +
4265 +       apparmor_enabled = 0;
4266 +       apparmor_disable();
4267 +       return 0;
4268 +}
4269 +
4270 +static int aa_reject_syscall(struct task_struct *task, gfp_t flags,
4271 +                            const char *name)
4272 +{
4273 +       struct aa_profile *profile = aa_get_profile(task);
4274 +       int error = 0;
4275 +
4276 +       if (profile) {
4277 +               error = aa_audit_syscallreject(profile, flags, name);
4278 +               aa_put_profile(profile);
4279 +       }
4280 +
4281 +       return error;
4282 +}
4283 +
4284 +static int apparmor_ptrace(struct task_struct *tracer,
4285 +                          struct task_struct *tracee)
4286 +{
4287 +       struct aa_task_context *cxt;
4288 +       int error = 0;
4289 +
4290 +       /*
4291 +        * tracer can ptrace tracee when
4292 +        * - tracer is unconfined
4293 +        * - tracer & tracee are in the same namespace &&
4294 +        *   - tracer is in complain mode
4295 +        *   - tracer and tracee are confined by the same profile
4296 +        *   - tracer profile has CAP_SYS_PTRACE
4297 +        */
4298 +
4299 +       rcu_read_lock();
4300 +       cxt = aa_task_context(tracer);
4301 +       if (cxt) {
4302 +               if (tracer->nsproxy != tracee->nsproxy) {
4303 +                       struct aa_audit sa;
4304 +                       memset(&sa, 0, sizeof(sa));
4305 +                       sa.operation = "ptrace";
4306 +                       sa.gfp_mask = GFP_ATOMIC;
4307 +                       sa.parent = tracer->pid;
4308 +                       sa.task = tracee->pid;
4309 +                       sa.info = "different namespaces";
4310 +                       aa_audit_reject(cxt->profile, &sa);
4311 +                       error = -EPERM;
4312 +               } else {
4313 +                       struct aa_task_context *tracee_cxt =
4314 +                               aa_task_context(tracee);
4315 +
4316 +                       error = aa_may_ptrace(cxt, tracee_cxt ?
4317 +                                                  tracee_cxt->profile : NULL);
4318 +                       if (error && PROFILE_COMPLAIN(cxt->profile)) {
4319 +                               struct aa_audit sa;
4320 +                               memset(&sa, 0, sizeof(sa));
4321 +                               sa.operation = "ptrace";
4322 +                               sa.gfp_mask = GFP_ATOMIC;
4323 +                               sa.parent = tracer->pid;
4324 +                               sa.task = tracee->pid;
4325 +                               aa_audit_hint(cxt->profile, &sa);
4326 +                       }
4327 +               }
4328 +       }
4329 +       rcu_read_unlock();
4330 +
4331 +       return error;
4332 +}
4333 +
4334 +static int apparmor_ptrace_may_access(struct task_struct *child,
4335 +                                     unsigned int mode)
4336 +{
4337 +       return apparmor_ptrace(current, child);
4338 +}
4339 +
4340 +
4341 +static int apparmor_ptrace_traceme(struct task_struct *parent)
4342 +{
4343 +       return apparmor_ptrace(parent, current);
4344 +}
4345 +
4346 +static int apparmor_capable(struct task_struct *task, int cap)
4347 +{
4348 +       int error;
4349 +       struct aa_task_context *cxt;
4350 +
4351 +       /* cap_capable returns 0 on success, else -EPERM */
4352 +       error = cap_capable(task, cap);
4353 +
4354 +       rcu_read_lock();
4355 +       cxt = aa_task_context(task);
4356 +       if (cxt && (!error || cap_raised(cxt->profile->set_caps, cap)))
4357 +               error = aa_capability(cxt, cap);
4358 +       rcu_read_unlock();
4359 +
4360 +       return error;
4361 +}
4362 +
4363 +static int apparmor_sysctl(struct ctl_table *table, int op)
4364 +{
4365 +       struct aa_profile *profile = aa_get_profile(current);
4366 +       int error = 0;
4367 +
4368 +       if (profile) {
4369 +               char *buffer, *name;
4370 +               int mask;
4371 +
4372 +               mask = 0;
4373 +               if (op & 4)
4374 +                       mask |= MAY_READ;
4375 +               if (op & 2)
4376 +                       mask |= MAY_WRITE;
4377 +
4378 +               error = -ENOMEM;
4379 +               buffer = (char*)__get_free_page(GFP_KERNEL);
4380 +               if (!buffer)
4381 +                       goto out;
4382 +               name = sysctl_pathname(table, buffer, PAGE_SIZE);
4383 +               if (name && name - buffer >= 5) {
4384 +                       name -= 5;
4385 +                       memcpy(name, "/proc", 5);
4386 +                       error = aa_perm_path(profile, "sysctl", name, mask, 0);
4387 +               }
4388 +               free_page((unsigned long)buffer);
4389 +       }
4390 +
4391 +out:
4392 +       aa_put_profile(profile);
4393 +       return error;
4394 +}
4395 +
4396 +static int apparmor_bprm_set_security(struct linux_binprm *bprm)
4397 +{
4398 +       /* handle capability bits with setuid, etc */
4399 +       cap_bprm_set_security(bprm);
4400 +       /* already set based on script name */
4401 +       if (bprm->sh_bang)
4402 +               return 0;
4403 +       return aa_register(bprm);
4404 +}
4405 +
4406 +static int apparmor_bprm_secureexec(struct linux_binprm *bprm)
4407 +{
4408 +       int ret = cap_bprm_secureexec(bprm);
4409 +
4410 +       if (!ret && (unsigned long)bprm->security & AA_SECURE_EXEC_NEEDED) {
4411 +               AA_DEBUG("%s: secureexec required for %s\n",
4412 +                        __FUNCTION__, bprm->filename);
4413 +               ret = 1;
4414 +       }
4415 +
4416 +       return ret;
4417 +}
4418 +
4419 +static int apparmor_sb_mount(char *dev_name, struct path *path, char *type,
4420 +                             unsigned long flags, void *data)
4421 +{
4422 +       return aa_reject_syscall(current, GFP_KERNEL, "mount");
4423 +}
4424 +
4425 +static int apparmor_umount(struct vfsmount *mnt, int flags)
4426 +{
4427 +       return aa_reject_syscall(current, GFP_KERNEL, "umount");
4428 +}
4429 +
4430 +static int apparmor_inode_mkdir(struct inode *dir, struct dentry *dentry,
4431 +                               struct vfsmount *mnt, int mask)
4432 +{
4433 +       struct aa_profile *profile;
4434 +       int error = 0;
4435 +
4436 +       if (!mnt || !mediated_filesystem(dir))
4437 +               goto out;
4438 +
4439 +       profile = aa_get_profile(current);
4440 +
4441 +       if (profile)
4442 +               error = aa_perm_dir(profile, "inode_mkdir", dentry, mnt,
4443 +                                   MAY_WRITE);
4444 +
4445 +       aa_put_profile(profile);
4446 +
4447 +out:
4448 +       return error;
4449 +}
4450 +
4451 +static int apparmor_inode_rmdir(struct inode *dir, struct dentry *dentry,
4452 +                               struct vfsmount *mnt)
4453 +{
4454 +       struct aa_profile *profile;
4455 +       int error = 0;
4456 +
4457 +       if (!mnt || !mediated_filesystem(dir))
4458 +               goto out;
4459 +
4460 +       profile = aa_get_profile(current);
4461 +
4462 +       if (profile)
4463 +               error = aa_perm_dir(profile, "inode_rmdir", dentry, mnt,
4464 +                                   MAY_WRITE);
4465 +
4466 +       aa_put_profile(profile);
4467 +
4468 +out:
4469 +       return error;
4470 +}
4471 +
4472 +static int aa_permission(const char *operation, struct inode *inode,
4473 +                        struct dentry *dentry, struct vfsmount *mnt,
4474 +                        int mask, int check)
4475 +{
4476 +       int error = 0;
4477 +
4478 +       if (mnt && mediated_filesystem(inode)) {
4479 +               struct aa_profile *profile;
4480 +
4481 +               profile = aa_get_profile(current);
4482 +               if (profile)
4483 +                       error = aa_perm(profile, operation, dentry, mnt, mask,
4484 +                                       check);
4485 +               aa_put_profile(profile);
4486 +       }
4487 +       return error;
4488 +}
4489 +
4490 +static inline int aa_mask_permissions(int mask)
4491 +{
4492 +       if (mask & MAY_APPEND)
4493 +               mask &= (MAY_READ | MAY_APPEND | MAY_EXEC);
4494 +       else
4495 +               mask &= (MAY_READ | MAY_WRITE | MAY_EXEC);
4496 +       return mask;
4497 +}
4498 +
4499 +static int apparmor_inode_create(struct inode *dir, struct dentry *dentry,
4500 +                                struct vfsmount *mnt, int mask)
4501 +{
4502 +       return aa_permission("inode_create", dir, dentry, mnt, MAY_APPEND, 0);
4503 +}
4504 +
4505 +static int apparmor_inode_link(struct dentry *old_dentry,
4506 +                              struct vfsmount *old_mnt, struct inode *dir,
4507 +                              struct dentry *new_dentry,
4508 +                              struct vfsmount *new_mnt)
4509 +{
4510 +       int error = 0;
4511 +       struct aa_profile *profile;
4512 +
4513 +       if (!old_mnt || !new_mnt || !mediated_filesystem(dir))
4514 +               goto out;
4515 +
4516 +       profile = aa_get_profile(current);
4517 +
4518 +       if (profile)
4519 +               error = aa_link(profile, new_dentry, new_mnt,
4520 +                               old_dentry, old_mnt);
4521 +
4522 +       aa_put_profile(profile);
4523 +
4524 +out:
4525 +       return error;
4526 +}
4527 +
4528 +static int apparmor_inode_unlink(struct inode *dir, struct dentry *dentry,
4529 +                                struct vfsmount *mnt)
4530 +{
4531 +       int check = 0;
4532 +
4533 +       if (S_ISDIR(dentry->d_inode->i_mode))
4534 +               check |= AA_CHECK_DIR;
4535 +       return aa_permission("inode_unlink", dir, dentry, mnt, MAY_WRITE,
4536 +                            check);
4537 +}
4538 +
4539 +static int apparmor_inode_symlink(struct inode *dir, struct dentry *dentry,
4540 +                                 struct vfsmount *mnt, const char *old_name)
4541 +{
4542 +       return aa_permission("inode_symlink", dir, dentry, mnt, MAY_WRITE, 0);
4543 +}
4544 +
4545 +static int apparmor_inode_mknod(struct inode *dir, struct dentry *dentry,
4546 +                               struct vfsmount *mnt, int mode, dev_t dev)
4547 +{
4548 +       return aa_permission("inode_mknod", dir, dentry, mnt, MAY_WRITE, 0);
4549 +}
4550 +
4551 +static int apparmor_inode_rename(struct inode *old_dir,
4552 +                                struct dentry *old_dentry,
4553 +                                struct vfsmount *old_mnt,
4554 +                                struct inode *new_dir,
4555 +                                struct dentry *new_dentry,
4556 +                                struct vfsmount *new_mnt)
4557 +{
4558 +       struct aa_profile *profile;
4559 +       int error = 0;
4560 +
4561 +       if ((!old_mnt && !new_mnt) || !mediated_filesystem(old_dir))
4562 +               goto out;
4563 +
4564 +       profile = aa_get_profile(current);
4565 +
4566 +       if (profile) {
4567 +               struct inode *inode = old_dentry->d_inode;
4568 +               int check = 0;
4569 +
4570 +               if (inode && S_ISDIR(inode->i_mode))
4571 +                       check |= AA_CHECK_DIR;
4572 +               if (old_mnt)
4573 +                       error = aa_perm(profile, "inode_rename", old_dentry,
4574 +                                       old_mnt, MAY_READ | MAY_WRITE, check);
4575 +
4576 +               if (!error && new_mnt) {
4577 +                       error = aa_perm(profile, "inode_rename", new_dentry,
4578 +                                       new_mnt, MAY_WRITE, check);
4579 +               }
4580 +       }
4581 +
4582 +       aa_put_profile(profile);
4583 +
4584 +out:
4585 +       return error;
4586 +}
4587 +
4588 +static int apparmor_inode_permission(struct inode *inode, int mask)
4589 +{
4590 +       return 0;
4591 +}
4592 +
4593 +static int apparmor_inode_setattr(struct dentry *dentry, struct vfsmount *mnt,
4594 +                                 struct iattr *iattr)
4595 +{
4596 +       int error = 0;
4597 +
4598 +       if (!mnt)
4599 +               goto out;
4600 +
4601 +       if (mediated_filesystem(dentry->d_inode)) {
4602 +               struct aa_profile *profile;
4603 +
4604 +               profile = aa_get_profile(current);
4605 +               /*
4606 +                * Mediate any attempt to change attributes of a file
4607 +                * (chmod, chown, chgrp, etc)
4608 +                */
4609 +               if (profile)
4610 +                       error = aa_attr(profile, dentry, mnt, iattr);
4611 +
4612 +               aa_put_profile(profile);
4613 +       }
4614 +
4615 +out:
4616 +       return error;
4617 +}
4618 +
4619 +static int aa_xattr_permission(struct dentry *dentry, struct vfsmount *mnt,
4620 +                              const char *operation, int mask,
4621 +                              struct file *file)
4622 +{
4623 +       int error = 0;
4624 +
4625 +       if (mnt && mediated_filesystem(dentry->d_inode)) {
4626 +               struct aa_profile *profile = aa_get_profile(current);
4627 +               int check = file ? AA_CHECK_FD : 0;
4628 +
4629 +               if (profile)
4630 +                       error = aa_perm_xattr(profile, operation, dentry, mnt,
4631 +                                             mask, check);
4632 +               aa_put_profile(profile);
4633 +       }
4634 +
4635 +       return error;
4636 +}
4637 +
4638 +static int apparmor_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
4639 +                                  const char *name, const void *value,
4640 +                                  size_t size, int flags, struct file *file)
4641 +{
4642 +       int error = cap_inode_setxattr(dentry, mnt, name, value, size, flags,
4643 +                                      file);
4644 +
4645 +       if (!error)
4646 +               error = aa_xattr_permission(dentry, mnt, "xattr set",
4647 +                                           MAY_WRITE, file);
4648 +       return error;
4649 +}
4650 +
4651 +static int apparmor_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
4652 +                                  const char *name, struct file *file)
4653 +{
4654 +       return aa_xattr_permission(dentry, mnt, "xattr get", MAY_READ, file);
4655 +}
4656 +
4657 +static int apparmor_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt,
4658 +                                   struct file *file)
4659 +{
4660 +       return aa_xattr_permission(dentry, mnt, "xattr list", MAY_READ, file);
4661 +}
4662 +
4663 +static int apparmor_inode_removexattr(struct dentry *dentry,
4664 +                                     struct vfsmount *mnt, const char *name,
4665 +                                     struct file *file)
4666 +{
4667 +       return aa_xattr_permission(dentry, mnt, "xattr remove", MAY_WRITE,
4668 +                                  file);
4669 +}
4670 +
4671 +static int aa_file_permission(const char *op, struct file *file, int mask)
4672 +{
4673 +       struct aa_profile *profile;
4674 +       struct aa_profile *file_profile = (struct aa_profile*)file->f_security;
4675 +       int error = 0;
4676 +
4677 +       if (!file_profile)
4678 +               goto out;
4679 +
4680 +       /*
4681 +        * If this file was opened under a different profile, we
4682 +        * revalidate the access against the current profile.
4683 +        */
4684 +       profile = aa_get_profile(current);
4685 +       if (profile && (file_profile != profile || mask & AA_MAY_LOCK)) {
4686 +               struct dentry *dentry = file->f_dentry;
4687 +               struct vfsmount *mnt = file->f_vfsmnt;
4688 +               struct inode *inode = dentry->d_inode;
4689 +               int check = AA_CHECK_FD;
4690 +
4691 +               /*
4692 +                * FIXME: We should remember which profiles we revalidated
4693 +                *        against.
4694 +                */
4695 +               if (S_ISDIR(inode->i_mode))
4696 +                       check |= AA_CHECK_DIR;
4697 +               error = aa_permission(op, inode, dentry, mnt, mask, check);
4698 +       }
4699 +       aa_put_profile(profile);
4700 +
4701 +out:
4702 +       return error;
4703 +}
4704 +
4705 +static int apparmor_file_permission(struct file *file, int mask)
4706 +{
4707 +       return aa_file_permission("file_permission", file,
4708 +                                 aa_mask_permissions(mask));
4709 +}
4710 +
4711 +static inline int apparmor_file_lock (struct file *file, unsigned int cmd)
4712 +{
4713 +       int mask = AA_MAY_LOCK;
4714 +       if (cmd == F_WRLCK)
4715 +               mask |= MAY_WRITE;
4716 +       return aa_file_permission("file_lock", file, mask);
4717 +}
4718 +
4719 +static int apparmor_file_alloc_security(struct file *file)
4720 +{
4721 +       struct aa_profile *profile;
4722 +
4723 +       profile = aa_get_profile(current);
4724 +       if (profile)
4725 +               file->f_security = profile;
4726 +
4727 +       return 0;
4728 +}
4729 +
4730 +static void apparmor_file_free_security(struct file *file)
4731 +{
4732 +       struct aa_profile *file_profile = (struct aa_profile*)file->f_security;
4733 +
4734 +       aa_put_profile(file_profile);
4735 +}
4736 +
4737 +static inline int aa_mmap(struct file *file, const char *operation,
4738 +                         unsigned long prot, unsigned long flags)
4739 +{
4740 +       struct dentry *dentry;
4741 +       int mask = 0;
4742 +
4743 +       if (!file || !file->f_security)
4744 +               return 0;
4745 +
4746 +       if (prot & PROT_READ)
4747 +               mask |= MAY_READ;
4748 +       /* Private mappings don't require write perms since they don't
4749 +        * write back to the files */
4750 +       if ((prot & PROT_WRITE) && !(flags & MAP_PRIVATE))
4751 +               mask |= MAY_WRITE;
4752 +       if (prot & PROT_EXEC)
4753 +               mask |= AA_EXEC_MMAP;
4754 +
4755 +       dentry = file->f_dentry;
4756 +       return aa_permission(operation, dentry->d_inode, dentry,
4757 +                            file->f_vfsmnt, mask, AA_CHECK_FD);
4758 +}
4759 +
4760 +static int apparmor_file_mmap(struct file *file, unsigned long reqprot,
4761 +                             unsigned long prot, unsigned long flags,
4762 +                             unsigned long addr, unsigned long addr_only)
4763 +{
4764 +       if ((addr < mmap_min_addr) && !capable(CAP_SYS_RAWIO)) {
4765 +               struct aa_profile *profile = aa_get_profile(current);
4766 +               if (profile)
4767 +                       /* future control check here */
4768 +                       return -EACCES;
4769 +               else
4770 +                       return -EACCES;
4771 +               aa_put_profile(profile);
4772 +       }
4773 +
4774 +       return aa_mmap(file, "file_mmap", prot, flags);
4775 +}
4776 +
4777 +static int apparmor_file_mprotect(struct vm_area_struct *vma,
4778 +                                 unsigned long reqprot, unsigned long prot)
4779 +{
4780 +       return aa_mmap(vma->vm_file, "file_mprotect", prot,
4781 +                      !(vma->vm_flags & VM_SHARED) ? MAP_PRIVATE : 0);
4782 +}
4783 +
4784 +static int apparmor_path_permission(struct path *path, int mask)
4785 +{
4786 +       struct inode *inode;
4787 +       int check = 0;
4788 +
4789 +       if (!path)
4790 +               return 0;
4791 +
4792 +       inode = path->dentry->d_inode;
4793 +
4794 +       mask = aa_mask_permissions(mask);
4795 +       if (S_ISDIR(inode->i_mode)) {
4796 +               check |= AA_CHECK_DIR;
4797 +               /* allow traverse accesses to directories */
4798 +               mask &= ~MAY_EXEC;
4799 +               if (!mask)
4800 +                       return 0;
4801 +       }
4802 +
4803 +       return aa_permission("inode_permission", inode, path->dentry,
4804 +                            path->mnt, mask, check);
4805 +}
4806 +
4807 +static int apparmor_task_alloc_security(struct task_struct *task)
4808 +{
4809 +       return aa_clone(task);
4810 +}
4811 +
4812 +/*
4813 + * Called from IRQ context from RCU callback.
4814 + */
4815 +static void apparmor_task_free_security(struct task_struct *task)
4816 +{
4817 +       aa_release(task);
4818 +}
4819 +
4820 +static int apparmor_socket_create(int family, int type, int protocol, int kern)
4821 +{
4822 +       struct aa_profile *profile;
4823 +       int error = 0;
4824 +
4825 +       if (kern)
4826 +               return 0;
4827 +
4828 +       profile = aa_get_profile(current);
4829 +       if (profile)
4830 +               error = aa_net_perm(profile, "socket_create", family,
4831 +                                                       type, protocol);
4832 +       aa_put_profile(profile);
4833 +
4834 +       return error;
4835 +}
4836 +
4837 +static int apparmor_socket_post_create(struct socket *sock, int family,
4838 +                                       int type, int protocol, int kern)
4839 +{
4840 +       struct sock *sk = sock->sk;
4841 +
4842 +       if (kern)
4843 +               return 0;
4844 +
4845 +       return aa_revalidate_sk(sk, "socket_post_create");
4846 +}
4847 +
4848 +static int apparmor_socket_bind(struct socket *sock,
4849 +                               struct sockaddr *address, int addrlen)
4850 +{
4851 +       struct sock *sk = sock->sk;
4852 +
4853 +       return aa_revalidate_sk(sk, "socket_bind");
4854 +}
4855 +
4856 +static int apparmor_socket_connect(struct socket *sock,
4857 +                                       struct sockaddr *address, int addrlen)
4858 +{
4859 +       struct sock *sk = sock->sk;
4860 +
4861 +       return aa_revalidate_sk(sk, "socket_connect");
4862 +}
4863 +
4864 +static int apparmor_socket_listen(struct socket *sock, int backlog)
4865 +{
4866 +       struct sock *sk = sock->sk;
4867 +
4868 +       return aa_revalidate_sk(sk, "socket_listen");
4869 +}
4870 +
4871 +static int apparmor_socket_accept(struct socket *sock, struct socket *newsock)
4872 +{
4873 +       struct sock *sk = sock->sk;
4874 +
4875 +       return aa_revalidate_sk(sk, "socket_accept");
4876 +}
4877 +
4878 +static int apparmor_socket_sendmsg(struct socket *sock,
4879 +                                       struct msghdr *msg, int size)
4880 +{
4881 +       struct sock *sk = sock->sk;
4882 +
4883 +       return aa_revalidate_sk(sk, "socket_sendmsg");
4884 +}
4885 +
4886 +static int apparmor_socket_recvmsg(struct socket *sock,
4887 +                                  struct msghdr *msg, int size, int flags)
4888 +{
4889 +       struct sock *sk = sock->sk;
4890 +
4891 +       return aa_revalidate_sk(sk, "socket_recvmsg");
4892 +}
4893 +
4894 +static int apparmor_socket_getsockname(struct socket *sock)
4895 +{
4896 +       struct sock *sk = sock->sk;
4897 +
4898 +       return aa_revalidate_sk(sk, "socket_getsockname");
4899 +}
4900 +
4901 +static int apparmor_socket_getpeername(struct socket *sock)
4902 +{
4903 +       struct sock *sk = sock->sk;
4904 +
4905 +       return aa_revalidate_sk(sk, "socket_getpeername");
4906 +}
4907 +
4908 +static int apparmor_socket_getsockopt(struct socket *sock, int level,
4909 +                                       int optname)
4910 +{
4911 +       struct sock *sk = sock->sk;
4912 +
4913 +       return aa_revalidate_sk(sk, "socket_getsockopt");
4914 +}
4915 +
4916 +static int apparmor_socket_setsockopt(struct socket *sock, int level,
4917 +                                       int optname)
4918 +{
4919 +       struct sock *sk = sock->sk;
4920 +
4921 +       return aa_revalidate_sk(sk, "socket_setsockopt");
4922 +}
4923 +
4924 +static int apparmor_socket_shutdown(struct socket *sock, int how)
4925 +{
4926 +       struct sock *sk = sock->sk;
4927 +
4928 +       return aa_revalidate_sk(sk, "socket_shutdown");
4929 +}
4930 +
4931 +static int apparmor_getprocattr(struct task_struct *task, char *name,
4932 +                               char **value)
4933 +{
4934 +       unsigned len;
4935 +       int error;
4936 +       struct aa_profile *profile;
4937 +
4938 +       /* AppArmor only supports the "current" process attribute */
4939 +       if (strcmp(name, "current") != 0)
4940 +               return -EINVAL;
4941 +
4942 +       /* must be task querying itself or admin */
4943 +       if (current != task && !capable(CAP_SYS_ADMIN))
4944 +               return -EPERM;
4945 +
4946 +       profile = aa_get_profile(task);
4947 +       error = aa_getprocattr(profile, value, &len);
4948 +       aa_put_profile(profile);
4949 +       if (!error)
4950 +               error = len;
4951 +
4952 +       return error;
4953 +}
4954 +
4955 +static int apparmor_setprocattr(struct task_struct *task, char *name,
4956 +                               void *value, size_t size)
4957 +{
4958 +       char *command, *args;
4959 +       int error;
4960 +
4961 +       if (strcmp(name, "current") != 0 || size == 0 || size >= PAGE_SIZE)
4962 +               return -EINVAL;
4963 +       args = value;
4964 +       args[size] = '\0';
4965 +       args = strstrip(args);
4966 +       command = strsep(&args, " ");
4967 +       if (!args)
4968 +               return -EINVAL;
4969 +       while (isspace(*args))
4970 +               args++;
4971 +       if (!*args)
4972 +               return -EINVAL;
4973 +
4974 +       if (strcmp(command, "changehat") == 0) {
4975 +               if (current != task)
4976 +                       return -EACCES;
4977 +               error = aa_setprocattr_changehat(args);
4978 +       } else if (strcmp(command, "changeprofile") == 0) {
4979 +               if (current != task)
4980 +                       return -EACCES;
4981 +               error = aa_setprocattr_changeprofile(args);
4982 +       } else if (strcmp(command, "setprofile") == 0) {
4983 +               struct aa_profile *profile;
4984 +
4985 +               /* Only an unconfined process with admin capabilities
4986 +                * may change the profile of another task.
4987 +                */
4988 +
4989 +               if (!capable(CAP_SYS_ADMIN))
4990 +                       return -EACCES;
4991 +
4992 +               profile = aa_get_profile(current);
4993 +               if (profile) {
4994 +                       struct aa_audit sa;
4995 +                       memset(&sa, 0, sizeof(sa));
4996 +                       sa.operation = "profile_set";
4997 +                       sa.gfp_mask = GFP_KERNEL;
4998 +                       sa.task = task->pid;
4999 +                       sa.info = "from confined process";
5000 +                       aa_audit_reject(profile, &sa);
5001 +                       aa_put_profile(profile);
5002 +                       return -EACCES;
5003 +               }
5004 +               error = aa_setprocattr_setprofile(task, args);
5005 +       } else {
5006 +               struct aa_audit sa;
5007 +               memset(&sa, 0, sizeof(sa));
5008 +               sa.operation = "setprocattr";
5009 +               sa.gfp_mask = GFP_KERNEL;
5010 +               sa.info = "invalid command";
5011 +               sa.name = command;
5012 +               sa.task = task->pid;
5013 +               aa_audit_reject(NULL, &sa);
5014 +               return -EINVAL;
5015 +       }
5016 +
5017 +       if (!error)
5018 +               error = size;
5019 +       return error;
5020 +}
5021 +
5022 +static int apparmor_task_setrlimit(unsigned int resource,
5023 +                                  struct rlimit *new_rlim)
5024 +{
5025 +       struct aa_profile *profile;
5026 +       int error = 0;
5027 +
5028 +       profile = aa_get_profile(current);
5029 +       if (profile) {
5030 +               error = aa_task_setrlimit(profile, resource, new_rlim);
5031 +       }
5032 +       aa_put_profile(profile);
5033 +
5034 +       return error;
5035 +}
5036 +
5037 +struct security_operations apparmor_ops = {
5038 +       .name =                         "apparmor",
5039 +       .ptrace_may_access =            apparmor_ptrace_may_access,
5040 +       .ptrace_traceme =               apparmor_ptrace_traceme,
5041 +       .capget =                       cap_capget,
5042 +       .capset_check =                 cap_capset_check,
5043 +       .capset_set =                   cap_capset_set,
5044 +       .sysctl =                       apparmor_sysctl,
5045 +       .capable =                      apparmor_capable,
5046 +       .syslog =                       cap_syslog,
5047 +
5048 +       .bprm_apply_creds =             cap_bprm_apply_creds,
5049 +       .bprm_set_security =            apparmor_bprm_set_security,
5050 +       .bprm_secureexec =              apparmor_bprm_secureexec,
5051 +
5052 +       .sb_mount =                     apparmor_sb_mount,
5053 +       .sb_umount =                    apparmor_umount,
5054 +
5055 +       .inode_mkdir =                  apparmor_inode_mkdir,
5056 +       .inode_rmdir =                  apparmor_inode_rmdir,
5057 +       .inode_create =                 apparmor_inode_create,
5058 +       .inode_link =                   apparmor_inode_link,
5059 +       .inode_unlink =                 apparmor_inode_unlink,
5060 +       .inode_symlink =                apparmor_inode_symlink,
5061 +       .inode_mknod =                  apparmor_inode_mknod,
5062 +       .inode_rename =                 apparmor_inode_rename,
5063 +       .inode_permission =             apparmor_inode_permission,
5064 +       .inode_setattr =                apparmor_inode_setattr,
5065 +       .inode_setxattr =               apparmor_inode_setxattr,
5066 +       .inode_getxattr =               apparmor_inode_getxattr,
5067 +       .inode_listxattr =              apparmor_inode_listxattr,
5068 +       .inode_removexattr =            apparmor_inode_removexattr,
5069 +       .file_permission =              apparmor_file_permission,
5070 +       .file_alloc_security =          apparmor_file_alloc_security,
5071 +       .file_free_security =           apparmor_file_free_security,
5072 +       .file_mmap =                    apparmor_file_mmap,
5073 +       .file_mprotect =                apparmor_file_mprotect,
5074 +       .file_lock =                    apparmor_file_lock,
5075 +
5076 +       .path_permission =              apparmor_path_permission,
5077 +
5078 +       .task_alloc_security =          apparmor_task_alloc_security,
5079 +       .task_free_security =           apparmor_task_free_security,
5080 +       .task_post_setuid =             cap_task_post_setuid,
5081 +       .task_reparent_to_init =        cap_task_reparent_to_init,
5082 +       .task_setrlimit =               apparmor_task_setrlimit,
5083 +
5084 +       .getprocattr =                  apparmor_getprocattr,
5085 +       .setprocattr =                  apparmor_setprocattr,
5086 +
5087 +       .socket_create =                apparmor_socket_create,
5088 +       .socket_post_create =           apparmor_socket_post_create,
5089 +       .socket_bind =                  apparmor_socket_bind,
5090 +       .socket_connect =               apparmor_socket_connect,
5091 +       .socket_listen =                apparmor_socket_listen,
5092 +       .socket_accept =                apparmor_socket_accept,
5093 +       .socket_sendmsg =               apparmor_socket_sendmsg,
5094 +       .socket_recvmsg =               apparmor_socket_recvmsg,
5095 +       .socket_getsockname =           apparmor_socket_getsockname,
5096 +       .socket_getpeername =           apparmor_socket_getpeername,
5097 +       .socket_getsockopt =            apparmor_socket_getsockopt,
5098 +       .socket_setsockopt =            apparmor_socket_setsockopt,
5099 +       .socket_shutdown =              apparmor_socket_shutdown,
5100 +};
5101 +
5102 +void info_message(const char *str)
5103 +{
5104 +       struct aa_audit sa;
5105 +       memset(&sa, 0, sizeof(sa));
5106 +       sa.gfp_mask = GFP_KERNEL;
5107 +       sa.info = str;
5108 +       printk(KERN_INFO "AppArmor: %s\n", str);
5109 +       if (audit_enabled)
5110 +               aa_audit_message(NULL, &sa, AUDIT_APPARMOR_STATUS);
5111 +}
5112 +
5113 +static int __init apparmor_init(void)
5114 +{
5115 +       int error;
5116 +
5117 +       if (!apparmor_enabled) {
5118 +               info_message("AppArmor disabled by boottime parameter\n");
5119 +               return 0;
5120 +       }
5121 +
5122 +       if ((error = create_apparmorfs())) {
5123 +               AA_ERROR("Unable to activate AppArmor filesystem\n");
5124 +               goto createfs_out;
5125 +       }
5126 +
5127 +       if ((error = alloc_default_namespace())){
5128 +               AA_ERROR("Unable to allocate default profile namespace\n");
5129 +               goto alloc_out;
5130 +       }
5131 +
5132 +       if ((error = register_security(&apparmor_ops))) {
5133 +               AA_ERROR("Unable to register AppArmor\n");
5134 +               goto register_security_out;
5135 +       }
5136 +
5137 +       /* Report that AppArmor successfully initialized */
5138 +       apparmor_initialized = 1;
5139 +       if (apparmor_complain)
5140 +               info_message("AppArmor initialized: complainmode enabled");
5141 +       else
5142 +               info_message("AppArmor initialized");
5143 +
5144 +       return error;
5145 +
5146 +register_security_out:
5147 +       free_default_namespace();
5148 +
5149 +alloc_out:
5150 +       destroy_apparmorfs();
5151 +
5152 +createfs_out:
5153 +       return error;
5154 +
5155 +}
5156 +
5157 +security_initcall(apparmor_init);
5158 +
5159 +void apparmor_disable(void)
5160 +{
5161 +       /* Remove and release all the profiles on the profile list. */
5162 +       mutex_lock(&aa_interface_lock);
5163 +       aa_profile_ns_list_release();
5164 +
5165 +       /* FIXME: cleanup profiles references on files */
5166 +       free_default_namespace();
5167 +
5168 +       /*
5169 +        * Delay for an rcu cycle to make sure that all active task
5170 +        * context readers have finished, and all profiles have been
5171 +        * freed by their rcu callbacks.
5172 +        */
5173 +       synchronize_rcu();
5174 +
5175 +       destroy_apparmorfs();
5176 +       mutex_unlock(&aa_interface_lock);
5177 +
5178 +       apparmor_initialized = 0;
5179 +
5180 +       info_message("AppArmor protection removed");
5181 +}
5182 +
5183 +MODULE_DESCRIPTION("AppArmor process confinement");
5184 +MODULE_AUTHOR("Novell/Immunix, http://bugs.opensuse.org");
5185 +MODULE_LICENSE("GPL");
5186 diff -uprN linux-2.6.27./security/apparmor/main.c linux-2.6.27/security/apparmor/main.c
5187 --- linux-2.6.27./security/apparmor/main.c      1970-01-01 01:00:00.000000000 +0100
5188 +++ linux-2.6.27/security/apparmor/main.c       2008-10-29 14:28:53.326113825 +0100
5189 @@ -0,0 +1,1690 @@
5190 +/*
5191 + *     Copyright (C) 2002-2007 Novell/SUSE
5192 + *
5193 + *     This program is free software; you can redistribute it and/or
5194 + *     modify it under the terms of the GNU General Public License as
5195 + *     published by the Free Software Foundation, version 2 of the
5196 + *     License.
5197 + *
5198 + *     AppArmor Core
5199 + */
5200 +
5201 +#include <linux/security.h>
5202 +#include <linux/namei.h>
5203 +#include <linux/audit.h>
5204 +#include <linux/mount.h>
5205 +#include <linux/ptrace.h>
5206 +#include <linux/socket.h>
5207 +#include <linux/net.h>
5208 +#include <net/sock.h>
5209 +
5210 +#include "apparmor.h"
5211 +
5212 +#include "inline.h"
5213 +
5214 +/*
5215 + * Table of capability names: we generate it from capabilities.h.
5216 + */
5217 +static const char *capability_names[] = {
5218 +#include "capability_names.h"
5219 +};
5220 +
5221 +struct aa_namespace *default_namespace;
5222 +
5223 +static int aa_inode_mode(struct inode *inode)
5224 +{
5225 +       /* if the inode doesn't exist the user is creating it */
5226 +       if (!inode || current->fsuid == inode->i_uid)
5227 +               return AA_USER_SHIFT;
5228 +       return AA_OTHER_SHIFT;
5229 +}
5230 +
5231 +int alloc_default_namespace(void)
5232 +{
5233 +       struct aa_namespace *ns;
5234 +       char *name = kstrdup("default", GFP_KERNEL);
5235 +       if (!name)
5236 +               return -ENOMEM;
5237 +       ns = alloc_aa_namespace(name);
5238 +       if (!ns) {
5239 +               kfree(name);
5240 +               return -ENOMEM;
5241 +       }
5242 +
5243 +       write_lock(&profile_ns_list_lock);
5244 +       default_namespace = ns;
5245 +       aa_get_namespace(ns);
5246 +       list_add(&ns->list, &profile_ns_list);
5247 +       write_unlock(&profile_ns_list_lock);
5248 +
5249 +       return 0;
5250 +}
5251 +
5252 +void free_default_namespace(void)
5253 +{
5254 +       write_lock(&profile_ns_list_lock);
5255 +       list_del_init(&default_namespace->list);
5256 +       write_unlock(&profile_ns_list_lock);
5257 +       aa_put_namespace(default_namespace);
5258 +       default_namespace = NULL;
5259 +}
5260 +
5261 +static void aa_audit_file_sub_mask(struct audit_buffer *ab, char *buffer,
5262 +                                  int mask)
5263 +{
5264 +       const char unsafex[] = "upcn";
5265 +       const char safex[] = "UPCN";
5266 +       char *m = buffer;
5267 +
5268 +       if (mask & AA_EXEC_MMAP)
5269 +               *m++ = 'm';
5270 +       if (mask & MAY_READ)
5271 +               *m++ = 'r';
5272 +       if (mask & MAY_WRITE)
5273 +               *m++ = 'w';
5274 +       else if (mask & MAY_APPEND)
5275 +               *m++ = 'a';
5276 +       if (mask & MAY_EXEC) {
5277 +               int index = AA_EXEC_INDEX(mask);
5278 +               /* all indexes > 4 are also named transitions */
5279 +               if (index > 4)
5280 +                       index = 4;
5281 +               if (index > 0) {
5282 +                       if (mask & AA_EXEC_UNSAFE)
5283 +                               *m++ = unsafex[index - 1];
5284 +                       else
5285 +                               *m++ = safex[index - 1];
5286 +               }
5287 +               if (mask & AA_EXEC_INHERIT)
5288 +                       *m++ = 'i';
5289 +               *m++ = 'x';
5290 +       }
5291 +       if (mask & AA_MAY_LINK)
5292 +               *m++ = 'l';
5293 +       if (mask & AA_MAY_LOCK)
5294 +               *m++ = 'k';
5295 +       *m++ = '\0';
5296 +}
5297 +
5298 +static void aa_audit_file_mask(struct audit_buffer *ab, const char *name,
5299 +                              int mask)
5300 +{
5301 +       char user[10], other[10];
5302 +
5303 +       aa_audit_file_sub_mask(ab, user,
5304 +                              (mask & AA_USER_PERMS) >> AA_USER_SHIFT);
5305 +       aa_audit_file_sub_mask(ab, other,
5306 +                              (mask & AA_OTHER_PERMS) >> AA_OTHER_SHIFT);
5307 +
5308 +       audit_log_format(ab, " %s=\"%s::%s\"", name, user, other);
5309 +}
5310 +
5311 +static const char *address_families[] = {
5312 +#include "af_names.h"
5313 +};
5314 +
5315 +static const char *sock_types[] = {
5316 +       "unknown(0)",
5317 +       "stream",
5318 +       "dgram",
5319 +       "raw",
5320 +       "rdm",
5321 +       "seqpacket",
5322 +       "dccp",
5323 +       "unknown(7)",
5324 +       "unknown(8)",
5325 +       "unknown(9)",
5326 +       "packet",
5327 +};
5328 +
5329 +/**
5330 + * aa_audit - Log an audit event to the audit subsystem
5331 + * @profile: profile to check against
5332 + * @sa: audit event
5333 + * @audit_cxt: audit context to log message to
5334 + * @type: audit event number
5335 + */
5336 +static int aa_audit_base(struct aa_profile *profile, struct aa_audit *sa,
5337 +                        struct audit_context *audit_cxt, int type)
5338 +{
5339 +       struct audit_buffer *ab = NULL;
5340 +
5341 +       ab = audit_log_start(audit_cxt, sa->gfp_mask, type);
5342 +
5343 +       if (!ab) {
5344 +               AA_ERROR("Unable to log event (%d) to audit subsys\n",
5345 +                        type);
5346 +                /* don't fail operations in complain mode even if logging
5347 +                 * fails */
5348 +               return type == AUDIT_APPARMOR_ALLOWED ? 0 : -ENOMEM;
5349 +       }
5350 +
5351 +       if (sa->operation)
5352 +               audit_log_format(ab, "operation=\"%s\"", sa->operation);
5353 +
5354 +       if (sa->info) {
5355 +               audit_log_format(ab, " info=\"%s\"", sa->info);
5356 +               if (sa->error_code)
5357 +                       audit_log_format(ab, " error=%d", sa->error_code);
5358 +       }
5359 +
5360 +       if (sa->request_mask)
5361 +               aa_audit_file_mask(ab, "requested_mask", sa->request_mask);
5362 +
5363 +       if (sa->denied_mask)
5364 +               aa_audit_file_mask(ab, "denied_mask", sa->denied_mask);
5365 +
5366 +       if (sa->request_mask)
5367 +               audit_log_format(ab, " fsuid=%d", current->fsuid);
5368 +
5369 +       if (sa->rlimit)
5370 +               audit_log_format(ab, " rlimit=%d", sa->rlimit - 1);
5371 +
5372 +       if (sa->iattr) {
5373 +               struct iattr *iattr = sa->iattr;
5374 +
5375 +               audit_log_format(ab, " attribute=\"%s%s%s%s%s%s%s\"",
5376 +                       iattr->ia_valid & ATTR_MODE ? "mode," : "",
5377 +                       iattr->ia_valid & ATTR_UID ? "uid," : "",
5378 +                       iattr->ia_valid & ATTR_GID ? "gid," : "",
5379 +                       iattr->ia_valid & ATTR_SIZE ? "size," : "",
5380 +                       iattr->ia_valid & (ATTR_ATIME | ATTR_ATIME_SET) ?
5381 +                               "atime," : "",
5382 +                       iattr->ia_valid & (ATTR_MTIME | ATTR_MTIME_SET) ?
5383 +                               "mtime," : "",
5384 +                       iattr->ia_valid & ATTR_CTIME ? "ctime," : "");
5385 +       }
5386 +
5387 +       if (sa->task)
5388 +               audit_log_format(ab, " task=%d", sa->task);
5389 +
5390 +       if (sa->parent)
5391 +               audit_log_format(ab, " parent=%d", sa->parent);
5392 +
5393 +       if (sa->name) {
5394 +               audit_log_format(ab, " name=");
5395 +               audit_log_untrustedstring(ab, sa->name);
5396 +       }
5397 +
5398 +       if (sa->name2) {
5399 +               audit_log_format(ab, " name2=");
5400 +               audit_log_untrustedstring(ab, sa->name2);
5401 +       }
5402 +
5403 +       if (sa->family || sa->type) {
5404 +               if (address_families[sa->family])
5405 +                       audit_log_format(ab, " family=\"%s\"",
5406 +                                        address_families[sa->family]);
5407 +               else
5408 +                       audit_log_format(ab, " family=\"unknown(%d)\"",
5409 +                                        sa->family);
5410 +
5411 +               if (sock_types[sa->type])
5412 +                       audit_log_format(ab, " sock_type=\"%s\"",
5413 +                                        sock_types[sa->type]);
5414 +               else
5415 +                       audit_log_format(ab, " sock_type=\"unknown(%d)\"",
5416 +                                        sa->type);
5417 +
5418 +               audit_log_format(ab, " protocol=%d", sa->protocol);
5419 +       }
5420 +
5421 +        audit_log_format(ab, " pid=%d", current->pid);
5422 +
5423 +       if (profile) {
5424 +               audit_log_format(ab, " profile=");
5425 +               audit_log_untrustedstring(ab, profile->name);
5426 +
5427 +               if (profile->ns != default_namespace) {
5428 +                       audit_log_format(ab, " namespace=");
5429 +                       audit_log_untrustedstring(ab, profile->ns->name);
5430 +               }
5431 +       }
5432 +
5433 +       audit_log_end(ab);
5434 +
5435 +       return type == AUDIT_APPARMOR_ALLOWED ? 0 : sa->error_code;
5436 +}
5437 +
5438 +/**
5439 + * aa_audit_syscallreject - Log a syscall rejection to the audit subsystem
5440 + * @profile: profile to check against
5441 + * @gfp: memory allocation flags
5442 + * @msg: string describing syscall being rejected
5443 + */
5444 +int aa_audit_syscallreject(struct aa_profile *profile, gfp_t gfp,
5445 +                          const char *msg)
5446 +{
5447 +       struct aa_audit sa;
5448 +       memset(&sa, 0, sizeof(sa));
5449 +       sa.operation = "syscall";
5450 +       sa.name = msg;
5451 +       sa.gfp_mask = gfp;
5452 +       sa.error_code = -EPERM;
5453 +
5454 +       return aa_audit_base(profile, &sa, current->audit_context,
5455 +                            AUDIT_APPARMOR_DENIED);
5456 +}
5457 +
5458 +int aa_audit_message(struct aa_profile *profile, struct aa_audit *sa,
5459 +                     int type)
5460 +{
5461 +       struct audit_context *audit_cxt;
5462 +
5463 +       audit_cxt = apparmor_logsyscall ? current->audit_context : NULL;
5464 +       return aa_audit_base(profile, sa, audit_cxt, type);
5465 +}
5466 +
5467 +void aa_audit_hint(struct aa_profile *profile, struct aa_audit *sa)
5468 +{
5469 +       aa_audit_message(profile, sa, AUDIT_APPARMOR_HINT);
5470 +}
5471 +
5472 +void aa_audit_status(struct aa_profile *profile, struct aa_audit *sa)
5473 +{
5474 +       aa_audit_message(profile, sa, AUDIT_APPARMOR_STATUS);
5475 +}
5476 +
5477 +int aa_audit_reject(struct aa_profile *profile, struct aa_audit *sa)
5478 +{
5479 +       return aa_audit_message(profile, sa, AUDIT_APPARMOR_DENIED);
5480 +}
5481 +
5482 +/**
5483 + * aa_audit - Log an audit event to the audit subsystem
5484 + * @profile: profile to check against
5485 + * @sa: audit event
5486 + */
5487 +int aa_audit(struct aa_profile *profile, struct aa_audit *sa)
5488 +{
5489 +       int type = AUDIT_APPARMOR_DENIED;
5490 +       struct audit_context *audit_cxt;
5491 +
5492 +       if (likely(!sa->error_code))
5493 +               type = AUDIT_APPARMOR_AUDIT;
5494 +       else if (PROFILE_COMPLAIN(profile))
5495 +               type = AUDIT_APPARMOR_ALLOWED;
5496 +
5497 +       audit_cxt = apparmor_logsyscall ? current->audit_context : NULL;
5498 +       return aa_audit_base(profile, sa, audit_cxt, type);
5499 +}
5500 +
5501 +static int aa_audit_file(struct aa_profile *profile, struct aa_audit *sa)
5502 +{
5503 +       if (likely(!sa->error_code)) {
5504 +               int mask = sa->audit_mask & AUDIT_FILE_MASK;
5505 +
5506 +               if (unlikely(PROFILE_AUDIT(profile)))
5507 +                       mask |= AUDIT_FILE_MASK;
5508 +
5509 +               if (likely(!(sa->request_mask & mask)))
5510 +                       return 0;
5511 +
5512 +               /* mask off perms that are not being force audited */
5513 +               sa->request_mask &= mask | ALL_AA_EXEC_TYPE;
5514 +       } else {
5515 +               int mask = AUDIT_QUIET_MASK(sa->audit_mask);
5516 +
5517 +               if (!(sa->denied_mask & ~mask))
5518 +                       return sa->error_code;
5519 +
5520 +               /* mask off perms whose denial is being silenced */
5521 +               if (!PROFILE_COMPLAIN(profile))
5522 +                       sa->denied_mask &= (~mask) | ALL_AA_EXEC_TYPE;
5523 +       }
5524 +
5525 +       return aa_audit(profile, sa);
5526 +}
5527 +
5528 +static int aa_audit_caps(struct aa_profile *profile, struct aa_audit *sa,
5529 +                        int cap)
5530 +{
5531 +       if (likely(!sa->error_code)) {
5532 +               if (likely(!PROFILE_AUDIT(profile) &&
5533 +                          !cap_raised(profile->audit_caps, cap)))
5534 +                       return 0;
5535 +       }
5536 +
5537 +       /* quieting of capabilities is handled the caps_logged cache */
5538 +       return aa_audit(profile, sa);
5539 +}
5540 +
5541 +/**
5542 + * aa_file_denied - check for @mask access on a file
5543 + * @profile: profile to check against
5544 + * @name: pathname of file
5545 + * @mask: permission mask requested for file
5546 + * @audit_mask: return audit mask for the match
5547 + *
5548 + * Return %0 on success, or else the permissions in @mask that the
5549 + * profile denies.
5550 + */
5551 +static int aa_file_denied(struct aa_profile *profile, const char *name,
5552 +                         int mask, int *audit_mask)
5553 +{
5554 +       return (mask & ~aa_match(profile->file_rules, name, audit_mask));
5555 +}
5556 +
5557 +/**
5558 + * aa_link_denied - check for permission to link a file
5559 + * @profile: profile to check against
5560 + * @link: pathname of link being created
5561 + * @target: pathname of target to be linked to
5562 + * @target_mode: UGO shift for target inode
5563 + * @request_mask: the permissions subset valid only if link succeeds
5564 + * @audit_mask: return the audit_mask for the link permission
5565 + * Return %0 on success, or else the permissions that the profile denies.
5566 + */
5567 +static int aa_link_denied(struct aa_profile *profile, const char *link,
5568 +                         const char *target, int target_mode,
5569 +                         int *request_mask, int *audit_mask)
5570 +{
5571 +       unsigned int state;
5572 +       int l_mode, t_mode, l_x, t_x, denied_mask = 0;
5573 +       int link_mask = AA_MAY_LINK << target_mode;
5574 +
5575 +       *request_mask = link_mask;
5576 +
5577 +       l_mode = aa_match_state(profile->file_rules, DFA_START, link, &state);
5578 +
5579 +       if (l_mode & link_mask) {
5580 +               int mode;
5581 +               /* test to see if target can be paired with link */
5582 +               state = aa_dfa_null_transition(profile->file_rules, state);
5583 +               mode = aa_match_state(profile->file_rules, state, target,
5584 +                                     &state);
5585 +
5586 +               if (!(mode & link_mask))
5587 +                       denied_mask |= link_mask;
5588 +
5589 +               *audit_mask = dfa_audit_mask(profile->file_rules, state);
5590 +
5591 +               /* return if link subset test is not required */
5592 +               if (!(mode & (AA_LINK_SUBSET_TEST << target_mode)))
5593 +                       return denied_mask;
5594 +       }
5595 +
5596 +       /* Do link perm subset test requiring permission on link are a
5597 +        * subset of the permissions on target.
5598 +        * If a subset test is required a permission subset test of the
5599 +        * perms for the link are done against the user::other of the
5600 +        * target's 'r', 'w', 'x', 'a', 'k', and 'm' permissions.
5601 +        *
5602 +        * If the link has 'x', an exact match of all the execute flags
5603 +        * must match.
5604 +        */
5605 +       denied_mask |= ~l_mode & link_mask;
5606 +
5607 +       t_mode = aa_match(profile->file_rules, target, NULL);
5608 +
5609 +       l_x = l_mode & (ALL_AA_EXEC_TYPE | AA_EXEC_BITS);
5610 +       t_x = t_mode & (ALL_AA_EXEC_TYPE | AA_EXEC_BITS);
5611 +
5612 +       /* For actual subset test ignore valid-profile-transition flags,
5613 +        * and link bits
5614 +        */
5615 +       l_mode &= AA_FILE_PERMS & ~AA_LINK_BITS;
5616 +       t_mode &= AA_FILE_PERMS & ~AA_LINK_BITS;
5617 +
5618 +       *request_mask = l_mode | link_mask;
5619 +
5620 +       if (l_mode) {
5621 +               int x = l_x | (t_x & ALL_AA_EXEC_UNSAFE);
5622 +               denied_mask |= l_mode & ~t_mode;
5623 +               /* mask off x modes not used by link */
5624 +
5625 +               /* handle exec subset
5626 +                * - link safe exec issubset of unsafe exec
5627 +                * - no link x perm is subset of target having x perm
5628 +                */
5629 +               if ((l_mode & AA_USER_EXEC) &&
5630 +                   (x & AA_USER_EXEC_TYPE) != (t_x & AA_USER_EXEC_TYPE))
5631 +                       denied_mask = AA_USER_EXEC | (l_x & AA_USER_EXEC_TYPE);
5632 +               if ((l_mode & AA_OTHER_EXEC) &&
5633 +                   (x & AA_OTHER_EXEC_TYPE) != (t_x & AA_OTHER_EXEC_TYPE))
5634 +                       denied_mask = AA_OTHER_EXEC | (l_x & AA_OTHER_EXEC_TYPE);
5635 +       }
5636 +
5637 +       return denied_mask;
5638 +}
5639 +
5640 +/**
5641 + * aa_get_name - compute the pathname of a file
5642 + * @dentry: dentry of the file
5643 + * @mnt: vfsmount of the file
5644 + * @buffer: buffer that aa_get_name() allocated
5645 + * @check: AA_CHECK_DIR is set if the file is a directory
5646 + *
5647 + * Returns a pointer to the beginning of the pathname (which usually differs
5648 + * from the beginning of the buffer), or an error code.
5649 + *
5650 + * We need @check to indicate whether the file is a directory or not because
5651 + * the file may not yet exist, and so we cannot check the inode's file type.
5652 + */
5653 +static char *aa_get_name(struct dentry *dentry, struct vfsmount *mnt,
5654 +                        char **buffer, int check)
5655 +{
5656 +       char *name;
5657 +       int is_dir, size = 256;
5658 +
5659 +       is_dir = (check & AA_CHECK_DIR) ? 1 : 0;
5660 +
5661 +       for (;;) {
5662 +               char *buf = kmalloc(size, GFP_KERNEL);
5663 +               if (!buf)
5664 +                       return ERR_PTR(-ENOMEM);
5665 +
5666 +               name = d_namespace_path(dentry, mnt, buf, size - is_dir);
5667 +               if (!IS_ERR(name)) {
5668 +                       if (name[0] != '/') {
5669 +                               /*
5670 +                                * This dentry is not connected to the
5671 +                                * namespace root -- reject access.
5672 +                                */
5673 +                               kfree(buf);
5674 +                               return ERR_PTR(-ENOENT);
5675 +                       }
5676 +                       if (is_dir && name[1] != '\0') {
5677 +                               /*
5678 +                                * Append "/" to the pathname. The root
5679 +                                * directory is a special case; it already
5680 +                                * ends in slash.
5681 +                                */
5682 +                               buf[size - 2] = '/';
5683 +                               buf[size - 1] = '\0';
5684 +                       }
5685 +
5686 +                       *buffer = buf;
5687 +                       return name;
5688 +               }
5689 +               if (PTR_ERR(name) != -ENAMETOOLONG)
5690 +                       return name;
5691 +
5692 +               kfree(buf);
5693 +               size <<= 1;
5694 +               if (size > apparmor_path_max)
5695 +                       return ERR_PTR(-ENAMETOOLONG);
5696 +       }
5697 +}
5698 +
5699 +static char *new_compound_name(const char *n1, const char *n2)
5700 +{
5701 +       char *name = kmalloc(strlen(n1) + strlen(n2) + 3, GFP_KERNEL);
5702 +       if (name)
5703 +               sprintf(name, "%s//%s", n1, n2);
5704 +       return name;
5705 +}
5706 +static inline void aa_put_name_buffer(char *buffer)
5707 +{
5708 +       kfree(buffer);
5709 +}
5710 +
5711 +/**
5712 + * aa_perm_dentry - check if @profile allows @mask for a file
5713 + * @profile: profile to check against
5714 + * @dentry: dentry of the file
5715 + * @mnt: vfsmount o the file
5716 + * @sa: audit context
5717 + * @mask: requested profile permissions
5718 + * @check: kind of check to perform
5719 + *
5720 + * Returns 0 upon success, or else an error code.
5721 + *
5722 + * @check indicates the file type, and whether the file was accessed through
5723 + * an open file descriptor (AA_CHECK_FD) or not.
5724 + */
5725 +static int aa_perm_dentry(struct aa_profile *profile, struct dentry *dentry,
5726 +                         struct vfsmount *mnt, struct aa_audit *sa, int check)
5727 +{
5728 +       int error;
5729 +       char *buffer = NULL;
5730 +
5731 +       sa->name = aa_get_name(dentry, mnt, &buffer, check);
5732 +       sa->request_mask <<= aa_inode_mode(dentry->d_inode);
5733 +       if (IS_ERR(sa->name)) {
5734 +               /*
5735 +                * deleted files are given a pass on permission checks when
5736 +                * accessed through a file descriptor.
5737 +                */
5738 +               if (PTR_ERR(sa->name) == -ENOENT && (check & AA_CHECK_FD))
5739 +                       sa->denied_mask = 0;
5740 +               else {
5741 +                       sa->denied_mask = sa->request_mask;
5742 +                       sa->error_code = PTR_ERR(sa->name);
5743 +                       if (sa->error_code == -ENOENT)
5744 +                               sa->info = "Failed name resolution - object not a valid entry";
5745 +                       else if (sa->error_code == -ENAMETOOLONG)
5746 +                               sa->info = "Failed name resolution - name too long";
5747 +                       else
5748 +                               sa->info = "Failed name resolution";
5749 +               }
5750 +               sa->name = NULL;
5751 +       } else
5752 +               sa->denied_mask = aa_file_denied(profile, sa->name,
5753 +                                                sa->request_mask,
5754 +                                                &sa->audit_mask);
5755 +
5756 +       if (!sa->denied_mask)
5757 +               sa->error_code = 0;
5758 +
5759 +       error = aa_audit_file(profile, sa);
5760 +       aa_put_name_buffer(buffer);
5761 +
5762 +       return error;
5763 +}
5764 +
5765 +/**
5766 + * aa_attr - check if attribute change is allowed
5767 + * @profile: profile to check against
5768 + * @dentry: dentry of the file to check
5769 + * @mnt: vfsmount of the file to check
5770 + * @iattr: attribute changes requested
5771 + */
5772 +int aa_attr(struct aa_profile *profile, struct dentry *dentry,
5773 +           struct vfsmount *mnt, struct iattr *iattr)
5774 +{
5775 +       struct inode *inode = dentry->d_inode;
5776 +       int error, check;
5777 +       struct aa_audit sa;
5778 +
5779 +       memset(&sa, 0, sizeof(sa));
5780 +       sa.operation = "setattr";
5781 +       sa.gfp_mask = GFP_KERNEL;
5782 +       sa.iattr = iattr;
5783 +       sa.request_mask = MAY_WRITE;
5784 +       sa.error_code = -EACCES;
5785 +
5786 +       check = 0;
5787 +       if (inode && S_ISDIR(inode->i_mode))
5788 +               check |= AA_CHECK_DIR;
5789 +       if (iattr->ia_valid & ATTR_FILE)
5790 +               check |= AA_CHECK_FD;
5791 +
5792 +       error = aa_perm_dentry(profile, dentry, mnt, &sa, check);
5793 +
5794 +       return error;
5795 +}
5796 +
5797 +/**
5798 + * aa_perm_xattr - check if xattr attribute change is allowed
5799 + * @profile: profile to check against
5800 + * @dentry: dentry of the file to check
5801 + * @mnt: vfsmount of the file to check
5802 + * @operation: xattr operation being done
5803 + * @mask: access mode requested
5804 + * @check: kind of check to perform
5805 + */
5806 +int aa_perm_xattr(struct aa_profile *profile, const char *operation,
5807 +                 struct dentry *dentry, struct vfsmount *mnt, int mask,
5808 +                 int check)
5809 +{
5810 +       struct inode *inode = dentry->d_inode;
5811 +       int error;
5812 +       struct aa_audit sa;
5813 +
5814 +       memset(&sa, 0, sizeof(sa));
5815 +       sa.operation = operation;
5816 +       sa.gfp_mask = GFP_KERNEL;
5817 +       sa.request_mask = mask;
5818 +       sa.error_code = -EACCES;
5819 +
5820 +       if (inode && S_ISDIR(inode->i_mode))
5821 +               check |= AA_CHECK_DIR;
5822 +
5823 +       error = aa_perm_dentry(profile, dentry, mnt, &sa, check);
5824 +
5825 +       return error;
5826 +}
5827 +
5828 +/**
5829 + * aa_perm - basic apparmor permissions check
5830 + * @profile: profile to check against
5831 + * @dentry: dentry of the file to check
5832 + * @mnt: vfsmount of the file to check
5833 + * @mask: access mode requested
5834 + * @check: kind of check to perform
5835 + *
5836 + * Determine if access @mask for the file is authorized by @profile.
5837 + * Returns 0 on success, or else an error code.
5838 + */
5839 +int aa_perm(struct aa_profile *profile, const char *operation,
5840 +           struct dentry *dentry, struct vfsmount *mnt, int mask, int check)
5841 +{
5842 +       struct aa_audit sa;
5843 +       int error = 0;
5844 +
5845 +       if (mask == 0)
5846 +               goto out;
5847 +
5848 +       memset(&sa, 0, sizeof(sa));
5849 +       sa.operation = operation;
5850 +       sa.gfp_mask = GFP_KERNEL;
5851 +       sa.request_mask = mask;
5852 +       sa.error_code = -EACCES;
5853 +
5854 +       error = aa_perm_dentry(profile, dentry, mnt, &sa, check);
5855 +
5856 +out:
5857 +       return error;
5858 +}
5859 +
5860 +/**
5861 + * aa_perm_dir
5862 + * @profile: profile to check against
5863 + * @dentry: dentry of directory to check
5864 + * @mnt: vfsmount of directory to check
5865 + * @operation: directory operation being performed
5866 + * @mask: access mode requested
5867 + *
5868 + * Determine if directory operation (make/remove) for dentry is authorized
5869 + * by @profile.
5870 + * Returns 0 on success, or else an error code.
5871 + */
5872 +int aa_perm_dir(struct aa_profile *profile, const char *operation,
5873 +               struct dentry *dentry, struct vfsmount *mnt, int mask)
5874 +{
5875 +       struct aa_audit sa;
5876 +
5877 +       memset(&sa, 0, sizeof(sa));
5878 +       sa.operation = operation;
5879 +       sa.gfp_mask = GFP_KERNEL;
5880 +       sa.request_mask = mask;
5881 +       sa.error_code = -EACCES;
5882 +
5883 +       return aa_perm_dentry(profile, dentry, mnt, &sa, AA_CHECK_DIR);
5884 +}
5885 +
5886 +int aa_perm_path(struct aa_profile *profile, const char *operation,
5887 +                const char *name, int mask, uid_t uid)
5888 +{
5889 +       struct aa_audit sa;
5890 +
5891 +       memset(&sa, 0, sizeof(sa));
5892 +       sa.operation = operation;
5893 +       sa.gfp_mask = GFP_KERNEL;
5894 +       sa.request_mask = mask;
5895 +       sa.name = name;
5896 +       if (current->fsuid == uid)
5897 +               sa.request_mask = mask << AA_USER_SHIFT;
5898 +       else
5899 +               sa.request_mask = mask << AA_OTHER_SHIFT;
5900 +
5901 +       sa.denied_mask = aa_file_denied(profile, name, sa.request_mask,
5902 +                                       &sa.audit_mask) ;
5903 +       sa.error_code = sa.denied_mask ? -EACCES : 0;
5904 +
5905 +       return aa_audit_file(profile, &sa);
5906 +}
5907 +
5908 +/**
5909 + * aa_capability - test permission to use capability
5910 + * @cxt: aa_task_context with profile to check against
5911 + * @cap: capability to be tested
5912 + *
5913 + * Look up capability in profile capability set.
5914 + * Returns 0 on success, or else an error code.
5915 + */
5916 +int aa_capability(struct aa_task_context *cxt, int cap)
5917 +{
5918 +       int error = cap_raised(cxt->profile->capabilities, cap) ? 0 : -EPERM;
5919 +       struct aa_audit sa;
5920 +
5921 +       /* test if cap has alread been logged */
5922 +       if (cap_raised(cxt->caps_logged, cap)) {
5923 +               if (PROFILE_COMPLAIN(cxt->profile))
5924 +                       error = 0;
5925 +               return error;
5926 +       } else
5927 +               /* don't worry about rcu replacement of the cxt here.
5928 +                * caps_logged is a cache to reduce the occurence of
5929 +                * duplicate messages in the log.  The worst that can
5930 +                * happen is duplicate capability messages shows up in
5931 +                * the audit log
5932 +                */
5933 +               cap_raise(cxt->caps_logged, cap);
5934 +
5935 +       memset(&sa, 0, sizeof(sa));
5936 +       sa.operation = "capable";
5937 +       sa.gfp_mask = GFP_ATOMIC;
5938 +       sa.name = capability_names[cap];
5939 +       sa.error_code = error;
5940 +
5941 +       error = aa_audit_caps(cxt->profile, &sa, cap);
5942 +
5943 +       return error;
5944 +}
5945 +
5946 +/* must be used inside rcu_read_lock or task_lock */
5947 +int aa_may_ptrace(struct aa_task_context *cxt, struct aa_profile *tracee)
5948 +{
5949 +       if (!cxt || cxt->profile == tracee)
5950 +               return 0;
5951 +       return aa_capability(cxt, CAP_SYS_PTRACE);
5952 +}
5953 +
5954 +/**
5955 + * aa_link - hard link check
5956 + * @profile: profile to check against
5957 + * @link: dentry of link being created
5958 + * @link_mnt: vfsmount of link being created
5959 + * @target: dentry of link target
5960 + * @target_mnt: vfsmunt of link target
5961 + *
5962 + * Returns 0 on success, or else an error code.
5963 + */
5964 +int aa_link(struct aa_profile *profile,
5965 +           struct dentry *link, struct vfsmount *link_mnt,
5966 +           struct dentry *target, struct vfsmount *target_mnt)
5967 +{
5968 +       int error;
5969 +       struct aa_audit sa;
5970 +       char *buffer = NULL, *buffer2 = NULL;
5971 +
5972 +       memset(&sa, 0, sizeof(sa));
5973 +       sa.operation = "inode_link";
5974 +       sa.gfp_mask = GFP_KERNEL;
5975 +       sa.name = aa_get_name(link, link_mnt, &buffer, 0);
5976 +       sa.name2 = aa_get_name(target, target_mnt, &buffer2, 0);
5977 +
5978 +       if (IS_ERR(sa.name)) {
5979 +               sa.error_code = PTR_ERR(sa.name);
5980 +               sa.name = NULL;
5981 +       }
5982 +       if (IS_ERR(sa.name2)) {
5983 +               sa.error_code = PTR_ERR(sa.name2);
5984 +               sa.name2 = NULL;
5985 +       }
5986 +
5987 +       if (sa.name && sa.name2) {
5988 +               sa.denied_mask = aa_link_denied(profile, sa.name, sa.name2,
5989 +                                               aa_inode_mode(target->d_inode),
5990 +                                               &sa.request_mask,
5991 +                                               &sa.audit_mask);
5992 +               sa.error_code = sa.denied_mask ? -EACCES : 0;
5993 +       }
5994 +
5995 +       error = aa_audit_file(profile, &sa);
5996 +
5997 +       aa_put_name_buffer(buffer);
5998 +       aa_put_name_buffer(buffer2);
5999 +
6000 +       return error;
6001 +}
6002 +
6003 +int aa_net_perm(struct aa_profile *profile, char *operation,
6004 +               int family, int type, int protocol)
6005 +{
6006 +       struct aa_audit sa;
6007 +       int error = 0;
6008 +       u16 family_mask, audit_mask, quiet_mask;
6009 +
6010 +       if ((family < 0) || (family >= AF_MAX))
6011 +               return -EINVAL;
6012 +
6013 +       if ((type < 0) || (type >= SOCK_MAX))
6014 +               return -EINVAL;
6015 +
6016 +       /* unix domain and netlink sockets are handled by ipc */
6017 +       if (family == AF_UNIX || family == AF_NETLINK)
6018 +               return 0;
6019 +
6020 +       family_mask = profile->network_families[family];
6021 +       audit_mask = profile->audit_network[family];
6022 +       quiet_mask = profile->quiet_network[family];
6023 +
6024 +       error = (family_mask & (1 << type)) ? 0 : -EACCES;
6025 +
6026 +       memset(&sa, 0, sizeof(sa));
6027 +       sa.operation = operation;
6028 +       sa.gfp_mask = GFP_KERNEL;
6029 +       sa.family = family;
6030 +       sa.type = type;
6031 +       sa.protocol = protocol;
6032 +       sa.error_code = error;
6033 +
6034 +       if (likely(!error)) {
6035 +               if (!PROFILE_AUDIT(profile) && !(family_mask & audit_mask))
6036 +                       return 0;
6037 +       } else if (!((1 << type) & ~quiet_mask)) {
6038 +               return error;
6039 +       }
6040 +
6041 +       error = aa_audit(profile, &sa);
6042 +
6043 +       return error;
6044 +}
6045 +
6046 +int aa_revalidate_sk(struct sock *sk, char *operation)
6047 +{
6048 +       struct aa_profile *profile;
6049 +       int error = 0;
6050 +
6051 +       /* this is some debugging code to flush out the network hooks that
6052 +          that are called in interrupt context */
6053 +       if (in_interrupt()) {
6054 +               printk("AppArmor Debug: Hook being called from interrupt context\n");
6055 +               dump_stack();
6056 +               return 0;
6057 +       }
6058 +
6059 +       profile = aa_get_profile(current);
6060 +       if (profile)
6061 +               error = aa_net_perm(profile, operation,
6062 +                                   sk->sk_family, sk->sk_type,
6063 +                                   sk->sk_protocol);
6064 +       aa_put_profile(profile);
6065 +
6066 +       return error;
6067 +}
6068 +/**
6069 + * aa_task_setrlimit - test permission to set an rlimit
6070 + * @profile - profile confining the task
6071 + * @resource - the resource being set
6072 + * @new_rlim - the new resource limit
6073 + *
6074 + * Control raising the processes hard limit.
6075 + */
6076 +int aa_task_setrlimit(struct aa_profile *profile, unsigned int resource,
6077 +                     struct rlimit *new_rlim)
6078 +{
6079 +       struct aa_audit sa;
6080 +       int error = 0;
6081 +
6082 +       memset(&sa, 0, sizeof(sa));
6083 +       sa.operation = "setrlimit";
6084 +       sa.gfp_mask = GFP_KERNEL;
6085 +       sa.rlimit = resource + 1;
6086 +
6087 +       if (profile->rlimits.mask & (1 << resource) &&
6088 +           new_rlim->rlim_max > profile->rlimits.limits[resource].rlim_max) {
6089 +               sa.error_code = -EACCES;
6090 +
6091 +               error = aa_audit(profile, &sa);
6092 +       }
6093 +
6094 +       return error;
6095 +}
6096 +
6097 +static int aa_rlimit_nproc(struct aa_profile *profile) {
6098 +       if (profile && (profile->rlimits.mask & (1 << RLIMIT_NPROC)) &&
6099 +           profile->task_count >= profile->rlimits.limits[RLIMIT_NPROC].rlim_max)
6100 +               return -EAGAIN;
6101 +       return 0;
6102 +}
6103 +
6104 +void aa_set_rlimits(struct task_struct *task, struct aa_profile *profile)
6105 +{
6106 +       int i, mask;
6107 +
6108 +       if (!profile)
6109 +               return;
6110 +
6111 +       if (!profile->rlimits.mask)
6112 +               return;
6113 +
6114 +       task_lock(task->group_leader);
6115 +       mask = 1;
6116 +       for (i = 0; i < RLIM_NLIMITS; i++, mask <<= 1) {
6117 +               struct rlimit new_rlim, *old_rlim;
6118 +
6119 +               /* check to see if NPROC which is per profile and handled
6120 +                * in clone/exec or whether this is a limit to be set
6121 +                * can't set cpu limit either right now
6122 +                */
6123 +               if (i == RLIMIT_NPROC || i == RLIMIT_CPU)
6124 +                       continue;
6125 +
6126 +               old_rlim = task->signal->rlim + i;
6127 +               new_rlim = *old_rlim;
6128 +
6129 +               if (mask & profile->rlimits.mask &&
6130 +                   profile->rlimits.limits[i].rlim_max < new_rlim.rlim_max) {
6131 +                       new_rlim.rlim_max = profile->rlimits.limits[i].rlim_max;
6132 +                       /* soft limit should not exceed hard limit */
6133 +                       if (new_rlim.rlim_cur > new_rlim.rlim_max)
6134 +                               new_rlim.rlim_cur = new_rlim.rlim_max;
6135 +               }
6136 +
6137 +               *old_rlim = new_rlim;
6138 +       }
6139 +       task_unlock(task->group_leader);
6140 +}
6141 +
6142 +/*******************************
6143 + * Global task related functions
6144 + *******************************/
6145 +
6146 +/**
6147 + * aa_clone - initialize the task context for a new task
6148 + * @child: task that is being created
6149 + *
6150 + * Returns 0 on success, or else an error code.
6151 + */
6152 +int aa_clone(struct task_struct *child)
6153 +{
6154 +       struct aa_audit sa;
6155 +       struct aa_task_context *cxt, *child_cxt;
6156 +       struct aa_profile *profile;
6157 +
6158 +       if (!aa_task_context(current))
6159 +               return 0;
6160 +       child_cxt = aa_alloc_task_context(GFP_KERNEL);
6161 +       if (!child_cxt)
6162 +               return -ENOMEM;
6163 +
6164 +       memset(&sa, 0, sizeof(sa));
6165 +       sa.operation = "clone";
6166 +       sa.task = child->pid;
6167 +       sa.gfp_mask = GFP_KERNEL;
6168 +
6169 +repeat:
6170 +       profile = aa_get_profile(current);
6171 +       if (profile) {
6172 +               lock_profile(profile);
6173 +               cxt = aa_task_context(current);
6174 +               if (unlikely(profile->isstale || !cxt ||
6175 +                            cxt->profile != profile)) {
6176 +                       /**
6177 +                        * Race with profile replacement or removal, or with
6178 +                        * task context removal.
6179 +                        */
6180 +                       unlock_profile(profile);
6181 +                       aa_put_profile(profile);
6182 +                       goto repeat;
6183 +               }
6184 +
6185 +               if (aa_rlimit_nproc(profile)) {
6186 +                       sa.info = "rlimit nproc limit exceeded";
6187 +                       unlock_profile(profile);
6188 +                       aa_audit_reject(profile, &sa);
6189 +                       aa_put_profile(profile);
6190 +                       return -EAGAIN;
6191 +               }
6192 +
6193 +               /* No need to grab the child's task lock here. */
6194 +               aa_change_task_context(child, child_cxt, profile,
6195 +                                      cxt->cookie, cxt->previous_profile);
6196 +
6197 +               unlock_profile(profile);
6198 +
6199 +               if (APPARMOR_COMPLAIN(child_cxt) &&
6200 +                   profile == profile->ns->null_complain_profile) {
6201 +                       aa_audit_hint(profile, &sa);
6202 +               }
6203 +               aa_put_profile(profile);
6204 +       } else
6205 +               aa_free_task_context(child_cxt);
6206 +
6207 +       return 0;
6208 +}
6209 +
6210 +static struct aa_profile *
6211 +aa_register_find(struct aa_profile *profile, const char* ns_name,
6212 +                const char *name, int mandatory, int complain,
6213 +                struct aa_audit *sa)
6214 +{
6215 +       struct aa_namespace *ns;
6216 +       struct aa_profile *new_profile;
6217 +       int ns_ref = 0;
6218 +
6219 +       if (profile)
6220 +               ns = profile->ns;
6221 +       else
6222 +               ns = default_namespace;
6223 +
6224 +       if (ns_name) {
6225 +               /* locate the profile namespace */
6226 +               ns = aa_find_namespace(ns_name);
6227 +               if (!ns) {
6228 +                       if (mandatory) {
6229 +                               sa->info = "profile namespace not found";
6230 +                               sa->denied_mask = sa->request_mask;
6231 +                               sa->error_code = -ENOENT;
6232 +                               return ERR_PTR(-ENOENT);
6233 +                       } else {
6234 +                               return NULL;
6235 +                       }
6236 +               }
6237 +               ns_ref++;
6238 +       }
6239 +
6240 +       /* Locate new profile */
6241 +       new_profile = aa_find_profile(ns, name);
6242 +
6243 +       if (new_profile) {
6244 +               AA_DEBUG("%s: setting profile %s\n",
6245 +                        __FUNCTION__, new_profile->name);
6246 +       } else if (mandatory && profile) {
6247 +               sa->info = "mandatory profile missing";
6248 +               sa->denied_mask = sa->request_mask;     /* shifted MAY_EXEC */
6249 +               if (complain) {
6250 +                       aa_audit_hint(profile, sa);
6251 +                       new_profile =
6252 +                           aa_dup_profile(profile->ns->null_complain_profile);
6253 +               } else {
6254 +                       sa->error_code = -EACCES;
6255 +                       if (ns_ref)
6256 +                               aa_put_namespace(ns);
6257 +                       return ERR_PTR(-EACCES);
6258 +               }
6259 +       } else {
6260 +               /* Only way we can get into this code is if task
6261 +                * is unconfined, pix, nix.
6262 +                */
6263 +               AA_DEBUG("%s: No profile found for exec image '%s'\n",
6264 +                        __FUNCTION__,
6265 +                        name);
6266 +       }
6267 +       if (ns_ref)
6268 +               aa_put_namespace(ns);
6269 +       return new_profile;
6270 +}
6271 +
6272 +static struct aa_profile *
6273 +aa_x_to_profile(struct aa_profile *profile, const char *filename, int xmode,
6274 +               struct aa_audit *sa, char **child)
6275 +{
6276 +       struct aa_profile *new_profile = NULL;
6277 +       int ix = xmode & AA_EXEC_INHERIT;
6278 +       int complain = PROFILE_COMPLAIN(profile);
6279 +       int index;
6280 +
6281 +       *child = NULL;
6282 +       switch (xmode & AA_EXEC_MODIFIERS) {
6283 +       case 0:
6284 +               /* only valid with ix flag */
6285 +               ix = 1;
6286 +               break;
6287 +       case AA_EXEC_UNCONFINED:
6288 +               /* only valid without ix flag */
6289 +               ix = 0;
6290 +               break;
6291 +       case AA_EXEC_PROFILE:
6292 +               new_profile = aa_register_find(profile, NULL, filename, !ix,
6293 +                                              complain, sa);
6294 +               break;
6295 +       case AA_EXEC_CHILD:
6296 +               *child = new_compound_name(profile->name, filename);
6297 +               sa->name2 = *child;
6298 +               if (!*child) {
6299 +                       sa->info = "Failed name resolution - exec failed";
6300 +                       sa->error_code = -ENOMEM;
6301 +                       new_profile = ERR_PTR(-ENOMEM);
6302 +               } else {
6303 +                       new_profile = aa_register_find(profile, NULL, *child,
6304 +                                                      !ix, complain, sa);
6305 +               }
6306 +               break;
6307 +       default:
6308 +               /* all other indexes are named transitions */
6309 +               index = AA_EXEC_INDEX(xmode);
6310 +               if (index - 4 > profile->exec_table_size) {
6311 +                       sa->info = "invalid named transition - exec failed";
6312 +                       sa->error_code = -EACCES;
6313 +                       new_profile = ERR_PTR(-EACCES);
6314 +               } else {
6315 +                       char *ns_name = NULL;
6316 +                       char *name = profile->exec_table[index - 4];
6317 +                       if (*name == ':') {
6318 +                               ns_name = name + 1;
6319 +                               name = ns_name + strlen(ns_name) + 1;
6320 +                       }
6321 +                       sa->name2 = name;
6322 +                       sa->name3 = ns_name;
6323 +                       new_profile =
6324 +                               aa_register_find(profile, ns_name, name,
6325 +                                                !ix, complain, sa);
6326 +               }
6327 +       }
6328 +       if (IS_ERR(new_profile))
6329 +               /* all these failures must be audited - no quieting */
6330 +               return ERR_PTR(aa_audit_reject(profile, sa));
6331 +       return new_profile;
6332 +}
6333 +
6334 +/**
6335 + * aa_register - register a new program
6336 + * @bprm: binprm of program being registered
6337 + *
6338 + * Try to register a new program during execve().  This should give the
6339 + * new program a valid aa_task_context if confined.
6340 + */
6341 +int aa_register(struct linux_binprm *bprm)
6342 +{
6343 +       const char *filename;
6344 +       char  *buffer = NULL, *child = NULL;
6345 +       struct file *filp = bprm->file;
6346 +       struct aa_profile *profile, *old_profile, *new_profile = NULL;
6347 +       int exec_mode, complain = 0, shift;
6348 +       struct aa_audit sa;
6349 +
6350 +       AA_DEBUG("%s\n", __FUNCTION__);
6351 +
6352 +       profile = aa_get_profile(current);
6353 +
6354 +       shift = aa_inode_mode(filp->f_dentry->d_inode);
6355 +       memset(&sa, 0, sizeof(sa));
6356 +       sa.operation = "exec";
6357 +       sa.gfp_mask = GFP_KERNEL;
6358 +       sa.request_mask = MAY_EXEC << shift;
6359 +
6360 +       filename = aa_get_name(filp->f_dentry, filp->f_vfsmnt, &buffer, 0);
6361 +       if (IS_ERR(filename)) {
6362 +               if (profile) {
6363 +                       sa.info = "Failed name resolution - exec failed";
6364 +                       sa.error_code = PTR_ERR(filename);
6365 +                       aa_audit_file(profile, &sa);
6366 +                       return sa.error_code;
6367 +               } else
6368 +                       return 0;
6369 +       }
6370 +       sa.name = filename;
6371 +
6372 +       exec_mode = AA_EXEC_UNSAFE << shift;
6373 +
6374 +repeat:
6375 +       if (profile) {
6376 +               complain = PROFILE_COMPLAIN(profile);
6377 +
6378 +               /* Confined task, determine what mode inherit, unconfined or
6379 +                * mandatory to load new profile
6380 +                */
6381 +               exec_mode = aa_match(profile->file_rules, filename,
6382 +                                    &sa.audit_mask);
6383 +
6384 +
6385 +               if (exec_mode & sa.request_mask) {
6386 +                       int xm = exec_mode >> shift;
6387 +                       new_profile = aa_x_to_profile(profile, filename,
6388 +                                                     xm, &sa, &child);
6389 +
6390 +                       if (!new_profile && (xm & AA_EXEC_INHERIT))
6391 +                               /* (p|c|n|)ix - don't change profile */
6392 +                               goto cleanup;
6393 +                       /* error case caught below */
6394 +
6395 +               } else if (sa.request_mask & AUDIT_QUIET_MASK(sa.audit_mask)) {
6396 +                       /* quiet failed exit */
6397 +                       new_profile = ERR_PTR(-EACCES);
6398 +               } else if (complain) {
6399 +                       /* There was no entry in calling profile
6400 +                        * describing mode to execute image in.
6401 +                        * Drop into null-profile (disabling secure exec).
6402 +                        */
6403 +                       new_profile =
6404 +                           aa_dup_profile(profile->ns->null_complain_profile);
6405 +                       exec_mode |= AA_EXEC_UNSAFE << shift;
6406 +               } else {
6407 +                       sa.denied_mask = sa.request_mask;
6408 +                       sa.error_code = -EACCES;
6409 +                       new_profile = ERR_PTR(aa_audit_file(profile, &sa));
6410 +               }
6411 +       } else {
6412 +               /* Unconfined task, load profile if it exists */
6413 +               new_profile = aa_register_find(NULL, NULL, filename, 0, 0, &sa);
6414 +               if (new_profile == NULL)
6415 +                       goto cleanup;
6416 +       }
6417 +
6418 +       if (IS_ERR(new_profile))
6419 +               goto cleanup;
6420 +
6421 +       old_profile = __aa_replace_profile(current, new_profile);
6422 +       if (IS_ERR(old_profile)) {
6423 +               aa_put_profile(new_profile);
6424 +               aa_put_profile(profile);
6425 +               if (PTR_ERR(old_profile) == -ESTALE) {
6426 +                       profile = aa_get_profile(current);
6427 +                       goto repeat;
6428 +               }
6429 +               if (PTR_ERR(old_profile) == -EPERM) {
6430 +                       sa.denied_mask = sa.request_mask;
6431 +                       sa.info = "unable to set profile due to ptrace";
6432 +                       sa.task = current->parent->pid;
6433 +                       aa_audit_reject(profile, &sa);
6434 +               }
6435 +               if (PTR_ERR(old_profile) == -EAGAIN) {
6436 +                       sa.info = "rlimit nproc limit exceeded";
6437 +                       aa_audit_reject(profile, &sa);
6438 +               }
6439 +               new_profile = old_profile;
6440 +               goto cleanup;
6441 +       }
6442 +       aa_put_profile(old_profile);
6443 +       aa_put_profile(profile);
6444 +
6445 +       /* Handle confined exec.
6446 +        * Can be at this point for the following reasons:
6447 +        * 1. unconfined switching to confined
6448 +        * 2. confined switching to different confinement
6449 +        * 3. confined switching to unconfined
6450 +        *
6451 +        * Cases 2 and 3 are marked as requiring secure exec
6452 +        * (unless policy specified "unsafe exec")
6453 +        */
6454 +       if (!(exec_mode & (AA_EXEC_UNSAFE << shift))) {
6455 +               unsigned long bprm_flags;
6456 +
6457 +               bprm_flags = AA_SECURE_EXEC_NEEDED;
6458 +               bprm->security = (void*)
6459 +                       ((unsigned long)bprm->security | bprm_flags);
6460 +       }
6461 +
6462 +       if (complain && new_profile &&
6463 +           new_profile == new_profile->ns->null_complain_profile) {
6464 +               sa.request_mask = 0;
6465 +               sa.name = NULL;
6466 +               sa.info = "set profile";
6467 +               aa_audit_hint(new_profile, &sa);
6468 +       }
6469 +
6470 +cleanup:
6471 +       aa_put_name_buffer(child);
6472 +       aa_put_name_buffer(buffer);
6473 +       if (IS_ERR(new_profile))
6474 +               return PTR_ERR(new_profile);
6475 +       aa_put_profile(new_profile);
6476 +       return 0;
6477 +}
6478 +
6479 +/**
6480 + * aa_release - release a task context
6481 + * @task: task being released
6482 + *
6483 + * This is called after a task has exited and the parent has reaped it.
6484 + */
6485 +void aa_release(struct task_struct *task)
6486 +{
6487 +       struct aa_task_context *cxt;
6488 +       struct aa_profile *profile;
6489 +       /*
6490 +        * While the task context is still on a profile's task context
6491 +        * list, another process could replace the profile under us,
6492 +        * leaving us with a locked profile that is no longer attached
6493 +        * to this task. So after locking the profile, we check that
6494 +        * the profile is still attached.  The profile lock is
6495 +        * sufficient to prevent the replacement race so we do not lock
6496 +        * the task.
6497 +        *
6498 +        * Use lock subtyping to avoid lockdep reporting a false irq
6499 +        * possible inversion between the task_lock and profile_lock
6500 +        *
6501 +        * We also avoid taking the task_lock here because lock_dep
6502 +        * would report another false {softirq-on-W} potential irq_lock
6503 +        * inversion.
6504 +        *
6505 +        * If the task does not have a profile attached we are safe;
6506 +        * nothing can race with us at this point.
6507 +        */
6508 +
6509 +repeat:
6510 +       profile = aa_get_profile(task);
6511 +       if (profile) {
6512 +               lock_profile_nested(profile, aa_lock_task_release);
6513 +               cxt = aa_task_context(task);
6514 +               if (unlikely(!cxt || cxt->profile != profile)) {
6515 +                       unlock_profile(profile);
6516 +                       aa_put_profile(profile);
6517 +                       goto repeat;
6518 +               }
6519 +               aa_change_task_context(task, NULL, NULL, 0, NULL);
6520 +               unlock_profile(profile);
6521 +               aa_put_profile(profile);
6522 +       }
6523 +}
6524 +
6525 +static int do_change_profile(struct aa_profile *expected,
6526 +                            struct aa_namespace *ns, const char *name,
6527 +                            u64 cookie, int restore, int hat,
6528 +                            struct aa_audit *sa)
6529 +{
6530 +       struct aa_profile *new_profile = NULL, *old_profile = NULL,
6531 +               *previous_profile = NULL;
6532 +       struct aa_task_context *new_cxt, *cxt;
6533 +       int error = 0;
6534 +
6535 +       sa->name = name;
6536 +
6537 +       new_cxt = aa_alloc_task_context(GFP_KERNEL);
6538 +       if (!new_cxt)
6539 +               return -ENOMEM;
6540 +
6541 +       new_profile = aa_find_profile(ns, name);
6542 +       if (!new_profile && !restore) {
6543 +               if (!PROFILE_COMPLAIN(expected)) {
6544 +                       aa_free_task_context(new_cxt);
6545 +                       return -ENOENT;
6546 +               }
6547 +               new_profile = aa_dup_profile(ns->null_complain_profile);
6548 +       } else if (new_profile && hat && !PROFILE_IS_HAT(new_profile)) {
6549 +               aa_free_task_context(new_cxt);
6550 +               aa_put_profile(new_profile);
6551 +               return error;
6552 +       }
6553 +
6554 +       cxt = lock_task_and_profiles(current, new_profile);
6555 +       if (!cxt) {
6556 +               error = -EPERM;
6557 +               goto out;
6558 +       }
6559 +       old_profile = cxt->profile;
6560 +
6561 +       if (cxt->profile != expected || (new_profile && new_profile->isstale)) {
6562 +               error = -ESTALE;
6563 +               goto out;
6564 +       }
6565 +
6566 +       if (cxt->previous_profile) {
6567 +               if (cxt->cookie != cookie) {
6568 +                       error = -EACCES;
6569 +                       sa->info = "killing process";
6570 +                       aa_audit_reject(cxt->profile, sa);
6571 +                       /* terminate process */
6572 +                       (void)send_sig_info(SIGKILL, NULL, current);
6573 +                       goto out;
6574 +               }
6575 +
6576 +               if (!restore)
6577 +                       previous_profile = cxt->previous_profile;
6578 +       } else
6579 +               previous_profile = cxt->profile;
6580 +
6581 +       if ((current->ptrace & PT_PTRACED) && aa_may_ptrace(cxt, new_profile)) {
6582 +               error = -EACCES;
6583 +               goto out;
6584 +       }
6585 +
6586 +       if ((error = aa_rlimit_nproc(new_profile))) {
6587 +               sa->info = "rlimit nproc limit exceeded";
6588 +               aa_audit_reject(cxt->profile, sa);
6589 +               goto out;
6590 +       }
6591 +
6592 +       if (new_profile == ns->null_complain_profile)
6593 +               aa_audit_hint(cxt->profile, sa);
6594 +
6595 +       if (APPARMOR_AUDIT(cxt))
6596 +               aa_audit_message(cxt->profile, sa, AUDIT_APPARMOR_AUDIT);
6597 +
6598 +       if (!restore && cookie)
6599 +               aa_change_task_context(current, new_cxt, new_profile, cookie,
6600 +                                      previous_profile);
6601 +       else
6602 +               /* either return to previous_profile, or a permanent change */
6603 +               aa_change_task_context(current, new_cxt, new_profile, 0, NULL);
6604 +
6605 +out:
6606 +       if (aa_task_context(current) != new_cxt)
6607 +               aa_free_task_context(new_cxt);
6608 +       task_unlock(current);
6609 +       unlock_both_profiles(old_profile, new_profile);
6610 +       aa_put_profile(new_profile);
6611 +       return error;
6612 +}
6613 +
6614 +/**
6615 + * aa_change_profile - perform a one-way profile transition
6616 + * @ns_name: name of the profile namespace to change to
6617 + * @name: name of profile to change to
6618 + * Change to new profile @name.  Unlike with hats, there is no way
6619 + * to change back.
6620 + *
6621 + * Returns %0 on success, error otherwise.
6622 + */
6623 +int aa_change_profile(const char *ns_name, const char *name)
6624 +{
6625 +       struct aa_task_context *cxt;
6626 +       struct aa_profile *profile = NULL;
6627 +       struct aa_namespace *ns = NULL;
6628 +       struct aa_audit sa;
6629 +       unsigned int state;
6630 +       int error = -EINVAL;
6631 +
6632 +       if (!name)
6633 +               return -EINVAL;
6634 +
6635 +       memset(&sa, 0, sizeof(sa));
6636 +       sa.gfp_mask = GFP_ATOMIC;
6637 +       sa.operation = "change_profile";
6638 +
6639 +repeat:
6640 +       task_lock(current);
6641 +       cxt = aa_task_context(current);
6642 +       if (cxt)
6643 +               profile = aa_dup_profile(cxt->profile);
6644 +       task_unlock(current);
6645 +
6646 +       if (ns_name)
6647 +               ns = aa_find_namespace(ns_name);
6648 +       else if (profile)
6649 +               ns = aa_get_namespace(profile->ns);
6650 +       else
6651 +               ns = aa_get_namespace(default_namespace);
6652 +
6653 +       if (!ns) {
6654 +               aa_put_profile(profile);
6655 +               return -ENOENT;
6656 +       }
6657 +
6658 +       if (!profile || PROFILE_COMPLAIN(profile) ||
6659 +           (ns == profile->ns &&
6660 +            (aa_match(profile->file_rules, name, NULL) & AA_CHANGE_PROFILE)))
6661 +               error = do_change_profile(profile, ns, name, 0, 0, 0, &sa);
6662 +       else {
6663 +               /* check for a rule with a namespace prepended */
6664 +               aa_match_state(profile->file_rules, DFA_START, ns->name,
6665 +                              &state);
6666 +               state = aa_dfa_null_transition(profile->file_rules, state);
6667 +               if ((aa_match_state(profile->file_rules, state, name, NULL) &
6668 +                     AA_CHANGE_PROFILE))
6669 +                       error = do_change_profile(profile, ns, name, 0, 0, 0,
6670 +                                                 &sa);
6671 +               else
6672 +                       /* no permission to transition to profile @name */
6673 +                       error = -EACCES;
6674 +       }
6675 +
6676 +       aa_put_namespace(ns);
6677 +       aa_put_profile(profile);
6678 +       if (error == -ESTALE)
6679 +               goto repeat;
6680 +
6681 +       return error;
6682 +}
6683 +
6684 +/**
6685 + * aa_change_hat - change hat to/from subprofile
6686 + * @hat_name: hat to change to
6687 + * @cookie: magic value to validate the hat change
6688 + *
6689 + * Change to new @hat_name, and store the @hat_magic in the current task
6690 + * context.  If the new @hat_name is %NULL and the @cookie matches that
6691 + * stored in the current task context and is not 0, return to the top level
6692 + * profile.
6693 + * Returns %0 on success, error otherwise.
6694 + */
6695 +int aa_change_hat(const char *hat_name, u64 cookie)
6696 +{
6697 +       struct aa_task_context *cxt;
6698 +       struct aa_profile *profile, *previous_profile;
6699 +       struct aa_audit sa;
6700 +       int error = 0;
6701 +
6702 +       memset(&sa, 0, sizeof(sa));
6703 +       sa.gfp_mask = GFP_ATOMIC;
6704 +       sa.operation = "change_hat";
6705 +
6706 +repeat:
6707 +       task_lock(current);
6708 +       cxt = aa_task_context(current);
6709 +       if (!cxt) {
6710 +               task_unlock(current);
6711 +               return -EPERM;
6712 +       }
6713 +       profile = aa_dup_profile(cxt->profile);
6714 +       previous_profile = aa_dup_profile(cxt->previous_profile);
6715 +       task_unlock(current);
6716 +
6717 +       if (hat_name) {
6718 +               char *name, *profile_name;
6719 +
6720 +               if (previous_profile)
6721 +                       profile_name = previous_profile->name;
6722 +               else
6723 +                       profile_name = profile->name;
6724 +
6725 +               name = new_compound_name(profile_name, hat_name);
6726 +               if (!name) {
6727 +                       error = -ENOMEM;
6728 +                       goto out;
6729 +               }
6730 +               error = do_change_profile(profile, profile->ns, name, cookie,
6731 +                                         0, 1, &sa);
6732 +               aa_put_name_buffer(name);
6733 +       } else if (previous_profile)
6734 +               error = do_change_profile(profile, profile->ns,
6735 +                                         previous_profile->name, cookie, 1, 0,
6736 +                                         &sa);
6737 +       /* else ignore restores when there is no saved profile */
6738 +
6739 +out:
6740 +       aa_put_profile(previous_profile);
6741 +       aa_put_profile(profile);
6742 +       if (error == -ESTALE)
6743 +               goto repeat;
6744 +
6745 +       return error;
6746 +}
6747 +
6748 +/**
6749 + * __aa_replace_profile - replace a task's profile
6750 + * @task: task to switch the profile of
6751 + * @profile: profile to switch to
6752 + *
6753 + * Returns a handle to the previous profile upon success, or else an
6754 + * error code.
6755 + */
6756 +struct aa_profile *__aa_replace_profile(struct task_struct *task,
6757 +                                       struct aa_profile *profile)
6758 +{
6759 +       struct aa_task_context *cxt, *new_cxt = NULL;
6760 +       struct aa_profile *old_profile = NULL;
6761 +
6762 +       if (profile) {
6763 +               new_cxt = aa_alloc_task_context(GFP_KERNEL);
6764 +               if (!new_cxt)
6765 +                       return ERR_PTR(-ENOMEM);
6766 +       }
6767 +
6768 +       cxt = lock_task_and_profiles(task, profile);
6769 +       if (unlikely(profile && profile->isstale)) {
6770 +               old_profile = ERR_PTR(-ESTALE);
6771 +               goto error;
6772 +       }
6773 +
6774 +       if ((current->ptrace & PT_PTRACED) && aa_may_ptrace(cxt, profile)) {
6775 +               old_profile = ERR_PTR(-EPERM);
6776 +               goto error;
6777 +       }
6778 +
6779 +       if (aa_rlimit_nproc(profile)) {
6780 +               old_profile = ERR_PTR(-EAGAIN);
6781 +               goto error;
6782 +       }
6783 +
6784 +       if (cxt)
6785 +               old_profile = aa_dup_profile(cxt->profile);
6786 +       aa_change_task_context(task, new_cxt, profile, 0, NULL);
6787 +
6788 +       task_unlock(task);
6789 +       aa_set_rlimits(task, profile);
6790 +       unlock_both_profiles(profile, old_profile);
6791 +       return old_profile;
6792 +
6793 +error:
6794 +       task_unlock(task);
6795 +       unlock_both_profiles(profile, cxt ? cxt->profile : NULL);
6796 +       aa_free_task_context(new_cxt);
6797 +       return old_profile;
6798 +}
6799 +
6800 +/**
6801 + * lock_task_and_profiles - lock the task and confining profiles and @profile
6802 + * @task: task to lock
6803 + * @profile: extra profile to lock in addition to the current profile
6804 + *
6805 + * Handle the spinning on locking to make sure the task context and
6806 + * profile are consistent once all locks are aquired.
6807 + *
6808 + * return the aa_task_context currently confining the task.  The task lock
6809 + * will be held whether or not the task is confined.
6810 + */
6811 +struct aa_task_context *
6812 +lock_task_and_profiles(struct task_struct *task, struct aa_profile *profile)
6813 +{
6814 +       struct aa_task_context *cxt;
6815 +       struct aa_profile *old_profile = NULL;
6816 +
6817 +       rcu_read_lock();
6818 +repeat:
6819 +       cxt = aa_task_context(task);
6820 +       if (cxt)
6821 +               old_profile = cxt->profile;
6822 +
6823 +       lock_both_profiles(profile, old_profile);
6824 +       task_lock(task);
6825 +
6826 +       /* check for race with profile transition, replacement or removal */
6827 +       if (unlikely(cxt != aa_task_context(task))) {
6828 +               task_unlock(task);
6829 +               unlock_both_profiles(profile, old_profile);
6830 +               old_profile = NULL;
6831 +               goto repeat;
6832 +       }
6833 +       rcu_read_unlock();
6834 +       return cxt;
6835 +}
6836 +
6837 +static void free_aa_task_context_rcu_callback(struct rcu_head *head)
6838 +{
6839 +       struct aa_task_context *cxt;
6840 +
6841 +       cxt = container_of(head, struct aa_task_context, rcu);
6842 +       aa_free_task_context(cxt);
6843 +}
6844 +
6845 +/**
6846 + * aa_change_task_context - switch a task to use a new context and profile
6847 + * @task: task that is having its task context changed
6848 + * @new_cxt: new task context to use after the switch
6849 + * @profile: new profile to use after the switch
6850 + * @cookie: magic value to switch to
6851 + * @previous_profile: profile the task can return to
6852 + */
6853 +void aa_change_task_context(struct task_struct *task,
6854 +                           struct aa_task_context *new_cxt,
6855 +                           struct aa_profile *profile, u64 cookie,
6856 +                           struct aa_profile *previous_profile)
6857 +{
6858 +       struct aa_task_context *old_cxt = aa_task_context(task);
6859 +
6860 +       if (old_cxt) {
6861 +               list_del_init(&old_cxt->list);
6862 +               old_cxt->profile->task_count--;
6863 +               call_rcu(&old_cxt->rcu, free_aa_task_context_rcu_callback);
6864 +       }
6865 +       if (new_cxt) {
6866 +               /* set the caps_logged cache to the quiet_caps mask
6867 +                * this has the effect of quieting caps that are not
6868 +                * supposed to be logged
6869 +                */
6870 +               new_cxt->caps_logged = profile->quiet_caps;
6871 +               new_cxt->cookie = cookie;
6872 +               new_cxt->task = task;
6873 +               new_cxt->profile = aa_dup_profile(profile);
6874 +               profile->task_count++;
6875 +               new_cxt->previous_profile = aa_dup_profile(previous_profile);
6876 +               list_move(&new_cxt->list, &profile->task_contexts);
6877 +       }
6878 +       rcu_assign_pointer(task->security, new_cxt);
6879 +}
6880 diff -uprN linux-2.6.27./security/apparmor/match.c linux-2.6.27/security/apparmor/match.c
6881 --- linux-2.6.27./security/apparmor/match.c     1970-01-01 01:00:00.000000000 +0100
6882 +++ linux-2.6.27/security/apparmor/match.c      2008-10-29 14:28:53.316113441 +0100
6883 @@ -0,0 +1,364 @@
6884 +/*
6885 + *     Copyright (C) 2007 Novell/SUSE
6886 + *
6887 + *     This program is free software; you can redistribute it and/or
6888 + *     modify it under the terms of the GNU General Public License as
6889 + *     published by the Free Software Foundation, version 2 of the
6890 + *     License.
6891 + *
6892 + *     Regular expression transition table matching
6893 + */
6894 +
6895 +#include <linux/kernel.h>
6896 +#include <linux/slab.h>
6897 +#include <linux/errno.h>
6898 +#include "apparmor.h"
6899 +#include "match.h"
6900 +#include "inline.h"
6901 +
6902 +static struct table_header *unpack_table(void *blob, size_t bsize)
6903 +{
6904 +       struct table_header *table = NULL;
6905 +       struct table_header th;
6906 +       size_t tsize;
6907 +
6908 +       if (bsize < sizeof(struct table_header))
6909 +               goto out;
6910 +
6911 +       th.td_id = be16_to_cpu(*(u16 *) (blob));
6912 +       th.td_flags = be16_to_cpu(*(u16 *) (blob + 2));
6913 +       th.td_lolen = be32_to_cpu(*(u32 *) (blob + 8));
6914 +       blob += sizeof(struct table_header);
6915 +
6916 +       if (!(th.td_flags == YYTD_DATA16 || th.td_flags == YYTD_DATA32 ||
6917 +               th.td_flags == YYTD_DATA8))
6918 +               goto out;
6919 +
6920 +       tsize = table_size(th.td_lolen, th.td_flags);
6921 +       if (bsize < tsize)
6922 +               goto out;
6923 +
6924 +       table = kmalloc(tsize, GFP_KERNEL);
6925 +       if (table) {
6926 +               *table = th;
6927 +               if (th.td_flags == YYTD_DATA8)
6928 +                       UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
6929 +                                    u8, byte_to_byte);
6930 +               else if (th.td_flags == YYTD_DATA16)
6931 +                       UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
6932 +                                    u16, be16_to_cpu);
6933 +               else
6934 +                       UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
6935 +                                    u32, be32_to_cpu);
6936 +       }
6937 +
6938 +out:
6939 +       return table;
6940 +}
6941 +
6942 +int unpack_dfa(struct aa_dfa *dfa, void *blob, size_t size)
6943 +{
6944 +       int hsize, i;
6945 +       int error = -ENOMEM;
6946 +
6947 +       /* get dfa table set header */
6948 +       if (size < sizeof(struct table_set_header))
6949 +               goto fail;
6950 +
6951 +       if (ntohl(*(u32 *)blob) != YYTH_MAGIC)
6952 +               goto fail;
6953 +
6954 +       hsize = ntohl(*(u32 *)(blob + 4));
6955 +       if (size < hsize)
6956 +               goto fail;
6957 +
6958 +       blob += hsize;
6959 +       size -= hsize;
6960 +
6961 +       error = -EPROTO;
6962 +       while (size > 0) {
6963 +               struct table_header *table;
6964 +               table = unpack_table(blob, size);
6965 +               if (!table)
6966 +                       goto fail;
6967 +
6968 +               switch(table->td_id) {
6969 +               case YYTD_ID_ACCEPT:
6970 +               case YYTD_ID_ACCEPT2:
6971 +               case YYTD_ID_BASE:
6972 +                       dfa->tables[table->td_id - 1] = table;
6973 +                       if (table->td_flags != YYTD_DATA32)
6974 +                               goto fail;
6975 +                       break;
6976 +               case YYTD_ID_DEF:
6977 +               case YYTD_ID_NXT:
6978 +               case YYTD_ID_CHK:
6979 +                       dfa->tables[table->td_id - 1] = table;
6980 +                       if (table->td_flags != YYTD_DATA16)
6981 +                               goto fail;
6982 +                       break;
6983 +               case YYTD_ID_EC:
6984 +                       dfa->tables[table->td_id - 1] = table;
6985 +                       if (table->td_flags != YYTD_DATA8)
6986 +                               goto fail;
6987 +                       break;
6988 +               default:
6989 +                       kfree(table);
6990 +                       goto fail;
6991 +               }
6992 +
6993 +               blob += table_size(table->td_lolen, table->td_flags);
6994 +               size -= table_size(table->td_lolen, table->td_flags);
6995 +       }
6996 +
6997 +       return 0;
6998 +
6999 +fail:
7000 +       for (i = 0; i < ARRAY_SIZE(dfa->tables); i++) {
7001 +               if (dfa->tables[i]) {
7002 +                       kfree(dfa->tables[i]);
7003 +                       dfa->tables[i] = NULL;
7004 +               }
7005 +       }
7006 +       return error;
7007 +}
7008 +
7009 +/**
7010 + * verify_dfa - verify that all the transitions and states in the dfa tables
7011 + *              are in bounds.
7012 + * @dfa: dfa to test
7013 + *
7014 + * assumes dfa has gone through the verification done by unpacking
7015 + */
7016 +int verify_dfa(struct aa_dfa *dfa)
7017 +{
7018 +       size_t i, state_count, trans_count;
7019 +       int error = -EPROTO;
7020 +
7021 +       /* check that required tables exist */
7022 +       if (!(dfa->tables[YYTD_ID_ACCEPT - 1] &&
7023 +             dfa->tables[YYTD_ID_ACCEPT2 - 1] &&
7024 +             dfa->tables[YYTD_ID_DEF - 1] &&
7025 +             dfa->tables[YYTD_ID_BASE - 1] &&
7026 +             dfa->tables[YYTD_ID_NXT - 1] &&
7027 +             dfa->tables[YYTD_ID_CHK - 1]))
7028 +               goto out;
7029 +
7030 +       /* accept.size == default.size == base.size */
7031 +       state_count = dfa->tables[YYTD_ID_BASE - 1]->td_lolen;
7032 +       if (!(state_count == dfa->tables[YYTD_ID_DEF - 1]->td_lolen &&
7033 +             state_count == dfa->tables[YYTD_ID_ACCEPT - 1]->td_lolen &&
7034 +             state_count == dfa->tables[YYTD_ID_ACCEPT2 - 1]->td_lolen))
7035 +               goto out;
7036 +
7037 +       /* next.size == chk.size */
7038 +       trans_count = dfa->tables[YYTD_ID_NXT - 1]->td_lolen;
7039 +       if (trans_count != dfa->tables[YYTD_ID_CHK - 1]->td_lolen)
7040 +               goto out;
7041 +
7042 +       /* if equivalence classes then its table size must be 256 */
7043 +       if (dfa->tables[YYTD_ID_EC - 1] &&
7044 +           dfa->tables[YYTD_ID_EC - 1]->td_lolen != 256)
7045 +               goto out;
7046 +
7047 +       for (i = 0; i < state_count; i++) {
7048 +               if (DEFAULT_TABLE(dfa)[i] >= state_count)
7049 +                       goto out;
7050 +               if (BASE_TABLE(dfa)[i] >= trans_count + 256)
7051 +                       goto out;
7052 +       }
7053 +
7054 +       for (i = 0; i < trans_count ; i++) {
7055 +               if (NEXT_TABLE(dfa)[i] >= state_count)
7056 +                       goto out;
7057 +               if (CHECK_TABLE(dfa)[i] >= state_count)
7058 +                       goto out;
7059 +       }
7060 +
7061 +       /* verify accept permissions */
7062 +       for (i = 0; i < state_count; i++) {
7063 +               int mode = ACCEPT_TABLE(dfa)[i];
7064 +
7065 +               if (mode & ~AA_VALID_PERM_MASK)
7066 +                       goto out;
7067 +               if (ACCEPT_TABLE2(dfa)[i] & ~AA_VALID_PERM2_MASK)
7068 +                       goto out;
7069 +
7070 +               /* if any exec modifier is set MAY_EXEC must be set */
7071 +               if ((mode & AA_USER_EXEC_TYPE) && !(mode & AA_USER_EXEC))
7072 +                       goto out;
7073 +               if ((mode & AA_OTHER_EXEC_TYPE) && !(mode & AA_OTHER_EXEC))
7074 +                       goto out;
7075 +       }
7076 +
7077 +       error = 0;
7078 +out:
7079 +       return error;
7080 +}
7081 +
7082 +struct aa_dfa *aa_match_alloc(void)
7083 +{
7084 +       return kzalloc(sizeof(struct aa_dfa), GFP_KERNEL);
7085 +}
7086 +
7087 +void aa_match_free(struct aa_dfa *dfa)
7088 +{
7089 +       if (dfa) {
7090 +               int i;
7091 +
7092 +               for (i = 0; i < ARRAY_SIZE(dfa->tables); i++)
7093 +                       kfree(dfa->tables[i]);
7094 +       }
7095 +       kfree(dfa);
7096 +}
7097 +
7098 +/**
7099 + * aa_dfa_next_state_len - traverse @dfa to find state @str stops at
7100 + * @dfa: the dfa to match @str against
7101 + * @start: the state of the dfa to start matching in
7102 + * @str: the string of bytes to match against the dfa
7103 + * @len: length of the string of bytes to match
7104 + *
7105 + * aa_dfa_next_state will match @str against the dfa and return the state it
7106 + * finished matching in. The final state can be used to look up the accepting
7107 + * label, or as the start state of a continuing match.
7108 + *
7109 + * aa_dfa_next_state could be implement using this function by doing
7110 + * return aa_dfa_next_state_len(dfa, start, str, strlen(str));
7111 + * but that would require traversing the string twice and be slightly
7112 + * slower.
7113 + */
7114 +unsigned int aa_dfa_next_state_len(struct aa_dfa *dfa, unsigned int start,
7115 +                                  const char *str, int len)
7116 +{
7117 +       u16 *def = DEFAULT_TABLE(dfa);
7118 +       u32 *base = BASE_TABLE(dfa);
7119 +       u16 *next = NEXT_TABLE(dfa);
7120 +       u16 *check = CHECK_TABLE(dfa);
7121 +       unsigned int state = start, pos;
7122 +
7123 +       if (state == 0)
7124 +               return 0;
7125 +
7126 +       /* current state is <state>, matching character *str */
7127 +       if (dfa->tables[YYTD_ID_EC - 1]) {
7128 +               u8 *equiv = EQUIV_TABLE(dfa);
7129 +               for (; len; len--) {
7130 +                       pos = base[state] + equiv[(u8)*str++];
7131 +                       if (check[pos] == state)
7132 +                               state = next[pos];
7133 +                       else
7134 +                               state = def[state];
7135 +               }
7136 +       } else {
7137 +               for (; len; len--) {
7138 +                       pos = base[state] + (u8)*str++;
7139 +                       if (check[pos] == state)
7140 +                               state = next[pos];
7141 +                       else
7142 +                               state = def[state];
7143 +               }
7144 +       }
7145 +       return state;
7146 +}
7147 +
7148 +/**
7149 + * aa_dfa_next_state - traverse @dfa to find state @str stops at
7150 + * @dfa: the dfa to match @str against
7151 + * @start: the state of the dfa to start matching in
7152 + * @str: the null terminated string of bytes to match against the dfa
7153 + *
7154 + * aa_dfa_next_state will match @str against the dfa and return the state it
7155 + * finished matching in. The final state can be used to look up the accepting
7156 + * label, or as the start state of a continuing match.
7157 + */
7158 +unsigned int aa_dfa_next_state(struct aa_dfa *dfa, unsigned int start,
7159 +                              const char *str)
7160 +{
7161 +       u16 *def = DEFAULT_TABLE(dfa);
7162 +       u32 *base = BASE_TABLE(dfa);
7163 +       u16 *next = NEXT_TABLE(dfa);
7164 +       u16 *check = CHECK_TABLE(dfa);
7165 +       unsigned int state = start, pos;
7166 +
7167 +       if (state == 0)
7168 +               return 0;
7169 +
7170 +       /* current state is <state>, matching character *str */
7171 +       if (dfa->tables[YYTD_ID_EC - 1]) {
7172 +               u8 *equiv = EQUIV_TABLE(dfa);
7173 +               while (*str) {
7174 +                       pos = base[state] + equiv[(u8)*str++];
7175 +                       if (check[pos] == state)
7176 +                               state = next[pos];
7177 +                       else
7178 +                               state = def[state];
7179 +               }
7180 +       } else {
7181 +               while (*str) {
7182 +                       pos = base[state] + (u8)*str++;
7183 +                       if (check[pos] == state)
7184 +                               state = next[pos];
7185 +                       else
7186 +                               state = def[state];
7187 +               }
7188 +       }
7189 +       return state;
7190 +}
7191 +
7192 +/**
7193 + * aa_dfa_null_transition - step to next state after null character
7194 + * @dfa: the dfa to match against
7195 + * @start: the state of the dfa to start matching in
7196 + *
7197 + * aa_dfa_null_transition transitions to the next state after a null
7198 + * character which is not used in standard matching and is only
7199 + * used to seperate pairs.
7200 + */
7201 +unsigned int aa_dfa_null_transition(struct aa_dfa *dfa, unsigned int start)
7202 +{
7203 +       return aa_dfa_next_state_len(dfa, start, "", 1);
7204 +}
7205 +
7206 +/**
7207 + * aa_dfa_match - find accept perm for @str in @dfa
7208 + * @dfa: the dfa to match @str against
7209 + * @str: the string to match against the dfa
7210 + * @audit_mask: the audit_mask for the final state
7211 + *
7212 + * aa_dfa_match will match @str and return the accept perms for the
7213 + * final state.
7214 + */
7215 +unsigned int aa_dfa_match(struct aa_dfa *dfa, const char *str, int *audit_mask)
7216 +{
7217 +       int state = aa_dfa_next_state(dfa, DFA_START, str);
7218 +       if (audit_mask)
7219 +               *audit_mask = dfa_audit_mask(dfa, state);
7220 +       return ACCEPT_TABLE(dfa)[state];
7221 +}
7222 +
7223 +/**
7224 + * aa_match_state - find accept perm and state for @str in @dfa
7225 + * @dfa: the dfa to match @str against
7226 + * @start: the state to start the match from
7227 + * @str: the string to match against the dfa
7228 + * @final: the state that the match finished in
7229 + *
7230 + * aa_match_state will match @str and return the accept perms, and @final
7231 + * state, the match occured in.
7232 + */
7233 +unsigned int aa_match_state(struct aa_dfa *dfa, unsigned int start,
7234 +                           const char *str, unsigned int *final)
7235 +{
7236 +       unsigned int state;
7237 +       if (dfa) {
7238 +               state = aa_dfa_next_state(dfa, start, str);
7239 +               if (final)
7240 +                       *final = state;
7241 +               return ACCEPT_TABLE(dfa)[state];
7242 +       }
7243 +       if (final)
7244 +               *final = 0;
7245 +       return 0;
7246 +}
7247 +
7248 diff -uprN linux-2.6.27./security/apparmor/match.h linux-2.6.27/security/apparmor/match.h
7249 --- linux-2.6.27./security/apparmor/match.h     1970-01-01 01:00:00.000000000 +0100
7250 +++ linux-2.6.27/security/apparmor/match.h      2008-10-29 14:28:53.316113441 +0100
7251 @@ -0,0 +1,87 @@
7252 +/*
7253 + *     Copyright (C) 2007 Novell/SUSE
7254 + *
7255 + *     This program is free software; you can redistribute it and/or
7256 + *     modify it under the terms of the GNU General Public License as
7257 + *     published by the Free Software Foundation, version 2 of the
7258 + *     License.
7259 + *
7260 + *     AppArmor submodule (match) prototypes
7261 + */
7262 +
7263 +#ifndef __MATCH_H
7264 +#define __MATCH_H
7265 +
7266 +#define DFA_START                      1
7267 +
7268 +/**
7269 + * The format used for transition tables is based on the GNU flex table
7270 + * file format (--tables-file option; see Table File Format in the flex
7271 + * info pages and the flex sources for documentation). The magic number
7272 + * used in the header is 0x1B5E783D insted of 0xF13C57B1 though, because
7273 + * the YY_ID_CHK (check) and YY_ID_DEF (default) tables are used
7274 + * slightly differently (see the apparmor-parser package).
7275 + */
7276 +
7277 +#define YYTH_MAGIC     0x1B5E783D
7278 +
7279 +struct table_set_header {
7280 +       u32             th_magic;       /* YYTH_MAGIC */
7281 +       u32             th_hsize;
7282 +       u32             th_ssize;
7283 +       u16             th_flags;
7284 +       char            th_version[];
7285 +};
7286 +
7287 +#define        YYTD_ID_ACCEPT  1
7288 +#define YYTD_ID_BASE   2
7289 +#define YYTD_ID_CHK    3
7290 +#define YYTD_ID_DEF    4
7291 +#define YYTD_ID_EC     5
7292 +#define YYTD_ID_META   6
7293 +#define YYTD_ID_ACCEPT2 7
7294 +#define YYTD_ID_NXT    8
7295 +
7296 +
7297 +#define YYTD_DATA8     1
7298 +#define YYTD_DATA16    2
7299 +#define YYTD_DATA32    4
7300 +
7301 +struct table_header {
7302 +       u16             td_id;
7303 +       u16             td_flags;
7304 +       u32             td_hilen;
7305 +       u32             td_lolen;
7306 +       char            td_data[];
7307 +};
7308 +
7309 +#define DEFAULT_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_DEF - 1]->td_data))
7310 +#define BASE_TABLE(DFA) ((u32 *)((DFA)->tables[YYTD_ID_BASE - 1]->td_data))
7311 +#define NEXT_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_NXT - 1]->td_data))
7312 +#define CHECK_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_CHK - 1]->td_data))
7313 +#define EQUIV_TABLE(DFA) ((u8 *)((DFA)->tables[YYTD_ID_EC - 1]->td_data))
7314 +#define ACCEPT_TABLE(DFA) ((u32 *)((DFA)->tables[YYTD_ID_ACCEPT - 1]->td_data))
7315 +#define ACCEPT_TABLE2(DFA) ((u32 *)((DFA)->tables[YYTD_ID_ACCEPT2 -1]->td_data))
7316 +
7317 +struct aa_dfa {
7318 +       struct table_header *tables[YYTD_ID_NXT];
7319 +};
7320 +
7321 +#define byte_to_byte(X) (X)
7322 +
7323 +#define UNPACK_ARRAY(TABLE, BLOB, LEN, TYPE, NTOHX) \
7324 +       do { \
7325 +               typeof(LEN) __i; \
7326 +               TYPE *__t = (TYPE *) TABLE; \
7327 +               TYPE *__b = (TYPE *) BLOB; \
7328 +               for (__i = 0; __i < LEN; __i++) { \
7329 +                       __t[__i] = NTOHX(__b[__i]); \
7330 +               } \
7331 +       } while (0)
7332 +
7333 +static inline size_t table_size(size_t len, size_t el_size)
7334 +{
7335 +       return ALIGN(sizeof(struct table_header) + len * el_size, 8);
7336 +}
7337 +
7338 +#endif /* __MATCH_H */
7339 diff -uprN linux-2.6.27./security/apparmor/module_interface.c linux-2.6.27/security/apparmor/module_interface.c
7340 --- linux-2.6.27./security/apparmor/module_interface.c  1970-01-01 01:00:00.000000000 +0100
7341 +++ linux-2.6.27/security/apparmor/module_interface.c   2008-10-29 14:28:53.329440939 +0100
7342 @@ -0,0 +1,967 @@
7343 +/*
7344 + *     Copyright (C) 1998-2007 Novell/SUSE
7345 + *
7346 + *     This program is free software; you can redistribute it and/or
7347 + *     modify it under the terms of the GNU General Public License as
7348 + *     published by the Free Software Foundation, version 2 of the
7349 + *     License.
7350 + *
7351 + *     AppArmor userspace policy interface
7352 + */
7353 +
7354 +#include <asm/unaligned.h>
7355 +
7356 +#include "apparmor.h"
7357 +#include "inline.h"
7358 +
7359 +/*
7360 + * This mutex is used to synchronize profile adds, replacements, and
7361 + * removals: we only allow one of these operations at a time.
7362 + * We do not use the profile list lock here in order to avoid blocking
7363 + * exec during those operations.  (Exec involves a profile list lookup
7364 + * for named-profile transitions.)
7365 + */
7366 +DEFINE_MUTEX(aa_interface_lock);
7367 +
7368 +/*
7369 + * The AppArmor interface treats data as a type byte followed by the
7370 + * actual data.  The interface has the notion of a a named entry
7371 + * which has a name (AA_NAME typecode followed by name string) followed by
7372 + * the entries typecode and data.  Named types allow for optional
7373 + * elements and extensions to be added and tested for without breaking
7374 + * backwards compatability.
7375 + */
7376 +
7377 +enum aa_code {
7378 +       AA_U8,
7379 +       AA_U16,
7380 +       AA_U32,
7381 +       AA_U64,
7382 +       AA_NAME,        /* same as string except it is items name */
7383 +       AA_STRING,
7384 +       AA_BLOB,
7385 +       AA_STRUCT,
7386 +       AA_STRUCTEND,
7387 +       AA_LIST,
7388 +       AA_LISTEND,
7389 +       AA_ARRAY,
7390 +       AA_ARRAYEND,
7391 +};
7392 +
7393 +/*
7394 + * aa_ext is the read of the buffer containing the serialized profile.  The
7395 + * data is copied into a kernel buffer in apparmorfs and then handed off to
7396 + * the unpack routines.
7397 + */
7398 +struct aa_ext {
7399 +       void *start;
7400 +       void *end;
7401 +       void *pos;      /* pointer to current position in the buffer */
7402 +       u32 version;
7403 +       char *ns_name;
7404 +};
7405 +
7406 +static inline int aa_inbounds(struct aa_ext *e, size_t size)
7407 +{
7408 +       return (size <= e->end - e->pos);
7409 +}
7410 +
7411 +/**
7412 + * aa_u16_chunck - test and do bounds checking for a u16 size based chunk
7413 + * @e: serialized data read head
7414 + * @chunk: start address for chunk of data
7415 + *
7416 + * return the size of chunk found with the read head at the end of
7417 + * the chunk.
7418 + */
7419 +static size_t aa_is_u16_chunk(struct aa_ext *e, char **chunk)
7420 +{
7421 +       void *pos = e->pos;
7422 +       size_t size = 0;
7423 +
7424 +       if (!aa_inbounds(e, sizeof(u16)))
7425 +               goto fail;
7426 +       size = le16_to_cpu(get_unaligned((u16 *)e->pos));
7427 +       e->pos += sizeof(u16);
7428 +       if (!aa_inbounds(e, size))
7429 +               goto fail;
7430 +       *chunk = e->pos;
7431 +       e->pos += size;
7432 +       return size;
7433 +
7434 +fail:
7435 +       e->pos = pos;
7436 +       return 0;
7437 +}
7438 +
7439 +static inline int aa_is_X(struct aa_ext *e, enum aa_code code)
7440 +{
7441 +       if (!aa_inbounds(e, 1))
7442 +               return 0;
7443 +       if (*(u8 *) e->pos != code)
7444 +               return 0;
7445 +       e->pos++;
7446 +       return 1;
7447 +}
7448 +
7449 +/**
7450 + * aa_is_nameX - check is the next element is of type X with a name of @name
7451 + * @e: serialized data extent information
7452 + * @code: type code
7453 + * @name: name to match to the serialized element.
7454 + *
7455 + * check that the next serialized data element is of type X and has a tag
7456 + * name @name.  If @name is specified then there must be a matching
7457 + * name element in the stream.  If @name is NULL any name element will be
7458 + * skipped and only the typecode will be tested.
7459 + * returns 1 on success (both type code and name tests match) and the read
7460 + * head is advanced past the headers
7461 + * returns %0 if either match failes, the read head does not move
7462 + */
7463 +static int aa_is_nameX(struct aa_ext *e, enum aa_code code, const char *name)
7464 +{
7465 +       void *pos = e->pos;
7466 +       /*
7467 +        * Check for presence of a tagname, and if present name size
7468 +        * AA_NAME tag value is a u16.
7469 +        */
7470 +       if (aa_is_X(e, AA_NAME)) {
7471 +               char *tag;
7472 +               size_t size = aa_is_u16_chunk(e, &tag);
7473 +               /* if a name is specified it must match. otherwise skip tag */
7474 +               if (name && (!size || strcmp(name, tag)))
7475 +                       goto fail;
7476 +       } else if (name) {
7477 +               /* if a name is specified and there is no name tag fail */
7478 +               goto fail;
7479 +       }
7480 +
7481 +       /* now check if type code matches */
7482 +       if (aa_is_X(e, code))
7483 +               return 1;
7484 +
7485 +fail:
7486 +       e->pos = pos;
7487 +       return 0;
7488 +}
7489 +
7490 +static int aa_is_u16(struct aa_ext *e, u16 *data, const char *name)
7491 +{
7492 +       void *pos = e->pos;
7493 +       if (aa_is_nameX(e, AA_U16, name)) {
7494 +               if (!aa_inbounds(e, sizeof(u16)))
7495 +                       goto fail;
7496 +               if (data)
7497 +                       *data = le16_to_cpu(get_unaligned((u16 *)e->pos));
7498 +               e->pos += sizeof(u16);
7499 +               return 1;
7500 +       }
7501 +fail:
7502 +       e->pos = pos;
7503 +       return 0;
7504 +}
7505 +
7506 +static int aa_is_u32(struct aa_ext *e, u32 *data, const char *name)
7507 +{
7508 +       void *pos = e->pos;
7509 +       if (aa_is_nameX(e, AA_U32, name)) {
7510 +               if (!aa_inbounds(e, sizeof(u32)))
7511 +                       goto fail;
7512 +               if (data)
7513 +                       *data = le32_to_cpu(get_unaligned((u32 *)e->pos));
7514 +               e->pos += sizeof(u32);
7515 +               return 1;
7516 +       }
7517 +fail:
7518 +       e->pos = pos;
7519 +       return 0;
7520 +}
7521 +
7522 +static int aa_is_u64(struct aa_ext *e, u64 *data, const char *name)
7523 +{
7524 +       void *pos = e->pos;
7525 +       if (aa_is_nameX(e, AA_U64, name)) {
7526 +               if (!aa_inbounds(e, sizeof(u64)))
7527 +                       goto fail;
7528 +               if (data)
7529 +                       *data = le64_to_cpu(get_unaligned((u64 *)e->pos));
7530 +               e->pos += sizeof(u64);
7531 +               return 1;
7532 +       }
7533 +fail:
7534 +       e->pos = pos;
7535 +       return 0;
7536 +}
7537 +
7538 +static size_t aa_is_array(struct aa_ext *e, const char *name)
7539 +{
7540 +       void *pos = e->pos;
7541 +       if (aa_is_nameX(e, AA_ARRAY, name)) {
7542 +               int size;
7543 +               if (!aa_inbounds(e, sizeof(u16)))
7544 +                       goto fail;
7545 +               size = (int) le16_to_cpu(get_unaligned((u16 *)e->pos));
7546 +               e->pos += sizeof(u16);
7547 +               return size;
7548 +       }
7549 +fail:
7550 +       e->pos = pos;
7551 +       return 0;
7552 +}
7553 +
7554 +static size_t aa_is_blob(struct aa_ext *e, char **blob, const char *name)
7555 +{
7556 +       void *pos = e->pos;
7557 +       if (aa_is_nameX(e, AA_BLOB, name)) {
7558 +               u32 size;
7559 +               if (!aa_inbounds(e, sizeof(u32)))
7560 +                       goto fail;
7561 +               size = le32_to_cpu(get_unaligned((u32 *)e->pos));
7562 +               e->pos += sizeof(u32);
7563 +               if (aa_inbounds(e, (size_t) size)) {
7564 +                       * blob = e->pos;
7565 +                       e->pos += size;
7566 +                       return size;
7567 +               }
7568 +       }
7569 +fail:
7570 +       e->pos = pos;
7571 +       return 0;
7572 +}
7573 +
7574 +static int aa_is_dynstring(struct aa_ext *e, char **string, const char *name)
7575 +{
7576 +       char *src_str;
7577 +       size_t size = 0;
7578 +       void *pos = e->pos;
7579 +       *string = NULL;
7580 +       if (aa_is_nameX(e, AA_STRING, name) &&
7581 +           (size = aa_is_u16_chunk(e, &src_str))) {
7582 +               char *str;
7583 +               if (!(str = kmalloc(size, GFP_KERNEL)))
7584 +                       goto fail;
7585 +               memcpy(str, src_str, size);
7586 +               *string = str;
7587 +       }
7588 +
7589 +       return size;
7590 +
7591 +fail:
7592 +       e->pos = pos;
7593 +       return 0;
7594 +}
7595 +
7596 +/**
7597 + * aa_unpack_dfa - unpack a file rule dfa
7598 + * @e: serialized data extent information
7599 + *
7600 + * returns dfa or ERR_PTR
7601 + */
7602 +static struct aa_dfa *aa_unpack_dfa(struct aa_ext *e)
7603 +{
7604 +       char *blob = NULL;
7605 +       size_t size, error = 0;
7606 +       struct aa_dfa *dfa = NULL;
7607 +
7608 +       size = aa_is_blob(e, &blob, "aadfa");
7609 +       if (size) {
7610 +               dfa = aa_match_alloc();
7611 +               if (dfa) {
7612 +                       /*
7613 +                        * The dfa is aligned with in the blob to 8 bytes
7614 +                        * from the beginning of the stream.
7615 +                        */
7616 +                       size_t sz = blob - (char *) e->start;
7617 +                       size_t pad = ALIGN(sz, 8) - sz;
7618 +                       error = unpack_dfa(dfa, blob + pad, size - pad);
7619 +                       if (!error)
7620 +                               error = verify_dfa(dfa);
7621 +               } else {
7622 +                       error = -ENOMEM;
7623 +               }
7624 +
7625 +               if (error) {
7626 +                       aa_match_free(dfa);
7627 +                       dfa = ERR_PTR(error);
7628 +               }
7629 +       }
7630 +
7631 +       return dfa;
7632 +}
7633 +
7634 +static int aa_unpack_exec_table(struct aa_ext *e, struct aa_profile *profile)
7635 +{
7636 +       void *pos = e->pos;
7637 +
7638 +       /* exec table is optional */
7639 +       if (aa_is_nameX(e, AA_STRUCT, "xtable")) {
7640 +               int i, size;
7641 +
7642 +               size = aa_is_array(e, NULL);
7643 +               /* currently 4 exec bits and entries 0-3 are reserved iupcx */
7644 +               if (size > 16 - 4)
7645 +                       goto fail;
7646 +               profile->exec_table = kzalloc(sizeof(char *) * size,
7647 +                                             GFP_KERNEL);
7648 +               if (!profile->exec_table)
7649 +                       goto fail;
7650 +
7651 +               for (i = 0; i < size; i++) {
7652 +                   char *tmp;
7653 +                       if (!aa_is_dynstring(e, &tmp, NULL))
7654 +                               goto fail;
7655 +                       /* note: strings beginning with a : have an embedded
7656 +                          \0 seperating the profile ns name from the profile
7657 +                          name */
7658 +                       profile->exec_table[i] = 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 +               profile->exec_table_size = size;
7665 +       }
7666 +       return 1;
7667 +
7668 +fail:
7669 +       e->pos = pos;
7670 +       return 0;
7671 +}
7672 +
7673 +int aa_unpack_rlimits(struct aa_ext *e, struct aa_profile *profile)
7674 +{
7675 +       void *pos = e->pos;
7676 +
7677 +       /* rlimits are optional */
7678 +       if (aa_is_nameX(e, AA_STRUCT, "rlimits")) {
7679 +               int i, size;
7680 +               u32 tmp = 0;
7681 +               if (!aa_is_u32(e, &tmp, NULL))
7682 +                       goto fail;
7683 +               profile->rlimits.mask = tmp;
7684 +
7685 +               size = aa_is_array(e, NULL);
7686 +               if (size > RLIM_NLIMITS)
7687 +                       goto fail;
7688 +               for (i = 0; i < size; i++) {
7689 +                       u64 tmp = 0;
7690 +                       if (!aa_is_u64(e, &tmp, NULL))
7691 +                               goto fail;
7692 +                       profile->rlimits.limits[i].rlim_max = tmp;
7693 +               }
7694 +               if (!aa_is_nameX(e, AA_ARRAYEND, NULL))
7695 +                       goto fail;
7696 +               if (!aa_is_nameX(e, AA_STRUCTEND, NULL))
7697 +                       goto fail;
7698 +       }
7699 +       return 1;
7700 +
7701 +fail:
7702 +       e->pos = pos;
7703 +       return 0;
7704 +}
7705 +
7706 +/**
7707 + * aa_unpack_profile - unpack a serialized profile
7708 + * @e: serialized data extent information
7709 + * @sa: audit struct for the operation
7710 + */
7711 +static struct aa_profile *aa_unpack_profile(struct aa_ext *e,
7712 +                                           struct aa_audit *sa)
7713 +{
7714 +       struct aa_profile *profile = NULL;
7715 +       size_t size = 0;
7716 +       int i, error = -EPROTO;
7717 +
7718 +       profile = alloc_aa_profile();
7719 +       if (!profile)
7720 +               return ERR_PTR(-ENOMEM);
7721 +
7722 +       /* check that we have the right struct being passed */
7723 +       if (!aa_is_nameX(e, AA_STRUCT, "profile"))
7724 +               goto fail;
7725 +       if (!aa_is_dynstring(e, &profile->name, NULL))
7726 +               goto fail;
7727 +
7728 +       /* per profile debug flags (complain, audit) */
7729 +       if (!aa_is_nameX(e, AA_STRUCT, "flags"))
7730 +               goto fail;
7731 +       if (!aa_is_u32(e, &(profile->flags.hat), NULL))
7732 +               goto fail;
7733 +       if (!aa_is_u32(e, &(profile->flags.complain), NULL))
7734 +               goto fail;
7735 +       if (!aa_is_u32(e, &(profile->flags.audit), NULL))
7736 +               goto fail;
7737 +       if (!aa_is_nameX(e, AA_STRUCTEND, NULL))
7738 +               goto fail;
7739 +
7740 +       if (!aa_is_u32(e, &(profile->capabilities.cap[0]), NULL))
7741 +               goto fail;
7742 +       if (!aa_is_u32(e, &(profile->audit_caps.cap[0]), NULL))
7743 +               goto fail;
7744 +       if (!aa_is_u32(e, &(profile->quiet_caps.cap[0]), NULL))
7745 +               goto fail;
7746 +       if (!aa_is_u32(e, &(profile->set_caps.cap[0]), NULL))
7747 +               goto fail;
7748 +
7749 +       if (aa_is_nameX(e, AA_STRUCT, "caps64")) {
7750 +               /* optional upper half of 64 bit caps */
7751 +               if (!aa_is_u32(e, &(profile->capabilities.cap[1]), NULL))
7752 +                       goto fail;
7753 +               if (!aa_is_u32(e, &(profile->audit_caps.cap[1]), NULL))
7754 +                       goto fail;
7755 +               if (!aa_is_u32(e, &(profile->quiet_caps.cap[1]), NULL))
7756 +                       goto fail;
7757 +               if (!aa_is_u32(e, &(profile->set_caps.cap[1]), NULL))
7758 +                       goto fail;
7759 +               if (!aa_is_nameX(e, AA_STRUCTEND, NULL))
7760 +                       goto fail;
7761 +       }
7762 +
7763 +       if (!aa_unpack_rlimits(e, profile))
7764 +               goto fail;
7765 +
7766 +       size = aa_is_array(e, "net_allowed_af");
7767 +       if (size) {
7768 +               if (size > AF_MAX)
7769 +                       goto fail;
7770 +
7771 +               for (i = 0; i < size; i++) {
7772 +                       if (!aa_is_u16(e, &profile->network_families[i], NULL))
7773 +                               goto fail;
7774 +                       if (!aa_is_u16(e, &profile->audit_network[i], NULL))
7775 +                               goto fail;
7776 +                       if (!aa_is_u16(e, &profile->quiet_network[i], NULL))
7777 +                               goto fail;
7778 +               }
7779 +               if (!aa_is_nameX(e, AA_ARRAYEND, NULL))
7780 +                       goto fail;
7781 +               /* allow unix domain and netlink sockets they are handled
7782 +                * by IPC
7783 +                */
7784 +       }
7785 +       profile->network_families[AF_UNIX] = 0xffff;
7786 +       profile->network_families[AF_NETLINK] = 0xffff;
7787 +
7788 +       /* get file rules */
7789 +       profile->file_rules = aa_unpack_dfa(e);
7790 +       if (IS_ERR(profile->file_rules)) {
7791 +               error = PTR_ERR(profile->file_rules);
7792 +               profile->file_rules = NULL;
7793 +               goto fail;
7794 +       }
7795 +
7796 +       if (!aa_unpack_exec_table(e, profile))
7797 +               goto fail;
7798 +
7799 +       if (!aa_is_nameX(e, AA_STRUCTEND, NULL))
7800 +               goto fail;
7801 +
7802 +       return profile;
7803 +
7804 +fail:
7805 +       sa->name = profile && profile->name ? profile->name : "unknown";
7806 +       if (!sa->info)
7807 +               sa->info = "failed to unpack profile";
7808 +       aa_audit_status(NULL, sa);
7809 +
7810 +       if (profile)
7811 +               free_aa_profile(profile);
7812 +
7813 +       return ERR_PTR(error);
7814 +}
7815 +
7816 +/**
7817 + * aa_verify_head - unpack serialized stream header
7818 + * @e: serialized data read head
7819 + * @operation: operation header is being verified for
7820 + *
7821 + * returns error or 0 if header is good
7822 + */
7823 +static int aa_verify_header(struct aa_ext *e, struct aa_audit *sa)
7824 +{
7825 +       /* get the interface version */
7826 +       if (!aa_is_u32(e, &e->version, "version")) {
7827 +               sa->info = "invalid profile format";
7828 +               aa_audit_status(NULL, sa);
7829 +               return -EPROTONOSUPPORT;
7830 +       }
7831 +
7832 +       /* check that the interface version is currently supported */
7833 +       if (e->version != 5) {
7834 +               sa->info = "unsupported interface version";
7835 +               aa_audit_status(NULL, sa);
7836 +               return -EPROTONOSUPPORT;
7837 +       }
7838 +
7839 +       /* read the namespace if present */
7840 +       if (!aa_is_dynstring(e, &e->ns_name, "namespace")) {
7841 +               e->ns_name = NULL;
7842 +       }
7843 +
7844 +       return 0;
7845 +}
7846 +
7847 +/**
7848 + * aa_add_profile - Unpack and add a new profile to the profile list
7849 + * @data: serialized data stream
7850 + * @size: size of the serialized data stream
7851 + */
7852 +ssize_t aa_add_profile(void *data, size_t size)
7853 +{
7854 +       struct aa_profile *profile = NULL;
7855 +       struct aa_namespace *ns = NULL;
7856 +       struct aa_ext e = {
7857 +               .start = data,
7858 +               .end = data + size,
7859 +               .pos = data,
7860 +               .ns_name = NULL
7861 +       };
7862 +       ssize_t error;
7863 +       struct aa_audit sa;
7864 +       memset(&sa, 0, sizeof(sa));
7865 +       sa.operation = "profile_load";
7866 +       sa.gfp_mask = GFP_KERNEL;
7867 +
7868 +       error = aa_verify_header(&e, &sa);
7869 +       if (error)
7870 +               return error;
7871 +
7872 +       profile = aa_unpack_profile(&e, &sa);
7873 +       if (IS_ERR(profile))
7874 +               return PTR_ERR(profile);
7875 +
7876 +       mutex_lock(&aa_interface_lock);
7877 +       write_lock(&profile_ns_list_lock);
7878 +       if (e.ns_name)
7879 +               ns = __aa_find_namespace(e.ns_name, &profile_ns_list);
7880 +       else
7881 +               ns = default_namespace;
7882 +       if (!ns) {
7883 +               struct aa_namespace *new_ns;
7884 +               write_unlock(&profile_ns_list_lock);
7885 +               new_ns = alloc_aa_namespace(e.ns_name);
7886 +               if (!new_ns) {
7887 +                       mutex_unlock(&aa_interface_lock);
7888 +                       return -ENOMEM;
7889 +               }
7890 +               write_lock(&profile_ns_list_lock);
7891 +               ns = __aa_find_namespace(e.ns_name, &profile_ns_list);
7892 +               if (!ns) {
7893 +                       list_add(&new_ns->list, &profile_ns_list);
7894 +                       ns = new_ns;
7895 +               } else
7896 +                       free_aa_namespace(new_ns);
7897 +       }
7898 +
7899 +       write_lock(&ns->lock);
7900 +       if (__aa_find_profile(profile->name, &ns->profiles)) {
7901 +               /* A profile with this name exists already. */
7902 +               write_unlock(&ns->lock);
7903 +               write_unlock(&profile_ns_list_lock);
7904 +               sa.name = profile->name;
7905 +               sa.name2 = ns->name;
7906 +               sa.info = "failed: profile already loaded";
7907 +               aa_audit_status(NULL, &sa);
7908 +               mutex_unlock(&aa_interface_lock);
7909 +               aa_put_profile(profile);
7910 +               return -EEXIST;
7911 +       }
7912 +       profile->ns = aa_get_namespace(ns);
7913 +       ns->profile_count++;
7914 +       list_add(&profile->list, &ns->profiles);
7915 +       write_unlock(&ns->lock);
7916 +       write_unlock(&profile_ns_list_lock);
7917 +
7918 +       sa.name = profile->name;
7919 +       sa.name2 = ns->name;
7920 +       aa_audit_status(NULL, &sa);
7921 +       mutex_unlock(&aa_interface_lock);
7922 +       return size;
7923 +}
7924 +
7925 +/**
7926 + * task_replace - replace a task's profile
7927 + * @task: task to replace profile on
7928 + * @new_cxt: new aa_task_context to do replacement with
7929 + * @new_profile: new profile
7930 + */
7931 +static inline void task_replace(struct task_struct *task,
7932 +                               struct aa_task_context *new_cxt,
7933 +                               struct aa_profile *new_profile)
7934 +{
7935 +       struct aa_task_context *cxt = aa_task_context(task);
7936 +
7937 +       AA_DEBUG("%s: replacing profile for task %d "
7938 +                "profile=%s (%p)\n",
7939 +                __FUNCTION__,
7940 +                cxt->task->pid,
7941 +                cxt->profile->name, cxt->profile);
7942 +
7943 +       aa_change_task_context(task, new_cxt, new_profile, cxt->cookie,
7944 +                              cxt->previous_profile);
7945 +}
7946 +
7947 +/**
7948 + * aa_replace_profile - replace a profile on the profile list
7949 + * @udata: serialized data stream
7950 + * @size: size of the serialized data stream
7951 + *
7952 + * unpack and replace a profile on the profile list and uses of that profile
7953 + * by any aa_task_context.  If the profile does not exist on the profile list
7954 + * it is added.  Return %0 or error.
7955 + */
7956 +ssize_t aa_replace_profile(void *udata, size_t size)
7957 +{
7958 +       struct aa_profile *old_profile, *new_profile;
7959 +       struct aa_namespace *ns;
7960 +       struct aa_task_context *new_cxt;
7961 +       struct aa_ext e = {
7962 +               .start = udata,
7963 +               .end = udata + size,
7964 +               .pos = udata,
7965 +               .ns_name = NULL
7966 +       };
7967 +       ssize_t error;
7968 +       struct aa_audit sa;
7969 +       memset(&sa, 0, sizeof(sa));
7970 +       sa.operation = "profile_replace";
7971 +       sa.gfp_mask = GFP_KERNEL;
7972 +
7973 +       error = aa_verify_header(&e, &sa);
7974 +       if (error)
7975 +               return error;
7976 +
7977 +       new_profile = aa_unpack_profile(&e, &sa);
7978 +       if (IS_ERR(new_profile))
7979 +               return PTR_ERR(new_profile);
7980 +
7981 +       mutex_lock(&aa_interface_lock);
7982 +       write_lock(&profile_ns_list_lock);
7983 +       if (e.ns_name)
7984 +               ns = __aa_find_namespace(e.ns_name, &profile_ns_list);
7985 +       else
7986 +               ns = default_namespace;
7987 +       if (!ns) {
7988 +               struct aa_namespace *new_ns;
7989 +               write_unlock(&profile_ns_list_lock);
7990 +               new_ns = alloc_aa_namespace(e.ns_name);
7991 +               if (!new_ns) {
7992 +                       mutex_unlock(&aa_interface_lock);
7993 +                       return -ENOMEM;
7994 +               }
7995 +               write_lock(&profile_ns_list_lock);
7996 +               ns = __aa_find_namespace(e.ns_name, &profile_ns_list);
7997 +               if (!ns) {
7998 +                       list_add(&new_ns->list, &profile_ns_list);
7999 +                       ns = new_ns;
8000 +               } else
8001 +                       free_aa_namespace(new_ns);
8002 +       }
8003 +
8004 +       write_lock(&ns->lock);
8005 +       old_profile = __aa_find_profile(new_profile->name, &ns->profiles);
8006 +       if (old_profile) {
8007 +               lock_profile(old_profile);
8008 +               old_profile->isstale = 1;
8009 +               list_del_init(&old_profile->list);
8010 +               unlock_profile(old_profile);
8011 +               ns->profile_count--;
8012 +       }
8013 +       new_profile->ns = aa_get_namespace(ns);
8014 +       ns->profile_count++;
8015 +       /* not don't need an extra ref count to keep new_profile as
8016 +        * it is protect by the interface mutex */
8017 +       list_add(&new_profile->list, &ns->profiles);
8018 +       write_unlock(&ns->lock);
8019 +       write_unlock(&profile_ns_list_lock);
8020 +
8021 +       if (!old_profile) {
8022 +               sa.operation = "profile_load";
8023 +               goto out;
8024 +       }
8025 +       /* do not fail replacement based off of profile's NPROC rlimit */
8026 +
8027 +       /*
8028 +        * Replacement needs to allocate a new aa_task_context for each
8029 +        * task confined by old_profile.  To do this the profile locks
8030 +        * are only held when the actual switch is done per task.  While
8031 +        * looping to allocate a new aa_task_context the old_task list
8032 +        * may get shorter if tasks exit/change their profile but will
8033 +        * not get longer as new task will not use old_profile detecting
8034 +        * that is stale.
8035 +        */
8036 +       do {
8037 +               new_cxt = aa_alloc_task_context(GFP_KERNEL | __GFP_NOFAIL);
8038 +
8039 +               lock_both_profiles(old_profile, new_profile);
8040 +               if (!list_empty(&old_profile->task_contexts)) {
8041 +                       struct task_struct *task =
8042 +                               list_entry(old_profile->task_contexts.next,
8043 +                                          struct aa_task_context, list)->task;
8044 +                       task_lock(task);
8045 +                       task_replace(task, new_cxt, new_profile);
8046 +                       task_unlock(task);
8047 +                       aa_set_rlimits(task, new_profile);
8048 +                       new_cxt = NULL;
8049 +               }
8050 +               unlock_both_profiles(old_profile, new_profile);
8051 +       } while (!new_cxt);
8052 +       aa_free_task_context(new_cxt);
8053 +       aa_put_profile(old_profile);
8054 +
8055 +out:
8056 +       sa.name = new_profile->name;
8057 +       sa.name2 = ns->name;
8058 +       aa_audit_status(NULL, &sa);
8059 +       mutex_unlock(&aa_interface_lock);
8060 +       return size;
8061 +}
8062 +
8063 +/**
8064 + * aa_remove_profile - remove a profile from the system
8065 + * @name: name of the profile to remove
8066 + * @size: size of the name
8067 + *
8068 + * remove a profile from the profile list and all aa_task_context references
8069 + * to said profile.
8070 + * NOTE: removing confinement does not restore rlimits to preconfinemnet values
8071 + */
8072 +ssize_t aa_remove_profile(char *name, size_t size)
8073 +{
8074 +       struct aa_namespace *ns;
8075 +       struct aa_profile *profile;
8076 +       struct aa_audit sa;
8077 +       memset(&sa, 0, sizeof(sa));
8078 +       sa.operation = "profile_remove";
8079 +       sa.gfp_mask = GFP_KERNEL;
8080 +
8081 +       mutex_lock(&aa_interface_lock);
8082 +       write_lock(&profile_ns_list_lock);
8083 +
8084 +       if (name[0] == ':') {
8085 +               char *split = strchr(name + 1, ':');
8086 +               if (!split)
8087 +                       goto noent;
8088 +               *split = 0;
8089 +               ns = __aa_find_namespace(name + 1, &profile_ns_list);
8090 +               name = split + 1;
8091 +       } else {
8092 +               ns = default_namespace;
8093 +       }
8094 +
8095 +       if (!ns)
8096 +               goto noent;
8097 +       sa.name2 = ns->name;
8098 +       write_lock(&ns->lock);
8099 +       profile = __aa_find_profile(name, &ns->profiles);
8100 +       if (!profile) {
8101 +               write_unlock(&ns->lock);
8102 +               goto noent;
8103 +       }
8104 +       sa.name = profile->name;
8105 +
8106 +       /* Remove the profile from each task context it is on. */
8107 +       lock_profile(profile);
8108 +       profile->isstale = 1;
8109 +       aa_unconfine_tasks(profile);
8110 +       list_del_init(&profile->list);
8111 +       ns->profile_count--;
8112 +       unlock_profile(profile);
8113 +       /* Release the profile itself. */
8114 +       write_unlock(&ns->lock);
8115 +       /* check to see if the namespace has become stale */
8116 +       if (ns != default_namespace && ns->profile_count == 0) {
8117 +               list_del_init(&ns->list);
8118 +               aa_put_namespace(ns);
8119 +       }
8120 +       write_unlock(&profile_ns_list_lock);
8121 +
8122 +       aa_audit_status(NULL, &sa);
8123 +       mutex_unlock(&aa_interface_lock);
8124 +       aa_put_profile(profile);
8125 +
8126 +       return size;
8127 +
8128 +noent:
8129 +       write_unlock(&profile_ns_list_lock);
8130 +       sa.info = "failed: profile does not exist";
8131 +       aa_audit_status(NULL, &sa);
8132 +       mutex_unlock(&aa_interface_lock);
8133 +       return -ENOENT;
8134 +}
8135 +
8136 +/**
8137 + * free_aa_namespace_kref - free aa_namespace by kref (see aa_put_namespace)
8138 + * @kr: kref callback for freeing of a namespace
8139 + */
8140 +void free_aa_namespace_kref(struct kref *kref)
8141 +{
8142 +       struct aa_namespace *ns=container_of(kref, struct aa_namespace, count);
8143 +
8144 +       free_aa_namespace(ns);
8145 +}
8146 +
8147 +/**
8148 + * alloc_aa_namespace - allocate, initialize and return a new namespace
8149 + * @name: a preallocated name
8150 + * Returns NULL on failure.
8151 + */
8152 +struct aa_namespace *alloc_aa_namespace(char *name)
8153 +{
8154 +       struct aa_namespace *ns;
8155 +
8156 +       ns = kzalloc(sizeof(*ns), GFP_KERNEL);
8157 +       AA_DEBUG("%s(%p)\n", __FUNCTION__, ns);
8158 +       if (ns) {
8159 +               ns->name = name;
8160 +               INIT_LIST_HEAD(&ns->list);
8161 +               INIT_LIST_HEAD(&ns->profiles);
8162 +               kref_init(&ns->count);
8163 +               rwlock_init(&ns->lock);
8164 +
8165 +               ns->null_complain_profile = alloc_aa_profile();
8166 +               if (!ns->null_complain_profile) {
8167 +                       if (!name)
8168 +                               kfree(ns->name);
8169 +                       kfree(ns);
8170 +                       return NULL;
8171 +               }
8172 +               ns->null_complain_profile->name =
8173 +                       kstrdup("null-complain-profile", GFP_KERNEL);
8174 +               if (!ns->null_complain_profile->name) {
8175 +                       free_aa_profile(ns->null_complain_profile);
8176 +                       if (!name)
8177 +                               kfree(ns->name);
8178 +                       kfree(ns);
8179 +                       return NULL;
8180 +               }
8181 +               ns->null_complain_profile->flags.complain = 1;
8182 +               /* null_complain_profile doesn't contribute to ns ref count */
8183 +               ns->null_complain_profile->ns = ns;
8184 +       }
8185 +       return ns;
8186 +}
8187 +
8188 +/**
8189 + * free_aa_namespace - free a profile namespace
8190 + * @namespace: the namespace to free
8191 + *
8192 + * Free a namespace.  All references to the namespace must have been put.
8193 + * If the namespace was referenced by a profile confining a task,
8194 + * free_aa_namespace will be called indirectly (through free_aa_profile)
8195 + * from an rcu callback routine, so we must not sleep here.
8196 + */
8197 +void free_aa_namespace(struct aa_namespace *ns)
8198 +{
8199 +       AA_DEBUG("%s(%p)\n", __FUNCTION__, ns);
8200 +
8201 +       if (!ns)
8202 +               return;
8203 +
8204 +       /* namespace still contains profiles -- invalid */
8205 +       if (!list_empty(&ns->profiles)) {
8206 +               AA_ERROR("%s: internal error, "
8207 +                        "namespace '%s' still contains profiles\n",
8208 +                        __FUNCTION__,
8209 +                        ns->name);
8210 +               BUG();
8211 +       }
8212 +       if (!list_empty(&ns->list)) {
8213 +               AA_ERROR("%s: internal error, "
8214 +                        "namespace '%s' still on list\n",
8215 +                        __FUNCTION__,
8216 +                        ns->name);
8217 +               BUG();
8218 +       }
8219 +       /* null_complain_profile doesn't contribute to ns ref counting */
8220 +       ns->null_complain_profile->ns = NULL;
8221 +       aa_put_profile(ns->null_complain_profile);
8222 +       kfree(ns->name);
8223 +       kfree(ns);
8224 +}
8225 +
8226 +/**
8227 + * free_aa_profile_kref - free aa_profile by kref (called by aa_put_profile)
8228 + * @kr: kref callback for freeing of a profile
8229 + */
8230 +void free_aa_profile_kref(struct kref *kref)
8231 +{
8232 +       struct aa_profile *p=container_of(kref, struct aa_profile, count);
8233 +
8234 +       free_aa_profile(p);
8235 +}
8236 +
8237 +/**
8238 + * alloc_aa_profile - allocate, initialize and return a new profile
8239 + * Returns NULL on failure.
8240 + */
8241 +struct aa_profile *alloc_aa_profile(void)
8242 +{
8243 +       struct aa_profile *profile;
8244 +
8245 +       profile = kzalloc(sizeof(*profile), GFP_KERNEL);
8246 +       AA_DEBUG("%s(%p)\n", __FUNCTION__, profile);
8247 +       if (profile) {
8248 +               INIT_LIST_HEAD(&profile->list);
8249 +               kref_init(&profile->count);
8250 +               INIT_LIST_HEAD(&profile->task_contexts);
8251 +               spin_lock_init(&profile->lock);
8252 +       }
8253 +       return profile;
8254 +}
8255 +
8256 +/**
8257 + * free_aa_profile - free a profile
8258 + * @profile: the profile to free
8259 + *
8260 + * Free a profile, its hats and null_profile. All references to the profile,
8261 + * its hats and null_profile must have been put.
8262 + *
8263 + * If the profile was referenced from a task context, free_aa_profile() will
8264 + * be called from an rcu callback routine, so we must not sleep here.
8265 + */
8266 +void free_aa_profile(struct aa_profile *profile)
8267 +{
8268 +       AA_DEBUG("%s(%p)\n", __FUNCTION__, profile);
8269 +
8270 +       if (!profile)
8271 +               return;
8272 +
8273 +       /* profile is still on profile namespace list -- invalid */
8274 +       if (!list_empty(&profile->list)) {
8275 +               AA_ERROR("%s: internal error, "
8276 +                        "profile '%s' still on global list\n",
8277 +                        __FUNCTION__,
8278 +                        profile->name);
8279 +               BUG();
8280 +       }
8281 +       aa_put_namespace(profile->ns);
8282 +
8283 +       aa_match_free(profile->file_rules);
8284 +
8285 +       if (profile->name) {
8286 +               AA_DEBUG("%s: %s\n", __FUNCTION__, profile->name);
8287 +               kfree(profile->name);
8288 +       }
8289 +
8290 +       kfree(profile);
8291 +}
8292 +
8293 +/**
8294 + * aa_unconfine_tasks - remove tasks on a profile's task context list
8295 + * @profile: profile to remove tasks from
8296 + *
8297 + * Assumes that @profile lock is held.
8298 + */
8299 +void aa_unconfine_tasks(struct aa_profile *profile)
8300 +{
8301 +       while (!list_empty(&profile->task_contexts)) {
8302 +               struct task_struct *task =
8303 +                       list_entry(profile->task_contexts.next,
8304 +                                  struct aa_task_context, list)->task;
8305 +               task_lock(task);
8306 +               aa_change_task_context(task, NULL, NULL, 0, NULL);
8307 +               task_unlock(task);
8308 +       }
8309 +}
8310 diff -uprN linux-2.6.27./security/apparmor/procattr.c linux-2.6.27/security/apparmor/procattr.c
8311 --- linux-2.6.27./security/apparmor/procattr.c  1970-01-01 01:00:00.000000000 +0100
8312 +++ linux-2.6.27/security/apparmor/procattr.c   2008-10-29 14:28:53.319441671 +0100
8313 @@ -0,0 +1,195 @@
8314 +/*
8315 + *     Copyright (C) 1998-2007 Novell/SUSE
8316 + *
8317 + *     This program is free software; you can redistribute it and/or
8318 + *     modify it under the terms of the GNU General Public License as
8319 + *     published by the Free Software Foundation, version 2 of the
8320 + *     License.
8321 + *
8322 + *     AppArmor /proc/pid/attr handling
8323 + */
8324 +
8325 +#include "apparmor.h"
8326 +#include "inline.h"
8327 +
8328 +int aa_getprocattr(struct aa_profile *profile, char **string, unsigned *len)
8329 +{
8330 +       char *str;
8331 +
8332 +       if (profile) {
8333 +               const char *mode_str = PROFILE_COMPLAIN(profile) ?
8334 +                       " (complain)" : " (enforce)";
8335 +               int mode_len, name_len, ns_len = 0;
8336 +
8337 +               mode_len = strlen(mode_str);
8338 +               name_len = strlen(profile->name);
8339 +               if (profile->ns != default_namespace)
8340 +                       ns_len = strlen(profile->ns->name) + 2;
8341 +               *len = mode_len + ns_len + name_len + 1;
8342 +               str = kmalloc(*len, GFP_ATOMIC);
8343 +               if (!str)
8344 +                       return -ENOMEM;
8345 +
8346 +               if (ns_len) {
8347 +                       *str++ = ':';
8348 +                       memcpy(str, profile->ns->name, ns_len - 2);
8349 +                       str += ns_len - 2;
8350 +                       *str++ = ':';
8351 +               }
8352 +               memcpy(str, profile->name, name_len);
8353 +               str += name_len;
8354 +               memcpy(str, mode_str, mode_len);
8355 +               str += mode_len;
8356 +               *str++ = '\n';
8357 +               str -= *len;
8358 +       } else {
8359 +               const char *unconfined_str = "unconfined\n";
8360 +
8361 +               *len = strlen(unconfined_str);
8362 +               str = kmalloc(*len, GFP_ATOMIC);
8363 +               if (!str)
8364 +                       return -ENOMEM;
8365 +
8366 +               memcpy(str, unconfined_str, *len);
8367 +       }
8368 +       *string = str;
8369 +
8370 +       return 0;
8371 +}
8372 +
8373 +static char *split_token_from_name(const char *op, char *args, u64 *cookie)
8374 +{
8375 +       char *name;
8376 +
8377 +       *cookie = simple_strtoull(args, &name, 16);
8378 +       if ((name == args) || *name != '^') {
8379 +               AA_ERROR("%s: Invalid input '%s'", op, args);
8380 +               return ERR_PTR(-EINVAL);
8381 +       }
8382 +
8383 +       name++;  /* skip ^ */
8384 +       if (!*name)
8385 +               name = NULL;
8386 +       return name;
8387 +}
8388 +
8389 +int aa_setprocattr_changehat(char *args)
8390 +{
8391 +       char *hat;
8392 +       u64 cookie;
8393 +
8394 +       hat = split_token_from_name("change_hat", args, &cookie);
8395 +       if (IS_ERR(hat))
8396 +               return PTR_ERR(hat);
8397 +
8398 +       if (!hat && !cookie) {
8399 +               AA_ERROR("change_hat: Invalid input, NULL hat and NULL magic");
8400 +               return -EINVAL;
8401 +       }
8402 +
8403 +       AA_DEBUG("%s: Magic 0x%llx Hat '%s'\n",
8404 +                __FUNCTION__, cookie, hat ? hat : NULL);
8405 +
8406 +       return aa_change_hat(hat, cookie);
8407 +}
8408 +
8409 +int aa_setprocattr_changeprofile(char *args)
8410 +{
8411 +       char *name = args, *ns_name = NULL;
8412 +
8413 +       if (name[0] == ':') {
8414 +               char *split = strchr(&name[1], ':');
8415 +               if (split) {
8416 +                       *split = 0;
8417 +                       ns_name = &name[1];
8418 +                       name = split + 1;
8419 +               }
8420 +       }
8421 +
8422 +       return aa_change_profile(ns_name, name);
8423 +}
8424 +
8425 +int aa_setprocattr_setprofile(struct task_struct *task, char *args)
8426 +{
8427 +       struct aa_profile *old_profile, *new_profile;
8428 +       struct aa_namespace *ns;
8429 +       struct aa_audit sa;
8430 +       char *name, *ns_name = NULL;
8431 +
8432 +       memset(&sa, 0, sizeof(sa));
8433 +       sa.operation = "profile_set";
8434 +       sa.gfp_mask = GFP_KERNEL;
8435 +       sa.task = task->pid;
8436 +
8437 +       AA_DEBUG("%s: current %d\n",
8438 +                __FUNCTION__, current->pid);
8439 +
8440 +       name = args;
8441 +       if (args[0] != '/') {
8442 +               char *split = strchr(args, ':');
8443 +               if (split) {
8444 +                       *split = 0;
8445 +                       ns_name = args;
8446 +                       name = split + 1;
8447 +               }
8448 +       }
8449 +       if (ns_name)
8450 +               ns = aa_find_namespace(ns_name);
8451 +       else
8452 +               ns = aa_get_namespace(default_namespace);
8453 +       if (!ns) {
8454 +               sa.name = ns_name;
8455 +               sa.info = "unknown namespace";
8456 +               aa_audit_reject(NULL, &sa);
8457 +               aa_put_namespace(ns);
8458 +               return -EINVAL;
8459 +       }
8460 +
8461 +repeat:
8462 +       if (strcmp(name, "unconfined") == 0)
8463 +               new_profile = NULL;
8464 +       else {
8465 +               new_profile = aa_find_profile(ns, name);
8466 +               if (!new_profile) {
8467 +                       sa.name = ns_name;
8468 +                       sa.name2 = name;
8469 +                       sa.info = "unknown profile";
8470 +                       aa_audit_reject(NULL, &sa);
8471 +                       aa_put_namespace(ns);
8472 +                       return -EINVAL;
8473 +               }
8474 +       }
8475 +
8476 +       old_profile = __aa_replace_profile(task, new_profile);
8477 +       if (IS_ERR(old_profile)) {
8478 +               int error;
8479 +
8480 +               aa_put_profile(new_profile);
8481 +               error = PTR_ERR(old_profile);
8482 +               if (error == -ESTALE)
8483 +                       goto repeat;
8484 +               aa_put_namespace(ns);
8485 +               return error;
8486 +       }
8487 +
8488 +       if (new_profile) {
8489 +               sa.name = ns_name;
8490 +               sa.name2 = name;
8491 +               sa.name3 = old_profile ? old_profile->name :
8492 +                       "unconfined";
8493 +               aa_audit_status(NULL, &sa);
8494 +       } else {
8495 +               if (old_profile) {
8496 +                       sa.name = "unconfined";
8497 +                       sa.name2 = old_profile->name;
8498 +                       aa_audit_status(NULL, &sa);
8499 +               } else {
8500 +                       sa.info = "task is unconfined";
8501 +                       aa_audit_status(NULL, &sa);
8502 +               }
8503 +       }
8504 +       aa_put_namespace(ns);
8505 +       aa_put_profile(old_profile);
8506 +       aa_put_profile(new_profile);
8507 +       return 0;
8508 +}
8509 diff -uprN linux-2.6.27./security/capability.c linux-2.6.27/security/capability.c
8510 --- linux-2.6.27./security/capability.c 2008-10-10 00:13:53.000000000 +0200
8511 +++ linux-2.6.27/security/capability.c  2008-10-29 02:02:02.169338920 +0100
8512 @@ -155,52 +155,56 @@ static int cap_inode_init_security(struc
8513  }
8514  
8515  static int cap_inode_create(struct inode *inode, struct dentry *dentry,
8516 -                           int mask)
8517 +                           struct vfsmount *mnt, int mask)
8518  {
8519         return 0;
8520  }
8521  
8522 -static int cap_inode_link(struct dentry *old_dentry, struct inode *inode,
8523 -                         struct dentry *new_dentry)
8524 +static int cap_inode_link(struct dentry *old_dentry, struct vfsmount *old_mnt,
8525 +                         struct inode *inode,
8526 +                         struct dentry *new_dentry, struct vfsmount *new_mnt)
8527  {
8528         return 0;
8529  }
8530  
8531 -static int cap_inode_unlink(struct inode *inode, struct dentry *dentry)
8532 +static int cap_inode_unlink(struct inode *inode, struct dentry *dentry,
8533 +                           struct vfsmount *mnt)
8534  {
8535         return 0;
8536  }
8537  
8538  static int cap_inode_symlink(struct inode *inode, struct dentry *dentry,
8539 -                            const char *name)
8540 +                            struct vfsmount *mnt, const char *name)
8541  {
8542         return 0;
8543  }
8544  
8545  static int cap_inode_mkdir(struct inode *inode, struct dentry *dentry,
8546 -                          int mask)
8547 +                          struct vfsmount *mnt, int mask)
8548  {
8549         return 0;
8550  }
8551  
8552 -static int cap_inode_rmdir(struct inode *inode, struct dentry *dentry)
8553 +static int cap_inode_rmdir(struct inode *inode, struct dentry *dentry,
8554 +                          struct vfsmount *mnt)
8555  {
8556         return 0;
8557  }
8558  
8559  static int cap_inode_mknod(struct inode *inode, struct dentry *dentry,
8560 -                          int mode, dev_t dev)
8561 +                          struct vfsmount *mnt, int mode, dev_t dev)
8562  {
8563         return 0;
8564  }
8565  
8566  static int cap_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
8567 -                           struct inode *new_inode, struct dentry *new_dentry)
8568 +                           struct vfsmount *old_mnt, struct inode *new_inode,
8569 +                           struct dentry *new_dentry, struct vfsmount *new_mnt)
8570  {
8571         return 0;
8572  }
8573  
8574 -static int cap_inode_readlink(struct dentry *dentry)
8575 +static int cap_inode_readlink(struct dentry *dentry, struct vfsmount *mnt)
8576  {
8577         return 0;
8578  }
8579 @@ -216,7 +220,8 @@ static int cap_inode_permission(struct i
8580         return 0;
8581  }
8582  
8583 -static int cap_inode_setattr(struct dentry *dentry, struct iattr *iattr)
8584 +static int cap_inode_setattr(struct dentry *dentry, struct vfsmount *mnt,
8585 +                            struct iattr *iattr)
8586  {
8587         return 0;
8588  }
8589 @@ -230,17 +235,20 @@ static void cap_inode_delete(struct inod
8590  {
8591  }
8592  
8593 -static void cap_inode_post_setxattr(struct dentry *dentry, const char *name,
8594 +static void cap_inode_post_setxattr(struct dentry *dentry, struct vfsmount *mnt,
8595 +                                   const char *name,
8596                                     const void *value, size_t size, int flags)
8597  {
8598  }
8599  
8600 -static int cap_inode_getxattr(struct dentry *dentry, const char *name)
8601 +static int cap_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
8602 +                             const char *name, struct file *f)
8603  {
8604         return 0;
8605  }
8606  
8607 -static int cap_inode_listxattr(struct dentry *dentry)
8608 +static int cap_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt,
8609 +                              struct file *f)
8610  {
8611         return 0;
8612  }
8613 @@ -335,6 +343,11 @@ static int cap_dentry_open(struct file *
8614         return 0;
8615  }
8616  
8617 +static int cap_path_permission(struct path *path, int mask)
8618 +{
8619 +       return security_inode_permission(path->dentry->d_inode, mask);
8620 +}
8621 +
8622  static int cap_task_create(unsigned long clone_flags)
8623  {
8624         return 0;
8625 @@ -889,6 +902,7 @@ void security_fixup_ops(struct security_
8626         set_to_cap_if_null(ops, file_send_sigiotask);
8627         set_to_cap_if_null(ops, file_receive);
8628         set_to_cap_if_null(ops, dentry_open);
8629 +       set_to_cap_if_null(ops, path_permission);
8630         set_to_cap_if_null(ops, task_create);
8631         set_to_cap_if_null(ops, task_alloc_security);
8632         set_to_cap_if_null(ops, task_free_security);
8633 diff -uprN linux-2.6.27./security/commoncap.c linux-2.6.27/security/commoncap.c
8634 --- linux-2.6.27./security/commoncap.c  2008-10-10 00:13:53.000000000 +0200
8635 +++ linux-2.6.27/security/commoncap.c   2008-10-29 02:02:02.043175933 +0100
8636 @@ -411,8 +411,9 @@ int cap_bprm_secureexec (struct linux_bi
8637                 current->egid != current->gid);
8638  }
8639  
8640 -int cap_inode_setxattr(struct dentry *dentry, const char *name,
8641 -                      const void *value, size_t size, int flags)
8642 +int cap_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
8643 +                      const char *name, const void *value, size_t size,
8644 +                      int flags, struct file *file)
8645  {
8646         if (!strcmp(name, XATTR_NAME_CAPS)) {
8647                 if (!capable(CAP_SETFCAP))
8648 @@ -425,7 +426,8 @@ int cap_inode_setxattr(struct dentry *de
8649         return 0;
8650  }
8651  
8652 -int cap_inode_removexattr(struct dentry *dentry, const char *name)
8653 +int cap_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
8654 +                         const char *name, struct file *file)
8655  {
8656         if (!strcmp(name, XATTR_NAME_CAPS)) {
8657                 if (!capable(CAP_SETFCAP))
8658 diff -uprN linux-2.6.27./security/security.c linux-2.6.27/security/security.c
8659 --- linux-2.6.27./security/security.c   2008-10-10 00:13:53.000000000 +0200
8660 +++ linux-2.6.27/security/security.c    2008-10-29 02:02:02.706853503 +0100
8661 @@ -358,72 +358,81 @@ int security_inode_init_security(struct 
8662  }
8663  EXPORT_SYMBOL(security_inode_init_security);
8664  
8665 -int security_inode_create(struct inode *dir, struct dentry *dentry, int mode)
8666 +int security_inode_create(struct inode *dir, struct dentry *dentry,
8667 +                         struct vfsmount *mnt, int mode)
8668  {
8669         if (unlikely(IS_PRIVATE(dir)))
8670                 return 0;
8671 -       return security_ops->inode_create(dir, dentry, mode);
8672 +       return security_ops->inode_create(dir, dentry, mnt, mode);
8673  }
8674  
8675 -int security_inode_link(struct dentry *old_dentry, struct inode *dir,
8676 -                        struct dentry *new_dentry)
8677 +int security_inode_link(struct dentry *old_dentry, struct vfsmount *old_mnt,
8678 +                       struct inode *dir, struct dentry *new_dentry,
8679 +                       struct vfsmount *new_mnt)
8680  {
8681         if (unlikely(IS_PRIVATE(old_dentry->d_inode)))
8682                 return 0;
8683 -       return security_ops->inode_link(old_dentry, dir, new_dentry);
8684 +       return security_ops->inode_link(old_dentry, old_mnt, dir,
8685 +                                        new_dentry, new_mnt);
8686  }
8687  
8688 -int security_inode_unlink(struct inode *dir, struct dentry *dentry)
8689 +int security_inode_unlink(struct inode *dir, struct dentry *dentry,
8690 +                         struct vfsmount *mnt)
8691  {
8692         if (unlikely(IS_PRIVATE(dentry->d_inode)))
8693                 return 0;
8694 -       return security_ops->inode_unlink(dir, dentry);
8695 +       return security_ops->inode_unlink(dir, dentry, mnt);
8696  }
8697  
8698  int security_inode_symlink(struct inode *dir, struct dentry *dentry,
8699 -                           const char *old_name)
8700 +                          struct vfsmount *mnt, const char *old_name)
8701  {
8702         if (unlikely(IS_PRIVATE(dir)))
8703                 return 0;
8704 -       return security_ops->inode_symlink(dir, dentry, old_name);
8705 +       return security_ops->inode_symlink(dir, dentry, mnt, old_name);
8706  }
8707  
8708 -int security_inode_mkdir(struct inode *dir, struct dentry *dentry, int mode)
8709 +int security_inode_mkdir(struct inode *dir, struct dentry *dentry,
8710 +                        struct vfsmount *mnt, int mode)
8711  {
8712         if (unlikely(IS_PRIVATE(dir)))
8713                 return 0;
8714 -       return security_ops->inode_mkdir(dir, dentry, mode);
8715 +       return security_ops->inode_mkdir(dir, dentry, mnt, mode);
8716  }
8717  
8718 -int security_inode_rmdir(struct inode *dir, struct dentry *dentry)
8719 +int security_inode_rmdir(struct inode *dir, struct dentry *dentry,
8720 +                        struct vfsmount *mnt)
8721  {
8722         if (unlikely(IS_PRIVATE(dentry->d_inode)))
8723                 return 0;
8724 -       return security_ops->inode_rmdir(dir, dentry);
8725 +       return security_ops->inode_rmdir(dir, dentry, mnt);
8726  }
8727  
8728 -int security_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
8729 +int security_inode_mknod(struct inode *dir, struct dentry *dentry,
8730 +                        struct vfsmount *mnt, int mode, dev_t dev)
8731  {
8732         if (unlikely(IS_PRIVATE(dir)))
8733                 return 0;
8734 -       return security_ops->inode_mknod(dir, dentry, mode, dev);
8735 +       return security_ops->inode_mknod(dir, dentry, mnt, mode, dev);
8736  }
8737 +EXPORT_SYMBOL_GPL(security_inode_permission);
8738  
8739  int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
8740 -                          struct inode *new_dir, struct dentry *new_dentry)
8741 +                         struct vfsmount *old_mnt, struct inode *new_dir,
8742 +                         struct dentry *new_dentry, struct vfsmount *new_mnt)
8743  {
8744          if (unlikely(IS_PRIVATE(old_dentry->d_inode) ||
8745              (new_dentry->d_inode && IS_PRIVATE(new_dentry->d_inode))))
8746                 return 0;
8747 -       return security_ops->inode_rename(old_dir, old_dentry,
8748 -                                          new_dir, new_dentry);
8749 +       return security_ops->inode_rename(old_dir, old_dentry, old_mnt,
8750 +                                          new_dir, new_dentry, new_mnt);
8751  }
8752  
8753 -int security_inode_readlink(struct dentry *dentry)
8754 +int security_inode_readlink(struct dentry *dentry, struct vfsmount *mnt)
8755  {
8756         if (unlikely(IS_PRIVATE(dentry->d_inode)))
8757                 return 0;
8758 -       return security_ops->inode_readlink(dentry);
8759 +       return security_ops->inode_readlink(dentry, mnt);
8760  }
8761  
8762  int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd)
8763 @@ -440,11 +449,12 @@ int security_inode_permission(struct ino
8764         return security_ops->inode_permission(inode, mask);
8765  }
8766  
8767 -int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
8768 +int security_inode_setattr(struct dentry *dentry, struct vfsmount *mnt,
8769 +                          struct iattr *attr)
8770  {
8771         if (unlikely(IS_PRIVATE(dentry->d_inode)))
8772                 return 0;
8773 -       return security_ops->inode_setattr(dentry, attr);
8774 +       return security_ops->inode_setattr(dentry, mnt, attr);
8775  }
8776  EXPORT_SYMBOL_GPL(security_inode_setattr);
8777  
8778 @@ -462,41 +472,48 @@ void security_inode_delete(struct inode 
8779         security_ops->inode_delete(inode);
8780  }
8781  
8782 -int security_inode_setxattr(struct dentry *dentry, const char *name,
8783 -                           const void *value, size_t size, int flags)
8784 +int security_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
8785 +                           const char *name, const void *value, size_t size,
8786 +                           int flags, struct file *file)
8787  {
8788         if (unlikely(IS_PRIVATE(dentry->d_inode)))
8789                 return 0;
8790 -       return security_ops->inode_setxattr(dentry, name, value, size, flags);
8791 +       return security_ops->inode_setxattr(dentry, mnt, name, value, size,
8792 +                                           flags, file);
8793  }
8794  
8795 -void security_inode_post_setxattr(struct dentry *dentry, const char *name,
8796 -                                 const void *value, size_t size, int flags)
8797 +void security_inode_post_setxattr(struct dentry *dentry, struct vfsmount *mnt,
8798 +                                 const char *name, const void *value,
8799 +                                 size_t size, int flags)
8800  {
8801         if (unlikely(IS_PRIVATE(dentry->d_inode)))
8802                 return;
8803 -       security_ops->inode_post_setxattr(dentry, name, value, size, flags);
8804 +       security_ops->inode_post_setxattr(dentry, mnt, name, value, size,
8805 +                                         flags);
8806  }
8807  
8808 -int security_inode_getxattr(struct dentry *dentry, const char *name)
8809 +int security_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
8810 +                           const char *name, struct file *file)
8811  {
8812         if (unlikely(IS_PRIVATE(dentry->d_inode)))
8813                 return 0;
8814 -       return security_ops->inode_getxattr(dentry, name);
8815 +       return security_ops->inode_getxattr(dentry, mnt, name, file);
8816  }
8817  
8818 -int security_inode_listxattr(struct dentry *dentry)
8819 +int security_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt,
8820 +                            struct file *file)
8821  {
8822         if (unlikely(IS_PRIVATE(dentry->d_inode)))
8823                 return 0;
8824 -       return security_ops->inode_listxattr(dentry);
8825 +       return security_ops->inode_listxattr(dentry, mnt, file);
8826  }
8827  
8828 -int security_inode_removexattr(struct dentry *dentry, const char *name)
8829 +int security_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
8830 +                              const char *name, struct file *file)
8831  {
8832         if (unlikely(IS_PRIVATE(dentry->d_inode)))
8833                 return 0;
8834 -       return security_ops->inode_removexattr(dentry, name);
8835 +       return security_ops->inode_removexattr(dentry, mnt, name, file);
8836  }
8837  
8838  int security_inode_need_killpriv(struct dentry *dentry)
8839 @@ -599,6 +616,15 @@ int security_dentry_open(struct file *fi
8840         return security_ops->dentry_open(file);
8841  }
8842  
8843 +int security_path_permission(struct path *path, int mask)
8844 +{
8845 +       struct inode *inode = path->dentry->d_inode;
8846 +       if (unlikely(IS_PRIVATE(inode)))
8847 +               return 0;
8848 +
8849 +       return security_ops->path_permission(path, mask);
8850 +}
8851 +
8852  int security_task_create(unsigned long clone_flags)
8853  {
8854         return security_ops->task_create(clone_flags);
8855 diff -uprN linux-2.6.27./security/selinux/hooks.c linux-2.6.27/security/selinux/hooks.c
8856 --- linux-2.6.27./security/selinux/hooks.c      2008-10-10 00:13:53.000000000 +0200
8857 +++ linux-2.6.27/security/selinux/hooks.c       2008-10-29 02:02:02.147048695 +0100
8858 @@ -1811,40 +1811,16 @@ static int selinux_capable(struct task_s
8859  
8860  static int selinux_sysctl_get_sid(ctl_table *table, u16 tclass, u32 *sid)
8861  {
8862 -       int buflen, rc;
8863 -       char *buffer, *path, *end;
8864 +       char *buffer, *path;
8865 +       int rc = -ENOMEM;
8866  
8867 -       rc = -ENOMEM;
8868         buffer = (char *)__get_free_page(GFP_KERNEL);
8869         if (!buffer)
8870                 goto out;
8871  
8872 -       buflen = PAGE_SIZE;
8873 -       end = buffer+buflen;
8874 -       *--end = '\0';
8875 -       buflen--;
8876 -       path = end-1;
8877 -       *path = '/';
8878 -       while (table) {
8879 -               const char *name = table->procname;
8880 -               size_t namelen = strlen(name);
8881 -               buflen -= namelen + 1;
8882 -               if (buflen < 0)
8883 -                       goto out_free;
8884 -               end -= namelen;
8885 -               memcpy(end, name, namelen);
8886 -               *--end = '/';
8887 -               path = end;
8888 -               table = table->parent;
8889 -       }
8890 -       buflen -= 4;
8891 -       if (buflen < 0)
8892 -               goto out_free;
8893 -       end -= 4;
8894 -       memcpy(end, "/sys", 4);
8895 -       path = end;
8896 -       rc = security_genfs_sid("proc", path, tclass, sid);
8897 -out_free:
8898 +       path = sysctl_pathname(table, buffer, PAGE_SIZE);
8899 +       if (path)
8900 +               rc = security_genfs_sid("proc", path, tclass, sid);
8901         free_page((unsigned long)buffer);
8902  out:
8903         return rc;
8904 @@ -2566,64 +2542,79 @@ static int selinux_inode_init_security(s
8905         return 0;
8906  }
8907  
8908 -static int selinux_inode_create(struct inode *dir, struct dentry *dentry, int mask)
8909 +static int selinux_inode_create(struct inode *dir, struct dentry *dentry,
8910 +                                struct vfsmount *mnt, int mask)
8911  {
8912         return may_create(dir, dentry, SECCLASS_FILE);
8913  }
8914  
8915 -static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
8916 +static int selinux_inode_link(struct dentry *old_dentry,
8917 +                             struct vfsmount *old_mnt,
8918 +                             struct inode *dir,
8919 +                             struct dentry *new_dentry,
8920 +                             struct vfsmount *new_mnt)
8921  {
8922         int rc;
8923  
8924 -       rc = secondary_ops->inode_link(old_dentry, dir, new_dentry);
8925 +       rc = secondary_ops->inode_link(old_dentry, old_mnt, dir, new_dentry,
8926 +                                      new_mnt);
8927         if (rc)
8928                 return rc;
8929         return may_link(dir, old_dentry, MAY_LINK);
8930  }
8931  
8932 -static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry)
8933 +static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry,
8934 +                               struct vfsmount *mnt)
8935  {
8936         int rc;
8937  
8938 -       rc = secondary_ops->inode_unlink(dir, dentry);
8939 +       rc = secondary_ops->inode_unlink(dir, dentry, mnt);
8940         if (rc)
8941                 return rc;
8942         return may_link(dir, dentry, MAY_UNLINK);
8943  }
8944  
8945 -static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name)
8946 +static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry,
8947 +                                struct vfsmount *mnt, const char *name)
8948  {
8949         return may_create(dir, dentry, SECCLASS_LNK_FILE);
8950  }
8951  
8952 -static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, int mask)
8953 +static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry,
8954 +                              struct vfsmount *mnt, int mask)
8955  {
8956         return may_create(dir, dentry, SECCLASS_DIR);
8957  }
8958  
8959 -static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry)
8960 +static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry,
8961 +                              struct vfsmount *mnt)
8962  {
8963         return may_link(dir, dentry, MAY_RMDIR);
8964  }
8965  
8966 -static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
8967 +static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry,
8968 +                              struct vfsmount *mnt, int mode, dev_t dev)
8969  {
8970         int rc;
8971  
8972 -       rc = secondary_ops->inode_mknod(dir, dentry, mode, dev);
8973 +       rc = secondary_ops->inode_mknod(dir, dentry, mnt, mode, dev);
8974         if (rc)
8975                 return rc;
8976  
8977         return may_create(dir, dentry, inode_mode_to_security_class(mode));
8978  }
8979  
8980 -static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
8981 -                               struct inode *new_inode, struct dentry *new_dentry)
8982 +static int selinux_inode_rename(struct inode *old_inode,
8983 +                               struct dentry *old_dentry,
8984 +                               struct vfsmount *old_mnt,
8985 +                                struct inode *new_inode,
8986 +                               struct dentry *new_dentry,
8987 +                               struct vfsmount *new_mnt)
8988  {
8989         return may_rename(old_inode, old_dentry, new_inode, new_dentry);
8990  }
8991  
8992 -static int selinux_inode_readlink(struct dentry *dentry)
8993 +static int selinux_inode_readlink(struct dentry *dentry, struct vfsmount *mnt)
8994  {
8995         return dentry_has_perm(current, NULL, dentry, FILE__READ);
8996  }
8997 @@ -2655,11 +2646,12 @@ static int selinux_inode_permission(stru
8998                                open_file_mask_to_av(inode->i_mode, mask), NULL);
8999  }
9000  
9001 -static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
9002 +static int selinux_inode_setattr(struct dentry *dentry, struct vfsmount *mnt,
9003 +                                struct iattr *iattr)
9004  {
9005         int rc;
9006  
9007 -       rc = secondary_ops->inode_setattr(dentry, iattr);
9008 +       rc = secondary_ops->inode_setattr(dentry, mnt, iattr);
9009         if (rc)
9010                 return rc;
9011  
9012 @@ -2697,8 +2689,9 @@ static int selinux_inode_setotherxattr(s
9013         return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
9014  }
9015  
9016 -static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
9017 -                                 const void *value, size_t size, int flags)
9018 +static int selinux_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
9019 +                                 const char *name, const void *value,
9020 +                                 size_t size, int flags, struct file *file)
9021  {
9022         struct task_security_struct *tsec = current->security;
9023         struct inode *inode = dentry->d_inode;
9024 @@ -2752,7 +2745,8 @@ static int selinux_inode_setxattr(struct
9025                             &ad);
9026  }
9027  
9028 -static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
9029 +static void selinux_inode_post_setxattr(struct dentry *dentry,
9030 +                                       struct vfsmount *mnt, const char *name,
9031                                         const void *value, size_t size,
9032                                         int flags)
9033  {
9034 @@ -2778,17 +2772,21 @@ static void selinux_inode_post_setxattr(
9035         return;
9036  }
9037  
9038 -static int selinux_inode_getxattr(struct dentry *dentry, const char *name)
9039 +static int selinux_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
9040 +                                 const char *name, struct file *file)
9041  {
9042         return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
9043  }
9044  
9045 -static int selinux_inode_listxattr(struct dentry *dentry)
9046 +static int selinux_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt,
9047 +                                  struct file *file)
9048  {
9049         return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
9050  }
9051  
9052 -static int selinux_inode_removexattr(struct dentry *dentry, const char *name)
9053 +static int selinux_inode_removexattr(struct dentry *dentry,
9054 +                                    struct vfsmount *mnt, const char *name,
9055 +                                    struct file *file)
9056  {
9057         if (strcmp(name, XATTR_NAME_SELINUX))
9058                 return selinux_inode_setotherxattr(dentry, name);
9059 diff -uprN linux-2.6.27./security/smack/smack_lsm.c linux-2.6.27/security/smack/smack_lsm.c
9060 --- linux-2.6.27./security/smack/smack_lsm.c    2008-10-10 00:13:53.000000000 +0200
9061 +++ linux-2.6.27/security/smack/smack_lsm.c     2008-10-29 02:02:02.110260164 +0100
9062 @@ -432,8 +432,9 @@ static int smack_inode_init_security(str
9063   *
9064   * Returns 0 if access is permitted, an error code otherwise
9065   */
9066 -static int smack_inode_link(struct dentry *old_dentry, struct inode *dir,
9067 -                           struct dentry *new_dentry)
9068 +static int smack_inode_link(struct dentry *old_dentry, struct vfsmount *old_mnt,
9069 +                           struct inode *dir,
9070 +                           struct dentry *new_dentry, struct vfsmount *new_mnt)
9071  {
9072         int rc;
9073         char *isp;
9074 @@ -453,11 +454,13 @@ static int smack_inode_link(struct dentr
9075   * smack_inode_unlink - Smack check on inode deletion
9076   * @dir: containing directory object
9077   * @dentry: file to unlink
9078 + * @mnt: vfsmount of file to unlink
9079   *
9080   * Returns 0 if current can write the containing directory
9081   * and the object, error code otherwise
9082   */
9083 -static int smack_inode_unlink(struct inode *dir, struct dentry *dentry)
9084 +static int smack_inode_unlink(struct inode *dir, struct dentry *dentry,
9085 +                             struct vfsmount *mnt)
9086  {
9087         struct inode *ip = dentry->d_inode;
9088         int rc;
9089 @@ -479,11 +482,13 @@ static int smack_inode_unlink(struct ino
9090   * smack_inode_rmdir - Smack check on directory deletion
9091   * @dir: containing directory object
9092   * @dentry: directory to unlink
9093 + * @mnt: vfsmount @dentry to unlink
9094   *
9095   * Returns 0 if current can write the containing directory
9096   * and the directory, error code otherwise
9097   */
9098 -static int smack_inode_rmdir(struct inode *dir, struct dentry *dentry)
9099 +static int smack_inode_rmdir(struct inode *dir, struct dentry *dentry,
9100 +                            struct vfsmount *mnt)
9101  {
9102         int rc;
9103  
9104 @@ -504,8 +509,10 @@ static int smack_inode_rmdir(struct inod
9105   * smack_inode_rename - Smack check on rename
9106   * @old_inode: the old directory
9107   * @old_dentry: unused
9108 + * @old_mnt: unused
9109   * @new_inode: the new directory
9110   * @new_dentry: unused
9111 + * @new_mnt: unused
9112   *
9113   * Read and write access is required on both the old and
9114   * new directories.
9115 @@ -514,8 +521,10 @@ static int smack_inode_rmdir(struct inod
9116   */
9117  static int smack_inode_rename(struct inode *old_inode,
9118                               struct dentry *old_dentry,
9119 +                             struct vfsmount *old_mnt,
9120                               struct inode *new_inode,
9121 -                             struct dentry *new_dentry)
9122 +                             struct dentry *new_dentry,
9123 +                             struct vfsmount *new_mnt)
9124  {
9125         int rc;
9126         char *isp;
9127 @@ -559,7 +568,8 @@ static int smack_inode_permission(struct
9128   *
9129   * Returns 0 if access is permitted, an error code otherwise
9130   */
9131 -static int smack_inode_setattr(struct dentry *dentry, struct iattr *iattr)
9132 +static int smack_inode_setattr(struct dentry *dentry, struct vfsmount *mnt,
9133 +                              struct iattr *iattr)
9134  {
9135         /*
9136          * Need to allow for clearing the setuid bit.
9137 @@ -585,17 +595,20 @@ static int smack_inode_getattr(struct vf
9138  /**
9139   * smack_inode_setxattr - Smack check for setting xattrs
9140   * @dentry: the object
9141 + * @mnt: unused
9142   * @name: name of the attribute
9143   * @value: unused
9144   * @size: unused
9145   * @flags: unused
9146 + * @file: unused
9147   *
9148   * This protects the Smack attribute explicitly.
9149   *
9150   * Returns 0 if access is permitted, an error code otherwise
9151   */
9152 -static int smack_inode_setxattr(struct dentry *dentry, const char *name,
9153 -                               const void *value, size_t size, int flags)
9154 +static int smack_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
9155 +                               const char *name, const void *value,
9156 +                               size_t size, int flags, struct file *file)
9157  {
9158         int rc = 0;
9159  
9160 @@ -605,7 +618,8 @@ static int smack_inode_setxattr(struct d
9161                 if (!capable(CAP_MAC_ADMIN))
9162                         rc = -EPERM;
9163         } else
9164 -               rc = cap_inode_setxattr(dentry, name, value, size, flags);
9165 +               rc = cap_inode_setxattr(dentry, mnt, name, value, size, flags,
9166 +                                       file);
9167  
9168         if (rc == 0)
9169                 rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE);
9170 @@ -616,6 +630,7 @@ static int smack_inode_setxattr(struct d
9171  /**
9172   * smack_inode_post_setxattr - Apply the Smack update approved above
9173   * @dentry: object
9174 + * @mnt: unused
9175   * @name: attribute name
9176   * @value: attribute value
9177   * @size: attribute size
9178 @@ -624,7 +639,8 @@ static int smack_inode_setxattr(struct d
9179   * Set the pointer in the inode blob to the entry found
9180   * in the master label list.
9181   */
9182 -static void smack_inode_post_setxattr(struct dentry *dentry, const char *name,
9183 +static void smack_inode_post_setxattr(struct dentry *dentry,
9184 +                                     struct vfsmount *mnt, const char *name,
9185                                       const void *value, size_t size, int flags)
9186  {
9187         struct inode_smack *isp;
9188 @@ -657,11 +673,14 @@ static void smack_inode_post_setxattr(st
9189  /*
9190   * smack_inode_getxattr - Smack check on getxattr
9191   * @dentry: the object
9192 + * @mnt: unused
9193   * @name: unused
9194 + * @file: unused
9195   *
9196   * Returns 0 if access is permitted, an error code otherwise
9197   */
9198 -static int smack_inode_getxattr(struct dentry *dentry, const char *name)
9199 +static int smack_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
9200 +                               const char *name, struct file *file)
9201  {
9202         return smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ);
9203  }
9204 @@ -669,13 +688,16 @@ static int smack_inode_getxattr(struct d
9205  /*
9206   * smack_inode_removexattr - Smack check on removexattr
9207   * @dentry: the object
9208 + * @mnt: unused
9209   * @name: name of the attribute
9210 + * @file: unused
9211   *
9212   * Removing the Smack attribute requires CAP_MAC_ADMIN
9213   *
9214   * Returns 0 if access is permitted, an error code otherwise
9215   */
9216 -static int smack_inode_removexattr(struct dentry *dentry, const char *name)
9217 +static int smack_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
9218 +                                  const char *name, struct file *file)
9219  {
9220         int rc = 0;
9221  
9222 @@ -685,7 +707,7 @@ static int smack_inode_removexattr(struc
9223                 if (!capable(CAP_MAC_ADMIN))
9224                         rc = -EPERM;
9225         } else
9226 -               rc = cap_inode_removexattr(dentry, name);
9227 +               rc = cap_inode_removexattr(dentry, mnt, name, file);
9228  
9229         if (rc == 0)
9230                 rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE);
This page took 0.802515 seconds and 3 git commands to generate.