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 | ||
