lsm,selinux: pass flowi_common instead of flowi to the LSM hooks

As pointed out by Herbert in a recent related patch, the LSM hooks do
not have the necessary address family information to use the flowi
struct safely.  As none of the LSMs currently use any of the protocol
specific flowi information, replace the flowi pointers with pointers
to the address family independent flowi_common struct.

Reported-by: Herbert Xu <herbert@gondor.apana.org.au>
Acked-by: James Morris <jamorris@linux.microsoft.com>
Signed-off-by: Paul Moore <paul@paul-moore.com>
This commit is contained in:
Paul Moore 2020-09-27 22:38:26 -04:00
parent b2d99bcb27
commit 3df98d7921
33 changed files with 85 additions and 66 deletions

View File

@ -1148,7 +1148,7 @@ static struct sock *chtls_recv_sock(struct sock *lsk,
fl6.daddr = ip6h->saddr; fl6.daddr = ip6h->saddr;
fl6.fl6_dport = inet_rsk(oreq)->ir_rmt_port; fl6.fl6_dport = inet_rsk(oreq)->ir_rmt_port;
fl6.fl6_sport = htons(inet_rsk(oreq)->ir_num); fl6.fl6_sport = htons(inet_rsk(oreq)->ir_num);
security_req_classify_flow(oreq, flowi6_to_flowi(&fl6)); security_req_classify_flow(oreq, flowi6_to_flowi_common(&fl6));
dst = ip6_dst_lookup_flow(sock_net(lsk), lsk, &fl6, NULL); dst = ip6_dst_lookup_flow(sock_net(lsk), lsk, &fl6, NULL);
if (IS_ERR(dst)) if (IS_ERR(dst))
goto free_sk; goto free_sk;

View File

@ -49,7 +49,7 @@ static int send4(struct wg_device *wg, struct sk_buff *skb,
rt = dst_cache_get_ip4(cache, &fl.saddr); rt = dst_cache_get_ip4(cache, &fl.saddr);
if (!rt) { if (!rt) {
security_sk_classify_flow(sock, flowi4_to_flowi(&fl)); security_sk_classify_flow(sock, flowi4_to_flowi_common(&fl));
if (unlikely(!inet_confirm_addr(sock_net(sock), NULL, 0, if (unlikely(!inet_confirm_addr(sock_net(sock), NULL, 0,
fl.saddr, RT_SCOPE_HOST))) { fl.saddr, RT_SCOPE_HOST))) {
endpoint->src4.s_addr = 0; endpoint->src4.s_addr = 0;
@ -129,7 +129,7 @@ static int send6(struct wg_device *wg, struct sk_buff *skb,
dst = dst_cache_get_ip6(cache, &fl.saddr); dst = dst_cache_get_ip6(cache, &fl.saddr);
if (!dst) { if (!dst) {
security_sk_classify_flow(sock, flowi6_to_flowi(&fl)); security_sk_classify_flow(sock, flowi6_to_flowi_common(&fl));
if (unlikely(!ipv6_addr_any(&fl.saddr) && if (unlikely(!ipv6_addr_any(&fl.saddr) &&
!ipv6_chk_addr(sock_net(sock), &fl.saddr, NULL, 0))) { !ipv6_chk_addr(sock_net(sock), &fl.saddr, NULL, 0))) {
endpoint->src6 = fl.saddr = in6addr_any; endpoint->src6 = fl.saddr = in6addr_any;

View File

@ -311,7 +311,7 @@ LSM_HOOK(int, 0, secmark_relabel_packet, u32 secid)
LSM_HOOK(void, LSM_RET_VOID, secmark_refcount_inc, void) LSM_HOOK(void, LSM_RET_VOID, secmark_refcount_inc, void)
LSM_HOOK(void, LSM_RET_VOID, secmark_refcount_dec, void) LSM_HOOK(void, LSM_RET_VOID, secmark_refcount_dec, void)
LSM_HOOK(void, LSM_RET_VOID, req_classify_flow, const struct request_sock *req, LSM_HOOK(void, LSM_RET_VOID, req_classify_flow, const struct request_sock *req,
struct flowi *fl) struct flowi_common *flic)
LSM_HOOK(int, 0, tun_dev_alloc_security, void **security) LSM_HOOK(int, 0, tun_dev_alloc_security, void **security)
LSM_HOOK(void, LSM_RET_VOID, tun_dev_free_security, void *security) LSM_HOOK(void, LSM_RET_VOID, tun_dev_free_security, void *security)
LSM_HOOK(int, 0, tun_dev_create, void) LSM_HOOK(int, 0, tun_dev_create, void)
@ -351,7 +351,7 @@ LSM_HOOK(int, 0, xfrm_state_delete_security, struct xfrm_state *x)
LSM_HOOK(int, 0, xfrm_policy_lookup, struct xfrm_sec_ctx *ctx, u32 fl_secid, LSM_HOOK(int, 0, xfrm_policy_lookup, struct xfrm_sec_ctx *ctx, u32 fl_secid,
u8 dir) u8 dir)
LSM_HOOK(int, 1, xfrm_state_pol_flow_match, struct xfrm_state *x, LSM_HOOK(int, 1, xfrm_state_pol_flow_match, struct xfrm_state *x,
struct xfrm_policy *xp, const struct flowi *fl) struct xfrm_policy *xp, const struct flowi_common *flic)
LSM_HOOK(int, 0, xfrm_decode_session, struct sk_buff *skb, u32 *secid, LSM_HOOK(int, 0, xfrm_decode_session, struct sk_buff *skb, u32 *secid,
int ckall) int ckall)
#endif /* CONFIG_SECURITY_NETWORK_XFRM */ #endif /* CONFIG_SECURITY_NETWORK_XFRM */

View File

@ -1105,7 +1105,7 @@
* @xfrm_state_pol_flow_match: * @xfrm_state_pol_flow_match:
* @x contains the state to match. * @x contains the state to match.
* @xp contains the policy to check for a match. * @xp contains the policy to check for a match.
* @fl contains the flow to check for a match. * @flic contains the flowi_common struct to check for a match.
* Return 1 if there is a match. * Return 1 if there is a match.
* @xfrm_decode_session: * @xfrm_decode_session:
* @skb points to skb to decode. * @skb points to skb to decode.

View File

@ -167,7 +167,7 @@ struct sk_buff;
struct sock; struct sock;
struct sockaddr; struct sockaddr;
struct socket; struct socket;
struct flowi; struct flowi_common;
struct dst_entry; struct dst_entry;
struct xfrm_selector; struct xfrm_selector;
struct xfrm_policy; struct xfrm_policy;
@ -1355,8 +1355,9 @@ int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u
int security_sk_alloc(struct sock *sk, int family, gfp_t priority); int security_sk_alloc(struct sock *sk, int family, gfp_t priority);
void security_sk_free(struct sock *sk); void security_sk_free(struct sock *sk);
void security_sk_clone(const struct sock *sk, struct sock *newsk); void security_sk_clone(const struct sock *sk, struct sock *newsk);
void security_sk_classify_flow(struct sock *sk, struct flowi *fl); void security_sk_classify_flow(struct sock *sk, struct flowi_common *flic);
void security_req_classify_flow(const struct request_sock *req, struct flowi *fl); void security_req_classify_flow(const struct request_sock *req,
struct flowi_common *flic);
void security_sock_graft(struct sock*sk, struct socket *parent); void security_sock_graft(struct sock*sk, struct socket *parent);
int security_inet_conn_request(struct sock *sk, int security_inet_conn_request(struct sock *sk,
struct sk_buff *skb, struct request_sock *req); struct sk_buff *skb, struct request_sock *req);
@ -1507,11 +1508,13 @@ static inline void security_sk_clone(const struct sock *sk, struct sock *newsk)
{ {
} }
static inline void security_sk_classify_flow(struct sock *sk, struct flowi *fl) static inline void security_sk_classify_flow(struct sock *sk,
struct flowi_common *flic)
{ {
} }
static inline void security_req_classify_flow(const struct request_sock *req, struct flowi *fl) static inline void security_req_classify_flow(const struct request_sock *req,
struct flowi_common *flic)
{ {
} }
@ -1638,9 +1641,9 @@ void security_xfrm_state_free(struct xfrm_state *x);
int security_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir); int security_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir);
int security_xfrm_state_pol_flow_match(struct xfrm_state *x, int security_xfrm_state_pol_flow_match(struct xfrm_state *x,
struct xfrm_policy *xp, struct xfrm_policy *xp,
const struct flowi *fl); const struct flowi_common *flic);
int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid); int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid);
void security_skb_classify_flow(struct sk_buff *skb, struct flowi *fl); void security_skb_classify_flow(struct sk_buff *skb, struct flowi_common *flic);
#else /* CONFIG_SECURITY_NETWORK_XFRM */ #else /* CONFIG_SECURITY_NETWORK_XFRM */
@ -1692,7 +1695,8 @@ static inline int security_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_s
} }
static inline int security_xfrm_state_pol_flow_match(struct xfrm_state *x, static inline int security_xfrm_state_pol_flow_match(struct xfrm_state *x,
struct xfrm_policy *xp, const struct flowi *fl) struct xfrm_policy *xp,
const struct flowi_common *flic)
{ {
return 1; return 1;
} }
@ -1702,7 +1706,8 @@ static inline int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid)
return 0; return 0;
} }
static inline void security_skb_classify_flow(struct sk_buff *skb, struct flowi *fl) static inline void security_skb_classify_flow(struct sk_buff *skb,
struct flowi_common *flic)
{ {
} }

View File

@ -195,11 +195,21 @@ static inline struct flowi *flowi4_to_flowi(struct flowi4 *fl4)
return container_of(fl4, struct flowi, u.ip4); return container_of(fl4, struct flowi, u.ip4);
} }
static inline struct flowi_common *flowi4_to_flowi_common(struct flowi4 *fl4)
{
return &(flowi4_to_flowi(fl4)->u.__fl_common);
}
static inline struct flowi *flowi6_to_flowi(struct flowi6 *fl6) static inline struct flowi *flowi6_to_flowi(struct flowi6 *fl6)
{ {
return container_of(fl6, struct flowi, u.ip6); return container_of(fl6, struct flowi, u.ip6);
} }
static inline struct flowi_common *flowi6_to_flowi_common(struct flowi6 *fl6)
{
return &(flowi6_to_flowi(fl6)->u.__fl_common);
}
static inline struct flowi *flowidn_to_flowi(struct flowidn *fldn) static inline struct flowi *flowidn_to_flowi(struct flowidn *fldn)
{ {
return container_of(fldn, struct flowi, u.dn); return container_of(fldn, struct flowi, u.dn);

View File

@ -165,7 +165,7 @@ static inline struct rtable *ip_route_output_ports(struct net *net, struct flowi
sk ? inet_sk_flowi_flags(sk) : 0, sk ? inet_sk_flowi_flags(sk) : 0,
daddr, saddr, dport, sport, sock_net_uid(net, sk)); daddr, saddr, dport, sport, sock_net_uid(net, sk));
if (sk) if (sk)
security_sk_classify_flow(sk, flowi4_to_flowi(fl4)); security_sk_classify_flow(sk, flowi4_to_flowi_common(fl4));
return ip_route_output_flow(net, fl4, sk); return ip_route_output_flow(net, fl4, sk);
} }
@ -322,7 +322,7 @@ static inline struct rtable *ip_route_connect(struct flowi4 *fl4,
ip_rt_put(rt); ip_rt_put(rt);
flowi4_update_output(fl4, oif, tos, fl4->daddr, fl4->saddr); flowi4_update_output(fl4, oif, tos, fl4->daddr, fl4->saddr);
} }
security_sk_classify_flow(sk, flowi4_to_flowi(fl4)); security_sk_classify_flow(sk, flowi4_to_flowi_common(fl4));
return ip_route_output_flow(net, fl4, sk); return ip_route_output_flow(net, fl4, sk);
} }
@ -338,7 +338,7 @@ static inline struct rtable *ip_route_newports(struct flowi4 *fl4, struct rtable
flowi4_update_output(fl4, sk->sk_bound_dev_if, flowi4_update_output(fl4, sk->sk_bound_dev_if,
RT_CONN_FLAGS(sk), fl4->daddr, RT_CONN_FLAGS(sk), fl4->daddr,
fl4->saddr); fl4->saddr);
security_sk_classify_flow(sk, flowi4_to_flowi(fl4)); security_sk_classify_flow(sk, flowi4_to_flowi_common(fl4));
return ip_route_output_flow(sock_net(sk), fl4, sk); return ip_route_output_flow(sock_net(sk), fl4, sk);
} }
return rt; return rt;

View File

@ -464,7 +464,7 @@ static struct dst_entry* dccp_v4_route_skb(struct net *net, struct sock *sk,
.fl4_dport = dccp_hdr(skb)->dccph_sport, .fl4_dport = dccp_hdr(skb)->dccph_sport,
}; };
security_skb_classify_flow(skb, flowi4_to_flowi(&fl4)); security_skb_classify_flow(skb, flowi4_to_flowi_common(&fl4));
rt = ip_route_output_flow(net, &fl4, sk); rt = ip_route_output_flow(net, &fl4, sk);
if (IS_ERR(rt)) { if (IS_ERR(rt)) {
IP_INC_STATS(net, IPSTATS_MIB_OUTNOROUTES); IP_INC_STATS(net, IPSTATS_MIB_OUTNOROUTES);

View File

@ -203,7 +203,7 @@ static int dccp_v6_send_response(const struct sock *sk, struct request_sock *req
fl6.flowi6_oif = ireq->ir_iif; fl6.flowi6_oif = ireq->ir_iif;
fl6.fl6_dport = ireq->ir_rmt_port; fl6.fl6_dport = ireq->ir_rmt_port;
fl6.fl6_sport = htons(ireq->ir_num); fl6.fl6_sport = htons(ireq->ir_num);
security_req_classify_flow(req, flowi6_to_flowi(&fl6)); security_req_classify_flow(req, flowi6_to_flowi_common(&fl6));
rcu_read_lock(); rcu_read_lock();
@ -279,7 +279,7 @@ static void dccp_v6_ctl_send_reset(const struct sock *sk, struct sk_buff *rxskb)
fl6.flowi6_oif = inet6_iif(rxskb); fl6.flowi6_oif = inet6_iif(rxskb);
fl6.fl6_dport = dccp_hdr(skb)->dccph_dport; fl6.fl6_dport = dccp_hdr(skb)->dccph_dport;
fl6.fl6_sport = dccp_hdr(skb)->dccph_sport; fl6.fl6_sport = dccp_hdr(skb)->dccph_sport;
security_skb_classify_flow(rxskb, flowi6_to_flowi(&fl6)); security_skb_classify_flow(rxskb, flowi6_to_flowi_common(&fl6));
/* sk = NULL, but it is safe for now. RST socket required. */ /* sk = NULL, but it is safe for now. RST socket required. */
dst = ip6_dst_lookup_flow(sock_net(ctl_sk), ctl_sk, &fl6, NULL); dst = ip6_dst_lookup_flow(sock_net(ctl_sk), ctl_sk, &fl6, NULL);
@ -907,7 +907,7 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
fl6.flowi6_oif = sk->sk_bound_dev_if; fl6.flowi6_oif = sk->sk_bound_dev_if;
fl6.fl6_dport = usin->sin6_port; fl6.fl6_dport = usin->sin6_port;
fl6.fl6_sport = inet->inet_sport; fl6.fl6_sport = inet->inet_sport;
security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); security_sk_classify_flow(sk, flowi6_to_flowi_common(&fl6));
opt = rcu_dereference_protected(np->opt, lockdep_sock_is_held(sk)); opt = rcu_dereference_protected(np->opt, lockdep_sock_is_held(sk));
final_p = fl6_update_dst(&fl6, opt, &final); final_p = fl6_update_dst(&fl6, opt, &final);

View File

@ -447,7 +447,7 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb)
fl4.flowi4_tos = RT_TOS(ip_hdr(skb)->tos); fl4.flowi4_tos = RT_TOS(ip_hdr(skb)->tos);
fl4.flowi4_proto = IPPROTO_ICMP; fl4.flowi4_proto = IPPROTO_ICMP;
fl4.flowi4_oif = l3mdev_master_ifindex(skb->dev); fl4.flowi4_oif = l3mdev_master_ifindex(skb->dev);
security_skb_classify_flow(skb, flowi4_to_flowi(&fl4)); security_skb_classify_flow(skb, flowi4_to_flowi_common(&fl4));
rt = ip_route_output_key(net, &fl4); rt = ip_route_output_key(net, &fl4);
if (IS_ERR(rt)) if (IS_ERR(rt))
goto out_unlock; goto out_unlock;
@ -503,7 +503,7 @@ static struct rtable *icmp_route_lookup(struct net *net,
route_lookup_dev = icmp_get_route_lookup_dev(skb_in); route_lookup_dev = icmp_get_route_lookup_dev(skb_in);
fl4->flowi4_oif = l3mdev_master_ifindex(route_lookup_dev); fl4->flowi4_oif = l3mdev_master_ifindex(route_lookup_dev);
security_skb_classify_flow(skb_in, flowi4_to_flowi(fl4)); security_skb_classify_flow(skb_in, flowi4_to_flowi_common(fl4));
rt = ip_route_output_key_hash(net, fl4, skb_in); rt = ip_route_output_key_hash(net, fl4, skb_in);
if (IS_ERR(rt)) if (IS_ERR(rt))
return rt; return rt;

View File

@ -602,7 +602,7 @@ struct dst_entry *inet_csk_route_req(const struct sock *sk,
(opt && opt->opt.srr) ? opt->opt.faddr : ireq->ir_rmt_addr, (opt && opt->opt.srr) ? opt->opt.faddr : ireq->ir_rmt_addr,
ireq->ir_loc_addr, ireq->ir_rmt_port, ireq->ir_loc_addr, ireq->ir_rmt_port,
htons(ireq->ir_num), sk->sk_uid); htons(ireq->ir_num), sk->sk_uid);
security_req_classify_flow(req, flowi4_to_flowi(fl4)); security_req_classify_flow(req, flowi4_to_flowi_common(fl4));
rt = ip_route_output_flow(net, fl4, sk); rt = ip_route_output_flow(net, fl4, sk);
if (IS_ERR(rt)) if (IS_ERR(rt))
goto no_route; goto no_route;
@ -640,7 +640,7 @@ struct dst_entry *inet_csk_route_child_sock(const struct sock *sk,
(opt && opt->opt.srr) ? opt->opt.faddr : ireq->ir_rmt_addr, (opt && opt->opt.srr) ? opt->opt.faddr : ireq->ir_rmt_addr,
ireq->ir_loc_addr, ireq->ir_rmt_port, ireq->ir_loc_addr, ireq->ir_rmt_port,
htons(ireq->ir_num), sk->sk_uid); htons(ireq->ir_num), sk->sk_uid);
security_req_classify_flow(req, flowi4_to_flowi(fl4)); security_req_classify_flow(req, flowi4_to_flowi_common(fl4));
rt = ip_route_output_flow(net, fl4, sk); rt = ip_route_output_flow(net, fl4, sk);
if (IS_ERR(rt)) if (IS_ERR(rt))
goto no_route; goto no_route;

View File

@ -1700,7 +1700,7 @@ void ip_send_unicast_reply(struct sock *sk, struct sk_buff *skb,
daddr, saddr, daddr, saddr,
tcp_hdr(skb)->source, tcp_hdr(skb)->dest, tcp_hdr(skb)->source, tcp_hdr(skb)->dest,
arg->uid); arg->uid);
security_skb_classify_flow(skb, flowi4_to_flowi(&fl4)); security_skb_classify_flow(skb, flowi4_to_flowi_common(&fl4));
rt = ip_route_output_key(net, &fl4); rt = ip_route_output_key(net, &fl4);
if (IS_ERR(rt)) if (IS_ERR(rt))
return; return;

View File

@ -778,7 +778,7 @@ static int ping_v4_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
fl4.fl4_icmp_type = user_icmph.type; fl4.fl4_icmp_type = user_icmph.type;
fl4.fl4_icmp_code = user_icmph.code; fl4.fl4_icmp_code = user_icmph.code;
security_sk_classify_flow(sk, flowi4_to_flowi(&fl4)); security_sk_classify_flow(sk, flowi4_to_flowi_common(&fl4));
rt = ip_route_output_flow(net, &fl4, sk); rt = ip_route_output_flow(net, &fl4, sk);
if (IS_ERR(rt)) { if (IS_ERR(rt)) {
err = PTR_ERR(rt); err = PTR_ERR(rt);

View File

@ -640,7 +640,7 @@ static int raw_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
goto done; goto done;
} }
security_sk_classify_flow(sk, flowi4_to_flowi(&fl4)); security_sk_classify_flow(sk, flowi4_to_flowi_common(&fl4));
rt = ip_route_output_flow(net, &fl4, sk); rt = ip_route_output_flow(net, &fl4, sk);
if (IS_ERR(rt)) { if (IS_ERR(rt)) {
err = PTR_ERR(rt); err = PTR_ERR(rt);

View File

@ -418,7 +418,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb)
inet_sk_flowi_flags(sk), inet_sk_flowi_flags(sk),
opt->srr ? opt->faddr : ireq->ir_rmt_addr, opt->srr ? opt->faddr : ireq->ir_rmt_addr,
ireq->ir_loc_addr, th->source, th->dest, sk->sk_uid); ireq->ir_loc_addr, th->source, th->dest, sk->sk_uid);
security_req_classify_flow(req, flowi4_to_flowi(&fl4)); security_req_classify_flow(req, flowi4_to_flowi_common(&fl4));
rt = ip_route_output_key(sock_net(sk), &fl4); rt = ip_route_output_key(sock_net(sk), &fl4);
if (IS_ERR(rt)) { if (IS_ERR(rt)) {
reqsk_free(req); reqsk_free(req);

View File

@ -1197,7 +1197,7 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
faddr, saddr, dport, inet->inet_sport, faddr, saddr, dport, inet->inet_sport,
sk->sk_uid); sk->sk_uid);
security_sk_classify_flow(sk, flowi4_to_flowi(fl4)); security_sk_classify_flow(sk, flowi4_to_flowi_common(fl4));
rt = ip_route_output_flow(net, fl4, sk); rt = ip_route_output_flow(net, fl4, sk);
if (IS_ERR(rt)) { if (IS_ERR(rt)) {
err = PTR_ERR(rt); err = PTR_ERR(rt);

View File

@ -819,7 +819,7 @@ int inet6_sk_rebuild_header(struct sock *sk)
fl6.fl6_dport = inet->inet_dport; fl6.fl6_dport = inet->inet_dport;
fl6.fl6_sport = inet->inet_sport; fl6.fl6_sport = inet->inet_sport;
fl6.flowi6_uid = sk->sk_uid; fl6.flowi6_uid = sk->sk_uid;
security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); security_sk_classify_flow(sk, flowi6_to_flowi_common(&fl6));
rcu_read_lock(); rcu_read_lock();
final_p = fl6_update_dst(&fl6, rcu_dereference(np->opt), final_p = fl6_update_dst(&fl6, rcu_dereference(np->opt),

View File

@ -60,7 +60,7 @@ static void ip6_datagram_flow_key_init(struct flowi6 *fl6, struct sock *sk)
if (!fl6->flowi6_oif && ipv6_addr_is_multicast(&fl6->daddr)) if (!fl6->flowi6_oif && ipv6_addr_is_multicast(&fl6->daddr))
fl6->flowi6_oif = np->mcast_oif; fl6->flowi6_oif = np->mcast_oif;
security_sk_classify_flow(sk, flowi6_to_flowi(fl6)); security_sk_classify_flow(sk, flowi6_to_flowi_common(fl6));
} }
int ip6_datagram_dst_update(struct sock *sk, bool fix_sk_saddr) int ip6_datagram_dst_update(struct sock *sk, bool fix_sk_saddr)

View File

@ -567,7 +567,7 @@ void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info,
fl6.fl6_icmp_code = code; fl6.fl6_icmp_code = code;
fl6.flowi6_uid = sock_net_uid(net, NULL); fl6.flowi6_uid = sock_net_uid(net, NULL);
fl6.mp_hash = rt6_multipath_hash(net, &fl6, skb, NULL); fl6.mp_hash = rt6_multipath_hash(net, &fl6, skb, NULL);
security_skb_classify_flow(skb, flowi6_to_flowi(&fl6)); security_skb_classify_flow(skb, flowi6_to_flowi_common(&fl6));
np = inet6_sk(sk); np = inet6_sk(sk);
@ -749,7 +749,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
fl6.fl6_icmp_type = ICMPV6_ECHO_REPLY; fl6.fl6_icmp_type = ICMPV6_ECHO_REPLY;
fl6.flowi6_mark = mark; fl6.flowi6_mark = mark;
fl6.flowi6_uid = sock_net_uid(net, NULL); fl6.flowi6_uid = sock_net_uid(net, NULL);
security_skb_classify_flow(skb, flowi6_to_flowi(&fl6)); security_skb_classify_flow(skb, flowi6_to_flowi_common(&fl6));
local_bh_disable(); local_bh_disable();
sk = icmpv6_xmit_lock(net); sk = icmpv6_xmit_lock(net);
@ -1002,7 +1002,7 @@ void icmpv6_flow_init(struct sock *sk, struct flowi6 *fl6,
fl6->fl6_icmp_type = type; fl6->fl6_icmp_type = type;
fl6->fl6_icmp_code = 0; fl6->fl6_icmp_code = 0;
fl6->flowi6_oif = oif; fl6->flowi6_oif = oif;
security_sk_classify_flow(sk, flowi6_to_flowi(fl6)); security_sk_classify_flow(sk, flowi6_to_flowi_common(fl6));
} }
static void __net_exit icmpv6_sk_exit(struct net *net) static void __net_exit icmpv6_sk_exit(struct net *net)

View File

@ -46,7 +46,7 @@ struct dst_entry *inet6_csk_route_req(const struct sock *sk,
fl6->fl6_dport = ireq->ir_rmt_port; fl6->fl6_dport = ireq->ir_rmt_port;
fl6->fl6_sport = htons(ireq->ir_num); fl6->fl6_sport = htons(ireq->ir_num);
fl6->flowi6_uid = sk->sk_uid; fl6->flowi6_uid = sk->sk_uid;
security_req_classify_flow(req, flowi6_to_flowi(fl6)); security_req_classify_flow(req, flowi6_to_flowi_common(fl6));
dst = ip6_dst_lookup_flow(sock_net(sk), sk, fl6, final_p); dst = ip6_dst_lookup_flow(sock_net(sk), sk, fl6, final_p);
if (IS_ERR(dst)) if (IS_ERR(dst))
@ -95,7 +95,7 @@ static struct dst_entry *inet6_csk_route_socket(struct sock *sk,
fl6->fl6_sport = inet->inet_sport; fl6->fl6_sport = inet->inet_sport;
fl6->fl6_dport = inet->inet_dport; fl6->fl6_dport = inet->inet_dport;
fl6->flowi6_uid = sk->sk_uid; fl6->flowi6_uid = sk->sk_uid;
security_sk_classify_flow(sk, flowi6_to_flowi(fl6)); security_sk_classify_flow(sk, flowi6_to_flowi_common(fl6));
rcu_read_lock(); rcu_read_lock();
final_p = fl6_update_dst(fl6, rcu_dereference(np->opt), &final); final_p = fl6_update_dst(fl6, rcu_dereference(np->opt), &final);

View File

@ -179,7 +179,7 @@ void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook)
fl6.flowi6_oif = l3mdev_master_ifindex(skb_dst(oldskb)->dev); fl6.flowi6_oif = l3mdev_master_ifindex(skb_dst(oldskb)->dev);
fl6.flowi6_mark = IP6_REPLY_MARK(net, oldskb->mark); fl6.flowi6_mark = IP6_REPLY_MARK(net, oldskb->mark);
security_skb_classify_flow(oldskb, flowi6_to_flowi(&fl6)); security_skb_classify_flow(oldskb, flowi6_to_flowi_common(&fl6));
dst = ip6_route_output(net, NULL, &fl6); dst = ip6_route_output(net, NULL, &fl6);
if (dst->error) { if (dst->error) {
dst_release(dst); dst_release(dst);

View File

@ -111,7 +111,7 @@ static int ping_v6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
fl6.flowi6_uid = sk->sk_uid; fl6.flowi6_uid = sk->sk_uid;
fl6.fl6_icmp_type = user_icmph.icmp6_type; fl6.fl6_icmp_type = user_icmph.icmp6_type;
fl6.fl6_icmp_code = user_icmph.icmp6_code; fl6.fl6_icmp_code = user_icmph.icmp6_code;
security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); security_sk_classify_flow(sk, flowi6_to_flowi_common(&fl6));
ipcm6_init_sk(&ipc6, np); ipcm6_init_sk(&ipc6, np);
ipc6.sockc.mark = sk->sk_mark; ipc6.sockc.mark = sk->sk_mark;

View File

@ -915,7 +915,7 @@ static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
fl6.flowi6_oif = np->mcast_oif; fl6.flowi6_oif = np->mcast_oif;
else if (!fl6.flowi6_oif) else if (!fl6.flowi6_oif)
fl6.flowi6_oif = np->ucast_oif; fl6.flowi6_oif = np->ucast_oif;
security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); security_sk_classify_flow(sk, flowi6_to_flowi_common(&fl6));
if (hdrincl) if (hdrincl)
fl6.flowi6_flags |= FLOWI_FLAG_KNOWN_NH; fl6.flowi6_flags |= FLOWI_FLAG_KNOWN_NH;

View File

@ -233,7 +233,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
fl6.fl6_dport = ireq->ir_rmt_port; fl6.fl6_dport = ireq->ir_rmt_port;
fl6.fl6_sport = inet_sk(sk)->inet_sport; fl6.fl6_sport = inet_sk(sk)->inet_sport;
fl6.flowi6_uid = sk->sk_uid; fl6.flowi6_uid = sk->sk_uid;
security_req_classify_flow(req, flowi6_to_flowi(&fl6)); security_req_classify_flow(req, flowi6_to_flowi_common(&fl6));
dst = ip6_dst_lookup_flow(sock_net(sk), sk, &fl6, final_p); dst = ip6_dst_lookup_flow(sock_net(sk), sk, &fl6, final_p);
if (IS_ERR(dst)) if (IS_ERR(dst))

View File

@ -278,7 +278,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
opt = rcu_dereference_protected(np->opt, lockdep_sock_is_held(sk)); opt = rcu_dereference_protected(np->opt, lockdep_sock_is_held(sk));
final_p = fl6_update_dst(&fl6, opt, &final); final_p = fl6_update_dst(&fl6, opt, &final);
security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); security_sk_classify_flow(sk, flowi6_to_flowi_common(&fl6));
dst = ip6_dst_lookup_flow(sock_net(sk), sk, &fl6, final_p); dst = ip6_dst_lookup_flow(sock_net(sk), sk, &fl6, final_p);
if (IS_ERR(dst)) { if (IS_ERR(dst)) {
@ -954,7 +954,7 @@ static void tcp_v6_send_response(const struct sock *sk, struct sk_buff *skb, u32
fl6.fl6_dport = t1->dest; fl6.fl6_dport = t1->dest;
fl6.fl6_sport = t1->source; fl6.fl6_sport = t1->source;
fl6.flowi6_uid = sock_net_uid(net, sk && sk_fullsock(sk) ? sk : NULL); fl6.flowi6_uid = sock_net_uid(net, sk && sk_fullsock(sk) ? sk : NULL);
security_skb_classify_flow(skb, flowi6_to_flowi(&fl6)); security_skb_classify_flow(skb, flowi6_to_flowi_common(&fl6));
/* Pass a socket to ip6_dst_lookup either it is for RST /* Pass a socket to ip6_dst_lookup either it is for RST
* Underlying function will use this to retrieve the network * Underlying function will use this to retrieve the network

View File

@ -1496,7 +1496,7 @@ do_udp_sendmsg:
} else if (!fl6.flowi6_oif) } else if (!fl6.flowi6_oif)
fl6.flowi6_oif = np->ucast_oif; fl6.flowi6_oif = np->ucast_oif;
security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); security_sk_classify_flow(sk, flowi6_to_flowi_common(&fl6));
if (ipc6.tclass < 0) if (ipc6.tclass < 0)
ipc6.tclass = np->tclass; ipc6.tclass = np->tclass;

View File

@ -606,7 +606,7 @@ static int l2tp_ip6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
else if (!fl6.flowi6_oif) else if (!fl6.flowi6_oif)
fl6.flowi6_oif = np->ucast_oif; fl6.flowi6_oif = np->ucast_oif;
security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); security_sk_classify_flow(sk, flowi6_to_flowi_common(&fl6));
if (ipc6.tclass < 0) if (ipc6.tclass < 0)
ipc6.tclass = np->tclass; ipc6.tclass = np->tclass;

View File

@ -849,7 +849,7 @@ synproxy_send_tcp_ipv6(struct net *net,
fl6.fl6_sport = nth->source; fl6.fl6_sport = nth->source;
fl6.fl6_dport = nth->dest; fl6.fl6_dport = nth->dest;
security_skb_classify_flow((struct sk_buff *)skb, security_skb_classify_flow((struct sk_buff *)skb,
flowi6_to_flowi(&fl6)); flowi6_to_flowi_common(&fl6));
err = nf_ip6_route(net, &dst, flowi6_to_flowi(&fl6), false); err = nf_ip6_route(net, &dst, flowi6_to_flowi(&fl6), false);
if (err) { if (err) {
goto free_nskb; goto free_nskb;

View File

@ -1021,7 +1021,8 @@ static void xfrm_state_look_at(struct xfrm_policy *pol, struct xfrm_state *x,
if ((x->sel.family && if ((x->sel.family &&
(x->sel.family != family || (x->sel.family != family ||
!xfrm_selector_match(&x->sel, fl, family))) || !xfrm_selector_match(&x->sel, fl, family))) ||
!security_xfrm_state_pol_flow_match(x, pol, fl)) !security_xfrm_state_pol_flow_match(x, pol,
&fl->u.__fl_common))
return; return;
if (!*best || if (!*best ||
@ -1036,7 +1037,8 @@ static void xfrm_state_look_at(struct xfrm_policy *pol, struct xfrm_state *x,
if ((!x->sel.family || if ((!x->sel.family ||
(x->sel.family == family && (x->sel.family == family &&
xfrm_selector_match(&x->sel, fl, family))) && xfrm_selector_match(&x->sel, fl, family))) &&
security_xfrm_state_pol_flow_match(x, pol, fl)) security_xfrm_state_pol_flow_match(x, pol,
&fl->u.__fl_common))
*error = -ESRCH; *error = -ESRCH;
} }
} }

View File

@ -2207,15 +2207,16 @@ void security_sk_clone(const struct sock *sk, struct sock *newsk)
} }
EXPORT_SYMBOL(security_sk_clone); EXPORT_SYMBOL(security_sk_clone);
void security_sk_classify_flow(struct sock *sk, struct flowi *fl) void security_sk_classify_flow(struct sock *sk, struct flowi_common *flic)
{ {
call_void_hook(sk_getsecid, sk, &fl->flowi_secid); call_void_hook(sk_getsecid, sk, &flic->flowic_secid);
} }
EXPORT_SYMBOL(security_sk_classify_flow); EXPORT_SYMBOL(security_sk_classify_flow);
void security_req_classify_flow(const struct request_sock *req, struct flowi *fl) void security_req_classify_flow(const struct request_sock *req,
struct flowi_common *flic)
{ {
call_void_hook(req_classify_flow, req, fl); call_void_hook(req_classify_flow, req, flic);
} }
EXPORT_SYMBOL(security_req_classify_flow); EXPORT_SYMBOL(security_req_classify_flow);
@ -2407,7 +2408,7 @@ int security_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir)
int security_xfrm_state_pol_flow_match(struct xfrm_state *x, int security_xfrm_state_pol_flow_match(struct xfrm_state *x,
struct xfrm_policy *xp, struct xfrm_policy *xp,
const struct flowi *fl) const struct flowi_common *flic)
{ {
struct security_hook_list *hp; struct security_hook_list *hp;
int rc = LSM_RET_DEFAULT(xfrm_state_pol_flow_match); int rc = LSM_RET_DEFAULT(xfrm_state_pol_flow_match);
@ -2423,7 +2424,7 @@ int security_xfrm_state_pol_flow_match(struct xfrm_state *x,
*/ */
hlist_for_each_entry(hp, &security_hook_heads.xfrm_state_pol_flow_match, hlist_for_each_entry(hp, &security_hook_heads.xfrm_state_pol_flow_match,
list) { list) {
rc = hp->hook.xfrm_state_pol_flow_match(x, xp, fl); rc = hp->hook.xfrm_state_pol_flow_match(x, xp, flic);
break; break;
} }
return rc; return rc;
@ -2434,9 +2435,9 @@ int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid)
return call_int_hook(xfrm_decode_session, 0, skb, secid, 1); return call_int_hook(xfrm_decode_session, 0, skb, secid, 1);
} }
void security_skb_classify_flow(struct sk_buff *skb, struct flowi *fl) void security_skb_classify_flow(struct sk_buff *skb, struct flowi_common *flic)
{ {
int rc = call_int_hook(xfrm_decode_session, 0, skb, &fl->flowi_secid, int rc = call_int_hook(xfrm_decode_session, 0, skb, &flic->flowic_secid,
0); 0);
BUG_ON(rc); BUG_ON(rc);

View File

@ -5437,9 +5437,9 @@ static void selinux_secmark_refcount_dec(void)
} }
static void selinux_req_classify_flow(const struct request_sock *req, static void selinux_req_classify_flow(const struct request_sock *req,
struct flowi *fl) struct flowi_common *flic)
{ {
fl->flowi_secid = req->secid; flic->flowic_secid = req->secid;
} }
static int selinux_tun_dev_alloc_security(void **security) static int selinux_tun_dev_alloc_security(void **security)

View File

@ -26,7 +26,7 @@ int selinux_xfrm_state_delete(struct xfrm_state *x);
int selinux_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir); int selinux_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir);
int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x,
struct xfrm_policy *xp, struct xfrm_policy *xp,
const struct flowi *fl); const struct flowi_common *flic);
#ifdef CONFIG_SECURITY_NETWORK_XFRM #ifdef CONFIG_SECURITY_NETWORK_XFRM
extern atomic_t selinux_xfrm_refcount; extern atomic_t selinux_xfrm_refcount;

View File

@ -175,9 +175,10 @@ int selinux_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir)
*/ */
int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x,
struct xfrm_policy *xp, struct xfrm_policy *xp,
const struct flowi *fl) const struct flowi_common *flic)
{ {
u32 state_sid; u32 state_sid;
u32 flic_sid;
if (!xp->security) if (!xp->security)
if (x->security) if (x->security)
@ -196,17 +197,17 @@ int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x,
return 0; return 0;
state_sid = x->security->ctx_sid; state_sid = x->security->ctx_sid;
flic_sid = flic->flowic_secid;
if (fl->flowi_secid != state_sid) if (flic_sid != state_sid)
return 0; return 0;
/* We don't need a separate SA Vs. policy polmatch check since the SA /* We don't need a separate SA Vs. policy polmatch check since the SA
* is now of the same label as the flow and a flow Vs. policy polmatch * is now of the same label as the flow and a flow Vs. policy polmatch
* check had already happened in selinux_xfrm_policy_lookup() above. */ * check had already happened in selinux_xfrm_policy_lookup() above. */
return (avc_has_perm(&selinux_state, return (avc_has_perm(&selinux_state, flic_sid, state_sid,
fl->flowi_secid, state_sid, SECCLASS_ASSOCIATION, ASSOCIATION__SENDTO,
SECCLASS_ASSOCIATION, ASSOCIATION__SENDTO, NULL) ? 0 : 1);
NULL) ? 0 : 1);
} }
static u32 selinux_xfrm_skb_sid_egress(struct sk_buff *skb) static u32 selinux_xfrm_skb_sid_egress(struct sk_buff *skb)