Merge branch 'akpm' (patches from Andrew)
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 9 Jun 2020 16:54:46 +0000 (09:54 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 9 Jun 2020 16:54:46 +0000 (09:54 -0700)
Merge even more updates from Andrew Morton:

 - a kernel-wide sweep of show_stack()

 - pagetable cleanups

 - abstract out accesses to mmap_sem - prep for mmap_sem scalability work

 - hch's user acess work

Subsystems affected by this patch series: debug, mm/pagemap, mm/maccess,
mm/documentation.

* emailed patches from Andrew Morton <akpm@linux-foundation.org>: (93 commits)
  include/linux/cache.h: expand documentation over __read_mostly
  maccess: return -ERANGE when probe_kernel_read() fails
  x86: use non-set_fs based maccess routines
  maccess: allow architectures to provide kernel probing directly
  maccess: move user access routines together
  maccess: always use strict semantics for probe_kernel_read
  maccess: remove strncpy_from_unsafe
  tracing/kprobes: handle mixed kernel/userspace probes better
  bpf: rework the compat kernel probe handling
  bpf:bpf_seq_printf(): handle potentially unsafe format string better
  bpf: handle the compat string in bpf_trace_copy_string better
  bpf: factor out a bpf_trace_copy_string helper
  maccess: unify the probe kernel arch hooks
  maccess: remove probe_read_common and probe_write_common
  maccess: rename strnlen_unsafe_user to strnlen_user_nofault
  maccess: rename strncpy_from_unsafe_strict to strncpy_from_kernel_nofault
  maccess: rename strncpy_from_unsafe_user to strncpy_from_user_nofault
  maccess: update the top of file comment
  maccess: clarify kerneldoc comments
  maccess: remove duplicate kerneldoc comments
  ...

1  2 
arch/x86/kernel/cpu/bugs.c
arch/x86/kernel/cpu/common.c
kernel/events/uprobes.c

@@@ -15,6 -15,7 +15,7 @@@
  #include <linux/nospec.h>
  #include <linux/prctl.h>
  #include <linux/sched/smt.h>
+ #include <linux/pgtable.h>
  
  #include <asm/spec-ctrl.h>
  #include <asm/cmdline.h>
@@@ -26,7 -27,6 +27,6 @@@
  #include <asm/vmx.h>
  #include <asm/paravirt.h>
  #include <asm/alternative.h>
- #include <asm/pgtable.h>
  #include <asm/set_memory.h>
  #include <asm/intel-family.h>
  #include <asm/e820/api.h>
@@@ -41,7 -41,6 +41,7 @@@ static void __init l1tf_select_mitigati
  static void __init mds_select_mitigation(void);
  static void __init mds_print_mitigation(void);
  static void __init taa_select_mitigation(void);
 +static void __init srbds_select_mitigation(void);
  
  /* The base value of the SPEC_CTRL MSR that always has to be preserved. */
  u64 x86_spec_ctrl_base;
@@@ -109,7 -108,6 +109,7 @@@ void __init check_bugs(void
        l1tf_select_mitigation();
        mds_select_mitigation();
        taa_select_mitigation();
 +      srbds_select_mitigation();
  
        /*
         * As MDS and TAA mitigations are inter-related, print MDS
@@@ -399,97 -397,6 +399,97 @@@ static int __init tsx_async_abort_parse
  }
  early_param("tsx_async_abort", tsx_async_abort_parse_cmdline);
  
 +#undef pr_fmt
 +#define pr_fmt(fmt)   "SRBDS: " fmt
 +
 +enum srbds_mitigations {
 +      SRBDS_MITIGATION_OFF,
 +      SRBDS_MITIGATION_UCODE_NEEDED,
 +      SRBDS_MITIGATION_FULL,
 +      SRBDS_MITIGATION_TSX_OFF,
 +      SRBDS_MITIGATION_HYPERVISOR,
 +};
 +
 +static enum srbds_mitigations srbds_mitigation __ro_after_init = SRBDS_MITIGATION_FULL;
 +
 +static const char * const srbds_strings[] = {
 +      [SRBDS_MITIGATION_OFF]          = "Vulnerable",
 +      [SRBDS_MITIGATION_UCODE_NEEDED] = "Vulnerable: No microcode",
 +      [SRBDS_MITIGATION_FULL]         = "Mitigation: Microcode",
 +      [SRBDS_MITIGATION_TSX_OFF]      = "Mitigation: TSX disabled",
 +      [SRBDS_MITIGATION_HYPERVISOR]   = "Unknown: Dependent on hypervisor status",
 +};
 +
 +static bool srbds_off;
 +
 +void update_srbds_msr(void)
 +{
 +      u64 mcu_ctrl;
 +
 +      if (!boot_cpu_has_bug(X86_BUG_SRBDS))
 +              return;
 +
 +      if (boot_cpu_has(X86_FEATURE_HYPERVISOR))
 +              return;
 +
 +      if (srbds_mitigation == SRBDS_MITIGATION_UCODE_NEEDED)
 +              return;
 +
 +      rdmsrl(MSR_IA32_MCU_OPT_CTRL, mcu_ctrl);
 +
 +      switch (srbds_mitigation) {
 +      case SRBDS_MITIGATION_OFF:
 +      case SRBDS_MITIGATION_TSX_OFF:
 +              mcu_ctrl |= RNGDS_MITG_DIS;
 +              break;
 +      case SRBDS_MITIGATION_FULL:
 +              mcu_ctrl &= ~RNGDS_MITG_DIS;
 +              break;
 +      default:
 +              break;
 +      }
 +
 +      wrmsrl(MSR_IA32_MCU_OPT_CTRL, mcu_ctrl);
 +}
 +
 +static void __init srbds_select_mitigation(void)
 +{
 +      u64 ia32_cap;
 +
 +      if (!boot_cpu_has_bug(X86_BUG_SRBDS))
 +              return;
 +
 +      /*
 +       * Check to see if this is one of the MDS_NO systems supporting
 +       * TSX that are only exposed to SRBDS when TSX is enabled.
 +       */
 +      ia32_cap = x86_read_arch_cap_msr();
 +      if ((ia32_cap & ARCH_CAP_MDS_NO) && !boot_cpu_has(X86_FEATURE_RTM))
 +              srbds_mitigation = SRBDS_MITIGATION_TSX_OFF;
 +      else if (boot_cpu_has(X86_FEATURE_HYPERVISOR))
 +              srbds_mitigation = SRBDS_MITIGATION_HYPERVISOR;
 +      else if (!boot_cpu_has(X86_FEATURE_SRBDS_CTRL))
 +              srbds_mitigation = SRBDS_MITIGATION_UCODE_NEEDED;
 +      else if (cpu_mitigations_off() || srbds_off)
 +              srbds_mitigation = SRBDS_MITIGATION_OFF;
 +
 +      update_srbds_msr();
 +      pr_info("%s\n", srbds_strings[srbds_mitigation]);
 +}
 +
 +static int __init srbds_parse_cmdline(char *str)
 +{
 +      if (!str)
 +              return -EINVAL;
 +
 +      if (!boot_cpu_has_bug(X86_BUG_SRBDS))
 +              return 0;
 +
 +      srbds_off = !strcmp(str, "off");
 +      return 0;
 +}
 +early_param("srbds", srbds_parse_cmdline);
 +
  #undef pr_fmt
  #define pr_fmt(fmt)     "Spectre V1 : " fmt
  
@@@ -1621,11 -1528,6 +1621,11 @@@ static char *ibpb_state(void
        return "";
  }
  
 +static ssize_t srbds_show_state(char *buf)
 +{
 +      return sprintf(buf, "%s\n", srbds_strings[srbds_mitigation]);
 +}
 +
  static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr,
                               char *buf, unsigned int bug)
  {
        case X86_BUG_ITLB_MULTIHIT:
                return itlb_multihit_show_state(buf);
  
 +      case X86_BUG_SRBDS:
 +              return srbds_show_state(buf);
 +
        default:
                break;
        }
@@@ -1719,9 -1618,4 +1719,9 @@@ ssize_t cpu_show_itlb_multihit(struct d
  {
        return cpu_show_common(dev, attr, buf, X86_BUG_ITLB_MULTIHIT);
  }
 +
 +ssize_t cpu_show_srbds(struct device *dev, struct device_attribute *attr, char *buf)
 +{
 +      return cpu_show_common(dev, attr, buf, X86_BUG_SRBDS);
 +}
  #endif
@@@ -21,6 -21,7 +21,7 @@@
  #include <linux/smp.h>
  #include <linux/io.h>
  #include <linux/syscore_ops.h>
+ #include <linux/pgtable.h>
  
  #include <asm/stackprotector.h>
  #include <asm/perf_event.h>
@@@ -35,7 -36,6 +36,6 @@@
  #include <asm/vsyscall.h>
  #include <linux/topology.h>
  #include <linux/cpumask.h>
- #include <asm/pgtable.h>
  #include <linux/atomic.h>
  #include <asm/proto.h>
  #include <asm/setup.h>
@@@ -1073,30 -1073,9 +1073,30 @@@ static const __initconst struct x86_cpu
        {}
  };
  
 -static bool __init cpu_matches(unsigned long which)
 +#define VULNBL_INTEL_STEPPINGS(model, steppings, issues)                 \
 +      X86_MATCH_VENDOR_FAM_MODEL_STEPPINGS_FEATURE(INTEL, 6,             \
 +                                          INTEL_FAM6_##model, steppings, \
 +                                          X86_FEATURE_ANY, issues)
 +
 +#define SRBDS         BIT(0)
 +
 +static const struct x86_cpu_id cpu_vuln_blacklist[] __initconst = {
 +      VULNBL_INTEL_STEPPINGS(IVYBRIDGE,       X86_STEPPING_ANY,               SRBDS),
 +      VULNBL_INTEL_STEPPINGS(HASWELL,         X86_STEPPING_ANY,               SRBDS),
 +      VULNBL_INTEL_STEPPINGS(HASWELL_L,       X86_STEPPING_ANY,               SRBDS),
 +      VULNBL_INTEL_STEPPINGS(HASWELL_G,       X86_STEPPING_ANY,               SRBDS),
 +      VULNBL_INTEL_STEPPINGS(BROADWELL_G,     X86_STEPPING_ANY,               SRBDS),
 +      VULNBL_INTEL_STEPPINGS(BROADWELL,       X86_STEPPING_ANY,               SRBDS),
 +      VULNBL_INTEL_STEPPINGS(SKYLAKE_L,       X86_STEPPING_ANY,               SRBDS),
 +      VULNBL_INTEL_STEPPINGS(SKYLAKE,         X86_STEPPING_ANY,               SRBDS),
 +      VULNBL_INTEL_STEPPINGS(KABYLAKE_L,      X86_STEPPINGS(0x0, 0xC),        SRBDS),
 +      VULNBL_INTEL_STEPPINGS(KABYLAKE,        X86_STEPPINGS(0x0, 0xD),        SRBDS),
 +      {}
 +};
 +
 +static bool __init cpu_matches(const struct x86_cpu_id *table, unsigned long which)
  {
 -      const struct x86_cpu_id *m = x86_match_cpu(cpu_vuln_whitelist);
 +      const struct x86_cpu_id *m = x86_match_cpu(table);
  
        return m && !!(m->driver_data & which);
  }
@@@ -1116,34 -1095,31 +1116,34 @@@ static void __init cpu_set_bug_bits(str
        u64 ia32_cap = x86_read_arch_cap_msr();
  
        /* Set ITLB_MULTIHIT bug if cpu is not in the whitelist and not mitigated */
 -      if (!cpu_matches(NO_ITLB_MULTIHIT) && !(ia32_cap & ARCH_CAP_PSCHANGE_MC_NO))
 +      if (!cpu_matches(cpu_vuln_whitelist, NO_ITLB_MULTIHIT) &&
 +          !(ia32_cap & ARCH_CAP_PSCHANGE_MC_NO))
                setup_force_cpu_bug(X86_BUG_ITLB_MULTIHIT);
  
 -      if (cpu_matches(NO_SPECULATION))
 +      if (cpu_matches(cpu_vuln_whitelist, NO_SPECULATION))
                return;
  
        setup_force_cpu_bug(X86_BUG_SPECTRE_V1);
  
 -      if (!cpu_matches(NO_SPECTRE_V2))
 +      if (!cpu_matches(cpu_vuln_whitelist, NO_SPECTRE_V2))
                setup_force_cpu_bug(X86_BUG_SPECTRE_V2);
  
 -      if (!cpu_matches(NO_SSB) && !(ia32_cap & ARCH_CAP_SSB_NO) &&
 +      if (!cpu_matches(cpu_vuln_whitelist, NO_SSB) &&
 +          !(ia32_cap & ARCH_CAP_SSB_NO) &&
           !cpu_has(c, X86_FEATURE_AMD_SSB_NO))
                setup_force_cpu_bug(X86_BUG_SPEC_STORE_BYPASS);
  
        if (ia32_cap & ARCH_CAP_IBRS_ALL)
                setup_force_cpu_cap(X86_FEATURE_IBRS_ENHANCED);
  
 -      if (!cpu_matches(NO_MDS) && !(ia32_cap & ARCH_CAP_MDS_NO)) {
 +      if (!cpu_matches(cpu_vuln_whitelist, NO_MDS) &&
 +          !(ia32_cap & ARCH_CAP_MDS_NO)) {
                setup_force_cpu_bug(X86_BUG_MDS);
 -              if (cpu_matches(MSBDS_ONLY))
 +              if (cpu_matches(cpu_vuln_whitelist, MSBDS_ONLY))
                        setup_force_cpu_bug(X86_BUG_MSBDS_ONLY);
        }
  
 -      if (!cpu_matches(NO_SWAPGS))
 +      if (!cpu_matches(cpu_vuln_whitelist, NO_SWAPGS))
                setup_force_cpu_bug(X86_BUG_SWAPGS);
  
        /*
             (ia32_cap & ARCH_CAP_TSX_CTRL_MSR)))
                setup_force_cpu_bug(X86_BUG_TAA);
  
 -      if (cpu_matches(NO_MELTDOWN))
 +      /*
 +       * SRBDS affects CPUs which support RDRAND or RDSEED and are listed
 +       * in the vulnerability blacklist.
 +       */
 +      if ((cpu_has(c, X86_FEATURE_RDRAND) ||
 +           cpu_has(c, X86_FEATURE_RDSEED)) &&
 +          cpu_matches(cpu_vuln_blacklist, SRBDS))
 +                  setup_force_cpu_bug(X86_BUG_SRBDS);
 +
 +      if (cpu_matches(cpu_vuln_whitelist, NO_MELTDOWN))
                return;
  
        /* Rogue Data Cache Load? No! */
  
        setup_force_cpu_bug(X86_BUG_CPU_MELTDOWN);
  
 -      if (cpu_matches(NO_L1TF))
 +      if (cpu_matches(cpu_vuln_whitelist, NO_L1TF))
                return;
  
        setup_force_cpu_bug(X86_BUG_L1TF);
@@@ -1607,7 -1574,6 +1607,7 @@@ void identify_secondary_cpu(struct cpui
        mtrr_ap_init();
        validate_apic_and_package_id(c);
        x86_spec_ctrl_setup_ap();
 +      update_srbds_msr();
  }
  
  static __init int setup_noclflush(char *arg)
diff --combined kernel/events/uprobes.c
@@@ -457,7 -457,7 +457,7 @@@ static int update_ref_ctr(struct uprob
   * @vaddr: the virtual address to store the opcode.
   * @opcode: opcode to be written at @vaddr.
   *
-  * Called with mm->mmap_sem held for write.
+  * Called with mm->mmap_lock held for write.
   * Return 0 (success) or a negative errno.
   */
  int uprobe_write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm,
@@@ -861,6 -861,10 +861,6 @@@ static int prepare_uprobe(struct uprob
        if (ret)
                goto out;
  
 -      /* uprobe_write_opcode() assumes we don't cross page boundary */
 -      BUG_ON((uprobe->offset & ~PAGE_MASK) +
 -                      UPROBE_SWBP_INSN_SIZE > PAGE_SIZE);
 -
        smp_wmb(); /* pairs with the smp_rmb() in handle_swbp() */
        set_bit(UPROBE_COPY_INSN, &uprobe->flags);
  
@@@ -1054,7 -1058,7 +1054,7 @@@ register_for_each_vma(struct uprobe *up
                if (err && is_register)
                        goto free;
  
-               down_write(&mm->mmap_sem);
+               mmap_write_lock(mm);
                vma = find_vma(mm, info->vaddr);
                if (!vma || !valid_vma(vma, is_register) ||
                    file_inode(vma->vm_file) != uprobe->inode)
                }
  
   unlock:
-               up_write(&mm->mmap_sem);
+               mmap_write_unlock(mm);
   free:
                mmput(mm);
                info = free_map_info(info);
@@@ -1156,15 -1160,6 +1156,15 @@@ static int __uprobe_register(struct ino
        if (offset > i_size_read(inode))
                return -EINVAL;
  
 +      /*
 +       * This ensures that copy_from_page(), copy_to_page() and
 +       * __update_ref_ctr() can't cross page boundary.
 +       */
 +      if (!IS_ALIGNED(offset, UPROBE_SWBP_INSN_SIZE))
 +              return -EINVAL;
 +      if (!IS_ALIGNED(ref_ctr_offset, sizeof(short)))
 +              return -EINVAL;
 +
   retry:
        uprobe = alloc_uprobe(inode, offset, ref_ctr_offset);
        if (!uprobe)
@@@ -1240,7 -1235,7 +1240,7 @@@ static int unapply_uprobe(struct uprob
        struct vm_area_struct *vma;
        int err = 0;
  
-       down_read(&mm->mmap_sem);
+       mmap_read_lock(mm);
        for (vma = mm->mmap; vma; vma = vma->vm_next) {
                unsigned long vaddr;
                loff_t offset;
                vaddr = offset_to_vaddr(vma, uprobe->offset);
                err |= remove_breakpoint(uprobe, mm, vaddr);
        }
-       up_read(&mm->mmap_sem);
+       mmap_read_unlock(mm);
  
        return err;
  }
@@@ -1354,7 -1349,7 +1354,7 @@@ static int delayed_ref_ctr_inc(struct v
  }
  
  /*
-  * Called from mmap_region/vma_adjust with mm->mmap_sem acquired.
+  * Called from mmap_region/vma_adjust with mm->mmap_lock acquired.
   *
   * Currently we ignore all errors and always return 0, the callers
   * can't handle the failure anyway.
@@@ -1444,7 -1439,7 +1444,7 @@@ static int xol_add_vma(struct mm_struc
        struct vm_area_struct *vma;
        int ret;
  
-       if (down_write_killable(&mm->mmap_sem))
+       if (mmap_write_lock_killable(mm))
                return -EINTR;
  
        if (mm->uprobes_state.xol_area) {
        /* pairs with get_xol_area() */
        smp_store_release(&mm->uprobes_state.xol_area, area); /* ^^^ */
   fail:
-       up_write(&mm->mmap_sem);
+       mmap_write_unlock(mm);
  
        return ret;
  }
@@@ -2013,9 -2008,6 +2013,9 @@@ static int is_trap_at_addr(struct mm_st
        uprobe_opcode_t opcode;
        int result;
  
 +      if (WARN_ON_ONCE(!IS_ALIGNED(vaddr, UPROBE_SWBP_INSN_SIZE)))
 +              return -EINVAL;
 +
        pagefault_disable();
        result = __get_user(opcode, (uprobe_opcode_t __user *)vaddr);
        pagefault_enable();
@@@ -2047,7 -2039,7 +2047,7 @@@ static struct uprobe *find_active_uprob
        struct uprobe *uprobe = NULL;
        struct vm_area_struct *vma;
  
-       down_read(&mm->mmap_sem);
+       mmap_read_lock(mm);
        vma = find_vma(mm, bp_vaddr);
        if (vma && vma->vm_start <= bp_vaddr) {
                if (valid_vma(vma, false)) {
  
        if (!uprobe && test_and_clear_bit(MMF_RECALC_UPROBES, &mm->flags))
                mmf_recalc_uprobes(mm);
-       up_read(&mm->mmap_sem);
+       mmap_read_unlock(mm);
  
        return uprobe;
  }