diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/capability.c | 24 | ||||
| -rw-r--r-- | kernel/events/core.c | 4 | ||||
| -rw-r--r-- | kernel/events/internal.h | 2 | ||||
| -rw-r--r-- | kernel/events/ring_buffer.c | 22 | ||||
| -rw-r--r-- | kernel/sched/clock.c | 26 | ||||
| -rw-r--r-- | kernel/sched/core.c | 8 | ||||
| -rw-r--r-- | kernel/sched/cputime.c | 2 | ||||
| -rw-r--r-- | kernel/sys.c | 3 | ||||
| -rw-r--r-- | kernel/trace/ftrace.c | 54 | ||||
| -rw-r--r-- | kernel/trace/trace.c | 9 | ||||
| -rw-r--r-- | kernel/trace/trace_stack.c | 2 | 
11 files changed, 112 insertions, 44 deletions
diff --git a/kernel/capability.c b/kernel/capability.c index 493d9725948..f6c2ce5701e 100644 --- a/kernel/capability.c +++ b/kernel/capability.c @@ -393,6 +393,30 @@ bool ns_capable(struct user_namespace *ns, int cap)  EXPORT_SYMBOL(ns_capable);  /** + * file_ns_capable - Determine if the file's opener had a capability in effect + * @file:  The file we want to check + * @ns:  The usernamespace we want the capability in + * @cap: The capability to be tested for + * + * Return true if task that opened the file had a capability in effect + * when the file was opened. + * + * This does not set PF_SUPERPRIV because the caller may not + * actually be privileged. + */ +bool file_ns_capable(const struct file *file, struct user_namespace *ns, int cap) +{ +	if (WARN_ON_ONCE(!cap_valid(cap))) +		return false; + +	if (security_capable(file->f_cred, ns, cap) == 0) +		return true; + +	return false; +} +EXPORT_SYMBOL(file_ns_capable); + +/**   * capable - Determine if the current task has a superior capability in effect   * @cap: The capability to be tested for   * diff --git a/kernel/events/core.c b/kernel/events/core.c index 59412d037ee..7e0962ed7f8 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -4737,7 +4737,8 @@ static void perf_event_mmap_event(struct perf_mmap_event *mmap_event)  	} else {  		if (arch_vma_name(mmap_event->vma)) {  			name = strncpy(tmp, arch_vma_name(mmap_event->vma), -				       sizeof(tmp)); +				       sizeof(tmp) - 1); +			tmp[sizeof(tmp) - 1] = '\0';  			goto got_name;  		} @@ -5986,6 +5987,7 @@ skip_type:  	if (pmu->pmu_cpu_context)  		goto got_cpu_context; +	ret = -ENOMEM;  	pmu->pmu_cpu_context = alloc_percpu(struct perf_cpu_context);  	if (!pmu->pmu_cpu_context)  		goto free_dev; diff --git a/kernel/events/internal.h b/kernel/events/internal.h index d56a64c99a8..eb675c4d59d 100644 --- a/kernel/events/internal.h +++ b/kernel/events/internal.h @@ -16,7 +16,7 @@ struct ring_buffer {  	int				page_order;	/* allocation order  */  #endif  	int				nr_pages;	/* nr of data pages  */ -	int				writable;	/* are we writable   */ +	int				overwrite;	/* can overwrite itself */  	atomic_t			poll;		/* POLL_ for wakeups */ diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c index 23cb34ff397..97fddb09762 100644 --- a/kernel/events/ring_buffer.c +++ b/kernel/events/ring_buffer.c @@ -18,12 +18,24 @@  static bool perf_output_space(struct ring_buffer *rb, unsigned long tail,  			      unsigned long offset, unsigned long head)  { -	unsigned long mask; +	unsigned long sz = perf_data_size(rb); +	unsigned long mask = sz - 1; -	if (!rb->writable) +	/* +	 * check if user-writable +	 * overwrite : over-write its own tail +	 * !overwrite: buffer possibly drops events. +	 */ +	if (rb->overwrite)  		return true; -	mask = perf_data_size(rb) - 1; +	/* +	 * verify that payload is not bigger than buffer +	 * otherwise masking logic may fail to detect +	 * the "not enough space" condition +	 */ +	if ((head - offset) > sz) +		return false;  	offset = (offset - tail) & mask;  	head   = (head   - tail) & mask; @@ -212,7 +224,9 @@ ring_buffer_init(struct ring_buffer *rb, long watermark, int flags)  		rb->watermark = max_size / 2;  	if (flags & RING_BUFFER_WRITABLE) -		rb->writable = 1; +		rb->overwrite = 0; +	else +		rb->overwrite = 1;  	atomic_set(&rb->refcount, 1); diff --git a/kernel/sched/clock.c b/kernel/sched/clock.c index c685e31492d..c3ae1446461 100644 --- a/kernel/sched/clock.c +++ b/kernel/sched/clock.c @@ -176,10 +176,36 @@ static u64 sched_clock_remote(struct sched_clock_data *scd)  	u64 this_clock, remote_clock;  	u64 *ptr, old_val, val; +#if BITS_PER_LONG != 64 +again: +	/* +	 * Careful here: The local and the remote clock values need to +	 * be read out atomic as we need to compare the values and +	 * then update either the local or the remote side. So the +	 * cmpxchg64 below only protects one readout. +	 * +	 * We must reread via sched_clock_local() in the retry case on +	 * 32bit as an NMI could use sched_clock_local() via the +	 * tracer and hit between the readout of +	 * the low32bit and the high 32bit portion. +	 */ +	this_clock = sched_clock_local(my_scd); +	/* +	 * We must enforce atomic readout on 32bit, otherwise the +	 * update on the remote cpu can hit inbetween the readout of +	 * the low32bit and the high 32bit portion. +	 */ +	remote_clock = cmpxchg64(&scd->clock, 0, 0); +#else +	/* +	 * On 64bit the read of [my]scd->clock is atomic versus the +	 * update, so we can avoid the above 32bit dance. +	 */  	sched_clock_local(my_scd);  again:  	this_clock = my_scd->clock;  	remote_clock = scd->clock; +#endif  	/*  	 * Use the opportunity that we have both locks diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 7f12624a393..67d04651f44 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -1498,8 +1498,10 @@ static void try_to_wake_up_local(struct task_struct *p)  {  	struct rq *rq = task_rq(p); -	BUG_ON(rq != this_rq()); -	BUG_ON(p == current); +	if (WARN_ON_ONCE(rq != this_rq()) || +	    WARN_ON_ONCE(p == current)) +		return; +  	lockdep_assert_held(&rq->lock);  	if (!raw_spin_trylock(&p->pi_lock)) { @@ -4999,7 +5001,7 @@ static void sd_free_ctl_entry(struct ctl_table **tablep)  }  static int min_load_idx = 0; -static int max_load_idx = CPU_LOAD_IDX_MAX; +static int max_load_idx = CPU_LOAD_IDX_MAX-1;  static void  set_table_entry(struct ctl_table *entry, diff --git a/kernel/sched/cputime.c b/kernel/sched/cputime.c index ed12cbb135f..e93cca92f38 100644 --- a/kernel/sched/cputime.c +++ b/kernel/sched/cputime.c @@ -310,7 +310,7 @@ void thread_group_cputime(struct task_struct *tsk, struct task_cputime *times)  	t = tsk;  	do { -		task_cputime(tsk, &utime, &stime); +		task_cputime(t, &utime, &stime);  		times->utime += utime;  		times->stime += stime;  		times->sum_exec_runtime += task_sched_runtime(t); diff --git a/kernel/sys.c b/kernel/sys.c index 39c9c4a2949..0da73cf73e6 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -324,7 +324,6 @@ void kernel_restart_prepare(char *cmd)  	system_state = SYSTEM_RESTART;  	usermodehelper_disable();  	device_shutdown(); -	syscore_shutdown();  }  /** @@ -370,6 +369,7 @@ void kernel_restart(char *cmd)  {  	kernel_restart_prepare(cmd);  	disable_nonboot_cpus(); +	syscore_shutdown();  	if (!cmd)  		printk(KERN_EMERG "Restarting system.\n");  	else @@ -395,6 +395,7 @@ static void kernel_shutdown_prepare(enum system_states state)  void kernel_halt(void)  {  	kernel_shutdown_prepare(SYSTEM_HALT); +	disable_nonboot_cpus();  	syscore_shutdown();  	printk(KERN_EMERG "System halted.\n");  	kmsg_dump(KMSG_DUMP_HALT); diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 6893d5a2bf0..b3fde6d7b7f 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -66,7 +66,7 @@  static struct ftrace_ops ftrace_list_end __read_mostly = {  	.func		= ftrace_stub, -	.flags		= FTRACE_OPS_FL_RECURSION_SAFE, +	.flags		= FTRACE_OPS_FL_RECURSION_SAFE | FTRACE_OPS_FL_STUB,  };  /* ftrace_enabled is a method to turn ftrace on or off */ @@ -694,7 +694,6 @@ int ftrace_profile_pages_init(struct ftrace_profile_stat *stat)  		free_page(tmp);  	} -	free_page((unsigned long)stat->pages);  	stat->pages = NULL;  	stat->start = NULL; @@ -1053,6 +1052,19 @@ static __init void ftrace_profile_debugfs(struct dentry *d_tracer)  static struct pid * const ftrace_swapper_pid = &init_struct_pid; +loff_t +ftrace_filter_lseek(struct file *file, loff_t offset, int whence) +{ +	loff_t ret; + +	if (file->f_mode & FMODE_READ) +		ret = seq_lseek(file, offset, whence); +	else +		file->f_pos = ret = 1; + +	return ret; +} +  #ifdef CONFIG_DYNAMIC_FTRACE  #ifndef CONFIG_FTRACE_MCOUNT_RECORD @@ -2613,7 +2625,7 @@ static void ftrace_filter_reset(struct ftrace_hash *hash)   * routine, you can use ftrace_filter_write() for the write   * routine if @flag has FTRACE_ITER_FILTER set, or   * ftrace_notrace_write() if @flag has FTRACE_ITER_NOTRACE set. - * ftrace_regex_lseek() should be used as the lseek routine, and + * ftrace_filter_lseek() should be used as the lseek routine, and   * release must call ftrace_regex_release().   */  int @@ -2697,19 +2709,6 @@ ftrace_notrace_open(struct inode *inode, struct file *file)  				 inode, file);  } -loff_t -ftrace_regex_lseek(struct file *file, loff_t offset, int whence) -{ -	loff_t ret; - -	if (file->f_mode & FMODE_READ) -		ret = seq_lseek(file, offset, whence); -	else -		file->f_pos = ret = 1; - -	return ret; -} -  static int ftrace_match(char *str, char *regex, int len, int type)  {  	int matched = 0; @@ -3441,14 +3440,14 @@ static char ftrace_filter_buf[FTRACE_FILTER_SIZE] __initdata;  static int __init set_ftrace_notrace(char *str)  { -	strncpy(ftrace_notrace_buf, str, FTRACE_FILTER_SIZE); +	strlcpy(ftrace_notrace_buf, str, FTRACE_FILTER_SIZE);  	return 1;  }  __setup("ftrace_notrace=", set_ftrace_notrace);  static int __init set_ftrace_filter(char *str)  { -	strncpy(ftrace_filter_buf, str, FTRACE_FILTER_SIZE); +	strlcpy(ftrace_filter_buf, str, FTRACE_FILTER_SIZE);  	return 1;  }  __setup("ftrace_filter=", set_ftrace_filter); @@ -3571,7 +3570,7 @@ static const struct file_operations ftrace_filter_fops = {  	.open = ftrace_filter_open,  	.read = seq_read,  	.write = ftrace_filter_write, -	.llseek = ftrace_regex_lseek, +	.llseek = ftrace_filter_lseek,  	.release = ftrace_regex_release,  }; @@ -3579,7 +3578,7 @@ static const struct file_operations ftrace_notrace_fops = {  	.open = ftrace_notrace_open,  	.read = seq_read,  	.write = ftrace_notrace_write, -	.llseek = ftrace_regex_lseek, +	.llseek = ftrace_filter_lseek,  	.release = ftrace_regex_release,  }; @@ -3784,8 +3783,8 @@ static const struct file_operations ftrace_graph_fops = {  	.open		= ftrace_graph_open,  	.read		= seq_read,  	.write		= ftrace_graph_write, +	.llseek		= ftrace_filter_lseek,  	.release	= ftrace_graph_release, -	.llseek		= seq_lseek,  };  #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ @@ -4131,7 +4130,8 @@ ftrace_ops_control_func(unsigned long ip, unsigned long parent_ip,  	preempt_disable_notrace();  	trace_recursion_set(TRACE_CONTROL_BIT);  	do_for_each_ftrace_op(op, ftrace_control_list) { -		if (!ftrace_function_local_disabled(op) && +		if (!(op->flags & FTRACE_OPS_FL_STUB) && +		    !ftrace_function_local_disabled(op) &&  		    ftrace_ops_test(op, ip))  			op->func(ip, parent_ip, op, regs);  	} while_for_each_ftrace_op(op); @@ -4439,7 +4439,7 @@ static const struct file_operations ftrace_pid_fops = {  	.open		= ftrace_pid_open,  	.write		= ftrace_pid_write,  	.read		= seq_read, -	.llseek		= seq_lseek, +	.llseek		= ftrace_filter_lseek,  	.release	= ftrace_pid_release,  }; @@ -4555,12 +4555,8 @@ ftrace_enable_sysctl(struct ctl_table *table, int write,  		ftrace_startup_sysctl();  		/* we are starting ftrace again */ -		if (ftrace_ops_list != &ftrace_list_end) { -			if (ftrace_ops_list->next == &ftrace_list_end) -				ftrace_trace_function = ftrace_ops_list->func; -			else -				ftrace_trace_function = ftrace_ops_list_func; -		} +		if (ftrace_ops_list != &ftrace_list_end) +			update_ftrace_function();  	} else {  		/* stopping ftrace calls (just send to ftrace_stub) */ diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 4f1dade5698..66338c4f7f4 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -132,7 +132,7 @@ static char *default_bootup_tracer;  static int __init set_cmdline_ftrace(char *str)  { -	strncpy(bootup_tracer_buf, str, MAX_TRACER_SIZE); +	strlcpy(bootup_tracer_buf, str, MAX_TRACER_SIZE);  	default_bootup_tracer = bootup_tracer_buf;  	/* We are using ftrace early, expand it */  	ring_buffer_expanded = 1; @@ -162,7 +162,7 @@ static char *trace_boot_options __initdata;  static int __init set_trace_boot_options(char *str)  { -	strncpy(trace_boot_options_buf, str, MAX_TRACER_SIZE); +	strlcpy(trace_boot_options_buf, str, MAX_TRACER_SIZE);  	trace_boot_options = trace_boot_options_buf;  	return 0;  } @@ -744,8 +744,11 @@ update_max_tr_single(struct trace_array *tr, struct task_struct *tsk, int cpu)  		return;  	WARN_ON_ONCE(!irqs_disabled()); -	if (WARN_ON_ONCE(!current_trace->allocated_snapshot)) +	if (!current_trace->allocated_snapshot) { +		/* Only the nop tracer should hit this when disabling */ +		WARN_ON_ONCE(current_trace != &nop_trace);  		return; +	}  	arch_spin_lock(&ftrace_max_lock); diff --git a/kernel/trace/trace_stack.c b/kernel/trace/trace_stack.c index 42ca822fc70..83a8b5b7bd3 100644 --- a/kernel/trace/trace_stack.c +++ b/kernel/trace/trace_stack.c @@ -322,7 +322,7 @@ static const struct file_operations stack_trace_filter_fops = {  	.open = stack_trace_filter_open,  	.read = seq_read,  	.write = ftrace_filter_write, -	.llseek = ftrace_regex_lseek, +	.llseek = ftrace_filter_lseek,  	.release = ftrace_regex_release,  };  |