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