[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>
This commit is contained in:
committed by
David S. Miller
parent
436058a49e
commit
00d3b7a453
142
fs/afs/super.c
142
fs/afs/super.c
@@ -24,12 +24,6 @@
|
||||
|
||||
#define AFS_FS_MAGIC 0x6B414653 /* 'kAFS' */
|
||||
|
||||
struct afs_mount_params {
|
||||
int rwpath;
|
||||
struct afs_cell *default_cell;
|
||||
struct afs_volume *volume;
|
||||
};
|
||||
|
||||
static void afs_i_init_once(void *foo, struct kmem_cache *cachep,
|
||||
unsigned long flags);
|
||||
|
||||
@@ -150,8 +144,8 @@ static int want_no_value(char *const *_value, const char *option)
|
||||
* - this function has been shamelessly adapted from the ext3 fs which
|
||||
* shamelessly adapted it from the msdos fs
|
||||
*/
|
||||
static int afs_super_parse_options(struct afs_mount_params *params,
|
||||
char *options, const char **devname)
|
||||
static int afs_parse_options(struct afs_mount_params *params,
|
||||
char *options, const char **devname)
|
||||
{
|
||||
struct afs_cell *cell;
|
||||
char *key, *value;
|
||||
@@ -183,8 +177,8 @@ static int afs_super_parse_options(struct afs_mount_params *params,
|
||||
cell = afs_cell_lookup(value, strlen(value));
|
||||
if (IS_ERR(cell))
|
||||
return PTR_ERR(cell);
|
||||
afs_put_cell(params->default_cell);
|
||||
params->default_cell = cell;
|
||||
afs_put_cell(params->cell);
|
||||
params->cell = cell;
|
||||
} else {
|
||||
printk("kAFS: Unknown mount option: '%s'\n", key);
|
||||
ret = -EINVAL;
|
||||
@@ -198,6 +192,99 @@ error:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* parse a device name to get cell name, volume name, volume type and R/W
|
||||
* selector
|
||||
* - this can be one of the following:
|
||||
* "%[cell:]volume[.]" R/W volume
|
||||
* "#[cell:]volume[.]" R/O or R/W volume (rwpath=0),
|
||||
* or R/W (rwpath=1) volume
|
||||
* "%[cell:]volume.readonly" R/O volume
|
||||
* "#[cell:]volume.readonly" R/O volume
|
||||
* "%[cell:]volume.backup" Backup volume
|
||||
* "#[cell:]volume.backup" Backup volume
|
||||
*/
|
||||
static int afs_parse_device_name(struct afs_mount_params *params,
|
||||
const char *name)
|
||||
{
|
||||
struct afs_cell *cell;
|
||||
const char *cellname, *suffix;
|
||||
int cellnamesz;
|
||||
|
||||
_enter(",%s", name);
|
||||
|
||||
if (!name) {
|
||||
printk(KERN_ERR "kAFS: no volume name specified\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((name[0] != '%' && name[0] != '#') || !name[1]) {
|
||||
printk(KERN_ERR "kAFS: unparsable volume name\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* determine the type of volume we're looking for */
|
||||
params->type = AFSVL_ROVOL;
|
||||
params->force = false;
|
||||
if (params->rwpath || name[0] == '%') {
|
||||
params->type = AFSVL_RWVOL;
|
||||
params->force = true;
|
||||
}
|
||||
name++;
|
||||
|
||||
/* split the cell name out if there is one */
|
||||
params->volname = strchr(name, ':');
|
||||
if (params->volname) {
|
||||
cellname = name;
|
||||
cellnamesz = params->volname - name;
|
||||
params->volname++;
|
||||
} else {
|
||||
params->volname = name;
|
||||
cellname = NULL;
|
||||
cellnamesz = 0;
|
||||
}
|
||||
|
||||
/* the volume type is further affected by a possible suffix */
|
||||
suffix = strrchr(params->volname, '.');
|
||||
if (suffix) {
|
||||
if (strcmp(suffix, ".readonly") == 0) {
|
||||
params->type = AFSVL_ROVOL;
|
||||
params->force = true;
|
||||
} else if (strcmp(suffix, ".backup") == 0) {
|
||||
params->type = AFSVL_BACKVOL;
|
||||
params->force = true;
|
||||
} else if (suffix[1] == 0) {
|
||||
} else {
|
||||
suffix = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
params->volnamesz = suffix ?
|
||||
suffix - params->volname : strlen(params->volname);
|
||||
|
||||
_debug("cell %*.*s [%p]",
|
||||
cellnamesz, cellnamesz, cellname ?: "", params->cell);
|
||||
|
||||
/* lookup the cell record */
|
||||
if (cellname || !params->cell) {
|
||||
cell = afs_cell_lookup(cellname, cellnamesz);
|
||||
if (IS_ERR(cell)) {
|
||||
printk(KERN_ERR "kAFS: unable to lookup cell '%s'\n",
|
||||
cellname ?: "");
|
||||
return PTR_ERR(cell);
|
||||
}
|
||||
afs_put_cell(params->cell);
|
||||
params->cell = cell;
|
||||
}
|
||||
|
||||
_debug("CELL:%s [%p] VOLUME:%*.*s SUFFIX:%s TYPE:%d%s",
|
||||
params->cell->name, params->cell,
|
||||
params->volnamesz, params->volnamesz, params->volname,
|
||||
suffix ?: "-", params->type, params->force ? " FORCE" : "");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* check a superblock to see if it's the one we're looking for
|
||||
*/
|
||||
@@ -244,7 +331,7 @@ static int afs_fill_super(struct super_block *sb, void *data)
|
||||
fid.vid = as->volume->vid;
|
||||
fid.vnode = 1;
|
||||
fid.unique = 1;
|
||||
inode = afs_iget(sb, &fid);
|
||||
inode = afs_iget(sb, params->key, &fid);
|
||||
if (IS_ERR(inode))
|
||||
goto error_inode;
|
||||
|
||||
@@ -285,31 +372,40 @@ static int afs_get_sb(struct file_system_type *fs_type,
|
||||
struct afs_mount_params params;
|
||||
struct super_block *sb;
|
||||
struct afs_volume *vol;
|
||||
struct key *key;
|
||||
int ret;
|
||||
|
||||
_enter(",,%s,%p", dev_name, options);
|
||||
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
|
||||
/* parse the options */
|
||||
/* parse the options and device name */
|
||||
if (options) {
|
||||
ret = afs_super_parse_options(¶ms, options, &dev_name);
|
||||
ret = afs_parse_options(¶ms, options, &dev_name);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
if (!dev_name) {
|
||||
printk("kAFS: no volume name specified\n");
|
||||
ret = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ret = afs_parse_device_name(¶ms, dev_name);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
||||
/* try and do the mount securely */
|
||||
key = afs_request_key(params.cell);
|
||||
if (IS_ERR(key)) {
|
||||
_leave(" = %ld [key]", PTR_ERR(key));
|
||||
ret = PTR_ERR(key);
|
||||
goto error;
|
||||
}
|
||||
params.key = key;
|
||||
|
||||
/* parse the device name */
|
||||
vol = afs_volume_lookup(dev_name, params.default_cell, params.rwpath);
|
||||
vol = afs_volume_lookup(¶ms);
|
||||
if (IS_ERR(vol)) {
|
||||
ret = PTR_ERR(vol);
|
||||
goto error;
|
||||
}
|
||||
|
||||
params.volume = vol;
|
||||
|
||||
/* allocate a deviceless superblock */
|
||||
@@ -337,13 +433,14 @@ static int afs_get_sb(struct file_system_type *fs_type,
|
||||
|
||||
simple_set_mnt(mnt, sb);
|
||||
afs_put_volume(params.volume);
|
||||
afs_put_cell(params.default_cell);
|
||||
afs_put_cell(params.cell);
|
||||
_leave(" = 0 [%p]", sb);
|
||||
return 0;
|
||||
|
||||
error:
|
||||
afs_put_volume(params.volume);
|
||||
afs_put_cell(params.default_cell);
|
||||
afs_put_cell(params.cell);
|
||||
key_put(params.key);
|
||||
_leave(" = %d", ret);
|
||||
return ret;
|
||||
}
|
||||
@@ -375,6 +472,7 @@ static void afs_i_init_once(void *_vnode, struct kmem_cache *cachep,
|
||||
memset(vnode, 0, sizeof(*vnode));
|
||||
inode_init_once(&vnode->vfs_inode);
|
||||
init_waitqueue_head(&vnode->update_waitq);
|
||||
mutex_init(&vnode->permits_lock);
|
||||
spin_lock_init(&vnode->lock);
|
||||
INIT_WORK(&vnode->cb_broken_work, afs_broken_callback_work);
|
||||
mutex_init(&vnode->cb_broken_lock);
|
||||
|
||||
Reference in New Issue
Block a user