When we are execing a setugid program, and we have a procfs filesystem

file open in one of the special file descriptors (0, 1, or 2), close
it before completing the exec.

Submitted by: nergal@idea.avet.com.pl
Constructive comments: deraadt@openbsd.org, sef, peter, jkh
This commit is contained in:
Warner Losh 2000-01-20 07:12:52 +00:00
parent 1a601bedea
commit 5e2664428c
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=56313
3 changed files with 61 additions and 0 deletions

View File

@ -40,6 +40,7 @@
*/ */
#include "opt_compat.h" #include "opt_compat.h"
#include "opt_dontuse.h"
#include <sys/param.h> #include <sys/param.h>
#include <sys/systm.h> #include <sys/systm.h>
#include <sys/sysproto.h> #include <sys/sysproto.h>
@ -936,6 +937,64 @@ fdfree(p)
FREE(fdp, M_FILEDESC); FREE(fdp, M_FILEDESC);
} }
/*
* For setuid/setgid programs we don't want to people to use that setuidness
* to generate error messages which write to a file which otherwise would
* otherwise be off limits to the proces.
*
* This is a gross hack to plug the hole. A better solution would involve
* a special vop or other form of generalized access control mechanism. We
* go ahead and just reject all procfs file systems accesses as dangerous.
*
* Since setugidsafety calls this only for fd 0, 1 and 2, this check is
* sufficient. We also don't for setugidness since we know we are.
*/
static int
is_unsafe(struct file *fp)
{
#if PROCFS
if (fp->f_type == DTYPE_VNODE &&
((struct vnode *)(fp->f_data))->v_tag == VT_PROCFS)
return (1);
#endif
return (0);
}
/*
* Make this setguid thing safe, if at all possible.
*/
void
setugidsafety(p)
struct proc *p;
{
struct filedesc *fdp = p->p_fd;
struct file **fpp;
char *fdfp;
register int i;
/* Certain daemons might not have file descriptors. */
if (fdp == NULL)
return;
fpp = fdp->fd_ofiles;
fdfp = fdp->fd_ofileflags;
for (i = 0; i <= fdp->fd_lastfile; i++, fpp++, fdfp++) {
if (i > 2)
break;
if (*fpp != NULL && is_unsafe(*fpp)) {
if (*fdfp & UF_MAPPED)
(void) munmapfd(p, i);
(void) closef(*fpp, p);
*fpp = NULL;
*fdfp = 0;
if (i < fdp->fd_freefile)
fdp->fd_freefile = i;
}
}
while (fdp->fd_lastfile > 0 && fdp->fd_ofiles[fdp->fd_lastfile] == NULL)
fdp->fd_lastfile--;
}
/* /*
* Close any files on exec? * Close any files on exec?
*/ */

View File

@ -289,6 +289,7 @@ interpret:
if (attr.va_mode & VSGID) if (attr.va_mode & VSGID)
p->p_ucred->cr_gid = attr.va_gid; p->p_ucred->cr_gid = attr.va_gid;
setsugid(p); setsugid(p);
setugidsafety(p);
} else { } else {
if (p->p_ucred->cr_uid == p->p_cred->p_ruid && if (p->p_ucred->cr_uid == p->p_cred->p_ruid &&
p->p_ucred->cr_gid == p->p_cred->p_rgid) p->p_ucred->cr_gid == p->p_cred->p_rgid)

View File

@ -140,6 +140,7 @@ pid_t fgetown __P((struct sigio *));
int fsetown __P((pid_t, struct sigio **)); int fsetown __P((pid_t, struct sigio **));
void funsetown __P((struct sigio *)); void funsetown __P((struct sigio *));
void funsetownlst __P((struct sigiolst *)); void funsetownlst __P((struct sigiolst *));
void setugidsafety __P((struct proc *p));
#endif #endif
#endif #endif