aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--security/safesetid/lsm.h1
-rw-r--r--security/safesetid/securityfs.c35
2 files changed, 32 insertions, 4 deletions
diff --git a/security/safesetid/lsm.h b/security/safesetid/lsm.h
index 4a34f558d964..db6d16e6bbc3 100644
--- a/security/safesetid/lsm.h
+++ b/security/safesetid/lsm.h
@@ -41,6 +41,7 @@ struct setuid_rule {
41 41
42struct setuid_ruleset { 42struct setuid_ruleset {
43 DECLARE_HASHTABLE(rules, SETID_HASH_BITS); 43 DECLARE_HASHTABLE(rules, SETID_HASH_BITS);
44 char *policy_str;
44 struct rcu_head rcu; 45 struct rcu_head rcu;
45}; 46};
46 47
diff --git a/security/safesetid/securityfs.c b/security/safesetid/securityfs.c
index 250d59e046c1..997b403c6255 100644
--- a/security/safesetid/securityfs.c
+++ b/security/safesetid/securityfs.c
@@ -19,7 +19,7 @@
19 19
20#include "lsm.h" 20#include "lsm.h"
21 21
22static DEFINE_SPINLOCK(policy_update_lock); 22static DEFINE_MUTEX(policy_update_lock);
23 23
24/* 24/*
25 * In the case the input buffer contains one or more invalid UIDs, the kuid_t 25 * 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 67
68 hash_for_each_safe(pol->rules, bucket, tmp, rule, next) 68 hash_for_each_safe(pol->rules, bucket, tmp, rule, next)
69 kfree(rule); 69 kfree(rule);
70 kfree(pol->policy_str);
70 kfree(pol); 71 kfree(pol);
71} 72}
72 73
@@ -85,6 +86,7 @@ static ssize_t handle_policy_update(struct file *file,
85 pol = kmalloc(sizeof(struct setuid_ruleset), GFP_KERNEL); 86 pol = kmalloc(sizeof(struct setuid_ruleset), GFP_KERNEL);
86 if (!pol) 87 if (!pol)
87 return -ENOMEM; 88 return -ENOMEM;
89 pol->policy_str = NULL;
88 hash_init(pol->rules); 90 hash_init(pol->rules);
89 91
90 p = buf = memdup_user_nul(ubuf, len); 92 p = buf = memdup_user_nul(ubuf, len);
@@ -92,6 +94,11 @@ static ssize_t handle_policy_update(struct file *file,
92 err = PTR_ERR(buf); 94 err = PTR_ERR(buf);
93 goto out_free_pol; 95 goto out_free_pol;
94 } 96 }
97 pol->policy_str = kstrdup(buf, GFP_KERNEL);
98 if (pol->policy_str == NULL) {
99 err = -ENOMEM;
100 goto out_free_buf;
101 }
95 102
96 /* policy lines, including the last one, end with \n */ 103 /* policy lines, including the last one, end with \n */
97 while (*p != '\0') { 104 while (*p != '\0') {
@@ -135,10 +142,10 @@ out_free_rule:
135 * What we really want here is an xchg() wrapper for RCU, but since that 142 * What we really want here is an xchg() wrapper for RCU, but since that
136 * doesn't currently exist, just use a spinlock for now. 143 * doesn't currently exist, just use a spinlock for now.
137 */ 144 */
138 spin_lock(&policy_update_lock); 145 mutex_lock(&policy_update_lock);
139 rcu_swap_protected(safesetid_setuid_rules, pol, 146 rcu_swap_protected(safesetid_setuid_rules, pol,
140 lockdep_is_held(&policy_update_lock)); 147 lockdep_is_held(&policy_update_lock));
141 spin_unlock(&policy_update_lock); 148 mutex_unlock(&policy_update_lock);
142 err = len; 149 err = len;
143 150
144out_free_buf: 151out_free_buf:
@@ -162,7 +169,27 @@ static ssize_t safesetid_file_write(struct file *file,
162 return handle_policy_update(file, buf, len); 169 return handle_policy_update(file, buf, len);
163} 170}
164 171
172static ssize_t safesetid_file_read(struct file *file, char __user *buf,
173 size_t len, loff_t *ppos)
174{
175 ssize_t res = 0;
176 struct setuid_ruleset *pol;
177 const char *kbuf;
178
179 mutex_lock(&policy_update_lock);
180 pol = rcu_dereference_protected(safesetid_setuid_rules,
181 lockdep_is_held(&policy_update_lock));
182 if (pol) {
183 kbuf = pol->policy_str;
184 res = simple_read_from_buffer(buf, len, ppos,
185 kbuf, strlen(kbuf));
186 }
187 mutex_unlock(&policy_update_lock);
188 return res;
189}
190
165static const struct file_operations safesetid_file_fops = { 191static const struct file_operations safesetid_file_fops = {
192 .read = safesetid_file_read,
166 .write = safesetid_file_write, 193 .write = safesetid_file_write,
167}; 194};
168 195
@@ -181,7 +208,7 @@ static int __init safesetid_init_securityfs(void)
181 goto error; 208 goto error;
182 } 209 }
183 210
184 policy_file = securityfs_create_file("whitelist_policy", 0200, 211 policy_file = securityfs_create_file("whitelist_policy", 0600,
185 policy_dir, NULL, &safesetid_file_fops); 212 policy_dir, NULL, &safesetid_file_fops);
186 if (IS_ERR(policy_file)) { 213 if (IS_ERR(policy_file)) {
187 ret = PTR_ERR(policy_file); 214 ret = PTR_ERR(policy_file);