Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 31 Jul 2019 20:23:10 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r350484 - in head/sys: amd64/amd64 compat/freebsd32 compat/ia32 kern sys
Message-ID:  <201907312023.x6VKNARv094353@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Wed Jul 31 20:23:10 2019
New Revision: 350484
URL: https://svnweb.freebsd.org/changeset/base/350484

Log:
  Make randomized stack gap between strings and pointers to argv/envs.
  
  This effectively makes the stack base on the csu _start entry
  randomized.
  
  The gap is enabled if ASLR is for the ABI is enabled, and then
  kern.elf{64,32}.aslr.stack_gap specify the max percentage of the
  initial stack size that can be wasted for gap.  Setting it to zero
  disables the gap, and max is capped at 50%.
  
  Only amd64 for now.
  
  Reviewed by:	cem, markj
  Discussed with:	emaste
  MFC after:	2 weeks
  Sponsored by:	The FreeBSD Foundation
  Differential revision:	https://reviews.freebsd.org/D21081

Modified:
  head/sys/amd64/amd64/elf_machdep.c
  head/sys/compat/freebsd32/freebsd32_misc.c
  head/sys/compat/ia32/ia32_sysvec.c
  head/sys/kern/imgact_elf.c
  head/sys/kern/kern_exec.c
  head/sys/sys/imgact.h
  head/sys/sys/imgact_elf.h
  head/sys/sys/sysent.h

Modified: head/sys/amd64/amd64/elf_machdep.c
==============================================================================
--- head/sys/amd64/amd64/elf_machdep.c	Wed Jul 31 20:04:39 2019	(r350483)
+++ head/sys/amd64/amd64/elf_machdep.c	Wed Jul 31 20:23:10 2019	(r350484)
@@ -82,6 +82,7 @@ struct sysentvec elf64_freebsd_sysvec = {
 	.sv_schedtail	= NULL,
 	.sv_thread_detach = NULL,
 	.sv_trap	= NULL,
+	.sv_stackgap	= elf64_stackgap,
 };
 INIT_SYSENTVEC(elf64_sysvec, &elf64_freebsd_sysvec);
 

Modified: head/sys/compat/freebsd32/freebsd32_misc.c
==============================================================================
--- head/sys/compat/freebsd32/freebsd32_misc.c	Wed Jul 31 20:04:39 2019	(r350483)
+++ head/sys/compat/freebsd32/freebsd32_misc.c	Wed Jul 31 20:23:10 2019	(r350484)
@@ -3166,6 +3166,9 @@ freebsd32_copyout_strings(struct image_params *imgp)
 	destp = rounddown2(destp, sizeof(uint32_t));
 
 	vectp = (uint32_t *)destp;
+	if (imgp->sysent->sv_stackgap != NULL)
+		imgp->sysent->sv_stackgap(imgp, (u_long *)&vectp);
+
 	if (imgp->auxargs) {
 		/*
 		 * Allocate room on the stack for the ELF auxargs

Modified: head/sys/compat/ia32/ia32_sysvec.c
==============================================================================
--- head/sys/compat/ia32/ia32_sysvec.c	Wed Jul 31 20:04:39 2019	(r350483)
+++ head/sys/compat/ia32/ia32_sysvec.c	Wed Jul 31 20:23:10 2019	(r350484)
@@ -128,6 +128,7 @@ struct sysentvec ia32_freebsd_sysvec = {
 	.sv_schedtail	= NULL,
 	.sv_thread_detach = NULL,
 	.sv_trap	= NULL,
+	.sv_stackgap	= elf32_stackgap,
 };
 INIT_SYSENTVEC(elf_ia32_sysvec, &ia32_freebsd_sysvec);
 

Modified: head/sys/kern/imgact_elf.c
==============================================================================
--- head/sys/kern/imgact_elf.c	Wed Jul 31 20:04:39 2019	(r350483)
+++ head/sys/kern/imgact_elf.c	Wed Jul 31 20:23:10 2019	(r350484)
@@ -156,6 +156,12 @@ SYSCTL_INT(ASLR_NODE_OID, OID_AUTO, honor_sbrk, CTLFLA
     &__elfN(aslr_honor_sbrk), 0,
     __XSTRING(__CONCAT(ELF, __ELF_WORD_SIZE)) ": assume sbrk is used");
 
+static int __elfN(aslr_stack_gap) = 3;
+SYSCTL_INT(ASLR_NODE_OID, OID_AUTO, stack_gap, CTLFLAG_RW,
+    &__elfN(aslr_stack_gap), 0,
+    __XSTRING(__CONCAT(ELF, __ELF_WORD_SIZE))
+    ": maximum percentage of main stack to waste on a random gap");
+
 static Elf_Brandinfo *elf_brand_list[MAX_BRANDS];
 
 #define	aligned(a, t)	(rounddown2((u_long)(a), sizeof(t)) == (u_long)(a))
@@ -2719,4 +2725,25 @@ __elfN(untrans_prot)(vm_prot_t prot)
 	if (prot & VM_PROT_WRITE)
 		flags |= PF_W;
 	return (flags);
+}
+
+void
+__elfN(stackgap)(struct image_params *imgp, u_long *stack_base)
+{
+	u_long range, rbase, gap;
+	int pct;
+
+	if ((imgp->map_flags & MAP_ASLR) == 0)
+		return;
+	pct = __elfN(aslr_stack_gap);
+	if (pct == 0)
+		return;
+	if (pct > 50)
+		pct = 50;
+	range = imgp->eff_stack_sz * pct / 100;
+	range *= pct;
+	arc4rand(&rbase, sizeof(rbase), 0);
+	gap = rbase % range;
+	gap &= ~(sizeof(u_long) - 1);
+	*stack_base -= gap;
 }

Modified: head/sys/kern/kern_exec.c
==============================================================================
--- head/sys/kern/kern_exec.c	Wed Jul 31 20:04:39 2019	(r350483)
+++ head/sys/kern/kern_exec.c	Wed Jul 31 20:23:10 2019	(r350484)
@@ -1128,6 +1128,7 @@ exec_new_vmspace(struct image_params *imgp, struct sys
 	} else {
 		ssiz = maxssiz;
 	}
+	imgp->eff_stack_sz = ssiz;
 	stack_addr = sv->sv_usrstack - ssiz;
 	error = vm_map_stack(map, stack_addr, (vm_size_t)ssiz,
 	    obj != NULL && imgp->stack_prot != 0 ? imgp->stack_prot :
@@ -1615,6 +1616,9 @@ exec_copyout_strings(struct image_params *imgp)
 	destp = rounddown2(destp, sizeof(void *));
 
 	vectp = (char **)destp;
+	if (imgp->sysent->sv_stackgap != NULL)
+		imgp->sysent->sv_stackgap(imgp, (u_long *)&vectp);
+
 	if (imgp->auxargs) {
 		/*
 		 * Allocate room on the stack for the ELF auxargs

Modified: head/sys/sys/imgact.h
==============================================================================
--- head/sys/sys/imgact.h	Wed Jul 31 20:04:39 2019	(r350483)
+++ head/sys/sys/imgact.h	Wed Jul 31 20:23:10 2019	(r350484)
@@ -87,6 +87,7 @@ struct image_params {
 	int pagesizeslen;
 	vm_prot_t stack_prot;
 	u_long stack_sz;
+	u_long eff_stack_sz;
 	struct ucred *newcred;		/* new credentials if changing */
 	bool credential_setid;		/* true if becoming setid */
 	bool textset;

Modified: head/sys/sys/imgact_elf.h
==============================================================================
--- head/sys/sys/imgact_elf.h	Wed Jul 31 20:04:39 2019	(r350483)
+++ head/sys/sys/imgact_elf.h	Wed Jul 31 20:23:10 2019	(r350484)
@@ -98,6 +98,7 @@ int	__elfN(remove_brand_entry)(Elf_Brandinfo *entry);
 int	__elfN(freebsd_fixup)(register_t **, struct image_params *);
 int	__elfN(coredump)(struct thread *, struct vnode *, off_t, int);
 size_t	__elfN(populate_note)(int, void *, void *, size_t, void **);
+void	__elfN(stackgap)(struct image_params *, u_long *);
 
 /* Machine specific function to dump per-thread information. */
 void	__elfN(dump_thread)(struct thread *, void *, size_t *);

Modified: head/sys/sys/sysent.h
==============================================================================
--- head/sys/sys/sysent.h	Wed Jul 31 20:04:39 2019	(r350483)
+++ head/sys/sys/sysent.h	Wed Jul 31 20:23:10 2019	(r350484)
@@ -109,6 +109,7 @@ struct sysentvec {
 	int		(*sv_coredump)(struct thread *, struct vnode *, off_t, int);
 					/* function to dump core, or NULL */
 	int		(*sv_imgact_try)(struct image_params *);
+	void		(*sv_stackgap)(struct image_params *, u_long *);
 	int		sv_minsigstksz;	/* minimum signal stack size */
 	vm_offset_t	sv_minuser;	/* VM_MIN_ADDRESS */
 	vm_offset_t	sv_maxuser;	/* VM_MAXUSER_ADDRESS */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201907312023.x6VKNARv094353>