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