PERFORCE change 119857 for review
John Baldwin
jhb at FreeBSD.org
Mon May 14 21:51:34 UTC 2007
http://perforce.freebsd.org/chv.cgi?CH=119857
Change 119857 by jhb at 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
More information about the p4-projects
mailing list