* jail_attach(2) changes both root and working directories. */
| 3964 | * jail_attach(2) changes both root and working directories. |
| 3965 | */ |
| 3966 | int |
| 3967 | pwd_chroot_chdir(struct thread *td, struct vnode *vp) |
| 3968 | { |
| 3969 | struct pwddesc *pdp; |
| 3970 | struct filedesc *fdp; |
| 3971 | struct pwd *newpwd, *oldpwd; |
| 3972 | int error; |
| 3973 | |
| 3974 | fdp = td->td_proc->p_fd; |
| 3975 | pdp = td->td_proc->p_pd; |
| 3976 | newpwd = pwd_alloc(); |
| 3977 | FILEDESC_SLOCK(fdp); |
| 3978 | PWDDESC_XLOCK(pdp); |
| 3979 | #pragma GCC diagnostic ignored "-Wcast-qual" |
| 3980 | oldpwd = PWDDESC_XLOCKED_LOAD_PWD(pdp); |
| 3981 | #pragma GCC diagnostic error "-Wcast-qual" |
| 3982 | error = chroot_refuse_vdir_fds(fdp); |
| 3983 | FILEDESC_SUNLOCK(fdp); |
| 3984 | if (error != 0) { |
| 3985 | PWDDESC_XUNLOCK(pdp); |
| 3986 | pwd_drop(newpwd); |
| 3987 | return (error); |
| 3988 | } |
| 3989 | |
| 3990 | vrefact(vp); |
| 3991 | newpwd->pwd_rdir = vp; |
| 3992 | vrefact(vp); |
| 3993 | newpwd->pwd_cdir = vp; |
| 3994 | if (oldpwd->pwd_jdir == NULL) { |
| 3995 | vrefact(vp); |
| 3996 | newpwd->pwd_jdir = vp; |
| 3997 | } |
| 3998 | pwd_fill(oldpwd, newpwd); |
| 3999 | pwd_set(pdp, newpwd); |
| 4000 | PWDDESC_XUNLOCK(pdp); |
| 4001 | pwd_drop(oldpwd); |
| 4002 | return (0); |
| 4003 | } |
| 4004 | |
| 4005 | void |
| 4006 | pwd_ensure_dirs(void) |
no test coverage detected