Page MenuHomeFreeBSD

D60035.1794807474.diff
No OneTemporary

Authored By
Unknown
Size
21 KB
Referenced Files
None
Subscribers
None

D60035.1794807474.diff

diff --git a/include/unistd.h b/include/unistd.h
--- a/include/unistd.h
+++ b/include/unistd.h
@@ -502,6 +502,7 @@
int acct(const char *);
int async_daemon(void);
+int chaltroot(const char *);
int check_utility_compat(const char *);
int close_range(unsigned int, unsigned int, int);
ssize_t copy_file_range(int, off_t *, int, off_t *, size_t, unsigned int);
@@ -517,6 +518,7 @@
int execvpe(const char *, char * const *, char * const *);
int feature_present(const char *);
int fchroot(int);
+int fchaltroot(int);
char *fflagstostr(u_long);
ssize_t freadlink(int fd, char *buf, size_t bufsize);
int getdomainname(char *, int);
diff --git a/lib/libsys/Makefile.sys b/lib/libsys/Makefile.sys
--- a/lib/libsys/Makefile.sys
+++ b/lib/libsys/Makefile.sys
@@ -416,7 +416,9 @@
MLINKS+=chown.2 fchown.2 \
chown.2 fchownat.2 \
chown.2 lchown.2
-MLINKS+=chroot.2 fchroot.2
+MLINKS+=chroot.2 fchroot.2 \
+ chroot.2 chaltroot.2 \
+ chroot.2 fchaltroot.2
MLINKS+=clock_gettime.2 clock_getres.2 \
clock_gettime.2 clock_settime.2
MLINKS+=closefrom.2 close_range.2
diff --git a/lib/libsys/Symbol.sys.map b/lib/libsys/Symbol.sys.map
--- a/lib/libsys/Symbol.sys.map
+++ b/lib/libsys/Symbol.sys.map
@@ -391,6 +391,8 @@
};
FBSD_1.9 {
+ chaltroot;
+ fchaltroot;
kexec_load;
pddupfd;
pdopenpid;
diff --git a/lib/libsys/_libsys.h b/lib/libsys/_libsys.h
--- a/lib/libsys/_libsys.h
+++ b/lib/libsys/_libsys.h
@@ -478,6 +478,8 @@
typedef int (__sys_pdopenpid_t)(pid_t, int);
typedef int (__sys_pddupfd_t)(int, int, int);
typedef int (__sys_pdptrace_t)(int, int, int, void *, int);
+typedef int (__sys_chaltroot_t)(const char *);
+typedef int (__sys_fchaltroot_t)(int);
_Noreturn void __sys__exit(int rval);
int __sys_fork(void);
@@ -891,6 +893,8 @@
int __sys_pdopenpid(pid_t pid, int flags);
int __sys_pddupfd(int pd, int fd, int flags);
int __sys_pdptrace(int req, int pfd, int lwpid, void * addr, int data);
+int __sys_chaltroot(const char * path);
+int __sys_fchaltroot(int fd);
__END_DECLS
#endif /* __LIBSYS_H_ */
diff --git a/lib/libsys/chroot.2 b/lib/libsys/chroot.2
--- a/lib/libsys/chroot.2
+++ b/lib/libsys/chroot.2
@@ -40,6 +40,10 @@
.Fn chroot "const char *dirname"
.Ft int
.Fn fchroot "int fd"
+.Ft int
+.Fn chaltroot "const char *dirname"
+.Ft int
+.Fn fchaltroot "int fd"
.Sh DESCRIPTION
The
.Fa dirname
@@ -61,13 +65,6 @@
.Fn chroot
has no effect on the process's current directory.
.Pp
-This call is restricted to the super-user, unless the
-.Ql Va security.bsd.unprivileged_chroot
-sysctl variable is set to 1
-and the process has enabled the
-.Dv PROC_NO_NEW_PRIVS_CTL
-.Xr procctl 2 .
-.Pp
Depending on the setting of the
.Ql kern.chroot_allow_open_directories
sysctl variable, open file descriptors which reference directories
@@ -106,6 +103,56 @@
system call is identical to
.Fn chroot
except it takes a file descriptor instead of path.
+.Pp
+The
+.Fn chaltroot
+system call sets or changes the 'alternative root' directory.
+If set to existing directory for which the process has the
+executable permissions, that directory is used as a root for
+file name lookups.
+If the lookup succeded, the result is used.
+If the lookup failed, second lookup is initiated with the
+process root directory controlled by the
+.Fn chroot
+call.
+.Pp
+Calling
+.Fn chaltroot
+system call with the
+.Fa path
+argument set to NULL
+disables the alternative root for the process.
+.Pp
+Same as normal root, the alternative root settings are
+inherited by the children processes created by
+.Xr fork 2 ,
+and preserved across images activations on
+.Xr execve 2.
+.Pp
+The alternative root facility is used by ABI emulators to
+provide a parallel installation of the foreigh systems files,
+while still providing the seamless access to the file hierarchy
+of the host system.
+.Pp
+The
+.Fn fchaltroot
+function is similar to
+.Fn chaltroot
+but takes a file descriptor to designate the new alternative root
+instead of the path.
+Calling the
+.Fn fchaltroot
+system call with the
+.Fa fd
+argument of -1 disables the alternative root for the process.
+.Pp
+All functions described in the page are restricted to the super-user,
+unless the
+.Ql Va security.bsd.unprivileged_chroot
+sysctl variable is set to 1
+and the process has enabled the
+.Dv PROC_NO_NEW_PRIVS_CTL
+.Xr procctl 2 .
.Sh RETURN VALUES
.Rv -std
.Sh ERRORS
diff --git a/lib/libsys/syscalls.map b/lib/libsys/syscalls.map
--- a/lib/libsys/syscalls.map
+++ b/lib/libsys/syscalls.map
@@ -831,4 +831,8 @@
__sys_pddupfd;
_pdptrace;
__sys_pdptrace;
+ _chaltroot;
+ __sys_chaltroot;
+ _fchaltroot;
+ __sys_fchaltroot;
};
diff --git a/sys/bsm/audit_kevents.h b/sys/bsm/audit_kevents.h
--- a/sys/bsm/audit_kevents.h
+++ b/sys/bsm/audit_kevents.h
@@ -667,6 +667,7 @@
#define AUE_PDRFORK 43273 /* FreeBSD-specific. */
#define AUE_PDOPENPID 43274 /* FreeBSD-specific. */
#define AUE_PDPTRACE 43275 /* FreeBSD-specific. */
+#define AUE_CHALTROOT 43276 /* FreeBSD-specific. */
/*
* Darwin BSM uses a number of AUE_O_* definitions, which are aliased to the
diff --git a/sys/compat/freebsd32/freebsd32_syscall.h b/sys/compat/freebsd32/freebsd32_syscall.h
--- a/sys/compat/freebsd32/freebsd32_syscall.h
+++ b/sys/compat/freebsd32/freebsd32_syscall.h
@@ -523,4 +523,6 @@
#define FREEBSD32_SYS_pdopenpid 603
#define FREEBSD32_SYS_pddupfd 604
#define FREEBSD32_SYS_freebsd32_pdptrace 605
-#define FREEBSD32_SYS_MAXSYSCALL 606
+#define FREEBSD32_SYS_chaltroot 606
+#define FREEBSD32_SYS_fchaltroot 607
+#define FREEBSD32_SYS_MAXSYSCALL 608
diff --git a/sys/compat/freebsd32/freebsd32_syscalls.c b/sys/compat/freebsd32/freebsd32_syscalls.c
--- a/sys/compat/freebsd32/freebsd32_syscalls.c
+++ b/sys/compat/freebsd32/freebsd32_syscalls.c
@@ -611,4 +611,6 @@
"pdopenpid", /* 603 = pdopenpid */
"pddupfd", /* 604 = pddupfd */
"freebsd32_pdptrace", /* 605 = freebsd32_pdptrace */
+ "chaltroot", /* 606 = chaltroot */
+ "fchaltroot", /* 607 = fchaltroot */
};
diff --git a/sys/compat/freebsd32/freebsd32_sysent.c b/sys/compat/freebsd32/freebsd32_sysent.c
--- a/sys/compat/freebsd32/freebsd32_sysent.c
+++ b/sys/compat/freebsd32/freebsd32_sysent.c
@@ -673,4 +673,6 @@
{ .sy_narg = AS(pdopenpid_args), .sy_call = (sy_call_t *)sys_pdopenpid, .sy_auevent = AUE_PDOPENPID, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 603 = pdopenpid */
{ .sy_narg = AS(pddupfd_args), .sy_call = (sy_call_t *)sys_pddupfd, .sy_auevent = AUE_NULL, .sy_flags = 0, .sy_thrcnt = SY_THR_STATIC }, /* 604 = pddupfd */
{ .sy_narg = AS(freebsd32_pdptrace_args), .sy_call = (sy_call_t *)freebsd32_pdptrace, .sy_auevent = AUE_PDPTRACE, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 605 = freebsd32_pdptrace */
+ { .sy_narg = AS(chaltroot_args), .sy_call = (sy_call_t *)sys_chaltroot, .sy_auevent = AUE_CHALTROOT, .sy_flags = 0, .sy_thrcnt = SY_THR_STATIC }, /* 606 = chaltroot */
+ { .sy_narg = AS(fchaltroot_args), .sy_call = (sy_call_t *)sys_fchaltroot, .sy_auevent = AUE_NULL, .sy_flags = 0, .sy_thrcnt = SY_THR_STATIC }, /* 607 = fchaltroot */
};
diff --git a/sys/compat/freebsd32/freebsd32_systrace_args.c b/sys/compat/freebsd32/freebsd32_systrace_args.c
--- a/sys/compat/freebsd32/freebsd32_systrace_args.c
+++ b/sys/compat/freebsd32/freebsd32_systrace_args.c
@@ -3486,6 +3486,20 @@
*n_args = 5;
break;
}
+ /* chaltroot */
+ case 606: {
+ struct chaltroot_args *p = params;
+ uarg[a++] = (intptr_t)p->path; /* const char * */
+ *n_args = 1;
+ break;
+ }
+ /* fchaltroot */
+ case 607: {
+ struct fchaltroot_args *p = params;
+ iarg[a++] = p->fd; /* int */
+ *n_args = 1;
+ break;
+ }
default:
*n_args = 0;
break;
@@ -9426,6 +9440,26 @@
break;
};
break;
+ /* chaltroot */
+ case 606:
+ switch (ndx) {
+ case 0:
+ p = "userland const char *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* fchaltroot */
+ case 607:
+ switch (ndx) {
+ case 0:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
default:
break;
};
@@ -11374,6 +11408,16 @@
if (ndx == 0 || ndx == 1)
p = "int";
break;
+ /* chaltroot */
+ case 606:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* fchaltroot */
+ case 607:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
default:
break;
};
diff --git a/sys/compat/linux/linux_util.c b/sys/compat/linux/linux_util.c
--- a/sys/compat/linux/linux_util.c
+++ b/sys/compat/linux/linux_util.c
@@ -88,9 +88,9 @@
return (0);
}
NDFREE_PNBUF(&nd);
- pwd_altroot(td, nd.ni_vp);
+ error = pwd_altroot(td, nd.ni_vp);
vrele(nd.ni_vp);
- return (0);
+ return (error);
}
void
diff --git a/sys/kern/init_sysent.c b/sys/kern/init_sysent.c
--- a/sys/kern/init_sysent.c
+++ b/sys/kern/init_sysent.c
@@ -672,4 +672,6 @@
{ .sy_narg = AS(pdopenpid_args), .sy_call = (sy_call_t *)sys_pdopenpid, .sy_auevent = AUE_PDOPENPID, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 603 = pdopenpid */
{ .sy_narg = AS(pddupfd_args), .sy_call = (sy_call_t *)sys_pddupfd, .sy_auevent = AUE_NULL, .sy_flags = 0, .sy_thrcnt = SY_THR_STATIC }, /* 604 = pddupfd */
{ .sy_narg = AS(pdptrace_args), .sy_call = (sy_call_t *)sys_pdptrace, .sy_auevent = AUE_PDPTRACE, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 605 = pdptrace */
+ { .sy_narg = AS(chaltroot_args), .sy_call = (sy_call_t *)sys_chaltroot, .sy_auevent = AUE_CHALTROOT, .sy_flags = 0, .sy_thrcnt = SY_THR_STATIC }, /* 606 = chaltroot */
+ { .sy_narg = AS(fchaltroot_args), .sy_call = (sy_call_t *)sys_fchaltroot, .sy_auevent = AUE_NULL, .sy_flags = 0, .sy_thrcnt = SY_THR_STATIC }, /* 607 = fchaltroot */
};
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -4336,35 +4336,40 @@
/*
* Process is transitioning to/from a non-native ABI.
*/
-void
+int
pwd_altroot(struct thread *td, struct vnode *altroot_vp)
{
struct pwddesc *pdp;
struct pwd *newpwd, *oldpwd;
+ if (altroot_vp != NULL && altroot_vp->v_type != VDIR)
+ return (ENOTDIR);
newpwd = pwd_alloc();
pdp = td->td_proc->p_pd;
PWDDESC_XLOCK(pdp);
oldpwd = PWDDESC_XLOCKED_LOAD_PWD(pdp);
- if (altroot_vp != NULL) {
- /*
- * Native process to a non-native ABI.
- */
-
- vrefact(altroot_vp);
- newpwd->pwd_adir = altroot_vp;
+ if (altroot_vp != oldpwd->pwd_adir) {
+ if (altroot_vp != NULL) {
+ /* Native process to a non-native ABI. */
+ vrefact(altroot_vp);
+ newpwd->pwd_adir = altroot_vp;
+ } else {
+ /* Non-native process to the native ABI. */
+ vrefact(oldpwd->pwd_rdir);
+ newpwd->pwd_adir = oldpwd->pwd_rdir;
+ }
+ pwd_fill(oldpwd, newpwd);
+ pwd_set(pdp, newpwd);
+ newpwd = NULL;
} else {
- /*
- * Non-native process to the native ABI.
- */
-
- vrefact(oldpwd->pwd_rdir);
- newpwd->pwd_adir = oldpwd->pwd_rdir;
+ oldpwd = NULL;
}
- pwd_fill(oldpwd, newpwd);
- pwd_set(pdp, newpwd);
PWDDESC_XUNLOCK(pdp);
- pwd_drop(oldpwd);
+ if (oldpwd != NULL)
+ pwd_drop(oldpwd);
+ if (newpwd != NULL)
+ pwd_drop(newpwd);
+ return (0);
}
/*
diff --git a/sys/kern/syscalls.c b/sys/kern/syscalls.c
--- a/sys/kern/syscalls.c
+++ b/sys/kern/syscalls.c
@@ -611,4 +611,6 @@
"pdopenpid", /* 603 = pdopenpid */
"pddupfd", /* 604 = pddupfd */
"pdptrace", /* 605 = pdptrace */
+ "chaltroot", /* 606 = chaltroot */
+ "fchaltroot", /* 607 = fchaltroot */
};
diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master
--- a/sys/kern/syscalls.master
+++ b/sys/kern/syscalls.master
@@ -3451,5 +3451,15 @@
int data
);
}
+606 AUE_CHALTROOT STD {
+ int chaltroot(
+ _In_z_ const char *path
+ );
+ }
+607 AUE_NULL STD {
+ int fchaltroot(
+ int fd
+ );
+ }
; vim: syntax=off
diff --git a/sys/kern/systrace_args.c b/sys/kern/systrace_args.c
--- a/sys/kern/systrace_args.c
+++ b/sys/kern/systrace_args.c
@@ -3583,6 +3583,20 @@
*n_args = 5;
break;
}
+ /* chaltroot */
+ case 606: {
+ struct chaltroot_args *p = params;
+ uarg[a++] = (intptr_t)p->path; /* const char * */
+ *n_args = 1;
+ break;
+ }
+ /* fchaltroot */
+ case 607: {
+ struct fchaltroot_args *p = params;
+ iarg[a++] = p->fd; /* int */
+ *n_args = 1;
+ break;
+ }
default:
*n_args = 0;
break;
@@ -9600,6 +9614,26 @@
break;
};
break;
+ /* chaltroot */
+ case 606:
+ switch (ndx) {
+ case 0:
+ p = "userland const char *";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* fchaltroot */
+ case 607:
+ switch (ndx) {
+ case 0:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
default:
break;
};
@@ -11643,6 +11677,16 @@
if (ndx == 0 || ndx == 1)
p = "int";
break;
+ /* chaltroot */
+ case 606:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
+ /* fchaltroot */
+ case 607:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
default:
break;
};
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -969,31 +969,31 @@
&unprivileged_chroot, 0,
"Unprivileged processes can use chroot(2)");
+static int
+chroot_unpriv(struct thread *td)
+{
+ if (priv_check(td, PRIV_VFS_CHROOT) == 0)
+ return (0);
+ if (unprivileged_chroot == 0)
+ return (EXTERROR(EPERM,
+ "security.bsd.unprivileged_chroot sysctl not enabled"));
+ if ((td->td_proc->p_flag2 & P2_NO_NEW_PRIVS) == 0)
+ return (EXTERROR(EPERM,
+ "PROC_NO_NEW_PRIVS not enabled"));
+ return (0);
+}
+
/*
* Takes locked vnode, unlocks it before returning.
*/
static int
kern_chroot(struct thread *td, struct vnode *vp)
{
- struct proc *p;
int error;
- error = priv_check(td, PRIV_VFS_CHROOT);
- if (error != 0) {
- p = td->td_proc;
- if (unprivileged_chroot == 0) {
- error = EXTERROR(EPERM,
- "security.bsd.unprivileged_chroot sysctl not enabled");
- goto e_vunlock;
- }
- if ((p->p_flag2 & P2_NO_NEW_PRIVS) == 0) {
- error = EXTERROR(EPERM,
- "PROC_NO_NEW_PRIVS not enabled");
- goto e_vunlock;
- }
- }
-
- error = change_dir(vp, td);
+ error = chroot_unpriv(td);
+ if (error == 0)
+ error = change_dir(vp, td);
if (error != 0)
goto e_vunlock;
#ifdef MAC
@@ -5329,3 +5329,76 @@
error = copyout(outoffp, uap->outoffp, sizeof(off_t));
return (error);
}
+
+int
+sys_chaltroot(struct thread *td, struct chaltroot_args *uap)
+{
+ struct nameidata nd;
+ int error;
+
+ error = chroot_unpriv(td);
+ if (error != 0)
+ return (error);
+
+ if (uap->path == NULL) {
+#ifdef MAC
+ error = mac_vnode_check_chaltroot(td->td_ucred, NULL);
+ if (error != 0)
+ return (error);
+#endif
+ return (pwd_altroot(td, NULL));
+ }
+
+ NDINIT(&nd, LOOKUP, FOLLOW | AUDITVNODE1, UIO_USERSPACE, uap->path);
+ error = namei(&nd);
+ if (error != 0)
+ return (error);
+ NDFREE_PNBUF(&nd);
+#ifdef MAC
+ error = mac_vnode_check_chaltroot(td->td_ucred, nd.ni_vp);
+ if (error == 0)
+#endif
+ error = pwd_altroot(td, nd.ni_vp);
+ vrele(nd.ni_vp);
+ return (error);
+}
+
+int
+sys_fchaltroot(struct thread *td, struct fchaltroot_args *uap)
+{
+ struct vnode *vp;
+ struct file *fp;
+ int error;
+ uint8_t fdflags;
+
+ error = chroot_unpriv(td);
+ if (error != 0)
+ return (error);
+
+ if (uap->fd == -1) {
+#ifdef MAC
+ error = mac_vnode_check_chaltroot(td->td_ucred, NULL);
+ if (error != 0)
+ return (error);
+#endif
+ return (pwd_altroot(td, NULL));
+ }
+
+ error = getvnode_path(td, uap->fd, &cap_fchroot_rights, &fdflags, &fp);
+ if (error != 0)
+ return (error);
+ if ((fdflags & UF_RESOLVE_BENEATH) != 0) {
+ fdrop(fp, td);
+ return (ENOTCAPABLE);
+ }
+ vp = fp->f_vnode;
+ vrefact(vp);
+ fdrop(fp, td);
+#ifdef MAC
+ error = mac_vnode_check_chaltroot(td->td_ucred, vp);
+ if (error == 0)
+#endif
+ error = pwd_altroot(td, vp);
+ vrele(vp);
+ return (error);
+}
diff --git a/sys/security/mac/mac_framework.h b/sys/security/mac/mac_framework.h
--- a/sys/security/mac/mac_framework.h
+++ b/sys/security/mac/mac_framework.h
@@ -535,6 +535,7 @@
return (mac_vnode_check_access_impl(cred, dvp, accmode));
return (0);
}
+int mac_vnode_check_chaltroot(struct ucred *cred, struct vnode *dvp);
int mac_vnode_check_chdir(struct ucred *cred, struct vnode *dvp);
int mac_vnode_check_chroot(struct ucred *cred, struct vnode *dvp);
int mac_vnode_check_create(struct ucred *cred, struct vnode *dvp,
diff --git a/sys/security/mac/mac_policy.h b/sys/security/mac/mac_policy.h
--- a/sys/security/mac/mac_policy.h
+++ b/sys/security/mac/mac_policy.h
@@ -619,6 +619,8 @@
typedef int (*mpo_vnode_check_access_t)(struct ucred *cred,
struct vnode *vp, struct label *vplabel,
accmode_t accmode);
+typedef int (*mpo_vnode_check_chaltroot_t)(struct ucred *cred,
+ struct vnode *dvp, struct label *dvplabel);
typedef int (*mpo_vnode_check_chdir_t)(struct ucred *cred,
struct vnode *dvp, struct label *dvplabel);
typedef int (*mpo_vnode_check_chroot_t)(struct ucred *cred,
@@ -1015,6 +1017,7 @@
mpo_thread_userret_t mpo_thread_userret;
mpo_vnode_check_access_t mpo_vnode_check_access;
+ mpo_vnode_check_chaltroot_t mpo_vnode_check_chaltroot;
mpo_vnode_check_chdir_t mpo_vnode_check_chdir;
mpo_vnode_check_chroot_t mpo_vnode_check_chroot;
mpo_vnode_check_create_t mpo_vnode_check_create;
diff --git a/sys/security/mac/mac_vfs.c b/sys/security/mac/mac_vfs.c
--- a/sys/security/mac/mac_vfs.c
+++ b/sys/security/mac/mac_vfs.c
@@ -464,6 +464,21 @@
return (error);
}
+MAC_CHECK_PROBE_DEFINE2(vnode_check_chaltroot, "struct ucred *",
+ "struct vnode *");
+
+int
+mac_vnode_check_chaltroot(struct ucred *cred, struct vnode *dvp)
+{
+ int error;
+
+ MAC_POLICY_CHECK(vnode_check_chaltroot, cred, dvp, dvp != NULL ?
+ dvp->v_label : NULL);
+ MAC_CHECK_PROBE2(vnode_check_chaltroot, error, cred, dvp);
+
+ return (error);
+}
+
MAC_CHECK_PROBE_DEFINE4(vnode_check_create, "struct ucred *",
"struct vnode *", "struct componentname *", "struct vattr *");
diff --git a/sys/sys/filedesc.h b/sys/sys/filedesc.h
--- a/sys/sys/filedesc.h
+++ b/sys/sys/filedesc.h
@@ -369,7 +369,7 @@
struct pwddesc *pdshare(struct pwddesc *pdp);
void pdunshare(struct thread *td);
-void pwd_altroot(struct thread *td, struct vnode *altroot_vp);
+int pwd_altroot(struct thread *td, struct vnode *altroot_vp);
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);
diff --git a/sys/sys/syscall.h b/sys/sys/syscall.h
--- a/sys/sys/syscall.h
+++ b/sys/sys/syscall.h
@@ -544,4 +544,6 @@
#define SYS_pdopenpid 603
#define SYS_pddupfd 604
#define SYS_pdptrace 605
-#define SYS_MAXSYSCALL 606
+#define SYS_chaltroot 606
+#define SYS_fchaltroot 607
+#define SYS_MAXSYSCALL 608
diff --git a/sys/sys/syscall.mk b/sys/sys/syscall.mk
--- a/sys/sys/syscall.mk
+++ b/sys/sys/syscall.mk
@@ -447,4 +447,6 @@
renameat2.o \
pdopenpid.o \
pddupfd.o \
- pdptrace.o
+ pdptrace.o \
+ chaltroot.o \
+ fchaltroot.o
diff --git a/sys/sys/sysproto.h b/sys/sys/sysproto.h
--- a/sys/sys/sysproto.h
+++ b/sys/sys/sysproto.h
@@ -1948,6 +1948,12 @@
char addr_l_[PADL_(void *)]; void * addr; char addr_r_[PADR_(void *)];
char data_l_[PADL_(int)]; int data; char data_r_[PADR_(int)];
};
+struct chaltroot_args {
+ char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)];
+};
+struct fchaltroot_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+};
int sys__exit(struct thread *, struct _exit_args *);
int sys_fork(struct thread *, struct fork_args *);
int sys_read(struct thread *, struct read_args *);
@@ -2361,6 +2367,8 @@
int sys_pdopenpid(struct thread *, struct pdopenpid_args *);
int sys_pddupfd(struct thread *, struct pddupfd_args *);
int sys_pdptrace(struct thread *, struct pdptrace_args *);
+int sys_chaltroot(struct thread *, struct chaltroot_args *);
+int sys_fchaltroot(struct thread *, struct fchaltroot_args *);
#ifdef COMPAT_43
@@ -3366,6 +3374,8 @@
#define SYS_AUE_pdopenpid AUE_PDOPENPID
#define SYS_AUE_pddupfd AUE_NULL
#define SYS_AUE_pdptrace AUE_PDPTRACE
+#define SYS_AUE_chaltroot AUE_CHALTROOT
+#define SYS_AUE_fchaltroot AUE_NULL
#undef PAD_
#undef PADL_
diff --git a/usr.sbin/chroot/chroot.8 b/usr.sbin/chroot/chroot.8
--- a/usr.sbin/chroot/chroot.8
+++ b/usr.sbin/chroot/chroot.8
@@ -37,6 +37,8 @@
.Op Fl g Ar group
.Op Fl u Ar user
.Op Fl n
+.Op Fl a
+.Op Fl A
.Ar newroot
.Op Ar command Op Ar arg ...
.Sh DESCRIPTION
@@ -71,6 +73,11 @@
.Va security.bsd.unprivileged_chroot
sysctl is set to 1, it will make it possible to chroot without
superuser privileges.
+.It Fl a
+Change the alternative root instead of root, see
+.Xr chaltroot 2 .
+.It Fl A
+Disable the alternative root.
.El
.Sh ENVIRONMENT
The following environment variable is referenced by
diff --git a/usr.sbin/chroot/chroot.c b/usr.sbin/chroot/chroot.c
--- a/usr.sbin/chroot/chroot.c
+++ b/usr.sbin/chroot/chroot.c
@@ -99,7 +99,7 @@
gid_t gid, *gidlist;
uid_t uid;
int arg, ch, error, gids;
- bool nonprivileged;
+ bool altroot, clear_altroot, nonprivileged;
gid = 0;
uid = 0;
@@ -107,7 +107,8 @@
user = group = grouplist = NULL;
gidlist = NULL;
nonprivileged = false;
- while ((ch = getopt(argc, argv, "G:g:u:n")) != -1) {
+ altroot = false;
+ while ((ch = getopt(argc, argv, "AaG:g:u:n")) != -1) {
switch(ch) {
case 'u':
user = optarg;
@@ -132,6 +133,12 @@
case 'n':
nonprivileged = true;
break;
+ case 'a':
+ altroot = true;
+ break;
+ case 'A':
+ clear_altroot = true;
+ break;
case '?':
default:
usage();
@@ -170,10 +177,12 @@
if (error != 0)
err(1, "procctl");
}
+ if (clear_altroot && chaltroot(NULL) == -1)
+ err(1, "%s: clearing altroot", argv[0]);
if (chdir(argv[0]) == -1)
err(1, "%s", argv[0]);
- if (chroot(".") == -1) {
+ if ((altroot ? chaltroot : chroot)(".") == -1) {
if (errno == EPERM && !nonprivileged && geteuid() != 0)
errx(1, "unprivileged use requires -n");
err(1, "%s", argv[0]);
@@ -202,6 +211,6 @@
usage(void)
{
(void)fprintf(stderr, "usage: chroot [-g group] [-G group,group,...] "
- "[-u user] [-n] newroot [command]\n");
+ "[-u user] [-naA] newroot [command]\n");
exit(1);
}

File Metadata

Mime Type
text/plain
Expires
Mon, Nov 16, 5:37 AM (21 h, 43 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
41762674
Default Alt Text
D60035.1794807474.diff (21 KB)

Event Timeline