PERFORCE change 122771 for review

Roman Divacky rdivacky at FreeBSD.org
Tue Jul 3 12:50:02 UTC 2007


http://perforce.freebsd.org/chv.cgi?CH=122771

Change 122771 by rdivacky at 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);


More information about the p4-projects mailing list