Skip to content

Commit

Permalink
When a process, such as jexec(8) or killall(1), calls jail_attach(2)
Browse files Browse the repository at this point in the history
to enter a jail, the jailed root can attach to it using ptrace(2) before
the current working directory is changed.
  • Loading branch information
laffer1 committed Feb 24, 2021
1 parent c1ddf40 commit d616f4d
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 6 deletions.
5 changes: 4 additions & 1 deletion lib/libc/sys/jail.2
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
.\"
.\" $FreeBSD: stable/11/lib/libc/sys/jail.2 300983 2016-05-30 05:21:24Z jamie $
.\"
.Dd February 8, 2012
.Dd February 19, 2021
.Dt JAIL 2
.Os
.Sh NAME
Expand Down Expand Up @@ -228,6 +228,9 @@ The
system call attaches the current process to an existing jail,
identified by
.Fa jid .
It changes the process's root and current directories to the jail's
.Va path
directory.
.Pp
The
.Fn jail_remove
Expand Down
40 changes: 36 additions & 4 deletions sys/kern/kern_descrip.c
Original file line number Diff line number Diff line change
Expand Up @@ -3052,10 +3052,9 @@ chroot_refuse_vdir_fds(struct filedesc *fdp)
}

/*
* Common routine for kern_chroot() and jail_attach(). The caller is
* responsible for invoking priv_check() and mac_vnode_check_chroot() to
* authorize this operation.
*/
* The caller is responsible for invoking priv_check() and
* mac_vnode_check_chroot() to authorize this operation.
*/
int
pwd_chroot(struct thread *td, struct vnode *vp)
{
Expand Down Expand Up @@ -3101,6 +3100,39 @@ pwd_chdir(struct thread *td, struct vnode *vp)
vrele(oldvp);
}

/*
* jail_attach(2) changes both root and working directories.
*/
int
pwd_chroot_chdir(struct thread *td, struct vnode *vp)
{
struct filedesc *fdp;
struct vnode *oldvrp, *oldvcp;
int error;

fdp = td->td_proc->p_fd;
FILEDESC_XLOCK(fdp);
error = chroot_refuse_vdir_fds(fdp);
if (error != 0) {
FILEDESC_XUNLOCK(fdp);
return (error);
}
oldvrp = fdp->fd_rdir;
vrefact(vp);
fdp->fd_rdir = vp;
oldvcp = fdp->fd_cdir;
vrefact(vp);
fdp->fd_cdir = vp;
if (fdp->fd_jdir == NULL) {
vrefact(vp);
fdp->fd_jdir = vp;
}
FILEDESC_XUNLOCK(fdp);
vrele(oldvrp);
vrele(oldvcp);
return (0);
}

/*
* Scan all active processes and prisons to see if any of them have a current
* or root directory of `olddp'. If so, replace them with the new mount point.
Expand Down
2 changes: 1 addition & 1 deletion sys/kern/kern_jail.c
Original file line number Diff line number Diff line change
Expand Up @@ -2418,7 +2418,7 @@ do_jail_attach(struct thread *td, struct prison *pr)
goto e_unlock;
#endif
VOP_UNLOCK(pr->pr_root, 0);
if ((error = pwd_chroot(td, pr->pr_root)))
if ((error = pwd_chroot_chdir(td, pr->pr_root)))
goto e_revert_osd;

newcred = crget();
Expand Down
1 change: 1 addition & 0 deletions sys/sys/filedesc.h
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ fd_modified(struct filedesc *fdp, int fd, seq_t seq)
/* cdir/rdir/jdir manipulation functions. */
void pwd_chdir(struct thread *td, struct vnode *vp);
int pwd_chroot(struct thread *td, struct vnode *vp);
int pwd_chroot_chdir(struct thread *td, struct vnode *vp);
void pwd_ensure_dirs(void);

#endif /* _KERNEL */
Expand Down

0 comments on commit d616f4d

Please sign in to comment.