diff options
author | Eric Paris <eparis@redhat.com> | 2013-04-16 17:26:51 -0400 |
---|---|---|
committer | Eric Paris <eparis@redhat.com> | 2013-04-30 15:31:28 -0400 |
commit | ab61d38ed8cf670946d12dc46b9198b521c790ea (patch) | |
tree | 742d96692c63be9f9811fcf624f65811f8f6e96c /kernel | |
parent | 62062cf8a3a99a933efdac549da380f230dbe982 (diff) |
audit: make validity checking generic
We have 2 interfaces to send audit rules. Rather than check validity of
things in 2 places make a helper function.
Signed-off-by: Eric Paris <eparis@redhat.com>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/auditfilter.c | 146 |
1 files changed, 70 insertions, 76 deletions
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index 9e666004e0dc..ff6e09d89278 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c | |||
@@ -310,7 +310,7 @@ static u32 audit_to_op(u32 op) | |||
310 | return n; | 310 | return n; |
311 | } | 311 | } |
312 | 312 | ||
313 | /* check if a field is valid for a given list */ | 313 | /* check if an audit field is valid */ |
314 | static int audit_field_valid(struct audit_entry *entry, struct audit_field *f) | 314 | static int audit_field_valid(struct audit_entry *entry, struct audit_field *f) |
315 | { | 315 | { |
316 | switch(f->type) { | 316 | switch(f->type) { |
@@ -320,6 +320,69 @@ static int audit_field_valid(struct audit_entry *entry, struct audit_field *f) | |||
320 | return -EINVAL; | 320 | return -EINVAL; |
321 | break; | 321 | break; |
322 | }; | 322 | }; |
323 | |||
324 | switch(f->type) { | ||
325 | default: | ||
326 | return -EINVAL; | ||
327 | case AUDIT_UID: | ||
328 | case AUDIT_EUID: | ||
329 | case AUDIT_SUID: | ||
330 | case AUDIT_FSUID: | ||
331 | case AUDIT_LOGINUID: | ||
332 | case AUDIT_OBJ_UID: | ||
333 | case AUDIT_GID: | ||
334 | case AUDIT_EGID: | ||
335 | case AUDIT_SGID: | ||
336 | case AUDIT_FSGID: | ||
337 | case AUDIT_OBJ_GID: | ||
338 | case AUDIT_PID: | ||
339 | case AUDIT_PERS: | ||
340 | case AUDIT_MSGTYPE: | ||
341 | case AUDIT_PPID: | ||
342 | case AUDIT_DEVMAJOR: | ||
343 | case AUDIT_DEVMINOR: | ||
344 | case AUDIT_EXIT: | ||
345 | case AUDIT_SUCCESS: | ||
346 | /* bit ops are only useful on syscall args */ | ||
347 | if (f->op == Audit_bitmask || f->op == Audit_bittest) | ||
348 | return -EINVAL; | ||
349 | break; | ||
350 | case AUDIT_ARG0: | ||
351 | case AUDIT_ARG1: | ||
352 | case AUDIT_ARG2: | ||
353 | case AUDIT_ARG3: | ||
354 | case AUDIT_SUBJ_USER: | ||
355 | case AUDIT_SUBJ_ROLE: | ||
356 | case AUDIT_SUBJ_TYPE: | ||
357 | case AUDIT_SUBJ_SEN: | ||
358 | case AUDIT_SUBJ_CLR: | ||
359 | case AUDIT_OBJ_USER: | ||
360 | case AUDIT_OBJ_ROLE: | ||
361 | case AUDIT_OBJ_TYPE: | ||
362 | case AUDIT_OBJ_LEV_LOW: | ||
363 | case AUDIT_OBJ_LEV_HIGH: | ||
364 | case AUDIT_WATCH: | ||
365 | case AUDIT_DIR: | ||
366 | case AUDIT_FILTERKEY: | ||
367 | break; | ||
368 | /* arch is only allowed to be = or != */ | ||
369 | case AUDIT_ARCH: | ||
370 | if (f->op != Audit_not_equal && f->op != Audit_equal) | ||
371 | return -EINVAL; | ||
372 | break; | ||
373 | case AUDIT_PERM: | ||
374 | if (f->val & ~15) | ||
375 | return -EINVAL; | ||
376 | break; | ||
377 | case AUDIT_FILETYPE: | ||
378 | if (f->val & ~S_IFMT) | ||
379 | return -EINVAL; | ||
380 | break; | ||
381 | case AUDIT_FIELD_COMPARE: | ||
382 | if (f->val > AUDIT_MAX_FIELD_COMPARE) | ||
383 | return -EINVAL; | ||
384 | break; | ||
385 | }; | ||
323 | return 0; | 386 | return 0; |
324 | } | 387 | } |
325 | 388 | ||
@@ -361,18 +424,17 @@ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule) | |||
361 | if (f->op == Audit_bad) | 424 | if (f->op == Audit_bad) |
362 | goto exit_free; | 425 | goto exit_free; |
363 | 426 | ||
364 | switch(f->type) { | 427 | err = audit_field_valid(entry, f); |
365 | default: | 428 | if (err) |
366 | goto exit_free; | 429 | goto exit_free; |
430 | |||
431 | err = -EINVAL; | ||
432 | switch (f->type) { | ||
367 | case AUDIT_UID: | 433 | case AUDIT_UID: |
368 | case AUDIT_EUID: | 434 | case AUDIT_EUID: |
369 | case AUDIT_SUID: | 435 | case AUDIT_SUID: |
370 | case AUDIT_FSUID: | 436 | case AUDIT_FSUID: |
371 | case AUDIT_LOGINUID: | 437 | case AUDIT_LOGINUID: |
372 | /* bit ops not implemented for uid comparisons */ | ||
373 | if (f->op == Audit_bitmask || f->op == Audit_bittest) | ||
374 | goto exit_free; | ||
375 | |||
376 | f->uid = make_kuid(current_user_ns(), f->val); | 438 | f->uid = make_kuid(current_user_ns(), f->val); |
377 | if (!uid_valid(f->uid)) | 439 | if (!uid_valid(f->uid)) |
378 | goto exit_free; | 440 | goto exit_free; |
@@ -381,45 +443,13 @@ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule) | |||
381 | case AUDIT_EGID: | 443 | case AUDIT_EGID: |
382 | case AUDIT_SGID: | 444 | case AUDIT_SGID: |
383 | case AUDIT_FSGID: | 445 | case AUDIT_FSGID: |
384 | /* bit ops not implemented for gid comparisons */ | ||
385 | if (f->op == Audit_bitmask || f->op == Audit_bittest) | ||
386 | goto exit_free; | ||
387 | |||
388 | f->gid = make_kgid(current_user_ns(), f->val); | 446 | f->gid = make_kgid(current_user_ns(), f->val); |
389 | if (!gid_valid(f->gid)) | 447 | if (!gid_valid(f->gid)) |
390 | goto exit_free; | 448 | goto exit_free; |
391 | break; | 449 | break; |
392 | case AUDIT_PID: | ||
393 | case AUDIT_PERS: | ||
394 | case AUDIT_MSGTYPE: | ||
395 | case AUDIT_PPID: | ||
396 | case AUDIT_DEVMAJOR: | ||
397 | case AUDIT_DEVMINOR: | ||
398 | case AUDIT_EXIT: | ||
399 | case AUDIT_SUCCESS: | ||
400 | /* bit ops are only useful on syscall args */ | ||
401 | if (f->op == Audit_bitmask || f->op == Audit_bittest) | ||
402 | goto exit_free; | ||
403 | break; | ||
404 | case AUDIT_ARG0: | ||
405 | case AUDIT_ARG1: | ||
406 | case AUDIT_ARG2: | ||
407 | case AUDIT_ARG3: | ||
408 | break; | ||
409 | /* arch is only allowed to be = or != */ | ||
410 | case AUDIT_ARCH: | 450 | case AUDIT_ARCH: |
411 | if (f->op != Audit_not_equal && f->op != Audit_equal) | ||
412 | goto exit_free; | ||
413 | entry->rule.arch_f = f; | 451 | entry->rule.arch_f = f; |
414 | break; | 452 | break; |
415 | case AUDIT_PERM: | ||
416 | if (f->val & ~15) | ||
417 | goto exit_free; | ||
418 | break; | ||
419 | case AUDIT_FILETYPE: | ||
420 | if (f->val & ~S_IFMT) | ||
421 | goto exit_free; | ||
422 | break; | ||
423 | case AUDIT_INODE: | 453 | case AUDIT_INODE: |
424 | err = audit_to_inode(&entry->rule, f); | 454 | err = audit_to_inode(&entry->rule, f); |
425 | if (err) | 455 | if (err) |
@@ -477,18 +507,13 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, | |||
477 | goto exit_free; | 507 | goto exit_free; |
478 | 508 | ||
479 | err = -EINVAL; | 509 | err = -EINVAL; |
480 | 510 | switch (f->type) { | |
481 | switch(f->type) { | ||
482 | case AUDIT_UID: | 511 | case AUDIT_UID: |
483 | case AUDIT_EUID: | 512 | case AUDIT_EUID: |
484 | case AUDIT_SUID: | 513 | case AUDIT_SUID: |
485 | case AUDIT_FSUID: | 514 | case AUDIT_FSUID: |
486 | case AUDIT_LOGINUID: | 515 | case AUDIT_LOGINUID: |
487 | case AUDIT_OBJ_UID: | 516 | case AUDIT_OBJ_UID: |
488 | /* bit ops not implemented for uid comparisons */ | ||
489 | if (f->op == Audit_bitmask || f->op == Audit_bittest) | ||
490 | goto exit_free; | ||
491 | |||
492 | f->uid = make_kuid(current_user_ns(), f->val); | 517 | f->uid = make_kuid(current_user_ns(), f->val); |
493 | if (!uid_valid(f->uid)) | 518 | if (!uid_valid(f->uid)) |
494 | goto exit_free; | 519 | goto exit_free; |
@@ -498,27 +523,10 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, | |||
498 | case AUDIT_SGID: | 523 | case AUDIT_SGID: |
499 | case AUDIT_FSGID: | 524 | case AUDIT_FSGID: |
500 | case AUDIT_OBJ_GID: | 525 | case AUDIT_OBJ_GID: |
501 | /* bit ops not implemented for gid comparisons */ | ||
502 | if (f->op == Audit_bitmask || f->op == Audit_bittest) | ||
503 | goto exit_free; | ||
504 | |||
505 | f->gid = make_kgid(current_user_ns(), f->val); | 526 | f->gid = make_kgid(current_user_ns(), f->val); |
506 | if (!gid_valid(f->gid)) | 527 | if (!gid_valid(f->gid)) |
507 | goto exit_free; | 528 | goto exit_free; |
508 | break; | 529 | break; |
509 | case AUDIT_PID: | ||
510 | case AUDIT_PERS: | ||
511 | case AUDIT_MSGTYPE: | ||
512 | case AUDIT_PPID: | ||
513 | case AUDIT_DEVMAJOR: | ||
514 | case AUDIT_DEVMINOR: | ||
515 | case AUDIT_EXIT: | ||
516 | case AUDIT_SUCCESS: | ||
517 | case AUDIT_ARG0: | ||
518 | case AUDIT_ARG1: | ||
519 | case AUDIT_ARG2: | ||
520 | case AUDIT_ARG3: | ||
521 | break; | ||
522 | case AUDIT_ARCH: | 530 | case AUDIT_ARCH: |
523 | entry->rule.arch_f = f; | 531 | entry->rule.arch_f = f; |
524 | break; | 532 | break; |
@@ -589,20 +597,6 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, | |||
589 | entry->rule.buflen += f->val; | 597 | entry->rule.buflen += f->val; |
590 | entry->rule.filterkey = str; | 598 | entry->rule.filterkey = str; |
591 | break; | 599 | break; |
592 | case AUDIT_PERM: | ||
593 | if (f->val & ~15) | ||
594 | goto exit_free; | ||
595 | break; | ||
596 | case AUDIT_FILETYPE: | ||
597 | if (f->val & ~S_IFMT) | ||
598 | goto exit_free; | ||
599 | break; | ||
600 | case AUDIT_FIELD_COMPARE: | ||
601 | if (f->val > AUDIT_MAX_FIELD_COMPARE) | ||
602 | goto exit_free; | ||
603 | break; | ||
604 | default: | ||
605 | goto exit_free; | ||
606 | } | 600 | } |
607 | } | 601 | } |
608 | 602 | ||