mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-16 17:57:38 -04:00
Merge tag 'ipsec-2026-06-22' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec
Steffen Klassert says: ==================== pull request (net): ipsec 2026-06-22 1) xfrm: use compat translator only for u64 alignment mismatch Gate the XFRM_USER_COMPAT translator on COMPAT_FOR_U64_ALIGNMENT so 32-bit compat tasks on arches whose 32-bit ABI already matches the native 64-bit layout are no longer rejected with -EOPNOTSUPP. From Sanman Pradhan. 2) net: af_key: initialize alg_key_len for IPComp states Initialize the alg_key_len to 0 in the IPComp branch of pfkey_msg2xfrm_state() so an uninitialized value cannot drive xfrm_alg_len() into a slab-out-of-bounds kmemdup during XFRM_MSG_MIGRATE. From Zijing Yin. 3) xfrm: Fix dev use-after-free in xfrm async resumption Stash the original skb->dev and extend the RCU critical section across xfrm_rcv_cb() and transport_finish() to prevent a tunnel-device UAF and original-device refcount leak when a callback replaces skb->dev. From Dong Chenchen. 4) xfrm: Fix xfrm state cache insertion race Move the state-validity check inside xfrm_state_lock in the input state cache insertion path so a state cannot be killed between the check and the insert. From Herbert Xu. 5) xfrm: annotate data-races around xfrm_policy_count[] and xfrm_policy_default[] Add READ_ONCE()/WRITE_ONCE() annotations on xfrm_policy_count and xfrm_policy_default to silence the KCSAN data race reported on net->xfrm.policy_count. From Eric Dumazet. 6) espintcp: use sk_msg_free_partial to fix partial send Replace the manual skmsg accounting in espintcp with sk_msg_free_partial() so the skmsg stays consistent on every iteration and the partial-send accounting bugs go away. From Sabrina Dubroca. 7) xfrm: validate selector family and prefixlen during match Reject mismatched address families in xfrm_selector_match() and bound prefixlen in addr4_match()/addr_match() to prevent the shift-out-of-bounds syzbot reported when an AF_UNSPEC selector with a large prefixlen is matched against an IPv4 flow. From Eric Dumazet. * tag 'ipsec-2026-06-22' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec: xfrm: validate selector family and prefixlen during match espintcp: use sk_msg_free_partial to fix partial send xfrm: annotate data-races around xfrm_policy_count[] and xfrm_policy_default[] xfrm: Fix xfrm state cache insertion race xfrm: Fix dev use-after-free in xfrm async resumption net: af_key: initialize alg_key_len for IPComp states xfrm: use compat translator only for u64 alignment mismatch ==================== Link: https://patch.msgid.link/20260622075726.29685-1-steffen.klassert@secunet.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
@@ -953,6 +953,9 @@ static inline bool addr_match(const void *token1, const void *token2,
|
||||
unsigned int pdw;
|
||||
unsigned int pbi;
|
||||
|
||||
if (prefixlen > 128)
|
||||
return false;
|
||||
|
||||
pdw = prefixlen >> 5; /* num of whole u32 in prefix */
|
||||
pbi = prefixlen & 0x1f; /* num of bits in incomplete u32 in prefix */
|
||||
|
||||
@@ -977,6 +980,10 @@ static inline bool addr4_match(__be32 a1, __be32 a2, u8 prefixlen)
|
||||
/* C99 6.5.7 (3): u32 << 32 is undefined behaviour */
|
||||
if (sizeof(long) == 4 && prefixlen == 0)
|
||||
return true;
|
||||
|
||||
if (prefixlen > 32)
|
||||
return false;
|
||||
|
||||
return !((a1 ^ a2) & htonl(~0UL << (32 - prefixlen)));
|
||||
}
|
||||
|
||||
@@ -1260,8 +1267,8 @@ int __xfrm_policy_check(struct sock *, int dir, struct sk_buff *skb,
|
||||
static inline bool __xfrm_check_nopolicy(struct net *net, struct sk_buff *skb,
|
||||
int dir)
|
||||
{
|
||||
if (!net->xfrm.policy_count[dir] && !secpath_exists(skb))
|
||||
return net->xfrm.policy_default[dir] == XFRM_USERPOLICY_ACCEPT;
|
||||
if (!READ_ONCE(net->xfrm.policy_count[dir]) && !secpath_exists(skb))
|
||||
return READ_ONCE(net->xfrm.policy_default[dir]) == XFRM_USERPOLICY_ACCEPT;
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -1361,8 +1368,8 @@ static inline int xfrm_route_forward(struct sk_buff *skb, unsigned short family)
|
||||
{
|
||||
struct net *net = dev_net(skb->dev);
|
||||
|
||||
if (!net->xfrm.policy_count[XFRM_POLICY_OUT] &&
|
||||
net->xfrm.policy_default[XFRM_POLICY_OUT] == XFRM_USERPOLICY_ACCEPT)
|
||||
if (!READ_ONCE(net->xfrm.policy_count[XFRM_POLICY_OUT]) &&
|
||||
READ_ONCE(net->xfrm.policy_default[XFRM_POLICY_OUT]) == XFRM_USERPOLICY_ACCEPT)
|
||||
return true;
|
||||
|
||||
return (skb_dst(skb)->flags & DST_NOXFRM) ||
|
||||
|
||||
@@ -76,8 +76,6 @@ int xfrm4_transport_finish(struct sk_buff *skb, int async)
|
||||
NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING,
|
||||
dev_net(dev), NULL, skb, dev, NULL,
|
||||
xfrm4_rcv_encap_finish);
|
||||
if (async)
|
||||
dev_put(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -71,8 +71,6 @@ int xfrm6_transport_finish(struct sk_buff *skb, int async)
|
||||
NF_HOOK(NFPROTO_IPV6, NF_INET_PRE_ROUTING,
|
||||
dev_net(dev), NULL, skb, dev, NULL,
|
||||
xfrm6_transport_finish2);
|
||||
if (async)
|
||||
dev_put(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1218,6 +1218,7 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net,
|
||||
goto out;
|
||||
}
|
||||
strcpy(x->calg->alg_name, a->name);
|
||||
x->calg->alg_key_len = 0;
|
||||
x->props.calgo = sa->sadb_sa_encrypt;
|
||||
} else {
|
||||
int keysize = 0;
|
||||
|
||||
@@ -212,43 +212,23 @@ static int espintcp_sendskmsg_locked(struct sock *sk,
|
||||
struct sk_msg *skmsg = &emsg->skmsg;
|
||||
bool more = flags & MSG_MORE;
|
||||
struct scatterlist *sg;
|
||||
int done = 0;
|
||||
int ret;
|
||||
|
||||
sg = &skmsg->sg.data[skmsg->sg.start];
|
||||
do {
|
||||
struct bio_vec bvec;
|
||||
size_t size = sg->length - emsg->offset;
|
||||
int offset = sg->offset + emsg->offset;
|
||||
struct page *p;
|
||||
|
||||
emsg->offset = 0;
|
||||
|
||||
sg = &skmsg->sg.data[skmsg->sg.start];
|
||||
if (sg_is_last(sg) && !more)
|
||||
msghdr.msg_flags &= ~MSG_MORE;
|
||||
|
||||
p = sg_page(sg);
|
||||
retry:
|
||||
bvec_set_page(&bvec, p, size, offset);
|
||||
iov_iter_bvec(&msghdr.msg_iter, ITER_SOURCE, &bvec, 1, size);
|
||||
ret = tcp_sendmsg_locked(sk, &msghdr, size);
|
||||
if (ret < 0) {
|
||||
emsg->offset = offset - sg->offset;
|
||||
skmsg->sg.start += done;
|
||||
bvec_set_page(&bvec, sg_page(sg), sg->length, sg->offset);
|
||||
iov_iter_bvec(&msghdr.msg_iter, ITER_SOURCE, &bvec, 1, sg->length);
|
||||
ret = tcp_sendmsg_locked(sk, &msghdr, sg->length);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ret != size) {
|
||||
offset += ret;
|
||||
size -= ret;
|
||||
goto retry;
|
||||
}
|
||||
|
||||
done++;
|
||||
put_page(p);
|
||||
sk_mem_uncharge(sk, sg->length);
|
||||
sg = sg_next(sg);
|
||||
} while (sg);
|
||||
sk_msg_free_partial(sk, skmsg, ret);
|
||||
} while (skmsg->sg.size);
|
||||
|
||||
memset(emsg, 0, sizeof(*emsg));
|
||||
|
||||
|
||||
@@ -467,6 +467,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
|
||||
{
|
||||
const struct xfrm_state_afinfo *afinfo;
|
||||
struct net *net = dev_net(skb->dev);
|
||||
struct net_device *dev = skb->dev;
|
||||
int err;
|
||||
__be32 seq;
|
||||
__be32 seq_hi;
|
||||
@@ -493,7 +494,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
|
||||
LINUX_MIB_XFRMINSTATEINVALID);
|
||||
|
||||
if (encap_type == -1)
|
||||
dev_put(skb->dev);
|
||||
dev_put(dev);
|
||||
goto drop;
|
||||
}
|
||||
|
||||
@@ -655,16 +656,16 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
|
||||
|
||||
if (!crypto_done) {
|
||||
spin_unlock(&x->lock);
|
||||
dev_hold(skb->dev);
|
||||
dev_hold(dev);
|
||||
|
||||
nexthdr = x->type->input(x, skb);
|
||||
if (nexthdr == -EINPROGRESS) {
|
||||
if (async)
|
||||
dev_put(skb->dev);
|
||||
dev_put(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
dev_put(skb->dev);
|
||||
dev_put(dev);
|
||||
spin_lock(&x->lock);
|
||||
}
|
||||
resume:
|
||||
@@ -699,7 +700,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
|
||||
err = xfrm_inner_mode_input(x, skb);
|
||||
if (err == -EINPROGRESS) {
|
||||
if (async)
|
||||
dev_put(skb->dev);
|
||||
dev_put(dev);
|
||||
return 0;
|
||||
} else if (err) {
|
||||
XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATEMODEERROR);
|
||||
@@ -726,9 +727,12 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
|
||||
crypto_done = false;
|
||||
} while (!err);
|
||||
|
||||
rcu_read_lock();
|
||||
err = xfrm_rcv_cb(skb, family, x->type->proto, 0);
|
||||
if (err)
|
||||
if (err) {
|
||||
rcu_read_unlock();
|
||||
goto drop;
|
||||
}
|
||||
|
||||
nf_reset_ct(skb);
|
||||
|
||||
@@ -739,8 +743,9 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
|
||||
if (skb_valid_dst(skb))
|
||||
skb_dst_drop(skb);
|
||||
if (async)
|
||||
dev_put(skb->dev);
|
||||
dev_put(dev);
|
||||
gro_cells_receive(&gro_cells, skb);
|
||||
rcu_read_unlock();
|
||||
return 0;
|
||||
} else {
|
||||
xo = xfrm_offload(skb);
|
||||
@@ -748,23 +753,21 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
|
||||
xfrm_gro = xo->flags & XFRM_GRO;
|
||||
|
||||
err = -EAFNOSUPPORT;
|
||||
rcu_read_lock();
|
||||
afinfo = xfrm_state_afinfo_get_rcu(x->props.family);
|
||||
if (likely(afinfo))
|
||||
err = afinfo->transport_finish(skb, xfrm_gro || async);
|
||||
rcu_read_unlock();
|
||||
if (xfrm_gro) {
|
||||
sp = skb_sec_path(skb);
|
||||
if (sp)
|
||||
sp->olen = 0;
|
||||
if (skb_valid_dst(skb))
|
||||
skb_dst_drop(skb);
|
||||
if (async)
|
||||
dev_put(skb->dev);
|
||||
gro_cells_receive(&gro_cells, skb);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (async)
|
||||
dev_put(dev);
|
||||
rcu_read_unlock();
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -772,7 +775,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
|
||||
spin_unlock(&x->lock);
|
||||
drop:
|
||||
if (async)
|
||||
dev_put(skb->dev);
|
||||
dev_put(dev);
|
||||
xfrm_rcv_cb(skb, family, x && x->type ? x->type->proto : nexthdr, -1);
|
||||
kfree_skb(skb);
|
||||
return 0;
|
||||
|
||||
@@ -242,6 +242,9 @@ __xfrm6_selector_match(const struct xfrm_selector *sel, const struct flowi *fl)
|
||||
bool xfrm_selector_match(const struct xfrm_selector *sel, const struct flowi *fl,
|
||||
unsigned short family)
|
||||
{
|
||||
if (family != sel->family && sel->family != AF_UNSPEC)
|
||||
return false;
|
||||
|
||||
switch (family) {
|
||||
case AF_INET:
|
||||
return __xfrm4_selector_match(sel, fl);
|
||||
@@ -685,7 +688,7 @@ static void xfrm_byidx_resize(struct net *net)
|
||||
|
||||
static inline int xfrm_bydst_should_resize(struct net *net, int dir, int *total)
|
||||
{
|
||||
unsigned int cnt = net->xfrm.policy_count[dir];
|
||||
unsigned int cnt = READ_ONCE(net->xfrm.policy_count[dir]);
|
||||
unsigned int hmask = net->xfrm.policy_bydst[dir].hmask;
|
||||
|
||||
if (total)
|
||||
@@ -711,12 +714,12 @@ static inline int xfrm_byidx_should_resize(struct net *net, int total)
|
||||
|
||||
void xfrm_spd_getinfo(struct net *net, struct xfrmk_spdinfo *si)
|
||||
{
|
||||
si->incnt = net->xfrm.policy_count[XFRM_POLICY_IN];
|
||||
si->outcnt = net->xfrm.policy_count[XFRM_POLICY_OUT];
|
||||
si->fwdcnt = net->xfrm.policy_count[XFRM_POLICY_FWD];
|
||||
si->inscnt = net->xfrm.policy_count[XFRM_POLICY_IN+XFRM_POLICY_MAX];
|
||||
si->outscnt = net->xfrm.policy_count[XFRM_POLICY_OUT+XFRM_POLICY_MAX];
|
||||
si->fwdscnt = net->xfrm.policy_count[XFRM_POLICY_FWD+XFRM_POLICY_MAX];
|
||||
si->incnt = READ_ONCE(net->xfrm.policy_count[XFRM_POLICY_IN]);
|
||||
si->outcnt = READ_ONCE(net->xfrm.policy_count[XFRM_POLICY_OUT]);
|
||||
si->fwdcnt = READ_ONCE(net->xfrm.policy_count[XFRM_POLICY_FWD]);
|
||||
si->inscnt = READ_ONCE(net->xfrm.policy_count[XFRM_POLICY_IN+XFRM_POLICY_MAX]);
|
||||
si->outscnt = READ_ONCE(net->xfrm.policy_count[XFRM_POLICY_OUT+XFRM_POLICY_MAX]);
|
||||
si->fwdscnt = READ_ONCE(net->xfrm.policy_count[XFRM_POLICY_FWD+XFRM_POLICY_MAX]);
|
||||
si->spdhcnt = net->xfrm.policy_idx_hmask;
|
||||
si->spdhmcnt = xfrm_policy_hashmax;
|
||||
}
|
||||
@@ -2318,7 +2321,7 @@ static void __xfrm_policy_link(struct xfrm_policy *pol, int dir)
|
||||
}
|
||||
|
||||
list_add(&pol->walk.all, &net->xfrm.policy_all);
|
||||
net->xfrm.policy_count[dir]++;
|
||||
WRITE_ONCE(net->xfrm.policy_count[dir], net->xfrm.policy_count[dir] + 1);
|
||||
xfrm_pol_hold(pol);
|
||||
}
|
||||
|
||||
@@ -2337,7 +2340,7 @@ static struct xfrm_policy *__xfrm_policy_unlink(struct xfrm_policy *pol,
|
||||
}
|
||||
|
||||
list_del_init(&pol->walk.all);
|
||||
net->xfrm.policy_count[dir]--;
|
||||
WRITE_ONCE(net->xfrm.policy_count[dir], net->xfrm.policy_count[dir] - 1);
|
||||
|
||||
return pol;
|
||||
}
|
||||
@@ -3222,7 +3225,7 @@ struct dst_entry *xfrm_lookup_with_ifid(struct net *net,
|
||||
|
||||
/* To accelerate a bit... */
|
||||
if (!if_id && ((dst_orig->flags & DST_NOXFRM) ||
|
||||
!net->xfrm.policy_count[XFRM_POLICY_OUT]))
|
||||
!READ_ONCE(net->xfrm.policy_count[XFRM_POLICY_OUT])))
|
||||
goto nopol;
|
||||
|
||||
xdst = xfrm_bundle_lookup(net, fl, family, dir, &xflo, if_id);
|
||||
@@ -3296,7 +3299,7 @@ struct dst_entry *xfrm_lookup_with_ifid(struct net *net,
|
||||
|
||||
nopol:
|
||||
if ((!dst_orig->dev || !(dst_orig->dev->flags & IFF_LOOPBACK)) &&
|
||||
net->xfrm.policy_default[dir] == XFRM_USERPOLICY_BLOCK) {
|
||||
READ_ONCE(net->xfrm.policy_default[dir]) == XFRM_USERPOLICY_BLOCK) {
|
||||
err = -EPERM;
|
||||
goto error;
|
||||
}
|
||||
@@ -3750,7 +3753,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
|
||||
const bool is_crypto_offload = sp &&
|
||||
(xfrm_input_state(skb)->xso.type == XFRM_DEV_OFFLOAD_CRYPTO);
|
||||
|
||||
if (net->xfrm.policy_default[dir] == XFRM_USERPOLICY_BLOCK) {
|
||||
if (READ_ONCE(net->xfrm.policy_default[dir]) == XFRM_USERPOLICY_BLOCK) {
|
||||
XFRM_INC_STATS(net, LINUX_MIB_XFRMINNOPOLS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1207,9 +1207,11 @@ struct xfrm_state *xfrm_input_state_lookup(struct net *net, u32 mark,
|
||||
struct hlist_head *state_cache_input;
|
||||
struct xfrm_state *x = NULL;
|
||||
|
||||
/* BH is always disabled on the input path. */
|
||||
lockdep_assert_in_softirq();
|
||||
|
||||
state_cache_input = raw_cpu_ptr(net->xfrm.state_cache_input);
|
||||
|
||||
rcu_read_lock();
|
||||
hlist_for_each_entry_rcu(x, state_cache_input, state_cache_input) {
|
||||
if (x->props.family != family ||
|
||||
x->id.spi != spi ||
|
||||
@@ -1227,20 +1229,25 @@ struct xfrm_state *xfrm_input_state_lookup(struct net *net, u32 mark,
|
||||
xfrm_hash_ptrs_get(net, &state_ptrs);
|
||||
|
||||
x = __xfrm_state_lookup(&state_ptrs, mark, daddr, spi, proto, family);
|
||||
|
||||
if (x && x->km.state == XFRM_STATE_VALID) {
|
||||
spin_lock_bh(&net->xfrm.xfrm_state_lock);
|
||||
if (hlist_unhashed(&x->state_cache_input)) {
|
||||
if (x) {
|
||||
spin_lock(&net->xfrm.xfrm_state_lock);
|
||||
if (x->km.state != XFRM_STATE_VALID) {
|
||||
/*
|
||||
* The state is about to be destroyed.
|
||||
*
|
||||
* Don't add it to the cache but still
|
||||
* return it to the caller.
|
||||
*/
|
||||
} else if (hlist_unhashed(&x->state_cache_input)) {
|
||||
hlist_add_head_rcu(&x->state_cache_input, state_cache_input);
|
||||
} else {
|
||||
hlist_del_rcu(&x->state_cache_input);
|
||||
hlist_add_head_rcu(&x->state_cache_input, state_cache_input);
|
||||
}
|
||||
spin_unlock_bh(&net->xfrm.xfrm_state_lock);
|
||||
spin_unlock(&net->xfrm.xfrm_state_lock);
|
||||
}
|
||||
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
return x;
|
||||
}
|
||||
EXPORT_SYMBOL(xfrm_input_state_lookup);
|
||||
@@ -3014,7 +3021,7 @@ int xfrm_user_policy(struct sock *sk, int optname, sockptr_t optval, int optlen)
|
||||
if (IS_ERR(data))
|
||||
return PTR_ERR(data);
|
||||
|
||||
if (in_compat_syscall()) {
|
||||
if (IS_ENABLED(CONFIG_COMPAT_FOR_U64_ALIGNMENT) && in_compat_syscall()) {
|
||||
struct xfrm_translator *xtr = xfrm_get_translator();
|
||||
|
||||
if (!xtr) {
|
||||
|
||||
@@ -2511,9 +2511,9 @@ static int xfrm_notify_userpolicy(struct net *net)
|
||||
}
|
||||
|
||||
up = nlmsg_data(nlh);
|
||||
up->in = net->xfrm.policy_default[XFRM_POLICY_IN];
|
||||
up->fwd = net->xfrm.policy_default[XFRM_POLICY_FWD];
|
||||
up->out = net->xfrm.policy_default[XFRM_POLICY_OUT];
|
||||
up->in = READ_ONCE(net->xfrm.policy_default[XFRM_POLICY_IN]);
|
||||
up->fwd = READ_ONCE(net->xfrm.policy_default[XFRM_POLICY_FWD]);
|
||||
up->out = READ_ONCE(net->xfrm.policy_default[XFRM_POLICY_OUT]);
|
||||
|
||||
nlmsg_end(skb, nlh);
|
||||
|
||||
@@ -2537,13 +2537,13 @@ static int xfrm_set_default(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||
struct xfrm_userpolicy_default *up = nlmsg_data(nlh);
|
||||
|
||||
if (xfrm_userpolicy_is_valid(up->in))
|
||||
net->xfrm.policy_default[XFRM_POLICY_IN] = up->in;
|
||||
WRITE_ONCE(net->xfrm.policy_default[XFRM_POLICY_IN], up->in);
|
||||
|
||||
if (xfrm_userpolicy_is_valid(up->fwd))
|
||||
net->xfrm.policy_default[XFRM_POLICY_FWD] = up->fwd;
|
||||
WRITE_ONCE(net->xfrm.policy_default[XFRM_POLICY_FWD], up->fwd);
|
||||
|
||||
if (xfrm_userpolicy_is_valid(up->out))
|
||||
net->xfrm.policy_default[XFRM_POLICY_OUT] = up->out;
|
||||
WRITE_ONCE(net->xfrm.policy_default[XFRM_POLICY_OUT], up->out);
|
||||
|
||||
rt_genid_bump_all(net);
|
||||
|
||||
@@ -2573,9 +2573,9 @@ static int xfrm_get_default(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||
}
|
||||
|
||||
r_up = nlmsg_data(r_nlh);
|
||||
r_up->in = net->xfrm.policy_default[XFRM_POLICY_IN];
|
||||
r_up->fwd = net->xfrm.policy_default[XFRM_POLICY_FWD];
|
||||
r_up->out = net->xfrm.policy_default[XFRM_POLICY_OUT];
|
||||
r_up->in = READ_ONCE(net->xfrm.policy_default[XFRM_POLICY_IN]);
|
||||
r_up->fwd = READ_ONCE(net->xfrm.policy_default[XFRM_POLICY_FWD]);
|
||||
r_up->out = READ_ONCE(net->xfrm.policy_default[XFRM_POLICY_OUT]);
|
||||
nlmsg_end(r_skb, r_nlh);
|
||||
|
||||
return nlmsg_unicast(xfrm_net_nlsk(net, skb), r_skb, portid);
|
||||
@@ -3835,7 +3835,7 @@ static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||
if (!netlink_net_capable(skb, CAP_NET_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
if (in_compat_syscall()) {
|
||||
if (IS_ENABLED(CONFIG_COMPAT_FOR_U64_ALIGNMENT) && in_compat_syscall()) {
|
||||
struct xfrm_translator *xtr = xfrm_get_translator();
|
||||
|
||||
if (!xtr)
|
||||
|
||||
Reference in New Issue
Block a user