aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVenkat Yekkirala <vyekkirala@TrustedCS.com>2006-08-05 02:08:56 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-09-22 17:53:22 -0400
commit892c141e62982272b9c738b5520ad0e5e1ad7b42 (patch)
treec8e0c9b3e55106d2cb085a5047b9d02dbbb28653
parent08554d6b33e60aa8ee40bbef94505941c0eefef2 (diff)
[MLSXFRM]: Add security sid to sock
This adds security for IP sockets at the sock level. Security at the sock level is needed to enforce the SELinux security policy for security associations even when a sock is orphaned (such as in the TCP LAST_ACK state). This will also be used to enforce SELinux controls over data arriving at or leaving a child socket while it's still waiting to be accepted. Signed-off-by: Venkat Yekkirala <vyekkirala@TrustedCS.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-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