Commit a0ba26f3 authored by David S. Miller's avatar David S. Miller

Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf

Daniel Borkmann says:

====================
pull-request: bpf 2020-03-27

The following pull-request contains BPF updates for your *net* tree.

We've added 3 non-merge commits during the last 4 day(s) which contain
a total of 4 files changed, 25 insertions(+), 20 deletions(-).

The main changes are:

1) Explicitly memset the bpf_attr structure on bpf() syscall to avoid
   having to rely on compiler to do so. Issues have been noticed on
   some compilers with padding and other oddities where the request was
   then unexpectedly rejected, from Greg Kroah-Hartman.

2) Sanitize the bpf_struct_ops TCP congestion control name in order to
   avoid problematic characters such as whitespaces, from Martin KaFai Lau.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 2e8c339b 5c6f2588
...@@ -160,6 +160,7 @@ static inline void copy_map_value(struct bpf_map *map, void *dst, void *src) ...@@ -160,6 +160,7 @@ static inline void copy_map_value(struct bpf_map *map, void *dst, void *src)
} }
void copy_map_value_locked(struct bpf_map *map, void *dst, void *src, void copy_map_value_locked(struct bpf_map *map, void *dst, void *src,
bool lock_src); bool lock_src);
int bpf_obj_name_cpy(char *dst, const char *src, unsigned int size);
struct bpf_offload_dev; struct bpf_offload_dev;
struct bpf_offloaded_map; struct bpf_offloaded_map;
......
...@@ -4564,7 +4564,7 @@ int btf_get_info_by_fd(const struct btf *btf, ...@@ -4564,7 +4564,7 @@ int btf_get_info_by_fd(const struct btf *btf,
union bpf_attr __user *uattr) union bpf_attr __user *uattr)
{ {
struct bpf_btf_info __user *uinfo; struct bpf_btf_info __user *uinfo;
struct bpf_btf_info info = {}; struct bpf_btf_info info;
u32 info_copy, btf_copy; u32 info_copy, btf_copy;
void __user *ubtf; void __user *ubtf;
u32 uinfo_len; u32 uinfo_len;
...@@ -4573,6 +4573,7 @@ int btf_get_info_by_fd(const struct btf *btf, ...@@ -4573,6 +4573,7 @@ int btf_get_info_by_fd(const struct btf *btf,
uinfo_len = attr->info.info_len; uinfo_len = attr->info.info_len;
info_copy = min_t(u32, uinfo_len, sizeof(info)); info_copy = min_t(u32, uinfo_len, sizeof(info));
memset(&info, 0, sizeof(info));
if (copy_from_user(&info, uinfo, info_copy)) if (copy_from_user(&info, uinfo, info_copy))
return -EFAULT; return -EFAULT;
......
...@@ -696,14 +696,15 @@ int bpf_get_file_flag(int flags) ...@@ -696,14 +696,15 @@ int bpf_get_file_flag(int flags)
offsetof(union bpf_attr, CMD##_LAST_FIELD) - \ offsetof(union bpf_attr, CMD##_LAST_FIELD) - \
sizeof(attr->CMD##_LAST_FIELD)) != NULL sizeof(attr->CMD##_LAST_FIELD)) != NULL
/* dst and src must have at least BPF_OBJ_NAME_LEN number of bytes. /* dst and src must have at least "size" number of bytes.
* Return 0 on success and < 0 on error. * Return strlen on success and < 0 on error.
*/ */
static int bpf_obj_name_cpy(char *dst, const char *src) int bpf_obj_name_cpy(char *dst, const char *src, unsigned int size)
{ {
const char *end = src + BPF_OBJ_NAME_LEN; const char *end = src + size;
const char *orig_src = src;
memset(dst, 0, BPF_OBJ_NAME_LEN); memset(dst, 0, size);
/* Copy all isalnum(), '_' and '.' chars. */ /* Copy all isalnum(), '_' and '.' chars. */
while (src < end && *src) { while (src < end && *src) {
if (!isalnum(*src) && if (!isalnum(*src) &&
...@@ -712,11 +713,11 @@ static int bpf_obj_name_cpy(char *dst, const char *src) ...@@ -712,11 +713,11 @@ static int bpf_obj_name_cpy(char *dst, const char *src)
*dst++ = *src++; *dst++ = *src++;
} }
/* No '\0' found in BPF_OBJ_NAME_LEN number of bytes */ /* No '\0' found in "size" number of bytes */
if (src == end) if (src == end)
return -EINVAL; return -EINVAL;
return 0; return src - orig_src;
} }
int map_check_no_btf(const struct bpf_map *map, int map_check_no_btf(const struct bpf_map *map,
...@@ -810,8 +811,9 @@ static int map_create(union bpf_attr *attr) ...@@ -810,8 +811,9 @@ static int map_create(union bpf_attr *attr)
if (IS_ERR(map)) if (IS_ERR(map))
return PTR_ERR(map); return PTR_ERR(map);
err = bpf_obj_name_cpy(map->name, attr->map_name); err = bpf_obj_name_cpy(map->name, attr->map_name,
if (err) sizeof(attr->map_name));
if (err < 0)
goto free_map; goto free_map;
atomic64_set(&map->refcnt, 1); atomic64_set(&map->refcnt, 1);
...@@ -2098,8 +2100,9 @@ static int bpf_prog_load(union bpf_attr *attr, union bpf_attr __user *uattr) ...@@ -2098,8 +2100,9 @@ static int bpf_prog_load(union bpf_attr *attr, union bpf_attr __user *uattr)
goto free_prog; goto free_prog;
prog->aux->load_time = ktime_get_boottime_ns(); prog->aux->load_time = ktime_get_boottime_ns();
err = bpf_obj_name_cpy(prog->aux->name, attr->prog_name); err = bpf_obj_name_cpy(prog->aux->name, attr->prog_name,
if (err) sizeof(attr->prog_name));
if (err < 0)
goto free_prog; goto free_prog;
/* run eBPF verifier */ /* run eBPF verifier */
...@@ -2792,7 +2795,7 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog, ...@@ -2792,7 +2795,7 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog,
union bpf_attr __user *uattr) union bpf_attr __user *uattr)
{ {
struct bpf_prog_info __user *uinfo = u64_to_user_ptr(attr->info.info); struct bpf_prog_info __user *uinfo = u64_to_user_ptr(attr->info.info);
struct bpf_prog_info info = {}; struct bpf_prog_info info;
u32 info_len = attr->info.info_len; u32 info_len = attr->info.info_len;
struct bpf_prog_stats stats; struct bpf_prog_stats stats;
char __user *uinsns; char __user *uinsns;
...@@ -2804,6 +2807,7 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog, ...@@ -2804,6 +2807,7 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog,
return err; return err;
info_len = min_t(u32, sizeof(info), info_len); info_len = min_t(u32, sizeof(info), info_len);
memset(&info, 0, sizeof(info));
if (copy_from_user(&info, uinfo, info_len)) if (copy_from_user(&info, uinfo, info_len))
return -EFAULT; return -EFAULT;
...@@ -3067,7 +3071,7 @@ static int bpf_map_get_info_by_fd(struct bpf_map *map, ...@@ -3067,7 +3071,7 @@ static int bpf_map_get_info_by_fd(struct bpf_map *map,
union bpf_attr __user *uattr) union bpf_attr __user *uattr)
{ {
struct bpf_map_info __user *uinfo = u64_to_user_ptr(attr->info.info); struct bpf_map_info __user *uinfo = u64_to_user_ptr(attr->info.info);
struct bpf_map_info info = {}; struct bpf_map_info info;
u32 info_len = attr->info.info_len; u32 info_len = attr->info.info_len;
int err; int err;
...@@ -3076,6 +3080,7 @@ static int bpf_map_get_info_by_fd(struct bpf_map *map, ...@@ -3076,6 +3080,7 @@ static int bpf_map_get_info_by_fd(struct bpf_map *map,
return err; return err;
info_len = min_t(u32, sizeof(info), info_len); info_len = min_t(u32, sizeof(info), info_len);
memset(&info, 0, sizeof(info));
info.type = map->map_type; info.type = map->map_type;
info.id = map->id; info.id = map->id;
info.key_size = map->key_size; info.key_size = map->key_size;
...@@ -3359,7 +3364,7 @@ static int bpf_map_do_batch(const union bpf_attr *attr, ...@@ -3359,7 +3364,7 @@ static int bpf_map_do_batch(const union bpf_attr *attr,
SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, size) SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, size)
{ {
union bpf_attr attr = {}; union bpf_attr attr;
int err; int err;
if (sysctl_unprivileged_bpf_disabled && !capable(CAP_SYS_ADMIN)) if (sysctl_unprivileged_bpf_disabled && !capable(CAP_SYS_ADMIN))
...@@ -3371,6 +3376,7 @@ SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, siz ...@@ -3371,6 +3376,7 @@ SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, siz
size = min_t(u32, size, sizeof(attr)); size = min_t(u32, size, sizeof(attr));
/* copy attributes from user space, may be less than sizeof(bpf_attr) */ /* copy attributes from user space, may be less than sizeof(bpf_attr) */
memset(&attr, 0, sizeof(attr));
if (copy_from_user(&attr, uattr, size) != 0) if (copy_from_user(&attr, uattr, size) != 0)
return -EFAULT; return -EFAULT;
......
...@@ -184,7 +184,6 @@ static int bpf_tcp_ca_init_member(const struct btf_type *t, ...@@ -184,7 +184,6 @@ static int bpf_tcp_ca_init_member(const struct btf_type *t,
{ {
const struct tcp_congestion_ops *utcp_ca; const struct tcp_congestion_ops *utcp_ca;
struct tcp_congestion_ops *tcp_ca; struct tcp_congestion_ops *tcp_ca;
size_t tcp_ca_name_len;
int prog_fd; int prog_fd;
u32 moff; u32 moff;
...@@ -199,13 +198,11 @@ static int bpf_tcp_ca_init_member(const struct btf_type *t, ...@@ -199,13 +198,11 @@ static int bpf_tcp_ca_init_member(const struct btf_type *t,
tcp_ca->flags = utcp_ca->flags; tcp_ca->flags = utcp_ca->flags;
return 1; return 1;
case offsetof(struct tcp_congestion_ops, name): case offsetof(struct tcp_congestion_ops, name):
tcp_ca_name_len = strnlen(utcp_ca->name, sizeof(utcp_ca->name)); if (bpf_obj_name_cpy(tcp_ca->name, utcp_ca->name,
if (!tcp_ca_name_len || sizeof(tcp_ca->name)) <= 0)
tcp_ca_name_len == sizeof(utcp_ca->name))
return -EINVAL; return -EINVAL;
if (tcp_ca_find(utcp_ca->name)) if (tcp_ca_find(utcp_ca->name))
return -EEXIST; return -EEXIST;
memcpy(tcp_ca->name, utcp_ca->name, sizeof(tcp_ca->name));
return 1; return 1;
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment