@@ -967,18 +967,13 @@ static int unprivileged_chroot = 0;
967967SYSCTL_INT (_security_bsd , OID_AUTO , unprivileged_chroot , CTLFLAG_RW ,
968968 & unprivileged_chroot , 0 ,
969969 "Unprivileged processes can use chroot(2)" );
970+
970971/*
971- * Change notion of root (``/'') directory .
972+ * Takes locked vnode, unlocks it before returning .
972973 */
973- #ifndef _SYS_SYSPROTO_H_
974- struct chroot_args {
975- char * path ;
976- };
977- #endif
978- int
979- sys_chroot (struct thread * td , struct chroot_args * uap )
974+ static int
975+ kern_chroot (struct thread * td , struct vnode * vp )
980976{
981- struct nameidata nd ;
982977 struct proc * p ;
983978 int error ;
984979
@@ -989,30 +984,75 @@ sys_chroot(struct thread *td, struct chroot_args *uap)
989984 if (unprivileged_chroot == 0 ||
990985 (p -> p_flag2 & P2_NO_NEW_PRIVS ) == 0 ) {
991986 PROC_UNLOCK (p );
992- return ( error ) ;
987+ goto e_vunlock ;
993988 }
994989 PROC_UNLOCK (p );
995990 }
996- NDINIT (& nd , LOOKUP , FOLLOW | LOCKSHARED | LOCKLEAF | AUDITVNODE1 ,
997- UIO_USERSPACE , uap -> path );
998- error = namei (& nd );
999- if (error != 0 )
1000- return (error );
1001- NDFREE_PNBUF (& nd );
1002- error = change_dir (nd .ni_vp , td );
991+
992+ error = change_dir (vp , td );
1003993 if (error != 0 )
1004994 goto e_vunlock ;
1005995#ifdef MAC
1006- error = mac_vnode_check_chroot (td -> td_ucred , nd . ni_vp );
996+ error = mac_vnode_check_chroot (td -> td_ucred , vp );
1007997 if (error != 0 )
1008998 goto e_vunlock ;
1009999#endif
1010- VOP_UNLOCK (nd . ni_vp );
1011- error = pwd_chroot (td , nd . ni_vp );
1012- vrele (nd . ni_vp );
1000+ VOP_UNLOCK (vp );
1001+ error = pwd_chroot (td , vp );
1002+ vrele (vp );
10131003 return (error );
10141004e_vunlock :
1015- vput (nd .ni_vp );
1005+ vput (vp );
1006+ return (error );
1007+ }
1008+
1009+ /*
1010+ * Change notion of root (``/'') directory.
1011+ */
1012+ #ifndef _SYS_SYSPROTO_H_
1013+ struct chroot_args {
1014+ char * path ;
1015+ };
1016+ #endif
1017+ int
1018+ sys_chroot (struct thread * td , struct chroot_args * uap )
1019+ {
1020+ struct nameidata nd ;
1021+ int error ;
1022+
1023+ NDINIT (& nd , LOOKUP , FOLLOW | LOCKSHARED | LOCKLEAF | AUDITVNODE1 ,
1024+ UIO_USERSPACE , uap -> path );
1025+ error = namei (& nd );
1026+ if (error != 0 )
1027+ return (error );
1028+ NDFREE_PNBUF (& nd );
1029+ error = kern_chroot (td , nd .ni_vp );
1030+ return (error );
1031+ }
1032+
1033+ /*
1034+ * Change notion of root directory to a given file descriptor.
1035+ */
1036+ #ifndef _SYS_SYSPROTO_H_
1037+ struct fchroot_args {
1038+ int fd ;
1039+ };
1040+ #endif
1041+ int
1042+ sys_fchroot (struct thread * td , struct fchroot_args * uap )
1043+ {
1044+ struct vnode * vp ;
1045+ struct file * fp ;
1046+ int error ;
1047+
1048+ error = getvnode_path (td , uap -> fd , & cap_fchroot_rights , & fp );
1049+ if (error != 0 )
1050+ return (error );
1051+ vp = fp -> f_vnode ;
1052+ vrefact (vp );
1053+ fdrop (fp , td );
1054+ vn_lock (vp , LK_SHARED | LK_RETRY );
1055+ error = kern_chroot (td , vp );
10161056 return (error );
10171057}
10181058
0 commit comments