aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/security.h12
-rw-r--r--include/net/sock.h13
-rw-r--r--net/core/sock.c2
-rw-r--r--security/dummy.c5
-rw-r--r--security/selinux/hooks.c38
-rw-r--r--security/selinux/include/objsec.h1
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
2891static inline void security_sk_clone(const struct sock *sk, struct sock *newsk)
2892{
2893 return security_ops->sk_clone_security(sk, newsk);
2894}
2895
2888static inline unsigned int security_sk_sid(struct sock *sk, struct flowi *fl, u8 dir) 2896static 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
3022static inline void security_sk_clone(const struct sock *sk, struct sock *newsk)
3023{
3024}
3025
3014static inline unsigned int security_sk_sid(struct sock *sk, struct flowi *fl, u8 dir) 3026static 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
975static 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
975extern int sock_i_uid(struct sock *sk); 988extern int sock_i_uid(struct sock *sk);
976extern unsigned long sock_i_ino(struct sock *sk); 989extern 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
808static inline void dummy_sk_clone_security (const struct sock *sk, struct sock *newsk)
809{
810}
811
808static unsigned int dummy_sk_getsid(struct sock *sk, struct flowi *fl, u8 dir) 812static 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
3554static unsigned int selinux_sk_getsid_security(struct sock *sk, struct flowi *fl, u8 dir) 3555static 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
3564static 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
3572static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb) 3575static 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
100struct sk_security_struct { 100struct 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