[PATCH v2 2/2] scsi: sg: Require CAP_SYS_ADMIN for BLKTRACE passthrough ioctls

From: Tao Cui

Date: Wed Nov 11 2026 - 09:53:31 EST


From: Tao Cui <cuitao@xxxxxxxxxx>

sg_ioctl_common() calls blk_trace_setup(), blk_trace_startstop()
and blk_trace_remove() directly instead of going through
blk_trace_ioctl(), so gating the block side does not close the sg
passthrough: an unprivileged process with access to an /dev/sg node
could still allocate relay buffers and control tracing state on the
underlying request queue.

Require CAP_SYS_ADMIN for the four passthrough commands. The check
sits after the command log line so the new rejections stay visible
in the ioctl trace, and it is qualified with
IS_ENABLED(CONFIG_BLK_DEV_IO_TRACE) so kernels without blktrace
keep returning -ENOTTY for these commands instead of a new -EPERM.

BLKTRACE ioctls through sg now get the same answer they would get
through the block device node: -EPERM for unprivileged callers,
regardless of the trace or queue state behind the node.

Signed-off-by: Tao Cui <cuitao@xxxxxxxxxx>
---
drivers/scsi/sg.c | 10 ++++++++++
1 file changed, 10 insertions(+)

diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 6551f1284d44..f863979604ef 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -911,6 +911,13 @@ static int put_compat_request_table(struct compat_sg_req_info __user *o,
}
#endif

+/* keep in sync with the commands blk_trace_ioctl() gates */
+static bool sg_is_blktrace_cmd(unsigned int cmd)
+{
+ return cmd == BLKTRACESETUP || cmd == BLKTRACESTART ||
+ cmd == BLKTRACESTOP || cmd == BLKTRACETEARDOWN;
+}
+
static long
sg_ioctl_common(struct file *filp, Sg_device *sdp, Sg_fd *sfp,
unsigned int cmd_in, void __user *p)
@@ -922,6 +929,9 @@ sg_ioctl_common(struct file *filp, Sg_device *sdp, Sg_fd *sfp,

SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sdp,
"sg_ioctl: cmd=0x%x\n", (int) cmd_in));
+ if (IS_ENABLED(CONFIG_BLK_DEV_IO_TRACE) &&
+ sg_is_blktrace_cmd(cmd_in) && !capable(CAP_SYS_ADMIN))
+ return -EPERM;
read_only = (O_RDWR != (filp->f_flags & O_ACCMODE));

switch (cmd_in) {
--
2.53.0