Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux

Pull s390 fixes from Martin Schwidefsky:
"Three more bug fixes for 4.6

- Due to a race in the dynamic page table code a multi-threaded
program can cause a translation specification exception. With
panic_on_oops a user space program can crash the system.

- An information leak with the /dev/sclp device.

- A use after free in the s390 PCI code"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux:
s390/sclp_ctl: fix potential information leak with /dev/sclp
s390/mm: fix asce_bits handling with dynamic pagetable levels
s390/pci: fix use after free in dma_init

+79 -88
+1 -1
arch/s390/include/asm/mmu.h
··· 11 11 spinlock_t list_lock; 12 12 struct list_head pgtable_list; 13 13 struct list_head gmap_list; 14 - unsigned long asce_bits; 14 + unsigned long asce; 15 15 unsigned long asce_limit; 16 16 unsigned long vdso_base; 17 17 /* The mmu context allocates 4K page tables. */
+22 -6
arch/s390/include/asm/mmu_context.h
··· 26 26 mm->context.has_pgste = 0; 27 27 mm->context.use_skey = 0; 28 28 #endif 29 - if (mm->context.asce_limit == 0) { 29 + switch (mm->context.asce_limit) { 30 + case 1UL << 42: 31 + /* 32 + * forked 3-level task, fall through to set new asce with new 33 + * mm->pgd 34 + */ 35 + case 0: 30 36 /* context created by exec, set asce limit to 4TB */ 31 - mm->context.asce_bits = _ASCE_TABLE_LENGTH | 32 - _ASCE_USER_BITS | _ASCE_TYPE_REGION3; 33 37 mm->context.asce_limit = STACK_TOP_MAX; 34 - } else if (mm->context.asce_limit == (1UL << 31)) { 38 + mm->context.asce = __pa(mm->pgd) | _ASCE_TABLE_LENGTH | 39 + _ASCE_USER_BITS | _ASCE_TYPE_REGION3; 40 + break; 41 + case 1UL << 53: 42 + /* forked 4-level task, set new asce with new mm->pgd */ 43 + mm->context.asce = __pa(mm->pgd) | _ASCE_TABLE_LENGTH | 44 + _ASCE_USER_BITS | _ASCE_TYPE_REGION2; 45 + break; 46 + case 1UL << 31: 47 + /* forked 2-level compat task, set new asce with new mm->pgd */ 48 + mm->context.asce = __pa(mm->pgd) | _ASCE_TABLE_LENGTH | 49 + _ASCE_USER_BITS | _ASCE_TYPE_SEGMENT; 50 + /* pgd_alloc() did not increase mm->nr_pmds */ 35 51 mm_inc_nr_pmds(mm); 36 52 } 37 53 crst_table_init((unsigned long *) mm->pgd, pgd_entry_type(mm)); ··· 58 42 59 43 static inline void set_user_asce(struct mm_struct *mm) 60 44 { 61 - S390_lowcore.user_asce = mm->context.asce_bits | __pa(mm->pgd); 45 + S390_lowcore.user_asce = mm->context.asce; 62 46 if (current->thread.mm_segment.ar4) 63 47 __ctl_load(S390_lowcore.user_asce, 7, 7); 64 48 set_cpu_flag(CIF_ASCE); ··· 87 71 { 88 72 int cpu = smp_processor_id(); 89 73 90 - S390_lowcore.user_asce = next->context.asce_bits | __pa(next->pgd); 74 + S390_lowcore.user_asce = next->context.asce; 91 75 if (prev == next) 92 76 return; 93 77 if (MACHINE_HAS_TLB_LC)
+2 -2
arch/s390/include/asm/pgalloc.h
··· 52 52 return _REGION2_ENTRY_EMPTY; 53 53 } 54 54 55 - int crst_table_upgrade(struct mm_struct *, unsigned long limit); 56 - void crst_table_downgrade(struct mm_struct *, unsigned long limit); 55 + int crst_table_upgrade(struct mm_struct *); 56 + void crst_table_downgrade(struct mm_struct *); 57 57 58 58 static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long address) 59 59 {
+1 -1
arch/s390/include/asm/processor.h
··· 175 175 regs->psw.mask = PSW_USER_BITS | PSW_MASK_BA; \ 176 176 regs->psw.addr = new_psw; \ 177 177 regs->gprs[15] = new_stackp; \ 178 - crst_table_downgrade(current->mm, 1UL << 31); \ 178 + crst_table_downgrade(current->mm); \ 179 179 execve_tail(); \ 180 180 } while (0) 181 181
+3 -6
arch/s390/include/asm/tlbflush.h
··· 110 110 static inline void __tlb_flush_kernel(void) 111 111 { 112 112 if (MACHINE_HAS_IDTE) 113 - __tlb_flush_idte((unsigned long) init_mm.pgd | 114 - init_mm.context.asce_bits); 113 + __tlb_flush_idte(init_mm.context.asce); 115 114 else 116 115 __tlb_flush_global(); 117 116 } ··· 132 133 static inline void __tlb_flush_kernel(void) 133 134 { 134 135 if (MACHINE_HAS_TLB_LC) 135 - __tlb_flush_idte_local((unsigned long) init_mm.pgd | 136 - init_mm.context.asce_bits); 136 + __tlb_flush_idte_local(init_mm.context.asce); 137 137 else 138 138 __tlb_flush_local(); 139 139 } ··· 146 148 * only ran on the local cpu. 147 149 */ 148 150 if (MACHINE_HAS_IDTE && list_empty(&mm->context.gmap_list)) 149 - __tlb_flush_asce(mm, (unsigned long) mm->pgd | 150 - mm->context.asce_bits); 151 + __tlb_flush_asce(mm, mm->context.asce); 151 152 else 152 153 __tlb_flush_full(mm); 153 154 }
+2 -1
arch/s390/mm/init.c
··· 89 89 asce_bits = _ASCE_TYPE_REGION3 | _ASCE_TABLE_LENGTH; 90 90 pgd_type = _REGION3_ENTRY_EMPTY; 91 91 } 92 - S390_lowcore.kernel_asce = (__pa(init_mm.pgd) & PAGE_MASK) | asce_bits; 92 + init_mm.context.asce = (__pa(init_mm.pgd) & PAGE_MASK) | asce_bits; 93 + S390_lowcore.kernel_asce = init_mm.context.asce; 93 94 clear_table((unsigned long *) init_mm.pgd, pgd_type, 94 95 sizeof(unsigned long)*2048); 95 96 vmem_map_init();
+3 -3
arch/s390/mm/mmap.c
··· 174 174 if (!(flags & MAP_FIXED)) 175 175 addr = 0; 176 176 if ((addr + len) >= TASK_SIZE) 177 - return crst_table_upgrade(current->mm, TASK_MAX_SIZE); 177 + return crst_table_upgrade(current->mm); 178 178 return 0; 179 179 } 180 180 ··· 191 191 return area; 192 192 if (area == -ENOMEM && !is_compat_task() && TASK_SIZE < TASK_MAX_SIZE) { 193 193 /* Upgrade the page table to 4 levels and retry. */ 194 - rc = crst_table_upgrade(mm, TASK_MAX_SIZE); 194 + rc = crst_table_upgrade(mm); 195 195 if (rc) 196 196 return (unsigned long) rc; 197 197 area = arch_get_unmapped_area(filp, addr, len, pgoff, flags); ··· 213 213 return area; 214 214 if (area == -ENOMEM && !is_compat_task() && TASK_SIZE < TASK_MAX_SIZE) { 215 215 /* Upgrade the page table to 4 levels and retry. */ 216 - rc = crst_table_upgrade(mm, TASK_MAX_SIZE); 216 + rc = crst_table_upgrade(mm); 217 217 if (rc) 218 218 return (unsigned long) rc; 219 219 area = arch_get_unmapped_area_topdown(filp, addr, len,
+28 -57
arch/s390/mm/pgalloc.c
··· 76 76 __tlb_flush_local(); 77 77 } 78 78 79 - int crst_table_upgrade(struct mm_struct *mm, unsigned long limit) 79 + int crst_table_upgrade(struct mm_struct *mm) 80 80 { 81 81 unsigned long *table, *pgd; 82 - unsigned long entry; 83 - int flush; 84 82 85 - BUG_ON(limit > TASK_MAX_SIZE); 86 - flush = 0; 87 - repeat: 83 + /* upgrade should only happen from 3 to 4 levels */ 84 + BUG_ON(mm->context.asce_limit != (1UL << 42)); 85 + 88 86 table = crst_table_alloc(mm); 89 87 if (!table) 90 88 return -ENOMEM; 89 + 91 90 spin_lock_bh(&mm->page_table_lock); 92 - if (mm->context.asce_limit < limit) { 93 - pgd = (unsigned long *) mm->pgd; 94 - if (mm->context.asce_limit <= (1UL << 31)) { 95 - entry = _REGION3_ENTRY_EMPTY; 96 - mm->context.asce_limit = 1UL << 42; 97 - mm->context.asce_bits = _ASCE_TABLE_LENGTH | 98 - _ASCE_USER_BITS | 99 - _ASCE_TYPE_REGION3; 100 - } else { 101 - entry = _REGION2_ENTRY_EMPTY; 102 - mm->context.asce_limit = 1UL << 53; 103 - mm->context.asce_bits = _ASCE_TABLE_LENGTH | 104 - _ASCE_USER_BITS | 105 - _ASCE_TYPE_REGION2; 106 - } 107 - crst_table_init(table, entry); 108 - pgd_populate(mm, (pgd_t *) table, (pud_t *) pgd); 109 - mm->pgd = (pgd_t *) table; 110 - mm->task_size = mm->context.asce_limit; 111 - table = NULL; 112 - flush = 1; 113 - } 91 + pgd = (unsigned long *) mm->pgd; 92 + crst_table_init(table, _REGION2_ENTRY_EMPTY); 93 + pgd_populate(mm, (pgd_t *) table, (pud_t *) pgd); 94 + mm->pgd = (pgd_t *) table; 95 + mm->context.asce_limit = 1UL << 53; 96 + mm->context.asce = __pa(mm->pgd) | _ASCE_TABLE_LENGTH | 97 + _ASCE_USER_BITS | _ASCE_TYPE_REGION2; 98 + mm->task_size = mm->context.asce_limit; 114 99 spin_unlock_bh(&mm->page_table_lock); 115 - if (table) 116 - crst_table_free(mm, table); 117 - if (mm->context.asce_limit < limit) 118 - goto repeat; 119 - if (flush) 120 - on_each_cpu(__crst_table_upgrade, mm, 0); 100 + 101 + on_each_cpu(__crst_table_upgrade, mm, 0); 121 102 return 0; 122 103 } 123 104 124 - void crst_table_downgrade(struct mm_struct *mm, unsigned long limit) 105 + void crst_table_downgrade(struct mm_struct *mm) 125 106 { 126 107 pgd_t *pgd; 108 + 109 + /* downgrade should only happen from 3 to 2 levels (compat only) */ 110 + BUG_ON(mm->context.asce_limit != (1UL << 42)); 127 111 128 112 if (current->active_mm == mm) { 129 113 clear_user_asce(); 130 114 __tlb_flush_mm(mm); 131 115 } 132 - while (mm->context.asce_limit > limit) { 133 - pgd = mm->pgd; 134 - switch (pgd_val(*pgd) & _REGION_ENTRY_TYPE_MASK) { 135 - case _REGION_ENTRY_TYPE_R2: 136 - mm->context.asce_limit = 1UL << 42; 137 - mm->context.asce_bits = _ASCE_TABLE_LENGTH | 138 - _ASCE_USER_BITS | 139 - _ASCE_TYPE_REGION3; 140 - break; 141 - case _REGION_ENTRY_TYPE_R3: 142 - mm->context.asce_limit = 1UL << 31; 143 - mm->context.asce_bits = _ASCE_TABLE_LENGTH | 144 - _ASCE_USER_BITS | 145 - _ASCE_TYPE_SEGMENT; 146 - break; 147 - default: 148 - BUG(); 149 - } 150 - mm->pgd = (pgd_t *) (pgd_val(*pgd) & _REGION_ENTRY_ORIGIN); 151 - mm->task_size = mm->context.asce_limit; 152 - crst_table_free(mm, (unsigned long *) pgd); 153 - } 116 + 117 + pgd = mm->pgd; 118 + mm->pgd = (pgd_t *) (pgd_val(*pgd) & _REGION_ENTRY_ORIGIN); 119 + mm->context.asce_limit = 1UL << 31; 120 + mm->context.asce = __pa(mm->pgd) | _ASCE_TABLE_LENGTH | 121 + _ASCE_USER_BITS | _ASCE_TYPE_SEGMENT; 122 + mm->task_size = mm->context.asce_limit; 123 + crst_table_free(mm, (unsigned long *) pgd); 124 + 154 125 if (current->active_mm == mm) 155 126 set_user_asce(mm); 156 127 }
+10 -6
arch/s390/pci/pci_dma.c
··· 457 457 zdev->dma_table = dma_alloc_cpu_table(); 458 458 if (!zdev->dma_table) { 459 459 rc = -ENOMEM; 460 - goto out_clean; 460 + goto out; 461 461 } 462 462 463 463 /* ··· 477 477 zdev->iommu_bitmap = vzalloc(zdev->iommu_pages / 8); 478 478 if (!zdev->iommu_bitmap) { 479 479 rc = -ENOMEM; 480 - goto out_reg; 480 + goto free_dma_table; 481 481 } 482 482 483 483 rc = zpci_register_ioat(zdev, 0, zdev->start_dma, zdev->end_dma, 484 484 (u64) zdev->dma_table); 485 485 if (rc) 486 - goto out_reg; 487 - return 0; 486 + goto free_bitmap; 488 487 489 - out_reg: 488 + return 0; 489 + free_bitmap: 490 + vfree(zdev->iommu_bitmap); 491 + zdev->iommu_bitmap = NULL; 492 + free_dma_table: 490 493 dma_free_cpu_table(zdev->dma_table); 491 - out_clean: 494 + zdev->dma_table = NULL; 495 + out: 492 496 return rc; 493 497 } 494 498
+7 -5
drivers/s390/char/sclp_ctl.c
··· 56 56 { 57 57 struct sclp_ctl_sccb ctl_sccb; 58 58 struct sccb_header *sccb; 59 + unsigned long copied; 59 60 int rc; 60 61 61 62 if (copy_from_user(&ctl_sccb, user_area, sizeof(ctl_sccb))) ··· 66 65 sccb = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA); 67 66 if (!sccb) 68 67 return -ENOMEM; 69 - if (copy_from_user(sccb, u64_to_uptr(ctl_sccb.sccb), sizeof(*sccb))) { 68 + copied = PAGE_SIZE - 69 + copy_from_user(sccb, u64_to_uptr(ctl_sccb.sccb), PAGE_SIZE); 70 + if (offsetof(struct sccb_header, length) + 71 + sizeof(sccb->length) > copied || sccb->length > copied) { 70 72 rc = -EFAULT; 71 73 goto out_free; 72 74 } 73 - if (sccb->length > PAGE_SIZE || sccb->length < 8) 74 - return -EINVAL; 75 - if (copy_from_user(sccb, u64_to_uptr(ctl_sccb.sccb), sccb->length)) { 76 - rc = -EFAULT; 75 + if (sccb->length < 8) { 76 + rc = -EINVAL; 77 77 goto out_free; 78 78 } 79 79 rc = sclp_sync_request(ctl_sccb.cmdw, sccb);