Skip to content

Commit d0de616

Browse files
committed
Merge tag 'ipsec-2024-05-02' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec
Steffen Klassert says: ==================== pull request (net): ipsec 2024-05-02 1) Fix an error pointer dereference in xfrm_in_fwd_icmp. From Antony Antony. 2) Preserve vlan tags for ESP transport mode software GRO. From Paul Davey. 3) Fix a spelling mistake in an uapi xfrm.h comment. From Anotny Antony. * tag 'ipsec-2024-05-02' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec: xfrm: Correct spelling mistake in xfrm.h comment xfrm: Preserve vlan tags for transport mode software GRO xfrm: fix possible derferencing in error path ==================== Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents f2d8590 + b6d2e43 commit d0de616

File tree

7 files changed

+39
-3
lines changed

7 files changed

+39
-3
lines changed

include/linux/skbuff.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3031,6 +3031,21 @@ static inline void skb_mac_header_rebuild(struct sk_buff *skb)
30313031
}
30323032
}
30333033

3034+
/* Move the full mac header up to current network_header.
3035+
* Leaves skb->data pointing at offset skb->mac_len into the mac_header.
3036+
* Must be provided the complete mac header length.
3037+
*/
3038+
static inline void skb_mac_header_rebuild_full(struct sk_buff *skb, u32 full_mac_len)
3039+
{
3040+
if (skb_mac_header_was_set(skb)) {
3041+
const unsigned char *old_mac = skb_mac_header(skb);
3042+
3043+
skb_set_mac_header(skb, -full_mac_len);
3044+
memmove(skb_mac_header(skb), old_mac, full_mac_len);
3045+
__skb_push(skb, full_mac_len - skb->mac_len);
3046+
}
3047+
}
3048+
30343049
static inline int skb_checksum_start_offset(const struct sk_buff *skb)
30353050
{
30363051
return skb->csum_start - skb_headroom(skb);

include/net/xfrm.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1049,6 +1049,9 @@ struct xfrm_offload {
10491049
#define CRYPTO_INVALID_PACKET_SYNTAX 64
10501050
#define CRYPTO_INVALID_PROTOCOL 128
10511051

1052+
/* Used to keep whole l2 header for transport mode GRO */
1053+
__u32 orig_mac_len;
1054+
10521055
__u8 proto;
10531056
__u8 inner_ipproto;
10541057
};

include/uapi/linux/xfrm.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ enum {
228228
#define XFRM_NR_MSGTYPES (XFRM_MSG_MAX + 1 - XFRM_MSG_BASE)
229229

230230
/*
231-
* Generic LSM security context for comunicating to user space
231+
* Generic LSM security context for communicating to user space
232232
* NOTE: Same format as sadb_x_sec_ctx
233233
*/
234234
struct xfrm_user_sec_ctx {

net/ipv4/xfrm4_input.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,11 @@ int xfrm4_transport_finish(struct sk_buff *skb, int async)
6363
ip_send_check(iph);
6464

6565
if (xo && (xo->flags & XFRM_GRO)) {
66-
skb_mac_header_rebuild(skb);
66+
/* The full l2 header needs to be preserved so that re-injecting the packet at l2
67+
* works correctly in the presence of vlan tags.
68+
*/
69+
skb_mac_header_rebuild_full(skb, xo->orig_mac_len);
70+
skb_reset_network_header(skb);
6771
skb_reset_transport_header(skb);
6872
return 0;
6973
}

net/ipv6/xfrm6_input.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,11 @@ int xfrm6_transport_finish(struct sk_buff *skb, int async)
5858
skb_postpush_rcsum(skb, skb_network_header(skb), nhlen);
5959

6060
if (xo && (xo->flags & XFRM_GRO)) {
61-
skb_mac_header_rebuild(skb);
61+
/* The full l2 header needs to be preserved so that re-injecting the packet at l2
62+
* works correctly in the presence of vlan tags.
63+
*/
64+
skb_mac_header_rebuild_full(skb, xo->orig_mac_len);
65+
skb_reset_network_header(skb);
6266
skb_reset_transport_header(skb);
6367
return 0;
6468
}

net/xfrm/xfrm_input.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,11 +389,15 @@ static int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb)
389389
*/
390390
static int xfrm4_transport_input(struct xfrm_state *x, struct sk_buff *skb)
391391
{
392+
struct xfrm_offload *xo = xfrm_offload(skb);
392393
int ihl = skb->data - skb_transport_header(skb);
393394

394395
if (skb->transport_header != skb->network_header) {
395396
memmove(skb_transport_header(skb),
396397
skb_network_header(skb), ihl);
398+
if (xo)
399+
xo->orig_mac_len =
400+
skb_mac_header_was_set(skb) ? skb_mac_header_len(skb) : 0;
397401
skb->network_header = skb->transport_header;
398402
}
399403
ip_hdr(skb)->tot_len = htons(skb->len + ihl);
@@ -404,11 +408,15 @@ static int xfrm4_transport_input(struct xfrm_state *x, struct sk_buff *skb)
404408
static int xfrm6_transport_input(struct xfrm_state *x, struct sk_buff *skb)
405409
{
406410
#if IS_ENABLED(CONFIG_IPV6)
411+
struct xfrm_offload *xo = xfrm_offload(skb);
407412
int ihl = skb->data - skb_transport_header(skb);
408413

409414
if (skb->transport_header != skb->network_header) {
410415
memmove(skb_transport_header(skb),
411416
skb_network_header(skb), ihl);
417+
if (xo)
418+
xo->orig_mac_len =
419+
skb_mac_header_was_set(skb) ? skb_mac_header_len(skb) : 0;
412420
skb->network_header = skb->transport_header;
413421
}
414422
ipv6_hdr(skb)->payload_len = htons(skb->len + ihl -

net/xfrm/xfrm_policy.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3593,6 +3593,8 @@ xfrm_policy *xfrm_in_fwd_icmp(struct sk_buff *skb,
35933593
return pol;
35943594

35953595
pol = xfrm_policy_lookup(net, &fl1, family, XFRM_POLICY_FWD, if_id);
3596+
if (IS_ERR(pol))
3597+
pol = NULL;
35963598
}
35973599

35983600
return pol;

0 commit comments

Comments
 (0)