Skip to content

Commit ce9b766

Browse files
klassertgregkh
authored andcommitted
xfrm: Don't use sk_family for socket policy lookups
commit 4c86d77743a54fb2d8a4d18a037a074c892bb3be upstream. On IPv4-mapped IPv6 addresses sk_family is AF_INET6, but the flow informations are created based on AF_INET. So the routing set up 'struct flowi4' but we try to access 'struct flowi6' what leads to an out of bounds access. Fix this by using the family we get with the dst_entry, like we do it for the standard policy lookup. Reported-by: Dmitry Vyukov <dvyukov@google.com> Tested-by: Dmitry Vyukov <dvyukov@google.com> Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 4b8adea commit ce9b766

1 file changed

Lines changed: 4 additions & 5 deletions

File tree

net/xfrm/xfrm_policy.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1216,7 +1216,7 @@ static inline int policy_to_flow_dir(int dir)
12161216
}
12171217

12181218
static struct xfrm_policy *xfrm_sk_policy_lookup(const struct sock *sk, int dir,
1219-
const struct flowi *fl)
1219+
const struct flowi *fl, u16 family)
12201220
{
12211221
struct xfrm_policy *pol;
12221222
struct net *net = sock_net(sk);
@@ -1225,8 +1225,7 @@ static struct xfrm_policy *xfrm_sk_policy_lookup(const struct sock *sk, int dir,
12251225
read_lock_bh(&net->xfrm.xfrm_policy_lock);
12261226
pol = rcu_dereference(sk->sk_policy[dir]);
12271227
if (pol != NULL) {
1228-
bool match = xfrm_selector_match(&pol->selector, fl,
1229-
sk->sk_family);
1228+
bool match = xfrm_selector_match(&pol->selector, fl, family);
12301229
int err = 0;
12311230

12321231
if (match) {
@@ -2174,7 +2173,7 @@ struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig,
21742173
sk = sk_const_to_full_sk(sk);
21752174
if (sk && sk->sk_policy[XFRM_POLICY_OUT]) {
21762175
num_pols = 1;
2177-
pols[0] = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl);
2176+
pols[0] = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl, family);
21782177
err = xfrm_expand_policies(fl, family, pols,
21792178
&num_pols, &num_xfrms);
21802179
if (err < 0)
@@ -2453,7 +2452,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
24532452
pol = NULL;
24542453
sk = sk_to_full_sk(sk);
24552454
if (sk && sk->sk_policy[dir]) {
2456-
pol = xfrm_sk_policy_lookup(sk, dir, &fl);
2455+
pol = xfrm_sk_policy_lookup(sk, dir, &fl, family);
24572456
if (IS_ERR(pol)) {
24582457
XFRM_INC_STATS(net, LINUX_MIB_XFRMINPOLERROR);
24592458
return 0;

0 commit comments

Comments
 (0)