mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-05-07 04:58:01 +02:00
bpf: clat: fix other verifier errors
When copying the IPv6 addresses via a direct assignement, the compiler generates 32-bit operations that the verifier doesn't like: > 237: (61) r3 = *(u32 *)(r8 +76) ; frame1: R3_w=pkt(r=0) R8=ctx() > ; .saddr = ip6h->saddr, @ clat.bpf.c:124 > 238: (63) *(u32 *)(r10 -64) = r3 > invalid size of register spill Use explicit memcpy() for those. Also, check the packet length before accessing the ICMPv6 header.
This commit is contained in:
parent
207f781d80
commit
aaa905b462
1 changed files with 16 additions and 15 deletions
|
|
@ -98,18 +98,16 @@ update_l4_checksum(struct __sk_buff *skb,
|
||||||
__u32 csum;
|
__u32 csum;
|
||||||
|
|
||||||
if (v4to6) {
|
if (v4to6) {
|
||||||
csum = bpf_csum_diff((__be32 *) &iph->saddr,
|
void *from_ptr = &iph->saddr;
|
||||||
2 * sizeof(__u32),
|
void *to_ptr = &ip6h->saddr;
|
||||||
(__be32 *) &ip6h->saddr,
|
|
||||||
2 * sizeof(struct in6_addr),
|
csum = bpf_csum_diff(from_ptr, 2 * sizeof(__u32), to_ptr, 2 * sizeof(struct in6_addr), 0);
|
||||||
0);
|
|
||||||
offset = (void *) (iph + 1) - data;
|
offset = (void *) (iph + 1) - data;
|
||||||
} else {
|
} else {
|
||||||
csum = bpf_csum_diff((__be32 *) &ip6h->saddr,
|
void *from_ptr = &ip6h->saddr;
|
||||||
2 * sizeof(struct in6_addr),
|
void *to_ptr = &iph->saddr;
|
||||||
(__be32 *) &iph->saddr,
|
|
||||||
2 * sizeof(__u32),
|
csum = bpf_csum_diff(from_ptr, 2 * sizeof(struct in6_addr), to_ptr, 2 * sizeof(__u32), 0);
|
||||||
0);
|
|
||||||
offset = (void *) (ip6h + 1) - data;
|
offset = (void *) (ip6h + 1) - data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -136,13 +134,13 @@ update_icmp_checksum(struct __sk_buff *skb,
|
||||||
bool add)
|
bool add)
|
||||||
{
|
{
|
||||||
void *data = SKB_DATA(skb);
|
void *data = SKB_DATA(skb);
|
||||||
struct icmpv6_pseudo ph = {.nh = IPPROTO_ICMPV6,
|
struct icmpv6_pseudo ph = {.nh = IPPROTO_ICMPV6, .len = ip6h->payload_len};
|
||||||
.saddr = ip6h->saddr,
|
|
||||||
.daddr = ip6h->daddr,
|
|
||||||
.len = ip6h->payload_len};
|
|
||||||
__u16 h_before, h_after, offset;
|
__u16 h_before, h_after, offset;
|
||||||
__u32 csum, u_before, u_after;
|
__u32 csum, u_before, u_after;
|
||||||
|
|
||||||
|
__builtin_memcpy(&ph.saddr, &ip6h->saddr, sizeof(struct in6_addr));
|
||||||
|
__builtin_memcpy(&ph.daddr, &ip6h->daddr, sizeof(struct in6_addr));
|
||||||
|
|
||||||
/* Do checksum update in two passes: first compute the incremental
|
/* Do checksum update in two passes: first compute the incremental
|
||||||
* checksum update of the ICMPv6 pseudo header, update the checksum
|
* checksum update of the ICMPv6 pseudo header, update the checksum
|
||||||
* using bpf_l4_csum_replace(), and then do a separate update for the
|
* using bpf_l4_csum_replace(), and then do a separate update for the
|
||||||
|
|
@ -577,7 +575,10 @@ clat_translate_v6(struct __sk_buff *skb,
|
||||||
switch (dst_hdr.protocol) {
|
switch (dst_hdr.protocol) {
|
||||||
case IPPROTO_ICMPV6:
|
case IPPROTO_ICMPV6:
|
||||||
|
|
||||||
new_icmp = (void *) (ip6h + 1);
|
new_icmp = (void *) (ip6h + 1);
|
||||||
|
if ((void *) (new_icmp + 1) > data_end)
|
||||||
|
goto out;
|
||||||
|
|
||||||
old_icmp6 = *((struct icmp6hdr *) (void *) new_icmp);
|
old_icmp6 = *((struct icmp6hdr *) (void *) new_icmp);
|
||||||
if (rewrite_icmpv6(ip6h, skb, &new_icmp, nh))
|
if (rewrite_icmpv6(ip6h, skb, &new_icmp, nh))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue