diff options
| author | David Howells <dhowells@redhat.com> | 2006-12-05 09:37:56 -0500 |
|---|---|---|
| committer | David Howells <dhowells@warthog.cambridge.redhat.com> | 2006-12-05 09:37:56 -0500 |
| commit | 4c1ac1b49122b805adfa4efc620592f68dccf5db (patch) | |
| tree | 87557f4bc2fd4fe65b7570489c2f610c45c0adcd /security | |
| parent | c4028958b6ecad064b1a6303a6a5906d4fe48d73 (diff) | |
| parent | d916faace3efc0bf19fe9a615a1ab8fa1a24cd93 (diff) | |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Conflicts:
drivers/infiniband/core/iwcm.c
drivers/net/chelsio/cxgb2.c
drivers/net/wireless/bcm43xx/bcm43xx_main.c
drivers/net/wireless/prism54/islpci_eth.c
drivers/usb/core/hub.h
drivers/usb/input/hid-core.c
net/core/netpoll.c
Fix up merge failures with Linus's head and fix new compilation failures.
Signed-Off-By: David Howells <dhowells@redhat.com>
Diffstat (limited to 'security')
24 files changed, 730 insertions, 712 deletions
diff --git a/security/dummy.c b/security/dummy.c index 43874c1e6e23..558795b237d6 100644 --- a/security/dummy.c +++ b/security/dummy.c | |||
| @@ -828,6 +828,11 @@ static inline void dummy_inet_csk_clone(struct sock *newsk, | |||
| 828 | { | 828 | { |
| 829 | } | 829 | } |
| 830 | 830 | ||
| 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 8ab5679a37a3..a29d78d3f44c 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
| @@ -58,6 +58,7 @@ | |||
| 58 | #include <linux/netlink.h> | 58 | #include <linux/netlink.h> |
| 59 | #include <linux/tcp.h> | 59 | #include <linux/tcp.h> |
| 60 | #include <linux/udp.h> | 60 | #include <linux/udp.h> |
| 61 | #include <linux/dccp.h> | ||
| 61 | #include <linux/quota.h> | 62 | #include <linux/quota.h> |
| 62 | #include <linux/un.h> /* for Unix socket types */ | 63 | #include <linux/un.h> /* for Unix socket types */ |
| 63 | #include <net/af_unix.h> /* for Unix socket types */ | 64 | #include <net/af_unix.h> /* for Unix socket types */ |
| @@ -751,6 +752,8 @@ static inline u16 socket_type_to_security_class(int family, int type, int protoc | |||
| 751 | return SECCLASS_UDP_SOCKET; | 752 | return SECCLASS_UDP_SOCKET; |
| 752 | else | 753 | else |
| 753 | return SECCLASS_RAWIP_SOCKET; | 754 | return SECCLASS_RAWIP_SOCKET; |
| 755 | case SOCK_DCCP: | ||
| 756 | return SECCLASS_DCCP_SOCKET; | ||
| 754 | default: | 757 | default: |
| 755 | return SECCLASS_RAWIP_SOCKET; | 758 | return SECCLASS_RAWIP_SOCKET; |
| 756 | } | 759 | } |
| @@ -1754,7 +1757,8 @@ static inline void flush_unauthorized_files(struct files_struct * files) | |||
| 1754 | get_file(devnull); | 1757 | get_file(devnull); |
| 1755 | } else { | 1758 | } else { |
| 1756 | devnull = dentry_open(dget(selinux_null), mntget(selinuxfs_mount), O_RDWR); | 1759 | devnull = dentry_open(dget(selinux_null), mntget(selinuxfs_mount), O_RDWR); |
| 1757 | if (!devnull) { | 1760 | if (IS_ERR(devnull)) { |
| 1761 | devnull = NULL; | ||
| 1758 | put_unused_fd(fd); | 1762 | put_unused_fd(fd); |
| 1759 | fput(file); | 1763 | fput(file); |
| 1760 | continue; | 1764 | continue; |
| @@ -2888,7 +2892,8 @@ static void selinux_task_to_inode(struct task_struct *p, | |||
| 2888 | } | 2892 | } |
| 2889 | 2893 | ||
| 2890 | /* Returns error only if unable to parse addresses */ | 2894 | /* Returns error only if unable to parse addresses */ |
| 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 | } |
| @@ -3437,7 +3482,13 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, | |||
| 3437 | node_perm = NODE__TCP_RECV; | 3482 | node_perm = NODE__TCP_RECV; |
| 3438 | recv_perm = TCP_SOCKET__RECV_MSG; | 3483 | recv_perm = TCP_SOCKET__RECV_MSG; |
| 3439 | break; | 3484 | break; |
| 3440 | 3485 | ||
| 3486 | case SECCLASS_DCCP_SOCKET: | ||
| 3487 | netif_perm = NETIF__DCCP_RECV; | ||
| 3488 | node_perm = NODE__DCCP_RECV; | ||
| 3489 | recv_perm = DCCP_SOCKET__RECV_MSG; | ||
| 3490 | break; | ||
| 3491 | |||
| 3441 | default: | 3492 | default: |
| 3442 | netif_perm = NETIF__RAWIP_RECV; | 3493 | netif_perm = NETIF__RAWIP_RECV; |
| 3443 | node_perm = NODE__RAWIP_RECV; | 3494 | node_perm = NODE__RAWIP_RECV; |
| @@ -3493,7 +3544,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
| 3493 | ad.u.net.netif = skb->dev ? skb->dev->name : "[unknown]"; | 3544 | ad.u.net.netif = skb->dev ? skb->dev->name : "[unknown]"; |
| 3494 | ad.u.net.family = family; | 3545 | ad.u.net.family = family; |
| 3495 | 3546 | ||
| 3496 | err = selinux_parse_skb(skb, &ad, &addrp, &len, 1); | 3547 | err = selinux_parse_skb(skb, &ad, &addrp, &len, 1, NULL); |
| 3497 | if (err) | 3548 | if (err) |
| 3498 | goto out; | 3549 | goto out; |
| 3499 | 3550 | ||
| @@ -3523,25 +3574,16 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *op | |||
| 3523 | u32 scontext_len; | 3574 | u32 scontext_len; |
| 3524 | struct sk_security_struct *ssec; | 3575 | struct sk_security_struct *ssec; |
| 3525 | struct inode_security_struct *isec; | 3576 | struct inode_security_struct *isec; |
| 3526 | u32 peer_sid = 0; | 3577 | u32 peer_sid = SECSID_NULL; |
| 3527 | 3578 | ||
| 3528 | isec = SOCK_INODE(sock)->i_security; | 3579 | isec = SOCK_INODE(sock)->i_security; |
| 3529 | 3580 | ||
| 3530 | /* if UNIX_STREAM check peer_sid, if TCP check dst for labelled sa */ | 3581 | if (isec->sclass == SECCLASS_UNIX_STREAM_SOCKET || |
| 3531 | if (isec->sclass == SECCLASS_UNIX_STREAM_SOCKET) { | 3582 | isec->sclass == SECCLASS_TCP_SOCKET) { |
| 3532 | ssec = sock->sk->sk_security; | 3583 | ssec = sock->sk->sk_security; |
| 3533 | peer_sid = ssec->peer_sid; | 3584 | peer_sid = ssec->peer_sid; |
| 3534 | } | 3585 | } |
| 3535 | else if (isec->sclass == SECCLASS_TCP_SOCKET) { | 3586 | if (peer_sid == SECSID_NULL) { |
| 3536 | peer_sid = selinux_netlbl_socket_getpeersec_stream(sock); | ||
| 3537 | if (peer_sid == SECSID_NULL) | ||
| 3538 | peer_sid = selinux_socket_getpeer_stream(sock->sk); | ||
| 3539 | if (peer_sid == SECSID_NULL) { | ||
| 3540 | err = -ENOPROTOOPT; | ||
| 3541 | goto out; | ||
| 3542 | } | ||
| 3543 | } | ||
| 3544 | else { | ||
| 3545 | err = -ENOPROTOOPT; | 3587 | err = -ENOPROTOOPT; |
| 3546 | goto out; | 3588 | goto out; |
| 3547 | } | 3589 | } |
| @@ -3573,13 +3615,12 @@ static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff * | |||
| 3573 | u32 peer_secid = SECSID_NULL; | 3615 | u32 peer_secid = SECSID_NULL; |
| 3574 | int err = 0; | 3616 | int err = 0; |
| 3575 | 3617 | ||
| 3576 | if (sock && (sock->sk->sk_family == PF_UNIX)) | 3618 | if (sock && sock->sk->sk_family == PF_UNIX) |
| 3577 | selinux_get_inode_sid(SOCK_INODE(sock), &peer_secid); | 3619 | selinux_get_inode_sid(SOCK_INODE(sock), &peer_secid); |
| 3578 | else if (skb) { | 3620 | else if (skb) |
| 3579 | peer_secid = selinux_netlbl_socket_getpeersec_dgram(skb); | 3621 | security_skb_extlbl_sid(skb, |
| 3580 | if (peer_secid == SECSID_NULL) | 3622 | SECINITSID_UNLABELED, |
| 3581 | peer_secid = selinux_socket_getpeer_dgram(skb); | 3623 | &peer_secid); |
| 3582 | } | ||
| 3583 | 3624 | ||
| 3584 | if (peer_secid == SECSID_NULL) | 3625 | if (peer_secid == SECSID_NULL) |
| 3585 | err = -EINVAL; | 3626 | err = -EINVAL; |
| @@ -3606,7 +3647,7 @@ static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk) | |||
| 3606 | newssec->sid = ssec->sid; | 3647 | newssec->sid = ssec->sid; |
| 3607 | newssec->peer_sid = ssec->peer_sid; | 3648 | newssec->peer_sid = ssec->peer_sid; |
| 3608 | 3649 | ||
| 3609 | selinux_netlbl_sk_clone_security(ssec, newssec); | 3650 | selinux_netlbl_sk_security_clone(ssec, newssec); |
| 3610 | } | 3651 | } |
| 3611 | 3652 | ||
| 3612 | static void selinux_sk_getsecid(struct sock *sk, u32 *secid) | 3653 | static void selinux_sk_getsecid(struct sock *sk, u32 *secid) |
| @@ -3640,17 +3681,10 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb, | |||
| 3640 | u32 newsid; | 3681 | u32 newsid; |
| 3641 | u32 peersid; | 3682 | u32 peersid; |
| 3642 | 3683 | ||
| 3643 | newsid = selinux_netlbl_inet_conn_request(skb, sksec->sid); | 3684 | security_skb_extlbl_sid(skb, SECINITSID_UNLABELED, &peersid); |
| 3644 | if (newsid != SECSID_NULL) { | ||
| 3645 | req->secid = newsid; | ||
| 3646 | return 0; | ||
| 3647 | } | ||
| 3648 | |||
| 3649 | err = selinux_xfrm_decode_session(skb, &peersid, 0); | ||
| 3650 | BUG_ON(err); | ||
| 3651 | |||
| 3652 | if (peersid == SECSID_NULL) { | 3685 | if (peersid == SECSID_NULL) { |
| 3653 | req->secid = sksec->sid; | 3686 | req->secid = sksec->sid; |
| 3687 | req->peer_secid = SECSID_NULL; | ||
| 3654 | return 0; | 3688 | return 0; |
| 3655 | } | 3689 | } |
| 3656 | 3690 | ||
| @@ -3659,6 +3693,7 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb, | |||
| 3659 | return err; | 3693 | return err; |
| 3660 | 3694 | ||
| 3661 | req->secid = newsid; | 3695 | req->secid = newsid; |
| 3696 | req->peer_secid = peersid; | ||
| 3662 | return 0; | 3697 | return 0; |
| 3663 | } | 3698 | } |
| 3664 | 3699 | ||
| @@ -3668,12 +3703,23 @@ static void selinux_inet_csk_clone(struct sock *newsk, | |||
| 3668 | struct sk_security_struct *newsksec = newsk->sk_security; | 3703 | struct sk_security_struct *newsksec = newsk->sk_security; |
| 3669 | 3704 | ||
| 3670 | newsksec->sid = req->secid; | 3705 | newsksec->sid = req->secid; |
| 3706 | newsksec->peer_sid = req->peer_secid; | ||
| 3671 | /* NOTE: Ideally, we should also get the isec->sid for the | 3707 | /* NOTE: Ideally, we should also get the isec->sid for the |
| 3672 | new socket in sync, but we don't have the isec available yet. | 3708 | new socket in sync, but we don't have the isec available yet. |
| 3673 | So we will wait until sock_graft to do it, by which | 3709 | So we will wait until sock_graft to do it, by which |
| 3674 | time it will have been created and available. */ | 3710 | time it will have been created and available. */ |
| 3675 | 3711 | ||
| 3676 | selinux_netlbl_sk_security_init(newsksec, req->rsk_ops->family); | 3712 | /* We don't need to take any sort of lock here as we are the only |
| 3713 | * thread with access to newsksec */ | ||
| 3714 | selinux_netlbl_sk_security_reset(newsksec, req->rsk_ops->family); | ||
| 3715 | } | ||
| 3716 | |||
| 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); | ||
| 3677 | } | 3723 | } |
| 3678 | 3724 | ||
| 3679 | static void selinux_req_classify_flow(const struct request_sock *req, | 3725 | static void selinux_req_classify_flow(const struct request_sock *req, |
| @@ -3756,7 +3802,13 @@ static int selinux_ip_postroute_last_compat(struct sock *sk, struct net_device * | |||
| 3756 | node_perm = NODE__TCP_SEND; | 3802 | node_perm = NODE__TCP_SEND; |
| 3757 | send_perm = TCP_SOCKET__SEND_MSG; | 3803 | send_perm = TCP_SOCKET__SEND_MSG; |
| 3758 | break; | 3804 | break; |
| 3759 | 3805 | ||
| 3806 | case SECCLASS_DCCP_SOCKET: | ||
| 3807 | netif_perm = NETIF__DCCP_SEND; | ||
| 3808 | node_perm = NODE__DCCP_SEND; | ||
| 3809 | send_perm = DCCP_SOCKET__SEND_MSG; | ||
| 3810 | break; | ||
| 3811 | |||
| 3760 | default: | 3812 | default: |
| 3761 | netif_perm = NETIF__RAWIP_SEND; | 3813 | netif_perm = NETIF__RAWIP_SEND; |
| 3762 | node_perm = NODE__RAWIP_SEND; | 3814 | node_perm = NODE__RAWIP_SEND; |
| @@ -3807,6 +3859,7 @@ static unsigned int selinux_ip_postroute_last(unsigned int hooknum, | |||
| 3807 | struct avc_audit_data ad; | 3859 | struct avc_audit_data ad; |
| 3808 | struct net_device *dev = (struct net_device *)out; | 3860 | struct net_device *dev = (struct net_device *)out; |
| 3809 | struct sk_security_struct *sksec; | 3861 | struct sk_security_struct *sksec; |
| 3862 | u8 proto; | ||
| 3810 | 3863 | ||
| 3811 | sk = skb->sk; | 3864 | sk = skb->sk; |
| 3812 | if (!sk) | 3865 | if (!sk) |
| @@ -3818,7 +3871,7 @@ static unsigned int selinux_ip_postroute_last(unsigned int hooknum, | |||
| 3818 | ad.u.net.netif = dev->name; | 3871 | ad.u.net.netif = dev->name; |
| 3819 | ad.u.net.family = family; | 3872 | ad.u.net.family = family; |
| 3820 | 3873 | ||
| 3821 | err = selinux_parse_skb(skb, &ad, &addrp, &len, 0); | 3874 | err = selinux_parse_skb(skb, &ad, &addrp, &len, 0, &proto); |
| 3822 | if (err) | 3875 | if (err) |
| 3823 | goto out; | 3876 | goto out; |
| 3824 | 3877 | ||
| @@ -3832,7 +3885,7 @@ static unsigned int selinux_ip_postroute_last(unsigned int hooknum, | |||
| 3832 | if (err) | 3885 | if (err) |
| 3833 | goto out; | 3886 | goto out; |
| 3834 | 3887 | ||
| 3835 | err = selinux_xfrm_postroute_last(sksec->sid, skb, &ad); | 3888 | err = selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto); |
| 3836 | out: | 3889 | out: |
| 3837 | return err ? NF_DROP : NF_ACCEPT; | 3890 | return err ? NF_DROP : NF_ACCEPT; |
| 3838 | } | 3891 | } |
| @@ -4738,6 +4791,7 @@ static struct security_operations selinux_ops = { | |||
| 4738 | .sock_graft = selinux_sock_graft, | 4791 | .sock_graft = selinux_sock_graft, |
| 4739 | .inet_conn_request = selinux_inet_conn_request, | 4792 | .inet_conn_request = selinux_inet_conn_request, |
| 4740 | .inet_csk_clone = selinux_inet_csk_clone, | 4793 | .inet_csk_clone = selinux_inet_csk_clone, |
| 4794 | .inet_conn_established = selinux_inet_conn_established, | ||
| 4741 | .req_classify_flow = selinux_req_classify_flow, | 4795 | .req_classify_flow = selinux_req_classify_flow, |
| 4742 | 4796 | ||
| 4743 | #ifdef CONFIG_SECURITY_NETWORK_XFRM | 4797 | #ifdef CONFIG_SECURITY_NETWORK_XFRM |
| @@ -4750,7 +4804,6 @@ static struct security_operations selinux_ops = { | |||
| 4750 | .xfrm_state_delete_security = selinux_xfrm_state_delete, | 4804 | .xfrm_state_delete_security = selinux_xfrm_state_delete, |
| 4751 | .xfrm_policy_lookup = selinux_xfrm_policy_lookup, | 4805 | .xfrm_policy_lookup = selinux_xfrm_policy_lookup, |
| 4752 | .xfrm_state_pol_flow_match = selinux_xfrm_state_pol_flow_match, | 4806 | .xfrm_state_pol_flow_match = selinux_xfrm_state_pol_flow_match, |
| 4753 | .xfrm_flow_state_match = selinux_xfrm_flow_state_match, | ||
| 4754 | .xfrm_decode_session = selinux_xfrm_decode_session, | 4807 | .xfrm_decode_session = selinux_xfrm_decode_session, |
| 4755 | #endif | 4808 | #endif |
| 4756 | 4809 | ||
diff --git a/security/selinux/include/av_inherit.h b/security/selinux/include/av_inherit.h index a68fdd55597f..8377a4ba3b95 100644 --- a/security/selinux/include/av_inherit.h +++ b/security/selinux/include/av_inherit.h | |||
| @@ -30,3 +30,4 @@ | |||
| 30 | S_(SECCLASS_NETLINK_DNRT_SOCKET, socket, 0x00400000UL) | 30 | S_(SECCLASS_NETLINK_DNRT_SOCKET, socket, 0x00400000UL) |
| 31 | S_(SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET, socket, 0x00400000UL) | 31 | S_(SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET, socket, 0x00400000UL) |
| 32 | S_(SECCLASS_APPLETALK_SOCKET, socket, 0x00400000UL) | 32 | S_(SECCLASS_APPLETALK_SOCKET, socket, 0x00400000UL) |
| 33 | S_(SECCLASS_DCCP_SOCKET, socket, 0x00400000UL) | ||
diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h index 09fc8a2345eb..ad9fb2d69b50 100644 --- a/security/selinux/include/av_perm_to_string.h +++ b/security/selinux/include/av_perm_to_string.h | |||
| @@ -35,12 +35,16 @@ | |||
| 35 | S_(SECCLASS_NODE, NODE__RAWIP_RECV, "rawip_recv") | 35 | S_(SECCLASS_NODE, NODE__RAWIP_RECV, "rawip_recv") |
| 36 | S_(SECCLASS_NODE, NODE__RAWIP_SEND, "rawip_send") | 36 | S_(SECCLASS_NODE, NODE__RAWIP_SEND, "rawip_send") |
| 37 | S_(SECCLASS_NODE, NODE__ENFORCE_DEST, "enforce_dest") | 37 | S_(SECCLASS_NODE, NODE__ENFORCE_DEST, "enforce_dest") |
| 38 | S_(SECCLASS_NODE, NODE__DCCP_RECV, "dccp_recv") | ||
| 39 | S_(SECCLASS_NODE, NODE__DCCP_SEND, "dccp_send") | ||
| 38 | S_(SECCLASS_NETIF, NETIF__TCP_RECV, "tcp_recv") | 40 | S_(SECCLASS_NETIF, NETIF__TCP_RECV, "tcp_recv") |
| 39 | S_(SECCLASS_NETIF, NETIF__TCP_SEND, "tcp_send") | 41 | S_(SECCLASS_NETIF, NETIF__TCP_SEND, "tcp_send") |
| 40 | S_(SECCLASS_NETIF, NETIF__UDP_RECV, "udp_recv") | 42 | S_(SECCLASS_NETIF, NETIF__UDP_RECV, "udp_recv") |
| 41 | S_(SECCLASS_NETIF, NETIF__UDP_SEND, "udp_send") | 43 | S_(SECCLASS_NETIF, NETIF__UDP_SEND, "udp_send") |
| 42 | S_(SECCLASS_NETIF, NETIF__RAWIP_RECV, "rawip_recv") | 44 | S_(SECCLASS_NETIF, NETIF__RAWIP_RECV, "rawip_recv") |
| 43 | S_(SECCLASS_NETIF, NETIF__RAWIP_SEND, "rawip_send") | 45 | S_(SECCLASS_NETIF, NETIF__RAWIP_SEND, "rawip_send") |
| 46 | S_(SECCLASS_NETIF, NETIF__DCCP_RECV, "dccp_recv") | ||
| 47 | S_(SECCLASS_NETIF, NETIF__DCCP_SEND, "dccp_send") | ||
| 44 | S_(SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__CONNECTTO, "connectto") | 48 | S_(SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__CONNECTTO, "connectto") |
| 45 | S_(SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__NEWCONN, "newconn") | 49 | S_(SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__NEWCONN, "newconn") |
| 46 | S_(SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__ACCEPTFROM, "acceptfrom") | 50 | S_(SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__ACCEPTFROM, "acceptfrom") |
| @@ -252,3 +256,7 @@ | |||
| 252 | S_(SECCLASS_KEY, KEY__LINK, "link") | 256 | S_(SECCLASS_KEY, KEY__LINK, "link") |
| 253 | S_(SECCLASS_KEY, KEY__SETATTR, "setattr") | 257 | S_(SECCLASS_KEY, KEY__SETATTR, "setattr") |
| 254 | S_(SECCLASS_KEY, KEY__CREATE, "create") | 258 | S_(SECCLASS_KEY, KEY__CREATE, "create") |
| 259 | S_(SECCLASS_CONTEXT, CONTEXT__TRANSLATE, "translate") | ||
| 260 | S_(SECCLASS_CONTEXT, CONTEXT__CONTAINS, "contains") | ||
| 261 | S_(SECCLASS_DCCP_SOCKET, DCCP_SOCKET__NODE_BIND, "node_bind") | ||
| 262 | S_(SECCLASS_DCCP_SOCKET, DCCP_SOCKET__NAME_CONNECT, "name_connect") | ||
diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h index 81f4f526c8b1..2de4b5fe3aa1 100644 --- a/security/selinux/include/av_permissions.h +++ b/security/selinux/include/av_permissions.h | |||
| @@ -312,6 +312,8 @@ | |||
| 312 | #define NODE__RAWIP_RECV 0x00000010UL | 312 | #define NODE__RAWIP_RECV 0x00000010UL |
| 313 | #define NODE__RAWIP_SEND 0x00000020UL | 313 | #define NODE__RAWIP_SEND 0x00000020UL |
| 314 | #define NODE__ENFORCE_DEST 0x00000040UL | 314 | #define NODE__ENFORCE_DEST 0x00000040UL |
| 315 | #define NODE__DCCP_RECV 0x00000080UL | ||
| 316 | #define NODE__DCCP_SEND 0x00000100UL | ||
| 315 | 317 | ||
| 316 | #define NETIF__TCP_RECV 0x00000001UL | 318 | #define NETIF__TCP_RECV 0x00000001UL |
| 317 | #define NETIF__TCP_SEND 0x00000002UL | 319 | #define NETIF__TCP_SEND 0x00000002UL |
| @@ -319,6 +321,8 @@ | |||
| 319 | #define NETIF__UDP_SEND 0x00000008UL | 321 | #define NETIF__UDP_SEND 0x00000008UL |
| 320 | #define NETIF__RAWIP_RECV 0x00000010UL | 322 | #define NETIF__RAWIP_RECV 0x00000010UL |
| 321 | #define NETIF__RAWIP_SEND 0x00000020UL | 323 | #define NETIF__RAWIP_SEND 0x00000020UL |
| 324 | #define NETIF__DCCP_RECV 0x00000040UL | ||
| 325 | #define NETIF__DCCP_SEND 0x00000080UL | ||
| 322 | 326 | ||
| 323 | #define NETLINK_SOCKET__IOCTL 0x00000001UL | 327 | #define NETLINK_SOCKET__IOCTL 0x00000001UL |
| 324 | #define NETLINK_SOCKET__READ 0x00000002UL | 328 | #define NETLINK_SOCKET__READ 0x00000002UL |
| @@ -970,3 +974,31 @@ | |||
| 970 | #define KEY__LINK 0x00000010UL | 974 | #define KEY__LINK 0x00000010UL |
| 971 | #define KEY__SETATTR 0x00000020UL | 975 | #define KEY__SETATTR 0x00000020UL |
| 972 | #define KEY__CREATE 0x00000040UL | 976 | #define KEY__CREATE 0x00000040UL |
| 977 | |||
| 978 | #define CONTEXT__TRANSLATE 0x00000001UL | ||
| 979 | #define CONTEXT__CONTAINS 0x00000002UL | ||
| 980 | |||
| 981 | #define DCCP_SOCKET__IOCTL 0x00000001UL | ||
| 982 | #define DCCP_SOCKET__READ 0x00000002UL | ||
| 983 | #define DCCP_SOCKET__WRITE 0x00000004UL | ||
| 984 | #define DCCP_SOCKET__CREATE 0x00000008UL | ||
| 985 | #define DCCP_SOCKET__GETATTR 0x00000010UL | ||
| 986 | #define DCCP_SOCKET__SETATTR 0x00000020UL | ||
| 987 | #define DCCP_SOCKET__LOCK 0x00000040UL | ||
| 988 | #define DCCP_SOCKET__RELABELFROM 0x00000080UL | ||
| 989 | #define DCCP_SOCKET__RELABELTO 0x00000100UL | ||
| 990 | #define DCCP_SOCKET__APPEND 0x00000200UL | ||
| 991 | #define DCCP_SOCKET__BIND 0x00000400UL | ||
| 992 | #define DCCP_SOCKET__CONNECT 0x00000800UL | ||
| 993 | #define DCCP_SOCKET__LISTEN 0x00001000UL | ||
| 994 | #define DCCP_SOCKET__ACCEPT 0x00002000UL | ||
| 995 | #define DCCP_SOCKET__GETOPT 0x00004000UL | ||
| 996 | #define DCCP_SOCKET__SETOPT 0x00008000UL | ||
| 997 | #define DCCP_SOCKET__SHUTDOWN 0x00010000UL | ||
| 998 | #define DCCP_SOCKET__RECVFROM 0x00020000UL | ||
| 999 | #define DCCP_SOCKET__SENDTO 0x00040000UL | ||
| 1000 | #define DCCP_SOCKET__RECV_MSG 0x00080000UL | ||
| 1001 | #define DCCP_SOCKET__SEND_MSG 0x00100000UL | ||
| 1002 | #define DCCP_SOCKET__NAME_BIND 0x00200000UL | ||
| 1003 | #define DCCP_SOCKET__NODE_BIND 0x00400000UL | ||
| 1004 | #define DCCP_SOCKET__NAME_CONNECT 0x00800000UL | ||
diff --git a/security/selinux/include/avc_ss.h b/security/selinux/include/avc_ss.h index 450a2831e2e3..ff869e8b6f4a 100644 --- a/security/selinux/include/avc_ss.h +++ b/security/selinux/include/avc_ss.h | |||
| @@ -10,5 +10,29 @@ | |||
| 10 | 10 | ||
| 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 9de10cc2cef2..2a732c9033e3 100644 --- a/security/selinux/include/selinux_netlabel.h +++ b/security/selinux/include/selinux_netlabel.h | |||
| @@ -38,19 +38,17 @@ | |||
| 38 | 38 | ||
| 39 | #ifdef CONFIG_NETLABEL | 39 | #ifdef CONFIG_NETLABEL |
| 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); |
| 56 | int selinux_netlbl_socket_setsockopt(struct socket *sock, | 54 | int selinux_netlbl_socket_setsockopt(struct socket *sock, |
| @@ -62,23 +60,23 @@ static inline void selinux_netlbl_cache_invalidate(void) | |||
| 62 | return; | 60 | return; |
| 63 | } | 61 | } |
| 64 | 62 | ||
| 65 | static inline int selinux_netlbl_socket_post_create(struct socket *sock, | 63 | static inline int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, |
| 66 | int sock_family, | 64 | u32 base_sid, |
| 67 | u32 sid) | 65 | u32 *sid) |
| 68 | { | 66 | { |
| 67 | *sid = SECSID_NULL; | ||
| 69 | return 0; | 68 | return 0; |
| 70 | } | 69 | } |
| 71 | 70 | ||
| 72 | static inline void selinux_netlbl_sock_graft(struct sock *sk, | 71 | static inline int selinux_netlbl_socket_post_create(struct socket *sock) |
| 73 | struct socket *sock) | ||
| 74 | { | 72 | { |
| 75 | return; | 73 | return 0; |
| 76 | } | 74 | } |
| 77 | 75 | ||
| 78 | static inline u32 selinux_netlbl_inet_conn_request(struct sk_buff *skb, | 76 | static inline void selinux_netlbl_sock_graft(struct sock *sk, |
| 79 | u32 sock_sid) | 77 | struct socket *sock) |
| 80 | { | 78 | { |
| 81 | return SECSID_NULL; | 79 | return; |
| 82 | } | 80 | } |
| 83 | 81 | ||
| 84 | 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, |
| @@ -88,14 +86,11 @@ static inline int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, | |||
| 88 | return 0; | 86 | return 0; |
| 89 | } | 87 | } |
| 90 | 88 | ||
| 91 | static inline u32 selinux_netlbl_socket_getpeersec_stream(struct socket *sock) | 89 | static inline void selinux_netlbl_sk_security_reset( |
| 92 | { | 90 | struct sk_security_struct *ssec, |
| 93 | return SECSID_NULL; | 91 | int family) |
| 94 | } | ||
| 95 | |||
| 96 | static inline u32 selinux_netlbl_socket_getpeersec_dgram(struct sk_buff *skb) | ||
| 97 | { | 92 | { |
| 98 | return SECSID_NULL; | 93 | return; |
| 99 | } | 94 | } |
| 100 | 95 | ||
| 101 | static inline void selinux_netlbl_sk_security_init( | 96 | static inline void selinux_netlbl_sk_security_init( |
| @@ -105,7 +100,7 @@ static inline void selinux_netlbl_sk_security_init( | |||
| 105 | return; | 100 | return; |
| 106 | } | 101 | } |
| 107 | 102 | ||
| 108 | static inline void selinux_netlbl_sk_clone_security( | 103 | static inline void selinux_netlbl_sk_security_clone( |
| 109 | struct sk_security_struct *ssec, | 104 | struct sk_security_struct *ssec, |
| 110 | struct sk_security_struct *newssec) | 105 | struct sk_security_struct *newssec) |
| 111 | { | 106 | { |
diff --git a/security/selinux/include/xfrm.h b/security/selinux/include/xfrm.h index 526b28019aca..161eb571c82d 100644 --- a/security/selinux/include/xfrm.h +++ b/security/selinux/include/xfrm.h | |||
| @@ -8,20 +8,17 @@ | |||
| 8 | #define _SELINUX_XFRM_H_ | 8 | #define _SELINUX_XFRM_H_ |
| 9 | 9 | ||
| 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 d539346ab3a2..ce492a6b38ed 100644 --- a/security/selinux/ss/ebitmap.c +++ b/security/selinux/ss/ebitmap.c | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | /* | 6 | /* |
| 7 | * Updated: Hewlett-Packard <paul.moore@hp.com> | 7 | * Updated: Hewlett-Packard <paul.moore@hp.com> |
| 8 | * | 8 | * |
| 9 | * Added ebitmap_export() and ebitmap_import() | 9 | * Added support to import/export the NetLabel category bitmap |
| 10 | * | 10 | * |
| 11 | * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 | 11 | * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 |
| 12 | */ | 12 | */ |
| @@ -14,6 +14,7 @@ | |||
| 14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
| 15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
| 16 | #include <linux/errno.h> | 16 | #include <linux/errno.h> |
| 17 | #include <net/netlabel.h> | ||
| 17 | #include "ebitmap.h" | 18 | #include "ebitmap.h" |
| 18 | #include "policydb.h" | 19 | #include "policydb.h" |
| 19 | 20 | ||
| @@ -67,141 +68,120 @@ int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src) | |||
| 67 | return 0; | 68 | return 0; |
| 68 | } | 69 | } |
| 69 | 70 | ||
| 71 | #ifdef CONFIG_NETLABEL | ||
| 70 | /** | 72 | /** |
| 71 | * ebitmap_export - Export an ebitmap to a unsigned char bitmap string | 73 | * ebitmap_netlbl_export - Export an ebitmap into a NetLabel category bitmap |
| 72 | * @src: the ebitmap to export | 74 | * @ebmap: the ebitmap to export |
| 73 | * @dst: the resulting bitmap string | 75 | * @catmap: the NetLabel category bitmap |
| 74 | * @dst_len: length of dst in bytes | ||
| 75 | * | 76 | * |
| 76 | * Description: | 77 | * Description: |
| 77 | * Allocate a buffer at least src->highbit bits long and export the extensible | 78 | * Export a SELinux extensibile bitmap into a NetLabel category bitmap. |
| 78 | * bitmap into the buffer. The bitmap string will be in little endian format, | 79 | * Returns zero on success, negative values on error. |
| 79 | * i.e. LSB first. The value returned in dst_len may not the true size of the | ||
| 80 | * buffer as the length of the buffer is rounded up to a multiple of MAPTYPE. | ||
| 81 | * The caller must free the buffer when finished. Returns zero on success, | ||
| 82 | * negative values on failure. | ||
| 83 | * | 80 | * |
| 84 | */ | 81 | */ |
| 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 | if (src->highbit == 0) { | 92 | * as well. It's not ideal but I think the tradeoff in terms of |
| 97 | *dst = NULL; | 93 | * neatness and speed is worth it. */ |
| 98 | *dst_len = 0; | 94 | |
| 95 | if (e_iter == NULL) { | ||
| 96 | *catmap = NULL; | ||
| 99 | return 0; | 97 | return 0; |
| 100 | } | 98 | } |
| 101 | 99 | ||
| 102 | bitmap_len = src->highbit / 8; | 100 | c_iter = netlbl_secattr_catmap_alloc(GFP_ATOMIC); |
| 103 | if (src->highbit % 7) | 101 | if (c_iter == NULL) |
| 104 | bitmap_len += 1; | ||
| 105 | |||
| 106 | bitmap = kzalloc((bitmap_len & ~(sizeof(MAPTYPE) - 1)) + | ||
| 107 | sizeof(MAPTYPE), | ||
| 108 | GFP_ATOMIC); | ||
| 109 | if (bitmap == NULL) | ||
| 110 | return -ENOMEM; | 102 | return -ENOMEM; |
| 103 | *catmap = c_iter; | ||
| 104 | c_iter->startbit = e_iter->startbit & ~(NETLBL_CATMAP_SIZE - 1); | ||
| 105 | |||
| 106 | while (e_iter != NULL) { | ||
| 107 | if (e_iter->startbit >= | ||
| 108 | (c_iter->startbit + NETLBL_CATMAP_SIZE)) { | ||
| 109 | c_iter->next = netlbl_secattr_catmap_alloc(GFP_ATOMIC); | ||
| 110 | if (c_iter->next == NULL) | ||
| 111 | goto netlbl_export_failure; | ||
| 112 | c_iter = c_iter->next; | ||
| 113 | c_iter->startbit = e_iter->startbit & | ||
| 114 | ~(NETLBL_CATMAP_SIZE - 1); | ||
| 115 | } | ||
| 116 | cmap_idx = (e_iter->startbit - c_iter->startbit) / | ||
| 117 | NETLBL_CATMAP_MAPSIZE; | ||
| 118 | c_iter->bitmap[cmap_idx] = e_iter->map; | ||
| 119 | e_iter = e_iter->next; | ||
| 120 | } | ||
| 111 | 121 | ||
| 112 | iter_node = src->node; | ||
| 113 | do { | ||
| 114 | bitmap_byte = iter_node->startbit / 8; | ||
| 115 | bitmask = 0x80; | ||
| 116 | node_val = iter_node->map; | ||
| 117 | do { | ||
| 118 | if (bitmask == 0) { | ||
| 119 | bitmap_byte++; | ||
| 120 | bitmask = 0x80; | ||
| 121 | } | ||
| 122 | if (node_val & (MAPTYPE)0x01) | ||
| 123 | bitmap[bitmap_byte] |= bitmask; | ||
| 124 | node_val >>= 1; | ||
| 125 | bitmask >>= 1; | ||
| 126 | } while (node_val > 0); | ||
| 127 | iter_node = iter_node->next; | ||
| 128 | } while (iter_node); | ||
| 129 | |||
| 130 | *dst = bitmap; | ||
| 131 | *dst_len = bitmap_len; | ||
| 132 | return 0; | 122 | return 0; |
| 123 | |||
| 124 | netlbl_export_failure: | ||
| 125 | netlbl_secattr_catmap_free(*catmap); | ||
| 126 | return -ENOMEM; | ||
| 133 | } | 127 | } |
| 134 | 128 | ||
| 135 | /** | 129 | /** |
| 136 | * ebitmap_import - Import an unsigned char bitmap string into an ebitmap | 130 | * ebitmap_netlbl_import - Import a NetLabel category bitmap into an ebitmap |
| 137 | * @src: the bitmap string | 131 | * @ebmap: the ebitmap to export |
| 138 | * @src_len: the bitmap length in bytes | 132 | * @catmap: the NetLabel category bitmap |
| 139 | * @dst: the empty ebitmap | ||
| 140 | * | 133 | * |
| 141 | * Description: | 134 | * Description: |
| 142 | * This function takes a little endian bitmap string in src and imports it into | 135 | * Import a NetLabel category bitmap into a SELinux extensibile bitmap. |
| 143 | * the ebitmap pointed to by dst. Returns zero on success, negative values on | 136 | * Returns zero on success, negative values on error. |
| 144 | * failure. | ||
| 145 | * | 137 | * |
| 146 | */ | 138 | */ |
| 147 | int ebitmap_import(const unsigned char *src, | 139 | int ebitmap_netlbl_import(struct ebitmap *ebmap, |
| 148 | size_t src_len, | 140 | struct netlbl_lsm_secattr_catmap *catmap) |
| 149 | struct ebitmap *dst) | ||
| 150 | { | 141 | { |
| 151 | size_t src_off = 0; | 142 | struct ebitmap_node *e_iter = NULL; |
| 152 | size_t node_limit; | 143 | struct ebitmap_node *emap_prev = NULL; |
| 153 | struct ebitmap_node *node_new; | 144 | struct netlbl_lsm_secattr_catmap *c_iter = catmap; |
| 154 | struct ebitmap_node *node_last = NULL; | 145 | u32 c_idx; |
| 155 | u32 i_byte; | ||
| 156 | u32 i_bit; | ||
| 157 | unsigned char src_byte; | ||
| 158 | |||
| 159 | while (src_off < src_len) { | ||
| 160 | if (src_len - src_off >= sizeof(MAPTYPE)) { | ||
| 161 | if (*(MAPTYPE *)&src[src_off] == 0) { | ||
| 162 | src_off += sizeof(MAPTYPE); | ||
| 163 | continue; | ||
| 164 | } | ||
| 165 | node_limit = sizeof(MAPTYPE); | ||
| 166 | } else { | ||
| 167 | for (src_byte = 0, i_byte = src_off; | ||
| 168 | i_byte < src_len && src_byte == 0; | ||
| 169 | i_byte++) | ||
| 170 | src_byte |= src[i_byte]; | ||
| 171 | if (src_byte == 0) | ||
| 172 | break; | ||
| 173 | node_limit = src_len - src_off; | ||
| 174 | } | ||
| 175 | 146 | ||
| 176 | node_new = kzalloc(sizeof(*node_new), GFP_ATOMIC); | 147 | /* This function is a much simpler because SELinux's MAPTYPE happens |
| 177 | if (unlikely(node_new == NULL)) { | 148 | * to be the same as NetLabel's NETLBL_CATMAP_MAPTYPE, if MAPTYPE is |
| 178 | ebitmap_destroy(dst); | 149 | * changed from a u64 this function will most likely need to be changed |
| 179 | return -ENOMEM; | 150 | * as well. It's not ideal but I think the tradeoff in terms of |
| 180 | } | 151 | * neatness and speed is worth it. */ |
| 181 | node_new->startbit = src_off * 8; | ||
| 182 | for (i_byte = 0; i_byte < node_limit; i_byte++) { | ||
| 183 | src_byte = src[src_off++]; | ||
| 184 | for (i_bit = i_byte * 8; src_byte != 0; i_bit++) { | ||
| 185 | if (src_byte & 0x80) | ||
| 186 | node_new->map |= MAPBIT << i_bit; | ||
| 187 | src_byte <<= 1; | ||
| 188 | } | ||
| 189 | } | ||
| 190 | 152 | ||
| 191 | if (node_last != NULL) | 153 | do { |
| 192 | node_last->next = node_new; | 154 | for (c_idx = 0; c_idx < NETLBL_CATMAP_MAPCNT; c_idx++) { |
| 193 | else | 155 | if (c_iter->bitmap[c_idx] == 0) |
| 194 | dst->node = node_new; | 156 | continue; |
| 195 | node_last = node_new; | 157 | |
| 196 | } | 158 | e_iter = kzalloc(sizeof(*e_iter), GFP_ATOMIC); |
| 159 | if (e_iter == NULL) | ||
| 160 | goto netlbl_import_failure; | ||
| 161 | if (emap_prev == NULL) | ||
| 162 | ebmap->node = e_iter; | ||
| 163 | else | ||
| 164 | emap_prev->next = e_iter; | ||
| 165 | emap_prev = e_iter; | ||
| 197 | 166 | ||
| 198 | if (likely(node_last != NULL)) | 167 | e_iter->startbit = c_iter->startbit + |
| 199 | dst->highbit = node_last->startbit + MAPSIZE; | 168 | NETLBL_CATMAP_MAPSIZE * c_idx; |
| 169 | e_iter->map = c_iter->bitmap[c_idx]; | ||
| 170 | } | ||
| 171 | c_iter = c_iter->next; | ||
| 172 | } while (c_iter != NULL); | ||
| 173 | if (e_iter != NULL) | ||
| 174 | ebmap->highbit = e_iter->startbit + MAPSIZE; | ||
| 200 | else | 175 | else |
| 201 | ebitmap_init(dst); | 176 | ebitmap_destroy(ebmap); |
| 202 | 177 | ||
| 203 | return 0; | 178 | return 0; |
| 179 | |||
| 180 | netlbl_import_failure: | ||
| 181 | ebitmap_destroy(ebmap); | ||
| 182 | return -ENOMEM; | ||
| 204 | } | 183 | } |
| 184 | #endif /* CONFIG_NETLABEL */ | ||
| 205 | 185 | ||
| 206 | int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2) | 186 | int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2) |
| 207 | { | 187 | { |
diff --git a/security/selinux/ss/ebitmap.h b/security/selinux/ss/ebitmap.h index da2d4651b10d..1270e34b61c1 100644 --- a/security/selinux/ss/ebitmap.h +++ b/security/selinux/ss/ebitmap.h | |||
| @@ -14,6 +14,8 @@ | |||
| 14 | #ifndef _SS_EBITMAP_H_ | 14 | #ifndef _SS_EBITMAP_H_ |
| 15 | #define _SS_EBITMAP_H_ | 15 | #define _SS_EBITMAP_H_ |
| 16 | 16 | ||
| 17 | #include <net/netlabel.h> | ||
| 18 | |||
| 17 | #define MAPTYPE u64 /* portion of bitmap in each node */ | 19 | #define MAPTYPE u64 /* portion of bitmap in each node */ |
| 18 | #define MAPSIZE (sizeof(MAPTYPE) * 8) /* number of bits in node bitmap */ | 20 | #define MAPSIZE (sizeof(MAPTYPE) * 8) /* number of bits in node bitmap */ |
| 19 | #define MAPBIT 1ULL /* a bit in the node bitmap */ | 21 | #define MAPBIT 1ULL /* a bit in the node bitmap */ |
| @@ -69,16 +71,28 @@ static inline int ebitmap_node_get_bit(struct ebitmap_node * n, | |||
| 69 | 71 | ||
| 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 2cca8e251624..b4f682dc13ff 100644 --- a/security/selinux/ss/mls.c +++ b/security/selinux/ss/mls.c | |||
| @@ -13,7 +13,7 @@ | |||
| 13 | /* | 13 | /* |
| 14 | * Updated: Hewlett-Packard <paul.moore@hp.com> | 14 | * Updated: Hewlett-Packard <paul.moore@hp.com> |
| 15 | * | 15 | * |
| 16 | * Added support to import/export the MLS label | 16 | * Added support to import/export the MLS label from NetLabel |
| 17 | * | 17 | * |
| 18 | * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 | 18 | * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 |
| 19 | */ | 19 | */ |
| @@ -22,6 +22,7 @@ | |||
| 22 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
| 23 | #include <linux/string.h> | 23 | #include <linux/string.h> |
| 24 | #include <linux/errno.h> | 24 | #include <linux/errno.h> |
| 25 | #include <net/netlabel.h> | ||
| 25 | #include "sidtab.h" | 26 | #include "sidtab.h" |
| 26 | #include "mls.h" | 27 | #include "mls.h" |
| 27 | #include "policydb.h" | 28 | #include "policydb.h" |
| @@ -571,163 +572,108 @@ int mls_compute_sid(struct context *scontext, | |||
| 571 | return -EINVAL; | 572 | return -EINVAL; |
| 572 | } | 573 | } |
| 573 | 574 | ||
| 575 | #ifdef CONFIG_NETLABEL | ||
| 574 | /** | 576 | /** |
| 575 | * mls_export_lvl - Export the MLS sensitivity levels | 577 | * mls_export_netlbl_lvl - Export the MLS sensitivity levels to NetLabel |
| 576 | * @context: the security context | 578 | * @context: the security context |
| 577 | * @low: the low sensitivity level | 579 | * @secattr: the NetLabel security attributes |
| 578 | * @high: the high sensitivity level | ||
| 579 | * | 580 | * |
| 580 | * Description: | 581 | * Description: |
| 581 | * Given the security context copy the low MLS sensitivity level into lvl_low | 582 | * Given the security context copy the low MLS sensitivity level into the |
| 582 | * and the high sensitivity level in lvl_high. The MLS levels are only | 583 | * NetLabel MLS sensitivity level field. |
| 583 | * exported if the pointers are not NULL, if they are NULL then that level is | ||
| 584 | * not exported. | ||
| 585 | * | 584 | * |
| 586 | */ | 585 | */ |
| 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 | *low = NULL; | ||
| 645 | *low_len = 0; | ||
| 646 | *high = NULL; | ||
| 647 | *high_len = 0; | ||
| 648 | return 0; | 632 | return 0; |
| 649 | } | ||
| 650 | 633 | ||
| 651 | if (low != NULL) { | 634 | rc = ebitmap_netlbl_export(&context->range.level[0].cat, |
| 652 | rc = ebitmap_export(&context->range.level[0].cat, | 635 | &secattr->mls_cat); |
| 653 | low, | 636 | if (rc == 0 && secattr->mls_cat != NULL) |
| 654 | low_len); | 637 | secattr->flags |= NETLBL_SECATTR_MLS_CAT; |
| 655 | if (rc != 0) | ||
| 656 | goto export_cat_failure; | ||
| 657 | } | ||
| 658 | if (high != NULL) { | ||
| 659 | rc = ebitmap_export(&context->range.level[1].cat, | ||
| 660 | high, | ||
| 661 | high_len); | ||
| 662 | if (rc != 0) | ||
| 663 | goto export_cat_failure; | ||
| 664 | } | ||
| 665 | |||
| 666 | return 0; | ||
| 667 | 638 | ||
| 668 | export_cat_failure: | ||
| 669 | if (low != NULL) { | ||
| 670 | kfree(*low); | ||
| 671 | *low = NULL; | ||
| 672 | *low_len = 0; | ||
| 673 | } | ||
| 674 | if (high != NULL) { | ||
| 675 | kfree(*high); | ||
| 676 | *high = NULL; | ||
| 677 | *high_len = 0; | ||
| 678 | } | ||
| 679 | return rc; | 639 | return rc; |
| 680 | } | 640 | } |
| 681 | 641 | ||
| 682 | /** | 642 | /** |
| 683 | * mls_import_cat - Import the MLS categories | 643 | * mls_import_netlbl_cat - Import the MLS categories from NetLabel |
| 684 | * @context: the security context | 644 | * @context: the security context |
| 685 | * @low: the low category | 645 | * @secattr: the NetLabel security attributes |
| 686 | * @low_len: length of the cat_low bitmap in bytes | ||
| 687 | * @high: the high category | ||
| 688 | * @high_len: length of the cat_high bitmap in bytes | ||
| 689 | * | 646 | * |
| 690 | * Description: | 647 | * Description: |
| 691 | * Given the security context and the two category bitmap strings import the | 648 | * Copy the NetLabel security attributes into the SELinux context; since the |
| 692 | * categories into the security context. The MLS categories are only imported | 649 | * NetLabel security attribute only contains a single MLS category use it for |
| 693 | * if the pointers are not NULL, if they are NULL they are skipped. Returns | 650 | * both the low and high categories of the context. Returns zero on success, |
| 694 | * zero on success, negative values on failure. | 651 | * negative values on failure. |
| 695 | * | 652 | * |
| 696 | */ | 653 | */ |
| 697 | int mls_import_cat(struct context *context, | 654 | int mls_import_netlbl_cat(struct context *context, |
| 698 | const unsigned char *low, | 655 | struct netlbl_lsm_secattr *secattr) |
| 699 | size_t low_len, | ||
| 700 | const unsigned char *high, | ||
| 701 | size_t high_len) | ||
| 702 | { | 656 | { |
| 703 | int rc = -EPERM; | 657 | int rc; |
| 704 | 658 | ||
| 705 | if (!selinux_mls_enabled) | 659 | if (!selinux_mls_enabled) |
| 706 | return 0; | 660 | return 0; |
| 707 | 661 | ||
| 708 | if (low != NULL) { | 662 | rc = ebitmap_netlbl_import(&context->range.level[0].cat, |
| 709 | rc = ebitmap_import(low, | 663 | secattr->mls_cat); |
| 710 | low_len, | 664 | if (rc != 0) |
| 711 | &context->range.level[0].cat); | 665 | goto import_netlbl_cat_failure; |
| 712 | if (rc != 0) | 666 | |
| 713 | goto import_cat_failure; | 667 | rc = ebitmap_cpy(&context->range.level[1].cat, |
| 714 | } | 668 | &context->range.level[0].cat); |
| 715 | if (high != NULL) { | 669 | if (rc != 0) |
| 716 | if (high == low) | 670 | goto import_netlbl_cat_failure; |
| 717 | rc = ebitmap_cpy(&context->range.level[1].cat, | ||
| 718 | &context->range.level[0].cat); | ||
| 719 | else | ||
| 720 | rc = ebitmap_import(high, | ||
| 721 | high_len, | ||
| 722 | &context->range.level[1].cat); | ||
| 723 | if (rc != 0) | ||
| 724 | goto import_cat_failure; | ||
| 725 | } | ||
| 726 | 671 | ||
| 727 | return 0; | 672 | return 0; |
| 728 | 673 | ||
| 729 | import_cat_failure: | 674 | import_netlbl_cat_failure: |
| 730 | ebitmap_destroy(&context->range.level[0].cat); | 675 | ebitmap_destroy(&context->range.level[0].cat); |
| 731 | ebitmap_destroy(&context->range.level[1].cat); | 676 | ebitmap_destroy(&context->range.level[1].cat); |
| 732 | return rc; | 677 | return rc; |
| 733 | } | 678 | } |
| 679 | #endif /* CONFIG_NETLABEL */ | ||
diff --git a/security/selinux/ss/mls.h b/security/selinux/ss/mls.h index df6032c6d492..661d6fc76966 100644 --- a/security/selinux/ss/mls.h +++ b/security/selinux/ss/mls.h | |||
| @@ -13,7 +13,7 @@ | |||
| 13 | /* | 13 | /* |
| 14 | * Updated: Hewlett-Packard <paul.moore@hp.com> | 14 | * Updated: Hewlett-Packard <paul.moore@hp.com> |
| 15 | * | 15 | * |
| 16 | * Added support to import/export the MLS label | 16 | * Added support to import/export the MLS label from NetLabel |
| 17 | * | 17 | * |
| 18 | * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 | 18 | * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 |
| 19 | */ | 19 | */ |
| @@ -69,19 +69,37 @@ int mls_compute_sid(struct context *scontext, | |||
| 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 bfe122764c98..bdb7070dd3dc 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c | |||
| @@ -17,9 +17,13 @@ | |||
| 17 | * | 17 | * |
| 18 | * Added support for NetLabel | 18 | * Added support for NetLabel |
| 19 | * | 19 | * |
| 20 | * Updated: Chad Sellers <csellers@tresys.com> | ||
| 21 | * | ||
| 22 | * Added validation of kernel classes and permissions | ||
| 23 | * | ||
| 20 | * Copyright (C) 2006 Hewlett-Packard Development Company, L.P. | 24 | * Copyright (C) 2006 Hewlett-Packard Development Company, L.P. |
| 21 | * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc. | 25 | * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc. |
| 22 | * Copyright (C) 2003 - 2004 Tresys Technology, LLC | 26 | * Copyright (C) 2003 - 2004, 2006 Tresys Technology, LLC |
| 23 | * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com> | 27 | * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com> |
| 24 | * This program is free software; you can redistribute it and/or modify | 28 | * This program is free software; you can redistribute it and/or modify |
| 25 | * it under the terms of the GNU General Public License as published by | 29 | * it under the terms of the GNU General Public License as published by |
| @@ -29,6 +33,7 @@ | |||
| 29 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
| 30 | #include <linux/string.h> | 34 | #include <linux/string.h> |
| 31 | #include <linux/spinlock.h> | 35 | #include <linux/spinlock.h> |
| 36 | #include <linux/rcupdate.h> | ||
| 32 | #include <linux/errno.h> | 37 | #include <linux/errno.h> |
| 33 | #include <linux/in.h> | 38 | #include <linux/in.h> |
| 34 | #include <linux/sched.h> | 39 | #include <linux/sched.h> |
| @@ -49,10 +54,17 @@ | |||
| 49 | #include "mls.h" | 54 | #include "mls.h" |
| 50 | #include "objsec.h" | 55 | #include "objsec.h" |
| 51 | #include "selinux_netlabel.h" | 56 | #include "selinux_netlabel.h" |
| 57 | #include "xfrm.h" | ||
| 58 | #include "ebitmap.h" | ||
| 52 | 59 | ||
| 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) |
| @@ -2409,19 +2484,18 @@ static int selinux_netlbl_socket_setsid(struct socket *sock, u32 sid) | |||
| 2409 | 2484 | ||
| 2410 | secattr.domain = kstrdup(policydb.p_type_val_to_name[ctx->type - 1], | 2485 | secattr.domain = kstrdup(policydb.p_type_val_to_name[ctx->type - 1], |
| 2411 | GFP_ATOMIC); | 2486 | GFP_ATOMIC); |
| 2412 | mls_export_lvl(ctx, &secattr.mls_lvl, NULL); | 2487 | secattr.flags |= NETLBL_SECATTR_DOMAIN; |
| 2413 | secattr.mls_lvl_vld = 1; | 2488 | mls_export_netlbl_lvl(ctx, &secattr); |
| 2414 | rc = mls_export_cat(ctx, | 2489 | rc = mls_export_netlbl_cat(ctx, &secattr); |
| 2415 | &secattr.mls_cat, | ||
| 2416 | &secattr.mls_cat_len, | ||
| 2417 | NULL, | ||
| 2418 | NULL); | ||
| 2419 | if (rc != 0) | 2490 | if (rc != 0) |
| 2420 | goto netlbl_socket_setsid_return; | 2491 | goto netlbl_socket_setsid_return; |
| 2421 | 2492 | ||
| 2422 | rc = netlbl_socket_setattr(sock, &secattr); | 2493 | rc = netlbl_socket_setattr(sock, &secattr); |
| 2423 | if (rc == 0) | 2494 | if (rc == 0) { |
| 2495 | spin_lock(&sksec->nlbl_lock); | ||
| 2424 | sksec->nlbl_state = NLBL_LABELED; | 2496 | sksec->nlbl_state = NLBL_LABELED; |
| 2497 | spin_unlock(&sksec->nlbl_lock); | ||
| 2498 | } | ||
| 2425 | 2499 | ||
| 2426 | netlbl_socket_setsid_return: | 2500 | netlbl_socket_setsid_return: |
| 2427 | POLICY_RDUNLOCK; | 2501 | POLICY_RDUNLOCK; |
| @@ -2430,6 +2504,25 @@ netlbl_socket_setsid_return: | |||
| 2430 | } | 2504 | } |
| 2431 | 2505 | ||
| 2432 | /** | 2506 | /** |
| 2507 | * selinux_netlbl_sk_security_reset - Reset the NetLabel fields | ||
| 2508 | * @ssec: the sk_security_struct | ||
| 2509 | * @family: the socket family | ||
| 2510 | * | ||
| 2511 | * Description: | ||
| 2512 | * Called when the NetLabel state of a sk_security_struct needs to be reset. | ||
| 2513 | * The caller is responsibile for all the NetLabel sk_security_struct locking. | ||
| 2514 | * | ||
| 2515 | */ | ||
| 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 | /** | ||
| 2433 | * selinux_netlbl_sk_security_init - Setup the NetLabel fields | 2526 | * selinux_netlbl_sk_security_init - Setup the NetLabel fields |
| 2434 | * @ssec: the sk_security_struct | 2527 | * @ssec: the sk_security_struct |
| 2435 | * @family: the socket family | 2528 | * @family: the socket family |
| @@ -2442,14 +2535,13 @@ netlbl_socket_setsid_return: | |||
| 2442 | void selinux_netlbl_sk_security_init(struct sk_security_struct *ssec, | 2535 | void selinux_netlbl_sk_security_init(struct sk_security_struct *ssec, |
| 2443 | int family) | 2536 | int family) |
| 2444 | { | 2537 | { |
| 2445 | if (family == PF_INET) | 2538 | /* No locking needed, we are the only one who has access to ssec */ |
| 2446 | ssec->nlbl_state = NLBL_REQUIRE; | 2539 | selinux_netlbl_sk_security_reset(ssec, family); |
| 2447 | else | 2540 | spin_lock_init(&ssec->nlbl_lock); |
| 2448 | ssec->nlbl_state = NLBL_UNSET; | ||
| 2449 | } | 2541 | } |
| 2450 | 2542 | ||
| 2451 | /** | 2543 | /** |
| 2452 | * selinux_netlbl_sk_clone_security - Copy the NetLabel fields | 2544 | * selinux_netlbl_sk_security_clone - Copy the NetLabel fields |
| 2453 | * @ssec: the original sk_security_struct | 2545 | * @ssec: the original sk_security_struct |
| 2454 | * @newssec: the cloned sk_security_struct | 2546 | * @newssec: the cloned sk_security_struct |
| 2455 | * | 2547 | * |
| @@ -2458,41 +2550,41 @@ void selinux_netlbl_sk_security_init(struct sk_security_struct *ssec, | |||
| 2458 | * @newssec. | 2550 | * @newssec. |
| 2459 | * | 2551 | * |
| 2460 | */ | 2552 | */ |
| 2461 | void selinux_netlbl_sk_clone_security(struct sk_security_struct *ssec, | 2553 | void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec, |
| 2462 | struct sk_security_struct *newssec) | 2554 | struct sk_security_struct *newssec) |
| 2463 | { | 2555 | { |
| 2556 | /* We don't need to take newssec->nlbl_lock because we are the only | ||
| 2557 | * thread with access to newssec, but we do need to take the RCU read | ||
| 2558 | * lock as other threads could have access to ssec */ | ||
| 2559 | rcu_read_lock(); | ||
| 2560 | selinux_netlbl_sk_security_reset(newssec, ssec->sk->sk_family); | ||
| 2464 | newssec->sclass = ssec->sclass; | 2561 | newssec->sclass = ssec->sclass; |
| 2465 | if (ssec->nlbl_state != NLBL_UNSET) | 2562 | rcu_read_unlock(); |
| 2466 | newssec->nlbl_state = NLBL_REQUIRE; | ||
| 2467 | else | ||
| 2468 | newssec->nlbl_state = NLBL_UNSET; | ||
| 2469 | } | 2563 | } |
| 2470 | 2564 | ||
| 2471 | /** | 2565 | /** |
| 2472 | * selinux_netlbl_socket_post_create - Label a socket using NetLabel | 2566 | * selinux_netlbl_socket_post_create - Label a socket using NetLabel |
| 2473 | * @sock: the socket to label | 2567 | * @sock: the socket to label |
| 2474 | * @sock_family: the socket family | ||
| 2475 | * @sid: the SID to use | ||
| 2476 | * | 2568 | * |
| 2477 | * Description: | 2569 | * Description: |
| 2478 | * Attempt to label a socket using the NetLabel mechanism using the given | 2570 | * Attempt to label a socket using the NetLabel mechanism using the given |
| 2479 | * SID. Returns zero values on success, negative values on failure. | 2571 | * SID. Returns zero values on success, negative values on failure. |
| 2480 | * | 2572 | * |
| 2481 | */ | 2573 | */ |
| 2482 | int selinux_netlbl_socket_post_create(struct socket *sock, | 2574 | int selinux_netlbl_socket_post_create(struct socket *sock) |
| 2483 | int sock_family, | ||
| 2484 | u32 sid) | ||
| 2485 | { | 2575 | { |
| 2576 | int rc = 0; | ||
| 2486 | struct inode_security_struct *isec = SOCK_INODE(sock)->i_security; | 2577 | struct inode_security_struct *isec = SOCK_INODE(sock)->i_security; |
| 2487 | struct sk_security_struct *sksec = sock->sk->sk_security; | 2578 | struct sk_security_struct *sksec = sock->sk->sk_security; |
| 2488 | 2579 | ||
| 2489 | sksec->sclass = isec->sclass; | 2580 | sksec->sclass = isec->sclass; |
| 2490 | 2581 | ||
| 2491 | if (sock_family != PF_INET) | 2582 | rcu_read_lock(); |
| 2492 | return 0; | 2583 | if (sksec->nlbl_state == NLBL_REQUIRE) |
| 2584 | rc = selinux_netlbl_socket_setsid(sock, sksec->sid); | ||
| 2585 | rcu_read_unlock(); | ||
| 2493 | 2586 | ||
| 2494 | sksec->nlbl_state = NLBL_REQUIRE; | 2587 | return rc; |
| 2495 | return selinux_netlbl_socket_setsid(sock, sid); | ||
| 2496 | } | 2588 | } |
| 2497 | 2589 | ||
| 2498 | /** | 2590 | /** |
| @@ -2514,11 +2606,16 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock) | |||
| 2514 | 2606 | ||
| 2515 | sksec->sclass = isec->sclass; | 2607 | sksec->sclass = isec->sclass; |
| 2516 | 2608 | ||
| 2517 | if (sk->sk_family != PF_INET) | 2609 | rcu_read_lock(); |
| 2610 | |||
| 2611 | if (sksec->nlbl_state != NLBL_REQUIRE) { | ||
| 2612 | rcu_read_unlock(); | ||
| 2518 | return; | 2613 | return; |
| 2614 | } | ||
| 2519 | 2615 | ||
| 2520 | netlbl_secattr_init(&secattr); | 2616 | netlbl_secattr_init(&secattr); |
| 2521 | if (netlbl_sock_getattr(sk, &secattr) == 0 && | 2617 | if (netlbl_sock_getattr(sk, &secattr) == 0 && |
| 2618 | secattr.flags != NETLBL_SECATTR_NONE && | ||
| 2522 | selinux_netlbl_secattr_to_sid(NULL, | 2619 | selinux_netlbl_secattr_to_sid(NULL, |
| 2523 | &secattr, | 2620 | &secattr, |
| 2524 | SECINITSID_UNLABELED, | 2621 | SECINITSID_UNLABELED, |
| @@ -2526,35 +2623,12 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock) | |||
| 2526 | sksec->peer_sid = nlbl_peer_sid; | 2623 | sksec->peer_sid = nlbl_peer_sid; |
| 2527 | netlbl_secattr_destroy(&secattr); | 2624 | netlbl_secattr_destroy(&secattr); |
| 2528 | 2625 | ||
| 2529 | sksec->nlbl_state = NLBL_REQUIRE; | ||
| 2530 | |||
| 2531 | /* Try to set the NetLabel on the socket to save time later, if we fail | 2626 | /* Try to set the NetLabel on the socket to save time later, if we fail |
| 2532 | * here we will pick up the pieces in later calls to | 2627 | * here we will pick up the pieces in later calls to |
| 2533 | * selinux_netlbl_inode_permission(). */ | 2628 | * selinux_netlbl_inode_permission(). */ |
| 2534 | selinux_netlbl_socket_setsid(sock, sksec->sid); | 2629 | selinux_netlbl_socket_setsid(sock, sksec->sid); |
| 2535 | } | ||
| 2536 | |||
| 2537 | /** | ||
| 2538 | * selinux_netlbl_inet_conn_request - Handle a new connection request | ||
| 2539 | * @skb: the packet | ||
| 2540 | * @sock_sid: the SID of the parent socket | ||
| 2541 | * | ||
| 2542 | * Description: | ||
| 2543 | * If present, use the security attributes of the packet in @skb and the | ||
| 2544 | * parent sock's SID to arrive at a SID for the new child sock. Returns the | ||
| 2545 | * SID of the connection or SECSID_NULL on failure. | ||
| 2546 | * | ||
| 2547 | */ | ||
| 2548 | u32 selinux_netlbl_inet_conn_request(struct sk_buff *skb, u32 sock_sid) | ||
| 2549 | { | ||
| 2550 | int rc; | ||
| 2551 | u32 peer_sid; | ||
| 2552 | |||
| 2553 | rc = selinux_netlbl_skbuff_getsid(skb, sock_sid, &peer_sid); | ||
| 2554 | if (rc != 0) | ||
| 2555 | return SECSID_NULL; | ||
| 2556 | 2630 | ||
| 2557 | return peer_sid; | 2631 | rcu_read_unlock(); |
| 2558 | } | 2632 | } |
| 2559 | 2633 | ||
| 2560 | /** | 2634 | /** |
| @@ -2572,25 +2646,24 @@ u32 selinux_netlbl_inet_conn_request(struct sk_buff *skb, u32 sock_sid) | |||
| 2572 | int selinux_netlbl_inode_permission(struct inode *inode, int mask) | 2646 | int selinux_netlbl_inode_permission(struct inode *inode, int mask) |
| 2573 | { | 2647 | { |
| 2574 | int rc; | 2648 | int rc; |
| 2575 | struct inode_security_struct *isec; | ||
| 2576 | struct sk_security_struct *sksec; | 2649 | struct sk_security_struct *sksec; |
| 2577 | struct socket *sock; | 2650 | struct socket *sock; |
| 2578 | 2651 | ||
| 2579 | if (!S_ISSOCK(inode->i_mode)) | 2652 | if (!S_ISSOCK(inode->i_mode) || |
| 2653 | ((mask & (MAY_WRITE | MAY_APPEND)) == 0)) | ||
| 2580 | return 0; | 2654 | return 0; |
| 2581 | |||
| 2582 | sock = SOCKET_I(inode); | 2655 | sock = SOCKET_I(inode); |
| 2583 | isec = inode->i_security; | ||
| 2584 | sksec = sock->sk->sk_security; | 2656 | sksec = sock->sk->sk_security; |
| 2585 | mutex_lock(&isec->lock); | 2657 | |
| 2586 | if (unlikely(sksec->nlbl_state == NLBL_REQUIRE && | 2658 | rcu_read_lock(); |
| 2587 | (mask & (MAY_WRITE | MAY_APPEND)))) { | 2659 | if (sksec->nlbl_state != NLBL_REQUIRE) { |
| 2588 | lock_sock(sock->sk); | 2660 | rcu_read_unlock(); |
| 2589 | rc = selinux_netlbl_socket_setsid(sock, sksec->sid); | 2661 | return 0; |
| 2590 | release_sock(sock->sk); | 2662 | } |
| 2591 | } else | 2663 | lock_sock(sock->sk); |
| 2592 | rc = 0; | 2664 | rc = selinux_netlbl_socket_setsid(sock, sksec->sid); |
| 2593 | mutex_unlock(&isec->lock); | 2665 | release_sock(sock->sk); |
| 2666 | rcu_read_unlock(); | ||
| 2594 | 2667 | ||
| 2595 | return rc; | 2668 | return rc; |
| 2596 | } | 2669 | } |
| @@ -2648,42 +2721,6 @@ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, | |||
| 2648 | } | 2721 | } |
| 2649 | 2722 | ||
| 2650 | /** | 2723 | /** |
| 2651 | * selinux_netlbl_socket_getpeersec_stream - Return the connected peer's SID | ||
| 2652 | * @sock: the socket | ||
| 2653 | * | ||
| 2654 | * Description: | ||
| 2655 | * Examine @sock to find the connected peer's SID. Returns the SID on success | ||
| 2656 | * or SECSID_NULL on error. | ||
| 2657 | * | ||
| 2658 | */ | ||
| 2659 | u32 selinux_netlbl_socket_getpeersec_stream(struct socket *sock) | ||
| 2660 | { | ||
| 2661 | struct sk_security_struct *sksec = sock->sk->sk_security; | ||
| 2662 | return sksec->peer_sid; | ||
| 2663 | } | ||
| 2664 | |||
| 2665 | /** | ||
| 2666 | * selinux_netlbl_socket_getpeersec_dgram - Return the SID of a NetLabel packet | ||
| 2667 | * @skb: the packet | ||
| 2668 | * | ||
| 2669 | * Description: | ||
| 2670 | * Examine @skb to find the SID assigned to it by NetLabel. Returns the SID on | ||
| 2671 | * success, SECSID_NULL on error. | ||
| 2672 | * | ||
| 2673 | */ | ||
| 2674 | u32 selinux_netlbl_socket_getpeersec_dgram(struct sk_buff *skb) | ||
| 2675 | { | ||
| 2676 | int peer_sid; | ||
| 2677 | |||
| 2678 | if (selinux_netlbl_skbuff_getsid(skb, | ||
| 2679 | SECINITSID_UNLABELED, | ||
| 2680 | &peer_sid) != 0) | ||
| 2681 | return SECSID_NULL; | ||
| 2682 | |||
| 2683 | return peer_sid; | ||
| 2684 | } | ||
| 2685 | |||
| 2686 | /** | ||
| 2687 | * selinux_netlbl_socket_setsockopt - Do not allow users to remove a NetLabel | 2724 | * selinux_netlbl_socket_setsockopt - Do not allow users to remove a NetLabel |
| 2688 | * @sock: the socket | 2725 | * @sock: the socket |
| 2689 | * @level: the socket level or protocol | 2726 | * @level: the socket level or protocol |
| @@ -2701,21 +2738,19 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock, | |||
| 2701 | int optname) | 2738 | int optname) |
| 2702 | { | 2739 | { |
| 2703 | int rc = 0; | 2740 | int rc = 0; |
| 2704 | struct inode *inode = SOCK_INODE(sock); | ||
| 2705 | struct sk_security_struct *sksec = sock->sk->sk_security; | 2741 | struct sk_security_struct *sksec = sock->sk->sk_security; |
| 2706 | struct inode_security_struct *isec = inode->i_security; | ||
| 2707 | struct netlbl_lsm_secattr secattr; | 2742 | struct netlbl_lsm_secattr secattr; |
| 2708 | 2743 | ||
| 2709 | mutex_lock(&isec->lock); | 2744 | rcu_read_lock(); |
| 2710 | if (level == IPPROTO_IP && optname == IP_OPTIONS && | 2745 | if (level == IPPROTO_IP && optname == IP_OPTIONS && |
| 2711 | sksec->nlbl_state == NLBL_LABELED) { | 2746 | sksec->nlbl_state == NLBL_LABELED) { |
| 2712 | netlbl_secattr_init(&secattr); | 2747 | netlbl_secattr_init(&secattr); |
| 2713 | rc = netlbl_socket_getattr(sock, &secattr); | 2748 | rc = netlbl_socket_getattr(sock, &secattr); |
| 2714 | if (rc == 0 && (secattr.cache || secattr.mls_lvl_vld)) | 2749 | if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE) |
| 2715 | rc = -EACCES; | 2750 | rc = -EACCES; |
| 2716 | netlbl_secattr_destroy(&secattr); | 2751 | netlbl_secattr_destroy(&secattr); |
| 2717 | } | 2752 | } |
| 2718 | mutex_unlock(&isec->lock); | 2753 | rcu_read_unlock(); |
| 2719 | 2754 | ||
| 2720 | return rc; | 2755 | return rc; |
| 2721 | } | 2756 | } |
diff --git a/security/selinux/ss/symtab.c b/security/selinux/ss/symtab.c index 24a10d36d3b6..837658a98a54 100644 --- a/security/selinux/ss/symtab.c +++ b/security/selinux/ss/symtab.c | |||
| @@ -9,9 +9,9 @@ | |||
| 9 | #include <linux/errno.h> | 9 | #include <linux/errno.h> |
| 10 | #include "symtab.h" | 10 | #include "symtab.h" |
| 11 | 11 | ||
| 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: |
