Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 14 May 2007 21:51:33 GMT
From:      John Baldwin <jhb@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 119857 for review
Message-ID:  <200705142151.l4ELpXvP068210@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=119857

Change 119857 by jhb@jhb_mutex on 2007/05/14 21:51:29

	Change handling of resource limits for 32-bit processes on 64-bit
	kernels so that we just cap the values on read instead of always
	creating a new limit structure on exec.  The problem with the old
	approach is that the new limits would be inherited by child 64-bit
	processes, which has proven to be a significant POLA violation.

Affected files ...

.. //depot/projects/smpng/sys/amd64/linux32/linux32_sysvec.c#25 edit
.. //depot/projects/smpng/sys/compat/ia32/ia32_sysvec.c#16 edit
.. //depot/projects/smpng/sys/kern/imgact_elf.c#55 edit
.. //depot/projects/smpng/sys/kern/kern_exec.c#104 edit
.. //depot/projects/smpng/sys/kern/kern_resource.c#71 edit
.. //depot/projects/smpng/sys/sys/sysent.h#26 edit

Differences ...

==== //depot/projects/smpng/sys/amd64/linux32/linux32_sysvec.c#25 (text+ko) ====

@@ -119,7 +119,7 @@
 static void     linux_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask);
 static void	exec_linux_setregs(struct thread *td, u_long entry,
 				   u_long stack, u_long ps_strings);
-static void	linux32_fixlimits(struct proc *p);
+static void	linux32_fixlimit(struct rlimit *rl, int which);
 
 extern LIST_HEAD(futex_list, futex) futex_list;
 extern struct sx futex_sx;
@@ -963,42 +963,36 @@
 SYSCTL_ULONG(_compat_linux32, OID_AUTO, maxvmem, CTLFLAG_RW,
     &linux32_maxvmem, 0, "");
 
-/*
- * XXX copied from ia32_sysvec.c.
- */
 static void
-linux32_fixlimits(struct proc *p)
+linux32_fixlimit(struct rlimit *rl, int which)
 {
-	struct plimit *oldlim, *newlim;
 
-	if (linux32_maxdsiz == 0 && linux32_maxssiz == 0 &&
-	    linux32_maxvmem == 0)
-		return;
-	newlim = lim_alloc();
-	PROC_LOCK(p);
-	oldlim = p->p_limit;
-	lim_copy(newlim, oldlim);
-	if (linux32_maxdsiz != 0) {
-		if (newlim->pl_rlimit[RLIMIT_DATA].rlim_cur > linux32_maxdsiz)
-		    newlim->pl_rlimit[RLIMIT_DATA].rlim_cur = linux32_maxdsiz;
-		if (newlim->pl_rlimit[RLIMIT_DATA].rlim_max > linux32_maxdsiz)
-		    newlim->pl_rlimit[RLIMIT_DATA].rlim_max = linux32_maxdsiz;
+	switch (which) {
+	case RLIMIT_DATA:
+		if (linux32_maxdsiz != 0) {			
+			if (rl->rlim_cur > linux32_maxdsiz)
+				rl->rlim_cur = linux32_maxdsiz;
+			if (rl->rlim_max > linux32_maxdsiz)
+				rl->rlim_max = linux32_maxdsiz;
+		}
+		break;
+	case RLIMIT_STACK:
+		if (linux32_maxssiz != 0) {
+			if (rl->rlim_cur > linux32_maxssiz)
+				rl->rlim_cur = linux32_maxssiz;
+			if (rl->rlim_max > linux32_maxssiz)
+				rl->rlim_max = linux32_maxssiz;
+		}
+		break;
+	case RLIMIT_VMEM:
+		if (linux32_maxvmem != 0) {
+			if (rl->rlim_cur > linux32_maxvmem)
+				rl->rlim_cur = linux32_maxvmem;
+			if (rl->rlim_max > linux32_maxvmem)
+				rl->rlim_max = linux32_maxvmem;
+		}
+		break;
 	}
-	if (linux32_maxssiz != 0) {
-		if (newlim->pl_rlimit[RLIMIT_STACK].rlim_cur > linux32_maxssiz)
-		    newlim->pl_rlimit[RLIMIT_STACK].rlim_cur = linux32_maxssiz;
-		if (newlim->pl_rlimit[RLIMIT_STACK].rlim_max > linux32_maxssiz)
-		    newlim->pl_rlimit[RLIMIT_STACK].rlim_max = linux32_maxssiz;
-	}
-	if (linux32_maxvmem != 0) {
-		if (newlim->pl_rlimit[RLIMIT_VMEM].rlim_cur > linux32_maxvmem)
-		    newlim->pl_rlimit[RLIMIT_VMEM].rlim_cur = linux32_maxvmem;
-		if (newlim->pl_rlimit[RLIMIT_VMEM].rlim_max > linux32_maxvmem)
-		    newlim->pl_rlimit[RLIMIT_VMEM].rlim_max = linux32_maxvmem;
-	}
-	p->p_limit = newlim;
-	PROC_UNLOCK(p);
-	lim_free(oldlim);
 }
 
 struct sysentvec elf_linux_sysvec = {
@@ -1027,7 +1021,7 @@
 	VM_PROT_ALL,
 	linux_copyout_strings,
 	exec_linux_setregs,
-	linux32_fixlimits
+	linux32_fixlimit
 };
 
 static Elf32_Brandinfo linux_brand = {

==== //depot/projects/smpng/sys/compat/ia32/ia32_sysvec.c#16 (text+ko) ====

@@ -94,7 +94,7 @@
 #endif
 
 static register_t *ia32_copyout_strings(struct image_params *imgp);
-static void ia32_fixlimits(struct proc *p);
+static void ia32_fixlimit(struct rlimit *rl, int which);
 
 extern struct sysent freebsd32_sysent[];
 
@@ -126,7 +126,7 @@
 	VM_PROT_ALL,
 	ia32_copyout_strings,
 	ia32_setregs,
-	ia32_fixlimits
+	ia32_fixlimit
 };
 
 
@@ -281,35 +281,33 @@
 SYSCTL_ULONG(_compat_ia32, OID_AUTO, maxvmem, CTLFLAG_RW, &ia32_maxvmem, 0, "");
 
 static void
-ia32_fixlimits(struct proc *p)
+ia32_fixlimit(struct rlimit *rl, int which)
 {
-	struct plimit *oldlim, *newlim;
 
-	if (ia32_maxdsiz == 0 && ia32_maxssiz == 0 && ia32_maxvmem == 0)
-		return;
-	newlim = lim_alloc();
-	PROC_LOCK(p);
-	oldlim = p->p_limit;
-	lim_copy(newlim, oldlim);
-	if (ia32_maxdsiz != 0) {
-		if (newlim->pl_rlimit[RLIMIT_DATA].rlim_cur > ia32_maxdsiz)
-		    newlim->pl_rlimit[RLIMIT_DATA].rlim_cur = ia32_maxdsiz;
-		if (newlim->pl_rlimit[RLIMIT_DATA].rlim_max > ia32_maxdsiz)
-		    newlim->pl_rlimit[RLIMIT_DATA].rlim_max = ia32_maxdsiz;
+	switch (which) {
+	case RLIMIT_DATA:
+		if (ia32_maxdsiz != 0) {
+			if (rl->rlim_cur > ia32_maxdsiz)
+				rl->rlim_cur = ia32_maxdsiz;
+			if (rl->rlim_max > ia32_maxdsiz)
+				rl->rlim_max = ia32_maxdsiz;
+		}
+		break;
+	case RLIMIT_STACK:
+		if (ia32_maxssiz != 0) {
+			if (rl->rlim_cur > ia32_maxssiz)
+				rl->rlim_cur = ia32_maxssiz;
+			if (rl->rlim_max > ia32_maxssiz)
+				rl->rlim_max = ia32_maxssiz;
+		}
+		break;
+	case RLIMIT_VMEM:
+		if (ia32_maxvmem != 0) {
+			if (rl->rlim_cur > ia32_maxvmem)
+				rl->rlim_cur = ia32_maxvmem;
+			if (rl->rlim_max > ia32_maxvmem)
+				rl->rlim_max = ia32_maxvmem;
+		}
+		break;
 	}
-	if (ia32_maxssiz != 0) {
-		if (newlim->pl_rlimit[RLIMIT_STACK].rlim_cur > ia32_maxssiz)
-		    newlim->pl_rlimit[RLIMIT_STACK].rlim_cur = ia32_maxssiz;
-		if (newlim->pl_rlimit[RLIMIT_STACK].rlim_max > ia32_maxssiz)
-		    newlim->pl_rlimit[RLIMIT_STACK].rlim_max = ia32_maxssiz;
-	}
-	if (ia32_maxvmem != 0) {
-		if (newlim->pl_rlimit[RLIMIT_VMEM].rlim_cur > ia32_maxvmem)
-		    newlim->pl_rlimit[RLIMIT_VMEM].rlim_cur = ia32_maxvmem;
-		if (newlim->pl_rlimit[RLIMIT_VMEM].rlim_max > ia32_maxvmem)
-		    newlim->pl_rlimit[RLIMIT_VMEM].rlim_max = ia32_maxvmem;
-	}
-	p->p_limit = newlim;
-	PROC_UNLOCK(p);
-	lim_free(oldlim);
 }

==== //depot/projects/smpng/sys/kern/imgact_elf.c#55 (text+ko) ====

@@ -667,6 +667,7 @@
 	VOP_UNLOCK(imgp->vp, 0, td);
 
 	exec_new_vmspace(imgp, sv);
+	imgp->proc->p_sysent = sv;
 
 	vn_lock(imgp->vp, LK_EXCLUSIVE | LK_RETRY, td);
 
@@ -784,7 +785,6 @@
 
 	imgp->entry_addr = entry;
 
-	imgp->proc->p_sysent = sv;
 	if (interp != NULL) {
 		VOP_UNLOCK(imgp->vp, 0, td);
 		if (brand_info->emul_path != NULL &&

==== //depot/projects/smpng/sys/kern/kern_exec.c#104 (text+ko) ====

@@ -908,15 +908,6 @@
 	EVENTHANDLER_INVOKE(process_exec, p, imgp);
 
 	/*
-	 * Here is as good a place as any to do any resource limit cleanups.
-	 * This is needed if a 64 bit binary exec's a 32 bit binary - the
-	 * data size limit may need to be changed to a value that makes
-	 * sense for the 32 bit binary.
-	 */
-	if (sv->sv_fixlimits != NULL)
-		sv->sv_fixlimits(p);
-
-	/*
 	 * Blow away entire process VM, if address space not shared,
 	 * otherwise, create a new VM space so that other threads are
 	 * not disrupted

==== //depot/projects/smpng/sys/kern/kern_resource.c#71 (text+ko) ====

@@ -701,6 +701,8 @@
 			limp->rlim_max = 1;
 		break;
 	}
+	if (td->td_proc->p_sysent->sv_fixlimit != NULL)
+		td->td_proc->p_sysent->sv_fixlimit(limp, which);
 	*alimp = *limp;
 	p->p_limit = newlim;
 	PROC_UNLOCK(p);
@@ -734,12 +736,6 @@
 		}
 	}
 
-	/*
-	 * The data size limit may need to be changed to a value
-	 * that makes sense for the 32 bit binary.
-	 */
-	if (p->p_sysent->sv_fixlimits != NULL)
-		p->p_sysent->sv_fixlimits(p);
 	return (0);
 }
 
@@ -1062,6 +1058,8 @@
 	KASSERT(which >= 0 && which < RLIM_NLIMITS,
 	    ("request for invalid resource limit"));
 	*rlp = p->p_limit->pl_rlimit[which];
+	if (p->p_sysent->sv_fixlimit != NULL)
+		p->p_sysent->sv_fixlimit(rlp, which);
 }
 
 /*

==== //depot/projects/smpng/sys/sys/sysent.h#26 (text+ko) ====

@@ -34,7 +34,7 @@
 
 #include <bsm/audit.h>
 
-struct proc;
+struct rlimit;
 struct sysent;
 struct thread;
 struct ksiginfo;
@@ -98,7 +98,7 @@
 	int		sv_stackprot;	/* vm protection for stack */
 	register_t	*(*sv_copyout_strings)(struct image_params *);
 	void		(*sv_setregs)(struct thread *, u_long, u_long, u_long);
-	void		(*sv_fixlimits)(struct proc *);
+	void		(*sv_fixlimit)(struct rlimit *, int);
 };
 
 #ifdef _KERNEL



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