apparmor: Make aa_remove_profile() callable from a different view
[linux-block.git] / security / apparmor / apparmorfs.c
CommitLineData
63e2b423
JJ
1/*
2 * AppArmor security module
3 *
4 * This file contains AppArmor /sys/kernel/security/apparmor interface functions
5 *
6 * Copyright (C) 1998-2008 Novell/SUSE
7 * Copyright 2009-2010 Canonical Ltd.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation, version 2 of the
12 * License.
13 */
14
0d259f04 15#include <linux/ctype.h>
63e2b423
JJ
16#include <linux/security.h>
17#include <linux/vmalloc.h>
18#include <linux/module.h>
19#include <linux/seq_file.h>
20#include <linux/uaccess.h>
a71ada30 21#include <linux/mount.h>
63e2b423 22#include <linux/namei.h>
e74abcf3 23#include <linux/capability.h>
29b3822f 24#include <linux/rcupdate.h>
a71ada30
JJ
25#include <uapi/linux/major.h>
26#include <linux/fs.h>
63e2b423
JJ
27
28#include "include/apparmor.h"
29#include "include/apparmorfs.h"
30#include "include/audit.h"
31#include "include/context.h"
f8eb8a13 32#include "include/crypto.h"
63e2b423 33#include "include/policy.h"
cff281f6 34#include "include/policy_ns.h"
d384b0a1 35#include "include/resource.h"
63e2b423 36
0d259f04
JJ
37/**
38 * aa_mangle_name - mangle a profile name to std profile layout form
39 * @name: profile name to mangle (NOT NULL)
40 * @target: buffer to store mangled name, same length as @name (MAYBE NULL)
41 *
42 * Returns: length of mangled name
43 */
bbe4a7c8 44static int mangle_name(const char *name, char *target)
0d259f04
JJ
45{
46 char *t = target;
47
48 while (*name == '/' || *name == '.')
49 name++;
50
51 if (target) {
52 for (; *name; name++) {
53 if (*name == '/')
54 *(t)++ = '.';
55 else if (isspace(*name))
56 *(t)++ = '_';
57 else if (isalnum(*name) || strchr("._-", *name))
58 *(t)++ = *name;
59 }
60
61 *t = 0;
62 } else {
63 int len = 0;
64 for (; *name; name++) {
65 if (isalnum(*name) || isspace(*name) ||
66 strchr("/._-", *name))
67 len++;
68 }
69
70 return len;
71 }
72
73 return t - target;
74}
75
63e2b423
JJ
76/**
77 * aa_simple_write_to_buffer - common routine for getting policy from user
78 * @op: operation doing the user buffer copy
79 * @userbuf: user buffer to copy data from (NOT NULL)
3ed02ada 80 * @alloc_size: size of user buffer (REQUIRES: @alloc_size >= @copy_size)
63e2b423
JJ
81 * @copy_size: size of data to copy from user buffer
82 * @pos: position write is at in the file (NOT NULL)
83 *
84 * Returns: kernel buffer containing copy of user buffer data or an
85 * ERR_PTR on failure.
86 */
87static char *aa_simple_write_to_buffer(int op, const char __user *userbuf,
88 size_t alloc_size, size_t copy_size,
89 loff_t *pos)
90{
91 char *data;
92
3ed02ada
JJ
93 BUG_ON(copy_size > alloc_size);
94
63e2b423
JJ
95 if (*pos != 0)
96 /* only writes from pos 0, that is complete writes */
97 return ERR_PTR(-ESPIPE);
98
99 /*
100 * Don't allow profile load/replace/remove from profiles that don't
101 * have CAP_MAC_ADMIN
102 */
103 if (!aa_may_manage_policy(op))
104 return ERR_PTR(-EACCES);
105
106 /* freed by caller to simple_write_to_buffer */
107 data = kvmalloc(alloc_size);
108 if (data == NULL)
109 return ERR_PTR(-ENOMEM);
110
111 if (copy_from_user(data, userbuf, copy_size)) {
112 kvfree(data);
113 return ERR_PTR(-EFAULT);
114 }
115
116 return data;
117}
118
119
120/* .load file hook fn to load policy */
121static ssize_t profile_load(struct file *f, const char __user *buf, size_t size,
122 loff_t *pos)
123{
124 char *data;
125 ssize_t error;
126
127 data = aa_simple_write_to_buffer(OP_PROF_LOAD, buf, size, size, pos);
128
129 error = PTR_ERR(data);
130 if (!IS_ERR(data)) {
73688d1e
JJ
131 error = aa_replace_profiles(__aa_current_profile()->ns, data,
132 size, PROF_ADD);
63e2b423
JJ
133 kvfree(data);
134 }
135
136 return error;
137}
138
139static const struct file_operations aa_fs_profile_load = {
6038f373
AB
140 .write = profile_load,
141 .llseek = default_llseek,
63e2b423
JJ
142};
143
144/* .replace file hook fn to load and/or replace policy */
145static ssize_t profile_replace(struct file *f, const char __user *buf,
146 size_t size, loff_t *pos)
147{
148 char *data;
149 ssize_t error;
150
151 data = aa_simple_write_to_buffer(OP_PROF_REPL, buf, size, size, pos);
152 error = PTR_ERR(data);
153 if (!IS_ERR(data)) {
73688d1e
JJ
154 error = aa_replace_profiles(__aa_current_profile()->ns, data,
155 size, PROF_REPLACE);
63e2b423
JJ
156 kvfree(data);
157 }
158
159 return error;
160}
161
162static const struct file_operations aa_fs_profile_replace = {
6038f373
AB
163 .write = profile_replace,
164 .llseek = default_llseek,
63e2b423
JJ
165};
166
167/* .remove file hook fn to remove loaded policy */
168static ssize_t profile_remove(struct file *f, const char __user *buf,
169 size_t size, loff_t *pos)
170{
171 char *data;
172 ssize_t error;
173
174 /*
175 * aa_remove_profile needs a null terminated string so 1 extra
176 * byte is allocated and the copied data is null terminated.
177 */
178 data = aa_simple_write_to_buffer(OP_PROF_RM, buf, size + 1, size, pos);
179
180 error = PTR_ERR(data);
181 if (!IS_ERR(data)) {
182 data[size] = 0;
b79473f2
JJ
183 error = aa_remove_profiles(__aa_current_profile()->ns, data,
184 size);
63e2b423
JJ
185 kvfree(data);
186 }
187
188 return error;
189}
190
191static const struct file_operations aa_fs_profile_remove = {
6038f373
AB
192 .write = profile_remove,
193 .llseek = default_llseek,
63e2b423
JJ
194};
195
e74abcf3
KC
196static int aa_fs_seq_show(struct seq_file *seq, void *v)
197{
198 struct aa_fs_entry *fs_file = seq->private;
199
200 if (!fs_file)
201 return 0;
202
203 switch (fs_file->v_type) {
204 case AA_FS_TYPE_BOOLEAN:
205 seq_printf(seq, "%s\n", fs_file->v.boolean ? "yes" : "no");
206 break;
a9bf8e9f
KC
207 case AA_FS_TYPE_STRING:
208 seq_printf(seq, "%s\n", fs_file->v.string);
209 break;
e74abcf3
KC
210 case AA_FS_TYPE_U64:
211 seq_printf(seq, "%#08lx\n", fs_file->v.u64);
212 break;
213 default:
214 /* Ignore unpritable entry types. */
215 break;
216 }
217
218 return 0;
219}
220
221static int aa_fs_seq_open(struct inode *inode, struct file *file)
222{
223 return single_open(file, aa_fs_seq_show, inode->i_private);
224}
225
226const struct file_operations aa_fs_seq_file_ops = {
227 .owner = THIS_MODULE,
228 .open = aa_fs_seq_open,
229 .read = seq_read,
230 .llseek = seq_lseek,
231 .release = single_release,
232};
233
0d259f04
JJ
234static int aa_fs_seq_profile_open(struct inode *inode, struct file *file,
235 int (*show)(struct seq_file *, void *))
236{
8399588a
JJ
237 struct aa_proxy *proxy = aa_get_proxy(inode->i_private);
238 int error = single_open(file, show, proxy);
0d259f04
JJ
239
240 if (error) {
241 file->private_data = NULL;
8399588a 242 aa_put_proxy(proxy);
0d259f04
JJ
243 }
244
245 return error;
246}
247
248static int aa_fs_seq_profile_release(struct inode *inode, struct file *file)
249{
250 struct seq_file *seq = (struct seq_file *) file->private_data;
251 if (seq)
8399588a 252 aa_put_proxy(seq->private);
0d259f04
JJ
253 return single_release(inode, file);
254}
255
256static int aa_fs_seq_profname_show(struct seq_file *seq, void *v)
257{
8399588a
JJ
258 struct aa_proxy *proxy = seq->private;
259 struct aa_profile *profile = aa_get_profile_rcu(&proxy->profile);
0d259f04
JJ
260 seq_printf(seq, "%s\n", profile->base.name);
261 aa_put_profile(profile);
262
263 return 0;
264}
265
266static int aa_fs_seq_profname_open(struct inode *inode, struct file *file)
267{
268 return aa_fs_seq_profile_open(inode, file, aa_fs_seq_profname_show);
269}
270
271static const struct file_operations aa_fs_profname_fops = {
272 .owner = THIS_MODULE,
273 .open = aa_fs_seq_profname_open,
274 .read = seq_read,
275 .llseek = seq_lseek,
276 .release = aa_fs_seq_profile_release,
277};
278
279static int aa_fs_seq_profmode_show(struct seq_file *seq, void *v)
280{
8399588a
JJ
281 struct aa_proxy *proxy = seq->private;
282 struct aa_profile *profile = aa_get_profile_rcu(&proxy->profile);
0d259f04
JJ
283 seq_printf(seq, "%s\n", aa_profile_mode_names[profile->mode]);
284 aa_put_profile(profile);
285
286 return 0;
287}
288
289static int aa_fs_seq_profmode_open(struct inode *inode, struct file *file)
290{
291 return aa_fs_seq_profile_open(inode, file, aa_fs_seq_profmode_show);
292}
293
294static const struct file_operations aa_fs_profmode_fops = {
295 .owner = THIS_MODULE,
296 .open = aa_fs_seq_profmode_open,
297 .read = seq_read,
298 .llseek = seq_lseek,
299 .release = aa_fs_seq_profile_release,
300};
301
556d0be7
JJ
302static int aa_fs_seq_profattach_show(struct seq_file *seq, void *v)
303{
8399588a
JJ
304 struct aa_proxy *proxy = seq->private;
305 struct aa_profile *profile = aa_get_profile_rcu(&proxy->profile);
556d0be7
JJ
306 if (profile->attach)
307 seq_printf(seq, "%s\n", profile->attach);
308 else if (profile->xmatch)
309 seq_puts(seq, "<unknown>\n");
310 else
311 seq_printf(seq, "%s\n", profile->base.name);
312 aa_put_profile(profile);
313
314 return 0;
315}
316
317static int aa_fs_seq_profattach_open(struct inode *inode, struct file *file)
318{
319 return aa_fs_seq_profile_open(inode, file, aa_fs_seq_profattach_show);
320}
321
322static const struct file_operations aa_fs_profattach_fops = {
323 .owner = THIS_MODULE,
324 .open = aa_fs_seq_profattach_open,
325 .read = seq_read,
326 .llseek = seq_lseek,
327 .release = aa_fs_seq_profile_release,
328};
329
f8eb8a13
JJ
330static int aa_fs_seq_hash_show(struct seq_file *seq, void *v)
331{
8399588a
JJ
332 struct aa_proxy *proxy = seq->private;
333 struct aa_profile *profile = aa_get_profile_rcu(&proxy->profile);
f8eb8a13
JJ
334 unsigned int i, size = aa_hash_size();
335
336 if (profile->hash) {
337 for (i = 0; i < size; i++)
338 seq_printf(seq, "%.2x", profile->hash[i]);
339 seq_puts(seq, "\n");
340 }
0b938a2e 341 aa_put_profile(profile);
f8eb8a13
JJ
342
343 return 0;
344}
345
346static int aa_fs_seq_hash_open(struct inode *inode, struct file *file)
347{
348 return single_open(file, aa_fs_seq_hash_show, inode->i_private);
349}
350
351static const struct file_operations aa_fs_seq_hash_fops = {
352 .owner = THIS_MODULE,
353 .open = aa_fs_seq_hash_open,
354 .read = seq_read,
355 .llseek = seq_lseek,
356 .release = single_release,
357};
358
a71ada30
JJ
359static int aa_fs_seq_show_ns_level(struct seq_file *seq, void *v)
360{
361 struct aa_ns *ns = aa_current_profile()->ns;
362
363 seq_printf(seq, "%d\n", ns->level);
364
365 return 0;
366}
367
368static int aa_fs_seq_open_ns_level(struct inode *inode, struct file *file)
369{
370 return single_open(file, aa_fs_seq_show_ns_level, inode->i_private);
371}
372
373static const struct file_operations aa_fs_ns_level = {
374 .owner = THIS_MODULE,
375 .open = aa_fs_seq_open_ns_level,
376 .read = seq_read,
377 .llseek = seq_lseek,
378 .release = single_release,
379};
380
0d259f04
JJ
381/** fns to setup dynamic per profile/namespace files **/
382void __aa_fs_profile_rmdir(struct aa_profile *profile)
383{
384 struct aa_profile *child;
385 int i;
386
387 if (!profile)
388 return;
389
390 list_for_each_entry(child, &profile->base.profiles, base.list)
391 __aa_fs_profile_rmdir(child);
392
393 for (i = AAFS_PROF_SIZEOF - 1; i >= 0; --i) {
8399588a 394 struct aa_proxy *proxy;
0d259f04
JJ
395 if (!profile->dents[i])
396 continue;
397
8399588a 398 proxy = d_inode(profile->dents[i])->i_private;
0d259f04 399 securityfs_remove(profile->dents[i]);
8399588a 400 aa_put_proxy(proxy);
0d259f04
JJ
401 profile->dents[i] = NULL;
402 }
403}
404
405void __aa_fs_profile_migrate_dents(struct aa_profile *old,
406 struct aa_profile *new)
407{
408 int i;
409
410 for (i = 0; i < AAFS_PROF_SIZEOF; i++) {
411 new->dents[i] = old->dents[i];
d671e890 412 if (new->dents[i])
078cd827 413 new->dents[i]->d_inode->i_mtime = current_time(new->dents[i]->d_inode);
0d259f04
JJ
414 old->dents[i] = NULL;
415 }
416}
417
418static struct dentry *create_profile_file(struct dentry *dir, const char *name,
419 struct aa_profile *profile,
420 const struct file_operations *fops)
421{
8399588a 422 struct aa_proxy *proxy = aa_get_proxy(profile->proxy);
0d259f04
JJ
423 struct dentry *dent;
424
8399588a 425 dent = securityfs_create_file(name, S_IFREG | 0444, dir, proxy, fops);
0d259f04 426 if (IS_ERR(dent))
8399588a 427 aa_put_proxy(proxy);
0d259f04
JJ
428
429 return dent;
430}
431
432/* requires lock be held */
433int __aa_fs_profile_mkdir(struct aa_profile *profile, struct dentry *parent)
434{
435 struct aa_profile *child;
436 struct dentry *dent = NULL, *dir;
437 int error;
438
439 if (!parent) {
440 struct aa_profile *p;
441 p = aa_deref_parent(profile);
442 dent = prof_dir(p);
443 /* adding to parent that previously didn't have children */
444 dent = securityfs_create_dir("profiles", dent);
445 if (IS_ERR(dent))
446 goto fail;
447 prof_child_dir(p) = parent = dent;
448 }
449
450 if (!profile->dirname) {
451 int len, id_len;
452 len = mangle_name(profile->base.name, NULL);
453 id_len = snprintf(NULL, 0, ".%ld", profile->ns->uniq_id);
454
455 profile->dirname = kmalloc(len + id_len + 1, GFP_KERNEL);
456 if (!profile->dirname)
457 goto fail;
458
459 mangle_name(profile->base.name, profile->dirname);
460 sprintf(profile->dirname + len, ".%ld", profile->ns->uniq_id++);
461 }
462
463 dent = securityfs_create_dir(profile->dirname, parent);
464 if (IS_ERR(dent))
465 goto fail;
466 prof_dir(profile) = dir = dent;
467
468 dent = create_profile_file(dir, "name", profile, &aa_fs_profname_fops);
469 if (IS_ERR(dent))
470 goto fail;
471 profile->dents[AAFS_PROF_NAME] = dent;
472
473 dent = create_profile_file(dir, "mode", profile, &aa_fs_profmode_fops);
474 if (IS_ERR(dent))
475 goto fail;
476 profile->dents[AAFS_PROF_MODE] = dent;
477
556d0be7
JJ
478 dent = create_profile_file(dir, "attach", profile,
479 &aa_fs_profattach_fops);
480 if (IS_ERR(dent))
481 goto fail;
482 profile->dents[AAFS_PROF_ATTACH] = dent;
483
f8eb8a13
JJ
484 if (profile->hash) {
485 dent = create_profile_file(dir, "sha1", profile,
486 &aa_fs_seq_hash_fops);
487 if (IS_ERR(dent))
488 goto fail;
489 profile->dents[AAFS_PROF_HASH] = dent;
490 }
491
0d259f04
JJ
492 list_for_each_entry(child, &profile->base.profiles, base.list) {
493 error = __aa_fs_profile_mkdir(child, prof_child_dir(profile));
494 if (error)
495 goto fail2;
496 }
497
498 return 0;
499
500fail:
501 error = PTR_ERR(dent);
502
503fail2:
504 __aa_fs_profile_rmdir(profile);
505
506 return error;
507}
508
98849dff 509void __aa_fs_ns_rmdir(struct aa_ns *ns)
0d259f04 510{
98849dff 511 struct aa_ns *sub;
0d259f04
JJ
512 struct aa_profile *child;
513 int i;
514
515 if (!ns)
516 return;
517
518 list_for_each_entry(child, &ns->base.profiles, base.list)
519 __aa_fs_profile_rmdir(child);
520
521 list_for_each_entry(sub, &ns->sub_ns, base.list) {
522 mutex_lock(&sub->lock);
98849dff 523 __aa_fs_ns_rmdir(sub);
0d259f04
JJ
524 mutex_unlock(&sub->lock);
525 }
526
527 for (i = AAFS_NS_SIZEOF - 1; i >= 0; --i) {
528 securityfs_remove(ns->dents[i]);
529 ns->dents[i] = NULL;
530 }
531}
532
98849dff 533int __aa_fs_ns_mkdir(struct aa_ns *ns, struct dentry *parent, const char *name)
0d259f04 534{
98849dff 535 struct aa_ns *sub;
0d259f04
JJ
536 struct aa_profile *child;
537 struct dentry *dent, *dir;
538 int error;
539
540 if (!name)
541 name = ns->base.name;
542
543 dent = securityfs_create_dir(name, parent);
544 if (IS_ERR(dent))
545 goto fail;
546 ns_dir(ns) = dir = dent;
547
548 dent = securityfs_create_dir("profiles", dir);
549 if (IS_ERR(dent))
550 goto fail;
551 ns_subprofs_dir(ns) = dent;
63e2b423 552
0d259f04
JJ
553 dent = securityfs_create_dir("namespaces", dir);
554 if (IS_ERR(dent))
555 goto fail;
556 ns_subns_dir(ns) = dent;
557
558 list_for_each_entry(child, &ns->base.profiles, base.list) {
559 error = __aa_fs_profile_mkdir(child, ns_subprofs_dir(ns));
560 if (error)
561 goto fail2;
562 }
563
564 list_for_each_entry(sub, &ns->sub_ns, base.list) {
565 mutex_lock(&sub->lock);
98849dff 566 error = __aa_fs_ns_mkdir(sub, ns_subns_dir(ns), NULL);
0d259f04
JJ
567 mutex_unlock(&sub->lock);
568 if (error)
569 goto fail2;
570 }
571
572 return 0;
573
574fail:
575 error = PTR_ERR(dent);
576
577fail2:
98849dff 578 __aa_fs_ns_rmdir(ns);
0d259f04
JJ
579
580 return error;
581}
582
583
29b3822f
JJ
584#define list_entry_is_head(pos, head, member) (&pos->member == (head))
585
586/**
98849dff 587 * __next_ns - find the next namespace to list
29b3822f
JJ
588 * @root: root namespace to stop search at (NOT NULL)
589 * @ns: current ns position (NOT NULL)
590 *
591 * Find the next namespace from @ns under @root and handle all locking needed
592 * while switching current namespace.
593 *
594 * Returns: next namespace or NULL if at last namespace under @root
595 * Requires: ns->parent->lock to be held
596 * NOTE: will not unlock root->lock
597 */
98849dff 598static struct aa_ns *__next_ns(struct aa_ns *root, struct aa_ns *ns)
29b3822f 599{
98849dff 600 struct aa_ns *parent, *next;
29b3822f
JJ
601
602 /* is next namespace a child */
603 if (!list_empty(&ns->sub_ns)) {
604 next = list_first_entry(&ns->sub_ns, typeof(*ns), base.list);
605 mutex_lock(&next->lock);
606 return next;
607 }
608
609 /* check if the next ns is a sibling, parent, gp, .. */
610 parent = ns->parent;
ed2c7da3 611 while (ns != root) {
29b3822f 612 mutex_unlock(&ns->lock);
38dbd7d8 613 next = list_next_entry(ns, base.list);
29b3822f
JJ
614 if (!list_entry_is_head(next, &parent->sub_ns, base.list)) {
615 mutex_lock(&next->lock);
616 return next;
617 }
29b3822f
JJ
618 ns = parent;
619 parent = parent->parent;
620 }
621
622 return NULL;
623}
624
625/**
626 * __first_profile - find the first profile in a namespace
627 * @root: namespace that is root of profiles being displayed (NOT NULL)
628 * @ns: namespace to start in (NOT NULL)
629 *
630 * Returns: unrefcounted profile or NULL if no profile
631 * Requires: profile->ns.lock to be held
632 */
98849dff
JJ
633static struct aa_profile *__first_profile(struct aa_ns *root,
634 struct aa_ns *ns)
29b3822f 635{
98849dff 636 for (; ns; ns = __next_ns(root, ns)) {
29b3822f
JJ
637 if (!list_empty(&ns->base.profiles))
638 return list_first_entry(&ns->base.profiles,
639 struct aa_profile, base.list);
640 }
641 return NULL;
642}
643
644/**
645 * __next_profile - step to the next profile in a profile tree
646 * @profile: current profile in tree (NOT NULL)
647 *
648 * Perform a depth first traversal on the profile tree in a namespace
649 *
650 * Returns: next profile or NULL if done
651 * Requires: profile->ns.lock to be held
652 */
653static struct aa_profile *__next_profile(struct aa_profile *p)
654{
655 struct aa_profile *parent;
98849dff 656 struct aa_ns *ns = p->ns;
29b3822f
JJ
657
658 /* is next profile a child */
659 if (!list_empty(&p->base.profiles))
660 return list_first_entry(&p->base.profiles, typeof(*p),
661 base.list);
662
663 /* is next profile a sibling, parent sibling, gp, sibling, .. */
664 parent = rcu_dereference_protected(p->parent,
665 mutex_is_locked(&p->ns->lock));
666 while (parent) {
38dbd7d8 667 p = list_next_entry(p, base.list);
29b3822f
JJ
668 if (!list_entry_is_head(p, &parent->base.profiles, base.list))
669 return p;
670 p = parent;
671 parent = rcu_dereference_protected(parent->parent,
672 mutex_is_locked(&parent->ns->lock));
673 }
674
675 /* is next another profile in the namespace */
38dbd7d8 676 p = list_next_entry(p, base.list);
29b3822f
JJ
677 if (!list_entry_is_head(p, &ns->base.profiles, base.list))
678 return p;
679
680 return NULL;
681}
682
683/**
684 * next_profile - step to the next profile in where ever it may be
685 * @root: root namespace (NOT NULL)
686 * @profile: current profile (NOT NULL)
687 *
688 * Returns: next profile or NULL if there isn't one
689 */
98849dff 690static struct aa_profile *next_profile(struct aa_ns *root,
29b3822f
JJ
691 struct aa_profile *profile)
692{
693 struct aa_profile *next = __next_profile(profile);
694 if (next)
695 return next;
696
697 /* finished all profiles in namespace move to next namespace */
98849dff 698 return __first_profile(root, __next_ns(root, profile->ns));
29b3822f
JJ
699}
700
701/**
702 * p_start - start a depth first traversal of profile tree
703 * @f: seq_file to fill
704 * @pos: current position
705 *
706 * Returns: first profile under current namespace or NULL if none found
707 *
708 * acquires first ns->lock
709 */
710static void *p_start(struct seq_file *f, loff_t *pos)
711{
712 struct aa_profile *profile = NULL;
98849dff 713 struct aa_ns *root = aa_current_profile()->ns;
29b3822f 714 loff_t l = *pos;
98849dff 715 f->private = aa_get_ns(root);
29b3822f
JJ
716
717
718 /* find the first profile */
719 mutex_lock(&root->lock);
720 profile = __first_profile(root, root);
721
722 /* skip to position */
723 for (; profile && l > 0; l--)
724 profile = next_profile(root, profile);
725
726 return profile;
727}
728
729/**
730 * p_next - read the next profile entry
731 * @f: seq_file to fill
732 * @p: profile previously returned
733 * @pos: current position
734 *
735 * Returns: next profile after @p or NULL if none
736 *
737 * may acquire/release locks in namespace tree as necessary
738 */
739static void *p_next(struct seq_file *f, void *p, loff_t *pos)
740{
741 struct aa_profile *profile = p;
98849dff 742 struct aa_ns *ns = f->private;
29b3822f
JJ
743 (*pos)++;
744
745 return next_profile(ns, profile);
746}
747
748/**
749 * p_stop - stop depth first traversal
750 * @f: seq_file we are filling
751 * @p: the last profile writen
752 *
753 * Release all locking done by p_start/p_next on namespace tree
754 */
755static void p_stop(struct seq_file *f, void *p)
756{
757 struct aa_profile *profile = p;
98849dff 758 struct aa_ns *root = f->private, *ns;
29b3822f
JJ
759
760 if (profile) {
761 for (ns = profile->ns; ns && ns != root; ns = ns->parent)
762 mutex_unlock(&ns->lock);
763 }
764 mutex_unlock(&root->lock);
98849dff 765 aa_put_ns(root);
29b3822f
JJ
766}
767
768/**
769 * seq_show_profile - show a profile entry
770 * @f: seq_file to file
771 * @p: current position (profile) (NOT NULL)
772 *
773 * Returns: error on failure
774 */
775static int seq_show_profile(struct seq_file *f, void *p)
776{
777 struct aa_profile *profile = (struct aa_profile *)p;
98849dff 778 struct aa_ns *root = f->private;
29b3822f
JJ
779
780 if (profile->ns != root)
92b6d8ef 781 seq_printf(f, ":%s://", aa_ns_name(root, profile->ns, true));
29b3822f
JJ
782 seq_printf(f, "%s (%s)\n", profile->base.hname,
783 aa_profile_mode_names[profile->mode]);
784
785 return 0;
786}
787
788static const struct seq_operations aa_fs_profiles_op = {
789 .start = p_start,
790 .next = p_next,
791 .stop = p_stop,
792 .show = seq_show_profile,
793};
794
795static int profiles_open(struct inode *inode, struct file *file)
796{
797 return seq_open(file, &aa_fs_profiles_op);
798}
799
800static int profiles_release(struct inode *inode, struct file *file)
801{
802 return seq_release(inode, file);
803}
804
805static const struct file_operations aa_fs_profiles_fops = {
806 .open = profiles_open,
807 .read = seq_read,
808 .llseek = seq_lseek,
809 .release = profiles_release,
810};
811
812
0d259f04 813/** Base file system setup **/
a9bf8e9f
KC
814static struct aa_fs_entry aa_fs_entry_file[] = {
815 AA_FS_FILE_STRING("mask", "create read write exec append mmap_exec " \
816 "link lock"),
817 { }
818};
819
e74abcf3
KC
820static struct aa_fs_entry aa_fs_entry_domain[] = {
821 AA_FS_FILE_BOOLEAN("change_hat", 1),
822 AA_FS_FILE_BOOLEAN("change_hatv", 1),
823 AA_FS_FILE_BOOLEAN("change_onexec", 1),
824 AA_FS_FILE_BOOLEAN("change_profile", 1),
34c426ac 825 AA_FS_FILE_BOOLEAN("fix_binfmt_elf_mmap", 1),
e74abcf3
KC
826 { }
827};
828
474d6b75
JJ
829static struct aa_fs_entry aa_fs_entry_versions[] = {
830 AA_FS_FILE_BOOLEAN("v5", 1),
831 { }
832};
833
9d910a3b 834static struct aa_fs_entry aa_fs_entry_policy[] = {
474d6b75
JJ
835 AA_FS_DIR("versions", aa_fs_entry_versions),
836 AA_FS_FILE_BOOLEAN("set_load", 1),
837 { }
9d910a3b
JJ
838};
839
e74abcf3 840static struct aa_fs_entry aa_fs_entry_features[] = {
9d910a3b 841 AA_FS_DIR("policy", aa_fs_entry_policy),
e74abcf3 842 AA_FS_DIR("domain", aa_fs_entry_domain),
a9bf8e9f 843 AA_FS_DIR("file", aa_fs_entry_file),
e74abcf3 844 AA_FS_FILE_U64("capability", VFS_CAP_FLAGS_MASK),
d384b0a1 845 AA_FS_DIR("rlimit", aa_fs_entry_rlimit),
84f1f787 846 AA_FS_DIR("caps", aa_fs_entry_caps),
e74abcf3
KC
847 { }
848};
849
9acd494b
KC
850static struct aa_fs_entry aa_fs_entry_apparmor[] = {
851 AA_FS_FILE_FOPS(".load", 0640, &aa_fs_profile_load),
852 AA_FS_FILE_FOPS(".replace", 0640, &aa_fs_profile_replace),
853 AA_FS_FILE_FOPS(".remove", 0640, &aa_fs_profile_remove),
a71ada30 854 AA_FS_FILE_FOPS(".ns_level", 0666, &aa_fs_ns_level),
29b3822f 855 AA_FS_FILE_FOPS("profiles", 0640, &aa_fs_profiles_fops),
e74abcf3 856 AA_FS_DIR("features", aa_fs_entry_features),
9acd494b
KC
857 { }
858};
63e2b423 859
9acd494b
KC
860static struct aa_fs_entry aa_fs_entry =
861 AA_FS_DIR("apparmor", aa_fs_entry_apparmor);
63e2b423 862
9acd494b
KC
863/**
864 * aafs_create_file - create a file entry in the apparmor securityfs
865 * @fs_file: aa_fs_entry to build an entry for (NOT NULL)
866 * @parent: the parent dentry in the securityfs
867 *
868 * Use aafs_remove_file to remove entries created with this fn.
869 */
870static int __init aafs_create_file(struct aa_fs_entry *fs_file,
871 struct dentry *parent)
872{
873 int error = 0;
874
875 fs_file->dentry = securityfs_create_file(fs_file->name,
876 S_IFREG | fs_file->mode,
877 parent, fs_file,
878 fs_file->file_ops);
879 if (IS_ERR(fs_file->dentry)) {
880 error = PTR_ERR(fs_file->dentry);
881 fs_file->dentry = NULL;
63e2b423 882 }
9acd494b 883 return error;
63e2b423
JJ
884}
885
0d259f04 886static void __init aafs_remove_dir(struct aa_fs_entry *fs_dir);
63e2b423 887/**
9acd494b
KC
888 * aafs_create_dir - recursively create a directory entry in the securityfs
889 * @fs_dir: aa_fs_entry (and all child entries) to build (NOT NULL)
890 * @parent: the parent dentry in the securityfs
63e2b423 891 *
9acd494b 892 * Use aafs_remove_dir to remove entries created with this fn.
63e2b423 893 */
9acd494b
KC
894static int __init aafs_create_dir(struct aa_fs_entry *fs_dir,
895 struct dentry *parent)
63e2b423 896{
9acd494b 897 struct aa_fs_entry *fs_file;
0d259f04
JJ
898 struct dentry *dir;
899 int error;
63e2b423 900
0d259f04
JJ
901 dir = securityfs_create_dir(fs_dir->name, parent);
902 if (IS_ERR(dir))
903 return PTR_ERR(dir);
904 fs_dir->dentry = dir;
63e2b423 905
0d259f04 906 for (fs_file = fs_dir->v.files; fs_file && fs_file->name; ++fs_file) {
9acd494b
KC
907 if (fs_file->v_type == AA_FS_TYPE_DIR)
908 error = aafs_create_dir(fs_file, fs_dir->dentry);
909 else
910 error = aafs_create_file(fs_file, fs_dir->dentry);
911 if (error)
912 goto failed;
913 }
914
915 return 0;
916
917failed:
0d259f04
JJ
918 aafs_remove_dir(fs_dir);
919
9acd494b
KC
920 return error;
921}
922
923/**
924 * aafs_remove_file - drop a single file entry in the apparmor securityfs
925 * @fs_file: aa_fs_entry to detach from the securityfs (NOT NULL)
926 */
927static void __init aafs_remove_file(struct aa_fs_entry *fs_file)
928{
929 if (!fs_file->dentry)
930 return;
931
932 securityfs_remove(fs_file->dentry);
933 fs_file->dentry = NULL;
934}
935
936/**
937 * aafs_remove_dir - recursively drop a directory entry from the securityfs
938 * @fs_dir: aa_fs_entry (and all child entries) to detach (NOT NULL)
939 */
940static void __init aafs_remove_dir(struct aa_fs_entry *fs_dir)
941{
942 struct aa_fs_entry *fs_file;
943
0d259f04 944 for (fs_file = fs_dir->v.files; fs_file && fs_file->name; ++fs_file) {
9acd494b
KC
945 if (fs_file->v_type == AA_FS_TYPE_DIR)
946 aafs_remove_dir(fs_file);
947 else
948 aafs_remove_file(fs_file);
949 }
950
951 aafs_remove_file(fs_dir);
63e2b423
JJ
952}
953
954/**
955 * aa_destroy_aafs - cleanup and free aafs
956 *
957 * releases dentries allocated by aa_create_aafs
958 */
959void __init aa_destroy_aafs(void)
960{
9acd494b 961 aafs_remove_dir(&aa_fs_entry);
63e2b423
JJ
962}
963
a71ada30
JJ
964
965#define NULL_FILE_NAME ".null"
966struct path aa_null;
967
968static int aa_mk_null_file(struct dentry *parent)
969{
970 struct vfsmount *mount = NULL;
971 struct dentry *dentry;
972 struct inode *inode;
973 int count = 0;
974 int error = simple_pin_fs(parent->d_sb->s_type, &mount, &count);
975
976 if (error)
977 return error;
978
979 inode_lock(d_inode(parent));
980 dentry = lookup_one_len(NULL_FILE_NAME, parent, strlen(NULL_FILE_NAME));
981 if (IS_ERR(dentry)) {
982 error = PTR_ERR(dentry);
983 goto out;
984 }
985 inode = new_inode(parent->d_inode->i_sb);
986 if (!inode) {
987 error = -ENOMEM;
988 goto out1;
989 }
990
991 inode->i_ino = get_next_ino();
992 inode->i_mode = S_IFCHR | S_IRUGO | S_IWUGO;
993 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
994 init_special_inode(inode, S_IFCHR | S_IRUGO | S_IWUGO,
995 MKDEV(MEM_MAJOR, 3));
996 d_instantiate(dentry, inode);
997 aa_null.dentry = dget(dentry);
998 aa_null.mnt = mntget(mount);
999
1000 error = 0;
1001
1002out1:
1003 dput(dentry);
1004out:
1005 inode_unlock(d_inode(parent));
1006 simple_release_fs(&mount, &count);
1007 return error;
1008}
1009
63e2b423
JJ
1010/**
1011 * aa_create_aafs - create the apparmor security filesystem
1012 *
1013 * dentries created here are released by aa_destroy_aafs
1014 *
1015 * Returns: error on failure
1016 */
3417d8d5 1017static int __init aa_create_aafs(void)
63e2b423
JJ
1018{
1019 int error;
1020
1021 if (!apparmor_initialized)
1022 return 0;
1023
9acd494b 1024 if (aa_fs_entry.dentry) {
63e2b423
JJ
1025 AA_ERROR("%s: AppArmor securityfs already exists\n", __func__);
1026 return -EEXIST;
1027 }
1028
9acd494b
KC
1029 /* Populate fs tree. */
1030 error = aafs_create_dir(&aa_fs_entry, NULL);
63e2b423
JJ
1031 if (error)
1032 goto error;
1033
98849dff 1034 error = __aa_fs_ns_mkdir(root_ns, aa_fs_entry.dentry, "policy");
0d259f04
JJ
1035 if (error)
1036 goto error;
1037
a71ada30
JJ
1038 error = aa_mk_null_file(aa_fs_entry.dentry);
1039 if (error)
1040 goto error;
1041
1042 /* TODO: add default profile to apparmorfs */
63e2b423
JJ
1043
1044 /* Report that AppArmor fs is enabled */
1045 aa_info_message("AppArmor Filesystem Enabled");
1046 return 0;
1047
1048error:
1049 aa_destroy_aafs();
1050 AA_ERROR("Error creating AppArmor securityfs\n");
1051 return error;
1052}
1053
1054fs_initcall(aa_create_aafs);