diff options
Diffstat (limited to 'security')
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 | ||
831 | static inline void dummy_inet_conn_established(struct sock *sk, | ||
832 | struct sk_buff *skb) | ||
833 | { | ||
834 | } | ||
835 | |||
831 | static inline void dummy_req_classify_flow(const struct request_sock *req, | 836 | static 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 |
838 | static int dummy_xfrm_policy_alloc_security(struct xfrm_policy *xp, | 843 | static 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 | ||
858 | static int dummy_xfrm_state_alloc_security(struct xfrm_state *x, | 863 | static 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 | ||
884 | static int dummy_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm, | ||
885 | struct xfrm_policy *xp) | ||
886 | { | ||
887 | return 1; | ||
888 | } | ||
889 | |||
890 | static int dummy_xfrm_decode_session(struct sk_buff *skb, u32 *fl, int ckall) | 889 | static 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 | ||
35 | static const struct av_perm_to_string | 35 | static 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 | ||
60 | static const struct av_inherit | 55 | static 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 | ||
61 | const 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 */ |
2891 | static int selinux_parse_skb_ipv4(struct sk_buff *skb, struct avc_audit_data *ad) | 2895 | static 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 */ |
2952 | static int selinux_parse_skb_ipv6(struct sk_buff *skb, struct avc_audit_data *ad) | 2976 | static 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 | ||
3008 | static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad, | 3048 | static 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 | ||
3314 | static int selinux_socket_setsockopt(struct socket *sock,int level,int optname) | 3359 | static 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 | ||
3319 | static int selinux_socket_getsockopt(struct socket *sock, int level, | 3370 | static 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 | ||
3606 | static void selinux_sk_getsecid(struct sock *sk, u32 *secid) | 3653 | static 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 | |||
3717 | static 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 | ||
3673 | static void selinux_req_classify_flow(const struct request_sock *req, | 3725 | static 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); |
3830 | out: | 3889 | out: |
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 | ||
11 | int avc_ss_reset(u32 seqno); | 11 | int avc_ss_reset(u32 seqno); |
12 | 12 | ||
13 | struct av_perm_to_string | ||
14 | { | ||
15 | u16 tclass; | ||
16 | u32 value; | ||
17 | const char *name; | ||
18 | }; | ||
19 | |||
20 | struct av_inherit | ||
21 | { | ||
22 | u16 tclass; | ||
23 | const char **common_pts; | ||
24 | u32 common_base; | ||
25 | }; | ||
26 | |||
27 | struct 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 | ||
37 | struct sk_buff; | ||
38 | |||
37 | extern int selinux_enabled; | 39 | extern int selinux_enabled; |
38 | extern int selinux_mls_enabled; | 40 | extern int selinux_mls_enabled; |
39 | 41 | ||
@@ -80,6 +82,8 @@ int security_netif_sid(char *name, u32 *if_sid, | |||
80 | int security_node_sid(u16 domain, void *addr, u32 addrlen, | 82 | int security_node_sid(u16 domain, void *addr, u32 addrlen, |
81 | u32 *out_sid); | 83 | u32 *out_sid); |
82 | 84 | ||
85 | void security_skb_extlbl_sid(struct sk_buff *skb, u32 base_sid, u32 *sid); | ||
86 | |||
83 | int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid, | 87 | int 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 |
40 | void selinux_netlbl_cache_invalidate(void); | 40 | void selinux_netlbl_cache_invalidate(void); |
41 | int selinux_netlbl_socket_post_create(struct socket *sock, | 41 | int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, u32 base_sid, u32 *sid); |
42 | int sock_family, | 42 | int selinux_netlbl_socket_post_create(struct socket *sock); |
43 | u32 sid); | ||
44 | void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock); | 43 | void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock); |
45 | u32 selinux_netlbl_inet_conn_request(struct sk_buff *skb, u32 sock_sid); | ||
46 | int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, | 44 | int 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); |
49 | u32 selinux_netlbl_socket_getpeersec_stream(struct socket *sock); | 47 | void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec, |
50 | u32 selinux_netlbl_socket_getpeersec_dgram(struct sk_buff *skb); | 48 | int family); |
51 | void selinux_netlbl_sk_security_init(struct sk_security_struct *ssec, | 49 | void selinux_netlbl_sk_security_init(struct sk_security_struct *ssec, |
52 | int family); | 50 | int family); |
53 | void selinux_netlbl_sk_clone_security(struct sk_security_struct *ssec, | 51 | void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec, |
54 | struct sk_security_struct *newssec); | 52 | struct sk_security_struct *newssec); |
55 | int selinux_netlbl_inode_permission(struct inode *inode, int mask); | 53 | int selinux_netlbl_inode_permission(struct inode *inode, int mask); |
54 | int selinux_netlbl_socket_setsockopt(struct socket *sock, | ||
55 | int level, | ||
56 | int optname); | ||
56 | #else | 57 | #else |
57 | static inline void selinux_netlbl_cache_invalidate(void) | 58 | static inline void selinux_netlbl_cache_invalidate(void) |
58 | { | 59 | { |
59 | return; | 60 | return; |
60 | } | 61 | } |
61 | 62 | ||
62 | static inline int selinux_netlbl_socket_post_create(struct socket *sock, | 63 | static 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 | ||
69 | static inline void selinux_netlbl_sock_graft(struct sock *sk, | 71 | static 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 | ||
75 | static inline u32 selinux_netlbl_inet_conn_request(struct sk_buff *skb, | 76 | static 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 | ||
81 | static inline int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, | 82 | static 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 | ||
88 | static inline u32 selinux_netlbl_socket_getpeersec_stream(struct socket *sock) | 89 | static inline void selinux_netlbl_sk_security_reset( |
89 | { | 90 | struct sk_security_struct *ssec, |
90 | return SECSID_NULL; | 91 | int family) |
91 | } | ||
92 | |||
93 | static inline u32 selinux_netlbl_socket_getpeersec_dgram(struct sk_buff *skb) | ||
94 | { | 92 | { |
95 | return SECSID_NULL; | 93 | return; |
96 | } | 94 | } |
97 | 95 | ||
98 | static inline void selinux_netlbl_sk_security_init( | 96 | static 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 | ||
105 | static inline void selinux_netlbl_sk_clone_security( | 103 | static 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 | |||
116 | static 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 | ||
10 | int selinux_xfrm_policy_alloc(struct xfrm_policy *xp, | 10 | int 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); |
12 | int selinux_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new); | 12 | int selinux_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new); |
13 | void selinux_xfrm_policy_free(struct xfrm_policy *xp); | 13 | void selinux_xfrm_policy_free(struct xfrm_policy *xp); |
14 | int selinux_xfrm_policy_delete(struct xfrm_policy *xp); | 14 | int selinux_xfrm_policy_delete(struct xfrm_policy *xp); |
15 | int selinux_xfrm_state_alloc(struct xfrm_state *x, | 15 | int 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); |
17 | void selinux_xfrm_state_free(struct xfrm_state *x); | 17 | void selinux_xfrm_state_free(struct xfrm_state *x); |
18 | int selinux_xfrm_state_delete(struct xfrm_state *x); | 18 | int selinux_xfrm_state_delete(struct xfrm_state *x); |
19 | int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir); | 19 | int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir); |
20 | int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, | 20 | int 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); |
22 | int 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) | |||
38 | int selinux_xfrm_sock_rcv_skb(u32 sid, struct sk_buff *skb, | 35 | int selinux_xfrm_sock_rcv_skb(u32 sid, struct sk_buff *skb, |
39 | struct avc_audit_data *ad); | 36 | struct avc_audit_data *ad); |
40 | int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, | 37 | int 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); |
42 | u32 selinux_socket_getpeer_stream(struct sock *sk); | ||
43 | u32 selinux_socket_getpeer_dgram(struct sk_buff *skb); | ||
44 | int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall); | 39 | int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall); |
45 | #else | 40 | #else |
46 | static inline int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb, | 41 | static 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 | ||
52 | static inline int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, | 47 | static 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 | ||
58 | static inline int selinux_socket_getpeer_stream(struct sock *sk) | ||
59 | { | ||
60 | return SECSID_NULL; | ||
61 | } | ||
62 | |||
63 | static inline int selinux_socket_getpeer_dgram(struct sk_buff *skb) | ||
64 | { | ||
65 | return SECSID_NULL; | ||
66 | } | ||
67 | static inline int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall) | 53 | static 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 | ||
60 | static 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 | */ |
85 | int ebitmap_export(const struct ebitmap *src, | 82 | int 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 | |||
124 | netlbl_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 | */ |
143 | int ebitmap_import(const unsigned char *src, | 139 | int 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 | |||
180 | netlbl_import_failure: | ||
181 | ebitmap_destroy(ebmap); | ||
182 | return -ENOMEM; | ||
200 | } | 183 | } |
184 | #endif /* CONFIG_NETLABEL */ | ||
201 | 185 | ||
202 | int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2) | 186 | int 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 | ||
70 | int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2); | 72 | int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2); |
71 | int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src); | 73 | int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src); |
72 | int ebitmap_export(const struct ebitmap *src, | ||
73 | unsigned char **dst, | ||
74 | size_t *dst_len); | ||
75 | int ebitmap_import(const unsigned char *src, | ||
76 | size_t src_len, | ||
77 | struct ebitmap *dst); | ||
78 | int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2); | 74 | int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2); |
79 | int ebitmap_get_bit(struct ebitmap *e, unsigned long bit); | 75 | int ebitmap_get_bit(struct ebitmap *e, unsigned long bit); |
80 | int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value); | 76 | int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value); |
81 | void ebitmap_destroy(struct ebitmap *e); | 77 | void ebitmap_destroy(struct ebitmap *e); |
82 | int ebitmap_read(struct ebitmap *e, void *fp); | 78 | int ebitmap_read(struct ebitmap *e, void *fp); |
83 | 79 | ||
80 | #ifdef CONFIG_NETLABEL | ||
81 | int ebitmap_netlbl_export(struct ebitmap *ebmap, | ||
82 | struct netlbl_lsm_secattr_catmap **catmap); | ||
83 | int ebitmap_netlbl_import(struct ebitmap *ebmap, | ||
84 | struct netlbl_lsm_secattr_catmap *catmap); | ||
85 | #else | ||
86 | static inline int ebitmap_netlbl_export(struct ebitmap *ebmap, | ||
87 | struct netlbl_lsm_secattr_catmap **catmap) | ||
88 | { | ||
89 | return -ENOMEM; | ||
90 | } | ||
91 | static 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 | ||
11 | struct hashtab *hashtab_create(u32 (*hash_value)(struct hashtab *h, void *key), | 11 | struct 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 | ||
74 | void *hashtab_search(struct hashtab *h, void *key) | 74 | void *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 | */ |
42 | struct hashtab *hashtab_create(u32 (*hash_value)(struct hashtab *h, void *key), | 42 | struct 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 | */ |
62 | void *hashtab_search(struct hashtab *h, void *k); | 62 | void *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 | */ |
587 | void mls_export_lvl(const struct context *context, u32 *low, u32 *high) | 586 | void 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 | */ |
610 | void mls_import_lvl(struct context *context, u32 low, u32 high) | 606 | void 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 | */ |
635 | int mls_export_cat(const struct context *context, | 626 | int 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 | ||
663 | export_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 | */ |
686 | int mls_import_cat(struct context *context, | 654 | int 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 | ||
718 | import_cat_failure: | 674 | import_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, | |||
69 | int mls_setup_user_range(struct context *fromcon, struct user_datum *user, | 69 | int mls_setup_user_range(struct context *fromcon, struct user_datum *user, |
70 | struct context *usercon); | 70 | struct context *usercon); |
71 | 71 | ||
72 | void mls_export_lvl(const struct context *context, u32 *low, u32 *high); | 72 | #ifdef CONFIG_NETLABEL |
73 | void mls_import_lvl(struct context *context, u32 low, u32 high); | 73 | void mls_export_netlbl_lvl(struct context *context, |
74 | 74 | struct netlbl_lsm_secattr *secattr); | |
75 | int mls_export_cat(const struct context *context, | 75 | void mls_import_netlbl_lvl(struct context *context, |
76 | unsigned char **low, | 76 | struct netlbl_lsm_secattr *secattr); |
77 | size_t *low_len, | 77 | int mls_export_netlbl_cat(struct context *context, |
78 | unsigned char **high, | 78 | struct netlbl_lsm_secattr *secattr); |
79 | size_t *high_len); | 79 | int mls_import_netlbl_cat(struct context *context, |
80 | int mls_import_cat(struct context *context, | 80 | struct netlbl_lsm_secattr *secattr); |
81 | const unsigned char *low, | 81 | #else |
82 | size_t low_len, | 82 | static 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 | } | ||
87 | static inline void mls_import_netlbl_lvl(struct context *context, | ||
88 | struct netlbl_lsm_secattr *secattr) | ||
89 | { | ||
90 | return; | ||
91 | } | ||
92 | static inline int mls_export_netlbl_cat(struct context *context, | ||
93 | struct netlbl_lsm_secattr *secattr) | ||
94 | { | ||
95 | return -ENOMEM; | ||
96 | } | ||
97 | static 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 | ||
471 | static int class_destroy(void *key, void *datum, void *p) | 471 | static 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) | |||
566 | static int (*destroy_f[SYM_NUM]) (void *key, void *datum, void *datap) = | 566 | static 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) | |||
1124 | out: | 1124 | out: |
1125 | return rc; | 1125 | return rc; |
1126 | bad: | 1126 | bad: |
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 | ||
53 | extern void selnl_notify_policyload(u32 seqno); | 60 | extern void selnl_notify_policyload(u32 seqno); |
54 | unsigned int policydb_loaded_version; | 61 | unsigned int policydb_loaded_version; |
55 | 62 | ||
63 | /* | ||
64 | * This is declared in avc.c | ||
65 | */ | ||
66 | extern const struct selinux_class_perm selinux_class_perm; | ||
67 | |||
56 | static DEFINE_RWLOCK(policy_rwlock); | 68 | static 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 | */ | ||
1026 | static 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 | } | ||
1048 | out: | ||
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 | */ |
1057 | static int validate_class(void *key, void *datum, void *p) | 1037 | static 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); | ||
1100 | out: | ||
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 | */ | ||
2207 | void 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 | ||
2228 | netlbl_cache_add_return: | 2304 | netlbl_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 | */ |
2363 | static int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, | 2436 | int 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 | */ |
2392 | static int selinux_netlbl_socket_setsid(struct socket *sock, u32 sid) | 2467 | static 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 | ||
2425 | netlbl_socket_setsid_return: | 2500 | netlbl_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 | */ | ||
2516 | void 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: | |||
2440 | void selinux_netlbl_sk_security_init(struct sk_security_struct *ssec, | 2535 | void 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 | */ |
2459 | void selinux_netlbl_sk_clone_security(struct sk_security_struct *ssec, | 2553 | void 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 | */ |
2480 | int selinux_netlbl_socket_post_create(struct socket *sock, | 2574 | int 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 | */ | ||
2546 | u32 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) | |||
2570 | int selinux_netlbl_inode_permission(struct inode *inode, int mask) | 2646 | int 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 | */ |
2657 | u32 selinux_netlbl_socket_getpeersec_stream(struct socket *sock) | 2736 | int 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 | */ | ||
2672 | u32 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 | ||
12 | static unsigned int symhash(struct hashtab *h, void *key) | 12 | static 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 | ||
26 | static int symcmp(struct hashtab *h, void *key1, void *key2) | 26 | static 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 | |||
155 | int 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 | ||
190 | int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall) | 160 | int 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 | */ |
228 | static int selinux_xfrm_sec_ctx_alloc(struct xfrm_sec_ctx **ctxp, | 198 | static 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 | ||
281 | not_from_user: | 250 | not_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 | */ |
325 | int selinux_xfrm_policy_alloc(struct xfrm_policy *xp, | 286 | int 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 | */ |
401 | int selinux_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *uctx, | 354 | int 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 | */ | ||
429 | u32 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 | |||
453 | out: | ||
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 | */ | ||
464 | u32 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 | */ |
548 | int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, | 440 | int 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); |
570 | out: | 483 | out: |