Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F162825039
D50371.id155543.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
8 KB
Referenced Files
None
Subscribers
None
D50371.id155543.diff
View Options
diff --git a/sys/fs/fdescfs/fdesc_vnops.c b/sys/fs/fdescfs/fdesc_vnops.c
--- a/sys/fs/fdescfs/fdesc_vnops.c
+++ b/sys/fs/fdescfs/fdesc_vnops.c
@@ -639,7 +639,7 @@
VOP_UNLOCK(vn);
td = curthread;
- error = fget_cap(td, fd_fd, &cap_no_rights, &fp, NULL);
+ error = fget_cap(td, fd_fd, &cap_no_rights, NULL, &fp, NULL);
if (error != 0)
goto out;
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
@@ -109,7 +109,8 @@
static void fdunused(struct filedesc *fdp, int fd);
static void fdused(struct filedesc *fdp, int fd);
static int fget_unlocked_seq(struct thread *td, int fd,
- cap_rights_t *needrightsp, struct file **fpp, seqc_t *seqp);
+ cap_rights_t *needrightsp, uint8_t *flagsp,
+ struct file **fpp, seqc_t *seqp);
static int getmaxfd(struct thread *td);
static u_long *filecaps_copy_prep(const struct filecaps *src);
static void filecaps_copy_finish(const struct filecaps *src,
@@ -2163,7 +2164,8 @@
seqc_write_begin(&fde->fde_seqc);
#endif
fde->fde_file = fp;
- fde->fde_flags = (flags & O_CLOEXEC) != 0 ? UF_EXCLOSE : 0;
+ fde->fde_flags = ((flags & O_CLOEXEC) != 0 ? UF_EXCLOSE : 0) |
+ ((flags & O_RESOLVE_BENEATH) != 0 ? UF_BENEATH : 0);
if (fcaps != NULL)
filecaps_move(fcaps, &fde->fde_caps);
else
@@ -2910,7 +2912,7 @@
#ifdef CAPABILITIES
int
-fget_cap(struct thread *td, int fd, cap_rights_t *needrightsp,
+fget_cap(struct thread *td, int fd, cap_rights_t *needrightsp, uint8_t *flagsp,
struct file **fpp, struct filecaps *havecapsp)
{
struct filedesc *fdp = td->td_proc->p_fd;
@@ -2920,7 +2922,8 @@
*fpp = NULL;
for (;;) {
- error = fget_unlocked_seq(td, fd, needrightsp, &fp, &seq);
+ error = fget_unlocked_seq(td, fd, needrightsp, flagsp, &fp,
+ &seq);
if (error != 0)
return (error);
@@ -2950,11 +2953,11 @@
}
#else
int
-fget_cap(struct thread *td, int fd, cap_rights_t *needrightsp,
+fget_cap(struct thread *td, int fd, cap_rights_t *needrightsp, uint8_t *flagsp,
struct file **fpp, struct filecaps *havecapsp)
{
int error;
- error = fget_unlocked(td, fd, needrightsp, fpp);
+ error = fget_unlocked(td, fd, needrightsp, flagsp, fpp);
if (havecapsp != NULL && error == 0)
filecaps_fill(havecapsp);
@@ -3151,13 +3154,15 @@
struct componentname *cnp;
cap_rights_t rights;
int error;
+ uint8_t flags;
td = curthread;
rights = *ndp->ni_rightsneeded;
cap_rights_set_one(&rights, CAP_LOOKUP);
cnp = &ndp->ni_cnd;
- error = fget_cap(td, ndp->ni_dirfd, &rights, &fp, &ndp->ni_filecaps);
+ error = fget_cap(td, ndp->ni_dirfd, &rights, &flags, &fp,
+ &ndp->ni_filecaps);
if (__predict_false(error != 0))
return (error);
if (__predict_false(fp->f_ops == &badfileops)) {
@@ -3175,6 +3180,8 @@
*/
if ((fp->f_flag & FSEARCH) != 0)
cnp->cn_flags |= NOEXECCHECK;
+ if ((flags & UF_BENEATH) != 0)
+ cnp->cn_flags |= RBENEATH;
fdrop(fp, td);
#ifdef CAPABILITIES
@@ -3222,7 +3229,7 @@
#ifdef CAPABILITIES
static int
fget_unlocked_seq(struct thread *td, int fd, cap_rights_t *needrightsp,
- struct file **fpp, seqc_t *seqp)
+ uint8_t *flagsp, struct file **fpp, seqc_t *seqp)
{
struct filedesc *fdp;
const struct filedescent *fde;
@@ -3231,6 +3238,7 @@
seqc_t seq;
cap_rights_t haverights;
int error;
+ uint8_t flags;
fdp = td->td_proc->p_fd;
fdt = fdp->fd_files;
@@ -3241,6 +3249,7 @@
seq = seqc_read_notmodify(fd_seqc(fdt, fd));
fde = &fdt->fdt_ofiles[fd];
haverights = *cap_rights_fde_inline(fde);
+ flags = fde->fde_flags;
fp = fde->fde_file;
if (__predict_false(fp == NULL)) {
if (seqc_consistent(fd_seqc(fdt, fd), seq))
@@ -3270,19 +3279,21 @@
fdrop(fp, td);
}
*fpp = fp;
- if (seqp != NULL) {
+ if (flagsp != NULL)
+ *flagsp = flags;
+ if (seqp != NULL)
*seqp = seq;
- }
return (0);
}
#else
static int
fget_unlocked_seq(struct thread *td, int fd, cap_rights_t *needrightsp,
- struct file **fpp, seqc_t *seqp __unused)
+ uint8_t *flagsp, struct file **fpp, seqc_t *seqp __unused)
{
struct filedesc *fdp;
const struct fdescenttbl *fdt;
struct file *fp;
+ uint8_t flags;
fdp = td->td_proc->p_fd;
fdt = fdp->fd_files;
@@ -3290,6 +3301,7 @@
return (EBADF);
for (;;) {
+ flags = fdt->fdt_ofiles[fd].fde_flags;
fp = fdt->fdt_ofiles[fd].fde_file;
if (__predict_false(fp == NULL))
return (EBADF);
@@ -3307,6 +3319,8 @@
break;
fdrop(fp, td);
}
+ if (flagsp != NULL)
+ *flagsp = flags;
*fpp = fp;
return (0);
}
@@ -3375,7 +3389,7 @@
fdrop(fp, td);
out_fallback:
*fpp = NULL;
- return (fget_unlocked_seq(td, fd, needrightsp, fpp, NULL));
+ return (fget_unlocked_seq(td, fd, needrightsp, NULL, fpp, NULL));
}
/*
@@ -3527,7 +3541,7 @@
fdp = td->td_proc->p_fd;
MPASS(cap_rights_is_set(rightsp, CAP_MMAP));
for (;;) {
- error = fget_unlocked_seq(td, fd, rightsp, &fp, &seq);
+ error = fget_unlocked_seq(td, fd, rightsp, NULL, &fp, &seq);
if (__predict_false(error != 0))
return (error);
if (__predict_false(fp->f_ops == &badfileops)) {
@@ -3580,7 +3594,7 @@
*fpp = NULL;
MPASS(cap_rights_is_set(rightsp, CAP_FCNTL));
for (;;) {
- error = fget_unlocked_seq(td, fd, rightsp, &fp, &seq);
+ error = fget_unlocked_seq(td, fd, rightsp, NULL, &fp, &seq);
if (error != 0)
return (error);
error = cap_fcntl_check(fdp, fd, needfcntl);
@@ -3641,7 +3655,7 @@
struct file *fp;
int error;
- error = fget_cap(td, fd, needrightsp, &fp, &caps);
+ error = fget_cap(td, fd, needrightsp, NULL, &fp, &caps);
if (error != 0)
return (error);
if (fp->f_ops == &badfileops) {
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
@@ -91,7 +91,7 @@
struct file *fp;
int error;
- error = fget_cap(td, fd, rightsp, &fp, havecapsp);
+ error = fget_cap(td, fd, rightsp, NULL, &fp, havecapsp);
if (__predict_false(error != 0))
return (error);
if (__predict_false(fp->f_type != DTYPE_SOCKET)) {
diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c
--- a/sys/kern/uipc_usrreq.c
+++ b/sys/kern/uipc_usrreq.c
@@ -56,7 +56,6 @@
* need a proper out-of-band
*/
-#include <sys/cdefs.h>
#include "opt_ddb.h"
#include <sys/param.h>
@@ -66,6 +65,7 @@
#include <sys/fcntl.h>
#include <sys/file.h>
#include <sys/filedesc.h>
+#include <sys/jail.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/malloc.h>
@@ -3409,22 +3409,33 @@
free(fdep[0], M_FILECAPS);
}
+static bool
+restrict_caps(struct file *fp, struct thread *td)
+{
+ struct prison *prison1, *prison2;
+
+ prison1 = fp->f_cred->cr_prison;
+ prison2 = td->td_ucred->cr_prison;
+ return (prison1 != prison2 && prison1->pr_root != prison2->pr_root);
+}
+
static int
unp_externalize(struct mbuf *control, struct mbuf **controlp, int flags)
{
struct thread *td = curthread; /* XXX */
struct cmsghdr *cm = mtod(control, struct cmsghdr *);
- int i;
int *fdp;
struct filedesc *fdesc = td->td_proc->p_fd;
struct filedescent **fdep;
void *data;
socklen_t clen = control->m_len, datalen;
- int error, newfds;
+ int error, fdflags, newfds;
u_int newlen;
UNP_LINK_UNLOCK_ASSERT();
+ fdflags = (flags & MSG_CMSG_CLOEXEC) ? O_CLOEXEC : 0;
+
error = 0;
if (controlp != NULL) /* controlp == NULL => free control messages */
*controlp = NULL;
@@ -3466,11 +3477,20 @@
*controlp = NULL;
goto next;
}
- for (i = 0; i < newfds; i++, fdp++) {
- _finstall(fdesc, fdep[i]->fde_file, *fdp,
- (flags & MSG_CMSG_CLOEXEC) != 0 ? O_CLOEXEC : 0,
- &fdep[i]->fde_caps);
- unp_externalize_fp(fdep[i]->fde_file);
+ for (int i = 0; i < newfds; i++, fdp++) {
+ struct filecaps caps;
+ struct file *fp;
+ bool xprison;
+
+ fp = fdep[i]->fde_file;
+ caps = fdep[i]->fde_caps;
+ xprison = restrict_caps(fp, td);
+ if (xprison)
+ cap_rights_clear(&caps.fc_rights,
+ CAP_FCHDIR, CAP_FCHROOT);
+ _finstall(fdesc, fp, *fdp, fdflags |
+ (xprison ? O_RESOLVE_BENEATH : 0), &caps);
+ unp_externalize_fp(fp);
}
/*
diff --git a/sys/sys/filedesc.h b/sys/sys/filedesc.h
--- a/sys/sys/filedesc.h
+++ b/sys/sys/filedesc.h
@@ -93,6 +93,7 @@
*/
struct pwd {
u_int pwd_refcount;
+ u_int pwd_flags;
struct vnode *pwd_cdir; /* current directory */
struct vnode *pwd_rdir; /* root directory */
struct vnode *pwd_jdir; /* jail root directory */
@@ -148,6 +149,7 @@
* Per-process open flags.
*/
#define UF_EXCLOSE 0x01 /* auto-close on exec */
+#define UF_BENEATH 0x02 /* lookups must be beneath this dir */
#ifdef _KERNEL
@@ -284,7 +286,7 @@
int fget_cap_noref(struct filedesc *fdp, int fd, cap_rights_t *needrightsp,
struct file **fpp, struct filecaps *havecapsp);
int fget_cap(struct thread *td, int fd, cap_rights_t *needrightsp,
- struct file **fpp, struct filecaps *havecapsp);
+ uint8_t *flagsp, struct file **fpp, struct filecaps *havecapsp);
/* Return a referenced file from an unlocked descriptor. */
int fget_unlocked(struct thread *td, int fd, cap_rights_t *needrightsp,
struct file **fpp);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Jul 18, 7:23 AM (5 h, 44 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35192079
Default Alt Text
D50371.id155543.diff (8 KB)
Attached To
Mode
D50371: unix: Restrict dirfds exchanged between jails with a different root
Attached
Detach File
Event Timeline
Log In to Comment