diff options
author | Daniel Borkmann <daniel@iogearbox.net> | 2018-06-02 17:06:37 -0400 |
---|---|---|
committer | Alexei Starovoitov <ast@kernel.org> | 2018-06-03 10:46:55 -0400 |
commit | 1fbc2e0cfcf9677683aea2b1f9ea76fbdc6fb6d1 (patch) | |
tree | 6e59f51bb75c719968536dabb35e6ababf68bff8 | |
parent | cb20b08ead401fd17627a36f035c0bf5bfee5567 (diff) |
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>
-rw-r--r-- | include/uapi/linux/bpf.h | 3 | ||||
-rw-r--r-- | net/core/filter.c | 6 |
2 files changed, 8 insertions, 1 deletions
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 661318141f72..f0b6608b1f1c 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h | |||
@@ -2268,7 +2268,7 @@ struct bpf_tunnel_key { | |||
2268 | }; | 2268 | }; |
2269 | __u8 tunnel_tos; | 2269 | __u8 tunnel_tos; |
2270 | __u8 tunnel_ttl; | 2270 | __u8 tunnel_ttl; |
2271 | __u16 tunnel_ext; | 2271 | __u16 tunnel_ext; /* Padding, future use. */ |
2272 | __u32 tunnel_label; | 2272 | __u32 tunnel_label; |
2273 | }; | 2273 | }; |
2274 | 2274 | ||
@@ -2279,6 +2279,7 @@ struct bpf_xfrm_state { | |||
2279 | __u32 reqid; | 2279 | __u32 reqid; |
2280 | __u32 spi; /* Stored in network byte order */ | 2280 | __u32 spi; /* Stored in network byte order */ |
2281 | __u16 family; | 2281 | __u16 family; |
2282 | __u16 ext; /* Padding, future use. */ | ||
2282 | union { | 2283 | union { |
2283 | __u32 remote_ipv4; /* Stored in network byte order */ | 2284 | __u32 remote_ipv4; /* Stored in network byte order */ |
2284 | __u32 remote_ipv6[4]; /* Stored in network byte order */ | 2285 | __u32 remote_ipv6[4]; /* Stored in network byte order */ |
diff --git a/net/core/filter.c b/net/core/filter.c index edbfaa613b6d..28e864777c0f 100644 --- a/net/core/filter.c +++ b/net/core/filter.c | |||
@@ -3445,6 +3445,7 @@ set_compat: | |||
3445 | to->tunnel_id = be64_to_cpu(info->key.tun_id); | 3445 | to->tunnel_id = be64_to_cpu(info->key.tun_id); |
3446 | to->tunnel_tos = info->key.tos; | 3446 | to->tunnel_tos = info->key.tos; |
3447 | to->tunnel_ttl = info->key.ttl; | 3447 | to->tunnel_ttl = info->key.ttl; |
3448 | to->tunnel_ext = 0; | ||
3448 | 3449 | ||
3449 | if (flags & BPF_F_TUNINFO_IPV6) { | 3450 | if (flags & BPF_F_TUNINFO_IPV6) { |
3450 | memcpy(to->remote_ipv6, &info->key.u.ipv6.src, | 3451 | memcpy(to->remote_ipv6, &info->key.u.ipv6.src, |
@@ -3452,6 +3453,8 @@ set_compat: | |||
3452 | to->tunnel_label = be32_to_cpu(info->key.label); | 3453 | to->tunnel_label = be32_to_cpu(info->key.label); |
3453 | } else { | 3454 | } else { |
3454 | to->remote_ipv4 = be32_to_cpu(info->key.u.ipv4.src); | 3455 | to->remote_ipv4 = be32_to_cpu(info->key.u.ipv4.src); |
3456 | memset(&to->remote_ipv6[1], 0, sizeof(__u32) * 3); | ||
3457 | to->tunnel_label = 0; | ||
3455 | } | 3458 | } |
3456 | 3459 | ||
3457 | if (unlikely(size != sizeof(struct bpf_tunnel_key))) | 3460 | if (unlikely(size != sizeof(struct bpf_tunnel_key))) |
@@ -4047,11 +4050,14 @@ BPF_CALL_5(bpf_skb_get_xfrm_state, struct sk_buff *, skb, u32, index, | |||
4047 | to->reqid = x->props.reqid; | 4050 | to->reqid = x->props.reqid; |
4048 | to->spi = x->id.spi; | 4051 | to->spi = x->id.spi; |
4049 | to->family = x->props.family; | 4052 | to->family = x->props.family; |
4053 | to->ext = 0; | ||
4054 | |||
4050 | if (to->family == AF_INET6) { | 4055 | if (to->family == AF_INET6) { |
4051 | memcpy(to->remote_ipv6, x->props.saddr.a6, | 4056 | memcpy(to->remote_ipv6, x->props.saddr.a6, |
4052 | sizeof(to->remote_ipv6)); | 4057 | sizeof(to->remote_ipv6)); |
4053 | } else { | 4058 | } else { |
4054 | to->remote_ipv4 = x->props.saddr.a4; | 4059 | to->remote_ipv4 = x->props.saddr.a4; |
4060 | memset(&to->remote_ipv6[1], 0, sizeof(__u32) * 3); | ||
4055 | } | 4061 | } |
4056 | 4062 | ||
4057 | return 0; | 4063 | return 0; |