diff options
author | rwatson <rwatson@FreeBSD.org> | 2011-07-17 23:05:24 +0000 |
---|---|---|
committer | rwatson <rwatson@FreeBSD.org> | 2011-07-17 23:05:24 +0000 |
commit | 7c21db8ed3ea76933360bc701c1cfe99e080cdb5 (patch) | |
tree | c4ed35a8f34e303ea8f9aaebd4a5bb9199dfb0dc /sys/kern/kern_sysctl.c | |
parent | 8c65d0122a45d4d6c8d002377782ad53a7a76d91 (diff) | |
download | FreeBSD-src-7c21db8ed3ea76933360bc701c1cfe99e080cdb5.zip FreeBSD-src-7c21db8ed3ea76933360bc701c1cfe99e080cdb5.tar.gz |
Define two new sysctl node flags: CTLFLAG_CAPRD and CTLFLAG_CAPRW, which
may be jointly referenced via the mask CTLFLAG_CAPRW. Sysctls with these
flags are available in Capsicum's capability mode; other sysctl nodes are
not.
Flag several useful sysctls as available in capability mode, such as memory
layout sysctls required by the run-time linker and malloc(3). Also expose
access to randomness and available kernel features.
A few sysctls are enabled to support name->MIB conversion; these may leak
information to capability mode by virtue of providing resolution on names
not flagged for access in capability mode. This is, generally, not a huge
problem, but might be something to resolve in the future. Flag these cases
with XXX comments.
Submitted by: jonathan
Sponsored by: Google, Inc.
Diffstat (limited to 'sys/kern/kern_sysctl.c')
-rw-r--r-- | sys/kern/kern_sysctl.c | 42 |
1 files changed, 36 insertions, 6 deletions
diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c index 8d2fdde..956bf0c 100644 --- a/sys/kern/kern_sysctl.c +++ b/sys/kern/kern_sysctl.c @@ -38,12 +38,14 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); +#include "opt_capsicum.h" #include "opt_compat.h" #include "opt_ktrace.h" #include <sys/param.h> #include <sys/fail.h> #include <sys/systm.h> +#include <sys/capability.h> #include <sys/kernel.h> #include <sys/sysctl.h> #include <sys/malloc.h> @@ -725,7 +727,12 @@ sysctl_sysctl_name(SYSCTL_HANDLER_ARGS) return (error); } -static SYSCTL_NODE(_sysctl, 1, name, CTLFLAG_RD, sysctl_sysctl_name, ""); +/* + * XXXRW/JA: Shouldn't return name data for nodes that we don't permit in + * capability mode. + */ +static SYSCTL_NODE(_sysctl, 1, name, CTLFLAG_RD | CTLFLAG_CAPRD, + sysctl_sysctl_name, ""); static int sysctl_sysctl_next_ls(struct sysctl_oid_list *lsp, int *name, u_int namelen, @@ -806,7 +813,12 @@ sysctl_sysctl_next(SYSCTL_HANDLER_ARGS) return (error); } -static SYSCTL_NODE(_sysctl, 2, next, CTLFLAG_RD, sysctl_sysctl_next, ""); +/* + * XXXRW/JA: Shouldn't return next data for nodes that we don't permit in + * capability mode. + */ +static SYSCTL_NODE(_sysctl, 2, next, CTLFLAG_RD | CTLFLAG_CAPRD, + sysctl_sysctl_next, ""); static int name2oid(char *name, int *oid, int *len, struct sysctl_oid **oidpp) @@ -902,9 +914,13 @@ sysctl_sysctl_name2oid(SYSCTL_HANDLER_ARGS) return (error); } +/* + * XXXRW/JA: Shouldn't return name2oid data for nodes that we don't permit in + * capability mode. + */ SYSCTL_PROC(_sysctl, 3, name2oid, - CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_MPSAFE, - 0, 0, sysctl_sysctl_name2oid, "I", ""); + CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_MPSAFE + | CTLFLAG_CAPRW, 0, 0, sysctl_sysctl_name2oid, "I", ""); static int sysctl_sysctl_oidfmt(SYSCTL_HANDLER_ARGS) @@ -931,7 +947,7 @@ sysctl_sysctl_oidfmt(SYSCTL_HANDLER_ARGS) } -static SYSCTL_NODE(_sysctl, 4, oidfmt, CTLFLAG_RD|CTLFLAG_MPSAFE, +static SYSCTL_NODE(_sysctl, 4, oidfmt, CTLFLAG_RD|CTLFLAG_MPSAFE|CTLFLAG_CAPRD, sysctl_sysctl_oidfmt, ""); static int @@ -955,7 +971,8 @@ sysctl_sysctl_oiddescr(SYSCTL_HANDLER_ARGS) return (error); } -static SYSCTL_NODE(_sysctl, 5, oiddescr, CTLFLAG_RD, sysctl_sysctl_oiddescr, ""); +static SYSCTL_NODE(_sysctl, 5, oiddescr, CTLFLAG_RD|CTLFLAG_CAPRD, + sysctl_sysctl_oiddescr, ""); /* * Default "handler" functions. @@ -1429,6 +1446,19 @@ sysctl_root(SYSCTL_HANDLER_ARGS) KASSERT(req->td != NULL, ("sysctl_root(): req->td == NULL")); +#ifdef CAPABILITY_MODE + /* + * If the process is in capability mode, then don't permit reading or + * writing unless specifically granted for the node. + */ + if (IN_CAPABILITY_MODE(req->td)) { + if (req->oldptr && !(oid->oid_kind & CTLFLAG_CAPRD)) + return (EPERM); + if (req->newptr && !(oid->oid_kind & CTLFLAG_CAPWR)) + return (EPERM); + } +#endif + /* Is this sysctl sensitive to securelevels? */ if (req->newptr && (oid->oid_kind & CTLFLAG_SECURE)) { lvl = (oid->oid_kind & CTLMASK_SECURE) >> CTLSHIFT_SECURE; |