#include <linux/mount.h>
#include <linux/uaccess.h>
+#include <linux/mutex.h>
#include <asm/processor.h>
#ifdef CONFIG_X86
+#include <asm/msr.h>
#include <asm/nmi.h>
#include <asm/stacktrace.h>
#include <asm/io.h>
extern char core_pattern[];
extern unsigned int core_pipe_limit;
#endif
+#ifdef CONFIG_USER_NS
+extern int unprivileged_userns_clone;
+#endif
extern int pid_max;
extern int pid_max_min, pid_max_max;
extern int percpu_pagelist_fraction;
void __user *buffer, size_t *lenp, loff_t *ppos);
#endif
+#ifdef CONFIG_X86
+int proc_dointvec_ibrs_ctrl(struct ctl_table *table, int write,
+ void __user *buffer, size_t *lenp, loff_t *ppos);
+int proc_dointvec_ibpb_ctrl(struct ctl_table *table, int write,
+ void __user *buffer, size_t *lenp, loff_t *ppos);
+int proc_dointvec_ibrs_dump(struct ctl_table *table, int write,
+ void __user *buffer, size_t *lenp, loff_t *ppos);
+#endif
+
#ifdef CONFIG_MAGIC_SYSRQ
/* Note: sysrq code uses it's own private copy */
static int __sysrq_enabled = CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE;
int sysctl_legacy_va_layout;
#endif
+u32 sysctl_ibrs_dump = 0;
+u32 sysctl_ibrs_enabled = 0;
+EXPORT_SYMBOL(sysctl_ibrs_enabled);
+u32 sysctl_ibpb_enabled = 0;
+EXPORT_SYMBOL(sysctl_ibpb_enabled);
+
/* The default sysctl tables: */
static struct ctl_table sysctl_base_table[] = {
.data = &sysctl_sched_time_avg,
.maxlen = sizeof(unsigned int),
.mode = 0644,
- .proc_handler = proc_dointvec,
+ .proc_handler = proc_dointvec_minmax,
+ .extra1 = &one,
},
#ifdef CONFIG_SCHEDSTATS
{
.proc_handler = proc_dointvec,
},
#endif
+#ifdef CONFIG_USER_NS
+ {
+ .procname = "unprivileged_userns_clone",
+ .data = &unprivileged_userns_clone,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec,
+ },
+#endif
#ifdef CONFIG_PROC_SYSCTL
{
.procname = "tainted",
.extra1 = &zero,
.extra2 = &one,
},
+#endif
+#ifdef CONFIG_X86
+ {
+ .procname = "ibrs_enabled",
+ .data = &sysctl_ibrs_enabled,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec_ibrs_ctrl,
+ .extra1 = &zero,
+ .extra2 = &two,
+ },
+ {
+ .procname = "ibpb_enabled",
+ .data = &sysctl_ibpb_enabled,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec_ibpb_ctrl,
+ .extra1 = &zero,
+ .extra2 = &one,
+ },
+ {
+ .procname = "ibrs_dump",
+ .data = &sysctl_ibrs_dump,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec_ibrs_dump,
+ .extra1 = &zero,
+ .extra2 = &one,
+ },
#endif
{ }
};
do_proc_dointvec_minmax_conv, ¶m);
}
+#ifdef CONFIG_X86
+int proc_dointvec_ibrs_dump(struct ctl_table *table, int write,
+ void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+ int ret, orig_inuse;
+ unsigned int cpu;
+
+
+ ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
+ printk("sysctl_ibrs_enabled = %u, sysctl_ibpb_enabled = %u\n", sysctl_ibrs_enabled, sysctl_ibpb_enabled);
+ printk("use_ibrs = %d, use_ibpb = %d\n", use_ibrs, use_ibpb);
+ mutex_lock(&spec_ctrl_mutex);
+ orig_inuse = use_ibrs;
+ /* temporary halt to ibrs usage to dump ibrs values */
+ clear_ibrs_inuse();
+ for_each_online_cpu(cpu) {
+ u64 val;
+
+ if (boot_cpu_has(X86_FEATURE_SPEC_CTRL))
+ rdmsrl_on_cpu(cpu, MSR_IA32_SPEC_CTRL, &val);
+ else
+ val = 0;
+ printk("read cpu %d ibrs val %lu\n", cpu, (unsigned long) val);
+ }
+ use_ibrs = orig_inuse;
+ mutex_unlock(&spec_ctrl_mutex);
+ return ret;
+}
+
+int proc_dointvec_ibrs_ctrl(struct ctl_table *table, int write,
+ void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+ int ret;
+ unsigned int cpu;
+
+ ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
+ pr_debug("sysctl_ibrs_enabled = %u, sysctl_ibpb_enabled = %u\n", sysctl_ibrs_enabled, sysctl_ibpb_enabled);
+ pr_debug("before:use_ibrs = %d, use_ibpb = %d\n", use_ibrs, use_ibpb);
+ mutex_lock(&spec_ctrl_mutex);
+ if (sysctl_ibrs_enabled == 0) {
+ /* always set IBRS off */
+ set_ibrs_disabled();
+ if (ibrs_supported) {
+ for_each_online_cpu(cpu)
+ wrmsrl_on_cpu(cpu, MSR_IA32_SPEC_CTRL, 0x0);
+ }
+ } else if (sysctl_ibrs_enabled == 2) {
+ /* always set IBRS on, even in user space */
+ clear_ibrs_disabled();
+ if (ibrs_supported) {
+ for_each_online_cpu(cpu)
+ wrmsrl_on_cpu(cpu, MSR_IA32_SPEC_CTRL, FEATURE_ENABLE_IBRS);
+ } else {
+ sysctl_ibrs_enabled = 0;
+ }
+ } else if (sysctl_ibrs_enabled == 1) {
+ /* use IBRS in kernel */
+ clear_ibrs_disabled();
+ if (!ibrs_inuse)
+ /* platform don't support ibrs */
+ sysctl_ibrs_enabled = 0;
+ }
+ mutex_unlock(&spec_ctrl_mutex);
+ pr_debug("after:use_ibrs = %d, use_ibpb = %d\n", use_ibrs, use_ibpb);
+ return ret;
+}
+
+int proc_dointvec_ibpb_ctrl(struct ctl_table *table, int write,
+ void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+ int ret;
+
+ ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
+ pr_debug("sysctl_ibrs_enabled = %u, sysctl_ibpb_enabled = %u\n", sysctl_ibrs_enabled, sysctl_ibpb_enabled);
+ pr_debug("before:use_ibrs = %d, use_ibpb = %d\n", use_ibrs, use_ibpb);
+ mutex_lock(&spec_ctrl_mutex);
+ if (sysctl_ibpb_enabled == 0)
+ set_ibpb_disabled();
+ else if (sysctl_ibpb_enabled == 1) {
+ clear_ibpb_disabled();
+ if (!ibpb_inuse)
+ /* platform don't support ibpb */
+ sysctl_ibpb_enabled = 0;
+ }
+ mutex_unlock(&spec_ctrl_mutex);
+ pr_debug("after:use_ibrs = %d, use_ibpb = %d\n", use_ibrs, use_ibpb);
+ return ret;
+}
+#endif
+
+
struct do_proc_douintvec_minmax_conv_param {
unsigned int *min;
unsigned int *max;