All of lore.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.