1c66b4d8dSRobert Watson /*- 2c66b4d8dSRobert Watson * Copyright (c) 1999-2002 Robert N. M. Watson 3c66b4d8dSRobert Watson * Copyright (c) 2001 Ilmar S. Habibulin 47f53207bSRobert Watson * Copyright (c) 2001-2005 Networks Associates Technology, Inc. 530d239bcSRobert Watson * Copyright (c) 2005-2006 SPARTA, Inc. 6c66b4d8dSRobert Watson * All rights reserved. 7c66b4d8dSRobert Watson * 8c66b4d8dSRobert Watson * This software was developed by Robert Watson and Ilmar Habibulin for the 9c66b4d8dSRobert Watson * TrustedBSD Project. 10c66b4d8dSRobert Watson * 117f53207bSRobert Watson * This software was developed for the FreeBSD Project in part by McAfee 127f53207bSRobert Watson * Research, the Technology Research Division of Network Associates, Inc. 137f53207bSRobert Watson * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the 147f53207bSRobert Watson * DARPA CHATS research program. 15c66b4d8dSRobert Watson * 166758f88eSRobert Watson * This software was enhanced by SPARTA ISSO under SPAWAR contract 176758f88eSRobert Watson * N66001-04-C-6019 ("SEFOS"). 186758f88eSRobert Watson * 19c66b4d8dSRobert Watson * Redistribution and use in source and binary forms, with or without 20c66b4d8dSRobert Watson * modification, are permitted provided that the following conditions 21c66b4d8dSRobert Watson * are met: 22c66b4d8dSRobert Watson * 1. Redistributions of source code must retain the above copyright 23c66b4d8dSRobert Watson * notice, this list of conditions and the following disclaimer. 24c66b4d8dSRobert Watson * 2. Redistributions in binary form must reproduce the above copyright 25c66b4d8dSRobert Watson * notice, this list of conditions and the following disclaimer in the 26c66b4d8dSRobert Watson * documentation and/or other materials provided with the distribution. 27c66b4d8dSRobert Watson * 28c66b4d8dSRobert Watson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 29c66b4d8dSRobert Watson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30c66b4d8dSRobert Watson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31c66b4d8dSRobert Watson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 32c66b4d8dSRobert Watson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33c66b4d8dSRobert Watson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34c66b4d8dSRobert Watson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35c66b4d8dSRobert Watson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36c66b4d8dSRobert Watson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37c66b4d8dSRobert Watson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38c66b4d8dSRobert Watson * SUCH DAMAGE. 39c66b4d8dSRobert Watson */ 40c66b4d8dSRobert Watson 41c66b4d8dSRobert Watson #include <sys/cdefs.h> 42c66b4d8dSRobert Watson __FBSDID("$FreeBSD$"); 43c66b4d8dSRobert Watson 44c66b4d8dSRobert Watson #include "opt_mac.h" 45c66b4d8dSRobert Watson 46c66b4d8dSRobert Watson #include <sys/param.h> 47c66b4d8dSRobert Watson #include <sys/kernel.h> 48c66b4d8dSRobert Watson #include <sys/lock.h> 49c66b4d8dSRobert Watson #include <sys/malloc.h> 50c66b4d8dSRobert Watson #include <sys/mutex.h> 51c66b4d8dSRobert Watson #include <sys/mac.h> 52c66b4d8dSRobert Watson #include <sys/sbuf.h> 53c66b4d8dSRobert Watson #include <sys/systm.h> 54c66b4d8dSRobert Watson #include <sys/mount.h> 55c66b4d8dSRobert Watson #include <sys/file.h> 56c66b4d8dSRobert Watson #include <sys/namei.h> 57c66b4d8dSRobert Watson #include <sys/protosw.h> 58c66b4d8dSRobert Watson #include <sys/socket.h> 59c66b4d8dSRobert Watson #include <sys/socketvar.h> 60c66b4d8dSRobert Watson #include <sys/sysctl.h> 61c66b4d8dSRobert Watson 62c66b4d8dSRobert Watson #include <net/bpfdesc.h> 63c66b4d8dSRobert Watson #include <net/if.h> 64c66b4d8dSRobert Watson #include <net/if_var.h> 65c66b4d8dSRobert Watson 66c66b4d8dSRobert Watson #include <netinet/in.h> 67c66b4d8dSRobert Watson #include <netinet/in_pcb.h> 68c66b4d8dSRobert Watson #include <netinet/ip_var.h> 69c66b4d8dSRobert Watson 70aed55708SRobert Watson #include <security/mac/mac_framework.h> 71c66b4d8dSRobert Watson #include <security/mac/mac_internal.h> 720efd6615SRobert Watson #include <security/mac/mac_policy.h> 73c66b4d8dSRobert Watson 74c66b4d8dSRobert Watson /* 75df3c68e4SRobert Watson * Currently, sockets hold two labels: the label of the socket itself, and a 76df3c68e4SRobert Watson * peer label, which may be used by policies to hold a copy of the label of 77df3c68e4SRobert Watson * any remote endpoint. 78df3c68e4SRobert Watson * 79df3c68e4SRobert Watson * Possibly, this peer label should be maintained at the protocol layer 80df3c68e4SRobert Watson * (inpcb, unpcb, etc), as this would allow protocol-aware code to maintain 81df3c68e4SRobert Watson * the label consistently. For example, it might be copied live from a 82df3c68e4SRobert Watson * remote socket for UNIX domain sockets rather than keeping a local copy on 83df3c68e4SRobert Watson * this endpoint, but be cached and updated based on packets received for 84df3c68e4SRobert Watson * TCP/IP. 85df3c68e4SRobert Watson */ 86df3c68e4SRobert Watson 87c66b4d8dSRobert Watson struct label * 88c66b4d8dSRobert Watson mac_socket_label_alloc(int flag) 89c66b4d8dSRobert Watson { 90c66b4d8dSRobert Watson struct label *label; 91c66b4d8dSRobert Watson int error; 92c66b4d8dSRobert Watson 93c66b4d8dSRobert Watson label = mac_labelzone_alloc(flag); 94c66b4d8dSRobert Watson if (label == NULL) 95c66b4d8dSRobert Watson return (NULL); 96c66b4d8dSRobert Watson 9730d239bcSRobert Watson MAC_CHECK(socket_init_label, label, flag); 98c66b4d8dSRobert Watson if (error) { 9930d239bcSRobert Watson MAC_PERFORM(socket_destroy_label, label); 100c66b4d8dSRobert Watson mac_labelzone_free(label); 101c66b4d8dSRobert Watson return (NULL); 102c66b4d8dSRobert Watson } 103c66b4d8dSRobert Watson return (label); 104c66b4d8dSRobert Watson } 105c66b4d8dSRobert Watson 106c66b4d8dSRobert Watson static struct label * 10730d239bcSRobert Watson mac_socketpeer_label_alloc(int flag) 108c66b4d8dSRobert Watson { 109c66b4d8dSRobert Watson struct label *label; 110c66b4d8dSRobert Watson int error; 111c66b4d8dSRobert Watson 112c66b4d8dSRobert Watson label = mac_labelzone_alloc(flag); 113c66b4d8dSRobert Watson if (label == NULL) 114c66b4d8dSRobert Watson return (NULL); 115c66b4d8dSRobert Watson 11630d239bcSRobert Watson MAC_CHECK(socketpeer_init_label, label, flag); 117c66b4d8dSRobert Watson if (error) { 11830d239bcSRobert Watson MAC_PERFORM(socketpeer_destroy_label, label); 119c66b4d8dSRobert Watson mac_labelzone_free(label); 120c66b4d8dSRobert Watson return (NULL); 121c66b4d8dSRobert Watson } 122c66b4d8dSRobert Watson return (label); 123c66b4d8dSRobert Watson } 124c66b4d8dSRobert Watson 125c66b4d8dSRobert Watson int 12630d239bcSRobert Watson mac_socket_init(struct socket *so, int flag) 127c66b4d8dSRobert Watson { 128c66b4d8dSRobert Watson 129c66b4d8dSRobert Watson so->so_label = mac_socket_label_alloc(flag); 130c66b4d8dSRobert Watson if (so->so_label == NULL) 131c66b4d8dSRobert Watson return (ENOMEM); 13230d239bcSRobert Watson so->so_peerlabel = mac_socketpeer_label_alloc(flag); 133c66b4d8dSRobert Watson if (so->so_peerlabel == NULL) { 134c66b4d8dSRobert Watson mac_socket_label_free(so->so_label); 135c66b4d8dSRobert Watson so->so_label = NULL; 136c66b4d8dSRobert Watson return (ENOMEM); 137c66b4d8dSRobert Watson } 138c66b4d8dSRobert Watson return (0); 139c66b4d8dSRobert Watson } 140c66b4d8dSRobert Watson 141c66b4d8dSRobert Watson void 142c66b4d8dSRobert Watson mac_socket_label_free(struct label *label) 143c66b4d8dSRobert Watson { 144c66b4d8dSRobert Watson 14530d239bcSRobert Watson MAC_PERFORM(socket_destroy_label, label); 146c66b4d8dSRobert Watson mac_labelzone_free(label); 147c66b4d8dSRobert Watson } 148c66b4d8dSRobert Watson 149c66b4d8dSRobert Watson static void 15030d239bcSRobert Watson mac_socketpeer_label_free(struct label *label) 151c66b4d8dSRobert Watson { 152c66b4d8dSRobert Watson 15330d239bcSRobert Watson MAC_PERFORM(socketpeer_destroy_label, label); 154c66b4d8dSRobert Watson mac_labelzone_free(label); 155c66b4d8dSRobert Watson } 156c66b4d8dSRobert Watson 157c66b4d8dSRobert Watson void 15830d239bcSRobert Watson mac_socket_destroy(struct socket *so) 159c66b4d8dSRobert Watson { 160c66b4d8dSRobert Watson 16126ae2b86SRobert Watson mac_socket_label_free(so->so_label); 16226ae2b86SRobert Watson so->so_label = NULL; 16330d239bcSRobert Watson mac_socketpeer_label_free(so->so_peerlabel); 16426ae2b86SRobert Watson so->so_peerlabel = NULL; 165c66b4d8dSRobert Watson } 166c66b4d8dSRobert Watson 167c66b4d8dSRobert Watson void 16830d239bcSRobert Watson mac_socket_copy_label(struct label *src, struct label *dest) 169c66b4d8dSRobert Watson { 170c66b4d8dSRobert Watson 17130d239bcSRobert Watson MAC_PERFORM(socket_copy_label, src, dest); 172c66b4d8dSRobert Watson } 173c66b4d8dSRobert Watson 174c66b4d8dSRobert Watson int 17530d239bcSRobert Watson mac_socket_externalize_label(struct label *label, char *elements, 176c66b4d8dSRobert Watson char *outbuf, size_t outbuflen) 177c66b4d8dSRobert Watson { 178c66b4d8dSRobert Watson int error; 179c66b4d8dSRobert Watson 180c66b4d8dSRobert Watson MAC_EXTERNALIZE(socket, label, elements, outbuf, outbuflen); 181c66b4d8dSRobert Watson 182c66b4d8dSRobert Watson return (error); 183c66b4d8dSRobert Watson } 184c66b4d8dSRobert Watson 185c66b4d8dSRobert Watson static int 18630d239bcSRobert Watson mac_socketpeer_externalize_label(struct label *label, char *elements, 187c66b4d8dSRobert Watson char *outbuf, size_t outbuflen) 188c66b4d8dSRobert Watson { 189c66b4d8dSRobert Watson int error; 190c66b4d8dSRobert Watson 19130d239bcSRobert Watson MAC_EXTERNALIZE(socketpeer, label, elements, outbuf, outbuflen); 192c66b4d8dSRobert Watson 193c66b4d8dSRobert Watson return (error); 194c66b4d8dSRobert Watson } 195c66b4d8dSRobert Watson 196c66b4d8dSRobert Watson int 19730d239bcSRobert Watson mac_socket_internalize_label(struct label *label, char *string) 198c66b4d8dSRobert Watson { 199c66b4d8dSRobert Watson int error; 200c66b4d8dSRobert Watson 201c66b4d8dSRobert Watson MAC_INTERNALIZE(socket, label, string); 202c66b4d8dSRobert Watson 203c66b4d8dSRobert Watson return (error); 204c66b4d8dSRobert Watson } 205c66b4d8dSRobert Watson 206c66b4d8dSRobert Watson void 20730d239bcSRobert Watson mac_socket_create(struct ucred *cred, struct socket *so) 208c66b4d8dSRobert Watson { 209c66b4d8dSRobert Watson 21030d239bcSRobert Watson MAC_PERFORM(socket_create, cred, so, so->so_label); 211c66b4d8dSRobert Watson } 212c66b4d8dSRobert Watson 213c66b4d8dSRobert Watson void 21430d239bcSRobert Watson mac_socket_newconn(struct socket *oldso, struct socket *newso) 215c66b4d8dSRobert Watson { 216c66b4d8dSRobert Watson 21726ae2b86SRobert Watson SOCK_LOCK_ASSERT(oldso); 21826ae2b86SRobert Watson 21930d239bcSRobert Watson MAC_PERFORM(socket_newconn, oldso, oldso->so_label, newso, 22026ae2b86SRobert Watson newso->so_label); 221c66b4d8dSRobert Watson } 222c66b4d8dSRobert Watson 223c66b4d8dSRobert Watson static void 22430d239bcSRobert Watson mac_socket_relabel(struct ucred *cred, struct socket *so, 225c66b4d8dSRobert Watson struct label *newlabel) 226c66b4d8dSRobert Watson { 227c66b4d8dSRobert Watson 22826ae2b86SRobert Watson SOCK_LOCK_ASSERT(so); 22926ae2b86SRobert Watson 23030d239bcSRobert Watson MAC_PERFORM(socket_relabel, cred, so, so->so_label, newlabel); 231c66b4d8dSRobert Watson } 232c66b4d8dSRobert Watson 233c66b4d8dSRobert Watson void 23430d239bcSRobert Watson mac_socketpeer_set_from_mbuf(struct mbuf *m, struct socket *so) 235c66b4d8dSRobert Watson { 236c66b4d8dSRobert Watson struct label *label; 237c66b4d8dSRobert Watson 23826ae2b86SRobert Watson SOCK_LOCK_ASSERT(so); 239310e7cebSRobert Watson 24026ae2b86SRobert Watson label = mac_mbuf_to_label(m); 241c66b4d8dSRobert Watson 24230d239bcSRobert Watson MAC_PERFORM(socketpeer_set_from_mbuf, m, label, so, 24326ae2b86SRobert Watson so->so_peerlabel); 244c66b4d8dSRobert Watson } 245c66b4d8dSRobert Watson 246c66b4d8dSRobert Watson void 24730d239bcSRobert Watson mac_socketpeer_set_from_socket(struct socket *oldso, struct socket *newso) 248c66b4d8dSRobert Watson { 249c66b4d8dSRobert Watson 250310e7cebSRobert Watson /* 251df3c68e4SRobert Watson * XXXRW: only hold the socket lock on one at a time, as one socket 252df3c68e4SRobert Watson * is the original, and one is the new. However, it's called in both 253df3c68e4SRobert Watson * directions, so we can't assert the lock here currently. 254310e7cebSRobert Watson */ 25530d239bcSRobert Watson MAC_PERFORM(socketpeer_set_from_socket, oldso, oldso->so_label, 25626ae2b86SRobert Watson newso, newso->so_peerlabel); 257c66b4d8dSRobert Watson } 258c66b4d8dSRobert Watson 259c66b4d8dSRobert Watson void 26030d239bcSRobert Watson mac_socket_create_mbuf(struct socket *so, struct mbuf *m) 261c66b4d8dSRobert Watson { 262c66b4d8dSRobert Watson struct label *label; 263c66b4d8dSRobert Watson 26426ae2b86SRobert Watson SOCK_LOCK_ASSERT(so); 265c66b4d8dSRobert Watson 26626ae2b86SRobert Watson label = mac_mbuf_to_label(m); 26726ae2b86SRobert Watson 26830d239bcSRobert Watson MAC_PERFORM(socket_create_mbuf, so, so->so_label, m, label); 269c66b4d8dSRobert Watson } 270c66b4d8dSRobert Watson 271c66b4d8dSRobert Watson int 27230d239bcSRobert Watson mac_socket_check_accept(struct ucred *cred, struct socket *so) 2737f53207bSRobert Watson { 2747f53207bSRobert Watson int error; 2757f53207bSRobert Watson 27626ae2b86SRobert Watson SOCK_LOCK_ASSERT(so); 2777f53207bSRobert Watson 27830d239bcSRobert Watson MAC_CHECK(socket_check_accept, cred, so, so->so_label); 2797f53207bSRobert Watson 2807f53207bSRobert Watson return (error); 2817f53207bSRobert Watson } 2827f53207bSRobert Watson 2837f53207bSRobert Watson int 28430d239bcSRobert Watson mac_socket_check_bind(struct ucred *ucred, struct socket *so, 28526ae2b86SRobert Watson struct sockaddr *sa) 286c66b4d8dSRobert Watson { 287c66b4d8dSRobert Watson int error; 288c66b4d8dSRobert Watson 28926ae2b86SRobert Watson SOCK_LOCK_ASSERT(so); 290310e7cebSRobert Watson 29130d239bcSRobert Watson MAC_CHECK(socket_check_bind, ucred, so, so->so_label, sa); 292c66b4d8dSRobert Watson 293c66b4d8dSRobert Watson return (error); 294c66b4d8dSRobert Watson } 295c66b4d8dSRobert Watson 296c66b4d8dSRobert Watson int 29730d239bcSRobert Watson mac_socket_check_connect(struct ucred *cred, struct socket *so, 29826ae2b86SRobert Watson struct sockaddr *sa) 299c66b4d8dSRobert Watson { 300c66b4d8dSRobert Watson int error; 301c66b4d8dSRobert Watson 30226ae2b86SRobert Watson SOCK_LOCK_ASSERT(so); 303310e7cebSRobert Watson 30430d239bcSRobert Watson MAC_CHECK(socket_check_connect, cred, so, so->so_label, sa); 305c66b4d8dSRobert Watson 306c66b4d8dSRobert Watson return (error); 307c66b4d8dSRobert Watson } 308c66b4d8dSRobert Watson 309c66b4d8dSRobert Watson int 31030d239bcSRobert Watson mac_socket_check_create(struct ucred *cred, int domain, int type, int proto) 3116758f88eSRobert Watson { 3126758f88eSRobert Watson int error; 3136758f88eSRobert Watson 31430d239bcSRobert Watson MAC_CHECK(socket_check_create, cred, domain, type, proto); 3156758f88eSRobert Watson 3166758f88eSRobert Watson return (error); 3176758f88eSRobert Watson } 3186758f88eSRobert Watson 3196758f88eSRobert Watson int 32030d239bcSRobert Watson mac_socket_check_deliver(struct socket *so, struct mbuf *m) 321c66b4d8dSRobert Watson { 322c66b4d8dSRobert Watson struct label *label; 323c66b4d8dSRobert Watson int error; 324c66b4d8dSRobert Watson 32526ae2b86SRobert Watson SOCK_LOCK_ASSERT(so); 326310e7cebSRobert Watson 32726ae2b86SRobert Watson label = mac_mbuf_to_label(m); 328c66b4d8dSRobert Watson 32930d239bcSRobert Watson MAC_CHECK(socket_check_deliver, so, so->so_label, m, label); 330c66b4d8dSRobert Watson 331c66b4d8dSRobert Watson return (error); 332c66b4d8dSRobert Watson } 333c66b4d8dSRobert Watson 334c66b4d8dSRobert Watson int 33530d239bcSRobert Watson mac_socket_check_listen(struct ucred *cred, struct socket *so) 336c66b4d8dSRobert Watson { 337c66b4d8dSRobert Watson int error; 338c66b4d8dSRobert Watson 33926ae2b86SRobert Watson SOCK_LOCK_ASSERT(so); 340310e7cebSRobert Watson 34130d239bcSRobert Watson MAC_CHECK(socket_check_listen, cred, so, so->so_label); 34226ae2b86SRobert Watson 343c66b4d8dSRobert Watson return (error); 344c66b4d8dSRobert Watson } 345c66b4d8dSRobert Watson 346c66b4d8dSRobert Watson int 34730d239bcSRobert Watson mac_socket_check_poll(struct ucred *cred, struct socket *so) 3487f53207bSRobert Watson { 3497f53207bSRobert Watson int error; 3507f53207bSRobert Watson 3517f53207bSRobert Watson SOCK_LOCK_ASSERT(so); 3527f53207bSRobert Watson 35330d239bcSRobert Watson MAC_CHECK(socket_check_poll, cred, so, so->so_label); 35426ae2b86SRobert Watson 3557f53207bSRobert Watson return (error); 3567f53207bSRobert Watson } 3577f53207bSRobert Watson 3587f53207bSRobert Watson int 35930d239bcSRobert Watson mac_socket_check_receive(struct ucred *cred, struct socket *so) 360c66b4d8dSRobert Watson { 361c66b4d8dSRobert Watson int error; 362c66b4d8dSRobert Watson 363310e7cebSRobert Watson SOCK_LOCK_ASSERT(so); 364310e7cebSRobert Watson 36530d239bcSRobert Watson MAC_CHECK(socket_check_receive, cred, so, so->so_label); 366c66b4d8dSRobert Watson 367c66b4d8dSRobert Watson return (error); 368c66b4d8dSRobert Watson } 369c66b4d8dSRobert Watson 370c66b4d8dSRobert Watson static int 37130d239bcSRobert Watson mac_socket_check_relabel(struct ucred *cred, struct socket *so, 372c66b4d8dSRobert Watson struct label *newlabel) 373c66b4d8dSRobert Watson { 374c66b4d8dSRobert Watson int error; 375c66b4d8dSRobert Watson 37626ae2b86SRobert Watson SOCK_LOCK_ASSERT(so); 377310e7cebSRobert Watson 37830d239bcSRobert Watson MAC_CHECK(socket_check_relabel, cred, so, so->so_label, newlabel); 379c66b4d8dSRobert Watson 380c66b4d8dSRobert Watson return (error); 381c66b4d8dSRobert Watson } 382c66b4d8dSRobert Watson 383c66b4d8dSRobert Watson int 38430d239bcSRobert Watson mac_socket_check_send(struct ucred *cred, struct socket *so) 385c66b4d8dSRobert Watson { 386c66b4d8dSRobert Watson int error; 387c66b4d8dSRobert Watson 388310e7cebSRobert Watson SOCK_LOCK_ASSERT(so); 389310e7cebSRobert Watson 39030d239bcSRobert Watson MAC_CHECK(socket_check_send, cred, so, so->so_label); 391c66b4d8dSRobert Watson 392c66b4d8dSRobert Watson return (error); 393c66b4d8dSRobert Watson } 394c66b4d8dSRobert Watson 395c66b4d8dSRobert Watson int 39630d239bcSRobert Watson mac_socket_check_stat(struct ucred *cred, struct socket *so) 3977f53207bSRobert Watson { 3987f53207bSRobert Watson int error; 3997f53207bSRobert Watson 4007f53207bSRobert Watson SOCK_LOCK_ASSERT(so); 4017f53207bSRobert Watson 40230d239bcSRobert Watson MAC_CHECK(socket_check_stat, cred, so, so->so_label); 4037f53207bSRobert Watson 4047f53207bSRobert Watson return (error); 4057f53207bSRobert Watson } 4067f53207bSRobert Watson 4077f53207bSRobert Watson int 40830d239bcSRobert Watson mac_socket_check_visible(struct ucred *cred, struct socket *so) 409c66b4d8dSRobert Watson { 410c66b4d8dSRobert Watson int error; 411c66b4d8dSRobert Watson 41226ae2b86SRobert Watson SOCK_LOCK_ASSERT(so); 413310e7cebSRobert Watson 41430d239bcSRobert Watson MAC_CHECK(socket_check_visible, cred, so, so->so_label); 415c66b4d8dSRobert Watson 416c66b4d8dSRobert Watson return (error); 417c66b4d8dSRobert Watson } 418c66b4d8dSRobert Watson 419c66b4d8dSRobert Watson int 420c66b4d8dSRobert Watson mac_socket_label_set(struct ucred *cred, struct socket *so, 421c66b4d8dSRobert Watson struct label *label) 422c66b4d8dSRobert Watson { 423c66b4d8dSRobert Watson int error; 424c66b4d8dSRobert Watson 425310e7cebSRobert Watson /* 426df3c68e4SRobert Watson * We acquire the socket lock when we perform the test and set, but 427df3c68e4SRobert Watson * have to release it as the pcb code needs to acquire the pcb lock, 428df3c68e4SRobert Watson * which will precede the socket lock in the lock order. However, 429df3c68e4SRobert Watson * this is fine, as any race will simply result in the inpcb being 430df3c68e4SRobert Watson * refreshed twice, but still consistently, as the inpcb code will 431df3c68e4SRobert Watson * acquire the socket lock before refreshing, holding both locks. 432310e7cebSRobert Watson */ 433310e7cebSRobert Watson SOCK_LOCK(so); 43430d239bcSRobert Watson error = mac_socket_check_relabel(cred, so, label); 435310e7cebSRobert Watson if (error) { 436310e7cebSRobert Watson SOCK_UNLOCK(so); 437c66b4d8dSRobert Watson return (error); 438310e7cebSRobert Watson } 439c66b4d8dSRobert Watson 44030d239bcSRobert Watson mac_socket_relabel(cred, so, label); 441310e7cebSRobert Watson SOCK_UNLOCK(so); 442df3c68e4SRobert Watson 443c66b4d8dSRobert Watson /* 444c66b4d8dSRobert Watson * If the protocol has expressed interest in socket layer changes, 445df3c68e4SRobert Watson * such as if it needs to propagate changes to a cached pcb label 446df3c68e4SRobert Watson * from the socket, notify it of the label change while holding the 447df3c68e4SRobert Watson * socket lock. 448c66b4d8dSRobert Watson */ 449c66b4d8dSRobert Watson if (so->so_proto->pr_usrreqs->pru_sosetlabel != NULL) 450c66b4d8dSRobert Watson (so->so_proto->pr_usrreqs->pru_sosetlabel)(so); 451c66b4d8dSRobert Watson 452c66b4d8dSRobert Watson return (0); 453c66b4d8dSRobert Watson } 454c66b4d8dSRobert Watson 455c66b4d8dSRobert Watson int 456c66b4d8dSRobert Watson mac_setsockopt_label(struct ucred *cred, struct socket *so, struct mac *mac) 457c66b4d8dSRobert Watson { 458c66b4d8dSRobert Watson struct label *intlabel; 459c66b4d8dSRobert Watson char *buffer; 460c66b4d8dSRobert Watson int error; 461c66b4d8dSRobert Watson 462c66b4d8dSRobert Watson error = mac_check_structmac_consistent(mac); 463c66b4d8dSRobert Watson if (error) 464c66b4d8dSRobert Watson return (error); 465c66b4d8dSRobert Watson 466c66b4d8dSRobert Watson buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 467c66b4d8dSRobert Watson error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL); 468c66b4d8dSRobert Watson if (error) { 469c66b4d8dSRobert Watson free(buffer, M_MACTEMP); 470c66b4d8dSRobert Watson return (error); 471c66b4d8dSRobert Watson } 472c66b4d8dSRobert Watson 473c66b4d8dSRobert Watson intlabel = mac_socket_label_alloc(M_WAITOK); 47430d239bcSRobert Watson error = mac_socket_internalize_label(intlabel, buffer); 475c66b4d8dSRobert Watson free(buffer, M_MACTEMP); 476c66b4d8dSRobert Watson if (error) 477c66b4d8dSRobert Watson goto out; 478c66b4d8dSRobert Watson 479c66b4d8dSRobert Watson error = mac_socket_label_set(cred, so, intlabel); 480c66b4d8dSRobert Watson out: 481c66b4d8dSRobert Watson mac_socket_label_free(intlabel); 482c66b4d8dSRobert Watson return (error); 483c66b4d8dSRobert Watson } 484c66b4d8dSRobert Watson 485c66b4d8dSRobert Watson int 486c66b4d8dSRobert Watson mac_getsockopt_label(struct ucred *cred, struct socket *so, struct mac *mac) 487c66b4d8dSRobert Watson { 488c66b4d8dSRobert Watson char *buffer, *elements; 489310e7cebSRobert Watson struct label *intlabel; 490c66b4d8dSRobert Watson int error; 491c66b4d8dSRobert Watson 492c66b4d8dSRobert Watson error = mac_check_structmac_consistent(mac); 493c66b4d8dSRobert Watson if (error) 494c66b4d8dSRobert Watson return (error); 495c66b4d8dSRobert Watson 496c66b4d8dSRobert Watson elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 497c66b4d8dSRobert Watson error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL); 498c66b4d8dSRobert Watson if (error) { 499c66b4d8dSRobert Watson free(elements, M_MACTEMP); 500c66b4d8dSRobert Watson return (error); 501c66b4d8dSRobert Watson } 502c66b4d8dSRobert Watson 503c66b4d8dSRobert Watson buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 504310e7cebSRobert Watson intlabel = mac_socket_label_alloc(M_WAITOK); 505310e7cebSRobert Watson SOCK_LOCK(so); 50630d239bcSRobert Watson mac_socket_copy_label(so->so_label, intlabel); 507310e7cebSRobert Watson SOCK_UNLOCK(so); 50830d239bcSRobert Watson error = mac_socket_externalize_label(intlabel, elements, buffer, 509310e7cebSRobert Watson mac->m_buflen); 510310e7cebSRobert Watson mac_socket_label_free(intlabel); 511c66b4d8dSRobert Watson if (error == 0) 512c66b4d8dSRobert Watson error = copyout(buffer, mac->m_string, strlen(buffer)+1); 513c66b4d8dSRobert Watson 514c66b4d8dSRobert Watson free(buffer, M_MACTEMP); 515c66b4d8dSRobert Watson free(elements, M_MACTEMP); 516c66b4d8dSRobert Watson 517c66b4d8dSRobert Watson return (error); 518c66b4d8dSRobert Watson } 519c66b4d8dSRobert Watson 520c66b4d8dSRobert Watson int 521c66b4d8dSRobert Watson mac_getsockopt_peerlabel(struct ucred *cred, struct socket *so, 522c66b4d8dSRobert Watson struct mac *mac) 523c66b4d8dSRobert Watson { 524c66b4d8dSRobert Watson char *elements, *buffer; 525310e7cebSRobert Watson struct label *intlabel; 526c66b4d8dSRobert Watson int error; 527c66b4d8dSRobert Watson 528c66b4d8dSRobert Watson error = mac_check_structmac_consistent(mac); 529c66b4d8dSRobert Watson if (error) 530c66b4d8dSRobert Watson return (error); 531c66b4d8dSRobert Watson 532c66b4d8dSRobert Watson elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 533c66b4d8dSRobert Watson error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL); 534c66b4d8dSRobert Watson if (error) { 535c66b4d8dSRobert Watson free(elements, M_MACTEMP); 536c66b4d8dSRobert Watson return (error); 537c66b4d8dSRobert Watson } 538c66b4d8dSRobert Watson 539c66b4d8dSRobert Watson buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 540310e7cebSRobert Watson intlabel = mac_socket_label_alloc(M_WAITOK); 541310e7cebSRobert Watson SOCK_LOCK(so); 54230d239bcSRobert Watson mac_socket_copy_label(so->so_peerlabel, intlabel); 543310e7cebSRobert Watson SOCK_UNLOCK(so); 54430d239bcSRobert Watson error = mac_socketpeer_externalize_label(intlabel, elements, buffer, 545310e7cebSRobert Watson mac->m_buflen); 546310e7cebSRobert Watson mac_socket_label_free(intlabel); 547c66b4d8dSRobert Watson if (error == 0) 548c66b4d8dSRobert Watson error = copyout(buffer, mac->m_string, strlen(buffer)+1); 549c66b4d8dSRobert Watson 550c66b4d8dSRobert Watson free(buffer, M_MACTEMP); 551c66b4d8dSRobert Watson free(elements, M_MACTEMP); 552c66b4d8dSRobert Watson 553c66b4d8dSRobert Watson return (error); 554c66b4d8dSRobert Watson } 555