Thread (13 messages) flat view 13 messages, 3 authors, 2019-12-13

Re: [PATCH bpf-next 1/3] bpftool: match several programs with same tag

From: Jakub Kicinski <hidden>
Date: 2019-12-10 20:36:31
Also in: bpf

On Tue, 10 Dec 2019 17:06:25 +0100, Paul Chaignon wrote:
When several BPF programs have the same tag, bpftool matches only the
first (in ID order).  This patch changes that behavior such that dump and
show commands return all matched programs.  Commands that require a single
program (e.g., pin and attach) will error out if given a tag that matches
several.  bpftool prog dump will also error out if file or visual are
given and several programs have the given tag.

In the case of the dump command, a program header is added before each
dump only if the tag matches several programs; this patch doesn't change
the output if a single program matches.
How does this work? Could you add examples to the commit message?

This header idea doesn't seem correct, aren't id and other per-instance
fields only printed once?
Signed-off-by: Paul Chaignon <redacted>
-		close(fd);
+		if (nb_fds > 0) {
+			tmp = realloc(fds, (nb_fds + 1) * sizeof(int));
+			if (!tmp) {
+				p_err("failed to realloc");
+				goto err_close_fd;
+			}
+			fds = tmp;
How does this work? the new array is never returned to the caller, and
the caller will most likely access freed memory, no?
+		}
+		fds[nb_fds++] = fd;
 	}
+
+err_close_fd:
+	close(fd);
+err_close_fds:
+	for (nb_fds--; nb_fds >= 0; nb_fds--)
+		close(fds[nb_fds]);
+	return -1;
 }
+int prog_parse_fd(int *argc, char ***argv)
+{
+	int *fds = NULL;
+	int nb_fds, fd;
+
+	fds = malloc(sizeof(int));
+	if (!fds) {
+		p_err("mem alloc failed");
+		return -1;
+	}
+	nb_fds = prog_parse_fds(argc, argv, fds);
+	if (nb_fds != 1) {
+		if (nb_fds > 1) {
+			p_err("several programs match this handle");
+			for (nb_fds--; nb_fds >= 0; nb_fds--)
nit: since you checked nb_fds is positive, while (nb_fds--) ?
+				close(fds[nb_fds]);
+		}
+		fd = -1;
+		goto err_free;
+	}
+
+	fd = fds[0];
+err_free:
nit: we tried to call the labels exit_xyz if the code is used on both
     error and success path, but maybe that pattern got lost over time.
+	free(fds);
+	return fd;
+}
+
 static void show_prog_maps(int fd, u32 num_maps)
 {
 	struct bpf_prog_info info = {};
 static int do_show(int argc, char **argv)
 {
+	int fd, nb_fds, i;
+	int *fds = NULL;
 	__u32 id = 0;
 	int err;
-	int fd;
 
 	if (show_pinned)
 		build_pinned_obj_table(&prog_table, BPF_OBJ_PROG);
 
 	if (argc == 2) {
-		fd = prog_parse_fd(&argc, &argv);
-		if (fd < 0)
+		fds = malloc(sizeof(int));
+		if (!fds) {
+			p_err("mem alloc failed");
 			return -1;
+		}
+		nb_fds = prog_parse_fds(&argc, &argv, fds);
+		if (nb_fds < 1)
+			goto err_free;
 
-		err = show_prog(fd);
-		close(fd);
-		return err;
+		if (json_output && nb_fds > 1)
+			jsonw_start_array(json_wtr);	/* root array */
+		for (i = 0; i < nb_fds; i++) {
+			err = show_prog(fds[i]);
+			close(fds[i]);
+			if (err) {
+				for (i++; i < nb_fds; i++)
+					close(fds[i]);
+				goto err_free;
I'm 90% sure JSON arrays close/end themselves on exit 🤔
+			}
+		}
+		if (json_output && nb_fds > 1)
+			jsonw_end_array(json_wtr);	/* root array */
+
+		return 0;
+
+err_free:
+		free(fds);
+		return -1;
Perhaps move the argc == 2 code to a separate function?
quoted hunk ↗ jump to hunk
 	}
 
 	if (argc)
@@ -408,101 +500,32 @@ static int do_show(int argc, char **argv)
 	return err;
 }
  
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help