aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-09-07 17:34:07 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-09-07 17:34:07 -0400
commit11c7b03d42a847db90862d0f9d8be6ce9b2f0553 (patch)
tree9c1d9e95c8ae09b4ee44821a9e570247d5a85a72 /security
parent6be48f2940af9ea8d93c23a0dd8e322672c92efd (diff)
parent73203361468894c3c017bfbdd9ddcbb468039604 (diff)
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull security subsystem updates from James Morris: "Nothing major for this kernel, just maintenance updates" * 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (21 commits) apparmor: add the ability to report a sha1 hash of loaded policy apparmor: export set of capabilities supported by the apparmor module apparmor: add the profile introspection file to interface apparmor: add an optional profile attachment string for profiles apparmor: add interface files for profiles and namespaces apparmor: allow setting any profile into the unconfined state apparmor: make free_profile available outside of policy.c apparmor: rework namespace free path apparmor: update how unconfined is handled apparmor: change how profile replacement update is done apparmor: convert profile lists to RCU based locking apparmor: provide base for multiple profiles to be replaced at once apparmor: add a features/policy dir to interface apparmor: enable users to query whether apparmor is enabled apparmor: remove minimum size check for vmalloc() Smack: parse multiple rules per write to load2, up to PAGE_SIZE-1 bytes Smack: network label match fix security: smack: add a hash table to quicken smk_find_entry() security: smack: fix memleak in smk_write_rules_list() xattr: Constify ->name member of "struct xattr". ...
Diffstat (limited to 'security')
-rw-r--r--security/apparmor/Kconfig12
-rw-r--r--security/apparmor/Makefile7
-rw-r--r--security/apparmor/apparmorfs.c636
-rw-r--r--security/apparmor/capability.c5
-rw-r--r--security/apparmor/context.c16
-rw-r--r--security/apparmor/crypto.c97
-rw-r--r--security/apparmor/domain.c24
-rw-r--r--security/apparmor/include/apparmor.h6
-rw-r--r--security/apparmor/include/apparmorfs.h40
-rw-r--r--security/apparmor/include/audit.h1
-rw-r--r--security/apparmor/include/capability.h4
-rw-r--r--security/apparmor/include/context.h15
-rw-r--r--security/apparmor/include/crypto.h36
-rw-r--r--security/apparmor/include/policy.h218
-rw-r--r--security/apparmor/include/policy_unpack.h21
-rw-r--r--security/apparmor/lib.c5
-rw-r--r--security/apparmor/lsm.c22
-rw-r--r--security/apparmor/policy.c609
-rw-r--r--security/apparmor/policy_unpack.c135
-rw-r--r--security/apparmor/procattr.c2
-rw-r--r--security/capability.c2
-rw-r--r--security/integrity/evm/evm_main.c2
-rw-r--r--security/security.c8
-rw-r--r--security/selinux/hooks.c17
-rw-r--r--security/smack/smack.h13
-rw-r--r--security/smack/smack_access.c29
-rw-r--r--security/smack/smack_lsm.c51
-rw-r--r--security/smack/smackfs.c180
28 files changed, 1666 insertions, 547 deletions
diff --git a/security/apparmor/Kconfig b/security/apparmor/Kconfig
index 9b9013b2e321..d49c53960b60 100644
--- a/security/apparmor/Kconfig
+++ b/security/apparmor/Kconfig
@@ -29,3 +29,15 @@ config SECURITY_APPARMOR_BOOTPARAM_VALUE
29 boot. 29 boot.
30 30
31 If you are unsure how to answer this question, answer 1. 31 If you are unsure how to answer this question, answer 1.
32
33config SECURITY_APPARMOR_HASH
34 bool "SHA1 hash of loaded profiles"
35 depends on SECURITY_APPARMOR
36 depends on CRYPTO
37 select CRYPTO_SHA1
38 default y
39
40 help
41 This option selects whether sha1 hashing is done against loaded
42 profiles and exported for inspection to user space via the apparmor
43 filesystem.
diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile
index 5706b74c857f..d693df874818 100644
--- a/security/apparmor/Makefile
+++ b/security/apparmor/Makefile
@@ -5,6 +5,7 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
5apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \ 5apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \
6 path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \ 6 path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \
7 resource.o sid.o file.o 7 resource.o sid.o file.o
8apparmor-$(CONFIG_SECURITY_APPARMOR_HASH) += crypto.o
8 9
9clean-files := capability_names.h rlim_names.h 10clean-files := capability_names.h rlim_names.h
10 11
@@ -18,7 +19,11 @@ quiet_cmd_make-caps = GEN $@
18cmd_make-caps = echo "static const char *const capability_names[] = {" > $@ ;\ 19cmd_make-caps = echo "static const char *const capability_names[] = {" > $@ ;\
19 sed $< >>$@ -r -n -e '/CAP_FS_MASK/d' \ 20 sed $< >>$@ -r -n -e '/CAP_FS_MASK/d' \
20 -e 's/^\#define[ \t]+CAP_([A-Z0-9_]+)[ \t]+([0-9]+)/[\2] = "\L\1",/p';\ 21 -e 's/^\#define[ \t]+CAP_([A-Z0-9_]+)[ \t]+([0-9]+)/[\2] = "\L\1",/p';\
21 echo "};" >> $@ 22 echo "};" >> $@ ;\
23 echo -n '\#define AA_FS_CAPS_MASK "' >> $@ ;\
24 sed $< -r -n -e '/CAP_FS_MASK/d' \
25 -e 's/^\#define[ \t]+CAP_([A-Z0-9_]+)[ \t]+([0-9]+)/\L\1/p' | \
26 tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@
22 27
23 28
24# Build a lower case string table of rlimit names. 29# Build a lower case string table of rlimit names.
diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
index 16c15ec6f670..95c2b2689a03 100644
--- a/security/apparmor/apparmorfs.c
+++ b/security/apparmor/apparmorfs.c
@@ -12,6 +12,7 @@
12 * License. 12 * License.
13 */ 13 */
14 14
15#include <linux/ctype.h>
15#include <linux/security.h> 16#include <linux/security.h>
16#include <linux/vmalloc.h> 17#include <linux/vmalloc.h>
17#include <linux/module.h> 18#include <linux/module.h>
@@ -19,15 +20,56 @@
19#include <linux/uaccess.h> 20#include <linux/uaccess.h>
20#include <linux/namei.h> 21#include <linux/namei.h>
21#include <linux/capability.h> 22#include <linux/capability.h>
23#include <linux/rcupdate.h>
22 24
23#include "include/apparmor.h" 25#include "include/apparmor.h"
24#include "include/apparmorfs.h" 26#include "include/apparmorfs.h"
25#include "include/audit.h" 27#include "include/audit.h"
26#include "include/context.h" 28#include "include/context.h"
29#include "include/crypto.h"
27#include "include/policy.h" 30#include "include/policy.h"
28#include "include/resource.h" 31#include "include/resource.h"
29 32
30/** 33/**
34 * aa_mangle_name - mangle a profile name to std profile layout form
35 * @name: profile name to mangle (NOT NULL)
36 * @target: buffer to store mangled name, same length as @name (MAYBE NULL)
37 *
38 * Returns: length of mangled name
39 */
40static int mangle_name(char *name, char *target)
41{
42 char *t = target;
43
44 while (*name == '/' || *name == '.')
45 name++;
46
47 if (target) {
48 for (; *name; name++) {
49 if (*name == '/')
50 *(t)++ = '.';
51 else if (isspace(*name))
52 *(t)++ = '_';
53 else if (isalnum(*name) || strchr("._-", *name))
54 *(t)++ = *name;
55 }
56
57 *t = 0;
58 } else {
59 int len = 0;
60 for (; *name; name++) {
61 if (isalnum(*name) || isspace(*name) ||
62 strchr("/._-", *name))
63 len++;
64 }
65
66 return len;
67 }
68
69 return t - target;
70}
71
72/**
31 * aa_simple_write_to_buffer - common routine for getting policy from user 73 * aa_simple_write_to_buffer - common routine for getting policy from user
32 * @op: operation doing the user buffer copy 74 * @op: operation doing the user buffer copy
33 * @userbuf: user buffer to copy data from (NOT NULL) 75 * @userbuf: user buffer to copy data from (NOT NULL)
@@ -182,8 +224,567 @@ const struct file_operations aa_fs_seq_file_ops = {
182 .release = single_release, 224 .release = single_release,
183}; 225};
184 226
185/** Base file system setup **/ 227static int aa_fs_seq_profile_open(struct inode *inode, struct file *file,
228 int (*show)(struct seq_file *, void *))
229{
230 struct aa_replacedby *r = aa_get_replacedby(inode->i_private);
231 int error = single_open(file, show, r);
232
233 if (error) {
234 file->private_data = NULL;
235 aa_put_replacedby(r);
236 }
237
238 return error;
239}
240
241static int aa_fs_seq_profile_release(struct inode *inode, struct file *file)
242{
243 struct seq_file *seq = (struct seq_file *) file->private_data;
244 if (seq)
245 aa_put_replacedby(seq->private);
246 return single_release(inode, file);
247}
248
249static int aa_fs_seq_profname_show(struct seq_file *seq, void *v)
250{
251 struct aa_replacedby *r = seq->private;
252 struct aa_profile *profile = aa_get_profile_rcu(&r->profile);
253 seq_printf(seq, "%s\n", profile->base.name);
254 aa_put_profile(profile);
255
256 return 0;
257}
258
259static int aa_fs_seq_profname_open(struct inode *inode, struct file *file)
260{
261 return aa_fs_seq_profile_open(inode, file, aa_fs_seq_profname_show);
262}
263
264static const struct file_operations aa_fs_profname_fops = {
265 .owner = THIS_MODULE,
266 .open = aa_fs_seq_profname_open,
267 .read = seq_read,
268 .llseek = seq_lseek,
269 .release = aa_fs_seq_profile_release,
270};
271
272static int aa_fs_seq_profmode_show(struct seq_file *seq, void *v)
273{
274 struct aa_replacedby *r = seq->private;
275 struct aa_profile *profile = aa_get_profile_rcu(&r->profile);
276 seq_printf(seq, "%s\n", aa_profile_mode_names[profile->mode]);
277 aa_put_profile(profile);
278
279 return 0;
280}
281
282static int aa_fs_seq_profmode_open(struct inode *inode, struct file *file)
283{
284 return aa_fs_seq_profile_open(inode, file, aa_fs_seq_profmode_show);
285}
286
287static const struct file_operations aa_fs_profmode_fops = {
288 .owner = THIS_MODULE,
289 .open = aa_fs_seq_profmode_open,
290 .read = seq_read,
291 .llseek = seq_lseek,
292 .release = aa_fs_seq_profile_release,
293};
294
295static int aa_fs_seq_profattach_show(struct seq_file *seq, void *v)
296{
297 struct aa_replacedby *r = seq->private;
298 struct aa_profile *profile = aa_get_profile_rcu(&r->profile);
299 if (profile->attach)
300 seq_printf(seq, "%s\n", profile->attach);
301 else if (profile->xmatch)
302 seq_puts(seq, "<unknown>\n");
303 else
304 seq_printf(seq, "%s\n", profile->base.name);
305 aa_put_profile(profile);
306
307 return 0;
308}
309
310static int aa_fs_seq_profattach_open(struct inode *inode, struct file *file)
311{
312 return aa_fs_seq_profile_open(inode, file, aa_fs_seq_profattach_show);
313}
314
315static const struct file_operations aa_fs_profattach_fops = {
316 .owner = THIS_MODULE,
317 .open = aa_fs_seq_profattach_open,
318 .read = seq_read,
319 .llseek = seq_lseek,
320 .release = aa_fs_seq_profile_release,
321};
322
323static int aa_fs_seq_hash_show(struct seq_file *seq, void *v)
324{
325 struct aa_replacedby *r = seq->private;
326 struct aa_profile *profile = aa_get_profile_rcu(&r->profile);
327 unsigned int i, size = aa_hash_size();
328
329 if (profile->hash) {
330 for (i = 0; i < size; i++)
331 seq_printf(seq, "%.2x", profile->hash[i]);
332 seq_puts(seq, "\n");
333 }
334
335 return 0;
336}
337
338static int aa_fs_seq_hash_open(struct inode *inode, struct file *file)
339{
340 return single_open(file, aa_fs_seq_hash_show, inode->i_private);
341}
342
343static const struct file_operations aa_fs_seq_hash_fops = {
344 .owner = THIS_MODULE,
345 .open = aa_fs_seq_hash_open,
346 .read = seq_read,
347 .llseek = seq_lseek,
348 .release = single_release,
349};
350
351/** fns to setup dynamic per profile/namespace files **/
352void __aa_fs_profile_rmdir(struct aa_profile *profile)
353{
354 struct aa_profile *child;
355 int i;
356
357 if (!profile)
358 return;
359
360 list_for_each_entry(child, &profile->base.profiles, base.list)
361 __aa_fs_profile_rmdir(child);
362
363 for (i = AAFS_PROF_SIZEOF - 1; i >= 0; --i) {
364 struct aa_replacedby *r;
365 if (!profile->dents[i])
366 continue;
367
368 r = profile->dents[i]->d_inode->i_private;
369 securityfs_remove(profile->dents[i]);
370 aa_put_replacedby(r);
371 profile->dents[i] = NULL;
372 }
373}
374
375void __aa_fs_profile_migrate_dents(struct aa_profile *old,
376 struct aa_profile *new)
377{
378 int i;
379
380 for (i = 0; i < AAFS_PROF_SIZEOF; i++) {
381 new->dents[i] = old->dents[i];
382 old->dents[i] = NULL;
383 }
384}
385
386static struct dentry *create_profile_file(struct dentry *dir, const char *name,
387 struct aa_profile *profile,
388 const struct file_operations *fops)
389{
390 struct aa_replacedby *r = aa_get_replacedby(profile->replacedby);
391 struct dentry *dent;
392
393 dent = securityfs_create_file(name, S_IFREG | 0444, dir, r, fops);
394 if (IS_ERR(dent))
395 aa_put_replacedby(r);
396
397 return dent;
398}
399
400/* requires lock be held */
401int __aa_fs_profile_mkdir(struct aa_profile *profile, struct dentry *parent)
402{
403 struct aa_profile *child;
404 struct dentry *dent = NULL, *dir;
405 int error;
406
407 if (!parent) {
408 struct aa_profile *p;
409 p = aa_deref_parent(profile);
410 dent = prof_dir(p);
411 /* adding to parent that previously didn't have children */
412 dent = securityfs_create_dir("profiles", dent);
413 if (IS_ERR(dent))
414 goto fail;
415 prof_child_dir(p) = parent = dent;
416 }
417
418 if (!profile->dirname) {
419 int len, id_len;
420 len = mangle_name(profile->base.name, NULL);
421 id_len = snprintf(NULL, 0, ".%ld", profile->ns->uniq_id);
422
423 profile->dirname = kmalloc(len + id_len + 1, GFP_KERNEL);
424 if (!profile->dirname)
425 goto fail;
426
427 mangle_name(profile->base.name, profile->dirname);
428 sprintf(profile->dirname + len, ".%ld", profile->ns->uniq_id++);
429 }
430
431 dent = securityfs_create_dir(profile->dirname, parent);
432 if (IS_ERR(dent))
433 goto fail;
434 prof_dir(profile) = dir = dent;
435
436 dent = create_profile_file(dir, "name", profile, &aa_fs_profname_fops);
437 if (IS_ERR(dent))
438 goto fail;
439 profile->dents[AAFS_PROF_NAME] = dent;
440
441 dent = create_profile_file(dir, "mode", profile, &aa_fs_profmode_fops);
442 if (IS_ERR(dent))
443 goto fail;
444 profile->dents[AAFS_PROF_MODE] = dent;
445
446 dent = create_profile_file(dir, "attach", profile,
447 &aa_fs_profattach_fops);
448 if (IS_ERR(dent))
449 goto fail;
450 profile->dents[AAFS_PROF_ATTACH] = dent;
451
452 if (profile->hash) {
453 dent = create_profile_file(dir, "sha1", profile,
454 &aa_fs_seq_hash_fops);
455 if (IS_ERR(dent))
456 goto fail;
457 profile->dents[AAFS_PROF_HASH] = dent;
458 }
459
460 list_for_each_entry(child, &profile->base.profiles, base.list) {
461 error = __aa_fs_profile_mkdir(child, prof_child_dir(profile));
462 if (error)
463 goto fail2;
464 }
465
466 return 0;
467
468fail:
469 error = PTR_ERR(dent);
470
471fail2:
472 __aa_fs_profile_rmdir(profile);
473
474 return error;
475}
476
477void __aa_fs_namespace_rmdir(struct aa_namespace *ns)
478{
479 struct aa_namespace *sub;
480 struct aa_profile *child;
481 int i;
482
483 if (!ns)
484 return;
485
486 list_for_each_entry(child, &ns->base.profiles, base.list)
487 __aa_fs_profile_rmdir(child);
488
489 list_for_each_entry(sub, &ns->sub_ns, base.list) {
490 mutex_lock(&sub->lock);
491 __aa_fs_namespace_rmdir(sub);
492 mutex_unlock(&sub->lock);
493 }
186 494
495 for (i = AAFS_NS_SIZEOF - 1; i >= 0; --i) {
496 securityfs_remove(ns->dents[i]);
497 ns->dents[i] = NULL;
498 }
499}
500
501int __aa_fs_namespace_mkdir(struct aa_namespace *ns, struct dentry *parent,
502 const char *name)
503{
504 struct aa_namespace *sub;
505 struct aa_profile *child;
506 struct dentry *dent, *dir;
507 int error;
508
509 if (!name)
510 name = ns->base.name;
511
512 dent = securityfs_create_dir(name, parent);
513 if (IS_ERR(dent))
514 goto fail;
515 ns_dir(ns) = dir = dent;
516
517 dent = securityfs_create_dir("profiles", dir);
518 if (IS_ERR(dent))
519 goto fail;
520 ns_subprofs_dir(ns) = dent;
521
522 dent = securityfs_create_dir("namespaces", dir);
523 if (IS_ERR(dent))
524 goto fail;
525 ns_subns_dir(ns) = dent;
526
527 list_for_each_entry(child, &ns->base.profiles, base.list) {
528 error = __aa_fs_profile_mkdir(child, ns_subprofs_dir(ns));
529 if (error)
530 goto fail2;
531 }
532
533 list_for_each_entry(sub, &ns->sub_ns, base.list) {
534 mutex_lock(&sub->lock);
535 error = __aa_fs_namespace_mkdir(sub, ns_subns_dir(ns), NULL);
536 mutex_unlock(&sub->lock);
537 if (error)
538 goto fail2;
539 }
540
541 return 0;
542
543fail:
544 error = PTR_ERR(dent);
545
546fail2:
547 __aa_fs_namespace_rmdir(ns);
548
549 return error;
550}
551
552
553#define list_entry_next(pos, member) \
554 list_entry(pos->member.next, typeof(*pos), member)
555#define list_entry_is_head(pos, head, member) (&pos->member == (head))
556
557/**
558 * __next_namespace - find the next namespace to list
559 * @root: root namespace to stop search at (NOT NULL)
560 * @ns: current ns position (NOT NULL)
561 *
562 * Find the next namespace from @ns under @root and handle all locking needed
563 * while switching current namespace.
564 *
565 * Returns: next namespace or NULL if at last namespace under @root
566 * Requires: ns->parent->lock to be held
567 * NOTE: will not unlock root->lock
568 */
569static struct aa_namespace *__next_namespace(struct aa_namespace *root,
570 struct aa_namespace *ns)
571{
572 struct aa_namespace *parent, *next;
573
574 /* is next namespace a child */
575 if (!list_empty(&ns->sub_ns)) {
576 next = list_first_entry(&ns->sub_ns, typeof(*ns), base.list);
577 mutex_lock(&next->lock);
578 return next;
579 }
580
581 /* check if the next ns is a sibling, parent, gp, .. */
582 parent = ns->parent;
583 while (parent) {
584 mutex_unlock(&ns->lock);
585 next = list_entry_next(ns, base.list);
586 if (!list_entry_is_head(next, &parent->sub_ns, base.list)) {
587 mutex_lock(&next->lock);
588 return next;
589 }
590 if (parent == root)
591 return NULL;
592 ns = parent;
593 parent = parent->parent;
594 }
595
596 return NULL;
597}
598
599/**
600 * __first_profile - find the first profile in a namespace
601 * @root: namespace that is root of profiles being displayed (NOT NULL)
602 * @ns: namespace to start in (NOT NULL)
603 *
604 * Returns: unrefcounted profile or NULL if no profile
605 * Requires: profile->ns.lock to be held
606 */
607static struct aa_profile *__first_profile(struct aa_namespace *root,
608 struct aa_namespace *ns)
609{
610 for (; ns; ns = __next_namespace(root, ns)) {
611 if (!list_empty(&ns->base.profiles))
612 return list_first_entry(&ns->base.profiles,
613 struct aa_profile, base.list);
614 }
615 return NULL;
616}
617
618/**
619 * __next_profile - step to the next profile in a profile tree
620 * @profile: current profile in tree (NOT NULL)
621 *
622 * Perform a depth first traversal on the profile tree in a namespace
623 *
624 * Returns: next profile or NULL if done
625 * Requires: profile->ns.lock to be held
626 */
627static struct aa_profile *__next_profile(struct aa_profile *p)
628{
629 struct aa_profile *parent;
630 struct aa_namespace *ns = p->ns;
631
632 /* is next profile a child */
633 if (!list_empty(&p->base.profiles))
634 return list_first_entry(&p->base.profiles, typeof(*p),
635 base.list);
636
637 /* is next profile a sibling, parent sibling, gp, sibling, .. */
638 parent = rcu_dereference_protected(p->parent,
639 mutex_is_locked(&p->ns->lock));
640 while (parent) {
641 p = list_entry_next(p, base.list);
642 if (!list_entry_is_head(p, &parent->base.profiles, base.list))
643 return p;
644 p = parent;
645 parent = rcu_dereference_protected(parent->parent,
646 mutex_is_locked(&parent->ns->lock));
647 }
648
649 /* is next another profile in the namespace */
650 p = list_entry_next(p, base.list);
651 if (!list_entry_is_head(p, &ns->base.profiles, base.list))
652 return p;
653
654 return NULL;
655}
656
657/**
658 * next_profile - step to the next profile in where ever it may be
659 * @root: root namespace (NOT NULL)
660 * @profile: current profile (NOT NULL)
661 *
662 * Returns: next profile or NULL if there isn't one
663 */
664static struct aa_profile *next_profile(struct aa_namespace *root,
665 struct aa_profile *profile)
666{
667 struct aa_profile *next = __next_profile(profile);
668 if (next)
669 return next;
670
671 /* finished all profiles in namespace move to next namespace */
672 return __first_profile(root, __next_namespace(root, profile->ns));
673}
674
675/**
676 * p_start - start a depth first traversal of profile tree
677 * @f: seq_file to fill
678 * @pos: current position
679 *
680 * Returns: first profile under current namespace or NULL if none found
681 *
682 * acquires first ns->lock
683 */
684static void *p_start(struct seq_file *f, loff_t *pos)
685{
686 struct aa_profile *profile = NULL;
687 struct aa_namespace *root = aa_current_profile()->ns;
688 loff_t l = *pos;
689 f->private = aa_get_namespace(root);
690
691
692 /* find the first profile */
693 mutex_lock(&root->lock);
694 profile = __first_profile(root, root);
695
696 /* skip to position */
697 for (; profile && l > 0; l--)
698 profile = next_profile(root, profile);
699
700 return profile;
701}
702
703/**
704 * p_next - read the next profile entry
705 * @f: seq_file to fill
706 * @p: profile previously returned
707 * @pos: current position
708 *
709 * Returns: next profile after @p or NULL if none
710 *
711 * may acquire/release locks in namespace tree as necessary
712 */
713static void *p_next(struct seq_file *f, void *p, loff_t *pos)
714{
715 struct aa_profile *profile = p;
716 struct aa_namespace *ns = f->private;
717 (*pos)++;
718
719 return next_profile(ns, profile);
720}
721
722/**
723 * p_stop - stop depth first traversal
724 * @f: seq_file we are filling
725 * @p: the last profile writen
726 *
727 * Release all locking done by p_start/p_next on namespace tree
728 */
729static void p_stop(struct seq_file *f, void *p)
730{
731 struct aa_profile *profile = p;
732 struct aa_namespace *root = f->private, *ns;
733
734 if (profile) {
735 for (ns = profile->ns; ns && ns != root; ns = ns->parent)
736 mutex_unlock(&ns->lock);
737 }
738 mutex_unlock(&root->lock);
739 aa_put_namespace(root);
740}
741
742/**
743 * seq_show_profile - show a profile entry
744 * @f: seq_file to file
745 * @p: current position (profile) (NOT NULL)
746 *
747 * Returns: error on failure
748 */
749static int seq_show_profile(struct seq_file *f, void *p)
750{
751 struct aa_profile *profile = (struct aa_profile *)p;
752 struct aa_namespace *root = f->private;
753
754 if (profile->ns != root)
755 seq_printf(f, ":%s://", aa_ns_name(root, profile->ns));
756 seq_printf(f, "%s (%s)\n", profile->base.hname,
757 aa_profile_mode_names[profile->mode]);
758
759 return 0;
760}
761
762static const struct seq_operations aa_fs_profiles_op = {
763 .start = p_start,
764 .next = p_next,
765 .stop = p_stop,
766 .show = seq_show_profile,
767};
768
769static int profiles_open(struct inode *inode, struct file *file)
770{
771 return seq_open(file, &aa_fs_profiles_op);
772}
773
774static int profiles_release(struct inode *inode, struct file *file)
775{
776 return seq_release(inode, file);
777}
778
779static const struct file_operations aa_fs_profiles_fops = {
780 .open = profiles_open,
781 .read = seq_read,
782 .llseek = seq_lseek,
783 .release = profiles_release,
784};
785
786
787/** Base file system setup **/
187static struct aa_fs_entry aa_fs_entry_file[] = { 788static struct aa_fs_entry aa_fs_entry_file[] = {
188 AA_FS_FILE_STRING("mask", "create read write exec append mmap_exec " \ 789 AA_FS_FILE_STRING("mask", "create read write exec append mmap_exec " \
189 "link lock"), 790 "link lock"),
@@ -198,11 +799,18 @@ static struct aa_fs_entry aa_fs_entry_domain[] = {
198 { } 799 { }
199}; 800};
200 801
802static struct aa_fs_entry aa_fs_entry_policy[] = {
803 AA_FS_FILE_BOOLEAN("set_load", 1),
804 {}
805};
806
201static struct aa_fs_entry aa_fs_entry_features[] = { 807static struct aa_fs_entry aa_fs_entry_features[] = {
808 AA_FS_DIR("policy", aa_fs_entry_policy),
202 AA_FS_DIR("domain", aa_fs_entry_domain), 809 AA_FS_DIR("domain", aa_fs_entry_domain),
203 AA_FS_DIR("file", aa_fs_entry_file), 810 AA_FS_DIR("file", aa_fs_entry_file),
204 AA_FS_FILE_U64("capability", VFS_CAP_FLAGS_MASK), 811 AA_FS_FILE_U64("capability", VFS_CAP_FLAGS_MASK),
205 AA_FS_DIR("rlimit", aa_fs_entry_rlimit), 812 AA_FS_DIR("rlimit", aa_fs_entry_rlimit),
813 AA_FS_DIR("caps", aa_fs_entry_caps),
206 { } 814 { }
207}; 815};
208 816
@@ -210,6 +818,7 @@ static struct aa_fs_entry aa_fs_entry_apparmor[] = {
210 AA_FS_FILE_FOPS(".load", 0640, &aa_fs_profile_load), 818 AA_FS_FILE_FOPS(".load", 0640, &aa_fs_profile_load),
211 AA_FS_FILE_FOPS(".replace", 0640, &aa_fs_profile_replace), 819 AA_FS_FILE_FOPS(".replace", 0640, &aa_fs_profile_replace),
212 AA_FS_FILE_FOPS(".remove", 0640, &aa_fs_profile_remove), 820 AA_FS_FILE_FOPS(".remove", 0640, &aa_fs_profile_remove),
821 AA_FS_FILE_FOPS("profiles", 0640, &aa_fs_profiles_fops),
213 AA_FS_DIR("features", aa_fs_entry_features), 822 AA_FS_DIR("features", aa_fs_entry_features),
214 { } 823 { }
215}; 824};
@@ -240,6 +849,7 @@ static int __init aafs_create_file(struct aa_fs_entry *fs_file,
240 return error; 849 return error;
241} 850}
242 851
852static void __init aafs_remove_dir(struct aa_fs_entry *fs_dir);
243/** 853/**
244 * aafs_create_dir - recursively create a directory entry in the securityfs 854 * aafs_create_dir - recursively create a directory entry in the securityfs
245 * @fs_dir: aa_fs_entry (and all child entries) to build (NOT NULL) 855 * @fs_dir: aa_fs_entry (and all child entries) to build (NOT NULL)
@@ -250,17 +860,16 @@ static int __init aafs_create_file(struct aa_fs_entry *fs_file,
250static int __init aafs_create_dir(struct aa_fs_entry *fs_dir, 860static int __init aafs_create_dir(struct aa_fs_entry *fs_dir,
251 struct dentry *parent) 861 struct dentry *parent)
252{ 862{
253 int error;
254 struct aa_fs_entry *fs_file; 863 struct aa_fs_entry *fs_file;
864 struct dentry *dir;
865 int error;
255 866
256 fs_dir->dentry = securityfs_create_dir(fs_dir->name, parent); 867 dir = securityfs_create_dir(fs_dir->name, parent);
257 if (IS_ERR(fs_dir->dentry)) { 868 if (IS_ERR(dir))
258 error = PTR_ERR(fs_dir->dentry); 869 return PTR_ERR(dir);
259 fs_dir->dentry = NULL; 870 fs_dir->dentry = dir;
260 goto failed;
261 }
262 871
263 for (fs_file = fs_dir->v.files; fs_file->name; ++fs_file) { 872 for (fs_file = fs_dir->v.files; fs_file && fs_file->name; ++fs_file) {
264 if (fs_file->v_type == AA_FS_TYPE_DIR) 873 if (fs_file->v_type == AA_FS_TYPE_DIR)
265 error = aafs_create_dir(fs_file, fs_dir->dentry); 874 error = aafs_create_dir(fs_file, fs_dir->dentry);
266 else 875 else
@@ -272,6 +881,8 @@ static int __init aafs_create_dir(struct aa_fs_entry *fs_dir,
272 return 0; 881 return 0;
273 882
274failed: 883failed:
884 aafs_remove_dir(fs_dir);
885
275 return error; 886 return error;
276} 887}
277 888
@@ -296,7 +907,7 @@ static void __init aafs_remove_dir(struct aa_fs_entry *fs_dir)
296{ 907{
297 struct aa_fs_entry *fs_file; 908 struct aa_fs_entry *fs_file;
298 909
299 for (fs_file = fs_dir->v.files; fs_file->name; ++fs_file) { 910 for (fs_file = fs_dir->v.files; fs_file && fs_file->name; ++fs_file) {
300 if (fs_file->v_type == AA_FS_TYPE_DIR) 911 if (fs_file->v_type == AA_FS_TYPE_DIR)
301 aafs_remove_dir(fs_file); 912 aafs_remove_dir(fs_file);
302 else 913 else
@@ -340,6 +951,11 @@ static int __init aa_create_aafs(void)
340 if (error) 951 if (error)
341 goto error; 952 goto error;
342 953
954 error = __aa_fs_namespace_mkdir(root_ns, aa_fs_entry.dentry,
955 "policy");
956 if (error)
957 goto error;
958
343 /* TODO: add support for apparmorfs_null and apparmorfs_mnt */ 959 /* TODO: add support for apparmorfs_null and apparmorfs_mnt */
344 960
345 /* Report that AppArmor fs is enabled */ 961 /* Report that AppArmor fs is enabled */
diff --git a/security/apparmor/capability.c b/security/apparmor/capability.c
index 887a5e948945..84d1f5f53877 100644
--- a/security/apparmor/capability.c
+++ b/security/apparmor/capability.c
@@ -27,6 +27,11 @@
27 */ 27 */
28#include "capability_names.h" 28#include "capability_names.h"
29 29
30struct aa_fs_entry aa_fs_entry_caps[] = {
31 AA_FS_FILE_STRING("mask", AA_FS_CAPS_MASK),
32 { }
33};
34
30struct audit_cache { 35struct audit_cache {
31 struct aa_profile *profile; 36 struct aa_profile *profile;
32 kernel_cap_t caps; 37 kernel_cap_t caps;
diff --git a/security/apparmor/context.c b/security/apparmor/context.c
index d5af1d15f26d..3064c6ced87c 100644
--- a/security/apparmor/context.c
+++ b/security/apparmor/context.c
@@ -112,9 +112,9 @@ int aa_replace_current_profile(struct aa_profile *profile)
112 aa_clear_task_cxt_trans(cxt); 112 aa_clear_task_cxt_trans(cxt);
113 113
114 /* be careful switching cxt->profile, when racing replacement it 114 /* be careful switching cxt->profile, when racing replacement it
115 * is possible that cxt->profile->replacedby is the reference keeping 115 * is possible that cxt->profile->replacedby->profile is the reference
116 * @profile valid, so make sure to get its reference before dropping 116 * keeping @profile valid, so make sure to get its reference before
117 * the reference on cxt->profile */ 117 * dropping the reference on cxt->profile */
118 aa_get_profile(profile); 118 aa_get_profile(profile);
119 aa_put_profile(cxt->profile); 119 aa_put_profile(cxt->profile);
120 cxt->profile = profile; 120 cxt->profile = profile;
@@ -175,7 +175,7 @@ int aa_set_current_hat(struct aa_profile *profile, u64 token)
175 abort_creds(new); 175 abort_creds(new);
176 return -EACCES; 176 return -EACCES;
177 } 177 }
178 cxt->profile = aa_get_profile(aa_newest_version(profile)); 178 cxt->profile = aa_get_newest_profile(profile);
179 /* clear exec on switching context */ 179 /* clear exec on switching context */
180 aa_put_profile(cxt->onexec); 180 aa_put_profile(cxt->onexec);
181 cxt->onexec = NULL; 181 cxt->onexec = NULL;
@@ -212,14 +212,8 @@ int aa_restore_previous_profile(u64 token)
212 } 212 }
213 213
214 aa_put_profile(cxt->profile); 214 aa_put_profile(cxt->profile);
215 cxt->profile = aa_newest_version(cxt->previous); 215 cxt->profile = aa_get_newest_profile(cxt->previous);
216 BUG_ON(!cxt->profile); 216 BUG_ON(!cxt->profile);
217 if (unlikely(cxt->profile != cxt->previous)) {
218 aa_get_profile(cxt->profile);
219 aa_put_profile(cxt->previous);
220 }
221 /* ref has been transfered so avoid putting ref in clear_task_cxt */
222 cxt->previous = NULL;
223 /* clear exec && prev information when restoring to previous context */ 217 /* clear exec && prev information when restoring to previous context */
224 aa_clear_task_cxt_trans(cxt); 218 aa_clear_task_cxt_trans(cxt);
225 219
diff --git a/security/apparmor/crypto.c b/security/apparmor/crypto.c
new file mode 100644
index 000000000000..d6222ba4e919
--- /dev/null
+++ b/security/apparmor/crypto.c
@@ -0,0 +1,97 @@
1/*
2 * AppArmor security module
3 *
4 * This file contains AppArmor policy loading interface function definitions.
5 *
6 * Copyright 2013 Canonical Ltd.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation, version 2 of the
11 * License.
12 *
13 * Fns to provide a checksum of policy that has been loaded this can be
14 * compared to userspace policy compiles to check loaded policy is what
15 * it should be.
16 */
17
18#include <linux/crypto.h>
19
20#include "include/apparmor.h"
21#include "include/crypto.h"
22
23static unsigned int apparmor_hash_size;
24
25static struct crypto_hash *apparmor_tfm;
26
27unsigned int aa_hash_size(void)
28{
29 return apparmor_hash_size;
30}
31
32int aa_calc_profile_hash(struct aa_profile *profile, u32 version, void *start,
33 size_t len)
34{
35 struct scatterlist sg[2];
36 struct hash_desc desc = {
37 .tfm = apparmor_tfm,
38 .flags = 0
39 };
40 int error = -ENOMEM;
41 u32 le32_version = cpu_to_le32(version);
42
43 if (!apparmor_tfm)
44 return 0;
45
46 sg_init_table(sg, 2);
47 sg_set_buf(&sg[0], &le32_version, 4);
48 sg_set_buf(&sg[1], (u8 *) start, len);
49
50 profile->hash = kzalloc(apparmor_hash_size, GFP_KERNEL);
51 if (!profile->hash)
52 goto fail;
53
54 error = crypto_hash_init(&desc);
55 if (error)
56 goto fail;
57 error = crypto_hash_update(&desc, &sg[0], 4);
58 if (error)
59 goto fail;
60 error = crypto_hash_update(&desc, &sg[1], len);
61 if (error)
62 goto fail;
63 error = crypto_hash_final(&desc, profile->hash);
64 if (error)
65 goto fail;
66
67 return 0;
68
69fail:
70 kfree(profile->hash);
71 profile->hash = NULL;
72
73 return error;
74}
75
76static int __init init_profile_hash(void)
77{
78 struct crypto_hash *tfm;
79
80 if (!apparmor_initialized)
81 return 0;
82
83 tfm = crypto_alloc_hash("sha1", 0, CRYPTO_ALG_ASYNC);
84 if (IS_ERR(tfm)) {
85 int error = PTR_ERR(tfm);
86 AA_ERROR("failed to setup profile sha1 hashing: %d\n", error);
87 return error;
88 }
89 apparmor_tfm = tfm;
90 apparmor_hash_size = crypto_hash_digestsize(apparmor_tfm);
91
92 aa_info_message("AppArmor sha1 policy hashing enabled");
93
94 return 0;
95}
96
97late_initcall(init_profile_hash);
diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c
index 01b7bd669a88..26c607c971f5 100644
--- a/security/apparmor/domain.c
+++ b/security/apparmor/domain.c
@@ -144,7 +144,7 @@ static struct aa_profile *__attach_match(const char *name,
144 int len = 0; 144 int len = 0;
145 struct aa_profile *profile, *candidate = NULL; 145 struct aa_profile *profile, *candidate = NULL;
146 146
147 list_for_each_entry(profile, head, base.list) { 147 list_for_each_entry_rcu(profile, head, base.list) {
148 if (profile->flags & PFLAG_NULL) 148 if (profile->flags & PFLAG_NULL)
149 continue; 149 continue;
150 if (profile->xmatch && profile->xmatch_len > len) { 150 if (profile->xmatch && profile->xmatch_len > len) {
@@ -177,9 +177,9 @@ static struct aa_profile *find_attach(struct aa_namespace *ns,
177{ 177{
178 struct aa_profile *profile; 178 struct aa_profile *profile;
179 179
180 read_lock(&ns->lock); 180 rcu_read_lock();
181 profile = aa_get_profile(__attach_match(name, list)); 181 profile = aa_get_profile(__attach_match(name, list));
182 read_unlock(&ns->lock); 182 rcu_read_unlock();
183 183
184 return profile; 184 return profile;
185} 185}
@@ -359,7 +359,7 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
359 cxt = cred_cxt(bprm->cred); 359 cxt = cred_cxt(bprm->cred);
360 BUG_ON(!cxt); 360 BUG_ON(!cxt);
361 361
362 profile = aa_get_profile(aa_newest_version(cxt->profile)); 362 profile = aa_get_newest_profile(cxt->profile);
363 /* 363 /*
364 * get the namespace from the replacement profile as replacement 364 * get the namespace from the replacement profile as replacement
365 * can change the namespace 365 * can change the namespace
@@ -371,8 +371,8 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
371 error = aa_path_name(&bprm->file->f_path, profile->path_flags, &buffer, 371 error = aa_path_name(&bprm->file->f_path, profile->path_flags, &buffer,
372 &name, &info); 372 &name, &info);
373 if (error) { 373 if (error) {
374 if (profile->flags & 374 if (unconfined(profile) ||
375 (PFLAG_IX_ON_NAME_ERROR | PFLAG_UNCONFINED)) 375 (profile->flags & PFLAG_IX_ON_NAME_ERROR))
376 error = 0; 376 error = 0;
377 name = bprm->filename; 377 name = bprm->filename;
378 goto audit; 378 goto audit;
@@ -417,7 +417,7 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
417 417
418 if (!(cp.allow & AA_MAY_ONEXEC)) 418 if (!(cp.allow & AA_MAY_ONEXEC))
419 goto audit; 419 goto audit;
420 new_profile = aa_get_profile(aa_newest_version(cxt->onexec)); 420 new_profile = aa_get_newest_profile(cxt->onexec);
421 goto apply; 421 goto apply;
422 } 422 }
423 423
@@ -434,7 +434,7 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
434 new_profile = aa_get_profile(profile); 434 new_profile = aa_get_profile(profile);
435 goto x_clear; 435 goto x_clear;
436 } else if (perms.xindex & AA_X_UNCONFINED) { 436 } else if (perms.xindex & AA_X_UNCONFINED) {
437 new_profile = aa_get_profile(ns->unconfined); 437 new_profile = aa_get_newest_profile(ns->unconfined);
438 info = "ux fallback"; 438 info = "ux fallback";
439 } else { 439 } else {
440 error = -ENOENT; 440 error = -ENOENT;
@@ -641,7 +641,10 @@ int aa_change_hat(const char *hats[], int count, u64 token, bool permtest)
641 if (count) { 641 if (count) {
642 /* attempting to change into a new hat or switch to a sibling */ 642 /* attempting to change into a new hat or switch to a sibling */
643 struct aa_profile *root; 643 struct aa_profile *root;
644 root = PROFILE_IS_HAT(profile) ? profile->parent : profile; 644 if (PROFILE_IS_HAT(profile))
645 root = aa_get_profile_rcu(&profile->parent);
646 else
647 root = aa_get_profile(profile);
645 648
646 /* find first matching hat */ 649 /* find first matching hat */
647 for (i = 0; i < count && !hat; i++) 650 for (i = 0; i < count && !hat; i++)
@@ -653,6 +656,7 @@ int aa_change_hat(const char *hats[], int count, u64 token, bool permtest)
653 error = -ECHILD; 656 error = -ECHILD;
654 else 657 else
655 error = -ENOENT; 658 error = -ENOENT;
659 aa_put_profile(root);
656 goto out; 660 goto out;
657 } 661 }
658 662
@@ -667,6 +671,7 @@ int aa_change_hat(const char *hats[], int count, u64 token, bool permtest)
667 671
668 /* freed below */ 672 /* freed below */
669 name = new_compound_name(root->base.hname, hats[0]); 673 name = new_compound_name(root->base.hname, hats[0]);
674 aa_put_profile(root);
670 target = name; 675 target = name;
671 /* released below */ 676 /* released below */
672 hat = aa_new_null_profile(profile, 1); 677 hat = aa_new_null_profile(profile, 1);
@@ -676,6 +681,7 @@ int aa_change_hat(const char *hats[], int count, u64 token, bool permtest)
676 goto audit; 681 goto audit;
677 } 682 }
678 } else { 683 } else {
684 aa_put_profile(root);
679 target = hat->base.hname; 685 target = hat->base.hname;
680 if (!PROFILE_IS_HAT(hat)) { 686 if (!PROFILE_IS_HAT(hat)) {
681 info = "target not hat"; 687 info = "target not hat";
diff --git a/security/apparmor/include/apparmor.h b/security/apparmor/include/apparmor.h
index 1ba2ca56a6ef..8fb1488a3cd4 100644
--- a/security/apparmor/include/apparmor.h
+++ b/security/apparmor/include/apparmor.h
@@ -78,6 +78,12 @@ static inline void *kvzalloc(size_t size)
78 return __aa_kvmalloc(size, __GFP_ZERO); 78 return __aa_kvmalloc(size, __GFP_ZERO);
79} 79}
80 80
81/* returns 0 if kref not incremented */
82static inline int kref_get_not0(struct kref *kref)
83{
84 return atomic_inc_not_zero(&kref->refcount);
85}
86
81/** 87/**
82 * aa_strneq - compare null terminated @str to a non null terminated substring 88 * aa_strneq - compare null terminated @str to a non null terminated substring
83 * @str: a null terminated string 89 * @str: a null terminated string
diff --git a/security/apparmor/include/apparmorfs.h b/security/apparmor/include/apparmorfs.h
index 7ea4769fab3f..414e56878dd0 100644
--- a/security/apparmor/include/apparmorfs.h
+++ b/security/apparmor/include/apparmorfs.h
@@ -61,4 +61,44 @@ extern const struct file_operations aa_fs_seq_file_ops;
61 61
62extern void __init aa_destroy_aafs(void); 62extern void __init aa_destroy_aafs(void);
63 63
64struct aa_profile;
65struct aa_namespace;
66
67enum aafs_ns_type {
68 AAFS_NS_DIR,
69 AAFS_NS_PROFS,
70 AAFS_NS_NS,
71 AAFS_NS_COUNT,
72 AAFS_NS_MAX_COUNT,
73 AAFS_NS_SIZE,
74 AAFS_NS_MAX_SIZE,
75 AAFS_NS_OWNER,
76 AAFS_NS_SIZEOF,
77};
78
79enum aafs_prof_type {
80 AAFS_PROF_DIR,
81 AAFS_PROF_PROFS,
82 AAFS_PROF_NAME,
83 AAFS_PROF_MODE,
84 AAFS_PROF_ATTACH,
85 AAFS_PROF_HASH,
86 AAFS_PROF_SIZEOF,
87};
88
89#define ns_dir(X) ((X)->dents[AAFS_NS_DIR])
90#define ns_subns_dir(X) ((X)->dents[AAFS_NS_NS])
91#define ns_subprofs_dir(X) ((X)->dents[AAFS_NS_PROFS])
92
93#define prof_dir(X) ((X)->dents[AAFS_PROF_DIR])
94#define prof_child_dir(X) ((X)->dents[AAFS_PROF_PROFS])
95
96void __aa_fs_profile_rmdir(struct aa_profile *profile);
97void __aa_fs_profile_migrate_dents(struct aa_profile *old,
98 struct aa_profile *new);
99int __aa_fs_profile_mkdir(struct aa_profile *profile, struct dentry *parent);
100void __aa_fs_namespace_rmdir(struct aa_namespace *ns);
101int __aa_fs_namespace_mkdir(struct aa_namespace *ns, struct dentry *parent,
102 const char *name);
103
64#endif /* __AA_APPARMORFS_H */ 104#endif /* __AA_APPARMORFS_H */
diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h
index 69d8cae634e7..30e8d7687259 100644
--- a/security/apparmor/include/audit.h
+++ b/security/apparmor/include/audit.h
@@ -27,7 +27,6 @@ struct aa_profile;
27 27
28extern const char *const audit_mode_names[]; 28extern const char *const audit_mode_names[];
29#define AUDIT_MAX_INDEX 5 29#define AUDIT_MAX_INDEX 5
30
31enum audit_mode { 30enum audit_mode {
32 AUDIT_NORMAL, /* follow normal auditing of accesses */ 31 AUDIT_NORMAL, /* follow normal auditing of accesses */
33 AUDIT_QUIET_DENIED, /* quiet all denied access messages */ 32 AUDIT_QUIET_DENIED, /* quiet all denied access messages */
diff --git a/security/apparmor/include/capability.h b/security/apparmor/include/capability.h
index c24d2959ea02..2e7c9d6a2f3b 100644
--- a/security/apparmor/include/capability.h
+++ b/security/apparmor/include/capability.h
@@ -17,6 +17,8 @@
17 17
18#include <linux/sched.h> 18#include <linux/sched.h>
19 19
20#include "apparmorfs.h"
21
20struct aa_profile; 22struct aa_profile;
21 23
22/* aa_caps - confinement data for capabilities 24/* aa_caps - confinement data for capabilities
@@ -34,6 +36,8 @@ struct aa_caps {
34 kernel_cap_t extended; 36 kernel_cap_t extended;
35}; 37};
36 38
39extern struct aa_fs_entry aa_fs_entry_caps[];
40
37int aa_capable(struct task_struct *task, struct aa_profile *profile, int cap, 41int aa_capable(struct task_struct *task, struct aa_profile *profile, int cap,
38 int audit); 42 int audit);
39 43
diff --git a/security/apparmor/include/context.h b/security/apparmor/include/context.h
index d44ba5802e3d..6bf65798e5d1 100644
--- a/security/apparmor/include/context.h
+++ b/security/apparmor/include/context.h
@@ -98,7 +98,7 @@ static inline struct aa_profile *aa_cred_profile(const struct cred *cred)
98{ 98{
99 struct aa_task_cxt *cxt = cred_cxt(cred); 99 struct aa_task_cxt *cxt = cred_cxt(cred);
100 BUG_ON(!cxt || !cxt->profile); 100 BUG_ON(!cxt || !cxt->profile);
101 return aa_newest_version(cxt->profile); 101 return cxt->profile;
102} 102}
103 103
104/** 104/**
@@ -152,15 +152,14 @@ static inline struct aa_profile *aa_current_profile(void)
152 struct aa_profile *profile; 152 struct aa_profile *profile;
153 BUG_ON(!cxt || !cxt->profile); 153 BUG_ON(!cxt || !cxt->profile);
154 154
155 profile = aa_newest_version(cxt->profile); 155 if (PROFILE_INVALID(cxt->profile)) {
156 /* 156 profile = aa_get_newest_profile(cxt->profile);
157 * Whether or not replacement succeeds, use newest profile so
158 * there is no need to update it after replacement.
159 */
160 if (unlikely((cxt->profile != profile)))
161 aa_replace_current_profile(profile); 157 aa_replace_current_profile(profile);
158 aa_put_profile(profile);
159 cxt = current_cxt();
160 }
162 161
163 return profile; 162 return cxt->profile;
164} 163}
165 164
166/** 165/**
diff --git a/security/apparmor/include/crypto.h b/security/apparmor/include/crypto.h
new file mode 100644
index 000000000000..dc418e5024d9
--- /dev/null
+++ b/security/apparmor/include/crypto.h
@@ -0,0 +1,36 @@
1/*
2 * AppArmor security module
3 *
4 * This file contains AppArmor policy loading interface function definitions.
5 *
6 * Copyright 2013 Canonical Ltd.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation, version 2 of the
11 * License.
12 */
13
14#ifndef __APPARMOR_CRYPTO_H
15#define __APPARMOR_CRYPTO_H
16
17#include "policy.h"
18
19#ifdef CONFIG_SECURITY_APPARMOR_HASH
20unsigned int aa_hash_size(void);
21int aa_calc_profile_hash(struct aa_profile *profile, u32 version, void *start,
22 size_t len);
23#else
24static inline int aa_calc_profile_hash(struct aa_profile *profile, u32 version,
25 void *start, size_t len)
26{
27 return 0;
28}
29
30static inline unsigned int aa_hash_size(void)
31{
32 return 0;
33}
34#endif
35
36#endif /* __APPARMOR_CRYPTO_H */
diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h
index b25491a3046a..f2d4b6348cbc 100644
--- a/security/apparmor/include/policy.h
+++ b/security/apparmor/include/policy.h
@@ -29,8 +29,8 @@
29#include "file.h" 29#include "file.h"
30#include "resource.h" 30#include "resource.h"
31 31
32extern const char *const profile_mode_names[]; 32extern const char *const aa_profile_mode_names[];
33#define APPARMOR_NAMES_MAX_INDEX 3 33#define APPARMOR_MODE_NAMES_MAX_INDEX 4
34 34
35#define PROFILE_MODE(_profile, _mode) \ 35#define PROFILE_MODE(_profile, _mode) \
36 ((aa_g_profile_mode == (_mode)) || \ 36 ((aa_g_profile_mode == (_mode)) || \
@@ -42,6 +42,10 @@ extern const char *const profile_mode_names[];
42 42
43#define PROFILE_IS_HAT(_profile) ((_profile)->flags & PFLAG_HAT) 43#define PROFILE_IS_HAT(_profile) ((_profile)->flags & PFLAG_HAT)
44 44
45#define PROFILE_INVALID(_profile) ((_profile)->flags & PFLAG_INVALID)
46
47#define on_list_rcu(X) (!list_empty(X) && (X)->prev != LIST_POISON2)
48
45/* 49/*
46 * FIXME: currently need a clean way to replace and remove profiles as a 50 * FIXME: currently need a clean way to replace and remove profiles as a
47 * set. It should be done at the namespace level. 51 * set. It should be done at the namespace level.
@@ -52,17 +56,19 @@ enum profile_mode {
52 APPARMOR_ENFORCE, /* enforce access rules */ 56 APPARMOR_ENFORCE, /* enforce access rules */
53 APPARMOR_COMPLAIN, /* allow and log access violations */ 57 APPARMOR_COMPLAIN, /* allow and log access violations */
54 APPARMOR_KILL, /* kill task on access violation */ 58 APPARMOR_KILL, /* kill task on access violation */
59 APPARMOR_UNCONFINED, /* profile set to unconfined */
55}; 60};
56 61
57enum profile_flags { 62enum profile_flags {
58 PFLAG_HAT = 1, /* profile is a hat */ 63 PFLAG_HAT = 1, /* profile is a hat */
59 PFLAG_UNCONFINED = 2, /* profile is an unconfined profile */
60 PFLAG_NULL = 4, /* profile is null learning profile */ 64 PFLAG_NULL = 4, /* profile is null learning profile */
61 PFLAG_IX_ON_NAME_ERROR = 8, /* fallback to ix on name lookup fail */ 65 PFLAG_IX_ON_NAME_ERROR = 8, /* fallback to ix on name lookup fail */
62 PFLAG_IMMUTABLE = 0x10, /* don't allow changes/replacement */ 66 PFLAG_IMMUTABLE = 0x10, /* don't allow changes/replacement */
63 PFLAG_USER_DEFINED = 0x20, /* user based profile - lower privs */ 67 PFLAG_USER_DEFINED = 0x20, /* user based profile - lower privs */
64 PFLAG_NO_LIST_REF = 0x40, /* list doesn't keep profile ref */ 68 PFLAG_NO_LIST_REF = 0x40, /* list doesn't keep profile ref */
65 PFLAG_OLD_NULL_TRANS = 0x100, /* use // as the null transition */ 69 PFLAG_OLD_NULL_TRANS = 0x100, /* use // as the null transition */
70 PFLAG_INVALID = 0x200, /* profile replaced/removed */
71 PFLAG_NS_COUNT = 0x400, /* carries NS ref count */
66 72
67 /* These flags must correspond with PATH_flags */ 73 /* These flags must correspond with PATH_flags */
68 PFLAG_MEDIATE_DELETED = 0x10000, /* mediate instead delegate deleted */ 74 PFLAG_MEDIATE_DELETED = 0x10000, /* mediate instead delegate deleted */
@@ -73,14 +79,12 @@ struct aa_profile;
73/* struct aa_policy - common part of both namespaces and profiles 79/* struct aa_policy - common part of both namespaces and profiles
74 * @name: name of the object 80 * @name: name of the object
75 * @hname - The hierarchical name 81 * @hname - The hierarchical name
76 * @count: reference count of the obj
77 * @list: list policy object is on 82 * @list: list policy object is on
78 * @profiles: head of the profiles list contained in the object 83 * @profiles: head of the profiles list contained in the object
79 */ 84 */
80struct aa_policy { 85struct aa_policy {
81 char *name; 86 char *name;
82 char *hname; 87 char *hname;
83 struct kref count;
84 struct list_head list; 88 struct list_head list;
85 struct list_head profiles; 89 struct list_head profiles;
86}; 90};
@@ -106,6 +110,8 @@ struct aa_ns_acct {
106 * @unconfined: special unconfined profile for the namespace 110 * @unconfined: special unconfined profile for the namespace
107 * @sub_ns: list of namespaces under the current namespace. 111 * @sub_ns: list of namespaces under the current namespace.
108 * @uniq_null: uniq value used for null learning profiles 112 * @uniq_null: uniq value used for null learning profiles
113 * @uniq_id: a unique id count for the profiles in the namespace
114 * @dents: dentries for the namespaces file entries in apparmorfs
109 * 115 *
110 * An aa_namespace defines the set profiles that are searched to determine 116 * An aa_namespace defines the set profiles that are searched to determine
111 * which profile to attach to a task. Profiles can not be shared between 117 * which profile to attach to a task. Profiles can not be shared between
@@ -124,11 +130,14 @@ struct aa_ns_acct {
124struct aa_namespace { 130struct aa_namespace {
125 struct aa_policy base; 131 struct aa_policy base;
126 struct aa_namespace *parent; 132 struct aa_namespace *parent;
127 rwlock_t lock; 133 struct mutex lock;
128 struct aa_ns_acct acct; 134 struct aa_ns_acct acct;
129 struct aa_profile *unconfined; 135 struct aa_profile *unconfined;
130 struct list_head sub_ns; 136 struct list_head sub_ns;
131 atomic_t uniq_null; 137 atomic_t uniq_null;
138 long uniq_id;
139
140 struct dentry *dents[AAFS_NS_SIZEOF];
132}; 141};
133 142
134/* struct aa_policydb - match engine for a policy 143/* struct aa_policydb - match engine for a policy
@@ -142,12 +151,21 @@ struct aa_policydb {
142 151
143}; 152};
144 153
154struct aa_replacedby {
155 struct kref count;
156 struct aa_profile __rcu *profile;
157};
158
159
145/* struct aa_profile - basic confinement data 160/* struct aa_profile - basic confinement data
146 * @base - base components of the profile (name, refcount, lists, lock ...) 161 * @base - base components of the profile (name, refcount, lists, lock ...)
162 * @count: reference count of the obj
163 * @rcu: rcu head used when removing from @list
147 * @parent: parent of profile 164 * @parent: parent of profile
148 * @ns: namespace the profile is in 165 * @ns: namespace the profile is in
149 * @replacedby: is set to the profile that replaced this profile 166 * @replacedby: is set to the profile that replaced this profile
150 * @rename: optional profile name that this profile renamed 167 * @rename: optional profile name that this profile renamed
168 * @attach: human readable attachment string
151 * @xmatch: optional extended matching for unconfined executables names 169 * @xmatch: optional extended matching for unconfined executables names
152 * @xmatch_len: xmatch prefix len, used to determine xmatch priority 170 * @xmatch_len: xmatch prefix len, used to determine xmatch priority
153 * @audit: the auditing mode of the profile 171 * @audit: the auditing mode of the profile
@@ -160,13 +178,15 @@ struct aa_policydb {
160 * @caps: capabilities for the profile 178 * @caps: capabilities for the profile
161 * @rlimits: rlimits for the profile 179 * @rlimits: rlimits for the profile
162 * 180 *
181 * @dents: dentries for the profiles file entries in apparmorfs
182 * @dirname: name of the profile dir in apparmorfs
183 *
163 * The AppArmor profile contains the basic confinement data. Each profile 184 * The AppArmor profile contains the basic confinement data. Each profile
164 * has a name, and exists in a namespace. The @name and @exec_match are 185 * has a name, and exists in a namespace. The @name and @exec_match are
165 * used to determine profile attachment against unconfined tasks. All other 186 * used to determine profile attachment against unconfined tasks. All other
166 * attachments are determined by profile X transition rules. 187 * attachments are determined by profile X transition rules.
167 * 188 *
168 * The @replacedby field is write protected by the profile lock. Reads 189 * The @replacedby struct is write protected by the profile lock.
169 * are assumed to be atomic, and are done without locking.
170 * 190 *
171 * Profiles have a hierarchy where hats and children profiles keep 191 * Profiles have a hierarchy where hats and children profiles keep
172 * a reference to their parent. 192 * a reference to their parent.
@@ -177,17 +197,20 @@ struct aa_policydb {
177 */ 197 */
178struct aa_profile { 198struct aa_profile {
179 struct aa_policy base; 199 struct aa_policy base;
180 struct aa_profile *parent; 200 struct kref count;
201 struct rcu_head rcu;
202 struct aa_profile __rcu *parent;
181 203
182 struct aa_namespace *ns; 204 struct aa_namespace *ns;
183 struct aa_profile *replacedby; 205 struct aa_replacedby *replacedby;
184 const char *rename; 206 const char *rename;
185 207
208 const char *attach;
186 struct aa_dfa *xmatch; 209 struct aa_dfa *xmatch;
187 int xmatch_len; 210 int xmatch_len;
188 enum audit_mode audit; 211 enum audit_mode audit;
189 enum profile_mode mode; 212 long mode;
190 u32 flags; 213 long flags;
191 u32 path_flags; 214 u32 path_flags;
192 int size; 215 int size;
193 216
@@ -195,6 +218,10 @@ struct aa_profile {
195 struct aa_file_rules file; 218 struct aa_file_rules file;
196 struct aa_caps caps; 219 struct aa_caps caps;
197 struct aa_rlimit rlimits; 220 struct aa_rlimit rlimits;
221
222 unsigned char *hash;
223 char *dirname;
224 struct dentry *dents[AAFS_PROF_SIZEOF];
198}; 225};
199 226
200extern struct aa_namespace *root_ns; 227extern struct aa_namespace *root_ns;
@@ -211,43 +238,11 @@ void aa_free_namespace_kref(struct kref *kref);
211struct aa_namespace *aa_find_namespace(struct aa_namespace *root, 238struct aa_namespace *aa_find_namespace(struct aa_namespace *root,
212 const char *name); 239 const char *name);
213 240
214static inline struct aa_policy *aa_get_common(struct aa_policy *c)
215{
216 if (c)
217 kref_get(&c->count);
218
219 return c;
220}
221
222/**
223 * aa_get_namespace - increment references count on @ns
224 * @ns: namespace to increment reference count of (MAYBE NULL)
225 *
226 * Returns: pointer to @ns, if @ns is NULL returns NULL
227 * Requires: @ns must be held with valid refcount when called
228 */
229static inline struct aa_namespace *aa_get_namespace(struct aa_namespace *ns)
230{
231 if (ns)
232 kref_get(&(ns->base.count));
233
234 return ns;
235}
236
237/**
238 * aa_put_namespace - decrement refcount on @ns
239 * @ns: namespace to put reference of
240 *
241 * Decrement reference count of @ns and if no longer in use free it
242 */
243static inline void aa_put_namespace(struct aa_namespace *ns)
244{
245 if (ns)
246 kref_put(&ns->base.count, aa_free_namespace_kref);
247}
248 241
242void aa_free_replacedby_kref(struct kref *kref);
249struct aa_profile *aa_alloc_profile(const char *name); 243struct aa_profile *aa_alloc_profile(const char *name);
250struct aa_profile *aa_new_null_profile(struct aa_profile *parent, int hat); 244struct aa_profile *aa_new_null_profile(struct aa_profile *parent, int hat);
245void aa_free_profile(struct aa_profile *profile);
251void aa_free_profile_kref(struct kref *kref); 246void aa_free_profile_kref(struct kref *kref);
252struct aa_profile *aa_find_child(struct aa_profile *parent, const char *name); 247struct aa_profile *aa_find_child(struct aa_profile *parent, const char *name);
253struct aa_profile *aa_lookup_profile(struct aa_namespace *ns, const char *name); 248struct aa_profile *aa_lookup_profile(struct aa_namespace *ns, const char *name);
@@ -259,25 +254,13 @@ ssize_t aa_remove_profiles(char *name, size_t size);
259#define PROF_ADD 1 254#define PROF_ADD 1
260#define PROF_REPLACE 0 255#define PROF_REPLACE 0
261 256
262#define unconfined(X) ((X)->flags & PFLAG_UNCONFINED) 257#define unconfined(X) ((X)->mode == APPARMOR_UNCONFINED)
263 258
264/**
265 * aa_newest_version - find the newest version of @profile
266 * @profile: the profile to check for newer versions of (NOT NULL)
267 *
268 * Returns: newest version of @profile, if @profile is the newest version
269 * return @profile.
270 *
271 * NOTE: the profile returned is not refcounted, The refcount on @profile
272 * must be held until the caller decides what to do with the returned newest
273 * version.
274 */
275static inline struct aa_profile *aa_newest_version(struct aa_profile *profile)
276{
277 while (profile->replacedby)
278 profile = profile->replacedby;
279 259
280 return profile; 260static inline struct aa_profile *aa_deref_parent(struct aa_profile *p)
261{
262 return rcu_dereference_protected(p->parent,
263 mutex_is_locked(&p->ns->lock));
281} 264}
282 265
283/** 266/**
@@ -290,19 +273,124 @@ static inline struct aa_profile *aa_newest_version(struct aa_profile *profile)
290static inline struct aa_profile *aa_get_profile(struct aa_profile *p) 273static inline struct aa_profile *aa_get_profile(struct aa_profile *p)
291{ 274{
292 if (p) 275 if (p)
293 kref_get(&(p->base.count)); 276 kref_get(&(p->count));
294 277
295 return p; 278 return p;
296} 279}
297 280
298/** 281/**
282 * aa_get_profile_not0 - increment refcount on profile @p found via lookup
283 * @p: profile (MAYBE NULL)
284 *
285 * Returns: pointer to @p if @p is NULL will return NULL
286 * Requires: @p must be held with valid refcount when called
287 */
288static inline struct aa_profile *aa_get_profile_not0(struct aa_profile *p)
289{
290 if (p && kref_get_not0(&p->count))
291 return p;
292
293 return NULL;
294}
295
296/**
297 * aa_get_profile_rcu - increment a refcount profile that can be replaced
298 * @p: pointer to profile that can be replaced (NOT NULL)
299 *
300 * Returns: pointer to a refcounted profile.
301 * else NULL if no profile
302 */
303static inline struct aa_profile *aa_get_profile_rcu(struct aa_profile __rcu **p)
304{
305 struct aa_profile *c;
306
307 rcu_read_lock();
308 do {
309 c = rcu_dereference(*p);
310 } while (c && !kref_get_not0(&c->count));
311 rcu_read_unlock();
312
313 return c;
314}
315
316/**
317 * aa_get_newest_profile - find the newest version of @profile
318 * @profile: the profile to check for newer versions of
319 *
320 * Returns: refcounted newest version of @profile taking into account
321 * replacement, renames and removals
322 * return @profile.
323 */
324static inline struct aa_profile *aa_get_newest_profile(struct aa_profile *p)
325{
326 if (!p)
327 return NULL;
328
329 if (PROFILE_INVALID(p))
330 return aa_get_profile_rcu(&p->replacedby->profile);
331
332 return aa_get_profile(p);
333}
334
335/**
299 * aa_put_profile - decrement refcount on profile @p 336 * aa_put_profile - decrement refcount on profile @p
300 * @p: profile (MAYBE NULL) 337 * @p: profile (MAYBE NULL)
301 */ 338 */
302static inline void aa_put_profile(struct aa_profile *p) 339static inline void aa_put_profile(struct aa_profile *p)
303{ 340{
304 if (p) 341 if (p)
305 kref_put(&p->base.count, aa_free_profile_kref); 342 kref_put(&p->count, aa_free_profile_kref);
343}
344
345static inline struct aa_replacedby *aa_get_replacedby(struct aa_replacedby *p)
346{
347 if (p)
348 kref_get(&(p->count));
349
350 return p;
351}
352
353static inline void aa_put_replacedby(struct aa_replacedby *p)
354{
355 if (p)
356 kref_put(&p->count, aa_free_replacedby_kref);
357}
358
359/* requires profile list write lock held */
360static inline void __aa_update_replacedby(struct aa_profile *orig,
361 struct aa_profile *new)
362{
363 struct aa_profile *tmp = rcu_dereference(orig->replacedby->profile);
364 rcu_assign_pointer(orig->replacedby->profile, aa_get_profile(new));
365 orig->flags |= PFLAG_INVALID;
366 aa_put_profile(tmp);
367}
368
369/**
370 * aa_get_namespace - increment references count on @ns
371 * @ns: namespace to increment reference count of (MAYBE NULL)
372 *
373 * Returns: pointer to @ns, if @ns is NULL returns NULL
374 * Requires: @ns must be held with valid refcount when called
375 */
376static inline struct aa_namespace *aa_get_namespace(struct aa_namespace *ns)
377{
378 if (ns)
379 aa_get_profile(ns->unconfined);
380
381 return ns;
382}
383
384/**
385 * aa_put_namespace - decrement refcount on @ns
386 * @ns: namespace to put reference of
387 *
388 * Decrement reference count of @ns and if no longer in use free it
389 */
390static inline void aa_put_namespace(struct aa_namespace *ns)
391{
392 if (ns)
393 aa_put_profile(ns->unconfined);
306} 394}
307 395
308static inline int AUDIT_MODE(struct aa_profile *profile) 396static inline int AUDIT_MODE(struct aa_profile *profile)
diff --git a/security/apparmor/include/policy_unpack.h b/security/apparmor/include/policy_unpack.h
index a2dcccac45aa..c214fb88b1bc 100644
--- a/security/apparmor/include/policy_unpack.h
+++ b/security/apparmor/include/policy_unpack.h
@@ -15,6 +15,25 @@
15#ifndef __POLICY_INTERFACE_H 15#ifndef __POLICY_INTERFACE_H
16#define __POLICY_INTERFACE_H 16#define __POLICY_INTERFACE_H
17 17
18struct aa_profile *aa_unpack(void *udata, size_t size, const char **ns); 18#include <linux/list.h>
19
20struct aa_load_ent {
21 struct list_head list;
22 struct aa_profile *new;
23 struct aa_profile *old;
24 struct aa_profile *rename;
25};
26
27void aa_load_ent_free(struct aa_load_ent *ent);
28struct aa_load_ent *aa_load_ent_alloc(void);
29
30#define PACKED_FLAG_HAT 1
31
32#define PACKED_MODE_ENFORCE 0
33#define PACKED_MODE_COMPLAIN 1
34#define PACKED_MODE_KILL 2
35#define PACKED_MODE_UNCONFINED 3
36
37int aa_unpack(void *udata, size_t size, struct list_head *lh, const char **ns);
19 38
20#endif /* __POLICY_INTERFACE_H */ 39#endif /* __POLICY_INTERFACE_H */
diff --git a/security/apparmor/lib.c b/security/apparmor/lib.c
index fcfe0233574c..69689922c491 100644
--- a/security/apparmor/lib.c
+++ b/security/apparmor/lib.c
@@ -97,11 +97,6 @@ void *__aa_kvmalloc(size_t size, gfp_t flags)
97 if (size <= (16*PAGE_SIZE)) 97 if (size <= (16*PAGE_SIZE))
98 buffer = kmalloc(size, flags | GFP_NOIO | __GFP_NOWARN); 98 buffer = kmalloc(size, flags | GFP_NOIO | __GFP_NOWARN);
99 if (!buffer) { 99 if (!buffer) {
100 /* see kvfree for why size must be at least work_struct size
101 * when allocated via vmalloc
102 */
103 if (size < sizeof(struct work_struct))
104 size = sizeof(struct work_struct);
105 if (flags & __GFP_ZERO) 100 if (flags & __GFP_ZERO)
106 buffer = vzalloc(size); 101 buffer = vzalloc(size);
107 else 102 else
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index e3a704c75ef6..fb99e18123b4 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -508,19 +508,21 @@ static int apparmor_getprocattr(struct task_struct *task, char *name,
508 /* released below */ 508 /* released below */
509 const struct cred *cred = get_task_cred(task); 509 const struct cred *cred = get_task_cred(task);
510 struct aa_task_cxt *cxt = cred_cxt(cred); 510 struct aa_task_cxt *cxt = cred_cxt(cred);
511 struct aa_profile *profile = NULL;
511 512
512 if (strcmp(name, "current") == 0) 513 if (strcmp(name, "current") == 0)
513 error = aa_getprocattr(aa_newest_version(cxt->profile), 514 profile = aa_get_newest_profile(cxt->profile);
514 value);
515 else if (strcmp(name, "prev") == 0 && cxt->previous) 515 else if (strcmp(name, "prev") == 0 && cxt->previous)
516 error = aa_getprocattr(aa_newest_version(cxt->previous), 516 profile = aa_get_newest_profile(cxt->previous);
517 value);
518 else if (strcmp(name, "exec") == 0 && cxt->onexec) 517 else if (strcmp(name, "exec") == 0 && cxt->onexec)
519 error = aa_getprocattr(aa_newest_version(cxt->onexec), 518 profile = aa_get_newest_profile(cxt->onexec);
520 value);
521 else 519 else
522 error = -EINVAL; 520 error = -EINVAL;
523 521
522 if (profile)
523 error = aa_getprocattr(profile, value);
524
525 aa_put_profile(profile);
524 put_cred(cred); 526 put_cred(cred);
525 527
526 return error; 528 return error;
@@ -744,7 +746,7 @@ module_param_named(paranoid_load, aa_g_paranoid_load, aabool,
744 746
745/* Boot time disable flag */ 747/* Boot time disable flag */
746static bool apparmor_enabled = CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE; 748static bool apparmor_enabled = CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE;
747module_param_named(enabled, apparmor_enabled, aabool, S_IRUSR); 749module_param_named(enabled, apparmor_enabled, bool, S_IRUGO);
748 750
749static int __init apparmor_enabled_setup(char *str) 751static int __init apparmor_enabled_setup(char *str)
750{ 752{
@@ -843,7 +845,7 @@ static int param_get_mode(char *buffer, struct kernel_param *kp)
843 if (!apparmor_enabled) 845 if (!apparmor_enabled)
844 return -EINVAL; 846 return -EINVAL;
845 847
846 return sprintf(buffer, "%s", profile_mode_names[aa_g_profile_mode]); 848 return sprintf(buffer, "%s", aa_profile_mode_names[aa_g_profile_mode]);
847} 849}
848 850
849static int param_set_mode(const char *val, struct kernel_param *kp) 851static int param_set_mode(const char *val, struct kernel_param *kp)
@@ -858,8 +860,8 @@ static int param_set_mode(const char *val, struct kernel_param *kp)
858 if (!val) 860 if (!val)
859 return -EINVAL; 861 return -EINVAL;
860 862
861 for (i = 0; i < APPARMOR_NAMES_MAX_INDEX; i++) { 863 for (i = 0; i < APPARMOR_MODE_NAMES_MAX_INDEX; i++) {
862 if (strcmp(val, profile_mode_names[i]) == 0) { 864 if (strcmp(val, aa_profile_mode_names[i]) == 0) {
863 aa_g_profile_mode = i; 865 aa_g_profile_mode = i;
864 return 0; 866 return 0;
865 } 867 }
diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
index 0f345c4dee5f..6172509fa2b7 100644
--- a/security/apparmor/policy.c
+++ b/security/apparmor/policy.c
@@ -92,10 +92,11 @@
92/* root profile namespace */ 92/* root profile namespace */
93struct aa_namespace *root_ns; 93struct aa_namespace *root_ns;
94 94
95const char *const profile_mode_names[] = { 95const char *const aa_profile_mode_names[] = {
96 "enforce", 96 "enforce",
97 "complain", 97 "complain",
98 "kill", 98 "kill",
99 "unconfined",
99}; 100};
100 101
101/** 102/**
@@ -141,7 +142,6 @@ static bool policy_init(struct aa_policy *policy, const char *prefix,
141 policy->name = (char *)hname_tail(policy->hname); 142 policy->name = (char *)hname_tail(policy->hname);
142 INIT_LIST_HEAD(&policy->list); 143 INIT_LIST_HEAD(&policy->list);
143 INIT_LIST_HEAD(&policy->profiles); 144 INIT_LIST_HEAD(&policy->profiles);
144 kref_init(&policy->count);
145 145
146 return 1; 146 return 1;
147} 147}
@@ -153,13 +153,13 @@ static bool policy_init(struct aa_policy *policy, const char *prefix,
153static void policy_destroy(struct aa_policy *policy) 153static void policy_destroy(struct aa_policy *policy)
154{ 154{
155 /* still contains profiles -- invalid */ 155 /* still contains profiles -- invalid */
156 if (!list_empty(&policy->profiles)) { 156 if (on_list_rcu(&policy->profiles)) {
157 AA_ERROR("%s: internal error, " 157 AA_ERROR("%s: internal error, "
158 "policy '%s' still contains profiles\n", 158 "policy '%s' still contains profiles\n",
159 __func__, policy->name); 159 __func__, policy->name);
160 BUG(); 160 BUG();
161 } 161 }
162 if (!list_empty(&policy->list)) { 162 if (on_list_rcu(&policy->list)) {
163 AA_ERROR("%s: internal error, policy '%s' still on list\n", 163 AA_ERROR("%s: internal error, policy '%s' still on list\n",
164 __func__, policy->name); 164 __func__, policy->name);
165 BUG(); 165 BUG();
@@ -174,7 +174,7 @@ static void policy_destroy(struct aa_policy *policy)
174 * @head: list to search (NOT NULL) 174 * @head: list to search (NOT NULL)
175 * @name: name to search for (NOT NULL) 175 * @name: name to search for (NOT NULL)
176 * 176 *
177 * Requires: correct locks for the @head list be held 177 * Requires: rcu_read_lock be held
178 * 178 *
179 * Returns: unrefcounted policy that match @name or NULL if not found 179 * Returns: unrefcounted policy that match @name or NULL if not found
180 */ 180 */
@@ -182,7 +182,7 @@ static struct aa_policy *__policy_find(struct list_head *head, const char *name)
182{ 182{
183 struct aa_policy *policy; 183 struct aa_policy *policy;
184 184
185 list_for_each_entry(policy, head, list) { 185 list_for_each_entry_rcu(policy, head, list) {
186 if (!strcmp(policy->name, name)) 186 if (!strcmp(policy->name, name))
187 return policy; 187 return policy;
188 } 188 }
@@ -195,7 +195,7 @@ static struct aa_policy *__policy_find(struct list_head *head, const char *name)
195 * @str: string to search for (NOT NULL) 195 * @str: string to search for (NOT NULL)
196 * @len: length of match required 196 * @len: length of match required
197 * 197 *
198 * Requires: correct locks for the @head list be held 198 * Requires: rcu_read_lock be held
199 * 199 *
200 * Returns: unrefcounted policy that match @str or NULL if not found 200 * Returns: unrefcounted policy that match @str or NULL if not found
201 * 201 *
@@ -207,7 +207,7 @@ static struct aa_policy *__policy_strn_find(struct list_head *head,
207{ 207{
208 struct aa_policy *policy; 208 struct aa_policy *policy;
209 209
210 list_for_each_entry(policy, head, list) { 210 list_for_each_entry_rcu(policy, head, list) {
211 if (aa_strneq(policy->name, str, len)) 211 if (aa_strneq(policy->name, str, len))
212 return policy; 212 return policy;
213 } 213 }
@@ -284,22 +284,19 @@ static struct aa_namespace *alloc_namespace(const char *prefix,
284 goto fail_ns; 284 goto fail_ns;
285 285
286 INIT_LIST_HEAD(&ns->sub_ns); 286 INIT_LIST_HEAD(&ns->sub_ns);
287 rwlock_init(&ns->lock); 287 mutex_init(&ns->lock);
288 288
289 /* released by free_namespace */ 289 /* released by free_namespace */
290 ns->unconfined = aa_alloc_profile("unconfined"); 290 ns->unconfined = aa_alloc_profile("unconfined");
291 if (!ns->unconfined) 291 if (!ns->unconfined)
292 goto fail_unconfined; 292 goto fail_unconfined;
293 293
294 ns->unconfined->flags = PFLAG_UNCONFINED | PFLAG_IX_ON_NAME_ERROR | 294 ns->unconfined->flags = PFLAG_IX_ON_NAME_ERROR |
295 PFLAG_IMMUTABLE; 295 PFLAG_IMMUTABLE | PFLAG_NS_COUNT;
296 ns->unconfined->mode = APPARMOR_UNCONFINED;
296 297
297 /* 298 /* ns and ns->unconfined share ns->unconfined refcount */
298 * released by free_namespace, however __remove_namespace breaks 299 ns->unconfined->ns = ns;
299 * the cyclic references (ns->unconfined, and unconfined->ns) and
300 * replaces with refs to parent namespace unconfined
301 */
302 ns->unconfined->ns = aa_get_namespace(ns);
303 300
304 atomic_set(&ns->uniq_null, 0); 301 atomic_set(&ns->uniq_null, 0);
305 302
@@ -327,30 +324,19 @@ static void free_namespace(struct aa_namespace *ns)
327 policy_destroy(&ns->base); 324 policy_destroy(&ns->base);
328 aa_put_namespace(ns->parent); 325 aa_put_namespace(ns->parent);
329 326
330 if (ns->unconfined && ns->unconfined->ns == ns) 327 ns->unconfined->ns = NULL;
331 ns->unconfined->ns = NULL; 328 aa_free_profile(ns->unconfined);
332
333 aa_put_profile(ns->unconfined);
334 kzfree(ns); 329 kzfree(ns);
335} 330}
336 331
337/** 332/**
338 * aa_free_namespace_kref - free aa_namespace by kref (see aa_put_namespace)
339 * @kr: kref callback for freeing of a namespace (NOT NULL)
340 */
341void aa_free_namespace_kref(struct kref *kref)
342{
343 free_namespace(container_of(kref, struct aa_namespace, base.count));
344}
345
346/**
347 * __aa_find_namespace - find a namespace on a list by @name 333 * __aa_find_namespace - find a namespace on a list by @name
348 * @head: list to search for namespace on (NOT NULL) 334 * @head: list to search for namespace on (NOT NULL)
349 * @name: name of namespace to look for (NOT NULL) 335 * @name: name of namespace to look for (NOT NULL)
350 * 336 *
351 * Returns: unrefcounted namespace 337 * Returns: unrefcounted namespace
352 * 338 *
353 * Requires: ns lock be held 339 * Requires: rcu_read_lock be held
354 */ 340 */
355static struct aa_namespace *__aa_find_namespace(struct list_head *head, 341static struct aa_namespace *__aa_find_namespace(struct list_head *head,
356 const char *name) 342 const char *name)
@@ -373,9 +359,9 @@ struct aa_namespace *aa_find_namespace(struct aa_namespace *root,
373{ 359{
374 struct aa_namespace *ns = NULL; 360 struct aa_namespace *ns = NULL;
375 361
376 read_lock(&root->lock); 362 rcu_read_lock();
377 ns = aa_get_namespace(__aa_find_namespace(&root->sub_ns, name)); 363 ns = aa_get_namespace(__aa_find_namespace(&root->sub_ns, name));
378 read_unlock(&root->lock); 364 rcu_read_unlock();
379 365
380 return ns; 366 return ns;
381} 367}
@@ -392,7 +378,7 @@ static struct aa_namespace *aa_prepare_namespace(const char *name)
392 378
393 root = aa_current_profile()->ns; 379 root = aa_current_profile()->ns;
394 380
395 write_lock(&root->lock); 381 mutex_lock(&root->lock);
396 382
397 /* if name isn't specified the profile is loaded to the current ns */ 383 /* if name isn't specified the profile is loaded to the current ns */
398 if (!name) { 384 if (!name) {
@@ -405,31 +391,23 @@ static struct aa_namespace *aa_prepare_namespace(const char *name)
405 /* released by caller */ 391 /* released by caller */
406 ns = aa_get_namespace(__aa_find_namespace(&root->sub_ns, name)); 392 ns = aa_get_namespace(__aa_find_namespace(&root->sub_ns, name));
407 if (!ns) { 393 if (!ns) {
408 /* namespace not found */ 394 ns = alloc_namespace(root->base.hname, name);
409 struct aa_namespace *new_ns; 395 if (!ns)
410 write_unlock(&root->lock); 396 goto out;
411 new_ns = alloc_namespace(root->base.hname, name); 397 if (__aa_fs_namespace_mkdir(ns, ns_subns_dir(root), name)) {
412 if (!new_ns) 398 AA_ERROR("Failed to create interface for ns %s\n",
413 return NULL; 399 ns->base.name);
414 write_lock(&root->lock); 400 free_namespace(ns);
415 /* test for race when new_ns was allocated */ 401 ns = NULL;
416 ns = __aa_find_namespace(&root->sub_ns, name); 402 goto out;
417 if (!ns) {
418 /* add parent ref */
419 new_ns->parent = aa_get_namespace(root);
420
421 list_add(&new_ns->base.list, &root->sub_ns);
422 /* add list ref */
423 ns = aa_get_namespace(new_ns);
424 } else {
425 /* raced so free the new one */
426 free_namespace(new_ns);
427 /* get reference on namespace */
428 aa_get_namespace(ns);
429 } 403 }
404 ns->parent = aa_get_namespace(root);
405 list_add_rcu(&ns->base.list, &root->sub_ns);
406 /* add list ref */
407 aa_get_namespace(ns);
430 } 408 }
431out: 409out:
432 write_unlock(&root->lock); 410 mutex_unlock(&root->lock);
433 411
434 /* return ref */ 412 /* return ref */
435 return ns; 413 return ns;
@@ -447,7 +425,7 @@ out:
447static void __list_add_profile(struct list_head *list, 425static void __list_add_profile(struct list_head *list,
448 struct aa_profile *profile) 426 struct aa_profile *profile)
449{ 427{
450 list_add(&profile->base.list, list); 428 list_add_rcu(&profile->base.list, list);
451 /* get list reference */ 429 /* get list reference */
452 aa_get_profile(profile); 430 aa_get_profile(profile);
453} 431}
@@ -466,49 +444,8 @@ static void __list_add_profile(struct list_head *list,
466 */ 444 */
467static void __list_remove_profile(struct aa_profile *profile) 445static void __list_remove_profile(struct aa_profile *profile)
468{ 446{
469 list_del_init(&profile->base.list); 447 list_del_rcu(&profile->base.list);
470 if (!(profile->flags & PFLAG_NO_LIST_REF)) 448 aa_put_profile(profile);
471 /* release list reference */
472 aa_put_profile(profile);
473}
474
475/**
476 * __replace_profile - replace @old with @new on a list
477 * @old: profile to be replaced (NOT NULL)
478 * @new: profile to replace @old with (NOT NULL)
479 *
480 * Will duplicate and refcount elements that @new inherits from @old
481 * and will inherit @old children.
482 *
483 * refcount @new for list, put @old list refcount
484 *
485 * Requires: namespace list lock be held, or list not be shared
486 */
487static void __replace_profile(struct aa_profile *old, struct aa_profile *new)
488{
489 struct aa_policy *policy;
490 struct aa_profile *child, *tmp;
491
492 if (old->parent)
493 policy = &old->parent->base;
494 else
495 policy = &old->ns->base;
496
497 /* released when @new is freed */
498 new->parent = aa_get_profile(old->parent);
499 new->ns = aa_get_namespace(old->ns);
500 __list_add_profile(&policy->profiles, new);
501 /* inherit children */
502 list_for_each_entry_safe(child, tmp, &old->base.profiles, base.list) {
503 aa_put_profile(child->parent);
504 child->parent = aa_get_profile(new);
505 /* list refcount transferred to @new*/
506 list_move(&child->base.list, &new->base.profiles);
507 }
508
509 /* released by free_profile */
510 old->replacedby = aa_get_profile(new);
511 __list_remove_profile(old);
512} 449}
513 450
514static void __profile_list_release(struct list_head *head); 451static void __profile_list_release(struct list_head *head);
@@ -524,7 +461,8 @@ static void __remove_profile(struct aa_profile *profile)
524 /* release any children lists first */ 461 /* release any children lists first */
525 __profile_list_release(&profile->base.profiles); 462 __profile_list_release(&profile->base.profiles);
526 /* released by free_profile */ 463 /* released by free_profile */
527 profile->replacedby = aa_get_profile(profile->ns->unconfined); 464 __aa_update_replacedby(profile, profile->ns->unconfined);
465 __aa_fs_profile_rmdir(profile);
528 __list_remove_profile(profile); 466 __list_remove_profile(profile);
529} 467}
530 468
@@ -552,14 +490,17 @@ static void destroy_namespace(struct aa_namespace *ns)
552 if (!ns) 490 if (!ns)
553 return; 491 return;
554 492
555 write_lock(&ns->lock); 493 mutex_lock(&ns->lock);
556 /* release all profiles in this namespace */ 494 /* release all profiles in this namespace */
557 __profile_list_release(&ns->base.profiles); 495 __profile_list_release(&ns->base.profiles);
558 496
559 /* release all sub namespaces */ 497 /* release all sub namespaces */
560 __ns_list_release(&ns->sub_ns); 498 __ns_list_release(&ns->sub_ns);
561 499
562 write_unlock(&ns->lock); 500 if (ns->parent)
501 __aa_update_replacedby(ns->unconfined, ns->parent->unconfined);
502 __aa_fs_namespace_rmdir(ns);
503 mutex_unlock(&ns->lock);
563} 504}
564 505
565/** 506/**
@@ -570,25 +511,9 @@ static void destroy_namespace(struct aa_namespace *ns)
570 */ 511 */
571static void __remove_namespace(struct aa_namespace *ns) 512static void __remove_namespace(struct aa_namespace *ns)
572{ 513{
573 struct aa_profile *unconfined = ns->unconfined;
574
575 /* remove ns from namespace list */ 514 /* remove ns from namespace list */
576 list_del_init(&ns->base.list); 515 list_del_rcu(&ns->base.list);
577
578 /*
579 * break the ns, unconfined profile cyclic reference and forward
580 * all new unconfined profiles requests to the parent namespace
581 * This will result in all confined tasks that have a profile
582 * being removed, inheriting the parent->unconfined profile.
583 */
584 if (ns->parent)
585 ns->unconfined = aa_get_profile(ns->parent->unconfined);
586
587 destroy_namespace(ns); 516 destroy_namespace(ns);
588
589 /* release original ns->unconfined ref */
590 aa_put_profile(unconfined);
591 /* release ns->base.list ref, from removal above */
592 aa_put_namespace(ns); 517 aa_put_namespace(ns);
593} 518}
594 519
@@ -634,8 +559,25 @@ void __init aa_free_root_ns(void)
634 aa_put_namespace(ns); 559 aa_put_namespace(ns);
635} 560}
636 561
562
563static void free_replacedby(struct aa_replacedby *r)
564{
565 if (r) {
566 aa_put_profile(rcu_dereference(r->profile));
567 kzfree(r);
568 }
569}
570
571
572void aa_free_replacedby_kref(struct kref *kref)
573{
574 struct aa_replacedby *r = container_of(kref, struct aa_replacedby,
575 count);
576 free_replacedby(r);
577}
578
637/** 579/**
638 * free_profile - free a profile 580 * aa_free_profile - free a profile
639 * @profile: the profile to free (MAYBE NULL) 581 * @profile: the profile to free (MAYBE NULL)
640 * 582 *
641 * Free a profile, its hats and null_profile. All references to the profile, 583 * Free a profile, its hats and null_profile. All references to the profile,
@@ -644,25 +586,16 @@ void __init aa_free_root_ns(void)
644 * If the profile was referenced from a task context, free_profile() will 586 * If the profile was referenced from a task context, free_profile() will
645 * be called from an rcu callback routine, so we must not sleep here. 587 * be called from an rcu callback routine, so we must not sleep here.
646 */ 588 */
647static void free_profile(struct aa_profile *profile) 589void aa_free_profile(struct aa_profile *profile)
648{ 590{
649 struct aa_profile *p;
650
651 AA_DEBUG("%s(%p)\n", __func__, profile); 591 AA_DEBUG("%s(%p)\n", __func__, profile);
652 592
653 if (!profile) 593 if (!profile)
654 return; 594 return;
655 595
656 if (!list_empty(&profile->base.list)) {
657 AA_ERROR("%s: internal error, "
658 "profile '%s' still on ns list\n",
659 __func__, profile->base.name);
660 BUG();
661 }
662
663 /* free children profiles */ 596 /* free children profiles */
664 policy_destroy(&profile->base); 597 policy_destroy(&profile->base);
665 aa_put_profile(profile->parent); 598 aa_put_profile(rcu_access_pointer(profile->parent));
666 599
667 aa_put_namespace(profile->ns); 600 aa_put_namespace(profile->ns);
668 kzfree(profile->rename); 601 kzfree(profile->rename);
@@ -671,44 +604,35 @@ static void free_profile(struct aa_profile *profile)
671 aa_free_cap_rules(&profile->caps); 604 aa_free_cap_rules(&profile->caps);
672 aa_free_rlimit_rules(&profile->rlimits); 605 aa_free_rlimit_rules(&profile->rlimits);
673 606
607 kzfree(profile->dirname);
674 aa_put_dfa(profile->xmatch); 608 aa_put_dfa(profile->xmatch);
675 aa_put_dfa(profile->policy.dfa); 609 aa_put_dfa(profile->policy.dfa);
676 610 aa_put_replacedby(profile->replacedby);
677 /* put the profile reference for replacedby, but not via
678 * put_profile(kref_put).
679 * replacedby can form a long chain that can result in cascading
680 * frees that blows the stack because kref_put makes a nested fn
681 * call (it looks like recursion, with free_profile calling
682 * free_profile) for each profile in the chain lp#1056078.
683 */
684 for (p = profile->replacedby; p; ) {
685 if (atomic_dec_and_test(&p->base.count.refcount)) {
686 /* no more refs on p, grab its replacedby */
687 struct aa_profile *next = p->replacedby;
688 /* break the chain */
689 p->replacedby = NULL;
690 /* now free p, chain is broken */
691 free_profile(p);
692
693 /* follow up with next profile in the chain */
694 p = next;
695 } else
696 break;
697 }
698 611
699 kzfree(profile); 612 kzfree(profile);
700} 613}
701 614
702/** 615/**
616 * aa_free_profile_rcu - free aa_profile by rcu (called by aa_free_profile_kref)
617 * @head: rcu_head callback for freeing of a profile (NOT NULL)
618 */
619static void aa_free_profile_rcu(struct rcu_head *head)
620{
621 struct aa_profile *p = container_of(head, struct aa_profile, rcu);
622 if (p->flags & PFLAG_NS_COUNT)
623 free_namespace(p->ns);
624 else
625 aa_free_profile(p);
626}
627
628/**
703 * aa_free_profile_kref - free aa_profile by kref (called by aa_put_profile) 629 * aa_free_profile_kref - free aa_profile by kref (called by aa_put_profile)
704 * @kr: kref callback for freeing of a profile (NOT NULL) 630 * @kr: kref callback for freeing of a profile (NOT NULL)
705 */ 631 */
706void aa_free_profile_kref(struct kref *kref) 632void aa_free_profile_kref(struct kref *kref)
707{ 633{
708 struct aa_profile *p = container_of(kref, struct aa_profile, 634 struct aa_profile *p = container_of(kref, struct aa_profile, count);
709 base.count); 635 call_rcu(&p->rcu, aa_free_profile_rcu);
710
711 free_profile(p);
712} 636}
713 637
714/** 638/**
@@ -726,13 +650,23 @@ struct aa_profile *aa_alloc_profile(const char *hname)
726 if (!profile) 650 if (!profile)
727 return NULL; 651 return NULL;
728 652
729 if (!policy_init(&profile->base, NULL, hname)) { 653 profile->replacedby = kzalloc(sizeof(struct aa_replacedby), GFP_KERNEL);
730 kzfree(profile); 654 if (!profile->replacedby)
731 return NULL; 655 goto fail;
732 } 656 kref_init(&profile->replacedby->count);
657
658 if (!policy_init(&profile->base, NULL, hname))
659 goto fail;
660 kref_init(&profile->count);
733 661
734 /* refcount released by caller */ 662 /* refcount released by caller */
735 return profile; 663 return profile;
664
665fail:
666 kzfree(profile->replacedby);
667 kzfree(profile);
668
669 return NULL;
736} 670}
737 671
738/** 672/**
@@ -772,12 +706,12 @@ struct aa_profile *aa_new_null_profile(struct aa_profile *parent, int hat)
772 profile->flags |= PFLAG_HAT; 706 profile->flags |= PFLAG_HAT;
773 707
774 /* released on free_profile */ 708 /* released on free_profile */
775 profile->parent = aa_get_profile(parent); 709 rcu_assign_pointer(profile->parent, aa_get_profile(parent));
776 profile->ns = aa_get_namespace(parent->ns); 710 profile->ns = aa_get_namespace(parent->ns);
777 711
778 write_lock(&profile->ns->lock); 712 mutex_lock(&profile->ns->lock);
779 __list_add_profile(&parent->base.profiles, profile); 713 __list_add_profile(&parent->base.profiles, profile);
780 write_unlock(&profile->ns->lock); 714 mutex_unlock(&profile->ns->lock);
781 715
782 /* refcount released by caller */ 716 /* refcount released by caller */
783 return profile; 717 return profile;
@@ -793,7 +727,7 @@ fail:
793 * @head: list to search (NOT NULL) 727 * @head: list to search (NOT NULL)
794 * @name: name of profile (NOT NULL) 728 * @name: name of profile (NOT NULL)
795 * 729 *
796 * Requires: ns lock protecting list be held 730 * Requires: rcu_read_lock be held
797 * 731 *
798 * Returns: unrefcounted profile ptr, or NULL if not found 732 * Returns: unrefcounted profile ptr, or NULL if not found
799 */ 733 */
@@ -808,7 +742,7 @@ static struct aa_profile *__find_child(struct list_head *head, const char *name)
808 * @name: name of profile (NOT NULL) 742 * @name: name of profile (NOT NULL)
809 * @len: length of @name substring to match 743 * @len: length of @name substring to match
810 * 744 *
811 * Requires: ns lock protecting list be held 745 * Requires: rcu_read_lock be held
812 * 746 *
813 * Returns: unrefcounted profile ptr, or NULL if not found 747 * Returns: unrefcounted profile ptr, or NULL if not found
814 */ 748 */
@@ -829,9 +763,9 @@ struct aa_profile *aa_find_child(struct aa_profile *parent, const char *name)
829{ 763{
830 struct aa_profile *profile; 764 struct aa_profile *profile;
831 765
832 read_lock(&parent->ns->lock); 766 rcu_read_lock();
833 profile = aa_get_profile(__find_child(&parent->base.profiles, name)); 767 profile = aa_get_profile(__find_child(&parent->base.profiles, name));
834 read_unlock(&parent->ns->lock); 768 rcu_read_unlock();
835 769
836 /* refcount released by caller */ 770 /* refcount released by caller */
837 return profile; 771 return profile;
@@ -846,7 +780,7 @@ struct aa_profile *aa_find_child(struct aa_profile *parent, const char *name)
846 * that matches hname does not need to exist, in general this 780 * that matches hname does not need to exist, in general this
847 * is used to load a new profile. 781 * is used to load a new profile.
848 * 782 *
849 * Requires: ns->lock be held 783 * Requires: rcu_read_lock be held
850 * 784 *
851 * Returns: unrefcounted policy or NULL if not found 785 * Returns: unrefcounted policy or NULL if not found
852 */ 786 */
@@ -878,7 +812,7 @@ static struct aa_policy *__lookup_parent(struct aa_namespace *ns,
878 * @base: base list to start looking up profile name from (NOT NULL) 812 * @base: base list to start looking up profile name from (NOT NULL)
879 * @hname: hierarchical profile name (NOT NULL) 813 * @hname: hierarchical profile name (NOT NULL)
880 * 814 *
881 * Requires: ns->lock be held 815 * Requires: rcu_read_lock be held
882 * 816 *
883 * Returns: unrefcounted profile pointer or NULL if not found 817 * Returns: unrefcounted profile pointer or NULL if not found
884 * 818 *
@@ -917,13 +851,15 @@ struct aa_profile *aa_lookup_profile(struct aa_namespace *ns, const char *hname)
917{ 851{
918 struct aa_profile *profile; 852 struct aa_profile *profile;
919 853
920 read_lock(&ns->lock); 854 rcu_read_lock();
921 profile = aa_get_profile(__lookup_profile(&ns->base, hname)); 855 do {
922 read_unlock(&ns->lock); 856 profile = __lookup_profile(&ns->base, hname);
857 } while (profile && !aa_get_profile_not0(profile));
858 rcu_read_unlock();
923 859
924 /* the unconfined profile is not in the regular profile list */ 860 /* the unconfined profile is not in the regular profile list */
925 if (!profile && strcmp(hname, "unconfined") == 0) 861 if (!profile && strcmp(hname, "unconfined") == 0)
926 profile = aa_get_profile(ns->unconfined); 862 profile = aa_get_newest_profile(ns->unconfined);
927 863
928 /* refcount released by caller */ 864 /* refcount released by caller */
929 return profile; 865 return profile;
@@ -953,25 +889,6 @@ static int replacement_allowed(struct aa_profile *profile, int noreplace,
953} 889}
954 890
955/** 891/**
956 * __add_new_profile - simple wrapper around __list_add_profile
957 * @ns: namespace that profile is being added to (NOT NULL)
958 * @policy: the policy container to add the profile to (NOT NULL)
959 * @profile: profile to add (NOT NULL)
960 *
961 * add a profile to a list and do other required basic allocations
962 */
963static void __add_new_profile(struct aa_namespace *ns, struct aa_policy *policy,
964 struct aa_profile *profile)
965{
966 if (policy != &ns->base)
967 /* released on profile replacement or free_profile */
968 profile->parent = aa_get_profile((struct aa_profile *) policy);
969 __list_add_profile(&policy->profiles, profile);
970 /* released on free_profile */
971 profile->ns = aa_get_namespace(ns);
972}
973
974/**
975 * aa_audit_policy - Do auditing of policy changes 892 * aa_audit_policy - Do auditing of policy changes
976 * @op: policy operation being performed 893 * @op: policy operation being performed
977 * @gfp: memory allocation flags 894 * @gfp: memory allocation flags
@@ -1019,6 +936,121 @@ bool aa_may_manage_policy(int op)
1019 return 1; 936 return 1;
1020} 937}
1021 938
939static struct aa_profile *__list_lookup_parent(struct list_head *lh,
940 struct aa_profile *profile)
941{
942 const char *base = hname_tail(profile->base.hname);
943 long len = base - profile->base.hname;
944 struct aa_load_ent *ent;
945
946 /* parent won't have trailing // so remove from len */
947 if (len <= 2)
948 return NULL;
949 len -= 2;
950
951 list_for_each_entry(ent, lh, list) {
952 if (ent->new == profile)
953 continue;
954 if (strncmp(ent->new->base.hname, profile->base.hname, len) ==
955 0 && ent->new->base.hname[len] == 0)
956 return ent->new;
957 }
958
959 return NULL;
960}
961
962/**
963 * __replace_profile - replace @old with @new on a list
964 * @old: profile to be replaced (NOT NULL)
965 * @new: profile to replace @old with (NOT NULL)
966 * @share_replacedby: transfer @old->replacedby to @new
967 *
968 * Will duplicate and refcount elements that @new inherits from @old
969 * and will inherit @old children.
970 *
971 * refcount @new for list, put @old list refcount
972 *
973 * Requires: namespace list lock be held, or list not be shared
974 */
975static void __replace_profile(struct aa_profile *old, struct aa_profile *new,
976 bool share_replacedby)
977{
978 struct aa_profile *child, *tmp;
979
980 if (!list_empty(&old->base.profiles)) {
981 LIST_HEAD(lh);
982 list_splice_init_rcu(&old->base.profiles, &lh, synchronize_rcu);
983
984 list_for_each_entry_safe(child, tmp, &lh, base.list) {
985 struct aa_profile *p;
986
987 list_del_init(&child->base.list);
988 p = __find_child(&new->base.profiles, child->base.name);
989 if (p) {
990 /* @p replaces @child */
991 __replace_profile(child, p, share_replacedby);
992 continue;
993 }
994
995 /* inherit @child and its children */
996 /* TODO: update hname of inherited children */
997 /* list refcount transferred to @new */
998 p = aa_deref_parent(child);
999 rcu_assign_pointer(child->parent, aa_get_profile(new));
1000 list_add_rcu(&child->base.list, &new->base.profiles);
1001 aa_put_profile(p);
1002 }
1003 }
1004
1005 if (!rcu_access_pointer(new->parent)) {
1006 struct aa_profile *parent = aa_deref_parent(old);
1007 rcu_assign_pointer(new->parent, aa_get_profile(parent));
1008 }
1009 __aa_update_replacedby(old, new);
1010 if (share_replacedby) {
1011 aa_put_replacedby(new->replacedby);
1012 new->replacedby = aa_get_replacedby(old->replacedby);
1013 } else if (!rcu_access_pointer(new->replacedby->profile))
1014 /* aafs interface uses replacedby */
1015 rcu_assign_pointer(new->replacedby->profile,
1016 aa_get_profile(new));
1017 __aa_fs_profile_migrate_dents(old, new);
1018
1019 if (list_empty(&new->base.list)) {
1020 /* new is not on a list already */
1021 list_replace_rcu(&old->base.list, &new->base.list);
1022 aa_get_profile(new);
1023 aa_put_profile(old);
1024 } else
1025 __list_remove_profile(old);
1026}
1027
1028/**
1029 * __lookup_replace - lookup replacement information for a profile
1030 * @ns - namespace the lookup occurs in
1031 * @hname - name of profile to lookup
1032 * @noreplace - true if not replacing an existing profile
1033 * @p - Returns: profile to be replaced
1034 * @info - Returns: info string on why lookup failed
1035 *
1036 * Returns: profile to replace (no ref) on success else ptr error
1037 */
1038static int __lookup_replace(struct aa_namespace *ns, const char *hname,
1039 bool noreplace, struct aa_profile **p,
1040 const char **info)
1041{
1042 *p = aa_get_profile(__lookup_profile(&ns->base, hname));
1043 if (*p) {
1044 int error = replacement_allowed(*p, noreplace, info);
1045 if (error) {
1046 *info = "profile can not be replaced";
1047 return error;
1048 }
1049 }
1050
1051 return 0;
1052}
1053
1022/** 1054/**
1023 * aa_replace_profiles - replace profile(s) on the profile list 1055 * aa_replace_profiles - replace profile(s) on the profile list
1024 * @udata: serialized data stream (NOT NULL) 1056 * @udata: serialized data stream (NOT NULL)
@@ -1033,21 +1065,17 @@ bool aa_may_manage_policy(int op)
1033 */ 1065 */
1034ssize_t aa_replace_profiles(void *udata, size_t size, bool noreplace) 1066ssize_t aa_replace_profiles(void *udata, size_t size, bool noreplace)
1035{ 1067{
1036 struct aa_policy *policy;
1037 struct aa_profile *old_profile = NULL, *new_profile = NULL;
1038 struct aa_profile *rename_profile = NULL;
1039 struct aa_namespace *ns = NULL;
1040 const char *ns_name, *name = NULL, *info = NULL; 1068 const char *ns_name, *name = NULL, *info = NULL;
1069 struct aa_namespace *ns = NULL;
1070 struct aa_load_ent *ent, *tmp;
1041 int op = OP_PROF_REPL; 1071 int op = OP_PROF_REPL;
1042 ssize_t error; 1072 ssize_t error;
1073 LIST_HEAD(lh);
1043 1074
1044 /* released below */ 1075 /* released below */
1045 new_profile = aa_unpack(udata, size, &ns_name); 1076 error = aa_unpack(udata, size, &lh, &ns_name);
1046 if (IS_ERR(new_profile)) { 1077 if (error)
1047 error = PTR_ERR(new_profile); 1078 goto out;
1048 new_profile = NULL;
1049 goto fail;
1050 }
1051 1079
1052 /* released below */ 1080 /* released below */
1053 ns = aa_prepare_namespace(ns_name); 1081 ns = aa_prepare_namespace(ns_name);
@@ -1058,71 +1086,140 @@ ssize_t aa_replace_profiles(void *udata, size_t size, bool noreplace)
1058 goto fail; 1086 goto fail;
1059 } 1087 }
1060 1088
1061 name = new_profile->base.hname; 1089 mutex_lock(&ns->lock);
1062 1090 /* setup parent and ns info */
1063 write_lock(&ns->lock); 1091 list_for_each_entry(ent, &lh, list) {
1064 /* no ref on policy only use inside lock */ 1092 struct aa_policy *policy;
1065 policy = __lookup_parent(ns, new_profile->base.hname); 1093
1094 name = ent->new->base.hname;
1095 error = __lookup_replace(ns, ent->new->base.hname, noreplace,
1096 &ent->old, &info);
1097 if (error)
1098 goto fail_lock;
1099
1100 if (ent->new->rename) {
1101 error = __lookup_replace(ns, ent->new->rename,
1102 noreplace, &ent->rename,
1103 &info);
1104 if (error)
1105 goto fail_lock;
1106 }
1066 1107
1067 if (!policy) { 1108 /* released when @new is freed */
1068 info = "parent does not exist"; 1109 ent->new->ns = aa_get_namespace(ns);
1069 error = -ENOENT; 1110
1070 goto audit; 1111 if (ent->old || ent->rename)
1112 continue;
1113
1114 /* no ref on policy only use inside lock */
1115 policy = __lookup_parent(ns, ent->new->base.hname);
1116 if (!policy) {
1117 struct aa_profile *p;
1118 p = __list_lookup_parent(&lh, ent->new);
1119 if (!p) {
1120 error = -ENOENT;
1121 info = "parent does not exist";
1122 name = ent->new->base.hname;
1123 goto fail_lock;
1124 }
1125 rcu_assign_pointer(ent->new->parent, aa_get_profile(p));
1126 } else if (policy != &ns->base) {
1127 /* released on profile replacement or free_profile */
1128 struct aa_profile *p = (struct aa_profile *) policy;
1129 rcu_assign_pointer(ent->new->parent, aa_get_profile(p));
1130 }
1071 } 1131 }
1072 1132
1073 old_profile = __find_child(&policy->profiles, new_profile->base.name); 1133 /* create new fs entries for introspection if needed */
1074 /* released below */ 1134 list_for_each_entry(ent, &lh, list) {
1075 aa_get_profile(old_profile); 1135 if (ent->old) {
1136 /* inherit old interface files */
1076 1137
1077 if (new_profile->rename) { 1138 /* if (ent->rename)
1078 rename_profile = __lookup_profile(&ns->base, 1139 TODO: support rename */
1079 new_profile->rename); 1140 /* } else if (ent->rename) {
1080 /* released below */ 1141 TODO: support rename */
1081 aa_get_profile(rename_profile); 1142 } else {
1143 struct dentry *parent;
1144 if (rcu_access_pointer(ent->new->parent)) {
1145 struct aa_profile *p;
1146 p = aa_deref_parent(ent->new);
1147 parent = prof_child_dir(p);
1148 } else
1149 parent = ns_subprofs_dir(ent->new->ns);
1150 error = __aa_fs_profile_mkdir(ent->new, parent);
1151 }
1082 1152
1083 if (!rename_profile) { 1153 if (error) {
1084 info = "profile to rename does not exist"; 1154 info = "failed to create ";
1085 name = new_profile->rename; 1155 goto fail_lock;
1086 error = -ENOENT;
1087 goto audit;
1088 } 1156 }
1089 } 1157 }
1090 1158
1091 error = replacement_allowed(old_profile, noreplace, &info); 1159 /* Done with checks that may fail - do actual replacement */
1092 if (error) 1160 list_for_each_entry_safe(ent, tmp, &lh, list) {
1093 goto audit; 1161 list_del_init(&ent->list);
1094 1162 op = (!ent->old && !ent->rename) ? OP_PROF_LOAD : OP_PROF_REPL;
1095 error = replacement_allowed(rename_profile, noreplace, &info); 1163
1096 if (error) 1164 audit_policy(op, GFP_ATOMIC, ent->new->base.name, NULL, error);
1097 goto audit; 1165
1098 1166 if (ent->old) {
1099audit: 1167 __replace_profile(ent->old, ent->new, 1);
1100 if (!old_profile && !rename_profile) 1168 if (ent->rename) {
1101 op = OP_PROF_LOAD; 1169 /* aafs interface uses replacedby */
1102 1170 struct aa_replacedby *r = ent->new->replacedby;
1103 error = audit_policy(op, GFP_ATOMIC, name, info, error); 1171 rcu_assign_pointer(r->profile,
1104 1172 aa_get_profile(ent->new));
1105 if (!error) { 1173 __replace_profile(ent->rename, ent->new, 0);
1106 if (rename_profile) 1174 }
1107 __replace_profile(rename_profile, new_profile); 1175 } else if (ent->rename) {
1108 if (old_profile) 1176 /* aafs interface uses replacedby */
1109 __replace_profile(old_profile, new_profile); 1177 rcu_assign_pointer(ent->new->replacedby->profile,
1110 if (!(old_profile || rename_profile)) 1178 aa_get_profile(ent->new));
1111 __add_new_profile(ns, policy, new_profile); 1179 __replace_profile(ent->rename, ent->new, 0);
1180 } else if (ent->new->parent) {
1181 struct aa_profile *parent, *newest;
1182 parent = aa_deref_parent(ent->new);
1183 newest = aa_get_newest_profile(parent);
1184
1185 /* parent replaced in this atomic set? */
1186 if (newest != parent) {
1187 aa_get_profile(newest);
1188 aa_put_profile(parent);
1189 rcu_assign_pointer(ent->new->parent, newest);
1190 } else
1191 aa_put_profile(newest);
1192 /* aafs interface uses replacedby */
1193 rcu_assign_pointer(ent->new->replacedby->profile,
1194 aa_get_profile(ent->new));
1195 __list_add_profile(&parent->base.profiles, ent->new);
1196 } else {
1197 /* aafs interface uses replacedby */
1198 rcu_assign_pointer(ent->new->replacedby->profile,
1199 aa_get_profile(ent->new));
1200 __list_add_profile(&ns->base.profiles, ent->new);
1201 }
1202 aa_load_ent_free(ent);
1112 } 1203 }
1113 write_unlock(&ns->lock); 1204 mutex_unlock(&ns->lock);
1114 1205
1115out: 1206out:
1116 aa_put_namespace(ns); 1207 aa_put_namespace(ns);
1117 aa_put_profile(rename_profile); 1208
1118 aa_put_profile(old_profile);
1119 aa_put_profile(new_profile);
1120 if (error) 1209 if (error)
1121 return error; 1210 return error;
1122 return size; 1211 return size;
1123 1212
1213fail_lock:
1214 mutex_unlock(&ns->lock);
1124fail: 1215fail:
1125 error = audit_policy(op, GFP_KERNEL, name, info, error); 1216 error = audit_policy(op, GFP_KERNEL, name, info, error);
1217
1218 list_for_each_entry_safe(ent, tmp, &lh, list) {
1219 list_del_init(&ent->list);
1220 aa_load_ent_free(ent);
1221 }
1222
1126 goto out; 1223 goto out;
1127} 1224}
1128 1225
@@ -1169,12 +1266,12 @@ ssize_t aa_remove_profiles(char *fqname, size_t size)
1169 1266
1170 if (!name) { 1267 if (!name) {
1171 /* remove namespace - can only happen if fqname[0] == ':' */ 1268 /* remove namespace - can only happen if fqname[0] == ':' */
1172 write_lock(&ns->parent->lock); 1269 mutex_lock(&ns->parent->lock);
1173 __remove_namespace(ns); 1270 __remove_namespace(ns);
1174 write_unlock(&ns->parent->lock); 1271 mutex_unlock(&ns->parent->lock);
1175 } else { 1272 } else {
1176 /* remove profile */ 1273 /* remove profile */
1177 write_lock(&ns->lock); 1274 mutex_lock(&ns->lock);
1178 profile = aa_get_profile(__lookup_profile(&ns->base, name)); 1275 profile = aa_get_profile(__lookup_profile(&ns->base, name));
1179 if (!profile) { 1276 if (!profile) {
1180 error = -ENOENT; 1277 error = -ENOENT;
@@ -1183,7 +1280,7 @@ ssize_t aa_remove_profiles(char *fqname, size_t size)
1183 } 1280 }
1184 name = profile->base.hname; 1281 name = profile->base.hname;
1185 __remove_profile(profile); 1282 __remove_profile(profile);
1186 write_unlock(&ns->lock); 1283 mutex_unlock(&ns->lock);
1187 } 1284 }
1188 1285
1189 /* don't fail removal if audit fails */ 1286 /* don't fail removal if audit fails */
@@ -1193,7 +1290,7 @@ ssize_t aa_remove_profiles(char *fqname, size_t size)
1193 return size; 1290 return size;
1194 1291
1195fail_ns_lock: 1292fail_ns_lock:
1196 write_unlock(&ns->lock); 1293 mutex_unlock(&ns->lock);
1197 aa_put_namespace(ns); 1294 aa_put_namespace(ns);
1198 1295
1199fail: 1296fail:
diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c
index 6dac7d77cb4d..a689f10930b5 100644
--- a/security/apparmor/policy_unpack.c
+++ b/security/apparmor/policy_unpack.c
@@ -24,6 +24,7 @@
24#include "include/apparmor.h" 24#include "include/apparmor.h"
25#include "include/audit.h" 25#include "include/audit.h"
26#include "include/context.h" 26#include "include/context.h"
27#include "include/crypto.h"
27#include "include/match.h" 28#include "include/match.h"
28#include "include/policy.h" 29#include "include/policy.h"
29#include "include/policy_unpack.h" 30#include "include/policy_unpack.h"
@@ -333,8 +334,10 @@ static struct aa_dfa *unpack_dfa(struct aa_ext *e)
333 /* 334 /*
334 * The dfa is aligned with in the blob to 8 bytes 335 * The dfa is aligned with in the blob to 8 bytes
335 * from the beginning of the stream. 336 * from the beginning of the stream.
337 * alignment adjust needed by dfa unpack
336 */ 338 */
337 size_t sz = blob - (char *)e->start; 339 size_t sz = blob - (char *) e->start -
340 ((e->pos - e->start) & 7);
338 size_t pad = ALIGN(sz, 8) - sz; 341 size_t pad = ALIGN(sz, 8) - sz;
339 int flags = TO_ACCEPT1_FLAG(YYTD_DATA32) | 342 int flags = TO_ACCEPT1_FLAG(YYTD_DATA32) |
340 TO_ACCEPT2_FLAG(YYTD_DATA32); 343 TO_ACCEPT2_FLAG(YYTD_DATA32);
@@ -490,6 +493,9 @@ static struct aa_profile *unpack_profile(struct aa_ext *e)
490 /* profile renaming is optional */ 493 /* profile renaming is optional */
491 (void) unpack_str(e, &profile->rename, "rename"); 494 (void) unpack_str(e, &profile->rename, "rename");
492 495
496 /* attachment string is optional */
497 (void) unpack_str(e, &profile->attach, "attach");
498
493 /* xmatch is optional and may be NULL */ 499 /* xmatch is optional and may be NULL */
494 profile->xmatch = unpack_dfa(e); 500 profile->xmatch = unpack_dfa(e);
495 if (IS_ERR(profile->xmatch)) { 501 if (IS_ERR(profile->xmatch)) {
@@ -509,12 +515,16 @@ static struct aa_profile *unpack_profile(struct aa_ext *e)
509 goto fail; 515 goto fail;
510 if (!unpack_u32(e, &tmp, NULL)) 516 if (!unpack_u32(e, &tmp, NULL))
511 goto fail; 517 goto fail;
512 if (tmp) 518 if (tmp & PACKED_FLAG_HAT)
513 profile->flags |= PFLAG_HAT; 519 profile->flags |= PFLAG_HAT;
514 if (!unpack_u32(e, &tmp, NULL)) 520 if (!unpack_u32(e, &tmp, NULL))
515 goto fail; 521 goto fail;
516 if (tmp) 522 if (tmp == PACKED_MODE_COMPLAIN)
517 profile->mode = APPARMOR_COMPLAIN; 523 profile->mode = APPARMOR_COMPLAIN;
524 else if (tmp == PACKED_MODE_KILL)
525 profile->mode = APPARMOR_KILL;
526 else if (tmp == PACKED_MODE_UNCONFINED)
527 profile->mode = APPARMOR_UNCONFINED;
518 if (!unpack_u32(e, &tmp, NULL)) 528 if (!unpack_u32(e, &tmp, NULL))
519 goto fail; 529 goto fail;
520 if (tmp) 530 if (tmp)
@@ -614,7 +624,7 @@ fail:
614 else if (!name) 624 else if (!name)
615 name = "unknown"; 625 name = "unknown";
616 audit_iface(profile, name, "failed to unpack profile", e, error); 626 audit_iface(profile, name, "failed to unpack profile", e, error);
617 aa_put_profile(profile); 627 aa_free_profile(profile);
618 628
619 return ERR_PTR(error); 629 return ERR_PTR(error);
620} 630}
@@ -622,29 +632,41 @@ fail:
622/** 632/**
623 * verify_head - unpack serialized stream header 633 * verify_head - unpack serialized stream header
624 * @e: serialized data read head (NOT NULL) 634 * @e: serialized data read head (NOT NULL)
635 * @required: whether the header is required or optional
625 * @ns: Returns - namespace if one is specified else NULL (NOT NULL) 636 * @ns: Returns - namespace if one is specified else NULL (NOT NULL)
626 * 637 *
627 * Returns: error or 0 if header is good 638 * Returns: error or 0 if header is good
628 */ 639 */
629static int verify_header(struct aa_ext *e, const char **ns) 640static int verify_header(struct aa_ext *e, int required, const char **ns)
630{ 641{
631 int error = -EPROTONOSUPPORT; 642 int error = -EPROTONOSUPPORT;
643 const char *name = NULL;
644 *ns = NULL;
645
632 /* get the interface version */ 646 /* get the interface version */
633 if (!unpack_u32(e, &e->version, "version")) { 647 if (!unpack_u32(e, &e->version, "version")) {
634 audit_iface(NULL, NULL, "invalid profile format", e, error); 648 if (required) {
635 return error; 649 audit_iface(NULL, NULL, "invalid profile format", e,
636 } 650 error);
651 return error;
652 }
637 653
638 /* check that the interface version is currently supported */ 654 /* check that the interface version is currently supported */
639 if (e->version != 5) { 655 if (e->version != 5) {
640 audit_iface(NULL, NULL, "unsupported interface version", e, 656 audit_iface(NULL, NULL, "unsupported interface version",
641 error); 657 e, error);
642 return error; 658 return error;
659 }
643 } 660 }
644 661
662
645 /* read the namespace if present */ 663 /* read the namespace if present */
646 if (!unpack_str(e, ns, "namespace")) 664 if (unpack_str(e, &name, "namespace")) {
647 *ns = NULL; 665 if (*ns && strcmp(*ns, name))
666 audit_iface(NULL, NULL, "invalid ns change", e, error);
667 else if (!*ns)
668 *ns = name;
669 }
648 670
649 return 0; 671 return 0;
650} 672}
@@ -693,18 +715,40 @@ static int verify_profile(struct aa_profile *profile)
693 return 0; 715 return 0;
694} 716}
695 717
718void aa_load_ent_free(struct aa_load_ent *ent)
719{
720 if (ent) {
721 aa_put_profile(ent->rename);
722 aa_put_profile(ent->old);
723 aa_put_profile(ent->new);
724 kzfree(ent);
725 }
726}
727
728struct aa_load_ent *aa_load_ent_alloc(void)
729{
730 struct aa_load_ent *ent = kzalloc(sizeof(*ent), GFP_KERNEL);
731 if (ent)
732 INIT_LIST_HEAD(&ent->list);
733 return ent;
734}
735
696/** 736/**
697 * aa_unpack - unpack packed binary profile data loaded from user space 737 * aa_unpack - unpack packed binary profile(s) data loaded from user space
698 * @udata: user data copied to kmem (NOT NULL) 738 * @udata: user data copied to kmem (NOT NULL)
699 * @size: the size of the user data 739 * @size: the size of the user data
740 * @lh: list to place unpacked profiles in a aa_repl_ws
700 * @ns: Returns namespace profile is in if specified else NULL (NOT NULL) 741 * @ns: Returns namespace profile is in if specified else NULL (NOT NULL)
701 * 742 *
702 * Unpack user data and return refcounted allocated profile or ERR_PTR 743 * Unpack user data and return refcounted allocated profile(s) stored in
744 * @lh in order of discovery, with the list chain stored in base.list
745 * or error
703 * 746 *
704 * Returns: profile else error pointer if fails to unpack 747 * Returns: profile(s) on @lh else error pointer if fails to unpack
705 */ 748 */
706struct aa_profile *aa_unpack(void *udata, size_t size, const char **ns) 749int aa_unpack(void *udata, size_t size, struct list_head *lh, const char **ns)
707{ 750{
751 struct aa_load_ent *tmp, *ent;
708 struct aa_profile *profile = NULL; 752 struct aa_profile *profile = NULL;
709 int error; 753 int error;
710 struct aa_ext e = { 754 struct aa_ext e = {
@@ -713,20 +757,49 @@ struct aa_profile *aa_unpack(void *udata, size_t size, const char **ns)
713 .pos = udata, 757 .pos = udata,
714 }; 758 };
715 759
716 error = verify_header(&e, ns); 760 *ns = NULL;
717 if (error) 761 while (e.pos < e.end) {
718 return ERR_PTR(error); 762 void *start;
763 error = verify_header(&e, e.pos == e.start, ns);
764 if (error)
765 goto fail;
766
767 start = e.pos;
768 profile = unpack_profile(&e);
769 if (IS_ERR(profile)) {
770 error = PTR_ERR(profile);
771 goto fail;
772 }
773
774 error = verify_profile(profile);
775 if (error)
776 goto fail_profile;
777
778 error = aa_calc_profile_hash(profile, e.version, start,
779 e.pos - start);
780 if (error)
781 goto fail_profile;
782
783 ent = aa_load_ent_alloc();
784 if (!ent) {
785 error = -ENOMEM;
786 goto fail_profile;
787 }
788
789 ent->new = profile;
790 list_add_tail(&ent->list, lh);
791 }
792
793 return 0;
719 794
720 profile = unpack_profile(&e); 795fail_profile:
721 if (IS_ERR(profile)) 796 aa_put_profile(profile);
722 return profile;
723 797
724 error = verify_profile(profile); 798fail:
725 if (error) { 799 list_for_each_entry_safe(ent, tmp, lh, list) {
726 aa_put_profile(profile); 800 list_del_init(&ent->list);
727 profile = ERR_PTR(error); 801 aa_load_ent_free(ent);
728 } 802 }
729 803
730 /* return refcount */ 804 return error;
731 return profile;
732} 805}
diff --git a/security/apparmor/procattr.c b/security/apparmor/procattr.c
index 6c9390179b89..b125acc9aa26 100644
--- a/security/apparmor/procattr.c
+++ b/security/apparmor/procattr.c
@@ -37,7 +37,7 @@ int aa_getprocattr(struct aa_profile *profile, char **string)
37{ 37{
38 char *str; 38 char *str;
39 int len = 0, mode_len = 0, ns_len = 0, name_len; 39 int len = 0, mode_len = 0, ns_len = 0, name_len;
40 const char *mode_str = profile_mode_names[profile->mode]; 40 const char *mode_str = aa_profile_mode_names[profile->mode];
41 const char *ns_name = NULL; 41 const char *ns_name = NULL;
42 struct aa_namespace *ns = profile->ns; 42 struct aa_namespace *ns = profile->ns;
43 struct aa_namespace *current_ns = __aa_current_profile()->ns; 43 struct aa_namespace *current_ns = __aa_current_profile()->ns;
diff --git a/security/capability.c b/security/capability.c
index 32b515766df1..dbeb9bc27b24 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -129,7 +129,7 @@ static void cap_inode_free_security(struct inode *inode)
129} 129}
130 130
131static int cap_inode_init_security(struct inode *inode, struct inode *dir, 131static int cap_inode_init_security(struct inode *inode, struct inode *dir,
132 const struct qstr *qstr, char **name, 132 const struct qstr *qstr, const char **name,
133 void **value, size_t *len) 133 void **value, size_t *len)
134{ 134{
135 return -EOPNOTSUPP; 135 return -EOPNOTSUPP;
diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c
index df0fa451a871..af9b6852f4e1 100644
--- a/security/integrity/evm/evm_main.c
+++ b/security/integrity/evm/evm_main.c
@@ -418,7 +418,7 @@ int evm_inode_init_security(struct inode *inode,
418 418
419 evm_xattr->value = xattr_data; 419 evm_xattr->value = xattr_data;
420 evm_xattr->value_len = sizeof(*xattr_data); 420 evm_xattr->value_len = sizeof(*xattr_data);
421 evm_xattr->name = kstrdup(XATTR_EVM_SUFFIX, GFP_NOFS); 421 evm_xattr->name = XATTR_EVM_SUFFIX;
422 return 0; 422 return 0;
423out: 423out:
424 kfree(xattr_data); 424 kfree(xattr_data);
diff --git a/security/security.c b/security/security.c
index 94b35aef6871..4dc31f4f2700 100644
--- a/security/security.c
+++ b/security/security.c
@@ -348,10 +348,10 @@ int security_inode_init_security(struct inode *inode, struct inode *dir,
348 if (unlikely(IS_PRIVATE(inode))) 348 if (unlikely(IS_PRIVATE(inode)))
349 return 0; 349 return 0;
350 350
351 memset(new_xattrs, 0, sizeof new_xattrs);
352 if (!initxattrs) 351 if (!initxattrs)
353 return security_ops->inode_init_security(inode, dir, qstr, 352 return security_ops->inode_init_security(inode, dir, qstr,
354 NULL, NULL, NULL); 353 NULL, NULL, NULL);
354 memset(new_xattrs, 0, sizeof(new_xattrs));
355 lsm_xattr = new_xattrs; 355 lsm_xattr = new_xattrs;
356 ret = security_ops->inode_init_security(inode, dir, qstr, 356 ret = security_ops->inode_init_security(inode, dir, qstr,
357 &lsm_xattr->name, 357 &lsm_xattr->name,
@@ -366,16 +366,14 @@ int security_inode_init_security(struct inode *inode, struct inode *dir,
366 goto out; 366 goto out;
367 ret = initxattrs(inode, new_xattrs, fs_data); 367 ret = initxattrs(inode, new_xattrs, fs_data);
368out: 368out:
369 for (xattr = new_xattrs; xattr->name != NULL; xattr++) { 369 for (xattr = new_xattrs; xattr->value != NULL; xattr++)
370 kfree(xattr->name);
371 kfree(xattr->value); 370 kfree(xattr->value);
372 }
373 return (ret == -EOPNOTSUPP) ? 0 : ret; 371 return (ret == -EOPNOTSUPP) ? 0 : ret;
374} 372}
375EXPORT_SYMBOL(security_inode_init_security); 373EXPORT_SYMBOL(security_inode_init_security);
376 374
377int security_old_inode_init_security(struct inode *inode, struct inode *dir, 375int security_old_inode_init_security(struct inode *inode, struct inode *dir,
378 const struct qstr *qstr, char **name, 376 const struct qstr *qstr, const char **name,
379 void **value, size_t *len) 377 void **value, size_t *len)
380{ 378{
381 if (unlikely(IS_PRIVATE(inode))) 379 if (unlikely(IS_PRIVATE(inode)))
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index c956390a9136..a5091ec06aa6 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2587,7 +2587,8 @@ static int selinux_dentry_init_security(struct dentry *dentry, int mode,
2587} 2587}
2588 2588
2589static int selinux_inode_init_security(struct inode *inode, struct inode *dir, 2589static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
2590 const struct qstr *qstr, char **name, 2590 const struct qstr *qstr,
2591 const char **name,
2591 void **value, size_t *len) 2592 void **value, size_t *len)
2592{ 2593{
2593 const struct task_security_struct *tsec = current_security(); 2594 const struct task_security_struct *tsec = current_security();
@@ -2595,7 +2596,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
2595 struct superblock_security_struct *sbsec; 2596 struct superblock_security_struct *sbsec;
2596 u32 sid, newsid, clen; 2597 u32 sid, newsid, clen;
2597 int rc; 2598 int rc;
2598 char *namep = NULL, *context; 2599 char *context;
2599 2600
2600 dsec = dir->i_security; 2601 dsec = dir->i_security;
2601 sbsec = dir->i_sb->s_security; 2602 sbsec = dir->i_sb->s_security;
@@ -2631,19 +2632,13 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
2631 if (!ss_initialized || !(sbsec->flags & SE_SBLABELSUPP)) 2632 if (!ss_initialized || !(sbsec->flags & SE_SBLABELSUPP))
2632 return -EOPNOTSUPP; 2633 return -EOPNOTSUPP;
2633 2634
2634 if (name) { 2635 if (name)
2635 namep = kstrdup(XATTR_SELINUX_SUFFIX, GFP_NOFS); 2636 *name = XATTR_SELINUX_SUFFIX;
2636 if (!namep)
2637 return -ENOMEM;
2638 *name = namep;
2639 }
2640 2637
2641 if (value && len) { 2638 if (value && len) {
2642 rc = security_sid_to_context_force(newsid, &context, &clen); 2639 rc = security_sid_to_context_force(newsid, &context, &clen);
2643 if (rc) { 2640 if (rc)
2644 kfree(namep);
2645 return rc; 2641 return rc;
2646 }
2647 *value = context; 2642 *value = context;
2648 *len = clen; 2643 *len = clen;
2649 } 2644 }
diff --git a/security/smack/smack.h b/security/smack/smack.h
index 339614c76e63..076b8e8a51ab 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -53,6 +53,7 @@
53 */ 53 */
54struct smack_known { 54struct smack_known {
55 struct list_head list; 55 struct list_head list;
56 struct hlist_node smk_hashed;
56 char *smk_known; 57 char *smk_known;
57 u32 smk_secid; 58 u32 smk_secid;
58 struct netlbl_lsm_secattr smk_netlabel; /* on wire labels */ 59 struct netlbl_lsm_secattr smk_netlabel; /* on wire labels */
@@ -167,9 +168,13 @@ struct smk_port_label {
167#define SMACK_CIPSO_DOI_INVALID -1 /* Not a DOI */ 168#define SMACK_CIPSO_DOI_INVALID -1 /* Not a DOI */
168#define SMACK_CIPSO_DIRECT_DEFAULT 250 /* Arbitrary */ 169#define SMACK_CIPSO_DIRECT_DEFAULT 250 /* Arbitrary */
169#define SMACK_CIPSO_MAPPED_DEFAULT 251 /* Also arbitrary */ 170#define SMACK_CIPSO_MAPPED_DEFAULT 251 /* Also arbitrary */
170#define SMACK_CIPSO_MAXCATVAL 63 /* Bigger gets harder */
171#define SMACK_CIPSO_MAXLEVEL 255 /* CIPSO 2.2 standard */ 171#define SMACK_CIPSO_MAXLEVEL 255 /* CIPSO 2.2 standard */
172#define SMACK_CIPSO_MAXCATNUM 239 /* CIPSO 2.2 standard */ 172/*
173 * CIPSO 2.2 standard is 239, but Smack wants to use the
174 * categories in a structured way that limits the value to
175 * the bits in 23 bytes, hence the unusual number.
176 */
177#define SMACK_CIPSO_MAXCATNUM 184 /* 23 * 8 */
173 178
174/* 179/*
175 * Flag for transmute access 180 * Flag for transmute access
@@ -222,6 +227,7 @@ char *smk_parse_smack(const char *string, int len);
222int smk_netlbl_mls(int, char *, struct netlbl_lsm_secattr *, int); 227int smk_netlbl_mls(int, char *, struct netlbl_lsm_secattr *, int);
223char *smk_import(const char *, int); 228char *smk_import(const char *, int);
224struct smack_known *smk_import_entry(const char *, int); 229struct smack_known *smk_import_entry(const char *, int);
230void smk_insert_entry(struct smack_known *skp);
225struct smack_known *smk_find_entry(const char *); 231struct smack_known *smk_find_entry(const char *);
226u32 smack_to_secid(const char *); 232u32 smack_to_secid(const char *);
227 233
@@ -247,6 +253,9 @@ extern struct list_head smk_netlbladdr_list;
247 253
248extern struct security_operations smack_ops; 254extern struct security_operations smack_ops;
249 255
256#define SMACK_HASH_SLOTS 16
257extern struct hlist_head smack_known_hash[SMACK_HASH_SLOTS];
258
250/* 259/*
251 * Is the directory transmuting? 260 * Is the directory transmuting?
252 */ 261 */
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c
index 6a0377f38620..b3b59b1e93d6 100644
--- a/security/smack/smack_access.c
+++ b/security/smack/smack_access.c
@@ -325,6 +325,25 @@ void smack_log(char *subject_label, char *object_label, int request,
325 325
326DEFINE_MUTEX(smack_known_lock); 326DEFINE_MUTEX(smack_known_lock);
327 327
328struct hlist_head smack_known_hash[SMACK_HASH_SLOTS];
329
330/**
331 * smk_insert_entry - insert a smack label into a hash map,
332 *
333 * this function must be called under smack_known_lock
334 */
335void smk_insert_entry(struct smack_known *skp)
336{
337 unsigned int hash;
338 struct hlist_head *head;
339
340 hash = full_name_hash(skp->smk_known, strlen(skp->smk_known));
341 head = &smack_known_hash[hash & (SMACK_HASH_SLOTS - 1)];
342
343 hlist_add_head_rcu(&skp->smk_hashed, head);
344 list_add_rcu(&skp->list, &smack_known_list);
345}
346
328/** 347/**
329 * smk_find_entry - find a label on the list, return the list entry 348 * smk_find_entry - find a label on the list, return the list entry
330 * @string: a text string that might be a Smack label 349 * @string: a text string that might be a Smack label
@@ -334,12 +353,16 @@ DEFINE_MUTEX(smack_known_lock);
334 */ 353 */
335struct smack_known *smk_find_entry(const char *string) 354struct smack_known *smk_find_entry(const char *string)
336{ 355{
356 unsigned int hash;
357 struct hlist_head *head;
337 struct smack_known *skp; 358 struct smack_known *skp;
338 359
339 list_for_each_entry_rcu(skp, &smack_known_list, list) { 360 hash = full_name_hash(string, strlen(string));
361 head = &smack_known_hash[hash & (SMACK_HASH_SLOTS - 1)];
362
363 hlist_for_each_entry_rcu(skp, head, smk_hashed)
340 if (strcmp(skp->smk_known, string) == 0) 364 if (strcmp(skp->smk_known, string) == 0)
341 return skp; 365 return skp;
342 }
343 366
344 return NULL; 367 return NULL;
345} 368}
@@ -475,7 +498,7 @@ struct smack_known *smk_import_entry(const char *string, int len)
475 * Make sure that the entry is actually 498 * Make sure that the entry is actually
476 * filled before putting it on the list. 499 * filled before putting it on the list.
477 */ 500 */
478 list_add_rcu(&skp->list, &smack_known_list); 501 smk_insert_entry(skp);
479 goto unlockout; 502 goto unlockout;
480 } 503 }
481 /* 504 /*
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index eefbd10e408f..8825375cc031 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -582,7 +582,7 @@ static void smack_inode_free_security(struct inode *inode)
582 * Returns 0 if it all works out, -ENOMEM if there's no memory 582 * Returns 0 if it all works out, -ENOMEM if there's no memory
583 */ 583 */
584static int smack_inode_init_security(struct inode *inode, struct inode *dir, 584static int smack_inode_init_security(struct inode *inode, struct inode *dir,
585 const struct qstr *qstr, char **name, 585 const struct qstr *qstr, const char **name,
586 void **value, size_t *len) 586 void **value, size_t *len)
587{ 587{
588 struct inode_smack *issp = inode->i_security; 588 struct inode_smack *issp = inode->i_security;
@@ -591,11 +591,8 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
591 char *dsp = smk_of_inode(dir); 591 char *dsp = smk_of_inode(dir);
592 int may; 592 int may;
593 593
594 if (name) { 594 if (name)
595 *name = kstrdup(XATTR_SMACK_SUFFIX, GFP_NOFS); 595 *name = XATTR_SMACK_SUFFIX;
596 if (*name == NULL)
597 return -ENOMEM;
598 }
599 596
600 if (value) { 597 if (value) {
601 rcu_read_lock(); 598 rcu_read_lock();
@@ -3065,6 +3062,8 @@ static struct smack_known *smack_from_secattr(struct netlbl_lsm_secattr *sap,
3065{ 3062{
3066 struct smack_known *skp; 3063 struct smack_known *skp;
3067 int found = 0; 3064 int found = 0;
3065 int acat;
3066 int kcat;
3068 3067
3069 if ((sap->flags & NETLBL_SECATTR_MLS_LVL) != 0) { 3068 if ((sap->flags & NETLBL_SECATTR_MLS_LVL) != 0) {
3070 /* 3069 /*
@@ -3081,12 +3080,28 @@ static struct smack_known *smack_from_secattr(struct netlbl_lsm_secattr *sap,
3081 list_for_each_entry(skp, &smack_known_list, list) { 3080 list_for_each_entry(skp, &smack_known_list, list) {
3082 if (sap->attr.mls.lvl != skp->smk_netlabel.attr.mls.lvl) 3081 if (sap->attr.mls.lvl != skp->smk_netlabel.attr.mls.lvl)
3083 continue; 3082 continue;
3084 if (memcmp(sap->attr.mls.cat, 3083 /*
3085 skp->smk_netlabel.attr.mls.cat, 3084 * Compare the catsets. Use the netlbl APIs.
3086 SMK_CIPSOLEN) != 0) 3085 */
3087 continue; 3086 if ((sap->flags & NETLBL_SECATTR_MLS_CAT) == 0) {
3088 found = 1; 3087 if ((skp->smk_netlabel.flags &
3089 break; 3088 NETLBL_SECATTR_MLS_CAT) == 0)
3089 found = 1;
3090 break;
3091 }
3092 for (acat = -1, kcat = -1; acat == kcat; ) {
3093 acat = netlbl_secattr_catmap_walk(
3094 sap->attr.mls.cat, acat + 1);
3095 kcat = netlbl_secattr_catmap_walk(
3096 skp->smk_netlabel.attr.mls.cat,
3097 kcat + 1);
3098 if (acat < 0 || kcat < 0)
3099 break;
3100 }
3101 if (acat == kcat) {
3102 found = 1;
3103 break;
3104 }
3090 } 3105 }
3091 rcu_read_unlock(); 3106 rcu_read_unlock();
3092 3107
@@ -3877,12 +3892,12 @@ static __init void init_smack_known_list(void)
3877 /* 3892 /*
3878 * Create the known labels list 3893 * Create the known labels list
3879 */ 3894 */
3880 list_add(&smack_known_huh.list, &smack_known_list); 3895 smk_insert_entry(&smack_known_huh);
3881 list_add(&smack_known_hat.list, &smack_known_list); 3896 smk_insert_entry(&smack_known_hat);
3882 list_add(&smack_known_star.list, &smack_known_list); 3897 smk_insert_entry(&smack_known_star);
3883 list_add(&smack_known_floor.list, &smack_known_list); 3898 smk_insert_entry(&smack_known_floor);
3884 list_add(&smack_known_invalid.list, &smack_known_list); 3899 smk_insert_entry(&smack_known_invalid);
3885 list_add(&smack_known_web.list, &smack_known_list); 3900 smk_insert_entry(&smack_known_web);
3886} 3901}
3887 3902
3888/** 3903/**
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
index ab167037b2dd..80f4b4a45725 100644
--- a/security/smack/smackfs.c
+++ b/security/smack/smackfs.c
@@ -368,56 +368,43 @@ static int smk_parse_rule(const char *data, struct smack_parsed_rule *rule,
368 * @data: string to be parsed, null terminated 368 * @data: string to be parsed, null terminated
369 * @rule: Will be filled with Smack parsed rule 369 * @rule: Will be filled with Smack parsed rule
370 * @import: if non-zero, import labels 370 * @import: if non-zero, import labels
371 * @change: if non-zero, data is from /smack/change-rule 371 * @tokens: numer of substrings expected in data
372 * 372 *
373 * Returns 0 on success, -1 on failure 373 * Returns number of processed bytes on success, -1 on failure.
374 */ 374 */
375static int smk_parse_long_rule(const char *data, struct smack_parsed_rule *rule, 375static ssize_t smk_parse_long_rule(char *data, struct smack_parsed_rule *rule,
376 int import, int change) 376 int import, int tokens)
377{ 377{
378 char *subject; 378 ssize_t cnt = 0;
379 char *object; 379 char *tok[4];
380 char *access1; 380 int i;
381 char *access2;
382 int datalen;
383 int rc = -1;
384 381
385 /* This is inefficient */ 382 /*
386 datalen = strlen(data); 383 * Parsing the rule in-place, filling all white-spaces with '\0'
384 */
385 for (i = 0; i < tokens; ++i) {
386 while (isspace(data[cnt]))
387 data[cnt++] = '\0';
387 388
388 /* Our first element can be 64 + \0 with no spaces */ 389 if (data[cnt] == '\0')
389 subject = kzalloc(datalen + 1, GFP_KERNEL); 390 /* Unexpected end of data */
390 if (subject == NULL) 391 return -1;
391 return -1; 392
392 object = kzalloc(datalen, GFP_KERNEL); 393 tok[i] = data + cnt;
393 if (object == NULL) 394
394 goto free_out_s; 395 while (data[cnt] && !isspace(data[cnt]))
395 access1 = kzalloc(datalen, GFP_KERNEL); 396 ++cnt;
396 if (access1 == NULL)
397 goto free_out_o;
398 access2 = kzalloc(datalen, GFP_KERNEL);
399 if (access2 == NULL)
400 goto free_out_a;
401
402 if (change) {
403 if (sscanf(data, "%s %s %s %s",
404 subject, object, access1, access2) == 4)
405 rc = smk_fill_rule(subject, object, access1, access2,
406 rule, import, 0);
407 } else {
408 if (sscanf(data, "%s %s %s", subject, object, access1) == 3)
409 rc = smk_fill_rule(subject, object, access1, NULL,
410 rule, import, 0);
411 } 397 }
398 while (isspace(data[cnt]))
399 data[cnt++] = '\0';
412 400
413 kfree(access2); 401 while (i < 4)
414free_out_a: 402 tok[i++] = NULL;
415 kfree(access1); 403
416free_out_o: 404 if (smk_fill_rule(tok[0], tok[1], tok[2], tok[3], rule, import, 0))
417 kfree(object); 405 return -1;
418free_out_s: 406
419 kfree(subject); 407 return cnt;
420 return rc;
421} 408}
422 409
423#define SMK_FIXED24_FMT 0 /* Fixed 24byte label format */ 410#define SMK_FIXED24_FMT 0 /* Fixed 24byte label format */
@@ -447,11 +434,12 @@ static ssize_t smk_write_rules_list(struct file *file, const char __user *buf,
447 struct list_head *rule_list, 434 struct list_head *rule_list,
448 struct mutex *rule_lock, int format) 435 struct mutex *rule_lock, int format)
449{ 436{
450 struct smack_parsed_rule *rule; 437 struct smack_parsed_rule rule;
451 char *data; 438 char *data;
452 int datalen; 439 int rc;
453 int rc = -EINVAL; 440 int trunc = 0;
454 int load = 0; 441 int tokens;
442 ssize_t cnt = 0;
455 443
456 /* 444 /*
457 * No partial writes. 445 * No partial writes.
@@ -466,11 +454,14 @@ static ssize_t smk_write_rules_list(struct file *file, const char __user *buf,
466 */ 454 */
467 if (count != SMK_OLOADLEN && count != SMK_LOADLEN) 455 if (count != SMK_OLOADLEN && count != SMK_LOADLEN)
468 return -EINVAL; 456 return -EINVAL;
469 datalen = SMK_LOADLEN; 457 } else {
470 } else 458 if (count >= PAGE_SIZE) {
471 datalen = count + 1; 459 count = PAGE_SIZE - 1;
460 trunc = 1;
461 }
462 }
472 463
473 data = kzalloc(datalen, GFP_KERNEL); 464 data = kmalloc(count + 1, GFP_KERNEL);
474 if (data == NULL) 465 if (data == NULL)
475 return -ENOMEM; 466 return -ENOMEM;
476 467
@@ -479,47 +470,49 @@ static ssize_t smk_write_rules_list(struct file *file, const char __user *buf,
479 goto out; 470 goto out;
480 } 471 }
481 472
482 rule = kzalloc(sizeof(*rule), GFP_KERNEL); 473 /*
483 if (rule == NULL) { 474 * In case of parsing only part of user buf,
484 rc = -ENOMEM; 475 * avoid having partial rule at the data buffer
485 goto out; 476 */
477 if (trunc) {
478 while (count > 0 && (data[count - 1] != '\n'))
479 --count;
480 if (count == 0) {
481 rc = -EINVAL;
482 goto out;
483 }
486 } 484 }
487 485
488 if (format == SMK_LONG_FMT) { 486 data[count] = '\0';
489 /* 487 tokens = (format == SMK_CHANGE_FMT ? 4 : 3);
490 * Be sure the data string is terminated. 488 while (cnt < count) {
491 */ 489 if (format == SMK_FIXED24_FMT) {
492 data[count] = '\0'; 490 rc = smk_parse_rule(data, &rule, 1);
493 if (smk_parse_long_rule(data, rule, 1, 0)) 491 if (rc != 0) {
494 goto out_free_rule; 492 rc = -EINVAL;
495 } else if (format == SMK_CHANGE_FMT) { 493 goto out;
496 data[count] = '\0'; 494 }
497 if (smk_parse_long_rule(data, rule, 1, 1)) 495 cnt = count;
498 goto out_free_rule; 496 } else {
499 } else { 497 rc = smk_parse_long_rule(data + cnt, &rule, 1, tokens);
500 /* 498 if (rc <= 0) {
501 * More on the minor hack for backward compatibility 499 rc = -EINVAL;
502 */ 500 goto out;
503 if (count == (SMK_OLOADLEN)) 501 }
504 data[SMK_OLOADLEN] = '-'; 502 cnt += rc;
505 if (smk_parse_rule(data, rule, 1)) 503 }
506 goto out_free_rule;
507 }
508 504
509 if (rule_list == NULL) { 505 if (rule_list == NULL)
510 load = 1; 506 rc = smk_set_access(&rule, &rule.smk_subject->smk_rules,
511 rule_list = &rule->smk_subject->smk_rules; 507 &rule.smk_subject->smk_rules_lock, 1);
512 rule_lock = &rule->smk_subject->smk_rules_lock; 508 else
513 } 509 rc = smk_set_access(&rule, rule_list, rule_lock, 0);
514 510
515 rc = smk_set_access(rule, rule_list, rule_lock, load); 511 if (rc)
516 if (rc == 0) { 512 goto out;
517 rc = count;
518 goto out;
519 } 513 }
520 514
521out_free_rule: 515 rc = cnt;
522 kfree(rule);
523out: 516out:
524 kfree(data); 517 kfree(data);
525 return rc; 518 return rc;
@@ -901,7 +894,7 @@ static ssize_t smk_set_cipso(struct file *file, const char __user *buf,
901 for (i = 0; i < catlen; i++) { 894 for (i = 0; i < catlen; i++) {
902 rule += SMK_DIGITLEN; 895 rule += SMK_DIGITLEN;
903 ret = sscanf(rule, "%u", &cat); 896 ret = sscanf(rule, "%u", &cat);
904 if (ret != 1 || cat > SMACK_CIPSO_MAXCATVAL) 897 if (ret != 1 || cat > SMACK_CIPSO_MAXCATNUM)
905 goto out; 898 goto out;
906 899
907 smack_catset_bit(cat, mapcatset); 900 smack_catset_bit(cat, mapcatset);
@@ -1840,7 +1833,6 @@ static ssize_t smk_user_access(struct file *file, const char __user *buf,
1840{ 1833{
1841 struct smack_parsed_rule rule; 1834 struct smack_parsed_rule rule;
1842 char *data; 1835 char *data;
1843 char *cod;
1844 int res; 1836 int res;
1845 1837
1846 data = simple_transaction_get(file, buf, count); 1838 data = simple_transaction_get(file, buf, count);
@@ -1853,18 +1845,12 @@ static ssize_t smk_user_access(struct file *file, const char __user *buf,
1853 res = smk_parse_rule(data, &rule, 0); 1845 res = smk_parse_rule(data, &rule, 0);
1854 } else { 1846 } else {
1855 /* 1847 /*
1856 * Copy the data to make sure the string is terminated. 1848 * simple_transaction_get() returns null-terminated data
1857 */ 1849 */
1858 cod = kzalloc(count + 1, GFP_KERNEL); 1850 res = smk_parse_long_rule(data, &rule, 0, 3);
1859 if (cod == NULL)
1860 return -ENOMEM;
1861 memcpy(cod, data, count);
1862 cod[count] = '\0';
1863 res = smk_parse_long_rule(cod, &rule, 0, 0);
1864 kfree(cod);
1865 } 1851 }
1866 1852
1867 if (res) 1853 if (res < 0)
1868 return -EINVAL; 1854 return -EINVAL;
1869 1855
1870 res = smk_access(rule.smk_subject, rule.smk_object, 1856 res = smk_access(rule.smk_subject, rule.smk_object,