From 72f12c5b169c9e2ced2572c79bfb7f1bf7fca70c Mon Sep 17 00:00:00 2001 From: Alex Hornung Date: Sat, 26 Jun 2010 22:34:28 +0100 Subject: [PATCH] chroot_kernel() - new syscall to set rootnch/rootvn * This new syscall can be used to override the default rootnch and rootvnode which are used for path lookups outside of a process context (i.e. in kernel-only context) --- include/unistd.h | 1 + sys/kern/init_sysent.c | 1 + sys/kern/syscalls.c | 1 + sys/kern/syscalls.master | 1 + sys/kern/vfs_syscalls.c | 42 ++++++++++++++++++++++++++++++++++++++++ sys/sys/syscall-hide.h | 1 + sys/sys/syscall.h | 3 ++- sys/sys/syscall.mk | 3 ++- sys/sys/sysproto.h | 7 +++++++ sys/sys/sysunion.h | 1 + 10 files changed, 59 insertions(+), 2 deletions(-) diff --git a/include/unistd.h b/include/unistd.h index db7ae7ebb8..d864fb7497 100644 --- a/include/unistd.h +++ b/include/unistd.h @@ -469,6 +469,7 @@ void sync(void); #if (__XSI_VISIBLE && __XSI_VISIBLE <= 500) || __BSD_VISIBLE int brk(const void *); int chroot(const char *); +int chroot_kernel(const char *); int getdtablesize(void); int getpagesize(void) __pure2; char *getpass(const char *); diff --git a/sys/kern/init_sysent.c b/sys/kern/init_sysent.c index 089c558d79..f186de105b 100644 --- a/sys/kern/init_sysent.c +++ b/sys/kern/init_sysent.c @@ -555,4 +555,5 @@ struct sysent sysent[] = { { AS(mq_timedreceive_args), (sy_call_t *)sys_mq_timedreceive }, /* 519 = mq_timedreceive */ { AS(ioprio_set_args), (sy_call_t *)sys_ioprio_set }, /* 520 = ioprio_set */ { AS(ioprio_get_args), (sy_call_t *)sys_ioprio_get }, /* 521 = ioprio_get */ + { AS(chroot_kernel_args), (sy_call_t *)sys_chroot_kernel }, /* 522 = chroot_kernel */ }; diff --git a/sys/kern/syscalls.c b/sys/kern/syscalls.c index a2bbb29df6..42d6c83c36 100644 --- a/sys/kern/syscalls.c +++ b/sys/kern/syscalls.c @@ -529,4 +529,5 @@ const char *syscallnames[] = { "mq_timedreceive", /* 519 = mq_timedreceive */ "ioprio_set", /* 520 = ioprio_set */ "ioprio_get", /* 521 = ioprio_get */ + "chroot_kernel", /* 522 = chroot_kernel */ }; diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master index 4977a5faa6..591bcef77e 100644 --- a/sys/kern/syscalls.master +++ b/sys/kern/syscalls.master @@ -731,3 +731,4 @@ const struct timespec *abs_timeout); } 520 STD BSD { int ioprio_set(int which, int who, int prio); } 521 STD BSD { int ioprio_get(int which, int who); } +522 STD BSD { int chroot_kernel(char *path); } diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 20807c7310..05733c7c66 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -1752,6 +1752,48 @@ sys_chroot(struct chroot_args *uap) return(error); } +int +sys_chroot_kernel(struct chroot_kernel_args *uap) +{ + struct thread *td = curthread; + struct nlookupdata nd; + struct nchandle *nch; + struct vnode *vp; + int error; + + get_mplock(); + error = nlookup_init(&nd, uap->path, UIO_USERSPACE, NLC_FOLLOW); + if (error) + goto error_nond; + + error = nlookup(&nd); + if (error) + goto error_out; + + nch = &nd.nl_nch; + + error = priv_check_cred(td->td_ucred, PRIV_VFS_CHROOT, 0); + if (error) + goto error_out; + + if ((vp = nch->ncp->nc_vp) == NULL) { + error = ENOENT; + goto error_out; + } + + if ((error = cache_vref(nch, nd.nl_cred, &vp)) != 0) + goto error_out; + + kprintf("chroot_kernel: set new rootnch/rootvnode to %s\n", uap->path); + vfs_cache_setroot(vp, cache_hold(nch)); + +error_out: + nlookup_done(&nd); +error_nond: + rel_mplock(); + return(error); +} + /* * Common routine for chroot and chdir. Given a locked, referenced vnode, * determine whether it is legal to chdir to the vnode. The vnode's state diff --git a/sys/sys/syscall-hide.h b/sys/sys/syscall-hide.h index a0ec77dbdd..06071954b6 100644 --- a/sys/sys/syscall-hide.h +++ b/sys/sys/syscall-hide.h @@ -352,3 +352,4 @@ HIDE_POSIX(mq_timedsend) HIDE_POSIX(mq_timedreceive) HIDE_BSD(ioprio_set) HIDE_BSD(ioprio_get) +HIDE_BSD(chroot_kernel) diff --git a/sys/sys/syscall.h b/sys/sys/syscall.h index ce21144f4d..b121f6e227 100644 --- a/sys/sys/syscall.h +++ b/sys/sys/syscall.h @@ -361,4 +361,5 @@ #define SYS_mq_timedreceive 519 #define SYS_ioprio_set 520 #define SYS_ioprio_get 521 -#define SYS_MAXSYSCALL 522 +#define SYS_chroot_kernel 522 +#define SYS_MAXSYSCALL 523 diff --git a/sys/sys/syscall.mk b/sys/sys/syscall.mk index a06739b1d0..4103f665da 100644 --- a/sys/sys/syscall.mk +++ b/sys/sys/syscall.mk @@ -300,4 +300,5 @@ MIASM = \ mq_timedsend.o \ mq_timedreceive.o \ ioprio_set.o \ - ioprio_get.o + ioprio_get.o \ + chroot_kernel.o diff --git a/sys/sys/sysproto.h b/sys/sys/sysproto.h index 4c3f31f1e9..6b365aff83 100644 --- a/sys/sys/sysproto.h +++ b/sys/sys/sysproto.h @@ -2295,6 +2295,12 @@ struct ioprio_get_args { int which; char which_[PAD_(int)]; int who; char who_[PAD_(int)]; }; +struct chroot_kernel_args { +#ifdef _KERNEL + struct sysmsg sysmsg; +#endif + char * path; char path_[PAD_(char *)]; +}; #ifdef COMPAT_43 @@ -2903,6 +2909,7 @@ int sys_mq_timedsend (struct mq_timedsend_args *); int sys_mq_timedreceive (struct mq_timedreceive_args *); int sys_ioprio_set (struct ioprio_set_args *); int sys_ioprio_get (struct ioprio_get_args *); +int sys_chroot_kernel (struct chroot_kernel_args *); #endif /* !_SYS_SYSPROTO_H_ */ #undef PAD_ diff --git a/sys/sys/sysunion.h b/sys/sys/sysunion.h index af303c182e..374ee3c482 100644 --- a/sys/sys/sysunion.h +++ b/sys/sys/sysunion.h @@ -408,4 +408,5 @@ union sysunion { struct mq_timedreceive_args mq_timedreceive; struct ioprio_set_args ioprio_set; struct ioprio_get_args ioprio_get; + struct chroot_kernel_args chroot_kernel; }; -- 2.41.0