Thread (14 messages) 14 messages, 2 authors, 2021-10-14

Re: [PATCH bpf-next v2 4/8] libbpf: Ensure that BPF syscall fds are never 0, 1, or 2

From: Song Liu <hidden>
Date: 2021-10-14 16:56:02
Also in: bpf

On Oct 13, 2021, at 12:33 AM, Kumar Kartikeya Dwivedi [off-list ref] wrote:

Add a simple wrapper for passing an fd and getting a new one >= 3 if it
is one of 0, 1, or 2. There are two primary reasons to make this change:
First, libbpf relies on the assumption a certain BPF fd is never 0 (e.g.
most recently noticed in [0]). Second, Alexei pointed out in [1] that
some environments reset stdin, stdout, and stderr if they notice an
invalid fd at these numbers. To protect against both these cases, switch
all internal BPF syscall wrappers in libbpf to always return an fd >= 3.
We only need to modify the syscall wrappers and not other code that
assumes a valid fd by doing >= 0, to avoid pointless churn, and because
it is still a valid assumption. The cost paid is two additional syscalls
if fd is in range [0, 2].
Acked-by: Song Liu <redacted>

With on nitpick below. 

[...]
+static inline int skel_reserve_bad_fds(struct bpf_load_and_run_opts *opts, int *fds)
+{
+	int fd, err, i;
+
+	for (i = 0; i < 3; i++) {
+		fd = open("/dev/null", O_RDONLY | O_CLOEXEC);
+		if (fd < 0) {
+			opts->errstr = "failed to reserve fd 0, 1, and 2";
+			err = -errno;
+			return err;
+		}
+		if (fd >= 3)
+			close(fd);
nit: Maybe likely(fd >= 3) and break here? 
quoted hunk ↗ jump to hunk
+		else
+			fds[i] = fd;
+	}
+	return 0;
+}
+
static inline int bpf_load_and_run(struct bpf_load_and_run_opts *opts)
{
-	int map_fd = -1, prog_fd = -1, key = 0, err;
+	int map_fd = -1, prog_fd = -1, key = 0, err, i;
+	int res_fds[3] = { -1, -1, -1 };
	union bpf_attr attr;

+	/* ensures that we don't open fd 0, 1, or 2 from here on out */
+	err = skel_reserve_bad_fds(opts, res_fds);
+	if (err < 0) {
+		errno = -err;
+		goto out;
+	}
+
	map_fd = bpf_create_map_name(BPF_MAP_TYPE_ARRAY, "__loader.map", 4,
				     opts->data_sz, 1, 0);
	if (map_fd < 0) {
@@ -115,6 +143,10 @@ static inline int bpf_load_and_run(struct bpf_load_and_run_opts *opts)
	}
	err = 0;
out:
+	for (i = 0; i < 3; i++) {
+		if (res_fds[i] >= 0)
+			close(res_fds[i]);
+	}
	if (map_fd >= 0)
		close(map_fd);
	if (prog_fd >= 0)
-- 
2.33.0
  
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help