Blame view

block/cmd-filter.c 5.42 KB
0b07de85a   Adel Gadllah   allow userspace t...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
  /*
   * Copyright 2004 Peter M. Jones <pjones@redhat.com>
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License version 2 as
   * published by the Free Software Foundation.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   *
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public Licens
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-
   *
   */
  
  #include <linux/list.h>
  #include <linux/genhd.h>
  #include <linux/spinlock.h>
0b07de85a   Adel Gadllah   allow userspace t...
23
24
25
26
27
  #include <linux/capability.h>
  #include <linux/bitops.h>
  
  #include <scsi/scsi.h>
  #include <linux/cdrom.h>
4beab5c62   FUJITA Tomonori   block: rename blk...
28
  int blk_verify_command(struct blk_cmd_filter *filter,
aeb5d7270   Al Viro   [PATCH] introduce...
29
  		       unsigned char *cmd, fmode_t has_write_perm)
0b07de85a   Adel Gadllah   allow userspace t...
30
31
32
33
34
35
36
37
38
39
40
41
42
43
  {
  	/* root can do any command. */
  	if (capable(CAP_SYS_RAWIO))
  		return 0;
  
  	/* if there's no filter set, assume we're filtering everything out */
  	if (!filter)
  		return -EPERM;
  
  	/* Anybody who can open the device can do a read-safe command */
  	if (test_bit(cmd[0], filter->read_ok))
  		return 0;
  
  	/* Write-safe commands require a writable open */
abf543937   FUJITA Tomonori   block: move cmdfi...
44
  	if (test_bit(cmd[0], filter->write_ok) && has_write_perm)
0b07de85a   Adel Gadllah   allow userspace t...
45
46
47
48
  		return 0;
  
  	return -EPERM;
  }
0b07de85a   Adel Gadllah   allow userspace t...
49
  EXPORT_SYMBOL(blk_verify_command);
2dc75d3c3   Jens Axboe   block: disable sy...
50
  #if 0
0b07de85a   Adel Gadllah   allow userspace t...
51
  /* and now, the sysfs stuff */
4beab5c62   FUJITA Tomonori   block: rename blk...
52
  static ssize_t rcf_cmds_show(struct blk_cmd_filter *filter, char *page,
0b07de85a   Adel Gadllah   allow userspace t...
53
54
55
56
57
58
59
60
61
62
63
64
65
  			     int rw)
  {
  	char *npage = page;
  	unsigned long *okbits;
  	int i;
  
  	if (rw == READ)
  		okbits = filter->read_ok;
  	else
  		okbits = filter->write_ok;
  
  	for (i = 0; i < BLK_SCSI_MAX_CMDS; i++) {
  		if (test_bit(i, okbits)) {
a4a778971   Adel Gadllah   block: clean up c...
66
  			npage += sprintf(npage, "0x%02x", i);
0b07de85a   Adel Gadllah   allow userspace t...
67
68
69
70
71
72
73
74
75
76
77
  			if (i < BLK_SCSI_MAX_CMDS - 1)
  				sprintf(npage++, " ");
  		}
  	}
  
  	if (npage != page)
  		npage += sprintf(npage, "
  ");
  
  	return npage - page;
  }
4beab5c62   FUJITA Tomonori   block: rename blk...
78
  static ssize_t rcf_readcmds_show(struct blk_cmd_filter *filter, char *page)
0b07de85a   Adel Gadllah   allow userspace t...
79
80
81
  {
  	return rcf_cmds_show(filter, page, READ);
  }
4beab5c62   FUJITA Tomonori   block: rename blk...
82
  static ssize_t rcf_writecmds_show(struct blk_cmd_filter *filter,
0b07de85a   Adel Gadllah   allow userspace t...
83
84
85
86
  				 char *page)
  {
  	return rcf_cmds_show(filter, page, WRITE);
  }
4beab5c62   FUJITA Tomonori   block: rename blk...
87
  static ssize_t rcf_cmds_store(struct blk_cmd_filter *filter,
0b07de85a   Adel Gadllah   allow userspace t...
88
89
  			      const char *page, size_t count, int rw)
  {
0b07de85a   Adel Gadllah   allow userspace t...
90
  	unsigned long okbits[BLK_SCSI_CMD_PER_LONG], *target_okbits;
a4a778971   Adel Gadllah   block: clean up c...
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
  	int cmd, set;
  	char *p, *status;
  
  	if (rw == READ) {
  		memcpy(&okbits, filter->read_ok, sizeof(okbits));
  		target_okbits = filter->read_ok;
  	} else {
  		memcpy(&okbits, filter->write_ok, sizeof(okbits));
  		target_okbits = filter->write_ok;
  	}
  
  	while ((p = strsep((char **)&page, " ")) != NULL) {
  		set = 1;
  
  		if (p[0] == '+') {
  			p++;
  		} else if (p[0] == '-') {
  			set = 0;
  			p++;
  		}
  
  		cmd = simple_strtol(p, &status, 16);
0b07de85a   Adel Gadllah   allow userspace t...
113
  		/* either of these cases means invalid input, so do nothing. */
a4a778971   Adel Gadllah   block: clean up c...
114
  		if ((status == p) || cmd >= BLK_SCSI_MAX_CMDS)
0b07de85a   Adel Gadllah   allow userspace t...
115
  			return -EINVAL;
a4a778971   Adel Gadllah   block: clean up c...
116
117
118
119
  		if (set)
  			__set_bit(cmd, okbits);
  		else
  			__clear_bit(cmd, okbits);
0b07de85a   Adel Gadllah   allow userspace t...
120
  	}
a4a778971   Adel Gadllah   block: clean up c...
121
  	memcpy(target_okbits, okbits, sizeof(okbits));
0b07de85a   Adel Gadllah   allow userspace t...
122
123
  	return count;
  }
4beab5c62   FUJITA Tomonori   block: rename blk...
124
  static ssize_t rcf_readcmds_store(struct blk_cmd_filter *filter,
0b07de85a   Adel Gadllah   allow userspace t...
125
126
127
128
  				  const char *page, size_t count)
  {
  	return rcf_cmds_store(filter, page, count, READ);
  }
4beab5c62   FUJITA Tomonori   block: rename blk...
129
  static ssize_t rcf_writecmds_store(struct blk_cmd_filter *filter,
0b07de85a   Adel Gadllah   allow userspace t...
130
131
132
133
134
135
136
  				   const char *page, size_t count)
  {
  	return rcf_cmds_store(filter, page, count, WRITE);
  }
  
  struct rcf_sysfs_entry {
  	struct attribute attr;
4beab5c62   FUJITA Tomonori   block: rename blk...
137
138
  	ssize_t (*show)(struct blk_cmd_filter *, char *);
  	ssize_t (*store)(struct blk_cmd_filter *, const char *, size_t);
0b07de85a   Adel Gadllah   allow userspace t...
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
  };
  
  static struct rcf_sysfs_entry rcf_readcmds_entry = {
  	.attr = { .name = "read_table", .mode = S_IRUGO | S_IWUSR },
  	.show = rcf_readcmds_show,
  	.store = rcf_readcmds_store,
  };
  
  static struct rcf_sysfs_entry rcf_writecmds_entry = {
  	.attr = {.name = "write_table", .mode = S_IRUGO | S_IWUSR },
  	.show = rcf_writecmds_show,
  	.store = rcf_writecmds_store,
  };
  
  static struct attribute *default_attrs[] = {
  	&rcf_readcmds_entry.attr,
  	&rcf_writecmds_entry.attr,
  	NULL,
  };
  
  #define to_rcf(atr) container_of((atr), struct rcf_sysfs_entry, attr)
  
  static ssize_t
  rcf_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
  {
  	struct rcf_sysfs_entry *entry = to_rcf(attr);
4beab5c62   FUJITA Tomonori   block: rename blk...
165
  	struct blk_cmd_filter *filter;
0b07de85a   Adel Gadllah   allow userspace t...
166

4beab5c62   FUJITA Tomonori   block: rename blk...
167
  	filter = container_of(kobj, struct blk_cmd_filter, kobj);
0b07de85a   Adel Gadllah   allow userspace t...
168
169
170
171
172
173
174
175
176
177
178
  	if (entry->show)
  		return entry->show(filter, page);
  
  	return 0;
  }
  
  static ssize_t
  rcf_attr_store(struct kobject *kobj, struct attribute *attr,
  			const char *page, size_t length)
  {
  	struct rcf_sysfs_entry *entry = to_rcf(attr);
4beab5c62   FUJITA Tomonori   block: rename blk...
179
  	struct blk_cmd_filter *filter;
0b07de85a   Adel Gadllah   allow userspace t...
180
181
182
183
184
185
  
  	if (!capable(CAP_SYS_RAWIO))
  		return -EPERM;
  
  	if (!entry->store)
  		return -EINVAL;
4beab5c62   FUJITA Tomonori   block: rename blk...
186
  	filter = container_of(kobj, struct blk_cmd_filter, kobj);
0b07de85a   Adel Gadllah   allow userspace t...
187
188
189
190
191
192
193
194
195
196
197
198
  	return entry->store(filter, page, length);
  }
  
  static struct sysfs_ops rcf_sysfs_ops = {
  	.show = rcf_attr_show,
  	.store = rcf_attr_store,
  };
  
  static struct kobj_type rcf_ktype = {
  	.sysfs_ops = &rcf_sysfs_ops,
  	.default_attrs = default_attrs,
  };
0b07de85a   Adel Gadllah   allow userspace t...
199
200
201
  int blk_register_filter(struct gendisk *disk)
  {
  	int ret;
4beab5c62   FUJITA Tomonori   block: rename blk...
202
  	struct blk_cmd_filter *filter = &disk->queue->cmd_filter;
0b07de85a   Adel Gadllah   allow userspace t...
203

4c46501d1   Tejun Heo   block: move holde...
204
205
  	ret = kobject_init_and_add(&filter->kobj, &rcf_ktype,
  				   &disk_to_dev(disk)->kobj,
abf543937   FUJITA Tomonori   block: move cmdfi...
206
  				   "%s", "cmd_filter");
0b07de85a   Adel Gadllah   allow userspace t...
207
208
  	if (ret < 0)
  		return ret;
0b07de85a   Adel Gadllah   allow userspace t...
209
210
  	return 0;
  }
bb23b431d   FUJITA Tomonori   remove blk_regist...
211
  EXPORT_SYMBOL(blk_register_filter);
0b07de85a   Adel Gadllah   allow userspace t...
212
213
214
  
  void blk_unregister_filter(struct gendisk *disk)
  {
4beab5c62   FUJITA Tomonori   block: rename blk...
215
  	struct blk_cmd_filter *filter = &disk->queue->cmd_filter;
0b07de85a   Adel Gadllah   allow userspace t...
216
217
  
  	kobject_put(&filter->kobj);
0b07de85a   Adel Gadllah   allow userspace t...
218
  }
bb23b431d   FUJITA Tomonori   remove blk_regist...
219
  EXPORT_SYMBOL(blk_unregister_filter);
2dc75d3c3   Jens Axboe   block: disable sy...
220
  #endif