[PATCH] pidfd_getfd: fix decoder

Ákos Uzonyi uzonyi.akos at gmail.com
Mon Apr 20 23:10:20 UTC 2020


The decoder incorrectly assumed the first argument being a pid,
but actually it is a pidfd.

As of now, the patch does not change behavior, since print_pid_fd
is not really implemented yet (just simply prints the fd).

* defs.h (pidfd_get_pid): New function definition.
* utils.c (pidfd_get_pid): New function, returns the pid of a pidfd.
(printpidfd): Rewritten using pidfd_get_pid.
(printfd): Removed path argument from printpidfd.
* pidfd_getfd.c: Use pidfd_get_pid to get the pid of the pidfd.

Fixes: v5.6~46 "Implement pidfd_getfd syscall decoding"

Signed-off-by: Ákos Uzonyi <uzonyi.akos at gmail.com>
---
 defs.h        |  1 +
 pidfd_getfd.c |  8 +++++++-
 util.c        | 36 +++++++++++++++++++++++-------------
 3 files changed, 31 insertions(+), 14 deletions(-)

diff --git a/defs.h b/defs.h
index 0968bc35..504c4eea 100644
--- a/defs.h
+++ b/defs.h
@@ -1027,6 +1027,7 @@ printpath(struct tcb *, kernel_ulong_t addr);
 
 # define TIMESPEC_TEXT_BUFSIZE \
 		(sizeof(long long) * 3 * 2 + sizeof("{tv_sec=-, tv_nsec=}"))
+extern pid_t pidfd_get_pid(struct tcb *, int);
 extern void printfd(struct tcb *, int);
 /**
  * Print file descriptor fd owned by process with ID pid (from the PID NS
diff --git a/pidfd_getfd.c b/pidfd_getfd.c
index c5c40ae6..b93563a5 100644
--- a/pidfd_getfd.c
+++ b/pidfd_getfd.c
@@ -15,7 +15,13 @@ SYS_FUNC(pidfd_getfd)
 	printfd(tcp, (int) tcp->u_arg[0]);
 	/* int fd */
 	tprints(", ");
-	print_pid_fd(tcp, (int) tcp->u_arg[0], (int) tcp->u_arg[1]);
+
+	pid_t pid = pidfd_get_pid(tcp, (int) tcp->u_arg[0]);
+	if (pid >= 0)
+		print_pid_fd(tcp, pid, (int) tcp->u_arg[1]);
+	else
+		tprintf("%d", (int) tcp->u_arg[1]);
+
 	/* unsigned int flags */
 	tprintf(", %#x", (unsigned int) tcp->u_arg[2]);
 
diff --git a/util.c b/util.c
index 0d9de2f6..c7f5d68d 100644
--- a/util.c
+++ b/util.c
@@ -567,43 +567,53 @@ printdev(struct tcb *tcp, int fd, const char *path)
 	return false;
 }
 
-static bool
-printpidfd(struct tcb *tcp, int fd, const char *path)
+pid_t
+pidfd_get_pid(struct tcb *tcp, int fd)
 {
 	static const char pidfd_path[] = "anon_inode:[pidfd]";
 
+	char path[PATH_MAX + 1];
+	if (getfdpath(tcp, fd, path, sizeof(path)) < 0)
+		return -1;
+
 	if (strcmp(path, pidfd_path))
-		return false;
+		return -1;
 
 	char fdi_path[sizeof("/proc/%u/fdinfo/%u") + 2 * sizeof(int) * 3];
 	xsprintf(fdi_path, "/proc/%u/fdinfo/%u", tcp->pid, fd);
 
 	FILE *f = fopen_stream(fdi_path, "r");
 	if (!f)
-		return false;
+		return -1;
 
 	static const char pid_pfx[] = "Pid:\t";
 	char *line = NULL;
 	size_t sz = 0;
-	bool ret = false;
+	pid_t pid = -1;
 	while (getline(&line, &sz, f) > 0) {
 		const char *pos = STR_STRIP_PREFIX(line, pid_pfx);
 		if (pos == line)
 			continue;
 
-		int pid = string_to_uint_ex(pos, NULL, INT_MAX, "\n");
-		if (pid >= 0) {
-			tprintf("pid:%d", pid);
-			ret = true;
-		}
-
+		pid = string_to_uint_ex(pos, NULL, INT_MAX, "\n");
 		break;
 	}
 
 	free(line);
 	fclose(f);
 
-	return ret;
+	return pid;
+}
+
+static bool
+printpidfd(struct tcb *tcp, int fd)
+{
+	int pid = pidfd_get_pid(tcp, fd);
+	if (pid < 0)
+		return false;
+
+	tprintf("pid:%d", pid);
+	return true;
 }
 
 void
@@ -620,7 +630,7 @@ printfd(struct tcb *tcp, int fd)
 		    printdev(tcp, fd, path))
 			goto printed;
 		if (is_number_in_set(DECODE_FD_PIDFD, decode_fd_set) &&
-		    printpidfd(tcp, fd, path))
+		    printpidfd(tcp, fd))
 			goto printed;
 		print_quoted_string_ex(path, strlen(path),
 			QUOTE_OMIT_LEADING_TRAILING_QUOTES, "<>");
-- 
2.26.1



More information about the Strace-devel mailing list