[PATCH 2/6] Extend printfd() to collect extra information about fd
Masatake YAMATO
yamato at redhat.com
Thu Mar 10 12:01:02 UTC 2022
The collected information can be used to improve decoding
arguments of system calls like ioctl.
* src/defs.h (fd_info): New structure definition for storing
extra information associated with a file descriptor.
(printfd_pid_filling_info): New function declaration extending
printfd_pid() to collect extra information about the fd when
printing it.
(printfd_pid): Inline it with using printfd_pid_filling_info().
(printfd_filling_info): New function based on
printfd_pid_filling_info().
(printfd): Use printfd_filling_info() instead of printfd_pid().
* src/ioctl.c (SYS_FUNC(ioctl)): Call printfd_filling_info()
instead of printfd() to collect extra information about the fd.
* src/util.c (printdev): Add an extra parameter `fd_info'. The
function stores extra information about the fd to the buffer
pointed by the parameter.
(printfd_pid_filling_info): New function doing what printfd_pid()
did and/or collecting the extra information about the fd.
Signed-off-by: Masatake YAMATO <yamato at redhat.com>
---
src/defs.h | 21 +++++++++++++++++++--
src/ioctl.c | 4 +++-
src/util.c | 39 ++++++++++++++++++++++++++++++++++-----
3 files changed, 56 insertions(+), 8 deletions(-)
diff --git a/src/defs.h b/src/defs.h
index d3d769be6..04c985268 100644
--- a/src/defs.h
+++ b/src/defs.h
@@ -653,6 +653,11 @@ static inline int set_tcb_priv_ulong(struct tcb *tcp, unsigned long val)
return set_tcb_priv_data(tcp, (void *) val, 0);
}
+struct fd_info {
+ enum { fd_info_unset, fd_info_dev_chr, fd_info_dev_blk } type;
+ unsigned int major, minor;
+};
+
/**
* @return 0 on success, -1 on error.
*/
@@ -1190,12 +1195,24 @@ extern pid_t pidfd_get_pid(pid_t pid_of_fd, int fd);
* Print file descriptor fd owned by process with ID pid (from the PID NS
* of the tracer).
*/
-extern void printfd_pid(struct tcb *tcp, pid_t pid, int fd);
+extern void printfd_pid_filling_info(struct tcb *tcp, pid_t pid, int fd,
+ struct fd_info **fd_info);
+
+static inline void printfd_pid(struct tcb *tcp, pid_t pid, int fd)
+{
+ printfd_pid_filling_info(tcp, pid, fd, NULL);
+}
+
+static inline void
+printfd_filling_info(struct tcb *tcp, int fd, struct fd_info **fd_info)
+{
+ printfd_pid_filling_info(tcp, tcp->pid, fd, fd_info);
+}
static inline void
printfd(struct tcb *tcp, int fd)
{
- printfd_pid(tcp, tcp->pid, fd);
+ printfd_filling_info(tcp, fd, NULL);
}
/**
diff --git a/src/ioctl.c b/src/ioctl.c
index 8173bdc6b..b6dcfff99 100644
--- a/src/ioctl.c
+++ b/src/ioctl.c
@@ -432,7 +432,9 @@ SYS_FUNC(ioctl)
int ret;
if (entering(tcp)) {
- printfd(tcp, tcp->u_arg[0]);
+ struct fd_info *fd_info = NULL;
+
+ printfd_filling_info(tcp, tcp->u_arg[0], &fd_info);
tprint_arg_next();
if (xlat_verbosity != XLAT_STYLE_ABBREV)
diff --git a/src/util.c b/src/util.c
index d0de13ada..8ef65b815 100644
--- a/src/util.c
+++ b/src/util.c
@@ -632,7 +632,7 @@ printsocket(struct tcb *tcp, int fd, const char *path)
}
static bool
-printdev(struct tcb *tcp, int fd, const char *path)
+printdev(struct tcb *tcp, int fd, const char *path, struct fd_info **fd_info)
{
strace_stat_t st;
@@ -654,6 +654,15 @@ printdev(struct tcb *tcp, int fd, const char *path)
tprintf("<%s %u:%u>>",
S_ISBLK(st.st_mode)? "block" : "char",
major(st.st_rdev), minor(st.st_rdev));
+
+ if (fd_info) {
+ struct fd_info *info = xmalloc(sizeof(*info));
+ info->type = S_ISBLK(st.st_mode)? fd_info_dev_blk: fd_info_dev_chr;
+ info->major = major(st.st_rdev);
+ info->minor = minor(st.st_rdev);
+ *fd_info = info;
+ }
+
return true;
}
@@ -726,18 +735,36 @@ print_quoted_string_in_angle_brackets(const char *str)
}
void
-printfd_pid(struct tcb *tcp, pid_t pid, int fd)
+printfd_pid_filling_info(struct tcb *tcp, pid_t pid, int fd, struct fd_info **fd_info)
{
PRINT_VAL_D(fd);
+ bool should_print = false;
char path[PATH_MAX + 1];
- if (pid > 0 && !number_set_array_is_empty(decode_fd_set, 0)
+ if (pid > 0
+ && ((should_print = !number_set_array_is_empty(decode_fd_set, 0)) || fd_info)
&& getfdpath_pid(pid, fd, path, sizeof(path)) >= 0) {
+ /*
+ * If FD_INFO is given, FT_INFO must be filled.
+ *
+ * <A> If the information of fd will be printed (SHOULD_PRINT),
+ * a helper function, printdev(), for printing also fills
+ * FD_INFO as side effect.
+ * <B> If the information of fd will not be printed (!SHOULD_PRINT),
+ * we must force to call the helper function for
+ * filling FD_INFO. However, nothing should be
+ * printed. Calling disable_tprint/enable_tprint
+ * is for disabling the output stream.
+ */
+ void *tprint_state = NULL;
+ if (!should_print)
+ tprint_state = disable_tprint();
+
if (is_number_in_set(DECODE_FD_SOCKET, decode_fd_set) &&
printsocket(tcp, fd, path))
goto printed;
- if (is_number_in_set(DECODE_FD_DEV, decode_fd_set) &&
- printdev(tcp, fd, path))
+ if ((fd_info || is_number_in_set(DECODE_FD_DEV, decode_fd_set)) &&
+ printdev(tcp, fd, path, fd_info))
goto printed;
if (is_number_in_set(DECODE_FD_PIDFD, decode_fd_set) &&
printpidfd(pid, fd, path))
@@ -745,6 +772,8 @@ printfd_pid(struct tcb *tcp, pid_t pid, int fd)
if (is_number_in_set(DECODE_FD_PATH, decode_fd_set))
print_quoted_string_in_angle_brackets(path);
printed: ;
+ if (!should_print)
+ enable_tprint(tprint_state);
}
selinux_printfdcon(pid, fd);
--
2.35.1
More information about the Strace-devel
mailing list