diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/bpf/syscall.c | 36 | ||||
| -rw-r--r-- | kernel/cgroup/cpuset.c | 4 | ||||
| -rw-r--r-- | kernel/compat.c | 20 | ||||
| -rw-r--r-- | kernel/entry/syscall_user_dispatch.c | 6 | ||||
| -rw-r--r-- | kernel/events/uprobes.c | 2 | ||||
| -rw-r--r-- | kernel/kexec_core.c | 7 | ||||
| -rw-r--r-- | kernel/ptrace.c | 18 | ||||
| -rw-r--r-- | kernel/sched/core.c | 5 | ||||
| -rw-r--r-- | kernel/sched/ext/cid.c | 6 | ||||
| -rw-r--r-- | kernel/sched/sched.h | 3 | ||||
| -rw-r--r-- | kernel/signal.c | 82 | ||||
| -rw-r--r-- | kernel/time/timer.c | 2 | ||||
| -rw-r--r-- | kernel/trace/bpf_trace.c | 12 |
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; } |
