Improve nested jail awareness of devfs by handling credentials.

Now that we start to use credentials on character devices more often
(because of MPSAFE TTY), move the prison-checks that are in place in the
TTY code into devfs.

Instead of strictly comparing the prisons, use the more common
prison_check() function to compare credentials. This means that
pseudo-terminals are only visible in devfs by processes within the same
jail and parent jails.

Even though regular users in parent jails can now interact with
pseudo-terminals from child jails, this seems to be the right approach.
These processes are also capable of interacting with the jailed
processes anyway, through signals for example.

Reviewed by:	kib, rwatson (older version)
This commit is contained in:
Ed Schouten 2009-06-20 14:50:32 +00:00
parent 6c3154f6a1
commit f8f6146082
3 changed files with 22 additions and 8 deletions

View file

@ -48,6 +48,7 @@
#include <sys/file.h>
#include <sys/filedesc.h>
#include <sys/filio.h>
#include <sys/jail.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/malloc.h>
@ -706,6 +707,22 @@ devfs_kqfilter_f(struct file *fp, struct knote *kn)
return (error);
}
static inline int
devfs_prison_check(struct devfs_dirent *de, struct ucred *tcr)
{
struct cdev_priv *cdp;
struct ucred *dcr;
cdp = de->de_cdp;
if (cdp == NULL)
return (0);
dcr = cdp->cdp_c.si_cred;
if (dcr == NULL)
return (0);
return (prison_check(tcr, dcr));
}
static int
devfs_lookupx(struct vop_lookup_args *ap, int *dm_unlock)
{
@ -831,6 +848,9 @@ devfs_lookupx(struct vop_lookup_args *ap, int *dm_unlock)
return (ENOENT);
}
if (devfs_prison_check(de, td->td_ucred))
return (ENOENT);
if ((cnp->cn_nameiop == DELETE) && (flags & ISLASTCN)) {
error = VOP_ACCESS(dvp, VWRITE, cnp->cn_cred, td);
if (error)
@ -1106,6 +1126,8 @@ devfs_readdir(struct vop_readdir_args *ap)
KASSERT(dd->de_cdp != (void *)0xdeadc0de, ("%s %d\n", __func__, __LINE__));
if (dd->de_flags & DE_WHITEOUT)
continue;
if (devfs_prison_check(dd, ap->a_cred))
continue;
if (dd->de_dirent->d_type == DT_DIR)
de = dd->de_dir;
else

View file

@ -219,13 +219,6 @@ ttydev_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
struct tty *tp = dev->si_drv1;
int error = 0;
/* Disallow access when the TTY belongs to a different prison. */
if (dev->si_cred != NULL &&
dev->si_cred->cr_prison != td->td_ucred->cr_prison &&
priv_check(td, PRIV_TTY_PRISON)) {
return (EPERM);
}
tty_lock(tp);
if (tty_gone(tp)) {
/* Device is already gone. */

View file

@ -211,7 +211,6 @@
#define PRIV_TTY_DRAINWAIT 251 /* Set tty drain wait time. */
#define PRIV_TTY_DTRWAIT 252 /* Set DTR wait on tty. */
#define PRIV_TTY_EXCLUSIVE 253 /* Override tty exclusive flag. */
#define PRIV_TTY_PRISON 254 /* Can open pts across jails. */
#define PRIV_TTY_STI 255 /* Simulate input on another tty. */
#define PRIV_TTY_SETA 256 /* Set tty termios structure. */