Skip to content

Commit 0c8d2d9

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 2017-08-21 1) Fix memleaks when ESP takes an error path. 2) Fix null pointer dereference when creating a sub policy that matches the same outer flow as main policy does. From Koichiro Den. 3) Fix possible out-of-bound access in xfrm_migrate. This patch should go to the stable trees too. From Vladis Dronov. 4) ESP can return positive and negative error values, so treat both cases as an error. Please pull or let me know if there are problems. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 3de33e1 + 4ff0308 commit 0c8d2d9

File tree

6 files changed

+29
-11
lines changed

6 files changed

+29
-11
lines changed

net/ipv4/esp4.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,7 @@ int esp_output_tail(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *
381381
(unsigned char *)esph - skb->data,
382382
assoclen + ivlen + esp->clen + alen);
383383
if (unlikely(err < 0))
384-
goto error;
384+
goto error_free;
385385

386386
if (!esp->inplace) {
387387
int allocsize;
@@ -392,7 +392,7 @@ int esp_output_tail(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *
392392
spin_lock_bh(&x->lock);
393393
if (unlikely(!skb_page_frag_refill(allocsize, pfrag, GFP_ATOMIC))) {
394394
spin_unlock_bh(&x->lock);
395-
goto error;
395+
goto error_free;
396396
}
397397

398398
skb_shinfo(skb)->nr_frags = 1;
@@ -409,7 +409,7 @@ int esp_output_tail(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *
409409
(unsigned char *)esph - skb->data,
410410
assoclen + ivlen + esp->clen + alen);
411411
if (unlikely(err < 0))
412-
goto error;
412+
goto error_free;
413413
}
414414

415415
if ((x->props.flags & XFRM_STATE_ESN))
@@ -442,8 +442,9 @@ int esp_output_tail(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *
442442

443443
if (sg != dsg)
444444
esp_ssg_unref(x, tmp);
445-
kfree(tmp);
446445

446+
error_free:
447+
kfree(tmp);
447448
error:
448449
return err;
449450
}
@@ -695,8 +696,10 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb)
695696

696697
sg_init_table(sg, nfrags);
697698
err = skb_to_sgvec(skb, sg, 0, skb->len);
698-
if (unlikely(err < 0))
699+
if (unlikely(err < 0)) {
700+
kfree(tmp);
699701
goto out;
702+
}
700703

701704
skb->ip_summed = CHECKSUM_NONE;
702705

net/ipv4/esp4_offload.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ static int esp_xmit(struct xfrm_state *x, struct sk_buff *skb, netdev_features_
257257
esp.seqno = cpu_to_be64(xo->seq.low + ((u64)xo->seq.hi << 32));
258258

259259
err = esp_output_tail(x, skb, &esp);
260-
if (err < 0)
260+
if (err)
261261
return err;
262262

263263
secpath_reset(skb);

net/ipv6/esp6.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@ int esp6_output_tail(struct xfrm_state *x, struct sk_buff *skb, struct esp_info
345345
(unsigned char *)esph - skb->data,
346346
assoclen + ivlen + esp->clen + alen);
347347
if (unlikely(err < 0))
348-
goto error;
348+
goto error_free;
349349

350350
if (!esp->inplace) {
351351
int allocsize;
@@ -356,7 +356,7 @@ int esp6_output_tail(struct xfrm_state *x, struct sk_buff *skb, struct esp_info
356356
spin_lock_bh(&x->lock);
357357
if (unlikely(!skb_page_frag_refill(allocsize, pfrag, GFP_ATOMIC))) {
358358
spin_unlock_bh(&x->lock);
359-
goto error;
359+
goto error_free;
360360
}
361361

362362
skb_shinfo(skb)->nr_frags = 1;
@@ -373,7 +373,7 @@ int esp6_output_tail(struct xfrm_state *x, struct sk_buff *skb, struct esp_info
373373
(unsigned char *)esph - skb->data,
374374
assoclen + ivlen + esp->clen + alen);
375375
if (unlikely(err < 0))
376-
goto error;
376+
goto error_free;
377377
}
378378

379379
if ((x->props.flags & XFRM_STATE_ESN))
@@ -406,8 +406,9 @@ int esp6_output_tail(struct xfrm_state *x, struct sk_buff *skb, struct esp_info
406406

407407
if (sg != dsg)
408408
esp_ssg_unref(x, tmp);
409-
kfree(tmp);
410409

410+
error_free:
411+
kfree(tmp);
411412
error:
412413
return err;
413414
}

net/ipv6/esp6_offload.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ static int esp6_xmit(struct xfrm_state *x, struct sk_buff *skb, netdev_features
286286
esp.seqno = cpu_to_be64(xo->seq.low + ((u64)xo->seq.hi << 32));
287287

288288
err = esp6_output_tail(x, skb, &esp);
289-
if (err < 0)
289+
if (err)
290290
return err;
291291

292292
secpath_reset(skb);

net/xfrm/xfrm_policy.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3308,9 +3308,15 @@ int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
33083308
struct xfrm_state *x_new[XFRM_MAX_DEPTH];
33093309
struct xfrm_migrate *mp;
33103310

3311+
/* Stage 0 - sanity checks */
33113312
if ((err = xfrm_migrate_check(m, num_migrate)) < 0)
33123313
goto out;
33133314

3315+
if (dir >= XFRM_POLICY_MAX) {
3316+
err = -EINVAL;
3317+
goto out;
3318+
}
3319+
33143320
/* Stage 1 - find policy */
33153321
if ((pol = xfrm_migrate_policy_find(sel, dir, type, net)) == NULL) {
33163322
err = -ENOENT;

net/xfrm/xfrm_state.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1620,6 +1620,7 @@ int
16201620
xfrm_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n,
16211621
unsigned short family, struct net *net)
16221622
{
1623+
int i;
16231624
int err = 0;
16241625
struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);
16251626
if (!afinfo)
@@ -1628,6 +1629,9 @@ xfrm_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n,
16281629
spin_lock_bh(&net->xfrm.xfrm_state_lock); /*FIXME*/
16291630
if (afinfo->tmpl_sort)
16301631
err = afinfo->tmpl_sort(dst, src, n);
1632+
else
1633+
for (i = 0; i < n; i++)
1634+
dst[i] = src[i];
16311635
spin_unlock_bh(&net->xfrm.xfrm_state_lock);
16321636
rcu_read_unlock();
16331637
return err;
@@ -1638,6 +1642,7 @@ int
16381642
xfrm_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n,
16391643
unsigned short family)
16401644
{
1645+
int i;
16411646
int err = 0;
16421647
struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);
16431648
struct net *net = xs_net(*src);
@@ -1648,6 +1653,9 @@ xfrm_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n,
16481653
spin_lock_bh(&net->xfrm.xfrm_state_lock);
16491654
if (afinfo->state_sort)
16501655
err = afinfo->state_sort(dst, src, n);
1656+
else
1657+
for (i = 0; i < n; i++)
1658+
dst[i] = src[i];
16511659
spin_unlock_bh(&net->xfrm.xfrm_state_lock);
16521660
rcu_read_unlock();
16531661
return err;

0 commit comments

Comments
 (0)