diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-10-28 20:17:49 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-10-28 20:17:49 -0700 |
commit | 9f51ae62c84a23ade0ba86457d30a30c9db0c50f (patch) | |
tree | d71bf5c81f17629d3d1b3131e0842c02bd9a7dd6 /kernel/bpf/btf.c | |
parent | 53b3b6bbfde6aae8d1ededc86ad4e0e1e00eb5f8 (diff) | |
parent | 747569b0a7c537d680bc94a988be6caad9960488 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Pull networking fixes from David Miller:
1) GRO overflow entries are not unlinked properly, resulting in list
poison pointers being dereferenced.
2) Fix bridge build with ipv6 disabled, from Nikolay Aleksandrov.
3) Direct packet access and other fixes in BPF from Daniel Borkmann.
4) gred_change_table_def() gets passed the wrong pointer, a pointer to
a set of unparsed attributes instead of the attribute itself. From
Jakub Kicinski.
5) Allow macsec device to be brought up even if it's lowerdev is down,
from Sabrina Dubroca.
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net:
net: diag: document swapped src/dst in udp_dump_one.
macsec: let the administrator set UP state even if lowerdev is down
macsec: update operstate when lower device changes
net: sched: gred: pass the right attribute to gred_change_table_def()
ptp: drop redundant kasprintf() to create worker name
net: bridge: remove ipv6 zero address check in mcast queries
net: Properly unlink GRO packets on overflow.
bpf: fix wrong helper enablement in cgroup local storage
bpf: add bpf_jit_limit knob to restrict unpriv allocations
bpf: make direct packet write unclone more robust
bpf: fix leaking uninitialized memory on pop/peek helpers
bpf: fix direct packet write into pop/peek helpers
bpf: fix cg_skb types to hint access type in may_access_direct_pkt_data
bpf: fix direct packet access for flow dissector progs
bpf: disallow direct packet access for unpriv in cg_skb
bpf: fix test suite to enable all unpriv program types
bpf, btf: fix a missing check bug in btf_parse
selftests/bpf: add config fragments BPF_STREAM_PARSER and XDP_SOCKETS
bpf: devmap: fix wrong interface selection in notifier_call
Diffstat (limited to 'kernel/bpf/btf.c')
-rw-r--r-- | kernel/bpf/btf.c | 58 |
1 files changed, 25 insertions, 33 deletions
diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c index 378cef70341c..ee4c82667d65 100644 --- a/kernel/bpf/btf.c +++ b/kernel/bpf/btf.c @@ -2067,56 +2067,47 @@ static int btf_check_sec_info(struct btf_verifier_env *env, return 0; } -static int btf_parse_hdr(struct btf_verifier_env *env, void __user *btf_data, - u32 btf_data_size) +static int btf_parse_hdr(struct btf_verifier_env *env) { + u32 hdr_len, hdr_copy, btf_data_size; const struct btf_header *hdr; - u32 hdr_len, hdr_copy; - /* - * Minimal part of the "struct btf_header" that - * contains the hdr_len. - */ - struct btf_min_header { - u16 magic; - u8 version; - u8 flags; - u32 hdr_len; - } __user *min_hdr; struct btf *btf; int err; btf = env->btf; - min_hdr = btf_data; + btf_data_size = btf->data_size; - if (btf_data_size < sizeof(*min_hdr)) { + if (btf_data_size < + offsetof(struct btf_header, hdr_len) + sizeof(hdr->hdr_len)) { btf_verifier_log(env, "hdr_len not found"); return -EINVAL; } - if (get_user(hdr_len, &min_hdr->hdr_len)) - return -EFAULT; - + hdr = btf->data; + hdr_len = hdr->hdr_len; if (btf_data_size < hdr_len) { btf_verifier_log(env, "btf_header not found"); return -EINVAL; } - err = bpf_check_uarg_tail_zero(btf_data, sizeof(btf->hdr), hdr_len); - if (err) { - if (err == -E2BIG) - btf_verifier_log(env, "Unsupported btf_header"); - return err; + /* Ensure the unsupported header fields are zero */ + if (hdr_len > sizeof(btf->hdr)) { + u8 *expected_zero = btf->data + sizeof(btf->hdr); + u8 *end = btf->data + hdr_len; + + for (; expected_zero < end; expected_zero++) { + if (*expected_zero) { + btf_verifier_log(env, "Unsupported btf_header"); + return -E2BIG; + } + } } hdr_copy = min_t(u32, hdr_len, sizeof(btf->hdr)); - if (copy_from_user(&btf->hdr, btf_data, hdr_copy)) - return -EFAULT; + memcpy(&btf->hdr, btf->data, hdr_copy); hdr = &btf->hdr; - if (hdr->hdr_len != hdr_len) - return -EINVAL; - btf_verifier_log_hdr(env, btf_data_size); if (hdr->magic != BTF_MAGIC) { @@ -2186,10 +2177,6 @@ static struct btf *btf_parse(void __user *btf_data, u32 btf_data_size, } env->btf = btf; - err = btf_parse_hdr(env, btf_data, btf_data_size); - if (err) - goto errout; - data = kvmalloc(btf_data_size, GFP_KERNEL | __GFP_NOWARN); if (!data) { err = -ENOMEM; @@ -2198,13 +2185,18 @@ static struct btf *btf_parse(void __user *btf_data, u32 btf_data_size, btf->data = data; btf->data_size = btf_data_size; - btf->nohdr_data = btf->data + btf->hdr.hdr_len; if (copy_from_user(data, btf_data, btf_data_size)) { err = -EFAULT; goto errout; } + err = btf_parse_hdr(env); + if (err) + goto errout; + + btf->nohdr_data = btf->data + btf->hdr.hdr_len; + err = btf_parse_str_sec(env); if (err) goto errout; |