diff options
| author | Jan Engelmohr <jan.engelmohr@mailbox.tu-dresden.de> | 2016-09-04 16:45:09 +0200 |
|---|---|---|
| committer | Moyster <oysterized@gmail.com> | 2016-09-10 00:45:11 +0200 |
| commit | 0a1e8e11acd3cc36b1d65023ce1cb1a06a887b11 (patch) | |
| tree | bd92a01ee850567d86074cca3fb6c928c960fe39 /kernel | |
| parent | ade0200dcde3ad70876875392b6bc156155b9b75 (diff) | |
3.10.102-> 3.10.103
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/module.c | 13 | ||||
| -rw-r--r-- | kernel/panic.c | 3 | ||||
| -rw-r--r-- | kernel/printk.c | 35 | ||||
| -rw-r--r-- | kernel/signal.c | 14 | ||||
| -rw-r--r-- | kernel/sysctl.c | 14 | ||||
| -rw-r--r-- | kernel/trace/trace_printk.c | 7 |
6 files changed, 71 insertions, 15 deletions
diff --git a/kernel/module.c b/kernel/module.c index d50d899b0..36df6184e 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -2475,13 +2475,18 @@ static inline void kmemleak_load_module(const struct module *mod, #endif #ifdef CONFIG_MODULE_SIG -static int module_sig_check(struct load_info *info) +static int module_sig_check(struct load_info *info, int flags) { int err = -ENOKEY; const unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1; const void *mod = info->hdr; - if (info->len > markerlen && + /* + * Require flags == 0, as a module with version information + * removed is no longer the module that was signed + */ + if (flags == 0 && + info->len > markerlen && memcmp(mod + info->len - markerlen, MODULE_SIG_STRING, markerlen) == 0) { /* We truncate the module to discard the signature */ info->len -= markerlen; @@ -2503,7 +2508,7 @@ static int module_sig_check(struct load_info *info) return err; } #else /* !CONFIG_MODULE_SIG */ -static int module_sig_check(struct load_info *info) +static int module_sig_check(struct load_info *info, int flags) { return 0; } @@ -3228,7 +3233,7 @@ static int load_module(struct load_info *info, const char __user *uargs, struct module *mod; long err; - err = module_sig_check(info); + err = module_sig_check(info, flags); if (err) goto free_copy; diff --git a/kernel/panic.c b/kernel/panic.c index 1050697a7..55f2f3129 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -22,6 +22,7 @@ #include <linux/sysrq.h> #include <linux/init.h> #include <linux/nmi.h> +#include <linux/console.h> #define PANIC_TIMER_STEP 100 #define PANIC_BLINK_SPD 18 @@ -134,6 +135,8 @@ void panic(const char *fmt, ...) bust_spinlocks(0); + console_flush_on_panic(); + if (!panic_blink) panic_blink = no_blink; diff --git a/kernel/printk.c b/kernel/printk.c index b30c61814..95cfcfd30 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -2161,7 +2161,7 @@ void console_unlock(void) static u64 seen_seq; unsigned long flags; bool wake_klogd = false; - bool retry; + bool do_cond_resched, retry; #ifdef LOG_TOO_MUCH_WARNING unsigned long total_log_size = 0; unsigned long long t1 = 0, t2 = 0; @@ -2174,6 +2174,18 @@ void console_unlock(void) return; } + /* + * Console drivers are called under logbuf_lock, so + * @console_may_schedule should be cleared before; however, we may + * end up dumping a lot of lines, for example, if called from + * console registration path, and should invoke cond_resched() + * between lines if allowable. Not doing so can cause a very long + * scheduling stall on a slow console leading to RCU stall and + * softlockup warnings which exacerbate the issue with more + * messages practically incapacitating the system. + */ + do_cond_resched = console_may_schedule; + console_may_schedule = 0; /* flush buffered message fragment immediately to console */ @@ -2269,6 +2281,8 @@ skip: call_console_drivers(level, text, len); #endif local_irq_restore(flags); + if (do_cond_resched) + cond_resched(); } console_locked = 0; mutex_release(&console_lock_dep_map, 1, _RET_IP_); @@ -2337,6 +2351,25 @@ void console_unblank(void) console_unlock(); } +/** + * console_flush_on_panic - flush console content on panic + * + * Immediately output all pending messages no matter what. + */ +void console_flush_on_panic(void) +{ + /* + * If someone else is holding the console lock, trylock will fail + * and may_schedule may be set. Ignore and proceed to unlock so + * that messages are flushed out. As this can be called from any + * context and we don't want to get preempted while flushing, + * ensure may_schedule is cleared. + */ + console_trylock(); + console_may_schedule = 0; + console_unlock(); +} + /* * Return the console tty driver structure and its associated index */ diff --git a/kernel/signal.c b/kernel/signal.c index 0991539b3..28db04b54 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -3013,11 +3013,9 @@ static int do_rt_sigqueueinfo(pid_t pid, int sig, siginfo_t *info) * Nor can they impersonate a kill()/tgkill(), which adds source info. */ if ((info->si_code >= 0 || info->si_code == SI_TKILL) && - (task_pid_vnr(current) != pid)) { - /* We used to allow any < 0 si_code */ - WARN_ON_ONCE(info->si_code < 0); + (task_pid_vnr(current) != pid)) return -EPERM; - } + info->si_signo = sig; /* POSIX.1b doesn't mention process groups. */ @@ -3062,12 +3060,10 @@ static int do_rt_tgsigqueueinfo(pid_t tgid, pid_t pid, int sig, siginfo_t *info) /* Not even root can pretend to send signals from the kernel. * Nor can they impersonate a kill()/tgkill(), which adds source info. */ - if (((info->si_code >= 0 || info->si_code == SI_TKILL)) && - (task_pid_vnr(current) != pid)) { - /* We used to allow any < 0 si_code */ - WARN_ON_ONCE(info->si_code < 0); + if ((info->si_code >= 0 || info->si_code == SI_TKILL) && + (task_pid_vnr(current) != pid)) return -EPERM; - } + info->si_signo = sig; return do_send_specific(tgid, pid, sig, info); diff --git a/kernel/sysctl.c b/kernel/sysctl.c index e5fefe968..781dce655 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -1683,6 +1683,20 @@ static struct ctl_table fs_table[] = { .proc_handler = &pipe_proc_fn, .extra1 = &pipe_min_size, }, + { + .procname = "pipe-user-pages-hard", + .data = &pipe_user_pages_hard, + .maxlen = sizeof(pipe_user_pages_hard), + .mode = 0644, + .proc_handler = proc_doulongvec_minmax, + }, + { + .procname = "pipe-user-pages-soft", + .data = &pipe_user_pages_soft, + .maxlen = sizeof(pipe_user_pages_soft), + .mode = 0644, + .proc_handler = proc_doulongvec_minmax, + }, { } }; diff --git a/kernel/trace/trace_printk.c b/kernel/trace/trace_printk.c index 14ffaa59a..9008103db 100644 --- a/kernel/trace/trace_printk.c +++ b/kernel/trace/trace_printk.c @@ -38,6 +38,10 @@ struct trace_bprintk_fmt { static inline struct trace_bprintk_fmt *lookup_format(const char *fmt) { struct trace_bprintk_fmt *pos; + + if (!fmt) + return ERR_PTR(-EINVAL); + list_for_each_entry(pos, &trace_bprintk_fmt_list, list) { if (!strcmp(pos->fmt, fmt)) return pos; @@ -59,7 +63,8 @@ void hold_module_trace_bprintk_format(const char **start, const char **end) for (iter = start; iter < end; iter++) { struct trace_bprintk_fmt *tb_fmt = lookup_format(*iter); if (tb_fmt) { - *iter = tb_fmt->fmt; + if (!IS_ERR(tb_fmt)) + *iter = tb_fmt->fmt; continue; } |
