From owner-p4-projects@FreeBSD.ORG Mon May 14 21:51:34 2007 Return-Path: X-Original-To: p4-projects@freebsd.org Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 66A4D16A468; Mon, 14 May 2007 21:51:34 +0000 (UTC) X-Original-To: perforce@freebsd.org Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 43A0516A403 for ; Mon, 14 May 2007 21:51:34 +0000 (UTC) (envelope-from jhb@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [69.147.83.41]) by mx1.freebsd.org (Postfix) with ESMTP id 2D62313C447 for ; Mon, 14 May 2007 21:51:34 +0000 (UTC) (envelope-from jhb@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.8/8.13.8) with ESMTP id l4ELpY6A068232 for ; Mon, 14 May 2007 21:51:34 GMT (envelope-from jhb@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.8/8.13.8/Submit) id l4ELpXvP068210 for perforce@freebsd.org; Mon, 14 May 2007 21:51:33 GMT (envelope-from jhb@freebsd.org) Date: Mon, 14 May 2007 21:51:33 GMT Message-Id: <200705142151.l4ELpXvP068210@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to jhb@freebsd.org using -f From: John Baldwin To: Perforce Change Reviews Cc: Subject: PERFORCE change 119857 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 14 May 2007 21:51:34 -0000 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 -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