summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/bpf/syscall.c36
-rw-r--r--kernel/cgroup/cpuset.c4
-rw-r--r--kernel/compat.c20
-rw-r--r--kernel/entry/syscall_user_dispatch.c6
-rw-r--r--kernel/events/uprobes.c2
-rw-r--r--kernel/kexec_core.c7
-rw-r--r--kernel/ptrace.c18
-rw-r--r--kernel/sched/core.c5
-rw-r--r--kernel/sched/ext/cid.c6
-rw-r--r--kernel/sched/sched.h3
-rw-r--r--kernel/signal.c82
-rw-r--r--kernel/time/timer.c2
-rw-r--r--kernel/trace/bpf_trace.c12
13 files changed, 99 insertions, 104 deletions
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 87cd122d1024..90bc7230afa8 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -5862,11 +5862,8 @@ err_put:
}
#define BPF_LINK_CREATE_LAST_FIELD link_create.uprobe_multi.path_fd
-static int link_create(union bpf_attr *attr, bpfptr_t uattr, struct bpf_common_attr *attr_common,
- bpfptr_t uattr_common, u32 size_common)
+static int link_create(union bpf_attr *attr, bpfptr_t uattr)
{
- struct bpf_verifier_log *log;
- struct bpf_log_attr attr_log;
struct bpf_prog *prog;
int ret;
@@ -5876,24 +5873,14 @@ static int link_create(union bpf_attr *attr, bpfptr_t uattr, struct bpf_common_a
if (attr->link_create.attach_type == BPF_STRUCT_OPS)
return bpf_struct_ops_link_create(attr);
- log = bpf_log_attr_create_vlog(&attr_log, attr_common, uattr_common, size_common);
- if (IS_ERR(log))
- return PTR_ERR(log);
-
prog = bpf_prog_get(attr->link_create.prog_fd);
- if (IS_ERR(prog)) {
- bpf_log(log, "Invalid prog_fd.\n");
- ret = PTR_ERR(prog);
- prog = NULL;
- goto out;
- }
+ if (IS_ERR(prog))
+ return PTR_ERR(prog);
ret = bpf_prog_attach_check_attach_type(prog,
attr->link_create.attach_type);
- if (ret) {
- bpf_log(log, "Invalid attach_type.\n");
+ if (ret)
goto out;
- }
switch (prog->type) {
case BPF_PROG_TYPE_CGROUP_SKB:
@@ -5944,7 +5931,7 @@ static int link_create(union bpf_attr *attr, bpfptr_t uattr, struct bpf_common_a
break;
#ifdef CONFIG_NET
case BPF_PROG_TYPE_XDP:
- ret = bpf_xdp_link_attach(attr, prog, log);
+ ret = bpf_xdp_link_attach(attr, prog);
break;
case BPF_PROG_TYPE_SCHED_CLS:
if (attr->link_create.attach_type == BPF_TCX_INGRESS ||
@@ -5972,19 +5959,12 @@ static int link_create(union bpf_attr *attr, bpfptr_t uattr, struct bpf_common_a
ret = bpf_uprobe_multi_link_attach(attr, prog);
break;
default:
- bpf_log(log, "Invalid prog type.\n");
ret = -EINVAL;
}
out:
- if (ret < 0) {
- int err = bpf_log_attr_finalize(&attr_log, log);
-
- ret = err ? err : ret;
- if (prog)
- bpf_prog_put(prog);
- }
- kfree(log);
+ if (ret < 0)
+ bpf_prog_put(prog);
return ret;
}
@@ -6556,7 +6536,7 @@ static int __sys_bpf(enum bpf_cmd cmd, bpfptr_t uattr, unsigned int size,
err = bpf_map_do_batch(&attr, uattr.user, BPF_MAP_DELETE_BATCH);
break;
case BPF_LINK_CREATE:
- err = link_create(&attr, uattr, &attr_common, uattr_common, size_common);
+ err = link_create(&attr, uattr);
break;
case BPF_LINK_UPDATE:
err = link_update(&attr);
diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index 585a982249ad..71644482faa7 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -478,10 +478,10 @@ static inline bool partition_is_populated(struct cpuset *cs,
rcu_read_lock();
cpuset_for_each_descendant_pre(cp, pos_css, cs) {
- if (cp == cs || cp == excluded_child)
+ if (cp == cs)
continue;
- if (is_partition_valid(cp)) {
+ if (cp == excluded_child || is_partition_valid(cp)) {
pos_css = css_rightmost_descendant(pos_css);
continue;
}
diff --git a/kernel/compat.c b/kernel/compat.c
index fb50f29d9b36..c754793c7d65 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -180,14 +180,18 @@ int get_compat_sigevent(struct sigevent *event,
const struct compat_sigevent __user *u_event)
{
memset(event, 0, sizeof(*event));
- return (!access_ok(u_event, sizeof(*u_event)) ||
- __get_user(event->sigev_value.sival_int,
- &u_event->sigev_value.sival_int) ||
- __get_user(event->sigev_signo, &u_event->sigev_signo) ||
- __get_user(event->sigev_notify, &u_event->sigev_notify) ||
- __get_user(event->sigev_notify_thread_id,
- &u_event->sigev_notify_thread_id))
- ? -EFAULT : 0;
+ scoped_user_read_access(u_event, Efault) {
+ unsafe_get_user(event->sigev_value.sival_int,
+ &u_event->sigev_value.sival_int, Efault);
+ unsafe_get_user(event->sigev_signo, &u_event->sigev_signo, Efault);
+ unsafe_get_user(event->sigev_notify, &u_event->sigev_notify, Efault);
+ unsafe_get_user(event->sigev_notify_thread_id,
+ &u_event->sigev_notify_thread_id, Efault);
+ }
+ return 0;
+
+Efault:
+ return -EFAULT;
}
long compat_get_bitmap(unsigned long *mask, const compat_ulong_t __user *umask,
diff --git a/kernel/entry/syscall_user_dispatch.c b/kernel/entry/syscall_user_dispatch.c
index 59c861866941..7d1dd7f1bf38 100644
--- a/kernel/entry/syscall_user_dispatch.c
+++ b/kernel/entry/syscall_user_dispatch.c
@@ -45,11 +45,7 @@ bool syscall_user_dispatch(struct pt_regs *regs)
return false;
if (likely(sd->selector)) {
- /*
- * access_ok() is performed once, at prctl time, when
- * the selector is loaded by userspace.
- */
- if (unlikely(__get_user(state, sd->selector))) {
+ if (unlikely(get_user(state, untagged_addr(sd->selector)))) {
force_exit_sig(SIGSEGV);
return true;
}
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index b89cc5cee002..caf444762a27 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -2404,7 +2404,7 @@ static int is_trap_at_addr(struct mm_struct *mm, unsigned long vaddr)
return -EINVAL;
pagefault_disable();
- result = __get_user(opcode, (uprobe_opcode_t __user *)vaddr);
+ result = get_user(opcode, (uprobe_opcode_t __user *)vaddr);
pagefault_enable();
if (likely(result == 0))
diff --git a/kernel/kexec_core.c b/kernel/kexec_core.c
index 7ee8c9f078f6..f4a31565c447 100644
--- a/kernel/kexec_core.c
+++ b/kernel/kexec_core.c
@@ -23,6 +23,7 @@
#include <linux/hardirq.h>
#include <linux/elf.h>
#include <linux/elfcore.h>
+#include <linux/export.h>
#include <linux/utsname.h>
#include <linux/numa.h>
#include <linux/suspend.h>
@@ -54,6 +55,12 @@ atomic_t __kexec_lock = ATOMIC_INIT(0);
/* Flag to indicate we are going to kexec a new kernel */
bool kexec_in_progress = false;
+bool kexec_is_in_progress(void)
+{
+ return kexec_in_progress;
+}
+EXPORT_SYMBOL_GPL(kexec_is_in_progress);
+
bool kexec_file_dbg_print;
/*
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 4e9822a87aab..3f2fe68ccb14 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -1365,16 +1365,13 @@ int ptrace_request(struct task_struct *child, long request,
struct iovec kiov;
struct iovec __user *uiov = datavp;
- if (!access_ok(uiov, sizeof(*uiov)))
- return -EFAULT;
-
- if (__get_user(kiov.iov_base, &uiov->iov_base) ||
- __get_user(kiov.iov_len, &uiov->iov_len))
+ if (get_user(kiov.iov_base, &uiov->iov_base) ||
+ get_user(kiov.iov_len, &uiov->iov_len))
return -EFAULT;
ret = ptrace_regset(child, request, addr, &kiov);
if (!ret)
- ret = __put_user(kiov.iov_len, &uiov->iov_len);
+ ret = put_user(kiov.iov_len, &uiov->iov_len);
break;
}
@@ -1531,11 +1528,8 @@ int compat_ptrace_request(struct task_struct *child, compat_long_t request,
compat_uptr_t ptr;
compat_size_t len;
- if (!access_ok(uiov, sizeof(*uiov)))
- return -EFAULT;
-
- if (__get_user(ptr, &uiov->iov_base) ||
- __get_user(len, &uiov->iov_len))
+ if (get_user(ptr, &uiov->iov_base) ||
+ get_user(len, &uiov->iov_len))
return -EFAULT;
kiov.iov_base = compat_ptr(ptr);
@@ -1543,7 +1537,7 @@ int compat_ptrace_request(struct task_struct *child, compat_long_t request,
ret = ptrace_regset(child, request, addr, &kiov);
if (!ret)
- ret = __put_user(kiov.iov_len, &uiov->iov_len);
+ ret = put_user(kiov.iov_len, &uiov->iov_len);
break;
}
#endif
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 0ab15f03cb94..04b62c16fa8c 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -10783,11 +10783,10 @@ static void __mm_update_max_cids(struct mm_mm_cid *mc)
static inline unsigned int mm_cid_calc_pcpu_thrs(struct mm_mm_cid *mc)
{
- unsigned int opt_cids;
+ unsigned int nr_cpus = mc->nr_cpus_allowed;
- opt_cids = min(mc->nr_cpus_allowed, mc->users);
/* Has to be at least 1 because 0 indicates PCPU mode off */
- return max(min(opt_cids - opt_cids / 4, num_possible_cpus() / 2), 1);
+ return max(min(nr_cpus - nr_cpus / 4, num_possible_cpus() / 2), 1);
}
static bool mm_update_max_cids(struct mm_struct *mm)
diff --git a/kernel/sched/ext/cid.c b/kernel/sched/ext/cid.c
index a5330b760ecd..8e04a8494e11 100644
--- a/kernel/sched/ext/cid.c
+++ b/kernel/sched/ext/cid.c
@@ -309,6 +309,12 @@ s32 scx_cid_init(struct scx_sched *sch)
* empty shard.
*/
cids_in_core = cpumask_weight(core_scratch);
+ if (cids_in_core > SCX_CID_SHARD_MAX_CPUS) {
+ scx_error(sch, "core with %u cpus exceeds max shard size %d",
+ cids_in_core, SCX_CID_SHARD_MAX_CPUS);
+ return -E2BIG;
+ }
+
max_cores = cores_per_shard + (shard_local < nr_large ? 1 : 0);
if (cores_in_shard &&
(cores_in_shard >= max_cores ||
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index 14614d10f387..e5f8358ab5be 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -2178,7 +2178,8 @@ queue_balance_callback(struct rq *rq,
* balance_push() is active, see the comment with
* balance_push_callback.
*/
- if (unlikely(head->next || rq->balance_callback == &balance_push_callback))
+ if (unlikely(head->next || rq->balance_callback == head ||
+ rq->balance_callback == &balance_push_callback))
return;
head->func = func;
diff --git a/kernel/signal.c b/kernel/signal.c
index e433de93b430..cb6ec7054eee 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -4553,11 +4553,12 @@ int restore_altstack(const stack_t __user *uss)
int __save_altstack(stack_t __user *uss, unsigned long sp)
{
- struct task_struct *t = current;
- int err = __put_user((void __user *)t->sas_ss_sp, &uss->ss_sp) |
- __put_user(t->sas_ss_flags, &uss->ss_flags) |
- __put_user(t->sas_ss_size, &uss->ss_size);
- return err;
+ scoped_user_write_access(uss, Efault)
+ unsafe_save_altstack(uss, sp, Efault);
+ return 0;
+
+Efault:
+ return -EFAULT;
}
#ifdef CONFIG_COMPAT
@@ -4606,13 +4607,12 @@ int compat_restore_altstack(const compat_stack_t __user *uss)
int __compat_save_altstack(compat_stack_t __user *uss, unsigned long sp)
{
- int err;
- struct task_struct *t = current;
- err = __put_user(ptr_to_compat((void __user *)t->sas_ss_sp),
- &uss->ss_sp) |
- __put_user(t->sas_ss_flags, &uss->ss_flags) |
- __put_user(t->sas_ss_size, &uss->ss_size);
- return err;
+ scoped_user_write_access(uss, Efault)
+ unsafe_compat_save_altstack(uss, sp, Efault);
+ return 0;
+
+Efault:
+ return -EFAULT;
}
#endif
@@ -4790,12 +4790,12 @@ SYSCALL_DEFINE3(sigaction, int, sig,
if (act) {
old_sigset_t mask;
- if (!access_ok(act, sizeof(*act)) ||
- __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
- __get_user(new_ka.sa.sa_restorer, &act->sa_restorer) ||
- __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
- __get_user(mask, &act->sa_mask))
- return -EFAULT;
+ scoped_user_read_access(act, Efault) {
+ unsafe_get_user(new_ka.sa.sa_handler, &act->sa_handler, Efault);
+ unsafe_get_user(new_ka.sa.sa_restorer, &act->sa_restorer, Efault);
+ unsafe_get_user(new_ka.sa.sa_flags, &act->sa_flags, Efault);
+ unsafe_get_user(mask, &act->sa_mask, Efault);
+ }
#ifdef __ARCH_HAS_KA_RESTORER
new_ka.ka_restorer = NULL;
#endif
@@ -4805,15 +4805,18 @@ SYSCALL_DEFINE3(sigaction, int, sig,
ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
if (!ret && oact) {
- if (!access_ok(oact, sizeof(*oact)) ||
- __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
- __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) ||
- __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
- __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
- return -EFAULT;
+ scoped_user_write_access(oact, Efault) {
+ unsafe_put_user(old_ka.sa.sa_handler, &oact->sa_handler, Efault);
+ unsafe_put_user(old_ka.sa.sa_restorer, &oact->sa_restorer, Efault);
+ unsafe_put_user(old_ka.sa.sa_flags, &oact->sa_flags, Efault);
+ unsafe_put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask, Efault);
+ }
}
return ret;
+
+Efault:
+ return -EFAULT;
}
#endif
#ifdef CONFIG_COMPAT_OLD_SIGACTION
@@ -4827,12 +4830,12 @@ COMPAT_SYSCALL_DEFINE3(sigaction, int, sig,
compat_uptr_t handler, restorer;
if (act) {
- if (!access_ok(act, sizeof(*act)) ||
- __get_user(handler, &act->sa_handler) ||
- __get_user(restorer, &act->sa_restorer) ||
- __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
- __get_user(mask, &act->sa_mask))
- return -EFAULT;
+ scoped_user_read_access(act, Efault) {
+ unsafe_get_user(handler, &act->sa_handler, Efault);
+ unsafe_get_user(restorer, &act->sa_restorer, Efault);
+ unsafe_get_user(new_ka.sa.sa_flags, &act->sa_flags, Efault);
+ unsafe_get_user(mask, &act->sa_mask, Efault);
+ }
#ifdef __ARCH_HAS_KA_RESTORER
new_ka.ka_restorer = NULL;
@@ -4845,16 +4848,19 @@ COMPAT_SYSCALL_DEFINE3(sigaction, int, sig,
ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
if (!ret && oact) {
- if (!access_ok(oact, sizeof(*oact)) ||
- __put_user(ptr_to_compat(old_ka.sa.sa_handler),
- &oact->sa_handler) ||
- __put_user(ptr_to_compat(old_ka.sa.sa_restorer),
- &oact->sa_restorer) ||
- __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
- __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
- return -EFAULT;
+ scoped_user_write_access(oact, Efault) {
+ unsafe_put_user(ptr_to_compat(old_ka.sa.sa_handler),
+ &oact->sa_handler, Efault);
+ unsafe_put_user(ptr_to_compat(old_ka.sa.sa_restorer),
+ &oact->sa_restorer, Efault);
+ unsafe_put_user(old_ka.sa.sa_flags, &oact->sa_flags, Efault);
+ unsafe_put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask, Efault);
+ }
}
return ret;
+
+Efault:
+ return -EFAULT;
}
#endif
diff --git a/kernel/time/timer.c b/kernel/time/timer.c
index 42afdcb229d8..a3c4e20a4e36 100644
--- a/kernel/time/timer.c
+++ b/kernel/time/timer.c
@@ -44,6 +44,7 @@
#include <linux/compat.h>
#include <linux/random.h>
#include <linux/sysctl.h>
+#include <linux/bitmap.h>
#include <linux/uaccess.h>
#include <asm/unistd.h>
@@ -2541,6 +2542,7 @@ int timers_dead_cpu(unsigned int cpu)
for (i = 0; i < WHEEL_SIZE; i++)
migrate_timer_list(new_base, old_base->vectors + i);
+ bitmap_zero(old_base->pending_map, WHEEL_SIZE);
raw_spin_unlock(&old_base->lock);
raw_spin_unlock_irq(&new_base->lock);
put_cpu_ptr(&timer_bases);
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
index 304b426bd44d..dfac5e1b8f40 100644
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -2404,7 +2404,7 @@ static int copy_user_syms(struct user_syms *us, unsigned long __user *usyms, u32
goto error;
for (p = buf, i = 0; i < cnt; i++) {
- if (__get_user(usymbol, usyms + i)) {
+ if (get_user(usymbol, usyms + i)) {
err = -EFAULT;
goto error;
}
@@ -3311,8 +3311,8 @@ int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr
/*
* All uoffsets/uref_ctr_offsets/ucookies arrays have the same value
- * size, we need to check their address range is safe for __get_user
- * calls.
+ * size. Check their address ranges up front, so that a bad pointer
+ * fails before anything is looked up or allocated.
*/
size = sizeof(*uoffsets) * cnt;
if (!access_ok(uoffsets, size) || !access_ok(uref_ctr_offsets, size) ||
@@ -3347,7 +3347,7 @@ int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr
goto error_free;
for (i = 0; i < cnt; i++) {
- if (__get_user(uprobes[i].offset, uoffsets + i)) {
+ if (get_user(uprobes[i].offset, uoffsets + i)) {
err = -EFAULT;
goto error_free;
}
@@ -3355,11 +3355,11 @@ int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr
err = -EINVAL;
goto error_free;
}
- if (uref_ctr_offsets && __get_user(uprobes[i].ref_ctr_offset, uref_ctr_offsets + i)) {
+ if (uref_ctr_offsets && get_user(uprobes[i].ref_ctr_offset, uref_ctr_offsets + i)) {
err = -EFAULT;
goto error_free;
}
- if (ucookies && __get_user(uprobes[i].cookie, ucookies + i)) {
+ if (ucookies && get_user(uprobes[i].cookie, ucookies + i)) {
err = -EFAULT;
goto error_free;
}