mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-28 17:41:50 +00:00
introduce cloning of fs_context
new primitive: vfs_dup_fs_context(). Comes with fs_context method (->dup()) for copying the filesystem-specific parts of fs_context, along with LSM one (->fs_context_dup()) for doing the same to LSM parts. [needs better commit message, and change of Author:, anyway] Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
cb50b348c7
commit
0b52075ee6
7 changed files with 175 additions and 0 deletions
|
@ -337,6 +337,47 @@ void fc_drop_locked(struct fs_context *fc)
|
||||||
|
|
||||||
static void legacy_fs_context_free(struct fs_context *fc);
|
static void legacy_fs_context_free(struct fs_context *fc);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* vfs_dup_fc_config: Duplicate a filesystem context.
|
||||||
|
* @src_fc: The context to copy.
|
||||||
|
*/
|
||||||
|
struct fs_context *vfs_dup_fs_context(struct fs_context *src_fc)
|
||||||
|
{
|
||||||
|
struct fs_context *fc;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!src_fc->ops->dup)
|
||||||
|
return ERR_PTR(-EOPNOTSUPP);
|
||||||
|
|
||||||
|
fc = kmemdup(src_fc, sizeof(struct fs_context), GFP_KERNEL);
|
||||||
|
if (!fc)
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
fc->fs_private = NULL;
|
||||||
|
fc->s_fs_info = NULL;
|
||||||
|
fc->source = NULL;
|
||||||
|
fc->security = NULL;
|
||||||
|
get_filesystem(fc->fs_type);
|
||||||
|
get_net(fc->net_ns);
|
||||||
|
get_user_ns(fc->user_ns);
|
||||||
|
get_cred(fc->cred);
|
||||||
|
|
||||||
|
/* Can't call put until we've called ->dup */
|
||||||
|
ret = fc->ops->dup(fc, src_fc);
|
||||||
|
if (ret < 0)
|
||||||
|
goto err_fc;
|
||||||
|
|
||||||
|
ret = security_fs_context_dup(fc, src_fc);
|
||||||
|
if (ret < 0)
|
||||||
|
goto err_fc;
|
||||||
|
return fc;
|
||||||
|
|
||||||
|
err_fc:
|
||||||
|
put_fs_context(fc);
|
||||||
|
return ERR_PTR(ret);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(vfs_dup_fs_context);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* put_fs_context - Dispose of a superblock configuration context.
|
* put_fs_context - Dispose of a superblock configuration context.
|
||||||
* @fc: The context to dispose of.
|
* @fc: The context to dispose of.
|
||||||
|
@ -380,6 +421,31 @@ static void legacy_fs_context_free(struct fs_context *fc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Duplicate a legacy config.
|
||||||
|
*/
|
||||||
|
static int legacy_fs_context_dup(struct fs_context *fc, struct fs_context *src_fc)
|
||||||
|
{
|
||||||
|
struct legacy_fs_context *ctx;
|
||||||
|
struct legacy_fs_context *src_ctx = src_fc->fs_private;
|
||||||
|
|
||||||
|
ctx = kmemdup(src_ctx, sizeof(*src_ctx), GFP_KERNEL);
|
||||||
|
if (!ctx)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
if (ctx->param_type == LEGACY_FS_INDIVIDUAL_PARAMS) {
|
||||||
|
ctx->legacy_data = kmemdup(src_ctx->legacy_data,
|
||||||
|
src_ctx->data_size, GFP_KERNEL);
|
||||||
|
if (!ctx->legacy_data) {
|
||||||
|
kfree(ctx);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fc->fs_private = ctx;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add a parameter to a legacy config. We build up a comma-separated list of
|
* Add a parameter to a legacy config. We build up a comma-separated list of
|
||||||
* options.
|
* options.
|
||||||
|
@ -514,6 +580,7 @@ static int legacy_reconfigure(struct fs_context *fc)
|
||||||
|
|
||||||
const struct fs_context_operations legacy_fs_context_ops = {
|
const struct fs_context_operations legacy_fs_context_ops = {
|
||||||
.free = legacy_fs_context_free,
|
.free = legacy_fs_context_free,
|
||||||
|
.dup = legacy_fs_context_dup,
|
||||||
.parse_param = legacy_parse_param,
|
.parse_param = legacy_parse_param,
|
||||||
.parse_monolithic = legacy_parse_monolithic,
|
.parse_monolithic = legacy_parse_monolithic,
|
||||||
.get_tree = legacy_get_tree,
|
.get_tree = legacy_get_tree,
|
||||||
|
|
|
@ -94,6 +94,7 @@ struct fs_context {
|
||||||
|
|
||||||
struct fs_context_operations {
|
struct fs_context_operations {
|
||||||
void (*free)(struct fs_context *fc);
|
void (*free)(struct fs_context *fc);
|
||||||
|
int (*dup)(struct fs_context *fc, struct fs_context *src_fc);
|
||||||
int (*parse_param)(struct fs_context *fc, struct fs_parameter *param);
|
int (*parse_param)(struct fs_context *fc, struct fs_parameter *param);
|
||||||
int (*parse_monolithic)(struct fs_context *fc, void *data);
|
int (*parse_monolithic)(struct fs_context *fc, void *data);
|
||||||
int (*get_tree)(struct fs_context *fc);
|
int (*get_tree)(struct fs_context *fc);
|
||||||
|
@ -111,6 +112,7 @@ extern struct fs_context *fs_context_for_reconfigure(struct dentry *dentry,
|
||||||
extern struct fs_context *fs_context_for_submount(struct file_system_type *fs_type,
|
extern struct fs_context *fs_context_for_submount(struct file_system_type *fs_type,
|
||||||
struct dentry *reference);
|
struct dentry *reference);
|
||||||
|
|
||||||
|
extern struct fs_context *vfs_dup_fs_context(struct fs_context *fc);
|
||||||
extern int vfs_parse_fs_param(struct fs_context *fc, struct fs_parameter *param);
|
extern int vfs_parse_fs_param(struct fs_context *fc, struct fs_parameter *param);
|
||||||
extern int vfs_parse_fs_string(struct fs_context *fc, const char *key,
|
extern int vfs_parse_fs_string(struct fs_context *fc, const char *key,
|
||||||
const char *value, size_t v_size);
|
const char *value, size_t v_size);
|
||||||
|
|
|
@ -79,6 +79,11 @@
|
||||||
* Security hooks for mount using fs_context.
|
* Security hooks for mount using fs_context.
|
||||||
* [See also Documentation/filesystems/mounting.txt]
|
* [See also Documentation/filesystems/mounting.txt]
|
||||||
*
|
*
|
||||||
|
* @fs_context_dup:
|
||||||
|
* Allocate and attach a security structure to sc->security. This pointer
|
||||||
|
* is initialised to NULL by the caller.
|
||||||
|
* @fc indicates the new filesystem context.
|
||||||
|
* @src_fc indicates the original filesystem context.
|
||||||
* @fs_context_parse_param:
|
* @fs_context_parse_param:
|
||||||
* Userspace provided a parameter to configure a superblock. The LSM may
|
* Userspace provided a parameter to configure a superblock. The LSM may
|
||||||
* reject it with an error and may use it for itself, in which case it
|
* reject it with an error and may use it for itself, in which case it
|
||||||
|
@ -1470,6 +1475,7 @@ union security_list_options {
|
||||||
void (*bprm_committing_creds)(struct linux_binprm *bprm);
|
void (*bprm_committing_creds)(struct linux_binprm *bprm);
|
||||||
void (*bprm_committed_creds)(struct linux_binprm *bprm);
|
void (*bprm_committed_creds)(struct linux_binprm *bprm);
|
||||||
|
|
||||||
|
int (*fs_context_dup)(struct fs_context *fc, struct fs_context *src_sc);
|
||||||
int (*fs_context_parse_param)(struct fs_context *fc, struct fs_parameter *param);
|
int (*fs_context_parse_param)(struct fs_context *fc, struct fs_parameter *param);
|
||||||
|
|
||||||
int (*sb_alloc_security)(struct super_block *sb);
|
int (*sb_alloc_security)(struct super_block *sb);
|
||||||
|
@ -1813,6 +1819,7 @@ struct security_hook_heads {
|
||||||
struct hlist_head bprm_check_security;
|
struct hlist_head bprm_check_security;
|
||||||
struct hlist_head bprm_committing_creds;
|
struct hlist_head bprm_committing_creds;
|
||||||
struct hlist_head bprm_committed_creds;
|
struct hlist_head bprm_committed_creds;
|
||||||
|
struct hlist_head fs_context_dup;
|
||||||
struct hlist_head fs_context_parse_param;
|
struct hlist_head fs_context_parse_param;
|
||||||
struct hlist_head sb_alloc_security;
|
struct hlist_head sb_alloc_security;
|
||||||
struct hlist_head sb_free_security;
|
struct hlist_head sb_free_security;
|
||||||
|
|
|
@ -223,6 +223,7 @@ int security_bprm_set_creds(struct linux_binprm *bprm);
|
||||||
int security_bprm_check(struct linux_binprm *bprm);
|
int security_bprm_check(struct linux_binprm *bprm);
|
||||||
void security_bprm_committing_creds(struct linux_binprm *bprm);
|
void security_bprm_committing_creds(struct linux_binprm *bprm);
|
||||||
void security_bprm_committed_creds(struct linux_binprm *bprm);
|
void security_bprm_committed_creds(struct linux_binprm *bprm);
|
||||||
|
int security_fs_context_dup(struct fs_context *fc, struct fs_context *src_fc);
|
||||||
int security_fs_context_parse_param(struct fs_context *fc, struct fs_parameter *param);
|
int security_fs_context_parse_param(struct fs_context *fc, struct fs_parameter *param);
|
||||||
int security_sb_alloc(struct super_block *sb);
|
int security_sb_alloc(struct super_block *sb);
|
||||||
void security_sb_free(struct super_block *sb);
|
void security_sb_free(struct super_block *sb);
|
||||||
|
@ -521,6 +522,11 @@ static inline void security_bprm_committed_creds(struct linux_binprm *bprm)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int security_fs_context_dup(struct fs_context *fc,
|
||||||
|
struct fs_context *src_fc)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
static inline int security_fs_context_parse_param(struct fs_context *fc,
|
static inline int security_fs_context_parse_param(struct fs_context *fc,
|
||||||
struct fs_parameter *param)
|
struct fs_parameter *param)
|
||||||
{
|
{
|
||||||
|
|
|
@ -374,6 +374,11 @@ void security_bprm_committed_creds(struct linux_binprm *bprm)
|
||||||
call_void_hook(bprm_committed_creds, bprm);
|
call_void_hook(bprm_committed_creds, bprm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int security_fs_context_dup(struct fs_context *fc, struct fs_context *src_fc)
|
||||||
|
{
|
||||||
|
return call_int_hook(fs_context_dup, 0, fc, src_fc);
|
||||||
|
}
|
||||||
|
|
||||||
int security_fs_context_parse_param(struct fs_context *fc, struct fs_parameter *param)
|
int security_fs_context_parse_param(struct fs_context *fc, struct fs_parameter *param)
|
||||||
{
|
{
|
||||||
return call_int_hook(fs_context_parse_param, -ENOPARAM, fc, param);
|
return call_int_hook(fs_context_parse_param, -ENOPARAM, fc, param);
|
||||||
|
|
|
@ -2764,6 +2764,44 @@ static int selinux_umount(struct vfsmount *mnt, int flags)
|
||||||
FILESYSTEM__UNMOUNT, NULL);
|
FILESYSTEM__UNMOUNT, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int selinux_fs_context_dup(struct fs_context *fc,
|
||||||
|
struct fs_context *src_fc)
|
||||||
|
{
|
||||||
|
const struct selinux_mnt_opts *src = src_fc->security;
|
||||||
|
struct selinux_mnt_opts *opts;
|
||||||
|
|
||||||
|
if (!src)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
fc->security = kzalloc(sizeof(struct selinux_mnt_opts), GFP_KERNEL);
|
||||||
|
if (!fc->security)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
opts = fc->security;
|
||||||
|
|
||||||
|
if (src->fscontext) {
|
||||||
|
opts->fscontext = kstrdup(src->fscontext, GFP_KERNEL);
|
||||||
|
if (!opts->fscontext)
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
if (src->context) {
|
||||||
|
opts->context = kstrdup(src->context, GFP_KERNEL);
|
||||||
|
if (!opts->context)
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
if (src->rootcontext) {
|
||||||
|
opts->rootcontext = kstrdup(src->rootcontext, GFP_KERNEL);
|
||||||
|
if (!opts->rootcontext)
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
if (src->defcontext) {
|
||||||
|
opts->defcontext = kstrdup(src->defcontext, GFP_KERNEL);
|
||||||
|
if (!opts->defcontext)
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static const struct fs_parameter_spec selinux_param_specs[] = {
|
static const struct fs_parameter_spec selinux_param_specs[] = {
|
||||||
fsparam_string(CONTEXT_STR, Opt_context),
|
fsparam_string(CONTEXT_STR, Opt_context),
|
||||||
fsparam_string(DEFCONTEXT_STR, Opt_defcontext),
|
fsparam_string(DEFCONTEXT_STR, Opt_defcontext),
|
||||||
|
@ -6745,6 +6783,7 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
|
||||||
LSM_HOOK_INIT(bprm_committing_creds, selinux_bprm_committing_creds),
|
LSM_HOOK_INIT(bprm_committing_creds, selinux_bprm_committing_creds),
|
||||||
LSM_HOOK_INIT(bprm_committed_creds, selinux_bprm_committed_creds),
|
LSM_HOOK_INIT(bprm_committed_creds, selinux_bprm_committed_creds),
|
||||||
|
|
||||||
|
LSM_HOOK_INIT(fs_context_dup, selinux_fs_context_dup),
|
||||||
LSM_HOOK_INIT(fs_context_parse_param, selinux_fs_context_parse_param),
|
LSM_HOOK_INIT(fs_context_parse_param, selinux_fs_context_parse_param),
|
||||||
|
|
||||||
LSM_HOOK_INIT(sb_alloc_security, selinux_sb_alloc_security),
|
LSM_HOOK_INIT(sb_alloc_security, selinux_sb_alloc_security),
|
||||||
|
|
|
@ -647,6 +647,54 @@ out_opt_err:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* smack_fs_context_dup - Duplicate the security data on fs_context duplication
|
||||||
|
* @fc: The new filesystem context.
|
||||||
|
* @src_fc: The source filesystem context being duplicated.
|
||||||
|
*
|
||||||
|
* Returns 0 on success or -ENOMEM on error.
|
||||||
|
*/
|
||||||
|
static int smack_fs_context_dup(struct fs_context *fc,
|
||||||
|
struct fs_context *src_fc)
|
||||||
|
{
|
||||||
|
struct smack_mnt_opts *dst, *src = src_fc->security;
|
||||||
|
|
||||||
|
if (!src)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
fc->security = kzalloc(sizeof(struct smack_mnt_opts), GFP_KERNEL);
|
||||||
|
if (!fc->security)
|
||||||
|
return -ENOMEM;
|
||||||
|
dst = fc->security;
|
||||||
|
|
||||||
|
if (src->fsdefault) {
|
||||||
|
dst->fsdefault = kstrdup(src->fsdefault, GFP_KERNEL);
|
||||||
|
if (!dst->fsdefault)
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
if (src->fsfloor) {
|
||||||
|
dst->fsfloor = kstrdup(src->fsfloor, GFP_KERNEL);
|
||||||
|
if (!dst->fsfloor)
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
if (src->fshat) {
|
||||||
|
dst->fshat = kstrdup(src->fshat, GFP_KERNEL);
|
||||||
|
if (!dst->fshat)
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
if (src->fsroot) {
|
||||||
|
dst->fsroot = kstrdup(src->fsroot, GFP_KERNEL);
|
||||||
|
if (!dst->fsroot)
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
if (src->fstransmute) {
|
||||||
|
dst->fstransmute = kstrdup(src->fstransmute, GFP_KERNEL);
|
||||||
|
if (!dst->fstransmute)
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static const struct fs_parameter_spec smack_param_specs[] = {
|
static const struct fs_parameter_spec smack_param_specs[] = {
|
||||||
fsparam_string("fsdefault", Opt_fsdefault),
|
fsparam_string("fsdefault", Opt_fsdefault),
|
||||||
fsparam_string("fsfloor", Opt_fsfloor),
|
fsparam_string("fsfloor", Opt_fsfloor),
|
||||||
|
@ -4626,6 +4674,7 @@ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {
|
||||||
LSM_HOOK_INIT(ptrace_traceme, smack_ptrace_traceme),
|
LSM_HOOK_INIT(ptrace_traceme, smack_ptrace_traceme),
|
||||||
LSM_HOOK_INIT(syslog, smack_syslog),
|
LSM_HOOK_INIT(syslog, smack_syslog),
|
||||||
|
|
||||||
|
LSM_HOOK_INIT(fs_context_dup, smack_fs_context_dup),
|
||||||
LSM_HOOK_INIT(fs_context_parse_param, smack_fs_context_parse_param),
|
LSM_HOOK_INIT(fs_context_parse_param, smack_fs_context_parse_param),
|
||||||
|
|
||||||
LSM_HOOK_INIT(sb_alloc_security, smack_sb_alloc_security),
|
LSM_HOOK_INIT(sb_alloc_security, smack_sb_alloc_security),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue