aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/sg.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/sg.c')
-rw-r--r--drivers/scsi/sg.c60
1 files changed, 23 insertions, 37 deletions
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index ea0edd1b2e76..fccd2e88d600 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -49,6 +49,7 @@ static int sg_version_num = 30534; /* 2 digits for each component */
49#include <linux/delay.h> 49#include <linux/delay.h>
50#include <linux/scatterlist.h> 50#include <linux/scatterlist.h>
51#include <linux/blktrace_api.h> 51#include <linux/blktrace_api.h>
52#include <linux/smp_lock.h>
52 53
53#include "scsi.h" 54#include "scsi.h"
54#include <scsi/scsi_dbg.h> 55#include <scsi/scsi_dbg.h>
@@ -182,8 +183,9 @@ static int sg_build_sgat(Sg_scatter_hold * schp, const Sg_fd * sfp,
182 int tablesize); 183 int tablesize);
183static ssize_t sg_new_read(Sg_fd * sfp, char __user *buf, size_t count, 184static ssize_t sg_new_read(Sg_fd * sfp, char __user *buf, size_t count,
184 Sg_request * srp); 185 Sg_request * srp);
185static ssize_t sg_new_write(Sg_fd * sfp, const char __user *buf, size_t count, 186static ssize_t sg_new_write(Sg_fd *sfp, struct file *file,
186 int blocking, int read_only, Sg_request ** o_srp); 187 const char __user *buf, size_t count, int blocking,
188 int read_only, Sg_request **o_srp);
187static int sg_common_write(Sg_fd * sfp, Sg_request * srp, 189static int sg_common_write(Sg_fd * sfp, Sg_request * srp,
188 unsigned char *cmnd, int timeout, int blocking); 190 unsigned char *cmnd, int timeout, int blocking);
189static int sg_u_iovec(sg_io_hdr_t * hp, int sg_num, int ind, 191static int sg_u_iovec(sg_io_hdr_t * hp, int sg_num, int ind,
@@ -204,7 +206,6 @@ static Sg_request *sg_get_rq_mark(Sg_fd * sfp, int pack_id);
204static Sg_request *sg_add_request(Sg_fd * sfp); 206static Sg_request *sg_add_request(Sg_fd * sfp);
205static int sg_remove_request(Sg_fd * sfp, Sg_request * srp); 207static int sg_remove_request(Sg_fd * sfp, Sg_request * srp);
206static int sg_res_in_use(Sg_fd * sfp); 208static 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); 209static int sg_build_direct(Sg_request * srp, Sg_fd * sfp, int dxfer_len);
209static Sg_device *sg_get_dev(int dev); 210static Sg_device *sg_get_dev(int dev);
210#ifdef CONFIG_SCSI_PROC_FS 211#ifdef CONFIG_SCSI_PROC_FS
@@ -227,19 +228,26 @@ sg_open(struct inode *inode, struct file *filp)
227 int res; 228 int res;
228 int retval; 229 int retval;
229 230
231 lock_kernel();
230 nonseekable_open(inode, filp); 232 nonseekable_open(inode, filp);
231 SCSI_LOG_TIMEOUT(3, printk("sg_open: dev=%d, flags=0x%x\n", dev, flags)); 233 SCSI_LOG_TIMEOUT(3, printk("sg_open: dev=%d, flags=0x%x\n", dev, flags));
232 sdp = sg_get_dev(dev); 234 sdp = sg_get_dev(dev);
233 if ((!sdp) || (!sdp->device)) 235 if ((!sdp) || (!sdp->device)) {
236 unlock_kernel();
234 return -ENXIO; 237 return -ENXIO;
235 if (sdp->detached) 238 }
239 if (sdp->detached) {
240 unlock_kernel();
236 return -ENODEV; 241 return -ENODEV;
242 }
237 243
238 /* This driver's module count bumped by fops_get in <linux/fs.h> */ 244 /* This driver's module count bumped by fops_get in <linux/fs.h> */
239 /* Prevent the device driver from vanishing while we sleep */ 245 /* Prevent the device driver from vanishing while we sleep */
240 retval = scsi_device_get(sdp->device); 246 retval = scsi_device_get(sdp->device);
241 if (retval) 247 if (retval) {
248 unlock_kernel();
242 return retval; 249 return retval;
250 }
243 251
244 if (!((flags & O_NONBLOCK) || 252 if (!((flags & O_NONBLOCK) ||
245 scsi_block_when_processing_errors(sdp->device))) { 253 scsi_block_when_processing_errors(sdp->device))) {
@@ -295,10 +303,12 @@ sg_open(struct inode *inode, struct file *filp)
295 retval = -ENOMEM; 303 retval = -ENOMEM;
296 goto error_out; 304 goto error_out;
297 } 305 }
306 unlock_kernel();
298 return 0; 307 return 0;
299 308
300 error_out: 309 error_out:
301 scsi_device_put(sdp->device); 310 scsi_device_put(sdp->device);
311 unlock_kernel();
302 return retval; 312 return retval;
303} 313}
304 314
@@ -544,7 +554,7 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
544 return -EFAULT; 554 return -EFAULT;
545 blocking = !(filp->f_flags & O_NONBLOCK); 555 blocking = !(filp->f_flags & O_NONBLOCK);
546 if (old_hdr.reply_len < 0) 556 if (old_hdr.reply_len < 0)
547 return sg_new_write(sfp, buf, count, blocking, 0, NULL); 557 return sg_new_write(sfp, filp, buf, count, blocking, 0, NULL);
548 if (count < (SZ_SG_HEADER + 6)) 558 if (count < (SZ_SG_HEADER + 6))
549 return -EIO; /* The minimum scsi command length is 6 bytes. */ 559 return -EIO; /* The minimum scsi command length is 6 bytes. */
550 560
@@ -621,8 +631,9 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
621} 631}
622 632
623static ssize_t 633static ssize_t
624sg_new_write(Sg_fd * sfp, const char __user *buf, size_t count, 634sg_new_write(Sg_fd *sfp, struct file *file, const char __user *buf,
625 int blocking, int read_only, Sg_request ** o_srp) 635 size_t count, int blocking, int read_only,
636 Sg_request **o_srp)
626{ 637{
627 int k; 638 int k;
628 Sg_request *srp; 639 Sg_request *srp;
@@ -678,8 +689,7 @@ sg_new_write(Sg_fd * sfp, const char __user *buf, size_t count,
678 sg_remove_request(sfp, srp); 689 sg_remove_request(sfp, srp);
679 return -EFAULT; 690 return -EFAULT;
680 } 691 }
681 if (read_only && 692 if (read_only && !blk_verify_command(file, cmnd)) {
682 (!sg_allow_access(cmnd[0], sfp->parentdp->device->type))) {
683 sg_remove_request(sfp, srp); 693 sg_remove_request(sfp, srp);
684 return -EPERM; 694 return -EPERM;
685 } 695 }
@@ -799,7 +809,7 @@ sg_ioctl(struct inode *inode, struct file *filp,
799 if (!access_ok(VERIFY_WRITE, p, SZ_SG_IO_HDR)) 809 if (!access_ok(VERIFY_WRITE, p, SZ_SG_IO_HDR))
800 return -EFAULT; 810 return -EFAULT;
801 result = 811 result =
802 sg_new_write(sfp, p, SZ_SG_IO_HDR, 812 sg_new_write(sfp, filp, p, SZ_SG_IO_HDR,
803 blocking, read_only, &srp); 813 blocking, read_only, &srp);
804 if (result < 0) 814 if (result < 0)
805 return result; 815 return result;
@@ -1048,7 +1058,7 @@ sg_ioctl(struct inode *inode, struct file *filp,
1048 1058
1049 if (copy_from_user(&opcode, siocp->data, 1)) 1059 if (copy_from_user(&opcode, siocp->data, 1))
1050 return -EFAULT; 1060 return -EFAULT;
1051 if (!sg_allow_access(opcode, sdp->device->type)) 1061 if (!blk_verify_command(filp, &opcode))
1052 return -EPERM; 1062 return -EPERM;
1053 } 1063 }
1054 return sg_scsi_ioctl(filp, sdp->device->request_queue, NULL, p); 1064 return sg_scsi_ioctl(filp, sdp->device->request_queue, NULL, p);
@@ -2502,30 +2512,6 @@ sg_page_free(struct page *page, int size)
2502 __free_pages(page, order); 2512 __free_pages(page, order);
2503} 2513}
2504 2514
2505#ifndef MAINTENANCE_IN_CMD
2506#define MAINTENANCE_IN_CMD 0xa3
2507#endif
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 2515#ifdef CONFIG_SCSI_PROC_FS
2530static int 2516static int
2531sg_idr_max_id(int id, void *p, void *data) 2517sg_idr_max_id(int id, void *p, void *data)