aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/auditsc.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/auditsc.c')
-rw-r--r--kernel/auditsc.c95
1 files changed, 56 insertions, 39 deletions
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;