[PATCH v2 4/6] Use finfo structure to arbitrate overwrapped IOCTL command assignments between TTY and SND
Masatake YAMATO
yamato at redhat.com
Fri Mar 11 18:02:07 UTC 2022
IOCTL command assignments are overwrapped.
We could observe the overwrapping when running vi under strace
on x86_64 arch:
ioctl(0, SNDCTL_TMR_START or TCSETS, {B38400 ...
If a fd opens /dev/pts/*, strace with this patch can decode
the same ioctl invocation like:
ioctl(0, TCSETS, {B38400 ...
* src/defs.h (+term_ioctl_decode_command_number): New function
declaration.
* src/ioctl.c (ioctl_decode_command_number): Add a new parameter
for passing finfo that can be used as hint for ioctl command
decoding. Handle the code `T': calling
term_ioctl_decode_command_number().
(SYS_FUNC(ioctl)): Pass finfo as hint to ioctl_decode_command_number().
* src/term.c(term_ioctl_decode_command_number): decode the command in
this earlier stage if the passed fd opens /dev/pts/*.
Signed-off-by: Masatake YAMATO <yamato at redhat.com>
---
src/defs.h | 4 ++++
src/ioctl.c | 7 ++++--
src/term.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 73 insertions(+), 2 deletions(-)
diff --git a/src/defs.h b/src/defs.h
index 8cfc8d767..8811fae8f 100644
--- a/src/defs.h
+++ b/src/defs.h
@@ -668,6 +668,10 @@ struct finfo {
extern
struct finfo *get_finfo_for_dev(const char *path, struct finfo *finfo);
+extern int
+term_ioctl_decode_command_number(int code,
+ struct tcb *tcp, struct finfo *finfo);
+
/**
* @return 0 on success, -1 on error.
*/
diff --git a/src/ioctl.c b/src/ioctl.c
index 0f9f0c9a9..a839da817 100644
--- a/src/ioctl.c
+++ b/src/ioctl.c
@@ -240,7 +240,7 @@ hiddev_decode_number(const unsigned int code)
}
static int
-ioctl_decode_command_number(struct tcb *tcp)
+ioctl_decode_command_number(struct tcb *tcp, struct finfo *finfo)
{
const unsigned int code = tcp->u_arg[1];
@@ -268,6 +268,9 @@ ioctl_decode_command_number(struct tcb *tcp)
return 1;
}
return 0;
+ case 'T':
+ return term_ioctl_decode_command_number(code,
+ tcp, finfo);
case 'U':
if (_IOC_DIR(code) == _IOC_READ && _IOC_NR(code) == 0x2c) {
tprints_arg_begin("UI_GET_SYSNAME");
@@ -445,7 +448,7 @@ SYS_FUNC(ioctl)
if (xlat_verbosity == XLAT_STYLE_VERBOSE)
tprint_comment_begin();
if (xlat_verbosity != XLAT_STYLE_RAW) {
- ret = ioctl_decode_command_number(tcp);
+ ret = ioctl_decode_command_number(tcp, finfo);
if (!(ret & IOCTL_NUMBER_STOP_LOOKUP)) {
iop = ioctl_lookup(tcp->u_arg[1]);
if (iop) {
diff --git a/src/term.c b/src/term.c
index 73cc7d63c..a0836a3d6 100644
--- a/src/term.c
+++ b/src/term.c
@@ -273,3 +273,67 @@ term_ioctl(struct tcb *const tcp, const unsigned int code,
return RVAL_IOCTL_DECODED;
}
+
+/* The command numbers for TCSETSF, TCSETSW, and TCSETS
+ * conflict with that for SND:
+ *
+ * 0x00005404
+ * { "SNDCTL_TMR_CONTINUE", 0x00005404 },
+ * { "TCSETSF", 0x00005404 },
+ * 0x00005403
+ * { "SNDCTL_TMR_STOP", 0x00005403 },
+ * { "TCSETSW", 0x00005403 },
+ * 0x00005402
+ * { "SNDCTL_TMR_START", 0x00005402 },
+ * { "TCSETS", 0x00005402 },
+ *
+ * This function tries to solve the command name with the
+ * device information associated with FD.
+ *
+ * Above overwrapping is observed on x86_64.
+ * On parisc and sparc, TCSETA, TCSETAW, and TCSETAF conflict
+ * with the SNDCTL commands:
+ *
+ * $ cd linux/arch
+ * $ grep "'T'" *\/include/uapi/asm/ioctls.h | grep '\<[234]\>'
+ * parisc/include/uapi/asm/ioctls.h:#define TCSETA _IOW('T', 2, struct termio)
+ * parisc/include/uapi/asm/ioctls.h:#define TCSETAW _IOW('T', 3, struct termio)
+ * parisc/include/uapi/asm/ioctls.h:#define TCSETAF _IOW('T', 4, struct termio)
+ * sparc/include/uapi/asm/ioctls.h:#define TCSETA _IOW('T', 2, struct termio)
+ * sparc/include/uapi/asm/ioctls.h:#define TCSETAW _IOW('T', 3, struct termio)
+ * sparc/include/uapi/asm/ioctls.h:#define TCSETAF _IOW('T', 4, struct termio)
+ */
+extern int
+term_ioctl_decode_command_number(int code,
+ struct tcb *tcp, struct finfo *finfo)
+{
+ /* See Documentation/admin-guide/devices.txt of
+ * Linux kernel source tree about the number 3, 4, 5, 136 ~ 143.
+ */
+ if (finfo
+ && finfo->type == finfo_dev_chr
+ && ((136 <= finfo->dev.major && finfo->dev.major <= 143)
+ || (3 <= finfo->dev.major && finfo->dev.major <= 5))) {
+ switch (code) {
+ case TCSETSF:
+ tprints("TCSETSF");
+ return IOCTL_NUMBER_STOP_LOOKUP;
+ case TCSETSW:
+ tprints("TCSETSW");
+ return IOCTL_NUMBER_STOP_LOOKUP;
+ case TCSETS:
+ tprints("TCSETS");
+ return IOCTL_NUMBER_STOP_LOOKUP;
+ case TCSETA:
+ tprints("TCSETA");
+ return IOCTL_NUMBER_STOP_LOOKUP;
+ case TCSETAW:
+ tprints("TCSETAW");
+ return IOCTL_NUMBER_STOP_LOOKUP;
+ case TCSETAF:
+ tprints("TCSETAF");
+ return IOCTL_NUMBER_STOP_LOOKUP;
+ }
+ }
+ return 0;
+}
--
2.35.1
More information about the Strace-devel
mailing list