public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Jeff Garzik <jgarzik@pobox.com>
To: Peter Jones <pmjones@gmail.com>
Cc: Kai Makisara <kai.makisara@kolumbus.fi>,
	Linus Torvalds <torvalds@osdl.org>,
	Alan Cox <alan@lxorguk.ukuu.org.uk>,
	Linux Kernel Mailing List <linux-kernel@vger.kernel.org>
Subject: Re: SG_IO and security
Date: Fri, 13 Aug 2004 15:37:41 -0400	[thread overview]
Message-ID: <411D1885.8060904@pobox.com> (raw)
In-Reply-To: <9ac707cb040813122522d4a71@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 1039 bytes --]

Peter Jones wrote:
> On Thu, 12 Aug 2004 22:22:36 +0300 (EEST), Kai Makisara
> <kai.makisara@kolumbus.fi> wrote:
> 
>>On Thu, 12 Aug 2004, Linus Torvalds wrote:
>>
>>>Let's see now:
>>>
>>>      brw-rw----    1 root     disk       3,   0 Jan 30  2003 /dev/hda
>>>
>>>would you put people you don't trust with your disk in the "disk" group?
>>>
>>
>>This protects disks in practice but SG_IO is currently supported by other
>>devices, at least SCSI tapes. It is reasonable in some organizations to
>>give r/w access to ordinary users so that they can read/write tapes. I
>>would be worried if this would enable the users, for instance, to mess up
>>the mode page contents of the drive or change the firmware.
> 
> 
> Sure, but for that we need command based filtering.

We have that now (sigh).  See attached patch, which is in BK...

A similar approach could be applied to tape as well.

Though in general I think command-based filtering is not scalable...  at 
the very least I would prefer a list loaded from userspace at boot.

	Jeff



[-- Attachment #2: patch --]
[-- Type: text/plain, Size: 4666 bytes --]

# ChangeSet
#   2004/08/12 17:51:15-07:00 torvalds@ppc970.osdl.org 
#   Allow non-root users certain raw commands if they are deemed safe.
#   
#   We allow more commands if the disk was opened read-write.
# 
diff -Nru a/drivers/block/scsi_ioctl.c b/drivers/block/scsi_ioctl.c
--- a/drivers/block/scsi_ioctl.c	2004-08-13 15:35:28 -04:00
+++ b/drivers/block/scsi_ioctl.c	2004-08-13 15:35:28 -04:00
@@ -105,8 +105,80 @@
 	return put_user(1, p);
 }
 
-static int sg_io(request_queue_t *q, struct gendisk *bd_disk,
-		 struct sg_io_hdr *hdr)
+#define CMD_READ_SAFE	0x01
+#define CMD_WRITE_SAFE	0x02
+#define safe_for_read(cmd)	[cmd] = CMD_READ_SAFE
+#define safe_for_write(cmd)	[cmd] = CMD_WRITE_SAFE
+
+static int verify_command(struct file *file, unsigned char *cmd)
+{
+	static const unsigned char cmd_type[256] = {
+
+		/* Basic read-only commands */
+		safe_for_read(TEST_UNIT_READY),
+		safe_for_read(REQUEST_SENSE),
+		safe_for_read(READ_6),
+		safe_for_read(READ_10),
+		safe_for_read(READ_12),
+		safe_for_read(READ_16),
+		safe_for_read(READ_BUFFER),
+		safe_for_read(READ_LONG),
+		safe_for_read(INQUIRY),
+		safe_for_read(MODE_SENSE),
+		safe_for_read(MODE_SENSE_10),
+		safe_for_read(START_STOP),
+
+		/* Audio CD commands */
+		safe_for_read(GPCMD_PLAY_CD),
+		safe_for_read(GPCMD_PLAY_AUDIO_10),
+		safe_for_read(GPCMD_PLAY_AUDIO_MSF),
+		safe_for_read(GPCMD_PLAY_AUDIO_TI),
+
+		/* CD/DVD data reading */
+		safe_for_read(GPCMD_READ_CD),
+		safe_for_read(GPCMD_READ_CD_MSF),
+		safe_for_read(GPCMD_READ_DISC_INFO),
+		safe_for_read(GPCMD_READ_CDVD_CAPACITY),
+		safe_for_read(GPCMD_READ_DVD_STRUCTURE),
+		safe_for_read(GPCMD_READ_HEADER),
+		safe_for_read(GPCMD_READ_TRACK_RZONE_INFO),
+		safe_for_read(GPCMD_READ_SUBCHANNEL),
+		safe_for_read(GPCMD_READ_TOC_PMA_ATIP),
+		safe_for_read(GPCMD_REPORT_KEY),
+		safe_for_read(GPCMD_SCAN),
+
+		/* Basic writing commands */
+		safe_for_write(WRITE_6),
+		safe_for_write(WRITE_10),
+		safe_for_write(WRITE_VERIFY),
+		safe_for_write(WRITE_12),
+		safe_for_write(WRITE_VERIFY_12),
+		safe_for_write(WRITE_16),
+		safe_for_write(WRITE_BUFFER),
+		safe_for_write(WRITE_LONG),
+	};
+	unsigned char type = cmd_type[cmd[0]];
+
+	/* Anybody who can open the device can do a read-safe command */
+	if (type & CMD_READ_SAFE)
+		return 0;
+
+	/* Write-safe commands just require a writable open.. */
+	if (type & CMD_WRITE_SAFE) {
+		if (file->f_mode & FMODE_WRITE)
+			return 0;
+	}
+
+	/* And root can do any command.. */
+	if (capable(CAP_SYS_RAWIO))
+		return 0;
+
+	/* Otherwise fail it with an "Operation not permitted" */
+	return -EPERM;
+}
+
+static int sg_io(struct file *file, request_queue_t *q,
+		struct gendisk *bd_disk, struct sg_io_hdr *hdr)
 {
 	unsigned long start_time;
 	int reading, writing;
@@ -115,14 +187,14 @@
 	char sense[SCSI_SENSE_BUFFERSIZE];
 	unsigned char cmd[BLK_MAX_CDB];
 
-	if (!capable(CAP_SYS_RAWIO))
-		return -EPERM;
 	if (hdr->interface_id != 'S')
 		return -EINVAL;
 	if (hdr->cmd_len > BLK_MAX_CDB)
 		return -EINVAL;
 	if (copy_from_user(cmd, hdr->cmdp, hdr->cmd_len))
 		return -EFAULT;
+	if (verify_command(file, cmd))
+		return -EPERM;
 
 	/*
 	 * we'll do that later
@@ -228,15 +300,13 @@
 #define READ_DEFECT_DATA_TIMEOUT	(60 * HZ )
 #define OMAX_SB_LEN 16          /* For backward compatibility */
 
-static int sg_scsi_ioctl(request_queue_t *q, struct gendisk *bd_disk,
-			 Scsi_Ioctl_Command __user *sic)
+static int sg_scsi_ioctl(struct file *file, request_queue_t *q,
+			 struct gendisk *bd_disk, Scsi_Ioctl_Command __user *sic)
 {
 	struct request *rq;
 	int err, in_len, out_len, bytes, opcode, cmdlen;
 	char *buffer = NULL, sense[SCSI_SENSE_BUFFERSIZE];
 
-	if (!capable(CAP_SYS_RAWIO))
-		return -EPERM;
 	/*
 	 * get in an out lengths, verify they don't exceed a page worth of data
 	 */
@@ -273,6 +343,10 @@
 	if (copy_from_user(buffer, sic->data + cmdlen, in_len))
 		goto error;
 
+	err = verify_command(file, rq->cmd);
+	if (err)
+		goto error;
+
 	switch (opcode) {
 		case SEND_DIAGNOSTIC:
 		case FORMAT_UNIT:
@@ -370,7 +444,7 @@
 			err = -EFAULT;
 			if (copy_from_user(&hdr, arg, sizeof(hdr)))
 				break;
-			err = sg_io(q, bd_disk, &hdr);
+			err = sg_io(file, q, bd_disk, &hdr);
 			if (err == -EFAULT)
 				break;
 
@@ -418,7 +492,7 @@
 			hdr.cmdp = ((struct cdrom_generic_command __user*) arg)->cmd;
 			hdr.cmd_len = sizeof(cgc.cmd);
 
-			err = sg_io(q, bd_disk, &hdr);
+			err = sg_io(file, q, bd_disk, &hdr);
 			if (err == -EFAULT)
 				break;
 
@@ -441,7 +515,7 @@
 			if (!arg)
 				break;
 
-			err = sg_scsi_ioctl(q, bd_disk, arg);
+			err = sg_scsi_ioctl(file, q, bd_disk, arg);
 			break;
 		case CDROMCLOSETRAY:
 			close = 1;

  reply	other threads:[~2004-08-13 19:42 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-08-12 12:17 SG_IO and security Alan Cox
2004-08-12 16:39 ` Linus Torvalds
2004-08-12 16:45   ` Linus Torvalds
2004-08-12 16:55     ` Jeff Garzik
2004-08-12 17:01       ` Jeff Garzik
2004-08-12 17:02       ` Linus Torvalds
2004-08-12 17:13         ` Jeff Garzik
2004-08-12 19:22         ` Kai Makisara
2004-08-13 19:25           ` Peter Jones
2004-08-13 19:37             ` Jeff Garzik [this message]
2004-08-14  7:22               ` Kai Makisara
2004-08-14 15:33                 ` Alan Cox
2004-08-16 22:24               ` Bill Davidsen
2004-08-16 22:00         ` Bill Davidsen
2004-08-12 17:06       ` Arjan van de Ven
2004-08-12 17:35     ` Jens Axboe
2004-08-12 18:29       ` Jens Axboe
2004-08-12 18:37         ` Jeff Garzik
2004-08-12 18:43           ` Jens Axboe
2004-08-12 18:45             ` Christoph Hellwig
2004-08-12 18:48               ` Jens Axboe
2004-08-12 20:19         ` Alan Cox
2004-08-12 20:16     ` Alan Cox
2004-08-12 22:51       ` Eric Lammerts
2004-08-13  0:09       ` Linus Torvalds
2004-08-13  6:59         ` Jens Axboe
2004-08-13  7:22           ` viro
2004-08-13  7:43           ` Arjan van de Ven
2004-08-13  7:46             ` Jens Axboe
2004-08-13 19:18               ` Jeff Garzik
2004-08-13 19:37                 ` Linus Torvalds
2004-08-13 19:44                   ` Jeff Garzik
2004-08-13 19:49     ` Florian Weimer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=411D1885.8060904@pobox.com \
    --to=jgarzik@pobox.com \
    --cc=alan@lxorguk.ukuu.org.uk \
    --cc=kai.makisara@kolumbus.fi \
    --cc=linux-kernel@vger.kernel.org \
    --cc=pmjones@gmail.com \
    --cc=torvalds@osdl.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox