Commit fbd9acb2 authored by Jann Horn's avatar Jann Horn Committed by Micah Morton

LSM: SafeSetID: add read handler

For debugging a running system, it is very helpful to be able to see what
policy the system is using. Add a read handler that can dump out a copy of
the loaded policy.
Signed-off-by: default avatarJann Horn <jannh@google.com>
Signed-off-by: default avatarMicah Morton <mortonm@chromium.org>
parent 03638e62
...@@ -41,6 +41,7 @@ struct setuid_rule { ...@@ -41,6 +41,7 @@ struct setuid_rule {
struct setuid_ruleset { struct setuid_ruleset {
DECLARE_HASHTABLE(rules, SETID_HASH_BITS); DECLARE_HASHTABLE(rules, SETID_HASH_BITS);
char *policy_str;
struct rcu_head rcu; struct rcu_head rcu;
}; };
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
#include "lsm.h" #include "lsm.h"
static DEFINE_SPINLOCK(policy_update_lock); static DEFINE_MUTEX(policy_update_lock);
/* /*
* In the case the input buffer contains one or more invalid UIDs, the kuid_t * In the case the input buffer contains one or more invalid UIDs, the kuid_t
...@@ -67,6 +67,7 @@ static void __release_ruleset(struct rcu_head *rcu) ...@@ -67,6 +67,7 @@ static void __release_ruleset(struct rcu_head *rcu)
hash_for_each_safe(pol->rules, bucket, tmp, rule, next) hash_for_each_safe(pol->rules, bucket, tmp, rule, next)
kfree(rule); kfree(rule);
kfree(pol->policy_str);
kfree(pol); kfree(pol);
} }
...@@ -85,6 +86,7 @@ static ssize_t handle_policy_update(struct file *file, ...@@ -85,6 +86,7 @@ static ssize_t handle_policy_update(struct file *file,
pol = kmalloc(sizeof(struct setuid_ruleset), GFP_KERNEL); pol = kmalloc(sizeof(struct setuid_ruleset), GFP_KERNEL);
if (!pol) if (!pol)
return -ENOMEM; return -ENOMEM;
pol->policy_str = NULL;
hash_init(pol->rules); hash_init(pol->rules);
p = buf = memdup_user_nul(ubuf, len); p = buf = memdup_user_nul(ubuf, len);
...@@ -92,6 +94,11 @@ static ssize_t handle_policy_update(struct file *file, ...@@ -92,6 +94,11 @@ static ssize_t handle_policy_update(struct file *file,
err = PTR_ERR(buf); err = PTR_ERR(buf);
goto out_free_pol; goto out_free_pol;
} }
pol->policy_str = kstrdup(buf, GFP_KERNEL);
if (pol->policy_str == NULL) {
err = -ENOMEM;
goto out_free_buf;
}
/* policy lines, including the last one, end with \n */ /* policy lines, including the last one, end with \n */
while (*p != '\0') { while (*p != '\0') {
...@@ -135,10 +142,10 @@ static ssize_t handle_policy_update(struct file *file, ...@@ -135,10 +142,10 @@ static ssize_t handle_policy_update(struct file *file,
* What we really want here is an xchg() wrapper for RCU, but since that * What we really want here is an xchg() wrapper for RCU, but since that
* doesn't currently exist, just use a spinlock for now. * doesn't currently exist, just use a spinlock for now.
*/ */
spin_lock(&policy_update_lock); mutex_lock(&policy_update_lock);
rcu_swap_protected(safesetid_setuid_rules, pol, rcu_swap_protected(safesetid_setuid_rules, pol,
lockdep_is_held(&policy_update_lock)); lockdep_is_held(&policy_update_lock));
spin_unlock(&policy_update_lock); mutex_unlock(&policy_update_lock);
err = len; err = len;
out_free_buf: out_free_buf:
...@@ -162,7 +169,27 @@ static ssize_t safesetid_file_write(struct file *file, ...@@ -162,7 +169,27 @@ static ssize_t safesetid_file_write(struct file *file,
return handle_policy_update(file, buf, len); return handle_policy_update(file, buf, len);
} }
static ssize_t safesetid_file_read(struct file *file, char __user *buf,
size_t len, loff_t *ppos)
{
ssize_t res = 0;
struct setuid_ruleset *pol;
const char *kbuf;
mutex_lock(&policy_update_lock);
pol = rcu_dereference_protected(safesetid_setuid_rules,
lockdep_is_held(&policy_update_lock));
if (pol) {
kbuf = pol->policy_str;
res = simple_read_from_buffer(buf, len, ppos,
kbuf, strlen(kbuf));
}
mutex_unlock(&policy_update_lock);
return res;
}
static const struct file_operations safesetid_file_fops = { static const struct file_operations safesetid_file_fops = {
.read = safesetid_file_read,
.write = safesetid_file_write, .write = safesetid_file_write,
}; };
...@@ -181,7 +208,7 @@ static int __init safesetid_init_securityfs(void) ...@@ -181,7 +208,7 @@ static int __init safesetid_init_securityfs(void)
goto error; goto error;
} }
policy_file = securityfs_create_file("whitelist_policy", 0200, policy_file = securityfs_create_file("whitelist_policy", 0600,
policy_dir, NULL, &safesetid_file_fops); policy_dir, NULL, &safesetid_file_fops);
if (IS_ERR(policy_file)) { if (IS_ERR(policy_file)) {
ret = PTR_ERR(policy_file); ret = PTR_ERR(policy_file);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment