Add a limit for child jails via the "children.cur" and "children.max"
parameters. This replaces the simple "allow.jails" permission. Approved by: bz (mentor)
This commit is contained in:
parent
bb8ddc66ea
commit
b97457e2e6
@ -25,7 +25,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd May 27, 2009
|
||||
.Dd June 23, 2009
|
||||
.Dt JAIL 2
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -293,9 +293,9 @@ will fail if:
|
||||
.Bl -tag -width Er
|
||||
.It Bq Er EPERM
|
||||
This process is not allowed to create a jail, either because it is not
|
||||
the super-user, or because it is in a jail where the
|
||||
.Va allow.jails
|
||||
parameter is not set.
|
||||
the super-user, or because it would exceed the jail's
|
||||
.Va children.max
|
||||
limit.
|
||||
.It Bq Er EFAULT
|
||||
.Fa jail
|
||||
points to an address outside the allocated address space of the process.
|
||||
@ -312,9 +312,9 @@ will fail if:
|
||||
.Bl -tag -width Er
|
||||
.It Bq Er EPERM
|
||||
This process is not allowed to create a jail, either because it is not
|
||||
the super-user, or because it is in a jail where the
|
||||
.Va allow.jails
|
||||
parameter is not set.
|
||||
the super-user, or because it would exceed the jail's
|
||||
.Va children.max
|
||||
limit.
|
||||
.It Bq Er EPERM
|
||||
A jail parameter was set to a less restrictive value then the current
|
||||
environment.
|
||||
|
@ -80,6 +80,7 @@ struct prison prison0 = {
|
||||
.pr_uref = 1,
|
||||
.pr_path = "/",
|
||||
.pr_securelevel = -1,
|
||||
.pr_childmax = JAIL_MAX,
|
||||
.pr_hostuuid = "00000000-0000-0000-0000-000000000000",
|
||||
.pr_children = LIST_HEAD_INITIALIZER(&prison0.pr_children),
|
||||
.pr_flags = PR_HOST,
|
||||
@ -152,7 +153,6 @@ static char *pr_allow_names[] = {
|
||||
"allow.chflags",
|
||||
"allow.mount",
|
||||
"allow.quotas",
|
||||
"allow.jails",
|
||||
"allow.socket_af",
|
||||
};
|
||||
|
||||
@ -163,7 +163,6 @@ static char *pr_allow_nonames[] = {
|
||||
"allow.nochflags",
|
||||
"allow.nomount",
|
||||
"allow.noquotas",
|
||||
"allow.nojails",
|
||||
"allow.nosocket_af",
|
||||
};
|
||||
|
||||
@ -479,8 +478,8 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
|
||||
unsigned long hid;
|
||||
size_t namelen, onamelen;
|
||||
int created, cuflags, descend, enforce, error, errmsg_len, errmsg_pos;
|
||||
int gotenforce, gothid, gotslevel, fi, jid, len;
|
||||
int slevel, vfslocked;
|
||||
int gotchildmax, gotenforce, gothid, gotslevel, fi, jid, len, level;
|
||||
int childmax, slevel, vfslocked;
|
||||
#if defined(INET) || defined(INET6)
|
||||
int ii, ij;
|
||||
#endif
|
||||
@ -500,7 +499,7 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
|
||||
if (error)
|
||||
return (error);
|
||||
mypr = ppr = td->td_ucred->cr_prison;
|
||||
if ((flags & JAIL_CREATE) && !(mypr->pr_allow & PR_ALLOW_JAILS))
|
||||
if ((flags & JAIL_CREATE) && mypr->pr_childmax == 0)
|
||||
return (EPERM);
|
||||
if (flags & ~JAIL_SET_MASK)
|
||||
return (EINVAL);
|
||||
@ -544,6 +543,15 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
|
||||
else
|
||||
gotslevel = 1;
|
||||
|
||||
error =
|
||||
vfs_copyopt(opts, "children.max", &childmax, sizeof(childmax));
|
||||
if (error == ENOENT)
|
||||
gotchildmax = 0;
|
||||
else if (error != 0)
|
||||
goto done_free;
|
||||
else
|
||||
gotchildmax = 1;
|
||||
|
||||
error = vfs_copyopt(opts, "enforce_statfs", &enforce, sizeof(enforce));
|
||||
gotenforce = (error == 0);
|
||||
if (gotenforce) {
|
||||
@ -1023,6 +1031,12 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
|
||||
|
||||
/* If there's no prison to update, create a new one and link it in. */
|
||||
if (pr == NULL) {
|
||||
for (tpr = mypr; tpr != NULL; tpr = tpr->pr_parent)
|
||||
if (tpr->pr_childcount >= tpr->pr_childmax) {
|
||||
error = EPERM;
|
||||
vfs_opterror(opts, "prison limit exceeded");
|
||||
goto done_unlock_list;
|
||||
}
|
||||
created = 1;
|
||||
mtx_lock(&ppr->pr_mtx);
|
||||
if (ppr->pr_ref == 0 || (ppr->pr_flags & PR_REMOVE)) {
|
||||
@ -1076,7 +1090,7 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
|
||||
TAILQ_INSERT_TAIL(&allprison, pr, pr_list);
|
||||
LIST_INSERT_HEAD(&ppr->pr_children, pr, pr_sibling);
|
||||
for (tpr = ppr; tpr != NULL; tpr = tpr->pr_parent)
|
||||
tpr->pr_prisoncount++;
|
||||
tpr->pr_childcount++;
|
||||
|
||||
pr->pr_parent = ppr;
|
||||
pr->pr_id = jid;
|
||||
@ -1163,6 +1177,12 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
|
||||
goto done_deref_locked;
|
||||
}
|
||||
}
|
||||
if (gotchildmax) {
|
||||
if (childmax >= ppr->pr_childmax) {
|
||||
error = EPERM;
|
||||
goto done_deref_locked;
|
||||
}
|
||||
}
|
||||
if (gotenforce) {
|
||||
if (enforce < ppr->pr_enforce_statfs) {
|
||||
error = EPERM;
|
||||
@ -1506,6 +1526,14 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
|
||||
if (tpr->pr_securelevel < slevel)
|
||||
tpr->pr_securelevel = slevel;
|
||||
}
|
||||
if (gotchildmax) {
|
||||
pr->pr_childmax = childmax;
|
||||
/* Set all child jails to under this limit. */
|
||||
FOREACH_PRISON_DESCENDANT_LOCKED_LEVEL(pr, tpr, descend, level)
|
||||
if (tpr->pr_childmax > childmax - level)
|
||||
tpr->pr_childmax = childmax > level
|
||||
? childmax - level : 0;
|
||||
}
|
||||
if (gotenforce) {
|
||||
pr->pr_enforce_statfs = enforce;
|
||||
/* Pass this restriction on to the children. */
|
||||
@ -1895,6 +1923,14 @@ kern_jail_get(struct thread *td, struct uio *optuio, int flags)
|
||||
sizeof(pr->pr_securelevel));
|
||||
if (error != 0 && error != ENOENT)
|
||||
goto done_deref;
|
||||
error = vfs_setopt(opts, "children.cur", &pr->pr_childcount,
|
||||
sizeof(pr->pr_childcount));
|
||||
if (error != 0 && error != ENOENT)
|
||||
goto done_deref;
|
||||
error = vfs_setopt(opts, "children.max", &pr->pr_childmax,
|
||||
sizeof(pr->pr_childmax));
|
||||
if (error != 0 && error != ENOENT)
|
||||
goto done_deref;
|
||||
error = vfs_setopts(opts, "host.hostname", pr->pr_hostname);
|
||||
if (error != 0 && error != ENOENT)
|
||||
goto done_deref;
|
||||
@ -2425,7 +2461,7 @@ prison_deref(struct prison *pr, int flags)
|
||||
LIST_REMOVE(pr, pr_sibling);
|
||||
ppr = pr->pr_parent;
|
||||
for (tpr = ppr; tpr != NULL; tpr = tpr->pr_parent)
|
||||
tpr->pr_prisoncount--;
|
||||
tpr->pr_childcount--;
|
||||
sx_downgrade(&allprison_lock);
|
||||
|
||||
#ifdef VIMAGE
|
||||
@ -3878,6 +3914,12 @@ SYSCTL_JAIL_PARAM(, vnet, CTLTYPE_INT | CTLFLAG_RDTUN,
|
||||
SYSCTL_JAIL_PARAM(, dying, CTLTYPE_INT | CTLFLAG_RD,
|
||||
"B", "Jail is in the process of shutting down");
|
||||
|
||||
SYSCTL_JAIL_PARAM_NODE(children, "Number of child jails");
|
||||
SYSCTL_JAIL_PARAM(_children, cur, CTLTYPE_INT | CTLFLAG_RD,
|
||||
"I", "Current number of child jails");
|
||||
SYSCTL_JAIL_PARAM(_children, max, CTLTYPE_INT | CTLFLAG_RW,
|
||||
"I", "Maximum number of child jails");
|
||||
|
||||
SYSCTL_JAIL_PARAM_NODE(host, "Jail host info");
|
||||
SYSCTL_JAIL_PARAM(, nohost, CTLTYPE_INT | CTLFLAG_RW,
|
||||
"BN", "Jail w/ no host info");
|
||||
@ -3921,8 +3963,6 @@ SYSCTL_JAIL_PARAM(_allow, mount, CTLTYPE_INT | CTLFLAG_RW,
|
||||
"B", "Jail may mount/unmount jail-friendly file systems");
|
||||
SYSCTL_JAIL_PARAM(_allow, quotas, CTLTYPE_INT | CTLFLAG_RW,
|
||||
"B", "Jail may set file quotas");
|
||||
SYSCTL_JAIL_PARAM(_allow, jails, CTLTYPE_INT | CTLFLAG_RW,
|
||||
"B", "Jail may create child jails");
|
||||
SYSCTL_JAIL_PARAM(_allow, socket_af, CTLTYPE_INT | CTLFLAG_RW,
|
||||
"B", "Jail may create sockets other than just UNIX/IPv4/IPv6/route");
|
||||
|
||||
@ -3954,6 +3994,7 @@ db_show_prison(struct prison *pr)
|
||||
#endif
|
||||
db_printf(" root = %p\n", pr->pr_root);
|
||||
db_printf(" securelevel = %d\n", pr->pr_securelevel);
|
||||
db_printf(" childcount = %d\n", pr->pr_childcount);
|
||||
db_printf(" child = %p\n", LIST_FIRST(&pr->pr_children));
|
||||
db_printf(" sibling = %p\n", LIST_NEXT(pr, pr_sibling));
|
||||
db_printf(" flags = %x", pr->pr_flags);
|
||||
|
@ -165,13 +165,14 @@ struct prison {
|
||||
struct in6_addr *pr_ip6; /* (p) v6 IPs of jail */
|
||||
LIST_HEAD(, prison) pr_children; /* (a) list of child jails */
|
||||
LIST_ENTRY(prison) pr_sibling; /* (a) next in parent's list */
|
||||
int pr_prisoncount; /* (a) number of child jails */
|
||||
int pr_childcount; /* (a) number of child jails */
|
||||
unsigned pr_allow; /* (p) PR_ALLOW_* flags */
|
||||
int pr_enforce_statfs; /* (p) statfs permission */
|
||||
char pr_domainname[MAXHOSTNAMELEN]; /* (p) jail domainname */
|
||||
char pr_hostuuid[HOSTUUIDLEN]; /* (p) jail hostuuid */
|
||||
unsigned long pr_hostid; /* (p) jail hostid */
|
||||
struct vnet *pr_vnet; /* (c) network stack */
|
||||
int pr_childmax; /* (p) maximum child jails */
|
||||
};
|
||||
#endif /* _KERNEL || _WANT_PRISON */
|
||||
|
||||
@ -197,9 +198,8 @@ struct prison {
|
||||
#define PR_ALLOW_CHFLAGS 0x0008
|
||||
#define PR_ALLOW_MOUNT 0x0010
|
||||
#define PR_ALLOW_QUOTAS 0x0020
|
||||
#define PR_ALLOW_JAILS 0x0040
|
||||
#define PR_ALLOW_SOCKET_AF 0x0080
|
||||
#define PR_ALLOW_ALL 0x00ff
|
||||
#define PR_ALLOW_SOCKET_AF 0x0040
|
||||
#define PR_ALLOW_ALL 0x007f
|
||||
|
||||
/*
|
||||
* OSD methods
|
||||
@ -270,6 +270,23 @@ prison_unlock(struct prison *pr)
|
||||
; \
|
||||
else
|
||||
|
||||
/*
|
||||
* As above, but also keep track of the level descended to.
|
||||
*/
|
||||
#define FOREACH_PRISON_DESCENDANT_LOCKED_LEVEL(ppr, cpr, descend, level)\
|
||||
for ((cpr) = (ppr), (descend) = 1, (level) = 0; \
|
||||
((cpr) = (((descend) && !LIST_EMPTY(&(cpr)->pr_children)) \
|
||||
? (level++, LIST_FIRST(&(cpr)->pr_children)) \
|
||||
: ((cpr) == (ppr) \
|
||||
? NULL \
|
||||
: ((prison_unlock(cpr), \
|
||||
(descend) = LIST_NEXT(cpr, pr_sibling) != NULL) \
|
||||
? LIST_NEXT(cpr, pr_sibling) \
|
||||
: (level--, (cpr)->pr_parent)))));) \
|
||||
if ((descend) ? (prison_lock(cpr), 0) : 1) \
|
||||
; \
|
||||
else
|
||||
|
||||
/*
|
||||
* Attributes of the physical system, and the root of the jail tree.
|
||||
*/
|
||||
|
@ -34,7 +34,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd May 29, 2009
|
||||
.Dd June 23, 2009
|
||||
.Dt JAIL 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -279,6 +279,17 @@ A jail never has a lower securelevel than the default system, but by
|
||||
setting this parameter it may have a higher one.
|
||||
If the system securelevel is changed, any jail securelevels will be at
|
||||
least as secure.
|
||||
.It Va children.max
|
||||
The number of child jails allowed to be created by this jail (or by
|
||||
other jails under this jail).
|
||||
This limit is zero by default, indicating the jail is not allowed to
|
||||
create child jails.
|
||||
See the
|
||||
.Va "Hierarchical Jails"
|
||||
section for more information.
|
||||
.It Va children.cur
|
||||
The number of descendents of this jail, including its own child jails
|
||||
and any jails created under them.
|
||||
.It Va enforce_statfs
|
||||
This determines which information processes in a jail are able to get
|
||||
about mount points.
|
||||
@ -368,10 +379,6 @@ with non-jailed parts of the system.
|
||||
Sockets within a jail are normally restricted to IPv4, IPv6, local
|
||||
(UNIX), and route. This allows access to other protocol stacks that
|
||||
have not had jail functionality added to them.
|
||||
.It Va allow.jails
|
||||
The prison root may create child jails under this jail. See the
|
||||
.Va "Hierarchical Jails"
|
||||
section for more information.
|
||||
.El
|
||||
.El
|
||||
.Pp
|
||||
@ -756,7 +763,7 @@ and
|
||||
.Va kern.hostuuid .
|
||||
.Ss "Hierarchical Jails"
|
||||
By setting a jail's
|
||||
.Va allow.jails
|
||||
.Va children.max
|
||||
parameter, processes within a jail may be able to create jails of their own.
|
||||
These child jails are kept in a hierarchy, with jails only able to see and/or
|
||||
modify the jails they created (or those jails' children).
|
||||
@ -782,8 +789,8 @@ and
|
||||
may not be bypassed in child jails.
|
||||
.Pp
|
||||
A child jail may in turn create its own child jails if its own
|
||||
.Va allow.jails
|
||||
parameter is set (remember it is off by default).
|
||||
.Va children.max
|
||||
parameter is set (remember it is zero by default).
|
||||
These jails are visible to and can be modified by their parent and all
|
||||
ancestors.
|
||||
.Pp
|
||||
|
Loading…
Reference in New Issue
Block a user