diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index f30f89adb98c..f7f80af68c25 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -113,8 +114,8 @@ SYSCTL_PROC(_kern, KERN_PS_STRINGS, ps_strings, CTLTYPE_ULONG|CTLFLAG_RD, NULL, 0, sysctl_kern_ps_strings, "LU", ""); /* XXX This should be vm_size_t. */ -SYSCTL_PROC(_kern, KERN_USRSTACK, usrstack, CTLTYPE_ULONG|CTLFLAG_RD, - NULL, 0, sysctl_kern_usrstack, "LU", ""); +SYSCTL_PROC(_kern, KERN_USRSTACK, usrstack, CTLTYPE_ULONG|CTLFLAG_RD| + CTLFLAG_CAPRD, NULL, 0, sysctl_kern_usrstack, "LU", ""); SYSCTL_PROC(_kern, OID_AUTO, stackprot, CTLTYPE_INT|CTLFLAG_RD, NULL, 0, sysctl_kern_stackprot, "I", ""); diff --git a/sys/kern/kern_mib.c b/sys/kern/kern_mib.c index f829551fcce0..75b3af936d0e 100644 --- a/sys/kern/kern_mib.c +++ b/sys/kern/kern_mib.c @@ -57,7 +57,7 @@ __FBSDID("$FreeBSD$"); SYSCTL_NODE(, 0, sysctl, CTLFLAG_RW, 0, "Sysctl internal magic"); -SYSCTL_NODE(, CTL_KERN, kern, CTLFLAG_RW, 0, +SYSCTL_NODE(, CTL_KERN, kern, CTLFLAG_RW|CTLFLAG_CAPRD, 0, "High kernel, proc, limits &c"); SYSCTL_NODE(, CTL_VM, vm, CTLFLAG_RW, 0, "Virtual memory"); @@ -90,23 +90,23 @@ SYSCTL_NODE(, OID_AUTO, regression, CTLFLAG_RW, 0, SYSCTL_STRING(_kern, OID_AUTO, ident, CTLFLAG_RD|CTLFLAG_MPSAFE, kern_ident, 0, "Kernel identifier"); -SYSCTL_STRING(_kern, KERN_OSRELEASE, osrelease, CTLFLAG_RD|CTLFLAG_MPSAFE, - osrelease, 0, "Operating system release"); +SYSCTL_STRING(_kern, KERN_OSRELEASE, osrelease, CTLFLAG_RD|CTLFLAG_MPSAFE| + CTLFLAG_CAPRD, osrelease, 0, "Operating system release"); -SYSCTL_INT(_kern, KERN_OSREV, osrevision, CTLFLAG_RD, +SYSCTL_INT(_kern, KERN_OSREV, osrevision, CTLFLAG_RD|CTLFLAG_CAPRD, 0, BSD, "Operating system revision"); SYSCTL_STRING(_kern, KERN_VERSION, version, CTLFLAG_RD|CTLFLAG_MPSAFE, version, 0, "Kernel version"); -SYSCTL_STRING(_kern, KERN_OSTYPE, ostype, CTLFLAG_RD|CTLFLAG_MPSAFE, - ostype, 0, "Operating system type"); +SYSCTL_STRING(_kern, KERN_OSTYPE, ostype, CTLFLAG_RD|CTLFLAG_MPSAFE| + CTLFLAG_CAPRD, ostype, 0, "Operating system type"); /* * NOTICE: The *userland* release date is available in * /usr/include/osreldate.h */ -SYSCTL_INT(_kern, KERN_OSRELDATE, osreldate, CTLFLAG_RD, +SYSCTL_INT(_kern, KERN_OSRELDATE, osreldate, CTLFLAG_RD|CTLFLAG_CAPRD, &osreldate, 0, "Kernel release date"); SYSCTL_INT(_kern, KERN_MAXPROC, maxproc, CTLFLAG_RDTUN, @@ -118,24 +118,24 @@ SYSCTL_INT(_kern, KERN_MAXPROCPERUID, maxprocperuid, CTLFLAG_RW, SYSCTL_INT(_kern, OID_AUTO, maxusers, CTLFLAG_RDTUN, &maxusers, 0, "Hint for kernel tuning"); -SYSCTL_INT(_kern, KERN_ARGMAX, argmax, CTLFLAG_RD, +SYSCTL_INT(_kern, KERN_ARGMAX, argmax, CTLFLAG_RD|CTLFLAG_CAPRD, 0, ARG_MAX, "Maximum bytes of argument to execve(2)"); -SYSCTL_INT(_kern, KERN_POSIX1, posix1version, CTLFLAG_RD, +SYSCTL_INT(_kern, KERN_POSIX1, posix1version, CTLFLAG_RD|CTLFLAG_CAPRD, 0, _POSIX_VERSION, "Version of POSIX attempting to comply to"); -SYSCTL_INT(_kern, KERN_NGROUPS, ngroups, CTLFLAG_RDTUN, +SYSCTL_INT(_kern, KERN_NGROUPS, ngroups, CTLFLAG_RDTUN|CTLFLAG_CAPRD, &ngroups_max, 0, "Maximum number of supplemental groups a user can belong to"); -SYSCTL_INT(_kern, KERN_JOB_CONTROL, job_control, CTLFLAG_RD, +SYSCTL_INT(_kern, KERN_JOB_CONTROL, job_control, CTLFLAG_RD|CTLFLAG_CAPRD, 0, 1, "Whether job control is available"); #ifdef _POSIX_SAVED_IDS -SYSCTL_INT(_kern, KERN_SAVED_IDS, saved_ids, CTLFLAG_RD, +SYSCTL_INT(_kern, KERN_SAVED_IDS, saved_ids, CTLFLAG_RD|CTLFLAG_CAPRD, 0, 1, "Whether saved set-group/user ID is available"); #else -SYSCTL_INT(_kern, KERN_SAVED_IDS, saved_ids, CTLFLAG_RD, +SYSCTL_INT(_kern, KERN_SAVED_IDS, saved_ids, CTLFLAG_RD|CTLFLAG_CAPRD, 0, 0, "Whether saved set-group/user ID is available"); #endif @@ -144,13 +144,13 @@ char kernelname[MAXPATHLEN] = "/kernel"; /* XXX bloat */ SYSCTL_STRING(_kern, KERN_BOOTFILE, bootfile, CTLFLAG_RW, kernelname, sizeof kernelname, "Name of kernel file booted"); -SYSCTL_INT(_hw, HW_NCPU, ncpu, CTLFLAG_RD, +SYSCTL_INT(_hw, HW_NCPU, ncpu, CTLFLAG_RD|CTLFLAG_CAPRD, &mp_ncpus, 0, "Number of active CPUs"); -SYSCTL_INT(_hw, HW_BYTEORDER, byteorder, CTLFLAG_RD, +SYSCTL_INT(_hw, HW_BYTEORDER, byteorder, CTLFLAG_RD|CTLFLAG_CAPRD, 0, BYTE_ORDER, "System byte order"); -SYSCTL_INT(_hw, HW_PAGESIZE, pagesize, CTLFLAG_RD, +SYSCTL_INT(_hw, HW_PAGESIZE, pagesize, CTLFLAG_RD|CTLFLAG_CAPRD, 0, PAGE_SIZE, "System memory page size"); static int @@ -167,7 +167,7 @@ sysctl_kern_arnd(SYSCTL_HANDLER_ARGS) } SYSCTL_PROC(_kern, KERN_ARND, arandom, - CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0, + CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_MPSAFE | CTLFLAG_CAPRD, NULL, 0, sysctl_kern_arnd, "", "arc4rand"); static int @@ -448,6 +448,8 @@ FEATURE(compat_freebsd7, "Compatible with FreeBSD 7"); * This is really cheating. These actually live in the libc, something * which I'm not quite sure is a good idea anyway, but in order for * getnext and friends to actually work, we define dummies here. + * + * XXXRW: These probably should be CTLFLAG_CAPRD. */ SYSCTL_STRING(_user, USER_CS_PATH, cs_path, CTLFLAG_RD, "", 0, "PATH that finds all the standard utilities"); diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c index 8d2fddec6b0f..956bf0c873cb 100644 --- a/sys/kern/kern_sysctl.c +++ b/sys/kern/kern_sysctl.c @@ -38,12 +38,14 @@ #include __FBSDID("$FreeBSD$"); +#include "opt_capsicum.h" #include "opt_compat.h" #include "opt_ktrace.h" #include #include #include +#include #include #include #include @@ -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; diff --git a/sys/kern/posix4_mib.c b/sys/kern/posix4_mib.c index 2fb926b8c846..e29978745f34 100644 --- a/sys/kern/posix4_mib.c +++ b/sys/kern/posix4_mib.c @@ -57,7 +57,8 @@ static int p31b_sysctl_proc(SYSCTL_HANDLER_ARGS); SYSCTL_DECL(_p1003_1b); #define P1B_SYSCTL(num, name) \ - SYSCTL_INT(_p1003_1b, num, name, CTLFLAG_RD, facility + num - 1, 0, ""); + SYSCTL_INT(_p1003_1b, num, name, CTLFLAG_RD | CTLFLAG_CAPRD, \ + facility + num - 1, 0, ""); #define P1B_SYSCTL_RW(num, name) \ SYSCTL_PROC(_p1003_1b, num, name, CTLTYPE_INT | CTLFLAG_RW, NULL, num, \ p31b_sysctl_proc, "I", ""); @@ -67,7 +68,7 @@ SYSCTL_DECL(_p1003_1b); SYSCTL_DECL(_kern_p1003_1b); #define P1B_SYSCTL(num, name) \ - SYSCTL_INT(_kern_p1003_1b, OID_AUTO, name, CTLFLAG_RD, \ + SYSCTL_INT(_kern_p1003_1b, OID_AUTO, name, CTLFLAG_RD | CTLFLAG_CAPRD, \ facility + num - 1, 0, ""); #define P1B_SYSCTL_RW(num, name) \ SYSCTL_PROC(_p1003_1b, OID_AUTO, name, CTLTYPE_INT | CTLFLAG_RW, NULL, \ diff --git a/sys/kern/subr_smp.c b/sys/kern/subr_smp.c index caec965d7aa0..d0c5deff04ec 100644 --- a/sys/kern/subr_smp.c +++ b/sys/kern/subr_smp.c @@ -70,25 +70,25 @@ int mp_maxcpus = MAXCPU; volatile int smp_started; u_int mp_maxid; -SYSCTL_NODE(_kern, OID_AUTO, smp, CTLFLAG_RD, NULL, "Kernel SMP"); +SYSCTL_NODE(_kern, OID_AUTO, smp, CTLFLAG_RD|CTLFLAG_CAPRD, NULL, "Kernel SMP"); -SYSCTL_UINT(_kern_smp, OID_AUTO, maxid, CTLFLAG_RD, &mp_maxid, 0, +SYSCTL_INT(_kern_smp, OID_AUTO, maxid, CTLFLAG_RD|CTLFLAG_CAPRD, &mp_maxid, 0, "Max CPU ID."); -SYSCTL_INT(_kern_smp, OID_AUTO, maxcpus, CTLFLAG_RD, &mp_maxcpus, 0, - "Max number of CPUs that the system was compiled for."); +SYSCTL_INT(_kern_smp, OID_AUTO, maxcpus, CTLFLAG_RD|CTLFLAG_CAPRD, &mp_maxcpus, + 0, "Max number of CPUs that the system was compiled for."); int smp_active = 0; /* are the APs allowed to run? */ SYSCTL_INT(_kern_smp, OID_AUTO, active, CTLFLAG_RW, &smp_active, 0, "Number of Auxillary Processors (APs) that were successfully started"); int smp_disabled = 0; /* has smp been disabled? */ -SYSCTL_INT(_kern_smp, OID_AUTO, disabled, CTLFLAG_RDTUN, &smp_disabled, 0, - "SMP has been disabled from the loader"); +SYSCTL_INT(_kern_smp, OID_AUTO, disabled, CTLFLAG_RDTUN|CTLFLAG_CAPRD, + &smp_disabled, 0, "SMP has been disabled from the loader"); TUNABLE_INT("kern.smp.disabled", &smp_disabled); int smp_cpus = 1; /* how many cpu's running */ -SYSCTL_INT(_kern_smp, OID_AUTO, cpus, CTLFLAG_RD, &smp_cpus, 0, +SYSCTL_INT(_kern_smp, OID_AUTO, cpus, CTLFLAG_RD|CTLFLAG_CAPRD, &smp_cpus, 0, "Number of CPUs online"); int smp_topology = 0; /* Which topology we're using. */ diff --git a/sys/sys/sysctl.h b/sys/sys/sysctl.h index b2ebae310158..1e879f550b0f 100644 --- a/sys/sys/sysctl.h +++ b/sys/sys/sysctl.h @@ -88,6 +88,9 @@ struct ctlname { #define CTLFLAG_VNET 0x00020000 /* Prisons with vnet can fiddle */ #define CTLFLAG_RDTUN (CTLFLAG_RD|CTLFLAG_TUN) #define CTLFLAG_DYING 0x00010000 /* oid is being removed */ +#define CTLFLAG_CAPRD 0x00008000 /* Can be read in capability mode */ +#define CTLFLAG_CAPWR 0x00004000 /* Can be written in capability mode */ +#define CTLFLAG_CAPRW (CTLFLAG_CAPRD|CTLFLAG_CAPWR) /* * Secure level. Note that CTLFLAG_SECURE == CTLFLAG_SECURE1. @@ -407,7 +410,8 @@ SYSCTL_ALLOWED_TYPES(UINT64, uint64_t *a; unsigned long long *b; ); * kernel features. */ #define FEATURE(name, desc) \ - SYSCTL_INT(_kern_features, OID_AUTO, name, CTLFLAG_RD, 0, 1, desc) + SYSCTL_INT(_kern_features, OID_AUTO, name, CTLFLAG_RD | CTLFLAG_CAPRD, \ + 0, 1, desc) #endif /* _KERNEL */