aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to 'security')
-rw-r--r--security/dummy.c17
-rw-r--r--security/selinux/avc.c23
-rw-r--r--security/selinux/hooks.c155
-rw-r--r--security/selinux/include/av_inherit.h1
-rw-r--r--security/selinux/include/av_perm_to_string.h8
-rw-r--r--security/selinux/include/av_permissions.h32
-rw-r--r--security/selinux/include/avc_ss.h24
-rw-r--r--security/selinux/include/class_to_string.h2
-rw-r--r--security/selinux/include/flask.h2
-rw-r--r--security/selinux/include/objsec.h2
-rw-r--r--security/selinux/include/security.h4
-rw-r--r--security/selinux/include/selinux_netlabel.h43
-rw-r--r--security/selinux/include/xfrm.h28
-rw-r--r--security/selinux/nlmsgtab.c1
-rw-r--r--security/selinux/ss/ebitmap.c198
-rw-r--r--security/selinux/ss/ebitmap.h26
-rw-r--r--security/selinux/ss/hashtab.c6
-rw-r--r--security/selinux/ss/hashtab.h10
-rw-r--r--security/selinux/ss/mls.c156
-rw-r--r--security/selinux/ss/mls.h46
-rw-r--r--security/selinux/ss/policydb.c6
-rw-r--r--security/selinux/ss/services.c437
-rw-r--r--security/selinux/ss/symtab.c8
-rw-r--r--security/selinux/xfrm.c207
24 files changed, 730 insertions, 712 deletions
diff --git a/security/dummy.c b/security/dummy.c
index 43874c1e6e23..558795b237d6 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -828,6 +828,11 @@ static inline void dummy_inet_csk_clone(struct sock *newsk,
828{ 828{
829} 829}
830 830
831static inline void dummy_inet_conn_established(struct sock *sk,
832 struct sk_buff *skb)
833{
834}
835
831static inline void dummy_req_classify_flow(const struct request_sock *req, 836static inline void dummy_req_classify_flow(const struct request_sock *req,
832 struct flowi *fl) 837 struct flowi *fl)
833{ 838{
@@ -836,7 +841,7 @@ static inline void dummy_req_classify_flow(const struct request_sock *req,
836 841
837#ifdef CONFIG_SECURITY_NETWORK_XFRM 842#ifdef CONFIG_SECURITY_NETWORK_XFRM
838static int dummy_xfrm_policy_alloc_security(struct xfrm_policy *xp, 843static int dummy_xfrm_policy_alloc_security(struct xfrm_policy *xp,
839 struct xfrm_user_sec_ctx *sec_ctx, struct sock *sk) 844 struct xfrm_user_sec_ctx *sec_ctx)
840{ 845{
841 return 0; 846 return 0;
842} 847}
@@ -856,7 +861,7 @@ static int dummy_xfrm_policy_delete_security(struct xfrm_policy *xp)
856} 861}
857 862
858static int dummy_xfrm_state_alloc_security(struct xfrm_state *x, 863static int dummy_xfrm_state_alloc_security(struct xfrm_state *x,
859 struct xfrm_user_sec_ctx *sec_ctx, struct xfrm_sec_ctx *pol, u32 secid) 864 struct xfrm_user_sec_ctx *sec_ctx, u32 secid)
860{ 865{
861 return 0; 866 return 0;
862} 867}
@@ -881,12 +886,6 @@ static int dummy_xfrm_state_pol_flow_match(struct xfrm_state *x,
881 return 1; 886 return 1;
882} 887}
883 888
884static int dummy_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm,
885 struct xfrm_policy *xp)
886{
887 return 1;
888}
889
890static int dummy_xfrm_decode_session(struct sk_buff *skb, u32 *fl, int ckall) 889static int dummy_xfrm_decode_session(struct sk_buff *skb, u32 *fl, int ckall)
891{ 890{
892 return 0; 891 return 0;
@@ -1108,6 +1107,7 @@ void security_fixup_ops (struct security_operations *ops)
1108 set_to_dummy_if_null(ops, sock_graft); 1107 set_to_dummy_if_null(ops, sock_graft);
1109 set_to_dummy_if_null(ops, inet_conn_request); 1108 set_to_dummy_if_null(ops, inet_conn_request);
1110 set_to_dummy_if_null(ops, inet_csk_clone); 1109 set_to_dummy_if_null(ops, inet_csk_clone);
1110 set_to_dummy_if_null(ops, inet_conn_established);
1111 set_to_dummy_if_null(ops, req_classify_flow); 1111 set_to_dummy_if_null(ops, req_classify_flow);
1112 #endif /* CONFIG_SECURITY_NETWORK */ 1112 #endif /* CONFIG_SECURITY_NETWORK */
1113#ifdef CONFIG_SECURITY_NETWORK_XFRM 1113#ifdef CONFIG_SECURITY_NETWORK_XFRM
@@ -1120,7 +1120,6 @@ void security_fixup_ops (struct security_operations *ops)
1120 set_to_dummy_if_null(ops, xfrm_state_delete_security); 1120 set_to_dummy_if_null(ops, xfrm_state_delete_security);
1121 set_to_dummy_if_null(ops, xfrm_policy_lookup); 1121 set_to_dummy_if_null(ops, xfrm_policy_lookup);
1122 set_to_dummy_if_null(ops, xfrm_state_pol_flow_match); 1122 set_to_dummy_if_null(ops, xfrm_state_pol_flow_match);
1123 set_to_dummy_if_null(ops, xfrm_flow_state_match);
1124 set_to_dummy_if_null(ops, xfrm_decode_session); 1123 set_to_dummy_if_null(ops, xfrm_decode_session);
1125#endif /* CONFIG_SECURITY_NETWORK_XFRM */ 1124#endif /* CONFIG_SECURITY_NETWORK_XFRM */
1126#ifdef CONFIG_KEYS 1125#ifdef CONFIG_KEYS
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index a300702da527..74c0319c417e 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -32,12 +32,7 @@
32#include "avc.h" 32#include "avc.h"
33#include "avc_ss.h" 33#include "avc_ss.h"
34 34
35static const struct av_perm_to_string 35static const struct av_perm_to_string av_perm_to_string[] = {
36{
37 u16 tclass;
38 u32 value;
39 const char *name;
40} av_perm_to_string[] = {
41#define S_(c, v, s) { c, v, s }, 36#define S_(c, v, s) { c, v, s },
42#include "av_perm_to_string.h" 37#include "av_perm_to_string.h"
43#undef S_ 38#undef S_
@@ -57,17 +52,21 @@ static const char *class_to_string[] = {
57#undef TE_ 52#undef TE_
58#undef S_ 53#undef S_
59 54
60static const struct av_inherit 55static const struct av_inherit av_inherit[] = {
61{
62 u16 tclass;
63 const char **common_pts;
64 u32 common_base;
65} av_inherit[] = {
66#define S_(c, i, b) { c, common_##i##_perm_to_string, b }, 56#define S_(c, i, b) { c, common_##i##_perm_to_string, b },
67#include "av_inherit.h" 57#include "av_inherit.h"
68#undef S_ 58#undef S_
69}; 59};
70 60
61const struct selinux_class_perm selinux_class_perm = {
62 av_perm_to_string,
63 ARRAY_SIZE(av_perm_to_string),
64 class_to_string,
65 ARRAY_SIZE(class_to_string),
66 av_inherit,
67 ARRAY_SIZE(av_inherit)
68};
69
71#define AVC_CACHE_SLOTS 512 70#define AVC_CACHE_SLOTS 512
72#define AVC_DEF_CACHE_THRESHOLD 512 71#define AVC_DEF_CACHE_THRESHOLD 512
73#define AVC_CACHE_RECLAIM 16 72#define AVC_CACHE_RECLAIM 16
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 8ab5679a37a3..a29d78d3f44c 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -58,6 +58,7 @@
58#include <linux/netlink.h> 58#include <linux/netlink.h>
59#include <linux/tcp.h> 59#include <linux/tcp.h>
60#include <linux/udp.h> 60#include <linux/udp.h>
61#include <linux/dccp.h>
61#include <linux/quota.h> 62#include <linux/quota.h>
62#include <linux/un.h> /* for Unix socket types */ 63#include <linux/un.h> /* for Unix socket types */
63#include <net/af_unix.h> /* for Unix socket types */ 64#include <net/af_unix.h> /* for Unix socket types */
@@ -751,6 +752,8 @@ static inline u16 socket_type_to_security_class(int family, int type, int protoc
751 return SECCLASS_UDP_SOCKET; 752 return SECCLASS_UDP_SOCKET;
752 else 753 else
753 return SECCLASS_RAWIP_SOCKET; 754 return SECCLASS_RAWIP_SOCKET;
755 case SOCK_DCCP:
756 return SECCLASS_DCCP_SOCKET;
754 default: 757 default:
755 return SECCLASS_RAWIP_SOCKET; 758 return SECCLASS_RAWIP_SOCKET;
756 } 759 }
@@ -1754,7 +1757,8 @@ static inline void flush_unauthorized_files(struct files_struct * files)
1754 get_file(devnull); 1757 get_file(devnull);
1755 } else { 1758 } else {
1756 devnull = dentry_open(dget(selinux_null), mntget(selinuxfs_mount), O_RDWR); 1759 devnull = dentry_open(dget(selinux_null), mntget(selinuxfs_mount), O_RDWR);
1757 if (!devnull) { 1760 if (IS_ERR(devnull)) {
1761 devnull = NULL;
1758 put_unused_fd(fd); 1762 put_unused_fd(fd);
1759 fput(file); 1763 fput(file);
1760 continue; 1764 continue;
@@ -2888,7 +2892,8 @@ static void selinux_task_to_inode(struct task_struct *p,
2888} 2892}
2889 2893
2890/* Returns error only if unable to parse addresses */ 2894/* Returns error only if unable to parse addresses */
2891static int selinux_parse_skb_ipv4(struct sk_buff *skb, struct avc_audit_data *ad) 2895static int selinux_parse_skb_ipv4(struct sk_buff *skb,
2896 struct avc_audit_data *ad, u8 *proto)
2892{ 2897{
2893 int offset, ihlen, ret = -EINVAL; 2898 int offset, ihlen, ret = -EINVAL;
2894 struct iphdr _iph, *ih; 2899 struct iphdr _iph, *ih;
@@ -2906,6 +2911,9 @@ static int selinux_parse_skb_ipv4(struct sk_buff *skb, struct avc_audit_data *ad
2906 ad->u.net.v4info.daddr = ih->daddr; 2911 ad->u.net.v4info.daddr = ih->daddr;
2907 ret = 0; 2912 ret = 0;
2908 2913
2914 if (proto)
2915 *proto = ih->protocol;
2916
2909 switch (ih->protocol) { 2917 switch (ih->protocol) {
2910 case IPPROTO_TCP: { 2918 case IPPROTO_TCP: {
2911 struct tcphdr _tcph, *th; 2919 struct tcphdr _tcph, *th;
@@ -2939,6 +2947,22 @@ static int selinux_parse_skb_ipv4(struct sk_buff *skb, struct avc_audit_data *ad
2939 break; 2947 break;
2940 } 2948 }
2941 2949
2950 case IPPROTO_DCCP: {
2951 struct dccp_hdr _dccph, *dh;
2952
2953 if (ntohs(ih->frag_off) & IP_OFFSET)
2954 break;
2955
2956 offset += ihlen;
2957 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
2958 if (dh == NULL)
2959 break;
2960
2961 ad->u.net.sport = dh->dccph_sport;
2962 ad->u.net.dport = dh->dccph_dport;
2963 break;
2964 }
2965
2942 default: 2966 default:
2943 break; 2967 break;
2944 } 2968 }
@@ -2949,7 +2973,8 @@ out:
2949#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 2973#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
2950 2974
2951/* Returns error only if unable to parse addresses */ 2975/* Returns error only if unable to parse addresses */
2952static int selinux_parse_skb_ipv6(struct sk_buff *skb, struct avc_audit_data *ad) 2976static int selinux_parse_skb_ipv6(struct sk_buff *skb,
2977 struct avc_audit_data *ad, u8 *proto)
2953{ 2978{
2954 u8 nexthdr; 2979 u8 nexthdr;
2955 int ret = -EINVAL, offset; 2980 int ret = -EINVAL, offset;
@@ -2970,6 +2995,9 @@ static int selinux_parse_skb_ipv6(struct sk_buff *skb, struct avc_audit_data *ad
2970 if (offset < 0) 2995 if (offset < 0)
2971 goto out; 2996 goto out;
2972 2997
2998 if (proto)
2999 *proto = nexthdr;
3000
2973 switch (nexthdr) { 3001 switch (nexthdr) {
2974 case IPPROTO_TCP: { 3002 case IPPROTO_TCP: {
2975 struct tcphdr _tcph, *th; 3003 struct tcphdr _tcph, *th;
@@ -2995,6 +3023,18 @@ static int selinux_parse_skb_ipv6(struct sk_buff *skb, struct avc_audit_data *ad
2995 break; 3023 break;
2996 } 3024 }
2997 3025
3026 case IPPROTO_DCCP: {
3027 struct dccp_hdr _dccph, *dh;
3028
3029 dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph);
3030 if (dh == NULL)
3031 break;
3032
3033 ad->u.net.sport = dh->dccph_sport;
3034 ad->u.net.dport = dh->dccph_dport;
3035 break;
3036 }
3037
2998 /* includes fragments */ 3038 /* includes fragments */
2999 default: 3039 default:
3000 break; 3040 break;
@@ -3006,13 +3046,13 @@ out:
3006#endif /* IPV6 */ 3046#endif /* IPV6 */
3007 3047
3008static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad, 3048static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad,
3009 char **addrp, int *len, int src) 3049 char **addrp, int *len, int src, u8 *proto)
3010{ 3050{
3011 int ret = 0; 3051 int ret = 0;
3012 3052
3013 switch (ad->u.net.family) { 3053 switch (ad->u.net.family) {
3014 case PF_INET: 3054 case PF_INET:
3015 ret = selinux_parse_skb_ipv4(skb, ad); 3055 ret = selinux_parse_skb_ipv4(skb, ad, proto);
3016 if (ret || !addrp) 3056 if (ret || !addrp)
3017 break; 3057 break;
3018 *len = 4; 3058 *len = 4;
@@ -3022,7 +3062,7 @@ static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad,
3022 3062
3023#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 3063#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3024 case PF_INET6: 3064 case PF_INET6:
3025 ret = selinux_parse_skb_ipv6(skb, ad); 3065 ret = selinux_parse_skb_ipv6(skb, ad, proto);
3026 if (ret || !addrp) 3066 if (ret || !addrp)
3027 break; 3067 break;
3028 *len = 16; 3068 *len = 16;
@@ -3100,9 +3140,7 @@ static int selinux_socket_post_create(struct socket *sock, int family,
3100 if (sock->sk) { 3140 if (sock->sk) {
3101 sksec = sock->sk->sk_security; 3141 sksec = sock->sk->sk_security;
3102 sksec->sid = isec->sid; 3142 sksec->sid = isec->sid;
3103 err = selinux_netlbl_socket_post_create(sock, 3143 err = selinux_netlbl_socket_post_create(sock);
3104 family,
3105 isec->sid);
3106 } 3144 }
3107 3145
3108 return err; 3146 return err;
@@ -3179,7 +3217,11 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
3179 case SECCLASS_UDP_SOCKET: 3217 case SECCLASS_UDP_SOCKET:
3180 node_perm = UDP_SOCKET__NODE_BIND; 3218 node_perm = UDP_SOCKET__NODE_BIND;
3181 break; 3219 break;
3182 3220
3221 case SECCLASS_DCCP_SOCKET:
3222 node_perm = DCCP_SOCKET__NODE_BIND;
3223 break;
3224
3183 default: 3225 default:
3184 node_perm = RAWIP_SOCKET__NODE_BIND; 3226 node_perm = RAWIP_SOCKET__NODE_BIND;
3185 break; 3227 break;
@@ -3217,16 +3259,17 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address,
3217 return err; 3259 return err;
3218 3260
3219 /* 3261 /*
3220 * If a TCP socket, check name_connect permission for the port. 3262 * If a TCP or DCCP socket, check name_connect permission for the port.
3221 */ 3263 */
3222 isec = SOCK_INODE(sock)->i_security; 3264 isec = SOCK_INODE(sock)->i_security;
3223 if (isec->sclass == SECCLASS_TCP_SOCKET) { 3265 if (isec->sclass == SECCLASS_TCP_SOCKET ||
3266 isec->sclass == SECCLASS_DCCP_SOCKET) {
3224 struct sock *sk = sock->sk; 3267 struct sock *sk = sock->sk;
3225 struct avc_audit_data ad; 3268 struct avc_audit_data ad;
3226 struct sockaddr_in *addr4 = NULL; 3269 struct sockaddr_in *addr4 = NULL;
3227 struct sockaddr_in6 *addr6 = NULL; 3270 struct sockaddr_in6 *addr6 = NULL;
3228 unsigned short snum; 3271 unsigned short snum;
3229 u32 sid; 3272 u32 sid, perm;
3230 3273
3231 if (sk->sk_family == PF_INET) { 3274 if (sk->sk_family == PF_INET) {
3232 addr4 = (struct sockaddr_in *)address; 3275 addr4 = (struct sockaddr_in *)address;
@@ -3245,11 +3288,13 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address,
3245 if (err) 3288 if (err)
3246 goto out; 3289 goto out;
3247 3290
3291 perm = (isec->sclass == SECCLASS_TCP_SOCKET) ?
3292 TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT;
3293
3248 AVC_AUDIT_DATA_INIT(&ad,NET); 3294 AVC_AUDIT_DATA_INIT(&ad,NET);
3249 ad.u.net.dport = htons(snum); 3295 ad.u.net.dport = htons(snum);
3250 ad.u.net.family = sk->sk_family; 3296 ad.u.net.family = sk->sk_family;
3251 err = avc_has_perm(isec->sid, sid, isec->sclass, 3297 err = avc_has_perm(isec->sid, sid, isec->sclass, perm, &ad);
3252 TCP_SOCKET__NAME_CONNECT, &ad);
3253 if (err) 3298 if (err)
3254 goto out; 3299 goto out;
3255 } 3300 }
@@ -3437,7 +3482,13 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
3437 node_perm = NODE__TCP_RECV; 3482 node_perm = NODE__TCP_RECV;
3438 recv_perm = TCP_SOCKET__RECV_MSG; 3483 recv_perm = TCP_SOCKET__RECV_MSG;
3439 break; 3484 break;
3440 3485
3486 case SECCLASS_DCCP_SOCKET:
3487 netif_perm = NETIF__DCCP_RECV;
3488 node_perm = NODE__DCCP_RECV;
3489 recv_perm = DCCP_SOCKET__RECV_MSG;
3490 break;
3491
3441 default: 3492 default:
3442 netif_perm = NETIF__RAWIP_RECV; 3493 netif_perm = NETIF__RAWIP_RECV;
3443 node_perm = NODE__RAWIP_RECV; 3494 node_perm = NODE__RAWIP_RECV;
@@ -3493,7 +3544,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
3493 ad.u.net.netif = skb->dev ? skb->dev->name : "[unknown]"; 3544 ad.u.net.netif = skb->dev ? skb->dev->name : "[unknown]";
3494 ad.u.net.family = family; 3545 ad.u.net.family = family;
3495 3546
3496 err = selinux_parse_skb(skb, &ad, &addrp, &len, 1); 3547 err = selinux_parse_skb(skb, &ad, &addrp, &len, 1, NULL);
3497 if (err) 3548 if (err)
3498 goto out; 3549 goto out;
3499 3550
@@ -3523,25 +3574,16 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *op
3523 u32 scontext_len; 3574 u32 scontext_len;
3524 struct sk_security_struct *ssec; 3575 struct sk_security_struct *ssec;
3525 struct inode_security_struct *isec; 3576 struct inode_security_struct *isec;
3526 u32 peer_sid = 0; 3577 u32 peer_sid = SECSID_NULL;
3527 3578
3528 isec = SOCK_INODE(sock)->i_security; 3579 isec = SOCK_INODE(sock)->i_security;
3529 3580
3530 /* if UNIX_STREAM check peer_sid, if TCP check dst for labelled sa */ 3581 if (isec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
3531 if (isec->sclass == SECCLASS_UNIX_STREAM_SOCKET) { 3582 isec->sclass == SECCLASS_TCP_SOCKET) {
3532 ssec = sock->sk->sk_security; 3583 ssec = sock->sk->sk_security;
3533 peer_sid = ssec->peer_sid; 3584 peer_sid = ssec->peer_sid;
3534 } 3585 }
3535 else if (isec->sclass == SECCLASS_TCP_SOCKET) { 3586 if (peer_sid == SECSID_NULL) {
3536 peer_sid = selinux_netlbl_socket_getpeersec_stream(sock);
3537 if (peer_sid == SECSID_NULL)
3538 peer_sid = selinux_socket_getpeer_stream(sock->sk);
3539 if (peer_sid == SECSID_NULL) {
3540 err = -ENOPROTOOPT;
3541 goto out;
3542 }
3543 }
3544 else {
3545 err = -ENOPROTOOPT; 3587 err = -ENOPROTOOPT;
3546 goto out; 3588 goto out;
3547 } 3589 }
@@ -3573,13 +3615,12 @@ static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *
3573 u32 peer_secid = SECSID_NULL; 3615 u32 peer_secid = SECSID_NULL;
3574 int err = 0; 3616 int err = 0;
3575 3617
3576 if (sock && (sock->sk->sk_family == PF_UNIX)) 3618 if (sock && sock->sk->sk_family == PF_UNIX)
3577 selinux_get_inode_sid(SOCK_INODE(sock), &peer_secid); 3619 selinux_get_inode_sid(SOCK_INODE(sock), &peer_secid);
3578 else if (skb) { 3620 else if (skb)
3579 peer_secid = selinux_netlbl_socket_getpeersec_dgram(skb); 3621 security_skb_extlbl_sid(skb,
3580 if (peer_secid == SECSID_NULL) 3622 SECINITSID_UNLABELED,
3581 peer_secid = selinux_socket_getpeer_dgram(skb); 3623 &peer_secid);
3582 }
3583 3624
3584 if (peer_secid == SECSID_NULL) 3625 if (peer_secid == SECSID_NULL)
3585 err = -EINVAL; 3626 err = -EINVAL;
@@ -3606,7 +3647,7 @@ static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
3606 newssec->sid = ssec->sid; 3647 newssec->sid = ssec->sid;
3607 newssec->peer_sid = ssec->peer_sid; 3648 newssec->peer_sid = ssec->peer_sid;
3608 3649
3609 selinux_netlbl_sk_clone_security(ssec, newssec); 3650 selinux_netlbl_sk_security_clone(ssec, newssec);
3610} 3651}
3611 3652
3612static void selinux_sk_getsecid(struct sock *sk, u32 *secid) 3653static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
@@ -3640,17 +3681,10 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
3640 u32 newsid; 3681 u32 newsid;
3641 u32 peersid; 3682 u32 peersid;
3642 3683
3643 newsid = selinux_netlbl_inet_conn_request(skb, sksec->sid); 3684 security_skb_extlbl_sid(skb, SECINITSID_UNLABELED, &peersid);
3644 if (newsid != SECSID_NULL) {
3645 req->secid = newsid;
3646 return 0;
3647 }
3648
3649 err = selinux_xfrm_decode_session(skb, &peersid, 0);
3650 BUG_ON(err);
3651
3652 if (peersid == SECSID_NULL) { 3685 if (peersid == SECSID_NULL) {
3653 req->secid = sksec->sid; 3686 req->secid = sksec->sid;
3687 req->peer_secid = SECSID_NULL;
3654 return 0; 3688 return 0;
3655 } 3689 }
3656 3690
@@ -3659,6 +3693,7 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
3659 return err; 3693 return err;
3660 3694
3661 req->secid = newsid; 3695 req->secid = newsid;
3696 req->peer_secid = peersid;
3662 return 0; 3697 return 0;
3663} 3698}
3664 3699
@@ -3668,12 +3703,23 @@ static void selinux_inet_csk_clone(struct sock *newsk,
3668 struct sk_security_struct *newsksec = newsk->sk_security; 3703 struct sk_security_struct *newsksec = newsk->sk_security;
3669 3704
3670 newsksec->sid = req->secid; 3705 newsksec->sid = req->secid;
3706 newsksec->peer_sid = req->peer_secid;
3671 /* NOTE: Ideally, we should also get the isec->sid for the 3707 /* NOTE: Ideally, we should also get the isec->sid for the
3672 new socket in sync, but we don't have the isec available yet. 3708 new socket in sync, but we don't have the isec available yet.
3673 So we will wait until sock_graft to do it, by which 3709 So we will wait until sock_graft to do it, by which
3674 time it will have been created and available. */ 3710 time it will have been created and available. */
3675 3711
3676 selinux_netlbl_sk_security_init(newsksec, req->rsk_ops->family); 3712 /* We don't need to take any sort of lock here as we are the only
3713 * thread with access to newsksec */
3714 selinux_netlbl_sk_security_reset(newsksec, req->rsk_ops->family);
3715}
3716
3717static void selinux_inet_conn_established(struct sock *sk,
3718 struct sk_buff *skb)
3719{
3720 struct sk_security_struct *sksec = sk->sk_security;
3721
3722 security_skb_extlbl_sid(skb, SECINITSID_UNLABELED, &sksec->peer_sid);
3677} 3723}
3678 3724
3679static void selinux_req_classify_flow(const struct request_sock *req, 3725static void selinux_req_classify_flow(const struct request_sock *req,
@@ -3756,7 +3802,13 @@ static int selinux_ip_postroute_last_compat(struct sock *sk, struct net_device *
3756 node_perm = NODE__TCP_SEND; 3802 node_perm = NODE__TCP_SEND;
3757 send_perm = TCP_SOCKET__SEND_MSG; 3803 send_perm = TCP_SOCKET__SEND_MSG;
3758 break; 3804 break;
3759 3805
3806 case SECCLASS_DCCP_SOCKET:
3807 netif_perm = NETIF__DCCP_SEND;
3808 node_perm = NODE__DCCP_SEND;
3809 send_perm = DCCP_SOCKET__SEND_MSG;
3810 break;
3811
3760 default: 3812 default:
3761 netif_perm = NETIF__RAWIP_SEND; 3813 netif_perm = NETIF__RAWIP_SEND;
3762 node_perm = NODE__RAWIP_SEND; 3814 node_perm = NODE__RAWIP_SEND;
@@ -3807,6 +3859,7 @@ static unsigned int selinux_ip_postroute_last(unsigned int hooknum,
3807 struct avc_audit_data ad; 3859 struct avc_audit_data ad;
3808 struct net_device *dev = (struct net_device *)out; 3860 struct net_device *dev = (struct net_device *)out;
3809 struct sk_security_struct *sksec; 3861 struct sk_security_struct *sksec;
3862 u8 proto;
3810 3863
3811 sk = skb->sk; 3864 sk = skb->sk;
3812 if (!sk) 3865 if (!sk)
@@ -3818,7 +3871,7 @@ static unsigned int selinux_ip_postroute_last(unsigned int hooknum,
3818 ad.u.net.netif = dev->name; 3871 ad.u.net.netif = dev->name;
3819 ad.u.net.family = family; 3872 ad.u.net.family = family;
3820 3873
3821 err = selinux_parse_skb(skb, &ad, &addrp, &len, 0); 3874 err = selinux_parse_skb(skb, &ad, &addrp, &len, 0, &proto);
3822 if (err) 3875 if (err)
3823 goto out; 3876 goto out;
3824 3877
@@ -3832,7 +3885,7 @@ static unsigned int selinux_ip_postroute_last(unsigned int hooknum,
3832 if (err) 3885 if (err)
3833 goto out; 3886 goto out;
3834 3887
3835 err = selinux_xfrm_postroute_last(sksec->sid, skb, &ad); 3888 err = selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto);
3836out: 3889out:
3837 return err ? NF_DROP : NF_ACCEPT; 3890 return err ? NF_DROP : NF_ACCEPT;
3838} 3891}
@@ -4738,6 +4791,7 @@ static struct security_operations selinux_ops = {
4738 .sock_graft = selinux_sock_graft, 4791 .sock_graft = selinux_sock_graft,
4739 .inet_conn_request = selinux_inet_conn_request, 4792 .inet_conn_request = selinux_inet_conn_request,
4740 .inet_csk_clone = selinux_inet_csk_clone, 4793 .inet_csk_clone = selinux_inet_csk_clone,
4794 .inet_conn_established = selinux_inet_conn_established,
4741 .req_classify_flow = selinux_req_classify_flow, 4795 .req_classify_flow = selinux_req_classify_flow,
4742 4796
4743#ifdef CONFIG_SECURITY_NETWORK_XFRM 4797#ifdef CONFIG_SECURITY_NETWORK_XFRM
@@ -4750,7 +4804,6 @@ static struct security_operations selinux_ops = {
4750 .xfrm_state_delete_security = selinux_xfrm_state_delete, 4804 .xfrm_state_delete_security = selinux_xfrm_state_delete,
4751 .xfrm_policy_lookup = selinux_xfrm_policy_lookup, 4805 .xfrm_policy_lookup = selinux_xfrm_policy_lookup,
4752 .xfrm_state_pol_flow_match = selinux_xfrm_state_pol_flow_match, 4806 .xfrm_state_pol_flow_match = selinux_xfrm_state_pol_flow_match,
4753 .xfrm_flow_state_match = selinux_xfrm_flow_state_match,
4754 .xfrm_decode_session = selinux_xfrm_decode_session, 4807 .xfrm_decode_session = selinux_xfrm_decode_session,
4755#endif 4808#endif
4756 4809
diff --git a/security/selinux/include/av_inherit.h b/security/selinux/include/av_inherit.h
index a68fdd55597f..8377a4ba3b95 100644
--- a/security/selinux/include/av_inherit.h
+++ b/security/selinux/include/av_inherit.h
@@ -30,3 +30,4 @@
30 S_(SECCLASS_NETLINK_DNRT_SOCKET, socket, 0x00400000UL) 30 S_(SECCLASS_NETLINK_DNRT_SOCKET, socket, 0x00400000UL)
31 S_(SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET, socket, 0x00400000UL) 31 S_(SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET, socket, 0x00400000UL)
32 S_(SECCLASS_APPLETALK_SOCKET, socket, 0x00400000UL) 32 S_(SECCLASS_APPLETALK_SOCKET, socket, 0x00400000UL)
33 S_(SECCLASS_DCCP_SOCKET, socket, 0x00400000UL)
diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h
index 09fc8a2345eb..ad9fb2d69b50 100644
--- a/security/selinux/include/av_perm_to_string.h
+++ b/security/selinux/include/av_perm_to_string.h
@@ -35,12 +35,16 @@
35 S_(SECCLASS_NODE, NODE__RAWIP_RECV, "rawip_recv") 35 S_(SECCLASS_NODE, NODE__RAWIP_RECV, "rawip_recv")
36 S_(SECCLASS_NODE, NODE__RAWIP_SEND, "rawip_send") 36 S_(SECCLASS_NODE, NODE__RAWIP_SEND, "rawip_send")
37 S_(SECCLASS_NODE, NODE__ENFORCE_DEST, "enforce_dest") 37 S_(SECCLASS_NODE, NODE__ENFORCE_DEST, "enforce_dest")
38 S_(SECCLASS_NODE, NODE__DCCP_RECV, "dccp_recv")
39 S_(SECCLASS_NODE, NODE__DCCP_SEND, "dccp_send")
38 S_(SECCLASS_NETIF, NETIF__TCP_RECV, "tcp_recv") 40 S_(SECCLASS_NETIF, NETIF__TCP_RECV, "tcp_recv")
39 S_(SECCLASS_NETIF, NETIF__TCP_SEND, "tcp_send") 41 S_(SECCLASS_NETIF, NETIF__TCP_SEND, "tcp_send")
40 S_(SECCLASS_NETIF, NETIF__UDP_RECV, "udp_recv") 42 S_(SECCLASS_NETIF, NETIF__UDP_RECV, "udp_recv")
41 S_(SECCLASS_NETIF, NETIF__UDP_SEND, "udp_send") 43 S_(SECCLASS_NETIF, NETIF__UDP_SEND, "udp_send")
42 S_(SECCLASS_NETIF, NETIF__RAWIP_RECV, "rawip_recv") 44 S_(SECCLASS_NETIF, NETIF__RAWIP_RECV, "rawip_recv")
43 S_(SECCLASS_NETIF, NETIF__RAWIP_SEND, "rawip_send") 45 S_(SECCLASS_NETIF, NETIF__RAWIP_SEND, "rawip_send")
46 S_(SECCLASS_NETIF, NETIF__DCCP_RECV, "dccp_recv")
47 S_(SECCLASS_NETIF, NETIF__DCCP_SEND, "dccp_send")
44 S_(SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__CONNECTTO, "connectto") 48 S_(SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__CONNECTTO, "connectto")
45 S_(SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__NEWCONN, "newconn") 49 S_(SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__NEWCONN, "newconn")
46 S_(SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__ACCEPTFROM, "acceptfrom") 50 S_(SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__ACCEPTFROM, "acceptfrom")
@@ -252,3 +256,7 @@
252 S_(SECCLASS_KEY, KEY__LINK, "link") 256 S_(SECCLASS_KEY, KEY__LINK, "link")
253 S_(SECCLASS_KEY, KEY__SETATTR, "setattr") 257 S_(SECCLASS_KEY, KEY__SETATTR, "setattr")
254 S_(SECCLASS_KEY, KEY__CREATE, "create") 258 S_(SECCLASS_KEY, KEY__CREATE, "create")
259 S_(SECCLASS_CONTEXT, CONTEXT__TRANSLATE, "translate")
260 S_(SECCLASS_CONTEXT, CONTEXT__CONTAINS, "contains")
261 S_(SECCLASS_DCCP_SOCKET, DCCP_SOCKET__NODE_BIND, "node_bind")
262 S_(SECCLASS_DCCP_SOCKET, DCCP_SOCKET__NAME_CONNECT, "name_connect")
diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h
index 81f4f526c8b1..2de4b5fe3aa1 100644
--- a/security/selinux/include/av_permissions.h
+++ b/security/selinux/include/av_permissions.h
@@ -312,6 +312,8 @@
312#define NODE__RAWIP_RECV 0x00000010UL 312#define NODE__RAWIP_RECV 0x00000010UL
313#define NODE__RAWIP_SEND 0x00000020UL 313#define NODE__RAWIP_SEND 0x00000020UL
314#define NODE__ENFORCE_DEST 0x00000040UL 314#define NODE__ENFORCE_DEST 0x00000040UL
315#define NODE__DCCP_RECV 0x00000080UL
316#define NODE__DCCP_SEND 0x00000100UL
315 317
316#define NETIF__TCP_RECV 0x00000001UL 318#define NETIF__TCP_RECV 0x00000001UL
317#define NETIF__TCP_SEND 0x00000002UL 319#define NETIF__TCP_SEND 0x00000002UL
@@ -319,6 +321,8 @@
319#define NETIF__UDP_SEND 0x00000008UL 321#define NETIF__UDP_SEND 0x00000008UL
320#define NETIF__RAWIP_RECV 0x00000010UL 322#define NETIF__RAWIP_RECV 0x00000010UL
321#define NETIF__RAWIP_SEND 0x00000020UL 323#define NETIF__RAWIP_SEND 0x00000020UL
324#define NETIF__DCCP_RECV 0x00000040UL
325#define NETIF__DCCP_SEND 0x00000080UL
322 326
323#define NETLINK_SOCKET__IOCTL 0x00000001UL 327#define NETLINK_SOCKET__IOCTL 0x00000001UL
324#define NETLINK_SOCKET__READ 0x00000002UL 328#define NETLINK_SOCKET__READ 0x00000002UL
@@ -970,3 +974,31 @@
970#define KEY__LINK 0x00000010UL 974#define KEY__LINK 0x00000010UL
971#define KEY__SETATTR 0x00000020UL 975#define KEY__SETATTR 0x00000020UL
972#define KEY__CREATE 0x00000040UL 976#define KEY__CREATE 0x00000040UL
977
978#define CONTEXT__TRANSLATE 0x00000001UL
979#define CONTEXT__CONTAINS 0x00000002UL
980
981#define DCCP_SOCKET__IOCTL 0x00000001UL
982#define DCCP_SOCKET__READ 0x00000002UL
983#define DCCP_SOCKET__WRITE 0x00000004UL
984#define DCCP_SOCKET__CREATE 0x00000008UL
985#define DCCP_SOCKET__GETATTR 0x00000010UL
986#define DCCP_SOCKET__SETATTR 0x00000020UL
987#define DCCP_SOCKET__LOCK 0x00000040UL
988#define DCCP_SOCKET__RELABELFROM 0x00000080UL
989#define DCCP_SOCKET__RELABELTO 0x00000100UL
990#define DCCP_SOCKET__APPEND 0x00000200UL
991#define DCCP_SOCKET__BIND 0x00000400UL
992#define DCCP_SOCKET__CONNECT 0x00000800UL
993#define DCCP_SOCKET__LISTEN 0x00001000UL
994#define DCCP_SOCKET__ACCEPT 0x00002000UL
995#define DCCP_SOCKET__GETOPT 0x00004000UL
996#define DCCP_SOCKET__SETOPT 0x00008000UL
997#define DCCP_SOCKET__SHUTDOWN 0x00010000UL
998#define DCCP_SOCKET__RECVFROM 0x00020000UL
999#define DCCP_SOCKET__SENDTO 0x00040000UL
1000#define DCCP_SOCKET__RECV_MSG 0x00080000UL
1001#define DCCP_SOCKET__SEND_MSG 0x00100000UL
1002#define DCCP_SOCKET__NAME_BIND 0x00200000UL
1003#define DCCP_SOCKET__NODE_BIND 0x00400000UL
1004#define DCCP_SOCKET__NAME_CONNECT 0x00800000UL
diff --git a/security/selinux/include/avc_ss.h b/security/selinux/include/avc_ss.h
index 450a2831e2e3..ff869e8b6f4a 100644
--- a/security/selinux/include/avc_ss.h
+++ b/security/selinux/include/avc_ss.h
@@ -10,5 +10,29 @@
10 10
11int avc_ss_reset(u32 seqno); 11int avc_ss_reset(u32 seqno);
12 12
13struct av_perm_to_string
14{
15 u16 tclass;
16 u32 value;
17 const char *name;
18};
19
20struct av_inherit
21{
22 u16 tclass;
23 const char **common_pts;
24 u32 common_base;
25};
26
27struct selinux_class_perm
28{
29 const struct av_perm_to_string *av_perm_to_string;
30 u32 av_pts_len;
31 const char **class_to_string;
32 u32 cts_len;
33 const struct av_inherit *av_inherit;
34 u32 av_inherit_len;
35};
36
13#endif /* _SELINUX_AVC_SS_H_ */ 37#endif /* _SELINUX_AVC_SS_H_ */
14 38
diff --git a/security/selinux/include/class_to_string.h b/security/selinux/include/class_to_string.h
index 24303b61309f..9f3ebb1bfae6 100644
--- a/security/selinux/include/class_to_string.h
+++ b/security/selinux/include/class_to_string.h
@@ -61,3 +61,5 @@
61 S_("appletalk_socket") 61 S_("appletalk_socket")
62 S_("packet") 62 S_("packet")
63 S_("key") 63 S_("key")
64 S_("context")
65 S_("dccp_socket")
diff --git a/security/selinux/include/flask.h b/security/selinux/include/flask.h
index 95887aed2a68..67cef371ee00 100644
--- a/security/selinux/include/flask.h
+++ b/security/selinux/include/flask.h
@@ -63,6 +63,8 @@
63#define SECCLASS_APPLETALK_SOCKET 56 63#define SECCLASS_APPLETALK_SOCKET 56
64#define SECCLASS_PACKET 57 64#define SECCLASS_PACKET 57
65#define SECCLASS_KEY 58 65#define SECCLASS_KEY 58
66#define SECCLASS_CONTEXT 59
67#define SECCLASS_DCCP_SOCKET 60
66 68
67/* 69/*
68 * Security identifier indices for initial entities 70 * Security identifier indices for initial entities
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
index ef2267fea8bd..91b88f0ba20c 100644
--- a/security/selinux/include/objsec.h
+++ b/security/selinux/include/objsec.h
@@ -23,6 +23,7 @@
23#include <linux/fs.h> 23#include <linux/fs.h>
24#include <linux/binfmts.h> 24#include <linux/binfmts.h>
25#include <linux/in.h> 25#include <linux/in.h>
26#include <linux/spinlock.h>
26#include "flask.h" 27#include "flask.h"
27#include "avc.h" 28#include "avc.h"
28 29
@@ -108,6 +109,7 @@ struct sk_security_struct {
108 NLBL_REQUIRE, 109 NLBL_REQUIRE,
109 NLBL_LABELED, 110 NLBL_LABELED,
110 } nlbl_state; 111 } nlbl_state;
112 spinlock_t nlbl_lock; /* protects nlbl_state */
111#endif 113#endif
112}; 114};
113 115
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index 1ef79172cc8c..210eec77e7ff 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -34,6 +34,8 @@
34#define POLICYDB_VERSION_MAX POLICYDB_VERSION_RANGETRANS 34#define POLICYDB_VERSION_MAX POLICYDB_VERSION_RANGETRANS
35#endif 35#endif
36 36
37struct sk_buff;
38
37extern int selinux_enabled; 39extern int selinux_enabled;
38extern int selinux_mls_enabled; 40extern int selinux_mls_enabled;
39 41
@@ -80,6 +82,8 @@ int security_netif_sid(char *name, u32 *if_sid,
80int security_node_sid(u16 domain, void *addr, u32 addrlen, 82int security_node_sid(u16 domain, void *addr, u32 addrlen,
81 u32 *out_sid); 83 u32 *out_sid);
82 84
85void security_skb_extlbl_sid(struct sk_buff *skb, u32 base_sid, u32 *sid);
86
83int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid, 87int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid,
84 u16 tclass); 88 u16 tclass);
85 89
diff --git a/security/selinux/include/selinux_netlabel.h b/security/selinux/include/selinux_netlabel.h
index 9de10cc2cef2..2a732c9033e3 100644
--- a/security/selinux/include/selinux_netlabel.h
+++ b/security/selinux/include/selinux_netlabel.h
@@ -38,19 +38,17 @@
38 38
39#ifdef CONFIG_NETLABEL 39#ifdef CONFIG_NETLABEL
40void selinux_netlbl_cache_invalidate(void); 40void selinux_netlbl_cache_invalidate(void);
41int selinux_netlbl_socket_post_create(struct socket *sock, 41int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, u32 base_sid, u32 *sid);
42 int sock_family, 42int selinux_netlbl_socket_post_create(struct socket *sock);
43 u32 sid);
44void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock); 43void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock);
45u32 selinux_netlbl_inet_conn_request(struct sk_buff *skb, u32 sock_sid);
46int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, 44int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
47 struct sk_buff *skb, 45 struct sk_buff *skb,
48 struct avc_audit_data *ad); 46 struct avc_audit_data *ad);
49u32 selinux_netlbl_socket_getpeersec_stream(struct socket *sock); 47void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec,
50u32 selinux_netlbl_socket_getpeersec_dgram(struct sk_buff *skb); 48 int family);
51void selinux_netlbl_sk_security_init(struct sk_security_struct *ssec, 49void selinux_netlbl_sk_security_init(struct sk_security_struct *ssec,
52 int family); 50 int family);
53void selinux_netlbl_sk_clone_security(struct sk_security_struct *ssec, 51void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec,
54 struct sk_security_struct *newssec); 52 struct sk_security_struct *newssec);
55int selinux_netlbl_inode_permission(struct inode *inode, int mask); 53int selinux_netlbl_inode_permission(struct inode *inode, int mask);
56int selinux_netlbl_socket_setsockopt(struct socket *sock, 54int selinux_netlbl_socket_setsockopt(struct socket *sock,
@@ -62,23 +60,23 @@ static inline void selinux_netlbl_cache_invalidate(void)
62 return; 60 return;
63} 61}
64 62
65static inline int selinux_netlbl_socket_post_create(struct socket *sock, 63static inline int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
66 int sock_family, 64 u32 base_sid,
67 u32 sid) 65 u32 *sid)
68{ 66{
67 *sid = SECSID_NULL;
69 return 0; 68 return 0;
70} 69}
71 70
72static inline void selinux_netlbl_sock_graft(struct sock *sk, 71static inline int selinux_netlbl_socket_post_create(struct socket *sock)
73 struct socket *sock)
74{ 72{
75 return; 73 return 0;
76} 74}
77 75
78static inline u32 selinux_netlbl_inet_conn_request(struct sk_buff *skb, 76static inline void selinux_netlbl_sock_graft(struct sock *sk,
79 u32 sock_sid) 77 struct socket *sock)
80{ 78{
81 return SECSID_NULL; 79 return;
82} 80}
83 81
84static inline int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, 82static inline int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
@@ -88,14 +86,11 @@ static inline int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
88 return 0; 86 return 0;
89} 87}
90 88
91static inline u32 selinux_netlbl_socket_getpeersec_stream(struct socket *sock) 89static inline void selinux_netlbl_sk_security_reset(
92{ 90 struct sk_security_struct *ssec,
93 return SECSID_NULL; 91 int family)
94}
95
96static inline u32 selinux_netlbl_socket_getpeersec_dgram(struct sk_buff *skb)
97{ 92{
98 return SECSID_NULL; 93 return;
99} 94}
100 95
101static inline void selinux_netlbl_sk_security_init( 96static inline void selinux_netlbl_sk_security_init(
@@ -105,7 +100,7 @@ static inline void selinux_netlbl_sk_security_init(
105 return; 100 return;
106} 101}
107 102
108static inline void selinux_netlbl_sk_clone_security( 103static inline void selinux_netlbl_sk_security_clone(
109 struct sk_security_struct *ssec, 104 struct sk_security_struct *ssec,
110 struct sk_security_struct *newssec) 105 struct sk_security_struct *newssec)
111{ 106{
diff --git a/security/selinux/include/xfrm.h b/security/selinux/include/xfrm.h
index 526b28019aca..161eb571c82d 100644
--- a/security/selinux/include/xfrm.h
+++ b/security/selinux/include/xfrm.h
@@ -8,20 +8,17 @@
8#define _SELINUX_XFRM_H_ 8#define _SELINUX_XFRM_H_
9 9
10int selinux_xfrm_policy_alloc(struct xfrm_policy *xp, 10int selinux_xfrm_policy_alloc(struct xfrm_policy *xp,
11 struct xfrm_user_sec_ctx *sec_ctx, struct sock *sk); 11 struct xfrm_user_sec_ctx *sec_ctx);
12int selinux_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new); 12int selinux_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new);
13void selinux_xfrm_policy_free(struct xfrm_policy *xp); 13void selinux_xfrm_policy_free(struct xfrm_policy *xp);
14int selinux_xfrm_policy_delete(struct xfrm_policy *xp); 14int selinux_xfrm_policy_delete(struct xfrm_policy *xp);
15int selinux_xfrm_state_alloc(struct xfrm_state *x, 15int selinux_xfrm_state_alloc(struct xfrm_state *x,
16 struct xfrm_user_sec_ctx *sec_ctx, struct xfrm_sec_ctx *pol, u32 secid); 16 struct xfrm_user_sec_ctx *sec_ctx, u32 secid);
17void selinux_xfrm_state_free(struct xfrm_state *x); 17void selinux_xfrm_state_free(struct xfrm_state *x);
18int selinux_xfrm_state_delete(struct xfrm_state *x); 18int selinux_xfrm_state_delete(struct xfrm_state *x);
19int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir); 19int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir);
20int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, 20int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x,
21 struct xfrm_policy *xp, struct flowi *fl); 21 struct xfrm_policy *xp, struct flowi *fl);
22int selinux_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm,
23 struct xfrm_policy *xp);
24
25 22
26/* 23/*
27 * Extract the security blob from the sock (it's actually on the socket) 24 * Extract the security blob from the sock (it's actually on the socket)
@@ -38,9 +35,7 @@ static inline struct inode_security_struct *get_sock_isec(struct sock *sk)
38int selinux_xfrm_sock_rcv_skb(u32 sid, struct sk_buff *skb, 35int selinux_xfrm_sock_rcv_skb(u32 sid, struct sk_buff *skb,
39 struct avc_audit_data *ad); 36 struct avc_audit_data *ad);
40int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, 37int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb,
41 struct avc_audit_data *ad); 38 struct avc_audit_data *ad, u8 proto);
42u32 selinux_socket_getpeer_stream(struct sock *sk);
43u32 selinux_socket_getpeer_dgram(struct sk_buff *skb);
44int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall); 39int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall);
45#else 40#else
46static inline int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb, 41static inline int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb,
@@ -50,20 +45,11 @@ static inline int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb,
50} 45}
51 46
52static inline int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, 47static inline int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb,
53 struct avc_audit_data *ad) 48 struct avc_audit_data *ad, u8 proto)
54{ 49{
55 return 0; 50 return 0;
56} 51}
57 52
58static inline int selinux_socket_getpeer_stream(struct sock *sk)
59{
60 return SECSID_NULL;
61}
62
63static inline int selinux_socket_getpeer_dgram(struct sk_buff *skb)
64{
65 return SECSID_NULL;
66}
67static inline int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall) 53static inline int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall)
68{ 54{
69 *sid = SECSID_NULL; 55 *sid = SECSID_NULL;
@@ -71,4 +57,10 @@ static inline int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int
71} 57}
72#endif 58#endif
73 59
60static inline void selinux_skb_xfrm_sid(struct sk_buff *skb, u32 *sid)
61{
62 int err = selinux_xfrm_decode_session(skb, sid, 0);
63 BUG_ON(err);
64}
65
74#endif /* _SELINUX_XFRM_H_ */ 66#endif /* _SELINUX_XFRM_H_ */
diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c
index b8f4d25cf335..ccfe8755735e 100644
--- a/security/selinux/nlmsgtab.c
+++ b/security/selinux/nlmsgtab.c
@@ -60,7 +60,6 @@ static struct nlmsg_perm nlmsg_route_perms[] =
60 { RTM_DELACTION, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, 60 { RTM_DELACTION, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
61 { RTM_GETACTION, NETLINK_ROUTE_SOCKET__NLMSG_READ }, 61 { RTM_GETACTION, NETLINK_ROUTE_SOCKET__NLMSG_READ },
62 { RTM_NEWPREFIX, NETLINK_ROUTE_SOCKET__NLMSG_WRITE }, 62 { RTM_NEWPREFIX, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
63 { RTM_GETPREFIX, NETLINK_ROUTE_SOCKET__NLMSG_READ },
64 { RTM_GETMULTICAST, NETLINK_ROUTE_SOCKET__NLMSG_READ }, 63 { RTM_GETMULTICAST, NETLINK_ROUTE_SOCKET__NLMSG_READ },
65 { RTM_GETANYCAST, NETLINK_ROUTE_SOCKET__NLMSG_READ }, 64 { RTM_GETANYCAST, NETLINK_ROUTE_SOCKET__NLMSG_READ },
66 { RTM_GETNEIGHTBL, NETLINK_ROUTE_SOCKET__NLMSG_READ }, 65 { RTM_GETNEIGHTBL, NETLINK_ROUTE_SOCKET__NLMSG_READ },
diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c
index d539346ab3a2..ce492a6b38ed 100644
--- a/security/selinux/ss/ebitmap.c
+++ b/security/selinux/ss/ebitmap.c
@@ -6,7 +6,7 @@
6/* 6/*
7 * Updated: Hewlett-Packard <paul.moore@hp.com> 7 * Updated: Hewlett-Packard <paul.moore@hp.com>
8 * 8 *
9 * Added ebitmap_export() and ebitmap_import() 9 * Added support to import/export the NetLabel category bitmap
10 * 10 *
11 * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 11 * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
12 */ 12 */
@@ -14,6 +14,7 @@
14#include <linux/kernel.h> 14#include <linux/kernel.h>
15#include <linux/slab.h> 15#include <linux/slab.h>
16#include <linux/errno.h> 16#include <linux/errno.h>
17#include <net/netlabel.h>
17#include "ebitmap.h" 18#include "ebitmap.h"
18#include "policydb.h" 19#include "policydb.h"
19 20
@@ -67,141 +68,120 @@ int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src)
67 return 0; 68 return 0;
68} 69}
69 70
71#ifdef CONFIG_NETLABEL
70/** 72/**
71 * ebitmap_export - Export an ebitmap to a unsigned char bitmap string 73 * ebitmap_netlbl_export - Export an ebitmap into a NetLabel category bitmap
72 * @src: the ebitmap to export 74 * @ebmap: the ebitmap to export
73 * @dst: the resulting bitmap string 75 * @catmap: the NetLabel category bitmap
74 * @dst_len: length of dst in bytes
75 * 76 *
76 * Description: 77 * Description:
77 * Allocate a buffer at least src->highbit bits long and export the extensible 78 * Export a SELinux extensibile bitmap into a NetLabel category bitmap.
78 * bitmap into the buffer. The bitmap string will be in little endian format, 79 * Returns zero on success, negative values on error.
79 * i.e. LSB first. The value returned in dst_len may not the true size of the
80 * buffer as the length of the buffer is rounded up to a multiple of MAPTYPE.
81 * The caller must free the buffer when finished. Returns zero on success,
82 * negative values on failure.
83 * 80 *
84 */ 81 */
85int ebitmap_export(const struct ebitmap *src, 82int ebitmap_netlbl_export(struct ebitmap *ebmap,
86 unsigned char **dst, 83 struct netlbl_lsm_secattr_catmap **catmap)
87 size_t *dst_len)
88{ 84{
89 size_t bitmap_len; 85 struct ebitmap_node *e_iter = ebmap->node;
90 unsigned char *bitmap; 86 struct netlbl_lsm_secattr_catmap *c_iter;
91 struct ebitmap_node *iter_node; 87 u32 cmap_idx;
92 MAPTYPE node_val; 88
93 size_t bitmap_byte; 89 /* This function is a much simpler because SELinux's MAPTYPE happens
94 unsigned char bitmask; 90 * to be the same as NetLabel's NETLBL_CATMAP_MAPTYPE, if MAPTYPE is
95 91 * changed from a u64 this function will most likely need to be changed
96 if (src->highbit == 0) { 92 * as well. It's not ideal but I think the tradeoff in terms of
97 *dst = NULL; 93 * neatness and speed is worth it. */
98 *dst_len = 0; 94
95 if (e_iter == NULL) {
96 *catmap = NULL;
99 return 0; 97 return 0;
100 } 98 }
101 99
102 bitmap_len = src->highbit / 8; 100 c_iter = netlbl_secattr_catmap_alloc(GFP_ATOMIC);
103 if (src->highbit % 7) 101 if (c_iter == NULL)
104 bitmap_len += 1;
105
106 bitmap = kzalloc((bitmap_len & ~(sizeof(MAPTYPE) - 1)) +
107 sizeof(MAPTYPE),
108 GFP_ATOMIC);
109 if (bitmap == NULL)
110 return -ENOMEM; 102 return -ENOMEM;
103 *catmap = c_iter;
104 c_iter->startbit = e_iter->startbit & ~(NETLBL_CATMAP_SIZE - 1);
105
106 while (e_iter != NULL) {
107 if (e_iter->startbit >=
108 (c_iter->startbit + NETLBL_CATMAP_SIZE)) {
109 c_iter->next = netlbl_secattr_catmap_alloc(GFP_ATOMIC);
110 if (c_iter->next == NULL)
111 goto netlbl_export_failure;
112 c_iter = c_iter->next;
113 c_iter->startbit = e_iter->startbit &
114 ~(NETLBL_CATMAP_SIZE - 1);
115 }
116 cmap_idx = (e_iter->startbit - c_iter->startbit) /
117 NETLBL_CATMAP_MAPSIZE;
118 c_iter->bitmap[cmap_idx] = e_iter->map;
119 e_iter = e_iter->next;
120 }
111 121
112 iter_node = src->node;
113 do {
114 bitmap_byte = iter_node->startbit / 8;
115 bitmask = 0x80;
116 node_val = iter_node->map;
117 do {
118 if (bitmask == 0) {
119 bitmap_byte++;
120 bitmask = 0x80;
121 }
122 if (node_val & (MAPTYPE)0x01)
123 bitmap[bitmap_byte] |= bitmask;
124 node_val >>= 1;
125 bitmask >>= 1;
126 } while (node_val > 0);
127 iter_node = iter_node->next;
128 } while (iter_node);
129
130 *dst = bitmap;
131 *dst_len = bitmap_len;
132 return 0; 122 return 0;
123
124netlbl_export_failure:
125 netlbl_secattr_catmap_free(*catmap);
126 return -ENOMEM;
133} 127}
134 128
135/** 129/**
136 * ebitmap_import - Import an unsigned char bitmap string into an ebitmap 130 * ebitmap_netlbl_import - Import a NetLabel category bitmap into an ebitmap
137 * @src: the bitmap string 131 * @ebmap: the ebitmap to export
138 * @src_len: the bitmap length in bytes 132 * @catmap: the NetLabel category bitmap
139 * @dst: the empty ebitmap
140 * 133 *
141 * Description: 134 * Description:
142 * This function takes a little endian bitmap string in src and imports it into 135 * Import a NetLabel category bitmap into a SELinux extensibile bitmap.
143 * the ebitmap pointed to by dst. Returns zero on success, negative values on 136 * Returns zero on success, negative values on error.
144 * failure.
145 * 137 *
146 */ 138 */
147int ebitmap_import(const unsigned char *src, 139int ebitmap_netlbl_import(struct ebitmap *ebmap,
148 size_t src_len, 140 struct netlbl_lsm_secattr_catmap *catmap)
149 struct ebitmap *dst)
150{ 141{
151 size_t src_off = 0; 142 struct ebitmap_node *e_iter = NULL;
152 size_t node_limit; 143 struct ebitmap_node *emap_prev = NULL;
153 struct ebitmap_node *node_new; 144 struct netlbl_lsm_secattr_catmap *c_iter = catmap;
154 struct ebitmap_node *node_last = NULL; 145 u32 c_idx;
155 u32 i_byte;
156 u32 i_bit;
157 unsigned char src_byte;
158
159 while (src_off < src_len) {
160 if (src_len - src_off >= sizeof(MAPTYPE)) {
161 if (*(MAPTYPE *)&src[src_off] == 0) {
162 src_off += sizeof(MAPTYPE);
163 continue;
164 }
165 node_limit = sizeof(MAPTYPE);
166 } else {
167 for (src_byte = 0, i_byte = src_off;
168 i_byte < src_len && src_byte == 0;
169 i_byte++)
170 src_byte |= src[i_byte];
171 if (src_byte == 0)
172 break;
173 node_limit = src_len - src_off;
174 }
175 146
176 node_new = kzalloc(sizeof(*node_new), GFP_ATOMIC); 147 /* This function is a much simpler because SELinux's MAPTYPE happens
177 if (unlikely(node_new == NULL)) { 148 * to be the same as NetLabel's NETLBL_CATMAP_MAPTYPE, if MAPTYPE is
178 ebitmap_destroy(dst); 149 * changed from a u64 this function will most likely need to be changed
179 return -ENOMEM; 150 * as well. It's not ideal but I think the tradeoff in terms of
180 } 151 * neatness and speed is worth it. */
181 node_new->startbit = src_off * 8;
182 for (i_byte = 0; i_byte < node_limit; i_byte++) {
183 src_byte = src[src_off++];
184 for (i_bit = i_byte * 8; src_byte != 0; i_bit++) {
185 if (src_byte & 0x80)
186 node_new->map |= MAPBIT << i_bit;
187 src_byte <<= 1;
188 }
189 }
190 152
191 if (node_last != NULL) 153 do {
192 node_last->next = node_new; 154 for (c_idx = 0; c_idx < NETLBL_CATMAP_MAPCNT; c_idx++) {
193 else 155 if (c_iter->bitmap[c_idx] == 0)
194 dst->node = node_new; 156 continue;
195 node_last = node_new; 157
196 } 158 e_iter = kzalloc(sizeof(*e_iter), GFP_ATOMIC);
159 if (e_iter == NULL)
160 goto netlbl_import_failure;
161 if (emap_prev == NULL)
162 ebmap->node = e_iter;
163 else
164 emap_prev->next = e_iter;
165 emap_prev = e_iter;
197 166
198 if (likely(node_last != NULL)) 167 e_iter->startbit = c_iter->startbit +
199 dst->highbit = node_last->startbit + MAPSIZE; 168 NETLBL_CATMAP_MAPSIZE * c_idx;
169 e_iter->map = c_iter->bitmap[c_idx];
170 }
171 c_iter = c_iter->next;
172 } while (c_iter != NULL);
173 if (e_iter != NULL)
174 ebmap->highbit = e_iter->startbit + MAPSIZE;
200 else 175 else
201 ebitmap_init(dst); 176 ebitmap_destroy(ebmap);
202 177
203 return 0; 178 return 0;
179
180netlbl_import_failure:
181 ebitmap_destroy(ebmap);
182 return -ENOMEM;
204} 183}
184#endif /* CONFIG_NETLABEL */
205 185
206int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2) 186int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2)
207{ 187{
diff --git a/security/selinux/ss/ebitmap.h b/security/selinux/ss/ebitmap.h
index da2d4651b10d..1270e34b61c1 100644
--- a/security/selinux/ss/ebitmap.h
+++ b/security/selinux/ss/ebitmap.h
@@ -14,6 +14,8 @@
14#ifndef _SS_EBITMAP_H_ 14#ifndef _SS_EBITMAP_H_
15#define _SS_EBITMAP_H_ 15#define _SS_EBITMAP_H_
16 16
17#include <net/netlabel.h>
18
17#define MAPTYPE u64 /* portion of bitmap in each node */ 19#define MAPTYPE u64 /* portion of bitmap in each node */
18#define MAPSIZE (sizeof(MAPTYPE) * 8) /* number of bits in node bitmap */ 20#define MAPSIZE (sizeof(MAPTYPE) * 8) /* number of bits in node bitmap */
19#define MAPBIT 1ULL /* a bit in the node bitmap */ 21#define MAPBIT 1ULL /* a bit in the node bitmap */
@@ -69,16 +71,28 @@ static inline int ebitmap_node_get_bit(struct ebitmap_node * n,
69 71
70int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2); 72int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2);
71int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src); 73int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src);
72int ebitmap_export(const struct ebitmap *src,
73 unsigned char **dst,
74 size_t *dst_len);
75int ebitmap_import(const unsigned char *src,
76 size_t src_len,
77 struct ebitmap *dst);
78int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2); 74int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2);
79int ebitmap_get_bit(struct ebitmap *e, unsigned long bit); 75int ebitmap_get_bit(struct ebitmap *e, unsigned long bit);
80int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value); 76int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value);
81void ebitmap_destroy(struct ebitmap *e); 77void ebitmap_destroy(struct ebitmap *e);
82int ebitmap_read(struct ebitmap *e, void *fp); 78int ebitmap_read(struct ebitmap *e, void *fp);
83 79
80#ifdef CONFIG_NETLABEL
81int ebitmap_netlbl_export(struct ebitmap *ebmap,
82 struct netlbl_lsm_secattr_catmap **catmap);
83int ebitmap_netlbl_import(struct ebitmap *ebmap,
84 struct netlbl_lsm_secattr_catmap *catmap);
85#else
86static inline int ebitmap_netlbl_export(struct ebitmap *ebmap,
87 struct netlbl_lsm_secattr_catmap **catmap)
88{
89 return -ENOMEM;
90}
91static inline int ebitmap_netlbl_import(struct ebitmap *ebmap,
92 struct netlbl_lsm_secattr_catmap *catmap)
93{
94 return -ENOMEM;
95}
96#endif
97
84#endif /* _SS_EBITMAP_H_ */ 98#endif /* _SS_EBITMAP_H_ */
diff --git a/security/selinux/ss/hashtab.c b/security/selinux/ss/hashtab.c
index 24e5ec957630..77b530c3bbce 100644
--- a/security/selinux/ss/hashtab.c
+++ b/security/selinux/ss/hashtab.c
@@ -8,8 +8,8 @@
8#include <linux/errno.h> 8#include <linux/errno.h>
9#include "hashtab.h" 9#include "hashtab.h"
10 10
11struct hashtab *hashtab_create(u32 (*hash_value)(struct hashtab *h, void *key), 11struct hashtab *hashtab_create(u32 (*hash_value)(struct hashtab *h, const void *key),
12 int (*keycmp)(struct hashtab *h, void *key1, void *key2), 12 int (*keycmp)(struct hashtab *h, const void *key1, const void *key2),
13 u32 size) 13 u32 size)
14{ 14{
15 struct hashtab *p; 15 struct hashtab *p;
@@ -71,7 +71,7 @@ int hashtab_insert(struct hashtab *h, void *key, void *datum)
71 return 0; 71 return 0;
72} 72}
73 73
74void *hashtab_search(struct hashtab *h, void *key) 74void *hashtab_search(struct hashtab *h, const void *key)
75{ 75{
76 u32 hvalue; 76 u32 hvalue;
77 struct hashtab_node *cur; 77 struct hashtab_node *cur;
diff --git a/security/selinux/ss/hashtab.h b/security/selinux/ss/hashtab.h
index 4cc85816a718..7e2ff3e3c6d2 100644
--- a/security/selinux/ss/hashtab.h
+++ b/security/selinux/ss/hashtab.h
@@ -22,9 +22,9 @@ struct hashtab {
22 struct hashtab_node **htable; /* hash table */ 22 struct hashtab_node **htable; /* hash table */
23 u32 size; /* number of slots in hash table */ 23 u32 size; /* number of slots in hash table */
24 u32 nel; /* number of elements in hash table */ 24 u32 nel; /* number of elements in hash table */
25 u32 (*hash_value)(struct hashtab *h, void *key); 25 u32 (*hash_value)(struct hashtab *h, const void *key);
26 /* hash function */ 26 /* hash function */
27 int (*keycmp)(struct hashtab *h, void *key1, void *key2); 27 int (*keycmp)(struct hashtab *h, const void *key1, const void *key2);
28 /* key comparison function */ 28 /* key comparison function */
29}; 29};
30 30
@@ -39,8 +39,8 @@ struct hashtab_info {
39 * Returns NULL if insufficent space is available or 39 * Returns NULL if insufficent space is available or
40 * the new hash table otherwise. 40 * the new hash table otherwise.
41 */ 41 */
42struct hashtab *hashtab_create(u32 (*hash_value)(struct hashtab *h, void *key), 42struct hashtab *hashtab_create(u32 (*hash_value)(struct hashtab *h, const void *key),
43 int (*keycmp)(struct hashtab *h, void *key1, void *key2), 43 int (*keycmp)(struct hashtab *h, const void *key1, const void *key2),
44 u32 size); 44 u32 size);
45 45
46/* 46/*
@@ -59,7 +59,7 @@ int hashtab_insert(struct hashtab *h, void *k, void *d);
59 * Returns NULL if no entry has the specified key or 59 * Returns NULL if no entry has the specified key or
60 * the datum of the entry otherwise. 60 * the datum of the entry otherwise.
61 */ 61 */
62void *hashtab_search(struct hashtab *h, void *k); 62void *hashtab_search(struct hashtab *h, const void *k);
63 63
64/* 64/*
65 * Destroys the specified hash table. 65 * Destroys the specified hash table.
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c
index 2cca8e251624..b4f682dc13ff 100644
--- a/security/selinux/ss/mls.c
+++ b/security/selinux/ss/mls.c
@@ -13,7 +13,7 @@
13/* 13/*
14 * Updated: Hewlett-Packard <paul.moore@hp.com> 14 * Updated: Hewlett-Packard <paul.moore@hp.com>
15 * 15 *
16 * Added support to import/export the MLS label 16 * Added support to import/export the MLS label from NetLabel
17 * 17 *
18 * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 18 * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
19 */ 19 */
@@ -22,6 +22,7 @@
22#include <linux/slab.h> 22#include <linux/slab.h>
23#include <linux/string.h> 23#include <linux/string.h>
24#include <linux/errno.h> 24#include <linux/errno.h>
25#include <net/netlabel.h>
25#include "sidtab.h" 26#include "sidtab.h"
26#include "mls.h" 27#include "mls.h"
27#include "policydb.h" 28#include "policydb.h"
@@ -571,163 +572,108 @@ int mls_compute_sid(struct context *scontext,
571 return -EINVAL; 572 return -EINVAL;
572} 573}
573 574
575#ifdef CONFIG_NETLABEL
574/** 576/**
575 * mls_export_lvl - Export the MLS sensitivity levels 577 * mls_export_netlbl_lvl - Export the MLS sensitivity levels to NetLabel
576 * @context: the security context 578 * @context: the security context
577 * @low: the low sensitivity level 579 * @secattr: the NetLabel security attributes
578 * @high: the high sensitivity level
579 * 580 *
580 * Description: 581 * Description:
581 * Given the security context copy the low MLS sensitivity level into lvl_low 582 * Given the security context copy the low MLS sensitivity level into the
582 * and the high sensitivity level in lvl_high. The MLS levels are only 583 * NetLabel MLS sensitivity level field.
583 * exported if the pointers are not NULL, if they are NULL then that level is
584 * not exported.
585 * 584 *
586 */ 585 */
587void mls_export_lvl(const struct context *context, u32 *low, u32 *high) 586void mls_export_netlbl_lvl(struct context *context,
587 struct netlbl_lsm_secattr *secattr)
588{ 588{
589 if (!selinux_mls_enabled) 589 if (!selinux_mls_enabled)
590 return; 590 return;
591 591
592 if (low != NULL) 592 secattr->mls_lvl = context->range.level[0].sens - 1;
593 *low = context->range.level[0].sens - 1; 593 secattr->flags |= NETLBL_SECATTR_MLS_LVL;
594 if (high != NULL)
595 *high = context->range.level[1].sens - 1;
596} 594}
597 595
598/** 596/**
599 * mls_import_lvl - Import the MLS sensitivity levels 597 * mls_import_netlbl_lvl - Import the NetLabel MLS sensitivity levels
600 * @context: the security context 598 * @context: the security context
601 * @low: the low sensitivity level 599 * @secattr: the NetLabel security attributes
602 * @high: the high sensitivity level
603 * 600 *
604 * Description: 601 * Description:
605 * Given the security context and the two sensitivty levels, set the MLS levels 602 * Given the security context and the NetLabel security attributes, copy the
606 * in the context according the two given as parameters. Returns zero on 603 * NetLabel MLS sensitivity level into the context.
607 * success, negative values on failure.
608 * 604 *
609 */ 605 */
610void mls_import_lvl(struct context *context, u32 low, u32 high) 606void mls_import_netlbl_lvl(struct context *context,
607 struct netlbl_lsm_secattr *secattr)
611{ 608{
612 if (!selinux_mls_enabled) 609 if (!selinux_mls_enabled)
613 return; 610 return;
614 611
615 context->range.level[0].sens = low + 1; 612 context->range.level[0].sens = secattr->mls_lvl + 1;
616 context->range.level[1].sens = high + 1; 613 context->range.level[1].sens = context->range.level[0].sens;
617} 614}
618 615
619/** 616/**
620 * mls_export_cat - Export the MLS categories 617 * mls_export_netlbl_cat - Export the MLS categories to NetLabel
621 * @context: the security context 618 * @context: the security context
622 * @low: the low category 619 * @secattr: the NetLabel security attributes
623 * @low_len: length of the cat_low bitmap in bytes
624 * @high: the high category
625 * @high_len: length of the cat_high bitmap in bytes
626 * 620 *
627 * Description: 621 * Description:
628 * Given the security context export the low MLS category bitmap into cat_low 622 * Given the security context copy the low MLS categories into the NetLabel
629 * and the high category bitmap into cat_high. The MLS categories are only 623 * MLS category field. Returns zero on success, negative values on failure.
630 * exported if the pointers are not NULL, if they are NULL then that level is
631 * not exported. The caller is responsibile for freeing the memory when
632 * finished. Returns zero on success, negative values on failure.
633 * 624 *
634 */ 625 */
635int mls_export_cat(const struct context *context, 626int mls_export_netlbl_cat(struct context *context,
636 unsigned char **low, 627 struct netlbl_lsm_secattr *secattr)
637 size_t *low_len,
638 unsigned char **high,
639 size_t *high_len)
640{ 628{
641 int rc = -EPERM; 629 int rc;
642 630
643 if (!selinux_mls_enabled) { 631 if (!selinux_mls_enabled)
644 *low = NULL;
645 *low_len = 0;
646 *high = NULL;
647 *high_len = 0;
648 return 0; 632 return 0;
649 }
650 633
651 if (low != NULL) { 634 rc = ebitmap_netlbl_export(&context->range.level[0].cat,
652 rc = ebitmap_export(&context->range.level[0].cat, 635 &secattr->mls_cat);
653 low, 636 if (rc == 0 && secattr->mls_cat != NULL)
654 low_len); 637 secattr->flags |= NETLBL_SECATTR_MLS_CAT;
655 if (rc != 0)
656 goto export_cat_failure;
657 }
658 if (high != NULL) {
659 rc = ebitmap_export(&context->range.level[1].cat,
660 high,
661 high_len);
662 if (rc != 0)
663 goto export_cat_failure;
664 }
665
666 return 0;
667 638
668export_cat_failure:
669 if (low != NULL) {
670 kfree(*low);
671 *low = NULL;
672 *low_len = 0;
673 }
674 if (high != NULL) {
675 kfree(*high);
676 *high = NULL;
677 *high_len = 0;
678 }
679 return rc; 639 return rc;
680} 640}
681 641
682/** 642/**
683 * mls_import_cat - Import the MLS categories 643 * mls_import_netlbl_cat - Import the MLS categories from NetLabel
684 * @context: the security context 644 * @context: the security context
685 * @low: the low category 645 * @secattr: the NetLabel security attributes
686 * @low_len: length of the cat_low bitmap in bytes
687 * @high: the high category
688 * @high_len: length of the cat_high bitmap in bytes
689 * 646 *
690 * Description: 647 * Description:
691 * Given the security context and the two category bitmap strings import the 648 * Copy the NetLabel security attributes into the SELinux context; since the
692 * categories into the security context. The MLS categories are only imported 649 * NetLabel security attribute only contains a single MLS category use it for
693 * if the pointers are not NULL, if they are NULL they are skipped. Returns 650 * both the low and high categories of the context. Returns zero on success,
694 * zero on success, negative values on failure. 651 * negative values on failure.
695 * 652 *
696 */ 653 */
697int mls_import_cat(struct context *context, 654int mls_import_netlbl_cat(struct context *context,
698 const unsigned char *low, 655 struct netlbl_lsm_secattr *secattr)
699 size_t low_len,
700 const unsigned char *high,
701 size_t high_len)
702{ 656{
703 int rc = -EPERM; 657 int rc;
704 658
705 if (!selinux_mls_enabled) 659 if (!selinux_mls_enabled)
706 return 0; 660 return 0;
707 661
708 if (low != NULL) { 662 rc = ebitmap_netlbl_import(&context->range.level[0].cat,
709 rc = ebitmap_import(low, 663 secattr->mls_cat);
710 low_len, 664 if (rc != 0)
711 &context->range.level[0].cat); 665 goto import_netlbl_cat_failure;
712 if (rc != 0) 666
713 goto import_cat_failure; 667 rc = ebitmap_cpy(&context->range.level[1].cat,
714 } 668 &context->range.level[0].cat);
715 if (high != NULL) { 669 if (rc != 0)
716 if (high == low) 670 goto import_netlbl_cat_failure;
717 rc = ebitmap_cpy(&context->range.level[1].cat,
718 &context->range.level[0].cat);
719 else
720 rc = ebitmap_import(high,
721 high_len,
722 &context->range.level[1].cat);
723 if (rc != 0)
724 goto import_cat_failure;
725 }
726 671
727 return 0; 672 return 0;
728 673
729import_cat_failure: 674import_netlbl_cat_failure:
730 ebitmap_destroy(&context->range.level[0].cat); 675 ebitmap_destroy(&context->range.level[0].cat);
731 ebitmap_destroy(&context->range.level[1].cat); 676 ebitmap_destroy(&context->range.level[1].cat);
732 return rc; 677 return rc;
733} 678}
679#endif /* CONFIG_NETLABEL */
diff --git a/security/selinux/ss/mls.h b/security/selinux/ss/mls.h
index df6032c6d492..661d6fc76966 100644
--- a/security/selinux/ss/mls.h
+++ b/security/selinux/ss/mls.h
@@ -13,7 +13,7 @@
13/* 13/*
14 * Updated: Hewlett-Packard <paul.moore@hp.com> 14 * Updated: Hewlett-Packard <paul.moore@hp.com>
15 * 15 *
16 * Added support to import/export the MLS label 16 * Added support to import/export the MLS label from NetLabel
17 * 17 *
18 * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 18 * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
19 */ 19 */
@@ -69,19 +69,37 @@ int mls_compute_sid(struct context *scontext,
69int mls_setup_user_range(struct context *fromcon, struct user_datum *user, 69int mls_setup_user_range(struct context *fromcon, struct user_datum *user,
70 struct context *usercon); 70 struct context *usercon);
71 71
72void mls_export_lvl(const struct context *context, u32 *low, u32 *high); 72#ifdef CONFIG_NETLABEL
73void mls_import_lvl(struct context *context, u32 low, u32 high); 73void mls_export_netlbl_lvl(struct context *context,
74 74 struct netlbl_lsm_secattr *secattr);
75int mls_export_cat(const struct context *context, 75void mls_import_netlbl_lvl(struct context *context,
76 unsigned char **low, 76 struct netlbl_lsm_secattr *secattr);
77 size_t *low_len, 77int mls_export_netlbl_cat(struct context *context,
78 unsigned char **high, 78 struct netlbl_lsm_secattr *secattr);
79 size_t *high_len); 79int mls_import_netlbl_cat(struct context *context,
80int mls_import_cat(struct context *context, 80 struct netlbl_lsm_secattr *secattr);
81 const unsigned char *low, 81#else
82 size_t low_len, 82static inline void mls_export_netlbl_lvl(struct context *context,
83 const unsigned char *high, 83 struct netlbl_lsm_secattr *secattr)
84 size_t high_len); 84{
85 return;
86}
87static inline void mls_import_netlbl_lvl(struct context *context,
88 struct netlbl_lsm_secattr *secattr)
89{
90 return;
91}
92static inline int mls_export_netlbl_cat(struct context *context,
93 struct netlbl_lsm_secattr *secattr)
94{
95 return -ENOMEM;
96}
97static inline int mls_import_netlbl_cat(struct context *context,
98 struct netlbl_lsm_secattr *secattr)
99{
100 return -ENOMEM;
101}
102#endif
85 103
86#endif /* _SS_MLS_H */ 104#endif /* _SS_MLS_H */
87 105
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index ba48961f9d05..cd79c6338aa0 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -468,7 +468,7 @@ static int common_destroy(void *key, void *datum, void *p)
468 return 0; 468 return 0;
469} 469}
470 470
471static int class_destroy(void *key, void *datum, void *p) 471static int cls_destroy(void *key, void *datum, void *p)
472{ 472{
473 struct class_datum *cladatum; 473 struct class_datum *cladatum;
474 struct constraint_node *constraint, *ctemp; 474 struct constraint_node *constraint, *ctemp;
@@ -566,7 +566,7 @@ static int cat_destroy(void *key, void *datum, void *p)
566static int (*destroy_f[SYM_NUM]) (void *key, void *datum, void *datap) = 566static int (*destroy_f[SYM_NUM]) (void *key, void *datum, void *datap) =
567{ 567{
568 common_destroy, 568 common_destroy,
569 class_destroy, 569 cls_destroy,
570 role_destroy, 570 role_destroy,
571 type_destroy, 571 type_destroy,
572 user_destroy, 572 user_destroy,
@@ -1124,7 +1124,7 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp)
1124out: 1124out:
1125 return rc; 1125 return rc;
1126bad: 1126bad:
1127 class_destroy(key, cladatum, NULL); 1127 cls_destroy(key, cladatum, NULL);
1128 goto out; 1128 goto out;
1129} 1129}
1130 1130
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index bfe122764c98..bdb7070dd3dc 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -17,9 +17,13 @@
17 * 17 *
18 * Added support for NetLabel 18 * Added support for NetLabel
19 * 19 *
20 * Updated: Chad Sellers <csellers@tresys.com>
21 *
22 * Added validation of kernel classes and permissions
23 *
20 * Copyright (C) 2006 Hewlett-Packard Development Company, L.P. 24 * Copyright (C) 2006 Hewlett-Packard Development Company, L.P.
21 * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc. 25 * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc.
22 * Copyright (C) 2003 - 2004 Tresys Technology, LLC 26 * Copyright (C) 2003 - 2004, 2006 Tresys Technology, LLC
23 * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com> 27 * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com>
24 * This program is free software; you can redistribute it and/or modify 28 * This program is free software; you can redistribute it and/or modify
25 * it under the terms of the GNU General Public License as published by 29 * it under the terms of the GNU General Public License as published by
@@ -29,6 +33,7 @@
29#include <linux/slab.h> 33#include <linux/slab.h>
30#include <linux/string.h> 34#include <linux/string.h>
31#include <linux/spinlock.h> 35#include <linux/spinlock.h>
36#include <linux/rcupdate.h>
32#include <linux/errno.h> 37#include <linux/errno.h>
33#include <linux/in.h> 38#include <linux/in.h>
34#include <linux/sched.h> 39#include <linux/sched.h>
@@ -49,10 +54,17 @@
49#include "mls.h" 54#include "mls.h"
50#include "objsec.h" 55#include "objsec.h"
51#include "selinux_netlabel.h" 56#include "selinux_netlabel.h"
57#include "xfrm.h"
58#include "ebitmap.h"
52 59
53extern void selnl_notify_policyload(u32 seqno); 60extern void selnl_notify_policyload(u32 seqno);
54unsigned int policydb_loaded_version; 61unsigned int policydb_loaded_version;
55 62
63/*
64 * This is declared in avc.c
65 */
66extern const struct selinux_class_perm selinux_class_perm;
67
56static DEFINE_RWLOCK(policy_rwlock); 68static DEFINE_RWLOCK(policy_rwlock);
57#define POLICY_RDLOCK read_lock(&policy_rwlock) 69#define POLICY_RDLOCK read_lock(&policy_rwlock)
58#define POLICY_WRLOCK write_lock_irq(&policy_rwlock) 70#define POLICY_WRLOCK write_lock_irq(&policy_rwlock)
@@ -1019,86 +1031,112 @@ int security_change_sid(u32 ssid,
1019} 1031}
1020 1032
1021/* 1033/*
1022 * Verify that each permission that is defined under the 1034 * Verify that each kernel class that is defined in the
1023 * existing policy is still defined with the same value 1035 * policy is correct
1024 * in the new policy.
1025 */
1026static int validate_perm(void *key, void *datum, void *p)
1027{
1028 struct hashtab *h;
1029 struct perm_datum *perdatum, *perdatum2;
1030 int rc = 0;
1031
1032
1033 h = p;
1034 perdatum = datum;
1035
1036 perdatum2 = hashtab_search(h, key);
1037 if (!perdatum2) {
1038 printk(KERN_ERR "security: permission %s disappeared",
1039 (char *)key);
1040 rc = -ENOENT;
1041 goto out;
1042 }
1043 if (perdatum->value != perdatum2->value) {
1044 printk(KERN_ERR "security: the value of permission %s changed",
1045 (char *)key);
1046 rc = -EINVAL;
1047 }
1048out:
1049 return rc;
1050}
1051
1052/*
1053 * Verify that each class that is defined under the
1054 * existing policy is still defined with the same
1055 * attributes in the new policy.
1056 */ 1036 */
1057static int validate_class(void *key, void *datum, void *p) 1037static int validate_classes(struct policydb *p)
1058{ 1038{
1059 struct policydb *newp; 1039 int i, j;
1060 struct class_datum *cladatum, *cladatum2; 1040 struct class_datum *cladatum;
1061 int rc; 1041 struct perm_datum *perdatum;
1062 1042 u32 nprim, tmp, common_pts_len, perm_val, pol_val;
1063 newp = p; 1043 u16 class_val;
1064 cladatum = datum; 1044 const struct selinux_class_perm *kdefs = &selinux_class_perm;
1065 1045 const char *def_class, *def_perm, *pol_class;
1066 cladatum2 = hashtab_search(newp->p_classes.table, key); 1046 struct symtab *perms;
1067 if (!cladatum2) { 1047
1068 printk(KERN_ERR "security: class %s disappeared\n", 1048 for (i = 1; i < kdefs->cts_len; i++) {
1069 (char *)key); 1049 def_class = kdefs->class_to_string[i];
1070 rc = -ENOENT; 1050 if (i > p->p_classes.nprim) {
1071 goto out; 1051 printk(KERN_INFO
1072 } 1052 "security: class %s not defined in policy\n",
1073 if (cladatum->value != cladatum2->value) { 1053 def_class);
1074 printk(KERN_ERR "security: the value of class %s changed\n", 1054 continue;
1075 (char *)key); 1055 }
1076 rc = -EINVAL; 1056 pol_class = p->p_class_val_to_name[i-1];
1077 goto out; 1057 if (strcmp(pol_class, def_class)) {
1058 printk(KERN_ERR
1059 "security: class %d is incorrect, found %s but should be %s\n",
1060 i, pol_class, def_class);
1061 return -EINVAL;
1062 }
1078 } 1063 }
1079 if ((cladatum->comdatum && !cladatum2->comdatum) || 1064 for (i = 0; i < kdefs->av_pts_len; i++) {
1080 (!cladatum->comdatum && cladatum2->comdatum)) { 1065 class_val = kdefs->av_perm_to_string[i].tclass;
1081 printk(KERN_ERR "security: the inherits clause for the access " 1066 perm_val = kdefs->av_perm_to_string[i].value;
1082 "vector definition for class %s changed\n", (char *)key); 1067 def_perm = kdefs->av_perm_to_string[i].name;
1083 rc = -EINVAL; 1068 if (class_val > p->p_classes.nprim)
1084 goto out; 1069 continue;
1070 pol_class = p->p_class_val_to_name[class_val-1];
1071 cladatum = hashtab_search(p->p_classes.table, pol_class);
1072 BUG_ON(!cladatum);
1073 perms = &cladatum->permissions;
1074 nprim = 1 << (perms->nprim - 1);
1075 if (perm_val > nprim) {
1076 printk(KERN_INFO
1077 "security: permission %s in class %s not defined in policy\n",
1078 def_perm, pol_class);
1079 continue;
1080 }
1081 perdatum = hashtab_search(perms->table, def_perm);
1082 if (perdatum == NULL) {
1083 printk(KERN_ERR
1084 "security: permission %s in class %s not found in policy\n",
1085 def_perm, pol_class);
1086 return -EINVAL;
1087 }
1088 pol_val = 1 << (perdatum->value - 1);
1089 if (pol_val != perm_val) {
1090 printk(KERN_ERR
1091 "security: permission %s in class %s has incorrect value\n",
1092 def_perm, pol_class);
1093 return -EINVAL;
1094 }
1085 } 1095 }
1086 if (cladatum->comdatum) { 1096 for (i = 0; i < kdefs->av_inherit_len; i++) {
1087 rc = hashtab_map(cladatum->comdatum->permissions.table, validate_perm, 1097 class_val = kdefs->av_inherit[i].tclass;
1088 cladatum2->comdatum->permissions.table); 1098 if (class_val > p->p_classes.nprim)
1089 if (rc) { 1099 continue;
1090 printk(" in the access vector definition for class " 1100 pol_class = p->p_class_val_to_name[class_val-1];
1091 "%s\n", (char *)key); 1101 cladatum = hashtab_search(p->p_classes.table, pol_class);
1092 goto out; 1102 BUG_ON(!cladatum);
1103 if (!cladatum->comdatum) {
1104 printk(KERN_ERR
1105 "security: class %s should have an inherits clause but does not\n",
1106 pol_class);
1107 return -EINVAL;
1108 }
1109 tmp = kdefs->av_inherit[i].common_base;
1110 common_pts_len = 0;
1111 while (!(tmp & 0x01)) {
1112 common_pts_len++;
1113 tmp >>= 1;
1114 }
1115 perms = &cladatum->comdatum->permissions;
1116 for (j = 0; j < common_pts_len; j++) {
1117 def_perm = kdefs->av_inherit[i].common_pts[j];
1118 if (j >= perms->nprim) {
1119 printk(KERN_INFO
1120 "security: permission %s in class %s not defined in policy\n",
1121 def_perm, pol_class);
1122 continue;
1123 }
1124 perdatum = hashtab_search(perms->table, def_perm);
1125 if (perdatum == NULL) {
1126 printk(KERN_ERR
1127 "security: permission %s in class %s not found in policy\n",
1128 def_perm, pol_class);
1129 return -EINVAL;
1130 }
1131 if (perdatum->value != j + 1) {
1132 printk(KERN_ERR
1133 "security: permission %s in class %s has incorrect value\n",
1134 def_perm, pol_class);
1135 return -EINVAL;
1136 }
1093 } 1137 }
1094 } 1138 }
1095 rc = hashtab_map(cladatum->permissions.table, validate_perm, 1139 return 0;
1096 cladatum2->permissions.table);
1097 if (rc)
1098 printk(" in access vector definition for class %s\n",
1099 (char *)key);
1100out:
1101 return rc;
1102} 1140}
1103 1141
1104/* Clone the SID into the new SID table. */ 1142/* Clone the SID into the new SID table. */
@@ -1243,6 +1281,16 @@ int security_load_policy(void *data, size_t len)
1243 avtab_cache_destroy(); 1281 avtab_cache_destroy();
1244 return -EINVAL; 1282 return -EINVAL;
1245 } 1283 }
1284 /* Verify that the kernel defined classes are correct. */
1285 if (validate_classes(&policydb)) {
1286 printk(KERN_ERR
1287 "security: the definition of a class is incorrect\n");
1288 LOAD_UNLOCK;
1289 sidtab_destroy(&sidtab);
1290 policydb_destroy(&policydb);
1291 avtab_cache_destroy();
1292 return -EINVAL;
1293 }
1246 policydb_loaded_version = policydb.policyvers; 1294 policydb_loaded_version = policydb.policyvers;
1247 ss_initialized = 1; 1295 ss_initialized = 1;
1248 seqno = ++latest_granting; 1296 seqno = ++latest_granting;
@@ -1265,10 +1313,10 @@ int security_load_policy(void *data, size_t len)
1265 1313
1266 sidtab_init(&newsidtab); 1314 sidtab_init(&newsidtab);
1267 1315
1268 /* Verify that the existing classes did not change. */ 1316 /* Verify that the kernel defined classes are correct. */
1269 if (hashtab_map(policydb.p_classes.table, validate_class, &newpolicydb)) { 1317 if (validate_classes(&newpolicydb)) {
1270 printk(KERN_ERR "security: the definition of an existing " 1318 printk(KERN_ERR
1271 "class changed\n"); 1319 "security: the definition of a class is incorrect\n");
1272 rc = -EINVAL; 1320 rc = -EINVAL;
1273 goto err; 1321 goto err;
1274 } 1322 }
@@ -2145,6 +2193,32 @@ void selinux_audit_set_callback(int (*callback)(void))
2145 aurule_callback = callback; 2193 aurule_callback = callback;
2146} 2194}
2147 2195
2196/**
2197 * security_skb_extlbl_sid - Determine the external label of a packet
2198 * @skb: the packet
2199 * @base_sid: the SELinux SID to use as a context for MLS only external labels
2200 * @sid: the packet's SID
2201 *
2202 * Description:
2203 * Check the various different forms of external packet labeling and determine
2204 * the external SID for the packet.
2205 *
2206 */
2207void security_skb_extlbl_sid(struct sk_buff *skb, u32 base_sid, u32 *sid)
2208{
2209 u32 xfrm_sid;
2210 u32 nlbl_sid;
2211
2212 selinux_skb_xfrm_sid(skb, &xfrm_sid);
2213 if (selinux_netlbl_skbuff_getsid(skb,
2214 (xfrm_sid == SECSID_NULL ?
2215 base_sid : xfrm_sid),
2216 &nlbl_sid) != 0)
2217 nlbl_sid = SECSID_NULL;
2218
2219 *sid = (nlbl_sid == SECSID_NULL ? xfrm_sid : nlbl_sid);
2220}
2221
2148#ifdef CONFIG_NETLABEL 2222#ifdef CONFIG_NETLABEL
2149/* 2223/*
2150 * This is the structure we store inside the NetLabel cache block. 2224 * This is the structure we store inside the NetLabel cache block.
@@ -2209,8 +2283,6 @@ static void selinux_netlbl_cache_add(struct sk_buff *skb, struct context *ctx)
2209 cache = kzalloc(sizeof(*cache), GFP_ATOMIC); 2283 cache = kzalloc(sizeof(*cache), GFP_ATOMIC);
2210 if (cache == NULL) 2284 if (cache == NULL)
2211 goto netlbl_cache_add_return; 2285 goto netlbl_cache_add_return;
2212 secattr.cache->free = selinux_netlbl_cache_free;
2213 secattr.cache->data = (void *)cache;
2214 2286
2215 cache->type = NETLBL_CACHE_T_MLS; 2287 cache->type = NETLBL_CACHE_T_MLS;
2216 if (ebitmap_cpy(&cache->data.mls_label.level[0].cat, 2288 if (ebitmap_cpy(&cache->data.mls_label.level[0].cat,
@@ -2223,6 +2295,10 @@ static void selinux_netlbl_cache_add(struct sk_buff *skb, struct context *ctx)
2223 cache->data.mls_label.level[0].sens = ctx->range.level[0].sens; 2295 cache->data.mls_label.level[0].sens = ctx->range.level[0].sens;
2224 cache->data.mls_label.level[1].sens = ctx->range.level[0].sens; 2296 cache->data.mls_label.level[1].sens = ctx->range.level[0].sens;
2225 2297
2298 secattr.cache->free = selinux_netlbl_cache_free;
2299 secattr.cache->data = (void *)cache;
2300 secattr.flags = NETLBL_SECATTR_CACHE;
2301
2226 netlbl_cache_add(skb, &secattr); 2302 netlbl_cache_add(skb, &secattr);
2227 2303
2228netlbl_cache_add_return: 2304netlbl_cache_add_return:
@@ -2268,7 +2344,7 @@ static int selinux_netlbl_secattr_to_sid(struct sk_buff *skb,
2268 2344
2269 POLICY_RDLOCK; 2345 POLICY_RDLOCK;
2270 2346
2271 if (secattr->cache) { 2347 if (secattr->flags & NETLBL_SECATTR_CACHE) {
2272 cache = NETLBL_CACHE(secattr->cache->data); 2348 cache = NETLBL_CACHE(secattr->cache->data);
2273 switch (cache->type) { 2349 switch (cache->type) {
2274 case NETLBL_CACHE_T_SID: 2350 case NETLBL_CACHE_T_SID:
@@ -2301,7 +2377,7 @@ static int selinux_netlbl_secattr_to_sid(struct sk_buff *skb,
2301 default: 2377 default:
2302 goto netlbl_secattr_to_sid_return; 2378 goto netlbl_secattr_to_sid_return;
2303 } 2379 }
2304 } else if (secattr->mls_lvl_vld) { 2380 } else if (secattr->flags & NETLBL_SECATTR_MLS_LVL) {
2305 ctx = sidtab_search(&sidtab, base_sid); 2381 ctx = sidtab_search(&sidtab, base_sid);
2306 if (ctx == NULL) 2382 if (ctx == NULL)
2307 goto netlbl_secattr_to_sid_return; 2383 goto netlbl_secattr_to_sid_return;
@@ -2309,13 +2385,10 @@ static int selinux_netlbl_secattr_to_sid(struct sk_buff *skb,
2309 ctx_new.user = ctx->user; 2385 ctx_new.user = ctx->user;
2310 ctx_new.role = ctx->role; 2386 ctx_new.role = ctx->role;
2311 ctx_new.type = ctx->type; 2387 ctx_new.type = ctx->type;
2312 mls_import_lvl(&ctx_new, secattr->mls_lvl, secattr->mls_lvl); 2388 mls_import_netlbl_lvl(&ctx_new, secattr);
2313 if (secattr->mls_cat) { 2389 if (secattr->flags & NETLBL_SECATTR_MLS_CAT) {
2314 if (mls_import_cat(&ctx_new, 2390 if (ebitmap_netlbl_import(&ctx_new.range.level[0].cat,
2315 secattr->mls_cat, 2391 secattr->mls_cat) != 0)
2316 secattr->mls_cat_len,
2317 NULL,
2318 0) != 0)
2319 goto netlbl_secattr_to_sid_return; 2392 goto netlbl_secattr_to_sid_return;
2320 ctx_new.range.level[1].cat.highbit = 2393 ctx_new.range.level[1].cat.highbit =
2321 ctx_new.range.level[0].cat.highbit; 2394 ctx_new.range.level[0].cat.highbit;
@@ -2360,20 +2433,20 @@ netlbl_secattr_to_sid_return_cleanup:
2360 * assign to the packet. Returns zero on success, negative values on failure. 2433 * assign to the packet. Returns zero on success, negative values on failure.
2361 * 2434 *
2362 */ 2435 */
2363static int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, 2436int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, u32 base_sid, u32 *sid)
2364 u32 base_sid,
2365 u32 *sid)
2366{ 2437{
2367 int rc; 2438 int rc;
2368 struct netlbl_lsm_secattr secattr; 2439 struct netlbl_lsm_secattr secattr;
2369 2440
2370 netlbl_secattr_init(&secattr); 2441 netlbl_secattr_init(&secattr);
2371 rc = netlbl_skbuff_getattr(skb, &secattr); 2442 rc = netlbl_skbuff_getattr(skb, &secattr);
2372 if (rc == 0) 2443 if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE)
2373 rc = selinux_netlbl_secattr_to_sid(skb, 2444 rc = selinux_netlbl_secattr_to_sid(skb,
2374 &secattr, 2445 &secattr,
2375 base_sid, 2446 base_sid,
2376 sid); 2447 sid);
2448 else
2449 *sid = SECSID_NULL;
2377 netlbl_secattr_destroy(&secattr); 2450 netlbl_secattr_destroy(&secattr);
2378 2451
2379 return rc; 2452 return rc;
@@ -2386,7 +2459,9 @@ static int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
2386 * 2459 *
2387 * Description: 2460 * Description:
2388 * Attempt to label a socket using the NetLabel mechanism using the given 2461 * Attempt to label a socket using the NetLabel mechanism using the given
2389 * SID. Returns zero values on success, negative values on failure. 2462 * SID. Returns zero values on success, negative values on failure. The
2463 * caller is responsibile for calling rcu_read_lock() before calling this
2464 * this function and rcu_read_unlock() after this function returns.
2390 * 2465 *
2391 */ 2466 */
2392static int selinux_netlbl_socket_setsid(struct socket *sock, u32 sid) 2467static int selinux_netlbl_socket_setsid(struct socket *sock, u32 sid)
@@ -2409,19 +2484,18 @@ static int selinux_netlbl_socket_setsid(struct socket *sock, u32 sid)
2409 2484
2410 secattr.domain = kstrdup(policydb.p_type_val_to_name[ctx->type - 1], 2485 secattr.domain = kstrdup(policydb.p_type_val_to_name[ctx->type - 1],
2411 GFP_ATOMIC); 2486 GFP_ATOMIC);
2412 mls_export_lvl(ctx, &secattr.mls_lvl, NULL); 2487 secattr.flags |= NETLBL_SECATTR_DOMAIN;
2413 secattr.mls_lvl_vld = 1; 2488 mls_export_netlbl_lvl(ctx, &secattr);
2414 rc = mls_export_cat(ctx, 2489 rc = mls_export_netlbl_cat(ctx, &secattr);
2415 &secattr.mls_cat,
2416 &secattr.mls_cat_len,
2417 NULL,
2418 NULL);
2419 if (rc != 0) 2490 if (rc != 0)
2420 goto netlbl_socket_setsid_return; 2491 goto netlbl_socket_setsid_return;
2421 2492
2422 rc = netlbl_socket_setattr(sock, &secattr); 2493 rc = netlbl_socket_setattr(sock, &secattr);
2423 if (rc == 0) 2494 if (rc == 0) {
2495 spin_lock(&sksec->nlbl_lock);
2424 sksec->nlbl_state = NLBL_LABELED; 2496 sksec->nlbl_state = NLBL_LABELED;
2497 spin_unlock(&sksec->nlbl_lock);
2498 }
2425 2499
2426netlbl_socket_setsid_return: 2500netlbl_socket_setsid_return:
2427 POLICY_RDUNLOCK; 2501 POLICY_RDUNLOCK;
@@ -2430,6 +2504,25 @@ netlbl_socket_setsid_return:
2430} 2504}
2431 2505
2432/** 2506/**
2507 * selinux_netlbl_sk_security_reset - Reset the NetLabel fields
2508 * @ssec: the sk_security_struct
2509 * @family: the socket family
2510 *
2511 * Description:
2512 * Called when the NetLabel state of a sk_security_struct needs to be reset.
2513 * The caller is responsibile for all the NetLabel sk_security_struct locking.
2514 *
2515 */
2516void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec,
2517 int family)
2518{
2519 if (family == PF_INET)
2520 ssec->nlbl_state = NLBL_REQUIRE;
2521 else
2522 ssec->nlbl_state = NLBL_UNSET;
2523}
2524
2525/**
2433 * selinux_netlbl_sk_security_init - Setup the NetLabel fields 2526 * selinux_netlbl_sk_security_init - Setup the NetLabel fields
2434 * @ssec: the sk_security_struct 2527 * @ssec: the sk_security_struct
2435 * @family: the socket family 2528 * @family: the socket family
@@ -2442,14 +2535,13 @@ netlbl_socket_setsid_return:
2442void selinux_netlbl_sk_security_init(struct sk_security_struct *ssec, 2535void selinux_netlbl_sk_security_init(struct sk_security_struct *ssec,
2443 int family) 2536 int family)
2444{ 2537{
2445 if (family == PF_INET) 2538 /* No locking needed, we are the only one who has access to ssec */
2446 ssec->nlbl_state = NLBL_REQUIRE; 2539 selinux_netlbl_sk_security_reset(ssec, family);
2447 else 2540 spin_lock_init(&ssec->nlbl_lock);
2448 ssec->nlbl_state = NLBL_UNSET;
2449} 2541}
2450 2542
2451/** 2543/**
2452 * selinux_netlbl_sk_clone_security - Copy the NetLabel fields 2544 * selinux_netlbl_sk_security_clone - Copy the NetLabel fields
2453 * @ssec: the original sk_security_struct 2545 * @ssec: the original sk_security_struct
2454 * @newssec: the cloned sk_security_struct 2546 * @newssec: the cloned sk_security_struct
2455 * 2547 *
@@ -2458,41 +2550,41 @@ void selinux_netlbl_sk_security_init(struct sk_security_struct *ssec,
2458 * @newssec. 2550 * @newssec.
2459 * 2551 *
2460 */ 2552 */
2461void selinux_netlbl_sk_clone_security(struct sk_security_struct *ssec, 2553void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec,
2462 struct sk_security_struct *newssec) 2554 struct sk_security_struct *newssec)
2463{ 2555{
2556 /* We don't need to take newssec->nlbl_lock because we are the only
2557 * thread with access to newssec, but we do need to take the RCU read
2558 * lock as other threads could have access to ssec */
2559 rcu_read_lock();
2560 selinux_netlbl_sk_security_reset(newssec, ssec->sk->sk_family);
2464 newssec->sclass = ssec->sclass; 2561 newssec->sclass = ssec->sclass;
2465 if (ssec->nlbl_state != NLBL_UNSET) 2562 rcu_read_unlock();
2466 newssec->nlbl_state = NLBL_REQUIRE;
2467 else
2468 newssec->nlbl_state = NLBL_UNSET;
2469} 2563}
2470 2564
2471/** 2565/**
2472 * selinux_netlbl_socket_post_create - Label a socket using NetLabel 2566 * selinux_netlbl_socket_post_create - Label a socket using NetLabel
2473 * @sock: the socket to label 2567 * @sock: the socket to label
2474 * @sock_family: the socket family
2475 * @sid: the SID to use
2476 * 2568 *
2477 * Description: 2569 * Description:
2478 * Attempt to label a socket using the NetLabel mechanism using the given 2570 * Attempt to label a socket using the NetLabel mechanism using the given
2479 * SID. Returns zero values on success, negative values on failure. 2571 * SID. Returns zero values on success, negative values on failure.
2480 * 2572 *
2481 */ 2573 */
2482int selinux_netlbl_socket_post_create(struct socket *sock, 2574int selinux_netlbl_socket_post_create(struct socket *sock)
2483 int sock_family,
2484 u32 sid)
2485{ 2575{
2576 int rc = 0;
2486 struct inode_security_struct *isec = SOCK_INODE(sock)->i_security; 2577 struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
2487 struct sk_security_struct *sksec = sock->sk->sk_security; 2578 struct sk_security_struct *sksec = sock->sk->sk_security;
2488 2579
2489 sksec->sclass = isec->sclass; 2580 sksec->sclass = isec->sclass;
2490 2581
2491 if (sock_family != PF_INET) 2582 rcu_read_lock();
2492 return 0; 2583 if (sksec->nlbl_state == NLBL_REQUIRE)
2584 rc = selinux_netlbl_socket_setsid(sock, sksec->sid);
2585 rcu_read_unlock();
2493 2586
2494 sksec->nlbl_state = NLBL_REQUIRE; 2587 return rc;
2495 return selinux_netlbl_socket_setsid(sock, sid);
2496} 2588}
2497 2589
2498/** 2590/**
@@ -2514,11 +2606,16 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock)
2514 2606
2515 sksec->sclass = isec->sclass; 2607 sksec->sclass = isec->sclass;
2516 2608
2517 if (sk->sk_family != PF_INET) 2609 rcu_read_lock();
2610
2611 if (sksec->nlbl_state != NLBL_REQUIRE) {
2612 rcu_read_unlock();
2518 return; 2613 return;
2614 }
2519 2615
2520 netlbl_secattr_init(&secattr); 2616 netlbl_secattr_init(&secattr);
2521 if (netlbl_sock_getattr(sk, &secattr) == 0 && 2617 if (netlbl_sock_getattr(sk, &secattr) == 0 &&
2618 secattr.flags != NETLBL_SECATTR_NONE &&
2522 selinux_netlbl_secattr_to_sid(NULL, 2619 selinux_netlbl_secattr_to_sid(NULL,
2523 &secattr, 2620 &secattr,
2524 SECINITSID_UNLABELED, 2621 SECINITSID_UNLABELED,
@@ -2526,35 +2623,12 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock)
2526 sksec->peer_sid = nlbl_peer_sid; 2623 sksec->peer_sid = nlbl_peer_sid;
2527 netlbl_secattr_destroy(&secattr); 2624 netlbl_secattr_destroy(&secattr);
2528 2625
2529 sksec->nlbl_state = NLBL_REQUIRE;
2530
2531 /* Try to set the NetLabel on the socket to save time later, if we fail 2626 /* Try to set the NetLabel on the socket to save time later, if we fail
2532 * here we will pick up the pieces in later calls to 2627 * here we will pick up the pieces in later calls to
2533 * selinux_netlbl_inode_permission(). */ 2628 * selinux_netlbl_inode_permission(). */
2534 selinux_netlbl_socket_setsid(sock, sksec->sid); 2629 selinux_netlbl_socket_setsid(sock, sksec->sid);
2535}
2536
2537/**
2538 * selinux_netlbl_inet_conn_request - Handle a new connection request
2539 * @skb: the packet
2540 * @sock_sid: the SID of the parent socket
2541 *
2542 * Description:
2543 * If present, use the security attributes of the packet in @skb and the
2544 * parent sock's SID to arrive at a SID for the new child sock. Returns the
2545 * SID of the connection or SECSID_NULL on failure.
2546 *
2547 */
2548u32 selinux_netlbl_inet_conn_request(struct sk_buff *skb, u32 sock_sid)
2549{
2550 int rc;
2551 u32 peer_sid;
2552
2553 rc = selinux_netlbl_skbuff_getsid(skb, sock_sid, &peer_sid);
2554 if (rc != 0)
2555 return SECSID_NULL;
2556 2630
2557 return peer_sid; 2631 rcu_read_unlock();
2558} 2632}
2559 2633
2560/** 2634/**
@@ -2572,25 +2646,24 @@ u32 selinux_netlbl_inet_conn_request(struct sk_buff *skb, u32 sock_sid)
2572int selinux_netlbl_inode_permission(struct inode *inode, int mask) 2646int selinux_netlbl_inode_permission(struct inode *inode, int mask)
2573{ 2647{
2574 int rc; 2648 int rc;
2575 struct inode_security_struct *isec;
2576 struct sk_security_struct *sksec; 2649 struct sk_security_struct *sksec;
2577 struct socket *sock; 2650 struct socket *sock;
2578 2651
2579 if (!S_ISSOCK(inode->i_mode)) 2652 if (!S_ISSOCK(inode->i_mode) ||
2653 ((mask & (MAY_WRITE | MAY_APPEND)) == 0))
2580 return 0; 2654 return 0;
2581
2582 sock = SOCKET_I(inode); 2655 sock = SOCKET_I(inode);
2583 isec = inode->i_security;
2584 sksec = sock->sk->sk_security; 2656 sksec = sock->sk->sk_security;
2585 mutex_lock(&isec->lock); 2657
2586 if (unlikely(sksec->nlbl_state == NLBL_REQUIRE && 2658 rcu_read_lock();
2587 (mask & (MAY_WRITE | MAY_APPEND)))) { 2659 if (sksec->nlbl_state != NLBL_REQUIRE) {
2588 lock_sock(sock->sk); 2660 rcu_read_unlock();
2589 rc = selinux_netlbl_socket_setsid(sock, sksec->sid); 2661 return 0;
2590 release_sock(sock->sk); 2662 }
2591 } else 2663 lock_sock(sock->sk);
2592 rc = 0; 2664 rc = selinux_netlbl_socket_setsid(sock, sksec->sid);
2593 mutex_unlock(&isec->lock); 2665 release_sock(sock->sk);
2666 rcu_read_unlock();
2594 2667
2595 return rc; 2668 return rc;
2596} 2669}
@@ -2648,42 +2721,6 @@ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
2648} 2721}
2649 2722
2650/** 2723/**
2651 * selinux_netlbl_socket_getpeersec_stream - Return the connected peer's SID
2652 * @sock: the socket
2653 *
2654 * Description:
2655 * Examine @sock to find the connected peer's SID. Returns the SID on success
2656 * or SECSID_NULL on error.
2657 *
2658 */
2659u32 selinux_netlbl_socket_getpeersec_stream(struct socket *sock)
2660{
2661 struct sk_security_struct *sksec = sock->sk->sk_security;
2662 return sksec->peer_sid;
2663}
2664
2665/**
2666 * selinux_netlbl_socket_getpeersec_dgram - Return the SID of a NetLabel packet
2667 * @skb: the packet
2668 *
2669 * Description:
2670 * Examine @skb to find the SID assigned to it by NetLabel. Returns the SID on
2671 * success, SECSID_NULL on error.
2672 *
2673 */
2674u32 selinux_netlbl_socket_getpeersec_dgram(struct sk_buff *skb)
2675{
2676 int peer_sid;
2677
2678 if (selinux_netlbl_skbuff_getsid(skb,
2679 SECINITSID_UNLABELED,
2680 &peer_sid) != 0)
2681 return SECSID_NULL;
2682
2683 return peer_sid;
2684}
2685
2686/**
2687 * selinux_netlbl_socket_setsockopt - Do not allow users to remove a NetLabel 2724 * selinux_netlbl_socket_setsockopt - Do not allow users to remove a NetLabel
2688 * @sock: the socket 2725 * @sock: the socket
2689 * @level: the socket level or protocol 2726 * @level: the socket level or protocol
@@ -2701,21 +2738,19 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock,
2701 int optname) 2738 int optname)
2702{ 2739{
2703 int rc = 0; 2740 int rc = 0;
2704 struct inode *inode = SOCK_INODE(sock);
2705 struct sk_security_struct *sksec = sock->sk->sk_security; 2741 struct sk_security_struct *sksec = sock->sk->sk_security;
2706 struct inode_security_struct *isec = inode->i_security;
2707 struct netlbl_lsm_secattr secattr; 2742 struct netlbl_lsm_secattr secattr;
2708 2743
2709 mutex_lock(&isec->lock); 2744 rcu_read_lock();
2710 if (level == IPPROTO_IP && optname == IP_OPTIONS && 2745 if (level == IPPROTO_IP && optname == IP_OPTIONS &&
2711 sksec->nlbl_state == NLBL_LABELED) { 2746 sksec->nlbl_state == NLBL_LABELED) {
2712 netlbl_secattr_init(&secattr); 2747 netlbl_secattr_init(&secattr);
2713 rc = netlbl_socket_getattr(sock, &secattr); 2748 rc = netlbl_socket_getattr(sock, &secattr);
2714 if (rc == 0 && (secattr.cache || secattr.mls_lvl_vld)) 2749 if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE)
2715 rc = -EACCES; 2750 rc = -EACCES;
2716 netlbl_secattr_destroy(&secattr); 2751 netlbl_secattr_destroy(&secattr);
2717 } 2752 }
2718 mutex_unlock(&isec->lock); 2753 rcu_read_unlock();
2719 2754
2720 return rc; 2755 return rc;
2721} 2756}
diff --git a/security/selinux/ss/symtab.c b/security/selinux/ss/symtab.c
index 24a10d36d3b6..837658a98a54 100644
--- a/security/selinux/ss/symtab.c
+++ b/security/selinux/ss/symtab.c
@@ -9,9 +9,9 @@
9#include <linux/errno.h> 9#include <linux/errno.h>
10#include "symtab.h" 10#include "symtab.h"
11 11
12static unsigned int symhash(struct hashtab *h, void *key) 12static unsigned int symhash(struct hashtab *h, const void *key)
13{ 13{
14 char *p, *keyp; 14 const char *p, *keyp;
15 unsigned int size; 15 unsigned int size;
16 unsigned int val; 16 unsigned int val;
17 17
@@ -23,9 +23,9 @@ static unsigned int symhash(struct hashtab *h, void *key)
23 return val & (h->size - 1); 23 return val & (h->size - 1);
24} 24}
25 25
26static int symcmp(struct hashtab *h, void *key1, void *key2) 26static int symcmp(struct hashtab *h, const void *key1, const void *key2)
27{ 27{
28 char *keyp1, *keyp2; 28 const char *keyp1, *keyp2;
29 29
30 keyp1 = key1; 30 keyp1 = key1;
31 keyp2 = key2; 31 keyp2 = key2;
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c
index 675b995a67c3..bd8d1ef40a90 100644
--- a/security/selinux/xfrm.c
+++ b/security/selinux/xfrm.c
@@ -115,76 +115,46 @@ int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, struct xfrm_policy *
115 struct flowi *fl) 115 struct flowi *fl)
116{ 116{
117 u32 state_sid; 117 u32 state_sid;
118 u32 pol_sid; 118 int rc;
119 int err;
120 119
121 if (xp->security) { 120 if (!xp->security)
122 if (!x->security)
123 /* unlabeled SA and labeled policy can't match */
124 return 0;
125 else
126 state_sid = x->security->ctx_sid;
127 pol_sid = xp->security->ctx_sid;
128 } else
129 if (x->security) 121 if (x->security)
130 /* unlabeled policy and labeled SA can't match */ 122 /* unlabeled policy and labeled SA can't match */
131 return 0; 123 return 0;
132 else 124 else
133 /* unlabeled policy and unlabeled SA match all flows */ 125 /* unlabeled policy and unlabeled SA match all flows */
134 return 1; 126 return 1;
135
136 err = avc_has_perm(state_sid, pol_sid, SECCLASS_ASSOCIATION,
137 ASSOCIATION__POLMATCH,
138 NULL);
139
140 if (err)
141 return 0;
142
143 err = avc_has_perm(fl->secid, state_sid, SECCLASS_ASSOCIATION,
144 ASSOCIATION__SENDTO,
145 NULL)? 0:1;
146
147 return err;
148}
149
150/*
151 * LSM hook implementation that authorizes that a particular outgoing flow
152 * can use a given security association.
153 */
154
155int selinux_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm,
156 struct xfrm_policy *xp)
157{
158 int rc = 0;
159 u32 sel_sid = SECINITSID_UNLABELED;
160 struct xfrm_sec_ctx *ctx;
161
162 if (!xp->security)
163 if (!xfrm->security)
164 return 1;
165 else
166 return 0;
167 else 127 else
168 if (!xfrm->security) 128 if (!x->security)
129 /* unlabeled SA and labeled policy can't match */
169 return 0; 130 return 0;
131 else
132 if (!selinux_authorizable_xfrm(x))
133 /* Not a SELinux-labeled SA */
134 return 0;
170 135
171 /* Context sid is either set to label or ANY_ASSOC */ 136 state_sid = x->security->ctx_sid;
172 if ((ctx = xfrm->security)) {
173 if (!selinux_authorizable_ctx(ctx))
174 return 0;
175 137
176 sel_sid = ctx->ctx_sid; 138 if (fl->secid != state_sid)
177 } 139 return 0;
178 140
179 rc = avc_has_perm(fl->secid, sel_sid, SECCLASS_ASSOCIATION, 141 rc = avc_has_perm(fl->secid, state_sid, SECCLASS_ASSOCIATION,
180 ASSOCIATION__SENDTO, 142 ASSOCIATION__SENDTO,
181 NULL)? 0:1; 143 NULL)? 0:1;
182 144
145 /*
146 * We don't need a separate SA Vs. policy polmatch check
147 * since the SA is now of the same label as the flow and
148 * a flow Vs. policy polmatch check had already happened
149 * in selinux_xfrm_policy_lookup() above.
150 */
151
183 return rc; 152 return rc;
184} 153}
185 154
186/* 155/*
187 * LSM hook implementation that determines the sid for the session. 156 * LSM hook implementation that checks and/or returns the xfrm sid for the
157 * incoming packet.
188 */ 158 */
189 159
190int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall) 160int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall)
@@ -226,16 +196,15 @@ int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall)
226 * CTX does not have a meaningful value on input 196 * CTX does not have a meaningful value on input
227 */ 197 */
228static int selinux_xfrm_sec_ctx_alloc(struct xfrm_sec_ctx **ctxp, 198static int selinux_xfrm_sec_ctx_alloc(struct xfrm_sec_ctx **ctxp,
229 struct xfrm_user_sec_ctx *uctx, struct xfrm_sec_ctx *pol, u32 sid) 199 struct xfrm_user_sec_ctx *uctx, u32 sid)
230{ 200{
231 int rc = 0; 201 int rc = 0;
232 struct task_security_struct *tsec = current->security; 202 struct task_security_struct *tsec = current->security;
233 struct xfrm_sec_ctx *ctx = NULL; 203 struct xfrm_sec_ctx *ctx = NULL;
234 char *ctx_str = NULL; 204 char *ctx_str = NULL;
235 u32 str_len; 205 u32 str_len;
236 u32 ctx_sid;
237 206
238 BUG_ON(uctx && pol); 207 BUG_ON(uctx && sid);
239 208
240 if (!uctx) 209 if (!uctx)
241 goto not_from_user; 210 goto not_from_user;
@@ -279,15 +248,7 @@ static int selinux_xfrm_sec_ctx_alloc(struct xfrm_sec_ctx **ctxp,
279 return rc; 248 return rc;
280 249
281not_from_user: 250not_from_user:
282 if (pol) { 251 rc = security_sid_to_context(sid, &ctx_str, &str_len);
283 rc = security_sid_mls_copy(pol->ctx_sid, sid, &ctx_sid);
284 if (rc)
285 goto out;
286 }
287 else
288 ctx_sid = sid;
289
290 rc = security_sid_to_context(ctx_sid, &ctx_str, &str_len);
291 if (rc) 252 if (rc)
292 goto out; 253 goto out;
293 254
@@ -302,7 +263,7 @@ not_from_user:
302 263
303 ctx->ctx_doi = XFRM_SC_DOI_LSM; 264 ctx->ctx_doi = XFRM_SC_DOI_LSM;
304 ctx->ctx_alg = XFRM_SC_ALG_SELINUX; 265 ctx->ctx_alg = XFRM_SC_ALG_SELINUX;
305 ctx->ctx_sid = ctx_sid; 266 ctx->ctx_sid = sid;
306 ctx->ctx_len = str_len; 267 ctx->ctx_len = str_len;
307 memcpy(ctx->ctx_str, 268 memcpy(ctx->ctx_str,
308 ctx_str, 269 ctx_str,
@@ -323,22 +284,14 @@ out2:
323 * xfrm_policy. 284 * xfrm_policy.
324 */ 285 */
325int selinux_xfrm_policy_alloc(struct xfrm_policy *xp, 286int selinux_xfrm_policy_alloc(struct xfrm_policy *xp,
326 struct xfrm_user_sec_ctx *uctx, struct sock *sk) 287 struct xfrm_user_sec_ctx *uctx)
327{ 288{
328 int err; 289 int err;
329 u32 sid;
330 290
331 BUG_ON(!xp); 291 BUG_ON(!xp);
332 BUG_ON(uctx && sk); 292 BUG_ON(!uctx);
333
334 if (sk) {
335 struct sk_security_struct *ssec = sk->sk_security;
336 sid = ssec->sid;
337 }
338 else
339 sid = SECSID_NULL;
340 293
341 err = selinux_xfrm_sec_ctx_alloc(&xp->security, uctx, NULL, sid); 294 err = selinux_xfrm_sec_ctx_alloc(&xp->security, uctx, 0);
342 return err; 295 return err;
343} 296}
344 297
@@ -399,13 +352,13 @@ int selinux_xfrm_policy_delete(struct xfrm_policy *xp)
399 * xfrm_state. 352 * xfrm_state.
400 */ 353 */
401int selinux_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *uctx, 354int selinux_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *uctx,
402 struct xfrm_sec_ctx *pol, u32 secid) 355 u32 secid)
403{ 356{
404 int err; 357 int err;
405 358
406 BUG_ON(!x); 359 BUG_ON(!x);
407 360
408 err = selinux_xfrm_sec_ctx_alloc(&x->security, uctx, pol, secid); 361 err = selinux_xfrm_sec_ctx_alloc(&x->security, uctx, secid);
409 return err; 362 return err;
410} 363}
411 364
@@ -419,74 +372,6 @@ void selinux_xfrm_state_free(struct xfrm_state *x)
419 kfree(ctx); 372 kfree(ctx);
420} 373}
421 374
422/*
423 * SELinux internal function to retrieve the context of a connected
424 * (sk->sk_state == TCP_ESTABLISHED) TCP socket based on its security
425 * association used to connect to the remote socket.
426 *
427 * Retrieve via getsockopt SO_PEERSEC.
428 */
429u32 selinux_socket_getpeer_stream(struct sock *sk)
430{
431 struct dst_entry *dst, *dst_test;
432 u32 peer_sid = SECSID_NULL;
433
434 if (sk->sk_state != TCP_ESTABLISHED)
435 goto out;
436
437 dst = sk_dst_get(sk);
438 if (!dst)
439 goto out;
440
441 for (dst_test = dst; dst_test != 0;
442 dst_test = dst_test->child) {
443 struct xfrm_state *x = dst_test->xfrm;
444
445 if (x && selinux_authorizable_xfrm(x)) {
446 struct xfrm_sec_ctx *ctx = x->security;
447 peer_sid = ctx->ctx_sid;
448 break;
449 }
450 }
451 dst_release(dst);
452
453out:
454 return peer_sid;
455}
456
457/*
458 * SELinux internal function to retrieve the context of a UDP packet
459 * based on its security association used to connect to the remote socket.
460 *
461 * Retrieve via setsockopt IP_PASSSEC and recvmsg with control message
462 * type SCM_SECURITY.
463 */
464u32 selinux_socket_getpeer_dgram(struct sk_buff *skb)
465{
466 struct sec_path *sp;
467
468 if (skb == NULL)
469 return SECSID_NULL;
470
471 if (skb->sk->sk_protocol != IPPROTO_UDP)
472 return SECSID_NULL;
473
474 sp = skb->sp;
475 if (sp) {
476 int i;
477
478 for (i = sp->len-1; i >= 0; i--) {
479 struct xfrm_state *x = sp->xvec[i];
480 if (selinux_authorizable_xfrm(x)) {
481 struct xfrm_sec_ctx *ctx = x->security;
482 return ctx->ctx_sid;
483 }
484 }
485 }
486
487 return SECSID_NULL;
488}
489
490 /* 375 /*
491 * LSM hook implementation that authorizes deletion of labeled SAs. 376 * LSM hook implementation that authorizes deletion of labeled SAs.
492 */ 377 */
@@ -532,6 +417,13 @@ int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb,
532 } 417 }
533 } 418 }
534 419
420 /*
421 * This check even when there's no association involved is
422 * intended, according to Trent Jaeger, to make sure a
423 * process can't engage in non-ipsec communication unless
424 * explicitly allowed by policy.
425 */
426
535 rc = avc_has_perm(isec_sid, sel_sid, SECCLASS_ASSOCIATION, 427 rc = avc_has_perm(isec_sid, sel_sid, SECCLASS_ASSOCIATION,
536 ASSOCIATION__RECVFROM, ad); 428 ASSOCIATION__RECVFROM, ad);
537 429
@@ -543,10 +435,10 @@ int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb,
543 * If we have no security association, then we need to determine 435 * If we have no security association, then we need to determine
544 * whether the socket is allowed to send to an unlabelled destination. 436 * whether the socket is allowed to send to an unlabelled destination.
545 * If we do have a authorizable security association, then it has already been 437 * If we do have a authorizable security association, then it has already been
546 * checked in xfrm_policy_lookup hook. 438 * checked in the selinux_xfrm_state_pol_flow_match hook above.
547 */ 439 */
548int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, 440int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb,
549 struct avc_audit_data *ad) 441 struct avc_audit_data *ad, u8 proto)
550{ 442{
551 struct dst_entry *dst; 443 struct dst_entry *dst;
552 int rc = 0; 444 int rc = 0;
@@ -565,6 +457,27 @@ int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb,
565 } 457 }
566 } 458 }
567 459
460 switch (proto) {
461 case IPPROTO_AH:
462 case IPPROTO_ESP:
463 case IPPROTO_COMP:
464 /*
465 * We should have already seen this packet once before
466 * it underwent xfrm(s). No need to subject it to the
467 * unlabeled check.
468 */
469 goto out;
470 default:
471 break;
472 }
473
474 /*
475 * This check even when there's no association involved is
476 * intended, according to Trent Jaeger, to make sure a
477 * process can't engage in non-ipsec communication unless
478 * explicitly allowed by policy.
479 */
480
568 rc = avc_has_perm(isec_sid, SECINITSID_UNLABELED, SECCLASS_ASSOCIATION, 481 rc = avc_has_perm(isec_sid, SECINITSID_UNLABELED, SECCLASS_ASSOCIATION,
569 ASSOCIATION__SENDTO, ad); 482 ASSOCIATION__SENDTO, ad);
570out: 483out: