aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorAmy Griffis <amy.griffis@hp.com>2005-08-17 11:05:35 -0400
committerDavid Woodhouse <dwmw2@shinybook.infradead.org>2005-08-17 11:05:35 -0400
commit3c789a19054034847afe80af2f23ebb0eebfbad6 (patch)
treecc983b5fd132c329e16d61d408d8a26ca048cf6b /kernel
parentc3896495942392f1a792da1cafba7a573cbf6fc2 (diff)
AUDIT: Prevent duplicate syscall rules
The following patch against audit.81 prevents duplicate syscall rules in a given filter list by walking the list on each rule add. I also removed the unused struct audit_entry in audit.c and made the static inlines in auditsc.c consistent. Signed-off-by: Amy Griffis <amy.griffis@hp.com> Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/audit.c5
-rw-r--r--kernel/auditsc.c95
2 files changed, 56 insertions, 44 deletions
diff --git a/kernel/audit.c b/kernel/audit.c
index d321e251d32b..8376ec10cf24 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -142,11 +142,6 @@ static void audit_set_pid(struct audit_buffer *ab, pid_t pid)
142 nlh->nlmsg_pid = pid; 142 nlh->nlmsg_pid = pid;
143} 143}
144 144
145struct audit_entry {
146 struct list_head list;
147 struct audit_rule rule;
148};
149
150static void audit_panic(const char *message) 145static void audit_panic(const char *message)
151{ 146{
152 switch (audit_failure) 147 switch (audit_failure)
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 818ef9fdab3c..488ba3dea8bb 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -190,9 +190,36 @@ struct audit_entry {
190 190
191extern int audit_pid; 191extern int audit_pid;
192 192
193/* Copy rule from user-space to kernel-space. Called from
194 * audit_add_rule during AUDIT_ADD. */
195static inline int audit_copy_rule(struct audit_rule *d, struct audit_rule *s)
196{
197 int i;
198
199 if (s->action != AUDIT_NEVER
200 && s->action != AUDIT_POSSIBLE
201 && s->action != AUDIT_ALWAYS)
202 return -1;
203 if (s->field_count < 0 || s->field_count > AUDIT_MAX_FIELDS)
204 return -1;
205 if ((s->flags & ~AUDIT_FILTER_PREPEND) >= AUDIT_NR_FILTERS)
206 return -1;
207
208 d->flags = s->flags;
209 d->action = s->action;
210 d->field_count = s->field_count;
211 for (i = 0; i < d->field_count; i++) {
212 d->fields[i] = s->fields[i];
213 d->values[i] = s->values[i];
214 }
215 for (i = 0; i < AUDIT_BITMASK_SIZE; i++) d->mask[i] = s->mask[i];
216 return 0;
217}
218
193/* Check to see if two rules are identical. It is called from 219/* Check to see if two rules are identical. It is called from
220 * audit_add_rule during AUDIT_ADD and
194 * audit_del_rule during AUDIT_DEL. */ 221 * audit_del_rule during AUDIT_DEL. */
195static int audit_compare_rule(struct audit_rule *a, struct audit_rule *b) 222static inline int audit_compare_rule(struct audit_rule *a, struct audit_rule *b)
196{ 223{
197 int i; 224 int i;
198 225
@@ -221,18 +248,37 @@ static int audit_compare_rule(struct audit_rule *a, struct audit_rule *b)
221/* Note that audit_add_rule and audit_del_rule are called via 248/* Note that audit_add_rule and audit_del_rule are called via
222 * audit_receive() in audit.c, and are protected by 249 * audit_receive() in audit.c, and are protected by
223 * audit_netlink_sem. */ 250 * audit_netlink_sem. */
224static inline void audit_add_rule(struct audit_entry *entry, 251static inline int audit_add_rule(struct audit_rule *rule,
225 struct list_head *list) 252 struct list_head *list)
226{ 253{
254 struct audit_entry *entry;
255
256 /* Do not use the _rcu iterator here, since this is the only
257 * addition routine. */
258 list_for_each_entry(entry, list, list) {
259 if (!audit_compare_rule(rule, &entry->rule)) {
260 return -EEXIST;
261 }
262 }
263
264 if (!(entry = kmalloc(sizeof(*entry), GFP_KERNEL)))
265 return -ENOMEM;
266 if (audit_copy_rule(&entry->rule, rule)) {
267 kfree(entry);
268 return -EINVAL;
269 }
270
227 if (entry->rule.flags & AUDIT_FILTER_PREPEND) { 271 if (entry->rule.flags & AUDIT_FILTER_PREPEND) {
228 entry->rule.flags &= ~AUDIT_FILTER_PREPEND; 272 entry->rule.flags &= ~AUDIT_FILTER_PREPEND;
229 list_add_rcu(&entry->list, list); 273 list_add_rcu(&entry->list, list);
230 } else { 274 } else {
231 list_add_tail_rcu(&entry->list, list); 275 list_add_tail_rcu(&entry->list, list);
232 } 276 }
277
278 return 0;
233} 279}
234 280
235static void audit_free_rule(struct rcu_head *head) 281static inline void audit_free_rule(struct rcu_head *head)
236{ 282{
237 struct audit_entry *e = container_of(head, struct audit_entry, rcu); 283 struct audit_entry *e = container_of(head, struct audit_entry, rcu);
238 kfree(e); 284 kfree(e);
@@ -258,32 +304,6 @@ static inline int audit_del_rule(struct audit_rule *rule,
258 return -ENOENT; /* No matching rule */ 304 return -ENOENT; /* No matching rule */
259} 305}
260 306
261/* Copy rule from user-space to kernel-space. Called during
262 * AUDIT_ADD. */
263static int audit_copy_rule(struct audit_rule *d, struct audit_rule *s)
264{
265 int i;
266
267 if (s->action != AUDIT_NEVER
268 && s->action != AUDIT_POSSIBLE
269 && s->action != AUDIT_ALWAYS)
270 return -1;
271 if (s->field_count < 0 || s->field_count > AUDIT_MAX_FIELDS)
272 return -1;
273 if ((s->flags & ~AUDIT_FILTER_PREPEND) >= AUDIT_NR_FILTERS)
274 return -1;
275
276 d->flags = s->flags;
277 d->action = s->action;
278 d->field_count = s->field_count;
279 for (i = 0; i < d->field_count; i++) {
280 d->fields[i] = s->fields[i];
281 d->values[i] = s->values[i];
282 }
283 for (i = 0; i < AUDIT_BITMASK_SIZE; i++) d->mask[i] = s->mask[i];
284 return 0;
285}
286
287static int audit_list_rules(void *_dest) 307static int audit_list_rules(void *_dest)
288{ 308{
289 int pid, seq; 309 int pid, seq;
@@ -313,7 +333,6 @@ static int audit_list_rules(void *_dest)
313int audit_receive_filter(int type, int pid, int uid, int seq, void *data, 333int audit_receive_filter(int type, int pid, int uid, int seq, void *data,
314 uid_t loginuid) 334 uid_t loginuid)
315{ 335{
316 struct audit_entry *entry;
317 struct task_struct *tsk; 336 struct task_struct *tsk;
318 int *dest; 337 int *dest;
319 int err = 0; 338 int err = 0;
@@ -340,16 +359,14 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data,
340 } 359 }
341 break; 360 break;
342 case AUDIT_ADD: 361 case AUDIT_ADD:
343 if (!(entry = kmalloc(sizeof(*entry), GFP_KERNEL))) 362 listnr =((struct audit_rule *)data)->flags & ~AUDIT_FILTER_PREPEND;
344 return -ENOMEM; 363 if (listnr >= AUDIT_NR_FILTERS)
345 if (audit_copy_rule(&entry->rule, data)) {
346 kfree(entry);
347 return -EINVAL; 364 return -EINVAL;
348 } 365
349 listnr = entry->rule.flags & ~AUDIT_FILTER_PREPEND; 366 err = audit_add_rule(data, &audit_filter_list[listnr]);
350 audit_add_rule(entry, &audit_filter_list[listnr]); 367 if (!err)
351 audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, 368 audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
352 "auid=%u added an audit rule\n", loginuid); 369 "auid=%u added an audit rule\n", loginuid);
353 break; 370 break;
354 case AUDIT_DEL: 371 case AUDIT_DEL:
355 listnr =((struct audit_rule *)data)->flags & ~AUDIT_FILTER_PREPEND; 372 listnr =((struct audit_rule *)data)->flags & ~AUDIT_FILTER_PREPEND;