From owner-p4-projects@FreeBSD.ORG Tue Jul 3 12:50:02 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 0B34416A469; Tue, 3 Jul 2007 12:50:02 +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 BECF216A400 for ; Tue, 3 Jul 2007 12:50:01 +0000 (UTC) (envelope-from rdivacky@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [69.147.83.41]) by mx1.freebsd.org (Postfix) with ESMTP id ABBCE13C469 for ; Tue, 3 Jul 2007 12:50:01 +0000 (UTC) (envelope-from rdivacky@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 l63Co1jY052527 for ; Tue, 3 Jul 2007 12:50:01 GMT (envelope-from rdivacky@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.8/8.13.8/Submit) id l63Co1fP052522 for perforce@freebsd.org; Tue, 3 Jul 2007 12:50:01 GMT (envelope-from rdivacky@FreeBSD.org) Date: Tue, 3 Jul 2007 12:50:01 GMT Message-Id: <200707031250.l63Co1fP052522@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to rdivacky@FreeBSD.org using -f From: Roman Divacky To: Perforce Change Reviews Cc: Subject: PERFORCE change 122771 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: Tue, 03 Jul 2007 12:50:02 -0000 http://perforce.freebsd.org/chv.cgi?CH=122771 Change 122771 by rdivacky@rdivacky_witten on 2007/07/03 12:49:29 Mostly backup previous commit and reimplement it. Introduce fgetvp_exec which returns a vnode if a file was opened with either FREAD or FEXEC and use this in do_execve(). This way we should be able to prevent some races introduced by dropping locks. Insisted upon by: kib Affected files ... .. //depot/projects/soc2007/rdivacky/linux_at/sys/kern/imgact_elf.c#4 edit .. //depot/projects/soc2007/rdivacky/linux_at/sys/kern/kern_descrip.c#4 edit .. //depot/projects/soc2007/rdivacky/linux_at/sys/kern/kern_exec.c#12 edit .. //depot/projects/soc2007/rdivacky/linux_at/sys/sys/fcntl.h#9 edit .. //depot/projects/soc2007/rdivacky/linux_at/sys/sys/file.h#2 edit .. //depot/projects/soc2007/rdivacky/linux_at/sys/sys/imgact.h#4 edit Differences ... ==== //depot/projects/soc2007/rdivacky/linux_at/sys/kern/imgact_elf.c#4 (text+ko) ==== @@ -512,7 +512,7 @@ /* * Check permissions, modes, uid, etc on the file, and "open" it. */ - error = exec_check_permissions(imgp, 0, 0); + error = exec_check_permissions(imgp); if (error) goto fail; ==== //depot/projects/soc2007/rdivacky/linux_at/sys/kern/kern_descrip.c#4 (text+ko) ==== @@ -1969,6 +1969,10 @@ FILEDESC_SUNLOCK(fdp); return (EBADF); } + if (flags == FEXEC && (fp->f_flag & FREAD) == 0 && (fp->f_flag & FEXEC) == 0) { + FILEDESC_SUNLOCK(fdp); + return (EBADF); + } if (hold) { fhold(fp); FILEDESC_SUNLOCK(fdp); @@ -2047,6 +2051,29 @@ } #endif + +/* Gets a vnode if file was opened with either FREAD or FEXEC flag. */ +int +fgetvp_exec(struct thread *td, int fd, struct vnode **vpp) +{ + struct file *fp; + int error; + + *vpp = NULL; + + if ((error = _fget(td, fd, &fp, FEXEC, 0)) != 0) + return (error); + if (fp->f_vnode == NULL) { + error = EINVAL; + } else { + *vpp = fp->f_vnode; + vref(*vpp); + } + FILEDESC_SUNLOCK(td->td_proc->p_fd); + + return (0); +} + /* * Like fget() but loads the underlying socket, or returns an error if the * descriptor does not represent a socket. ==== //depot/projects/soc2007/rdivacky/linux_at/sys/kern/kern_exec.c#12 (text+ko) ==== @@ -391,7 +391,7 @@ binvp = ndp->ni_vp; imgp->vp = binvp; } else { - error = fgetvp(td, args->fd, &binvp); + error = fgetvp_exec(td, args->fd, &binvp); if (error) goto exec_fail; vfslocked = VFS_LOCK_GIANT(binvp->v_mount); @@ -402,7 +402,7 @@ /* * Check file permissions (also 'opens' file) */ - error = exec_check_permissions(imgp, args->fname == NULL, args->fd); + error = exec_check_permissions(imgp); if (error) goto exec_fail_dealloc; @@ -1226,10 +1226,8 @@ * Return 0 for success or error code on failure. */ int -exec_check_permissions(imgp, fexecve, fd) +exec_check_permissions(imgp) struct image_params *imgp; - int fexecve; - int fd; { struct vnode *vp = imgp->vp; struct vattr *attr = imgp->attr; @@ -1283,27 +1281,6 @@ return (ETXTBSY); /* - * Check for the mode the file was opened with - */ - if (fexecve) { - struct file f; - struct file *fp = &f; - - FILEDESC_SLOCK(td->td_proc->p_fd); - fp = fget_locked(td->td_proc->p_fd, fd); - if (fp == NULL || fp->f_ops == &badfileops) { - FILEDESC_SUNLOCK(td->td_proc->p_fd); - return (EBADF); - } - fhold(fp); - FILEDESC_SUNLOCK(td->td_proc->p_fd); - if (!(fp->f_flag & FREAD) && !(fp->f_flag & O_EXEC)) { - fdrop(fp, td); - return (EACCES); - } - fdrop(fp, td); - } - /* * Call filesystem specific open routine (which does nothing in the * general case). */ ==== //depot/projects/soc2007/rdivacky/linux_at/sys/sys/fcntl.h#9 (text+ko) ==== @@ -104,6 +104,7 @@ #define FHASLOCK 0x4000 /* descriptor holds advisory lock */ #endif #define O_EXEC 0x8000 /* open for execute only */ +#define FEXEC 0x8000 /* Defined by POSIX Extended API ... TODO: number of the spec */ #define AT_FDCWD -100 /* Use the current working directory to determine the target of relative @@ -135,7 +136,7 @@ #define OFLAGS(fflags) ((fflags) - 1) /* bits to save after open */ -#define FMASK (FREAD|FWRITE|FAPPEND|FASYNC|FFSYNC|FNONBLOCK|O_DIRECT|O_EXEC) +#define FMASK (FREAD|FWRITE|FAPPEND|FASYNC|FFSYNC|FNONBLOCK|O_DIRECT|FEXEC) /* bits settable by fcntl(F_SETFL, ...) */ #define FCNTLFLAGS (FAPPEND|FASYNC|FFSYNC|FNONBLOCK|FPOSIXSHM|O_DIRECT) #endif ==== //depot/projects/soc2007/rdivacky/linux_at/sys/sys/file.h#2 (text+ko) ==== @@ -205,6 +205,7 @@ int fgetvp(struct thread *td, int fd, struct vnode **vpp); int fgetvp_read(struct thread *td, int fd, struct vnode **vpp); int fgetvp_write(struct thread *td, int fd, struct vnode **vpp); +int fgetvp_exec(struct thread *td, int fd, struct vnode **vpp); int fgetsock(struct thread *td, int fd, struct socket **spp, u_int *fflagp); void fputsock(struct socket *sp); ==== //depot/projects/soc2007/rdivacky/linux_at/sys/sys/imgact.h#4 (text+ko) ==== @@ -71,7 +71,7 @@ struct sysentvec; struct thread; -int exec_check_permissions(struct image_params *, int fexecve, int fd); +int exec_check_permissions(struct image_params *); register_t *exec_copyout_strings(struct image_params *); int exec_new_vmspace(struct image_params *, struct sysentvec *); void exec_setregs(struct thread *, u_long, u_long, u_long);