commit:     deeb81d32b2d6b7408271c5d0483307f20262d08
Author:     Mike Pagano <mpagano <AT> gentoo <DOT> org>
AuthorDate: Wed Mar 16 19:40:25 2016 +0000
Commit:     Mike Pagano <mpagano <AT> gentoo <DOT> org>
CommitDate: Wed Mar 16 19:40:25 2016 +0000
URL:        https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=deeb81d3

Linux patch 3.10.101

 0000_README               |    4 +
 1100_linux-3.10.101.patch | 1493 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 1497 insertions(+)

diff --git a/0000_README b/0000_README
index bdc1498..92f6908 100644
--- a/0000_README
+++ b/0000_README
@@ -442,6 +442,10 @@ Patch:  1099_linux-3.10.100.patch
 From:   http://www.kernel.org
 Desc:   Linux 3.10.100
 
+Patch:  1100_linux-3.10.101.patch
+From:   http://www.kernel.org
+Desc:   Linux 3.10.101
+
 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/1100_linux-3.10.101.patch b/1100_linux-3.10.101.patch
new file mode 100644
index 0000000..d9647df
--- /dev/null
+++ b/1100_linux-3.10.101.patch
@@ -0,0 +1,1493 @@
+diff --git a/Documentation/filesystems/efivarfs.txt 
b/Documentation/filesystems/efivarfs.txt
+index c477af086e65..686a64bba775 100644
+--- a/Documentation/filesystems/efivarfs.txt
++++ b/Documentation/filesystems/efivarfs.txt
+@@ -14,3 +14,10 @@ filesystem.
+ efivarfs is typically mounted like this,
+ 
+       mount -t efivarfs none /sys/firmware/efi/efivars
++
++Due to the presence of numerous firmware bugs where removing non-standard
++UEFI variables causes the system firmware to fail to POST, efivarfs
++files that are not well-known standardized variables are created
++as immutable files.  This doesn't prevent removal - "chattr -i" will work -
++but it does prevent this kind of failure from being accomplished
++accidentally.
+diff --git a/Makefile b/Makefile
+index 40d4d3bf52c3..4be9e643cef0 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,6 +1,6 @@
+ VERSION = 3
+ PATCHLEVEL = 10
+-SUBLEVEL = 100
++SUBLEVEL = 101
+ EXTRAVERSION =
+ NAME = TOSSUG Baby Fish
+ 
+diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c
+index 6ee59a0eb268..48b4cf6b2a24 100644
+--- a/arch/powerpc/kernel/module_64.c
++++ b/arch/powerpc/kernel/module_64.c
+@@ -192,7 +192,7 @@ static void dedotify(Elf64_Sym *syms, unsigned int 
numsyms, char *strtab)
+               if (syms[i].st_shndx == SHN_UNDEF) {
+                       char *name = strtab + syms[i].st_name;
+                       if (name[0] == '.')
+-                              memmove(name, name+1, strlen(name));
++                              syms[i].st_name++;
+               }
+       }
+ }
+diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
+index 04cc2fa7744f..335fe70967a8 100644
+--- a/arch/x86/kvm/vmx.c
++++ b/arch/x86/kvm/vmx.c
+@@ -1487,6 +1487,13 @@ static void add_atomic_switch_msr(struct vcpu_vmx *vmx, 
unsigned msr,
+                       return;
+               }
+               break;
++      case MSR_IA32_PEBS_ENABLE:
++              /* PEBS needs a quiescent period after being disabled (to write
++               * a record).  Disabling PEBS through VMX MSR swapping doesn't
++               * provide that period, so a CPU could write host's record into
++               * guest's memory.
++               */
++              wrmsrl(MSR_IA32_PEBS_ENABLE, 0);
+       }
+ 
+       for (i = 0; i < m->nr; ++i)
+diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
+index 41ba726c1ce2..7f2b6dec4b2b 100644
+--- a/arch/x86/kvm/x86.c
++++ b/arch/x86/kvm/x86.c
+@@ -1941,6 +1941,8 @@ static void accumulate_steal_time(struct kvm_vcpu *vcpu)
+ 
+ static void record_steal_time(struct kvm_vcpu *vcpu)
+ {
++      accumulate_steal_time(vcpu);
++
+       if (!(vcpu->arch.st.msr_val & KVM_MSR_ENABLED))
+               return;
+ 
+@@ -2074,12 +2076,6 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct 
msr_data *msr_info)
+               if (!(data & KVM_MSR_ENABLED))
+                       break;
+ 
+-              vcpu->arch.st.last_steal = current->sched_info.run_delay;
+-
+-              preempt_disable();
+-              accumulate_steal_time(vcpu);
+-              preempt_enable();
+-
+               kvm_make_request(KVM_REQ_STEAL_UPDATE, vcpu);
+ 
+               break;
+@@ -2758,7 +2754,6 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
+               vcpu->cpu = cpu;
+       }
+ 
+-      accumulate_steal_time(vcpu);
+       kvm_make_request(KVM_REQ_STEAL_UPDATE, vcpu);
+ }
+ 
+diff --git a/crypto/af_alg.c b/crypto/af_alg.c
+index 0ca108f3c840..1aaa555fab56 100644
+--- a/crypto/af_alg.c
++++ b/crypto/af_alg.c
+@@ -125,23 +125,6 @@ int af_alg_release(struct socket *sock)
+ }
+ EXPORT_SYMBOL_GPL(af_alg_release);
+ 
+-void af_alg_release_parent(struct sock *sk)
+-{
+-      struct alg_sock *ask = alg_sk(sk);
+-      bool last;
+-
+-      sk = ask->parent;
+-      ask = alg_sk(sk);
+-
+-      lock_sock(sk);
+-      last = !--ask->refcnt;
+-      release_sock(sk);
+-
+-      if (last)
+-              sock_put(sk);
+-}
+-EXPORT_SYMBOL_GPL(af_alg_release_parent);
+-
+ static int alg_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
+ {
+       struct sock *sk = sock->sk;
+@@ -149,7 +132,6 @@ static int alg_bind(struct socket *sock, struct sockaddr 
*uaddr, int addr_len)
+       struct sockaddr_alg *sa = (void *)uaddr;
+       const struct af_alg_type *type;
+       void *private;
+-      int err;
+ 
+       if (sock->state == SS_CONNECTED)
+               return -EINVAL;
+@@ -175,22 +157,16 @@ static int alg_bind(struct socket *sock, struct sockaddr 
*uaddr, int addr_len)
+               return PTR_ERR(private);
+       }
+ 
+-      err = -EBUSY;
+       lock_sock(sk);
+-      if (ask->refcnt)
+-              goto unlock;
+ 
+       swap(ask->type, type);
+       swap(ask->private, private);
+ 
+-      err = 0;
+-
+-unlock:
+       release_sock(sk);
+ 
+       alg_do_release(type, private);
+ 
+-      return err;
++      return 0;
+ }
+ 
+ static int alg_setkey(struct sock *sk, char __user *ukey,
+@@ -223,15 +199,11 @@ static int alg_setsockopt(struct socket *sock, int 
level, int optname,
+       struct sock *sk = sock->sk;
+       struct alg_sock *ask = alg_sk(sk);
+       const struct af_alg_type *type;
+-      int err = -EBUSY;
++      int err = -ENOPROTOOPT;
+ 
+       lock_sock(sk);
+-      if (ask->refcnt)
+-              goto unlock;
+-
+       type = ask->type;
+ 
+-      err = -ENOPROTOOPT;
+       if (level != SOL_ALG || !type)
+               goto unlock;
+ 
+@@ -280,8 +252,7 @@ int af_alg_accept(struct sock *sk, struct socket *newsock)
+ 
+       sk2->sk_family = PF_ALG;
+ 
+-      if (!ask->refcnt++)
+-              sock_hold(sk);
++      sock_hold(sk);
+       alg_sk(sk2)->parent = sk;
+       alg_sk(sk2)->type = type;
+ 
+diff --git a/drivers/firmware/efi/efivars.c b/drivers/firmware/efi/efivars.c
+index 8bd1bb6dbe47..24ae2a694e9b 100644
+--- a/drivers/firmware/efi/efivars.c
++++ b/drivers/firmware/efi/efivars.c
+@@ -219,7 +219,8 @@ efivar_store_raw(struct efivar_entry *entry, const char 
*buf, size_t count)
+       }
+ 
+       if ((new_var->Attributes & ~EFI_VARIABLE_MASK) != 0 ||
+-          efivar_validate(new_var, new_var->Data, new_var->DataSize) == 
false) {
++          efivar_validate(new_var->VendorGuid, new_var->VariableName,
++                          new_var->Data, new_var->DataSize) == false) {
+               printk(KERN_ERR "efivars: Malformed variable content\n");
+               return -EINVAL;
+       }
+@@ -334,7 +335,8 @@ static ssize_t efivar_create(struct file *filp, struct 
kobject *kobj,
+               return -EACCES;
+ 
+       if ((new_var->Attributes & ~EFI_VARIABLE_MASK) != 0 ||
+-          efivar_validate(new_var, new_var->Data, new_var->DataSize) == 
false) {
++          efivar_validate(new_var->VendorGuid, new_var->VariableName,
++                          new_var->Data, new_var->DataSize) == false) {
+               printk(KERN_ERR "efivars: Malformed variable content\n");
+               return -EINVAL;
+       }
+@@ -405,35 +407,27 @@ efivar_create_sysfs_entry(struct efivar_entry *new_var)
+ {
+       int i, short_name_size;
+       char *short_name;
+-      unsigned long variable_name_size;
+-      efi_char16_t *variable_name;
+-
+-      variable_name = new_var->var.VariableName;
+-      variable_name_size = ucs2_strlen(variable_name) * sizeof(efi_char16_t);
++      unsigned long utf8_name_size;
++      efi_char16_t *variable_name = new_var->var.VariableName;
+ 
+       /*
+-       * Length of the variable bytes in ASCII, plus the '-' separator,
++       * Length of the variable bytes in UTF8, plus the '-' separator,
+        * plus the GUID, plus trailing NUL
+        */
+-      short_name_size = variable_name_size / sizeof(efi_char16_t)
+-                              + 1 + EFI_VARIABLE_GUID_LEN + 1;
+-
+-      short_name = kzalloc(short_name_size, GFP_KERNEL);
++      utf8_name_size = ucs2_utf8size(variable_name);
++      short_name_size = utf8_name_size + 1 + EFI_VARIABLE_GUID_LEN + 1;
+ 
++      short_name = kmalloc(short_name_size, GFP_KERNEL);
+       if (!short_name)
+               return 1;
+ 
+-      /* Convert Unicode to normal chars (assume top bits are 0),
+-         ala UTF-8 */
+-      for (i=0; i < (int)(variable_name_size / sizeof(efi_char16_t)); i++) {
+-              short_name[i] = variable_name[i] & 0xFF;
+-      }
++      ucs2_as_utf8(short_name, variable_name, short_name_size);
++
+       /* This is ugly, but necessary to separate one vendor's
+          private variables from another's.         */
+-
+-      *(short_name + strlen(short_name)) = '-';
++      short_name[utf8_name_size] = '-';
+       efi_guid_unparse(&new_var->var.VendorGuid,
+-                       short_name + strlen(short_name));
++                       short_name + utf8_name_size + 1);
+ 
+       new_var->kobj.kset = efivars_kset;
+ 
+diff --git a/drivers/firmware/efi/vars.c b/drivers/firmware/efi/vars.c
+index 7dbc319e1cf5..9f82b5545edd 100644
+--- a/drivers/firmware/efi/vars.c
++++ b/drivers/firmware/efi/vars.c
+@@ -42,7 +42,7 @@ DECLARE_WORK(efivar_work, NULL);
+ EXPORT_SYMBOL_GPL(efivar_work);
+ 
+ static bool
+-validate_device_path(struct efi_variable *var, int match, u8 *buffer,
++validate_device_path(efi_char16_t *var_name, int match, u8 *buffer,
+                    unsigned long len)
+ {
+       struct efi_generic_dev_path *node;
+@@ -75,7 +75,7 @@ validate_device_path(struct efi_variable *var, int match, u8 
*buffer,
+ }
+ 
+ static bool
+-validate_boot_order(struct efi_variable *var, int match, u8 *buffer,
++validate_boot_order(efi_char16_t *var_name, int match, u8 *buffer,
+                   unsigned long len)
+ {
+       /* An array of 16-bit integers */
+@@ -86,18 +86,18 @@ validate_boot_order(struct efi_variable *var, int match, 
u8 *buffer,
+ }
+ 
+ static bool
+-validate_load_option(struct efi_variable *var, int match, u8 *buffer,
++validate_load_option(efi_char16_t *var_name, int match, u8 *buffer,
+                    unsigned long len)
+ {
+       u16 filepathlength;
+       int i, desclength = 0, namelen;
+ 
+-      namelen = ucs2_strnlen(var->VariableName, sizeof(var->VariableName));
++      namelen = ucs2_strnlen(var_name, EFI_VAR_NAME_LEN);
+ 
+       /* Either "Boot" or "Driver" followed by four digits of hex */
+       for (i = match; i < match+4; i++) {
+-              if (var->VariableName[i] > 127 ||
+-                  hex_to_bin(var->VariableName[i] & 0xff) < 0)
++              if (var_name[i] > 127 ||
++                  hex_to_bin(var_name[i] & 0xff) < 0)
+                       return true;
+       }
+ 
+@@ -132,12 +132,12 @@ validate_load_option(struct efi_variable *var, int 
match, u8 *buffer,
+       /*
+        * And, finally, check the filepath
+        */
+-      return validate_device_path(var, match, buffer + desclength + 6,
++      return validate_device_path(var_name, match, buffer + desclength + 6,
+                                   filepathlength);
+ }
+ 
+ static bool
+-validate_uint16(struct efi_variable *var, int match, u8 *buffer,
++validate_uint16(efi_char16_t *var_name, int match, u8 *buffer,
+               unsigned long len)
+ {
+       /* A single 16-bit integer */
+@@ -148,7 +148,7 @@ validate_uint16(struct efi_variable *var, int match, u8 
*buffer,
+ }
+ 
+ static bool
+-validate_ascii_string(struct efi_variable *var, int match, u8 *buffer,
++validate_ascii_string(efi_char16_t *var_name, int match, u8 *buffer,
+                     unsigned long len)
+ {
+       int i;
+@@ -165,67 +165,133 @@ validate_ascii_string(struct efi_variable *var, int 
match, u8 *buffer,
+ }
+ 
+ struct variable_validate {
++      efi_guid_t vendor;
+       char *name;
+-      bool (*validate)(struct efi_variable *var, int match, u8 *data,
++      bool (*validate)(efi_char16_t *var_name, int match, u8 *data,
+                        unsigned long len);
+ };
+ 
++/*
++ * This is the list of variables we need to validate, as well as the
++ * whitelist for what we think is safe not to default to immutable.
++ *
++ * If it has a validate() method that's not NULL, it'll go into the
++ * validation routine.  If not, it is assumed valid, but still used for
++ * whitelisting.
++ *
++ * Note that it's sorted by {vendor,name}, but globbed names must come after
++ * any other name with the same prefix.
++ */
+ static const struct variable_validate variable_validate[] = {
+-      { "BootNext", validate_uint16 },
+-      { "BootOrder", validate_boot_order },
+-      { "DriverOrder", validate_boot_order },
+-      { "Boot*", validate_load_option },
+-      { "Driver*", validate_load_option },
+-      { "ConIn", validate_device_path },
+-      { "ConInDev", validate_device_path },
+-      { "ConOut", validate_device_path },
+-      { "ConOutDev", validate_device_path },
+-      { "ErrOut", validate_device_path },
+-      { "ErrOutDev", validate_device_path },
+-      { "Timeout", validate_uint16 },
+-      { "Lang", validate_ascii_string },
+-      { "PlatformLang", validate_ascii_string },
+-      { "", NULL },
++      { EFI_GLOBAL_VARIABLE_GUID, "BootNext", validate_uint16 },
++      { EFI_GLOBAL_VARIABLE_GUID, "BootOrder", validate_boot_order },
++      { EFI_GLOBAL_VARIABLE_GUID, "Boot*", validate_load_option },
++      { EFI_GLOBAL_VARIABLE_GUID, "DriverOrder", validate_boot_order },
++      { EFI_GLOBAL_VARIABLE_GUID, "Driver*", validate_load_option },
++      { EFI_GLOBAL_VARIABLE_GUID, "ConIn", validate_device_path },
++      { EFI_GLOBAL_VARIABLE_GUID, "ConInDev", validate_device_path },
++      { EFI_GLOBAL_VARIABLE_GUID, "ConOut", validate_device_path },
++      { EFI_GLOBAL_VARIABLE_GUID, "ConOutDev", validate_device_path },
++      { EFI_GLOBAL_VARIABLE_GUID, "ErrOut", validate_device_path },
++      { EFI_GLOBAL_VARIABLE_GUID, "ErrOutDev", validate_device_path },
++      { EFI_GLOBAL_VARIABLE_GUID, "Lang", validate_ascii_string },
++      { EFI_GLOBAL_VARIABLE_GUID, "OsIndications", NULL },
++      { EFI_GLOBAL_VARIABLE_GUID, "PlatformLang", validate_ascii_string },
++      { EFI_GLOBAL_VARIABLE_GUID, "Timeout", validate_uint16 },
++      { LINUX_EFI_CRASH_GUID, "*", NULL },
++      { NULL_GUID, "", NULL },
+ };
+ 
++static bool
++variable_matches(const char *var_name, size_t len, const char *match_name,
++               int *match)
++{
++      for (*match = 0; ; (*match)++) {
++              char c = match_name[*match];
++              char u = var_name[*match];
++
++              /* Wildcard in the matching name means we've matched */
++              if (c == '*')
++                      return true;
++
++              /* Case sensitive match */
++              if (!c && *match == len)
++                      return true;
++
++              if (c != u)
++                      return false;
++
++              if (!c)
++                      return true;
++      }
++      return true;
++}
++
+ bool
+-efivar_validate(struct efi_variable *var, u8 *data, unsigned long len)
++efivar_validate(efi_guid_t vendor, efi_char16_t *var_name, u8 *data,
++              unsigned long data_size)
+ {
+       int i;
+-      u16 *unicode_name = var->VariableName;
++      unsigned long utf8_size;
++      u8 *utf8_name;
+ 
+-      for (i = 0; variable_validate[i].validate != NULL; i++) {
+-              const char *name = variable_validate[i].name;
+-              int match;
++      utf8_size = ucs2_utf8size(var_name);
++      utf8_name = kmalloc(utf8_size + 1, GFP_KERNEL);
++      if (!utf8_name)
++              return false;
+ 
+-              for (match = 0; ; match++) {
+-                      char c = name[match];
+-                      u16 u = unicode_name[match];
++      ucs2_as_utf8(utf8_name, var_name, utf8_size);
++      utf8_name[utf8_size] = '\0';
+ 
+-                      /* All special variables are plain ascii */
+-                      if (u > 127)
+-                              return true;
++      for (i = 0; variable_validate[i].name[0] != '\0'; i++) {
++              const char *name = variable_validate[i].name;
++              int match = 0;
+ 
+-                      /* Wildcard in the matching name means we've matched */
+-                      if (c == '*')
+-                              return variable_validate[i].validate(var,
+-                                                           match, data, len);
++              if (efi_guidcmp(vendor, variable_validate[i].vendor))
++                      continue;
+ 
+-                      /* Case sensitive match */
+-                      if (c != u)
++              if (variable_matches(utf8_name, utf8_size+1, name, &match)) {
++                      if (variable_validate[i].validate == NULL)
+                               break;
+-
+-                      /* Reached the end of the string while matching */
+-                      if (!c)
+-                              return variable_validate[i].validate(var,
+-                                                           match, data, len);
++                      kfree(utf8_name);
++                      return variable_validate[i].validate(var_name, match,
++                                                           data, data_size);
+               }
+       }
+-
++      kfree(utf8_name);
+       return true;
+ }
+ EXPORT_SYMBOL_GPL(efivar_validate);
+ 
++bool
++efivar_variable_is_removable(efi_guid_t vendor, const char *var_name,
++                           size_t len)
++{
++      int i;
++      bool found = false;
++      int match = 0;
++
++      /*
++       * Check if our variable is in the validated variables list
++       */
++      for (i = 0; variable_validate[i].name[0] != '\0'; i++) {
++              if (efi_guidcmp(variable_validate[i].vendor, vendor))
++                      continue;
++
++              if (variable_matches(var_name, len,
++                                   variable_validate[i].name, &match)) {
++                      found = true;
++                      break;
++              }
++      }
++
++      /*
++       * If it's in our list, it is removable.
++       */
++      return found;
++}
++EXPORT_SYMBOL_GPL(efivar_variable_is_removable);
++
+ static efi_status_t
+ check_var_size(u32 attributes, unsigned long size)
+ {
+@@ -797,7 +863,7 @@ int efivar_entry_set_get_size(struct efivar_entry *entry, 
u32 attributes,
+ 
+       *set = false;
+ 
+-      if (efivar_validate(&entry->var, data, *size) == false)
++      if (efivar_validate(*vendor, name, data, *size) == false)
+               return -EINVAL;
+ 
+       /*
+diff --git a/fs/efivarfs/file.c b/fs/efivarfs/file.c
+index 8dd524f32284..08f105a06fbf 100644
+--- a/fs/efivarfs/file.c
++++ b/fs/efivarfs/file.c
+@@ -10,6 +10,7 @@
+ #include <linux/efi.h>
+ #include <linux/fs.h>
+ #include <linux/slab.h>
++#include <linux/mount.h>
+ 
+ #include "internal.h"
+ 
+@@ -108,9 +109,79 @@ out_free:
+       return size;
+ }
+ 
++static int
++efivarfs_ioc_getxflags(struct file *file, void __user *arg)
++{
++      struct inode *inode = file->f_mapping->host;
++      unsigned int i_flags;
++      unsigned int flags = 0;
++
++      i_flags = inode->i_flags;
++      if (i_flags & S_IMMUTABLE)
++              flags |= FS_IMMUTABLE_FL;
++
++      if (copy_to_user(arg, &flags, sizeof(flags)))
++              return -EFAULT;
++      return 0;
++}
++
++static int
++efivarfs_ioc_setxflags(struct file *file, void __user *arg)
++{
++      struct inode *inode = file->f_mapping->host;
++      unsigned int flags;
++      unsigned int i_flags = 0;
++      int error;
++
++      if (!inode_owner_or_capable(inode))
++              return -EACCES;
++
++      if (copy_from_user(&flags, arg, sizeof(flags)))
++              return -EFAULT;
++
++      if (flags & ~FS_IMMUTABLE_FL)
++              return -EOPNOTSUPP;
++
++      if (!capable(CAP_LINUX_IMMUTABLE))
++              return -EPERM;
++
++      if (flags & FS_IMMUTABLE_FL)
++              i_flags |= S_IMMUTABLE;
++
++
++      error = mnt_want_write_file(file);
++      if (error)
++              return error;
++
++      mutex_lock(&inode->i_mutex);
++      inode->i_flags &= ~S_IMMUTABLE;
++      inode->i_flags |= i_flags;
++      mutex_unlock(&inode->i_mutex);
++
++      mnt_drop_write_file(file);
++
++      return 0;
++}
++
++long
++efivarfs_file_ioctl(struct file *file, unsigned int cmd, unsigned long p)
++{
++      void __user *arg = (void __user *)p;
++
++      switch (cmd) {
++      case FS_IOC_GETFLAGS:
++              return efivarfs_ioc_getxflags(file, arg);
++      case FS_IOC_SETFLAGS:
++              return efivarfs_ioc_setxflags(file, arg);
++      }
++
++      return -ENOTTY;
++}
++
+ const struct file_operations efivarfs_file_operations = {
+       .open   = simple_open,
+       .read   = efivarfs_file_read,
+       .write  = efivarfs_file_write,
+       .llseek = no_llseek,
++      .unlocked_ioctl = efivarfs_file_ioctl,
+ };
+diff --git a/fs/efivarfs/inode.c b/fs/efivarfs/inode.c
+index 7e787fb90293..d0351bc7b533 100644
+--- a/fs/efivarfs/inode.c
++++ b/fs/efivarfs/inode.c
+@@ -15,7 +15,8 @@
+ #include "internal.h"
+ 
+ struct inode *efivarfs_get_inode(struct super_block *sb,
+-                              const struct inode *dir, int mode, dev_t dev)
++                              const struct inode *dir, int mode,
++                              dev_t dev, bool is_removable)
+ {
+       struct inode *inode = new_inode(sb);
+ 
+@@ -23,6 +24,7 @@ struct inode *efivarfs_get_inode(struct super_block *sb,
+               inode->i_ino = get_next_ino();
+               inode->i_mode = mode;
+               inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
++              inode->i_flags = is_removable ? 0 : S_IMMUTABLE;
+               switch (mode & S_IFMT) {
+               case S_IFREG:
+                       inode->i_fop = &efivarfs_file_operations;
+@@ -102,22 +104,17 @@ static void efivarfs_hex_to_guid(const char *str, 
efi_guid_t *guid)
+ static int efivarfs_create(struct inode *dir, struct dentry *dentry,
+                         umode_t mode, bool excl)
+ {
+-      struct inode *inode;
++      struct inode *inode = NULL;
+       struct efivar_entry *var;
+       int namelen, i = 0, err = 0;
++      bool is_removable = false;
+ 
+       if (!efivarfs_valid_name(dentry->d_name.name, dentry->d_name.len))
+               return -EINVAL;
+ 
+-      inode = efivarfs_get_inode(dir->i_sb, dir, mode, 0);
+-      if (!inode)
+-              return -ENOMEM;
+-
+       var = kzalloc(sizeof(struct efivar_entry), GFP_KERNEL);
+-      if (!var) {
+-              err = -ENOMEM;
+-              goto out;
+-      }
++      if (!var)
++              return -ENOMEM;
+ 
+       /* length of the variable name itself: remove GUID and separator */
+       namelen = dentry->d_name.len - EFI_VARIABLE_GUID_LEN - 1;
+@@ -125,6 +122,16 @@ static int efivarfs_create(struct inode *dir, struct 
dentry *dentry,
+       efivarfs_hex_to_guid(dentry->d_name.name + namelen + 1,
+                       &var->var.VendorGuid);
+ 
++      if (efivar_variable_is_removable(var->var.VendorGuid,
++                                       dentry->d_name.name, namelen))
++              is_removable = true;
++
++      inode = efivarfs_get_inode(dir->i_sb, dir, mode, 0, is_removable);
++      if (!inode) {
++              err = -ENOMEM;
++              goto out;
++      }
++
+       for (i = 0; i < namelen; i++)
+               var->var.VariableName[i] = dentry->d_name.name[i];
+ 
+@@ -138,7 +145,8 @@ static int efivarfs_create(struct inode *dir, struct 
dentry *dentry,
+ out:
+       if (err) {
+               kfree(var);
+-              iput(inode);
++              if (inode)
++                      iput(inode);
+       }
+       return err;
+ }
+diff --git a/fs/efivarfs/internal.h b/fs/efivarfs/internal.h
+index b5ff16addb7c..b4505188e799 100644
+--- a/fs/efivarfs/internal.h
++++ b/fs/efivarfs/internal.h
+@@ -15,7 +15,8 @@ extern const struct file_operations efivarfs_file_operations;
+ extern const struct inode_operations efivarfs_dir_inode_operations;
+ extern bool efivarfs_valid_name(const char *str, int len);
+ extern struct inode *efivarfs_get_inode(struct super_block *sb,
+-                      const struct inode *dir, int mode, dev_t dev);
++                      const struct inode *dir, int mode, dev_t dev,
++                      bool is_removable);
+ 
+ extern struct list_head efivarfs_list;
+ 
+diff --git a/fs/efivarfs/super.c b/fs/efivarfs/super.c
+index 141aee31884f..5a3655f690d9 100644
+--- a/fs/efivarfs/super.c
++++ b/fs/efivarfs/super.c
+@@ -128,8 +128,9 @@ static int efivarfs_callback(efi_char16_t *name16, 
efi_guid_t vendor,
+       struct dentry *dentry, *root = sb->s_root;
+       unsigned long size = 0;
+       char *name;
+-      int len, i;
++      int len;
+       int err = -ENOMEM;
++      bool is_removable = false;
+ 
+       entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+       if (!entry)
+@@ -138,15 +139,17 @@ static int efivarfs_callback(efi_char16_t *name16, 
efi_guid_t vendor,
+       memcpy(entry->var.VariableName, name16, name_size);
+       memcpy(&(entry->var.VendorGuid), &vendor, sizeof(efi_guid_t));
+ 
+-      len = ucs2_strlen(entry->var.VariableName);
++      len = ucs2_utf8size(entry->var.VariableName);
+ 
+       /* name, plus '-', plus GUID, plus NUL*/
+       name = kmalloc(len + 1 + EFI_VARIABLE_GUID_LEN + 1, GFP_KERNEL);
+       if (!name)
+               goto fail;
+ 
+-      for (i = 0; i < len; i++)
+-              name[i] = entry->var.VariableName[i] & 0xFF;
++      ucs2_as_utf8(name, entry->var.VariableName, len);
++
++      if (efivar_variable_is_removable(entry->var.VendorGuid, name, len))
++              is_removable = true;
+ 
+       name[len] = '-';
+ 
+@@ -154,7 +157,8 @@ static int efivarfs_callback(efi_char16_t *name16, 
efi_guid_t vendor,
+ 
+       name[len + EFI_VARIABLE_GUID_LEN+1] = '\0';
+ 
+-      inode = efivarfs_get_inode(sb, root->d_inode, S_IFREG | 0644, 0);
++      inode = efivarfs_get_inode(sb, root->d_inode, S_IFREG | 0644, 0,
++                                 is_removable);
+       if (!inode)
+               goto fail_name;
+ 
+@@ -210,7 +214,7 @@ static int efivarfs_fill_super(struct super_block *sb, 
void *data, int silent)
+       sb->s_d_op              = &efivarfs_d_ops;
+       sb->s_time_gran         = 1;
+ 
+-      inode = efivarfs_get_inode(sb, NULL, S_IFDIR | 0755, 0);
++      inode = efivarfs_get_inode(sb, NULL, S_IFDIR | 0755, 0, true);
+       if (!inode)
+               return -ENOMEM;
+       inode->i_op = &efivarfs_dir_inode_operations;
+diff --git a/include/crypto/if_alg.h b/include/crypto/if_alg.h
+index 2f38daaab3d7..d61c11170213 100644
+--- a/include/crypto/if_alg.h
++++ b/include/crypto/if_alg.h
+@@ -30,8 +30,6 @@ struct alg_sock {
+ 
+       struct sock *parent;
+ 
+-      unsigned int refcnt;
+-
+       const struct af_alg_type *type;
+       void *private;
+ };
+@@ -66,7 +64,6 @@ int af_alg_register_type(const struct af_alg_type *type);
+ int af_alg_unregister_type(const struct af_alg_type *type);
+ 
+ int af_alg_release(struct socket *sock);
+-void af_alg_release_parent(struct sock *sk);
+ int af_alg_accept(struct sock *sk, struct socket *newsock);
+ 
+ int af_alg_make_sg(struct af_alg_sgl *sgl, void __user *addr, int len,
+@@ -83,6 +80,11 @@ static inline struct alg_sock *alg_sk(struct sock *sk)
+       return (struct alg_sock *)sk;
+ }
+ 
++static inline void af_alg_release_parent(struct sock *sk)
++{
++      sock_put(alg_sk(sk)->parent);
++}
++
+ static inline void af_alg_init_completion(struct af_alg_completion 
*completion)
+ {
+       init_completion(&completion->completion);
+diff --git a/include/linux/efi.h b/include/linux/efi.h
+index 2bc0ad78d058..63fa51c864ec 100644
+--- a/include/linux/efi.h
++++ b/include/linux/efi.h
+@@ -769,8 +769,10 @@ struct efivars {
+  * and we use a page for reading/writing.
+  */
+ 
++#define EFI_VAR_NAME_LEN      1024
++
+ struct efi_variable {
+-      efi_char16_t  VariableName[1024/sizeof(efi_char16_t)];
++      efi_char16_t  VariableName[EFI_VAR_NAME_LEN/sizeof(efi_char16_t)];
+       efi_guid_t    VendorGuid;
+       unsigned long DataSize;
+       __u8          Data[1024];
+@@ -832,7 +834,10 @@ int efivar_entry_iter(int (*func)(struct efivar_entry *, 
void *),
+ struct efivar_entry *efivar_entry_find(efi_char16_t *name, efi_guid_t guid,
+                                      struct list_head *head, bool remove);
+ 
+-bool efivar_validate(struct efi_variable *var, u8 *data, unsigned long len);
++bool efivar_validate(efi_guid_t vendor, efi_char16_t *var_name, u8 *data,
++                   unsigned long data_size);
++bool efivar_variable_is_removable(efi_guid_t vendor, const char *name,
++                                size_t len);
+ 
+ extern struct work_struct efivar_work;
+ void efivar_run_worker(void);
+diff --git a/include/linux/module.h b/include/linux/module.h
+index 46f1ea01e6f6..761dc2848ffa 100644
+--- a/include/linux/module.h
++++ b/include/linux/module.h
+@@ -220,6 +220,12 @@ struct module_ref {
+       unsigned long decs;
+ } __attribute((aligned(2 * sizeof(unsigned long))));
+ 
++struct mod_kallsyms {
++      Elf_Sym *symtab;
++      unsigned int num_symtab;
++      char *strtab;
++};
++
+ struct module
+ {
+       enum module_state state;
+@@ -308,14 +314,9 @@ struct module
+ #endif
+ 
+ #ifdef CONFIG_KALLSYMS
+-      /*
+-       * We keep the symbol and string tables for kallsyms.
+-       * The core_* fields below are temporary, loader-only (they
+-       * could really be discarded after module init).
+-       */
+-      Elf_Sym *symtab, *core_symtab;
+-      unsigned int num_symtab, core_num_syms;
+-      char *strtab, *core_strtab;
++      /* Protected by RCU and/or module_mutex: use rcu_dereference() */
++      struct mod_kallsyms *kallsyms;
++      struct mod_kallsyms core_kallsyms;
+ 
+       /* Section attributes */
+       struct module_sect_attrs *sect_attrs;
+diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h
+index 0b2d0cbe0bab..36e5e9998865 100644
+--- a/include/linux/tracepoint.h
++++ b/include/linux/tracepoint.h
+@@ -129,9 +129,6 @@ static inline void tracepoint_synchronize_unregister(void)
+               void *it_func;                                          \
+               void *__data;                                           \
+                                                                       \
+-              if (!cpu_online(raw_smp_processor_id()))                \
+-                      return;                                         \
+-                                                                      \
+               if (!(cond))                                            \
+                       return;                                         \
+               prercu;                                                 \
+@@ -265,15 +262,19 @@ static inline void 
tracepoint_synchronize_unregister(void)
+  * "void *__data, proto" as the callback prototype.
+  */
+ #define DECLARE_TRACE_NOARGS(name)                                    \
+-              __DECLARE_TRACE(name, void, , 1, void *__data, __data)
++      __DECLARE_TRACE(name, void, ,                                   \
++                      cpu_online(raw_smp_processor_id()),             \
++                      void *__data, __data)
+ 
+ #define DECLARE_TRACE(name, proto, args)                              \
+-              __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args), 1,   \
+-                              PARAMS(void *__data, proto),            \
+-                              PARAMS(__data, args))
++      __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),              \
++                      cpu_online(raw_smp_processor_id()),             \
++                      PARAMS(void *__data, proto),                    \
++                      PARAMS(__data, args))
+ 
+ #define DECLARE_TRACE_CONDITION(name, proto, args, cond)              \
+-      __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args), PARAMS(cond), \
++      __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),              \
++                      cpu_online(raw_smp_processor_id()) && (PARAMS(cond)), \
+                       PARAMS(void *__data, proto),                    \
+                       PARAMS(__data, args))
+ 
+diff --git a/include/linux/ucs2_string.h b/include/linux/ucs2_string.h
+index cbb20afdbc01..bb679b48f408 100644
+--- a/include/linux/ucs2_string.h
++++ b/include/linux/ucs2_string.h
+@@ -11,4 +11,8 @@ unsigned long ucs2_strlen(const ucs2_char_t *s);
+ unsigned long ucs2_strsize(const ucs2_char_t *data, unsigned long maxlength);
+ int ucs2_strncmp(const ucs2_char_t *a, const ucs2_char_t *b, size_t len);
+ 
++unsigned long ucs2_utf8size(const ucs2_char_t *src);
++unsigned long ucs2_as_utf8(u8 *dest, const ucs2_char_t *src,
++                         unsigned long maxlength);
++
+ #endif /* _LINUX_UCS2_STRING_H_ */
+diff --git a/kernel/module.c b/kernel/module.c
+index 70a4754c001f..f8a4f48b48a9 100644
+--- a/kernel/module.c
++++ b/kernel/module.c
+@@ -179,6 +179,9 @@ struct load_info {
+       struct _ddebug *debug;
+       unsigned int num_debug;
+       bool sig_ok;
++#ifdef CONFIG_KALLSYMS
++      unsigned long mod_kallsyms_init_off;
++#endif
+       struct {
+               unsigned int sym, str, mod, vers, info, pcpu;
+       } index;
+@@ -2346,8 +2349,20 @@ static void layout_symtab(struct module *mod, struct 
load_info *info)
+       strsect->sh_entsize = get_offset(mod, &mod->init_size, strsect,
+                                        info->index.str) | INIT_OFFSET_MASK;
+       pr_debug("\t%s\n", info->secstrings + strsect->sh_name);
++
++      /* We'll tack temporary mod_kallsyms on the end. */
++      mod->init_size = ALIGN(mod->init_size,
++                             __alignof__(struct mod_kallsyms));
++      info->mod_kallsyms_init_off = mod->init_size;
++      mod->init_size += sizeof(struct mod_kallsyms);
++      mod->init_size = debug_align(mod->init_size);
+ }
+ 
++/*
++ * We use the full symtab and strtab which layout_symtab arranged to
++ * be appended to the init section.  Later we switch to the cut-down
++ * core-only ones.
++ */
+ static void add_kallsyms(struct module *mod, const struct load_info *info)
+ {
+       unsigned int i, ndst;
+@@ -2356,28 +2371,33 @@ static void add_kallsyms(struct module *mod, const 
struct load_info *info)
+       char *s;
+       Elf_Shdr *symsec = &info->sechdrs[info->index.sym];
+ 
+-      mod->symtab = (void *)symsec->sh_addr;
+-      mod->num_symtab = symsec->sh_size / sizeof(Elf_Sym);
++      /* Set up to point into init section. */
++      mod->kallsyms = mod->module_init + info->mod_kallsyms_init_off;
++
++      mod->kallsyms->symtab = (void *)symsec->sh_addr;
++      mod->kallsyms->num_symtab = symsec->sh_size / sizeof(Elf_Sym);
+       /* Make sure we get permanent strtab: don't use info->strtab. */
+-      mod->strtab = (void *)info->sechdrs[info->index.str].sh_addr;
++      mod->kallsyms->strtab = (void *)info->sechdrs[info->index.str].sh_addr;
+ 
+       /* Set types up while we still have access to sections. */
+-      for (i = 0; i < mod->num_symtab; i++)
+-              mod->symtab[i].st_info = elf_type(&mod->symtab[i], info);
+-
+-      mod->core_symtab = dst = mod->module_core + info->symoffs;
+-      mod->core_strtab = s = mod->module_core + info->stroffs;
+-      src = mod->symtab;
+-      for (ndst = i = 0; i < mod->num_symtab; i++) {
++      for (i = 0; i < mod->kallsyms->num_symtab; i++)
++              mod->kallsyms->symtab[i].st_info
++                      = elf_type(&mod->kallsyms->symtab[i], info);
++
++      /* Now populate the cut down core kallsyms for after init. */
++      mod->core_kallsyms.symtab = dst = mod->module_core + info->symoffs;
++      mod->core_kallsyms.strtab = s = mod->module_core + info->stroffs;
++      src = mod->kallsyms->symtab;
++      for (ndst = i = 0; i < mod->kallsyms->num_symtab; i++) {
+               if (i == 0 ||
+                   is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum)) {
+                       dst[ndst] = src[i];
+-                      dst[ndst++].st_name = s - mod->core_strtab;
+-                      s += strlcpy(s, &mod->strtab[src[i].st_name],
++                      dst[ndst++].st_name = s - mod->core_kallsyms.strtab;
++                      s += strlcpy(s, &mod->kallsyms->strtab[src[i].st_name],
+                                    KSYM_NAME_LEN) + 1;
+               }
+       }
+-      mod->core_num_syms = ndst;
++      mod->core_kallsyms.num_symtab = ndst;
+ }
+ #else
+ static inline void layout_symtab(struct module *mod, struct load_info *info)
+@@ -3117,9 +3137,8 @@ static int do_init_module(struct module *mod)
+       module_put(mod);
+       trim_init_extable(mod);
+ #ifdef CONFIG_KALLSYMS
+-      mod->num_symtab = mod->core_num_syms;
+-      mod->symtab = mod->core_symtab;
+-      mod->strtab = mod->core_strtab;
++      /* Switch to core kallsyms now init is done: kallsyms may be walking! */
++      rcu_assign_pointer(mod->kallsyms, &mod->core_kallsyms);
+ #endif
+       unset_module_init_ro_nx(mod);
+       module_free(mod, mod->module_init);
+@@ -3398,9 +3417,9 @@ static inline int is_arm_mapping_symbol(const char *str)
+              && (str[2] == '\0' || str[2] == '.');
+ }
+ 
+-static const char *symname(struct module *mod, unsigned int symnum)
++static const char *symname(struct mod_kallsyms *kallsyms, unsigned int symnum)
+ {
+-      return mod->strtab + mod->symtab[symnum].st_name;
++      return kallsyms->strtab + kallsyms->symtab[symnum].st_name;
+ }
+ 
+ static const char *get_ksymbol(struct module *mod,
+@@ -3410,6 +3429,7 @@ static const char *get_ksymbol(struct module *mod,
+ {
+       unsigned int i, best = 0;
+       unsigned long nextval;
++      struct mod_kallsyms *kallsyms = rcu_dereference_sched(mod->kallsyms);
+ 
+       /* At worse, next value is at end of module */
+       if (within_module_init(addr, mod))
+@@ -3419,32 +3439,32 @@ static const char *get_ksymbol(struct module *mod,
+ 
+       /* Scan for closest preceding symbol, and next symbol. (ELF
+          starts real symbols at 1). */
+-      for (i = 1; i < mod->num_symtab; i++) {
+-              if (mod->symtab[i].st_shndx == SHN_UNDEF)
++      for (i = 1; i < kallsyms->num_symtab; i++) {
++              if (kallsyms->symtab[i].st_shndx == SHN_UNDEF)
+                       continue;
+ 
+               /* We ignore unnamed symbols: they're uninformative
+                * and inserted at a whim. */
+-              if (*symname(mod, i) == '\0'
+-                  || is_arm_mapping_symbol(symname(mod, i)))
++              if (*symname(kallsyms, i) == '\0'
++                  || is_arm_mapping_symbol(symname(kallsyms, i)))
+                       continue;
+ 
+-              if (mod->symtab[i].st_value <= addr
+-                  && mod->symtab[i].st_value > mod->symtab[best].st_value)
++              if (kallsyms->symtab[i].st_value <= addr
++                  && kallsyms->symtab[i].st_value > 
kallsyms->symtab[best].st_value)
+                       best = i;
+-              if (mod->symtab[i].st_value > addr
+-                  && mod->symtab[i].st_value < nextval)
+-                      nextval = mod->symtab[i].st_value;
++              if (kallsyms->symtab[i].st_value > addr
++                  && kallsyms->symtab[i].st_value < nextval)
++                      nextval = kallsyms->symtab[i].st_value;
+       }
+ 
+       if (!best)
+               return NULL;
+ 
+       if (size)
+-              *size = nextval - mod->symtab[best].st_value;
++              *size = nextval - kallsyms->symtab[best].st_value;
+       if (offset)
+-              *offset = addr - mod->symtab[best].st_value;
+-      return symname(mod, best);
++              *offset = addr - kallsyms->symtab[best].st_value;
++      return symname(kallsyms, best);
+ }
+ 
+ /* For kallsyms to ask for address resolution.  NULL means not found.  Careful
+@@ -3540,18 +3560,21 @@ int module_get_kallsym(unsigned int symnum, unsigned 
long *value, char *type,
+ 
+       preempt_disable();
+       list_for_each_entry_rcu(mod, &modules, list) {
++              struct mod_kallsyms *kallsyms;
++
+               if (mod->state == MODULE_STATE_UNFORMED)
+                       continue;
+-              if (symnum < mod->num_symtab) {
+-                      *value = mod->symtab[symnum].st_value;
+-                      *type = mod->symtab[symnum].st_info;
+-                      strlcpy(name, symname(mod, symnum), KSYM_NAME_LEN);
++              kallsyms = rcu_dereference_sched(mod->kallsyms);
++              if (symnum < kallsyms->num_symtab) {
++                      *value = kallsyms->symtab[symnum].st_value;
++                      *type = kallsyms->symtab[symnum].st_info;
++                      strlcpy(name, symname(kallsyms, symnum), KSYM_NAME_LEN);
+                       strlcpy(module_name, mod->name, MODULE_NAME_LEN);
+                       *exported = is_exported(name, *value, mod);
+                       preempt_enable();
+                       return 0;
+               }
+-              symnum -= mod->num_symtab;
++              symnum -= kallsyms->num_symtab;
+       }
+       preempt_enable();
+       return -ERANGE;
+@@ -3560,11 +3583,12 @@ int module_get_kallsym(unsigned int symnum, unsigned 
long *value, char *type,
+ static unsigned long mod_find_symname(struct module *mod, const char *name)
+ {
+       unsigned int i;
++      struct mod_kallsyms *kallsyms = rcu_dereference_sched(mod->kallsyms);
+ 
+-      for (i = 0; i < mod->num_symtab; i++)
+-              if (strcmp(name, symname(mod, i)) == 0 &&
+-                  mod->symtab[i].st_info != 'U')
+-                      return mod->symtab[i].st_value;
++      for (i = 0; i < kallsyms->num_symtab; i++)
++              if (strcmp(name, symname(kallsyms, i)) == 0 &&
++                  kallsyms->symtab[i].st_info != 'U')
++                      return kallsyms->symtab[i].st_value;
+       return 0;
+ }
+ 
+@@ -3603,11 +3627,14 @@ int module_kallsyms_on_each_symbol(int (*fn)(void *, 
const char *,
+       int ret;
+ 
+       list_for_each_entry(mod, &modules, list) {
++              /* We hold module_mutex: no need for rcu_dereference_sched */
++              struct mod_kallsyms *kallsyms = mod->kallsyms;
++
+               if (mod->state == MODULE_STATE_UNFORMED)
+                       continue;
+-              for (i = 0; i < mod->num_symtab; i++) {
+-                      ret = fn(data, symname(mod, i),
+-                               mod, mod->symtab[i].st_value);
++              for (i = 0; i < kallsyms->num_symtab; i++) {
++                      ret = fn(data, symname(kallsyms, i),
++                               mod, kallsyms->symtab[i].st_value);
+                       if (ret != 0)
+                               return ret;
+               }
+diff --git a/lib/ucs2_string.c b/lib/ucs2_string.c
+index 6f500ef2301d..f0b323abb4c6 100644
+--- a/lib/ucs2_string.c
++++ b/lib/ucs2_string.c
+@@ -49,3 +49,65 @@ ucs2_strncmp(const ucs2_char_t *a, const ucs2_char_t *b, 
size_t len)
+         }
+ }
+ EXPORT_SYMBOL(ucs2_strncmp);
++
++unsigned long
++ucs2_utf8size(const ucs2_char_t *src)
++{
++      unsigned long i;
++      unsigned long j = 0;
++
++      for (i = 0; i < ucs2_strlen(src); i++) {
++              u16 c = src[i];
++
++              if (c >= 0x800)
++                      j += 3;
++              else if (c >= 0x80)
++                      j += 2;
++              else
++                      j += 1;
++      }
++
++      return j;
++}
++EXPORT_SYMBOL(ucs2_utf8size);
++
++/*
++ * copy at most maxlength bytes of whole utf8 characters to dest from the
++ * ucs2 string src.
++ *
++ * The return value is the number of characters copied, not including the
++ * final NUL character.
++ */
++unsigned long
++ucs2_as_utf8(u8 *dest, const ucs2_char_t *src, unsigned long maxlength)
++{
++      unsigned int i;
++      unsigned long j = 0;
++      unsigned long limit = ucs2_strnlen(src, maxlength);
++
++      for (i = 0; maxlength && i < limit; i++) {
++              u16 c = src[i];
++
++              if (c >= 0x800) {
++                      if (maxlength < 3)
++                              break;
++                      maxlength -= 3;
++                      dest[j++] = 0xe0 | (c & 0xf000) >> 12;
++                      dest[j++] = 0x80 | (c & 0x0fc0) >> 6;
++                      dest[j++] = 0x80 | (c & 0x003f);
++              } else if (c >= 0x80) {
++                      if (maxlength < 2)
++                              break;
++                      maxlength -= 2;
++                      dest[j++] = 0xc0 | (c & 0x7c0) >> 6;
++                      dest[j++] = 0x80 | (c & 0x03f);
++              } else {
++                      maxlength -= 1;
++                      dest[j++] = c & 0x7f;
++              }
++      }
++      if (maxlength)
++              dest[j] = '\0';
++      return j;
++}
++EXPORT_SYMBOL(ucs2_as_utf8);
+diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c
+index 31bf2586fb84..864408026202 100644
+--- a/net/mac80211/agg-rx.c
++++ b/net/mac80211/agg-rx.c
+@@ -290,7 +290,7 @@ void ieee80211_process_addba_request(struct 
ieee80211_local *local,
+       }
+ 
+       /* prepare A-MPDU MLME for Rx aggregation */
+-      tid_agg_rx = kmalloc(sizeof(struct tid_ampdu_rx), GFP_KERNEL);
++      tid_agg_rx = kzalloc(sizeof(*tid_agg_rx), GFP_KERNEL);
+       if (!tid_agg_rx)
+               goto end;
+ 
+diff --git a/net/mac80211/rc80211_minstrel_ht.c 
b/net/mac80211/rc80211_minstrel_ht.c
+index f3bbea1eb9e7..13f10aab9213 100644
+--- a/net/mac80211/rc80211_minstrel_ht.c
++++ b/net/mac80211/rc80211_minstrel_ht.c
+@@ -454,7 +454,7 @@ minstrel_aggr_check(struct ieee80211_sta *pubsta, struct 
sk_buff *skb)
+       if (skb_get_queue_mapping(skb) == IEEE80211_AC_VO)
+               return;
+ 
+-      ieee80211_start_tx_ba_session(pubsta, tid, 5000);
++      ieee80211_start_tx_ba_session(pubsta, tid, 0);
+ }
+ 
+ static void
+diff --git a/net/wireless/wext-core.c b/net/wireless/wext-core.c
+index c8717c1d082e..87dd619fb2e9 100644
+--- a/net/wireless/wext-core.c
++++ b/net/wireless/wext-core.c
+@@ -342,6 +342,39 @@ static const int compat_event_type_size[] = {
+ 
+ /* IW event code */
+ 
++static void wireless_nlevent_flush(void)
++{
++      struct sk_buff *skb;
++      struct net *net;
++
++      ASSERT_RTNL();
++
++      for_each_net(net) {
++              while ((skb = skb_dequeue(&net->wext_nlevents)))
++                      rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL,
++                                  GFP_KERNEL);
++      }
++}
++
++static int wext_netdev_notifier_call(struct notifier_block *nb,
++                                   unsigned long state, void *ptr)
++{
++      /*
++       * When a netdev changes state in any way, flush all pending messages
++       * to avoid them going out in a strange order, e.g. RTM_NEWLINK after
++       * RTM_DELLINK, or with IFF_UP after without IFF_UP during dev_close()
++       * or similar - all of which could otherwise happen due to delays from
++       * schedule_work().
++       */
++      wireless_nlevent_flush();
++
++      return NOTIFY_OK;
++}
++
++static struct notifier_block wext_netdev_notifier = {
++      .notifier_call = wext_netdev_notifier_call,
++};
++
+ static int __net_init wext_pernet_init(struct net *net)
+ {
+       skb_queue_head_init(&net->wext_nlevents);
+@@ -360,7 +393,12 @@ static struct pernet_operations wext_pernet_ops = {
+ 
+ static int __init wireless_nlevent_init(void)
+ {
+-      return register_pernet_subsys(&wext_pernet_ops);
++      int err = register_pernet_subsys(&wext_pernet_ops);
++
++      if (err)
++              return err;
++
++      return register_netdevice_notifier(&wext_netdev_notifier);
+ }
+ 
+ subsys_initcall(wireless_nlevent_init);
+@@ -368,17 +406,8 @@ subsys_initcall(wireless_nlevent_init);
+ /* Process events generated by the wireless layer or the driver. */
+ static void wireless_nlevent_process(struct work_struct *work)
+ {
+-      struct sk_buff *skb;
+-      struct net *net;
+-
+       rtnl_lock();
+-
+-      for_each_net(net) {
+-              while ((skb = skb_dequeue(&net->wext_nlevents)))
+-                      rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL,
+-                                  GFP_KERNEL);
+-      }
+-
++      wireless_nlevent_flush();
+       rtnl_unlock();
+ }
+ 
+diff --git a/sound/soc/codecs/wm8958-dsp2.c b/sound/soc/codecs/wm8958-dsp2.c
+index 754f88e1fdab..4892966fc1b8 100644
+--- a/sound/soc/codecs/wm8958-dsp2.c
++++ b/sound/soc/codecs/wm8958-dsp2.c
+@@ -459,7 +459,7 @@ static int wm8958_put_mbc_enum(struct snd_kcontrol 
*kcontrol,
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+       struct wm8994 *control = wm8994->wm8994;
+-      int value = ucontrol->value.integer.value[0];
++      int value = ucontrol->value.enumerated.item[0];
+       int reg;
+ 
+       /* Don't allow on the fly reconfiguration */
+@@ -549,7 +549,7 @@ static int wm8958_put_vss_enum(struct snd_kcontrol 
*kcontrol,
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+       struct wm8994 *control = wm8994->wm8994;
+-      int value = ucontrol->value.integer.value[0];
++      int value = ucontrol->value.enumerated.item[0];
+       int reg;
+ 
+       /* Don't allow on the fly reconfiguration */
+@@ -582,7 +582,7 @@ static int wm8958_put_vss_hpf_enum(struct snd_kcontrol 
*kcontrol,
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+       struct wm8994 *control = wm8994->wm8994;
+-      int value = ucontrol->value.integer.value[0];
++      int value = ucontrol->value.enumerated.item[0];
+       int reg;
+ 
+       /* Don't allow on the fly reconfiguration */
+@@ -749,7 +749,7 @@ static int wm8958_put_enh_eq_enum(struct snd_kcontrol 
*kcontrol,
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+       struct wm8994 *control = wm8994->wm8994;
+-      int value = ucontrol->value.integer.value[0];
++      int value = ucontrol->value.enumerated.item[0];
+       int reg;
+ 
+       /* Don't allow on the fly reconfiguration */
+diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
+index 6e746c7474bf..cda3cf23474b 100644
+--- a/sound/soc/codecs/wm8994.c
++++ b/sound/soc/codecs/wm8994.c
+@@ -361,7 +361,7 @@ static int wm8994_put_drc_enum(struct snd_kcontrol 
*kcontrol,
+       struct wm8994 *control = wm8994->wm8994;
+       struct wm8994_pdata *pdata = &control->pdata;
+       int drc = wm8994_get_drc(kcontrol->id.name);
+-      int value = ucontrol->value.integer.value[0];
++      int value = ucontrol->value.enumerated.item[0];
+ 
+       if (drc < 0)
+               return drc;
+@@ -468,7 +468,7 @@ static int wm8994_put_retune_mobile_enum(struct 
snd_kcontrol *kcontrol,
+       struct wm8994 *control = wm8994->wm8994;
+       struct wm8994_pdata *pdata = &control->pdata;
+       int block = wm8994_get_retune_mobile_block(kcontrol->id.name);
+-      int value = ucontrol->value.integer.value[0];
++      int value = ucontrol->value.enumerated.item[0];
+ 
+       if (block < 0)
+               return block;
+diff --git a/tools/testing/selftests/efivarfs/efivarfs.sh 
b/tools/testing/selftests/efivarfs/efivarfs.sh
+index 77edcdcc016b..057278448515 100644
+--- a/tools/testing/selftests/efivarfs/efivarfs.sh
++++ b/tools/testing/selftests/efivarfs/efivarfs.sh
+@@ -88,7 +88,11 @@ test_delete()
+               exit 1
+       fi
+ 
+-      rm $file
++      rm $file 2>/dev/null
++      if [ $? -ne 0 ]; then
++              chattr -i $file
++              rm $file
++      fi
+ 
+       if [ -e $file ]; then
+               echo "$file couldn't be deleted" >&2
+@@ -111,6 +115,7 @@ test_zero_size_delete()
+               exit 1
+       fi
+ 
++      chattr -i $file
+       printf "$attrs" > $file
+ 
+       if [ -e $file ]; then
+@@ -141,7 +146,11 @@ test_valid_filenames()
+                       echo "$file could not be created" >&2
+                       ret=1
+               else
+-                      rm $file
++                      rm $file 2>/dev/null
++                      if [ $? -ne 0 ]; then
++                              chattr -i $file
++                              rm $file
++                      fi
+               fi
+       done
+ 
+@@ -174,7 +183,11 @@ test_invalid_filenames()
+ 
+               if [ -e $file ]; then
+                       echo "Creating $file should have failed" >&2
+-                      rm $file
++                      rm $file 2>/dev/null
++                      if [ $? -ne 0 ]; then
++                              chattr -i $file
++                              rm $file
++                      fi
+                       ret=1
+               fi
+       done
+diff --git a/tools/testing/selftests/efivarfs/open-unlink.c 
b/tools/testing/selftests/efivarfs/open-unlink.c
+index 8c0764407b3c..4af74f733036 100644
+--- a/tools/testing/selftests/efivarfs/open-unlink.c
++++ b/tools/testing/selftests/efivarfs/open-unlink.c
+@@ -1,10 +1,68 @@
++#include <errno.h>
+ #include <stdio.h>
+ #include <stdint.h>
+ #include <stdlib.h>
+ #include <unistd.h>
++#include <sys/ioctl.h>
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <fcntl.h>
++#include <linux/fs.h>
++
++static int set_immutable(const char *path, int immutable)
++{
++      unsigned int flags;
++      int fd;
++      int rc;
++      int error;
++
++      fd = open(path, O_RDONLY);
++      if (fd < 0)
++              return fd;
++
++      rc = ioctl(fd, FS_IOC_GETFLAGS, &flags);
++      if (rc < 0) {
++              error = errno;
++              close(fd);
++              errno = error;
++              return rc;
++      }
++
++      if (immutable)
++              flags |= FS_IMMUTABLE_FL;
++      else
++              flags &= ~FS_IMMUTABLE_FL;
++
++      rc = ioctl(fd, FS_IOC_SETFLAGS, &flags);
++      error = errno;
++      close(fd);
++      errno = error;
++      return rc;
++}
++
++static int get_immutable(const char *path)
++{
++      unsigned int flags;
++      int fd;
++      int rc;
++      int error;
++
++      fd = open(path, O_RDONLY);
++      if (fd < 0)
++              return fd;
++
++      rc = ioctl(fd, FS_IOC_GETFLAGS, &flags);
++      if (rc < 0) {
++              error = errno;
++              close(fd);
++              errno = error;
++              return rc;
++      }
++      close(fd);
++      if (flags & FS_IMMUTABLE_FL)
++              return 1;
++      return 0;
++}
+ 
+ int main(int argc, char **argv)
+ {
+@@ -27,7 +85,7 @@ int main(int argc, char **argv)
+       buf[4] = 0;
+ 
+       /* create a test variable */
+-      fd = open(path, O_WRONLY | O_CREAT);
++      fd = open(path, O_WRONLY | O_CREAT, 0600);
+       if (fd < 0) {
+               perror("open(O_WRONLY)");
+               return EXIT_FAILURE;
+@@ -41,6 +99,18 @@ int main(int argc, char **argv)
+ 
+       close(fd);
+ 
++      rc = get_immutable(path);
++      if (rc < 0) {
++              perror("ioctl(FS_IOC_GETFLAGS)");
++              return EXIT_FAILURE;
++      } else if (rc) {
++              rc = set_immutable(path, 0);
++              if (rc < 0) {
++                      perror("ioctl(FS_IOC_SETFLAGS)");
++                      return EXIT_FAILURE;
++              }
++      }
++
+       fd = open(path, O_RDONLY);
+       if (fd < 0) {
+               perror("open");

Reply via email to