Merge 4.9.34 into android-4.9
Changes in 4.9.34 fs: pass on flags in compat_writev configfs: Fix race between create_link and configfs_rmdir can: gs_usb: fix memory leak in gs_cmd_reset() ila_xlat: add missing hash secret initialization cpufreq: conservative: Allow down_threshold to take values from 1 to 10 vb2: Fix an off by one error in 'vb2_plane_vaddr' mac80211: don't look at the PM bit of BAR frames mac80211/wpa: use constant time memory comparison for MACs drm/amdgpu: Fix overflow of watermark calcs at > 4k resolutions. drm/i915: Fix GVT-g PVINFO version compatibility check usb: musb: dsps: keep VBUS on for host-only mode mac80211: fix CSA in IBSS mode mac80211: fix packet statistics for fast-RX mac80211: fix IBSS presp allocation size mac80211: strictly check mesh address extension mode mac80211: fix dropped counter in multiqueue RX mac80211: don't send SMPS action frame in AP mode when not needed drm/mediatek: fix mtk_hdmi_setup_vendor_specific_infoframe mistake drm/vc4: Fix OOPSes from trying to cache a partially constructed BO. serial: efm32: Fix parity management in 'efm32_uart_console_get_options()' serial: sh-sci: Fix late enablement of AUTORTS x86/mm/32: Set the '__vmalloc_start_set' flag in initmem_init() mfd: omap-usb-tll: Fix inverted bit use for USB TLL mode staging: rtl8188eu: prevent an underflow in rtw_check_beacon_data() staging: iio: tsl2x7x_core: Fix standard deviation calculation iio: st_pressure: Fix data sign iio: proximity: as3935: recalibrate RCO after resume iio: adc: ti_am335x_adc: allocating too much in probe IB/mlx5: Fix kernel to user leak prevention logic usb: gadget: udc: renesas_usb3: fix pm_runtime functions calling usb: gadget: udc: renesas_usb3: fix deadlock by spinlock usb: gadget: udc: renesas_usb3: lock for PN_ registers access USB: hub: fix SS max number of ports usb: core: fix potential memory leak in error path during hcd creation USB: usbip: fix nonconforming hub descriptor pvrusb2: reduce stack usage pvr2_eeprom_analyze() USB: gadget: dummy_hcd: fix hub-descriptor removable fields usb: r8a66597-hcd: select a different endpoint on timeout usb: r8a66597-hcd: decrease timeout ath10k: fix napi crash during rmmod when probe firmware fails misc: mic: double free on ioctl error path drivers/misc/c2port/c2port-duramar2150.c: checking for NULL instead of IS_ERR() usb: xhci: Fix USB 3.1 supported protocol parsing usb: xhci: ASMedia ASM1042A chipset need shorts TX quirk USB: gadget: fix GPF in gadgetfs USB: gadgetfs, dummy-hcd, net2280: fix locking for callbacks mm/memory-failure.c: use compound_head() flags for huge pages swap: cond_resched in swap_cgroup_prepare() iio: imu: inv_mpu6050: add accel lpf setting for chip >= MPU6500 sched/core: Idle_task_exit() shouldn't use switch_mm_irqs_off() genirq: Release resources in __setup_irq() error path alarmtimer: Prevent overflow of relative timers usb: gadget: composite: Fix function used to free memory usb: dwc3: exynos fix axius clock error path to do cleanup MIPS: Fix bnezc/jialc return address calculation MIPS: .its targets depend on vmlinux vTPM: Fix missing NULL check crypto: Work around deallocated stack frame reference gcc bug on sparc. alarmtimer: Rate limit periodic intervals mm: larger stack guard gap, between vmas Allow stack to grow up to address space limit mm: fix new crash in unmapped_area_topdown() Linux 4.9.34 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
@@ -183,6 +183,7 @@ SYSCALL_DEFINE1(brk, unsigned long, brk)
|
||||
unsigned long retval;
|
||||
unsigned long newbrk, oldbrk;
|
||||
struct mm_struct *mm = current->mm;
|
||||
struct vm_area_struct *next;
|
||||
unsigned long min_brk;
|
||||
bool populate;
|
||||
|
||||
@@ -228,7 +229,8 @@ SYSCALL_DEFINE1(brk, unsigned long, brk)
|
||||
}
|
||||
|
||||
/* Check against existing mmap mappings. */
|
||||
if (find_vma_intersection(mm, oldbrk, newbrk+PAGE_SIZE))
|
||||
next = find_vma(mm, oldbrk);
|
||||
if (next && newbrk + PAGE_SIZE > vm_start_gap(next))
|
||||
goto out;
|
||||
|
||||
/* Ok, looks good - let it rip. */
|
||||
@@ -251,10 +253,22 @@ out:
|
||||
|
||||
static long vma_compute_subtree_gap(struct vm_area_struct *vma)
|
||||
{
|
||||
unsigned long max, subtree_gap;
|
||||
max = vma->vm_start;
|
||||
if (vma->vm_prev)
|
||||
max -= vma->vm_prev->vm_end;
|
||||
unsigned long max, prev_end, subtree_gap;
|
||||
|
||||
/*
|
||||
* Note: in the rare case of a VM_GROWSDOWN above a VM_GROWSUP, we
|
||||
* allow two stack_guard_gaps between them here, and when choosing
|
||||
* an unmapped area; whereas when expanding we only require one.
|
||||
* That's a little inconsistent, but keeps the code here simpler.
|
||||
*/
|
||||
max = vm_start_gap(vma);
|
||||
if (vma->vm_prev) {
|
||||
prev_end = vm_end_gap(vma->vm_prev);
|
||||
if (max > prev_end)
|
||||
max -= prev_end;
|
||||
else
|
||||
max = 0;
|
||||
}
|
||||
if (vma->vm_rb.rb_left) {
|
||||
subtree_gap = rb_entry(vma->vm_rb.rb_left,
|
||||
struct vm_area_struct, vm_rb)->rb_subtree_gap;
|
||||
@@ -350,7 +364,7 @@ static void validate_mm(struct mm_struct *mm)
|
||||
anon_vma_unlock_read(anon_vma);
|
||||
}
|
||||
|
||||
highest_address = vma->vm_end;
|
||||
highest_address = vm_end_gap(vma);
|
||||
vma = vma->vm_next;
|
||||
i++;
|
||||
}
|
||||
@@ -539,7 +553,7 @@ void __vma_link_rb(struct mm_struct *mm, struct vm_area_struct *vma,
|
||||
if (vma->vm_next)
|
||||
vma_gap_update(vma->vm_next);
|
||||
else
|
||||
mm->highest_vm_end = vma->vm_end;
|
||||
mm->highest_vm_end = vm_end_gap(vma);
|
||||
|
||||
/*
|
||||
* vma->vm_prev wasn't known when we followed the rbtree to find the
|
||||
@@ -854,7 +868,7 @@ again:
|
||||
vma_gap_update(vma);
|
||||
if (end_changed) {
|
||||
if (!next)
|
||||
mm->highest_vm_end = end;
|
||||
mm->highest_vm_end = vm_end_gap(vma);
|
||||
else if (!adjust_next)
|
||||
vma_gap_update(next);
|
||||
}
|
||||
@@ -939,7 +953,7 @@ again:
|
||||
* mm->highest_vm_end doesn't need any update
|
||||
* in remove_next == 1 case.
|
||||
*/
|
||||
VM_WARN_ON(mm->highest_vm_end != end);
|
||||
VM_WARN_ON(mm->highest_vm_end != vm_end_gap(vma));
|
||||
}
|
||||
}
|
||||
if (insert && file)
|
||||
@@ -1792,7 +1806,7 @@ unsigned long unmapped_area(struct vm_unmapped_area_info *info)
|
||||
|
||||
while (true) {
|
||||
/* Visit left subtree if it looks promising */
|
||||
gap_end = vma->vm_start;
|
||||
gap_end = vm_start_gap(vma);
|
||||
if (gap_end >= low_limit && vma->vm_rb.rb_left) {
|
||||
struct vm_area_struct *left =
|
||||
rb_entry(vma->vm_rb.rb_left,
|
||||
@@ -1803,12 +1817,13 @@ unsigned long unmapped_area(struct vm_unmapped_area_info *info)
|
||||
}
|
||||
}
|
||||
|
||||
gap_start = vma->vm_prev ? vma->vm_prev->vm_end : 0;
|
||||
gap_start = vma->vm_prev ? vm_end_gap(vma->vm_prev) : 0;
|
||||
check_current:
|
||||
/* Check if current node has a suitable gap */
|
||||
if (gap_start > high_limit)
|
||||
return -ENOMEM;
|
||||
if (gap_end >= low_limit && gap_end - gap_start >= length)
|
||||
if (gap_end >= low_limit &&
|
||||
gap_end > gap_start && gap_end - gap_start >= length)
|
||||
goto found;
|
||||
|
||||
/* Visit right subtree if it looks promising */
|
||||
@@ -1830,8 +1845,8 @@ check_current:
|
||||
vma = rb_entry(rb_parent(prev),
|
||||
struct vm_area_struct, vm_rb);
|
||||
if (prev == vma->vm_rb.rb_left) {
|
||||
gap_start = vma->vm_prev->vm_end;
|
||||
gap_end = vma->vm_start;
|
||||
gap_start = vm_end_gap(vma->vm_prev);
|
||||
gap_end = vm_start_gap(vma);
|
||||
goto check_current;
|
||||
}
|
||||
}
|
||||
@@ -1895,7 +1910,7 @@ unsigned long unmapped_area_topdown(struct vm_unmapped_area_info *info)
|
||||
|
||||
while (true) {
|
||||
/* Visit right subtree if it looks promising */
|
||||
gap_start = vma->vm_prev ? vma->vm_prev->vm_end : 0;
|
||||
gap_start = vma->vm_prev ? vm_end_gap(vma->vm_prev) : 0;
|
||||
if (gap_start <= high_limit && vma->vm_rb.rb_right) {
|
||||
struct vm_area_struct *right =
|
||||
rb_entry(vma->vm_rb.rb_right,
|
||||
@@ -1908,10 +1923,11 @@ unsigned long unmapped_area_topdown(struct vm_unmapped_area_info *info)
|
||||
|
||||
check_current:
|
||||
/* Check if current node has a suitable gap */
|
||||
gap_end = vma->vm_start;
|
||||
gap_end = vm_start_gap(vma);
|
||||
if (gap_end < low_limit)
|
||||
return -ENOMEM;
|
||||
if (gap_start <= high_limit && gap_end - gap_start >= length)
|
||||
if (gap_start <= high_limit &&
|
||||
gap_end > gap_start && gap_end - gap_start >= length)
|
||||
goto found;
|
||||
|
||||
/* Visit left subtree if it looks promising */
|
||||
@@ -1934,7 +1950,7 @@ check_current:
|
||||
struct vm_area_struct, vm_rb);
|
||||
if (prev == vma->vm_rb.rb_right) {
|
||||
gap_start = vma->vm_prev ?
|
||||
vma->vm_prev->vm_end : 0;
|
||||
vm_end_gap(vma->vm_prev) : 0;
|
||||
goto check_current;
|
||||
}
|
||||
}
|
||||
@@ -1972,7 +1988,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
|
||||
unsigned long len, unsigned long pgoff, unsigned long flags)
|
||||
{
|
||||
struct mm_struct *mm = current->mm;
|
||||
struct vm_area_struct *vma;
|
||||
struct vm_area_struct *vma, *prev;
|
||||
struct vm_unmapped_area_info info;
|
||||
|
||||
if (len > TASK_SIZE - mmap_min_addr)
|
||||
@@ -1983,9 +1999,10 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
|
||||
|
||||
if (addr) {
|
||||
addr = PAGE_ALIGN(addr);
|
||||
vma = find_vma(mm, addr);
|
||||
vma = find_vma_prev(mm, addr, &prev);
|
||||
if (TASK_SIZE - len >= addr && addr >= mmap_min_addr &&
|
||||
(!vma || addr + len <= vma->vm_start))
|
||||
(!vma || addr + len <= vm_start_gap(vma)) &&
|
||||
(!prev || addr >= vm_end_gap(prev)))
|
||||
return addr;
|
||||
}
|
||||
|
||||
@@ -2008,7 +2025,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
|
||||
const unsigned long len, const unsigned long pgoff,
|
||||
const unsigned long flags)
|
||||
{
|
||||
struct vm_area_struct *vma;
|
||||
struct vm_area_struct *vma, *prev;
|
||||
struct mm_struct *mm = current->mm;
|
||||
unsigned long addr = addr0;
|
||||
struct vm_unmapped_area_info info;
|
||||
@@ -2023,9 +2040,10 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
|
||||
/* requesting a specific address */
|
||||
if (addr) {
|
||||
addr = PAGE_ALIGN(addr);
|
||||
vma = find_vma(mm, addr);
|
||||
vma = find_vma_prev(mm, addr, &prev);
|
||||
if (TASK_SIZE - len >= addr && addr >= mmap_min_addr &&
|
||||
(!vma || addr + len <= vma->vm_start))
|
||||
(!vma || addr + len <= vm_start_gap(vma)) &&
|
||||
(!prev || addr >= vm_end_gap(prev)))
|
||||
return addr;
|
||||
}
|
||||
|
||||
@@ -2160,21 +2178,19 @@ find_vma_prev(struct mm_struct *mm, unsigned long addr,
|
||||
* update accounting. This is shared with both the
|
||||
* grow-up and grow-down cases.
|
||||
*/
|
||||
static int acct_stack_growth(struct vm_area_struct *vma, unsigned long size, unsigned long grow)
|
||||
static int acct_stack_growth(struct vm_area_struct *vma,
|
||||
unsigned long size, unsigned long grow)
|
||||
{
|
||||
struct mm_struct *mm = vma->vm_mm;
|
||||
struct rlimit *rlim = current->signal->rlim;
|
||||
unsigned long new_start, actual_size;
|
||||
unsigned long new_start;
|
||||
|
||||
/* address space limit tests */
|
||||
if (!may_expand_vm(mm, vma->vm_flags, grow))
|
||||
return -ENOMEM;
|
||||
|
||||
/* Stack limit test */
|
||||
actual_size = size;
|
||||
if (size && (vma->vm_flags & (VM_GROWSUP | VM_GROWSDOWN)))
|
||||
actual_size -= PAGE_SIZE;
|
||||
if (actual_size > READ_ONCE(rlim[RLIMIT_STACK].rlim_cur))
|
||||
if (size > READ_ONCE(rlim[RLIMIT_STACK].rlim_cur))
|
||||
return -ENOMEM;
|
||||
|
||||
/* mlock limit tests */
|
||||
@@ -2212,16 +2228,32 @@ static int acct_stack_growth(struct vm_area_struct *vma, unsigned long size, uns
|
||||
int expand_upwards(struct vm_area_struct *vma, unsigned long address)
|
||||
{
|
||||
struct mm_struct *mm = vma->vm_mm;
|
||||
struct vm_area_struct *next;
|
||||
unsigned long gap_addr;
|
||||
int error = 0;
|
||||
|
||||
if (!(vma->vm_flags & VM_GROWSUP))
|
||||
return -EFAULT;
|
||||
|
||||
/* Guard against wrapping around to address 0. */
|
||||
if (address < PAGE_ALIGN(address+4))
|
||||
address = PAGE_ALIGN(address+4);
|
||||
else
|
||||
/* Guard against exceeding limits of the address space. */
|
||||
address &= PAGE_MASK;
|
||||
if (address >= TASK_SIZE)
|
||||
return -ENOMEM;
|
||||
address += PAGE_SIZE;
|
||||
|
||||
/* Enforce stack_guard_gap */
|
||||
gap_addr = address + stack_guard_gap;
|
||||
|
||||
/* Guard against overflow */
|
||||
if (gap_addr < address || gap_addr > TASK_SIZE)
|
||||
gap_addr = TASK_SIZE;
|
||||
|
||||
next = vma->vm_next;
|
||||
if (next && next->vm_start < gap_addr) {
|
||||
if (!(next->vm_flags & VM_GROWSUP))
|
||||
return -ENOMEM;
|
||||
/* Check that both stack segments have the same anon_vma? */
|
||||
}
|
||||
|
||||
/* We must make sure the anon_vma is allocated. */
|
||||
if (unlikely(anon_vma_prepare(vma)))
|
||||
@@ -2266,7 +2298,7 @@ int expand_upwards(struct vm_area_struct *vma, unsigned long address)
|
||||
if (vma->vm_next)
|
||||
vma_gap_update(vma->vm_next);
|
||||
else
|
||||
mm->highest_vm_end = address;
|
||||
mm->highest_vm_end = vm_end_gap(vma);
|
||||
spin_unlock(&mm->page_table_lock);
|
||||
|
||||
perf_event_mmap(vma);
|
||||
@@ -2287,6 +2319,8 @@ int expand_downwards(struct vm_area_struct *vma,
|
||||
unsigned long address)
|
||||
{
|
||||
struct mm_struct *mm = vma->vm_mm;
|
||||
struct vm_area_struct *prev;
|
||||
unsigned long gap_addr;
|
||||
int error;
|
||||
|
||||
address &= PAGE_MASK;
|
||||
@@ -2294,6 +2328,17 @@ int expand_downwards(struct vm_area_struct *vma,
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
/* Enforce stack_guard_gap */
|
||||
gap_addr = address - stack_guard_gap;
|
||||
if (gap_addr > address)
|
||||
return -ENOMEM;
|
||||
prev = vma->vm_prev;
|
||||
if (prev && prev->vm_end > gap_addr) {
|
||||
if (!(prev->vm_flags & VM_GROWSDOWN))
|
||||
return -ENOMEM;
|
||||
/* Check that both stack segments have the same anon_vma? */
|
||||
}
|
||||
|
||||
/* We must make sure the anon_vma is allocated. */
|
||||
if (unlikely(anon_vma_prepare(vma)))
|
||||
return -ENOMEM;
|
||||
@@ -2348,28 +2393,25 @@ int expand_downwards(struct vm_area_struct *vma,
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Note how expand_stack() refuses to expand the stack all the way to
|
||||
* abut the next virtual mapping, *unless* that mapping itself is also
|
||||
* a stack mapping. We want to leave room for a guard page, after all
|
||||
* (the guard page itself is not added here, that is done by the
|
||||
* actual page faulting logic)
|
||||
*
|
||||
* This matches the behavior of the guard page logic (see mm/memory.c:
|
||||
* check_stack_guard_page()), which only allows the guard page to be
|
||||
* removed under these circumstances.
|
||||
*/
|
||||
/* enforced gap between the expanding stack and other mappings. */
|
||||
unsigned long stack_guard_gap = 256UL<<PAGE_SHIFT;
|
||||
|
||||
static int __init cmdline_parse_stack_guard_gap(char *p)
|
||||
{
|
||||
unsigned long val;
|
||||
char *endptr;
|
||||
|
||||
val = simple_strtoul(p, &endptr, 10);
|
||||
if (!*endptr)
|
||||
stack_guard_gap = val << PAGE_SHIFT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
__setup("stack_guard_gap=", cmdline_parse_stack_guard_gap);
|
||||
|
||||
#ifdef CONFIG_STACK_GROWSUP
|
||||
int expand_stack(struct vm_area_struct *vma, unsigned long address)
|
||||
{
|
||||
struct vm_area_struct *next;
|
||||
|
||||
address &= PAGE_MASK;
|
||||
next = vma->vm_next;
|
||||
if (next && next->vm_start == address + PAGE_SIZE) {
|
||||
if (!(next->vm_flags & VM_GROWSUP))
|
||||
return -ENOMEM;
|
||||
}
|
||||
return expand_upwards(vma, address);
|
||||
}
|
||||
|
||||
@@ -2391,14 +2433,6 @@ find_extend_vma(struct mm_struct *mm, unsigned long addr)
|
||||
#else
|
||||
int expand_stack(struct vm_area_struct *vma, unsigned long address)
|
||||
{
|
||||
struct vm_area_struct *prev;
|
||||
|
||||
address &= PAGE_MASK;
|
||||
prev = vma->vm_prev;
|
||||
if (prev && prev->vm_end == address) {
|
||||
if (!(prev->vm_flags & VM_GROWSDOWN))
|
||||
return -ENOMEM;
|
||||
}
|
||||
return expand_downwards(vma, address);
|
||||
}
|
||||
|
||||
@@ -2496,7 +2530,7 @@ detach_vmas_to_be_unmapped(struct mm_struct *mm, struct vm_area_struct *vma,
|
||||
vma->vm_prev = prev;
|
||||
vma_gap_update(vma);
|
||||
} else
|
||||
mm->highest_vm_end = prev ? prev->vm_end : 0;
|
||||
mm->highest_vm_end = prev ? vm_end_gap(prev) : 0;
|
||||
tail_vma->vm_next = NULL;
|
||||
|
||||
/* Kill the cache */
|
||||
|
||||
Reference in New Issue
Block a user