aboutsummaryrefslogtreecommitdiffstats
path: root/security/apparmor/policy_unpack.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/apparmor/policy_unpack.c')
-rw-r--r--security/apparmor/policy_unpack.c135
1 files changed, 104 insertions, 31 deletions
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}