Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Daniel Borkmann says:

====================
pull-request: bpf 2021-01-16

1) Fix a double bpf_prog_put() for BPF_PROG_{TYPE_EXT,TYPE_TRACING} types in
   link creation's error path causing a refcount underflow, from Jiri Olsa.

2) Fix BTF validation errors for the case where kernel modules don't declare
   any new types and end up with an empty BTF, from Andrii Nakryiko.

3) Fix BPF local storage helpers to first check their {task,inode} owners for
   being NULL before access, from KP Singh.

4) Fix a memory leak in BPF setsockopt handling for the case where optlen is
   zero and thus temporary optval buffer should be freed, from Stanislav Fomichev.

5) Fix a syzbot memory allocation splat in BPF_PROG_TEST_RUN infra for
   raw_tracepoint caused by too big ctx_size_in, from Song Liu.

6) Fix LLVM code generation issues with verifier where PTR_TO_MEM{,_OR_NULL}
   registers were spilled to stack but not recognized, from Gilad Reti.

* https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf:
  MAINTAINERS: Update my email address
  selftests/bpf: Add verifier test for PTR_TO_MEM spill
  bpf: Support PTR_TO_MEM{,_OR_NULL} register spilling
  bpf: Reject too big ctx_size_in for raw_tp test run
  libbpf: Allow loading empty BTFs
  bpf: Allow empty module BTFs
  bpf: Don't leak memory in bpf getsockopt when optlen == 0
  bpf: Update local storage test to check handling of null ptrs
  bpf: Fix typo in bpf_inode_storage.c
  bpf: Local storage helpers should check nullness of owner ptr passed
  bpf: Prevent double bpf_prog_put call from bpf_tracing_prog_attach
====================

Link: https://lore.kernel.org/r/20210116002025.15706-1-daniel@iogearbox.net
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
kuba-moo committed Jan 16, 2021
2 parents c96adff + 235ecd3 commit e23a8d0
Show file tree
Hide file tree
Showing 14 changed files with 128 additions and 115 deletions.
2 changes: 2 additions & 0 deletions .mailmap
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ Bart Van Assche <bvanassche@acm.org> <bart.vanassche@wdc.com>
Ben Gardner <bgardner@wabtec.com>
Ben M Cahill <ben.m.cahill@intel.com>
Björn Steinbrink <B.Steinbrink@gmx.de>
Björn Töpel <bjorn@kernel.org> <bjorn.topel@gmail.com>
Björn Töpel <bjorn@kernel.org> <bjorn.topel@intel.com>
Boris Brezillon <bbrezillon@kernel.org> <b.brezillon.dev@gmail.com>
Boris Brezillon <bbrezillon@kernel.org> <b.brezillon@overkiz.com>
Boris Brezillon <bbrezillon@kernel.org> <boris.brezillon@bootlin.com>
Expand Down
4 changes: 2 additions & 2 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -3334,7 +3334,7 @@ F: arch/riscv/net/
X: arch/riscv/net/bpf_jit_comp64.c

BPF JIT for RISC-V (64-bit)
M: Björn Töpel <bjorn.topel@gmail.com>
M: Björn Töpel <bjorn@kernel.org>
L: netdev@vger.kernel.org
L: bpf@vger.kernel.org
S: Maintained
Expand Down Expand Up @@ -19415,7 +19415,7 @@ F: drivers/net/ethernet/*/*/*xdp*
K: (?:\b|_)xdp(?:\b|_)

XDP SOCKETS (AF_XDP)
M: Björn Töpel <bjorn.topel@intel.com>
M: Björn Töpel <bjorn@kernel.org>
M: Magnus Karlsson <magnus.karlsson@intel.com>
R: Jonathan Lemon <jonathan.lemon@gmail.com>
L: netdev@vger.kernel.org
Expand Down
9 changes: 6 additions & 3 deletions kernel/bpf/bpf_inode_storage.c
Original file line number Diff line number Diff line change
Expand Up @@ -176,14 +176,14 @@ BPF_CALL_4(bpf_inode_storage_get, struct bpf_map *, map, struct inode *, inode,
* bpf_local_storage_update expects the owner to have a
* valid storage pointer.
*/
if (!inode_storage_ptr(inode))
if (!inode || !inode_storage_ptr(inode))
return (unsigned long)NULL;

sdata = inode_storage_lookup(inode, map, true);
if (sdata)
return (unsigned long)sdata->data;

/* This helper must only called from where the inode is gurranteed
/* This helper must only called from where the inode is guaranteed
* to have a refcount and cannot be freed.
*/
if (flags & BPF_LOCAL_STORAGE_GET_F_CREATE) {
Expand All @@ -200,7 +200,10 @@ BPF_CALL_4(bpf_inode_storage_get, struct bpf_map *, map, struct inode *, inode,
BPF_CALL_2(bpf_inode_storage_delete,
struct bpf_map *, map, struct inode *, inode)
{
/* This helper must only called from where the inode is gurranteed
if (!inode)
return -EINVAL;

/* This helper must only called from where the inode is guaranteed
* to have a refcount and cannot be freed.
*/
return inode_storage_delete(inode, map);
Expand Down
5 changes: 4 additions & 1 deletion kernel/bpf/bpf_task_storage.c
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ BPF_CALL_4(bpf_task_storage_get, struct bpf_map *, map, struct task_struct *,
* bpf_local_storage_update expects the owner to have a
* valid storage pointer.
*/
if (!task_storage_ptr(task))
if (!task || !task_storage_ptr(task))
return (unsigned long)NULL;

sdata = task_storage_lookup(task, map, true);
Expand All @@ -243,6 +243,9 @@ BPF_CALL_4(bpf_task_storage_get, struct bpf_map *, map, struct task_struct *,
BPF_CALL_2(bpf_task_storage_delete, struct bpf_map *, map, struct task_struct *,
task)
{
if (!task)
return -EINVAL;

/* This helper must only be called from places where the lifetime of the task
* is guaranteed. Either by being refcounted or by being protected
* by an RCU read-side critical section.
Expand Down
2 changes: 1 addition & 1 deletion kernel/bpf/btf.c
Original file line number Diff line number Diff line change
Expand Up @@ -4172,7 +4172,7 @@ static int btf_parse_hdr(struct btf_verifier_env *env)
return -ENOTSUPP;
}

if (btf_data_size == hdr->hdr_len) {
if (!btf->base_btf && btf_data_size == hdr->hdr_len) {
btf_verifier_log(env, "No data");
return -EINVAL;
}
Expand Down
5 changes: 3 additions & 2 deletions kernel/bpf/cgroup.c
Original file line number Diff line number Diff line change
Expand Up @@ -1391,12 +1391,13 @@ int __cgroup_bpf_run_filter_setsockopt(struct sock *sk, int *level,
if (ctx.optlen != 0) {
*optlen = ctx.optlen;
*kernel_optval = ctx.optval;
/* export and don't free sockopt buf */
return 0;
}
}

out:
if (ret)
sockopt_free_buf(&ctx);
sockopt_free_buf(&ctx);
return ret;
}

Expand Down
6 changes: 4 additions & 2 deletions kernel/bpf/syscall.c
Original file line number Diff line number Diff line change
Expand Up @@ -2712,7 +2712,6 @@ static int bpf_tracing_prog_attach(struct bpf_prog *prog,
out_put_prog:
if (tgt_prog_fd && tgt_prog)
bpf_prog_put(tgt_prog);
bpf_prog_put(prog);
return err;
}

Expand Down Expand Up @@ -2825,7 +2824,10 @@ static int bpf_raw_tracepoint_open(const union bpf_attr *attr)
tp_name = prog->aux->attach_func_name;
break;
}
return bpf_tracing_prog_attach(prog, 0, 0);
err = bpf_tracing_prog_attach(prog, 0, 0);
if (err >= 0)
return err;
goto out_put_prog;
case BPF_PROG_TYPE_RAW_TRACEPOINT:
case BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE:
if (strncpy_from_user(buf,
Expand Down
2 changes: 2 additions & 0 deletions kernel/bpf/verifier.c
Original file line number Diff line number Diff line change
Expand Up @@ -2217,6 +2217,8 @@ static bool is_spillable_regtype(enum bpf_reg_type type)
case PTR_TO_RDWR_BUF:
case PTR_TO_RDWR_BUF_OR_NULL:
case PTR_TO_PERCPU_BTF_ID:
case PTR_TO_MEM:
case PTR_TO_MEM_OR_NULL:
return true;
default:
return false;
Expand Down
3 changes: 2 additions & 1 deletion net/bpf/test_run.c
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,8 @@ int bpf_prog_test_run_raw_tp(struct bpf_prog *prog,
kattr->test.repeat)
return -EINVAL;

if (ctx_size_in < prog->aux->max_ctx_offset)
if (ctx_size_in < prog->aux->max_ctx_offset ||
ctx_size_in > MAX_BPF_FUNC_ARGS * sizeof(u64))
return -EINVAL;

if ((kattr->test.flags & BPF_F_TEST_RUN_ON_CPU) == 0 && cpu != 0)
Expand Down
5 changes: 0 additions & 5 deletions tools/lib/bpf/btf.c
Original file line number Diff line number Diff line change
Expand Up @@ -240,11 +240,6 @@ static int btf_parse_hdr(struct btf *btf)
}

meta_left = btf->raw_size - sizeof(*hdr);
if (!meta_left) {
pr_debug("BTF has no data\n");
return -EINVAL;
}

if (meta_left < hdr->str_off + hdr->str_len) {
pr_debug("Invalid BTF total size:%u\n", btf->raw_size);
return -EINVAL;
Expand Down
96 changes: 26 additions & 70 deletions tools/testing/selftests/bpf/prog_tests/test_local_storage.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,61 +34,6 @@ struct storage {
struct bpf_spin_lock lock;
};

/* Copies an rm binary to a temp file. dest is a mkstemp template */
static int copy_rm(char *dest)
{
int fd_in, fd_out = -1, ret = 0;
struct stat stat;
char *buf = NULL;

fd_in = open("/bin/rm", O_RDONLY);
if (fd_in < 0)
return -errno;

fd_out = mkstemp(dest);
if (fd_out < 0) {
ret = -errno;
goto out;
}

ret = fstat(fd_in, &stat);
if (ret == -1) {
ret = -errno;
goto out;
}

buf = malloc(stat.st_blksize);
if (!buf) {
ret = -errno;
goto out;
}

while (ret = read(fd_in, buf, stat.st_blksize), ret > 0) {
ret = write(fd_out, buf, ret);
if (ret < 0) {
ret = -errno;
goto out;

}
}
if (ret < 0) {
ret = -errno;
goto out;

}

/* Set executable permission on the copied file */
ret = chmod(dest, 0100);
if (ret == -1)
ret = -errno;

out:
free(buf);
close(fd_in);
close(fd_out);
return ret;
}

/* Fork and exec the provided rm binary and return the exit code of the
* forked process and its pid.
*/
Expand Down Expand Up @@ -168,9 +113,11 @@ static bool check_syscall_operations(int map_fd, int obj_fd)

void test_test_local_storage(void)
{
char tmp_exec_path[PATH_MAX] = "/tmp/copy_of_rmXXXXXX";
char tmp_dir_path[64] = "/tmp/local_storageXXXXXX";
int err, serv_sk = -1, task_fd = -1, rm_fd = -1;
struct local_storage *skel = NULL;
char tmp_exec_path[64];
char cmd[256];

skel = local_storage__open_and_load();
if (CHECK(!skel, "skel_load", "lsm skeleton failed\n"))
Expand All @@ -189,18 +136,24 @@ void test_test_local_storage(void)
task_fd))
goto close_prog;

err = copy_rm(tmp_exec_path);
if (CHECK(err < 0, "copy_rm", "err %d errno %d\n", err, errno))
if (CHECK(!mkdtemp(tmp_dir_path), "mkdtemp",
"unable to create tmpdir: %d\n", errno))
goto close_prog;

snprintf(tmp_exec_path, sizeof(tmp_exec_path), "%s/copy_of_rm",
tmp_dir_path);
snprintf(cmd, sizeof(cmd), "cp /bin/rm %s", tmp_exec_path);
if (CHECK_FAIL(system(cmd)))
goto close_prog_rmdir;

rm_fd = open(tmp_exec_path, O_RDONLY);
if (CHECK(rm_fd < 0, "open", "failed to open %s err:%d, errno:%d",
tmp_exec_path, rm_fd, errno))
goto close_prog;
goto close_prog_rmdir;

if (!check_syscall_operations(bpf_map__fd(skel->maps.inode_storage_map),
rm_fd))
goto close_prog;
goto close_prog_rmdir;

/* Sets skel->bss->monitored_pid to the pid of the forked child
* forks a child process that executes tmp_exec_path and tries to
Expand All @@ -209,33 +162,36 @@ void test_test_local_storage(void)
*/
err = run_self_unlink(&skel->bss->monitored_pid, tmp_exec_path);
if (CHECK(err != EPERM, "run_self_unlink", "err %d want EPERM\n", err))
goto close_prog_unlink;
goto close_prog_rmdir;

/* Set the process being monitored to be the current process */
skel->bss->monitored_pid = getpid();

/* Remove the temporary created executable */
err = unlink(tmp_exec_path);
if (CHECK(err != 0, "unlink", "unable to unlink %s: %d", tmp_exec_path,
errno))
goto close_prog_unlink;
/* Move copy_of_rm to a new location so that it triggers the
* inode_rename LSM hook with a new_dentry that has a NULL inode ptr.
*/
snprintf(cmd, sizeof(cmd), "mv %s/copy_of_rm %s/check_null_ptr",
tmp_dir_path, tmp_dir_path);
if (CHECK_FAIL(system(cmd)))
goto close_prog_rmdir;

CHECK(skel->data->inode_storage_result != 0, "inode_storage_result",
"inode_local_storage not set\n");

serv_sk = start_server(AF_INET6, SOCK_STREAM, NULL, 0, 0);
if (CHECK(serv_sk < 0, "start_server", "failed to start server\n"))
goto close_prog;
goto close_prog_rmdir;

CHECK(skel->data->sk_storage_result != 0, "sk_storage_result",
"sk_local_storage not set\n");

if (!check_syscall_operations(bpf_map__fd(skel->maps.sk_storage_map),
serv_sk))
goto close_prog;
goto close_prog_rmdir;

close_prog_unlink:
unlink(tmp_exec_path);
close_prog_rmdir:
snprintf(cmd, sizeof(cmd), "rm -rf %s", tmp_dir_path);
system(cmd);
close_prog:
close(serv_sk);
close(rm_fd);
Expand Down
Loading

0 comments on commit e23a8d0

Please sign in to comment.