From: Matthew Dharm <mdharm-scsi@one-eyed-alien.net>
To: James Bottomley <James.Bottomley@SteelEye.com>
Cc: Linus Torvalds <torvalds@transmeta.com>,
USB Developers <linux-usb-devel@lists.sourceforge.net>,
USB Storage List <usb-storage@one-eyed-alien.net>,
Linux SCSI list <linux-scsi@vger.kernel.org>,
Greg KH <greg@kroah.com>
Subject: Re: PATCH: exclude certain commands from emulated SCSI hosts
Date: Sun, 20 Apr 2003 14:33:51 -0700 [thread overview]
Message-ID: <20030420143351.C20891@one-eyed-alien.net> (raw)
In-Reply-To: <1049556643.1762.16.camel@mulgrave>; from James.Bottomley@SteelEye.com on Sat, Apr 05, 2003 at 09:30:41AM -0600
[-- Attachment #1: Type: text/plain, Size: 6604 bytes --]
How about this patch? It is based on James' work, but I cleaned up the
comments a bit and eliminated a structure which was used to only hold two
elements. I also added a filter type and fixed the symbol problems when
modules were used.
I've tested this, and it works well. Linus, if you'll take this I've got
several more patches -- ones to make usb-storage use this to cut some
undesireable commands, and one to fix up the INQUIRY probing in scsi_scan.c
to be compatible with the filter code.
Linus, please apply this to 2.5.
Matt
# This is a BitKeeper generated patch for the following project:
# Project Name: greg k-h's linux 2.5 USB kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
# ChangeSet 1.670 -> 1.671
# drivers/scsi/scsi_syms.c 1.20 -> 1.21
# drivers/scsi/scsi.h 1.31 -> 1.32
# drivers/scsi/scsi_lib.c 1.34 -> 1.35
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 03/04/19 mdharm@zen.san.one-eyed-alien.net 1.671
# Added SCSI command filter.
# --------------------------------------------
#
diff -Nru a/drivers/scsi/scsi.h b/drivers/scsi/scsi.h
--- a/drivers/scsi/scsi.h Sat Apr 19 17:16:59 2003
+++ b/drivers/scsi/scsi.h Sat Apr 19 17:16:59 2003
@@ -960,4 +960,52 @@
extern int scsi_sysfs_register(void);
extern void scsi_sysfs_unregister(void);
+/* SCSI command filter
+ *
+ * The 'command' array contains either (a) a SCSI command byte, or
+ * (b) an 'exception' rule. These are distinguished by the high-byte;
+ * SCSI commands have 0 there, exceptions have some other value.
+ *
+ * Thus, *command < 0x100 is a SCSI command, >= 0x100 is an
+ * exception. Exception codes are defined below.
+ *
+ * The format of the exceptions is:
+ *
+ * Bit 15: invert the specific condition
+ * Bit 14-12: Reserved
+ * Bit 11-8: command opcode (must be > 0)
+ * Bit 7-0: Command specific
+ */
+
+/* set filter type to whitelist or blacklist filtering */
+enum scsi_cmd_filter_type {
+ SCSI_FILTER_WHITELIST, SCSI_FILTER_BLACKLIST
+};
+
+extern int scsi_filter_cmd(struct scsi_cmnd *,
+ enum scsi_cmd_filter_type, unsigned short* );
+
+/* exception definitions for the filter */
+#define SCSI_FILTER_INVERT 0x8000
+
+/* opcodes for the filter */
+#define SCSI_FILTER_INQUIRY_LEN 0x0100
+#define SCSI_FILTER_INQUIRY_EVPD 0x0200
+
+/* marker for end of filter list */
+#define SCSI_FILTER_LIST_END 0xFFFF
+
+/* useful filter commands */
+#define SCSI_FILTER_INQUIRY_36 (SCSI_FILTER_INQUIRY_LEN | 36)
+#define SCSI_FILTER_INQUIRY_NOT36 (SCSI_FILTER_INVERT | SCSI_FILTER_INQUIRY_36)
+#define SCSI_FILTER_INQUIRY_NOT_EVPD (SCSI_FILTER_INVERT | SCSI_FILTER_INQUIRY_EVPD)
+
+static inline unsigned short scsi_filter_opcode(unsigned short command) {
+ return command & 0x7f00;
+}
+
+static inline unsigned char scsi_filter_data(unsigned short command) {
+ return (unsigned char)(command & 0x00ff);
+}
+
#endif /* _SCSI_H */
diff -Nru a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
--- a/drivers/scsi/scsi_lib.c Sat Apr 19 17:16:59 2003
+++ b/drivers/scsi/scsi_lib.c Sat Apr 19 17:16:59 2003
@@ -1368,3 +1368,89 @@
kmem_cache_destroy(sgp->slab);
}
}
+
+static inline int scsi_filter_exceptions(struct scsi_cmnd *cmd,
+ unsigned short command)
+{
+ int found = 0;
+
+ /* specials begin at 0x100 */
+ if(command < 0x100)
+ return 0;
+
+ /* we check for inversion in each switch so that we can define each
+ * test to act only on a specific subset of commands
+ */
+ switch(scsi_filter_opcode(command)) {
+ case SCSI_FILTER_INQUIRY_EVPD:
+ if(cmd->cmnd[0] == INQUIRY) {
+ /* is EVPD bit set? */
+ found = (cmd->cmnd[1] & 0x1);
+
+ /* now check for inversion */
+ if(command & SCSI_FILTER_INVERT)
+ found = !found;
+ }
+ break;
+ case SCSI_FILTER_INQUIRY_LEN:
+ if(cmd->cmnd[0] == INQUIRY) {
+ /* does the transfer length match the data */
+ found = (cmd->cmnd[4] == scsi_filter_data(command));
+
+ /* now check for inversion */
+ if(command & SCSI_FILTER_INVERT)
+ found = !found;
+ }
+ break;
+ default:
+ /* unrecognized filter */
+ break;
+ }
+
+ return found;
+}
+
+/**
+ * scsi_filter_cmd - Filter a given command against a list
+ * @cmd: command to be filtered.
+ * @filter: pointer to the filter containing the type (black/white list) and
+ * zero terminated list of commands to filter against (first byte only). See
+ * scsi.h for details on the filter structure.
+ *
+ * Returns 0 if the filter passed successfully and the driver can continue
+ * processing the command or 1 if the filter failed and the command should
+ * be finished (via ->scsi_done). In the latter case, the command will have
+ * the sense fields filled in indicating the correct sense for an illegal
+ * request.
+ **/
+int scsi_filter_cmd(struct scsi_cmnd *cmd, enum scsi_cmd_filter_type type,
+ unsigned short* command)
+{
+ int found = 0;
+
+ /* search command list for a match */
+ for( ; *command != SCSI_FILTER_LIST_END; command++) {
+ found = scsi_filter_exceptions(cmd, *command);
+ found += (cmd->cmnd[0] == *command);
+ if(found)
+ break;
+ }
+
+ /* pass behavior -- found on a whitelist or not found on a blacklist */
+ if((found && type == SCSI_FILTER_WHITELIST) ||
+ (!found && type == SCSI_FILTER_BLACKLIST))
+ return 0;
+
+ /* fill in the Check Condition/Illegal request */
+ cmd->result = SAM_STAT_CHECK_CONDITION;
+ memset(cmd->sense_buffer, '\0', sizeof(cmd->sense_buffer));
+ cmd->sense_buffer[0] = 0xF0; /* valid, response code 0x70 */
+ cmd->sense_buffer[2] = ILLEGAL_REQUEST;
+
+ /* ASC 0x20, ASCQ 0x00: Invalid command operation code */
+ cmd->sense_buffer[12] = 0x20;
+ cmd->sense_buffer[13] = 0x00;
+
+ return 1;
+}
+
diff -Nru a/drivers/scsi/scsi_syms.c b/drivers/scsi/scsi_syms.c
--- a/drivers/scsi/scsi_syms.c Sat Apr 19 17:16:59 2003
+++ b/drivers/scsi/scsi_syms.c Sat Apr 19 17:16:59 2003
@@ -55,6 +55,7 @@
#if defined(CONFIG_SCSI_LOGGING) /* { */
EXPORT_SYMBOL(scsi_logging_level);
#endif
+EXPORT_SYMBOL(scsi_filter_cmd);
EXPORT_SYMBOL(scsi_allocate_request);
EXPORT_SYMBOL(scsi_release_request);
--
Matthew Dharm Home: mdharm-usb@one-eyed-alien.net
Maintainer, Linux USB Mass Storage Driver
Would you mind not using our Web server? We're trying to have a game of
Quake here.
-- Greg
User Friendly, 5/11/1998
[-- Attachment #2: Type: application/pgp-signature, Size: 232 bytes --]
next prev parent reply other threads:[~2003-04-20 21:22 UTC|newest]
Thread overview: 45+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20030322193046.A17056@one-eyed-alien.net>
[not found] ` <20030322193149.B17056@one-eyed-alien.net>
2003-03-23 3:37 ` PATCH: exclude certain commands from emulated SCSI hosts Matthew Dharm
2003-03-23 4:09 ` Linus Torvalds
2003-03-23 7:31 ` Matthew Dharm
2003-03-23 7:39 ` Linus Torvalds
2003-03-23 18:13 ` [usb-storage] " Matthew Dharm
2003-03-24 1:05 ` Douglas Gilbert
2003-03-24 1:26 ` James Bottomley
2003-03-24 1:37 ` Matthew Dharm
2003-03-24 1:39 ` James Bottomley
2003-03-24 7:04 ` Matthew Dharm
2003-03-24 15:15 ` James Bottomley
2003-03-24 16:29 ` Linus Torvalds
2003-03-24 16:43 ` James Bottomley
2003-03-24 16:52 ` Jens Axboe
2003-03-24 16:56 ` James Bottomley
2003-03-24 17:30 ` Matthew Dharm
2003-04-05 15:30 ` James Bottomley
2003-04-05 19:27 ` Matthew Dharm
2003-04-05 19:45 ` James Bottomley
2003-04-05 19:55 ` Matthew Dharm
2003-04-05 20:08 ` James Bottomley
2003-04-06 0:20 ` Matthew Dharm
2003-04-06 0:22 ` Matthew Dharm
2003-04-06 15:39 ` James Bottomley
2003-04-07 22:33 ` Patrick Mansfield
2003-04-07 23:14 ` James Bottomley
2003-04-08 0:51 ` Patrick Mansfield
2003-04-20 21:33 ` Matthew Dharm [this message]
2003-04-20 21:35 ` Matthew Dharm
2003-04-21 16:20 ` James Bottomley
2003-04-21 17:02 ` Matthew Dharm
2003-04-21 16:28 ` James Bottomley
2003-04-21 17:01 ` Matthew Dharm
2003-04-21 19:23 ` James Bottomley
2003-04-21 19:35 ` Matthew Dharm
2003-04-21 21:27 ` James Bottomley
2003-04-21 23:37 ` Matthew Dharm
2003-04-21 21:28 ` Patrick Mansfield
2003-04-21 23:45 ` Matthew Dharm
2003-03-24 1:58 ` Linus Torvalds
2003-03-24 6:58 ` Matthew Dharm
2003-04-22 17:37 [usb-storage] " James Bottomley
2003-04-22 18:13 ` Alan Stern
-- strict thread matches above, loose matches on Subject: below --
2003-04-22 19:30 Andries.Brouwer
2003-04-22 19:41 ` James Bottomley
2003-04-22 19:50 Andries.Brouwer
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=20030420143351.C20891@one-eyed-alien.net \
--to=mdharm-scsi@one-eyed-alien.net \
--cc=James.Bottomley@SteelEye.com \
--cc=greg@kroah.com \
--cc=linux-scsi@vger.kernel.org \
--cc=linux-usb-devel@lists.sourceforge.net \
--cc=torvalds@transmeta.com \
--cc=usb-storage@one-eyed-alien.net \
/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