summaryrefslogtreecommitdiffstats
path: root/fs/exec.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2017-07-03 19:51:42 +0200
committerTakashi Iwai <tiwai@suse.de>2017-07-03 19:51:42 +0200
commit818a23e3882b1bf65d1719e407be04716e69a4d5 (patch)
tree6e4267b570541f779e7d85c11eb14312fa86fbb1 /fs/exec.c
parentALSA: hda/realtek - Remove GPIO_MASK (diff)
parentMerge remote-tracking branch 'asoc/topic/inte' into asoc-next (diff)
downloadlinux-818a23e3882b1bf65d1719e407be04716e69a4d5.tar.xz
linux-818a23e3882b1bf65d1719e407be04716e69a4d5.zip
Merge tag 'asoc-v4.13' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus
ASoC: Updates for v4.13 The big news with this release is the of-graph card, this provides a replacement for simple-card that is much more flexibile and scalable, allowing many more systems to use a generic sound card than was possible before: - The of-graph card, finally merged after a long and dedicated effort by Morimoto-san. - New widget types intended mainly for use with DSPs. - New drivers for Allwinner V3s SoCs, Ensonic ES8316, several classes of x86 machine, Rockchip PDM controllers, STM32 I2S and S/PDIF controllers and ZTE AUD96P22 CODECs.
Diffstat (limited to 'fs/exec.c')
-rw-r--r--fs/exec.c28
1 files changed, 24 insertions, 4 deletions
diff --git a/fs/exec.c b/fs/exec.c
index 72934df68471..904199086490 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -220,8 +220,26 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos,
if (write) {
unsigned long size = bprm->vma->vm_end - bprm->vma->vm_start;
+ unsigned long ptr_size;
struct rlimit *rlim;
+ /*
+ * Since the stack will hold pointers to the strings, we
+ * must account for them as well.
+ *
+ * The size calculation is the entire vma while each arg page is
+ * built, so each time we get here it's calculating how far it
+ * is currently (rather than each call being just the newly
+ * added size from the arg page). As a result, we need to
+ * always add the entire size of the pointers, so that on the
+ * last call to get_arg_page() we'll actually have the entire
+ * correct size.
+ */
+ ptr_size = (bprm->argc + bprm->envc) * sizeof(void *);
+ if (ptr_size > ULONG_MAX - size)
+ goto fail;
+ size += ptr_size;
+
acct_arg_size(bprm, size / PAGE_SIZE);
/*
@@ -239,13 +257,15 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos,
* to work from.
*/
rlim = current->signal->rlim;
- if (size > ACCESS_ONCE(rlim[RLIMIT_STACK].rlim_cur) / 4) {
- put_page(page);
- return NULL;
- }
+ if (size > READ_ONCE(rlim[RLIMIT_STACK].rlim_cur) / 4)
+ goto fail;
}
return page;
+
+fail:
+ put_page(page);
+ return NULL;
}
static void put_arg_page(struct page *page)