Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F144404948
D44373.id54425.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
18 KB
Referenced Files
None
Subscribers
None
D44373.id54425.diff
View Options
diff --git a/include/unistd.h b/include/unistd.h
--- a/include/unistd.h
+++ b/include/unistd.h
@@ -465,6 +465,7 @@
#if (__XSI_VISIBLE && __XSI_VISIBLE <= 500) || __BSD_VISIBLE
int brk(const void *);
int chroot(const char *);
+int fchroot(int);
int getdtablesize(void);
int getpagesize(void) __pure2;
char *getpass(const char *);
diff --git a/lib/libsys/Makefile.sys b/lib/libsys/Makefile.sys
--- a/lib/libsys/Makefile.sys
+++ b/lib/libsys/Makefile.sys
@@ -417,6 +417,7 @@
MLINKS+=chown.2 fchown.2 \
chown.2 fchownat.2 \
chown.2 lchown.2
+MLINKS+=chroot.2 fchroot.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
@@ -429,6 +429,7 @@
FBSD_1.8 {
kcmp;
+ fchroot;
};
FBSDprivate_1.0 {
diff --git a/lib/libsys/chroot.2 b/lib/libsys/chroot.2
--- a/lib/libsys/chroot.2
+++ b/lib/libsys/chroot.2
@@ -29,7 +29,8 @@
.Dt CHROOT 2
.Os
.Sh NAME
-.Nm chroot
+.Nm chroot ,
+.Nm fchroot
.Nd change root directory
.Sh LIBRARY
.Lb libc
@@ -37,6 +38,8 @@
.In unistd.h
.Ft int
.Fn chroot "const char *dirname"
+.Ft int
+.Fn fchroot "int fd"
.Sh DESCRIPTION
The
.Fa dirname
@@ -92,6 +95,12 @@
mimicking the historic insecure behavior of
.Fn chroot
still present on other systems.
+.Pp
+The
+.Fn fchroot
+is identical to
+.Fn chroot
+except it takes a file descriptor instead of path.
.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
@@ -801,4 +801,6 @@
__sys_timerfd_settime;
_kcmp;
__sys_kcmp;
+ _fchroot;
+ __sys_fchroot;
};
diff --git a/share/man/man4/rights.4 b/share/man/man4/rights.4
--- a/share/man/man4/rights.4
+++ b/share/man/man4/rights.4
@@ -164,9 +164,6 @@
.It Dv CAP_EXTATTR_SET
Permit
.Xr extattr_set_fd 2 .
-.It Dv CAP_FCHDIR
-Permit
-.Xr fchdir 2 .
.It Dv CAP_FCHFLAGS
Permit
.Xr fchflags 2
diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c
--- a/sys/kern/imgact_elf.c
+++ b/sys/kern/imgact_elf.c
@@ -792,15 +792,6 @@
u_long base_addr = 0;
int error;
-#ifdef CAPABILITY_MODE
- /*
- * XXXJA: This check can go away once we are sufficiently confident
- * that the checks in namei() are correct.
- */
- if (IN_CAPABILITY_MODE(curthread))
- return (ECAPMODE);
-#endif
-
tempdata = malloc(sizeof(*tempdata), M_TEMP, M_WAITOK | M_ZERO);
nd = &tempdata->nd;
attr = &tempdata->attr;
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -453,18 +453,6 @@
interpret:
if (args->fname != NULL) {
-#ifdef CAPABILITY_MODE
- /*
- * While capability mode can't reach this point via direct
- * path arguments to execve(), we also don't allow
- * interpreters to be used in capability mode (for now).
- * Catch indirect lookups and return a permissions error.
- */
- if (IN_CAPABILITY_MODE(td)) {
- error = ECAPMODE;
- goto exec_fail;
- }
-#endif
/*
* Translate the file name. namei() returns a vnode
diff --git a/sys/kern/kern_mib.c b/sys/kern/kern_mib.c
--- a/sys/kern/kern_mib.c
+++ b/sys/kern/kern_mib.c
@@ -98,7 +98,7 @@
SYSCTL_INT(_kern, KERN_OSREV, osrevision, CTLFLAG_RD | CTLFLAG_CAPRD,
SYSCTL_NULL_INT_PTR, BSD, "Operating system revision");
-SYSCTL_STRING(_kern, KERN_VERSION, version, CTLFLAG_RD,
+SYSCTL_STRING(_kern, KERN_VERSION, version, CTLFLAG_RD | CTLFLAG_CAPRD,
version, 0, "Kernel version");
SYSCTL_STRING(_kern, OID_AUTO, compiler_version, CTLFLAG_RD,
diff --git a/sys/kern/subr_capability.c b/sys/kern/subr_capability.c
--- a/sys/kern/subr_capability.c
+++ b/sys/kern/subr_capability.c
@@ -55,7 +55,6 @@
__read_mostly cap_rights_t cap_chflags_rights;
__read_mostly cap_rights_t cap_connect_rights;
__read_mostly cap_rights_t cap_event_rights;
-__read_mostly cap_rights_t cap_fchdir_rights;
__read_mostly cap_rights_t cap_fchflags_rights;
__read_mostly cap_rights_t cap_fchmod_rights;
__read_mostly cap_rights_t cap_fchown_rights;
@@ -96,6 +95,7 @@
__read_mostly cap_rights_t cap_unlinkat_rights;
__read_mostly cap_rights_t cap_write_rights;
__read_mostly cap_rights_t cap_no_rights;
+__read_mostly cap_rights_t cap_all_rights;
static void
cap_rights_sysinit(void *arg)
@@ -104,7 +104,6 @@
cap_rights_init_one(&cap_bind_rights, CAP_BIND);
cap_rights_init_one(&cap_connect_rights, CAP_CONNECT);
cap_rights_init_one(&cap_event_rights, CAP_EVENT);
- cap_rights_init_one(&cap_fchdir_rights, CAP_FCHDIR);
cap_rights_init_one(&cap_fchflags_rights, CAP_FCHFLAGS);
cap_rights_init_one(&cap_fchmod_rights, CAP_FCHMOD);
cap_rights_init_one(&cap_fchown_rights, CAP_FCHOWN);
@@ -145,6 +144,8 @@
cap_rights_init_one(&cap_unlinkat_rights, CAP_UNLINKAT);
cap_rights_init_one(&cap_write_rights, CAP_WRITE);
cap_rights_init(&cap_no_rights);
+ cap_rights_init(&cap_all_rights);
+ CAP_ALL(&cap_all_rights);
}
SYSINIT(cap_rights_sysinit, SI_SUB_COPYRIGHT, SI_ORDER_ANY, cap_rights_sysinit,
NULL);
diff --git a/sys/kern/sys_capability.c b/sys/kern/sys_capability.c
--- a/sys/kern/sys_capability.c
+++ b/sys/kern/sys_capability.c
@@ -76,6 +76,7 @@
#include <sys/systm.h>
#include <sys/ucred.h>
#include <sys/uio.h>
+#include <sys/vnode.h>
#include <sys/ktrace.h>
#include <security/audit/audit.h>
@@ -101,6 +102,15 @@
{
struct ucred *newcred, *oldcred;
struct proc *p;
+ struct vnode *ecapmodevp;
+
+ // XXX: ecapmodevp should be global
+ // XXX: ecapmode_vnodeops, to return the right errno? make sure we're returning the wrong one now.
+ getnewvnode("ecapmode", NULL, &dead_vnodeops, &ecapmodevp);
+ ecapmodevp->v_state = VSTATE_CONSTRUCTED; // XXX: needed?
+
+ pwd_chdir(td, ecapmodevp);
+ pwd_chroot(td, ecapmodevp);
if (IN_CAPABILITY_MODE(td))
return (0);
diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master
--- a/sys/kern/syscalls.master
+++ b/sys/kern/syscalls.master
@@ -143,7 +143,7 @@
size_t nbyte
);
}
-5 AUE_OPEN_RWTC STD {
+5 AUE_OPEN_RWTC STD|CAPENABLED {
int open(
_In_z_ const char *path,
int flags,
@@ -157,7 +157,7 @@
int fd
);
}
-7 AUE_WAIT4 STD {
+7 AUE_WAIT4 STD|CAPENABLED {
int wait4(
int pid,
_Out_opt_ int *status,
@@ -177,18 +177,18 @@
_In_z_ const char *link
);
}
-10 AUE_UNLINK STD {
+10 AUE_UNLINK STD|CAPENABLED {
int unlink(
_In_z_ const char *path
);
}
11 AUE_NULL OBSOL execv
-12 AUE_CHDIR STD {
+12 AUE_CHDIR STD|CAPENABLED {
int chdir(
_In_z_ const char *path
);
}
-13 AUE_FCHDIR STD {
+13 AUE_FCHDIR STD|CAPENABLED {
int fchdir(
int fd
);
@@ -200,7 +200,7 @@
uint32_t dev
);
}
-15 AUE_CHMOD STD {
+15 AUE_CHMOD STD|CAPENABLED {
int chmod(
_In_z_ const char *path,
mode_t mode
@@ -313,7 +313,7 @@
_Inout_ __socklen_t *alen
);
}
-33 AUE_ACCESS STD {
+33 AUE_ACCESS STD|CAPENABLED {
int access(
_In_z_ const char *path,
int amode
@@ -443,20 +443,20 @@
_In_z_ const char *path
);
}
-57 AUE_SYMLINK STD {
+57 AUE_SYMLINK STD|CAPENABLED {
int symlink(
_In_z_ const char *path,
_In_z_ const char *link
);
}
-58 AUE_READLINK STD {
+58 AUE_READLINK STD|CAPENABLED {
ssize_t readlink(
_In_z_ const char *path,
_Out_writes_z_(count) char *buf,
size_t count
);
}
-59 AUE_EXECVE STD {
+59 AUE_EXECVE STD|CAPENABLED {
int execve(
_In_z_ const char *fname,
_In_z_ char **argv,
@@ -497,7 +497,7 @@
int flags
);
}
-66 AUE_VFORK STD {
+66 AUE_VFORK STD|CAPENABLED {
int vfork(void);
}
67 AUE_NULL OBSOL vread
@@ -650,7 +650,7 @@
int protocol
);
}
-98 AUE_CONNECT STD {
+98 AUE_CONNECT STD|CAPENABLED {
int connect(
int s,
_In_reads_bytes_(namelen) const struct sockaddr *name,
@@ -836,7 +836,7 @@
int egid
);
}
-128 AUE_RENAME STD {
+128 AUE_RENAME STD|CAPENABLED {
int rename(
_In_z_ const char *from,
_In_z_ const char *to
@@ -890,7 +890,7 @@
_Out_writes_(2) int *rsv
);
}
-136 AUE_MKDIR STD {
+136 AUE_MKDIR STD|CAPENABLED {
int mkdir(
_In_z_ const char *path,
mode_t mode
@@ -1146,7 +1146,7 @@
_Out_ _Contains_timet_ struct freebsd11_stat *ub
);
}
-191 AUE_PATHCONF STD {
+191 AUE_PATHCONF STD|CAPENABLED {
int pathconf(
_In_z_ const char *path,
int name
@@ -1455,7 +1455,7 @@
int inherit
);
}
-251 AUE_RFORK STD {
+251 AUE_RFORK STD|CAPENABLED {
int rfork(
int flags
);
@@ -1692,7 +1692,7 @@
325 AUE_MUNLOCKALL STD|CAPENABLED {
int munlockall(void);
}
-326 AUE_GETCWD STD {
+326 AUE_GETCWD STD|CAPENABLED {
int __getcwd(
_Out_writes_z_(buflen) char *buf,
size_t buflen
@@ -1980,7 +1980,7 @@
);
}
375 AUE_NULL OBSOL nfsclnt
-376 AUE_EACCESS STD {
+376 AUE_EACCESS STD|CAPENABLED {
int eaccess(
_In_z_ const char *path,
int amode
@@ -2243,7 +2243,7 @@
_In_z_ const char *name
);
}
-425 AUE_ACL_GET_LINK STD {
+425 AUE_ACL_GET_LINK STD|CAPENABLED {
int __acl_get_link(
_In_z_ const char *path,
acl_type_t type,
@@ -2819,7 +2819,7 @@
_Inout_opt_ _Contains_long_ struct shmid_ds *buf
);
}
-513 AUE_LPATHCONF STD {
+513 AUE_LPATHCONF STD|CAPENABLED {
int lpathconf(
_In_z_ const char *path,
int name
@@ -3234,7 +3234,7 @@
_Inout_opt_ uint32_t *ptr
);
}
-574 AUE_REALPATHAT STD {
+574 AUE_REALPATHAT STD|CAPENABLED {
int __realpathat(
int fd,
_In_z_ const char *path,
@@ -3333,5 +3333,11 @@
uintptr_t idx2
);
}
+589 AUE_NULL STD|CAPENABLED {
+ int fchroot(
+ int fd
+ );
+ }
+
; vim: syntax=off
diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c
--- a/sys/kern/uipc_syscalls.c
+++ b/sys/kern/uipc_syscalls.c
@@ -467,11 +467,6 @@
struct file *fp;
int error;
-#ifdef CAPABILITY_MODE
- if (IN_CAPABILITY_MODE(td) && (dirfd == AT_FDCWD))
- return (ECAPMODE);
-#endif
-
AUDIT_ARG_FD(fd);
AUDIT_ARG_SOCKADDR(td, dirfd, sa);
error = getsock(td, fd, &cap_connect_rights, &fp);
diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c
--- a/sys/kern/vfs_lookup.c
+++ b/sys/kern/vfs_lookup.c
@@ -271,13 +271,6 @@
struct componentname *cnp;
cnp = &ndp->ni_cnd;
- if ((ndp->ni_lcf & NI_LCF_STRICTRELATIVE) != 0) {
-#ifdef KTRACE
- if (KTRPOINT(curthread, KTR_CAPFAIL))
- ktrcapfail(CAPFAIL_LOOKUP, NULL, NULL);
-#endif
- return (ENOTCAPABLE);
- }
while (*(cnp->cn_nameptr) == '/') {
cnp->cn_nameptr++;
ndp->ni_pathlen--;
@@ -318,15 +311,9 @@
* the relative root.
*/
if (IN_CAPABILITY_MODE(td) && (cnp->cn_flags & NOCAPCHECK) == 0) {
+ // XXX: also set NI_LCF_CAP_DOTDOT?
ndp->ni_lcf |= NI_LCF_STRICTRELATIVE;
ndp->ni_resflags |= NIRES_STRICTREL;
- if (ndp->ni_dirfd == AT_FDCWD) {
-#ifdef KTRACE
- if (KTRPOINT(td, KTR_CAPFAIL))
- ktrcapfail(CAPFAIL_LOOKUP, NULL, NULL);
-#endif
- return (ECAPMODE);
- }
}
#endif
error = 0;
@@ -344,6 +331,7 @@
if (cnp->cn_pnbuf[0] == '/') {
ndp->ni_resflags |= NIRES_ABS;
+ CAP_ALL(&ndp->ni_filecaps.fc_rights);
error = namei_handle_root(ndp, dpp);
} else {
if (ndp->ni_startdir != NULL) {
@@ -351,6 +339,7 @@
startdir_used = true;
} else if (ndp->ni_dirfd == AT_FDCWD) {
*dpp = pwd->pwd_cdir;
+ CAP_ALL(&ndp->ni_filecaps.fc_rights);
vrefact(*dpp);
} else {
if (cnp->cn_flags & AUDITVNODE1)
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
@@ -898,7 +898,12 @@
int error;
AUDIT_ARG_FD(uap->fd);
- error = getvnode_path(td, uap->fd, &cap_fchdir_rights,
+ /*
+ * XXX: Instead of cap_fchdir_rights we require file descriptors
+ * passed to fchdir(2) to have full rights, so then we don't
+ * need to track those rights for process' cwd and root.
+ */
+ error = getvnode_path(td, uap->fd, &cap_all_rights,
&fp);
if (error != 0)
return (error);
@@ -967,18 +972,13 @@
SYSCTL_INT(_security_bsd, OID_AUTO, unprivileged_chroot, CTLFLAG_RW,
&unprivileged_chroot, 0,
"Unprivileged processes can use chroot(2)");
+
/*
- * Change notion of root (``/'') directory.
+ * Takes locked vnode, unlocks it before returning.
*/
-#ifndef _SYS_SYSPROTO_H_
-struct chroot_args {
- char *path;
-};
-#endif
-int
-sys_chroot(struct thread *td, struct chroot_args *uap)
+static int
+kern_chroot(struct thread *td, struct vnode *vp)
{
- struct nameidata nd;
struct proc *p;
int error;
@@ -989,30 +989,80 @@
if (unprivileged_chroot == 0 ||
(p->p_flag2 & P2_NO_NEW_PRIVS) == 0) {
PROC_UNLOCK(p);
- return (error);
+ goto e_vunlock;
}
PROC_UNLOCK(p);
}
- NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF | AUDITVNODE1,
- UIO_USERSPACE, uap->path);
- error = namei(&nd);
- if (error != 0)
- return (error);
- NDFREE_PNBUF(&nd);
- error = change_dir(nd.ni_vp, td);
+
+ error = change_dir(vp, td);
if (error != 0)
goto e_vunlock;
#ifdef MAC
- error = mac_vnode_check_chroot(td->td_ucred, nd.ni_vp);
+ error = mac_vnode_check_chroot(td->td_ucred, vp);
if (error != 0)
goto e_vunlock;
#endif
- VOP_UNLOCK(nd.ni_vp);
- error = pwd_chroot(td, nd.ni_vp);
- vrele(nd.ni_vp);
+ VOP_UNLOCK(vp);
+ error = pwd_chroot(td, vp);
+ vrele(vp);
return (error);
e_vunlock:
- vput(nd.ni_vp);
+ vput(vp);
+ return (error);
+}
+
+/*
+ * Change notion of root (``/'') directory.
+ */
+#ifndef _SYS_SYSPROTO_H_
+struct chroot_args {
+ char *path;
+};
+#endif
+int
+sys_chroot(struct thread *td, struct chroot_args *uap)
+{
+ struct nameidata nd;
+ int error;
+
+ NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF | AUDITVNODE1,
+ UIO_USERSPACE, uap->path);
+ error = namei(&nd);
+ if (error != 0)
+ return (error);
+ NDFREE_PNBUF(&nd);
+ error = kern_chroot(td, nd.ni_vp);
+ return (error);
+}
+
+#ifndef _SYS_SYSPROTO_H_
+struct fchroot_args {
+ int fd;
+};
+#endif
+int
+sys_fchroot(struct thread *td, struct fchroot_args *uap)
+{
+ struct vnode *vp;
+ struct file *fp;
+ int error;
+
+ /*
+ * XXX: I don't understand how it'd interact with pwd_jdir
+ * in cache_fplookup() and namei_setup(); let's make sure
+ * it cannot happen for now.
+ */
+ if (jailed(td->td_ucred))
+ return (EPERM);
+
+ error = getvnode_path(td, uap->fd, &cap_all_rights, &fp);
+ if (error != 0)
+ return (error);
+ vp = fp->f_vnode;
+ vrefact(vp);
+ fdrop(fp, td);
+ vn_lock(vp, LK_SHARED | LK_RETRY);
+ error = kern_chroot(td, vp);
return (error);
}
diff --git a/sys/sys/caprights.h b/sys/sys/caprights.h
--- a/sys/sys/caprights.h
+++ b/sys/sys/caprights.h
@@ -59,10 +59,10 @@
#ifdef _KERNEL
extern cap_rights_t cap_accept_rights;
+extern cap_rights_t cap_all_rights;
extern cap_rights_t cap_bind_rights;
extern cap_rights_t cap_connect_rights;
extern cap_rights_t cap_event_rights;
-extern cap_rights_t cap_fchdir_rights;
extern cap_rights_t cap_fchflags_rights;
extern cap_rights_t cap_fchmod_rights;
extern cap_rights_t cap_fchown_rights;
diff --git a/sys/sys/capsicum.h b/sys/sys/capsicum.h
--- a/sys/sys/capsicum.h
+++ b/sys/sys/capsicum.h
@@ -114,7 +114,7 @@
#define CAP_LOOKUP CAPRIGHT(0, 0x0000000000000400ULL)
/* VFS methods. */
-/* Allows for fchdir(2). */
+/* No longer used. */
#define CAP_FCHDIR CAPRIGHT(0, 0x0000000000000800ULL)
/* Allows for fchflags(2). */
#define CAP_FCHFLAGS CAPRIGHT(0, 0x0000000000001000ULL)
@@ -451,6 +451,7 @@
int cap_fcntl_check(struct filedesc *fdp, int fd, int cmd);
extern bool trap_enotcap;
+extern bool old_capsicum_semantics;
#else /* !_KERNEL */
diff --git a/usr.bin/procstat/procstat_files.c b/usr.bin/procstat/procstat_files.c
--- a/usr.bin/procstat/procstat_files.c
+++ b/usr.bin/procstat/procstat_files.c
@@ -145,7 +145,6 @@
{ CAP_FTRUNCATE, "ft" },
/* VFS methods. */
- { CAP_FCHDIR, "cd" },
{ CAP_FCHFLAGS, "cf" },
{ CAP_FCHMOD, "cm" },
{ CAP_FCHOWN, "cn" },
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
@@ -33,6 +33,7 @@
.Nd change root directory
.Sh SYNOPSIS
.Nm
+.Op Fl d
.Op Fl G Ar group Ns Op Cm \&, Ns Ar group ...
.Op Fl g Ar group
.Op Fl u Ar user
@@ -51,6 +52,10 @@
.Pp
The options are as follows:
.Bl -tag -width "-G group[,group ...]"
+.It Fl d
+Treat
+.Ar newroot
+as a file descriptor number.
.It Fl G Ar group Ns Op Cm \&, Ns Ar group ...
Run the command with the permissions of the specified groups.
.It Fl g Ar group
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
@@ -30,10 +30,12 @@
*/
#include <sys/types.h>
+#include <sys/capsicum.h>
#include <sys/procctl.h>
#include <ctype.h>
#include <err.h>
+#include <fcntl.h>
#include <grp.h>
#include <limits.h>
#include <paths.h>
@@ -55,16 +57,22 @@
const char *shell;
gid_t gid, *gidlist;
uid_t uid;
- int arg, ch, error, gids;
+ int arg, ch, cwd, error, fd, gids;
long ngroups_max;
- bool nonprivileged;
+ bool fd_not_path, nonprivileged, capsicate;
gid = 0;
uid = 0;
user = group = grouplist = NULL;
- nonprivileged = false;
- while ((ch = getopt(argc, argv, "G:g:u:n")) != -1) {
+ capsicate = fd_not_path = nonprivileged = false;
+ while ((ch = getopt(argc, argv, "CdG:g:u:n")) != -1) {
switch(ch) {
+ case 'C':
+ capsicate = true;
+ break;
+ case 'd':
+ fd_not_path = true;
+ break;
case 'u':
user = optarg;
if (*user == '\0')
@@ -153,8 +161,31 @@
err(1, "procctl");
}
- if (chdir(argv[0]) == -1 || chroot(".") == -1)
- err(1, "%s", argv[0]);
+ if (fd_not_path) {
+ if (capsicate) {
+ cwd = open(".", O_RDONLY | O_DIRECTORY);
+ if (cwd < 0)
+ err(1, ".");
+ error = cap_enter();
+ if (error != 0)
+ err(1, "cap_enter");
+ }
+
+ fd = (uid_t)strtoul(argv[0], &endp, 0);
+ if (*endp != '\0')
+ errx(1, "%s is not a number", argv[0]);
+ if (fchdir(cwd) == -1)
+ err(1, "fchdir");
+ if (fchroot(fd) == -1)
+ err(1, "fchroot");
+ } else {
+ if (capsicate)
+ errx(1, "-C requires -d");
+ if (chdir(argv[0]) == -1)
+ err(1, "%s", argv[0]);
+ if (chroot(".") == -1)
+ err(1, "chroot");
+ }
if (gids && setgroups(gids, gidlist) == -1)
err(1, "setgroups");
@@ -178,7 +209,8 @@
static void
usage(void)
{
- (void)fprintf(stderr, "usage: chroot [-g group] [-G group,group,...] "
+ (void)fprintf(stderr,
+ "usage: chroot [-C] [-d] [-g group] [-G group,group,...] "
"[-u user] [-n] newroot [command]\n");
exit(1);
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Feb 9, 6:39 AM (11 h, 44 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28549324
Default Alt Text
D44373.id54425.diff (18 KB)
Attached To
Mode
D44373: Capsicum vs the Pathnames, a PoC
Attached
Detach File
Event Timeline
Log In to Comment