aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/security.h38
-rw-r--r--include/net/route.h3
-rw-r--r--net/dccp/ipv4.c1
-rw-r--r--net/dccp/ipv6.c6
-rw-r--r--net/ipv4/af_inet.c1
-rw-r--r--net/ipv4/icmp.c2
-rw-r--r--net/ipv4/inet_connection_sock.c1
-rw-r--r--net/ipv4/ip_output.c2
-rw-r--r--net/ipv4/netfilter/ipt_REJECT.c1
-rw-r--r--net/ipv4/raw.c1
-rw-r--r--net/ipv4/syncookies.c1
-rw-r--r--net/ipv4/udp.c1
-rw-r--r--net/ipv6/af_inet6.c1
-rw-r--r--net/ipv6/datagram.c2
-rw-r--r--net/ipv6/icmp.c2
-rw-r--r--net/ipv6/inet6_connection_sock.c1
-rw-r--r--net/ipv6/ndisc.c1
-rw-r--r--net/ipv6/netfilter/ip6t_REJECT.c1
-rw-r--r--net/ipv6/raw.c1
-rw-r--r--net/ipv6/tcp_ipv6.c7
-rw-r--r--net/ipv6/udp.c2
-rw-r--r--net/xfrm/xfrm_policy.c3
-rw-r--r--security/dummy.c7
-rw-r--r--security/selinux/hooks.c8
-rw-r--r--security/selinux/include/xfrm.h14
-rw-r--r--security/selinux/xfrm.c11
26 files changed, 79 insertions, 40 deletions
diff --git a/include/linux/security.h b/include/linux/security.h
index 2c4921d79d19..f3909d189fe0 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -32,6 +32,7 @@
32#include <linux/sched.h> 32#include <linux/sched.h>
33#include <linux/key.h> 33#include <linux/key.h>
34#include <linux/xfrm.h> 34#include <linux/xfrm.h>
35#include <net/flow.h>
35 36
36struct ctl_table; 37struct ctl_table;
37 38
@@ -815,8 +816,8 @@ struct swap_info_struct;
815 * Deallocate security structure. 816 * Deallocate security structure.
816 * @sk_clone_security: 817 * @sk_clone_security:
817 * Clone/copy security structure. 818 * Clone/copy security structure.
818 * @sk_getsid: 819 * @sk_getsecid:
819 * Retrieve the LSM-specific sid for the sock to enable caching of network 820 * Retrieve the LSM-specific secid for the sock to enable caching of network
820 * authorizations. 821 * authorizations.
821 * 822 *
822 * Security hooks for XFRM operations. 823 * Security hooks for XFRM operations.
@@ -882,8 +883,9 @@ struct swap_info_struct;
882 * Return 1 if there is a match. 883 * Return 1 if there is a match.
883 * @xfrm_decode_session: 884 * @xfrm_decode_session:
884 * @skb points to skb to decode. 885 * @skb points to skb to decode.
885 * @fl points to the flow key to set. 886 * @secid points to the flow key secid to set.
886 * Return 0 if successful decoding. 887 * @ckall says if all xfrms used should be checked for same secid.
888 * Return 0 if ckall is zero or all xfrms used have the same secid.
887 * 889 *
888 * Security hooks affecting all Key Management operations 890 * Security hooks affecting all Key Management operations
889 * 891 *
@@ -1353,7 +1355,7 @@ struct security_operations {
1353 int (*sk_alloc_security) (struct sock *sk, int family, gfp_t priority); 1355 int (*sk_alloc_security) (struct sock *sk, int family, gfp_t priority);
1354 void (*sk_free_security) (struct sock *sk); 1356 void (*sk_free_security) (struct sock *sk);
1355 void (*sk_clone_security) (const struct sock *sk, struct sock *newsk); 1357 void (*sk_clone_security) (const struct sock *sk, struct sock *newsk);
1356 unsigned int (*sk_getsid) (struct sock *sk, struct flowi *fl, u8 dir); 1358 void (*sk_getsecid) (struct sock *sk, u32 *secid);
1357#endif /* CONFIG_SECURITY_NETWORK */ 1359#endif /* CONFIG_SECURITY_NETWORK */
1358 1360
1359#ifdef CONFIG_SECURITY_NETWORK_XFRM 1361#ifdef CONFIG_SECURITY_NETWORK_XFRM
@@ -1370,7 +1372,7 @@ struct security_operations {
1370 int (*xfrm_state_pol_flow_match)(struct xfrm_state *x, 1372 int (*xfrm_state_pol_flow_match)(struct xfrm_state *x,
1371 struct xfrm_policy *xp, struct flowi *fl); 1373 struct xfrm_policy *xp, struct flowi *fl);
1372 int (*xfrm_flow_state_match)(struct flowi *fl, struct xfrm_state *xfrm); 1374 int (*xfrm_flow_state_match)(struct flowi *fl, struct xfrm_state *xfrm);
1373 int (*xfrm_decode_session)(struct sk_buff *skb, struct flowi *fl); 1375 int (*xfrm_decode_session)(struct sk_buff *skb, u32 *secid, int ckall);
1374#endif /* CONFIG_SECURITY_NETWORK_XFRM */ 1376#endif /* CONFIG_SECURITY_NETWORK_XFRM */
1375 1377
1376 /* key management security hooks */ 1378 /* key management security hooks */
@@ -2917,9 +2919,9 @@ static inline void security_sk_clone(const struct sock *sk, struct sock *newsk)
2917 return security_ops->sk_clone_security(sk, newsk); 2919 return security_ops->sk_clone_security(sk, newsk);
2918} 2920}
2919 2921
2920static inline unsigned int security_sk_sid(struct sock *sk, struct flowi *fl, u8 dir) 2922static inline void security_sk_classify_flow(struct sock *sk, struct flowi *fl)
2921{ 2923{
2922 return security_ops->sk_getsid(sk, fl, dir); 2924 security_ops->sk_getsecid(sk, &fl->secid);
2923} 2925}
2924#else /* CONFIG_SECURITY_NETWORK */ 2926#else /* CONFIG_SECURITY_NETWORK */
2925static inline int security_unix_stream_connect(struct socket * sock, 2927static inline int security_unix_stream_connect(struct socket * sock,
@@ -3047,9 +3049,8 @@ static inline void security_sk_clone(const struct sock *sk, struct sock *newsk)
3047{ 3049{
3048} 3050}
3049 3051
3050static inline unsigned int security_sk_sid(struct sock *sk, struct flowi *fl, u8 dir) 3052static inline void security_sk_classify_flow(struct sock *sk, struct flowi *fl)
3051{ 3053{
3052 return 0;
3053} 3054}
3054#endif /* CONFIG_SECURITY_NETWORK */ 3055#endif /* CONFIG_SECURITY_NETWORK */
3055 3056
@@ -3114,9 +3115,16 @@ static inline int security_xfrm_flow_state_match(struct flowi *fl, struct xfrm_s
3114 return security_ops->xfrm_flow_state_match(fl, xfrm); 3115 return security_ops->xfrm_flow_state_match(fl, xfrm);
3115} 3116}
3116 3117
3117static inline int security_xfrm_decode_session(struct sk_buff *skb, struct flowi *fl) 3118static inline int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid)
3119{
3120 return security_ops->xfrm_decode_session(skb, secid, 1);
3121}
3122
3123static inline void security_skb_classify_flow(struct sk_buff *skb, struct flowi *fl)
3118{ 3124{
3119 return security_ops->xfrm_decode_session(skb, fl); 3125 int rc = security_ops->xfrm_decode_session(skb, &fl->secid, 0);
3126
3127 BUG_ON(rc);
3120} 3128}
3121#else /* CONFIG_SECURITY_NETWORK_XFRM */ 3129#else /* CONFIG_SECURITY_NETWORK_XFRM */
3122static inline int security_xfrm_policy_alloc(struct xfrm_policy *xp, struct xfrm_user_sec_ctx *sec_ctx) 3130static inline int security_xfrm_policy_alloc(struct xfrm_policy *xp, struct xfrm_user_sec_ctx *sec_ctx)
@@ -3176,11 +3184,15 @@ static inline int security_xfrm_flow_state_match(struct flowi *fl,
3176 return 1; 3184 return 1;
3177} 3185}
3178 3186
3179static inline int security_xfrm_decode_session(struct sk_buff *skb, struct flowi *fl) 3187static inline int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid)
3180{ 3188{
3181 return 0; 3189 return 0;
3182} 3190}
3183 3191
3192static inline void security_skb_classify_flow(struct sk_buff *skb, struct flowi *fl)
3193{
3194}
3195
3184#endif /* CONFIG_SECURITY_NETWORK_XFRM */ 3196#endif /* CONFIG_SECURITY_NETWORK_XFRM */
3185 3197
3186#ifdef CONFIG_KEYS 3198#ifdef CONFIG_KEYS
diff --git a/include/net/route.h b/include/net/route.h
index c4a068692dcc..7f93ac0e0899 100644
--- a/include/net/route.h
+++ b/include/net/route.h
@@ -32,6 +32,7 @@
32#include <linux/route.h> 32#include <linux/route.h>
33#include <linux/ip.h> 33#include <linux/ip.h>
34#include <linux/cache.h> 34#include <linux/cache.h>
35#include <linux/security.h>
35 36
36#ifndef __KERNEL__ 37#ifndef __KERNEL__
37#warning This file is not supposed to be used outside of kernel. 38#warning This file is not supposed to be used outside of kernel.
@@ -166,6 +167,7 @@ static inline int ip_route_connect(struct rtable **rp, u32 dst,
166 ip_rt_put(*rp); 167 ip_rt_put(*rp);
167 *rp = NULL; 168 *rp = NULL;
168 } 169 }
170 security_sk_classify_flow(sk, &fl);
169 return ip_route_output_flow(rp, &fl, sk, 0); 171 return ip_route_output_flow(rp, &fl, sk, 0);
170} 172}
171 173
@@ -182,6 +184,7 @@ static inline int ip_route_newports(struct rtable **rp, u8 protocol,
182 fl.proto = protocol; 184 fl.proto = protocol;
183 ip_rt_put(*rp); 185 ip_rt_put(*rp);
184 *rp = NULL; 186 *rp = NULL;
187 security_sk_classify_flow(sk, &fl);
185 return ip_route_output_flow(rp, &fl, sk, 0); 188 return ip_route_output_flow(rp, &fl, sk, 0);
186 } 189 }
187 return 0; 190 return 0;
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index 7f56f7e8f571..386498053b1c 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -678,6 +678,7 @@ static struct dst_entry* dccp_v4_route_skb(struct sock *sk,
678 } 678 }
679 }; 679 };
680 680
681 security_skb_classify_flow(skb, &fl);
681 if (ip_route_output_flow(&rt, &fl, sk, 0)) { 682 if (ip_route_output_flow(&rt, &fl, sk, 0)) {
682 IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES); 683 IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES);
683 return NULL; 684 return NULL;
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
index 610c722ac27f..53d255c01431 100644
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -201,6 +201,7 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
201 fl.oif = sk->sk_bound_dev_if; 201 fl.oif = sk->sk_bound_dev_if;
202 fl.fl_ip_dport = usin->sin6_port; 202 fl.fl_ip_dport = usin->sin6_port;
203 fl.fl_ip_sport = inet->sport; 203 fl.fl_ip_sport = inet->sport;
204 security_sk_classify_flow(sk, &fl);
204 205
205 if (np->opt != NULL && np->opt->srcrt != NULL) { 206 if (np->opt != NULL && np->opt->srcrt != NULL) {
206 const struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt; 207 const struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt;
@@ -322,6 +323,7 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
322 fl.oif = sk->sk_bound_dev_if; 323 fl.oif = sk->sk_bound_dev_if;
323 fl.fl_ip_dport = inet->dport; 324 fl.fl_ip_dport = inet->dport;
324 fl.fl_ip_sport = inet->sport; 325 fl.fl_ip_sport = inet->sport;
326 security_sk_classify_flow(sk, &fl);
325 327
326 err = ip6_dst_lookup(sk, &dst, &fl); 328 err = ip6_dst_lookup(sk, &dst, &fl);
327 if (err) { 329 if (err) {
@@ -422,6 +424,7 @@ static int dccp_v6_send_response(struct sock *sk, struct request_sock *req,
422 fl.oif = ireq6->iif; 424 fl.oif = ireq6->iif;
423 fl.fl_ip_dport = inet_rsk(req)->rmt_port; 425 fl.fl_ip_dport = inet_rsk(req)->rmt_port;
424 fl.fl_ip_sport = inet_sk(sk)->sport; 426 fl.fl_ip_sport = inet_sk(sk)->sport;
427 security_sk_classify_flow(sk, &fl);
425 428
426 if (dst == NULL) { 429 if (dst == NULL) {
427 opt = np->opt; 430 opt = np->opt;
@@ -566,6 +569,7 @@ static void dccp_v6_ctl_send_reset(struct sk_buff *rxskb)
566 fl.oif = inet6_iif(rxskb); 569 fl.oif = inet6_iif(rxskb);
567 fl.fl_ip_dport = dh->dccph_dport; 570 fl.fl_ip_dport = dh->dccph_dport;
568 fl.fl_ip_sport = dh->dccph_sport; 571 fl.fl_ip_sport = dh->dccph_sport;
572 security_skb_classify_flow(rxskb, &fl);
569 573
570 /* sk = NULL, but it is safe for now. RST socket required. */ 574 /* sk = NULL, but it is safe for now. RST socket required. */
571 if (!ip6_dst_lookup(NULL, &skb->dst, &fl)) { 575 if (!ip6_dst_lookup(NULL, &skb->dst, &fl)) {
@@ -622,6 +626,7 @@ static void dccp_v6_reqsk_send_ack(struct sk_buff *rxskb,
622 fl.oif = inet6_iif(rxskb); 626 fl.oif = inet6_iif(rxskb);
623 fl.fl_ip_dport = dh->dccph_dport; 627 fl.fl_ip_dport = dh->dccph_dport;
624 fl.fl_ip_sport = dh->dccph_sport; 628 fl.fl_ip_sport = dh->dccph_sport;
629 security_skb_classify_flow(rxskb, &fl);
625 630
626 if (!ip6_dst_lookup(NULL, &skb->dst, &fl)) { 631 if (!ip6_dst_lookup(NULL, &skb->dst, &fl)) {
627 if (xfrm_lookup(&skb->dst, &fl, NULL, 0) >= 0) { 632 if (xfrm_lookup(&skb->dst, &fl, NULL, 0) >= 0) {
@@ -842,6 +847,7 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk,
842 fl.oif = sk->sk_bound_dev_if; 847 fl.oif = sk->sk_bound_dev_if;
843 fl.fl_ip_dport = inet_rsk(req)->rmt_port; 848 fl.fl_ip_dport = inet_rsk(req)->rmt_port;
844 fl.fl_ip_sport = inet_sk(sk)->sport; 849 fl.fl_ip_sport = inet_sk(sk)->sport;
850 security_sk_classify_flow(sk, &fl);
845 851
846 if (ip6_dst_lookup(sk, &dst, &fl)) 852 if (ip6_dst_lookup(sk, &dst, &fl))
847 goto out; 853 goto out;
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index c84a32070f8d..fc40da3b6d39 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1074,6 +1074,7 @@ int inet_sk_rebuild_header(struct sock *sk)
1074 }, 1074 },
1075 }; 1075 };
1076 1076
1077 security_sk_classify_flow(sk, &fl);
1077 err = ip_route_output_flow(&rt, &fl, sk, 0); 1078 err = ip_route_output_flow(&rt, &fl, sk, 0);
1078} 1079}
1079 if (!err) 1080 if (!err)
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index 4c86ac3d882d..6ad797c14163 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -406,6 +406,7 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb)
406 .saddr = rt->rt_spec_dst, 406 .saddr = rt->rt_spec_dst,
407 .tos = RT_TOS(skb->nh.iph->tos) } }, 407 .tos = RT_TOS(skb->nh.iph->tos) } },
408 .proto = IPPROTO_ICMP }; 408 .proto = IPPROTO_ICMP };
409 security_skb_classify_flow(skb, &fl);
409 if (ip_route_output_key(&rt, &fl)) 410 if (ip_route_output_key(&rt, &fl))
410 goto out_unlock; 411 goto out_unlock;
411 } 412 }
@@ -560,6 +561,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, u32 info)
560 } 561 }
561 } 562 }
562 }; 563 };
564 security_skb_classify_flow(skb_in, &fl);
563 if (ip_route_output_key(&rt, &fl)) 565 if (ip_route_output_key(&rt, &fl))
564 goto out_unlock; 566 goto out_unlock;
565 } 567 }
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index e50a1bfd7ccc..772b4eac78bc 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -327,6 +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 if (ip_route_output_flow(&rt, &fl, sk, 0)) { 331 if (ip_route_output_flow(&rt, &fl, sk, 0)) {
331 IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES); 332 IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES);
332 return NULL; 333 return NULL;
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index a2ede167e045..308bdeac3455 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -328,6 +328,7 @@ int ip_queue_xmit(struct sk_buff *skb, int ipfragok)
328 * keep trying until route appears or the connection times 328 * keep trying until route appears or the connection times
329 * itself out. 329 * itself out.
330 */ 330 */
331 security_sk_classify_flow(sk, &fl);
331 if (ip_route_output_flow(&rt, &fl, sk, 0)) 332 if (ip_route_output_flow(&rt, &fl, sk, 0))
332 goto no_route; 333 goto no_route;
333 } 334 }
@@ -1366,6 +1367,7 @@ void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *ar
1366 { .sport = skb->h.th->dest, 1367 { .sport = skb->h.th->dest,
1367 .dport = skb->h.th->source } }, 1368 .dport = skb->h.th->source } },
1368 .proto = sk->sk_protocol }; 1369 .proto = sk->sk_protocol };
1370 security_skb_classify_flow(skb, &fl);
1369 if (ip_route_output_key(&rt, &fl)) 1371 if (ip_route_output_key(&rt, &fl))
1370 return; 1372 return;
1371 } 1373 }
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c
index 269bc2067cb8..7f905bf2bde5 100644
--- a/net/ipv4/netfilter/ipt_REJECT.c
+++ b/net/ipv4/netfilter/ipt_REJECT.c
@@ -90,6 +90,7 @@ static inline struct rtable *route_reverse(struct sk_buff *skb,
90 fl.proto = IPPROTO_TCP; 90 fl.proto = IPPROTO_TCP;
91 fl.fl_ip_sport = tcph->dest; 91 fl.fl_ip_sport = tcph->dest;
92 fl.fl_ip_dport = tcph->source; 92 fl.fl_ip_dport = tcph->source;
93 security_skb_classify_flow(skb, &fl);
93 94
94 xfrm_lookup((struct dst_entry **)&rt, &fl, NULL, 0); 95 xfrm_lookup((struct dst_entry **)&rt, &fl, NULL, 0);
95 96
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index 62b2762a2420..fe44cb50a1c5 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -484,6 +484,7 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
484 if (!inet->hdrincl) 484 if (!inet->hdrincl)
485 raw_probe_proto_opt(&fl, msg); 485 raw_probe_proto_opt(&fl, msg);
486 486
487 security_sk_classify_flow(sk, &fl);
487 err = ip_route_output_flow(&rt, &fl, sk, !(msg->msg_flags&MSG_DONTWAIT)); 488 err = ip_route_output_flow(&rt, &fl, sk, !(msg->msg_flags&MSG_DONTWAIT));
488 } 489 }
489 if (err) 490 if (err)
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
index e20be3331f67..307dc3c0d635 100644
--- a/net/ipv4/syncookies.c
+++ b/net/ipv4/syncookies.c
@@ -259,6 +259,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
259 .uli_u = { .ports = 259 .uli_u = { .ports =
260 { .sport = skb->h.th->dest, 260 { .sport = skb->h.th->dest,
261 .dport = skb->h.th->source } } }; 261 .dport = skb->h.th->source } } };
262 security_sk_classify_flow(sk, &fl);
262 if (ip_route_output_key(&rt, &fl)) { 263 if (ip_route_output_key(&rt, &fl)) {
263 reqsk_free(req); 264 reqsk_free(req);
264 goto out; 265 goto out;
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index f136cec96d95..a4d005eccc7f 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -603,6 +603,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
603 .uli_u = { .ports = 603 .uli_u = { .ports =
604 { .sport = inet->sport, 604 { .sport = inet->sport,
605 .dport = dport } } }; 605 .dport = dport } } };
606 security_sk_classify_flow(sk, &fl);
606 err = ip_route_output_flow(&rt, &fl, sk, !(msg->msg_flags&MSG_DONTWAIT)); 607 err = ip_route_output_flow(&rt, &fl, sk, !(msg->msg_flags&MSG_DONTWAIT));
607 if (err) 608 if (err)
608 goto out; 609 goto out;
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index ac85e9c532c2..82a1b1a328db 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -637,6 +637,7 @@ int inet6_sk_rebuild_header(struct sock *sk)
637 fl.oif = sk->sk_bound_dev_if; 637 fl.oif = sk->sk_bound_dev_if;
638 fl.fl_ip_dport = inet->dport; 638 fl.fl_ip_dport = inet->dport;
639 fl.fl_ip_sport = inet->sport; 639 fl.fl_ip_sport = inet->sport;
640 security_sk_classify_flow(sk, &fl);
640 641
641 if (np->opt && np->opt->srcrt) { 642 if (np->opt && np->opt->srcrt) {
642 struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt; 643 struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt;
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index 3b55b4c8e2d1..c73508e090a6 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -156,6 +156,8 @@ ipv4_connected:
156 if (!fl.oif && (addr_type&IPV6_ADDR_MULTICAST)) 156 if (!fl.oif && (addr_type&IPV6_ADDR_MULTICAST))
157 fl.oif = np->mcast_oif; 157 fl.oif = np->mcast_oif;
158 158
159 security_sk_classify_flow(sk, &fl);
160
159 if (flowlabel) { 161 if (flowlabel) {
160 if (flowlabel->opt && flowlabel->opt->srcrt) { 162 if (flowlabel->opt && flowlabel->opt->srcrt) {
161 struct rt0_hdr *rt0 = (struct rt0_hdr *) flowlabel->opt->srcrt; 163 struct rt0_hdr *rt0 = (struct rt0_hdr *) flowlabel->opt->srcrt;
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index 356a8a7ef22a..dbfce089e916 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -358,6 +358,7 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info,
358 fl.oif = iif; 358 fl.oif = iif;
359 fl.fl_icmp_type = type; 359 fl.fl_icmp_type = type;
360 fl.fl_icmp_code = code; 360 fl.fl_icmp_code = code;
361 security_skb_classify_flow(skb, &fl);
361 362
362 if (icmpv6_xmit_lock()) 363 if (icmpv6_xmit_lock())
363 return; 364 return;
@@ -472,6 +473,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
472 ipv6_addr_copy(&fl.fl6_src, saddr); 473 ipv6_addr_copy(&fl.fl6_src, saddr);
473 fl.oif = skb->dev->ifindex; 474 fl.oif = skb->dev->ifindex;
474 fl.fl_icmp_type = ICMPV6_ECHO_REPLY; 475 fl.fl_icmp_type = ICMPV6_ECHO_REPLY;
476 security_skb_classify_flow(skb, &fl);
475 477
476 if (icmpv6_xmit_lock()) 478 if (icmpv6_xmit_lock())
477 return; 479 return;
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c
index bf491077b822..7a51a258615d 100644
--- a/net/ipv6/inet6_connection_sock.c
+++ b/net/ipv6/inet6_connection_sock.c
@@ -157,6 +157,7 @@ int inet6_csk_xmit(struct sk_buff *skb, int ipfragok)
157 fl.oif = sk->sk_bound_dev_if; 157 fl.oif = sk->sk_bound_dev_if;
158 fl.fl_ip_sport = inet->sport; 158 fl.fl_ip_sport = inet->sport;
159 fl.fl_ip_dport = inet->dport; 159 fl.fl_ip_dport = inet->dport;
160 security_sk_classify_flow(sk, &fl);
160 161
161 if (np->opt && np->opt->srcrt) { 162 if (np->opt && np->opt->srcrt) {
162 struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt; 163 struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt;
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index b50055b9278d..67cfc3813c32 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -419,6 +419,7 @@ static inline void ndisc_flow_init(struct flowi *fl, u8 type,
419 fl->proto = IPPROTO_ICMPV6; 419 fl->proto = IPPROTO_ICMPV6;
420 fl->fl_icmp_type = type; 420 fl->fl_icmp_type = type;
421 fl->fl_icmp_code = 0; 421 fl->fl_icmp_code = 0;
422 security_sk_classify_flow(ndisc_socket->sk, fl);
422} 423}
423 424
424static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh, 425static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c
index 8629ba195d2d..c4eba1aeb323 100644
--- a/net/ipv6/netfilter/ip6t_REJECT.c
+++ b/net/ipv6/netfilter/ip6t_REJECT.c
@@ -96,6 +96,7 @@ static void send_reset(struct sk_buff *oldskb)
96 ipv6_addr_copy(&fl.fl6_dst, &oip6h->saddr); 96 ipv6_addr_copy(&fl.fl6_dst, &oip6h->saddr);
97 fl.fl_ip_sport = otcph.dest; 97 fl.fl_ip_sport = otcph.dest;
98 fl.fl_ip_dport = otcph.source; 98 fl.fl_ip_dport = otcph.source;
99 security_skb_classify_flow(oldskb, &fl);
99 dst = ip6_route_output(NULL, &fl); 100 dst = ip6_route_output(NULL, &fl);
100 if (dst == NULL) 101 if (dst == NULL)
101 return; 102 return;
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 15b862d8acab..d5040e172292 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -759,6 +759,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
759 759
760 if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) 760 if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst))
761 fl.oif = np->mcast_oif; 761 fl.oif = np->mcast_oif;
762 security_sk_classify_flow(sk, &fl);
762 763
763 err = ip6_dst_lookup(sk, &dst, &fl); 764 err = ip6_dst_lookup(sk, &dst, &fl);
764 if (err) 765 if (err)
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 802a1a6b1037..46922e57e311 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -251,6 +251,8 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
251 final_p = &final; 251 final_p = &final;
252 } 252 }
253 253
254 security_sk_classify_flow(sk, &fl);
255
254 err = ip6_dst_lookup(sk, &dst, &fl); 256 err = ip6_dst_lookup(sk, &dst, &fl);
255 if (err) 257 if (err)
256 goto failure; 258 goto failure;
@@ -374,6 +376,7 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
374 fl.oif = sk->sk_bound_dev_if; 376 fl.oif = sk->sk_bound_dev_if;
375 fl.fl_ip_dport = inet->dport; 377 fl.fl_ip_dport = inet->dport;
376 fl.fl_ip_sport = inet->sport; 378 fl.fl_ip_sport = inet->sport;
379 security_skb_classify_flow(skb, &fl);
377 380
378 if ((err = ip6_dst_lookup(sk, &dst, &fl))) { 381 if ((err = ip6_dst_lookup(sk, &dst, &fl))) {
379 sk->sk_err_soft = -err; 382 sk->sk_err_soft = -err;
@@ -467,6 +470,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req,
467 fl.oif = treq->iif; 470 fl.oif = treq->iif;
468 fl.fl_ip_dport = inet_rsk(req)->rmt_port; 471 fl.fl_ip_dport = inet_rsk(req)->rmt_port;
469 fl.fl_ip_sport = inet_sk(sk)->sport; 472 fl.fl_ip_sport = inet_sk(sk)->sport;
473 security_sk_classify_flow(sk, &fl);
470 474
471 if (dst == NULL) { 475 if (dst == NULL) {
472 opt = np->opt; 476 opt = np->opt;
@@ -625,6 +629,7 @@ static void tcp_v6_send_reset(struct sk_buff *skb)
625 fl.oif = inet6_iif(skb); 629 fl.oif = inet6_iif(skb);
626 fl.fl_ip_dport = t1->dest; 630 fl.fl_ip_dport = t1->dest;
627 fl.fl_ip_sport = t1->source; 631 fl.fl_ip_sport = t1->source;
632 security_skb_classify_flow(skb, &fl);
628 633
629 /* sk = NULL, but it is safe for now. RST socket required. */ 634 /* sk = NULL, but it is safe for now. RST socket required. */
630 if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) { 635 if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) {
@@ -691,6 +696,7 @@ static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32
691 fl.oif = inet6_iif(skb); 696 fl.oif = inet6_iif(skb);
692 fl.fl_ip_dport = t1->dest; 697 fl.fl_ip_dport = t1->dest;
693 fl.fl_ip_sport = t1->source; 698 fl.fl_ip_sport = t1->source;
699 security_skb_classify_flow(skb, &fl);
694 700
695 if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) { 701 if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) {
696 if (xfrm_lookup(&buff->dst, &fl, NULL, 0) >= 0) { 702 if (xfrm_lookup(&buff->dst, &fl, NULL, 0) >= 0) {
@@ -923,6 +929,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
923 fl.oif = sk->sk_bound_dev_if; 929 fl.oif = sk->sk_bound_dev_if;
924 fl.fl_ip_dport = inet_rsk(req)->rmt_port; 930 fl.fl_ip_dport = inet_rsk(req)->rmt_port;
925 fl.fl_ip_sport = inet_sk(sk)->sport; 931 fl.fl_ip_sport = inet_sk(sk)->sport;
932 security_sk_classify_flow(sk, &fl);
926 933
927 if (ip6_dst_lookup(sk, &dst, &fl)) 934 if (ip6_dst_lookup(sk, &dst, &fl))
928 goto out; 935 goto out;
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 3d54f246411e..82c7c9cde2a8 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -782,6 +782,8 @@ do_udp_sendmsg:
782 connected = 0; 782 connected = 0;
783 } 783 }
784 784
785 security_sk_classify_flow(sk, fl);
786
785 err = ip6_sk_dst_lookup(sk, &dst, fl); 787 err = ip6_sk_dst_lookup(sk, &dst, fl);
786 if (err) 788 if (err)
787 goto out; 789 goto out;
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 79405daadc52..32c963c90573 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -863,7 +863,6 @@ int xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl,
863 u16 family; 863 u16 family;
864 u8 dir = policy_to_flow_dir(XFRM_POLICY_OUT); 864 u8 dir = policy_to_flow_dir(XFRM_POLICY_OUT);
865 865
866 fl->secid = security_sk_sid(sk, fl, dir);
867restart: 866restart:
868 genid = atomic_read(&flow_cache_genid); 867 genid = atomic_read(&flow_cache_genid);
869 policy = NULL; 868 policy = NULL;
@@ -1039,7 +1038,7 @@ xfrm_decode_session(struct sk_buff *skb, struct flowi *fl, unsigned short family
1039 return -EAFNOSUPPORT; 1038 return -EAFNOSUPPORT;
1040 1039
1041 afinfo->decode_session(skb, fl); 1040 afinfo->decode_session(skb, fl);
1042 err = security_xfrm_decode_session(skb, fl); 1041 err = security_xfrm_decode_session(skb, &fl->secid);
1043 xfrm_policy_put_afinfo(afinfo); 1042 xfrm_policy_put_afinfo(afinfo);
1044 return err; 1043 return err;
1045} 1044}
diff --git a/security/dummy.c b/security/dummy.c
index c1f10654871e..c0ff6b9bfd7d 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -809,9 +809,8 @@ static inline void dummy_sk_clone_security (const struct sock *sk, struct sock *
809{ 809{
810} 810}
811 811
812static unsigned int dummy_sk_getsid(struct sock *sk, struct flowi *fl, u8 dir) 812static inline void dummy_sk_getsecid(struct sock *sk, u32 *secid)
813{ 813{
814 return 0;
815} 814}
816#endif /* CONFIG_SECURITY_NETWORK */ 815#endif /* CONFIG_SECURITY_NETWORK */
817 816
@@ -866,7 +865,7 @@ static int dummy_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm
866 return 1; 865 return 1;
867} 866}
868 867
869static int dummy_xfrm_decode_session(struct sk_buff *skb, struct flowi *fl) 868static int dummy_xfrm_decode_session(struct sk_buff *skb, u32 *fl, int ckall)
870{ 869{
871 return 0; 870 return 0;
872} 871}
@@ -1083,7 +1082,7 @@ void security_fixup_ops (struct security_operations *ops)
1083 set_to_dummy_if_null(ops, sk_alloc_security); 1082 set_to_dummy_if_null(ops, sk_alloc_security);
1084 set_to_dummy_if_null(ops, sk_free_security); 1083 set_to_dummy_if_null(ops, sk_free_security);
1085 set_to_dummy_if_null(ops, sk_clone_security); 1084 set_to_dummy_if_null(ops, sk_clone_security);
1086 set_to_dummy_if_null(ops, sk_getsid); 1085 set_to_dummy_if_null(ops, sk_getsecid);
1087 #endif /* CONFIG_SECURITY_NETWORK */ 1086 #endif /* CONFIG_SECURITY_NETWORK */
1088#ifdef CONFIG_SECURITY_NETWORK_XFRM 1087#ifdef CONFIG_SECURITY_NETWORK_XFRM
1089 set_to_dummy_if_null(ops, xfrm_policy_alloc_security); 1088 set_to_dummy_if_null(ops, xfrm_policy_alloc_security);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 5c189da07bc9..4e5989d584ce 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -3561,14 +3561,14 @@ static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
3561 newssec->peer_sid = ssec->peer_sid; 3561 newssec->peer_sid = ssec->peer_sid;
3562} 3562}
3563 3563
3564static unsigned int selinux_sk_getsid_security(struct sock *sk, struct flowi *fl, u8 dir) 3564static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
3565{ 3565{
3566 if (!sk) 3566 if (!sk)
3567 return selinux_no_sk_sid(fl); 3567 *secid = SECINITSID_ANY_SOCKET;
3568 else { 3568 else {
3569 struct sk_security_struct *sksec = sk->sk_security; 3569 struct sk_security_struct *sksec = sk->sk_security;
3570 3570
3571 return sksec->sid; 3571 *secid = sksec->sid;
3572 } 3572 }
3573} 3573}
3574 3574
@@ -4622,7 +4622,7 @@ static struct security_operations selinux_ops = {
4622 .sk_alloc_security = selinux_sk_alloc_security, 4622 .sk_alloc_security = selinux_sk_alloc_security,
4623 .sk_free_security = selinux_sk_free_security, 4623 .sk_free_security = selinux_sk_free_security,
4624 .sk_clone_security = selinux_sk_clone_security, 4624 .sk_clone_security = selinux_sk_clone_security,
4625 .sk_getsid = selinux_sk_getsid_security, 4625 .sk_getsecid = selinux_sk_getsecid,
4626 4626
4627#ifdef CONFIG_SECURITY_NETWORK_XFRM 4627#ifdef CONFIG_SECURITY_NETWORK_XFRM
4628 .xfrm_policy_alloc_security = selinux_xfrm_policy_alloc, 4628 .xfrm_policy_alloc_security = selinux_xfrm_policy_alloc,
diff --git a/security/selinux/include/xfrm.h b/security/selinux/include/xfrm.h
index f51a3e84bd9b..8e45c1d588a8 100644
--- a/security/selinux/include/xfrm.h
+++ b/security/selinux/include/xfrm.h
@@ -19,7 +19,7 @@ int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir);
19int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, 19int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x,
20 struct xfrm_policy *xp, struct flowi *fl); 20 struct xfrm_policy *xp, struct flowi *fl);
21int selinux_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm); 21int selinux_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm);
22int selinux_xfrm_decode_session(struct sk_buff *skb, struct flowi *fl); 22int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *fl, int ckall);
23 23
24 24
25/* 25/*
@@ -33,18 +33,6 @@ static inline struct inode_security_struct *get_sock_isec(struct sock *sk)
33 return SOCK_INODE(sk->sk_socket)->i_security; 33 return SOCK_INODE(sk->sk_socket)->i_security;
34} 34}
35 35
36
37static inline u32 selinux_no_sk_sid(struct flowi *fl)
38{
39 /* NOTE: no sock occurs on ICMP reply, forwards, ... */
40 /* icmp_reply: authorize as kernel packet */
41 if (fl && fl->proto == IPPROTO_ICMP) {
42 return SECINITSID_KERNEL;
43 }
44
45 return SECINITSID_ANY_SOCKET;
46}
47
48#ifdef CONFIG_SECURITY_NETWORK_XFRM 36#ifdef CONFIG_SECURITY_NETWORK_XFRM
49int selinux_xfrm_sock_rcv_skb(u32 sid, struct sk_buff *skb, 37int selinux_xfrm_sock_rcv_skb(u32 sid, struct sk_buff *skb,
50 struct avc_audit_data *ad); 38 struct avc_audit_data *ad);
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c
index a502b0540e3d..c750ef7af66f 100644
--- a/security/selinux/xfrm.c
+++ b/security/selinux/xfrm.c
@@ -158,11 +158,11 @@ int selinux_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm)
158 * LSM hook implementation that determines the sid for the session. 158 * LSM hook implementation that determines the sid for the session.
159 */ 159 */
160 160
161int selinux_xfrm_decode_session(struct sk_buff *skb, struct flowi *fl) 161int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall)
162{ 162{
163 struct sec_path *sp; 163 struct sec_path *sp;
164 164
165 fl->secid = SECSID_NULL; 165 *sid = SECSID_NULL;
166 166
167 if (skb == NULL) 167 if (skb == NULL)
168 return 0; 168 return 0;
@@ -177,10 +177,13 @@ int selinux_xfrm_decode_session(struct sk_buff *skb, struct flowi *fl)
177 struct xfrm_sec_ctx *ctx = x->security; 177 struct xfrm_sec_ctx *ctx = x->security;
178 178
179 if (!sid_set) { 179 if (!sid_set) {
180 fl->secid = ctx->ctx_sid; 180 *sid = ctx->ctx_sid;
181 sid_set = 1; 181 sid_set = 1;
182
183 if (!ckall)
184 break;
182 } 185 }
183 else if (fl->secid != ctx->ctx_sid) 186 else if (*sid != ctx->ctx_sid)
184 return -EINVAL; 187 return -EINVAL;
185 } 188 }
186 } 189 }