diff options
-rw-r--r-- | block/bsg.c | 27 | ||||
-rw-r--r-- | include/linux/bsg.h | 6 |
2 files changed, 27 insertions, 6 deletions
diff --git a/block/bsg.c b/block/bsg.c index 13ecc951a4c0..461c9f56f3ee 100644 --- a/block/bsg.c +++ b/block/bsg.c | |||
@@ -208,7 +208,11 @@ static int blk_fill_sgv4_hdr_rq(request_queue_t *q, struct request *rq, | |||
208 | if (copy_from_user(rq->cmd, (void *)(unsigned long)hdr->request, | 208 | if (copy_from_user(rq->cmd, (void *)(unsigned long)hdr->request, |
209 | hdr->request_len)) | 209 | hdr->request_len)) |
210 | return -EFAULT; | 210 | return -EFAULT; |
211 | if (blk_verify_command(rq->cmd, has_write_perm)) | 211 | |
212 | if (hdr->subprotocol == BSG_SUB_PROTOCOL_SCSI_CMD) { | ||
213 | if (blk_verify_command(rq->cmd, has_write_perm)) | ||
214 | return -EPERM; | ||
215 | } else if (!capable(CAP_SYS_RAWIO)) | ||
212 | return -EPERM; | 216 | return -EPERM; |
213 | 217 | ||
214 | /* | 218 | /* |
@@ -232,6 +236,8 @@ static int blk_fill_sgv4_hdr_rq(request_queue_t *q, struct request *rq, | |||
232 | static int | 236 | static int |
233 | bsg_validate_sgv4_hdr(request_queue_t *q, struct sg_io_v4 *hdr, int *rw) | 237 | bsg_validate_sgv4_hdr(request_queue_t *q, struct sg_io_v4 *hdr, int *rw) |
234 | { | 238 | { |
239 | int ret = 0; | ||
240 | |||
235 | if (hdr->guard != 'Q') | 241 | if (hdr->guard != 'Q') |
236 | return -EINVAL; | 242 | return -EINVAL; |
237 | if (hdr->request_len > BLK_MAX_CDB) | 243 | if (hdr->request_len > BLK_MAX_CDB) |
@@ -240,13 +246,22 @@ bsg_validate_sgv4_hdr(request_queue_t *q, struct sg_io_v4 *hdr, int *rw) | |||
240 | hdr->din_xfer_len > (q->max_sectors << 9)) | 246 | hdr->din_xfer_len > (q->max_sectors << 9)) |
241 | return -EIO; | 247 | return -EIO; |
242 | 248 | ||
243 | /* not supported currently */ | 249 | switch (hdr->protocol) { |
244 | if (hdr->protocol || hdr->subprotocol) | 250 | case BSG_PROTOCOL_SCSI: |
245 | return -EINVAL; | 251 | switch (hdr->subprotocol) { |
252 | case BSG_SUB_PROTOCOL_SCSI_CMD: | ||
253 | case BSG_SUB_PROTOCOL_SCSI_TRANSPORT: | ||
254 | break; | ||
255 | default: | ||
256 | ret = -EINVAL; | ||
257 | } | ||
258 | break; | ||
259 | default: | ||
260 | ret = -EINVAL; | ||
261 | } | ||
246 | 262 | ||
247 | *rw = hdr->dout_xfer_len ? WRITE : READ; | 263 | *rw = hdr->dout_xfer_len ? WRITE : READ; |
248 | 264 | return ret; | |
249 | return 0; | ||
250 | } | 265 | } |
251 | 266 | ||
252 | /* | 267 | /* |
diff --git a/include/linux/bsg.h b/include/linux/bsg.h index 0dd01f90ba5e..bd998ca6cb2e 100644 --- a/include/linux/bsg.h +++ b/include/linux/bsg.h | |||
@@ -1,6 +1,12 @@ | |||
1 | #ifndef BSG_H | 1 | #ifndef BSG_H |
2 | #define BSG_H | 2 | #define BSG_H |
3 | 3 | ||
4 | #define BSG_PROTOCOL_SCSI 0 | ||
5 | |||
6 | #define BSG_SUB_PROTOCOL_SCSI_CMD 0 | ||
7 | #define BSG_SUB_PROTOCOL_SCSI_TMF 1 | ||
8 | #define BSG_SUB_PROTOCOL_SCSI_TRANSPORT 2 | ||
9 | |||
4 | struct sg_io_v4 { | 10 | struct sg_io_v4 { |
5 | __s32 guard; /* [i] 'Q' to differentiate from v3 */ | 11 | __s32 guard; /* [i] 'Q' to differentiate from v3 */ |
6 | __u32 protocol; /* [i] 0 -> SCSI , .... */ | 12 | __u32 protocol; /* [i] 0 -> SCSI , .... */ |