commit: 28f69bd2360b5e24a3766113bd181016554af45e Author: Mike Pagano <mpagano <AT> gentoo <DOT> org> AuthorDate: Fri Mar 31 10:44:32 2017 +0000 Commit: Mike Pagano <mpagano <AT> gentoo <DOT> org> CommitDate: Fri Mar 31 10:44:32 2017 +0000 URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=28f69bd2
Linux patch 4.9.20 0000_README | 4 + 1019_linux-4.9.20.patch | 554 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 558 insertions(+) diff --git a/0000_README b/0000_README index 4eb0378..feea55b 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 0000000..91b8b98 --- /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, +- ®s, +- 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, +- ®s, +- (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, +- ®s, +- (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 *)®s; + + /* 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 *)®s, r = 0; r < ARRAY_SIZE(register_offset); r++) ++ BUILD_BUG_ON(sizeof(regs) % sizeof(long) != 0); ++ for (reg = (long *)®s, 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 *)®s, r = 0; r < ARRAY_SIZE(register_offset); r++) ++ for (reg = (long *)®s, 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;