Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save paigeadelethompson/0fc590bb4ad1b682d6e227dca7097cbf to your computer and use it in GitHub Desktop.
Save paigeadelethompson/0fc590bb4ad1b682d6e227dca7097cbf to your computer and use it in GitHub Desktop.
diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c
index 6ffeab59112b..fca83c74671b 100644
--- a/sys/kern/kern_jail.c
+++ b/sys/kern/kern_jail.c
@@ -325,8 +325,11 @@ sys_jail(struct thread *td, struct jail_args *uap)
struct jail j;
error = copyin(uap->jail, &version, sizeof(uint32_t));
- if (error)
+ if (error) {
+ if (bootverbose)
+ printf("jail: failed to copy version from userspace (error=%d)\n", error);
return (error);
+ }
switch (version) {
case 0:
@@ -336,8 +339,11 @@ sys_jail(struct thread *td, struct jail_args *uap)
/* FreeBSD single IPv4 jails. */
bzero(&j, sizeof(struct jail));
error = copyin(uap->jail, &j0, sizeof(struct jail_v0));
- if (error)
+ if (error) {
+ if (bootverbose)
+ printf("jail: failed to copy jail_v0 structure from userspace (error=%d)\n", error);
return (error);
+ }
j.version = j0.version;
j.path = j0.path;
j.hostname = j0.hostname;
@@ -350,17 +356,24 @@ sys_jail(struct thread *td, struct jail_args *uap)
* Version 1 was used by multi-IPv4 jail implementations
* that never made it into the official kernel.
*/
+ if (bootverbose)
+ printf("jail: unsupported jail API version 1\n");
return (EINVAL);
case 2: /* JAIL_API_VERSION */
/* FreeBSD multi-IPv4/IPv6,noIP jails. */
error = copyin(uap->jail, &j, sizeof(struct jail));
- if (error)
+ if (error) {
+ if (bootverbose)
+ printf("jail: failed to copy jail structure from userspace (error=%d)\n", error);
return (error);
+ }
break;
default:
/* Sci-Fi jails are not supported, sorry. */
+ if (bootverbose)
+ printf("jail: unsupported jail API version %d\n", version);
return (EINVAL);
}
return (kern_jail(td, &j));
@@ -424,20 +437,32 @@ kern_jail(struct thread *td, struct jail *j)
tmplen = MAXPATHLEN + MAXHOSTNAMELEN + MAXHOSTNAMELEN;
#ifdef INET
ip4s = (j->version == 0) ? 1 : j->ip4s;
- if (ip4s > jail_max_af_ips)
+ if (ip4s > jail_max_af_ips) {
+ if (bootverbose)
+ printf("jail: too many IPv4 addresses specified (max=%u)\n", jail_max_af_ips);
return (EINVAL);
+ }
tmplen += ip4s * sizeof(struct in_addr);
#else
- if (j->ip4s > 0)
+ if (j->ip4s > 0) {
+ if (bootverbose)
+ printf("jail: IPv4 addresses specified but INET not compiled in kernel\n");
return (EINVAL);
+ }
#endif
#ifdef INET6
- if (j->ip6s > jail_max_af_ips)
+ if (j->ip6s > jail_max_af_ips) {
+ if (bootverbose)
+ printf("jail: too many IPv6 addresses specified (max=%u)\n", jail_max_af_ips);
return (EINVAL);
+ }
tmplen += j->ip6s * sizeof(struct in6_addr);
#else
- if (j->ip6s > 0)
+ if (j->ip6s > 0) {
+ if (bootverbose)
+ printf("jail: IPv6 addresses specified but INET6 not compiled in kernel\n");
return (EINVAL);
+ }
#endif
u_path = malloc(tmplen, M_TEMP, M_WAITOK);
u_hostname = u_path + MAXPATHLEN;
@@ -459,6 +484,8 @@ kern_jail(struct thread *td, struct jail *j)
error = copyinstr(j->path, u_path, MAXPATHLEN,
&optiov[opt.uio_iovcnt].iov_len);
if (error) {
+ if (bootverbose)
+ printf("jail: failed to copy path from userspace (error=%d)\n", error);
free(u_path, M_TEMP);
return (error);
}
@@ -470,6 +497,8 @@ kern_jail(struct thread *td, struct jail *j)
error = copyinstr(j->hostname, u_hostname, MAXHOSTNAMELEN,
&optiov[opt.uio_iovcnt].iov_len);
if (error) {
+ if (bootverbose)
+ printf("jail: failed to copy hostname from userspace (error=%d)\n", error);
free(u_path, M_TEMP);
return (error);
}
@@ -482,6 +511,8 @@ kern_jail(struct thread *td, struct jail *j)
error = copyinstr(j->jailname, u_name, MAXHOSTNAMELEN,
&optiov[opt.uio_iovcnt].iov_len);
if (error) {
+ if (bootverbose)
+ printf("jail: failed to copy jail name from userspace (error=%d)\n", error);
free(u_path, M_TEMP);
return (error);
}
@@ -498,6 +529,8 @@ kern_jail(struct thread *td, struct jail *j)
else {
error = copyin(j->ip4, u_ip4, optiov[opt.uio_iovcnt].iov_len);
if (error) {
+ if (bootverbose)
+ printf("jail: failed to copy IPv4 addresses from userspace (error=%d)\n", error);
free(u_path, M_TEMP);
return (error);
}
@@ -512,6 +545,8 @@ kern_jail(struct thread *td, struct jail *j)
optiov[opt.uio_iovcnt].iov_len = j->ip6s * sizeof(struct in6_addr);
error = copyin(j->ip6, u_ip6, optiov[opt.uio_iovcnt].iov_len);
if (error) {
+ if (bootverbose)
+ printf("jail: failed to copy IPv6 addresses from userspace (error=%d)\n", error);
free(u_path, M_TEMP);
return (error);
}
@@ -538,12 +573,18 @@ sys_jail_set(struct thread *td, struct jail_set_args *uap)
int error;
/* Check that we have an even number of iovecs. */
- if (uap->iovcnt & 1)
+ if (uap->iovcnt & 1) {
+ if (bootverbose)
+ printf("jail: odd number of iovecs specified (error=EINVAL)\n");
return (EINVAL);
+ }
error = copyinuio(uap->iovp, uap->iovcnt, &auio);
- if (error)
+ if (error) {
+ if (bootverbose)
+ printf("jail: failed to copy in iovecs (error=%d)\n", error);
return (error);
+ }
error = kern_jail_set(td, auio, uap->flags);
freeuio(auio);
return (error);
@@ -651,12 +692,16 @@ prison_ip_copyin(const pr_family_t af, void *op, uint32_t cnt)
*/
for (int i = 0; i < cnt; i++) {
if (!pr_families[af].valid(PR_IP(pip, af, i))) {
+ if (bootverbose)
+ printf("jail: invalid IP address at index %d\n", i);
free(pip, M_PRISON);
return (NULL);
}
if (i + 1 < cnt &&
(cmp(PR_IP(pip, af, 0), PR_IP(pip, af, i + 1)) == 0 ||
cmp(PR_IP(pip, af, i), PR_IP(pip, af, i + 1)) == 0)) {
+ if (bootverbose)
+ printf("jail: duplicate IP address at index %d\n", i + 1);
free(pip, M_PRISON);
return (NULL);
}
@@ -833,8 +878,11 @@ prison_ip_restrict(struct prison *pr, const pr_family_t af,
if (!(pr->pr_flags & pr_families[af].ip_flag)) {
if (new == NULL) {
new = prison_ip_alloc(af, ppip->ips, M_NOWAIT);
- if (new == NULL)
+ if (new == NULL) {
+ if (bootverbose)
+ printf("jail: failed to allocate memory for IP addresses\n");
return (false); /* Redo */
+ }
}
/* This has no user settings, so just copy the parent's list. */
MPASS(new->ips == ppip->ips);
@@ -851,8 +899,11 @@ prison_ip_restrict(struct prison *pr, const pr_family_t af,
if (new == NULL) {
new = prison_ip_alloc(af, pip->ips, M_NOWAIT);
- if (new == NULL)
+ if (new == NULL) {
+ if (bootverbose)
+ printf("jail: failed to allocate memory for IP addresses\n");
return (false); /* Redo */
+ }
}
for (int pi = 0; pi < ppip->ips; pi++)
@@ -893,6 +944,8 @@ prison_ip_restrict(struct prison *pr, const pr_family_t af,
}
}
if (ips == 0) {
+ if (bootverbose)
+ printf("jail: no valid IP addresses remain after restriction\n");
if (newp == NULL || *newp == NULL)
prison_ip_free(new);
new = NULL;
@@ -925,8 +978,11 @@ prison_ip_check(const struct prison *pr, const pr_family_t af,
sx_xlocked(&allprison_lock));
pip = atomic_load_ptr(&pr->pr_addrs[af]);
- if (__predict_false(pip == NULL))
+ if (__predict_false(pip == NULL)) {
+ if (bootverbose)
+ printf("jail: no IP addresses configured for family %d (error=EAFNOSUPPORT)\n", af);
return (EAFNOSUPPORT);
+ }
/* Check the primary IP. */
if (cmp(PR_IP(pip, af, 0), addr) == 0)
@@ -948,6 +1004,8 @@ prison_ip_check(const struct prison *pr, const pr_family_t af,
return (0);
}
+ if (bootverbose)
+ printf("jail: IP address not found in jail (family=%d)\n", af);
return (EADDRNOTAVAIL);
}
@@ -1019,13 +1077,22 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
error = priv_check(td, PRIV_JAIL_SET);
if (!error && (flags & JAIL_ATTACH))
error = priv_check(td, PRIV_JAIL_ATTACH);
- if (error)
+ if (error) {
+ if (bootverbose)
+ printf("jail: insufficient privileges for jail_set (error=%d)\n", error);
return (error);
+ }
mypr = td->td_ucred->cr_prison;
- if ((flags & JAIL_CREATE) && mypr->pr_childmax == 0)
+ if ((flags & JAIL_CREATE) && mypr->pr_childmax == 0) {
+ if (bootverbose)
+ printf("jail: cannot create jail when childmax is 0 (error=EPERM)\n");
return (EPERM);
- if (flags & ~JAIL_SET_MASK)
+ }
+ if (flags & ~JAIL_SET_MASK) {
+ if (bootverbose)
+ printf("jail: invalid flags specified (flags=0x%x)\n", flags);
return (EINVAL);
+ }
/*
* Check all the parameters before committing to anything. Not all
@@ -1038,8 +1105,11 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
* than duplicate it under a different name.
*/
error = vfs_buildopts(optuio, &opts);
- if (error)
+ if (error) {
+ if (bootverbose)
+ printf("jail: failed to build options list (error=%d)\n", error);
return (error);
+ }
#ifdef INET
ip4 = NULL;
#endif
@@ -1084,6 +1154,8 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
else if (error != 0)
goto done_free;
else if (enforce < 0 || enforce > 2) {
+ if (bootverbose)
+ printf("jail: invalid enforce_statfs value %d\n", enforce);
error = EINVAL;
goto done_free;
} else
@@ -1116,6 +1188,8 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
switch (jsys) {
case JAIL_SYS_DISABLE:
if (!jsf->disable) {
+ if (bootverbose)
+ printf("jail: system disable not allowed for %s\n", jsf->name);
error = EINVAL;
goto done_free;
}
@@ -1127,6 +1201,8 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
case JAIL_SYS_INHERIT:
break;
default:
+ if (bootverbose)
+ printf("jail: invalid system flag value %d for %s\n", jsys, jsf->name);
error = EINVAL;
goto done_free;
}
@@ -1134,12 +1210,16 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
}
if ((flags & (JAIL_CREATE | JAIL_ATTACH)) == JAIL_CREATE
&& !(pr_flags & PR_PERSIST)) {
+ if (bootverbose)
+ printf("jail: new jail must persist or attach\n");
error = EINVAL;
vfs_opterror(opts, "new jail must persist or attach");
goto done_errmsg;
}
#ifdef VIMAGE
if ((flags & JAIL_UPDATE) && (ch_flags & PR_VNET)) {
+ if (bootverbose)
+ printf("jail: vnet cannot be changed after creation\n");
error = EINVAL;
vfs_opterror(opts, "vnet cannot be changed after creation");
goto done_errmsg;
@@ -1147,6 +1227,8 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
#endif
#ifdef INET
if ((flags & JAIL_UPDATE) && (ch_flags & PR_IP4_USER)) {
+ if (bootverbose)
+ printf("jail: ip4 cannot be changed after creation\n");
error = EINVAL;
vfs_opterror(opts, "ip4 cannot be changed after creation");
goto done_errmsg;
@@ -1154,6 +1236,8 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
#endif
#ifdef INET6
if ((flags & JAIL_UPDATE) && (ch_flags & PR_IP6_USER)) {
+ if (bootverbose)
+ printf("jail: ip6 cannot be changed after creation\n");
error = EINVAL;
vfs_opterror(opts, "ip6 cannot be changed after creation");
goto done_errmsg;
@@ -1177,6 +1261,8 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
goto done_free;
else {
if (len == 0 || name[len - 1] != '\0') {
+ if (bootverbose)
+ printf("jail: invalid name parameter length or termination\n");
error = EINVAL;
goto done_free;
}
@@ -1195,6 +1281,8 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
ch_flags |= PR_HOST;
pr_flags |= PR_HOST;
if (len == 0 || host[len - 1] != '\0') {
+ if (bootverbose)
+ printf("jail: invalid hostname parameter length or termination\n");
error = EINVAL;
goto done_free;
}
@@ -1213,6 +1301,8 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
ch_flags |= PR_HOST;
pr_flags |= PR_HOST;
if (len == 0 || domain[len - 1] != '\0') {
+ if (bootverbose)
+ printf("jail: invalid domainname parameter length or termination\n");
error = EINVAL;
goto done_free;
}
@@ -1231,6 +1321,8 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
ch_flags |= PR_HOST;
pr_flags |= PR_HOST;
if (len == 0 || uuid[len - 1] != '\0') {
+ if (bootverbose)
+ printf("jail: invalid hostuuid parameter length or termination\n");
error = EINVAL;
goto done_free;
}
@@ -1266,6 +1358,8 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
else if (error != 0)
goto done_free;
else if (ip4s & (sizeof(struct in_addr) - 1)) {
+ if (bootverbose)
+ printf("jail: invalid IPv4 address size alignment\n");
error = EINVAL;
goto done_free;
} else {
@@ -1274,12 +1368,16 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
if (ip4s > 0) {
ip4s /= sizeof(struct in_addr);
if (ip4s > jail_max_af_ips) {
+ if (bootverbose)
+ printf("jail: too many IPv4 addresses (max=%u)\n", jail_max_af_ips);
error = EINVAL;
vfs_opterror(opts, "too many IPv4 addresses");
goto done_errmsg;
}
ip4 = prison_ip_copyin(PR_INET, op, ip4s);
if (ip4 == NULL) {
+ if (bootverbose)
+ printf("jail: failed to copy in IPv4 addresses\n");
error = EINVAL;
goto done_free;
}
@@ -1294,6 +1392,8 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
else if (error != 0)
goto done_free;
else if (ip6s & (sizeof(struct in6_addr) - 1)) {
+ if (bootverbose)
+ printf("jail: invalid IPv6 address size alignment\n");
error = EINVAL;
goto done_free;
} else {
@@ -1302,12 +1402,16 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
if (ip6s > 0) {
ip6s /= sizeof(struct in6_addr);
if (ip6s > jail_max_af_ips) {
+ if (bootverbose)
+ printf("jail: too many IPv6 addresses (max=%u)\n", jail_max_af_ips);
error = EINVAL;
vfs_opterror(opts, "too many IPv6 addresses");
goto done_errmsg;
}
ip6 = prison_ip_copyin(PR_INET6, op, ip6s);
if (ip6 == NULL) {
+ if (bootverbose)
+ printf("jail: failed to copy in IPv6 addresses\n");
error = EINVAL;
goto done_free;
}
@@ -1317,6 +1421,8 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
#if defined(VIMAGE) && (defined(INET) || defined(INET6))
if ((ch_flags & PR_VNET) && (ch_flags & (PR_IP4_USER | PR_IP6_USER))) {
+ if (bootverbose)
+ printf("jail: vnet jails cannot have IP address restrictions\n");
error = EINVAL;
vfs_opterror(opts,
"vnet jails cannot have IP address restrictions");
@@ -1331,12 +1437,16 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
goto done_free;
else {
if (flags & JAIL_UPDATE) {
+ if (bootverbose)
+ printf("jail: osrelease cannot be changed after creation\n");
error = EINVAL;
vfs_opterror(opts,
"osrelease cannot be changed after creation");
goto done_errmsg;
}
if (len == 0 || osrelstr[len - 1] != '\0') {
+ if (bootverbose)
+ printf("jail: invalid osrelease parameter length or termination\n");
error = EINVAL;
goto done_free;
}
@@ -1356,12 +1466,16 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
goto done_free;
else {
if (flags & JAIL_UPDATE) {
+ if (bootverbose)
+ printf("jail: osreldate cannot be changed after creation\n");
error = EINVAL;
vfs_opterror(opts,
"osreldate cannot be changed after creation");
goto done_errmsg;
}
if (osreldt == 0) {
+ if (bootverbose)
+ printf("jail: osreldate cannot be 0\n");
error = EINVAL;
vfs_opterror(opts, "osreldate cannot be 0");
goto done_errmsg;
@@ -1383,12 +1497,17 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
}
if (len == 0 || path[len - 1] != '\0') {
error = EINVAL;
+ if (bootverbose)
+ printf("jail: invalid path length or termination (error=%d)\n", error);
goto done_free;
}
NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, path);
error = namei(&nd);
- if (error)
+ if (error) {
+ if (bootverbose)
+ printf("jail: namei lookup failed for path (error=%d)\n", error);
goto done_free;
+ }
root = nd.ni_vp;
NDFREE_PNBUF(&nd);
g_path = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
@@ -1398,10 +1517,14 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
path = g_path;
} else {
/* exit on other errors */
+ if (bootverbose)
+ printf("jail: failed to get global path (error=%d)\n", error);
goto done_free;
}
if (root->v_type != VDIR) {
error = ENOTDIR;
+ if (bootverbose)
+ printf("jail: root path is not a directory (error=%d)\n", error);
vput(root);
goto done_free;
}
@@ -1427,10 +1550,14 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
if (!prison_isalive(ppr)) {
/* This jail is dying. This process will surely follow. */
error = EAGAIN;
+ if (bootverbose)
+ printf("jail: parent jail is dying (error=%d)\n", error);
goto done_deref;
}
if (jid != 0) {
if (jid < 0) {
+ if (bootverbose)
+ printf("jail: negative jail ID specified (error=%d)\n", EINVAL);
error = EINVAL;
vfs_opterror(opts, "negative jid");
goto done_deref;
@@ -1462,6 +1589,8 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
*/
error = EEXIST;
vfs_opterror(opts, "jail %d already exists", jid);
+ if (bootverbose)
+ printf("jail: attempt to create jail with existing ID %d (error=%d)\n", jid, error);
goto done_deref;
}
if ((pr == NULL)
@@ -1475,6 +1604,8 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
*/
error = ENOENT;
vfs_opterror(opts, "jail %d not found", jid);
+ if (bootverbose)
+ printf("jail: jail %d not found or not visible (error=%d)\n", jid, error);
goto done_deref;
}
}
@@ -1499,6 +1630,8 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
if (pr != NULL) {
if (strncmp(name, ppr->pr_name, namelc - name)
|| ppr->pr_name[namelc - name] != '\0') {
+ if (bootverbose)
+ printf("jail: cannot change jail's parent\n");
error = EINVAL;
vfs_opterror(opts,
"cannot change jail's parent");
@@ -1705,8 +1838,11 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
* Unlike other initial settings, this may return an error.
*/
error = cpuset_create_root(ppr, &pr->pr_cpuset);
- if (error)
+ if (error) {
+ if (bootverbose)
+ printf("jail: failed to create root cpuset (error=%d)\n", error);
goto done_deref;
+ }
mtx_lock(&pr->pr_mtx);
drflags |= PD_LOCKED;
@@ -1748,18 +1884,24 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
if (gotslevel) {
if (slevel < ppr->pr_securelevel) {
error = EPERM;
+ if (bootverbose)
+ printf("jail: attempt to lower securelevel (error=%d)\n", error);
goto done_deref;
}
}
if (gotchildmax) {
if (childmax >= ppr->pr_childmax) {
error = EPERM;
+ if (bootverbose)
+ printf("jail: childmax exceeds parent's limit (error=%d)\n", error);
goto done_deref;
}
}
if (gotenforce) {
if (enforce < ppr->pr_enforce_statfs) {
error = EPERM;
+ if (bootverbose)
+ printf("jail: attempt to lower enforce_statfs (error=%d)\n", error);
goto done_deref;
}
}
@@ -1768,6 +1910,8 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
* devfs_rsnum is a uint16_t
*/
if (rsnum < 0 || rsnum > 65535) {
+ if (bootverbose)
+ printf("jail: invalid devfs ruleset number (error=%d)\n", EINVAL);
error = EINVAL;
goto done_deref;
}
@@ -1777,6 +1921,8 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
if (jailed(td->td_ucred)) {
if (rsnum > 0 && rsnum != ppr->pr_devfs_rsnum) {
error = EPERM;
+ if (bootverbose)
+ printf("jail: nested jail cannot change devfs ruleset (error=%d)\n", error);
goto done_deref;
} else
rsnum = ppr->pr_devfs_rsnum;
@@ -1788,6 +1934,8 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
!prison_ip_parent_match(ppr->pr_addrs[PR_INET], ip4,
PR_INET)) {
error = EPERM;
+ if (bootverbose)
+ printf("jail: IPv4 addresses not allowed by parent jail (error=%d)\n", error);
goto done_deref;
}
if (!prison_ip_conflict_check(ppr, pr, ip4, PR_INET)) {
@@ -1803,6 +1951,8 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
!prison_ip_parent_match(ppr->pr_addrs[PR_INET6], ip6,
PR_INET6)) {
error = EPERM;
+ if (bootverbose)
+ printf("jail: IPv6 addresses not allowed by parent jail (error=%d)\n", error);
goto done_deref;
}
if (!prison_ip_conflict_check(ppr, pr, ip6, PR_INET6)) {
@@ -1822,6 +1972,8 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
snprintf(namelc = numbuf, sizeof(numbuf), "%d", jid);
else if ((strtoul(namelc, &p, 10) != jid ||
namelc[0] < '1' || namelc[0] > '9') && *p == '\0') {
+ if (bootverbose)
+ printf("jail: name cannot be numeric unless it is the jid\n");
error = EINVAL;
vfs_opterror(opts,
"name cannot be numeric (unless it is the jid)");
@@ -1836,12 +1988,16 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
namelen = strlen(namelc);
if (pnamelen + namelen + 1 > sizeof(pr->pr_name)) {
error = ENAMETOOLONG;
+ if (bootverbose)
+ printf("jail: name too long for jail (error=%d)\n", error);
goto done_deref;
}
FOREACH_PRISON_DESCENDANT(pr, tpr, descend) {
if (strlen(tpr->pr_name) + (namelen - onamelen) >=
sizeof(pr->pr_name)) {
error = ENAMETOOLONG;
+ if (bootverbose)
+ printf("jail: name too long for descendant jail (error=%d)\n", error);
goto done_deref;
}
}
@@ -1849,6 +2005,8 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
pr_allow_diff = pr_allow & ~ppr->pr_allow;
if (pr_allow_diff & ~PR_ALLOW_DIFFERENCES) {
error = EPERM;
+ if (bootverbose)
+ printf("jail: requested permissions not allowed by parent jail (error=%d)\n", error);
goto done_deref;
}
@@ -1860,14 +2018,19 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
mtx_unlock(&pr->pr_mtx);
drflags &= ~PD_LOCKED;
error = osd_jail_call(pr, PR_METHOD_CHECK, opts);
- if (error != 0)
+ if (error != 0) {
+ if (bootverbose)
+ printf("jail: module parameter check failed (error=%d)\n", error);
goto done_deref;
+ }
mtx_lock(&pr->pr_mtx);
drflags |= PD_LOCKED;
/* At this point, all valid parameters should have been noted. */
TAILQ_FOREACH(opt, opts, link) {
if (!opt->seen && strcmp(opt->name, "errmsg")) {
+ if (bootverbose)
+ printf("jail: unknown parameter: %s\n", opt->name);
error = EINVAL;
vfs_opterror(opts, "unknown parameter: %s", opt->name);
goto done_deref;
@@ -2093,12 +2256,18 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
/* Let the modules do their work. */
if (created) {
error = osd_jail_call(pr, PR_METHOD_CREATE, opts);
- if (error)
+ if (error) {
+ if (bootverbose)
+ printf("jail: module create method failed (error=%d)\n", error);
goto done_deref;
+ }
}
error = osd_jail_call(pr, PR_METHOD_SET, opts);
- if (error)
+ if (error) {
+ if (bootverbose)
+ printf("jail: module set method failed (error=%d)\n", error);
goto done_deref;
+ }
/*
* A new prison is now ready to be seen; either it has gained a user
@@ -2304,16 +2473,22 @@ sys_jail_get(struct thread *td, struct jail_get_args *uap)
int error;
/* Check that we have an even number of iovecs. */
- if (uap->iovcnt & 1)
+ if (uap->iovcnt & 1) {
+ if (bootverbose)
+ printf("jail_get: odd number of iovecs (error=%d)\n", EINVAL);
return (EINVAL);
+ }
error = copyinuio(uap->iovp, uap->iovcnt, &auio);
if (error)
return (error);
error = kern_jail_get(td, auio, uap->flags);
- if (error == 0)
+ if (error == 0) {
error = copyout(auio->uio_iov, uap->iovp,
uap->iovcnt * sizeof(struct iovec));
+ if (error && bootverbose)
+ printf("jail: failed to get jail parameters (error=%d)\n", error);
+ }
freeuio(auio);
return (error);
}
@@ -2330,13 +2505,19 @@ kern_jail_get(struct thread *td, struct uio *optuio, int flags)
int drflags, error, errmsg_len, errmsg_pos, i, jid, len, pos;
unsigned f;
- if (flags & ~JAIL_GET_MASK)
+ if (flags & ~JAIL_GET_MASK) {
+ if (bootverbose)
+ printf("jail: invalid flags (error=EINVAL)\n");
return (EINVAL);
+ }
/* Get the parameter list. */
error = vfs_buildopts(optuio, &opts);
- if (error)
+ if (error) {
+ if (bootverbose)
+ printf("jail: failed to build options list (error=%d)\n", error);
return (error);
+ }
errmsg_pos = vfs_getopt_pos(opts, "errmsg");
mypr = td->td_ucred->cr_prison;
pr = NULL;
@@ -2359,6 +2540,8 @@ kern_jail_get(struct thread *td, struct uio *optuio, int flags)
}
error = ENOENT;
vfs_opterror(opts, "no jail after %d", jid);
+ if (bootverbose)
+ printf("jail: no jail found after jid %d (error=%d)\n", jid, error);
goto done;
} else if (error != ENOENT)
goto done;
@@ -2374,12 +2557,16 @@ kern_jail_get(struct thread *td, struct uio *optuio, int flags)
error = ENOENT;
vfs_opterror(opts, "jail %d is dying",
jid);
+ if (bootverbose)
+ printf("jail: jail %d is dying (error=%d)\n", jid, error);
goto done;
}
goto found_prison;
}
error = ENOENT;
vfs_opterror(opts, "jail %d not found", jid);
+ if (bootverbose)
+ printf("jail: jail %d not found (error=%d)\n", jid, error);
goto done;
}
} else if (error != ENOENT)
@@ -2388,6 +2575,8 @@ kern_jail_get(struct thread *td, struct uio *optuio, int flags)
error = vfs_getopt(opts, "name", (void **)&name, &len);
if (error == 0) {
if (len == 0 || name[len - 1] != '\0') {
+ if (bootverbose)
+ printf("jail: invalid name parameter length or termination (error=EINVAL)\n");
error = EINVAL;
goto done;
}
@@ -2553,6 +2742,8 @@ kern_jail_get(struct thread *td, struct uio *optuio, int flags)
/* By now, all parameters should have been noted. */
TAILQ_FOREACH(opt, opts, link) {
if (!opt->seen && strcmp(opt->name, "errmsg")) {
+ if (bootverbose)
+ printf("jail: unknown parameter: %s\n", opt->name);
error = EINVAL;
vfs_opterror(opts, "unknown parameter: %s", opt->name);
goto done;
@@ -2574,8 +2765,11 @@ kern_jail_get(struct thread *td, struct uio *optuio, int flags)
error = copyout(opt->value,
optuio->uio_iov[pos].iov_base,
opt->len);
- if (error)
+ if (error) {
+ if (bootverbose)
+ printf("jail: failed to copy out parameter value (error=%d)\n", error);
break;
+ }
}
}
}
@@ -2618,12 +2812,17 @@ sys_jail_remove(struct thread *td, struct jail_remove_args *uap)
int error;
error = priv_check(td, PRIV_JAIL_REMOVE);
- if (error)
+ if (error) {
+ if (bootverbose)
+ printf("jail: insufficient privileges to remove jail (error=%d)\n", error);
return (error);
+ }
sx_xlock(&allprison_lock);
pr = prison_find_child(td->td_ucred->cr_prison, uap->jid);
if (pr == NULL) {
+ if (bootverbose)
+ printf("jail: jail %d not found for removal\n", uap->jid);
sx_xunlock(&allprison_lock);
return (EINVAL);
}
@@ -2649,18 +2848,25 @@ sys_jail_attach(struct thread *td, struct jail_attach_args *uap)
int error;
error = priv_check(td, PRIV_JAIL_ATTACH);
- if (error)
+ if (error) {
+ if (bootverbose)
+ printf("jail: insufficient privileges to attach to jail (error=%d)\n", error);
return (error);
+ }
sx_slock(&allprison_lock);
pr = prison_find_child(td->td_ucred->cr_prison, uap->jid);
if (pr == NULL) {
+ if (bootverbose)
+ printf("jail: jail %d not found for attachment (error=EINVAL)\n", uap->jid);
sx_sunlock(&allprison_lock);
return (EINVAL);
}
/* Do not allow a process to attach to a prison that is not alive. */
if (!prison_isalive(pr)) {
+ if (bootverbose)
+ printf("jail: cannot attach to non-alive jail %d (error=EINVAL)\n", uap->jid);
mtx_unlock(&pr->pr_mtx);
sx_sunlock(&allprison_lock);
return (EINVAL);
@@ -2696,6 +2902,8 @@ do_jail_attach(struct thread *td, struct prison *pr, int drflags)
/* Let modules do whatever they need to prepare for attaching. */
error = osd_jail_call(pr, PR_METHOD_ATTACH, td);
if (error) {
+ if (bootverbose)
+ printf("jail: module attachment preparation failed (error=%d)\n", error);
prison_deref(pr, drflags);
return (error);
}
@@ -2707,19 +2915,31 @@ do_jail_attach(struct thread *td, struct prison *pr, int drflags)
*/
p = td->td_proc;
error = cpuset_setproc_update_set(p, pr->pr_cpuset);
- if (error)
+ if (error) {
+ if (bootverbose)
+ printf("jail: failed to update CPU set for jail (error=%d)\n", error);
goto e_revert_osd;
+ }
vn_lock(pr->pr_root, LK_EXCLUSIVE | LK_RETRY);
- if ((error = change_dir(pr->pr_root, td)) != 0)
+ if ((error = change_dir(pr->pr_root, td)) != 0) {
+ if (bootverbose)
+ printf("jail: failed to change directory to jail root (error=%d)\n", error);
goto e_unlock;
+ }
#ifdef MAC
- if ((error = mac_vnode_check_chroot(td->td_ucred, pr->pr_root)))
+ if ((error = mac_vnode_check_chroot(td->td_ucred, pr->pr_root))) {
+ if (bootverbose)
+ printf("jail: MAC check failed for jail root (error=%d)\n", error);
goto e_unlock;
+ }
#endif
VOP_UNLOCK(pr->pr_root);
- if ((error = pwd_chroot_chdir(td, pr->pr_root)))
+ if ((error = pwd_chroot_chdir(td, pr->pr_root))) {
+ if (bootverbose)
+ printf("jail: failed to change process root directory (error=%d)\n", error);
goto e_revert_osd;
+ }
newcred = crget();
PROC_LOCK(p);
@@ -2745,6 +2965,8 @@ do_jail_attach(struct thread *td, struct prison *pr, int drflags)
* with it.
*/
if (!prison_isalive(pr)) {
+ if (bootverbose)
+ printf("jail: prison died during credential change, killing process (jid=%d)\n", pr->pr_id);
PROC_LOCK(p);
kern_psignal(p, SIGKILL);
PROC_UNLOCK(p);
@@ -2779,8 +3001,12 @@ prison_find(int prid)
break;
KASSERT(prison_isvalid(pr), ("Found invalid prison %p", pr));
mtx_lock(&pr->pr_mtx);
+ if (bootverbose)
+ printf("jail: found prison %d\n", prid);
return (pr);
}
+ if (bootverbose)
+ printf("jail: prison %d not found\n", prid);
return (NULL);
}
@@ -2917,6 +3143,8 @@ prison_free(struct prison *pr)
* Don't remove the last reference in this context,
* in case there are locks held.
*/
+ if (bootverbose)
+ printf("jail: scheduling deferred free for prison %d\n", pr->pr_id);
taskqueue_enqueue(taskqueue_jail_remove, &pr->pr_task);
}
}
@@ -2934,6 +3162,8 @@ prison_free_not_last(struct prison *pr)
KASSERT(!lastref,
("prison_free_not_last freed last ref on prison %p (jid=%d).",
pr, pr->pr_id));
+ if (lastref && bootverbose)
+ printf("jail: prison_free_not_last unexpectedly freed last ref on prison %d\n", pr->pr_id);
#else
refcount_release(&pr->pr_ref);
#endif
@@ -3052,8 +3282,12 @@ prison_complete(void *context, int pending)
* This could be called to release the last reference, or the last
* user reference (plus the reference held in prison_proc_free).
*/
+ if (bootverbose)
+ printf("jail: completing deferred free for prison %d\n", pr->pr_id);
drflags = prison_lock_xlock(pr, PD_DEREF);
if (pr->pr_flags & PR_COMPLETE_PROC) {
+ if (bootverbose)
+ printf("jail: completing process free for prison %d\n", pr->pr_id);
pr->pr_flags &= ~PR_COMPLETE_PROC;
drflags |= PD_DEUREF;
}
@@ -3469,8 +3703,11 @@ prison_check_af(struct ucred *cred, int af)
{
mtx_lock(&pr->pr_mtx);
if ((pr->pr_flags & PR_IP4) &&
- pr->pr_addrs[PR_INET] == NULL)
+ pr->pr_addrs[PR_INET] == NULL) {
error = EAFNOSUPPORT;
+ if (bootverbose)
+ printf("jail: IPv4 not supported in jail (error=%d)\n", error);
+ }
mtx_unlock(&pr->pr_mtx);
}
break;
@@ -3481,8 +3718,11 @@ prison_check_af(struct ucred *cred, int af)
{
mtx_lock(&pr->pr_mtx);
if ((pr->pr_flags & PR_IP6) &&
- pr->pr_addrs[PR_INET6] == NULL)
+ pr->pr_addrs[PR_INET6] == NULL) {
error = EAFNOSUPPORT;
+ if (bootverbose)
+ printf("jail: IPv6 not supported in jail (error=%d)\n", error);
+ }
mtx_unlock(&pr->pr_mtx);
}
break;
@@ -3492,8 +3732,11 @@ prison_check_af(struct ucred *cred, int af)
case AF_NETLINK:
break;
default:
- if (!(pr->pr_allow & PR_ALLOW_SOCKET_AF))
+ if (!(pr->pr_allow & PR_ALLOW_SOCKET_AF)) {
error = EAFNOSUPPORT;
+ if (bootverbose)
+ printf("jail: address family not allowed in jail (error=%d)\n", error);
+ }
}
return (error);
}
jail: module attachment preparation failed (error=22)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment