diff options
Diffstat (limited to 'security/smack/smack_lsm.c')
-rw-r--r-- | security/smack/smack_lsm.c | 92 |
1 files changed, 91 insertions, 1 deletions
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 424bce4ef21d..5c1613519d5a 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -43,6 +43,8 @@ #include <linux/shm.h> #include <linux/binfmts.h> #include <linux/parser.h> +#include <linux/fs_context.h> +#include <linux/fs_parser.h> #include "smack.h" #define TRANS_TRUE "TRUE" @@ -526,7 +528,6 @@ static int smack_syslog(int typefrom_file) return rc; } - /* * Superblock Hooks. */ @@ -631,6 +632,92 @@ out_opt_err: 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[] = { + fsparam_string("fsdefault", Opt_fsdefault), + fsparam_string("fsfloor", Opt_fsfloor), + fsparam_string("fshat", Opt_fshat), + fsparam_string("fsroot", Opt_fsroot), + fsparam_string("fstransmute", Opt_fstransmute), + {} +}; + +static const struct fs_parameter_description smack_fs_parameters = { + .name = "smack", + .specs = smack_param_specs, +}; + +/** + * smack_fs_context_parse_param - Parse a single mount parameter + * @fc: The new filesystem context being constructed. + * @param: The parameter. + * + * Returns 0 on success, -ENOPARAM to pass the parameter on or anything else on + * error. + */ +static int smack_fs_context_parse_param(struct fs_context *fc, + struct fs_parameter *param) +{ + struct fs_parse_result result; + int opt, rc; + + opt = fs_parse(fc, &smack_fs_parameters, param, &result); + if (opt < 0) + return opt; + + rc = smack_add_opt(opt, param->string, &fc->security); + if (!rc) + param->string = NULL; + return rc; +} + static int smack_sb_eat_lsm_opts(char *options, void **mnt_opts) { char *from = options, *to = options; @@ -4495,6 +4582,9 @@ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = { LSM_HOOK_INIT(ptrace_traceme, smack_ptrace_traceme), 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(sb_alloc_security, smack_sb_alloc_security), LSM_HOOK_INIT(sb_free_security, smack_sb_free_security), LSM_HOOK_INIT(sb_free_mnt_opts, smack_free_mnt_opts), |