Enable users to manage Smack policies through the new hooks lsm_config_self_policy and lsm_config_system_policy.
lsm_config_self_policy allows adding Smack policies for the current cred. For now it remains restricted to CAP_MAC_ADMIN. lsm_config_system_policy allows adding globabl Smack policies. This is restricted to CAP_MAC_ADMIN. Signed-off-by: Maxime Bélair <[email protected]> --- security/smack/smack.h | 8 +++++ security/smack/smack_lsm.c | 73 ++++++++++++++++++++++++++++++++++++++ security/smack/smackfs.c | 2 +- 3 files changed, 82 insertions(+), 1 deletion(-) diff --git a/security/smack/smack.h b/security/smack/smack.h index bf6a6ed3946c..3e3d30dfdcf7 100644 --- a/security/smack/smack.h +++ b/security/smack/smack.h @@ -275,6 +275,14 @@ struct smk_audit_info { #endif }; +/* + * This function is in smackfs.c + */ +ssize_t smk_write_rules_list(struct file *file, const char __user *buf, + size_t count, loff_t *ppos, + struct list_head *rule_list, + struct mutex *rule_lock, int format); + /* * These functions are in smack_access.c */ diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 99833168604e..bf4bb2242768 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -5027,6 +5027,76 @@ static int smack_uring_cmd(struct io_uring_cmd *ioucmd) #endif /* CONFIG_IO_URING */ +/** + * smack_lsm_config_system_policy - Configure a system smack policy + * @op: operation to perform. Currently, only LSM_POLICY_LOAD is supported + * @buf: User-supplied buffer in the form "<fmt><policy>" + * <fmt> is the 1-byte format of <policy> + * <policy> is the policy to load + * @size: size of @buf + * @flags: reserved for future use; must be zero + * + * Returns: number of written rules on success, negative value on error + */ +static int smack_lsm_config_system_policy(u32 op, void __user *buf, size_t size, + u32 flags) +{ + loff_t pos = 0; + u8 fmt; + + if (op != LSM_POLICY_LOAD || flags) + return -EOPNOTSUPP; + + if (size < 2) + return -EINVAL; + + if (get_user(fmt, (uint8_t *)buf)) + return -EFAULT; + + return smk_write_rules_list(NULL, buf + 1, size - 1, &pos, NULL, NULL, fmt); +} + +/** + * smack_lsm_config_self_policy - Configure a smack policy for the current cred + * @op: operation to perform. Currently, only LSM_POLICY_LOAD is supported + * @buf: User-supplied buffer in the form "<fmt><policy>" + * <fmt> is the 1-byte format of <policy> + * <policy> is the policy to load + * @size: size of @buf + * @flags: reserved for future use; must be zero + * + * Returns: number of written rules on success, negative value on error + */ +static int smack_lsm_config_self_policy(u32 op, void __user *buf, size_t size, + u32 flags) +{ + loff_t pos = 0; + u8 fmt; + struct task_smack *tsp; + + if (op != LSM_POLICY_LOAD || flags) + return -EOPNOTSUPP; + + if (size < 2) + return -EINVAL; + + if (get_user(fmt, (uint8_t *)buf)) + return -EFAULT; + /** + * smk_write_rules_list could be used to gain privileges. + * This function is thus restricted to CAP_MAC_ADMIN. + * TODO: Ensure that the new rule does not give extra privileges + * before dropping this CAP_MAC_ADMIN check. + */ + if (!capable(CAP_MAC_ADMIN)) + return -EPERM; + + + tsp = smack_cred(current_cred()); + return smk_write_rules_list(NULL, buf + 1, size - 1, &pos, &tsp->smk_rules, + &tsp->smk_rules_lock, fmt); +} + struct lsm_blob_sizes smack_blob_sizes __ro_after_init = { .lbs_cred = sizeof(struct task_smack), .lbs_file = sizeof(struct smack_known *), @@ -5203,6 +5273,9 @@ static struct security_hook_list smack_hooks[] __ro_after_init = { LSM_HOOK_INIT(uring_sqpoll, smack_uring_sqpoll), LSM_HOOK_INIT(uring_cmd, smack_uring_cmd), #endif + LSM_HOOK_INIT(lsm_config_self_policy, smack_lsm_config_self_policy), + LSM_HOOK_INIT(lsm_config_system_policy, smack_lsm_config_system_policy), + }; diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index 90a67e410808..ed1814588d56 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c @@ -441,7 +441,7 @@ static ssize_t smk_parse_long_rule(char *data, struct smack_parsed_rule *rule, * "subject<whitespace>object<whitespace> * acc_enable<whitespace>acc_disable[<whitespace>...]" */ -static ssize_t smk_write_rules_list(struct file *file, const char __user *buf, +ssize_t smk_write_rules_list(struct file *file, const char __user *buf, size_t count, loff_t *ppos, struct list_head *rule_list, struct mutex *rule_lock, int format) -- 2.48.1
