Merge branch 'akpm' (patches from Andrew)
Merge more updates from Andrew Morton: - the rest of MM - procfs updates - various misc things - more y2038 fixes - get_maintainer updates - lib/ updates - checkpatch updates - various epoll updates - autofs updates - hfsplus - some reiserfs work - fatfs updates - signal.c cleanups - ipc/ updates * emailed patches from Andrew Morton <akpm@linux-foundation.org>: (166 commits) ipc/util.c: update return value of ipc_getref from int to bool ipc/util.c: further variable name cleanups ipc: simplify ipc initialization ipc: get rid of ids->tables_initialized hack lib/rhashtable: guarantee initial hashtable allocation lib/rhashtable: simplify bucket_table_alloc() ipc: drop ipc_lock() ipc/util.c: correct comment in ipc_obtain_object_check ipc: rename ipcctl_pre_down_nolock() ipc/util.c: use ipc_rcu_putref() for failues in ipc_addid() ipc: reorganize initialization of kern_ipc_perm.seq ipc: compute kern_ipc_perm.id under the ipc lock init/Kconfig: remove EXPERT from CHECKPOINT_RESTORE fs/sysv/inode.c: use ktime_get_real_seconds() for superblock stamp adfs: use timespec64 for time conversion kernel/sysctl.c: fix typos in comments drivers/rapidio/devices/rio_mport_cdev.c: remove redundant pointer md fork: don't copy inconsistent signal handler state to child signal: make get_signal() return bool signal: make sigkill_pending() return bool ...
This commit is contained in:
@@ -14,8 +14,8 @@
|
||||
#include <asm/sections.h>
|
||||
|
||||
/* vmcoreinfo stuff */
|
||||
static unsigned char *vmcoreinfo_data;
|
||||
static size_t vmcoreinfo_size;
|
||||
unsigned char *vmcoreinfo_data;
|
||||
size_t vmcoreinfo_size;
|
||||
u32 *vmcoreinfo_note;
|
||||
|
||||
/* trusted vmcoreinfo, e.g. we can make a copy in the crash memory */
|
||||
@@ -344,7 +344,7 @@ void crash_save_vmcoreinfo(void)
|
||||
if (vmcoreinfo_data_safecopy)
|
||||
vmcoreinfo_data = vmcoreinfo_data_safecopy;
|
||||
|
||||
vmcoreinfo_append_str("CRASHTIME=%ld\n", get_seconds());
|
||||
vmcoreinfo_append_str("CRASHTIME=%lld\n", ktime_get_real_seconds());
|
||||
update_vmcoreinfo_note();
|
||||
}
|
||||
|
||||
@@ -401,7 +401,7 @@ static int __init crash_save_vmcoreinfo_init(void)
|
||||
VMCOREINFO_SYMBOL(init_uts_ns);
|
||||
VMCOREINFO_SYMBOL(node_online_map);
|
||||
#ifdef CONFIG_MMU
|
||||
VMCOREINFO_SYMBOL(swapper_pg_dir);
|
||||
VMCOREINFO_SYMBOL_ARRAY(swapper_pg_dir);
|
||||
#endif
|
||||
VMCOREINFO_SYMBOL(_stext);
|
||||
VMCOREINFO_SYMBOL(vmap_area_list);
|
||||
|
@@ -310,8 +310,9 @@ static struct kmem_cache *mm_cachep;
|
||||
|
||||
struct vm_area_struct *vm_area_alloc(struct mm_struct *mm)
|
||||
{
|
||||
struct vm_area_struct *vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
|
||||
struct vm_area_struct *vma;
|
||||
|
||||
vma = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL);
|
||||
if (vma)
|
||||
vma_init(vma, mm);
|
||||
return vma;
|
||||
@@ -1301,6 +1302,7 @@ static int copy_mm(unsigned long clone_flags, struct task_struct *tsk)
|
||||
tsk->nvcsw = tsk->nivcsw = 0;
|
||||
#ifdef CONFIG_DETECT_HUNG_TASK
|
||||
tsk->last_switch_count = tsk->nvcsw + tsk->nivcsw;
|
||||
tsk->last_switch_time = 0;
|
||||
#endif
|
||||
|
||||
tsk->mm = NULL;
|
||||
@@ -1425,7 +1427,9 @@ static int copy_sighand(unsigned long clone_flags, struct task_struct *tsk)
|
||||
return -ENOMEM;
|
||||
|
||||
atomic_set(&sig->count, 1);
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
memcpy(sig->action, current->sighand->action, sizeof(sig->action));
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@@ -40,6 +40,11 @@ int __read_mostly sysctl_hung_task_check_count = PID_MAX_LIMIT;
|
||||
*/
|
||||
unsigned long __read_mostly sysctl_hung_task_timeout_secs = CONFIG_DEFAULT_HUNG_TASK_TIMEOUT;
|
||||
|
||||
/*
|
||||
* Zero (default value) means use sysctl_hung_task_timeout_secs:
|
||||
*/
|
||||
unsigned long __read_mostly sysctl_hung_task_check_interval_secs;
|
||||
|
||||
int __read_mostly sysctl_hung_task_warnings = 10;
|
||||
|
||||
static int __read_mostly did_panic;
|
||||
@@ -98,8 +103,11 @@ static void check_hung_task(struct task_struct *t, unsigned long timeout)
|
||||
|
||||
if (switch_count != t->last_switch_count) {
|
||||
t->last_switch_count = switch_count;
|
||||
t->last_switch_time = jiffies;
|
||||
return;
|
||||
}
|
||||
if (time_is_after_jiffies(t->last_switch_time + timeout * HZ))
|
||||
return;
|
||||
|
||||
trace_sched_process_hang(t);
|
||||
|
||||
@@ -245,8 +253,13 @@ static int watchdog(void *dummy)
|
||||
|
||||
for ( ; ; ) {
|
||||
unsigned long timeout = sysctl_hung_task_timeout_secs;
|
||||
long t = hung_timeout_jiffies(hung_last_checked, timeout);
|
||||
unsigned long interval = sysctl_hung_task_check_interval_secs;
|
||||
long t;
|
||||
|
||||
if (interval == 0)
|
||||
interval = timeout;
|
||||
interval = min_t(unsigned long, interval, timeout);
|
||||
t = hung_timeout_jiffies(hung_last_checked, interval);
|
||||
if (t <= 0) {
|
||||
if (!atomic_xchg(&reset_hung_task, 0))
|
||||
check_hung_uninterruptible_tasks(timeout);
|
||||
|
@@ -529,12 +529,30 @@ static bool check_symbol(const struct symsearch *syms,
|
||||
return true;
|
||||
}
|
||||
|
||||
static unsigned long kernel_symbol_value(const struct kernel_symbol *sym)
|
||||
{
|
||||
#ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS
|
||||
return (unsigned long)offset_to_ptr(&sym->value_offset);
|
||||
#else
|
||||
return sym->value;
|
||||
#endif
|
||||
}
|
||||
|
||||
static const char *kernel_symbol_name(const struct kernel_symbol *sym)
|
||||
{
|
||||
#ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS
|
||||
return offset_to_ptr(&sym->name_offset);
|
||||
#else
|
||||
return sym->name;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int cmp_name(const void *va, const void *vb)
|
||||
{
|
||||
const char *a;
|
||||
const struct kernel_symbol *b;
|
||||
a = va; b = vb;
|
||||
return strcmp(a, b->name);
|
||||
return strcmp(a, kernel_symbol_name(b));
|
||||
}
|
||||
|
||||
static bool find_symbol_in_section(const struct symsearch *syms,
|
||||
@@ -2170,7 +2188,7 @@ void *__symbol_get(const char *symbol)
|
||||
sym = NULL;
|
||||
preempt_enable();
|
||||
|
||||
return sym ? (void *)sym->value : NULL;
|
||||
return sym ? (void *)kernel_symbol_value(sym) : NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__symbol_get);
|
||||
|
||||
@@ -2200,10 +2218,12 @@ static int verify_export_symbols(struct module *mod)
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(arr); i++) {
|
||||
for (s = arr[i].sym; s < arr[i].sym + arr[i].num; s++) {
|
||||
if (find_symbol(s->name, &owner, NULL, true, false)) {
|
||||
if (find_symbol(kernel_symbol_name(s), &owner, NULL,
|
||||
true, false)) {
|
||||
pr_err("%s: exports duplicate symbol %s"
|
||||
" (owned by %s)\n",
|
||||
mod->name, s->name, module_name(owner));
|
||||
mod->name, kernel_symbol_name(s),
|
||||
module_name(owner));
|
||||
return -ENOEXEC;
|
||||
}
|
||||
}
|
||||
@@ -2252,7 +2272,7 @@ static int simplify_symbols(struct module *mod, const struct load_info *info)
|
||||
ksym = resolve_symbol_wait(mod, info, name);
|
||||
/* Ok if resolved. */
|
||||
if (ksym && !IS_ERR(ksym)) {
|
||||
sym[i].st_value = ksym->value;
|
||||
sym[i].st_value = kernel_symbol_value(ksym);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2516,7 +2536,7 @@ static int is_exported(const char *name, unsigned long value,
|
||||
ks = lookup_symbol(name, __start___ksymtab, __stop___ksymtab);
|
||||
else
|
||||
ks = lookup_symbol(name, mod->syms, mod->syms + mod->num_syms);
|
||||
return ks != NULL && ks->value == value;
|
||||
return ks != NULL && kernel_symbol_value(ks) == value;
|
||||
}
|
||||
|
||||
/* As per nm */
|
||||
|
@@ -2788,7 +2788,8 @@ EXPORT_SYMBOL(unregister_console);
|
||||
void __init console_init(void)
|
||||
{
|
||||
int ret;
|
||||
initcall_t *call;
|
||||
initcall_t call;
|
||||
initcall_entry_t *ce;
|
||||
|
||||
/* Setup the default TTY line discipline. */
|
||||
n_tty_init();
|
||||
@@ -2797,13 +2798,14 @@ void __init console_init(void)
|
||||
* set up the console device so that later boot sequences can
|
||||
* inform about problems etc..
|
||||
*/
|
||||
call = __con_initcall_start;
|
||||
ce = __con_initcall_start;
|
||||
trace_initcall_level("console");
|
||||
while (call < __con_initcall_end) {
|
||||
trace_initcall_start((*call));
|
||||
ret = (*call)();
|
||||
trace_initcall_finish((*call), ret);
|
||||
call++;
|
||||
while (ce < __con_initcall_end) {
|
||||
call = initcall_from_entry(ce);
|
||||
trace_initcall_start(call);
|
||||
ret = call();
|
||||
trace_initcall_finish(call, ret);
|
||||
ce++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -69,6 +69,8 @@ static int __wake_up_common(struct wait_queue_head *wq_head, unsigned int mode,
|
||||
wait_queue_entry_t *curr, *next;
|
||||
int cnt = 0;
|
||||
|
||||
lockdep_assert_held(&wq_head->lock);
|
||||
|
||||
if (bookmark && (bookmark->flags & WQ_FLAG_BOOKMARK)) {
|
||||
curr = list_next_entry(bookmark, entry);
|
||||
|
||||
|
170
kernel/signal.c
170
kernel/signal.c
@@ -65,14 +65,14 @@ static void __user *sig_handler(struct task_struct *t, int sig)
|
||||
return t->sighand->action[sig - 1].sa.sa_handler;
|
||||
}
|
||||
|
||||
static int sig_handler_ignored(void __user *handler, int sig)
|
||||
static inline bool sig_handler_ignored(void __user *handler, int sig)
|
||||
{
|
||||
/* Is it explicitly or implicitly ignored? */
|
||||
return handler == SIG_IGN ||
|
||||
(handler == SIG_DFL && sig_kernel_ignore(sig));
|
||||
(handler == SIG_DFL && sig_kernel_ignore(sig));
|
||||
}
|
||||
|
||||
static int sig_task_ignored(struct task_struct *t, int sig, bool force)
|
||||
static bool sig_task_ignored(struct task_struct *t, int sig, bool force)
|
||||
{
|
||||
void __user *handler;
|
||||
|
||||
@@ -80,12 +80,12 @@ static int sig_task_ignored(struct task_struct *t, int sig, bool force)
|
||||
|
||||
if (unlikely(t->signal->flags & SIGNAL_UNKILLABLE) &&
|
||||
handler == SIG_DFL && !(force && sig_kernel_only(sig)))
|
||||
return 1;
|
||||
return true;
|
||||
|
||||
return sig_handler_ignored(handler, sig);
|
||||
}
|
||||
|
||||
static int sig_ignored(struct task_struct *t, int sig, bool force)
|
||||
static bool sig_ignored(struct task_struct *t, int sig, bool force)
|
||||
{
|
||||
/*
|
||||
* Blocked signals are never ignored, since the
|
||||
@@ -93,7 +93,7 @@ static int sig_ignored(struct task_struct *t, int sig, bool force)
|
||||
* unblocked.
|
||||
*/
|
||||
if (sigismember(&t->blocked, sig) || sigismember(&t->real_blocked, sig))
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
/*
|
||||
* Tracers may want to know about even ignored signal unless it
|
||||
@@ -101,7 +101,7 @@ static int sig_ignored(struct task_struct *t, int sig, bool force)
|
||||
* by SIGNAL_UNKILLABLE task.
|
||||
*/
|
||||
if (t->ptrace && sig != SIGKILL)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
return sig_task_ignored(t, sig, force);
|
||||
}
|
||||
@@ -110,7 +110,7 @@ static int sig_ignored(struct task_struct *t, int sig, bool force)
|
||||
* Re-calculate pending state from the set of locally pending
|
||||
* signals, globally pending signals, and blocked signals.
|
||||
*/
|
||||
static inline int has_pending_signals(sigset_t *signal, sigset_t *blocked)
|
||||
static inline bool has_pending_signals(sigset_t *signal, sigset_t *blocked)
|
||||
{
|
||||
unsigned long ready;
|
||||
long i;
|
||||
@@ -138,20 +138,21 @@ static inline int has_pending_signals(sigset_t *signal, sigset_t *blocked)
|
||||
|
||||
#define PENDING(p,b) has_pending_signals(&(p)->signal, (b))
|
||||
|
||||
static int recalc_sigpending_tsk(struct task_struct *t)
|
||||
static bool recalc_sigpending_tsk(struct task_struct *t)
|
||||
{
|
||||
if ((t->jobctl & JOBCTL_PENDING_MASK) ||
|
||||
PENDING(&t->pending, &t->blocked) ||
|
||||
PENDING(&t->signal->shared_pending, &t->blocked)) {
|
||||
set_tsk_thread_flag(t, TIF_SIGPENDING);
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* We must never clear the flag in another thread, or in current
|
||||
* when it's possible the current syscall is returning -ERESTART*.
|
||||
* So we don't clear it here, and only callers who know they should do.
|
||||
*/
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -529,13 +530,15 @@ flush_signal_handlers(struct task_struct *t, int force_default)
|
||||
}
|
||||
}
|
||||
|
||||
int unhandled_signal(struct task_struct *tsk, int sig)
|
||||
bool unhandled_signal(struct task_struct *tsk, int sig)
|
||||
{
|
||||
void __user *handler = tsk->sighand->action[sig-1].sa.sa_handler;
|
||||
if (is_global_init(tsk))
|
||||
return 1;
|
||||
return true;
|
||||
|
||||
if (handler != SIG_IGN && handler != SIG_DFL)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
/* if ptraced, let the tracer determine */
|
||||
return !tsk->ptrace;
|
||||
}
|
||||
@@ -709,14 +712,14 @@ void signal_wake_up_state(struct task_struct *t, unsigned int state)
|
||||
*
|
||||
* All callers must be holding the siglock.
|
||||
*/
|
||||
static int flush_sigqueue_mask(sigset_t *mask, struct sigpending *s)
|
||||
static void flush_sigqueue_mask(sigset_t *mask, struct sigpending *s)
|
||||
{
|
||||
struct sigqueue *q, *n;
|
||||
sigset_t m;
|
||||
|
||||
sigandsets(&m, mask, &s->signal);
|
||||
if (sigisemptyset(&m))
|
||||
return 0;
|
||||
return;
|
||||
|
||||
sigandnsets(&s->signal, &s->signal, mask);
|
||||
list_for_each_entry_safe(q, n, &s->list, list) {
|
||||
@@ -725,7 +728,6 @@ static int flush_sigqueue_mask(sigset_t *mask, struct sigpending *s)
|
||||
__sigqueue_free(q);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int is_si_special(const struct siginfo *info)
|
||||
@@ -742,21 +744,16 @@ static inline bool si_fromuser(const struct siginfo *info)
|
||||
/*
|
||||
* called with RCU read lock from check_kill_permission()
|
||||
*/
|
||||
static int kill_ok_by_cred(struct task_struct *t)
|
||||
static bool kill_ok_by_cred(struct task_struct *t)
|
||||
{
|
||||
const struct cred *cred = current_cred();
|
||||
const struct cred *tcred = __task_cred(t);
|
||||
|
||||
if (uid_eq(cred->euid, tcred->suid) ||
|
||||
uid_eq(cred->euid, tcred->uid) ||
|
||||
uid_eq(cred->uid, tcred->suid) ||
|
||||
uid_eq(cred->uid, tcred->uid))
|
||||
return 1;
|
||||
|
||||
if (ns_capable(tcred->user_ns, CAP_KILL))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
return uid_eq(cred->euid, tcred->suid) ||
|
||||
uid_eq(cred->euid, tcred->uid) ||
|
||||
uid_eq(cred->uid, tcred->suid) ||
|
||||
uid_eq(cred->uid, tcred->uid) ||
|
||||
ns_capable(tcred->user_ns, CAP_KILL);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -907,16 +904,20 @@ static bool prepare_signal(int sig, struct task_struct *p, bool force)
|
||||
* as soon as they're available, so putting the signal on the shared queue
|
||||
* will be equivalent to sending it to one such thread.
|
||||
*/
|
||||
static inline int wants_signal(int sig, struct task_struct *p)
|
||||
static inline bool wants_signal(int sig, struct task_struct *p)
|
||||
{
|
||||
if (sigismember(&p->blocked, sig))
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
if (p->flags & PF_EXITING)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
if (sig == SIGKILL)
|
||||
return 1;
|
||||
return true;
|
||||
|
||||
if (task_is_stopped_or_traced(p))
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
return task_curr(p) || !signal_pending(p);
|
||||
}
|
||||
|
||||
@@ -996,7 +997,7 @@ static void complete_signal(int sig, struct task_struct *p, enum pid_type type)
|
||||
return;
|
||||
}
|
||||
|
||||
static inline int legacy_queue(struct sigpending *signals, int sig)
|
||||
static inline bool legacy_queue(struct sigpending *signals, int sig)
|
||||
{
|
||||
return (sig < SIGRTMIN) && sigismember(&signals->signal, sig);
|
||||
}
|
||||
@@ -1380,14 +1381,15 @@ static int kill_proc_info(int sig, struct siginfo *info, pid_t pid)
|
||||
return error;
|
||||
}
|
||||
|
||||
static int kill_as_cred_perm(const struct cred *cred,
|
||||
struct task_struct *target)
|
||||
static inline bool kill_as_cred_perm(const struct cred *cred,
|
||||
struct task_struct *target)
|
||||
{
|
||||
const struct cred *pcred = __task_cred(target);
|
||||
if (!uid_eq(cred->euid, pcred->suid) && !uid_eq(cred->euid, pcred->uid) &&
|
||||
!uid_eq(cred->uid, pcred->suid) && !uid_eq(cred->uid, pcred->uid))
|
||||
return 0;
|
||||
return 1;
|
||||
|
||||
return uid_eq(cred->euid, pcred->suid) ||
|
||||
uid_eq(cred->euid, pcred->uid) ||
|
||||
uid_eq(cred->uid, pcred->suid) ||
|
||||
uid_eq(cred->uid, pcred->uid);
|
||||
}
|
||||
|
||||
/* like kill_pid_info(), but doesn't use uid/euid of "current" */
|
||||
@@ -1500,8 +1502,7 @@ send_sig(int sig, struct task_struct *p, int priv)
|
||||
return send_sig_info(sig, __si_special(priv), p);
|
||||
}
|
||||
|
||||
void
|
||||
force_sig(int sig, struct task_struct *p)
|
||||
void force_sig(int sig, struct task_struct *p)
|
||||
{
|
||||
force_sig_info(sig, SEND_SIG_PRIV, p);
|
||||
}
|
||||
@@ -1512,8 +1513,7 @@ force_sig(int sig, struct task_struct *p)
|
||||
* the problem was already a SIGSEGV, we'll want to
|
||||
* make sure we don't even try to deliver the signal..
|
||||
*/
|
||||
int
|
||||
force_sigsegv(int sig, struct task_struct *p)
|
||||
void force_sigsegv(int sig, struct task_struct *p)
|
||||
{
|
||||
if (sig == SIGSEGV) {
|
||||
unsigned long flags;
|
||||
@@ -1522,7 +1522,6 @@ force_sigsegv(int sig, struct task_struct *p)
|
||||
spin_unlock_irqrestore(&p->sighand->siglock, flags);
|
||||
}
|
||||
force_sig(SIGSEGV, p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int force_sig_fault(int sig, int code, void __user *addr
|
||||
@@ -1923,10 +1922,10 @@ static void do_notify_parent_cldstop(struct task_struct *tsk,
|
||||
spin_unlock_irqrestore(&sighand->siglock, flags);
|
||||
}
|
||||
|
||||
static inline int may_ptrace_stop(void)
|
||||
static inline bool may_ptrace_stop(void)
|
||||
{
|
||||
if (!likely(current->ptrace))
|
||||
return 0;
|
||||
return false;
|
||||
/*
|
||||
* Are we in the middle of do_coredump?
|
||||
* If so and our tracer is also part of the coredump stopping
|
||||
@@ -1942,19 +1941,19 @@ static inline int may_ptrace_stop(void)
|
||||
*/
|
||||
if (unlikely(current->mm->core_state) &&
|
||||
unlikely(current->mm == current->parent->mm))
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return non-zero if there is a SIGKILL that should be waking us up.
|
||||
* Called with the siglock held.
|
||||
*/
|
||||
static int sigkill_pending(struct task_struct *tsk)
|
||||
static bool sigkill_pending(struct task_struct *tsk)
|
||||
{
|
||||
return sigismember(&tsk->pending.signal, SIGKILL) ||
|
||||
sigismember(&tsk->signal->shared_pending.signal, SIGKILL);
|
||||
return sigismember(&tsk->pending.signal, SIGKILL) ||
|
||||
sigismember(&tsk->signal->shared_pending.signal, SIGKILL);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2334,7 +2333,7 @@ static int ptrace_signal(int signr, siginfo_t *info)
|
||||
return signr;
|
||||
}
|
||||
|
||||
int get_signal(struct ksignal *ksig)
|
||||
bool get_signal(struct ksignal *ksig)
|
||||
{
|
||||
struct sighand_struct *sighand = current->sighand;
|
||||
struct signal_struct *signal = current->signal;
|
||||
@@ -2344,7 +2343,7 @@ int get_signal(struct ksignal *ksig)
|
||||
task_work_run();
|
||||
|
||||
if (unlikely(uprobe_deny_signal()))
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
/*
|
||||
* Do this once, we can't return to user-mode if freezing() == T.
|
||||
@@ -2801,7 +2800,7 @@ COMPAT_SYSCALL_DEFINE4(rt_sigprocmask, int, how, compat_sigset_t __user *, nset,
|
||||
}
|
||||
#endif
|
||||
|
||||
static int do_sigpending(sigset_t *set)
|
||||
static void do_sigpending(sigset_t *set)
|
||||
{
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
sigorsets(set, ¤t->pending.signal,
|
||||
@@ -2810,7 +2809,6 @@ static int do_sigpending(sigset_t *set)
|
||||
|
||||
/* Outside the lock because only this thread touches it. */
|
||||
sigandsets(set, ¤t->blocked, set);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2822,15 +2820,16 @@ static int do_sigpending(sigset_t *set)
|
||||
SYSCALL_DEFINE2(rt_sigpending, sigset_t __user *, uset, size_t, sigsetsize)
|
||||
{
|
||||
sigset_t set;
|
||||
int err;
|
||||
|
||||
if (sigsetsize > sizeof(*uset))
|
||||
return -EINVAL;
|
||||
|
||||
err = do_sigpending(&set);
|
||||
if (!err && copy_to_user(uset, &set, sigsetsize))
|
||||
err = -EFAULT;
|
||||
return err;
|
||||
do_sigpending(&set);
|
||||
|
||||
if (copy_to_user(uset, &set, sigsetsize))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
@@ -2838,15 +2837,13 @@ COMPAT_SYSCALL_DEFINE2(rt_sigpending, compat_sigset_t __user *, uset,
|
||||
compat_size_t, sigsetsize)
|
||||
{
|
||||
sigset_t set;
|
||||
int err;
|
||||
|
||||
if (sigsetsize > sizeof(*uset))
|
||||
return -EINVAL;
|
||||
|
||||
err = do_sigpending(&set);
|
||||
if (!err)
|
||||
err = put_compat_sigset(uset, &set, sigsetsize);
|
||||
return err;
|
||||
do_sigpending(&set);
|
||||
|
||||
return put_compat_sigset(uset, &set, sigsetsize);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -3608,25 +3605,26 @@ int __compat_save_altstack(compat_stack_t __user *uss, unsigned long sp)
|
||||
SYSCALL_DEFINE1(sigpending, old_sigset_t __user *, uset)
|
||||
{
|
||||
sigset_t set;
|
||||
int err;
|
||||
|
||||
if (sizeof(old_sigset_t) > sizeof(*uset))
|
||||
return -EINVAL;
|
||||
|
||||
err = do_sigpending(&set);
|
||||
if (!err && copy_to_user(uset, &set, sizeof(old_sigset_t)))
|
||||
err = -EFAULT;
|
||||
return err;
|
||||
do_sigpending(&set);
|
||||
|
||||
if (copy_to_user(uset, &set, sizeof(old_sigset_t)))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
COMPAT_SYSCALL_DEFINE1(sigpending, compat_old_sigset_t __user *, set32)
|
||||
{
|
||||
sigset_t set;
|
||||
int err = do_sigpending(&set);
|
||||
if (!err)
|
||||
err = put_user(set.sig[0], set32);
|
||||
return err;
|
||||
|
||||
do_sigpending(&set);
|
||||
|
||||
return put_user(set.sig[0], set32);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -3697,25 +3695,23 @@ SYSCALL_DEFINE4(rt_sigaction, int, sig,
|
||||
size_t, sigsetsize)
|
||||
{
|
||||
struct k_sigaction new_sa, old_sa;
|
||||
int ret = -EINVAL;
|
||||
int ret;
|
||||
|
||||
/* XXX: Don't preclude handling different sized sigset_t's. */
|
||||
if (sigsetsize != sizeof(sigset_t))
|
||||
goto out;
|
||||
return -EINVAL;
|
||||
|
||||
if (act) {
|
||||
if (copy_from_user(&new_sa.sa, act, sizeof(new_sa.sa)))
|
||||
return -EFAULT;
|
||||
}
|
||||
if (act && copy_from_user(&new_sa.sa, act, sizeof(new_sa.sa)))
|
||||
return -EFAULT;
|
||||
|
||||
ret = do_sigaction(sig, act ? &new_sa : NULL, oact ? &old_sa : NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!ret && oact) {
|
||||
if (copy_to_user(oact, &old_sa.sa, sizeof(old_sa.sa)))
|
||||
return -EFAULT;
|
||||
}
|
||||
out:
|
||||
return ret;
|
||||
if (oact && copy_to_user(oact, &old_sa.sa, sizeof(old_sa.sa)))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#ifdef CONFIG_COMPAT
|
||||
COMPAT_SYSCALL_DEFINE4(rt_sigaction, int, sig,
|
||||
|
@@ -145,7 +145,10 @@ static int minolduid;
|
||||
static int ngroups_max = NGROUPS_MAX;
|
||||
static const int cap_last_cap = CAP_LAST_CAP;
|
||||
|
||||
/*this is needed for proc_doulongvec_minmax of sysctl_hung_task_timeout_secs */
|
||||
/*
|
||||
* This is needed for proc_doulongvec_minmax of sysctl_hung_task_timeout_secs
|
||||
* and hung_task_check_interval_secs
|
||||
*/
|
||||
#ifdef CONFIG_DETECT_HUNG_TASK
|
||||
static unsigned long hung_task_timeout_max = (LONG_MAX/HZ);
|
||||
#endif
|
||||
@@ -222,7 +225,7 @@ static int proc_dopipe_max_size(struct ctl_table *table, int write,
|
||||
void __user *buffer, size_t *lenp, loff_t *ppos);
|
||||
|
||||
#ifdef CONFIG_MAGIC_SYSRQ
|
||||
/* Note: sysrq code uses it's own private copy */
|
||||
/* Note: sysrq code uses its own private copy */
|
||||
static int __sysrq_enabled = CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE;
|
||||
|
||||
static int sysrq_sysctl_handler(struct ctl_table *table, int write,
|
||||
@@ -1090,6 +1093,14 @@ static struct ctl_table kern_table[] = {
|
||||
.proc_handler = proc_dohung_task_timeout_secs,
|
||||
.extra2 = &hung_task_timeout_max,
|
||||
},
|
||||
{
|
||||
.procname = "hung_task_check_interval_secs",
|
||||
.data = &sysctl_hung_task_check_interval_secs,
|
||||
.maxlen = sizeof(unsigned long),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dohung_task_timeout_secs,
|
||||
.extra2 = &hung_task_timeout_max,
|
||||
},
|
||||
{
|
||||
.procname = "hung_task_warnings",
|
||||
.data = &sysctl_hung_task_warnings,
|
||||
@@ -1965,13 +1976,13 @@ static void warn_sysctl_write(struct ctl_table *table)
|
||||
}
|
||||
|
||||
/**
|
||||
* proc_first_pos_non_zero_ignore - check if firs position is allowed
|
||||
* proc_first_pos_non_zero_ignore - check if first position is allowed
|
||||
* @ppos: file position
|
||||
* @table: the sysctl table
|
||||
*
|
||||
* Returns true if the first position is non-zero and the sysctl_writes_strict
|
||||
* mode indicates this is not allowed for numeric input types. String proc
|
||||
* hadlers can ignore the return value.
|
||||
* handlers can ignore the return value.
|
||||
*/
|
||||
static bool proc_first_pos_non_zero_ignore(loff_t *ppos,
|
||||
struct ctl_table *table)
|
||||
|
@@ -371,6 +371,27 @@ int tracepoint_probe_unregister(struct tracepoint *tp, void *probe, void *data)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tracepoint_probe_unregister);
|
||||
|
||||
static void for_each_tracepoint_range(struct tracepoint * const *begin,
|
||||
struct tracepoint * const *end,
|
||||
void (*fct)(struct tracepoint *tp, void *priv),
|
||||
void *priv)
|
||||
{
|
||||
if (!begin)
|
||||
return;
|
||||
|
||||
if (IS_ENABLED(CONFIG_HAVE_ARCH_PREL32_RELOCATIONS)) {
|
||||
const int *iter;
|
||||
|
||||
for (iter = (const int *)begin; iter < (const int *)end; iter++)
|
||||
fct(offset_to_ptr(iter), priv);
|
||||
} else {
|
||||
struct tracepoint * const *iter;
|
||||
|
||||
for (iter = begin; iter < end; iter++)
|
||||
fct(*iter, priv);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MODULES
|
||||
bool trace_module_has_bad_taint(struct module *mod)
|
||||
{
|
||||
@@ -435,15 +456,9 @@ EXPORT_SYMBOL_GPL(unregister_tracepoint_module_notifier);
|
||||
* Ensure the tracer unregistered the module's probes before the module
|
||||
* teardown is performed. Prevents leaks of probe and data pointers.
|
||||
*/
|
||||
static void tp_module_going_check_quiescent(struct tracepoint * const *begin,
|
||||
struct tracepoint * const *end)
|
||||
static void tp_module_going_check_quiescent(struct tracepoint *tp, void *priv)
|
||||
{
|
||||
struct tracepoint * const *iter;
|
||||
|
||||
if (!begin)
|
||||
return;
|
||||
for (iter = begin; iter < end; iter++)
|
||||
WARN_ON_ONCE((*iter)->funcs);
|
||||
WARN_ON_ONCE(tp->funcs);
|
||||
}
|
||||
|
||||
static int tracepoint_module_coming(struct module *mod)
|
||||
@@ -494,8 +509,9 @@ static void tracepoint_module_going(struct module *mod)
|
||||
* Called the going notifier before checking for
|
||||
* quiescence.
|
||||
*/
|
||||
tp_module_going_check_quiescent(mod->tracepoints_ptrs,
|
||||
mod->tracepoints_ptrs + mod->num_tracepoints);
|
||||
for_each_tracepoint_range(mod->tracepoints_ptrs,
|
||||
mod->tracepoints_ptrs + mod->num_tracepoints,
|
||||
tp_module_going_check_quiescent, NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -547,19 +563,6 @@ static __init int init_tracepoints(void)
|
||||
__initcall(init_tracepoints);
|
||||
#endif /* CONFIG_MODULES */
|
||||
|
||||
static void for_each_tracepoint_range(struct tracepoint * const *begin,
|
||||
struct tracepoint * const *end,
|
||||
void (*fct)(struct tracepoint *tp, void *priv),
|
||||
void *priv)
|
||||
{
|
||||
struct tracepoint * const *iter;
|
||||
|
||||
if (!begin)
|
||||
return;
|
||||
for (iter = begin; iter < end; iter++)
|
||||
fct(*iter, priv);
|
||||
}
|
||||
|
||||
/**
|
||||
* for_each_kernel_tracepoint - iteration on all kernel tracepoints
|
||||
* @fct: callback
|
||||
|
@@ -96,7 +96,7 @@ static DEFINE_SPINLOCK(uidhash_lock);
|
||||
|
||||
/* root_user.__count is 1, for init task cred */
|
||||
struct user_struct root_user = {
|
||||
.__count = ATOMIC_INIT(1),
|
||||
.__count = REFCOUNT_INIT(1),
|
||||
.processes = ATOMIC_INIT(1),
|
||||
.sigpending = ATOMIC_INIT(0),
|
||||
.locked_shm = 0,
|
||||
@@ -123,7 +123,7 @@ static struct user_struct *uid_hash_find(kuid_t uid, struct hlist_head *hashent)
|
||||
|
||||
hlist_for_each_entry(user, hashent, uidhash_node) {
|
||||
if (uid_eq(user->uid, uid)) {
|
||||
atomic_inc(&user->__count);
|
||||
refcount_inc(&user->__count);
|
||||
return user;
|
||||
}
|
||||
}
|
||||
@@ -169,11 +169,8 @@ void free_uid(struct user_struct *up)
|
||||
if (!up)
|
||||
return;
|
||||
|
||||
local_irq_save(flags);
|
||||
if (atomic_dec_and_lock(&up->__count, &uidhash_lock))
|
||||
if (refcount_dec_and_lock_irqsave(&up->__count, &uidhash_lock, &flags))
|
||||
free_user(up, flags);
|
||||
else
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
struct user_struct *alloc_uid(kuid_t uid)
|
||||
@@ -191,7 +188,7 @@ struct user_struct *alloc_uid(kuid_t uid)
|
||||
goto out_unlock;
|
||||
|
||||
new->uid = uid;
|
||||
atomic_set(&new->__count, 1);
|
||||
refcount_set(&new->__count, 1);
|
||||
ratelimit_state_init(&new->ratelimit, HZ, 100);
|
||||
ratelimit_set_flags(&new->ratelimit, RATELIMIT_MSG_ON_RELEASE);
|
||||
|
||||
|
Reference in New Issue
Block a user