Commit e6ea60ba authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files
Alexei Starovoitov says:

====================
1) libbpf should not attempt to load unused subprogs, from Andrii.

2) Make strncpy_from_user() mask out bytes after NUL terminator, from Daniel.

3) Relax return code check for subprograms in the BPF verifier, from Dmitrii.

4) Fix several sockmap issues, from John.

* https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf:
  fail_function: Remove a redundant mutex unlock
  selftest/bpf: Test bpf_probe_read_user_str() strips trailing bytes after NUL
  lib/strncpy_from_user.c: Mask out bytes after NUL terminator.
  libbpf: Fix VERSIONED_SYM_COUNT number parsing
  bpf, sockmap: Avoid failures from skb_to_sgvec when skb has frag_list
  bpf, sockmap: Handle memory acct if skb_verdict prog redirects to self
  bpf, sockmap: Avoid returning unneeded EAGAIN when redirecting to self
  bpf, sockmap: Use truesize with sk_rmem_schedule()
  bpf, sockmap: Ensure SO_RCVBUF memory is observed on ingress redirect
  bpf, sockmap: Fix partial copy_page_to_iter so progress can still be made
  selftests/bpf: Fix error return code in run_getsockopt_test()
  bpf: Relax return code check for subprograms
  tools, bpftool: Add missing close before bpftool net attach exit
  MAINTAINERS/bpf: Update Andrii's entry.
  selftests/bpf: Fix unused attribute usage in subprogs_unused test
  bpf: Fix unsigned 'datasec_id' compared with zero in check_pseudo_btf_id
  bpf: Fix passing zero to PTR_ERR() in bpf_btf_printf_prepare
  libbpf: Don't attempt to load unused subprog as an entry-point BPF program
====================

Link: https://lore.kernel.org/r/20201119200721.288-1-alexei.starovoitov@gmail.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 90b49784 2801a5da
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -3243,10 +3243,10 @@ F: drivers/iio/accel/bma400*
BPF (Safe dynamic programs and tools)
M:	Alexei Starovoitov <ast@kernel.org>
M:	Daniel Borkmann <daniel@iogearbox.net>
M:	Andrii Nakryiko <andrii@kernel.org>
R:	Martin KaFai Lau <kafai@fb.com>
R:	Song Liu <songliubraving@fb.com>
R:	Yonghong Song <yhs@fb.com>
R:	Andrii Nakryiko <andrii@kernel.org>
R:	John Fastabend <john.fastabend@gmail.com>
R:	KP Singh <kpsingh@chromium.org>
L:	netdev@vger.kernel.org
+15 −3
Original line number Diff line number Diff line
@@ -7786,9 +7786,11 @@ static int check_return_code(struct bpf_verifier_env *env)
	struct tnum range = tnum_range(0, 1);
	enum bpf_prog_type prog_type = resolve_prog_type(env->prog);
	int err;
	const bool is_subprog = env->cur_state->frame[0]->subprogno;

	/* LSM and struct_ops func-ptr's return type could be "void" */
	if ((prog_type == BPF_PROG_TYPE_STRUCT_OPS ||
	if (!is_subprog &&
	    (prog_type == BPF_PROG_TYPE_STRUCT_OPS ||
	     prog_type == BPF_PROG_TYPE_LSM) &&
	    !prog->aux->attach_func_proto->type)
		return 0;
@@ -7808,6 +7810,16 @@ static int check_return_code(struct bpf_verifier_env *env)
		return -EACCES;
	}

	reg = cur_regs(env) + BPF_REG_0;
	if (is_subprog) {
		if (reg->type != SCALAR_VALUE) {
			verbose(env, "At subprogram exit the register R0 is not a scalar value (%s)\n",
				reg_type_str[reg->type]);
			return -EINVAL;
		}
		return 0;
	}

	switch (prog_type) {
	case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
		if (env->prog->expected_attach_type == BPF_CGROUP_UDP4_RECVMSG ||
@@ -7861,7 +7873,6 @@ static int check_return_code(struct bpf_verifier_env *env)
		return 0;
	}

	reg = cur_regs(env) + BPF_REG_0;
	if (reg->type != SCALAR_VALUE) {
		verbose(env, "At program exit the register R0 is not a known value (%s)\n",
			reg_type_str[reg->type]);
@@ -9572,12 +9583,13 @@ static int check_pseudo_btf_id(struct bpf_verifier_env *env,
			       struct bpf_insn *insn,
			       struct bpf_insn_aux_data *aux)
{
	u32 datasec_id, type, id = insn->imm;
	const struct btf_var_secinfo *vsi;
	const struct btf_type *datasec;
	const struct btf_type *t;
	const char *sym_name;
	bool percpu = false;
	u32 type, id = insn->imm;
	s32 datasec_id;
	u64 addr;
	int i;

+3 −2
Original line number Diff line number Diff line
@@ -253,7 +253,7 @@ static ssize_t fei_write(struct file *file, const char __user *buffer,

	if (copy_from_user(buf, buffer, count)) {
		ret = -EFAULT;
		goto out;
		goto out_free;
	}
	buf[count] = '\0';
	sym = strstrip(buf);
@@ -307,8 +307,9 @@ static ssize_t fei_write(struct file *file, const char __user *buffer,
		ret = count;
	}
out:
	kfree(buf);
	mutex_unlock(&fei_lock);
out_free:
	kfree(buf);
	return ret;
}

+11 −1
Original line number Diff line number Diff line
@@ -181,6 +181,16 @@ bpf_probe_read_user_str_common(void *dst, u32 size,
{
	int ret;

	/*
	 * NB: We rely on strncpy_from_user() not copying junk past the NUL
	 * terminator into `dst`.
	 *
	 * strncpy_from_user() does long-sized strides in the fast path. If the
	 * strncpy does not mask out the bytes after the NUL in `unsafe_ptr`,
	 * then there could be junk after the NUL in `dst`. If user takes `dst`
	 * and keys a hash map with it, then semantically identical strings can
	 * occupy multiple entries in the map.
	 */
	ret = strncpy_from_user_nofault(dst, unsafe_ptr, size);
	if (unlikely(ret < 0))
		memset(dst, 0, size);
@@ -1198,7 +1208,7 @@ static int bpf_btf_printf_prepare(struct btf_ptr *ptr, u32 btf_ptr_size,
	*btf = bpf_get_btf_vmlinux();

	if (IS_ERR_OR_NULL(*btf))
		return PTR_ERR(*btf);
		return IS_ERR(*btf) ? PTR_ERR(*btf) : -EINVAL;

	if (ptr->type_id > 0)
		*btf_id = ptr->type_id;
+17 −2
Original line number Diff line number Diff line
@@ -35,17 +35,32 @@ static inline long do_strncpy_from_user(char *dst, const char __user *src,
		goto byte_at_a_time;

	while (max >= sizeof(unsigned long)) {
		unsigned long c, data;
		unsigned long c, data, mask;

		/* Fall back to byte-at-a-time if we get a page fault */
		unsafe_get_user(c, (unsigned long __user *)(src+res), byte_at_a_time);

		*(unsigned long *)(dst+res) = c;
		/*
		 * Note that we mask out the bytes following the NUL. This is
		 * important to do because string oblivious code may read past
		 * the NUL. For those routines, we don't want to give them
		 * potentially random bytes after the NUL in `src`.
		 *
		 * One example of such code is BPF map keys. BPF treats map keys
		 * as an opaque set of bytes. Without the post-NUL mask, any BPF
		 * maps keyed by strings returned from strncpy_from_user() may
		 * have multiple entries for semantically identical strings.
		 */
		if (has_zero(c, &data, &constants)) {
			data = prep_zero_mask(c, data, &constants);
			data = create_zero_mask(data);
			mask = zero_bytemask(data);
			*(unsigned long *)(dst+res) = c & mask;
			return res + find_zero(data);
		}

		*(unsigned long *)(dst+res) = c;

		res += sizeof(unsigned long);
		max -= sizeof(unsigned long);
	}
Loading