aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/sg.c
diff options
context:
space:
mode:
authorAdel Gadllah <adel.gadllah@gmail.com>2008-06-26 07:48:27 -0400
committerJens Axboe <jens.axboe@oracle.com>2008-07-03 07:21:14 -0400
commit0b07de85a76e1346e675f0e98437378932473df7 (patch)
treeb86e5e0be27679c408ab525534c76162754129b9 /drivers/scsi/sg.c
parent6e2401ad6f33de15ff00f78b88159f00a14f3b35 (diff)
allow userspace to modify scsi command filter on per device basis
This patch exports the per-gendisk command filter to user space through sysfs, so it can be changed by the system administrator. All users of the old cmd filter have been converted to use the new one. Original patch from Peter Jones. Signed-off-by: Adel Gadllah <adel.gadllah@gmail.com> Signed-off-by: Peter Jones <pjones@redhat.com> Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'drivers/scsi/sg.c')
-rw-r--r--drivers/scsi/sg.c40
1 files changed, 10 insertions, 30 deletions
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index ea0edd1b2e76..f7abccaffaec 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -182,8 +182,9 @@ static int sg_build_sgat(Sg_scatter_hold * schp, const Sg_fd * sfp,
182 int tablesize); 182 int tablesize);
183static ssize_t sg_new_read(Sg_fd * sfp, char __user *buf, size_t count, 183static ssize_t sg_new_read(Sg_fd * sfp, char __user *buf, size_t count,
184 Sg_request * srp); 184 Sg_request * srp);
185static ssize_t sg_new_write(Sg_fd * sfp, const char __user *buf, size_t count, 185static ssize_t sg_new_write(Sg_fd *sfp, struct file *file,
186 int blocking, int read_only, Sg_request ** o_srp); 186 const char __user *buf, size_t count, int blocking,
187 int read_only, Sg_request **o_srp);
187static int sg_common_write(Sg_fd * sfp, Sg_request * srp, 188static int sg_common_write(Sg_fd * sfp, Sg_request * srp,
188 unsigned char *cmnd, int timeout, int blocking); 189 unsigned char *cmnd, int timeout, int blocking);
189static int sg_u_iovec(sg_io_hdr_t * hp, int sg_num, int ind, 190static int sg_u_iovec(sg_io_hdr_t * hp, int sg_num, int ind,
@@ -204,7 +205,6 @@ static Sg_request *sg_get_rq_mark(Sg_fd * sfp, int pack_id);
204static Sg_request *sg_add_request(Sg_fd * sfp); 205static Sg_request *sg_add_request(Sg_fd * sfp);
205static int sg_remove_request(Sg_fd * sfp, Sg_request * srp); 206static int sg_remove_request(Sg_fd * sfp, Sg_request * srp);
206static int sg_res_in_use(Sg_fd * sfp); 207static int sg_res_in_use(Sg_fd * sfp);
207static int sg_allow_access(unsigned char opcode, char dev_type);
208static int sg_build_direct(Sg_request * srp, Sg_fd * sfp, int dxfer_len); 208static int sg_build_direct(Sg_request * srp, Sg_fd * sfp, int dxfer_len);
209static Sg_device *sg_get_dev(int dev); 209static Sg_device *sg_get_dev(int dev);
210#ifdef CONFIG_SCSI_PROC_FS 210#ifdef CONFIG_SCSI_PROC_FS
@@ -544,7 +544,7 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
544 return -EFAULT; 544 return -EFAULT;
545 blocking = !(filp->f_flags & O_NONBLOCK); 545 blocking = !(filp->f_flags & O_NONBLOCK);
546 if (old_hdr.reply_len < 0) 546 if (old_hdr.reply_len < 0)
547 return sg_new_write(sfp, buf, count, blocking, 0, NULL); 547 return sg_new_write(sfp, filp, buf, count, blocking, 0, NULL);
548 if (count < (SZ_SG_HEADER + 6)) 548 if (count < (SZ_SG_HEADER + 6))
549 return -EIO; /* The minimum scsi command length is 6 bytes. */ 549 return -EIO; /* The minimum scsi command length is 6 bytes. */
550 550
@@ -621,8 +621,9 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
621} 621}
622 622
623static ssize_t 623static ssize_t
624sg_new_write(Sg_fd * sfp, const char __user *buf, size_t count, 624sg_new_write(Sg_fd *sfp, struct file *file, const char __user *buf,
625 int blocking, int read_only, Sg_request ** o_srp) 625 size_t count, int blocking, int read_only,
626 Sg_request **o_srp)
626{ 627{
627 int k; 628 int k;
628 Sg_request *srp; 629 Sg_request *srp;
@@ -678,8 +679,7 @@ sg_new_write(Sg_fd * sfp, const char __user *buf, size_t count,
678 sg_remove_request(sfp, srp); 679 sg_remove_request(sfp, srp);
679 return -EFAULT; 680 return -EFAULT;
680 } 681 }
681 if (read_only && 682 if (read_only && (!blk_verify_command(file, cmnd))) {
682 (!sg_allow_access(cmnd[0], sfp->parentdp->device->type))) {
683 sg_remove_request(sfp, srp); 683 sg_remove_request(sfp, srp);
684 return -EPERM; 684 return -EPERM;
685 } 685 }
@@ -799,7 +799,7 @@ sg_ioctl(struct inode *inode, struct file *filp,
799 if (!access_ok(VERIFY_WRITE, p, SZ_SG_IO_HDR)) 799 if (!access_ok(VERIFY_WRITE, p, SZ_SG_IO_HDR))
800 return -EFAULT; 800 return -EFAULT;
801 result = 801 result =
802 sg_new_write(sfp, p, SZ_SG_IO_HDR, 802 sg_new_write(sfp, filp, p, SZ_SG_IO_HDR,
803 blocking, read_only, &srp); 803 blocking, read_only, &srp);
804 if (result < 0) 804 if (result < 0)
805 return result; 805 return result;
@@ -1048,7 +1048,7 @@ sg_ioctl(struct inode *inode, struct file *filp,
1048 1048
1049 if (copy_from_user(&opcode, siocp->data, 1)) 1049 if (copy_from_user(&opcode, siocp->data, 1))
1050 return -EFAULT; 1050 return -EFAULT;
1051 if (!sg_allow_access(opcode, sdp->device->type)) 1051 if (!blk_verify_command(filp, &opcode))
1052 return -EPERM; 1052 return -EPERM;
1053 } 1053 }
1054 return sg_scsi_ioctl(filp, sdp->device->request_queue, NULL, p); 1054 return sg_scsi_ioctl(filp, sdp->device->request_queue, NULL, p);
@@ -2506,26 +2506,6 @@ sg_page_free(struct page *page, int size)
2506#define MAINTENANCE_IN_CMD 0xa3 2506#define MAINTENANCE_IN_CMD 0xa3
2507#endif 2507#endif
2508 2508
2509static unsigned char allow_ops[] = { TEST_UNIT_READY, REQUEST_SENSE,
2510 INQUIRY, READ_CAPACITY, READ_BUFFER, READ_6, READ_10, READ_12,
2511 READ_16, MODE_SENSE, MODE_SENSE_10, LOG_SENSE, REPORT_LUNS,
2512 SERVICE_ACTION_IN, RECEIVE_DIAGNOSTIC, READ_LONG, MAINTENANCE_IN_CMD
2513};
2514
2515static int
2516sg_allow_access(unsigned char opcode, char dev_type)
2517{
2518 int k;
2519
2520 if (TYPE_SCANNER == dev_type) /* TYPE_ROM maybe burner */
2521 return 1;
2522 for (k = 0; k < sizeof (allow_ops); ++k) {
2523 if (opcode == allow_ops[k])
2524 return 1;
2525 }
2526 return 0;
2527}
2528
2529#ifdef CONFIG_SCSI_PROC_FS 2509#ifdef CONFIG_SCSI_PROC_FS
2530static int 2510static int
2531sg_idr_max_id(int id, void *p, void *data) 2511sg_idr_max_id(int id, void *p, void *data)