diff options
-rw-r--r-- | fs/exec.c | 28 |
1 files changed, 24 insertions, 4 deletions
@@ -220,8 +220,26 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, | |||
220 | 220 | ||
221 | if (write) { | 221 | if (write) { |
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 | unsigned long ptr_size; | ||
223 | struct rlimit *rlim; | 224 | struct rlimit *rlim; |
224 | 225 | ||
226 | /* | ||
227 | * Since the stack will hold pointers to the strings, we | ||
228 | * must account for them as well. | ||
229 | * | ||
230 | * The size calculation is the entire vma while each arg page is | ||
231 | * built, so each time we get here it's calculating how far it | ||
232 | * is currently (rather than each call being just the newly | ||
233 | * added size from the arg page). As a result, we need to | ||
234 | * always add the entire size of the pointers, so that on the | ||
235 | * last call to get_arg_page() we'll actually have the entire | ||
236 | * correct size. | ||
237 | */ | ||
238 | ptr_size = (bprm->argc + bprm->envc) * sizeof(void *); | ||
239 | if (ptr_size > ULONG_MAX - size) | ||
240 | goto fail; | ||
241 | size += ptr_size; | ||
242 | |||
225 | acct_arg_size(bprm, size / PAGE_SIZE); | 243 | acct_arg_size(bprm, size / PAGE_SIZE); |
226 | 244 | ||
227 | /* | 245 | /* |
@@ -239,13 +257,15 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, | |||
239 | * to work from. | 257 | * to work from. |
240 | */ | 258 | */ |
241 | rlim = current->signal->rlim; | 259 | rlim = current->signal->rlim; |
242 | if (size > ACCESS_ONCE(rlim[RLIMIT_STACK].rlim_cur) / 4) { | 260 | if (size > READ_ONCE(rlim[RLIMIT_STACK].rlim_cur) / 4) |
243 | put_page(page); | 261 | goto fail; |
244 | return NULL; | ||
245 | } | ||
246 | } | 262 | } |
247 | 263 | ||
248 | return page; | 264 | return page; |
265 | |||
266 | fail: | ||
267 | put_page(page); | ||
268 | return NULL; | ||
249 | } | 269 | } |
250 | 270 | ||
251 | static void put_arg_page(struct page *page) | 271 | static void put_arg_page(struct page *page) |