View | Details | Raw Unified | Return to bug 1039348
Collapse All | Expand All

(-)a/arch/ia64/mm/fault.c (-1 / +1 lines)
Lines 226-232 ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re Link Here
226
		 */
226
		 */
227
		if (address > vma->vm_end + PAGE_SIZE - sizeof(long))
227
		if (address > vma->vm_end + PAGE_SIZE - sizeof(long))
228
			goto bad_area;
228
			goto bad_area;
229
		if (expand_upwards(vma, address))
229
		if (expand_upwards(vma, address, 0))
230
			goto bad_area;
230
			goto bad_area;
231
	}
231
	}
232
	goto good_area;
232
	goto good_area;
(-)a/fs/exec.c (-1 / +7 lines)
Lines 200-206 static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, Link Here
200
200
201
#ifdef CONFIG_STACK_GROWSUP
201
#ifdef CONFIG_STACK_GROWSUP
202
	if (write) {
202
	if (write) {
203
		ret = expand_downwards(bprm->vma, pos);
203
		ret = expand_downwards(bprm->vma, pos, 0);
204
		if (ret < 0)
204
		if (ret < 0)
205
			return NULL;
205
			return NULL;
206
	}
206
	}
Lines 222-227 static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, Link Here
222
		unsigned long size = bprm->vma->vm_end - bprm->vma->vm_start;
222
		unsigned long size = bprm->vma->vm_end - bprm->vma->vm_start;
223
		struct rlimit *rlim;
223
		struct rlimit *rlim;
224
224
225
		/*
226
		 * GRWOSUP doesn't really have any gap at this stage because we grow
227
		 * the stack down now. See the expand_downwards above.
228
		 */
229
		if (!IS_ENABLED(CONFIG_STACK_GROWSUP))
230
			size -= stack_guard_gap;
225
		acct_arg_size(bprm, size / PAGE_SIZE);
231
		acct_arg_size(bprm, size / PAGE_SIZE);
226
232
227
		/*
233
		/*
(-)a/fs/proc/task_mmu.c (-4 / +7 lines)
Lines 300-310 show_map_vma(struct seq_file *m, struct vm_area_struct *vma, int is_pid) Link Here
300
300
301
	/* We don't show the stack guard page in /proc/maps */
301
	/* We don't show the stack guard page in /proc/maps */
302
	start = vma->vm_start;
302
	start = vma->vm_start;
303
	if (stack_guard_page_start(vma, start))
304
		start += PAGE_SIZE;
305
	end = vma->vm_end;
303
	end = vma->vm_end;
306
	if (stack_guard_page_end(vma, end))
304
	if (vma->vm_flags & VM_GROWSDOWN) {
307
		end -= PAGE_SIZE;
305
		if (stack_guard_area(vma, start))
306
			start += stack_guard_gap;
307
	} else if (vma->vm_flags & VM_GROWSUP) {
308
		if (stack_guard_area(vma, end))
309
			end -= stack_guard_gap;
310
	}
308
311
309
	seq_setwidth(m, 25 + sizeof(void *) * 6 - 1);
312
	seq_setwidth(m, 25 + sizeof(void *) * 6 - 1);
310
	seq_printf(m, "%08lx-%08lx %c%c%c%c %08llx %02x:%02x %lu ",
313
	seq_printf(m, "%08lx-%08lx %c%c%c%c %08llx %02x:%02x %lu ",
(-)a/include/linux/mm.h (-31 / +9 lines)
Lines 1393-1404 int clear_page_dirty_for_io(struct page *page); Link Here
1393
1393
1394
int get_cmdline(struct task_struct *task, char *buffer, int buflen);
1394
int get_cmdline(struct task_struct *task, char *buffer, int buflen);
1395
1395
1396
/* Is the vma a continuation of the stack vma above it? */
1397
static inline int vma_growsdown(struct vm_area_struct *vma, unsigned long addr)
1398
{
1399
	return vma && (vma->vm_end == addr) && (vma->vm_flags & VM_GROWSDOWN);
1400
}
1401
1402
static inline bool vma_is_anonymous(struct vm_area_struct *vma)
1396
static inline bool vma_is_anonymous(struct vm_area_struct *vma)
1403
{
1397
{
1404
	return !vma->vm_ops;
1398
	return !vma->vm_ops;
Lines 1414-1441 bool vma_is_shmem(struct vm_area_struct *vma); Link Here
1414
static inline bool vma_is_shmem(struct vm_area_struct *vma) { return false; }
1408
static inline bool vma_is_shmem(struct vm_area_struct *vma) { return false; }
1415
#endif
1409
#endif
1416
1410
1417
static inline int stack_guard_page_start(struct vm_area_struct *vma,
1418
					     unsigned long addr)
1419
{
1420
	return (vma->vm_flags & VM_GROWSDOWN) &&
1421
		(vma->vm_start == addr) &&
1422
		!vma_growsdown(vma->vm_prev, addr);
1423
}
1424
1425
/* Is the vma a continuation of the stack vma below it? */
1426
static inline int vma_growsup(struct vm_area_struct *vma, unsigned long addr)
1427
{
1428
	return vma && (vma->vm_start == addr) && (vma->vm_flags & VM_GROWSUP);
1429
}
1430
1431
static inline int stack_guard_page_end(struct vm_area_struct *vma,
1432
					   unsigned long addr)
1433
{
1434
	return (vma->vm_flags & VM_GROWSUP) &&
1435
		(vma->vm_end == addr) &&
1436
		!vma_growsup(vma->vm_next, addr);
1437
}
1438
1439
int vma_is_stack_for_current(struct vm_area_struct *vma);
1411
int vma_is_stack_for_current(struct vm_area_struct *vma);
1440
1412
1441
extern unsigned long move_page_tables(struct vm_area_struct *vma,
1413
extern unsigned long move_page_tables(struct vm_area_struct *vma,
Lines 2222-2237 void page_cache_async_readahead(struct address_space *mapping, Link Here
2222
				pgoff_t offset,
2194
				pgoff_t offset,
2223
				unsigned long size);
2195
				unsigned long size);
2224
2196
2197
extern unsigned long stack_guard_gap;
2225
/* Generic expand stack which grows the stack according to GROWS{UP,DOWN} */
2198
/* Generic expand stack which grows the stack according to GROWS{UP,DOWN} */
2226
extern int expand_stack(struct vm_area_struct *vma, unsigned long address);
2199
extern int expand_stack(struct vm_area_struct *vma, unsigned long address);
2200
extern int stack_guard_area(struct vm_area_struct *vma, unsigned long address);
2227
2201
2228
/* CONFIG_STACK_GROWSUP still needs to to grow downwards at some places */
2202
/* CONFIG_STACK_GROWSUP still needs to to grow downwards at some places */
2229
extern int expand_downwards(struct vm_area_struct *vma,
2203
extern int expand_downwards(struct vm_area_struct *vma,
2230
		unsigned long address);
2204
		unsigned long address, unsigned long gap);
2205
unsigned long expandable_stack_area(struct vm_area_struct *vma,
2206
		unsigned long address, unsigned long *gap);
2207
2231
#if VM_GROWSUP
2208
#if VM_GROWSUP
2232
extern int expand_upwards(struct vm_area_struct *vma, unsigned long address);
2209
extern int expand_upwards(struct vm_area_struct *vma,
2210
		unsigned long address, unsigned long gap);
2233
#else
2211
#else
2234
  #define expand_upwards(vma, address) (0)
2212
  #define expand_upwards(vma, address, gap) (0)
2235
#endif
2213
#endif
2236
2214
2237
/* Look up the first VMA which satisfies  addr < vm_end,  NULL if none. */
2215
/* Look up the first VMA which satisfies  addr < vm_end,  NULL if none. */
(-)a/mm/gup.c (-3 / +1 lines)
Lines 388-396 static int faultin_page(struct task_struct *tsk, struct vm_area_struct *vma, Link Here
388
	if ((*flags & (FOLL_POPULATE | FOLL_MLOCK)) == FOLL_MLOCK)
388
	if ((*flags & (FOLL_POPULATE | FOLL_MLOCK)) == FOLL_MLOCK)
389
		return -ENOENT;
389
		return -ENOENT;
390
	/* For mm_populate(), just skip the stack guard page. */
390
	/* For mm_populate(), just skip the stack guard page. */
391
	if ((*flags & FOLL_POPULATE) &&
391
	if ((*flags & FOLL_POPULATE) && stack_guard_area(vma, address))
392
			(stack_guard_page_start(vma, address) ||
393
			 stack_guard_page_end(vma, address + PAGE_SIZE)))
394
		return -ENOENT;
392
		return -ENOENT;
395
	if (*flags & FOLL_WRITE)
393
	if (*flags & FOLL_WRITE)
396
		fault_flags |= FAULT_FLAG_WRITE;
394
		fault_flags |= FAULT_FLAG_WRITE;
(-)a/mm/memory.c (-33 / +2 lines)
Lines 2854-2892 int do_swap_page(struct vm_fault *vmf) Link Here
2854
	return ret;
2854
	return ret;
2855
}
2855
}
2856
2856
2857
/*
2858
 * This is like a special single-page "expand_{down|up}wards()",
2859
 * except we must first make sure that 'address{-|+}PAGE_SIZE'
2860
 * doesn't hit another vma.
2861
 */
2862
static inline int check_stack_guard_page(struct vm_area_struct *vma, unsigned long address)
2863
{
2864
	address &= PAGE_MASK;
2865
	if ((vma->vm_flags & VM_GROWSDOWN) && address == vma->vm_start) {
2866
		struct vm_area_struct *prev = vma->vm_prev;
2867
2868
		/*
2869
		 * Is there a mapping abutting this one below?
2870
		 *
2871
		 * That's only ok if it's the same stack mapping
2872
		 * that has gotten split..
2873
		 */
2874
		if (prev && prev->vm_end == address)
2875
			return prev->vm_flags & VM_GROWSDOWN ? 0 : -ENOMEM;
2876
2857
2877
		return expand_downwards(vma, address - PAGE_SIZE);
2878
	}
2879
	if ((vma->vm_flags & VM_GROWSUP) && address + PAGE_SIZE == vma->vm_end) {
2880
		struct vm_area_struct *next = vma->vm_next;
2881
2882
		/* As VM_GROWSDOWN but s/below/above/ */
2883
		if (next && next->vm_start == address + PAGE_SIZE)
2884
			return next->vm_flags & VM_GROWSUP ? 0 : -ENOMEM;
2885
2886
		return expand_upwards(vma, address + PAGE_SIZE);
2887
	}
2888
	return 0;
2889
}
2890
2858
2891
/*
2859
/*
2892
 * We enter with non-exclusive mmap_sem (to exclude vma changes,
2860
 * We enter with non-exclusive mmap_sem (to exclude vma changes,
Lines 2905-2911 static int do_anonymous_page(struct vm_fault *vmf) Link Here
2905
		return VM_FAULT_SIGBUS;
2873
		return VM_FAULT_SIGBUS;
2906
2874
2907
	/* Check if we need to add a guard page to the stack */
2875
	/* Check if we need to add a guard page to the stack */
2908
	if (check_stack_guard_page(vma, vmf->address) < 0)
2876
	if ((vma->vm_flags & (VM_GROWSDOWN|VM_GROWSUP)) &&
2877
			expand_stack(vma, vmf->address) < 0)
2909
		return VM_FAULT_SIGSEGV;
2878
		return VM_FAULT_SIGSEGV;
2910
2879
2911
	/*
2880
	/*
(-)a/mm/mmap.c (-30 / +123 lines)
Lines 2155-2161 find_vma_prev(struct mm_struct *mm, unsigned long addr, Link Here
2155
 * update accounting. This is shared with both the
2155
 * update accounting. This is shared with both the
2156
 * grow-up and grow-down cases.
2156
 * grow-up and grow-down cases.
2157
 */
2157
 */
2158
static int acct_stack_growth(struct vm_area_struct *vma, unsigned long size, unsigned long grow)
2158
static int acct_stack_growth(struct vm_area_struct *vma, unsigned long size, unsigned long grow,
2159
		unsigned long gap)
2159
{
2160
{
2160
	struct mm_struct *mm = vma->vm_mm;
2161
	struct mm_struct *mm = vma->vm_mm;
2161
	struct rlimit *rlim = current->signal->rlim;
2162
	struct rlimit *rlim = current->signal->rlim;
Lines 2168-2174 static int acct_stack_growth(struct vm_area_struct *vma, unsigned long size, uns Link Here
2168
	/* Stack limit test */
2169
	/* Stack limit test */
2169
	actual_size = size;
2170
	actual_size = size;
2170
	if (size && (vma->vm_flags & (VM_GROWSUP | VM_GROWSDOWN)))
2171
	if (size && (vma->vm_flags & (VM_GROWSUP | VM_GROWSDOWN)))
2171
		actual_size -= PAGE_SIZE;
2172
		actual_size -= gap;
2172
	if (actual_size > READ_ONCE(rlim[RLIMIT_STACK].rlim_cur))
2173
	if (actual_size > READ_ONCE(rlim[RLIMIT_STACK].rlim_cur))
2173
		return -ENOMEM;
2174
		return -ENOMEM;
2174
2175
Lines 2204-2210 static int acct_stack_growth(struct vm_area_struct *vma, unsigned long size, uns Link Here
2204
 * PA-RISC uses this for its stack; IA64 for its Register Backing Store.
2205
 * PA-RISC uses this for its stack; IA64 for its Register Backing Store.
2205
 * vma is the last one with address > vma->vm_end.  Have to extend vma.
2206
 * vma is the last one with address > vma->vm_end.  Have to extend vma.
2206
 */
2207
 */
2207
int expand_upwards(struct vm_area_struct *vma, unsigned long address)
2208
int expand_upwards(struct vm_area_struct *vma, unsigned long address, unsigned long gap)
2208
{
2209
{
2209
	struct mm_struct *mm = vma->vm_mm;
2210
	struct mm_struct *mm = vma->vm_mm;
2210
	int error = 0;
2211
	int error = 0;
Lines 2212-2223 int expand_upwards(struct vm_area_struct *vma, unsigned long address) Link Here
2212
	if (!(vma->vm_flags & VM_GROWSUP))
2213
	if (!(vma->vm_flags & VM_GROWSUP))
2213
		return -EFAULT;
2214
		return -EFAULT;
2214
2215
2215
	/* Guard against wrapping around to address 0. */
2216
	if (address < PAGE_ALIGN(address+4))
2217
		address = PAGE_ALIGN(address+4);
2218
	else
2219
		return -ENOMEM;
2220
2221
	/* We must make sure the anon_vma is allocated. */
2216
	/* We must make sure the anon_vma is allocated. */
2222
	if (unlikely(anon_vma_prepare(vma)))
2217
	if (unlikely(anon_vma_prepare(vma)))
2223
		return -ENOMEM;
2218
		return -ENOMEM;
Lines 2238-2244 int expand_upwards(struct vm_area_struct *vma, unsigned long address) Link Here
2238
2233
2239
		error = -ENOMEM;
2234
		error = -ENOMEM;
2240
		if (vma->vm_pgoff + (size >> PAGE_SHIFT) >= vma->vm_pgoff) {
2235
		if (vma->vm_pgoff + (size >> PAGE_SHIFT) >= vma->vm_pgoff) {
2241
			error = acct_stack_growth(vma, size, grow);
2236
			error = acct_stack_growth(vma, size, grow, gap);
2242
			if (!error) {
2237
			if (!error) {
2243
				/*
2238
				/*
2244
				 * vma_gap_update() doesn't support concurrent
2239
				 * vma_gap_update() doesn't support concurrent
Lines 2279-2285 int expand_upwards(struct vm_area_struct *vma, unsigned long address) Link Here
2279
 * vma is the first one with address < vma->vm_start.  Have to extend vma.
2274
 * vma is the first one with address < vma->vm_start.  Have to extend vma.
2280
 */
2275
 */
2281
int expand_downwards(struct vm_area_struct *vma,
2276
int expand_downwards(struct vm_area_struct *vma,
2282
				   unsigned long address)
2277
				   unsigned long address, unsigned long gap)
2283
{
2278
{
2284
	struct mm_struct *mm = vma->vm_mm;
2279
	struct mm_struct *mm = vma->vm_mm;
2285
	int error;
2280
	int error;
Lines 2309-2315 int expand_downwards(struct vm_area_struct *vma, Link Here
2309
2304
2310
		error = -ENOMEM;
2305
		error = -ENOMEM;
2311
		if (grow <= vma->vm_pgoff) {
2306
		if (grow <= vma->vm_pgoff) {
2312
			error = acct_stack_growth(vma, size, grow);
2307
			error = acct_stack_growth(vma, size, grow, gap);
2313
			if (!error) {
2308
			if (!error) {
2314
				/*
2309
				/*
2315
				 * vma_gap_update() doesn't support concurrent
2310
				 * vma_gap_update() doesn't support concurrent
Lines 2343-2371 int expand_downwards(struct vm_area_struct *vma, Link Here
2343
	return error;
2338
	return error;
2344
}
2339
}
2345
2340
2341
/* enforced gap between the expanding stack and other mappings. */
2342
unsigned long stack_guard_gap = 256UL<<PAGE_SHIFT;
2343
2346
/*
2344
/*
2347
 * Note how expand_stack() refuses to expand the stack all the way to
2345
 * Note how expand_stack() refuses to expand the stack all the way to
2348
 * abut the next virtual mapping, *unless* that mapping itself is also
2346
 * abut the next virtual mapping, *unless* that mapping itself is also
2349
 * a stack mapping. We want to leave room for a guard page, after all
2347
 * a stack mapping. We want to leave room for a guard area, after all
2350
 * (the guard page itself is not added here, that is done by the
2348
 * (the guard page itself is not added here, that is done by the
2351
 * actual page faulting logic)
2349
 * actual page faulting logic)
2352
 *
2353
 * This matches the behavior of the guard page logic (see mm/memory.c:
2354
 * check_stack_guard_page()), which only allows the guard page to be
2355
 * removed under these circumstances.
2356
 */
2350
 */
2357
#ifdef CONFIG_STACK_GROWSUP
2351
#ifdef CONFIG_STACK_GROWSUP
2352
unsigned long expandable_stack_area(struct vm_area_struct *vma,
2353
		unsigned long address, unsigned long *gap)
2354
{
2355
	struct vm_area_struct *next = vma->vm_next;
2356
	unsigned long guard_gap = stack_guard_gap;
2357
	unsigned long guard_addr;
2358
2359
	address = ALIGN(address, PAGE_SIZE);;
2360
	if (!next)
2361
		goto out;
2362
2363
	if (next->vm_flags & VM_GROWSUP) {
2364
		guard_gap = min(guard_gap, next->vm_start - address);
2365
		goto out;
2366
	}
2367
2368
	if (next->vm_start - address < guard_gap)
2369
		return -ENOMEM;
2370
out:
2371
	if (TASK_SIZE - address < guard_gap)
2372
		guard_gap = TASK_SIZE - address;
2373
	guard_addr = address + guard_gap;
2374
	*gap = guard_gap;
2375
2376
	return guard_addr;
2377
}
2378
2358
int expand_stack(struct vm_area_struct *vma, unsigned long address)
2379
int expand_stack(struct vm_area_struct *vma, unsigned long address)
2359
{
2380
{
2381
	unsigned long gap;
2382
2383
	address = expandable_stack_area(vma, address, &gap);
2384
	if (IS_ERR_VALUE(address))
2385
		return -ENOMEM;
2386
	return expand_upwards(vma, address, gap);
2387
}
2388
2389
int stack_guard_area(struct vm_area_struct *vma, unsigned long address)
2390
{
2360
	struct vm_area_struct *next;
2391
	struct vm_area_struct *next;
2361
2392
2362
	address &= PAGE_MASK;
2393
	if (!(vma->vm_flags & VM_GROWSUP))
2394
		return 0;
2395
2396
	/*
2397
	 * strictly speaking there is a guard gap between disjoint stacks
2398
	 * but the gap is not canonical (it might be smaller) and it is
2399
	 * reasonably safe to assume that we can ignore that gap for stack
2400
	 * POPULATE or /proc/<pid>[s]maps purposes
2401
	 */
2363
	next = vma->vm_next;
2402
	next = vma->vm_next;
2364
	if (next && next->vm_start == address + PAGE_SIZE) {
2403
	if (next && next->vm_flags & VM_GROWSUP)
2365
		if (!(next->vm_flags & VM_GROWSUP))
2404
		return 0;
2366
			return -ENOMEM;
2405
2367
	}
2406
	return vma->vm_end - address <= stack_guard_gap;
2368
	return expand_upwards(vma, address);
2369
}
2407
}
2370
2408
2371
struct vm_area_struct *
2409
struct vm_area_struct *
Lines 2384-2400 find_extend_vma(struct mm_struct *mm, unsigned long addr) Link Here
2384
	return prev;
2422
	return prev;
2385
}
2423
}
2386
#else
2424
#else
2425
unsigned long expandable_stack_area(struct vm_area_struct *vma,
2426
		unsigned long address, unsigned long *gap)
2427
{
2428
	struct vm_area_struct *prev = vma->vm_prev;
2429
	unsigned long guard_gap = stack_guard_gap;
2430
	unsigned long guard_addr;
2431
2432
	address &= PAGE_MASK;
2433
	if (!prev)
2434
		goto out;
2435
2436
	/*
2437
	 * Is there a mapping abutting this one below?
2438
	 *
2439
	 * That's only ok if it's the same stack mapping
2440
	 * that has gotten split or there is sufficient gap
2441
	 * between mappings
2442
	 */
2443
	if (prev->vm_flags & VM_GROWSDOWN) {
2444
		guard_gap = min(guard_gap, address - prev->vm_end);
2445
		goto out;
2446
	}
2447
2448
	if (address - prev->vm_end < guard_gap)
2449
		return -ENOMEM;
2450
2451
out:
2452
	/* make sure we won't underflow */
2453
	if (address < mmap_min_addr)
2454
		return -ENOMEM;
2455
	if (address - mmap_min_addr < guard_gap)
2456
		guard_gap = address - mmap_min_addr;
2457
2458
	guard_addr = address - guard_gap;
2459
	*gap = guard_gap;
2460
2461
	return guard_addr;
2462
}
2463
2387
int expand_stack(struct vm_area_struct *vma, unsigned long address)
2464
int expand_stack(struct vm_area_struct *vma, unsigned long address)
2388
{
2465
{
2466
	unsigned long gap;
2467
2468
	address = expandable_stack_area(vma, address, &gap);
2469
	if (IS_ERR_VALUE(address))
2470
		return -ENOMEM;
2471
	return expand_downwards(vma, address, gap);
2472
}
2473
2474
int stack_guard_area(struct vm_area_struct *vma, unsigned long address)
2475
{
2389
	struct vm_area_struct *prev;
2476
	struct vm_area_struct *prev;
2390
2477
2391
	address &= PAGE_MASK;
2478
	if (!(vma->vm_flags & VM_GROWSDOWN))
2479
		return 0;
2480
2481
	/*
2482
	 * strictly speaking there is a guard gap between disjoint stacks
2483
	 * but the gap is not canonical (it might be smaller) and it is
2484
	 * reasonably safe to assume that we can ignore that gap for stack
2485
	 * POPULATE or /proc/<pid>[s]maps purposes
2486
	 */
2392
	prev = vma->vm_prev;
2487
	prev = vma->vm_prev;
2393
	if (prev && prev->vm_end == address) {
2488
	if (prev && prev->vm_flags & VM_GROWSDOWN)
2394
		if (!(prev->vm_flags & VM_GROWSDOWN))
2489
		return 0;
2395
			return -ENOMEM;
2490
2396
	}
2491
	return address - vma->vm_start < stack_guard_gap;
2397
	return expand_downwards(vma, address);
2398
}
2492
}
2399
2493
2400
struct vm_area_struct *
2494
struct vm_area_struct *
2401
- 

Return to bug 1039348