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.

apparmor: make sure unix socket labeling is correctly updated.

When a unix socket is passed into a different confinement domain make
sure its cached mediation labeling is updated to correctly reflect
which domains are using the socket.

Fixes: c05e705812d1 ("apparmor: add fine grained af_unix mediation")
Signed-off-by: John Johansen <john.johansen@canonical.com>

+231 -62
+76 -3
security/apparmor/af_unix.c
··· 646 646 peer_label); 647 647 } 648 648 649 + /* sk_plabel for comparison only */ 650 + static void update_sk_ctx(struct sock *sk, struct aa_label *label, 651 + struct aa_label *plabel) 652 + { 653 + struct aa_label *l, *old; 654 + struct aa_sk_ctx *ctx = aa_sock(sk); 655 + bool update_sk; 656 + 657 + rcu_read_lock(); 658 + update_sk = (plabel && 659 + (plabel != rcu_access_pointer(ctx->peer_lastupdate) || 660 + !aa_label_is_subset(plabel, rcu_dereference(ctx->peer)))) || 661 + !__aa_subj_label_is_cached(label, rcu_dereference(ctx->label)); 662 + rcu_read_unlock(); 663 + if (!update_sk) 664 + return; 665 + 666 + spin_lock(&unix_sk(sk)->lock); 667 + old = rcu_dereference_protected(ctx->label, 668 + lockdep_is_held(&unix_sk(sk)->lock)); 669 + l = aa_label_merge(old, label, GFP_ATOMIC); 670 + if (l) { 671 + if (l != old) { 672 + rcu_assign_pointer(ctx->label, l); 673 + aa_put_label(old); 674 + } else 675 + aa_put_label(l); 676 + } 677 + if (plabel && rcu_access_pointer(ctx->peer_lastupdate) != plabel) { 678 + old = rcu_dereference_protected(ctx->peer, lockdep_is_held(&unix_sk(sk)->lock)); 679 + 680 + if (old == plabel) { 681 + rcu_assign_pointer(ctx->peer_lastupdate, plabel); 682 + } else if (aa_label_is_subset(plabel, old)) { 683 + rcu_assign_pointer(ctx->peer_lastupdate, plabel); 684 + rcu_assign_pointer(ctx->peer, aa_get_label(plabel)); 685 + aa_put_label(old); 686 + } /* else race or a subset - don't update */ 687 + } 688 + spin_unlock(&unix_sk(sk)->lock); 689 + } 690 + 691 + static void update_peer_ctx(struct sock *sk, struct aa_sk_ctx *ctx, 692 + struct aa_label *label) 693 + { 694 + struct aa_label *l, *old; 695 + 696 + spin_lock(&unix_sk(sk)->lock); 697 + old = rcu_dereference_protected(ctx->peer, 698 + lockdep_is_held(&unix_sk(sk)->lock)); 699 + l = aa_label_merge(old, label, GFP_ATOMIC); 700 + if (l) { 701 + if (l != old) { 702 + rcu_assign_pointer(ctx->peer, l); 703 + aa_put_label(old); 704 + } else 705 + aa_put_label(l); 706 + } 707 + spin_unlock(&unix_sk(sk)->lock); 708 + } 709 + 649 710 /* This fn is only checked if something has changed in the security 650 711 * boundaries. Otherwise cached info off file is sufficient 651 712 */ ··· 716 655 struct socket *sock = (struct socket *) file->private_data; 717 656 struct sockaddr_un *addr, *peer_addr; 718 657 int addrlen, peer_addrlen; 658 + struct aa_label *plabel = NULL; 719 659 struct sock *peer_sk = NULL; 720 660 u32 sk_req = request & ~NET_PEER_MASK; 721 661 struct path path; ··· 728 666 AA_BUG(!sock->sk); 729 667 AA_BUG(sock->sk->sk_family != PF_UNIX); 730 668 731 - /* TODO: update sock label with new task label */ 732 669 /* investigate only using lock via unix_peer_get() 733 670 * addr only needs the memory barrier, but need to investigate 734 671 * path ··· 762 701 unix_fs_perm(op, request, subj_cred, label, 763 702 is_unix_fs(peer_sk) ? &peer_path : NULL)); 764 703 } else if (!is_sk_fs) { 704 + struct aa_label *plabel; 765 705 struct aa_sk_ctx *pctx = aa_sock(peer_sk); 766 706 707 + rcu_read_lock(); 708 + plabel = aa_get_label_rcu(&pctx->label); 709 + rcu_read_unlock(); 767 710 /* no fs check of aa_unix_peer_perm because conditions above 768 711 * ensure they will never be done 769 712 */ ··· 778 713 peer_addr, peer_addrlen, 779 714 is_unix_fs(peer_sk) ? 780 715 &peer_path : NULL, 781 - pctx->label), 782 - unix_peer_perm(file->f_cred, pctx->label, op, 716 + plabel), 717 + unix_peer_perm(file->f_cred, plabel, op, 783 718 MAY_READ | MAY_WRITE, peer_sk, 784 719 is_unix_fs(peer_sk) ? 785 720 &peer_path : NULL, 786 721 addr, addrlen, 787 722 is_sk_fs ? &path : NULL, 788 723 label))); 724 + if (!error && !__aa_subj_label_is_cached(plabel, label)) 725 + update_peer_ctx(peer_sk, pctx, label); 789 726 } 790 727 sock_put(peer_sk); 791 728 792 729 out: 793 730 731 + /* update peer cache to latest successful perm check */ 732 + if (error == 0) 733 + update_sk_ctx(sock->sk, label, plabel); 734 + aa_put_label(plabel); 735 + 794 736 return error; 795 737 } 738 +
+26 -9
security/apparmor/file.c
··· 561 561 return error; 562 562 } 563 563 564 - /* wrapper fn to indicate semantics of the check */ 565 - static bool __subj_label_is_cached(struct aa_label *subj_label, 566 - struct aa_label *obj_label) 567 - { 568 - return aa_label_is_subset(obj_label, subj_label); 569 - } 570 - 571 564 /* for now separate fn to indicate semantics of the check */ 572 565 static bool __file_is_delegated(struct aa_label *obj_label) 573 566 { 574 567 return unconfined(obj_label); 568 + } 569 + 570 + static bool __unix_needs_revalidation(struct file *file, struct aa_label *label, 571 + u32 request) 572 + { 573 + struct socket *sock = (struct socket *) file->private_data; 574 + 575 + lockdep_assert_in_rcu_read_lock(); 576 + 577 + if (!S_ISSOCK(file_inode(file)->i_mode)) 578 + return false; 579 + if (request & NET_PEER_MASK) 580 + return false; 581 + if (sock->sk->sk_family == PF_UNIX) { 582 + struct aa_sk_ctx *ctx = aa_sock(sock->sk); 583 + 584 + if (rcu_access_pointer(ctx->peer) != 585 + rcu_access_pointer(ctx->peer_lastupdate)) 586 + return true; 587 + return !__aa_subj_label_is_cached(rcu_dereference(ctx->label), 588 + label); 589 + } 590 + return false; 575 591 } 576 592 577 593 /** ··· 628 612 */ 629 613 denied = request & ~fctx->allow; 630 614 if (unconfined(label) || __file_is_delegated(flabel) || 631 - (!denied && __subj_label_is_cached(label, flabel))) { 615 + __unix_needs_revalidation(file, label, request) || 616 + (!denied && __aa_subj_label_is_cached(label, flabel))) { 632 617 rcu_read_unlock(); 633 618 goto done; 634 619 } 635 620 621 + /* slow path - revalidate access */ 636 622 flabel = aa_get_newest_label(flabel); 637 623 rcu_read_unlock(); 638 - /* TODO: label cross check */ 639 624 640 625 if (file->f_path.mnt && path_mediated_fs(file->f_path.dentry)) 641 626 error = __file_path_perm(op, subj_cred, label, flabel, file,
+7
security/apparmor/include/label.h
··· 415 415 kref_put(&l->count, aa_label_kref); 416 416 } 417 417 418 + /* wrapper fn to indicate semantics of the check */ 419 + static inline bool __aa_subj_label_is_cached(struct aa_label *subj_label, 420 + struct aa_label *obj_label) 421 + { 422 + return aa_label_is_subset(obj_label, subj_label); 423 + } 424 + 418 425 419 426 struct aa_proxy *aa_alloc_proxy(struct aa_label *l, gfp_t gfp); 420 427 void aa_proxy_kref(struct kref *kref);
+3 -2
security/apparmor/include/net.h
··· 47 47 #define NET_PEER_MASK (AA_MAY_SEND | AA_MAY_RECEIVE | AA_MAY_CONNECT | \ 48 48 AA_MAY_ACCEPT) 49 49 struct aa_sk_ctx { 50 - struct aa_label *label; 51 - struct aa_label *peer; 50 + struct aa_label __rcu *label; 51 + struct aa_label __rcu *peer; 52 + struct aa_label __rcu *peer_lastupdate; /* ptr cmp only, no deref */ 52 53 }; 53 54 54 55 static inline struct aa_sk_ctx *aa_sock(const struct sock *sk)
+118 -47
security/apparmor/lsm.c
··· 508 508 struct aa_file_ctx *ctx = file_ctx(file); 509 509 struct aa_label *label = begin_current_label_crit_section(); 510 510 511 - spin_lock_init(&ctx->lock); 512 511 rcu_assign_pointer(ctx->label, aa_get_label(label)); 513 512 end_current_label_crit_section(label); 514 513 return 0; ··· 1075 1076 return error; 1076 1077 } 1077 1078 1079 + static int apparmor_sk_alloc_security(struct sock *sk, int family, gfp_t gfp) 1080 + { 1081 + struct aa_sk_ctx *ctx = aa_sock(sk); 1082 + struct aa_label *label; 1083 + bool needput; 1084 + 1085 + label = __begin_current_label_crit_section(&needput); 1086 + //spin_lock_init(&ctx->lock); 1087 + rcu_assign_pointer(ctx->label, aa_get_label(label)); 1088 + rcu_assign_pointer(ctx->peer, NULL); 1089 + rcu_assign_pointer(ctx->peer_lastupdate, NULL); 1090 + __end_current_label_crit_section(label, needput); 1091 + return 0; 1092 + } 1093 + 1078 1094 static void apparmor_sk_free_security(struct sock *sk) 1079 1095 { 1080 1096 struct aa_sk_ctx *ctx = aa_sock(sk); 1081 1097 1082 - aa_put_label(ctx->label); 1083 - aa_put_label(ctx->peer); 1098 + /* dead these won't be updated any more */ 1099 + aa_put_label(rcu_dereference_protected(ctx->label, true)); 1100 + aa_put_label(rcu_dereference_protected(ctx->peer, true)); 1101 + aa_put_label(rcu_dereference_protected(ctx->peer_lastupdate, true)); 1084 1102 } 1085 1103 1086 1104 /** ··· 1111 1095 struct aa_sk_ctx *ctx = aa_sock(sk); 1112 1096 struct aa_sk_ctx *new = aa_sock(newsk); 1113 1097 1114 - if (new->label) 1115 - aa_put_label(new->label); 1116 - new->label = aa_get_label(ctx->label); 1098 + /* not actually in use yet */ 1099 + if (rcu_access_pointer(ctx->label) != rcu_access_pointer(new->label)) { 1100 + aa_put_label(rcu_dereference_protected(new->label, true)); 1101 + rcu_assign_pointer(new->label, aa_get_label_rcu(&ctx->label)); 1102 + } 1117 1103 1118 - if (new->peer) 1119 - aa_put_label(new->peer); 1120 - new->peer = aa_get_label(ctx->peer); 1104 + if (rcu_access_pointer(ctx->peer) != rcu_access_pointer(new->peer)) { 1105 + aa_put_label(rcu_dereference_protected(new->peer, true)); 1106 + rcu_assign_pointer(new->peer, aa_get_label_rcu(&ctx->peer)); 1107 + } 1108 + 1109 + if (rcu_access_pointer(ctx->peer_lastupdate) != rcu_access_pointer(new->peer_lastupdate)) { 1110 + aa_put_label(rcu_dereference_protected(new->peer_lastupdate, true)); 1111 + rcu_assign_pointer(new->peer_lastupdate, 1112 + aa_get_label_rcu(&ctx->peer_lastupdate)); 1113 + } 1121 1114 } 1122 1115 1123 1116 static int unix_connect_perm(const struct cred *cred, struct aa_label *label, ··· 1137 1112 1138 1113 error = aa_unix_peer_perm(cred, label, OP_CONNECT, 1139 1114 (AA_MAY_CONNECT | AA_MAY_SEND | AA_MAY_RECEIVE), 1140 - sk, peer_sk, peer_ctx->label); 1115 + sk, peer_sk, 1116 + rcu_dereference_protected(peer_ctx->label, 1117 + lockdep_is_held(&unix_sk(peer_sk)->lock))); 1141 1118 if (!is_unix_fs(peer_sk)) { 1142 1119 last_error(error, 1143 1120 aa_unix_peer_perm(cred, 1144 - peer_ctx->label, OP_CONNECT, 1121 + rcu_dereference_protected(peer_ctx->label, 1122 + lockdep_is_held(&unix_sk(peer_sk)->lock)), 1123 + OP_CONNECT, 1145 1124 (AA_MAY_ACCEPT | AA_MAY_SEND | AA_MAY_RECEIVE), 1146 - peer_sk, sk, label)); 1125 + peer_sk, sk, label)); 1147 1126 } 1148 1127 1149 1128 return error; 1150 1129 } 1151 1130 1131 + /* lockdep check in unix_connect_perm - push sks here to check */ 1152 1132 static void unix_connect_peers(struct aa_sk_ctx *sk_ctx, 1153 1133 struct aa_sk_ctx *peer_ctx) 1154 1134 { 1155 1135 /* Cross reference the peer labels for SO_PEERSEC */ 1156 - aa_put_label(peer_ctx->peer); 1157 - aa_put_label(sk_ctx->peer); 1136 + struct aa_label *label = rcu_dereference_protected(sk_ctx->label, true); 1158 1137 1159 - peer_ctx->peer = aa_get_label(sk_ctx->label); 1160 - sk_ctx->peer = aa_get_label(peer_ctx->label); 1138 + aa_get_label(label); 1139 + aa_put_label(rcu_dereference_protected(peer_ctx->peer, 1140 + true)); 1141 + rcu_assign_pointer(peer_ctx->peer, label); /* transfer cnt */ 1142 + 1143 + label = aa_get_label(rcu_dereference_protected(peer_ctx->label, 1144 + true)); 1145 + //spin_unlock(&peer_ctx->lock); 1146 + 1147 + //spin_lock(&sk_ctx->lock); 1148 + aa_put_label(rcu_dereference_protected(sk_ctx->peer, 1149 + true)); 1150 + aa_put_label(rcu_dereference_protected(sk_ctx->peer_lastupdate, 1151 + true)); 1152 + 1153 + rcu_assign_pointer(sk_ctx->peer, aa_get_label(label)); 1154 + rcu_assign_pointer(sk_ctx->peer_lastupdate, label); /* transfer cnt */ 1155 + //spin_unlock(&sk_ctx->lock); 1161 1156 } 1162 1157 1163 1158 /** ··· 1203 1158 return error; 1204 1159 1205 1160 /* newsk doesn't go through post_create */ 1206 - AA_BUG(new_ctx->label); 1207 - new_ctx->label = aa_get_label(peer_ctx->label); 1161 + AA_BUG(rcu_access_pointer(new_ctx->label)); 1162 + rcu_assign_pointer(new_ctx->label, 1163 + aa_get_label(rcu_dereference_protected(peer_ctx->label, 1164 + true))); 1208 1165 1209 1166 /* Cross reference the peer labels for SO_PEERSEC */ 1210 1167 unix_connect_peers(sk_ctx, new_ctx); ··· 1230 1183 1231 1184 label = __begin_current_label_crit_section(&needput); 1232 1185 error = xcheck(aa_unix_peer_perm(current_cred(), 1233 - label, OP_SENDMSG, AA_MAY_SEND, 1234 - sock->sk, peer->sk, peer_ctx->label), 1186 + label, OP_SENDMSG, AA_MAY_SEND, 1187 + sock->sk, peer->sk, 1188 + rcu_dereference_protected(peer_ctx->label, 1189 + true)), 1235 1190 aa_unix_peer_perm(peer->file ? peer->file->f_cred : NULL, 1236 - peer_ctx->label, OP_SENDMSG, 1237 - AA_MAY_RECEIVE, 1238 - peer->sk, sock->sk, label)); 1191 + rcu_dereference_protected(peer_ctx->label, 1192 + true), 1193 + OP_SENDMSG, AA_MAY_RECEIVE, peer->sk, 1194 + sock->sk, label)); 1239 1195 __end_current_label_crit_section(label, needput); 1240 1196 1241 1197 return error; ··· 1296 1246 if (sock->sk) { 1297 1247 struct aa_sk_ctx *ctx = aa_sock(sock->sk); 1298 1248 1299 - aa_put_label(ctx->label); 1300 - ctx->label = aa_get_label(label); 1249 + /* still not live */ 1250 + aa_put_label(rcu_dereference_protected(ctx->label, true)); 1251 + rcu_assign_pointer(ctx->label, aa_get_label(label)); 1301 1252 } 1302 1253 aa_put_label(label); 1303 1254 ··· 1311 1260 struct aa_sk_ctx *a_ctx = aa_sock(socka->sk); 1312 1261 struct aa_sk_ctx *b_ctx = aa_sock(sockb->sk); 1313 1262 struct aa_label *label; 1314 - int error = 0; 1315 1263 1316 - aa_put_label(a_ctx->label); 1317 - aa_put_label(b_ctx->label); 1318 - 1264 + /* socks not live yet - initial values set in sk_alloc */ 1319 1265 label = begin_current_label_crit_section(); 1320 - a_ctx->label = aa_get_label(label); 1321 - b_ctx->label = aa_get_label(label); 1266 + if (rcu_access_pointer(a_ctx->label) != label) { 1267 + AA_BUG("a_ctx != label"); 1268 + aa_put_label(rcu_dereference_protected(a_ctx->label, true)); 1269 + rcu_assign_pointer(a_ctx->label, aa_get_label(label)); 1270 + } 1271 + if (rcu_access_pointer(b_ctx->label) != label) { 1272 + AA_BUG("b_ctx != label"); 1273 + aa_put_label(rcu_dereference_protected(b_ctx->label, true)); 1274 + rcu_assign_pointer(b_ctx->label, aa_get_label(label)); 1275 + } 1322 1276 1323 1277 if (socka->sk->sk_family == PF_UNIX) { 1324 1278 /* unix socket pairs by-pass unix_stream_connect */ 1325 - if (!error) 1326 - unix_connect_peers(a_ctx, b_ctx); 1279 + unix_connect_peers(a_ctx, b_ctx); 1327 1280 } 1328 1281 end_current_label_crit_section(label); 1329 1282 1330 - return error; 1283 + return 0; 1331 1284 } 1332 1285 1333 1286 /** ··· 1485 1430 static int apparmor_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) 1486 1431 { 1487 1432 struct aa_sk_ctx *ctx = aa_sock(sk); 1433 + int error; 1488 1434 1489 1435 if (!skb->secmark) 1490 1436 return 0; ··· 1494 1438 * If reach here before socket_post_create hook is called, in which 1495 1439 * case label is null, drop the packet. 1496 1440 */ 1497 - if (!ctx->label) 1441 + if (!rcu_access_pointer(ctx->label)) 1498 1442 return -EACCES; 1499 1443 1500 - return apparmor_secmark_check(ctx->label, OP_RECVMSG, AA_MAY_RECEIVE, 1501 - skb->secmark, sk); 1444 + rcu_read_lock(); 1445 + error = apparmor_secmark_check(rcu_dereference(ctx->label), OP_RECVMSG, 1446 + AA_MAY_RECEIVE, skb->secmark, sk); 1447 + rcu_read_unlock(); 1448 + 1449 + return error; 1502 1450 } 1503 1451 #endif 1504 1452 ··· 1512 1452 struct aa_sk_ctx *ctx = aa_sock(sk); 1513 1453 struct aa_label *label = ERR_PTR(-ENOPROTOOPT); 1514 1454 1515 - if (ctx->peer) 1516 - return aa_get_label(ctx->peer); 1455 + if (rcu_access_pointer(ctx->peer)) 1456 + return aa_get_label_rcu(&ctx->peer); 1517 1457 1518 1458 if (sk->sk_family != PF_UNIX) 1519 1459 return ERR_PTR(-ENOPROTOOPT); ··· 1540 1480 struct aa_label *label; 1541 1481 struct aa_label *peer; 1542 1482 1543 - label = begin_current_label_crit_section(); 1544 1483 peer = sk_peer_get_label(sock->sk); 1545 1484 if (IS_ERR(peer)) { 1546 1485 error = PTR_ERR(peer); 1547 1486 goto done; 1548 1487 } 1488 + label = begin_current_label_crit_section(); 1549 1489 slen = aa_label_asxprint(&name, labels_ns(label), peer, 1550 1490 FLAG_SHOW_MODE | FLAG_VIEW_SUBNS | 1551 1491 FLAG_HIDDEN_UNCONFINED, GFP_KERNEL); ··· 1566 1506 error = -EFAULT; 1567 1507 1568 1508 done_put: 1509 + end_current_label_crit_section(label); 1569 1510 aa_put_label(peer); 1570 1511 done: 1571 - end_current_label_crit_section(label); 1572 1512 kfree(name); 1573 1513 return error; 1574 1514 } ··· 1604 1544 { 1605 1545 struct aa_sk_ctx *ctx = aa_sock(sk); 1606 1546 1607 - if (!ctx->label) 1608 - ctx->label = aa_get_current_label(); 1547 + /* setup - not live */ 1548 + if (!rcu_access_pointer(ctx->label)) 1549 + rcu_assign_pointer(ctx->label, aa_get_current_label()); 1609 1550 } 1610 1551 1611 1552 #ifdef CONFIG_NETWORK_SECMARK ··· 1614 1553 struct request_sock *req) 1615 1554 { 1616 1555 struct aa_sk_ctx *ctx = aa_sock(sk); 1556 + int error; 1617 1557 1618 1558 if (!skb->secmark) 1619 1559 return 0; 1620 1560 1621 - return apparmor_secmark_check(ctx->label, OP_CONNECT, AA_MAY_CONNECT, 1622 - skb->secmark, sk); 1561 + rcu_read_lock(); 1562 + error = apparmor_secmark_check(rcu_dereference(ctx->label), OP_CONNECT, 1563 + AA_MAY_CONNECT, skb->secmark, sk); 1564 + rcu_read_unlock(); 1565 + 1566 + return error; 1623 1567 } 1624 1568 #endif 1625 1569 ··· 1681 1615 LSM_HOOK_INIT(getprocattr, apparmor_getprocattr), 1682 1616 LSM_HOOK_INIT(setprocattr, apparmor_setprocattr), 1683 1617 1618 + LSM_HOOK_INIT(sk_alloc_security, apparmor_sk_alloc_security), 1684 1619 LSM_HOOK_INIT(sk_free_security, apparmor_sk_free_security), 1685 1620 LSM_HOOK_INIT(sk_clone_security, apparmor_sk_clone_security), 1686 1621 ··· 2333 2266 { 2334 2267 struct aa_sk_ctx *ctx; 2335 2268 struct sock *sk; 2269 + int error; 2336 2270 2337 2271 if (!skb->secmark) 2338 2272 return NF_ACCEPT; ··· 2343 2275 return NF_ACCEPT; 2344 2276 2345 2277 ctx = aa_sock(sk); 2346 - if (!apparmor_secmark_check(ctx->label, OP_SENDMSG, AA_MAY_SEND, 2347 - skb->secmark, sk)) 2278 + rcu_read_lock(); 2279 + error = apparmor_secmark_check(rcu_dereference(ctx->label), OP_SENDMSG, 2280 + AA_MAY_SEND, skb->secmark, sk); 2281 + rcu_read_unlock(); 2282 + if (!error) 2348 2283 return NF_ACCEPT; 2349 2284 2350 2285 return NF_DROP_ERR(-ECONNREFUSED);
+1 -1
security/apparmor/net.c
··· 292 292 AA_BUG(!label); 293 293 AA_BUG(!sk); 294 294 295 - if (ctx->label != kernel_t && !unconfined(label)) { 295 + if (rcu_access_pointer(ctx->label) != kernel_t && !unconfined(label)) { 296 296 struct aa_profile *profile; 297 297 DEFINE_AUDIT_SK(ad, op, subj_cred, sk); 298 298