Skip to content

Commit bd2ec34

Browse files
author
Paolo Abeni
committed
Merge tag 'ipsec-2025-05-21' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec
Steffen Klassert says: ==================== pull request (net): ipsec 2025-05-21 1) Fix some missing kfree_skb in the error paths of espintcp. From Sabrina Dubroca. 2) Fix a reference leak in espintcp. From Sabrina Dubroca. 3) Fix UDP GRO handling for ESPINUDP. From Tobias Brunner. 4) Fix ipcomp truesize computation on the receive path. From Sabrina Dubroca. 5) Sanitize marks before policy/state insertation. From Paul Chaignon. * tag 'ipsec-2025-05-21' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec: xfrm: Sanitize marks before insert xfrm: ipcomp: fix truesize computation on receive xfrm: Fix UDP GRO handling for some corner cases espintcp: remove encap socket caching to avoid reference leak espintcp: fix skb leaks ==================== Link: https://patch.msgid.link/[email protected] Signed-off-by: Paolo Abeni <[email protected]>
2 parents e279024 + 0b91fda commit bd2ec34

File tree

9 files changed

+44
-115
lines changed

9 files changed

+44
-115
lines changed

include/net/xfrm.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,6 @@ struct xfrm_state {
236236

237237
/* Data for encapsulator */
238238
struct xfrm_encap_tmpl *encap;
239-
struct sock __rcu *encap_sk;
240239

241240
/* NAT keepalive */
242241
u32 nat_keepalive_interval; /* seconds */

net/ipv4/esp4.c

Lines changed: 7 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -120,47 +120,16 @@ static void esp_ssg_unref(struct xfrm_state *x, void *tmp, struct sk_buff *skb)
120120
}
121121

122122
#ifdef CONFIG_INET_ESPINTCP
123-
struct esp_tcp_sk {
124-
struct sock *sk;
125-
struct rcu_head rcu;
126-
};
127-
128-
static void esp_free_tcp_sk(struct rcu_head *head)
129-
{
130-
struct esp_tcp_sk *esk = container_of(head, struct esp_tcp_sk, rcu);
131-
132-
sock_put(esk->sk);
133-
kfree(esk);
134-
}
135-
136123
static struct sock *esp_find_tcp_sk(struct xfrm_state *x)
137124
{
138125
struct xfrm_encap_tmpl *encap = x->encap;
139126
struct net *net = xs_net(x);
140-
struct esp_tcp_sk *esk;
141127
__be16 sport, dport;
142-
struct sock *nsk;
143128
struct sock *sk;
144129

145-
sk = rcu_dereference(x->encap_sk);
146-
if (sk && sk->sk_state == TCP_ESTABLISHED)
147-
return sk;
148-
149130
spin_lock_bh(&x->lock);
150131
sport = encap->encap_sport;
151132
dport = encap->encap_dport;
152-
nsk = rcu_dereference_protected(x->encap_sk,
153-
lockdep_is_held(&x->lock));
154-
if (sk && sk == nsk) {
155-
esk = kmalloc(sizeof(*esk), GFP_ATOMIC);
156-
if (!esk) {
157-
spin_unlock_bh(&x->lock);
158-
return ERR_PTR(-ENOMEM);
159-
}
160-
RCU_INIT_POINTER(x->encap_sk, NULL);
161-
esk->sk = sk;
162-
call_rcu(&esk->rcu, esp_free_tcp_sk);
163-
}
164133
spin_unlock_bh(&x->lock);
165134

166135
sk = inet_lookup_established(net, net->ipv4.tcp_death_row.hashinfo, x->id.daddr.a4,
@@ -173,20 +142,6 @@ static struct sock *esp_find_tcp_sk(struct xfrm_state *x)
173142
return ERR_PTR(-EINVAL);
174143
}
175144

176-
spin_lock_bh(&x->lock);
177-
nsk = rcu_dereference_protected(x->encap_sk,
178-
lockdep_is_held(&x->lock));
179-
if (encap->encap_sport != sport ||
180-
encap->encap_dport != dport) {
181-
sock_put(sk);
182-
sk = nsk ?: ERR_PTR(-EREMCHG);
183-
} else if (sk == nsk) {
184-
sock_put(sk);
185-
} else {
186-
rcu_assign_pointer(x->encap_sk, sk);
187-
}
188-
spin_unlock_bh(&x->lock);
189-
190145
return sk;
191146
}
192147

@@ -199,8 +154,10 @@ static int esp_output_tcp_finish(struct xfrm_state *x, struct sk_buff *skb)
199154

200155
sk = esp_find_tcp_sk(x);
201156
err = PTR_ERR_OR_ZERO(sk);
202-
if (err)
157+
if (err) {
158+
kfree_skb(skb);
203159
goto out;
160+
}
204161

205162
bh_lock_sock(sk);
206163
if (sock_owned_by_user(sk))
@@ -209,6 +166,8 @@ static int esp_output_tcp_finish(struct xfrm_state *x, struct sk_buff *skb)
209166
err = espintcp_push_skb(sk, skb);
210167
bh_unlock_sock(sk);
211168

169+
sock_put(sk);
170+
212171
out:
213172
rcu_read_unlock();
214173
return err;
@@ -392,6 +351,8 @@ static struct ip_esp_hdr *esp_output_tcp_encap(struct xfrm_state *x,
392351
if (IS_ERR(sk))
393352
return ERR_CAST(sk);
394353

354+
sock_put(sk);
355+
395356
*lenp = htons(len);
396357
esph = (struct ip_esp_hdr *)(lenp + 1);
397358

net/ipv4/xfrm4_input.c

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -182,23 +182,26 @@ struct sk_buff *xfrm4_gro_udp_encap_rcv(struct sock *sk, struct list_head *head,
182182
int offset = skb_gro_offset(skb);
183183
const struct net_offload *ops;
184184
struct sk_buff *pp = NULL;
185-
int ret;
186-
187-
offset = offset - sizeof(struct udphdr);
185+
int len, dlen;
186+
__u8 *udpdata;
187+
__be32 *udpdata32;
188188

189-
if (!pskb_pull(skb, offset))
189+
len = skb->len - offset;
190+
dlen = offset + min(len, 8);
191+
udpdata = skb_gro_header(skb, dlen, offset);
192+
udpdata32 = (__be32 *)udpdata;
193+
if (unlikely(!udpdata))
190194
return NULL;
191195

192196
rcu_read_lock();
193197
ops = rcu_dereference(inet_offloads[IPPROTO_ESP]);
194198
if (!ops || !ops->callbacks.gro_receive)
195199
goto out;
196200

197-
ret = __xfrm4_udp_encap_rcv(sk, skb, false);
198-
if (ret)
201+
/* check if it is a keepalive or IKE packet */
202+
if (len <= sizeof(struct ip_esp_hdr) || udpdata32[0] == 0)
199203
goto out;
200204

201-
skb_push(skb, offset);
202205
NAPI_GRO_CB(skb)->proto = IPPROTO_UDP;
203206

204207
pp = call_gro_receive(ops->callbacks.gro_receive, head, skb);
@@ -208,7 +211,6 @@ struct sk_buff *xfrm4_gro_udp_encap_rcv(struct sock *sk, struct list_head *head,
208211

209212
out:
210213
rcu_read_unlock();
211-
skb_push(skb, offset);
212214
NAPI_GRO_CB(skb)->same_flow = 0;
213215
NAPI_GRO_CB(skb)->flush = 1;
214216

net/ipv6/esp6.c

Lines changed: 7 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -137,47 +137,16 @@ static void esp_ssg_unref(struct xfrm_state *x, void *tmp, struct sk_buff *skb)
137137
}
138138

139139
#ifdef CONFIG_INET6_ESPINTCP
140-
struct esp_tcp_sk {
141-
struct sock *sk;
142-
struct rcu_head rcu;
143-
};
144-
145-
static void esp_free_tcp_sk(struct rcu_head *head)
146-
{
147-
struct esp_tcp_sk *esk = container_of(head, struct esp_tcp_sk, rcu);
148-
149-
sock_put(esk->sk);
150-
kfree(esk);
151-
}
152-
153140
static struct sock *esp6_find_tcp_sk(struct xfrm_state *x)
154141
{
155142
struct xfrm_encap_tmpl *encap = x->encap;
156143
struct net *net = xs_net(x);
157-
struct esp_tcp_sk *esk;
158144
__be16 sport, dport;
159-
struct sock *nsk;
160145
struct sock *sk;
161146

162-
sk = rcu_dereference(x->encap_sk);
163-
if (sk && sk->sk_state == TCP_ESTABLISHED)
164-
return sk;
165-
166147
spin_lock_bh(&x->lock);
167148
sport = encap->encap_sport;
168149
dport = encap->encap_dport;
169-
nsk = rcu_dereference_protected(x->encap_sk,
170-
lockdep_is_held(&x->lock));
171-
if (sk && sk == nsk) {
172-
esk = kmalloc(sizeof(*esk), GFP_ATOMIC);
173-
if (!esk) {
174-
spin_unlock_bh(&x->lock);
175-
return ERR_PTR(-ENOMEM);
176-
}
177-
RCU_INIT_POINTER(x->encap_sk, NULL);
178-
esk->sk = sk;
179-
call_rcu(&esk->rcu, esp_free_tcp_sk);
180-
}
181150
spin_unlock_bh(&x->lock);
182151

183152
sk = __inet6_lookup_established(net, net->ipv4.tcp_death_row.hashinfo, &x->id.daddr.in6,
@@ -190,20 +159,6 @@ static struct sock *esp6_find_tcp_sk(struct xfrm_state *x)
190159
return ERR_PTR(-EINVAL);
191160
}
192161

193-
spin_lock_bh(&x->lock);
194-
nsk = rcu_dereference_protected(x->encap_sk,
195-
lockdep_is_held(&x->lock));
196-
if (encap->encap_sport != sport ||
197-
encap->encap_dport != dport) {
198-
sock_put(sk);
199-
sk = nsk ?: ERR_PTR(-EREMCHG);
200-
} else if (sk == nsk) {
201-
sock_put(sk);
202-
} else {
203-
rcu_assign_pointer(x->encap_sk, sk);
204-
}
205-
spin_unlock_bh(&x->lock);
206-
207162
return sk;
208163
}
209164

@@ -216,8 +171,10 @@ static int esp_output_tcp_finish(struct xfrm_state *x, struct sk_buff *skb)
216171

217172
sk = esp6_find_tcp_sk(x);
218173
err = PTR_ERR_OR_ZERO(sk);
219-
if (err)
174+
if (err) {
175+
kfree_skb(skb);
220176
goto out;
177+
}
221178

222179
bh_lock_sock(sk);
223180
if (sock_owned_by_user(sk))
@@ -226,6 +183,8 @@ static int esp_output_tcp_finish(struct xfrm_state *x, struct sk_buff *skb)
226183
err = espintcp_push_skb(sk, skb);
227184
bh_unlock_sock(sk);
228185

186+
sock_put(sk);
187+
229188
out:
230189
rcu_read_unlock();
231190
return err;
@@ -422,6 +381,8 @@ static struct ip_esp_hdr *esp6_output_tcp_encap(struct xfrm_state *x,
422381
if (IS_ERR(sk))
423382
return ERR_CAST(sk);
424383

384+
sock_put(sk);
385+
425386
*lenp = htons(len);
426387
esph = (struct ip_esp_hdr *)(lenp + 1);
427388

net/ipv6/xfrm6_input.c

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -179,26 +179,29 @@ struct sk_buff *xfrm6_gro_udp_encap_rcv(struct sock *sk, struct list_head *head,
179179
int offset = skb_gro_offset(skb);
180180
const struct net_offload *ops;
181181
struct sk_buff *pp = NULL;
182-
int ret;
182+
int len, dlen;
183+
__u8 *udpdata;
184+
__be32 *udpdata32;
183185

184186
if (skb->protocol == htons(ETH_P_IP))
185187
return xfrm4_gro_udp_encap_rcv(sk, head, skb);
186188

187-
offset = offset - sizeof(struct udphdr);
188-
189-
if (!pskb_pull(skb, offset))
189+
len = skb->len - offset;
190+
dlen = offset + min(len, 8);
191+
udpdata = skb_gro_header(skb, dlen, offset);
192+
udpdata32 = (__be32 *)udpdata;
193+
if (unlikely(!udpdata))
190194
return NULL;
191195

192196
rcu_read_lock();
193197
ops = rcu_dereference(inet6_offloads[IPPROTO_ESP]);
194198
if (!ops || !ops->callbacks.gro_receive)
195199
goto out;
196200

197-
ret = __xfrm6_udp_encap_rcv(sk, skb, false);
198-
if (ret)
201+
/* check if it is a keepalive or IKE packet */
202+
if (len <= sizeof(struct ip_esp_hdr) || udpdata32[0] == 0)
199203
goto out;
200204

201-
skb_push(skb, offset);
202205
NAPI_GRO_CB(skb)->proto = IPPROTO_UDP;
203206

204207
pp = call_gro_receive(ops->callbacks.gro_receive, head, skb);
@@ -208,7 +211,6 @@ struct sk_buff *xfrm6_gro_udp_encap_rcv(struct sock *sk, struct list_head *head,
208211

209212
out:
210213
rcu_read_unlock();
211-
skb_push(skb, offset);
212214
NAPI_GRO_CB(skb)->same_flow = 0;
213215
NAPI_GRO_CB(skb)->flush = 1;
214216

net/xfrm/espintcp.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,8 +171,10 @@ int espintcp_queue_out(struct sock *sk, struct sk_buff *skb)
171171
struct espintcp_ctx *ctx = espintcp_getctx(sk);
172172

173173
if (skb_queue_len(&ctx->out_queue) >=
174-
READ_ONCE(net_hotdata.max_backlog))
174+
READ_ONCE(net_hotdata.max_backlog)) {
175+
kfree_skb(skb);
175176
return -ENOBUFS;
177+
}
176178

177179
__skb_queue_tail(&ctx->out_queue, skb);
178180

net/xfrm/xfrm_ipcomp.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ static int ipcomp_post_acomp(struct sk_buff *skb, int err, int hlen)
4848
{
4949
struct acomp_req *req = ipcomp_cb(skb)->req;
5050
struct ipcomp_req_extra *extra;
51-
const int plen = skb->data_len;
5251
struct scatterlist *dsg;
5352
int len, dlen;
5453

@@ -64,7 +63,7 @@ static int ipcomp_post_acomp(struct sk_buff *skb, int err, int hlen)
6463

6564
/* Only update truesize on input. */
6665
if (!hlen)
67-
skb->truesize += dlen - plen;
66+
skb->truesize += dlen;
6867
skb->data_len = dlen;
6968
skb->len += dlen;
7069

net/xfrm/xfrm_policy.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1581,6 +1581,9 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
15811581
struct xfrm_policy *delpol;
15821582
struct hlist_head *chain;
15831583

1584+
/* Sanitize mark before store */
1585+
policy->mark.v &= policy->mark.m;
1586+
15841587
spin_lock_bh(&net->xfrm.xfrm_policy_lock);
15851588
chain = policy_hash_bysel(net, &policy->selector, policy->family, dir);
15861589
if (chain)

net/xfrm/xfrm_state.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -838,9 +838,6 @@ int __xfrm_state_delete(struct xfrm_state *x)
838838
xfrm_nat_keepalive_state_updated(x);
839839
spin_unlock(&net->xfrm.xfrm_state_lock);
840840

841-
if (x->encap_sk)
842-
sock_put(rcu_dereference_raw(x->encap_sk));
843-
844841
xfrm_dev_state_delete(x);
845842

846843
/* All xfrm_state objects are created by xfrm_state_alloc.
@@ -1721,6 +1718,9 @@ static void __xfrm_state_insert(struct xfrm_state *x)
17211718

17221719
list_add(&x->km.all, &net->xfrm.state_all);
17231720

1721+
/* Sanitize mark before store */
1722+
x->mark.v &= x->mark.m;
1723+
17241724
h = xfrm_dst_hash(net, &x->id.daddr, &x->props.saddr,
17251725
x->props.reqid, x->props.family);
17261726
XFRM_STATE_INSERT(bydst, &x->bydst, net->xfrm.state_bydst + h,

0 commit comments

Comments
 (0)