aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVenkat Yekkirala <vyekkirala@TrustedCS.com>2006-07-25 02:32:50 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-09-22 17:53:29 -0400
commit4237c75c0a35535d7f9f2bfeeb4b4df1e068a0bf (patch)
tree02adcb6fe6c346a8b99cf161ba5233ed1e572727
parentcb969f072b6d67770b559617f14e767f47e77ece (diff)
[MLSXFRM]: Auto-labeling of child sockets
This automatically labels the TCP, Unix stream, and dccp child sockets as well as openreqs to be at the same MLS level as the peer. This will result in the selection of appropriately labeled IPSec Security Associations. This also uses the sock's sid (as opposed to the isec sid) in SELinux enforcement of secmark in rcv_skb and postroute_last hooks. Signed-off-by: Venkat Yekkirala <vyekkirala@TrustedCS.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/security.h55
-rw-r--r--include/net/request_sock.h1
-rw-r--r--include/net/sock.h1
-rw-r--r--net/dccp/ipv4.c3
-rw-r--r--net/dccp/ipv6.c7
-rw-r--r--net/ipv4/inet_connection_sock.c4
-rw-r--r--net/ipv4/syncookies.c6
-rw-r--r--net/ipv4/tcp_ipv4.c3
-rw-r--r--net/ipv6/tcp_ipv6.c6
-rw-r--r--security/dummy.c24
-rw-r--r--security/selinux/hooks.c137
-rw-r--r--security/selinux/xfrm.c1
12 files changed, 197 insertions, 51 deletions
diff --git a/include/linux/security.h b/include/linux/security.h
index 8e3dc6c51a6d..bb4c80fdfe7a 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -90,6 +90,7 @@ extern int cap_netlink_recv(struct sk_buff *skb, int cap);
90struct nfsctl_arg; 90struct nfsctl_arg;
91struct sched_param; 91struct sched_param;
92struct swap_info_struct; 92struct swap_info_struct;
93struct request_sock;
93 94
94/* bprm_apply_creds unsafe reasons */ 95/* bprm_apply_creds unsafe reasons */
95#define LSM_UNSAFE_SHARE 1 96#define LSM_UNSAFE_SHARE 1
@@ -819,6 +820,14 @@ struct swap_info_struct;
819 * @sk_getsecid: 820 * @sk_getsecid:
820 * Retrieve the LSM-specific secid for the sock to enable caching of network 821 * Retrieve the LSM-specific secid for the sock to enable caching of network
821 * authorizations. 822 * authorizations.
823 * @sock_graft:
824 * Sets the socket's isec sid to the sock's sid.
825 * @inet_conn_request:
826 * Sets the openreq's sid to socket's sid with MLS portion taken from peer sid.
827 * @inet_csk_clone:
828 * Sets the new child socket's sid to the openreq sid.
829 * @req_classify_flow:
830 * Sets the flow's sid to the openreq sid.
822 * 831 *
823 * Security hooks for XFRM operations. 832 * Security hooks for XFRM operations.
824 * 833 *
@@ -1358,6 +1367,11 @@ struct security_operations {
1358 void (*sk_free_security) (struct sock *sk); 1367 void (*sk_free_security) (struct sock *sk);
1359 void (*sk_clone_security) (const struct sock *sk, struct sock *newsk); 1368 void (*sk_clone_security) (const struct sock *sk, struct sock *newsk);
1360 void (*sk_getsecid) (struct sock *sk, u32 *secid); 1369 void (*sk_getsecid) (struct sock *sk, u32 *secid);
1370 void (*sock_graft)(struct sock* sk, struct socket *parent);
1371 int (*inet_conn_request)(struct sock *sk, struct sk_buff *skb,
1372 struct request_sock *req);
1373 void (*inet_csk_clone)(struct sock *newsk, const struct request_sock *req);
1374 void (*req_classify_flow)(const struct request_sock *req, struct flowi *fl);
1361#endif /* CONFIG_SECURITY_NETWORK */ 1375#endif /* CONFIG_SECURITY_NETWORK */
1362 1376
1363#ifdef CONFIG_SECURITY_NETWORK_XFRM 1377#ifdef CONFIG_SECURITY_NETWORK_XFRM
@@ -2926,6 +2940,28 @@ static inline void security_sk_classify_flow(struct sock *sk, struct flowi *fl)
2926{ 2940{
2927 security_ops->sk_getsecid(sk, &fl->secid); 2941 security_ops->sk_getsecid(sk, &fl->secid);
2928} 2942}
2943
2944static inline void security_req_classify_flow(const struct request_sock *req, struct flowi *fl)
2945{
2946 security_ops->req_classify_flow(req, fl);
2947}
2948
2949static inline void security_sock_graft(struct sock* sk, struct socket *parent)
2950{
2951 security_ops->sock_graft(sk, parent);
2952}
2953
2954static inline int security_inet_conn_request(struct sock *sk,
2955 struct sk_buff *skb, struct request_sock *req)
2956{
2957 return security_ops->inet_conn_request(sk, skb, req);
2958}
2959
2960static inline void security_inet_csk_clone(struct sock *newsk,
2961 const struct request_sock *req)
2962{
2963 security_ops->inet_csk_clone(newsk, req);
2964}
2929#else /* CONFIG_SECURITY_NETWORK */ 2965#else /* CONFIG_SECURITY_NETWORK */
2930static inline int security_unix_stream_connect(struct socket * sock, 2966static inline int security_unix_stream_connect(struct socket * sock,
2931 struct socket * other, 2967 struct socket * other,
@@ -3055,6 +3091,25 @@ static inline void security_sk_clone(const struct sock *sk, struct sock *newsk)
3055static inline void security_sk_classify_flow(struct sock *sk, struct flowi *fl) 3091static inline void security_sk_classify_flow(struct sock *sk, struct flowi *fl)
3056{ 3092{
3057} 3093}
3094
3095static inline void security_req_classify_flow(const struct request_sock *req, struct flowi *fl)
3096{
3097}
3098
3099static inline void security_sock_graft(struct sock* sk, struct socket *parent)
3100{
3101}
3102
3103static inline int security_inet_conn_request(struct sock *sk,
3104 struct sk_buff *skb, struct request_sock *req)
3105{
3106 return 0;
3107}
3108
3109static inline void security_inet_csk_clone(struct sock *newsk,
3110 const struct request_sock *req)
3111{
3112}
3058#endif /* CONFIG_SECURITY_NETWORK */ 3113#endif /* CONFIG_SECURITY_NETWORK */
3059 3114
3060#ifdef CONFIG_SECURITY_NETWORK_XFRM 3115#ifdef CONFIG_SECURITY_NETWORK_XFRM
diff --git a/include/net/request_sock.h b/include/net/request_sock.h
index c5d7f920c352..8e165ca16bd8 100644
--- a/include/net/request_sock.h
+++ b/include/net/request_sock.h
@@ -53,6 +53,7 @@ struct request_sock {
53 unsigned long expires; 53 unsigned long expires;
54 struct request_sock_ops *rsk_ops; 54 struct request_sock_ops *rsk_ops;
55 struct sock *sk; 55 struct sock *sk;
56 u32 secid;
56}; 57};
57 58
58static inline struct request_sock *reqsk_alloc(struct request_sock_ops *ops) 59static inline struct request_sock *reqsk_alloc(struct request_sock_ops *ops)
diff --git a/include/net/sock.h b/include/net/sock.h
index 91cdceb3c028..337ebec84c70 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -969,6 +969,7 @@ static inline void sock_graft(struct sock *sk, struct socket *parent)
969 sk->sk_sleep = &parent->wait; 969 sk->sk_sleep = &parent->wait;
970 parent->sk = sk; 970 parent->sk = sk;
971 sk->sk_socket = parent; 971 sk->sk_socket = parent;
972 security_sock_graft(sk, parent);
972 write_unlock_bh(&sk->sk_callback_lock); 973 write_unlock_bh(&sk->sk_callback_lock);
973} 974}
974 975
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index 386498053b1c..171d363876ee 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -501,6 +501,9 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
501 501
502 dccp_openreq_init(req, &dp, skb); 502 dccp_openreq_init(req, &dp, skb);
503 503
504 if (security_inet_conn_request(sk, skb, req))
505 goto drop_and_free;
506
504 ireq = inet_rsk(req); 507 ireq = inet_rsk(req);
505 ireq->loc_addr = daddr; 508 ireq->loc_addr = daddr;
506 ireq->rmt_addr = saddr; 509 ireq->rmt_addr = saddr;
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
index 53d255c01431..231bc7c7e749 100644
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -424,7 +424,7 @@ static int dccp_v6_send_response(struct sock *sk, struct request_sock *req,
424 fl.oif = ireq6->iif; 424 fl.oif = ireq6->iif;
425 fl.fl_ip_dport = inet_rsk(req)->rmt_port; 425 fl.fl_ip_dport = inet_rsk(req)->rmt_port;
426 fl.fl_ip_sport = inet_sk(sk)->sport; 426 fl.fl_ip_sport = inet_sk(sk)->sport;
427 security_sk_classify_flow(sk, &fl); 427 security_req_classify_flow(req, &fl);
428 428
429 if (dst == NULL) { 429 if (dst == NULL) {
430 opt = np->opt; 430 opt = np->opt;
@@ -626,7 +626,7 @@ static void dccp_v6_reqsk_send_ack(struct sk_buff *rxskb,
626 fl.oif = inet6_iif(rxskb); 626 fl.oif = inet6_iif(rxskb);
627 fl.fl_ip_dport = dh->dccph_dport; 627 fl.fl_ip_dport = dh->dccph_dport;
628 fl.fl_ip_sport = dh->dccph_sport; 628 fl.fl_ip_sport = dh->dccph_sport;
629 security_skb_classify_flow(rxskb, &fl); 629 security_req_classify_flow(req, &fl);
630 630
631 if (!ip6_dst_lookup(NULL, &skb->dst, &fl)) { 631 if (!ip6_dst_lookup(NULL, &skb->dst, &fl)) {
632 if (xfrm_lookup(&skb->dst, &fl, NULL, 0) >= 0) { 632 if (xfrm_lookup(&skb->dst, &fl, NULL, 0) >= 0) {
@@ -709,6 +709,9 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
709 709
710 dccp_openreq_init(req, &dp, skb); 710 dccp_openreq_init(req, &dp, skb);
711 711
712 if (security_inet_conn_request(sk, skb, req))
713 goto drop_and_free;
714
712 ireq6 = inet6_rsk(req); 715 ireq6 = inet6_rsk(req);
713 ireq = inet_rsk(req); 716 ireq = inet_rsk(req);
714 ipv6_addr_copy(&ireq6->rmt_addr, &skb->nh.ipv6h->saddr); 717 ipv6_addr_copy(&ireq6->rmt_addr, &skb->nh.ipv6h->saddr);
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index 772b4eac78bc..07204391d083 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -327,7 +327,7 @@ struct dst_entry* inet_csk_route_req(struct sock *sk,
327 { .sport = inet_sk(sk)->sport, 327 { .sport = inet_sk(sk)->sport,
328 .dport = ireq->rmt_port } } }; 328 .dport = ireq->rmt_port } } };
329 329
330 security_sk_classify_flow(sk, &fl); 330 security_req_classify_flow(req, &fl);
331 if (ip_route_output_flow(&rt, &fl, sk, 0)) { 331 if (ip_route_output_flow(&rt, &fl, sk, 0)) {
332 IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES); 332 IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES);
333 return NULL; 333 return NULL;
@@ -510,6 +510,8 @@ struct sock *inet_csk_clone(struct sock *sk, const struct request_sock *req,
510 510
511 /* Deinitialize accept_queue to trap illegal accesses. */ 511 /* Deinitialize accept_queue to trap illegal accesses. */
512 memset(&newicsk->icsk_accept_queue, 0, sizeof(newicsk->icsk_accept_queue)); 512 memset(&newicsk->icsk_accept_queue, 0, sizeof(newicsk->icsk_accept_queue));
513
514 security_inet_csk_clone(newsk, req);
513 } 515 }
514 return newsk; 516 return newsk;
515} 517}
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
index 307dc3c0d635..661e0a4bca72 100644
--- a/net/ipv4/syncookies.c
+++ b/net/ipv4/syncookies.c
@@ -214,6 +214,10 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
214 if (!req) 214 if (!req)
215 goto out; 215 goto out;
216 216
217 if (security_inet_conn_request(sk, skb, req)) {
218 reqsk_free(req);
219 goto out;
220 }
217 ireq = inet_rsk(req); 221 ireq = inet_rsk(req);
218 treq = tcp_rsk(req); 222 treq = tcp_rsk(req);
219 treq->rcv_isn = htonl(skb->h.th->seq) - 1; 223 treq->rcv_isn = htonl(skb->h.th->seq) - 1;
@@ -259,7 +263,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
259 .uli_u = { .ports = 263 .uli_u = { .ports =
260 { .sport = skb->h.th->dest, 264 { .sport = skb->h.th->dest,
261 .dport = skb->h.th->source } } }; 265 .dport = skb->h.th->source } } };
262 security_sk_classify_flow(sk, &fl); 266 security_req_classify_flow(req, &fl);
263 if (ip_route_output_key(&rt, &fl)) { 267 if (ip_route_output_key(&rt, &fl)) {
264 reqsk_free(req); 268 reqsk_free(req);
265 goto out; 269 goto out;
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 4b04c3edd4a9..43f6740244f8 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -798,6 +798,9 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
798 798
799 tcp_openreq_init(req, &tmp_opt, skb); 799 tcp_openreq_init(req, &tmp_opt, skb);
800 800
801 if (security_inet_conn_request(sk, skb, req))
802 goto drop_and_free;
803
801 ireq = inet_rsk(req); 804 ireq = inet_rsk(req);
802 ireq->loc_addr = daddr; 805 ireq->loc_addr = daddr;
803 ireq->rmt_addr = saddr; 806 ireq->rmt_addr = saddr;
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 46922e57e311..302786a11cd6 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -470,7 +470,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req,
470 fl.oif = treq->iif; 470 fl.oif = treq->iif;
471 fl.fl_ip_dport = inet_rsk(req)->rmt_port; 471 fl.fl_ip_dport = inet_rsk(req)->rmt_port;
472 fl.fl_ip_sport = inet_sk(sk)->sport; 472 fl.fl_ip_sport = inet_sk(sk)->sport;
473 security_sk_classify_flow(sk, &fl); 473 security_req_classify_flow(req, &fl);
474 474
475 if (dst == NULL) { 475 if (dst == NULL) {
476 opt = np->opt; 476 opt = np->opt;
@@ -826,6 +826,8 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
826 826
827 tcp_rsk(req)->snt_isn = isn; 827 tcp_rsk(req)->snt_isn = isn;
828 828
829 security_inet_conn_request(sk, skb, req);
830
829 if (tcp_v6_send_synack(sk, req, NULL)) 831 if (tcp_v6_send_synack(sk, req, NULL))
830 goto drop; 832 goto drop;
831 833
@@ -929,7 +931,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
929 fl.oif = sk->sk_bound_dev_if; 931 fl.oif = sk->sk_bound_dev_if;
930 fl.fl_ip_dport = inet_rsk(req)->rmt_port; 932 fl.fl_ip_dport = inet_rsk(req)->rmt_port;
931 fl.fl_ip_sport = inet_sk(sk)->sport; 933 fl.fl_ip_sport = inet_sk(sk)->sport;
932 security_sk_classify_flow(sk, &fl); 934 security_req_classify_flow(req, &fl);
933 935
934 if (ip6_dst_lookup(sk, &dst, &fl)) 936 if (ip6_dst_lookup(sk, &dst, &fl))
935 goto out; 937 goto out;
diff --git a/security/dummy.c b/security/dummy.c
index 66cc06404930..1c45f8e4aad1 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -812,6 +812,26 @@ static inline void dummy_sk_clone_security (const struct sock *sk, struct sock *
812static inline void dummy_sk_getsecid(struct sock *sk, u32 *secid) 812static inline void dummy_sk_getsecid(struct sock *sk, u32 *secid)
813{ 813{
814} 814}
815
816static inline void dummy_sock_graft(struct sock* sk, struct socket *parent)
817{
818}
819
820static inline int dummy_inet_conn_request(struct sock *sk,
821 struct sk_buff *skb, struct request_sock *req)
822{
823 return 0;
824}
825
826static inline void dummy_inet_csk_clone(struct sock *newsk,
827 const struct request_sock *req)
828{
829}
830
831static inline void dummy_req_classify_flow(const struct request_sock *req,
832 struct flowi *fl)
833{
834}
815#endif /* CONFIG_SECURITY_NETWORK */ 835#endif /* CONFIG_SECURITY_NETWORK */
816 836
817#ifdef CONFIG_SECURITY_NETWORK_XFRM 837#ifdef CONFIG_SECURITY_NETWORK_XFRM
@@ -1084,6 +1104,10 @@ void security_fixup_ops (struct security_operations *ops)
1084 set_to_dummy_if_null(ops, sk_free_security); 1104 set_to_dummy_if_null(ops, sk_free_security);
1085 set_to_dummy_if_null(ops, sk_clone_security); 1105 set_to_dummy_if_null(ops, sk_clone_security);
1086 set_to_dummy_if_null(ops, sk_getsecid); 1106 set_to_dummy_if_null(ops, sk_getsecid);
1107 set_to_dummy_if_null(ops, sock_graft);
1108 set_to_dummy_if_null(ops, inet_conn_request);
1109 set_to_dummy_if_null(ops, inet_csk_clone);
1110 set_to_dummy_if_null(ops, req_classify_flow);
1087 #endif /* CONFIG_SECURITY_NETWORK */ 1111 #endif /* CONFIG_SECURITY_NETWORK */
1088#ifdef CONFIG_SECURITY_NETWORK_XFRM 1112#ifdef CONFIG_SECURITY_NETWORK_XFRM
1089 set_to_dummy_if_null(ops, xfrm_policy_alloc_security); 1113 set_to_dummy_if_null(ops, xfrm_policy_alloc_security);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 4e5989d584ce..1dc935f7b919 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -3328,8 +3328,9 @@ static int selinux_socket_unix_stream_connect(struct socket *sock,
3328 /* server child socket */ 3328 /* server child socket */
3329 ssec = newsk->sk_security; 3329 ssec = newsk->sk_security;
3330 ssec->peer_sid = isec->sid; 3330 ssec->peer_sid = isec->sid;
3331 3331 err = security_sid_mls_copy(other_isec->sid, ssec->peer_sid, &ssec->sid);
3332 return 0; 3332
3333 return err;
3333} 3334}
3334 3335
3335static int selinux_socket_unix_may_send(struct socket *sock, 3336static int selinux_socket_unix_may_send(struct socket *sock,
@@ -3355,11 +3356,29 @@ static int selinux_socket_unix_may_send(struct socket *sock,
3355} 3356}
3356 3357
3357static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, 3358static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
3358 struct avc_audit_data *ad, u32 sock_sid, u16 sock_class, 3359 struct avc_audit_data *ad, u16 family, char *addrp, int len)
3359 u16 family, char *addrp, int len)
3360{ 3360{
3361 int err = 0; 3361 int err = 0;
3362 u32 netif_perm, node_perm, node_sid, if_sid, recv_perm = 0; 3362 u32 netif_perm, node_perm, node_sid, if_sid, recv_perm = 0;
3363 struct socket *sock;
3364 u16 sock_class = 0;
3365 u32 sock_sid = 0;
3366
3367 read_lock_bh(&sk->sk_callback_lock);
3368 sock = sk->sk_socket;
3369 if (sock) {
3370 struct inode *inode;
3371 inode = SOCK_INODE(sock);
3372 if (inode) {
3373 struct inode_security_struct *isec;
3374 isec = inode->i_security;
3375 sock_sid = isec->sid;
3376 sock_class = isec->sclass;
3377 }
3378 }
3379 read_unlock_bh(&sk->sk_callback_lock);
3380 if (!sock_sid)
3381 goto out;
3363 3382
3364 if (!skb->dev) 3383 if (!skb->dev)
3365 goto out; 3384 goto out;
@@ -3419,12 +3438,10 @@ out:
3419static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) 3438static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
3420{ 3439{
3421 u16 family; 3440 u16 family;
3422 u16 sock_class = 0;
3423 char *addrp; 3441 char *addrp;
3424 int len, err = 0; 3442 int len, err = 0;
3425 u32 sock_sid = 0;
3426 struct socket *sock;
3427 struct avc_audit_data ad; 3443 struct avc_audit_data ad;
3444 struct sk_security_struct *sksec = sk->sk_security;
3428 3445
3429 family = sk->sk_family; 3446 family = sk->sk_family;
3430 if (family != PF_INET && family != PF_INET6) 3447 if (family != PF_INET && family != PF_INET6)
@@ -3434,22 +3451,6 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
3434 if (family == PF_INET6 && skb->protocol == ntohs(ETH_P_IP)) 3451 if (family == PF_INET6 && skb->protocol == ntohs(ETH_P_IP))
3435 family = PF_INET; 3452 family = PF_INET;
3436 3453
3437 read_lock_bh(&sk->sk_callback_lock);
3438 sock = sk->sk_socket;
3439 if (sock) {
3440 struct inode *inode;
3441 inode = SOCK_INODE(sock);
3442 if (inode) {
3443 struct inode_security_struct *isec;
3444 isec = inode->i_security;
3445 sock_sid = isec->sid;
3446 sock_class = isec->sclass;
3447 }
3448 }
3449 read_unlock_bh(&sk->sk_callback_lock);
3450 if (!sock_sid)
3451 goto out;
3452
3453 AVC_AUDIT_DATA_INIT(&ad, NET); 3454 AVC_AUDIT_DATA_INIT(&ad, NET);
3454 ad.u.net.netif = skb->dev ? skb->dev->name : "[unknown]"; 3455 ad.u.net.netif = skb->dev ? skb->dev->name : "[unknown]";
3455 ad.u.net.family = family; 3456 ad.u.net.family = family;
@@ -3459,16 +3460,15 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
3459 goto out; 3460 goto out;
3460 3461
3461 if (selinux_compat_net) 3462 if (selinux_compat_net)
3462 err = selinux_sock_rcv_skb_compat(sk, skb, &ad, sock_sid, 3463 err = selinux_sock_rcv_skb_compat(sk, skb, &ad, family,
3463 sock_class, family,
3464 addrp, len); 3464 addrp, len);
3465 else 3465 else
3466 err = avc_has_perm(sock_sid, skb->secmark, SECCLASS_PACKET, 3466 err = avc_has_perm(sksec->sid, skb->secmark, SECCLASS_PACKET,
3467 PACKET__RECV, &ad); 3467 PACKET__RECV, &ad);
3468 if (err) 3468 if (err)
3469 goto out; 3469 goto out;
3470 3470
3471 err = selinux_xfrm_sock_rcv_skb(sock_sid, skb, &ad); 3471 err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad);
3472out: 3472out:
3473 return err; 3473 return err;
3474} 3474}
@@ -3572,6 +3572,49 @@ static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
3572 } 3572 }
3573} 3573}
3574 3574
3575void selinux_sock_graft(struct sock* sk, struct socket *parent)
3576{
3577 struct inode_security_struct *isec = SOCK_INODE(parent)->i_security;
3578 struct sk_security_struct *sksec = sk->sk_security;
3579
3580 isec->sid = sksec->sid;
3581}
3582
3583int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
3584 struct request_sock *req)
3585{
3586 struct sk_security_struct *sksec = sk->sk_security;
3587 int err;
3588 u32 newsid = 0;
3589 u32 peersid;
3590
3591 err = selinux_xfrm_decode_session(skb, &peersid, 0);
3592 BUG_ON(err);
3593
3594 err = security_sid_mls_copy(sksec->sid, peersid, &newsid);
3595 if (err)
3596 return err;
3597
3598 req->secid = newsid;
3599 return 0;
3600}
3601
3602void selinux_inet_csk_clone(struct sock *newsk, const struct request_sock *req)
3603{
3604 struct sk_security_struct *newsksec = newsk->sk_security;
3605
3606 newsksec->sid = req->secid;
3607 /* NOTE: Ideally, we should also get the isec->sid for the
3608 new socket in sync, but we don't have the isec available yet.
3609 So we will wait until sock_graft to do it, by which
3610 time it will have been created and available. */
3611}
3612
3613void selinux_req_classify_flow(const struct request_sock *req, struct flowi *fl)
3614{
3615 fl->secid = req->secid;
3616}
3617
3575static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb) 3618static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
3576{ 3619{
3577 int err = 0; 3620 int err = 0;
@@ -3611,12 +3654,24 @@ out:
3611#ifdef CONFIG_NETFILTER 3654#ifdef CONFIG_NETFILTER
3612 3655
3613static int selinux_ip_postroute_last_compat(struct sock *sk, struct net_device *dev, 3656static int selinux_ip_postroute_last_compat(struct sock *sk, struct net_device *dev,
3614 struct inode_security_struct *isec,
3615 struct avc_audit_data *ad, 3657 struct avc_audit_data *ad,
3616 u16 family, char *addrp, int len) 3658 u16 family, char *addrp, int len)
3617{ 3659{
3618 int err; 3660 int err = 0;
3619 u32 netif_perm, node_perm, node_sid, if_sid, send_perm = 0; 3661 u32 netif_perm, node_perm, node_sid, if_sid, send_perm = 0;
3662 struct socket *sock;
3663 struct inode *inode;
3664 struct inode_security_struct *isec;
3665
3666 sock = sk->sk_socket;
3667 if (!sock)
3668 goto out;
3669
3670 inode = SOCK_INODE(sock);
3671 if (!inode)
3672 goto out;
3673
3674 isec = inode->i_security;
3620 3675
3621 err = sel_netif_sids(dev, &if_sid, NULL); 3676 err = sel_netif_sids(dev, &if_sid, NULL);
3622 if (err) 3677 if (err)
@@ -3681,26 +3736,16 @@ static unsigned int selinux_ip_postroute_last(unsigned int hooknum,
3681 char *addrp; 3736 char *addrp;
3682 int len, err = 0; 3737 int len, err = 0;
3683 struct sock *sk; 3738 struct sock *sk;
3684 struct socket *sock;
3685 struct inode *inode;
3686 struct sk_buff *skb = *pskb; 3739 struct sk_buff *skb = *pskb;
3687 struct inode_security_struct *isec;
3688 struct avc_audit_data ad; 3740 struct avc_audit_data ad;
3689 struct net_device *dev = (struct net_device *)out; 3741 struct net_device *dev = (struct net_device *)out;
3742 struct sk_security_struct *sksec;
3690 3743
3691 sk = skb->sk; 3744 sk = skb->sk;
3692 if (!sk) 3745 if (!sk)
3693 goto out; 3746 goto out;
3694 3747
3695 sock = sk->sk_socket; 3748 sksec = sk->sk_security;
3696 if (!sock)
3697 goto out;
3698
3699 inode = SOCK_INODE(sock);
3700 if (!inode)
3701 goto out;
3702
3703 isec = inode->i_security;
3704 3749
3705 AVC_AUDIT_DATA_INIT(&ad, NET); 3750 AVC_AUDIT_DATA_INIT(&ad, NET);
3706 ad.u.net.netif = dev->name; 3751 ad.u.net.netif = dev->name;
@@ -3711,16 +3756,16 @@ static unsigned int selinux_ip_postroute_last(unsigned int hooknum,
3711 goto out; 3756 goto out;
3712 3757
3713 if (selinux_compat_net) 3758 if (selinux_compat_net)
3714 err = selinux_ip_postroute_last_compat(sk, dev, isec, &ad, 3759 err = selinux_ip_postroute_last_compat(sk, dev, &ad,
3715 family, addrp, len); 3760 family, addrp, len);
3716 else 3761 else
3717 err = avc_has_perm(isec->sid, skb->secmark, SECCLASS_PACKET, 3762 err = avc_has_perm(sksec->sid, skb->secmark, SECCLASS_PACKET,
3718 PACKET__SEND, &ad); 3763 PACKET__SEND, &ad);
3719 3764
3720 if (err) 3765 if (err)
3721 goto out; 3766 goto out;
3722 3767
3723 err = selinux_xfrm_postroute_last(isec->sid, skb, &ad); 3768 err = selinux_xfrm_postroute_last(sksec->sid, skb, &ad);
3724out: 3769out:
3725 return err ? NF_DROP : NF_ACCEPT; 3770 return err ? NF_DROP : NF_ACCEPT;
3726} 3771}
@@ -4623,6 +4668,10 @@ static struct security_operations selinux_ops = {
4623 .sk_free_security = selinux_sk_free_security, 4668 .sk_free_security = selinux_sk_free_security,
4624 .sk_clone_security = selinux_sk_clone_security, 4669 .sk_clone_security = selinux_sk_clone_security,
4625 .sk_getsecid = selinux_sk_getsecid, 4670 .sk_getsecid = selinux_sk_getsecid,
4671 .sock_graft = selinux_sock_graft,
4672 .inet_conn_request = selinux_inet_conn_request,
4673 .inet_csk_clone = selinux_inet_csk_clone,
4674 .req_classify_flow = selinux_req_classify_flow,
4626 4675
4627#ifdef CONFIG_SECURITY_NETWORK_XFRM 4676#ifdef CONFIG_SECURITY_NETWORK_XFRM
4628 .xfrm_policy_alloc_security = selinux_xfrm_policy_alloc, 4677 .xfrm_policy_alloc_security = selinux_xfrm_policy_alloc,
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c
index d3690f985135..3e742b850af6 100644
--- a/security/selinux/xfrm.c
+++ b/security/selinux/xfrm.c
@@ -271,7 +271,6 @@ not_from_user:
271 goto out; 271 goto out;
272 } 272 }
273 273
274
275 ctx->ctx_doi = XFRM_SC_DOI_LSM; 274 ctx->ctx_doi = XFRM_SC_DOI_LSM;
276 ctx->ctx_alg = XFRM_SC_ALG_SELINUX; 275 ctx->ctx_alg = XFRM_SC_ALG_SELINUX;
277 ctx->ctx_sid = ctx_sid; 276 ctx->ctx_sid = ctx_sid;