Page MenuHomeFreeBSD

D38144.id116105.diff
No OneTemporary

D38144.id116105.diff

diff --git a/sys/kern/kern_jail.c.ident b/sys/kern/kern_jail.c.new
--- a/sys/kern/kern_jail.c.ident
+++ b/sys/kern/kern_jail.c.new
@@ -118,6 +118,7 @@
.pr_flags = PR_HOST|_PR_IP_SADDRSEL,
#endif
.pr_allow = PR_ALLOW_ALL_STATIC,
+ .pr_permid = 1,
};
MTX_SYSINIT(prison0, &prison0.pr_mtx, "jail mutex", MTX_DEF);
@@ -988,6 +989,7 @@
uint64_t pr_allow_diff;
unsigned tallow;
char numbuf[12];
+ static uint64_t init_permid = 2;
error = priv_check(td, PRIV_JAIL_SET);
if (!error && (flags & JAIL_ATTACH))
@@ -1617,6 +1619,7 @@
TASK_INIT(&pr->pr_task, 0, prison_complete, pr);
pr->pr_id = jid;
+ pr->pr_permid = init_permid++;
if (inspr != NULL)
TAILQ_INSERT_BEFORE(inspr, pr, pr_list);
else
@@ -3533,6 +3536,27 @@
if (__predict_false(pr->pr_state != PRISON_STATE_ALIVE))
return (false);
return (true);
+}
+
+/*
+ * Return true if the prison is currently alive. Identified by pr_permid.
+ */
+bool
+prison_isalive_permid(const uint64_t prison_permid)
+{
+ struct prison *pr;
+ bool alive;
+
+ sx_slock(&allprison_lock);
+ TAILQ_FOREACH(pr, &allprison, pr_list) {
+ if (pr->pr_permid == prison_permid) {
+ alive = prison_isalive(pr);
+ sx_unlock(&allprison_lock);
+ return (alive);
+ }
+ }
+ sx_unlock(&allprison_lock);
+ return (false);
}
/*
diff --git a/sys/kern/vfs_export.c.ident b/sys/kern/vfs_export.c
--- a/sys/kern/vfs_export.c.ident
+++ b/sys/kern/vfs_export.c
@@ -52,6 +52,7 @@
#include <sys/mbuf.h>
#include <sys/mount.h>
#include <sys/mutex.h>
+#include <sys/proc.h>
#include <sys/rmlock.h>
#include <sys/refcount.h>
#include <sys/signalvar.h>
@@ -297,10 +298,11 @@
* the structure is described in sys/mount.h
*/
int
-vfs_export(struct mount *mp, struct export_args *argp)
+vfs_export(struct mount *mp, struct export_args *argp, bool prison_check_alive)
{
struct netexport *nep;
int error;
+ uint64_t jail_permid;
if ((argp->ex_flags & (MNT_DELEXPORT | MNT_EXPORTED)) == 0)
return (EINVAL);
@@ -311,13 +313,32 @@
return (EINVAL);
error = 0;
+ jail_permid = curthread->td_ucred->cr_prison->pr_permid;
lockmgr(&mp->mnt_explock, LK_EXCLUSIVE, NULL);
nep = mp->mnt_export;
+ /* If prison_check_alive is passed in as false, do not do the check. */
+ if (prison_check_alive && mp->mnt_exjail > 1)
+ prison_check_alive = prison_isalive_permid(mp->mnt_exjail);
if (argp->ex_flags & MNT_DELEXPORT) {
if (nep == NULL) {
+ KASSERT(mp->mnt_exjail == 0,
+ ("vfs_export: mnt_exjail delexport not 0"));
error = ENOENT;
goto out;
}
+ KASSERT(mp->mnt_exjail != 0,
+ ("vfs_export: mnt_exjail delexport 0"));
+ if (jail_permid == 1 && mp->mnt_exjail != jail_permid &&
+ prison_check_alive) {
+ /* EXDEV will not get logged by mountd(8). */
+ error = EXDEV;
+ goto out;
+ } else if (mp->mnt_exjail != jail_permid &&
+ prison_check_alive) {
+ /* EPERM will get logged by mountd(8). */
+ error = EPERM;
+ goto out;
+ }
if (mp->mnt_flag & MNT_EXPUBLIC) {
vfs_setpublicfs(NULL, NULL, NULL);
MNT_ILOCK(mp);
@@ -326,6 +347,7 @@
}
vfs_free_addrlist(nep);
mp->mnt_export = NULL;
+ mp->mnt_exjail = 0;
free(nep, M_MOUNT);
nep = NULL;
MNT_ILOCK(mp);
@@ -334,8 +356,16 @@
}
if (argp->ex_flags & MNT_EXPORTED) {
if (nep == NULL) {
+ KASSERT(mp->mnt_exjail == 0,
+ ("vfs_export: mnt_exjail not 0"));
nep = malloc(sizeof(struct netexport), M_MOUNT, M_WAITOK | M_ZERO);
mp->mnt_export = nep;
+ } else if (mp->mnt_exjail != jail_permid &&
+ prison_check_alive) {
+ KASSERT(mp->mnt_exjail != 0,
+ ("vfs_export: mnt_exjail 0"));
+ error = EPERM;
+ goto out;
}
if (argp->ex_flags & MNT_EXPUBLIC) {
if ((error = vfs_setpublicfs(mp, nep, argp)) != 0)
@@ -350,6 +380,7 @@
}
if ((error = vfs_hang_addrlist(mp, nep, argp)))
goto out;
+ mp->mnt_exjail = jail_permid;
MNT_ILOCK(mp);
mp->mnt_flag |= MNT_EXPORTED;
MNT_IUNLOCK(mp);
diff --git a/sys/kern/vfs_mount.c.ident b/sys/kern/vfs_mount.c
--- a/sys/kern/vfs_mount.c.ident
+++ b/sys/kern/vfs_mount.c
@@ -158,7 +158,7 @@
mp = (struct mount *)mem;
mtx_init(&mp->mnt_mtx, "struct mount mtx", NULL, MTX_DEF);
mtx_init(&mp->mnt_listmtx, "struct mount vlist mtx", NULL, MTX_DEF);
- lockinit(&mp->mnt_explock, PVFS, "explock", 0, 0);
+ lockinit(&mp->mnt_explock, PVFS, "explock", 0, LK_NOWITNESS);
mp->mnt_pcpu = uma_zalloc_pcpu(pcpu_zone_16, M_WAITOK | M_ZERO);
mp->mnt_ref = 0;
mp->mnt_vfs_ops = 1;
@@ -1471,7 +1471,7 @@
} else
export_error = EINVAL;
if (export_error == 0)
- export_error = vfs_export(mp, &export);
+ export_error = vfs_export(mp, &export, true);
free(export.ex_groups, M_TEMP);
break;
case (sizeof(export)):
@@ -1493,7 +1493,7 @@
else
export_error = EINVAL;
if (export_error == 0)
- export_error = vfs_export(mp, &export);
+ export_error = vfs_export(mp, &export, true);
free(grps, M_TEMP);
break;
default:
diff --git a/sys/sys/jail.h.ident b/sys/sys/jail.h
--- a/sys/sys/jail.h.ident
+++ b/sys/sys/jail.h
@@ -199,6 +199,7 @@
int pr_spare[2];
int pr_osreldate; /* (c) kern.osreldate value */
unsigned long pr_hostid; /* (p) jail hostid */
+ uint64_t pr_permid; /* (c) permanent jail id */
char pr_name[MAXHOSTNAMELEN]; /* (p) admin jail name */
char pr_path[MAXPATHLEN]; /* (c) chroot path */
char pr_hostname[MAXHOSTNAMELEN]; /* (p) jail hostname */
@@ -442,6 +443,7 @@
void prison_set_allow(struct ucred *cred, unsigned flag, int enable);
int prison_ischild(struct prison *, struct prison *);
bool prison_isalive(const struct prison *);
+bool prison_isalive_permid(const uint64_t prison_permid);
bool prison_isvalid(struct prison *);
#if defined(INET) || defined(INET6)
int prison_ip_check(const struct prison *, const pr_family_t, const void *);
diff --git a/sys/sys/mount.h.ident b/sys/sys/mount.h
--- a/sys/sys/mount.h.ident
+++ b/sys/sys/mount.h
@@ -252,6 +252,7 @@
int mnt_secondary_writes; /* (i) # of secondary writes */
int mnt_secondary_accwrites;/* (i) secondary wr. starts */
struct thread *mnt_susp_owner; /* (i) thread owning suspension */
+ uint64_t mnt_exjail; /* exported in jail ident */
#define mnt_endzero mnt_gjprovider
char *mnt_gjprovider; /* gjournal provider name */
struct mtx mnt_listmtx;
@@ -1017,7 +1018,7 @@
void vfs_periodic(struct mount *, int);
int vfs_busy(struct mount *, int);
int vfs_export /* process mount export info */
- (struct mount *, struct export_args *);
+ (struct mount *, struct export_args *, bool);
void vfs_allocate_syncvnode(struct mount *);
void vfs_deallocate_syncvnode(struct mount *);
int vfs_donmount(struct thread *td, uint64_t fsflags,

File Metadata

Mime Type
text/plain
Expires
Thu, May 21, 11:35 PM (12 h, 28 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33409033
Default Alt Text
D38144.id116105.diff (6 KB)

Event Timeline