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.c163
-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.h53
-rw-r--r--security/selinux/include/xfrm.h28
-rw-r--r--security/selinux/nlmsgtab.c1
-rw-r--r--security/selinux/ss/ebitmap.c200
-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.c143
-rw-r--r--security/selinux/ss/mls.h46
-rw-r--r--security/selinux/ss/policydb.c6
-rw-r--r--security/selinux/ss/services.c448
-rw-r--r--security/selinux/ss/symtab.c8
-rw-r--r--security/selinux/xfrm.c207
24 files changed, 774 insertions, 686 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 e9969a2fc846..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 }
@@ -3313,7 +3358,13 @@ static int selinux_socket_getpeername(struct socket *sock)
3313 3358
3314static int selinux_socket_setsockopt(struct socket *sock,int level,int optname) 3359static int selinux_socket_setsockopt(struct socket *sock,int level,int optname)
3315{ 3360{
3316 return socket_has_perm(current, sock, SOCKET__SETOPT); 3361 int err;
3362
3363 err = socket_has_perm(current, sock, SOCKET__SETOPT);
3364 if (err)
3365 return err;
3366
3367 return selinux_netlbl_socket_setsockopt(sock, level, optname);
3317} 3368}
3318 3369
3319static int selinux_socket_getsockopt(struct socket *sock, int level, 3370static int selinux_socket_getsockopt(struct socket *sock, int level,
@@ -3431,7 +3482,13 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
3431 node_perm = NODE__TCP_RECV; 3482 node_perm = NODE__TCP_RECV;
3432 recv_perm = TCP_SOCKET__RECV_MSG; 3483 recv_perm = TCP_SOCKET__RECV_MSG;
3433 break; 3484 break;
3434 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
3435 default: 3492 default:
3436 netif_perm = NETIF__RAWIP_RECV; 3493 netif_perm = NETIF__RAWIP_RECV;
3437 node_perm = NODE__RAWIP_RECV; 3494 node_perm = NODE__RAWIP_RECV;
@@ -3487,7 +3544,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
3487 ad.u.net.netif = skb->dev ? skb->dev->name : "[unknown]"; 3544 ad.u.net.netif = skb->dev ? skb->dev->name : "[unknown]";
3488 ad.u.net.family = family; 3545 ad.u.net.family = family;
3489 3546
3490 err = selinux_parse_skb(skb, &ad, &addrp, &len, 1); 3547 err = selinux_parse_skb(skb, &ad, &addrp, &len, 1, NULL);
3491 if (err) 3548 if (err)
3492 goto out; 3549 goto out;
3493 3550
@@ -3517,25 +3574,16 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *op
3517 u32 scontext_len; 3574 u32 scontext_len;
3518 struct sk_security_struct *ssec; 3575 struct sk_security_struct *ssec;
3519 struct inode_security_struct *isec; 3576 struct inode_security_struct *isec;
3520 u32 peer_sid = 0; 3577 u32 peer_sid = SECSID_NULL;
3521 3578
3522 isec = SOCK_INODE(sock)->i_security; 3579 isec = SOCK_INODE(sock)->i_security;
3523 3580
3524 /* if UNIX_STREAM check peer_sid, if TCP check dst for labelled sa */ 3581 if (isec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
3525 if (isec->sclass == SECCLASS_UNIX_STREAM_SOCKET) { 3582 isec->sclass == SECCLASS_TCP_SOCKET) {
3526 ssec = sock->sk->sk_security; 3583 ssec = sock->sk->sk_security;
3527 peer_sid = ssec->peer_sid; 3584 peer_sid = ssec->peer_sid;
3528 } 3585 }
3529 else if (isec->sclass == SECCLASS_TCP_SOCKET) { 3586 if (peer_sid == SECSID_NULL) {
3530 peer_sid = selinux_netlbl_socket_getpeersec_stream(sock);
3531 if (peer_sid == SECSID_NULL)
3532 peer_sid = selinux_socket_getpeer_stream(sock->sk);
3533 if (peer_sid == SECSID_NULL) {
3534 err = -ENOPROTOOPT;
3535 goto out;
3536 }
3537 }
3538 else {
3539 err = -ENOPROTOOPT; 3587 err = -ENOPROTOOPT;
3540 goto out; 3588 goto out;
3541 } 3589 }
@@ -3567,13 +3615,12 @@ static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *
3567 u32 peer_secid = SECSID_NULL; 3615 u32 peer_secid = SECSID_NULL;
3568 int err = 0; 3616 int err = 0;
3569 3617
3570 if (sock && (sock->sk->sk_family == PF_UNIX)) 3618 if (sock && sock->sk->sk_family == PF_UNIX)
3571 selinux_get_inode_sid(SOCK_INODE(sock), &peer_secid); 3619 selinux_get_inode_sid(SOCK_INODE(sock), &peer_secid);
3572 else if (skb) { 3620 else if (skb)
3573 peer_secid = selinux_netlbl_socket_getpeersec_dgram(skb); 3621 security_skb_extlbl_sid(skb,
3574 if (peer_secid == SECSID_NULL) 3622 SECINITSID_UNLABELED,
3575 peer_secid = selinux_socket_getpeer_dgram(skb); 3623 &peer_secid);
3576 }
3577 3624
3578 if (peer_secid == SECSID_NULL) 3625 if (peer_secid == SECSID_NULL)
3579 err = -EINVAL; 3626 err = -EINVAL;
@@ -3600,7 +3647,7 @@ static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
3600 newssec->sid = ssec->sid; 3647 newssec->sid = ssec->sid;
3601 newssec->peer_sid = ssec->peer_sid; 3648 newssec->peer_sid = ssec->peer_sid;
3602 3649
3603 selinux_netlbl_sk_clone_security(ssec, newssec); 3650 selinux_netlbl_sk_security_clone(ssec, newssec);
3604} 3651}
3605 3652
3606static void selinux_sk_getsecid(struct sock *sk, u32 *secid) 3653static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
@@ -3634,17 +3681,10 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
3634 u32 newsid; 3681 u32 newsid;
3635 u32 peersid; 3682 u32 peersid;
3636 3683
3637 newsid = selinux_netlbl_inet_conn_request(skb, sksec->sid); 3684 security_skb_extlbl_sid(skb, SECINITSID_UNLABELED, &peersid);
3638 if (newsid != SECSID_NULL) {
3639 req->secid = newsid;
3640 return 0;
3641 }
3642
3643 err = selinux_xfrm_decode_session(skb, &peersid, 0);
3644 BUG_ON(err);
3645
3646 if (peersid == SECSID_NULL) { 3685 if (peersid == SECSID_NULL) {
3647 req->secid = sksec->sid; 3686 req->secid = sksec->sid;
3687 req->peer_secid = SECSID_NULL;
3648 return 0; 3688 return 0;
3649 } 3689 }
3650 3690
@@ -3653,6 +3693,7 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
3653 return err; 3693 return err;
3654 3694
3655 req->secid = newsid; 3695 req->secid = newsid;
3696 req->peer_secid = peersid;
3656 return 0; 3697 return 0;
3657} 3698}
3658 3699
@@ -3662,12 +3703,23 @@ static void selinux_inet_csk_clone(struct sock *newsk,
3662 struct sk_security_struct *newsksec = newsk->sk_security; 3703 struct sk_security_struct *newsksec = newsk->sk_security;
3663 3704
3664 newsksec->sid = req->secid; 3705 newsksec->sid = req->secid;
3706 newsksec->peer_sid = req->peer_secid;
3665 /* NOTE: Ideally, we should also get the isec->sid for the 3707 /* NOTE: Ideally, we should also get the isec->sid for the
3666 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.
3667 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
3668 time it will have been created and available. */ 3710 time it will have been created and available. */
3669 3711
3670 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);
3671} 3723}
3672 3724
3673static void selinux_req_classify_flow(const struct request_sock *req, 3725static void selinux_req_classify_flow(const struct request_sock *req,
@@ -3750,7 +3802,13 @@ static int selinux_ip_postroute_last_compat(struct sock *sk, struct net_device *
3750 node_perm = NODE__TCP_SEND; 3802 node_perm = NODE__TCP_SEND;
3751 send_perm = TCP_SOCKET__SEND_MSG; 3803 send_perm = TCP_SOCKET__SEND_MSG;
3752 break; 3804 break;
3753 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
3754 default: 3812 default:
3755 netif_perm = NETIF__RAWIP_SEND; 3813 netif_perm = NETIF__RAWIP_SEND;
3756 node_perm = NODE__RAWIP_SEND; 3814 node_perm = NODE__RAWIP_SEND;
@@ -3801,6 +3859,7 @@ static unsigned int selinux_ip_postroute_last(unsigned int hooknum,
3801 struct avc_audit_data ad; 3859 struct avc_audit_data ad;
3802 struct net_device *dev = (struct net_device *)out; 3860 struct net_device *dev = (struct net_device *)out;
3803 struct sk_security_struct *sksec; 3861 struct sk_security_struct *sksec;
3862 u8 proto;
3804 3863
3805 sk = skb->sk; 3864 sk = skb->sk;
3806 if (!sk) 3865 if (!sk)
@@ -3812,7 +3871,7 @@ static unsigned int selinux_ip_postroute_last(unsigned int hooknum,
3812 ad.u.net.netif = dev->name; 3871 ad.u.net.netif = dev->name;
3813 ad.u.net.family = family; 3872 ad.u.net.family = family;
3814 3873
3815 err = selinux_parse_skb(skb, &ad, &addrp, &len, 0); 3874 err = selinux_parse_skb(skb, &ad, &addrp, &len, 0, &proto);
3816 if (err) 3875 if (err)
3817 goto out; 3876 goto out;
3818 3877
@@ -3826,7 +3885,7 @@ static unsigned int selinux_ip_postroute_last(unsigned int hooknum,
3826 if (err) 3885 if (err)
3827 goto out; 3886 goto out;
3828 3887
3829 err = selinux_xfrm_postroute_last(sksec->sid, skb, &ad); 3888 err = selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto);
3830out: 3889out:
3831 return err ? NF_DROP : NF_ACCEPT; 3890 return err ? NF_DROP : NF_ACCEPT;
3832} 3891}
@@ -4732,6 +4791,7 @@ static struct security_operations selinux_ops = {
4732 .sock_graft = selinux_sock_graft, 4791 .sock_graft = selinux_sock_graft,
4733 .inet_conn_request = selinux_inet_conn_request, 4792 .inet_conn_request = selinux_inet_conn_request,
4734 .inet_csk_clone = selinux_inet_csk_clone, 4793 .inet_csk_clone = selinux_inet_csk_clone,
4794 .inet_conn_established = selinux_inet_conn_established,
4735 .req_classify_flow = selinux_req_classify_flow, 4795 .req_classify_flow = selinux_req_classify_flow,
4736 4796
4737#ifdef CONFIG_SECURITY_NETWORK_XFRM 4797#ifdef CONFIG_SECURITY_NETWORK_XFRM
@@ -4744,7 +4804,6 @@ static struct security_operations selinux_ops = {
4744 .xfrm_state_delete_security = selinux_xfrm_state_delete, 4804 .xfrm_state_delete_security = selinux_xfrm_state_delete,
4745 .xfrm_policy_lookup = selinux_xfrm_policy_lookup, 4805 .xfrm_policy_lookup = selinux_xfrm_policy_lookup,
4746 .xfrm_state_pol_flow_match = selinux_xfrm_state_pol_flow_match, 4806 .xfrm_state_pol_flow_match = selinux_xfrm_state_pol_flow_match,
4747 .xfrm_flow_state_match = selinux_xfrm_flow_state_match,
4748 .xfrm_decode_session = selinux_xfrm_decode_session, 4807 .xfrm_decode_session = selinux_xfrm_decode_session,
4749#endif 4808#endif
4750 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 ecab4bddaaf4..2a732c9033e3 100644
--- a/security/selinux/include/selinux_netlabel.h
+++ b/security/selinux/include/selinux_netlabel.h
@@ -38,44 +38,45 @@
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);
54int selinux_netlbl_socket_setsockopt(struct socket *sock,
55 int level,
56 int optname);
56#else 57#else
57static inline void selinux_netlbl_cache_invalidate(void) 58static inline void selinux_netlbl_cache_invalidate(void)
58{ 59{
59 return; 60 return;
60} 61}
61 62
62static inline int selinux_netlbl_socket_post_create(struct socket *sock, 63static inline int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
63 int sock_family, 64 u32 base_sid,
64 u32 sid) 65 u32 *sid)
65{ 66{
67 *sid = SECSID_NULL;
66 return 0; 68 return 0;
67} 69}
68 70
69static inline void selinux_netlbl_sock_graft(struct sock *sk, 71static inline int selinux_netlbl_socket_post_create(struct socket *sock)
70 struct socket *sock)
71{ 72{
72 return; 73 return 0;
73} 74}
74 75
75static inline u32 selinux_netlbl_inet_conn_request(struct sk_buff *skb, 76static inline void selinux_netlbl_sock_graft(struct sock *sk,
76 u32 sock_sid) 77 struct socket *sock)
77{ 78{
78 return SECSID_NULL; 79 return;
79} 80}
80 81
81static 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,
@@ -85,14 +86,11 @@ static inline int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
85 return 0; 86 return 0;
86} 87}
87 88
88static inline u32 selinux_netlbl_socket_getpeersec_stream(struct socket *sock) 89static inline void selinux_netlbl_sk_security_reset(
89{ 90 struct sk_security_struct *ssec,
90 return SECSID_NULL; 91 int family)
91}
92
93static inline u32 selinux_netlbl_socket_getpeersec_dgram(struct sk_buff *skb)
94{ 92{
95 return SECSID_NULL; 93 return;
96} 94}
97 95
98static inline void selinux_netlbl_sk_security_init( 96static inline void selinux_netlbl_sk_security_init(
@@ -102,7 +100,7 @@ static inline void selinux_netlbl_sk_security_init(
102 return; 100 return;
103} 101}
104 102
105static inline void selinux_netlbl_sk_clone_security( 103static inline void selinux_netlbl_sk_security_clone(
106 struct sk_security_struct *ssec, 104 struct sk_security_struct *ssec,
107 struct sk_security_struct *newssec) 105 struct sk_security_struct *newssec)
108{ 106{
@@ -114,6 +112,13 @@ static inline int selinux_netlbl_inode_permission(struct inode *inode,
114{ 112{
115 return 0; 113 return 0;
116} 114}
115
116static inline int selinux_netlbl_socket_setsockopt(struct socket *sock,
117 int level,
118 int optname)
119{
120 return 0;
121}
117#endif /* CONFIG_NETLABEL */ 122#endif /* CONFIG_NETLABEL */
118 123
119#endif 124#endif
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 cfed1d30fa6a..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,137 +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 bitmap_len = src->highbit / 8; 92 * as well. It's not ideal but I think the tradeoff in terms of
97 if (src->highbit % 7) 93 * neatness and speed is worth it. */
98 bitmap_len += 1; 94
99 if (bitmap_len == 0) 95 if (e_iter == NULL) {
100 return -EINVAL; 96 *catmap = NULL;
101 97 return 0;
102 bitmap = kzalloc((bitmap_len & ~(sizeof(MAPTYPE) - 1)) + 98 }
103 sizeof(MAPTYPE), 99
104 GFP_ATOMIC); 100 c_iter = netlbl_secattr_catmap_alloc(GFP_ATOMIC);
105 if (bitmap == NULL) 101 if (c_iter == NULL)
106 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 }
107 121
108 iter_node = src->node;
109 do {
110 bitmap_byte = iter_node->startbit / 8;
111 bitmask = 0x80;
112 node_val = iter_node->map;
113 do {
114 if (bitmask == 0) {
115 bitmap_byte++;
116 bitmask = 0x80;
117 }
118 if (node_val & (MAPTYPE)0x01)
119 bitmap[bitmap_byte] |= bitmask;
120 node_val >>= 1;
121 bitmask >>= 1;
122 } while (node_val > 0);
123 iter_node = iter_node->next;
124 } while (iter_node);
125
126 *dst = bitmap;
127 *dst_len = bitmap_len;
128 return 0; 122 return 0;
123
124netlbl_export_failure:
125 netlbl_secattr_catmap_free(*catmap);
126 return -ENOMEM;
129} 127}
130 128
131/** 129/**
132 * ebitmap_import - Import an unsigned char bitmap string into an ebitmap 130 * ebitmap_netlbl_import - Import a NetLabel category bitmap into an ebitmap
133 * @src: the bitmap string 131 * @ebmap: the ebitmap to export
134 * @src_len: the bitmap length in bytes 132 * @catmap: the NetLabel category bitmap
135 * @dst: the empty ebitmap
136 * 133 *
137 * Description: 134 * Description:
138 * 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.
139 * the ebitmap pointed to by dst. Returns zero on success, negative values on 136 * Returns zero on success, negative values on error.
140 * failure.
141 * 137 *
142 */ 138 */
143int ebitmap_import(const unsigned char *src, 139int ebitmap_netlbl_import(struct ebitmap *ebmap,
144 size_t src_len, 140 struct netlbl_lsm_secattr_catmap *catmap)
145 struct ebitmap *dst)
146{ 141{
147 size_t src_off = 0; 142 struct ebitmap_node *e_iter = NULL;
148 size_t node_limit; 143 struct ebitmap_node *emap_prev = NULL;
149 struct ebitmap_node *node_new; 144 struct netlbl_lsm_secattr_catmap *c_iter = catmap;
150 struct ebitmap_node *node_last = NULL; 145 u32 c_idx;
151 u32 i_byte;
152 u32 i_bit;
153 unsigned char src_byte;
154
155 while (src_off < src_len) {
156 if (src_len - src_off >= sizeof(MAPTYPE)) {
157 if (*(MAPTYPE *)&src[src_off] == 0) {
158 src_off += sizeof(MAPTYPE);
159 continue;
160 }
161 node_limit = sizeof(MAPTYPE);
162 } else {
163 for (src_byte = 0, i_byte = src_off;
164 i_byte < src_len && src_byte == 0;
165 i_byte++)
166 src_byte |= src[i_byte];
167 if (src_byte == 0)
168 break;
169 node_limit = src_len - src_off;
170 }
171 146
172 node_new = kzalloc(sizeof(*node_new), GFP_ATOMIC); 147 /* This function is a much simpler because SELinux's MAPTYPE happens
173 if (unlikely(node_new == NULL)) { 148 * to be the same as NetLabel's NETLBL_CATMAP_MAPTYPE, if MAPTYPE is
174 ebitmap_destroy(dst); 149 * changed from a u64 this function will most likely need to be changed
175 return -ENOMEM; 150 * as well. It's not ideal but I think the tradeoff in terms of
176 } 151 * neatness and speed is worth it. */
177 node_new->startbit = src_off * 8;
178 for (i_byte = 0; i_byte < node_limit; i_byte++) {
179 src_byte = src[src_off++];
180 for (i_bit = i_byte * 8; src_byte != 0; i_bit++) {
181 if (src_byte & 0x80)
182 node_new->map |= MAPBIT << i_bit;
183 src_byte <<= 1;
184 }
185 }
186 152
187 if (node_last != NULL) 153 do {
188 node_last->next = node_new; 154 for (c_idx = 0; c_idx < NETLBL_CATMAP_MAPCNT; c_idx++) {
189 else 155 if (c_iter->bitmap[c_idx] == 0)
190 dst->node = node_new; 156 continue;
191 node_last = node_new; 157
192 } 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;
193 166
194 if (likely(node_last != NULL)) 167 e_iter->startbit = c_iter->startbit +
195 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;
196 else 175 else
197 ebitmap_init(dst); 176 ebitmap_destroy(ebmap);
198 177
199 return 0; 178 return 0;
179
180netlbl_import_failure:
181 ebitmap_destroy(ebmap);
182 return -ENOMEM;
200} 183}
184#endif /* CONFIG_NETLABEL */
201 185
202int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2) 186int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2)
203{ 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 c713af23250a..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,152 +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 return 0; 632 return 0;
645 633
646 if (low != NULL) { 634 rc = ebitmap_netlbl_export(&context->range.level[0].cat,
647 rc = ebitmap_export(&context->range.level[0].cat, 635 &secattr->mls_cat);
648 low, 636 if (rc == 0 && secattr->mls_cat != NULL)
649 low_len); 637 secattr->flags |= NETLBL_SECATTR_MLS_CAT;
650 if (rc != 0)
651 goto export_cat_failure;
652 }
653 if (high != NULL) {
654 rc = ebitmap_export(&context->range.level[1].cat,
655 high,
656 high_len);
657 if (rc != 0)
658 goto export_cat_failure;
659 }
660
661 return 0;
662 638
663export_cat_failure:
664 if (low != NULL)
665 kfree(*low);
666 if (high != NULL)
667 kfree(*high);
668 return rc; 639 return rc;
669} 640}
670 641
671/** 642/**
672 * mls_import_cat - Import the MLS categories 643 * mls_import_netlbl_cat - Import the MLS categories from NetLabel
673 * @context: the security context 644 * @context: the security context
674 * @low: the low category 645 * @secattr: the NetLabel security attributes
675 * @low_len: length of the cat_low bitmap in bytes
676 * @high: the high category
677 * @high_len: length of the cat_high bitmap in bytes
678 * 646 *
679 * Description: 647 * Description:
680 * Given the security context and the two category bitmap strings import the 648 * Copy the NetLabel security attributes into the SELinux context; since the
681 * categories into the security context. The MLS categories are only imported 649 * NetLabel security attribute only contains a single MLS category use it for
682 * 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,
683 * zero on success, negative values on failure. 651 * negative values on failure.
684 * 652 *
685 */ 653 */
686int mls_import_cat(struct context *context, 654int mls_import_netlbl_cat(struct context *context,
687 const unsigned char *low, 655 struct netlbl_lsm_secattr *secattr)
688 size_t low_len,
689 const unsigned char *high,
690 size_t high_len)
691{ 656{
692 int rc = -EPERM; 657 int rc;
693 658
694 if (!selinux_mls_enabled) 659 if (!selinux_mls_enabled)
695 return 0; 660 return 0;
696 661
697 if (low != NULL) { 662 rc = ebitmap_netlbl_import(&context->range.level[0].cat,
698 rc = ebitmap_import(low, 663 secattr->mls_cat);
699 low_len, 664 if (rc != 0)
700 &context->range.level[0].cat); 665 goto import_netlbl_cat_failure;
701 if (rc != 0) 666
702 goto import_cat_failure; 667 rc = ebitmap_cpy(&context->range.level[1].cat,
703 } 668 &context->range.level[0].cat);
704 if (high != NULL) { 669 if (rc != 0)
705 if (high == low) 670 goto import_netlbl_cat_failure;
706 rc = ebitmap_cpy(&context->range.level[1].cat,
707 &context->range.level[0].cat);
708 else
709 rc = ebitmap_import(high,
710 high_len,
711 &context->range.level[1].cat);
712 if (rc != 0)
713 goto import_cat_failure;
714 }
715 671
716 return 0; 672 return 0;
717 673
718import_cat_failure: 674import_netlbl_cat_failure:
719 ebitmap_destroy(&context->range.level[0].cat); 675 ebitmap_destroy(&context->range.level[0].cat);
720 ebitmap_destroy(&context->range.level[1].cat); 676 ebitmap_destroy(&context->range.level[1].cat);
721 return rc; 677 return rc;
722} 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 18274b005090..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)
@@ -2399,35 +2474,55 @@ static int selinux_netlbl_socket_setsid(struct socket *sock, u32 sid)
2399 if (!ss_initialized) 2474 if (!ss_initialized)
2400 return 0; 2475 return 0;
2401 2476
2477 netlbl_secattr_init(&secattr);
2478
2402 POLICY_RDLOCK; 2479 POLICY_RDLOCK;
2403 2480
2404 ctx = sidtab_search(&sidtab, sid); 2481 ctx = sidtab_search(&sidtab, sid);
2405 if (ctx == NULL) 2482 if (ctx == NULL)
2406 goto netlbl_socket_setsid_return; 2483 goto netlbl_socket_setsid_return;
2407 2484
2408 netlbl_secattr_init(&secattr);
2409 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],
2410 GFP_ATOMIC); 2486 GFP_ATOMIC);
2411 mls_export_lvl(ctx, &secattr.mls_lvl, NULL); 2487 secattr.flags |= NETLBL_SECATTR_DOMAIN;
2412 secattr.mls_lvl_vld = 1; 2488 mls_export_netlbl_lvl(ctx, &secattr);
2413 mls_export_cat(ctx, 2489 rc = mls_export_netlbl_cat(ctx, &secattr);
2414 &secattr.mls_cat, 2490 if (rc != 0)
2415 &secattr.mls_cat_len, 2491 goto netlbl_socket_setsid_return;
2416 NULL,
2417 NULL);
2418 2492
2419 rc = netlbl_socket_setattr(sock, &secattr); 2493 rc = netlbl_socket_setattr(sock, &secattr);
2420 if (rc == 0) 2494 if (rc == 0) {
2495 spin_lock(&sksec->nlbl_lock);
2421 sksec->nlbl_state = NLBL_LABELED; 2496 sksec->nlbl_state = NLBL_LABELED;
2422 2497 spin_unlock(&sksec->nlbl_lock);
2423 netlbl_secattr_destroy(&secattr); 2498 }
2424 2499
2425netlbl_socket_setsid_return: 2500netlbl_socket_setsid_return:
2426 POLICY_RDUNLOCK; 2501 POLICY_RDUNLOCK;
2502 netlbl_secattr_destroy(&secattr);
2427 return rc; 2503 return rc;
2428} 2504}
2429 2505
2430/** 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/**
2431 * selinux_netlbl_sk_security_init - Setup the NetLabel fields 2526 * selinux_netlbl_sk_security_init - Setup the NetLabel fields
2432 * @ssec: the sk_security_struct 2527 * @ssec: the sk_security_struct
2433 * @family: the socket family 2528 * @family: the socket family
@@ -2440,14 +2535,13 @@ netlbl_socket_setsid_return:
2440void selinux_netlbl_sk_security_init(struct sk_security_struct *ssec, 2535void selinux_netlbl_sk_security_init(struct sk_security_struct *ssec,
2441 int family) 2536 int family)
2442{ 2537{
2443 if (family == PF_INET) 2538 /* No locking needed, we are the only one who has access to ssec */
2444 ssec->nlbl_state = NLBL_REQUIRE; 2539 selinux_netlbl_sk_security_reset(ssec, family);
2445 else 2540 spin_lock_init(&ssec->nlbl_lock);
2446 ssec->nlbl_state = NLBL_UNSET;
2447} 2541}
2448 2542
2449/** 2543/**
2450 * selinux_netlbl_sk_clone_security - Copy the NetLabel fields 2544 * selinux_netlbl_sk_security_clone - Copy the NetLabel fields
2451 * @ssec: the original sk_security_struct 2545 * @ssec: the original sk_security_struct
2452 * @newssec: the cloned sk_security_struct 2546 * @newssec: the cloned sk_security_struct
2453 * 2547 *
@@ -2456,41 +2550,41 @@ void selinux_netlbl_sk_security_init(struct sk_security_struct *ssec,
2456 * @newssec. 2550 * @newssec.
2457 * 2551 *
2458 */ 2552 */
2459void selinux_netlbl_sk_clone_security(struct sk_security_struct *ssec, 2553void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec,
2460 struct sk_security_struct *newssec) 2554 struct sk_security_struct *newssec)
2461{ 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);
2462 newssec->sclass = ssec->sclass; 2561 newssec->sclass = ssec->sclass;
2463 if (ssec->nlbl_state != NLBL_UNSET) 2562 rcu_read_unlock();
2464 newssec->nlbl_state = NLBL_REQUIRE;
2465 else
2466 newssec->nlbl_state = NLBL_UNSET;
2467} 2563}
2468 2564
2469/** 2565/**
2470 * selinux_netlbl_socket_post_create - Label a socket using NetLabel 2566 * selinux_netlbl_socket_post_create - Label a socket using NetLabel
2471 * @sock: the socket to label 2567 * @sock: the socket to label
2472 * @sock_family: the socket family
2473 * @sid: the SID to use
2474 * 2568 *
2475 * Description: 2569 * Description:
2476 * 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
2477 * SID. Returns zero values on success, negative values on failure. 2571 * SID. Returns zero values on success, negative values on failure.
2478 * 2572 *
2479 */ 2573 */
2480int selinux_netlbl_socket_post_create(struct socket *sock, 2574int selinux_netlbl_socket_post_create(struct socket *sock)
2481 int sock_family,
2482 u32 sid)
2483{ 2575{
2576 int rc = 0;
2484 struct inode_security_struct *isec = SOCK_INODE(sock)->i_security; 2577 struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
2485 struct sk_security_struct *sksec = sock->sk->sk_security; 2578 struct sk_security_struct *sksec = sock->sk->sk_security;
2486 2579
2487 sksec->sclass = isec->sclass; 2580 sksec->sclass = isec->sclass;
2488 2581
2489 if (sock_family != PF_INET) 2582 rcu_read_lock();
2490 return 0; 2583 if (sksec->nlbl_state == NLBL_REQUIRE)
2584 rc = selinux_netlbl_socket_setsid(sock, sksec->sid);
2585 rcu_read_unlock();
2491 2586
2492 sksec->nlbl_state = NLBL_REQUIRE; 2587 return rc;
2493 return selinux_netlbl_socket_setsid(sock, sid);
2494} 2588}
2495 2589
2496/** 2590/**
@@ -2512,11 +2606,16 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock)
2512 2606
2513 sksec->sclass = isec->sclass; 2607 sksec->sclass = isec->sclass;
2514 2608
2515 if (sk->sk_family != PF_INET) 2609 rcu_read_lock();
2610
2611 if (sksec->nlbl_state != NLBL_REQUIRE) {
2612 rcu_read_unlock();
2516 return; 2613 return;
2614 }
2517 2615
2518 netlbl_secattr_init(&secattr); 2616 netlbl_secattr_init(&secattr);
2519 if (netlbl_sock_getattr(sk, &secattr) == 0 && 2617 if (netlbl_sock_getattr(sk, &secattr) == 0 &&
2618 secattr.flags != NETLBL_SECATTR_NONE &&
2520 selinux_netlbl_secattr_to_sid(NULL, 2619 selinux_netlbl_secattr_to_sid(NULL,
2521 &secattr, 2620 &secattr,
2522 SECINITSID_UNLABELED, 2621 SECINITSID_UNLABELED,
@@ -2524,35 +2623,12 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock)
2524 sksec->peer_sid = nlbl_peer_sid; 2623 sksec->peer_sid = nlbl_peer_sid;
2525 netlbl_secattr_destroy(&secattr); 2624 netlbl_secattr_destroy(&secattr);
2526 2625
2527 sksec->nlbl_state = NLBL_REQUIRE;
2528
2529 /* 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
2530 * here we will pick up the pieces in later calls to 2627 * here we will pick up the pieces in later calls to
2531 * selinux_netlbl_inode_permission(). */ 2628 * selinux_netlbl_inode_permission(). */
2532 selinux_netlbl_socket_setsid(sock, sksec->sid); 2629 selinux_netlbl_socket_setsid(sock, sksec->sid);
2533}
2534 2630
2535/** 2631 rcu_read_unlock();
2536 * selinux_netlbl_inet_conn_request - Handle a new connection request
2537 * @skb: the packet
2538 * @sock_sid: the SID of the parent socket
2539 *
2540 * Description:
2541 * If present, use the security attributes of the packet in @skb and the
2542 * parent sock's SID to arrive at a SID for the new child sock. Returns the
2543 * SID of the connection or SECSID_NULL on failure.
2544 *
2545 */
2546u32 selinux_netlbl_inet_conn_request(struct sk_buff *skb, u32 sock_sid)
2547{
2548 int rc;
2549 u32 peer_sid;
2550
2551 rc = selinux_netlbl_skbuff_getsid(skb, sock_sid, &peer_sid);
2552 if (rc != 0)
2553 return SECSID_NULL;
2554
2555 return peer_sid;
2556} 2632}
2557 2633
2558/** 2634/**
@@ -2570,25 +2646,24 @@ u32 selinux_netlbl_inet_conn_request(struct sk_buff *skb, u32 sock_sid)
2570int selinux_netlbl_inode_permission(struct inode *inode, int mask) 2646int selinux_netlbl_inode_permission(struct inode *inode, int mask)
2571{ 2647{
2572 int rc; 2648 int rc;
2573 struct inode_security_struct *isec;
2574 struct sk_security_struct *sksec; 2649 struct sk_security_struct *sksec;
2575 struct socket *sock; 2650 struct socket *sock;
2576 2651
2577 if (!S_ISSOCK(inode->i_mode)) 2652 if (!S_ISSOCK(inode->i_mode) ||
2653 ((mask & (MAY_WRITE | MAY_APPEND)) == 0))
2578 return 0; 2654 return 0;
2579
2580 sock = SOCKET_I(inode); 2655 sock = SOCKET_I(inode);
2581 isec = inode->i_security;
2582 sksec = sock->sk->sk_security; 2656 sksec = sock->sk->sk_security;
2583 mutex_lock(&isec->lock); 2657
2584 if (unlikely(sksec->nlbl_state == NLBL_REQUIRE && 2658 rcu_read_lock();
2585 (mask & (MAY_WRITE | MAY_APPEND)))) { 2659 if (sksec->nlbl_state != NLBL_REQUIRE) {
2586 lock_sock(sock->sk); 2660 rcu_read_unlock();
2587 rc = selinux_netlbl_socket_setsid(sock, sksec->sid); 2661 return 0;
2588 release_sock(sock->sk); 2662 }
2589 } else 2663 lock_sock(sock->sk);
2590 rc = 0; 2664 rc = selinux_netlbl_socket_setsid(sock, sksec->sid);
2591 mutex_unlock(&isec->lock); 2665 release_sock(sock->sk);
2666 rcu_read_unlock();
2592 2667
2593 return rc; 2668 return rc;
2594} 2669}
@@ -2646,38 +2721,37 @@ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
2646} 2721}
2647 2722
2648/** 2723/**
2649 * selinux_netlbl_socket_getpeersec_stream - Return the connected peer's SID 2724 * selinux_netlbl_socket_setsockopt - Do not allow users to remove a NetLabel
2650 * @sock: the socket 2725 * @sock: the socket
2726 * @level: the socket level or protocol
2727 * @optname: the socket option name
2651 * 2728 *
2652 * Description: 2729 * Description:
2653 * Examine @sock to find the connected peer's SID. Returns the SID on success 2730 * Check the setsockopt() call and if the user is trying to replace the IP
2654 * or SECSID_NULL on error. 2731 * options on a socket and a NetLabel is in place for the socket deny the
2732 * access; otherwise allow the access. Returns zero when the access is
2733 * allowed, -EACCES when denied, and other negative values on error.
2655 * 2734 *
2656 */ 2735 */
2657u32 selinux_netlbl_socket_getpeersec_stream(struct socket *sock) 2736int selinux_netlbl_socket_setsockopt(struct socket *sock,
2737 int level,
2738 int optname)
2658{ 2739{
2740 int rc = 0;
2659 struct sk_security_struct *sksec = sock->sk->sk_security; 2741 struct sk_security_struct *sksec = sock->sk->sk_security;
2660 return sksec->peer_sid; 2742 struct netlbl_lsm_secattr secattr;
2661}
2662
2663/**
2664 * selinux_netlbl_socket_getpeersec_dgram - Return the SID of a NetLabel packet
2665 * @skb: the packet
2666 *
2667 * Description:
2668 * Examine @skb to find the SID assigned to it by NetLabel. Returns the SID on
2669 * success, SECSID_NULL on error.
2670 *
2671 */
2672u32 selinux_netlbl_socket_getpeersec_dgram(struct sk_buff *skb)
2673{
2674 int peer_sid;
2675 2743
2676 if (selinux_netlbl_skbuff_getsid(skb, 2744 rcu_read_lock();
2677 SECINITSID_UNLABELED, 2745 if (level == IPPROTO_IP && optname == IP_OPTIONS &&
2678 &peer_sid) != 0) 2746 sksec->nlbl_state == NLBL_LABELED) {
2679 return SECSID_NULL; 2747 netlbl_secattr_init(&secattr);
2748 rc = netlbl_socket_getattr(sock, &secattr);
2749 if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE)
2750 rc = -EACCES;
2751 netlbl_secattr_destroy(&secattr);
2752 }
2753 rcu_read_unlock();
2680 2754
2681 return peer_sid; 2755 return rc;
2682} 2756}
2683#endif /* CONFIG_NETLABEL */ 2757#endif /* CONFIG_NETLABEL */
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: