diff options
Diffstat (limited to 'arch/x86/kernel')
-rw-r--r-- | arch/x86/kernel/cpu/intel_rdt_ctrlmondata.c | 4 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/mtrr/if.c | 2 | ||||
-rw-r--r-- | arch/x86/kernel/macros.S | 16 | ||||
-rw-r--r-- | arch/x86/kernel/process_64.c | 99 | ||||
-rw-r--r-- | arch/x86/kernel/ptrace.c | 9 |
5 files changed, 66 insertions, 64 deletions
diff --git a/arch/x86/kernel/cpu/intel_rdt_ctrlmondata.c b/arch/x86/kernel/cpu/intel_rdt_ctrlmondata.c index 27937458c231..efa4a519f5e5 100644 --- a/arch/x86/kernel/cpu/intel_rdt_ctrlmondata.c +++ b/arch/x86/kernel/cpu/intel_rdt_ctrlmondata.c @@ -23,6 +23,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include <linux/cpu.h> #include <linux/kernfs.h> #include <linux/seq_file.h> #include <linux/slab.h> @@ -310,9 +311,11 @@ ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of, return -EINVAL; buf[nbytes - 1] = '\0'; + cpus_read_lock(); rdtgrp = rdtgroup_kn_lock_live(of->kn); if (!rdtgrp) { rdtgroup_kn_unlock(of->kn); + cpus_read_unlock(); return -ENOENT; } rdt_last_cmd_clear(); @@ -367,6 +370,7 @@ ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of, out: rdtgroup_kn_unlock(of->kn); + cpus_read_unlock(); return ret ?: nbytes; } diff --git a/arch/x86/kernel/cpu/mtrr/if.c b/arch/x86/kernel/cpu/mtrr/if.c index 2e173d47b450..4d36dcc1cf87 100644 --- a/arch/x86/kernel/cpu/mtrr/if.c +++ b/arch/x86/kernel/cpu/mtrr/if.c @@ -165,6 +165,8 @@ mtrr_ioctl(struct file *file, unsigned int cmd, unsigned long __arg) struct mtrr_gentry gentry; void __user *arg = (void __user *) __arg; + memset(&gentry, 0, sizeof(gentry)); + switch (cmd) { case MTRRIOC_ADD_ENTRY: case MTRRIOC_SET_ENTRY: diff --git a/arch/x86/kernel/macros.S b/arch/x86/kernel/macros.S deleted file mode 100644 index 161c95059044..000000000000 --- a/arch/x86/kernel/macros.S +++ /dev/null @@ -1,16 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ - -/* - * This file includes headers whose assembly part includes macros which are - * commonly used. The macros are precompiled into assmebly file which is later - * assembled together with each compiled file. - */ - -#include <linux/compiler.h> -#include <asm/refcount.h> -#include <asm/alternative-asm.h> -#include <asm/bug.h> -#include <asm/paravirt.h> -#include <asm/asm.h> -#include <asm/cpufeature.h> -#include <asm/jump_label.h> diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index bbfbf017065c..ddd4fa718c43 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -339,24 +339,6 @@ static unsigned long x86_fsgsbase_read_task(struct task_struct *task, return base; } -void x86_fsbase_write_cpu(unsigned long fsbase) -{ - /* - * Set the selector to 0 as a notion, that the segment base is - * overwritten, which will be checked for skipping the segment load - * during context switch. - */ - loadseg(FS, 0); - wrmsrl(MSR_FS_BASE, fsbase); -} - -void x86_gsbase_write_cpu_inactive(unsigned long gsbase) -{ - /* Set the selector to 0 for the same reason as %fs above. */ - loadseg(GS, 0); - wrmsrl(MSR_KERNEL_GS_BASE, gsbase); -} - unsigned long x86_fsbase_read_task(struct task_struct *task) { unsigned long fsbase; @@ -385,38 +367,18 @@ unsigned long x86_gsbase_read_task(struct task_struct *task) return gsbase; } -int x86_fsbase_write_task(struct task_struct *task, unsigned long fsbase) +void x86_fsbase_write_task(struct task_struct *task, unsigned long fsbase) { - /* - * Not strictly needed for %fs, but do it for symmetry - * with %gs - */ - if (unlikely(fsbase >= TASK_SIZE_MAX)) - return -EPERM; + WARN_ON_ONCE(task == current); - preempt_disable(); task->thread.fsbase = fsbase; - if (task == current) - x86_fsbase_write_cpu(fsbase); - task->thread.fsindex = 0; - preempt_enable(); - - return 0; } -int x86_gsbase_write_task(struct task_struct *task, unsigned long gsbase) +void x86_gsbase_write_task(struct task_struct *task, unsigned long gsbase) { - if (unlikely(gsbase >= TASK_SIZE_MAX)) - return -EPERM; + WARN_ON_ONCE(task == current); - preempt_disable(); task->thread.gsbase = gsbase; - if (task == current) - x86_gsbase_write_cpu_inactive(gsbase); - task->thread.gsindex = 0; - preempt_enable(); - - return 0; } int copy_thread_tls(unsigned long clone_flags, unsigned long sp, @@ -754,11 +716,60 @@ long do_arch_prctl_64(struct task_struct *task, int option, unsigned long arg2) switch (option) { case ARCH_SET_GS: { - ret = x86_gsbase_write_task(task, arg2); + if (unlikely(arg2 >= TASK_SIZE_MAX)) + return -EPERM; + + preempt_disable(); + /* + * ARCH_SET_GS has always overwritten the index + * and the base. Zero is the most sensible value + * to put in the index, and is the only value that + * makes any sense if FSGSBASE is unavailable. + */ + if (task == current) { + loadseg(GS, 0); + x86_gsbase_write_cpu_inactive(arg2); + + /* + * On non-FSGSBASE systems, save_base_legacy() expects + * that we also fill in thread.gsbase. + */ + task->thread.gsbase = arg2; + + } else { + task->thread.gsindex = 0; + x86_gsbase_write_task(task, arg2); + } + preempt_enable(); break; } case ARCH_SET_FS: { - ret = x86_fsbase_write_task(task, arg2); + /* + * Not strictly needed for %fs, but do it for symmetry + * with %gs + */ + if (unlikely(arg2 >= TASK_SIZE_MAX)) + return -EPERM; + + preempt_disable(); + /* + * Set the selector to 0 for the same reason + * as %gs above. + */ + if (task == current) { + loadseg(FS, 0); + x86_fsbase_write_cpu(arg2); + + /* + * On non-FSGSBASE systems, save_base_legacy() expects + * that we also fill in thread.fsbase. + */ + task->thread.fsbase = arg2; + } else { + task->thread.fsindex = 0; + x86_fsbase_write_task(task, arg2); + } + preempt_enable(); break; } case ARCH_GET_FS: { diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index ffae9b9740fd..4b8ee05dd6ad 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c @@ -397,11 +397,12 @@ static int putreg(struct task_struct *child, if (value >= TASK_SIZE_MAX) return -EIO; /* - * When changing the FS base, use the same - * mechanism as for do_arch_prctl_64(). + * When changing the FS base, use do_arch_prctl_64() + * to set the index to zero and to set the base + * as requested. */ if (child->thread.fsbase != value) - return x86_fsbase_write_task(child, value); + return do_arch_prctl_64(child, ARCH_SET_FS, value); return 0; case offsetof(struct user_regs_struct,gs_base): /* @@ -410,7 +411,7 @@ static int putreg(struct task_struct *child, if (value >= TASK_SIZE_MAX) return -EIO; if (child->thread.gsbase != value) - return x86_gsbase_write_task(child, value); + return do_arch_prctl_64(child, ARCH_SET_GS, value); return 0; #endif } |