Message ID | 1479394415-30924-3-git-send-email-luis.henriques@canonical.com |
---|---|
State | New |
Headers | show |
On 17/11/16 14:53, Luis Henriques wrote: > From: Mathias Krause <minipli@googlemail.com> > > If /proc/<PID>/environ gets read before the envp[] array is fully set up > in create_{aout,elf,elf_fdpic,flat}_tables(), we might end up trying to > read more bytes than are actually written, as env_start will already be > set but env_end will still be zero, making the range calculation > underflow, allowing to read beyond the end of what has been written. > > Fix this as it is done for /proc/<PID>/cmdline by testing env_end for > zero. It is, apparently, intentionally set last in create_*_tables(). > > This bug was found by the PaX size_overflow plugin that detected the > arithmetic underflow of 'this_len = env_end - (env_start + src)' when > env_end is still zero. > > The expected consequence is that userland trying to access > /proc/<PID>/environ of a not yet fully set up process may get > inconsistent data as we're in the middle of copying in the environment > variables. > > Fixes: https://forums.grsecurity.net/viewtopic.php?f=3&t=4363 > Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=116461 > Signed-off-by: Mathias Krause <minipli@googlemail.com> > Cc: Emese Revfy <re.emese@gmail.com> > Cc: Pax Team <pageexec@freemail.hu> > Cc: Al Viro <viro@zeniv.linux.org.uk> > Cc: Mateusz Guzik <mguzik@redhat.com> > Cc: Alexey Dobriyan <adobriyan@gmail.com> > Cc: Cyrill Gorcunov <gorcunov@openvz.org> > Cc: Jarod Wilson <jarod@redhat.com> > Signed-off-by: Andrew Morton <akpm@linux-foundation.org> > Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> > CVE-2016-7916 > (cherry picked from commit 8148a73c9901a8794a50f950083c00ccf97d43b3) > Signed-off-by: Luis Henriques <luis.henriques@canonical.com> > --- > fs/proc/base.c | 3 ++- > 1 file changed, 2 insertions(+), 1 deletion(-) > > diff --git a/fs/proc/base.c b/fs/proc/base.c > index 0d9205f3e5bf..4dd9d5541088 100644 > --- a/fs/proc/base.c > +++ b/fs/proc/base.c > @@ -841,7 +841,8 @@ static ssize_t environ_read(struct file *file, char __user *buf, > int ret = 0; > struct mm_struct *mm = file->private_data; > > - if (!mm) > + /* Ensure the process spawned far enough to have an environment. */ > + if (!mm || !mm->env_end) > return 0; > > page = (char *)__get_free_page(GFP_TEMPORARY); > Looks good to me Acked-by: Colin Ian King <colin.king@canonical.com>
diff --git a/fs/proc/base.c b/fs/proc/base.c index 0d9205f3e5bf..4dd9d5541088 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -841,7 +841,8 @@ static ssize_t environ_read(struct file *file, char __user *buf, int ret = 0; struct mm_struct *mm = file->private_data; - if (!mm) + /* Ensure the process spawned far enough to have an environment. */ + if (!mm || !mm->env_end) return 0; page = (char *)__get_free_page(GFP_TEMPORARY);