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.c114
1 files changed, 86 insertions, 28 deletions
diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c
index 6dac7d77cb4d..080a26b11f01 100644
--- a/security/apparmor/policy_unpack.c
+++ b/security/apparmor/policy_unpack.c
@@ -333,8 +333,10 @@ static struct aa_dfa *unpack_dfa(struct aa_ext *e)
333 /* 333 /*
334 * The dfa is aligned with in the blob to 8 bytes 334 * The dfa is aligned with in the blob to 8 bytes
335 * from the beginning of the stream. 335 * from the beginning of the stream.
336 * alignment adjust needed by dfa unpack
336 */ 337 */
337 size_t sz = blob - (char *)e->start; 338 size_t sz = blob - (char *) e->start -
339 ((e->pos - e->start) & 7);
338 size_t pad = ALIGN(sz, 8) - sz; 340 size_t pad = ALIGN(sz, 8) - sz;
339 int flags = TO_ACCEPT1_FLAG(YYTD_DATA32) | 341 int flags = TO_ACCEPT1_FLAG(YYTD_DATA32) |
340 TO_ACCEPT2_FLAG(YYTD_DATA32); 342 TO_ACCEPT2_FLAG(YYTD_DATA32);
@@ -622,29 +624,41 @@ fail:
622/** 624/**
623 * verify_head - unpack serialized stream header 625 * verify_head - unpack serialized stream header
624 * @e: serialized data read head (NOT NULL) 626 * @e: serialized data read head (NOT NULL)
627 * @required: whether the header is required or optional
625 * @ns: Returns - namespace if one is specified else NULL (NOT NULL) 628 * @ns: Returns - namespace if one is specified else NULL (NOT NULL)
626 * 629 *
627 * Returns: error or 0 if header is good 630 * Returns: error or 0 if header is good
628 */ 631 */
629static int verify_header(struct aa_ext *e, const char **ns) 632static int verify_header(struct aa_ext *e, int required, const char **ns)
630{ 633{
631 int error = -EPROTONOSUPPORT; 634 int error = -EPROTONOSUPPORT;
635 const char *name = NULL;
636 *ns = NULL;
637
632 /* get the interface version */ 638 /* get the interface version */
633 if (!unpack_u32(e, &e->version, "version")) { 639 if (!unpack_u32(e, &e->version, "version")) {
634 audit_iface(NULL, NULL, "invalid profile format", e, error); 640 if (required) {
635 return error; 641 audit_iface(NULL, NULL, "invalid profile format", e,
636 } 642 error);
643 return error;
644 }
637 645
638 /* check that the interface version is currently supported */ 646 /* check that the interface version is currently supported */
639 if (e->version != 5) { 647 if (e->version != 5) {
640 audit_iface(NULL, NULL, "unsupported interface version", e, 648 audit_iface(NULL, NULL, "unsupported interface version",
641 error); 649 e, error);
642 return error; 650 return error;
651 }
643 } 652 }
644 653
654
645 /* read the namespace if present */ 655 /* read the namespace if present */
646 if (!unpack_str(e, ns, "namespace")) 656 if (unpack_str(e, &name, "namespace")) {
647 *ns = NULL; 657 if (*ns && strcmp(*ns, name))
658 audit_iface(NULL, NULL, "invalid ns change", e, error);
659 else if (!*ns)
660 *ns = name;
661 }
648 662
649 return 0; 663 return 0;
650} 664}
@@ -693,18 +707,40 @@ static int verify_profile(struct aa_profile *profile)
693 return 0; 707 return 0;
694} 708}
695 709
710void aa_load_ent_free(struct aa_load_ent *ent)
711{
712 if (ent) {
713 aa_put_profile(ent->rename);
714 aa_put_profile(ent->old);
715 aa_put_profile(ent->new);
716 kzfree(ent);
717 }
718}
719
720struct aa_load_ent *aa_load_ent_alloc(void)
721{
722 struct aa_load_ent *ent = kzalloc(sizeof(*ent), GFP_KERNEL);
723 if (ent)
724 INIT_LIST_HEAD(&ent->list);
725 return ent;
726}
727
696/** 728/**
697 * aa_unpack - unpack packed binary profile data loaded from user space 729 * aa_unpack - unpack packed binary profile(s) data loaded from user space
698 * @udata: user data copied to kmem (NOT NULL) 730 * @udata: user data copied to kmem (NOT NULL)
699 * @size: the size of the user data 731 * @size: the size of the user data
732 * @lh: list to place unpacked profiles in a aa_repl_ws
700 * @ns: Returns namespace profile is in if specified else NULL (NOT NULL) 733 * @ns: Returns namespace profile is in if specified else NULL (NOT NULL)
701 * 734 *
702 * Unpack user data and return refcounted allocated profile or ERR_PTR 735 * Unpack user data and return refcounted allocated profile(s) stored in
736 * @lh in order of discovery, with the list chain stored in base.list
737 * or error
703 * 738 *
704 * Returns: profile else error pointer if fails to unpack 739 * Returns: profile(s) on @lh else error pointer if fails to unpack
705 */ 740 */
706struct aa_profile *aa_unpack(void *udata, size_t size, const char **ns) 741int aa_unpack(void *udata, size_t size, struct list_head *lh, const char **ns)
707{ 742{
743 struct aa_load_ent *tmp, *ent;
708 struct aa_profile *profile = NULL; 744 struct aa_profile *profile = NULL;
709 int error; 745 int error;
710 struct aa_ext e = { 746 struct aa_ext e = {
@@ -713,20 +749,42 @@ struct aa_profile *aa_unpack(void *udata, size_t size, const char **ns)
713 .pos = udata, 749 .pos = udata,
714 }; 750 };
715 751
716 error = verify_header(&e, ns); 752 *ns = NULL;
717 if (error) 753 while (e.pos < e.end) {
718 return ERR_PTR(error); 754 error = verify_header(&e, e.pos == e.start, ns);
755 if (error)
756 goto fail;
719 757
720 profile = unpack_profile(&e); 758 profile = unpack_profile(&e);
721 if (IS_ERR(profile)) 759 if (IS_ERR(profile)) {
722 return profile; 760 error = PTR_ERR(profile);
761 goto fail;
762 }
763
764 error = verify_profile(profile);
765 if (error) {
766 aa_put_profile(profile);
767 goto fail;
768 }
769
770 ent = aa_load_ent_alloc();
771 if (!ent) {
772 error = -ENOMEM;
773 aa_put_profile(profile);
774 goto fail;
775 }
723 776
724 error = verify_profile(profile); 777 ent->new = profile;
725 if (error) { 778 list_add_tail(&ent->list, lh);
726 aa_put_profile(profile);
727 profile = ERR_PTR(error);
728 } 779 }
729 780
730 /* return refcount */ 781 return 0;
731 return profile; 782
783fail:
784 list_for_each_entry_safe(ent, tmp, lh, list) {
785 list_del_init(&ent->list);
786 aa_load_ent_free(ent);
787 }
788
789 return error;
732} 790}