summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Pagano <mpagano@gentoo.org>2017-03-31 06:44:32 -0400
committerMike Pagano <mpagano@gentoo.org>2017-03-31 06:44:32 -0400
commit28f69bd2360b5e24a3766113bd181016554af45e (patch)
tree723c281d6b0f363f552921a7dff2ea7e906a96b3
parentLinux patch 4.9.19 (diff)
downloadlinux-patches-28f69bd2.tar.gz
linux-patches-28f69bd2.tar.bz2
linux-patches-28f69bd2.zip
Linux patch 4.9.204.9-21
-rw-r--r--0000_README4
-rw-r--r--1019_linux-4.9.20.patch554
2 files changed, 558 insertions, 0 deletions
diff --git a/0000_README b/0000_README
index 4eb03786..feea55ba 100644
--- a/0000_README
+++ b/0000_README
@@ -119,6 +119,10 @@ Patch: 1018_linux-4.9.19.patch
From: http://www.kernel.org
Desc: Linux 4.9.19
+Patch: 1019_linux-4.9.20.patch
+From: http://www.kernel.org
+Desc: Linux 4.9.20
+
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/1019_linux-4.9.20.patch b/1019_linux-4.9.20.patch
new file mode 100644
index 00000000..91b8b987
--- /dev/null
+++ b/1019_linux-4.9.20.patch
@@ -0,0 +1,554 @@
+diff --git a/Makefile b/Makefile
+index ba1c6a8e6a70..44960184701a 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,6 +1,6 @@
+ VERSION = 4
+ PATCHLEVEL = 9
+-SUBLEVEL = 19
++SUBLEVEL = 20
+ EXTRAVERSION =
+ NAME = Roaring Lionus
+
+diff --git a/arch/c6x/kernel/ptrace.c b/arch/c6x/kernel/ptrace.c
+index 3c494e84444d..a511ac16a8e3 100644
+--- a/arch/c6x/kernel/ptrace.c
++++ b/arch/c6x/kernel/ptrace.c
+@@ -69,46 +69,6 @@ static int gpr_get(struct task_struct *target,
+ 0, sizeof(*regs));
+ }
+
+-static int gpr_set(struct task_struct *target,
+- const struct user_regset *regset,
+- unsigned int pos, unsigned int count,
+- const void *kbuf, const void __user *ubuf)
+-{
+- int ret;
+- struct pt_regs *regs = task_pt_regs(target);
+-
+- /* Don't copyin TSR or CSR */
+- ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+- &regs,
+- 0, PT_TSR * sizeof(long));
+- if (ret)
+- return ret;
+-
+- ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+- PT_TSR * sizeof(long),
+- (PT_TSR + 1) * sizeof(long));
+- if (ret)
+- return ret;
+-
+- ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+- &regs,
+- (PT_TSR + 1) * sizeof(long),
+- PT_CSR * sizeof(long));
+- if (ret)
+- return ret;
+-
+- ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+- PT_CSR * sizeof(long),
+- (PT_CSR + 1) * sizeof(long));
+- if (ret)
+- return ret;
+-
+- ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+- &regs,
+- (PT_CSR + 1) * sizeof(long), -1);
+- return ret;
+-}
+-
+ enum c6x_regset {
+ REGSET_GPR,
+ };
+@@ -120,7 +80,6 @@ static const struct user_regset c6x_regsets[] = {
+ .size = sizeof(u32),
+ .align = sizeof(u32),
+ .get = gpr_get,
+- .set = gpr_set
+ },
+ };
+
+diff --git a/arch/h8300/kernel/ptrace.c b/arch/h8300/kernel/ptrace.c
+index 92075544a19a..0dc1c8f622bc 100644
+--- a/arch/h8300/kernel/ptrace.c
++++ b/arch/h8300/kernel/ptrace.c
+@@ -95,7 +95,8 @@ static int regs_get(struct task_struct *target,
+ long *reg = (long *)&regs;
+
+ /* build user regs in buffer */
+- for (r = 0; r < ARRAY_SIZE(register_offset); r++)
++ BUILD_BUG_ON(sizeof(regs) % sizeof(long) != 0);
++ for (r = 0; r < sizeof(regs) / sizeof(long); r++)
+ *reg++ = h8300_get_reg(target, r);
+
+ return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+@@ -113,7 +114,8 @@ static int regs_set(struct task_struct *target,
+ long *reg;
+
+ /* build user regs in buffer */
+- for (reg = (long *)&regs, r = 0; r < ARRAY_SIZE(register_offset); r++)
++ BUILD_BUG_ON(sizeof(regs) % sizeof(long) != 0);
++ for (reg = (long *)&regs, r = 0; r < sizeof(regs) / sizeof(long); r++)
+ *reg++ = h8300_get_reg(target, r);
+
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+@@ -122,7 +124,7 @@ static int regs_set(struct task_struct *target,
+ return ret;
+
+ /* write back to pt_regs */
+- for (reg = (long *)&regs, r = 0; r < ARRAY_SIZE(register_offset); r++)
++ for (reg = (long *)&regs, r = 0; r < sizeof(regs) / sizeof(long); r++)
+ h8300_put_reg(target, r, *reg++);
+ return 0;
+ }
+diff --git a/arch/metag/kernel/ptrace.c b/arch/metag/kernel/ptrace.c
+index 7563628822bd..5e2dc7defd2c 100644
+--- a/arch/metag/kernel/ptrace.c
++++ b/arch/metag/kernel/ptrace.c
+@@ -24,6 +24,16 @@
+ * user_regset definitions.
+ */
+
++static unsigned long user_txstatus(const struct pt_regs *regs)
++{
++ unsigned long data = (unsigned long)regs->ctx.Flags;
++
++ if (regs->ctx.SaveMask & TBICTX_CBUF_BIT)
++ data |= USER_GP_REGS_STATUS_CATCH_BIT;
++
++ return data;
++}
++
+ int metag_gp_regs_copyout(const struct pt_regs *regs,
+ unsigned int pos, unsigned int count,
+ void *kbuf, void __user *ubuf)
+@@ -62,9 +72,7 @@ int metag_gp_regs_copyout(const struct pt_regs *regs,
+ if (ret)
+ goto out;
+ /* TXSTATUS */
+- data = (unsigned long)regs->ctx.Flags;
+- if (regs->ctx.SaveMask & TBICTX_CBUF_BIT)
+- data |= USER_GP_REGS_STATUS_CATCH_BIT;
++ data = user_txstatus(regs);
+ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+ &data, 4*25, 4*26);
+ if (ret)
+@@ -119,6 +127,7 @@ int metag_gp_regs_copyin(struct pt_regs *regs,
+ if (ret)
+ goto out;
+ /* TXSTATUS */
++ data = user_txstatus(regs);
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ &data, 4*25, 4*26);
+ if (ret)
+@@ -244,6 +253,8 @@ int metag_rp_state_copyin(struct pt_regs *regs,
+ unsigned long long *ptr;
+ int ret, i;
+
++ if (count < 4*13)
++ return -EINVAL;
+ /* Read the entire pipeline before making any changes */
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ &rp, 0, 4*13);
+@@ -303,7 +314,7 @@ static int metag_tls_set(struct task_struct *target,
+ const void *kbuf, const void __user *ubuf)
+ {
+ int ret;
+- void __user *tls;
++ void __user *tls = target->thread.tls_ptr;
+
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &tls, 0, -1);
+ if (ret)
+diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
+index a92994d60e91..bf83dc1eecfb 100644
+--- a/arch/mips/kernel/ptrace.c
++++ b/arch/mips/kernel/ptrace.c
+@@ -485,7 +485,8 @@ static int fpr_set(struct task_struct *target,
+ &target->thread.fpu,
+ 0, sizeof(elf_fpregset_t));
+
+- for (i = 0; i < NUM_FPU_REGS; i++) {
++ BUILD_BUG_ON(sizeof(fpr_val) != sizeof(elf_fpreg_t));
++ for (i = 0; i < NUM_FPU_REGS && count >= sizeof(elf_fpreg_t); i++) {
+ err = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ &fpr_val, i * sizeof(elf_fpreg_t),
+ (i + 1) * sizeof(elf_fpreg_t));
+diff --git a/arch/sparc/kernel/ptrace_64.c b/arch/sparc/kernel/ptrace_64.c
+index ac082dd8c67d..7037ca3b4328 100644
+--- a/arch/sparc/kernel/ptrace_64.c
++++ b/arch/sparc/kernel/ptrace_64.c
+@@ -313,7 +313,7 @@ static int genregs64_set(struct task_struct *target,
+ }
+
+ if (!ret) {
+- unsigned long y;
++ unsigned long y = regs->y;
+
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ &y,
+diff --git a/arch/x86/include/asm/kvm_page_track.h b/arch/x86/include/asm/kvm_page_track.h
+index c2b8d24a235c..6226cb0eca23 100644
+--- a/arch/x86/include/asm/kvm_page_track.h
++++ b/arch/x86/include/asm/kvm_page_track.h
+@@ -35,6 +35,7 @@ struct kvm_page_track_notifier_node {
+ };
+
+ void kvm_page_track_init(struct kvm *kvm);
++void kvm_page_track_cleanup(struct kvm *kvm);
+
+ void kvm_page_track_free_memslot(struct kvm_memory_slot *free,
+ struct kvm_memory_slot *dont);
+diff --git a/arch/x86/kvm/page_track.c b/arch/x86/kvm/page_track.c
+index b431539c3714..85024e0cfaa5 100644
+--- a/arch/x86/kvm/page_track.c
++++ b/arch/x86/kvm/page_track.c
+@@ -156,6 +156,14 @@ bool kvm_page_track_is_active(struct kvm_vcpu *vcpu, gfn_t gfn,
+ return !!ACCESS_ONCE(slot->arch.gfn_track[mode][index]);
+ }
+
++void kvm_page_track_cleanup(struct kvm *kvm)
++{
++ struct kvm_page_track_notifier_head *head;
++
++ head = &kvm->arch.track_notifier_head;
++ cleanup_srcu_struct(&head->track_srcu);
++}
++
+ void kvm_page_track_init(struct kvm *kvm)
+ {
+ struct kvm_page_track_notifier_head *head;
+diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
+index 731044efb195..e5bc139d1ba7 100644
+--- a/arch/x86/kvm/x86.c
++++ b/arch/x86/kvm/x86.c
+@@ -7976,6 +7976,7 @@ void kvm_arch_destroy_vm(struct kvm *kvm)
+ kvm_free_vcpus(kvm);
+ kvfree(rcu_dereference_check(kvm->arch.apic_map, 1));
+ kvm_mmu_uninit_vm(kvm);
++ kvm_page_track_cleanup(kvm);
+ }
+
+ void kvm_arch_free_memslot(struct kvm *kvm, struct kvm_memory_slot *free,
+diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c
+index 775c88303017..bedce3453dd3 100644
+--- a/drivers/pinctrl/qcom/pinctrl-msm.c
++++ b/drivers/pinctrl/qcom/pinctrl-msm.c
+@@ -594,10 +594,6 @@ static void msm_gpio_irq_unmask(struct irq_data *d)
+
+ spin_lock_irqsave(&pctrl->lock, flags);
+
+- val = readl(pctrl->regs + g->intr_status_reg);
+- val &= ~BIT(g->intr_status_bit);
+- writel(val, pctrl->regs + g->intr_status_reg);
+-
+ val = readl(pctrl->regs + g->intr_cfg_reg);
+ val |= BIT(g->intr_enable_bit);
+ writel(val, pctrl->regs + g->intr_cfg_reg);
+diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
+index 338575fb2d27..358feca54945 100644
+--- a/drivers/usb/musb/musb_core.c
++++ b/drivers/usb/musb/musb_core.c
+@@ -2467,8 +2467,8 @@ static int musb_remove(struct platform_device *pdev)
+ pm_runtime_get_sync(musb->controller);
+ musb_host_cleanup(musb);
+ musb_gadget_cleanup(musb);
+- spin_lock_irqsave(&musb->lock, flags);
+ musb_platform_disable(musb);
++ spin_lock_irqsave(&musb->lock, flags);
+ musb_generic_disable(musb);
+ spin_unlock_irqrestore(&musb->lock, flags);
+ musb_writeb(musb->mregs, MUSB_DEVCTL, 0);
+diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
+index 9d2738e9217f..2c2e6792f7e0 100644
+--- a/drivers/virtio/virtio_balloon.c
++++ b/drivers/virtio/virtio_balloon.c
+@@ -427,6 +427,8 @@ static int init_vqs(struct virtio_balloon *vb)
+ * Prime this virtqueue with one buffer so the hypervisor can
+ * use it to signal us later (it can't be broken yet!).
+ */
++ update_balloon_stats(vb);
++
+ sg_init_one(&sg, vb->stats, sizeof vb->stats);
+ if (virtqueue_add_outbuf(vb->stats_vq, &sg, 1, vb, GFP_KERNEL)
+ < 0)
+diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c
+index 98f87fe8f186..61cfccea77bc 100644
+--- a/fs/crypto/crypto.c
++++ b/fs/crypto/crypto.c
+@@ -352,7 +352,6 @@ EXPORT_SYMBOL(fscrypt_zeroout_range);
+ static int fscrypt_d_revalidate(struct dentry *dentry, unsigned int flags)
+ {
+ struct dentry *dir;
+- struct fscrypt_info *ci;
+ int dir_has_key, cached_with_key;
+
+ if (flags & LOOKUP_RCU)
+@@ -364,18 +363,11 @@ static int fscrypt_d_revalidate(struct dentry *dentry, unsigned int flags)
+ return 0;
+ }
+
+- ci = d_inode(dir)->i_crypt_info;
+- if (ci && ci->ci_keyring_key &&
+- (ci->ci_keyring_key->flags & ((1 << KEY_FLAG_INVALIDATED) |
+- (1 << KEY_FLAG_REVOKED) |
+- (1 << KEY_FLAG_DEAD))))
+- ci = NULL;
+-
+ /* this should eventually be an flag in d_flags */
+ spin_lock(&dentry->d_lock);
+ cached_with_key = dentry->d_flags & DCACHE_ENCRYPTED_WITH_KEY;
+ spin_unlock(&dentry->d_lock);
+- dir_has_key = (ci != NULL);
++ dir_has_key = (d_inode(dir)->i_crypt_info != NULL);
+ dput(dir);
+
+ /*
+diff --git a/fs/crypto/fname.c b/fs/crypto/fname.c
+index 9b774f4b50c8..80bb956e14e5 100644
+--- a/fs/crypto/fname.c
++++ b/fs/crypto/fname.c
+@@ -350,7 +350,7 @@ int fscrypt_setup_filename(struct inode *dir, const struct qstr *iname,
+ fname->disk_name.len = iname->len;
+ return 0;
+ }
+- ret = get_crypt_info(dir);
++ ret = fscrypt_get_encryption_info(dir);
+ if (ret && ret != -EOPNOTSUPP)
+ return ret;
+
+diff --git a/fs/crypto/keyinfo.c b/fs/crypto/keyinfo.c
+index 67fb6d8876d0..bb4606368eb1 100644
+--- a/fs/crypto/keyinfo.c
++++ b/fs/crypto/keyinfo.c
+@@ -99,6 +99,7 @@ static int validate_user_key(struct fscrypt_info *crypt_info,
+ kfree(full_key_descriptor);
+ if (IS_ERR(keyring_key))
+ return PTR_ERR(keyring_key);
++ down_read(&keyring_key->sem);
+
+ if (keyring_key->type != &key_type_logon) {
+ printk_once(KERN_WARNING
+@@ -106,11 +107,9 @@ static int validate_user_key(struct fscrypt_info *crypt_info,
+ res = -ENOKEY;
+ goto out;
+ }
+- down_read(&keyring_key->sem);
+ ukp = user_key_payload(keyring_key);
+ if (ukp->datalen != sizeof(struct fscrypt_key)) {
+ res = -EINVAL;
+- up_read(&keyring_key->sem);
+ goto out;
+ }
+ master_key = (struct fscrypt_key *)ukp->data;
+@@ -121,17 +120,11 @@ static int validate_user_key(struct fscrypt_info *crypt_info,
+ "%s: key size incorrect: %d\n",
+ __func__, master_key->size);
+ res = -ENOKEY;
+- up_read(&keyring_key->sem);
+ goto out;
+ }
+ res = derive_key_aes(ctx->nonce, master_key->raw, raw_key);
+- up_read(&keyring_key->sem);
+- if (res)
+- goto out;
+-
+- crypt_info->ci_keyring_key = keyring_key;
+- return 0;
+ out:
++ up_read(&keyring_key->sem);
+ key_put(keyring_key);
+ return res;
+ }
+@@ -173,12 +166,11 @@ static void put_crypt_info(struct fscrypt_info *ci)
+ if (!ci)
+ return;
+
+- key_put(ci->ci_keyring_key);
+ crypto_free_skcipher(ci->ci_ctfm);
+ kmem_cache_free(fscrypt_info_cachep, ci);
+ }
+
+-int get_crypt_info(struct inode *inode)
++int fscrypt_get_encryption_info(struct inode *inode)
+ {
+ struct fscrypt_info *crypt_info;
+ struct fscrypt_context ctx;
+@@ -188,21 +180,15 @@ int get_crypt_info(struct inode *inode)
+ u8 *raw_key = NULL;
+ int res;
+
++ if (inode->i_crypt_info)
++ return 0;
++
+ res = fscrypt_initialize();
+ if (res)
+ return res;
+
+ if (!inode->i_sb->s_cop->get_context)
+ return -EOPNOTSUPP;
+-retry:
+- crypt_info = ACCESS_ONCE(inode->i_crypt_info);
+- if (crypt_info) {
+- if (!crypt_info->ci_keyring_key ||
+- key_validate(crypt_info->ci_keyring_key) == 0)
+- return 0;
+- fscrypt_put_encryption_info(inode, crypt_info);
+- goto retry;
+- }
+
+ res = inode->i_sb->s_cop->get_context(inode, &ctx, sizeof(ctx));
+ if (res < 0) {
+@@ -230,7 +216,6 @@ int get_crypt_info(struct inode *inode)
+ crypt_info->ci_data_mode = ctx.contents_encryption_mode;
+ crypt_info->ci_filename_mode = ctx.filenames_encryption_mode;
+ crypt_info->ci_ctfm = NULL;
+- crypt_info->ci_keyring_key = NULL;
+ memcpy(crypt_info->ci_master_key, ctx.master_key_descriptor,
+ sizeof(crypt_info->ci_master_key));
+
+@@ -285,14 +270,8 @@ int get_crypt_info(struct inode *inode)
+ if (res)
+ goto out;
+
+- kzfree(raw_key);
+- raw_key = NULL;
+- if (cmpxchg(&inode->i_crypt_info, NULL, crypt_info) != NULL) {
+- put_crypt_info(crypt_info);
+- goto retry;
+- }
+- return 0;
+-
++ if (cmpxchg(&inode->i_crypt_info, NULL, crypt_info) == NULL)
++ crypt_info = NULL;
+ out:
+ if (res == -ENOKEY)
+ res = 0;
+@@ -300,6 +279,7 @@ int get_crypt_info(struct inode *inode)
+ kzfree(raw_key);
+ return res;
+ }
++EXPORT_SYMBOL(fscrypt_get_encryption_info);
+
+ void fscrypt_put_encryption_info(struct inode *inode, struct fscrypt_info *ci)
+ {
+@@ -317,17 +297,3 @@ void fscrypt_put_encryption_info(struct inode *inode, struct fscrypt_info *ci)
+ put_crypt_info(ci);
+ }
+ EXPORT_SYMBOL(fscrypt_put_encryption_info);
+-
+-int fscrypt_get_encryption_info(struct inode *inode)
+-{
+- struct fscrypt_info *ci = inode->i_crypt_info;
+-
+- if (!ci ||
+- (ci->ci_keyring_key &&
+- (ci->ci_keyring_key->flags & ((1 << KEY_FLAG_INVALIDATED) |
+- (1 << KEY_FLAG_REVOKED) |
+- (1 << KEY_FLAG_DEAD)))))
+- return get_crypt_info(inode);
+- return 0;
+-}
+-EXPORT_SYMBOL(fscrypt_get_encryption_info);
+diff --git a/include/linux/fscrypto.h b/include/linux/fscrypto.h
+index ff8b11b26f31..f6dfc2950f76 100644
+--- a/include/linux/fscrypto.h
++++ b/include/linux/fscrypto.h
+@@ -79,7 +79,6 @@ struct fscrypt_info {
+ u8 ci_filename_mode;
+ u8 ci_flags;
+ struct crypto_skcipher *ci_ctfm;
+- struct key *ci_keyring_key;
+ u8 ci_master_key[FS_KEY_DESCRIPTOR_SIZE];
+ };
+
+@@ -256,7 +255,6 @@ extern int fscrypt_has_permitted_context(struct inode *, struct inode *);
+ extern int fscrypt_inherit_context(struct inode *, struct inode *,
+ void *, bool);
+ /* keyinfo.c */
+-extern int get_crypt_info(struct inode *);
+ extern int fscrypt_get_encryption_info(struct inode *);
+ extern void fscrypt_put_encryption_info(struct inode *, struct fscrypt_info *);
+
+diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c
+index 37e2449186c4..c95c5122b105 100644
+--- a/kernel/sched/deadline.c
++++ b/kernel/sched/deadline.c
+@@ -1729,12 +1729,11 @@ static void switched_to_dl(struct rq *rq, struct task_struct *p)
+ #ifdef CONFIG_SMP
+ if (tsk_nr_cpus_allowed(p) > 1 && rq->dl.overloaded)
+ queue_push_tasks(rq);
+-#else
++#endif
+ if (dl_task(rq->curr))
+ check_preempt_curr_dl(rq, p, 0);
+ else
+ resched_curr(rq);
+-#endif
+ }
+ }
+
+diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c
+index 2516b8df6dbb..f139f22ce30d 100644
+--- a/kernel/sched/rt.c
++++ b/kernel/sched/rt.c
+@@ -2198,10 +2198,9 @@ static void switched_to_rt(struct rq *rq, struct task_struct *p)
+ #ifdef CONFIG_SMP
+ if (tsk_nr_cpus_allowed(p) > 1 && rq->rt.overloaded)
+ queue_push_tasks(rq);
+-#else
++#endif /* CONFIG_SMP */
+ if (p->prio < rq->curr->prio)
+ resched_curr(rq);
+-#endif /* CONFIG_SMP */
+ }
+ }
+
+diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
+index 5bf7e1bfeac7..e0437a7aa1a2 100644
+--- a/net/xfrm/xfrm_policy.c
++++ b/net/xfrm/xfrm_policy.c
+@@ -3062,6 +3062,11 @@ static int __net_init xfrm_net_init(struct net *net)
+ {
+ int rv;
+
++ /* Initialize the per-net locks here */
++ spin_lock_init(&net->xfrm.xfrm_state_lock);
++ spin_lock_init(&net->xfrm.xfrm_policy_lock);
++ mutex_init(&net->xfrm.xfrm_cfg_mutex);
++
+ rv = xfrm_statistics_init(net);
+ if (rv < 0)
+ goto out_statistics;
+@@ -3078,11 +3083,6 @@ static int __net_init xfrm_net_init(struct net *net)
+ if (rv < 0)
+ goto out;
+
+- /* Initialize the per-net locks here */
+- spin_lock_init(&net->xfrm.xfrm_state_lock);
+- spin_lock_init(&net->xfrm.xfrm_policy_lock);
+- mutex_init(&net->xfrm.xfrm_cfg_mutex);
+-
+ return 0;
+
+ out:
+diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
+index 671a1d0333f0..a7e27e1140dd 100644
+--- a/net/xfrm/xfrm_user.c
++++ b/net/xfrm/xfrm_user.c
+@@ -412,7 +412,14 @@ static inline int xfrm_replay_verify_len(struct xfrm_replay_state_esn *replay_es
+ up = nla_data(rp);
+ ulen = xfrm_replay_state_esn_len(up);
+
+- if (nla_len(rp) < ulen || xfrm_replay_state_esn_len(replay_esn) != ulen)
++ /* Check the overall length and the internal bitmap length to avoid
++ * potential overflow. */
++ if (nla_len(rp) < ulen ||
++ xfrm_replay_state_esn_len(replay_esn) != ulen ||
++ replay_esn->bmp_len != up->bmp_len)
++ return -EINVAL;
++
++ if (up->replay_window > up->bmp_len * sizeof(__u32) * 8)
+ return -EINVAL;
+
+ return 0;