17bc82500SRobert Watson /*- 273275908SRobert Watson * Copyright (c) 2002, 2003 Networks Associates Technology, Inc. 37bc82500SRobert Watson * All rights reserved. 47bc82500SRobert Watson * 56201265bSRobert Watson * This software was developed for the FreeBSD Project in part by Network 66201265bSRobert Watson * Associates Laboratories, the Security Research Division of Network 76201265bSRobert Watson * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), 86201265bSRobert Watson * as part of the DARPA CHATS research program. 97bc82500SRobert Watson * 107bc82500SRobert Watson * Redistribution and use in source and binary forms, with or without 117bc82500SRobert Watson * modification, are permitted provided that the following conditions 127bc82500SRobert Watson * are met: 137bc82500SRobert Watson * 1. Redistributions of source code must retain the above copyright 147bc82500SRobert Watson * notice, this list of conditions and the following disclaimer. 157bc82500SRobert Watson * 2. Redistributions in binary form must reproduce the above copyright 167bc82500SRobert Watson * notice, this list of conditions and the following disclaimer in the 177bc82500SRobert Watson * documentation and/or other materials provided with the distribution. 187bc82500SRobert Watson * 197bc82500SRobert Watson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 207bc82500SRobert Watson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 217bc82500SRobert Watson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 227bc82500SRobert Watson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 237bc82500SRobert Watson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 247bc82500SRobert Watson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 257bc82500SRobert Watson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 267bc82500SRobert Watson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 277bc82500SRobert Watson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 287bc82500SRobert Watson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 297bc82500SRobert Watson * SUCH DAMAGE. 307bc82500SRobert Watson */ 31677b542eSDavid E. O'Brien 32677b542eSDavid E. O'Brien #include <sys/cdefs.h> 33677b542eSDavid E. O'Brien __FBSDID("$FreeBSD$"); 34677b542eSDavid E. O'Brien 357bc82500SRobert Watson #include "opt_mac.h" 36f9d0d524SRobert Watson 377bc82500SRobert Watson #include <sys/param.h> 3895fab37eSRobert Watson #include <sys/kernel.h> 3995fab37eSRobert Watson #include <sys/lock.h> 40b656366bSBruce Evans #include <sys/malloc.h> 4195fab37eSRobert Watson #include <sys/mutex.h> 4295fab37eSRobert Watson #include <sys/mac.h> 43f51e5803SRobert Watson #include <sys/sbuf.h> 4495fab37eSRobert Watson #include <sys/systm.h> 4595fab37eSRobert Watson #include <sys/vnode.h> 4695fab37eSRobert Watson #include <sys/pipe.h> 4795fab37eSRobert Watson #include <sys/sysctl.h> 4895fab37eSRobert Watson 4995fab37eSRobert Watson #include <sys/mac_policy.h> 5095fab37eSRobert Watson 5173275908SRobert Watson #include <security/mac/mac_internal.h> 5295fab37eSRobert Watson 53b88c98f6SRobert Watson static int mac_enforce_pipe = 1; 54b88c98f6SRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_pipe, CTLFLAG_RW, 55b88c98f6SRobert Watson &mac_enforce_pipe, 0, "Enforce MAC policy on pipe operations"); 56c031391bSRobert Watson TUNABLE_INT("security.mac.enforce_pipe", &mac_enforce_pipe); 57b88c98f6SRobert Watson 58f050add5SRobert Watson #ifdef MAC_DEBUG 5973275908SRobert Watson static unsigned int nmacpipes; 60b2f0927aSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, pipes, CTLFLAG_RD, 6195fab37eSRobert Watson &nmacpipes, 0, "number of pipes in use"); 62f050add5SRobert Watson #endif 6395fab37eSRobert Watson 6495fab37eSRobert Watson MALLOC_DEFINE(M_MACPIPELABEL, "macpipelabel", "MAC labels for pipes"); 6508bcdc58SRobert Watson 6608bcdc58SRobert Watson void 67f7b951a8SRobert Watson mac_init_pipe_label(struct label *label) 68f7b951a8SRobert Watson { 69f7b951a8SRobert Watson 70f7b951a8SRobert Watson mac_init_label(label); 71f7b951a8SRobert Watson MAC_PERFORM(init_pipe_label, label); 728d8d5ea8SRobert Watson MAC_DEBUG_COUNTER_INC(&nmacpipes); 73f7b951a8SRobert Watson } 74f7b951a8SRobert Watson 7508bcdc58SRobert Watson void 7608bcdc58SRobert Watson mac_init_pipe(struct pipe *pipe) 7708bcdc58SRobert Watson { 7808bcdc58SRobert Watson struct label *label; 7908bcdc58SRobert Watson 80a163d034SWarner Losh label = malloc(sizeof(struct label), M_MACPIPELABEL, M_ZERO|M_WAITOK); 8108bcdc58SRobert Watson pipe->pipe_label = label; 8208bcdc58SRobert Watson pipe->pipe_peer->pipe_label = label; 83f7b951a8SRobert Watson mac_init_pipe_label(label); 8408bcdc58SRobert Watson } 8508bcdc58SRobert Watson 862555374cSRobert Watson void 87f7b951a8SRobert Watson mac_destroy_pipe_label(struct label *label) 88f7b951a8SRobert Watson { 89f7b951a8SRobert Watson 90f7b951a8SRobert Watson MAC_PERFORM(destroy_pipe_label, label); 91f7b951a8SRobert Watson mac_destroy_label(label); 928d8d5ea8SRobert Watson MAC_DEBUG_COUNTER_DEC(&nmacpipes); 93f7b951a8SRobert Watson } 94f7b951a8SRobert Watson 9587807196SRobert Watson void 9687807196SRobert Watson mac_destroy_pipe(struct pipe *pipe) 9708bcdc58SRobert Watson { 9808bcdc58SRobert Watson 99f7b951a8SRobert Watson mac_destroy_pipe_label(pipe->pipe_label); 10087807196SRobert Watson free(pipe->pipe_label, M_MACPIPELABEL); 10187807196SRobert Watson } 10287807196SRobert Watson 1032555374cSRobert Watson void 104f7b951a8SRobert Watson mac_copy_pipe_label(struct label *src, struct label *dest) 105f7b951a8SRobert Watson { 106f7b951a8SRobert Watson 107f7b951a8SRobert Watson MAC_PERFORM(copy_pipe_label, src, dest); 108f7b951a8SRobert Watson } 109f7b951a8SRobert Watson 11073275908SRobert Watson int 111f7b951a8SRobert Watson mac_externalize_pipe_label(struct label *label, char *elements, 11283b7b0edSRobert Watson char *outbuf, size_t outbuflen) 113f7b951a8SRobert Watson { 114f7b951a8SRobert Watson int error; 115f7b951a8SRobert Watson 116da77b2faSRobert Watson MAC_EXTERNALIZE(pipe, label, elements, outbuf, outbuflen); 117f7b951a8SRobert Watson 118f7b951a8SRobert Watson return (error); 119f7b951a8SRobert Watson } 120f7b951a8SRobert Watson 12173275908SRobert Watson int 122f7b951a8SRobert Watson mac_internalize_pipe_label(struct label *label, char *string) 123f7b951a8SRobert Watson { 124f7b951a8SRobert Watson int error; 125f7b951a8SRobert Watson 126da77b2faSRobert Watson MAC_INTERNALIZE(pipe, label, string); 127f7b951a8SRobert Watson 128f7b951a8SRobert Watson return (error); 129f7b951a8SRobert Watson } 130f7b951a8SRobert Watson 13195fab37eSRobert Watson void 13295fab37eSRobert Watson mac_create_pipe(struct ucred *cred, struct pipe *pipe) 13395fab37eSRobert Watson { 13495fab37eSRobert Watson 13595fab37eSRobert Watson MAC_PERFORM(create_pipe, cred, pipe, pipe->pipe_label); 13695fab37eSRobert Watson } 13795fab37eSRobert Watson 13895fab37eSRobert Watson static void 13995fab37eSRobert Watson mac_relabel_pipe(struct ucred *cred, struct pipe *pipe, struct label *newlabel) 14095fab37eSRobert Watson { 14195fab37eSRobert Watson 14295fab37eSRobert Watson MAC_PERFORM(relabel_pipe, cred, pipe, pipe->pipe_label, newlabel); 14395fab37eSRobert Watson } 14495fab37eSRobert Watson 14595fab37eSRobert Watson int 14695fab37eSRobert Watson mac_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe, unsigned long cmd, 14795fab37eSRobert Watson void *data) 14895fab37eSRobert Watson { 14995fab37eSRobert Watson int error; 15095fab37eSRobert Watson 1511aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 1521aa37f53SRobert Watson 1531aa37f53SRobert Watson if (!mac_enforce_pipe) 1541aa37f53SRobert Watson return (0); 1551aa37f53SRobert Watson 15695fab37eSRobert Watson MAC_CHECK(check_pipe_ioctl, cred, pipe, pipe->pipe_label, cmd, data); 15795fab37eSRobert Watson 15895fab37eSRobert Watson return (error); 15995fab37eSRobert Watson } 16095fab37eSRobert Watson 16195fab37eSRobert Watson int 162c024c3eeSRobert Watson mac_check_pipe_poll(struct ucred *cred, struct pipe *pipe) 16395fab37eSRobert Watson { 16495fab37eSRobert Watson int error; 16595fab37eSRobert Watson 1661aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 1671aa37f53SRobert Watson 1681aa37f53SRobert Watson if (!mac_enforce_pipe) 1691aa37f53SRobert Watson return (0); 1701aa37f53SRobert Watson 171c024c3eeSRobert Watson MAC_CHECK(check_pipe_poll, cred, pipe, pipe->pipe_label); 172c024c3eeSRobert Watson 173c024c3eeSRobert Watson return (error); 174c024c3eeSRobert Watson } 175c024c3eeSRobert Watson 176c024c3eeSRobert Watson int 177c024c3eeSRobert Watson mac_check_pipe_read(struct ucred *cred, struct pipe *pipe) 178c024c3eeSRobert Watson { 179c024c3eeSRobert Watson int error; 180c024c3eeSRobert Watson 1811aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 1821aa37f53SRobert Watson 1831aa37f53SRobert Watson if (!mac_enforce_pipe) 1841aa37f53SRobert Watson return (0); 1851aa37f53SRobert Watson 186c024c3eeSRobert Watson MAC_CHECK(check_pipe_read, cred, pipe, pipe->pipe_label); 18795fab37eSRobert Watson 18895fab37eSRobert Watson return (error); 18995fab37eSRobert Watson } 19095fab37eSRobert Watson 19195fab37eSRobert Watson static int 19295fab37eSRobert Watson mac_check_pipe_relabel(struct ucred *cred, struct pipe *pipe, 19395fab37eSRobert Watson struct label *newlabel) 19495fab37eSRobert Watson { 19595fab37eSRobert Watson int error; 19695fab37eSRobert Watson 1971aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 1981aa37f53SRobert Watson 1991aa37f53SRobert Watson if (!mac_enforce_pipe) 2001aa37f53SRobert Watson return (0); 2011aa37f53SRobert Watson 20295fab37eSRobert Watson MAC_CHECK(check_pipe_relabel, cred, pipe, pipe->pipe_label, newlabel); 20395fab37eSRobert Watson 20495fab37eSRobert Watson return (error); 20595fab37eSRobert Watson } 20695fab37eSRobert Watson 20795fab37eSRobert Watson int 208c024c3eeSRobert Watson mac_check_pipe_stat(struct ucred *cred, struct pipe *pipe) 209c024c3eeSRobert Watson { 210c024c3eeSRobert Watson int error; 211c024c3eeSRobert Watson 2121aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 2131aa37f53SRobert Watson 2141aa37f53SRobert Watson if (!mac_enforce_pipe) 2151aa37f53SRobert Watson return (0); 2161aa37f53SRobert Watson 217c024c3eeSRobert Watson MAC_CHECK(check_pipe_stat, cred, pipe, pipe->pipe_label); 218c024c3eeSRobert Watson 219c024c3eeSRobert Watson return (error); 220c024c3eeSRobert Watson } 221c024c3eeSRobert Watson 222c024c3eeSRobert Watson int 223c024c3eeSRobert Watson mac_check_pipe_write(struct ucred *cred, struct pipe *pipe) 224c024c3eeSRobert Watson { 225c024c3eeSRobert Watson int error; 226c024c3eeSRobert Watson 2271aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 2281aa37f53SRobert Watson 2291aa37f53SRobert Watson if (!mac_enforce_pipe) 2301aa37f53SRobert Watson return (0); 2311aa37f53SRobert Watson 232c024c3eeSRobert Watson MAC_CHECK(check_pipe_write, cred, pipe, pipe->pipe_label); 233c024c3eeSRobert Watson 234c024c3eeSRobert Watson return (error); 235c024c3eeSRobert Watson } 236c024c3eeSRobert Watson 237c024c3eeSRobert Watson int 23895fab37eSRobert Watson mac_pipe_label_set(struct ucred *cred, struct pipe *pipe, struct label *label) 23995fab37eSRobert Watson { 24095fab37eSRobert Watson int error; 24195fab37eSRobert Watson 2421aa37f53SRobert Watson PIPE_LOCK_ASSERT(pipe, MA_OWNED); 2431aa37f53SRobert Watson 24495fab37eSRobert Watson error = mac_check_pipe_relabel(cred, pipe, label); 24595fab37eSRobert Watson if (error) 24695fab37eSRobert Watson return (error); 24795fab37eSRobert Watson 24895fab37eSRobert Watson mac_relabel_pipe(cred, pipe, label); 24995fab37eSRobert Watson 25095fab37eSRobert Watson return (0); 25195fab37eSRobert Watson } 252