mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-09 12:17:12 +09:00
Merge 4.9.20 into android-4.9
Changes in 4.9.20: xfrm: policy: init locks early xfrm_user: validate XFRM_MSG_NEWAE XFRMA_REPLAY_ESN_VAL replay_window xfrm_user: validate XFRM_MSG_NEWAE incoming ESN size harder KVM: x86: cleanup the page tracking SRCU instance virtio_balloon: init 1st buffer in stats vq pinctrl: qcom: Don't clear status bit on irq_unmask c6x/ptrace: Remove useless PTRACE_SETREGSET implementation h8300/ptrace: Fix incorrect register transfer count mips/ptrace: Preserve previous registers for short regset write sparc/ptrace: Preserve previous registers for short regset write metag/ptrace: Preserve previous registers for short regset write metag/ptrace: Provide default TXSTATUS for short NT_PRSTATUS metag/ptrace: Reject partial NT_METAG_RPIPE writes fscrypt: remove broken support for detecting keyring key revocation sched/rt: Add a missing rescheduling point usb: musb: fix possible spinlock deadlock Linux 4.9.20 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
2
Makefile
2
Makefile
@@ -1,6 +1,6 @@
|
||||
VERSION = 4
|
||||
PATCHLEVEL = 9
|
||||
SUBLEVEL = 19
|
||||
SUBLEVEL = 20
|
||||
EXTRAVERSION =
|
||||
NAME = Roaring Lionus
|
||||
|
||||
|
||||
@@ -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
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
/*
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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 @@ retry:
|
||||
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 @@ got_key:
|
||||
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 @@ out:
|
||||
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);
|
||||
|
||||
@@ -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 *);
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2253,10 +2253,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 */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user