Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

bpf: make sure to clear unused fields in tunnel/xfrm state fetch

Since the remaining bits are not filled in struct bpf_tunnel_key
resp. struct bpf_xfrm_state and originate from uninitialized stack
space, we should make sure to clear them before handing control
back to the program.

Also add a padding element to struct bpf_xfrm_state for future use
similar as we have in struct bpf_tunnel_key and clear it as well.

struct bpf_xfrm_state {
__u32 reqid; /* 0 4 */
__u32 spi; /* 4 4 */
__u16 family; /* 8 2 */

/* XXX 2 bytes hole, try to pack */

union {
__u32 remote_ipv4; /* 4 */
__u32 remote_ipv6[4]; /* 16 */
}; /* 12 16 */

/* size: 28, cachelines: 1, members: 4 */
/* sum members: 26, holes: 1, sum holes: 2 */
/* last cacheline: 28 bytes */
};

Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: Song Liu <songliubraving@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

Daniel Borkmann and committed by
Alexei Starovoitov
1fbc2e0c cb20b08e

+8 -1
+2 -1
include/uapi/linux/bpf.h
··· 2268 2268 }; 2269 2269 __u8 tunnel_tos; 2270 2270 __u8 tunnel_ttl; 2271 - __u16 tunnel_ext; 2271 + __u16 tunnel_ext; /* Padding, future use. */ 2272 2272 __u32 tunnel_label; 2273 2273 }; 2274 2274 ··· 2279 2279 __u32 reqid; 2280 2280 __u32 spi; /* Stored in network byte order */ 2281 2281 __u16 family; 2282 + __u16 ext; /* Padding, future use. */ 2282 2283 union { 2283 2284 __u32 remote_ipv4; /* Stored in network byte order */ 2284 2285 __u32 remote_ipv6[4]; /* Stored in network byte order */
+6
net/core/filter.c
··· 3445 3445 to->tunnel_id = be64_to_cpu(info->key.tun_id); 3446 3446 to->tunnel_tos = info->key.tos; 3447 3447 to->tunnel_ttl = info->key.ttl; 3448 + to->tunnel_ext = 0; 3448 3449 3449 3450 if (flags & BPF_F_TUNINFO_IPV6) { 3450 3451 memcpy(to->remote_ipv6, &info->key.u.ipv6.src, ··· 3453 3452 to->tunnel_label = be32_to_cpu(info->key.label); 3454 3453 } else { 3455 3454 to->remote_ipv4 = be32_to_cpu(info->key.u.ipv4.src); 3455 + memset(&to->remote_ipv6[1], 0, sizeof(__u32) * 3); 3456 + to->tunnel_label = 0; 3456 3457 } 3457 3458 3458 3459 if (unlikely(size != sizeof(struct bpf_tunnel_key))) ··· 4050 4047 to->reqid = x->props.reqid; 4051 4048 to->spi = x->id.spi; 4052 4049 to->family = x->props.family; 4050 + to->ext = 0; 4051 + 4053 4052 if (to->family == AF_INET6) { 4054 4053 memcpy(to->remote_ipv6, x->props.saddr.a6, 4055 4054 sizeof(to->remote_ipv6)); 4056 4055 } else { 4057 4056 to->remote_ipv4 = x->props.saddr.a4; 4057 + memset(&to->remote_ipv6[1], 0, sizeof(__u32) * 3); 4058 4058 } 4059 4059 4060 4060 return 0;