aboutsummaryrefslogtreecommitdiffstats
path: root/fs/afs/super.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2007-04-26 18:57:07 -0400
committerDavid S. Miller <davem@davemloft.net>2007-04-26 18:57:07 -0400
commit00d3b7a4533e367b0dc2812a706db8f9f071c27f (patch)
treef0b1ae0266267cb2c54cb11aa61ad0758ce9c0f5 /fs/afs/super.c
parent436058a49e0fb91c74454dbee9cfee6fb53b4336 (diff)
[AFS]: Add security support.
Add security support to the AFS filesystem. Kerberos IV tickets are added as RxRPC keys are added to the session keyring with the klog program. open() and other VFS operations then find this ticket with request_key() and either use it immediately (eg: mkdir, unlink) or attach it to a file descriptor (open). Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'fs/afs/super.c')
-rw-r--r--fs/afs/super.c142
1 files changed, 120 insertions, 22 deletions
diff --git a/fs/afs/super.c b/fs/afs/super.c
index 77e68759788..497350a5463 100644
--- a/fs/afs/super.c
+++ b/fs/afs/super.c
@@ -24,12 +24,6 @@
24 24
25#define AFS_FS_MAGIC 0x6B414653 /* 'kAFS' */ 25#define AFS_FS_MAGIC 0x6B414653 /* 'kAFS' */
26 26
27struct afs_mount_params {
28 int rwpath;
29 struct afs_cell *default_cell;
30 struct afs_volume *volume;
31};
32
33static void afs_i_init_once(void *foo, struct kmem_cache *cachep, 27static void afs_i_init_once(void *foo, struct kmem_cache *cachep,
34 unsigned long flags); 28 unsigned long flags);
35 29
@@ -150,8 +144,8 @@ static int want_no_value(char *const *_value, const char *option)
150 * - this function has been shamelessly adapted from the ext3 fs which 144 * - this function has been shamelessly adapted from the ext3 fs which
151 * shamelessly adapted it from the msdos fs 145 * shamelessly adapted it from the msdos fs
152 */ 146 */
153static int afs_super_parse_options(struct afs_mount_params *params, 147static int afs_parse_options(struct afs_mount_params *params,
154 char *options, const char **devname) 148 char *options, const char **devname)
155{ 149{
156 struct afs_cell *cell; 150 struct afs_cell *cell;
157 char *key, *value; 151 char *key, *value;
@@ -183,8 +177,8 @@ static int afs_super_parse_options(struct afs_mount_params *params,
183 cell = afs_cell_lookup(value, strlen(value)); 177 cell = afs_cell_lookup(value, strlen(value));
184 if (IS_ERR(cell)) 178 if (IS_ERR(cell))
185 return PTR_ERR(cell); 179 return PTR_ERR(cell);
186 afs_put_cell(params->default_cell); 180 afs_put_cell(params->cell);
187 params->default_cell = cell; 181 params->cell = cell;
188 } else { 182 } else {
189 printk("kAFS: Unknown mount option: '%s'\n", key); 183 printk("kAFS: Unknown mount option: '%s'\n", key);
190 ret = -EINVAL; 184 ret = -EINVAL;
@@ -199,6 +193,99 @@ error:
199} 193}
200 194
201/* 195/*
196 * parse a device name to get cell name, volume name, volume type and R/W
197 * selector
198 * - this can be one of the following:
199 * "%[cell:]volume[.]" R/W volume
200 * "#[cell:]volume[.]" R/O or R/W volume (rwpath=0),
201 * or R/W (rwpath=1) volume
202 * "%[cell:]volume.readonly" R/O volume
203 * "#[cell:]volume.readonly" R/O volume
204 * "%[cell:]volume.backup" Backup volume
205 * "#[cell:]volume.backup" Backup volume
206 */
207static int afs_parse_device_name(struct afs_mount_params *params,
208 const char *name)
209{
210 struct afs_cell *cell;
211 const char *cellname, *suffix;
212 int cellnamesz;
213
214 _enter(",%s", name);
215
216 if (!name) {
217 printk(KERN_ERR "kAFS: no volume name specified\n");
218 return -EINVAL;
219 }
220
221 if ((name[0] != '%' && name[0] != '#') || !name[1]) {
222 printk(KERN_ERR "kAFS: unparsable volume name\n");
223 return -EINVAL;
224 }
225
226 /* determine the type of volume we're looking for */
227 params->type = AFSVL_ROVOL;
228 params->force = false;
229 if (params->rwpath || name[0] == '%') {
230 params->type = AFSVL_RWVOL;
231 params->force = true;
232 }
233 name++;
234
235 /* split the cell name out if there is one */
236 params->volname = strchr(name, ':');
237 if (params->volname) {
238 cellname = name;
239 cellnamesz = params->volname - name;
240 params->volname++;
241 } else {
242 params->volname = name;
243 cellname = NULL;
244 cellnamesz = 0;
245 }
246
247 /* the volume type is further affected by a possible suffix */
248 suffix = strrchr(params->volname, '.');
249 if (suffix) {
250 if (strcmp(suffix, ".readonly") == 0) {
251 params->type = AFSVL_ROVOL;
252 params->force = true;
253 } else if (strcmp(suffix, ".backup") == 0) {
254 params->type = AFSVL_BACKVOL;
255 params->force = true;
256 } else if (suffix[1] == 0) {
257 } else {
258 suffix = NULL;
259 }
260 }
261
262 params->volnamesz = suffix ?
263 suffix - params->volname : strlen(params->volname);
264
265 _debug("cell %*.*s [%p]",
266 cellnamesz, cellnamesz, cellname ?: "", params->cell);
267
268 /* lookup the cell record */
269 if (cellname || !params->cell) {
270 cell = afs_cell_lookup(cellname, cellnamesz);
271 if (IS_ERR(cell)) {
272 printk(KERN_ERR "kAFS: unable to lookup cell '%s'\n",
273 cellname ?: "");
274 return PTR_ERR(cell);
275 }
276 afs_put_cell(params->cell);
277 params->cell = cell;
278 }
279
280 _debug("CELL:%s [%p] VOLUME:%*.*s SUFFIX:%s TYPE:%d%s",
281 params->cell->name, params->cell,
282 params->volnamesz, params->volnamesz, params->volname,
283 suffix ?: "-", params->type, params->force ? " FORCE" : "");
284
285 return 0;
286}
287
288/*
202 * check a superblock to see if it's the one we're looking for 289 * check a superblock to see if it's the one we're looking for
203 */ 290 */
204static int afs_test_super(struct super_block *sb, void *data) 291static int afs_test_super(struct super_block *sb, void *data)
@@ -244,7 +331,7 @@ static int afs_fill_super(struct super_block *sb, void *data)
244 fid.vid = as->volume->vid; 331 fid.vid = as->volume->vid;
245 fid.vnode = 1; 332 fid.vnode = 1;
246 fid.unique = 1; 333 fid.unique = 1;
247 inode = afs_iget(sb, &fid); 334 inode = afs_iget(sb, params->key, &fid);
248 if (IS_ERR(inode)) 335 if (IS_ERR(inode))
249 goto error_inode; 336 goto error_inode;
250 337
@@ -285,31 +372,40 @@ static int afs_get_sb(struct file_system_type *fs_type,
285 struct afs_mount_params params; 372 struct afs_mount_params params;
286 struct super_block *sb; 373 struct super_block *sb;
287 struct afs_volume *vol; 374 struct afs_volume *vol;
375 struct key *key;
288 int ret; 376 int ret;
289 377
290 _enter(",,%s,%p", dev_name, options); 378 _enter(",,%s,%p", dev_name, options);
291 379
292 memset(&params, 0, sizeof(params)); 380 memset(&params, 0, sizeof(params));
293 381
294 /* parse the options */ 382 /* parse the options and device name */
295 if (options) { 383 if (options) {
296 ret = afs_super_parse_options(&params, options, &dev_name); 384 ret = afs_parse_options(&params, options, &dev_name);
297 if (ret < 0) 385 if (ret < 0)
298 goto error; 386 goto error;
299 if (!dev_name) {
300 printk("kAFS: no volume name specified\n");
301 ret = -EINVAL;
302 goto error;
303 }
304 } 387 }
305 388
389
390 ret = afs_parse_device_name(&params, dev_name);
391 if (ret < 0)
392 goto error;
393
394 /* try and do the mount securely */
395 key = afs_request_key(params.cell);
396 if (IS_ERR(key)) {
397 _leave(" = %ld [key]", PTR_ERR(key));
398 ret = PTR_ERR(key);
399 goto error;
400 }
401 params.key = key;
402
306 /* parse the device name */ 403 /* parse the device name */
307 vol = afs_volume_lookup(dev_name, params.default_cell, params.rwpath); 404 vol = afs_volume_lookup(&params);
308 if (IS_ERR(vol)) { 405 if (IS_ERR(vol)) {
309 ret = PTR_ERR(vol); 406 ret = PTR_ERR(vol);
310 goto error; 407 goto error;
311 } 408 }
312
313 params.volume = vol; 409 params.volume = vol;
314 410
315 /* allocate a deviceless superblock */ 411 /* allocate a deviceless superblock */
@@ -337,13 +433,14 @@ static int afs_get_sb(struct file_system_type *fs_type,
337 433
338 simple_set_mnt(mnt, sb); 434 simple_set_mnt(mnt, sb);
339 afs_put_volume(params.volume); 435 afs_put_volume(params.volume);
340 afs_put_cell(params.default_cell); 436 afs_put_cell(params.cell);
341 _leave(" = 0 [%p]", sb); 437 _leave(" = 0 [%p]", sb);
342 return 0; 438 return 0;
343 439
344error: 440error:
345 afs_put_volume(params.volume); 441 afs_put_volume(params.volume);
346 afs_put_cell(params.default_cell); 442 afs_put_cell(params.cell);
443 key_put(params.key);
347 _leave(" = %d", ret); 444 _leave(" = %d", ret);
348 return ret; 445 return ret;
349} 446}
@@ -375,6 +472,7 @@ static void afs_i_init_once(void *_vnode, struct kmem_cache *cachep,
375 memset(vnode, 0, sizeof(*vnode)); 472 memset(vnode, 0, sizeof(*vnode));
376 inode_init_once(&vnode->vfs_inode); 473 inode_init_once(&vnode->vfs_inode);
377 init_waitqueue_head(&vnode->update_waitq); 474 init_waitqueue_head(&vnode->update_waitq);
475 mutex_init(&vnode->permits_lock);
378 spin_lock_init(&vnode->lock); 476 spin_lock_init(&vnode->lock);
379 INIT_WORK(&vnode->cb_broken_work, afs_broken_callback_work); 477 INIT_WORK(&vnode->cb_broken_work, afs_broken_callback_work);
380 mutex_init(&vnode->cb_broken_lock); 478 mutex_init(&vnode->cb_broken_lock);