Merge 4.9.76 into android-4.9-o
Changes in 4.9.76 kernel/acct.c: fix the acct->needcheck check in check_free_space() crypto: n2 - cure use after free crypto: chacha20poly1305 - validate the digest size crypto: pcrypt - fix freeing pcrypt instances sunxi-rsb: Include OF based modalias in device uevent fscache: Fix the default for fscache_maybe_release_page() nbd: fix use-after-free of rq/bio in the xmit path kernel: make groups_sort calling a responsibility group_info allocators kernel/signal.c: protect the traced SIGNAL_UNKILLABLE tasks from SIGKILL kernel/signal.c: protect the SIGNAL_UNKILLABLE tasks from !sig_kernel_only() signals kernel/signal.c: remove the no longer needed SIGNAL_UNKILLABLE check in complete_signal() iommu/arm-smmu-v3: Don't free page table ops twice iommu/arm-smmu-v3: Cope with duplicated Stream IDs ARC: uaccess: dont use "l" gcc inline asm constraint modifier Input: elantech - add new icbody type 15 x86/microcode/AMD: Add support for fam17h microcode loading parisc: Fix alignment of pa_tlb_lock in assembly on 32-bit SMP kernel parisc: qemu idle sleep support x86/tlb: Drop the _GPL from the cpu_tlbstate export Map the vsyscall page with _PAGE_USER mtd: nand: pxa3xx: Fix READOOB implementation Linux 4.9.76 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 = 75
|
||||
SUBLEVEL = 76
|
||||
EXTRAVERSION =
|
||||
NAME = Roaring Lionus
|
||||
|
||||
|
||||
@@ -673,6 +673,7 @@ __arc_strncpy_from_user(char *dst, const char __user *src, long count)
|
||||
return 0;
|
||||
|
||||
__asm__ __volatile__(
|
||||
" mov lp_count, %5 \n"
|
||||
" lp 3f \n"
|
||||
"1: ldb.ab %3, [%2, 1] \n"
|
||||
" breq.d %3, 0, 3f \n"
|
||||
@@ -689,8 +690,8 @@ __arc_strncpy_from_user(char *dst, const char __user *src, long count)
|
||||
" .word 1b, 4b \n"
|
||||
" .previous \n"
|
||||
: "+r"(res), "+r"(dst), "+r"(src), "=r"(val)
|
||||
: "g"(-EFAULT), "l"(count)
|
||||
: "memory");
|
||||
: "g"(-EFAULT), "r"(count)
|
||||
: "lp_count", "lp_start", "lp_end", "memory");
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
for the semaphore. */
|
||||
|
||||
#define __PA_LDCW_ALIGNMENT 16
|
||||
#define __PA_LDCW_ALIGN_ORDER 4
|
||||
#define __ldcw_align(a) ({ \
|
||||
unsigned long __ret = (unsigned long) &(a)->lock[0]; \
|
||||
__ret = (__ret + __PA_LDCW_ALIGNMENT - 1) \
|
||||
@@ -28,6 +29,7 @@
|
||||
ldcd). */
|
||||
|
||||
#define __PA_LDCW_ALIGNMENT 4
|
||||
#define __PA_LDCW_ALIGN_ORDER 2
|
||||
#define __ldcw_align(a) (&(a)->slock)
|
||||
#define __LDCW "ldcw,co"
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/signal.h>
|
||||
#include <asm/unistd.h>
|
||||
#include <asm/ldcw.h>
|
||||
#include <asm/thread_info.h>
|
||||
|
||||
#include <linux/linkage.h>
|
||||
@@ -46,6 +47,14 @@
|
||||
#endif
|
||||
|
||||
.import pa_tlb_lock,data
|
||||
.macro load_pa_tlb_lock reg
|
||||
#if __PA_LDCW_ALIGNMENT > 4
|
||||
load32 PA(pa_tlb_lock) + __PA_LDCW_ALIGNMENT-1, \reg
|
||||
depi 0,31,__PA_LDCW_ALIGN_ORDER, \reg
|
||||
#else
|
||||
load32 PA(pa_tlb_lock), \reg
|
||||
#endif
|
||||
.endm
|
||||
|
||||
/* space_to_prot macro creates a prot id from a space id */
|
||||
|
||||
@@ -457,7 +466,7 @@
|
||||
.macro tlb_lock spc,ptp,pte,tmp,tmp1,fault
|
||||
#ifdef CONFIG_SMP
|
||||
cmpib,COND(=),n 0,\spc,2f
|
||||
load32 PA(pa_tlb_lock),\tmp
|
||||
load_pa_tlb_lock \tmp
|
||||
1: LDCW 0(\tmp),\tmp1
|
||||
cmpib,COND(=) 0,\tmp1,1b
|
||||
nop
|
||||
@@ -480,7 +489,7 @@
|
||||
/* Release pa_tlb_lock lock. */
|
||||
.macro tlb_unlock1 spc,tmp
|
||||
#ifdef CONFIG_SMP
|
||||
load32 PA(pa_tlb_lock),\tmp
|
||||
load_pa_tlb_lock \tmp
|
||||
tlb_unlock0 \spc,\tmp
|
||||
#endif
|
||||
.endm
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include <asm/assembly.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/cache.h>
|
||||
#include <asm/ldcw.h>
|
||||
#include <linux/linkage.h>
|
||||
|
||||
.text
|
||||
@@ -333,8 +334,12 @@ ENDPROC_CFI(flush_data_cache_local)
|
||||
|
||||
.macro tlb_lock la,flags,tmp
|
||||
#ifdef CONFIG_SMP
|
||||
ldil L%pa_tlb_lock,%r1
|
||||
ldo R%pa_tlb_lock(%r1),\la
|
||||
#if __PA_LDCW_ALIGNMENT > 4
|
||||
load32 pa_tlb_lock + __PA_LDCW_ALIGNMENT-1, \la
|
||||
depi 0,31,__PA_LDCW_ALIGN_ORDER, \la
|
||||
#else
|
||||
load32 pa_tlb_lock, \la
|
||||
#endif
|
||||
rsm PSW_SM_I,\flags
|
||||
1: LDCW 0(\la),\tmp
|
||||
cmpib,<>,n 0,\tmp,3f
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/personality.h>
|
||||
#include <linux/ptrace.h>
|
||||
@@ -180,6 +181,44 @@ int dump_task_fpu (struct task_struct *tsk, elf_fpregset_t *r)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Idle thread support
|
||||
*
|
||||
* Detect when running on QEMU with SeaBIOS PDC Firmware and let
|
||||
* QEMU idle the host too.
|
||||
*/
|
||||
|
||||
int running_on_qemu __read_mostly;
|
||||
|
||||
void __cpuidle arch_cpu_idle_dead(void)
|
||||
{
|
||||
/* nop on real hardware, qemu will offline CPU. */
|
||||
asm volatile("or %%r31,%%r31,%%r31\n":::);
|
||||
}
|
||||
|
||||
void __cpuidle arch_cpu_idle(void)
|
||||
{
|
||||
local_irq_enable();
|
||||
|
||||
/* nop on real hardware, qemu will idle sleep. */
|
||||
asm volatile("or %%r10,%%r10,%%r10\n":::);
|
||||
}
|
||||
|
||||
static int __init parisc_idle_init(void)
|
||||
{
|
||||
const char *marker;
|
||||
|
||||
/* check QEMU/SeaBIOS marker in PAGE0 */
|
||||
marker = (char *) &PAGE0->pad0;
|
||||
running_on_qemu = (memcmp(marker, "SeaBIOS", 8) == 0);
|
||||
|
||||
if (!running_on_qemu)
|
||||
cpu_idle_poll_ctrl(1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
arch_initcall(parisc_idle_init);
|
||||
|
||||
/*
|
||||
* Copy architecture-specific thread state
|
||||
*/
|
||||
|
||||
@@ -263,6 +263,7 @@ COMPAT_SYSCALL_DEFINE2(s390_setgroups16, int, gidsetsize, u16 __user *, grouplis
|
||||
return retval;
|
||||
}
|
||||
|
||||
groups_sort(group_info);
|
||||
retval = set_current_groups(group_info);
|
||||
put_group_info(group_info);
|
||||
|
||||
|
||||
@@ -66,6 +66,11 @@ static int __init vsyscall_setup(char *str)
|
||||
}
|
||||
early_param("vsyscall", vsyscall_setup);
|
||||
|
||||
bool vsyscall_enabled(void)
|
||||
{
|
||||
return vsyscall_mode != NONE;
|
||||
}
|
||||
|
||||
static void warn_bad_vsyscall(const char *level, struct pt_regs *regs,
|
||||
const char *message)
|
||||
{
|
||||
|
||||
@@ -12,12 +12,14 @@ extern void map_vsyscall(void);
|
||||
* Returns true if handled.
|
||||
*/
|
||||
extern bool emulate_vsyscall(struct pt_regs *regs, unsigned long address);
|
||||
extern bool vsyscall_enabled(void);
|
||||
#else
|
||||
static inline void map_vsyscall(void) {}
|
||||
static inline bool emulate_vsyscall(struct pt_regs *regs, unsigned long address)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
static inline bool vsyscall_enabled(void) { return false; }
|
||||
#endif
|
||||
|
||||
#endif /* _ASM_X86_VSYSCALL_H */
|
||||
|
||||
@@ -592,6 +592,7 @@ static unsigned int verify_patch_size(u8 family, u32 patch_size,
|
||||
#define F14H_MPB_MAX_SIZE 1824
|
||||
#define F15H_MPB_MAX_SIZE 4096
|
||||
#define F16H_MPB_MAX_SIZE 3458
|
||||
#define F17H_MPB_MAX_SIZE 3200
|
||||
|
||||
switch (family) {
|
||||
case 0x14:
|
||||
@@ -603,6 +604,9 @@ static unsigned int verify_patch_size(u8 family, u32 patch_size,
|
||||
case 0x16:
|
||||
max_size = F16H_MPB_MAX_SIZE;
|
||||
break;
|
||||
case 0x17:
|
||||
max_size = F17H_MPB_MAX_SIZE;
|
||||
break;
|
||||
default:
|
||||
max_size = F1XH_MPB_MAX_SIZE;
|
||||
break;
|
||||
|
||||
@@ -768,7 +768,7 @@ DEFINE_PER_CPU_SHARED_ALIGNED(struct tlb_state, cpu_tlbstate) = {
|
||||
.state = 0,
|
||||
.cr4 = ~0UL, /* fail hard if we screw up cr4 shadow initialization */
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(cpu_tlbstate);
|
||||
EXPORT_PER_CPU_SYMBOL(cpu_tlbstate);
|
||||
|
||||
void update_cache_mode_entry(unsigned entry, enum page_cache_mode cache)
|
||||
{
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <asm/pgalloc.h>
|
||||
#include <asm/desc.h>
|
||||
#include <asm/cmdline.h>
|
||||
#include <asm/vsyscall.h>
|
||||
|
||||
int kaiser_enabled __read_mostly = 1;
|
||||
EXPORT_SYMBOL(kaiser_enabled); /* for inlined TLB flush functions */
|
||||
@@ -110,12 +111,13 @@ static inline unsigned long get_pa_from_mapping(unsigned long vaddr)
|
||||
*
|
||||
* Returns a pointer to a PTE on success, or NULL on failure.
|
||||
*/
|
||||
static pte_t *kaiser_pagetable_walk(unsigned long address)
|
||||
static pte_t *kaiser_pagetable_walk(unsigned long address, bool user)
|
||||
{
|
||||
pmd_t *pmd;
|
||||
pud_t *pud;
|
||||
pgd_t *pgd = native_get_shadow_pgd(pgd_offset_k(address));
|
||||
gfp_t gfp = (GFP_KERNEL | __GFP_NOTRACK | __GFP_ZERO);
|
||||
unsigned long prot = _KERNPG_TABLE;
|
||||
|
||||
if (pgd_none(*pgd)) {
|
||||
WARN_ONCE(1, "All shadow pgds should have been populated");
|
||||
@@ -123,6 +125,17 @@ static pte_t *kaiser_pagetable_walk(unsigned long address)
|
||||
}
|
||||
BUILD_BUG_ON(pgd_large(*pgd) != 0);
|
||||
|
||||
if (user) {
|
||||
/*
|
||||
* The vsyscall page is the only page that will have
|
||||
* _PAGE_USER set. Catch everything else.
|
||||
*/
|
||||
BUG_ON(address != VSYSCALL_ADDR);
|
||||
|
||||
set_pgd(pgd, __pgd(pgd_val(*pgd) | _PAGE_USER));
|
||||
prot = _PAGE_TABLE;
|
||||
}
|
||||
|
||||
pud = pud_offset(pgd, address);
|
||||
/* The shadow page tables do not use large mappings: */
|
||||
if (pud_large(*pud)) {
|
||||
@@ -135,7 +148,7 @@ static pte_t *kaiser_pagetable_walk(unsigned long address)
|
||||
return NULL;
|
||||
spin_lock(&shadow_table_allocation_lock);
|
||||
if (pud_none(*pud)) {
|
||||
set_pud(pud, __pud(_KERNPG_TABLE | __pa(new_pmd_page)));
|
||||
set_pud(pud, __pud(prot | __pa(new_pmd_page)));
|
||||
__inc_zone_page_state(virt_to_page((void *)
|
||||
new_pmd_page), NR_KAISERTABLE);
|
||||
} else
|
||||
@@ -155,7 +168,7 @@ static pte_t *kaiser_pagetable_walk(unsigned long address)
|
||||
return NULL;
|
||||
spin_lock(&shadow_table_allocation_lock);
|
||||
if (pmd_none(*pmd)) {
|
||||
set_pmd(pmd, __pmd(_KERNPG_TABLE | __pa(new_pte_page)));
|
||||
set_pmd(pmd, __pmd(prot | __pa(new_pte_page)));
|
||||
__inc_zone_page_state(virt_to_page((void *)
|
||||
new_pte_page), NR_KAISERTABLE);
|
||||
} else
|
||||
@@ -191,7 +204,7 @@ static int kaiser_add_user_map(const void *__start_addr, unsigned long size,
|
||||
ret = -EIO;
|
||||
break;
|
||||
}
|
||||
pte = kaiser_pagetable_walk(address);
|
||||
pte = kaiser_pagetable_walk(address, flags & _PAGE_USER);
|
||||
if (!pte) {
|
||||
ret = -ENOMEM;
|
||||
break;
|
||||
@@ -318,6 +331,19 @@ void __init kaiser_init(void)
|
||||
|
||||
kaiser_init_all_pgds();
|
||||
|
||||
/*
|
||||
* Note that this sets _PAGE_USER and it needs to happen when the
|
||||
* pagetable hierarchy gets created, i.e., early. Otherwise
|
||||
* kaiser_pagetable_walk() will encounter initialized PTEs in the
|
||||
* hierarchy and not set the proper permissions, leading to the
|
||||
* pagefaults with page-protection violations when trying to read the
|
||||
* vsyscall page. For example.
|
||||
*/
|
||||
if (vsyscall_enabled())
|
||||
kaiser_add_user_map_early((void *)VSYSCALL_ADDR,
|
||||
PAGE_SIZE,
|
||||
__PAGE_KERNEL_VSYSCALL);
|
||||
|
||||
for_each_possible_cpu(cpu) {
|
||||
void *percpu_vaddr = __per_cpu_user_mapped_start +
|
||||
per_cpu_offset(cpu);
|
||||
|
||||
@@ -610,6 +610,11 @@ static int chachapoly_create(struct crypto_template *tmpl, struct rtattr **tb,
|
||||
algt->mask));
|
||||
if (IS_ERR(poly))
|
||||
return PTR_ERR(poly);
|
||||
poly_hash = __crypto_hash_alg_common(poly);
|
||||
|
||||
err = -EINVAL;
|
||||
if (poly_hash->digestsize != POLY1305_DIGEST_SIZE)
|
||||
goto out_put_poly;
|
||||
|
||||
err = -ENOMEM;
|
||||
inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
|
||||
@@ -618,7 +623,6 @@ static int chachapoly_create(struct crypto_template *tmpl, struct rtattr **tb,
|
||||
|
||||
ctx = aead_instance_ctx(inst);
|
||||
ctx->saltlen = CHACHAPOLY_IV_SIZE - ivsize;
|
||||
poly_hash = __crypto_hash_alg_common(poly);
|
||||
err = crypto_init_ahash_spawn(&ctx->poly, poly_hash,
|
||||
aead_crypto_instance(inst));
|
||||
if (err)
|
||||
|
||||
@@ -254,6 +254,14 @@ static void pcrypt_aead_exit_tfm(struct crypto_aead *tfm)
|
||||
crypto_free_aead(ctx->child);
|
||||
}
|
||||
|
||||
static void pcrypt_free(struct aead_instance *inst)
|
||||
{
|
||||
struct pcrypt_instance_ctx *ctx = aead_instance_ctx(inst);
|
||||
|
||||
crypto_drop_aead(&ctx->spawn);
|
||||
kfree(inst);
|
||||
}
|
||||
|
||||
static int pcrypt_init_instance(struct crypto_instance *inst,
|
||||
struct crypto_alg *alg)
|
||||
{
|
||||
@@ -319,6 +327,8 @@ static int pcrypt_create_aead(struct crypto_template *tmpl, struct rtattr **tb,
|
||||
inst->alg.encrypt = pcrypt_aead_encrypt;
|
||||
inst->alg.decrypt = pcrypt_aead_decrypt;
|
||||
|
||||
inst->free = pcrypt_free;
|
||||
|
||||
err = aead_register_instance(tmpl, inst);
|
||||
if (err)
|
||||
goto out_drop_aead;
|
||||
@@ -349,14 +359,6 @@ static int pcrypt_create(struct crypto_template *tmpl, struct rtattr **tb)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static void pcrypt_free(struct crypto_instance *inst)
|
||||
{
|
||||
struct pcrypt_instance_ctx *ctx = crypto_instance_ctx(inst);
|
||||
|
||||
crypto_drop_aead(&ctx->spawn);
|
||||
kfree(inst);
|
||||
}
|
||||
|
||||
static int pcrypt_cpumask_change_notify(struct notifier_block *self,
|
||||
unsigned long val, void *data)
|
||||
{
|
||||
@@ -469,7 +471,6 @@ static void pcrypt_fini_padata(struct padata_pcrypt *pcrypt)
|
||||
static struct crypto_template pcrypt_tmpl = {
|
||||
.name = "pcrypt",
|
||||
.create = pcrypt_create,
|
||||
.free = pcrypt_free,
|
||||
.module = THIS_MODULE,
|
||||
};
|
||||
|
||||
|
||||
@@ -272,6 +272,7 @@ static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd)
|
||||
int result, flags;
|
||||
struct nbd_request request;
|
||||
unsigned long size = blk_rq_bytes(req);
|
||||
struct bio *bio;
|
||||
u32 type;
|
||||
|
||||
if (req->cmd_type == REQ_TYPE_DRV_PRIV)
|
||||
@@ -305,16 +306,20 @@ static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd)
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (type == NBD_CMD_WRITE) {
|
||||
struct req_iterator iter;
|
||||
if (type != NBD_CMD_WRITE)
|
||||
return 0;
|
||||
|
||||
flags = 0;
|
||||
bio = req->bio;
|
||||
while (bio) {
|
||||
struct bio *next = bio->bi_next;
|
||||
struct bvec_iter iter;
|
||||
struct bio_vec bvec;
|
||||
/*
|
||||
* we are really probing at internals to determine
|
||||
* whether to set MSG_MORE or not...
|
||||
*/
|
||||
rq_for_each_segment(bvec, req, iter) {
|
||||
flags = 0;
|
||||
if (!rq_iter_last(bvec, iter))
|
||||
|
||||
bio_for_each_segment(bvec, bio, iter) {
|
||||
bool is_last = !next && bio_iter_last(bvec, iter);
|
||||
|
||||
if (is_last)
|
||||
flags = MSG_MORE;
|
||||
dev_dbg(nbd_to_dev(nbd), "request %p: sending %d bytes data\n",
|
||||
cmd, bvec.bv_len);
|
||||
@@ -325,7 +330,16 @@ static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd)
|
||||
result);
|
||||
return -EIO;
|
||||
}
|
||||
/*
|
||||
* The completion might already have come in,
|
||||
* so break for the last one instead of letting
|
||||
* the iterator do it. This prevents use-after-free
|
||||
* of the bio.
|
||||
*/
|
||||
if (is_last)
|
||||
break;
|
||||
}
|
||||
bio = next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -178,6 +178,7 @@ static struct bus_type sunxi_rsb_bus = {
|
||||
.match = sunxi_rsb_device_match,
|
||||
.probe = sunxi_rsb_device_probe,
|
||||
.remove = sunxi_rsb_device_remove,
|
||||
.uevent = of_device_uevent_modalias,
|
||||
};
|
||||
|
||||
static void sunxi_rsb_dev_release(struct device *dev)
|
||||
|
||||
@@ -1620,6 +1620,7 @@ static int queue_cache_init(void)
|
||||
CWQ_ENTRY_SIZE, 0, NULL);
|
||||
if (!queue_cache[HV_NCS_QTYPE_CWQ - 1]) {
|
||||
kmem_cache_destroy(queue_cache[HV_NCS_QTYPE_MAU - 1]);
|
||||
queue_cache[HV_NCS_QTYPE_MAU - 1] = NULL;
|
||||
return -ENOMEM;
|
||||
}
|
||||
return 0;
|
||||
@@ -1629,6 +1630,8 @@ static void queue_cache_destroy(void)
|
||||
{
|
||||
kmem_cache_destroy(queue_cache[HV_NCS_QTYPE_MAU - 1]);
|
||||
kmem_cache_destroy(queue_cache[HV_NCS_QTYPE_CWQ - 1]);
|
||||
queue_cache[HV_NCS_QTYPE_MAU - 1] = NULL;
|
||||
queue_cache[HV_NCS_QTYPE_CWQ - 1] = NULL;
|
||||
}
|
||||
|
||||
static int spu_queue_register(struct spu_queue *p, unsigned long q_type)
|
||||
|
||||
@@ -1609,7 +1609,7 @@ static int elantech_set_properties(struct elantech_data *etd)
|
||||
case 5:
|
||||
etd->hw_version = 3;
|
||||
break;
|
||||
case 6 ... 14:
|
||||
case 6 ... 15:
|
||||
etd->hw_version = 4;
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -1547,13 +1547,15 @@ static int arm_smmu_domain_finalise(struct iommu_domain *domain)
|
||||
domain->pgsize_bitmap = pgtbl_cfg.pgsize_bitmap;
|
||||
domain->geometry.aperture_end = (1UL << ias) - 1;
|
||||
domain->geometry.force_aperture = true;
|
||||
smmu_domain->pgtbl_ops = pgtbl_ops;
|
||||
|
||||
ret = finalise_stage_fn(smmu_domain, &pgtbl_cfg);
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
free_io_pgtable_ops(pgtbl_ops);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
smmu_domain->pgtbl_ops = pgtbl_ops;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __le64 *arm_smmu_get_step_for_sid(struct arm_smmu_device *smmu, u32 sid)
|
||||
@@ -1580,7 +1582,7 @@ static __le64 *arm_smmu_get_step_for_sid(struct arm_smmu_device *smmu, u32 sid)
|
||||
|
||||
static int arm_smmu_install_ste_for_dev(struct iommu_fwspec *fwspec)
|
||||
{
|
||||
int i;
|
||||
int i, j;
|
||||
struct arm_smmu_master_data *master = fwspec->iommu_priv;
|
||||
struct arm_smmu_device *smmu = master->smmu;
|
||||
|
||||
@@ -1588,6 +1590,13 @@ static int arm_smmu_install_ste_for_dev(struct iommu_fwspec *fwspec)
|
||||
u32 sid = fwspec->ids[i];
|
||||
__le64 *step = arm_smmu_get_step_for_sid(smmu, sid);
|
||||
|
||||
/* Bridged PCI devices may end up with duplicated IDs */
|
||||
for (j = 0; j < i; j++)
|
||||
if (fwspec->ids[j] == sid)
|
||||
break;
|
||||
if (j < i)
|
||||
continue;
|
||||
|
||||
arm_smmu_write_strtab_ent(smmu, sid, step, &master->ste);
|
||||
}
|
||||
|
||||
|
||||
@@ -950,6 +950,7 @@ static void prepare_start_command(struct pxa3xx_nand_info *info, int command)
|
||||
|
||||
switch (command) {
|
||||
case NAND_CMD_READ0:
|
||||
case NAND_CMD_READOOB:
|
||||
case NAND_CMD_PAGEPROG:
|
||||
info->use_ecc = 1;
|
||||
break;
|
||||
|
||||
@@ -59,6 +59,9 @@ int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp)
|
||||
gi->gid[i] = exp->ex_anon_gid;
|
||||
else
|
||||
gi->gid[i] = rqgi->gid[i];
|
||||
|
||||
/* Each thread allocates its own gi, no race */
|
||||
groups_sort(gi);
|
||||
}
|
||||
} else {
|
||||
gi = get_group_info(rqgi);
|
||||
|
||||
@@ -82,6 +82,7 @@ extern int set_current_groups(struct group_info *);
|
||||
extern void set_groups(struct cred *, struct group_info *);
|
||||
extern int groups_search(const struct group_info *, kgid_t);
|
||||
extern bool may_setgroups(void);
|
||||
extern void groups_sort(struct group_info *);
|
||||
|
||||
/*
|
||||
* The security context of a task
|
||||
|
||||
@@ -764,7 +764,7 @@ bool fscache_maybe_release_page(struct fscache_cookie *cookie,
|
||||
{
|
||||
if (fscache_cookie_valid(cookie) && PageFsCache(page))
|
||||
return __fscache_maybe_release_page(cookie, page, gfp);
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -99,7 +99,7 @@ static int check_free_space(struct bsd_acct_struct *acct)
|
||||
{
|
||||
struct kstatfs sbuf;
|
||||
|
||||
if (time_is_before_jiffies(acct->needcheck))
|
||||
if (time_is_after_jiffies(acct->needcheck))
|
||||
goto out;
|
||||
|
||||
/* May block */
|
||||
|
||||
@@ -77,7 +77,7 @@ static int groups_from_user(struct group_info *group_info,
|
||||
}
|
||||
|
||||
/* a simple Shell sort */
|
||||
static void groups_sort(struct group_info *group_info)
|
||||
void groups_sort(struct group_info *group_info)
|
||||
{
|
||||
int base, max, stride;
|
||||
int gidsetsize = group_info->ngroups;
|
||||
@@ -103,6 +103,7 @@ static void groups_sort(struct group_info *group_info)
|
||||
stride /= 3;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(groups_sort);
|
||||
|
||||
/* a simple bsearch */
|
||||
int groups_search(const struct group_info *group_info, kgid_t grp)
|
||||
@@ -134,7 +135,6 @@ int groups_search(const struct group_info *group_info, kgid_t grp)
|
||||
void set_groups(struct cred *new, struct group_info *group_info)
|
||||
{
|
||||
put_group_info(new->group_info);
|
||||
groups_sort(group_info);
|
||||
get_group_info(group_info);
|
||||
new->group_info = group_info;
|
||||
}
|
||||
@@ -218,6 +218,7 @@ SYSCALL_DEFINE2(setgroups, int, gidsetsize, gid_t __user *, grouplist)
|
||||
return retval;
|
||||
}
|
||||
|
||||
groups_sort(group_info);
|
||||
retval = set_current_groups(group_info);
|
||||
put_group_info(group_info);
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ static int sig_task_ignored(struct task_struct *t, int sig, bool force)
|
||||
handler = sig_handler(t, sig);
|
||||
|
||||
if (unlikely(t->signal->flags & SIGNAL_UNKILLABLE) &&
|
||||
handler == SIG_DFL && !force)
|
||||
handler == SIG_DFL && !(force && sig_kernel_only(sig)))
|
||||
return 1;
|
||||
|
||||
return sig_handler_ignored(handler, sig);
|
||||
@@ -88,13 +88,15 @@ static int sig_ignored(struct task_struct *t, int sig, bool force)
|
||||
if (sigismember(&t->blocked, sig) || sigismember(&t->real_blocked, sig))
|
||||
return 0;
|
||||
|
||||
if (!sig_task_ignored(t, sig, force))
|
||||
/*
|
||||
* Tracers may want to know about even ignored signal unless it
|
||||
* is SIGKILL which can't be reported anyway but can be ignored
|
||||
* by SIGNAL_UNKILLABLE task.
|
||||
*/
|
||||
if (t->ptrace && sig != SIGKILL)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Tracers may want to know about even ignored signals.
|
||||
*/
|
||||
return !t->ptrace;
|
||||
return sig_task_ignored(t, sig, force);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -917,9 +919,9 @@ static void complete_signal(int sig, struct task_struct *p, int group)
|
||||
* then start taking the whole group down immediately.
|
||||
*/
|
||||
if (sig_fatal(p, sig) &&
|
||||
!(signal->flags & (SIGNAL_UNKILLABLE | SIGNAL_GROUP_EXIT)) &&
|
||||
!(signal->flags & SIGNAL_GROUP_EXIT) &&
|
||||
!sigismember(&t->real_blocked, sig) &&
|
||||
(sig == SIGKILL || !t->ptrace)) {
|
||||
(sig == SIGKILL || !p->ptrace)) {
|
||||
/*
|
||||
* This signal will be fatal to the whole group.
|
||||
*/
|
||||
|
||||
@@ -190,6 +190,7 @@ SYSCALL_DEFINE2(setgroups16, int, gidsetsize, old_gid_t __user *, grouplist)
|
||||
return retval;
|
||||
}
|
||||
|
||||
groups_sort(group_info);
|
||||
retval = set_current_groups(group_info);
|
||||
put_group_info(group_info);
|
||||
|
||||
|
||||
@@ -231,6 +231,7 @@ static int gssx_dec_linux_creds(struct xdr_stream *xdr,
|
||||
goto out_free_groups;
|
||||
creds->cr_group_info->gid[i] = kgid;
|
||||
}
|
||||
groups_sort(creds->cr_group_info);
|
||||
|
||||
return 0;
|
||||
out_free_groups:
|
||||
|
||||
@@ -481,6 +481,7 @@ static int rsc_parse(struct cache_detail *cd,
|
||||
goto out;
|
||||
rsci.cred.cr_group_info->gid[i] = kgid;
|
||||
}
|
||||
groups_sort(rsci.cred.cr_group_info);
|
||||
|
||||
/* mech name */
|
||||
len = qword_get(&mesg, buf, mlen);
|
||||
|
||||
@@ -520,6 +520,7 @@ static int unix_gid_parse(struct cache_detail *cd,
|
||||
ug.gi->gid[i] = kgid;
|
||||
}
|
||||
|
||||
groups_sort(ug.gi);
|
||||
ugp = unix_gid_lookup(cd, uid);
|
||||
if (ugp) {
|
||||
struct cache_head *ch;
|
||||
@@ -819,6 +820,7 @@ svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp)
|
||||
kgid_t kgid = make_kgid(&init_user_ns, svc_getnl(argv));
|
||||
cred->cr_group_info->gid[i] = kgid;
|
||||
}
|
||||
groups_sort(cred->cr_group_info);
|
||||
if (svc_getu32(argv) != htonl(RPC_AUTH_NULL) || svc_getu32(argv) != 0) {
|
||||
*authp = rpc_autherr_badverf;
|
||||
return SVC_DENIED;
|
||||
|
||||
Reference in New Issue
Block a user