diff options
Diffstat (limited to 'security')
-rw-r--r-- | security/smack/smack_lsm.c | 106 |
1 files changed, 63 insertions, 43 deletions
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 489a85afa477..04a98c361a65 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c | |||
@@ -1667,10 +1667,13 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name, | |||
1667 | ssp->smk_in = sp; | 1667 | ssp->smk_in = sp; |
1668 | else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) { | 1668 | else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) { |
1669 | ssp->smk_out = sp; | 1669 | ssp->smk_out = sp; |
1670 | rc = smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET); | 1670 | if (sock->sk->sk_family != PF_UNIX) { |
1671 | if (rc != 0) | 1671 | rc = smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET); |
1672 | printk(KERN_WARNING "Smack: \"%s\" netlbl error %d.\n", | 1672 | if (rc != 0) |
1673 | __func__, -rc); | 1673 | printk(KERN_WARNING |
1674 | "Smack: \"%s\" netlbl error %d.\n", | ||
1675 | __func__, -rc); | ||
1676 | } | ||
1674 | } else | 1677 | } else |
1675 | return -EOPNOTSUPP; | 1678 | return -EOPNOTSUPP; |
1676 | 1679 | ||
@@ -2267,9 +2270,10 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) | |||
2267 | break; | 2270 | break; |
2268 | case SOCKFS_MAGIC: | 2271 | case SOCKFS_MAGIC: |
2269 | /* | 2272 | /* |
2270 | * Casey says sockets get the smack of the task. | 2273 | * Socket access is controlled by the socket |
2274 | * structures associated with the task involved. | ||
2271 | */ | 2275 | */ |
2272 | final = csp; | 2276 | final = smack_known_star.smk_known; |
2273 | break; | 2277 | break; |
2274 | case PROC_SUPER_MAGIC: | 2278 | case PROC_SUPER_MAGIC: |
2275 | /* | 2279 | /* |
@@ -2296,7 +2300,16 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) | |||
2296 | /* | 2300 | /* |
2297 | * This isn't an understood special case. | 2301 | * This isn't an understood special case. |
2298 | * Get the value from the xattr. | 2302 | * Get the value from the xattr. |
2299 | * | 2303 | */ |
2304 | |||
2305 | /* | ||
2306 | * UNIX domain sockets use lower level socket data. | ||
2307 | */ | ||
2308 | if (S_ISSOCK(inode->i_mode)) { | ||
2309 | final = smack_known_star.smk_known; | ||
2310 | break; | ||
2311 | } | ||
2312 | /* | ||
2300 | * No xattr support means, alas, no SMACK label. | 2313 | * No xattr support means, alas, no SMACK label. |
2301 | * Use the aforeapplied default. | 2314 | * Use the aforeapplied default. |
2302 | * It would be curious if the label of the task | 2315 | * It would be curious if the label of the task |
@@ -2418,14 +2431,18 @@ static int smack_setprocattr(struct task_struct *p, char *name, | |||
2418 | static int smack_unix_stream_connect(struct socket *sock, | 2431 | static int smack_unix_stream_connect(struct socket *sock, |
2419 | struct socket *other, struct sock *newsk) | 2432 | struct socket *other, struct sock *newsk) |
2420 | { | 2433 | { |
2421 | struct inode *sp = SOCK_INODE(sock); | 2434 | struct socket_smack *ssp = sock->sk->sk_security; |
2422 | struct inode *op = SOCK_INODE(other); | 2435 | struct socket_smack *osp = other->sk->sk_security; |
2423 | struct smk_audit_info ad; | 2436 | struct smk_audit_info ad; |
2437 | int rc = 0; | ||
2424 | 2438 | ||
2425 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET); | 2439 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET); |
2426 | smk_ad_setfield_u_net_sk(&ad, other->sk); | 2440 | smk_ad_setfield_u_net_sk(&ad, other->sk); |
2427 | return smk_access(smk_of_inode(sp), smk_of_inode(op), | 2441 | |
2428 | MAY_READWRITE, &ad); | 2442 | if (!capable(CAP_MAC_OVERRIDE)) |
2443 | rc = smk_access(ssp->smk_out, osp->smk_in, MAY_WRITE, &ad); | ||
2444 | |||
2445 | return rc; | ||
2429 | } | 2446 | } |
2430 | 2447 | ||
2431 | /** | 2448 | /** |
@@ -2438,13 +2455,18 @@ static int smack_unix_stream_connect(struct socket *sock, | |||
2438 | */ | 2455 | */ |
2439 | static int smack_unix_may_send(struct socket *sock, struct socket *other) | 2456 | static int smack_unix_may_send(struct socket *sock, struct socket *other) |
2440 | { | 2457 | { |
2441 | struct inode *sp = SOCK_INODE(sock); | 2458 | struct socket_smack *ssp = sock->sk->sk_security; |
2442 | struct inode *op = SOCK_INODE(other); | 2459 | struct socket_smack *osp = other->sk->sk_security; |
2443 | struct smk_audit_info ad; | 2460 | struct smk_audit_info ad; |
2461 | int rc = 0; | ||
2444 | 2462 | ||
2445 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET); | 2463 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET); |
2446 | smk_ad_setfield_u_net_sk(&ad, other->sk); | 2464 | smk_ad_setfield_u_net_sk(&ad, other->sk); |
2447 | return smk_access(smk_of_inode(sp), smk_of_inode(op), MAY_WRITE, &ad); | 2465 | |
2466 | if (!capable(CAP_MAC_OVERRIDE)) | ||
2467 | rc = smk_access(ssp->smk_out, osp->smk_in, MAY_WRITE, &ad); | ||
2468 | |||
2469 | return rc; | ||
2448 | } | 2470 | } |
2449 | 2471 | ||
2450 | /** | 2472 | /** |
@@ -2629,7 +2651,7 @@ static int smack_socket_getpeersec_stream(struct socket *sock, | |||
2629 | 2651 | ||
2630 | /** | 2652 | /** |
2631 | * smack_socket_getpeersec_dgram - pull in packet label | 2653 | * smack_socket_getpeersec_dgram - pull in packet label |
2632 | * @sock: the socket | 2654 | * @sock: the peer socket |
2633 | * @skb: packet data | 2655 | * @skb: packet data |
2634 | * @secid: pointer to where to put the secid of the packet | 2656 | * @secid: pointer to where to put the secid of the packet |
2635 | * | 2657 | * |
@@ -2640,41 +2662,39 @@ static int smack_socket_getpeersec_dgram(struct socket *sock, | |||
2640 | 2662 | ||
2641 | { | 2663 | { |
2642 | struct netlbl_lsm_secattr secattr; | 2664 | struct netlbl_lsm_secattr secattr; |
2643 | struct sock *sk; | 2665 | struct socket_smack *sp; |
2644 | char smack[SMK_LABELLEN]; | 2666 | char smack[SMK_LABELLEN]; |
2645 | int family = PF_INET; | 2667 | int family = PF_UNSPEC; |
2646 | u32 s; | 2668 | u32 s = 0; /* 0 is the invalid secid */ |
2647 | int rc; | 2669 | int rc; |
2648 | 2670 | ||
2649 | /* | 2671 | if (skb != NULL) { |
2650 | * Only works for families with packets. | 2672 | if (skb->protocol == htons(ETH_P_IP)) |
2651 | */ | 2673 | family = PF_INET; |
2652 | if (sock != NULL) { | 2674 | else if (skb->protocol == htons(ETH_P_IPV6)) |
2653 | sk = sock->sk; | 2675 | family = PF_INET6; |
2654 | if (sk->sk_family != PF_INET && sk->sk_family != PF_INET6) | ||
2655 | return 0; | ||
2656 | family = sk->sk_family; | ||
2657 | } | 2676 | } |
2658 | /* | 2677 | if (family == PF_UNSPEC && sock != NULL) |
2659 | * Translate what netlabel gave us. | 2678 | family = sock->sk->sk_family; |
2660 | */ | ||
2661 | netlbl_secattr_init(&secattr); | ||
2662 | rc = netlbl_skbuff_getattr(skb, family, &secattr); | ||
2663 | if (rc == 0) | ||
2664 | smack_from_secattr(&secattr, smack); | ||
2665 | netlbl_secattr_destroy(&secattr); | ||
2666 | |||
2667 | /* | ||
2668 | * Give up if we couldn't get anything | ||
2669 | */ | ||
2670 | if (rc != 0) | ||
2671 | return rc; | ||
2672 | 2679 | ||
2673 | s = smack_to_secid(smack); | 2680 | if (family == PF_UNIX) { |
2681 | sp = sock->sk->sk_security; | ||
2682 | s = smack_to_secid(sp->smk_out); | ||
2683 | } else if (family == PF_INET || family == PF_INET6) { | ||
2684 | /* | ||
2685 | * Translate what netlabel gave us. | ||
2686 | */ | ||
2687 | netlbl_secattr_init(&secattr); | ||
2688 | rc = netlbl_skbuff_getattr(skb, family, &secattr); | ||
2689 | if (rc == 0) { | ||
2690 | smack_from_secattr(&secattr, smack); | ||
2691 | s = smack_to_secid(smack); | ||
2692 | } | ||
2693 | netlbl_secattr_destroy(&secattr); | ||
2694 | } | ||
2695 | *secid = s; | ||
2674 | if (s == 0) | 2696 | if (s == 0) |
2675 | return -EINVAL; | 2697 | return -EINVAL; |
2676 | |||
2677 | *secid = s; | ||
2678 | return 0; | 2698 | return 0; |
2679 | } | 2699 | } |
2680 | 2700 | ||