Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'apparmor-pr-2018-11-01' of git://git.kernel.org/pub/scm/linux/kernel/git/jj/linux-apparmor

Pull apparmor updates from John Johansen:
"Features/Improvements:
- replace spin_is_locked() with lockdep
- add base support for secmark labeling and matching

Cleanups:
- clean an indentation issue, remove extraneous space
- remove no-op permission check in policy_unpack
- fix checkpatch missing spaces error in Parse secmark policy
- fix network performance issue in aa_label_sk_perm

Bug fixes:
- add #ifdef checks for secmark filtering
- fix an error code in __aa_create_ns()
- don't try to replace stale label in ptrace checks
- fix failure to audit context info in build_change_hat
- check buffer bounds when mapping permissions mask
- fully initialize aa_perms struct when answering userspace query
- fix uninitialized value in aa_split_fqname"

* tag 'apparmor-pr-2018-11-01' of git://git.kernel.org/pub/scm/linux/kernel/git/jj/linux-apparmor:
apparmor: clean an indentation issue, remove extraneous space
apparmor: fix checkpatch error in Parse secmark policy
apparmor: add #ifdef checks for secmark filtering
apparmor: Fix uninitialized value in aa_split_fqname
apparmor: don't try to replace stale label in ptraceme check
apparmor: Replace spin_is_locked() with lockdep
apparmor: Allow filtering based on secmark policy
apparmor: Parse secmark policy
apparmor: Add a wildcard secid
apparmor: don't try to replace stale label in ptrace access check
apparmor: Fix network performance issue in aa_label_sk_perm

+291 -17
+1 -1
security/apparmor/apparmorfs.c
··· 1742 1742 if (error) 1743 1743 return error; 1744 1744 1745 - parent = aa_get_ns(dir->i_private); 1745 + parent = aa_get_ns(dir->i_private); 1746 1746 /* rmdir calls the generic securityfs functions to remove files 1747 1747 * from the apparmor dir. It is up to the apparmor ns locking 1748 1748 * to avoid races.
+1 -1
security/apparmor/file.c
··· 496 496 /* update caching of label on file_ctx */ 497 497 spin_lock(&fctx->lock); 498 498 old = rcu_dereference_protected(fctx->label, 499 - spin_is_locked(&fctx->lock)); 499 + lockdep_is_held(&fctx->lock)); 500 500 l = aa_label_merge(old, label, GFP_ATOMIC); 501 501 if (l) { 502 502 if (l != old) {
+2
security/apparmor/include/cred.h
··· 151 151 { 152 152 struct aa_label *label = aa_current_raw_label(); 153 153 154 + might_sleep(); 155 + 154 156 if (label_is_stale(label)) { 155 157 label = aa_get_newest_label(label); 156 158 if (aa_replace_current_label(label) == 0)
+10
security/apparmor/include/net.h
··· 83 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 93 extern struct aa_sfs_entry aa_sfs_entry_network[]; 87 94 88 95 void audit_net_cb(struct audit_buffer *ab, void *va); ··· 109 102 110 103 int aa_sock_file_perm(struct aa_label *label, const char *op, u32 request, 111 104 struct socket *sock); 105 + 106 + int apparmor_secmark_check(struct aa_label *label, char *op, u32 request, 107 + u32 secid, struct sock *sk); 112 108 113 109 #endif /* __AA_NET_H */
+3
security/apparmor/include/policy.h
··· 155 155 156 156 struct aa_rlimit rlimits; 157 157 158 + int secmark_count; 159 + struct aa_secmark *secmark; 160 + 158 161 struct aa_loaddata *rawdata; 159 162 unsigned char *hash; 160 163 char *dirname;
+3
security/apparmor/include/secid.h
··· 22 22 /* secid value that will not be allocated */ 23 23 #define AA_SECID_INVALID 0 24 24 25 + /* secid value that matches any other secid */ 26 + #define AA_SECID_WILDCARD 1 27 + 25 28 struct aa_label *aa_secid_to_label(u32 secid); 26 29 int apparmor_secid_to_secctx(u32 secid, char **secdata, u32 *seclen); 27 30 int apparmor_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid);
+4 -2
security/apparmor/lib.c
··· 90 90 const char *end = fqname + n; 91 91 const char *name = skipn_spaces(fqname, n); 92 92 93 - if (!name) 94 - return NULL; 95 93 *ns_name = NULL; 96 94 *ns_len = 0; 95 + 96 + if (!name) 97 + return NULL; 98 + 97 99 if (name[0] == ':') { 98 100 char *split = strnchr(&name[1], end - &name[1], ':'); 99 101 *ns_name = skipn_spaces(&name[1], end - &name[1]);
+125 -5
security/apparmor/lsm.c
··· 23 23 #include <linux/sysctl.h> 24 24 #include <linux/audit.h> 25 25 #include <linux/user_namespace.h> 26 + #include <linux/netfilter_ipv4.h> 27 + #include <linux/netfilter_ipv6.h> 26 28 #include <net/sock.h> 27 29 28 30 #include "include/apparmor.h" ··· 116 114 struct aa_label *tracer, *tracee; 117 115 int error; 118 116 119 - tracer = begin_current_label_crit_section(); 117 + tracer = __begin_current_label_crit_section(); 120 118 tracee = aa_get_task_label(child); 121 119 error = aa_may_ptrace(tracer, tracee, 122 120 (mode & PTRACE_MODE_READ) ? AA_PTRACE_READ 123 121 : AA_PTRACE_TRACE); 124 122 aa_put_label(tracee); 125 - end_current_label_crit_section(tracer); 123 + __end_current_label_crit_section(tracer); 126 124 127 125 return error; 128 126 } ··· 132 130 struct aa_label *tracer, *tracee; 133 131 int error; 134 132 135 - tracee = begin_current_label_crit_section(); 133 + tracee = __begin_current_label_crit_section(); 136 134 tracer = aa_get_task_label(parent); 137 135 error = aa_may_ptrace(tracer, tracee, AA_PTRACE_TRACE); 138 136 aa_put_label(tracer); 139 - end_current_label_crit_section(tracee); 137 + __end_current_label_crit_section(tracee); 140 138 141 139 return error; 142 140 } ··· 1022 1020 return aa_sock_perm(OP_SHUTDOWN, AA_MAY_SHUTDOWN, sock); 1023 1021 } 1024 1022 1023 + #ifdef CONFIG_NETWORK_SECMARK 1025 1024 /** 1026 1025 * apparmor_socket_sock_recv_skb - check perms before associating skb to sk 1027 1026 * ··· 1033 1030 */ 1034 1031 static int apparmor_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) 1035 1032 { 1036 - return 0; 1033 + struct aa_sk_ctx *ctx = SK_CTX(sk); 1034 + 1035 + if (!skb->secmark) 1036 + return 0; 1037 + 1038 + return apparmor_secmark_check(ctx->label, OP_RECVMSG, AA_MAY_RECEIVE, 1039 + skb->secmark, sk); 1037 1040 } 1041 + #endif 1038 1042 1039 1043 1040 1044 static struct aa_label *sk_peer_label(struct sock *sk) ··· 1136 1126 ctx->label = aa_get_current_label(); 1137 1127 } 1138 1128 1129 + #ifdef CONFIG_NETWORK_SECMARK 1130 + static int apparmor_inet_conn_request(struct sock *sk, struct sk_buff *skb, 1131 + struct request_sock *req) 1132 + { 1133 + struct aa_sk_ctx *ctx = SK_CTX(sk); 1134 + 1135 + if (!skb->secmark) 1136 + return 0; 1137 + 1138 + return apparmor_secmark_check(ctx->label, OP_CONNECT, AA_MAY_CONNECT, 1139 + skb->secmark, sk); 1140 + } 1141 + #endif 1142 + 1139 1143 static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = { 1140 1144 LSM_HOOK_INIT(ptrace_access_check, apparmor_ptrace_access_check), 1141 1145 LSM_HOOK_INIT(ptrace_traceme, apparmor_ptrace_traceme), ··· 1201 1177 LSM_HOOK_INIT(socket_getsockopt, apparmor_socket_getsockopt), 1202 1178 LSM_HOOK_INIT(socket_setsockopt, apparmor_socket_setsockopt), 1203 1179 LSM_HOOK_INIT(socket_shutdown, apparmor_socket_shutdown), 1180 + #ifdef CONFIG_NETWORK_SECMARK 1204 1181 LSM_HOOK_INIT(socket_sock_rcv_skb, apparmor_socket_sock_rcv_skb), 1182 + #endif 1205 1183 LSM_HOOK_INIT(socket_getpeersec_stream, 1206 1184 apparmor_socket_getpeersec_stream), 1207 1185 LSM_HOOK_INIT(socket_getpeersec_dgram, 1208 1186 apparmor_socket_getpeersec_dgram), 1209 1187 LSM_HOOK_INIT(sock_graft, apparmor_sock_graft), 1188 + #ifdef CONFIG_NETWORK_SECMARK 1189 + LSM_HOOK_INIT(inet_conn_request, apparmor_inet_conn_request), 1190 + #endif 1210 1191 1211 1192 LSM_HOOK_INIT(cred_alloc_blank, apparmor_cred_alloc_blank), 1212 1193 LSM_HOOK_INIT(cred_free, apparmor_cred_free), ··· 1566 1537 return 0; 1567 1538 } 1568 1539 #endif /* CONFIG_SYSCTL */ 1540 + 1541 + #if defined(CONFIG_NETFILTER) && defined(CONFIG_NETWORK_SECMARK) 1542 + static unsigned int apparmor_ip_postroute(void *priv, 1543 + struct sk_buff *skb, 1544 + const struct nf_hook_state *state) 1545 + { 1546 + struct aa_sk_ctx *ctx; 1547 + struct sock *sk; 1548 + 1549 + if (!skb->secmark) 1550 + return NF_ACCEPT; 1551 + 1552 + sk = skb_to_full_sk(skb); 1553 + if (sk == NULL) 1554 + return NF_ACCEPT; 1555 + 1556 + ctx = SK_CTX(sk); 1557 + if (!apparmor_secmark_check(ctx->label, OP_SENDMSG, AA_MAY_SEND, 1558 + skb->secmark, sk)) 1559 + return NF_ACCEPT; 1560 + 1561 + return NF_DROP_ERR(-ECONNREFUSED); 1562 + 1563 + } 1564 + 1565 + static unsigned int apparmor_ipv4_postroute(void *priv, 1566 + struct sk_buff *skb, 1567 + const struct nf_hook_state *state) 1568 + { 1569 + return apparmor_ip_postroute(priv, skb, state); 1570 + } 1571 + 1572 + static unsigned int apparmor_ipv6_postroute(void *priv, 1573 + struct sk_buff *skb, 1574 + const struct nf_hook_state *state) 1575 + { 1576 + return apparmor_ip_postroute(priv, skb, state); 1577 + } 1578 + 1579 + static const struct nf_hook_ops apparmor_nf_ops[] = { 1580 + { 1581 + .hook = apparmor_ipv4_postroute, 1582 + .pf = NFPROTO_IPV4, 1583 + .hooknum = NF_INET_POST_ROUTING, 1584 + .priority = NF_IP_PRI_SELINUX_FIRST, 1585 + }, 1586 + #if IS_ENABLED(CONFIG_IPV6) 1587 + { 1588 + .hook = apparmor_ipv6_postroute, 1589 + .pf = NFPROTO_IPV6, 1590 + .hooknum = NF_INET_POST_ROUTING, 1591 + .priority = NF_IP6_PRI_SELINUX_FIRST, 1592 + }, 1593 + #endif 1594 + }; 1595 + 1596 + static int __net_init apparmor_nf_register(struct net *net) 1597 + { 1598 + int ret; 1599 + 1600 + ret = nf_register_net_hooks(net, apparmor_nf_ops, 1601 + ARRAY_SIZE(apparmor_nf_ops)); 1602 + return ret; 1603 + } 1604 + 1605 + static void __net_exit apparmor_nf_unregister(struct net *net) 1606 + { 1607 + nf_unregister_net_hooks(net, apparmor_nf_ops, 1608 + ARRAY_SIZE(apparmor_nf_ops)); 1609 + } 1610 + 1611 + static struct pernet_operations apparmor_net_ops = { 1612 + .init = apparmor_nf_register, 1613 + .exit = apparmor_nf_unregister, 1614 + }; 1615 + 1616 + static int __init apparmor_nf_ip_init(void) 1617 + { 1618 + int err; 1619 + 1620 + if (!apparmor_enabled) 1621 + return 0; 1622 + 1623 + err = register_pernet_subsys(&apparmor_net_ops); 1624 + if (err) 1625 + panic("Apparmor: register_pernet_subsys: error %d\n", err); 1626 + 1627 + return 0; 1628 + } 1629 + __initcall(apparmor_nf_ip_init); 1630 + #endif 1569 1631 1570 1632 static int __init apparmor_init(void) 1571 1633 {
+77 -6
security/apparmor/net.c
··· 18 18 #include "include/label.h" 19 19 #include "include/net.h" 20 20 #include "include/policy.h" 21 + #include "include/secid.h" 21 22 22 23 #include "net_names.h" 23 24 ··· 147 146 static int aa_label_sk_perm(struct aa_label *label, const char *op, u32 request, 148 147 struct sock *sk) 149 148 { 150 - struct aa_profile *profile; 151 - DEFINE_AUDIT_SK(sa, op, sk); 149 + int error = 0; 152 150 153 151 AA_BUG(!label); 154 152 AA_BUG(!sk); 155 153 156 - if (unconfined(label)) 157 - return 0; 154 + if (!unconfined(label)) { 155 + struct aa_profile *profile; 156 + DEFINE_AUDIT_SK(sa, op, sk); 158 157 159 - return fn_for_each_confined(label, profile, 160 - aa_profile_af_sk_perm(profile, &sa, request, sk)); 158 + error = fn_for_each_confined(label, profile, 159 + aa_profile_af_sk_perm(profile, &sa, request, sk)); 160 + } 161 + 162 + return error; 161 163 } 162 164 163 165 int aa_sk_perm(const char *op, u32 request, struct sock *sk) ··· 189 185 190 186 return aa_label_sk_perm(label, op, request, sock->sk); 191 187 } 188 + 189 + #ifdef CONFIG_NETWORK_SECMARK 190 + static int apparmor_secmark_init(struct aa_secmark *secmark) 191 + { 192 + struct aa_label *label; 193 + 194 + if (secmark->label[0] == '*') { 195 + secmark->secid = AA_SECID_WILDCARD; 196 + return 0; 197 + } 198 + 199 + label = aa_label_strn_parse(&root_ns->unconfined->label, 200 + secmark->label, strlen(secmark->label), 201 + GFP_ATOMIC, false, false); 202 + 203 + if (IS_ERR(label)) 204 + return PTR_ERR(label); 205 + 206 + secmark->secid = label->secid; 207 + 208 + return 0; 209 + } 210 + 211 + static int aa_secmark_perm(struct aa_profile *profile, u32 request, u32 secid, 212 + struct common_audit_data *sa, struct sock *sk) 213 + { 214 + int i, ret; 215 + struct aa_perms perms = { }; 216 + 217 + if (profile->secmark_count == 0) 218 + return 0; 219 + 220 + for (i = 0; i < profile->secmark_count; i++) { 221 + if (!profile->secmark[i].secid) { 222 + ret = apparmor_secmark_init(&profile->secmark[i]); 223 + if (ret) 224 + return ret; 225 + } 226 + 227 + if (profile->secmark[i].secid == secid || 228 + profile->secmark[i].secid == AA_SECID_WILDCARD) { 229 + if (profile->secmark[i].deny) 230 + perms.deny = ALL_PERMS_MASK; 231 + else 232 + perms.allow = ALL_PERMS_MASK; 233 + 234 + if (profile->secmark[i].audit) 235 + perms.audit = ALL_PERMS_MASK; 236 + } 237 + } 238 + 239 + aa_apply_modes_to_perms(profile, &perms); 240 + 241 + return aa_check_perms(profile, &perms, request, sa, audit_net_cb); 242 + } 243 + 244 + int apparmor_secmark_check(struct aa_label *label, char *op, u32 request, 245 + u32 secid, struct sock *sk) 246 + { 247 + struct aa_profile *profile; 248 + DEFINE_AUDIT_SK(sa, op, sk); 249 + 250 + return fn_for_each_confined(label, profile, 251 + aa_secmark_perm(profile, request, secid, 252 + &sa, sk)); 253 + } 254 + #endif
+3
security/apparmor/policy.c
··· 231 231 for (i = 0; i < profile->xattr_count; i++) 232 232 kzfree(profile->xattrs[i]); 233 233 kzfree(profile->xattrs); 234 + for (i = 0; i < profile->secmark_count; i++) 235 + kzfree(profile->secmark[i].label); 236 + kzfree(profile->secmark); 234 237 kzfree(profile->dirname); 235 238 aa_put_dfa(profile->xmatch); 236 239 aa_put_dfa(profile->policy.dfa);
+61
security/apparmor/policy_unpack.c
··· 292 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 308 static bool unpack_u32(struct aa_ext *e, u32 *data, const char *name) 296 309 { 297 310 if (unpack_nameX(e, AA_U32, name)) { ··· 542 529 return 0; 543 530 } 544 531 532 + static bool unpack_secmark(struct aa_ext *e, struct aa_profile *profile) 533 + { 534 + void *pos = e->pos; 535 + int i, size; 536 + 537 + if (unpack_nameX(e, AA_STRUCT, "secmark")) { 538 + size = unpack_array(e, NULL); 539 + 540 + profile->secmark = kcalloc(size, sizeof(struct aa_secmark), 541 + GFP_KERNEL); 542 + if (!profile->secmark) 543 + goto fail; 544 + 545 + profile->secmark_count = size; 546 + 547 + for (i = 0; i < size; i++) { 548 + if (!unpack_u8(e, &profile->secmark[i].audit, NULL)) 549 + goto fail; 550 + if (!unpack_u8(e, &profile->secmark[i].deny, NULL)) 551 + goto fail; 552 + if (!unpack_strdup(e, &profile->secmark[i].label, NULL)) 553 + goto fail; 554 + } 555 + if (!unpack_nameX(e, AA_ARRAYEND, NULL)) 556 + goto fail; 557 + if (!unpack_nameX(e, AA_STRUCTEND, NULL)) 558 + goto fail; 559 + } 560 + 561 + return 1; 562 + 563 + fail: 564 + if (profile->secmark) { 565 + for (i = 0; i < size; i++) 566 + kfree(profile->secmark[i].label); 567 + kfree(profile->secmark); 568 + profile->secmark_count = 0; 569 + } 570 + 571 + e->pos = pos; 572 + return 0; 573 + } 574 + 545 575 static bool unpack_rlimits(struct aa_ext *e, struct aa_profile *profile) 546 576 { 547 577 void *pos = e->pos; ··· 780 724 781 725 if (!unpack_rlimits(e, profile)) { 782 726 info = "failed to unpack profile rlimits"; 727 + goto fail; 728 + } 729 + 730 + if (!unpack_secmark(e, profile)) { 731 + info = "failed to unpack profile secmark rules"; 783 732 goto fail; 784 733 } 785 734
+1 -2
security/apparmor/secid.c
··· 32 32 * secids - do not pin labels with a refcount. They rely on the label 33 33 * properly updating/freeing them 34 34 */ 35 - 36 - #define AA_FIRST_SECID 1 35 + #define AA_FIRST_SECID 2 37 36 38 37 static DEFINE_IDR(aa_secids); 39 38 static DEFINE_SPINLOCK(secid_lock);