aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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;