* The caller is responsible for invoking priv_check() and * mac_vnode_check_chroot() to authorize this operation. */
| 3897 | * mac_vnode_check_chroot() to authorize this operation. |
| 3898 | */ |
| 3899 | int |
| 3900 | pwd_chroot(struct thread *td, struct vnode *vp) |
| 3901 | { |
| 3902 | struct pwddesc *pdp; |
| 3903 | struct filedesc *fdp; |
| 3904 | struct pwd *newpwd, *oldpwd; |
| 3905 | int error; |
| 3906 | |
| 3907 | fdp = td->td_proc->p_fd; |
| 3908 | pdp = td->td_proc->p_pd; |
| 3909 | newpwd = pwd_alloc(); |
| 3910 | FILEDESC_SLOCK(fdp); |
| 3911 | PWDDESC_XLOCK(pdp); |
| 3912 | #pragma GCC diagnostic ignored "-Wcast-qual" |
| 3913 | oldpwd = PWDDESC_XLOCKED_LOAD_PWD(pdp); |
| 3914 | #pragma GCC diagnostic error "-Wcast-qual" |
| 3915 | if (chroot_allow_open_directories == 0 || |
| 3916 | (chroot_allow_open_directories == 1 && |
| 3917 | oldpwd->pwd_rdir != rootvnode)) { |
| 3918 | error = chroot_refuse_vdir_fds(fdp); |
| 3919 | FILEDESC_SUNLOCK(fdp); |
| 3920 | if (error != 0) { |
| 3921 | PWDDESC_XUNLOCK(pdp); |
| 3922 | pwd_drop(newpwd); |
| 3923 | return (error); |
| 3924 | } |
| 3925 | } else { |
| 3926 | FILEDESC_SUNLOCK(fdp); |
| 3927 | } |
| 3928 | |
| 3929 | vrefact(vp); |
| 3930 | newpwd->pwd_rdir = vp; |
| 3931 | if (oldpwd->pwd_jdir == NULL) { |
| 3932 | vrefact(vp); |
| 3933 | newpwd->pwd_jdir = vp; |
| 3934 | } |
| 3935 | pwd_fill(oldpwd, newpwd); |
| 3936 | pwd_set(pdp, newpwd); |
| 3937 | PWDDESC_XUNLOCK(pdp); |
| 3938 | pwd_drop(oldpwd); |
| 3939 | return (0); |
| 3940 | } |
| 3941 | |
| 3942 | void |
| 3943 | pwd_chdir(struct thread *td, struct vnode *vp) |
no test coverage detected