Skip to content

Commit 8d46215

Browse files
committed
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec
Steffen Klassert says: ==================== pull request (net): ipsec 2020-07-31 1) Fix policy matching with mark and mask on userspace interfaces. From Xin Long. 2) Several fixes for the new ESP in TCP encapsulation. From Sabrina Dubroca. 3) Fix crash when the hold queue is used. The assumption that xdst->path and dst->child are not a NULL pointer only if dst->xfrm is not a NULL pointer is true with the exception of using the hold queue. Fix this by checking for hold queue usage before dereferencing xdst->path or dst->child. 4) Validate pfkey_dump parameter before sending them. From Mark Salyzyn. 5) Fix the location of the transport header with ESP in UDPv6 encapsulation. From Sabrina Dubroca. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents e535d87 + 71b59bf commit 8d46215

File tree

6 files changed

+104
-58
lines changed

6 files changed

+104
-58
lines changed

include/net/xfrm.h

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -941,7 +941,7 @@ struct xfrm_dst {
941941
static inline struct dst_entry *xfrm_dst_path(const struct dst_entry *dst)
942942
{
943943
#ifdef CONFIG_XFRM
944-
if (dst->xfrm) {
944+
if (dst->xfrm || (dst->flags & DST_XFRM_QUEUE)) {
945945
const struct xfrm_dst *xdst = (const struct xfrm_dst *) dst;
946946

947947
return xdst->path;
@@ -953,7 +953,7 @@ static inline struct dst_entry *xfrm_dst_path(const struct dst_entry *dst)
953953
static inline struct dst_entry *xfrm_dst_child(const struct dst_entry *dst)
954954
{
955955
#ifdef CONFIG_XFRM
956-
if (dst->xfrm) {
956+
if (dst->xfrm || (dst->flags & DST_XFRM_QUEUE)) {
957957
struct xfrm_dst *xdst = (struct xfrm_dst *) dst;
958958
return xdst->child;
959959
}
@@ -1630,13 +1630,16 @@ int xfrm_policy_walk(struct net *net, struct xfrm_policy_walk *walk,
16301630
void *);
16311631
void xfrm_policy_walk_done(struct xfrm_policy_walk *walk, struct net *net);
16321632
int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl);
1633-
struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u32 mark, u32 if_id,
1634-
u8 type, int dir,
1633+
struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net,
1634+
const struct xfrm_mark *mark,
1635+
u32 if_id, u8 type, int dir,
16351636
struct xfrm_selector *sel,
16361637
struct xfrm_sec_ctx *ctx, int delete,
16371638
int *err);
1638-
struct xfrm_policy *xfrm_policy_byid(struct net *net, u32 mark, u32 if_id, u8,
1639-
int dir, u32 id, int delete, int *err);
1639+
struct xfrm_policy *xfrm_policy_byid(struct net *net,
1640+
const struct xfrm_mark *mark, u32 if_id,
1641+
u8 type, int dir, u32 id, int delete,
1642+
int *err);
16401643
int xfrm_policy_flush(struct net *net, u8 type, bool task_valid);
16411644
void xfrm_policy_hash_rebuild(struct net *net);
16421645
u32 xfrm_get_acqseq(void);

net/ipv6/esp6.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -805,10 +805,17 @@ int esp6_input_done2(struct sk_buff *skb, int err)
805805

806806
if (x->encap) {
807807
const struct ipv6hdr *ip6h = ipv6_hdr(skb);
808+
int offset = skb_network_offset(skb) + sizeof(*ip6h);
808809
struct xfrm_encap_tmpl *encap = x->encap;
809-
struct udphdr *uh = (void *)(skb_network_header(skb) + hdr_len);
810-
struct tcphdr *th = (void *)(skb_network_header(skb) + hdr_len);
811-
__be16 source;
810+
u8 nexthdr = ip6h->nexthdr;
811+
__be16 frag_off, source;
812+
struct udphdr *uh;
813+
struct tcphdr *th;
814+
815+
offset = ipv6_skip_exthdr(skb, offset, &nexthdr, &frag_off);
816+
uh = (void *)(skb->data + offset);
817+
th = (void *)(skb->data + offset);
818+
hdr_len += offset;
812819

813820
switch (x->encap->encap_type) {
814821
case TCP_ENCAP_ESPINTCP:

net/key/af_key.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1849,6 +1849,13 @@ static int pfkey_dump(struct sock *sk, struct sk_buff *skb, const struct sadb_ms
18491849
if (ext_hdrs[SADB_X_EXT_FILTER - 1]) {
18501850
struct sadb_x_filter *xfilter = ext_hdrs[SADB_X_EXT_FILTER - 1];
18511851

1852+
if ((xfilter->sadb_x_filter_splen >=
1853+
(sizeof(xfrm_address_t) << 3)) ||
1854+
(xfilter->sadb_x_filter_dplen >=
1855+
(sizeof(xfrm_address_t) << 3))) {
1856+
mutex_unlock(&pfk->dump_lock);
1857+
return -EINVAL;
1858+
}
18521859
filter = kmalloc(sizeof(*filter), GFP_KERNEL);
18531860
if (filter == NULL) {
18541861
mutex_unlock(&pfk->dump_lock);
@@ -2400,7 +2407,7 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, const struct sa
24002407
return err;
24012408
}
24022409

2403-
xp = xfrm_policy_bysel_ctx(net, DUMMY_MARK, 0, XFRM_POLICY_TYPE_MAIN,
2410+
xp = xfrm_policy_bysel_ctx(net, &dummy_mark, 0, XFRM_POLICY_TYPE_MAIN,
24042411
pol->sadb_x_policy_dir - 1, &sel, pol_ctx,
24052412
1, &err);
24062413
security_xfrm_policy_free(pol_ctx);
@@ -2651,7 +2658,7 @@ static int pfkey_spdget(struct sock *sk, struct sk_buff *skb, const struct sadb_
26512658
return -EINVAL;
26522659

26532660
delete = (hdr->sadb_msg_type == SADB_X_SPDDELETE2);
2654-
xp = xfrm_policy_byid(net, DUMMY_MARK, 0, XFRM_POLICY_TYPE_MAIN,
2661+
xp = xfrm_policy_byid(net, &dummy_mark, 0, XFRM_POLICY_TYPE_MAIN,
26552662
dir, pol->sadb_x_policy_id, delete, &err);
26562663
if (xp == NULL)
26572664
return -ENOENT;

net/xfrm/espintcp.c

Lines changed: 47 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ static void handle_nonesp(struct espintcp_ctx *ctx, struct sk_buff *skb,
1515
{
1616
if (atomic_read(&sk->sk_rmem_alloc) >= sk->sk_rcvbuf ||
1717
!sk_rmem_schedule(sk, skb, skb->truesize)) {
18+
XFRM_INC_STATS(sock_net(sk), LINUX_MIB_XFRMINERROR);
1819
kfree_skb(skb);
1920
return;
2021
}
@@ -49,23 +50,51 @@ static void espintcp_rcv(struct strparser *strp, struct sk_buff *skb)
4950
struct espintcp_ctx *ctx = container_of(strp, struct espintcp_ctx,
5051
strp);
5152
struct strp_msg *rxm = strp_msg(skb);
53+
int len = rxm->full_len - 2;
5254
u32 nonesp_marker;
5355
int err;
5456

57+
/* keepalive packet? */
58+
if (unlikely(len == 1)) {
59+
u8 data;
60+
61+
err = skb_copy_bits(skb, rxm->offset + 2, &data, 1);
62+
if (err < 0) {
63+
XFRM_INC_STATS(sock_net(strp->sk), LINUX_MIB_XFRMINHDRERROR);
64+
kfree_skb(skb);
65+
return;
66+
}
67+
68+
if (data == 0xff) {
69+
kfree_skb(skb);
70+
return;
71+
}
72+
}
73+
74+
/* drop other short messages */
75+
if (unlikely(len <= sizeof(nonesp_marker))) {
76+
XFRM_INC_STATS(sock_net(strp->sk), LINUX_MIB_XFRMINHDRERROR);
77+
kfree_skb(skb);
78+
return;
79+
}
80+
5581
err = skb_copy_bits(skb, rxm->offset + 2, &nonesp_marker,
5682
sizeof(nonesp_marker));
5783
if (err < 0) {
84+
XFRM_INC_STATS(sock_net(strp->sk), LINUX_MIB_XFRMINHDRERROR);
5885
kfree_skb(skb);
5986
return;
6087
}
6188

6289
/* remove header, leave non-ESP marker/SPI */
6390
if (!__pskb_pull(skb, rxm->offset + 2)) {
91+
XFRM_INC_STATS(sock_net(strp->sk), LINUX_MIB_XFRMINERROR);
6492
kfree_skb(skb);
6593
return;
6694
}
6795

6896
if (pskb_trim(skb, rxm->full_len - 2) != 0) {
97+
XFRM_INC_STATS(sock_net(strp->sk), LINUX_MIB_XFRMINERROR);
6998
kfree_skb(skb);
7099
return;
71100
}
@@ -91,7 +120,7 @@ static int espintcp_parse(struct strparser *strp, struct sk_buff *skb)
91120
return err;
92121

93122
len = be16_to_cpu(blen);
94-
if (len < 6)
123+
if (len < 2)
95124
return -EINVAL;
96125

97126
return len;
@@ -109,8 +138,11 @@ static int espintcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
109138
flags |= nonblock ? MSG_DONTWAIT : 0;
110139

111140
skb = __skb_recv_datagram(sk, &ctx->ike_queue, flags, &off, &err);
112-
if (!skb)
141+
if (!skb) {
142+
if (err == -EAGAIN && sk->sk_shutdown & RCV_SHUTDOWN)
143+
return 0;
113144
return err;
145+
}
114146

115147
copied = len;
116148
if (copied > skb->len)
@@ -213,7 +245,7 @@ static int espintcp_sendskmsg_locked(struct sock *sk,
213245
return 0;
214246
}
215247

216-
static int espintcp_push_msgs(struct sock *sk)
248+
static int espintcp_push_msgs(struct sock *sk, int flags)
217249
{
218250
struct espintcp_ctx *ctx = espintcp_getctx(sk);
219251
struct espintcp_msg *emsg = &ctx->partial;
@@ -227,12 +259,12 @@ static int espintcp_push_msgs(struct sock *sk)
227259
ctx->tx_running = 1;
228260

229261
if (emsg->skb)
230-
err = espintcp_sendskb_locked(sk, emsg, 0);
262+
err = espintcp_sendskb_locked(sk, emsg, flags);
231263
else
232-
err = espintcp_sendskmsg_locked(sk, emsg, 0);
264+
err = espintcp_sendskmsg_locked(sk, emsg, flags);
233265
if (err == -EAGAIN) {
234266
ctx->tx_running = 0;
235-
return 0;
267+
return flags & MSG_DONTWAIT ? -EAGAIN : 0;
236268
}
237269
if (!err)
238270
memset(emsg, 0, sizeof(*emsg));
@@ -257,7 +289,7 @@ int espintcp_push_skb(struct sock *sk, struct sk_buff *skb)
257289
offset = skb_transport_offset(skb);
258290
len = skb->len - offset;
259291

260-
espintcp_push_msgs(sk);
292+
espintcp_push_msgs(sk, 0);
261293

262294
if (emsg->len) {
263295
kfree_skb(skb);
@@ -270,7 +302,7 @@ int espintcp_push_skb(struct sock *sk, struct sk_buff *skb)
270302
emsg->len = len;
271303
emsg->skb = skb;
272304

273-
espintcp_push_msgs(sk);
305+
espintcp_push_msgs(sk, 0);
274306

275307
return 0;
276308
}
@@ -287,7 +319,7 @@ static int espintcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
287319
char buf[2] = {0};
288320
int err, end;
289321

290-
if (msg->msg_flags)
322+
if (msg->msg_flags & ~MSG_DONTWAIT)
291323
return -EOPNOTSUPP;
292324

293325
if (size > MAX_ESPINTCP_MSG)
@@ -298,9 +330,10 @@ static int espintcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
298330

299331
lock_sock(sk);
300332

301-
err = espintcp_push_msgs(sk);
333+
err = espintcp_push_msgs(sk, msg->msg_flags & MSG_DONTWAIT);
302334
if (err < 0) {
303-
err = -ENOBUFS;
335+
if (err != -EAGAIN || !(msg->msg_flags & MSG_DONTWAIT))
336+
err = -ENOBUFS;
304337
goto unlock;
305338
}
306339

@@ -337,10 +370,9 @@ static int espintcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
337370

338371
tcp_rate_check_app_limited(sk);
339372

340-
err = espintcp_push_msgs(sk);
373+
err = espintcp_push_msgs(sk, msg->msg_flags & MSG_DONTWAIT);
341374
/* this message could be partially sent, keep it */
342-
if (err < 0)
343-
goto unlock;
375+
344376
release_sock(sk);
345377

346378
return size;
@@ -374,7 +406,7 @@ static void espintcp_tx_work(struct work_struct *work)
374406

375407
lock_sock(sk);
376408
if (!ctx->tx_running)
377-
espintcp_push_msgs(sk);
409+
espintcp_push_msgs(sk, 0);
378410
release_sock(sk);
379411
}
380412

net/xfrm/xfrm_policy.c

Lines changed: 18 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
#ifdef CONFIG_XFRM_STATISTICS
4040
#include <net/snmp.h>
4141
#endif
42-
#ifdef CONFIG_INET_ESPINTCP
42+
#ifdef CONFIG_XFRM_ESPINTCP
4343
#include <net/espintcp.h>
4444
#endif
4545

@@ -1433,14 +1433,10 @@ static void xfrm_policy_requeue(struct xfrm_policy *old,
14331433
spin_unlock_bh(&pq->hold_queue.lock);
14341434
}
14351435

1436-
static bool xfrm_policy_mark_match(struct xfrm_policy *policy,
1437-
struct xfrm_policy *pol)
1436+
static inline bool xfrm_policy_mark_match(const struct xfrm_mark *mark,
1437+
struct xfrm_policy *pol)
14381438
{
1439-
if (policy->mark.v == pol->mark.v &&
1440-
policy->priority == pol->priority)
1441-
return true;
1442-
1443-
return false;
1439+
return mark->v == pol->mark.v && mark->m == pol->mark.m;
14441440
}
14451441

14461442
static u32 xfrm_pol_bin_key(const void *data, u32 len, u32 seed)
@@ -1503,7 +1499,7 @@ static void xfrm_policy_insert_inexact_list(struct hlist_head *chain,
15031499
if (pol->type == policy->type &&
15041500
pol->if_id == policy->if_id &&
15051501
!selector_cmp(&pol->selector, &policy->selector) &&
1506-
xfrm_policy_mark_match(policy, pol) &&
1502+
xfrm_policy_mark_match(&policy->mark, pol) &&
15071503
xfrm_sec_ctx_match(pol->security, policy->security) &&
15081504
!WARN_ON(delpol)) {
15091505
delpol = pol;
@@ -1538,7 +1534,7 @@ static struct xfrm_policy *xfrm_policy_insert_list(struct hlist_head *chain,
15381534
if (pol->type == policy->type &&
15391535
pol->if_id == policy->if_id &&
15401536
!selector_cmp(&pol->selector, &policy->selector) &&
1541-
xfrm_policy_mark_match(policy, pol) &&
1537+
xfrm_policy_mark_match(&policy->mark, pol) &&
15421538
xfrm_sec_ctx_match(pol->security, policy->security) &&
15431539
!WARN_ON(delpol)) {
15441540
if (excl)
@@ -1610,9 +1606,8 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
16101606
EXPORT_SYMBOL(xfrm_policy_insert);
16111607

16121608
static struct xfrm_policy *
1613-
__xfrm_policy_bysel_ctx(struct hlist_head *chain, u32 mark, u32 if_id,
1614-
u8 type, int dir,
1615-
struct xfrm_selector *sel,
1609+
__xfrm_policy_bysel_ctx(struct hlist_head *chain, const struct xfrm_mark *mark,
1610+
u32 if_id, u8 type, int dir, struct xfrm_selector *sel,
16161611
struct xfrm_sec_ctx *ctx)
16171612
{
16181613
struct xfrm_policy *pol;
@@ -1623,7 +1618,7 @@ __xfrm_policy_bysel_ctx(struct hlist_head *chain, u32 mark, u32 if_id,
16231618
hlist_for_each_entry(pol, chain, bydst) {
16241619
if (pol->type == type &&
16251620
pol->if_id == if_id &&
1626-
(mark & pol->mark.m) == pol->mark.v &&
1621+
xfrm_policy_mark_match(mark, pol) &&
16271622
!selector_cmp(sel, &pol->selector) &&
16281623
xfrm_sec_ctx_match(ctx, pol->security))
16291624
return pol;
@@ -1632,11 +1627,10 @@ __xfrm_policy_bysel_ctx(struct hlist_head *chain, u32 mark, u32 if_id,
16321627
return NULL;
16331628
}
16341629

1635-
struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u32 mark, u32 if_id,
1636-
u8 type, int dir,
1637-
struct xfrm_selector *sel,
1638-
struct xfrm_sec_ctx *ctx, int delete,
1639-
int *err)
1630+
struct xfrm_policy *
1631+
xfrm_policy_bysel_ctx(struct net *net, const struct xfrm_mark *mark, u32 if_id,
1632+
u8 type, int dir, struct xfrm_selector *sel,
1633+
struct xfrm_sec_ctx *ctx, int delete, int *err)
16401634
{
16411635
struct xfrm_pol_inexact_bin *bin = NULL;
16421636
struct xfrm_policy *pol, *ret = NULL;
@@ -1703,9 +1697,9 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u32 mark, u32 if_id,
17031697
}
17041698
EXPORT_SYMBOL(xfrm_policy_bysel_ctx);
17051699

1706-
struct xfrm_policy *xfrm_policy_byid(struct net *net, u32 mark, u32 if_id,
1707-
u8 type, int dir, u32 id, int delete,
1708-
int *err)
1700+
struct xfrm_policy *
1701+
xfrm_policy_byid(struct net *net, const struct xfrm_mark *mark, u32 if_id,
1702+
u8 type, int dir, u32 id, int delete, int *err)
17091703
{
17101704
struct xfrm_policy *pol, *ret;
17111705
struct hlist_head *chain;
@@ -1720,8 +1714,7 @@ struct xfrm_policy *xfrm_policy_byid(struct net *net, u32 mark, u32 if_id,
17201714
ret = NULL;
17211715
hlist_for_each_entry(pol, chain, byidx) {
17221716
if (pol->type == type && pol->index == id &&
1723-
pol->if_id == if_id &&
1724-
(mark & pol->mark.m) == pol->mark.v) {
1717+
pol->if_id == if_id && xfrm_policy_mark_match(mark, pol)) {
17251718
xfrm_pol_hold(pol);
17261719
if (delete) {
17271720
*err = security_xfrm_policy_delete(
@@ -4156,7 +4149,7 @@ void __init xfrm_init(void)
41564149
seqcount_init(&xfrm_policy_hash_generation);
41574150
xfrm_input_init();
41584151

4159-
#ifdef CONFIG_INET_ESPINTCP
4152+
#ifdef CONFIG_XFRM_ESPINTCP
41604153
espintcp_init();
41614154
#endif
41624155

0 commit comments

Comments
 (0)