Path: blob/main/sys/security/mac_partition/mac_partition.c
39481 views
/*-1* Copyright (c) 1999-2002, 2007-2008 Robert N. M. Watson2* Copyright (c) 2001-2002 Networks Associates Technology, Inc.3* Copyright (c) 2006 SPARTA, Inc.4* Copyright (c) 2008 Apple Inc.5* All rights reserved.6*7* This software was developed by Robert Watson for the TrustedBSD Project.8*9* This software was developed for the FreeBSD Project in part by Network10* Associates Laboratories, the Security Research Division of Network11* Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),12* as part of the DARPA CHATS research program.13*14* This software was enhanced by SPARTA ISSO under SPAWAR contract15* N66001-04-C-6019 ("SEFOS").16*17* Redistribution and use in source and binary forms, with or without18* modification, are permitted provided that the following conditions19* are met:20* 1. Redistributions of source code must retain the above copyright21* notice, this list of conditions and the following disclaimer.22* 2. Redistributions in binary form must reproduce the above copyright23* notice, this list of conditions and the following disclaimer in the24* documentation and/or other materials provided with the distribution.25*26* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND27* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE28* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE29* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE30* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL31* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS32* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)33* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT34* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY35* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF36* SUCH DAMAGE.37*/3839/*40* Developed by the TrustedBSD Project.41*42* Experiment with a partition-like model.43*/4445#include <sys/param.h>46#include <sys/kernel.h>47#include <sys/module.h>48#include <sys/priv.h>49#include <sys/proc.h>50#include <sys/sbuf.h>51#include <sys/socket.h>52#include <sys/socketvar.h>53#include <sys/systm.h>54#include <sys/sysctl.h>5556#include <net/route.h>57#include <netinet/in.h>58#include <netinet/in_pcb.h>5960#include <security/mac/mac_policy.h>61#include <security/mac_partition/mac_partition.h>6263static SYSCTL_NODE(_security_mac, OID_AUTO, partition,64CTLFLAG_RW | CTLFLAG_MPSAFE, 0,65"TrustedBSD mac_partition policy controls");6667static int partition_enabled = 1;68SYSCTL_INT(_security_mac_partition, OID_AUTO, enabled, CTLFLAG_RW,69&partition_enabled, 0, "Enforce partition policy");7071static int partition_slot;72#define SLOT(l) mac_label_get((l), partition_slot)73#define SLOT_SET(l, v) mac_label_set((l), partition_slot, (v))7475static int76partition_check(struct label *subject, struct label *object)77{7879if (partition_enabled == 0)80return (0);8182if (subject == NULL)83return (0);8485if (SLOT(subject) == 0)86return (0);8788/*89* If the object label hasn't been allocated, then it's effectively90* not in a partition, and we know the subject is as it has a label91* and it's not 0, so reject.92*/93if (object == NULL)94return (EPERM);9596if (SLOT(subject) == SLOT(object))97return (0);9899return (EPERM);100}101102/*103* Object-specific entry points are sorted alphabetically by object type name104* and then by operation.105*/106static int107partition_cred_check_relabel(struct ucred *cred, struct label *newlabel)108{109int error;110111error = 0;112113/*114* Treat "0" as a no-op request because it reflects an unset115* partition label. If we ever want to support switching back to an116* unpartitioned state for a process, we'll need to differentiate the117* "not in a partition" and "no partition defined during internalize"118* conditions.119*/120if (SLOT(newlabel) != 0) {121/*122* Require BSD privilege in order to change the partition.123* Originally we also required that the process not be in a124* partition in the first place, but this didn't interact125* well with sendmail.126*/127error = priv_check_cred(cred, PRIV_MAC_PARTITION);128}129130return (error);131}132133static int134partition_cred_check_visible(struct ucred *cr1, struct ucred *cr2)135{136int error;137138error = partition_check(cr1->cr_label, cr2->cr_label);139140return (error == 0 ? 0 : ESRCH);141}142143static void144partition_cred_copy_label(struct label *src, struct label *dest)145{146147if (src != NULL && dest != NULL)148SLOT_SET(dest, SLOT(src));149else if (dest != NULL)150SLOT_SET(dest, 0);151}152153static void154partition_cred_create_init(struct ucred *cred)155{156157SLOT_SET(cred->cr_label, 0);158}159160static void161partition_cred_create_swapper(struct ucred *cred)162{163164SLOT_SET(cred->cr_label, 0);165}166167static void168partition_cred_destroy_label(struct label *label)169{170171SLOT_SET(label, 0);172}173174static int175partition_cred_externalize_label(struct label *label, char *element_name,176struct sbuf *sb, int *claimed)177{178179if (strcmp(MAC_PARTITION_LABEL_NAME, element_name) != 0)180return (0);181182(*claimed)++;183184if (label != NULL) {185if (sbuf_printf(sb, "%jd", (intmax_t)SLOT(label)) == -1)186return (EINVAL);187} else {188if (sbuf_printf(sb, "0") == -1)189return (EINVAL);190}191return (0);192}193194static void195partition_cred_init_label(struct label *label)196{197198SLOT_SET(label, 0);199}200201static int202partition_cred_internalize_label(struct label *label, char *element_name,203char *element_data, int *claimed)204{205206if (strcmp(MAC_PARTITION_LABEL_NAME, element_name) != 0)207return (0);208209(*claimed)++;210SLOT_SET(label, strtol(element_data, NULL, 10));211return (0);212}213214static void215partition_cred_relabel(struct ucred *cred, struct label *newlabel)216{217218if (newlabel != NULL && SLOT(newlabel) != 0)219SLOT_SET(cred->cr_label, SLOT(newlabel));220}221222static int223partition_inpcb_check_visible(struct ucred *cred, struct inpcb *inp,224struct label *inplabel)225{226int error;227228error = partition_check(cred->cr_label, inp->inp_cred->cr_label);229230return (error ? ENOENT : 0);231}232233static int234partition_proc_check_debug(struct ucred *cred, struct proc *p)235{236int error;237238error = partition_check(cred->cr_label, p->p_ucred->cr_label);239240return (error ? ESRCH : 0);241}242243static int244partition_proc_check_sched(struct ucred *cred, struct proc *p)245{246int error;247248error = partition_check(cred->cr_label, p->p_ucred->cr_label);249250return (error ? ESRCH : 0);251}252253static int254partition_proc_check_signal(struct ucred *cred, struct proc *p,255int signum)256{257int error;258259error = partition_check(cred->cr_label, p->p_ucred->cr_label);260261return (error ? ESRCH : 0);262}263264static int265partition_socket_check_visible(struct ucred *cred, struct socket *so,266struct label *solabel)267{268int error;269270error = partition_check(cred->cr_label, so->so_cred->cr_label);271272return (error ? ENOENT : 0);273}274275static int276partition_vnode_check_exec(struct ucred *cred, struct vnode *vp,277struct label *vplabel, struct image_params *imgp,278struct label *execlabel)279{280281if (execlabel != NULL) {282/*283* We currently don't permit labels to be changed at284* exec-time as part of the partition model, so disallow285* non-NULL partition label changes in execlabel.286*/287if (SLOT(execlabel) != 0)288return (EINVAL);289}290291return (0);292}293294static struct mac_policy_ops partition_ops =295{296.mpo_cred_check_relabel = partition_cred_check_relabel,297.mpo_cred_check_visible = partition_cred_check_visible,298.mpo_cred_copy_label = partition_cred_copy_label,299.mpo_cred_create_init = partition_cred_create_init,300.mpo_cred_create_swapper = partition_cred_create_swapper,301.mpo_cred_destroy_label = partition_cred_destroy_label,302.mpo_cred_externalize_label = partition_cred_externalize_label,303.mpo_cred_init_label = partition_cred_init_label,304.mpo_cred_internalize_label = partition_cred_internalize_label,305.mpo_cred_relabel = partition_cred_relabel,306.mpo_inpcb_check_visible = partition_inpcb_check_visible,307.mpo_proc_check_debug = partition_proc_check_debug,308.mpo_proc_check_sched = partition_proc_check_sched,309.mpo_proc_check_signal = partition_proc_check_signal,310.mpo_socket_check_visible = partition_socket_check_visible,311.mpo_vnode_check_exec = partition_vnode_check_exec,312};313314MAC_POLICY_SET(&partition_ops, mac_partition, "TrustedBSD MAC/Partition",315MPC_LOADTIME_FLAG_UNLOADOK, &partition_slot);316317318