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