diff options
author | Matthew Garrett <mjg59@google.com> | 2018-05-24 16:27:46 -0400 |
---|---|---|
committer | John Johansen <john.johansen@canonical.com> | 2018-10-03 09:18:38 -0400 |
commit | 9caafbe2b4cf4c635826a2832e93cf648605de8b (patch) | |
tree | 3d09ad1db13f0be16c42f04133101b9a36f777e5 | |
parent | 617a629c08bfffb05249131079d9a38322902e5b (diff) |
apparmor: Parse secmark policy
Add support for parsing secmark policy provided by userspace, and
store that in the overall policy.
Signed-off-by: Matthew Garrett <mjg59@google.com>
Signed-off-by: John Johansen <john.johansen@canonical.com>
-rw-r--r-- | security/apparmor/include/net.h | 10 | ||||
-rw-r--r-- | security/apparmor/include/policy.h | 3 | ||||
-rw-r--r-- | security/apparmor/policy.c | 3 | ||||
-rw-r--r-- | security/apparmor/policy_unpack.c | 61 |
4 files changed, 77 insertions, 0 deletions
diff --git a/security/apparmor/include/net.h b/security/apparmor/include/net.h index ec7228e857a9..7334ac966d01 100644 --- a/security/apparmor/include/net.h +++ b/security/apparmor/include/net.h | |||
@@ -83,6 +83,13 @@ struct aa_sk_ctx { | |||
83 | __e; \ | 83 | __e; \ |
84 | }) | 84 | }) |
85 | 85 | ||
86 | struct aa_secmark { | ||
87 | u8 audit; | ||
88 | u8 deny; | ||
89 | u32 secid; | ||
90 | char *label; | ||
91 | }; | ||
92 | |||
86 | extern struct aa_sfs_entry aa_sfs_entry_network[]; | 93 | extern struct aa_sfs_entry aa_sfs_entry_network[]; |
87 | 94 | ||
88 | void audit_net_cb(struct audit_buffer *ab, void *va); | 95 | void audit_net_cb(struct audit_buffer *ab, void *va); |
@@ -103,4 +110,7 @@ int aa_sk_perm(const char *op, u32 request, struct sock *sk); | |||
103 | int aa_sock_file_perm(struct aa_label *label, const char *op, u32 request, | 110 | int aa_sock_file_perm(struct aa_label *label, const char *op, u32 request, |
104 | struct socket *sock); | 111 | struct socket *sock); |
105 | 112 | ||
113 | int apparmor_secmark_check(struct aa_label *label, char *op, u32 request, | ||
114 | u32 secid, struct sock *sk); | ||
115 | |||
106 | #endif /* __AA_NET_H */ | 116 | #endif /* __AA_NET_H */ |
diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h index ab64c6b5db5a..8e6707c837be 100644 --- a/security/apparmor/include/policy.h +++ b/security/apparmor/include/policy.h | |||
@@ -155,6 +155,9 @@ struct aa_profile { | |||
155 | 155 | ||
156 | struct aa_rlimit rlimits; | 156 | struct aa_rlimit rlimits; |
157 | 157 | ||
158 | int secmark_count; | ||
159 | struct aa_secmark *secmark; | ||
160 | |||
158 | struct aa_loaddata *rawdata; | 161 | struct aa_loaddata *rawdata; |
159 | unsigned char *hash; | 162 | unsigned char *hash; |
160 | char *dirname; | 163 | char *dirname; |
diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c index 1590e2de4e84..8d846a747b84 100644 --- a/security/apparmor/policy.c +++ b/security/apparmor/policy.c | |||
@@ -231,6 +231,9 @@ void aa_free_profile(struct aa_profile *profile) | |||
231 | for (i = 0; i < profile->xattr_count; i++) | 231 | for (i = 0; i < profile->xattr_count; i++) |
232 | kzfree(profile->xattrs[i]); | 232 | kzfree(profile->xattrs[i]); |
233 | kzfree(profile->xattrs); | 233 | kzfree(profile->xattrs); |
234 | for (i=0; i < profile->secmark_count; i++) | ||
235 | kzfree(profile->secmark[i].label); | ||
236 | kzfree(profile->secmark); | ||
234 | kzfree(profile->dirname); | 237 | kzfree(profile->dirname); |
235 | aa_put_dfa(profile->xmatch); | 238 | aa_put_dfa(profile->xmatch); |
236 | aa_put_dfa(profile->policy.dfa); | 239 | aa_put_dfa(profile->policy.dfa); |
diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c index 21cb384d712a..379682e2a8d5 100644 --- a/security/apparmor/policy_unpack.c +++ b/security/apparmor/policy_unpack.c | |||
@@ -292,6 +292,19 @@ fail: | |||
292 | return 0; | 292 | return 0; |
293 | } | 293 | } |
294 | 294 | ||
295 | static bool unpack_u8(struct aa_ext *e, u8 *data, const char *name) | ||
296 | { | ||
297 | if (unpack_nameX(e, AA_U8, name)) { | ||
298 | if (!inbounds(e, sizeof(u8))) | ||
299 | return 0; | ||
300 | if (data) | ||
301 | *data = get_unaligned((u8 *)e->pos); | ||
302 | e->pos += sizeof(u8); | ||
303 | return 1; | ||
304 | } | ||
305 | return 0; | ||
306 | } | ||
307 | |||
295 | static bool unpack_u32(struct aa_ext *e, u32 *data, const char *name) | 308 | static bool unpack_u32(struct aa_ext *e, u32 *data, const char *name) |
296 | { | 309 | { |
297 | if (unpack_nameX(e, AA_U32, name)) { | 310 | if (unpack_nameX(e, AA_U32, name)) { |
@@ -529,6 +542,49 @@ fail: | |||
529 | return 0; | 542 | return 0; |
530 | } | 543 | } |
531 | 544 | ||
545 | static bool unpack_secmark(struct aa_ext *e, struct aa_profile *profile) | ||
546 | { | ||
547 | void *pos = e->pos; | ||
548 | int i, size; | ||
549 | |||
550 | if (unpack_nameX(e, AA_STRUCT, "secmark")) { | ||
551 | size = unpack_array(e, NULL); | ||
552 | |||
553 | profile->secmark = kcalloc(size, sizeof(struct aa_secmark), | ||
554 | GFP_KERNEL); | ||
555 | if (!profile->secmark) | ||
556 | goto fail; | ||
557 | |||
558 | profile->secmark_count = size; | ||
559 | |||
560 | for (i = 0; i < size; i++) { | ||
561 | if (!unpack_u8(e, &profile->secmark[i].audit, NULL)) | ||
562 | goto fail; | ||
563 | if (!unpack_u8(e, &profile->secmark[i].deny, NULL)) | ||
564 | goto fail; | ||
565 | if (!unpack_strdup(e, &profile->secmark[i].label, NULL)) | ||
566 | goto fail; | ||
567 | } | ||
568 | if (!unpack_nameX(e, AA_ARRAYEND, NULL)) | ||
569 | goto fail; | ||
570 | if (!unpack_nameX(e, AA_STRUCTEND, NULL)) | ||
571 | goto fail; | ||
572 | } | ||
573 | |||
574 | return 1; | ||
575 | |||
576 | fail: | ||
577 | if (profile->secmark) { | ||
578 | for (i = 0; i < size; i++) | ||
579 | kfree(profile->secmark[i].label); | ||
580 | kfree(profile->secmark); | ||
581 | profile->secmark_count = 0; | ||
582 | } | ||
583 | |||
584 | e->pos = pos; | ||
585 | return 0; | ||
586 | } | ||
587 | |||
532 | static bool unpack_rlimits(struct aa_ext *e, struct aa_profile *profile) | 588 | static bool unpack_rlimits(struct aa_ext *e, struct aa_profile *profile) |
533 | { | 589 | { |
534 | void *pos = e->pos; | 590 | void *pos = e->pos; |
@@ -727,6 +783,11 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name) | |||
727 | goto fail; | 783 | goto fail; |
728 | } | 784 | } |
729 | 785 | ||
786 | if (!unpack_secmark(e, profile)) { | ||
787 | info = "failed to unpack profile secmark rules"; | ||
788 | goto fail; | ||
789 | } | ||
790 | |||
730 | if (unpack_nameX(e, AA_STRUCT, "policydb")) { | 791 | if (unpack_nameX(e, AA_STRUCT, "policydb")) { |
731 | /* generic policy dfa - optional and may be NULL */ | 792 | /* generic policy dfa - optional and may be NULL */ |
732 | info = "failed to unpack policydb"; | 793 | info = "failed to unpack policydb"; |