diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/audit.h | 5 | ||||
| -rw-r--r-- | kernel/audit_tree.c | 3 | ||||
| -rw-r--r-- | kernel/auditfilter.c | 325 | ||||
| -rw-r--r-- | kernel/auditsc.c | 739 | ||||
| -rw-r--r-- | kernel/capability.c | 4 | ||||
| -rw-r--r-- | kernel/cgroup.c | 7 | ||||
| -rw-r--r-- | kernel/cpu.c | 6 | ||||
| -rw-r--r-- | kernel/futex.c | 72 | ||||
| -rw-r--r-- | kernel/module.c | 59 | ||||
| -rw-r--r-- | kernel/stop_machine.c | 55 |
10 files changed, 596 insertions, 679 deletions
diff --git a/kernel/audit.h b/kernel/audit.h index 9d6717412fe..16f18cac661 100644 --- a/kernel/audit.h +++ b/kernel/audit.h | |||
| @@ -159,11 +159,8 @@ static inline int audit_signal_info(int sig, struct task_struct *t) | |||
| 159 | return __audit_signal_info(sig, t); | 159 | return __audit_signal_info(sig, t); |
| 160 | return 0; | 160 | return 0; |
| 161 | } | 161 | } |
| 162 | extern enum audit_state audit_filter_inodes(struct task_struct *, | 162 | extern void audit_filter_inodes(struct task_struct *, struct audit_context *); |
| 163 | struct audit_context *); | ||
| 164 | extern void audit_set_auditable(struct audit_context *); | ||
| 165 | #else | 163 | #else |
| 166 | #define audit_signal_info(s,t) AUDIT_DISABLED | 164 | #define audit_signal_info(s,t) AUDIT_DISABLED |
| 167 | #define audit_filter_inodes(t,c) AUDIT_DISABLED | 165 | #define audit_filter_inodes(t,c) AUDIT_DISABLED |
| 168 | #define audit_set_auditable(c) | ||
| 169 | #endif | 166 | #endif |
diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c index 8b509441f49..8ad9545b8db 100644 --- a/kernel/audit_tree.c +++ b/kernel/audit_tree.c | |||
| @@ -450,6 +450,7 @@ static void kill_rules(struct audit_tree *tree) | |||
| 450 | audit_log_end(ab); | 450 | audit_log_end(ab); |
| 451 | rule->tree = NULL; | 451 | rule->tree = NULL; |
| 452 | list_del_rcu(&entry->list); | 452 | list_del_rcu(&entry->list); |
| 453 | list_del(&entry->rule.list); | ||
| 453 | call_rcu(&entry->rcu, audit_free_rule_rcu); | 454 | call_rcu(&entry->rcu, audit_free_rule_rcu); |
| 454 | } | 455 | } |
| 455 | } | 456 | } |
| @@ -617,7 +618,7 @@ int audit_make_tree(struct audit_krule *rule, char *pathname, u32 op) | |||
| 617 | 618 | ||
| 618 | if (pathname[0] != '/' || | 619 | if (pathname[0] != '/' || |
| 619 | rule->listnr != AUDIT_FILTER_EXIT || | 620 | rule->listnr != AUDIT_FILTER_EXIT || |
| 620 | op & ~AUDIT_EQUAL || | 621 | op != Audit_equal || |
| 621 | rule->inode_f || rule->watch || rule->tree) | 622 | rule->inode_f || rule->watch || rule->tree) |
| 622 | return -EINVAL; | 623 | return -EINVAL; |
| 623 | rule->tree = alloc_tree(pathname); | 624 | rule->tree = alloc_tree(pathname); |
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index 9fd85a4640a..fbf24d121d9 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c | |||
| @@ -86,6 +86,14 @@ struct list_head audit_filter_list[AUDIT_NR_FILTERS] = { | |||
| 86 | #error Fix audit_filter_list initialiser | 86 | #error Fix audit_filter_list initialiser |
| 87 | #endif | 87 | #endif |
| 88 | }; | 88 | }; |
| 89 | static struct list_head audit_rules_list[AUDIT_NR_FILTERS] = { | ||
| 90 | LIST_HEAD_INIT(audit_rules_list[0]), | ||
| 91 | LIST_HEAD_INIT(audit_rules_list[1]), | ||
| 92 | LIST_HEAD_INIT(audit_rules_list[2]), | ||
| 93 | LIST_HEAD_INIT(audit_rules_list[3]), | ||
| 94 | LIST_HEAD_INIT(audit_rules_list[4]), | ||
| 95 | LIST_HEAD_INIT(audit_rules_list[5]), | ||
| 96 | }; | ||
| 89 | 97 | ||
| 90 | DEFINE_MUTEX(audit_filter_mutex); | 98 | DEFINE_MUTEX(audit_filter_mutex); |
| 91 | 99 | ||
| @@ -244,7 +252,8 @@ static inline int audit_to_inode(struct audit_krule *krule, | |||
| 244 | struct audit_field *f) | 252 | struct audit_field *f) |
| 245 | { | 253 | { |
| 246 | if (krule->listnr != AUDIT_FILTER_EXIT || | 254 | if (krule->listnr != AUDIT_FILTER_EXIT || |
| 247 | krule->watch || krule->inode_f || krule->tree) | 255 | krule->watch || krule->inode_f || krule->tree || |
| 256 | (f->op != Audit_equal && f->op != Audit_not_equal)) | ||
| 248 | return -EINVAL; | 257 | return -EINVAL; |
| 249 | 258 | ||
| 250 | krule->inode_f = f; | 259 | krule->inode_f = f; |
| @@ -262,7 +271,7 @@ static int audit_to_watch(struct audit_krule *krule, char *path, int len, | |||
| 262 | 271 | ||
| 263 | if (path[0] != '/' || path[len-1] == '/' || | 272 | if (path[0] != '/' || path[len-1] == '/' || |
| 264 | krule->listnr != AUDIT_FILTER_EXIT || | 273 | krule->listnr != AUDIT_FILTER_EXIT || |
| 265 | op & ~AUDIT_EQUAL || | 274 | op != Audit_equal || |
| 266 | krule->inode_f || krule->watch || krule->tree) | 275 | krule->inode_f || krule->watch || krule->tree) |
| 267 | return -EINVAL; | 276 | return -EINVAL; |
| 268 | 277 | ||
| @@ -412,12 +421,32 @@ exit_err: | |||
| 412 | return ERR_PTR(err); | 421 | return ERR_PTR(err); |
| 413 | } | 422 | } |
| 414 | 423 | ||
| 424 | static u32 audit_ops[] = | ||
| 425 | { | ||
| 426 | [Audit_equal] = AUDIT_EQUAL, | ||
| 427 | [Audit_not_equal] = AUDIT_NOT_EQUAL, | ||
| 428 | [Audit_bitmask] = AUDIT_BIT_MASK, | ||
| 429 | [Audit_bittest] = AUDIT_BIT_TEST, | ||
| 430 | [Audit_lt] = AUDIT_LESS_THAN, | ||
| 431 | [Audit_gt] = AUDIT_GREATER_THAN, | ||
| 432 | [Audit_le] = AUDIT_LESS_THAN_OR_EQUAL, | ||
| 433 | [Audit_ge] = AUDIT_GREATER_THAN_OR_EQUAL, | ||
| 434 | }; | ||
| 435 | |||
| 436 | static u32 audit_to_op(u32 op) | ||
| 437 | { | ||
| 438 | u32 n; | ||
| 439 | for (n = Audit_equal; n < Audit_bad && audit_ops[n] != op; n++) | ||
| 440 | ; | ||
| 441 | return n; | ||
| 442 | } | ||
| 443 | |||
| 444 | |||
| 415 | /* Translate struct audit_rule to kernel's rule respresentation. | 445 | /* Translate struct audit_rule to kernel's rule respresentation. |
| 416 | * Exists for backward compatibility with userspace. */ | 446 | * Exists for backward compatibility with userspace. */ |
| 417 | static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule) | 447 | static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule) |
| 418 | { | 448 | { |
| 419 | struct audit_entry *entry; | 449 | struct audit_entry *entry; |
| 420 | struct audit_field *ino_f; | ||
| 421 | int err = 0; | 450 | int err = 0; |
| 422 | int i; | 451 | int i; |
| 423 | 452 | ||
| @@ -427,12 +456,28 @@ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule) | |||
| 427 | 456 | ||
| 428 | for (i = 0; i < rule->field_count; i++) { | 457 | for (i = 0; i < rule->field_count; i++) { |
| 429 | struct audit_field *f = &entry->rule.fields[i]; | 458 | struct audit_field *f = &entry->rule.fields[i]; |
| 459 | u32 n; | ||
| 460 | |||
| 461 | n = rule->fields[i] & (AUDIT_NEGATE|AUDIT_OPERATORS); | ||
| 462 | |||
| 463 | /* Support for legacy operators where | ||
| 464 | * AUDIT_NEGATE bit signifies != and otherwise assumes == */ | ||
| 465 | if (n & AUDIT_NEGATE) | ||
| 466 | f->op = Audit_not_equal; | ||
| 467 | else if (!n) | ||
| 468 | f->op = Audit_equal; | ||
| 469 | else | ||
| 470 | f->op = audit_to_op(n); | ||
| 471 | |||
| 472 | entry->rule.vers_ops = (n & AUDIT_OPERATORS) ? 2 : 1; | ||
| 430 | 473 | ||
| 431 | f->op = rule->fields[i] & (AUDIT_NEGATE|AUDIT_OPERATORS); | ||
| 432 | f->type = rule->fields[i] & ~(AUDIT_NEGATE|AUDIT_OPERATORS); | 474 | f->type = rule->fields[i] & ~(AUDIT_NEGATE|AUDIT_OPERATORS); |
| 433 | f->val = rule->values[i]; | 475 | f->val = rule->values[i]; |
| 434 | 476 | ||
| 435 | err = -EINVAL; | 477 | err = -EINVAL; |
| 478 | if (f->op == Audit_bad) | ||
| 479 | goto exit_free; | ||
| 480 | |||
| 436 | switch(f->type) { | 481 | switch(f->type) { |
| 437 | default: | 482 | default: |
| 438 | goto exit_free; | 483 | goto exit_free; |
| @@ -454,11 +499,8 @@ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule) | |||
| 454 | case AUDIT_EXIT: | 499 | case AUDIT_EXIT: |
| 455 | case AUDIT_SUCCESS: | 500 | case AUDIT_SUCCESS: |
| 456 | /* bit ops are only useful on syscall args */ | 501 | /* bit ops are only useful on syscall args */ |
| 457 | if (f->op == AUDIT_BIT_MASK || | 502 | if (f->op == Audit_bitmask || f->op == Audit_bittest) |
| 458 | f->op == AUDIT_BIT_TEST) { | ||
| 459 | err = -EINVAL; | ||
| 460 | goto exit_free; | 503 | goto exit_free; |
| 461 | } | ||
| 462 | break; | 504 | break; |
| 463 | case AUDIT_ARG0: | 505 | case AUDIT_ARG0: |
| 464 | case AUDIT_ARG1: | 506 | case AUDIT_ARG1: |
| @@ -467,11 +509,8 @@ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule) | |||
| 467 | break; | 509 | break; |
| 468 | /* arch is only allowed to be = or != */ | 510 | /* arch is only allowed to be = or != */ |
| 469 | case AUDIT_ARCH: | 511 | case AUDIT_ARCH: |
| 470 | if ((f->op != AUDIT_NOT_EQUAL) && (f->op != AUDIT_EQUAL) | 512 | if (f->op != Audit_not_equal && f->op != Audit_equal) |
| 471 | && (f->op != AUDIT_NEGATE) && (f->op)) { | ||
| 472 | err = -EINVAL; | ||
| 473 | goto exit_free; | 513 | goto exit_free; |
| 474 | } | ||
| 475 | entry->rule.arch_f = f; | 514 | entry->rule.arch_f = f; |
| 476 | break; | 515 | break; |
| 477 | case AUDIT_PERM: | 516 | case AUDIT_PERM: |
| @@ -488,33 +527,10 @@ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule) | |||
| 488 | goto exit_free; | 527 | goto exit_free; |
| 489 | break; | 528 | break; |
| 490 | } | 529 | } |
| 491 | |||
| 492 | entry->rule.vers_ops = (f->op & AUDIT_OPERATORS) ? 2 : 1; | ||
| 493 | |||
| 494 | /* Support for legacy operators where | ||
