Subject: Re: setrlimit(2) strange behaviour under compat_netbsd32
To: NetBSD current <current-users@NetBSD.org>
From: Nicolas Joly <njoly@pasteur.fr>
List: current-users
Date: 11/21/2006 12:17:24
--bg08WKrSYDhXBjb5
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
On Mon, Nov 20, 2006 at 08:42:53PM +0100, Nicolas Joly wrote:
>
> I just noticed a strange setrlimit(2) behaviour under compat_netbsd32
> (and compat_linux32) on my -current amd64 workstation ...
>
> It seems that 32bits programs, running under compat_netbsd32, using
> setrlimit force all other programs to have their maximum data size
> fixed at 3GB, where native 64bits apps used 8GB previously.
I tracked this one to the `netbsd32_adjust_limits()' function (called
when creating a new process under compat_netbsd32), where data and
stack limits are set without checking for shared `p_limit' structure
(p_limit->p_refcnt > 1). This explain the side effect where processes
have their limits changed when a compat_netbsd32 (or compat_linux32)
program is run.
What about the attached patch, that use `dosetrlimit()' to ensure the
needed copy-on-write behaviour for shared structure.
--
Nicolas Joly
Biological Software and Databanks.
Institut Pasteur, Paris.
--bg08WKrSYDhXBjb5
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="netbsd-netbsd32limits.diff"
Index: sys/compat/linux32/arch/amd64/linux32_machdep.c
===================================================================
RCS file: /cvsroot/src/sys/compat/linux32/arch/amd64/linux32_machdep.c,v
retrieving revision 1.1
diff -u -r1.1 linux32_machdep.c
--- sys/compat/linux32/arch/amd64/linux32_machdep.c 9 Feb 2006 19:18:57 -0000 1.1
+++ sys/compat/linux32/arch/amd64/linux32_machdep.c 21 Nov 2006 10:17:47 -0000
@@ -290,7 +290,7 @@
pmap_ldt_cleanup(p);
#endif
- netbsd32_adjust_limits(p);
+ netbsd32_adjust_limits(l);
l->l_md.md_flags &= ~MDP_USEDFPU;
pcb->pcb_flags = 0;
@@ -301,11 +301,11 @@
pcb->pcb_gs = 0;
- l->l_proc->p_flag |= P_32;
+ p->p_flag |= P_32;
tf = l->l_md.md_regs;
tf->tf_rax = 0;
- tf->tf_rbx = (u_int64_t)l->l_proc->p_psstr & 0xffffffff;
+ tf->tf_rbx = (u_int64_t)p->p_psstr & 0xffffffff;
tf->tf_rcx = pack->ep_entry & 0xffffffff;
tf->tf_rdx = 0;
tf->tf_rsi = 0;
Index: sys/arch/amd64/amd64/netbsd32_machdep.c
===================================================================
RCS file: /cvsroot/src/sys/arch/amd64/amd64/netbsd32_machdep.c,v
retrieving revision 1.28
diff -u -r1.28 netbsd32_machdep.c
--- sys/arch/amd64/amd64/netbsd32_machdep.c 23 Oct 2006 12:11:47 -0000 1.28
+++ sys/arch/amd64/amd64/netbsd32_machdep.c 21 Nov 2006 10:17:47 -0000
@@ -125,7 +125,7 @@
pmap_ldt_cleanup(p);
#endif
- netbsd32_adjust_limits(p);
+ netbsd32_adjust_limits(l);
l->l_md.md_flags &= ~MDP_USEDFPU;
pcb->pcb_flags = 0;
@@ -134,7 +134,7 @@
pcb->pcb_savefpu.fp_fxsave.fx_mxcsr_mask = __INITIAL_MXCSR_MASK__;
- l->l_proc->p_flag |= P_32;
+ p->p_flag |= P_32;
tf = l->l_md.md_regs;
tf->tf_ds = LSEL(LUDATA32_SEL, SEL_UPL);
Index: sys/arch/sparc64/sparc64/netbsd32_machdep.c
===================================================================
RCS file: /cvsroot/src/sys/arch/sparc64/sparc64/netbsd32_machdep.c,v
retrieving revision 1.63
diff -u -r1.63 netbsd32_machdep.c
--- sys/arch/sparc64/sparc64/netbsd32_machdep.c 22 Oct 2006 10:50:44 -0000 1.63
+++ sys/arch/sparc64/sparc64/netbsd32_machdep.c 21 Nov 2006 10:17:47 -0000
@@ -112,7 +112,7 @@
/* Mark this as a 32-bit emulation */
p->p_flag |= P_32;
- netbsd32_adjust_limits(p);
+ netbsd32_adjust_limits(l);
/* Setup the ev_out32 hook */
#if NFIRM_EVENTS > 0
Index: sys/compat/netbsd32/netbsd32.h
===================================================================
RCS file: /cvsroot/src/sys/compat/netbsd32/netbsd32.h,v
retrieving revision 1.54
diff -u -r1.54 netbsd32.h
--- sys/compat/netbsd32/netbsd32.h 13 Jul 2006 12:00:25 -0000 1.54
+++ sys/compat/netbsd32/netbsd32.h 21 Nov 2006 10:17:47 -0000
@@ -676,7 +676,7 @@
void netbsd32_from_stat43 __P((struct stat43 *, struct netbsd32_stat43 *));
vaddr_t netbsd32_vm_default_addr(struct proc *, vaddr_t, vsize_t);
-void netbsd32_adjust_limits(struct proc *);
+void netbsd32_adjust_limits(struct lwp *);
void netbsd32_si_to_si32(siginfo32_t *, const siginfo_t *);
void netbsd32_si32_to_si(siginfo_t *, const siginfo32_t *);
Index: sys/compat/netbsd32/netbsd32_netbsd.c
===================================================================
RCS file: /cvsroot/src/sys/compat/netbsd32/netbsd32_netbsd.c,v
retrieving revision 1.112
diff -u -r1.112 netbsd32_netbsd.c
--- sys/compat/netbsd32/netbsd32_netbsd.c 14 Nov 2006 13:34:29 -0000 1.112
+++ sys/compat/netbsd32/netbsd32_netbsd.c 21 Nov 2006 10:17:48 -0000
@@ -2312,23 +2312,26 @@
}
void
-netbsd32_adjust_limits(struct proc *p)
+netbsd32_adjust_limits(struct lwp *l)
{
- rlim_t *valp;
+ struct proc *p = l->l_proc;
+ struct rlimit lim;
- valp = &p->p_rlimit[RLIMIT_DATA].rlim_cur;
- if (*valp != RLIM_INFINITY && *valp > MAXDSIZ32)
- *valp = MAXDSIZ32;
- valp = &p->p_rlimit[RLIMIT_DATA].rlim_max;
- if (*valp != RLIM_INFINITY && *valp > MAXDSIZ32)
- *valp = MAXDSIZ32;
-
- valp = &p->p_rlimit[RLIMIT_STACK].rlim_cur;
- if (*valp != RLIM_INFINITY && *valp > MAXSSIZ32)
- *valp = MAXSSIZ32;
- valp = &p->p_rlimit[RLIMIT_STACK].rlim_max;
- if (*valp != RLIM_INFINITY && *valp > MAXSSIZ32)
- *valp = MAXSSIZ32;
+ lim.rlim_cur = p->p_rlimit[RLIMIT_DATA].rlim_cur;
+ if (lim.rlim_cur != RLIM_INFINITY && lim.rlim_cur > MAXDSIZ32)
+ lim.rlim_cur = MAXDSIZ32;
+ lim.rlim_max = p->p_rlimit[RLIMIT_DATA].rlim_max;
+ if (lim.rlim_max != RLIM_INFINITY && lim.rlim_max > MAXDSIZ32)
+ lim.rlim_max = MAXDSIZ32;
+ dosetrlimit(l, p, RLIMIT_DATA, &lim);
+
+ lim.rlim_cur = p->p_rlimit[RLIMIT_STACK].rlim_cur;
+ if (lim.rlim_cur != RLIM_INFINITY && lim.rlim_cur > MAXSSIZ32)
+ lim.rlim_cur = MAXSSIZ32;
+ lim.rlim_max = p->p_rlimit[RLIMIT_STACK].rlim_max;
+ if (lim.rlim_max != RLIM_INFINITY && lim.rlim_max > MAXSSIZ32)
+ lim.rlim_max = MAXSSIZ32;
+ dosetrlimit(l, p, RLIMIT_STACK, &lim);
}
int
--bg08WKrSYDhXBjb5--