diff options
-rw-r--r-- | include/linux/security.h | 12 | ||||
-rw-r--r-- | include/net/sock.h | 13 | ||||
-rw-r--r-- | net/core/sock.c | 2 | ||||
-rw-r--r-- | security/dummy.c | 5 | ||||
-rw-r--r-- | security/selinux/hooks.c | 38 | ||||
-rw-r--r-- | security/selinux/include/objsec.h | 1 |
6 files changed, 53 insertions, 18 deletions
diff --git a/include/linux/security.h b/include/linux/security.h index 6bc2aad494ff..4d7fb59996b0 100644 --- a/include/linux/security.h +++ b/include/linux/security.h | |||
@@ -812,6 +812,8 @@ struct swap_info_struct; | |||
812 | * which is used to copy security attributes between local stream sockets. | 812 | * which is used to copy security attributes between local stream sockets. |
813 | * @sk_free_security: | 813 | * @sk_free_security: |
814 | * Deallocate security structure. | 814 | * Deallocate security structure. |
815 | * @sk_clone_security: | ||
816 | * Clone/copy security structure. | ||
815 | * @sk_getsid: | 817 | * @sk_getsid: |
816 | * Retrieve the LSM-specific sid for the sock to enable caching of network | 818 | * Retrieve the LSM-specific sid for the sock to enable caching of network |
817 | * authorizations. | 819 | * authorizations. |
@@ -1332,6 +1334,7 @@ struct security_operations { | |||
1332 | int (*socket_getpeersec_dgram) (struct socket *sock, struct sk_buff *skb, u32 *secid); | 1334 | int (*socket_getpeersec_dgram) (struct socket *sock, struct sk_buff *skb, u32 *secid); |
1333 | int (*sk_alloc_security) (struct sock *sk, int family, gfp_t priority); | 1335 | int (*sk_alloc_security) (struct sock *sk, int family, gfp_t priority); |
1334 | void (*sk_free_security) (struct sock *sk); | 1336 | void (*sk_free_security) (struct sock *sk); |
1337 | void (*sk_clone_security) (const struct sock *sk, struct sock *newsk); | ||
1335 | unsigned int (*sk_getsid) (struct sock *sk, struct flowi *fl, u8 dir); | 1338 | unsigned int (*sk_getsid) (struct sock *sk, struct flowi *fl, u8 dir); |
1336 | #endif /* CONFIG_SECURITY_NETWORK */ | 1339 | #endif /* CONFIG_SECURITY_NETWORK */ |
1337 | 1340 | ||
@@ -2885,6 +2888,11 @@ static inline void security_sk_free(struct sock *sk) | |||
2885 | return security_ops->sk_free_security(sk); | 2888 | return security_ops->sk_free_security(sk); |
2886 | } | 2889 | } |
2887 | 2890 | ||
2891 | static inline void security_sk_clone(const struct sock *sk, struct sock *newsk) | ||
2892 | { | ||
2893 | return security_ops->sk_clone_security(sk, newsk); | ||
2894 | } | ||
2895 | |||
2888 | static inline unsigned int security_sk_sid(struct sock *sk, struct flowi *fl, u8 dir) | 2896 | static inline unsigned int security_sk_sid(struct sock *sk, struct flowi *fl, u8 dir) |
2889 | { | 2897 | { |
2890 | return security_ops->sk_getsid(sk, fl, dir); | 2898 | return security_ops->sk_getsid(sk, fl, dir); |
@@ -3011,6 +3019,10 @@ static inline void security_sk_free(struct sock *sk) | |||
3011 | { | 3019 | { |
3012 | } | 3020 | } |
3013 | 3021 | ||
3022 | static inline void security_sk_clone(const struct sock *sk, struct sock *newsk) | ||
3023 | { | ||
3024 | } | ||
3025 | |||
3014 | static inline unsigned int security_sk_sid(struct sock *sk, struct flowi *fl, u8 dir) | 3026 | static inline unsigned int security_sk_sid(struct sock *sk, struct flowi *fl, u8 dir) |
3015 | { | 3027 | { |
3016 | return 0; | 3028 | return 0; |
diff --git a/include/net/sock.h b/include/net/sock.h index 324b3ea233d6..91cdceb3c028 100644 --- a/include/net/sock.h +++ b/include/net/sock.h | |||
@@ -972,6 +972,19 @@ static inline void sock_graft(struct sock *sk, struct socket *parent) | |||
972 | write_unlock_bh(&sk->sk_callback_lock); | 972 | write_unlock_bh(&sk->sk_callback_lock); |
973 | } | 973 | } |
974 | 974 | ||
975 | static inline void sock_copy(struct sock *nsk, const struct sock *osk) | ||
976 | { | ||
977 | #ifdef CONFIG_SECURITY_NETWORK | ||
978 | void *sptr = nsk->sk_security; | ||
979 | #endif | ||
980 | |||
981 | memcpy(nsk, osk, osk->sk_prot->obj_size); | ||
982 | #ifdef CONFIG_SECURITY_NETWORK | ||
983 | nsk->sk_security = sptr; | ||
984 | security_sk_clone(osk, nsk); | ||
985 | #endif | ||
986 | } | ||
987 | |||
975 | extern int sock_i_uid(struct sock *sk); | 988 | extern int sock_i_uid(struct sock *sk); |
976 | extern unsigned long sock_i_ino(struct sock *sk); | 989 | extern unsigned long sock_i_ino(struct sock *sk); |
977 | 990 | ||
diff --git a/net/core/sock.c b/net/core/sock.c index 51fcfbc041a7..b67d868649cd 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -911,7 +911,7 @@ struct sock *sk_clone(const struct sock *sk, const gfp_t priority) | |||
911 | if (newsk != NULL) { | 911 | if (newsk != NULL) { |
912 | struct sk_filter *filter; | 912 | struct sk_filter *filter; |
913 | 913 | ||
914 | memcpy(newsk, sk, sk->sk_prot->obj_size); | 914 | sock_copy(newsk, sk); |
915 | 915 | ||
916 | /* SANITY */ | 916 | /* SANITY */ |
917 | sk_node_init(&newsk->sk_node); | 917 | sk_node_init(&newsk->sk_node); |
diff --git a/security/dummy.c b/security/dummy.c index 58c6d399c844..bd3bc5faa9a8 100644 --- a/security/dummy.c +++ b/security/dummy.c | |||
@@ -805,6 +805,10 @@ static inline void dummy_sk_free_security (struct sock *sk) | |||
805 | { | 805 | { |
806 | } | 806 | } |
807 | 807 | ||
808 | static inline void dummy_sk_clone_security (const struct sock *sk, struct sock *newsk) | ||
809 | { | ||
810 | } | ||
811 | |||
808 | static unsigned int dummy_sk_getsid(struct sock *sk, struct flowi *fl, u8 dir) | 812 | static unsigned int dummy_sk_getsid(struct sock *sk, struct flowi *fl, u8 dir) |
809 | { | 813 | { |
810 | return 0; | 814 | return 0; |
@@ -1060,6 +1064,7 @@ void security_fixup_ops (struct security_operations *ops) | |||
1060 | set_to_dummy_if_null(ops, socket_getpeersec_dgram); | 1064 | set_to_dummy_if_null(ops, socket_getpeersec_dgram); |
1061 | set_to_dummy_if_null(ops, sk_alloc_security); | 1065 | set_to_dummy_if_null(ops, sk_alloc_security); |
1062 | set_to_dummy_if_null(ops, sk_free_security); | 1066 | set_to_dummy_if_null(ops, sk_free_security); |
1067 | set_to_dummy_if_null(ops, sk_clone_security); | ||
1063 | set_to_dummy_if_null(ops, sk_getsid); | 1068 | set_to_dummy_if_null(ops, sk_getsid); |
1064 | #endif /* CONFIG_SECURITY_NETWORK */ | 1069 | #endif /* CONFIG_SECURITY_NETWORK */ |
1065 | #ifdef CONFIG_SECURITY_NETWORK_XFRM | 1070 | #ifdef CONFIG_SECURITY_NETWORK_XFRM |
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 5d1b8c733199..d67abf77584a 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -269,15 +269,13 @@ static int sk_alloc_security(struct sock *sk, int family, gfp_t priority) | |||
269 | { | 269 | { |
270 | struct sk_security_struct *ssec; | 270 | struct sk_security_struct *ssec; |
271 | 271 | ||
272 | if (family != PF_UNIX) | ||
273 | return 0; | ||
274 | |||
275 | ssec = kzalloc(sizeof(*ssec), priority); | 272 | ssec = kzalloc(sizeof(*ssec), priority); |
276 | if (!ssec) | 273 | if (!ssec) |
277 | return -ENOMEM; | 274 | return -ENOMEM; |
278 | 275 | ||
279 | ssec->sk = sk; | 276 | ssec->sk = sk; |
280 | ssec->peer_sid = SECINITSID_UNLABELED; | 277 | ssec->peer_sid = SECINITSID_UNLABELED; |
278 | ssec->sid = SECINITSID_UNLABELED; | ||
281 | sk->sk_security = ssec; | 279 | sk->sk_security = ssec; |
282 | 280 | ||
283 | return 0; | 281 | return 0; |
@@ -287,9 +285,6 @@ static void sk_free_security(struct sock *sk) | |||
287 | { | 285 | { |
288 | struct sk_security_struct *ssec = sk->sk_security; | 286 | struct sk_security_struct *ssec = sk->sk_security; |
289 | 287 | ||
290 | if (sk->sk_family != PF_UNIX) | ||
291 | return; | ||
292 | |||
293 | sk->sk_security = NULL; | 288 | sk->sk_security = NULL; |
294 | kfree(ssec); | 289 | kfree(ssec); |
295 | } | 290 | } |
@@ -3068,6 +3063,7 @@ static void selinux_socket_post_create(struct socket *sock, int family, | |||
3068 | { | 3063 | { |
3069 | struct inode_security_struct *isec; | 3064 | struct inode_security_struct *isec; |
3070 | struct task_security_struct *tsec; | 3065 | struct task_security_struct *tsec; |
3066 | struct sk_security_struct *sksec; | ||
3071 | u32 newsid; | 3067 | u32 newsid; |
3072 | 3068 | ||
3073 | isec = SOCK_INODE(sock)->i_security; | 3069 | isec = SOCK_INODE(sock)->i_security; |
@@ -3078,6 +3074,11 @@ static void selinux_socket_post_create(struct socket *sock, int family, | |||
3078 | isec->sid = kern ? SECINITSID_KERNEL : newsid; | 3074 | isec->sid = kern ? SECINITSID_KERNEL : newsid; |
3079 | isec->initialized = 1; | 3075 | isec->initialized = 1; |
3080 | 3076 | ||
3077 | if (sock->sk) { | ||
3078 | sksec = sock->sk->sk_security; | ||
3079 | sksec->sid = isec->sid; | ||
3080 | } | ||
3081 | |||
3081 | return; | 3082 | return; |
3082 | } | 3083 | } |
3083 | 3084 | ||
@@ -3551,22 +3552,24 @@ static void selinux_sk_free_security(struct sock *sk) | |||
3551 | sk_free_security(sk); | 3552 | sk_free_security(sk); |
3552 | } | 3553 | } |
3553 | 3554 | ||
3554 | static unsigned int selinux_sk_getsid_security(struct sock *sk, struct flowi *fl, u8 dir) | 3555 | static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk) |
3555 | { | 3556 | { |
3556 | struct inode_security_struct *isec; | 3557 | struct sk_security_struct *ssec = sk->sk_security; |
3557 | u32 sock_sid = SECINITSID_ANY_SOCKET; | 3558 | struct sk_security_struct *newssec = newsk->sk_security; |
3558 | 3559 | ||
3560 | newssec->sid = ssec->sid; | ||
3561 | newssec->peer_sid = ssec->peer_sid; | ||
3562 | } | ||
3563 | |||
3564 | static unsigned int selinux_sk_getsid_security(struct sock *sk, struct flowi *fl, u8 dir) | ||
3565 | { | ||
3559 | if (!sk) | 3566 | if (!sk) |
3560 | return selinux_no_sk_sid(fl); | 3567 | return selinux_no_sk_sid(fl); |
3568 | else { | ||
3569 | struct sk_security_struct *sksec = sk->sk_security; | ||
3561 | 3570 | ||
3562 | read_lock_bh(&sk->sk_callback_lock); | 3571 | return sksec->sid; |
3563 | isec = get_sock_isec(sk); | 3572 | } |
3564 | |||
3565 | if (isec) | ||
3566 | sock_sid = isec->sid; | ||
3567 | |||
3568 | read_unlock_bh(&sk->sk_callback_lock); | ||
3569 | return sock_sid; | ||
3570 | } | 3573 | } |
3571 | 3574 | ||
3572 | static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb) | 3575 | static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb) |
@@ -4618,6 +4621,7 @@ static struct security_operations selinux_ops = { | |||
4618 | .socket_getpeersec_dgram = selinux_socket_getpeersec_dgram, | 4621 | .socket_getpeersec_dgram = selinux_socket_getpeersec_dgram, |
4619 | .sk_alloc_security = selinux_sk_alloc_security, | 4622 | .sk_alloc_security = selinux_sk_alloc_security, |
4620 | .sk_free_security = selinux_sk_free_security, | 4623 | .sk_free_security = selinux_sk_free_security, |
4624 | .sk_clone_security = selinux_sk_clone_security, | ||
4621 | .sk_getsid = selinux_sk_getsid_security, | 4625 | .sk_getsid = selinux_sk_getsid_security, |
4622 | 4626 | ||
4623 | #ifdef CONFIG_SECURITY_NETWORK_XFRM | 4627 | #ifdef CONFIG_SECURITY_NETWORK_XFRM |
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h index 940178865fc7..79b9e0af19a0 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h | |||
@@ -99,6 +99,7 @@ struct netif_security_struct { | |||
99 | 99 | ||
100 | struct sk_security_struct { | 100 | struct sk_security_struct { |
101 | struct sock *sk; /* back pointer to sk object */ | 101 | struct sock *sk; /* back pointer to sk object */ |
102 | u32 sid; /* SID of this object */ | ||
102 | u32 peer_sid; /* SID of peer */ | 103 | u32 peer_sid; /* SID of peer */ |
103 | }; | 104 | }; |
104 | 105 | ||