Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at 2bac406df52100aec42e230a2cc2986d34e86218 334 lines 9.6 kB view raw
1/* 2 * Copyright 2004 Peter M. Jones <pjones@redhat.com> 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License version 2 as 6 * published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public Licens 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111- 17 * 18 */ 19 20#include <linux/list.h> 21#include <linux/genhd.h> 22#include <linux/spinlock.h> 23#include <linux/parser.h> 24#include <linux/capability.h> 25#include <linux/bitops.h> 26 27#include <scsi/scsi.h> 28#include <linux/cdrom.h> 29 30int blk_cmd_filter_verify_command(struct blk_scsi_cmd_filter *filter, 31 unsigned char *cmd, mode_t *f_mode) 32{ 33 /* root can do any command. */ 34 if (capable(CAP_SYS_RAWIO)) 35 return 0; 36 37 /* if there's no filter set, assume we're filtering everything out */ 38 if (!filter) 39 return -EPERM; 40 41 /* Anybody who can open the device can do a read-safe command */ 42 if (test_bit(cmd[0], filter->read_ok)) 43 return 0; 44 45 /* Write-safe commands require a writable open */ 46 if (test_bit(cmd[0], filter->write_ok) && (*f_mode & FMODE_WRITE)) 47 return 0; 48 49 return -EPERM; 50} 51EXPORT_SYMBOL(blk_cmd_filter_verify_command); 52 53int blk_verify_command(struct file *file, unsigned char *cmd) 54{ 55 struct gendisk *disk; 56 struct inode *inode; 57 58 if (!file) 59 return -EINVAL; 60 61 inode = file->f_dentry->d_inode; 62 if (!inode) 63 return -EINVAL; 64 65 disk = inode->i_bdev->bd_disk; 66 67 return blk_cmd_filter_verify_command(&disk->cmd_filter, 68 cmd, &file->f_mode); 69} 70EXPORT_SYMBOL(blk_verify_command); 71 72/* and now, the sysfs stuff */ 73static ssize_t rcf_cmds_show(struct blk_scsi_cmd_filter *filter, char *page, 74 int rw) 75{ 76 char *npage = page; 77 unsigned long *okbits; 78 int i; 79 80 if (rw == READ) 81 okbits = filter->read_ok; 82 else 83 okbits = filter->write_ok; 84 85 for (i = 0; i < BLK_SCSI_MAX_CMDS; i++) { 86 if (test_bit(i, okbits)) { 87 sprintf(npage, "%02x", i); 88 npage += 2; 89 if (i < BLK_SCSI_MAX_CMDS - 1) 90 sprintf(npage++, " "); 91 } 92 } 93 94 if (npage != page) 95 npage += sprintf(npage, "\n"); 96 97 return npage - page; 98} 99 100static ssize_t rcf_readcmds_show(struct blk_scsi_cmd_filter *filter, char *page) 101{ 102 return rcf_cmds_show(filter, page, READ); 103} 104 105static ssize_t rcf_writecmds_show(struct blk_scsi_cmd_filter *filter, 106 char *page) 107{ 108 return rcf_cmds_show(filter, page, WRITE); 109} 110 111static ssize_t rcf_cmds_store(struct blk_scsi_cmd_filter *filter, 112 const char *page, size_t count, int rw) 113{ 114 ssize_t ret = 0; 115 unsigned long okbits[BLK_SCSI_CMD_PER_LONG], *target_okbits; 116 int cmd, status, len; 117 substring_t ss; 118 119 memset(&okbits, 0, sizeof(okbits)); 120 121 for (len = strlen(page); len > 0; len -= 3) { 122 if (len < 2) 123 break; 124 ss.from = (char *) page + ret; 125 ss.to = (char *) page + ret + 2; 126 ret += 3; 127 status = match_hex(&ss, &cmd); 128 /* either of these cases means invalid input, so do nothing. */ 129 if (status || cmd >= BLK_SCSI_MAX_CMDS) 130 return -EINVAL; 131 132 __set_bit(cmd, okbits); 133 } 134 135 if (rw == READ) 136 target_okbits = filter->read_ok; 137 else 138 target_okbits = filter->write_ok; 139 140 memmove(target_okbits, okbits, sizeof(okbits)); 141 return count; 142} 143 144static ssize_t rcf_readcmds_store(struct blk_scsi_cmd_filter *filter, 145 const char *page, size_t count) 146{ 147 return rcf_cmds_store(filter, page, count, READ); 148} 149 150static ssize_t rcf_writecmds_store(struct blk_scsi_cmd_filter *filter, 151 const char *page, size_t count) 152{ 153 return rcf_cmds_store(filter, page, count, WRITE); 154} 155 156struct rcf_sysfs_entry { 157 struct attribute attr; 158 ssize_t (*show)(struct blk_scsi_cmd_filter *, char *); 159 ssize_t (*store)(struct blk_scsi_cmd_filter *, const char *, size_t); 160}; 161 162static struct rcf_sysfs_entry rcf_readcmds_entry = { 163 .attr = { .name = "read_table", .mode = S_IRUGO | S_IWUSR }, 164 .show = rcf_readcmds_show, 165 .store = rcf_readcmds_store, 166}; 167 168static struct rcf_sysfs_entry rcf_writecmds_entry = { 169 .attr = {.name = "write_table", .mode = S_IRUGO | S_IWUSR }, 170 .show = rcf_writecmds_show, 171 .store = rcf_writecmds_store, 172}; 173 174static struct attribute *default_attrs[] = { 175 &rcf_readcmds_entry.attr, 176 &rcf_writecmds_entry.attr, 177 NULL, 178}; 179 180#define to_rcf(atr) container_of((atr), struct rcf_sysfs_entry, attr) 181 182static ssize_t 183rcf_attr_show(struct kobject *kobj, struct attribute *attr, char *page) 184{ 185 struct rcf_sysfs_entry *entry = to_rcf(attr); 186 struct blk_scsi_cmd_filter *filter; 187 188 filter = container_of(kobj, struct blk_scsi_cmd_filter, kobj); 189 if (entry->show) 190 return entry->show(filter, page); 191 192 return 0; 193} 194 195static ssize_t 196rcf_attr_store(struct kobject *kobj, struct attribute *attr, 197 const char *page, size_t length) 198{ 199 struct rcf_sysfs_entry *entry = to_rcf(attr); 200 struct blk_scsi_cmd_filter *filter; 201 202 if (!capable(CAP_SYS_RAWIO)) 203 return -EPERM; 204 205 if (!entry->store) 206 return -EINVAL; 207 208 filter = container_of(kobj, struct blk_scsi_cmd_filter, kobj); 209 return entry->store(filter, page, length); 210} 211 212static struct sysfs_ops rcf_sysfs_ops = { 213 .show = rcf_attr_show, 214 .store = rcf_attr_store, 215}; 216 217static struct kobj_type rcf_ktype = { 218 .sysfs_ops = &rcf_sysfs_ops, 219 .default_attrs = default_attrs, 220}; 221 222#ifndef MAINTENANCE_IN_CMD 223#define MAINTENANCE_IN_CMD 0xa3 224#endif 225 226static void rcf_set_defaults(struct blk_scsi_cmd_filter *filter) 227{ 228 /* Basic read-only commands */ 229 __set_bit(TEST_UNIT_READY, filter->read_ok); 230 __set_bit(REQUEST_SENSE, filter->read_ok); 231 __set_bit(READ_6, filter->read_ok); 232 __set_bit(READ_10, filter->read_ok); 233 __set_bit(READ_12, filter->read_ok); 234 __set_bit(READ_16, filter->read_ok); 235 __set_bit(READ_BUFFER, filter->read_ok); 236 __set_bit(READ_DEFECT_DATA, filter->read_ok); 237 __set_bit(READ_CAPACITY, filter->read_ok); 238 __set_bit(READ_LONG, filter->read_ok); 239 __set_bit(INQUIRY, filter->read_ok); 240 __set_bit(MODE_SENSE, filter->read_ok); 241 __set_bit(MODE_SENSE_10, filter->read_ok); 242 __set_bit(LOG_SENSE, filter->read_ok); 243 __set_bit(START_STOP, filter->read_ok); 244 __set_bit(GPCMD_VERIFY_10, filter->read_ok); 245 __set_bit(VERIFY_16, filter->read_ok); 246 __set_bit(REPORT_LUNS, filter->read_ok); 247 __set_bit(SERVICE_ACTION_IN, filter->read_ok); 248 __set_bit(RECEIVE_DIAGNOSTIC, filter->read_ok); 249 __set_bit(MAINTENANCE_IN_CMD, filter->read_ok); 250 __set_bit(GPCMD_READ_BUFFER_CAPACITY, filter->read_ok); 251 252 /* Audio CD commands */ 253 __set_bit(GPCMD_PLAY_CD, filter->read_ok); 254 __set_bit(GPCMD_PLAY_AUDIO_10, filter->read_ok); 255 __set_bit(GPCMD_PLAY_AUDIO_MSF, filter->read_ok); 256 __set_bit(GPCMD_PLAY_AUDIO_TI, filter->read_ok); 257 __set_bit(GPCMD_PAUSE_RESUME, filter->read_ok); 258 259 /* CD/DVD data reading */ 260 __set_bit(GPCMD_READ_CD, filter->read_ok); 261 __set_bit(GPCMD_READ_CD_MSF, filter->read_ok); 262 __set_bit(GPCMD_READ_DISC_INFO, filter->read_ok); 263 __set_bit(GPCMD_READ_CDVD_CAPACITY, filter->read_ok); 264 __set_bit(GPCMD_READ_DVD_STRUCTURE, filter->read_ok); 265 __set_bit(GPCMD_READ_HEADER, filter->read_ok); 266 __set_bit(GPCMD_READ_TRACK_RZONE_INFO, filter->read_ok); 267 __set_bit(GPCMD_READ_SUBCHANNEL, filter->read_ok); 268 __set_bit(GPCMD_READ_TOC_PMA_ATIP, filter->read_ok); 269 __set_bit(GPCMD_REPORT_KEY, filter->read_ok); 270 __set_bit(GPCMD_SCAN, filter->read_ok); 271 __set_bit(GPCMD_GET_CONFIGURATION, filter->read_ok); 272 __set_bit(GPCMD_READ_FORMAT_CAPACITIES, filter->read_ok); 273 __set_bit(GPCMD_GET_EVENT_STATUS_NOTIFICATION, filter->read_ok); 274 __set_bit(GPCMD_GET_PERFORMANCE, filter->read_ok); 275 __set_bit(GPCMD_SEEK, filter->read_ok); 276 __set_bit(GPCMD_STOP_PLAY_SCAN, filter->read_ok); 277 278 /* Basic writing commands */ 279 __set_bit(WRITE_6, filter->write_ok); 280 __set_bit(WRITE_10, filter->write_ok); 281 __set_bit(WRITE_VERIFY, filter->write_ok); 282 __set_bit(WRITE_12, filter->write_ok); 283 __set_bit(WRITE_VERIFY_12, filter->write_ok); 284 __set_bit(WRITE_16, filter->write_ok); 285 __set_bit(WRITE_LONG, filter->write_ok); 286 __set_bit(WRITE_LONG_2, filter->write_ok); 287 __set_bit(ERASE, filter->write_ok); 288 __set_bit(GPCMD_MODE_SELECT_10, filter->write_ok); 289 __set_bit(MODE_SELECT, filter->write_ok); 290 __set_bit(LOG_SELECT, filter->write_ok); 291 __set_bit(GPCMD_BLANK, filter->write_ok); 292 __set_bit(GPCMD_CLOSE_TRACK, filter->write_ok); 293 __set_bit(GPCMD_FLUSH_CACHE, filter->write_ok); 294 __set_bit(GPCMD_FORMAT_UNIT, filter->write_ok); 295 __set_bit(GPCMD_REPAIR_RZONE_TRACK, filter->write_ok); 296 __set_bit(GPCMD_RESERVE_RZONE_TRACK, filter->write_ok); 297 __set_bit(GPCMD_SEND_DVD_STRUCTURE, filter->write_ok); 298 __set_bit(GPCMD_SEND_EVENT, filter->write_ok); 299 __set_bit(GPCMD_SEND_KEY, filter->write_ok); 300 __set_bit(GPCMD_SEND_OPC, filter->write_ok); 301 __set_bit(GPCMD_SEND_CUE_SHEET, filter->write_ok); 302 __set_bit(GPCMD_SET_SPEED, filter->write_ok); 303 __set_bit(GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL, filter->write_ok); 304 __set_bit(GPCMD_LOAD_UNLOAD, filter->write_ok); 305 __set_bit(GPCMD_SET_STREAMING, filter->write_ok); 306} 307 308int blk_register_filter(struct gendisk *disk) 309{ 310 int ret; 311 struct blk_scsi_cmd_filter *filter = &disk->cmd_filter; 312 struct kobject *parent = kobject_get(disk->holder_dir->parent); 313 314 if (!parent) 315 return -ENODEV; 316 317 ret = kobject_init_and_add(&filter->kobj, &rcf_ktype, parent, 318 "%s", "cmd_filter"); 319 320 if (ret < 0) 321 return ret; 322 323 rcf_set_defaults(filter); 324 return 0; 325} 326 327void blk_unregister_filter(struct gendisk *disk) 328{ 329 struct blk_scsi_cmd_filter *filter = &disk->cmd_filter; 330 331 kobject_put(&filter->kobj); 332 kobject_put(disk->holder_dir->parent); 333} 334