Unbreak handling of descriptors opened with O_EXEC by fexecve(2).

While here return EBADF for descriptors opened for writing (previously it was ETXTBSY).

Add fgetvp_exec function which performs appropriate checks.

PR:		kern/169651
In collaboration with:	kib
Approved by:	trasz (mentor)
MFC after:	1 week
This commit is contained in:
Mateusz Guzik 2012-07-08 00:51:38 +00:00
parent 7027e4dac4
commit 28a7f60741
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=238220
3 changed files with 15 additions and 4 deletions

View File

@ -2340,11 +2340,11 @@ _fget(struct thread *td, int fd, struct file **fpp, int flags,
/*
* FREAD and FWRITE failure return EBADF as per POSIX.
*
* Only one flag, or 0, may be specified.
*/
if ((flags == FREAD && (fp->f_flag & FREAD) == 0) ||
(flags == FWRITE && (fp->f_flag & FWRITE) == 0)) {
(flags == FWRITE && (fp->f_flag & FWRITE) == 0) ||
(flags == (FREAD | FEXEC) &&
(((fp->f_flag & flags) == 0) || ((fp->f_flag & FWRITE) != 0)))) {
fdrop(fp, td);
return (EBADF);
}
@ -2444,6 +2444,13 @@ fgetvp_read(struct thread *td, int fd, cap_rights_t rights, struct vnode **vpp)
return (_fgetvp(td, fd, FREAD, rights, NULL, vpp));
}
int
fgetvp_exec(struct thread *td, int fd, cap_rights_t rights, struct vnode **vpp)
{
return (_fgetvp(td, fd, FREAD | FEXEC, rights, NULL, vpp));
}
#ifdef notyet
int
fgetvp_write(struct thread *td, int fd, cap_rights_t rights,

View File

@ -443,8 +443,10 @@ do_execve(td, args, mac_p)
/*
* Some might argue that CAP_READ and/or CAP_MMAP should also
* be required here; such arguments will be entertained.
*
* Descriptors opened only with O_EXEC or O_RDONLY are allowed.
*/
error = fgetvp_read(td, args->fd, CAP_FEXECVE, &binvp);
error = fgetvp_exec(td, args->fd, CAP_FEXECVE, &binvp);
if (error)
goto exec_fail;
vfslocked = VFS_LOCK_GIANT(binvp->v_mount);

View File

@ -238,6 +238,8 @@ fo_chown_t invfo_chown;
void finit(struct file *, u_int, short, void *, struct fileops *);
int fgetvp(struct thread *td, int fd, cap_rights_t rights, struct vnode **vpp);
int fgetvp_exec(struct thread *td, int fd, cap_rights_t rights,
struct vnode **vpp);
int fgetvp_rights(struct thread *td, int fd, cap_rights_t need,
cap_rights_t *have, struct vnode **vpp);
int fgetvp_read(struct thread *td, int fd, cap_rights_t rights,