diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/audit.c | 13 | ||||
| -rw-r--r-- | kernel/auditfilter.c | 10 | ||||
| -rw-r--r-- | kernel/auditsc.c | 4 | ||||
| -rw-r--r-- | kernel/exit.c | 6 | ||||
| -rw-r--r-- | kernel/kgdb.c | 94 | ||||
| -rw-r--r-- | kernel/mutex.c | 1 |
6 files changed, 92 insertions, 36 deletions
diff --git a/kernel/audit.c b/kernel/audit.c index e092f1c0ce30..4414e93d8750 100644 --- a/kernel/audit.c +++ b/kernel/audit.c | |||
| @@ -707,12 +707,14 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 707 | if (status_get->mask & AUDIT_STATUS_ENABLED) { | 707 | if (status_get->mask & AUDIT_STATUS_ENABLED) { |
| 708 | err = audit_set_enabled(status_get->enabled, | 708 | err = audit_set_enabled(status_get->enabled, |
| 709 | loginuid, sessionid, sid); | 709 | loginuid, sessionid, sid); |
| 710 | if (err < 0) return err; | 710 | if (err < 0) |
| 711 | return err; | ||
| 711 | } | 712 | } |
| 712 | if (status_get->mask & AUDIT_STATUS_FAILURE) { | 713 | if (status_get->mask & AUDIT_STATUS_FAILURE) { |
| 713 | err = audit_set_failure(status_get->failure, | 714 | err = audit_set_failure(status_get->failure, |
| 714 | loginuid, sessionid, sid); | 715 | loginuid, sessionid, sid); |
| 715 | if (err < 0) return err; | 716 | if (err < 0) |
| 717 | return err; | ||
| 716 | } | 718 | } |
| 717 | if (status_get->mask & AUDIT_STATUS_PID) { | 719 | if (status_get->mask & AUDIT_STATUS_PID) { |
| 718 | int new_pid = status_get->pid; | 720 | int new_pid = status_get->pid; |
| @@ -725,9 +727,12 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 725 | audit_pid = new_pid; | 727 | audit_pid = new_pid; |
| 726 | audit_nlk_pid = NETLINK_CB(skb).pid; | 728 | audit_nlk_pid = NETLINK_CB(skb).pid; |
| 727 | } | 729 | } |
| 728 | if (status_get->mask & AUDIT_STATUS_RATE_LIMIT) | 730 | if (status_get->mask & AUDIT_STATUS_RATE_LIMIT) { |
| 729 | err = audit_set_rate_limit(status_get->rate_limit, | 731 | err = audit_set_rate_limit(status_get->rate_limit, |
| 730 | loginuid, sessionid, sid); | 732 | loginuid, sessionid, sid); |
| 733 | if (err < 0) | ||
| 734 | return err; | ||
| 735 | } | ||
| 731 | if (status_get->mask & AUDIT_STATUS_BACKLOG_LIMIT) | 736 | if (status_get->mask & AUDIT_STATUS_BACKLOG_LIMIT) |
| 732 | err = audit_set_backlog_limit(status_get->backlog_limit, | 737 | err = audit_set_backlog_limit(status_get->backlog_limit, |
| 733 | loginuid, sessionid, sid); | 738 | loginuid, sessionid, sid); |
| @@ -1366,7 +1371,7 @@ int audit_string_contains_control(const char *string, size_t len) | |||
| 1366 | { | 1371 | { |
| 1367 | const unsigned char *p; | 1372 | const unsigned char *p; |
| 1368 | for (p = string; p < (const unsigned char *)string + len && *p; p++) { | 1373 | for (p = string; p < (const unsigned char *)string + len && *p; p++) { |
| 1369 | if (*p == '"' || *p < 0x21 || *p > 0x7f) | 1374 | if (*p == '"' || *p < 0x21 || *p > 0x7e) |
| 1370 | return 1; | 1375 | return 1; |
| 1371 | } | 1376 | } |
| 1372 | return 0; | 1377 | return 0; |
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index 98c50cc671bb..b7d354e2b0ef 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c | |||
| @@ -1022,8 +1022,11 @@ static void audit_update_watch(struct audit_parent *parent, | |||
| 1022 | struct audit_buffer *ab; | 1022 | struct audit_buffer *ab; |
| 1023 | ab = audit_log_start(NULL, GFP_KERNEL, | 1023 | ab = audit_log_start(NULL, GFP_KERNEL, |
| 1024 | AUDIT_CONFIG_CHANGE); | 1024 | AUDIT_CONFIG_CHANGE); |
| 1025 | audit_log_format(ab, "auid=%u ses=%u", | ||
| 1026 | audit_get_loginuid(current), | ||
| 1027 | audit_get_sessionid(current)); | ||
| 1025 | audit_log_format(ab, | 1028 | audit_log_format(ab, |
| 1026 | "op=updated rules specifying path="); | 1029 | " op=updated rules specifying path="); |
| 1027 | audit_log_untrustedstring(ab, owatch->path); | 1030 | audit_log_untrustedstring(ab, owatch->path); |
| 1028 | audit_log_format(ab, " with dev=%u ino=%lu\n", | 1031 | audit_log_format(ab, " with dev=%u ino=%lu\n", |
| 1029 | dev, ino); | 1032 | dev, ino); |
| @@ -1058,7 +1061,10 @@ static void audit_remove_parent_watches(struct audit_parent *parent) | |||
| 1058 | struct audit_buffer *ab; | 1061 | struct audit_buffer *ab; |
| 1059 | ab = audit_log_start(NULL, GFP_KERNEL, | 1062 | ab = audit_log_start(NULL, GFP_KERNEL, |
| 1060 | AUDIT_CONFIG_CHANGE); | 1063 | AUDIT_CONFIG_CHANGE); |
| 1061 | audit_log_format(ab, "op=remove rule path="); | 1064 | audit_log_format(ab, "auid=%u ses=%u", |
| 1065 | audit_get_loginuid(current), | ||
| 1066 | audit_get_sessionid(current)); | ||
| 1067 | audit_log_format(ab, " op=remove rule path="); | ||
| 1062 | audit_log_untrustedstring(ab, w->path); | 1068 | audit_log_untrustedstring(ab, w->path); |
| 1063 | if (r->filterkey) { | 1069 | if (r->filterkey) { |
| 1064 | audit_log_format(ab, " key="); | 1070 | audit_log_format(ab, " key="); |
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 4699950e65bd..496c3dd37276 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
| @@ -610,7 +610,7 @@ static int audit_filter_rules(struct task_struct *tsk, | |||
| 610 | if (!result) | 610 | if (!result) |
| 611 | return 0; | 611 | return 0; |
| 612 | } | 612 | } |
| 613 | if (rule->filterkey) | 613 | if (rule->filterkey && ctx) |
| 614 | ctx->filterkey = kstrdup(rule->filterkey, GFP_ATOMIC); | 614 | ctx->filterkey = kstrdup(rule->filterkey, GFP_ATOMIC); |
| 615 | switch (rule->action) { | 615 | switch (rule->action) { |
| 616 | case AUDIT_NEVER: *state = AUDIT_DISABLED; break; | 616 | case AUDIT_NEVER: *state = AUDIT_DISABLED; break; |
| @@ -2375,7 +2375,7 @@ int __audit_signal_info(int sig, struct task_struct *t) | |||
| 2375 | struct audit_context *ctx = tsk->audit_context; | 2375 | struct audit_context *ctx = tsk->audit_context; |
| 2376 | 2376 | ||
| 2377 | if (audit_pid && t->tgid == audit_pid) { | 2377 | if (audit_pid && t->tgid == audit_pid) { |
| 2378 | if (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1) { | 2378 | if (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1 || sig == SIGUSR2) { |
| 2379 | audit_sig_pid = tsk->pid; | 2379 | audit_sig_pid = tsk->pid; |
| 2380 | if (tsk->loginuid != -1) | 2380 | if (tsk->loginuid != -1) |
| 2381 | audit_sig_uid = tsk->loginuid; | 2381 | audit_sig_uid = tsk->loginuid; |
diff --git a/kernel/exit.c b/kernel/exit.c index eb4d6470d1d0..38ec40630149 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
| @@ -911,10 +911,10 @@ static void exit_notify(struct task_struct *tsk, int group_dead) | |||
| 911 | tsk->exit_signal = SIGCHLD; | 911 | tsk->exit_signal = SIGCHLD; |
| 912 | 912 | ||
| 913 | signal = tracehook_notify_death(tsk, &cookie, group_dead); | 913 | signal = tracehook_notify_death(tsk, &cookie, group_dead); |
| 914 | if (signal > 0) | 914 | if (signal >= 0) |
| 915 | signal = do_notify_parent(tsk, signal); | 915 | signal = do_notify_parent(tsk, signal); |
| 916 | 916 | ||
| 917 | tsk->exit_state = signal < 0 ? EXIT_DEAD : EXIT_ZOMBIE; | 917 | tsk->exit_state = signal == DEATH_REAP ? EXIT_DEAD : EXIT_ZOMBIE; |
| 918 | 918 | ||
| 919 | /* mt-exec, de_thread() is waiting for us */ | 919 | /* mt-exec, de_thread() is waiting for us */ |
| 920 | if (thread_group_leader(tsk) && | 920 | if (thread_group_leader(tsk) && |
| @@ -927,7 +927,7 @@ static void exit_notify(struct task_struct *tsk, int group_dead) | |||
| 927 | tracehook_report_death(tsk, signal, cookie, group_dead); | 927 | tracehook_report_death(tsk, signal, cookie, group_dead); |
| 928 | 928 | ||
| 929 | /* If the process is dead, release it - nobody will wait for it */ | 929 | /* If the process is dead, release it - nobody will wait for it */ |
| 930 | if (signal < 0) | 930 | if (signal == DEATH_REAP) |
| 931 | release_task(tsk); | 931 | release_task(tsk); |
| 932 | } | 932 | } |
| 933 | 933 | ||
diff --git a/kernel/kgdb.c b/kernel/kgdb.c index 3ec23c3ec97f..eaa21fc9ad1d 100644 --- a/kernel/kgdb.c +++ b/kernel/kgdb.c | |||
| @@ -56,12 +56,14 @@ | |||
| 56 | 56 | ||
| 57 | static int kgdb_break_asap; | 57 | static int kgdb_break_asap; |
| 58 | 58 | ||
| 59 | #define KGDB_MAX_THREAD_QUERY 17 | ||
| 59 | struct kgdb_state { | 60 | struct kgdb_state { |
| 60 | int ex_vector; | 61 | int ex_vector; |
| 61 | int signo; | 62 | int signo; |
| 62 | int err_code; | 63 | int err_code; |
| 63 | int cpu; | 64 | int cpu; |
| 64 | int pass_exception; | 65 | int pass_exception; |
| 66 | unsigned long thr_query; | ||
| 65 | unsigned long threadid; | 67 | unsigned long threadid; |
| 66 | long kgdb_usethreadid; | 68 | long kgdb_usethreadid; |
| 67 | struct pt_regs *linux_regs; | 69 | struct pt_regs *linux_regs; |
| @@ -166,13 +168,6 @@ early_param("nokgdbroundup", opt_nokgdbroundup); | |||
| 166 | * Weak aliases for breakpoint management, | 168 | * Weak aliases for breakpoint management, |
| 167 | * can be overriden by architectures when needed: | 169 | * can be overriden by architectures when needed: |
| 168 | */ | 170 | */ |
| 169 | int __weak kgdb_validate_break_address(unsigned long addr) | ||
| 170 | { | ||
| 171 | char tmp_variable[BREAK_INSTR_SIZE]; | ||
| 172 | |||
| 173 | return probe_kernel_read(tmp_variable, (char *)addr, BREAK_INSTR_SIZE); | ||
| 174 | } | ||
| 175 | |||
| 176 | int __weak kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr) | 171 | int __weak kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr) |
| 177 | { | 172 | { |
| 178 | int err; | 173 | int err; |
| @@ -191,6 +186,25 @@ int __weak kgdb_arch_remove_breakpoint(unsigned long addr, char *bundle) | |||
| 191 | (char *)bundle, BREAK_INSTR_SIZE); | 186 | (char *)bundle, BREAK_INSTR_SIZE); |
| 192 | } | 187 | } |
| 193 | 188 | ||
| 189 | int __weak kgdb_validate_break_address(unsigned long addr) | ||
| 190 | { | ||
| 191 | char tmp_variable[BREAK_INSTR_SIZE]; | ||
| 192 | int err; | ||
| 193 | /* Validate setting the breakpoint and then removing it. In the | ||
| 194 | * remove fails, the kernel needs to emit a bad message because we | ||
| 195 | * are deep trouble not being able to put things back the way we | ||
| 196 | * found them. | ||
| 197 | */ | ||
| 198 | err = kgdb_arch_set_breakpoint(addr, tmp_variable); | ||
| 199 | if (err) | ||
| 200 | return err; | ||
| 201 | err = kgdb_arch_remove_breakpoint(addr, tmp_variable); | ||
| 202 | if (err) | ||
| 203 | printk(KERN_ERR "KGDB: Critical breakpoint error, kernel " | ||
| 204 | "memory destroyed at: %lx", addr); | ||
| 205 | return err; | ||
| 206 | } | ||
| 207 | |||
| 194 | unsigned long __weak kgdb_arch_pc(int exception, struct pt_regs *regs) | 208 | unsigned long __weak kgdb_arch_pc(int exception, struct pt_regs *regs) |
| 195 | { | 209 | { |
| 196 | return instruction_pointer(regs); | 210 | return instruction_pointer(regs); |
| @@ -433,9 +447,14 @@ int kgdb_hex2long(char **ptr, unsigned long *long_val) | |||
| 433 | { | 447 | { |
| 434 | int hex_val; | 448 | int hex_val; |
| 435 | int num = 0; | 449 | int num = 0; |
| 450 | int negate = 0; | ||
| 436 | 451 | ||
| 437 | *long_val = 0; | 452 | *long_val = 0; |
| 438 | 453 | ||
| 454 | if (**ptr == '-') { | ||
| 455 | negate = 1; | ||
| 456 | (*ptr)++; | ||
| 457 | } | ||
| 439 | while (**ptr) { | 458 | while (**ptr) { |
| 440 | hex_val = hex(**ptr); | 459 | hex_val = hex(**ptr); |
| 441 | if (hex_val < 0) | 460 | if (hex_val < 0) |
| @@ -446,6 +465,9 @@ int kgdb_hex2long(char **ptr, unsigned long *long_val) | |||
| 446 | (*ptr)++; | 465 | (*ptr)++; |
| 447 | } | 466 | } |
| 448 | 467 | ||
| 468 | if (negate) | ||
| 469 | *long_val = -*long_val; | ||
| 470 | |||
| 449 | return num; | 471 | return num; |
| 450 | } | 472 | } |
| 451 | 473 | ||
| @@ -515,10 +537,16 @@ static void int_to_threadref(unsigned char *id, int value) | |||
| 515 | static struct task_struct *getthread(struct pt_regs *regs, int tid) | 537 | static struct task_struct *getthread(struct pt_regs *regs, int tid) |
| 516 | { | 538 | { |
| 517 | /* | 539 | /* |
| 518 | * Non-positive TIDs are remapped idle tasks: | 540 | * Non-positive TIDs are remapped to the cpu shadow information |
| 519 | */ | 541 | */ |
| 520 | if (tid <= 0) | 542 | if (tid == 0 || tid == -1) |
| 521 | return idle_task(-tid); | 543 | tid = -atomic_read(&kgdb_active) - 2; |
| 544 | if (tid < 0) { | ||
| 545 | if (kgdb_info[-tid - 2].task) | ||
| 546 | return kgdb_info[-tid - 2].task; | ||
| 547 | else | ||
| 548 | return idle_task(-tid - 2); | ||
| 549 | } | ||
| 522 | 550 | ||
| 523 | /* | 551 | /* |
| 524 | * find_task_by_pid_ns() does not take the tasklist lock anymore | 552 | * find_task_by_pid_ns() does not take the tasklist lock anymore |
| @@ -725,14 +753,15 @@ setundefined: | |||
| 725 | } | 753 | } |
| 726 | 754 | ||
| 727 | /* | 755 | /* |
| 728 | * Remap normal tasks to their real PID, idle tasks to -1 ... -NR_CPUs: | 756 | * Remap normal tasks to their real PID, |
| 757 | * CPU shadow threads are mapped to -CPU - 2 | ||
| 729 | */ | 758 | */ |
| 730 | static inline int shadow_pid(int realpid) | 759 | static inline int shadow_pid(int realpid) |
| 731 | { | 760 | { |
| 732 | if (realpid) | 761 | if (realpid) |
| 733 | return realpid; | 762 | return realpid; |
| 734 | 763 | ||
| 735 | return -1-raw_smp_processor_id(); | 764 | return -raw_smp_processor_id() - 2; |
| 736 | } | 765 | } |
| 737 | 766 | ||
| 738 | static char gdbmsgbuf[BUFMAX + 1]; | 767 | static char gdbmsgbuf[BUFMAX + 1]; |
| @@ -826,7 +855,7 @@ static void gdb_cmd_getregs(struct kgdb_state *ks) | |||
| 826 | local_debuggerinfo = kgdb_info[ks->cpu].debuggerinfo; | 855 | local_debuggerinfo = kgdb_info[ks->cpu].debuggerinfo; |
| 827 | } else { | 856 | } else { |
| 828 | local_debuggerinfo = NULL; | 857 | local_debuggerinfo = NULL; |
| 829 | for (i = 0; i < NR_CPUS; i++) { | 858 | for_each_online_cpu(i) { |
| 830 | /* | 859 | /* |
| 831 | * Try to find the task on some other | 860 | * Try to find the task on some other |
| 832 | * or possibly this node if we do not | 861 | * or possibly this node if we do not |
| @@ -960,10 +989,13 @@ static int gdb_cmd_reboot(struct kgdb_state *ks) | |||
| 960 | /* Handle the 'q' query packets */ | 989 | /* Handle the 'q' query packets */ |
| 961 | static void gdb_cmd_query(struct kgdb_state *ks) | 990 | static void gdb_cmd_query(struct kgdb_state *ks) |
| 962 | { | 991 | { |
| 963 | struct task_struct *thread; | 992 | struct task_struct *g; |
| 993 | struct task_struct *p; | ||
| 964 | unsigned char thref[8]; | 994 | unsigned char thref[8]; |
| 965 | char *ptr; | 995 | char *ptr; |
| 966 | int i; | 996 | int i; |
| 997 | int cpu; | ||
| 998 | int finished = 0; | ||
| 967 | 999 | ||
| 968 | switch (remcom_in_buffer[1]) { | 1000 | switch (remcom_in_buffer[1]) { |
| 969 | case 's': | 1001 | case 's': |
| @@ -973,22 +1005,34 @@ static void gdb_cmd_query(struct kgdb_state *ks) | |||
| 973 | break; | 1005 | break; |
| 974 | } | 1006 | } |
| 975 | 1007 | ||
| 976 | if (remcom_in_buffer[1] == 'f') | 1008 | i = 0; |
| 977 | ks->threadid = 1; | ||
| 978 | |||
| 979 | remcom_out_buffer[0] = 'm'; | 1009 | remcom_out_buffer[0] = 'm'; |
| 980 | ptr = remcom_out_buffer + 1; | 1010 | ptr = remcom_out_buffer + 1; |
| 981 | 1011 | if (remcom_in_buffer[1] == 'f') { | |
| 982 | for (i = 0; i < 17; ks->threadid++) { | 1012 | /* Each cpu is a shadow thread */ |
| 983 | thread = getthread(ks->linux_regs, ks->threadid); | 1013 | for_each_online_cpu(cpu) { |
| 984 | if (thread) { | 1014 | ks->thr_query = 0; |
| 985 | int_to_threadref(thref, ks->threadid); | 1015 | int_to_threadref(thref, -cpu - 2); |
| 986 | pack_threadid(ptr, thref); | 1016 | pack_threadid(ptr, thref); |
| 987 | ptr += BUF_THREAD_ID_SIZE; | 1017 | ptr += BUF_THREAD_ID_SIZE; |
| 988 | *(ptr++) = ','; | 1018 | *(ptr++) = ','; |
| 989 | i++; | 1019 | i++; |
| 990 | } | 1020 | } |
| 991 | } | 1021 | } |
| 1022 | |||
| 1023 | do_each_thread(g, p) { | ||
| 1024 | if (i >= ks->thr_query && !finished) { | ||
| 1025 | int_to_threadref(thref, p->pid); | ||
| 1026 | pack_threadid(ptr, thref); | ||
| 1027 | ptr += BUF_THREAD_ID_SIZE; | ||
| 1028 | *(ptr++) = ','; | ||
| 1029 | ks->thr_query++; | ||
| 1030 | if (ks->thr_query % KGDB_MAX_THREAD_QUERY == 0) | ||
| 1031 | finished = 1; | ||
| 1032 | } | ||
| 1033 | i++; | ||
| 1034 | } while_each_thread(g, p); | ||
| 1035 | |||
| 992 | *(--ptr) = '\0'; | 1036 | *(--ptr) = '\0'; |
| 993 | break; | 1037 | break; |
| 994 | 1038 | ||
| @@ -1011,15 +1055,15 @@ static void gdb_cmd_query(struct kgdb_state *ks) | |||
| 1011 | error_packet(remcom_out_buffer, -EINVAL); | 1055 | error_packet(remcom_out_buffer, -EINVAL); |
| 1012 | break; | 1056 | break; |
| 1013 | } | 1057 | } |
| 1014 | if (ks->threadid > 0) { | 1058 | if ((int)ks->threadid > 0) { |
| 1015 | kgdb_mem2hex(getthread(ks->linux_regs, | 1059 | kgdb_mem2hex(getthread(ks->linux_regs, |
| 1016 | ks->threadid)->comm, | 1060 | ks->threadid)->comm, |
| 1017 | remcom_out_buffer, 16); | 1061 | remcom_out_buffer, 16); |
| 1018 | } else { | 1062 | } else { |
| 1019 | static char tmpstr[23 + BUF_THREAD_ID_SIZE]; | 1063 | static char tmpstr[23 + BUF_THREAD_ID_SIZE]; |
| 1020 | 1064 | ||
| 1021 | sprintf(tmpstr, "Shadow task %d for pid 0", | 1065 | sprintf(tmpstr, "shadowCPU%d", |
| 1022 | (int)(-ks->threadid-1)); | 1066 | (int)(-ks->threadid - 2)); |
| 1023 | kgdb_mem2hex(tmpstr, remcom_out_buffer, strlen(tmpstr)); | 1067 | kgdb_mem2hex(tmpstr, remcom_out_buffer, strlen(tmpstr)); |
| 1024 | } | 1068 | } |
| 1025 | break; | 1069 | break; |
diff --git a/kernel/mutex.c b/kernel/mutex.c index bcdc9ac8ef60..12c779dc65d4 100644 --- a/kernel/mutex.c +++ b/kernel/mutex.c | |||
| @@ -34,6 +34,7 @@ | |||
| 34 | /*** | 34 | /*** |
| 35 | * mutex_init - initialize the mutex | 35 | * mutex_init - initialize the mutex |
| 36 | * @lock: the mutex to be initialized | 36 | * @lock: the mutex to be initialized |
| 37 | * @key: the lock_class_key for the class; used by mutex lock debugging | ||
| 37 | * | 38 | * |
| 38 | * Initialize the mutex to unlocked state. | 39 | * Initialize the mutex to unlocked state. |
| 39 | * | 40 | * |
