commit:     ea4709ae5b6d7054a381c8c5ee5db3980e0e543f
Author:     Alice Ferrazzi <alicef <AT> gentoo <DOT> org>
AuthorDate: Thu Apr 27 09:42:05 2017 +0000
Commit:     Alice Ferrazzi <alicef <AT> gentoo <DOT> org>
CommitDate: Thu Apr 27 09:42:05 2017 +0000
URL:        https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=ea4709ae

Linux patch 4.10.13

 0000_README              |   4 +
 1012_linux-4.10.13.patch | 814 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 818 insertions(+)

diff --git a/0000_README b/0000_README
index e55a9e7..0aa6665 100644
--- a/0000_README
+++ b/0000_README
@@ -91,6 +91,10 @@ Patch:  1011_linux-4.10.12.patch
 From:   http://www.kernel.org
 Desc:   Linux 4.10.12
 
+Patch:  1012_linux-4.10.13.patch
+From:   http://www.kernel.org
+Desc:   Linux 4.10.13
+
 Patch:  1500_XATTR_USER_PREFIX.patch
 From:   https://bugs.gentoo.org/show_bug.cgi?id=470644
 Desc:   Support for namespace user.pax.* on tmpfs.

diff --git a/1012_linux-4.10.13.patch b/1012_linux-4.10.13.patch
new file mode 100644
index 0000000..7c9db8c
--- /dev/null
+++ b/1012_linux-4.10.13.patch
@@ -0,0 +1,814 @@
+diff --git a/Makefile b/Makefile
+index 9689d3f644ea..8285f4de02d1 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,6 +1,6 @@
+ VERSION = 4
+ PATCHLEVEL = 10
+-SUBLEVEL = 12
++SUBLEVEL = 13
+ EXTRAVERSION =
+ NAME = Fearless Coyote
+ 
+diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
+index 6432d4bf08c8..767ef6d68c9e 100644
+--- a/arch/powerpc/kernel/entry_64.S
++++ b/arch/powerpc/kernel/entry_64.S
+@@ -689,7 +689,7 @@ resume_kernel:
+ 
+       addi    r8,r1,INT_FRAME_SIZE    /* Get the kprobed function entry */
+ 
+-      lwz     r3,GPR1(r1)
++      ld      r3,GPR1(r1)
+       subi    r3,r3,INT_FRAME_SIZE    /* dst: Allocate a trampoline exception 
frame */
+       mr      r4,r1                   /* src:  current exception frame */
+       mr      r1,r3                   /* Reroute the trampoline frame to r1 */
+@@ -703,8 +703,8 @@ resume_kernel:
+       addi    r6,r6,8
+       bdnz    2b
+ 
+-      /* Do real store operation to complete stwu */
+-      lwz     r5,GPR1(r1)
++      /* Do real store operation to complete stdu */
++      ld      r5,GPR1(r1)
+       std     r8,0(r5)
+ 
+       /* Clear _TIF_EMULATE_STACK_STORE flag */
+diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h
+index 0362cd5fa187..0cea7026e4ff 100644
+--- a/arch/s390/include/asm/pgtable.h
++++ b/arch/s390/include/asm/pgtable.h
+@@ -1029,6 +1029,8 @@ int get_guest_storage_key(struct mm_struct *mm, unsigned 
long addr,
+ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
+                             pte_t *ptep, pte_t entry)
+ {
++      if (pte_present(entry))
++              pte_val(entry) &= ~_PAGE_UNUSED;
+       if (mm_has_pgste(mm))
+               ptep_set_pte_at(mm, addr, ptep, entry);
+       else
+diff --git a/arch/x86/kernel/cpu/mcheck/mce-genpool.c 
b/arch/x86/kernel/cpu/mcheck/mce-genpool.c
+index 93d824ec3120..040af1939460 100644
+--- a/arch/x86/kernel/cpu/mcheck/mce-genpool.c
++++ b/arch/x86/kernel/cpu/mcheck/mce-genpool.c
+@@ -85,7 +85,7 @@ void mce_gen_pool_process(void)
+       head = llist_reverse_order(head);
+       llist_for_each_entry_safe(node, tmp, head, llnode) {
+               mce = &node->mce;
+-              atomic_notifier_call_chain(&x86_mce_decoder_chain, 0, mce);
++              blocking_notifier_call_chain(&x86_mce_decoder_chain, 0, mce);
+               gen_pool_free(mce_evt_pool, (unsigned long)node, sizeof(*node));
+       }
+ }
+diff --git a/arch/x86/kernel/cpu/mcheck/mce-internal.h 
b/arch/x86/kernel/cpu/mcheck/mce-internal.h
+index cd74a3f00aea..de20902ecf23 100644
+--- a/arch/x86/kernel/cpu/mcheck/mce-internal.h
++++ b/arch/x86/kernel/cpu/mcheck/mce-internal.h
+@@ -13,7 +13,7 @@ enum severity_level {
+       MCE_PANIC_SEVERITY,
+ };
+ 
+-extern struct atomic_notifier_head x86_mce_decoder_chain;
++extern struct blocking_notifier_head x86_mce_decoder_chain;
+ 
+ #define ATTR_LEN              16
+ #define INITIAL_CHECK_INTERVAL        5 * 60 /* 5 minutes */
+diff --git a/arch/x86/kernel/cpu/mcheck/mce.c 
b/arch/x86/kernel/cpu/mcheck/mce.c
+index 036fc03aefbd..fcf8b8d6ebfb 100644
+--- a/arch/x86/kernel/cpu/mcheck/mce.c
++++ b/arch/x86/kernel/cpu/mcheck/mce.c
+@@ -123,7 +123,7 @@ static void (*quirk_no_way_out)(int bank, struct mce *m, 
struct pt_regs *regs);
+  * CPU/chipset specific EDAC code can register a notifier call here to print
+  * MCE errors in a human-readable form.
+  */
+-ATOMIC_NOTIFIER_HEAD(x86_mce_decoder_chain);
++BLOCKING_NOTIFIER_HEAD(x86_mce_decoder_chain);
+ 
+ /* Do initial initialization of a struct mce */
+ void mce_setup(struct mce *m)
+@@ -223,7 +223,7 @@ void mce_register_decode_chain(struct notifier_block *nb)
+       if (nb != &mce_srao_nb && nb->priority == INT_MAX)
+               nb->priority -= 1;
+ 
+-      atomic_notifier_chain_register(&x86_mce_decoder_chain, nb);
++      blocking_notifier_chain_register(&x86_mce_decoder_chain, nb);
+ }
+ EXPORT_SYMBOL_GPL(mce_register_decode_chain);
+ 
+@@ -231,7 +231,7 @@ void mce_unregister_decode_chain(struct notifier_block *nb)
+ {
+       atomic_dec(&num_notifiers);
+ 
+-      atomic_notifier_chain_unregister(&x86_mce_decoder_chain, nb);
++      blocking_notifier_chain_unregister(&x86_mce_decoder_chain, nb);
+ }
+ EXPORT_SYMBOL_GPL(mce_unregister_decode_chain);
+ 
+@@ -324,18 +324,7 @@ static void __print_mce(struct mce *m)
+ 
+ static void print_mce(struct mce *m)
+ {
+-      int ret = 0;
+-
+       __print_mce(m);
+-
+-      /*
+-       * Print out human-readable details about the MCE error,
+-       * (if the CPU has an implementation for that)
+-       */
+-      ret = atomic_notifier_call_chain(&x86_mce_decoder_chain, 0, m);
+-      if (ret == NOTIFY_STOP)
+-              return;
+-
+       pr_emerg_ratelimited(HW_ERR "Run the above through 'mcelog --ascii'\n");
+ }
+ 
+diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c 
b/arch/x86/kernel/cpu/mcheck/mce_amd.c
+index a5fd137417a2..b44a25d77a84 100644
+--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
++++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
+@@ -60,7 +60,7 @@ static const char * const th_names[] = {
+       "load_store",
+       "insn_fetch",
+       "combined_unit",
+-      "",
++      "decode_unit",
+       "northbridge",
+       "execution_unit",
+ };
+diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
+index fcd4ce6f78d5..1c2b846c5776 100644
+--- a/drivers/acpi/power.c
++++ b/drivers/acpi/power.c
+@@ -200,6 +200,7 @@ static int acpi_power_get_list_state(struct list_head 
*list, int *state)
+               return -EINVAL;
+ 
+       /* The state of the list is 'on' IFF all resources are 'on'. */
++      cur_state = 0;
+       list_for_each_entry(entry, list, node) {
+               struct acpi_power_resource *resource = entry->resource;
+               acpi_handle handle = resource->device.handle;
+diff --git a/drivers/dax/Kconfig b/drivers/dax/Kconfig
+index 3e2ab3b14eea..9e95bf94eb13 100644
+--- a/drivers/dax/Kconfig
++++ b/drivers/dax/Kconfig
+@@ -2,6 +2,7 @@ menuconfig DEV_DAX
+       tristate "DAX: direct access to differentiated memory"
+       default m if NVDIMM_DAX
+       depends on TRANSPARENT_HUGEPAGE
++      select SRCU
+       help
+         Support raw access to differentiated (persistence, bandwidth,
+         latency...) memory via an mmap(2) capable character
+diff --git a/drivers/dax/dax.c b/drivers/dax/dax.c
+index 20ab6bf9d1c7..53a016c3dffa 100644
+--- a/drivers/dax/dax.c
++++ b/drivers/dax/dax.c
+@@ -24,6 +24,7 @@
+ #include "dax.h"
+ 
+ static dev_t dax_devt;
++DEFINE_STATIC_SRCU(dax_srcu);
+ static struct class *dax_class;
+ static DEFINE_IDA(dax_minor_ida);
+ static int nr_dax = CONFIG_NR_DEV_DAX;
+@@ -59,7 +60,7 @@ struct dax_region {
+  * @region - parent region
+  * @dev - device backing the character device
+  * @cdev - core chardev data
+- * @alive - !alive + rcu grace period == no new mappings can be established
++ * @alive - !alive + srcu grace period == no new mappings can be established
+  * @id - child id in the region
+  * @num_resources - number of physical address extents in this device
+  * @res - array of physical address ranges
+@@ -530,7 +531,7 @@ static int __dax_dev_pmd_fault(struct dax_dev *dax_dev,
+ static int dax_dev_pmd_fault(struct vm_area_struct *vma, unsigned long addr,
+               pmd_t *pmd, unsigned int flags)
+ {
+-      int rc;
++      int rc, id;
+       struct file *filp = vma->vm_file;
+       struct dax_dev *dax_dev = filp->private_data;
+ 
+@@ -538,9 +539,9 @@ static int dax_dev_pmd_fault(struct vm_area_struct *vma, 
unsigned long addr,
+                       current->comm, (flags & FAULT_FLAG_WRITE)
+                       ? "write" : "read", vma->vm_start, vma->vm_end);
+ 
+-      rcu_read_lock();
++      id = srcu_read_lock(&dax_srcu);
+       rc = __dax_dev_pmd_fault(dax_dev, vma, addr, pmd, flags);
+-      rcu_read_unlock();
++      srcu_read_unlock(&dax_srcu, id);
+ 
+       return rc;
+ }
+@@ -656,11 +657,11 @@ static void unregister_dax_dev(void *dev)
+        * Note, rcu is not protecting the liveness of dax_dev, rcu is
+        * ensuring that any fault handlers that might have seen
+        * dax_dev->alive == true, have completed.  Any fault handlers
+-       * that start after synchronize_rcu() has started will abort
++       * that start after synchronize_srcu() has started will abort
+        * upon seeing dax_dev->alive == false.
+        */
+       dax_dev->alive = false;
+-      synchronize_rcu();
++      synchronize_srcu(&dax_srcu);
+       unmap_mapping_range(dax_dev->inode->i_mapping, 0, 0, 1);
+       cdev_del(cdev);
+       device_unregister(dev);
+diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
+index 6ef4f2fcfe43..0611f082f392 100644
+--- a/drivers/hid/wacom_wac.c
++++ b/drivers/hid/wacom_wac.c
+@@ -1798,7 +1798,7 @@ static void wacom_wac_pen_event(struct hid_device *hdev, 
struct hid_field *field
+               return;
+       case HID_DG_TOOLSERIALNUMBER:
+               wacom_wac->serial[0] = (wacom_wac->serial[0] & ~0xFFFFFFFFULL);
+-              wacom_wac->serial[0] |= value;
++              wacom_wac->serial[0] |= (__u32)value;
+               return;
+       case WACOM_HID_WD_SENSE:
+               wacom_wac->hid_data.sense_state = value;
+diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
+index db7d1d666ac1..7826994c45bf 100644
+--- a/drivers/input/mouse/elantech.c
++++ b/drivers/input/mouse/elantech.c
+@@ -1118,6 +1118,7 @@ static int elantech_get_resolution_v4(struct psmouse 
*psmouse,
+  * Asus UX32VD             0x361f02        00, 15, 0e      clickpad
+  * Avatar AVIU-145A2       0x361f00        ?               clickpad
+  * Fujitsu LIFEBOOK E544   0x470f00        d0, 12, 09      2 hw buttons
++ * Fujitsu LIFEBOOK E547   0x470f00        50, 12, 09      2 hw buttons
+  * Fujitsu LIFEBOOK E554   0x570f01        40, 14, 0c      2 hw buttons
+  * Fujitsu T725            0x470f01        05, 12, 09      2 hw buttons
+  * Fujitsu H730            0x570f00        c0, 14, 0c      3 hw buttons (**)
+@@ -1524,6 +1525,13 @@ static const struct dmi_system_id 
elantech_dmi_force_crc_enabled[] = {
+               },
+       },
+       {
++              /* Fujitsu LIFEBOOK E547 does not work with crc_enabled == 0 */
++              .matches = {
++                      DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
++                      DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK E547"),
++              },
++      },
++      {
+               /* Fujitsu LIFEBOOK E554  does not work with crc_enabled == 0 */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
+index 73db08558e4d..0a634d23b2ef 100644
+--- a/drivers/mmc/host/dw_mmc.c
++++ b/drivers/mmc/host/dw_mmc.c
+@@ -22,6 +22,7 @@
+ #include <linux/ioport.h>
+ #include <linux/module.h>
+ #include <linux/platform_device.h>
++#include <linux/pm_runtime.h>
+ #include <linux/seq_file.h>
+ #include <linux/slab.h>
+ #include <linux/stat.h>
+@@ -1179,11 +1180,13 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot, 
bool force_clkinit)
+               if ((clock != slot->__clk_old &&
+                       !test_bit(DW_MMC_CARD_NEEDS_POLL, &slot->flags)) ||
+                       force_clkinit) {
+-                      dev_info(&slot->mmc->class_dev,
+-                               "Bus speed (slot %d) = %dHz (slot req %dHz, 
actual %dHZ div = %d)\n",
+-                               slot->id, host->bus_hz, clock,
+-                               div ? ((host->bus_hz / div) >> 1) :
+-                               host->bus_hz, div);
++                      /* Silent the verbose log if calling from PM context */
++                      if (!force_clkinit)
++                              dev_info(&slot->mmc->class_dev,
++                                       "Bus speed (slot %d) = %dHz (slot req 
%dHz, actual %dHZ div = %d)\n",
++                                       slot->id, host->bus_hz, clock,
++                                       div ? ((host->bus_hz / div) >> 1) :
++                                       host->bus_hz, div);
+ 
+                       /*
+                        * If card is polling, display the message only
+@@ -1616,10 +1619,16 @@ static void dw_mci_init_card(struct mmc_host *mmc, 
struct mmc_card *card)
+ 
+               if (card->type == MMC_TYPE_SDIO ||
+                   card->type == MMC_TYPE_SD_COMBO) {
+-                      set_bit(DW_MMC_CARD_NO_LOW_PWR, &slot->flags);
++                      if (!test_bit(DW_MMC_CARD_NO_LOW_PWR, &slot->flags)) {
++                              pm_runtime_get_noresume(mmc->parent);
++                              set_bit(DW_MMC_CARD_NO_LOW_PWR, &slot->flags);
++                      }
+                       clk_en_a = clk_en_a_old & ~clken_low_pwr;
+               } else {
+-                      clear_bit(DW_MMC_CARD_NO_LOW_PWR, &slot->flags);
++                      if (test_bit(DW_MMC_CARD_NO_LOW_PWR, &slot->flags)) {
++                              pm_runtime_put_noidle(mmc->parent);
++                              clear_bit(DW_MMC_CARD_NO_LOW_PWR, &slot->flags);
++                      }
+                       clk_en_a = clk_en_a_old | clken_low_pwr;
+               }
+ 
+diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c 
b/drivers/mmc/host/sdhci-esdhc-imx.c
+index 7123ef96ed18..445fc47dc3e7 100644
+--- a/drivers/mmc/host/sdhci-esdhc-imx.c
++++ b/drivers/mmc/host/sdhci-esdhc-imx.c
+@@ -830,6 +830,7 @@ static int esdhc_change_pinstate(struct sdhci_host *host,
+ 
+       switch (uhs) {
+       case MMC_TIMING_UHS_SDR50:
++      case MMC_TIMING_UHS_DDR50:
+               pinctrl = imx_data->pins_100mhz;
+               break;
+       case MMC_TIMING_UHS_SDR104:
+diff --git a/drivers/mtd/ubi/upd.c b/drivers/mtd/ubi/upd.c
+index 0134ba32a057..39712560b4c1 100644
+--- a/drivers/mtd/ubi/upd.c
++++ b/drivers/mtd/ubi/upd.c
+@@ -148,11 +148,11 @@ int ubi_start_update(struct ubi_device *ubi, struct 
ubi_volume *vol,
+                       return err;
+       }
+ 
+-      if (bytes == 0) {
+-              err = ubi_wl_flush(ubi, UBI_ALL, UBI_ALL);
+-              if (err)
+-                      return err;
++      err = ubi_wl_flush(ubi, UBI_ALL, UBI_ALL);
++      if (err)
++              return err;
+ 
++      if (bytes == 0) {
+               err = clear_update_marker(ubi, vol, 0);
+               if (err)
+                       return err;
+diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
+index 7ea8a3393936..54a7d078a3a8 100644
+--- a/fs/cifs/cifsglob.h
++++ b/fs/cifs/cifsglob.h
+@@ -933,7 +933,6 @@ struct cifs_tcon {
+       bool use_persistent:1; /* use persistent instead of durable handles */
+ #ifdef CONFIG_CIFS_SMB2
+       bool print:1;           /* set if connection to printer share */
+-      bool bad_network_name:1; /* set if ret status STATUS_BAD_NETWORK_NAME */
+       __le32 capabilities;
+       __u32 share_flags;
+       __u32 maximal_access;
+diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c
+index fc537c29044e..87b87e091e8e 100644
+--- a/fs/cifs/smb1ops.c
++++ b/fs/cifs/smb1ops.c
+@@ -1015,6 +1015,15 @@ cifs_dir_needs_close(struct cifsFileInfo *cfile)
+       return !cfile->srch_inf.endOfSearch && !cfile->invalidHandle;
+ }
+ 
++static bool
++cifs_can_echo(struct TCP_Server_Info *server)
++{
++      if (server->tcpStatus == CifsGood)
++              return true;
++
++      return false;
++}
++
+ struct smb_version_operations smb1_operations = {
+       .send_cancel = send_nt_cancel,
+       .compare_fids = cifs_compare_fids,
+@@ -1049,6 +1058,7 @@ struct smb_version_operations smb1_operations = {
+       .get_dfs_refer = CIFSGetDFSRefer,
+       .qfs_tcon = cifs_qfs_tcon,
+       .is_path_accessible = cifs_is_path_accessible,
++      .can_echo = cifs_can_echo,
+       .query_path_info = cifs_query_path_info,
+       .query_file_info = cifs_query_file_info,
+       .get_srv_inum = cifs_get_srv_inum,
+diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
+index 7080dac3592c..802185386851 100644
+--- a/fs/cifs/smb2pdu.c
++++ b/fs/cifs/smb2pdu.c
+@@ -1084,9 +1084,6 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, 
const char *tree,
+       else
+               return -EIO;
+ 
+-      if (tcon && tcon->bad_network_name)
+-              return -ENOENT;
+-
+       if ((tcon && tcon->seal) &&
+           ((ses->server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION) == 0)) {
+               cifs_dbg(VFS, "encryption requested but no server support");
+@@ -1188,8 +1185,6 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, 
const char *tree,
+ tcon_error_exit:
+       if (rsp->hdr.Status == STATUS_BAD_NETWORK_NAME) {
+               cifs_dbg(VFS, "BAD_NETWORK_NAME: %s\n", tree);
+-              if (tcon)
+-                      tcon->bad_network_name = true;
+       }
+       goto tcon_exit;
+ }
+diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c
+index 528369f3e472..beaddaf52fba 100644
+--- a/fs/ubifs/dir.c
++++ b/fs/ubifs/dir.c
+@@ -748,6 +748,11 @@ static int ubifs_link(struct dentry *old_dentry, struct 
inode *dir,
+               goto out_fname;
+ 
+       lock_2_inodes(dir, inode);
++
++      /* Handle O_TMPFILE corner case, it is allowed to link a O_TMPFILE. */
++      if (inode->i_nlink == 0)
++              ubifs_delete_orphan(c, inode->i_ino);
++
+       inc_nlink(inode);
+       ihold(inode);
+       inode->i_ctime = ubifs_current_time(inode);
+@@ -768,6 +773,8 @@ static int ubifs_link(struct dentry *old_dentry, struct 
inode *dir,
+       dir->i_size -= sz_change;
+       dir_ui->ui_size = dir->i_size;
+       drop_nlink(inode);
++      if (inode->i_nlink == 0)
++              ubifs_add_orphan(c, inode->i_ino);
+       unlock_2_inodes(dir, inode);
+       ubifs_release_budget(c, &req);
+       iput(inode);
+@@ -1316,9 +1323,6 @@ static int do_rename(struct inode *old_dir, struct 
dentry *old_dentry,
+       unsigned int uninitialized_var(saved_nlink);
+       struct fscrypt_name old_nm, new_nm;
+ 
+-      if (flags & ~RENAME_NOREPLACE)
+-              return -EINVAL;
+-
+       /*
+        * Budget request settings: deletion direntry, new direntry, removing
+        * the old inode, and changing old and new parent directory inodes.
+diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
+index 8df48ccb8af6..79172c35c2b2 100644
+--- a/kernel/trace/ring_buffer.c
++++ b/kernel/trace/ring_buffer.c
+@@ -3404,11 +3404,23 @@ EXPORT_SYMBOL_GPL(ring_buffer_iter_reset);
+ int ring_buffer_iter_empty(struct ring_buffer_iter *iter)
+ {
+       struct ring_buffer_per_cpu *cpu_buffer;
++      struct buffer_page *reader;
++      struct buffer_page *head_page;
++      struct buffer_page *commit_page;
++      unsigned commit;
+ 
+       cpu_buffer = iter->cpu_buffer;
+ 
+-      return iter->head_page == cpu_buffer->commit_page &&
+-              iter->head == rb_commit_index(cpu_buffer);
++      /* Remember, trace recording is off when iterator is in use */
++      reader = cpu_buffer->reader_page;
++      head_page = cpu_buffer->head_page;
++      commit_page = cpu_buffer->commit_page;
++      commit = rb_page_commit(commit_page);
++
++      return ((iter->head_page == commit_page && iter->head == commit) ||
++              (iter->head_page == reader && commit_page == head_page &&
++               head_page->read == commit &&
++               iter->head == rb_page_commit(cpu_buffer->reader_page)));
+ }
+ EXPORT_SYMBOL_GPL(ring_buffer_iter_empty);
+ 
+diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
+index 6ee340a43f18..f76ff14be517 100644
+--- a/kernel/trace/trace.c
++++ b/kernel/trace/trace.c
+@@ -6740,11 +6740,13 @@ ftrace_trace_snapshot_callback(struct ftrace_hash 
*hash,
+               return ret;
+ 
+  out_reg:
+-      ret = register_ftrace_function_probe(glob, ops, count);
++      ret = alloc_snapshot(&global_trace);
++      if (ret < 0)
++              goto out;
+ 
+-      if (ret >= 0)
+-              alloc_snapshot(&global_trace);
++      ret = register_ftrace_function_probe(glob, ops, count);
+ 
++ out:
+       return ret < 0 ? ret : 0;
+ }
+ 
+diff --git a/mm/migrate.c b/mm/migrate.c
+index 87f4d0f81819..c509a92639f6 100644
+--- a/mm/migrate.c
++++ b/mm/migrate.c
+@@ -183,9 +183,9 @@ void putback_movable_pages(struct list_head *l)
+                       unlock_page(page);
+                       put_page(page);
+               } else {
+-                      putback_lru_page(page);
+                       dec_node_page_state(page, NR_ISOLATED_ANON +
+                                       page_is_file_cache(page));
++                      putback_lru_page(page);
+               }
+       }
+ }
+diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
+index 1109e60e9121..03476694a7c8 100644
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -208,6 +208,51 @@ ieee80211_rx_radiotap_hdrlen(struct ieee80211_local 
*local,
+       return len;
+ }
+ 
++static void ieee80211_handle_mu_mimo_mon(struct ieee80211_sub_if_data *sdata,
++                                       struct sk_buff *skb,
++                                       int rtap_vendor_space)
++{
++      struct {
++              struct ieee80211_hdr_3addr hdr;
++              u8 category;
++              u8 action_code;
++      } __packed action;
++
++      if (!sdata)
++              return;
++
++      BUILD_BUG_ON(sizeof(action) != IEEE80211_MIN_ACTION_SIZE + 1);
++
++      if (skb->len < rtap_vendor_space + sizeof(action) +
++                     VHT_MUMIMO_GROUPS_DATA_LEN)
++              return;
++
++      if (!is_valid_ether_addr(sdata->u.mntr.mu_follow_addr))
++              return;
++
++      skb_copy_bits(skb, rtap_vendor_space, &action, sizeof(action));
++
++      if (!ieee80211_is_action(action.hdr.frame_control))
++              return;
++
++      if (action.category != WLAN_CATEGORY_VHT)
++              return;
++
++      if (action.action_code != WLAN_VHT_ACTION_GROUPID_MGMT)
++              return;
++
++      if (!ether_addr_equal(action.hdr.addr1, sdata->u.mntr.mu_follow_addr))
++              return;
++
++      skb = skb_copy(skb, GFP_ATOMIC);
++      if (!skb)
++              return;
++
++      skb->pkt_type = IEEE80211_SDATA_QUEUE_TYPE_FRAME;
++      skb_queue_tail(&sdata->skb_queue, skb);
++      ieee80211_queue_work(&sdata->local->hw, &sdata->work);
++}
++
+ /*
+  * ieee80211_add_rx_radiotap_header - add radiotap header
+  *
+@@ -515,7 +560,6 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct 
sk_buff *origskb,
+       struct net_device *prev_dev = NULL;
+       int present_fcs_len = 0;
+       unsigned int rtap_vendor_space = 0;
+-      struct ieee80211_mgmt *mgmt;
+       struct ieee80211_sub_if_data *monitor_sdata =
+               rcu_dereference(local->monitor_sdata);
+ 
+@@ -553,6 +597,8 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct 
sk_buff *origskb,
+               return remove_monitor_info(local, origskb, rtap_vendor_space);
+       }
+ 
++      ieee80211_handle_mu_mimo_mon(monitor_sdata, origskb, rtap_vendor_space);
++
+       /* room for the radiotap header based on driver features */
+       rt_hdrlen = ieee80211_rx_radiotap_hdrlen(local, status, origskb);
+       needed_headroom = rt_hdrlen - rtap_vendor_space;
+@@ -618,23 +664,6 @@ ieee80211_rx_monitor(struct ieee80211_local *local, 
struct sk_buff *origskb,
+               ieee80211_rx_stats(sdata->dev, skb->len);
+       }
+ 
+-      mgmt = (void *)skb->data;
+-      if (monitor_sdata &&
+-          skb->len >= IEEE80211_MIN_ACTION_SIZE + 1 + 
VHT_MUMIMO_GROUPS_DATA_LEN &&
+-          ieee80211_is_action(mgmt->frame_control) &&
+-          mgmt->u.action.category == WLAN_CATEGORY_VHT &&
+-          mgmt->u.action.u.vht_group_notif.action_code == 
WLAN_VHT_ACTION_GROUPID_MGMT &&
+-          is_valid_ether_addr(monitor_sdata->u.mntr.mu_follow_addr) &&
+-          ether_addr_equal(mgmt->da, monitor_sdata->u.mntr.mu_follow_addr)) {
+-              struct sk_buff *mu_skb = skb_copy(skb, GFP_ATOMIC);
+-
+-              if (mu_skb) {
+-                      mu_skb->pkt_type = IEEE80211_SDATA_QUEUE_TYPE_FRAME;
+-                      skb_queue_tail(&monitor_sdata->skb_queue, mu_skb);
+-                      ieee80211_queue_work(&local->hw, &monitor_sdata->work);
+-              }
+-      }
+-
+       if (prev_dev) {
+               skb->dev = prev_dev;
+               netif_receive_skb(skb);
+@@ -3614,6 +3643,27 @@ static bool ieee80211_accept_frame(struct 
ieee80211_rx_data *rx)
+                           !ether_addr_equal(bssid, hdr->addr1))
+                               return false;
+               }
++
++              /*
++               * 802.11-2016 Table 9-26 says that for data frames, A1 must be
++               * the BSSID - we've checked that already but may have accepted
++               * the wildcard (ff:ff:ff:ff:ff:ff).
++               *
++               * It also says:
++               *      The BSSID of the Data frame is determined as follows:
++               *      a) If the STA is contained within an AP or is associated
++               *         with an AP, the BSSID is the address currently in use
++               *         by the STA contained in the AP.
++               *
++               * So we should not accept data frames with an address that's
++               * multicast.
++               *
++               * Accepting it also opens a security problem because stations
++               * could encrypt it with the GTK and inject traffic that way.
++               */
++              if (ieee80211_is_data(hdr->frame_control) && multicast)
++                      return false;
++
+               return true;
+       case NL80211_IFTYPE_WDS:
+               if (bssid || !ieee80211_is_data(hdr->frame_control))
+diff --git a/security/keys/gc.c b/security/keys/gc.c
+index addf060399e0..9cb4fe4478a1 100644
+--- a/security/keys/gc.c
++++ b/security/keys/gc.c
+@@ -46,7 +46,7 @@ static unsigned long key_gc_flags;
+  * immediately unlinked.
+  */
+ struct key_type key_type_dead = {
+-      .name = "dead",
++      .name = ".dead",
+ };
+ 
+ /*
+diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
+index 04a764f71ec8..3c7f6897fd5b 100644
+--- a/security/keys/keyctl.c
++++ b/security/keys/keyctl.c
+@@ -271,7 +271,8 @@ long keyctl_get_keyring_ID(key_serial_t id, int create)
+  * Create and join an anonymous session keyring or join a named session
+  * keyring, creating it if necessary.  A named session keyring must have 
Search
+  * permission for it to be joined.  Session keyrings without this permit will
+- * be skipped over.
++ * be skipped over.  It is not permitted for userspace to create or join
++ * keyrings whose name begin with a dot.
+  *
+  * If successful, the ID of the joined session keyring will be returned.
+  */
+@@ -288,12 +289,16 @@ long keyctl_join_session_keyring(const char __user 
*_name)
+                       ret = PTR_ERR(name);
+                       goto error;
+               }
++
++              ret = -EPERM;
++              if (name[0] == '.')
++                      goto error_name;
+       }
+ 
+       /* join the session */
+       ret = join_session_keyring(name);
++error_name:
+       kfree(name);
+-
+ error:
+       return ret;
+ }
+@@ -1251,8 +1256,8 @@ long keyctl_reject_key(key_serial_t id, unsigned 
timeout, unsigned error,
+  * Read or set the default keyring in which request_key() will cache keys and
+  * return the old setting.
+  *
+- * If a process keyring is specified then this will be created if it doesn't
+- * yet exist.  The old setting will be returned if successful.
++ * If a thread or process keyring is specified then it will be created if it
++ * doesn't yet exist.  The old setting will be returned if successful.
+  */
+ long keyctl_set_reqkey_keyring(int reqkey_defl)
+ {
+@@ -1277,11 +1282,8 @@ long keyctl_set_reqkey_keyring(int reqkey_defl)
+ 
+       case KEY_REQKEY_DEFL_PROCESS_KEYRING:
+               ret = install_process_keyring_to_cred(new);
+-              if (ret < 0) {
+-                      if (ret != -EEXIST)
+-                              goto error;
+-                      ret = 0;
+-              }
++              if (ret < 0)
++                      goto error;
+               goto set;
+ 
+       case KEY_REQKEY_DEFL_DEFAULT:
+diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
+index 918cddcd4516..855b94df1126 100644
+--- a/security/keys/process_keys.c
++++ b/security/keys/process_keys.c
+@@ -127,13 +127,18 @@ int install_user_keyrings(void)
+ }
+ 
+ /*
+- * Install a fresh thread keyring directly to new credentials.  This keyring 
is
+- * allowed to overrun the quota.
++ * Install a thread keyring to the given credentials struct if it didn't have
++ * one already.  This is allowed to overrun the quota.
++ *
++ * Return: 0 if a thread keyring is now present; -errno on failure.
+  */
+ int install_thread_keyring_to_cred(struct cred *new)
+ {
+       struct key *keyring;
+ 
++      if (new->thread_keyring)
++              return 0;
++
+       keyring = keyring_alloc("_tid", new->uid, new->gid, new,
+                               KEY_POS_ALL | KEY_USR_VIEW,
+                               KEY_ALLOC_QUOTA_OVERRUN,
+@@ -146,7 +151,9 @@ int install_thread_keyring_to_cred(struct cred *new)
+ }
+ 
+ /*
+- * Install a fresh thread keyring, discarding the old one.
++ * Install a thread keyring to the current task if it didn't have one already.
++ *
++ * Return: 0 if a thread keyring is now present; -errno on failure.
+  */
+ static int install_thread_keyring(void)
+ {
+@@ -157,8 +164,6 @@ static int install_thread_keyring(void)
+       if (!new)
+               return -ENOMEM;
+ 
+-      BUG_ON(new->thread_keyring);
+-
+       ret = install_thread_keyring_to_cred(new);
+       if (ret < 0) {
+               abort_creds(new);
+@@ -169,17 +174,17 @@ static int install_thread_keyring(void)
+ }
+ 
+ /*
+- * Install a process keyring directly to a credentials struct.
++ * Install a process keyring to the given credentials struct if it didn't have
++ * one already.  This is allowed to overrun the quota.
+  *
+- * Returns -EEXIST if there was already a process keyring, 0 if one installed,
+- * and other value on any other error
++ * Return: 0 if a process keyring is now present; -errno on failure.
+  */
+ int install_process_keyring_to_cred(struct cred *new)
+ {
+       struct key *keyring;
+ 
+       if (new->process_keyring)
+-              return -EEXIST;
++              return 0;
+ 
+       keyring = keyring_alloc("_pid", new->uid, new->gid, new,
+                               KEY_POS_ALL | KEY_USR_VIEW,
+@@ -193,11 +198,9 @@ int install_process_keyring_to_cred(struct cred *new)
+ }
+ 
+ /*
+- * Make sure a process keyring is installed for the current process.  The
+- * existing process keyring is not replaced.
++ * Install a process keyring to the current task if it didn't have one 
already.
+  *
+- * Returns 0 if there is a process keyring by the end of this function, some
+- * error otherwise.
++ * Return: 0 if a process keyring is now present; -errno on failure.
+  */
+ static int install_process_keyring(void)
+ {
+@@ -211,14 +214,18 @@ static int install_process_keyring(void)
+       ret = install_process_keyring_to_cred(new);
+       if (ret < 0) {
+               abort_creds(new);
+-              return ret != -EEXIST ? ret : 0;
++              return ret;
+       }
+ 
+       return commit_creds(new);
+ }
+ 
+ /*
+- * Install a session keyring directly to a credentials struct.
++ * Install the given keyring as the session keyring of the given credentials
++ * struct, replacing the existing one if any.  If the given keyring is NULL,
++ * then install a new anonymous session keyring.
++ *
++ * Return: 0 on success; -errno on failure.
+  */
+ int install_session_keyring_to_cred(struct cred *cred, struct key *keyring)
+ {
+@@ -253,8 +260,11 @@ int install_session_keyring_to_cred(struct cred *cred, 
struct key *keyring)
+ }
+ 
+ /*
+- * Install a session keyring, discarding the old one.  If a keyring is not
+- * supplied, an empty one is invented.
++ * Install the given keyring as the session keyring of the current task,
++ * replacing the existing one if any.  If the given keyring is NULL, then
++ * install a new anonymous session keyring.
++ *
++ * Return: 0 on success; -errno on failure.
+  */
+ static int install_session_keyring(struct key *keyring)
+ {

Reply via email to