From: Alexandre Ghiti alex@ghiti.fr
[ Upstream commit af0f4297286f13a75edf93677b1fb2fc16c412a7 ]
This commit takes care of stack randomization and stack guard gap when computing mmap base address and checks if the task asked for randomization. This fixes the problem uncovered and not fixed for arm here: https://lkml.kernel.org/r/20170622200033.25714-1-riel@redhat.com
Link: http://lkml.kernel.org/r/20190730055113.23635-7-alex@ghiti.fr Signed-off-by: Alexandre Ghiti alex@ghiti.fr Acked-by: Kees Cook keescook@chromium.org Reviewed-by: Luis Chamberlain mcgrof@kernel.org Cc: Albert Ou aou@eecs.berkeley.edu Cc: Alexander Viro viro@zeniv.linux.org.uk Cc: Catalin Marinas catalin.marinas@arm.com Cc: Christoph Hellwig hch@infradead.org Cc: Christoph Hellwig hch@lst.de Cc: James Hogan jhogan@kernel.org Cc: Palmer Dabbelt palmer@sifive.com Cc: Paul Burton paul.burton@mips.com Cc: Ralf Baechle ralf@linux-mips.org Cc: Russell King linux@armlinux.org.uk Cc: Will Deacon will.deacon@arm.com Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Sasha Levin sashal@kernel.org --- arch/arm/mm/mmap.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mm/mmap.c b/arch/arm/mm/mmap.c index f866870db749c..bff3d00bda5be 100644 --- a/arch/arm/mm/mmap.c +++ b/arch/arm/mm/mmap.c @@ -18,8 +18,9 @@ (((pgoff)<<PAGE_SHIFT) & (SHMLBA-1)))
/* gap between mmap and stack */ -#define MIN_GAP (128*1024*1024UL) -#define MAX_GAP ((TASK_SIZE)/6*5) +#define MIN_GAP (128*1024*1024UL) +#define MAX_GAP ((TASK_SIZE)/6*5) +#define STACK_RND_MASK (0x7ff >> (PAGE_SHIFT - 12))
static int mmap_is_legacy(struct rlimit *rlim_stack) { @@ -35,6 +36,15 @@ static int mmap_is_legacy(struct rlimit *rlim_stack) static unsigned long mmap_base(unsigned long rnd, struct rlimit *rlim_stack) { unsigned long gap = rlim_stack->rlim_cur; + unsigned long pad = stack_guard_gap; + + /* Account for stack randomization if necessary */ + if (current->flags & PF_RANDOMIZE) + pad += (STACK_RND_MASK << PAGE_SHIFT); + + /* Values close to RLIM_INFINITY can overflow. */ + if (gap + pad > gap) + gap += pad;
if (gap < MIN_GAP) gap = MIN_GAP;