1db2661ceSRobert Watson /*- 23de40469SRobert Watson * Copyright (c) 1999-2002, 2007-2009 Robert N. M. Watson 3c77cf2b1SRobert Watson * Copyright (c) 2001-2005 Networks Associates Technology, Inc. 430d239bcSRobert Watson * Copyright (c) 2006 SPARTA, Inc. 5db2661ceSRobert Watson * All rights reserved. 6db2661ceSRobert Watson * 7db2661ceSRobert Watson * This software was developed by Robert Watson for the TrustedBSD Project. 8db2661ceSRobert Watson * 9db2661ceSRobert Watson * This software was developed for the FreeBSD Project in part by NAI Labs, 10db2661ceSRobert Watson * the Security Research Division of Network Associates, Inc. under 11db2661ceSRobert Watson * DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA 12db2661ceSRobert Watson * CHATS research program. 13db2661ceSRobert Watson * 1430d239bcSRobert Watson * This software was enhanced by SPARTA ISSO under SPAWAR contract 1530d239bcSRobert Watson * N66001-04-C-6019 ("SEFOS"). 1630d239bcSRobert Watson * 17db2661ceSRobert Watson * Redistribution and use in source and binary forms, with or without 18db2661ceSRobert Watson * modification, are permitted provided that the following conditions 19db2661ceSRobert Watson * are met: 20db2661ceSRobert Watson * 1. Redistributions of source code must retain the above copyright 21db2661ceSRobert Watson * notice, this list of conditions and the following disclaimer. 22db2661ceSRobert Watson * 2. Redistributions in binary form must reproduce the above copyright 23db2661ceSRobert Watson * notice, this list of conditions and the following disclaimer in the 24db2661ceSRobert Watson * documentation and/or other materials provided with the distribution. 25db2661ceSRobert Watson * 26db2661ceSRobert Watson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 27db2661ceSRobert Watson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28db2661ceSRobert Watson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29db2661ceSRobert Watson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 30db2661ceSRobert Watson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31db2661ceSRobert Watson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32db2661ceSRobert Watson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33db2661ceSRobert Watson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34db2661ceSRobert Watson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35db2661ceSRobert Watson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36db2661ceSRobert Watson * SUCH DAMAGE. 37db2661ceSRobert Watson * 38db2661ceSRobert Watson * $FreeBSD$ 39db2661ceSRobert Watson */ 40db2661ceSRobert Watson 41db2661ceSRobert Watson /* 42db2661ceSRobert Watson * Developed by the TrustedBSD Project. 43c14d15aeSRobert Watson * 44db2661ceSRobert Watson * Low-watermark floating label mandatory integrity policy. 45db2661ceSRobert Watson */ 46db2661ceSRobert Watson 47db2661ceSRobert Watson #include <sys/types.h> 48db2661ceSRobert Watson #include <sys/param.h> 49db2661ceSRobert Watson #include <sys/acl.h> 50db2661ceSRobert Watson #include <sys/conf.h> 51db2661ceSRobert Watson #include <sys/extattr.h> 52db2661ceSRobert Watson #include <sys/kernel.h> 53db2661ceSRobert Watson #include <sys/malloc.h> 54c92163dcSChristian S.J. Peron #include <sys/mman.h> 55db2661ceSRobert Watson #include <sys/mount.h> 56acd3428bSRobert Watson #include <sys/priv.h> 57db2661ceSRobert Watson #include <sys/proc.h> 58f51e5803SRobert Watson #include <sys/sbuf.h> 59db2661ceSRobert Watson #include <sys/systm.h> 60db2661ceSRobert Watson #include <sys/sysproto.h> 61db2661ceSRobert Watson #include <sys/sysent.h> 62db2661ceSRobert Watson #include <sys/systm.h> 63db2661ceSRobert Watson #include <sys/vnode.h> 64db2661ceSRobert Watson #include <sys/file.h> 65db2661ceSRobert Watson #include <sys/socket.h> 66db2661ceSRobert Watson #include <sys/socketvar.h> 6736422989SPoul-Henning Kamp #include <sys/sx.h> 68db2661ceSRobert Watson #include <sys/pipe.h> 69db2661ceSRobert Watson #include <sys/sysctl.h> 70db2661ceSRobert Watson #include <sys/syslog.h> 71db2661ceSRobert Watson 72db2661ceSRobert Watson #include <fs/devfs/devfs.h> 73db2661ceSRobert Watson 74db2661ceSRobert Watson #include <net/bpfdesc.h> 75db2661ceSRobert Watson #include <net/if.h> 76db2661ceSRobert Watson #include <net/if_types.h> 77db2661ceSRobert Watson #include <net/if_var.h> 78db2661ceSRobert Watson 79db2661ceSRobert Watson #include <netinet/in.h> 80a557af22SRobert Watson #include <netinet/in_pcb.h> 81db2661ceSRobert Watson #include <netinet/ip_var.h> 82db2661ceSRobert Watson 83db2661ceSRobert Watson #include <vm/vm.h> 84db2661ceSRobert Watson 850efd6615SRobert Watson #include <security/mac/mac_policy.h> 86aed55708SRobert Watson #include <security/mac/mac_framework.h> 87db2661ceSRobert Watson #include <security/mac_lomac/mac_lomac.h> 88db2661ceSRobert Watson 89db2661ceSRobert Watson struct mac_lomac_proc { 90db2661ceSRobert Watson struct mac_lomac mac_lomac; 91db2661ceSRobert Watson struct mtx mtx; 92db2661ceSRobert Watson }; 93db2661ceSRobert Watson 94db2661ceSRobert Watson SYSCTL_DECL(_security_mac); 95db2661ceSRobert Watson 967029da5cSPawel Biernacki static SYSCTL_NODE(_security_mac, OID_AUTO, lomac, 977029da5cSPawel Biernacki CTLFLAG_RW | CTLFLAG_MPSAFE, 0, 98db2661ceSRobert Watson "TrustedBSD mac_lomac policy controls"); 99db2661ceSRobert Watson 1003f1a7a90SRobert Watson static int lomac_label_size = sizeof(struct mac_lomac); 101db2661ceSRobert Watson SYSCTL_INT(_security_mac_lomac, OID_AUTO, label_size, CTLFLAG_RD, 1023f1a7a90SRobert Watson &lomac_label_size, 0, "Size of struct mac_lomac"); 103db2661ceSRobert Watson 1043f1a7a90SRobert Watson static int lomac_enabled = 1; 105af3b2549SHans Petter Selasky SYSCTL_INT(_security_mac_lomac, OID_AUTO, enabled, CTLFLAG_RWTUN, 1063f1a7a90SRobert Watson &lomac_enabled, 0, "Enforce MAC/LOMAC policy"); 107db2661ceSRobert Watson 108db2661ceSRobert Watson static int destroyed_not_inited; 109db2661ceSRobert Watson SYSCTL_INT(_security_mac_lomac, OID_AUTO, destroyed_not_inited, CTLFLAG_RD, 110db2661ceSRobert Watson &destroyed_not_inited, 0, "Count of labels destroyed but not inited"); 111db2661ceSRobert Watson 112db2661ceSRobert Watson static int trust_all_interfaces = 0; 113af3b2549SHans Petter Selasky SYSCTL_INT(_security_mac_lomac, OID_AUTO, trust_all_interfaces, CTLFLAG_RDTUN, 114db2661ceSRobert Watson &trust_all_interfaces, 0, "Consider all interfaces 'trusted' by MAC/LOMAC"); 115db2661ceSRobert Watson 116db2661ceSRobert Watson static char trusted_interfaces[128]; 117af3b2549SHans Petter Selasky SYSCTL_STRING(_security_mac_lomac, OID_AUTO, trusted_interfaces, CTLFLAG_RDTUN, 118db2661ceSRobert Watson trusted_interfaces, 0, "Interfaces considered 'trusted' by MAC/LOMAC"); 119db2661ceSRobert Watson 120db2661ceSRobert Watson static int ptys_equal = 0; 121af3b2549SHans Petter Selasky SYSCTL_INT(_security_mac_lomac, OID_AUTO, ptys_equal, CTLFLAG_RWTUN, 122db2661ceSRobert Watson &ptys_equal, 0, "Label pty devices as lomac/equal on create"); 123db2661ceSRobert Watson 124db2661ceSRobert Watson static int revocation_enabled = 1; 125af3b2549SHans Petter Selasky SYSCTL_INT(_security_mac_lomac, OID_AUTO, revocation_enabled, CTLFLAG_RWTUN, 126db2661ceSRobert Watson &revocation_enabled, 0, "Revoke access to objects on relabel"); 127db2661ceSRobert Watson 1283f1a7a90SRobert Watson static int lomac_slot; 1293f1a7a90SRobert Watson #define SLOT(l) ((struct mac_lomac *)mac_label_get((l), lomac_slot)) 1303f1a7a90SRobert Watson #define SLOT_SET(l, val) mac_label_set((l), lomac_slot, (uintptr_t)(val)) 131db2661ceSRobert Watson #define PSLOT(l) ((struct mac_lomac_proc *) \ 1323f1a7a90SRobert Watson mac_label_get((l), lomac_slot)) 1333f1a7a90SRobert Watson #define PSLOT_SET(l, val) mac_label_set((l), lomac_slot, (uintptr_t)(val)) 134db2661ceSRobert Watson 135d745c852SEd Schouten static MALLOC_DEFINE(M_LOMAC, "mac_lomac_label", "MAC/LOMAC labels"); 136db2661ceSRobert Watson 137db2661ceSRobert Watson static struct mac_lomac * 138db2661ceSRobert Watson lomac_alloc(int flag) 139db2661ceSRobert Watson { 1403f1a7a90SRobert Watson struct mac_lomac *ml; 141db2661ceSRobert Watson 1423f1a7a90SRobert Watson ml = malloc(sizeof(*ml), M_LOMAC, M_ZERO | flag); 143db2661ceSRobert Watson 1443f1a7a90SRobert Watson return (ml); 145db2661ceSRobert Watson } 146db2661ceSRobert Watson 147db2661ceSRobert Watson static void 1483f1a7a90SRobert Watson lomac_free(struct mac_lomac *ml) 149db2661ceSRobert Watson { 150db2661ceSRobert Watson 1513f1a7a90SRobert Watson if (ml != NULL) 1523f1a7a90SRobert Watson free(ml, M_LOMAC); 153db2661ceSRobert Watson else 154db2661ceSRobert Watson atomic_add_int(&destroyed_not_inited, 1); 155db2661ceSRobert Watson } 156db2661ceSRobert Watson 157db2661ceSRobert Watson static int 1583f1a7a90SRobert Watson lomac_atmostflags(struct mac_lomac *ml, int flags) 159db2661ceSRobert Watson { 160db2661ceSRobert Watson 1613f1a7a90SRobert Watson if ((ml->ml_flags & flags) != ml->ml_flags) 162db2661ceSRobert Watson return (EINVAL); 163db2661ceSRobert Watson return (0); 164db2661ceSRobert Watson } 165db2661ceSRobert Watson 166db2661ceSRobert Watson static int 1673f1a7a90SRobert Watson lomac_dominate_element(struct mac_lomac_element *a, 168db2661ceSRobert Watson struct mac_lomac_element *b) 169db2661ceSRobert Watson { 170db2661ceSRobert Watson 171db2661ceSRobert Watson switch (a->mle_type) { 172db2661ceSRobert Watson case MAC_LOMAC_TYPE_EQUAL: 173db2661ceSRobert Watson case MAC_LOMAC_TYPE_HIGH: 174db2661ceSRobert Watson return (1); 175db2661ceSRobert Watson 176db2661ceSRobert Watson case MAC_LOMAC_TYPE_LOW: 177db2661ceSRobert Watson switch (b->mle_type) { 178db2661ceSRobert Watson case MAC_LOMAC_TYPE_GRADE: 179db2661ceSRobert Watson case MAC_LOMAC_TYPE_HIGH: 180db2661ceSRobert Watson return (0); 181db2661ceSRobert Watson 182db2661ceSRobert Watson case MAC_LOMAC_TYPE_EQUAL: 183db2661ceSRobert Watson case MAC_LOMAC_TYPE_LOW: 184db2661ceSRobert Watson return (1); 185db2661ceSRobert Watson 186db2661ceSRobert Watson default: 1873f1a7a90SRobert Watson panic("lomac_dominate_element: b->mle_type invalid"); 188db2661ceSRobert Watson } 189db2661ceSRobert Watson 190db2661ceSRobert Watson case MAC_LOMAC_TYPE_GRADE: 191db2661ceSRobert Watson switch (b->mle_type) { 192db2661ceSRobert Watson case MAC_LOMAC_TYPE_EQUAL: 193db2661ceSRobert Watson case MAC_LOMAC_TYPE_LOW: 194db2661ceSRobert Watson return (1); 195db2661ceSRobert Watson 196db2661ceSRobert Watson case MAC_LOMAC_TYPE_HIGH: 197db2661ceSRobert Watson return (0); 198db2661ceSRobert Watson 199db2661ceSRobert Watson case MAC_LOMAC_TYPE_GRADE: 200db2661ceSRobert Watson return (a->mle_grade >= b->mle_grade); 201db2661ceSRobert Watson 202db2661ceSRobert Watson default: 2033f1a7a90SRobert Watson panic("lomac_dominate_element: b->mle_type invalid"); 204db2661ceSRobert Watson } 205db2661ceSRobert Watson 206db2661ceSRobert Watson default: 2073f1a7a90SRobert Watson panic("lomac_dominate_element: a->mle_type invalid"); 208db2661ceSRobert Watson } 209db2661ceSRobert Watson } 210db2661ceSRobert Watson 211db2661ceSRobert Watson static int 2123f1a7a90SRobert Watson lomac_range_in_range(struct mac_lomac *rangea, struct mac_lomac *rangeb) 213db2661ceSRobert Watson { 214db2661ceSRobert Watson 2153f1a7a90SRobert Watson return (lomac_dominate_element(&rangeb->ml_rangehigh, 216db2661ceSRobert Watson &rangea->ml_rangehigh) && 2173f1a7a90SRobert Watson lomac_dominate_element(&rangea->ml_rangelow, 218db2661ceSRobert Watson &rangeb->ml_rangelow)); 219db2661ceSRobert Watson } 220db2661ceSRobert Watson 221db2661ceSRobert Watson static int 2223f1a7a90SRobert Watson lomac_single_in_range(struct mac_lomac *single, struct mac_lomac *range) 223db2661ceSRobert Watson { 224db2661ceSRobert Watson 225db2661ceSRobert Watson KASSERT((single->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0, 2263f1a7a90SRobert Watson ("lomac_single_in_range: a not single")); 227db2661ceSRobert Watson KASSERT((range->ml_flags & MAC_LOMAC_FLAG_RANGE) != 0, 2283f1a7a90SRobert Watson ("lomac_single_in_range: b not range")); 229db2661ceSRobert Watson 2303f1a7a90SRobert Watson return (lomac_dominate_element(&range->ml_rangehigh, 2313f1a7a90SRobert Watson &single->ml_single) && lomac_dominate_element(&single->ml_single, 232db2661ceSRobert Watson &range->ml_rangelow)); 233db2661ceSRobert Watson } 234db2661ceSRobert Watson 235db2661ceSRobert Watson static int 2363f1a7a90SRobert Watson lomac_auxsingle_in_range(struct mac_lomac *single, struct mac_lomac *range) 237db2661ceSRobert Watson { 238db2661ceSRobert Watson 239db2661ceSRobert Watson KASSERT((single->ml_flags & MAC_LOMAC_FLAG_AUX) != 0, 2403f1a7a90SRobert Watson ("lomac_single_in_range: a not auxsingle")); 241db2661ceSRobert Watson KASSERT((range->ml_flags & MAC_LOMAC_FLAG_RANGE) != 0, 2423f1a7a90SRobert Watson ("lomac_single_in_range: b not range")); 243db2661ceSRobert Watson 2443f1a7a90SRobert Watson return (lomac_dominate_element(&range->ml_rangehigh, 245db2661ceSRobert Watson &single->ml_auxsingle) && 2463f1a7a90SRobert Watson lomac_dominate_element(&single->ml_auxsingle, 247db2661ceSRobert Watson &range->ml_rangelow)); 248db2661ceSRobert Watson } 249db2661ceSRobert Watson 250db2661ceSRobert Watson static int 2513f1a7a90SRobert Watson lomac_dominate_single(struct mac_lomac *a, struct mac_lomac *b) 252db2661ceSRobert Watson { 253db2661ceSRobert Watson KASSERT((a->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0, 2543f1a7a90SRobert Watson ("lomac_dominate_single: a not single")); 255db2661ceSRobert Watson KASSERT((b->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0, 2563f1a7a90SRobert Watson ("lomac_dominate_single: b not single")); 257db2661ceSRobert Watson 2583f1a7a90SRobert Watson return (lomac_dominate_element(&a->ml_single, &b->ml_single)); 259db2661ceSRobert Watson } 260db2661ceSRobert Watson 261db2661ceSRobert Watson static int 2623f1a7a90SRobert Watson lomac_subject_dominate(struct mac_lomac *a, struct mac_lomac *b) 263db2661ceSRobert Watson { 264db2661ceSRobert Watson KASSERT((~a->ml_flags & 265db2661ceSRobert Watson (MAC_LOMAC_FLAG_SINGLE | MAC_LOMAC_FLAG_RANGE)) == 0, 2663f1a7a90SRobert Watson ("lomac_dominate_single: a not subject")); 267db2661ceSRobert Watson KASSERT((b->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0, 2683f1a7a90SRobert Watson ("lomac_dominate_single: b not single")); 269db2661ceSRobert Watson 2703f1a7a90SRobert Watson return (lomac_dominate_element(&a->ml_rangehigh, &b->ml_single)); 271db2661ceSRobert Watson } 272db2661ceSRobert Watson 273db2661ceSRobert Watson static int 2743f1a7a90SRobert Watson lomac_equal_element(struct mac_lomac_element *a, struct mac_lomac_element *b) 275db2661ceSRobert Watson { 276db2661ceSRobert Watson 277db2661ceSRobert Watson if (a->mle_type == MAC_LOMAC_TYPE_EQUAL || 278db2661ceSRobert Watson b->mle_type == MAC_LOMAC_TYPE_EQUAL) 279db2661ceSRobert Watson return (1); 280db2661ceSRobert Watson 281db2661ceSRobert Watson return (a->mle_type == b->mle_type && a->mle_grade == b->mle_grade); 282db2661ceSRobert Watson } 283db2661ceSRobert Watson 284db2661ceSRobert Watson static int 2853f1a7a90SRobert Watson lomac_equal_single(struct mac_lomac *a, struct mac_lomac *b) 286db2661ceSRobert Watson { 287db2661ceSRobert Watson 288db2661ceSRobert Watson KASSERT((a->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0, 2893f1a7a90SRobert Watson ("lomac_equal_single: a not single")); 290db2661ceSRobert Watson KASSERT((b->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0, 2913f1a7a90SRobert Watson ("lomac_equal_single: b not single")); 292db2661ceSRobert Watson 2933f1a7a90SRobert Watson return (lomac_equal_element(&a->ml_single, &b->ml_single)); 294db2661ceSRobert Watson } 295db2661ceSRobert Watson 296db2661ceSRobert Watson static int 2973f1a7a90SRobert Watson lomac_contains_equal(struct mac_lomac *ml) 298db2661ceSRobert Watson { 299db2661ceSRobert Watson 3003f1a7a90SRobert Watson if (ml->ml_flags & MAC_LOMAC_FLAG_SINGLE) 3013f1a7a90SRobert Watson if (ml->ml_single.mle_type == MAC_LOMAC_TYPE_EQUAL) 302db2661ceSRobert Watson return (1); 3033f1a7a90SRobert Watson if (ml->ml_flags & MAC_LOMAC_FLAG_AUX) 3043f1a7a90SRobert Watson if (ml->ml_auxsingle.mle_type == MAC_LOMAC_TYPE_EQUAL) 305db2661ceSRobert Watson return (1); 306db2661ceSRobert Watson 3073f1a7a90SRobert Watson if (ml->ml_flags & MAC_LOMAC_FLAG_RANGE) { 3083f1a7a90SRobert Watson if (ml->ml_rangelow.mle_type == MAC_LOMAC_TYPE_EQUAL) 309db2661ceSRobert Watson return (1); 3103f1a7a90SRobert Watson if (ml->ml_rangehigh.mle_type == MAC_LOMAC_TYPE_EQUAL) 311db2661ceSRobert Watson return (1); 312db2661ceSRobert Watson } 313db2661ceSRobert Watson 314db2661ceSRobert Watson return (0); 315db2661ceSRobert Watson } 316db2661ceSRobert Watson 317db2661ceSRobert Watson static int 3183f1a7a90SRobert Watson lomac_subject_privileged(struct mac_lomac *ml) 319db2661ceSRobert Watson { 320db2661ceSRobert Watson 3213f1a7a90SRobert Watson KASSERT((ml->ml_flags & MAC_LOMAC_FLAGS_BOTH) == 322db2661ceSRobert Watson MAC_LOMAC_FLAGS_BOTH, 3233f1a7a90SRobert Watson ("lomac_subject_privileged: subject doesn't have both labels")); 324db2661ceSRobert Watson 325db2661ceSRobert Watson /* If the single is EQUAL, it's ok. */ 3263f1a7a90SRobert Watson if (ml->ml_single.mle_type == MAC_LOMAC_TYPE_EQUAL) 327db2661ceSRobert Watson return (0); 328db2661ceSRobert Watson 329db2661ceSRobert Watson /* If either range endpoint is EQUAL, it's ok. */ 3303f1a7a90SRobert Watson if (ml->ml_rangelow.mle_type == MAC_LOMAC_TYPE_EQUAL || 3313f1a7a90SRobert Watson ml->ml_rangehigh.mle_type == MAC_LOMAC_TYPE_EQUAL) 332db2661ceSRobert Watson return (0); 333db2661ceSRobert Watson 334db2661ceSRobert Watson /* If the range is low-high, it's ok. */ 3353f1a7a90SRobert Watson if (ml->ml_rangelow.mle_type == MAC_LOMAC_TYPE_LOW && 3363f1a7a90SRobert Watson ml->ml_rangehigh.mle_type == MAC_LOMAC_TYPE_HIGH) 337db2661ceSRobert Watson return (0); 338db2661ceSRobert Watson 339db2661ceSRobert Watson /* It's not ok. */ 340db2661ceSRobert Watson return (EPERM); 341db2661ceSRobert Watson } 342db2661ceSRobert Watson 343db2661ceSRobert Watson static int 3443f1a7a90SRobert Watson lomac_high_single(struct mac_lomac *ml) 345db2661ceSRobert Watson { 346db2661ceSRobert Watson 3473f1a7a90SRobert Watson KASSERT((ml->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0, 3483f1a7a90SRobert Watson ("lomac_high_single: mac_lomac not single")); 349db2661ceSRobert Watson 3503f1a7a90SRobert Watson return (ml->ml_single.mle_type == MAC_LOMAC_TYPE_HIGH); 351db2661ceSRobert Watson } 352db2661ceSRobert Watson 353db2661ceSRobert Watson static int 3543f1a7a90SRobert Watson lomac_valid(struct mac_lomac *ml) 355db2661ceSRobert Watson { 356db2661ceSRobert Watson 3573f1a7a90SRobert Watson if (ml->ml_flags & MAC_LOMAC_FLAG_SINGLE) { 3583f1a7a90SRobert Watson switch (ml->ml_single.mle_type) { 359db2661ceSRobert Watson case MAC_LOMAC_TYPE_GRADE: 360db2661ceSRobert Watson case MAC_LOMAC_TYPE_EQUAL: 361db2661ceSRobert Watson case MAC_LOMAC_TYPE_HIGH: 362db2661ceSRobert Watson case MAC_LOMAC_TYPE_LOW: 363db2661ceSRobert Watson break; 364db2661ceSRobert Watson 365db2661ceSRobert Watson default: 366db2661ceSRobert Watson return (EINVAL); 367db2661ceSRobert Watson } 368db2661ceSRobert Watson } else { 3693f1a7a90SRobert Watson if (ml->ml_single.mle_type != MAC_LOMAC_TYPE_UNDEF) 370db2661ceSRobert Watson return (EINVAL); 371db2661ceSRobert Watson } 372db2661ceSRobert Watson 3733f1a7a90SRobert Watson if (ml->ml_flags & MAC_LOMAC_FLAG_AUX) { 3743f1a7a90SRobert Watson switch (ml->ml_auxsingle.mle_type) { 375db2661ceSRobert Watson case MAC_LOMAC_TYPE_GRADE: 376db2661ceSRobert Watson case MAC_LOMAC_TYPE_EQUAL: 377db2661ceSRobert Watson case MAC_LOMAC_TYPE_HIGH: 378db2661ceSRobert Watson case MAC_LOMAC_TYPE_LOW: 379db2661ceSRobert Watson break; 380db2661ceSRobert Watson 381db2661ceSRobert Watson default: 382db2661ceSRobert Watson return (EINVAL); 383db2661ceSRobert Watson } 384db2661ceSRobert Watson } else { 3853f1a7a90SRobert Watson if (ml->ml_auxsingle.mle_type != MAC_LOMAC_TYPE_UNDEF) 386db2661ceSRobert Watson return (EINVAL); 387db2661ceSRobert Watson } 388db2661ceSRobert Watson 3893f1a7a90SRobert Watson if (ml->ml_flags & MAC_LOMAC_FLAG_RANGE) { 3903f1a7a90SRobert Watson switch (ml->ml_rangelow.mle_type) { 391db2661ceSRobert Watson case MAC_LOMAC_TYPE_GRADE: 392db2661ceSRobert Watson case MAC_LOMAC_TYPE_EQUAL: 393db2661ceSRobert Watson case MAC_LOMAC_TYPE_HIGH: 394db2661ceSRobert Watson case MAC_LOMAC_TYPE_LOW: 395db2661ceSRobert Watson break; 396db2661ceSRobert Watson 397db2661ceSRobert Watson default: 398db2661ceSRobert Watson return (EINVAL); 399db2661ceSRobert Watson } 400db2661ceSRobert Watson 4013f1a7a90SRobert Watson switch (ml->ml_rangehigh.mle_type) { 402db2661ceSRobert Watson case MAC_LOMAC_TYPE_GRADE: 403db2661ceSRobert Watson case MAC_LOMAC_TYPE_EQUAL: 404db2661ceSRobert Watson case MAC_LOMAC_TYPE_HIGH: 405db2661ceSRobert Watson case MAC_LOMAC_TYPE_LOW: 406db2661ceSRobert Watson break; 407db2661ceSRobert Watson 408db2661ceSRobert Watson default: 409db2661ceSRobert Watson return (EINVAL); 410db2661ceSRobert Watson } 4113f1a7a90SRobert Watson if (!lomac_dominate_element(&ml->ml_rangehigh, 4123f1a7a90SRobert Watson &ml->ml_rangelow)) 413db2661ceSRobert Watson return (EINVAL); 414db2661ceSRobert Watson } else { 4153f1a7a90SRobert Watson if (ml->ml_rangelow.mle_type != MAC_LOMAC_TYPE_UNDEF || 4163f1a7a90SRobert Watson ml->ml_rangehigh.mle_type != MAC_LOMAC_TYPE_UNDEF) 417db2661ceSRobert Watson return (EINVAL); 418db2661ceSRobert Watson } 419db2661ceSRobert Watson 420db2661ceSRobert Watson return (0); 421db2661ceSRobert Watson } 422db2661ceSRobert Watson 423db2661ceSRobert Watson static void 4243f1a7a90SRobert Watson lomac_set_range(struct mac_lomac *ml, u_short typelow, u_short gradelow, 4253f1a7a90SRobert Watson u_short typehigh, u_short gradehigh) 426db2661ceSRobert Watson { 427db2661ceSRobert Watson 4283f1a7a90SRobert Watson ml->ml_rangelow.mle_type = typelow; 4293f1a7a90SRobert Watson ml->ml_rangelow.mle_grade = gradelow; 4303f1a7a90SRobert Watson ml->ml_rangehigh.mle_type = typehigh; 4313f1a7a90SRobert Watson ml->ml_rangehigh.mle_grade = gradehigh; 4323f1a7a90SRobert Watson ml->ml_flags |= MAC_LOMAC_FLAG_RANGE; 433db2661ceSRobert Watson } 434db2661ceSRobert Watson 435db2661ceSRobert Watson static void 4363f1a7a90SRobert Watson lomac_set_single(struct mac_lomac *ml, u_short type, u_short grade) 437db2661ceSRobert Watson { 438db2661ceSRobert Watson 4393f1a7a90SRobert Watson ml->ml_single.mle_type = type; 4403f1a7a90SRobert Watson ml->ml_single.mle_grade = grade; 4413f1a7a90SRobert Watson ml->ml_flags |= MAC_LOMAC_FLAG_SINGLE; 442db2661ceSRobert Watson } 443db2661ceSRobert Watson 444db2661ceSRobert Watson static void 4453f1a7a90SRobert Watson lomac_copy_range(struct mac_lomac *labelfrom, struct mac_lomac *labelto) 446db2661ceSRobert Watson { 447db2661ceSRobert Watson 448db2661ceSRobert Watson KASSERT((labelfrom->ml_flags & MAC_LOMAC_FLAG_RANGE) != 0, 4493f1a7a90SRobert Watson ("lomac_copy_range: labelfrom not range")); 450db2661ceSRobert Watson 451db2661ceSRobert Watson labelto->ml_rangelow = labelfrom->ml_rangelow; 452db2661ceSRobert Watson labelto->ml_rangehigh = labelfrom->ml_rangehigh; 453db2661ceSRobert Watson labelto->ml_flags |= MAC_LOMAC_FLAG_RANGE; 454db2661ceSRobert Watson } 455db2661ceSRobert Watson 456db2661ceSRobert Watson static void 4573f1a7a90SRobert Watson lomac_copy_single(struct mac_lomac *labelfrom, struct mac_lomac *labelto) 458db2661ceSRobert Watson { 459db2661ceSRobert Watson 460db2661ceSRobert Watson KASSERT((labelfrom->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0, 4613f1a7a90SRobert Watson ("lomac_copy_single: labelfrom not single")); 462db2661ceSRobert Watson 463db2661ceSRobert Watson labelto->ml_single = labelfrom->ml_single; 464db2661ceSRobert Watson labelto->ml_flags |= MAC_LOMAC_FLAG_SINGLE; 465db2661ceSRobert Watson } 466db2661ceSRobert Watson 467db2661ceSRobert Watson static void 4683f1a7a90SRobert Watson lomac_copy_auxsingle(struct mac_lomac *labelfrom, struct mac_lomac *labelto) 469db2661ceSRobert Watson { 470db2661ceSRobert Watson 471db2661ceSRobert Watson KASSERT((labelfrom->ml_flags & MAC_LOMAC_FLAG_AUX) != 0, 4723f1a7a90SRobert Watson ("lomac_copy_auxsingle: labelfrom not auxsingle")); 473db2661ceSRobert Watson 474db2661ceSRobert Watson labelto->ml_auxsingle = labelfrom->ml_auxsingle; 475db2661ceSRobert Watson labelto->ml_flags |= MAC_LOMAC_FLAG_AUX; 476db2661ceSRobert Watson } 477db2661ceSRobert Watson 478db2661ceSRobert Watson static void 4793f1a7a90SRobert Watson lomac_copy(struct mac_lomac *source, struct mac_lomac *dest) 480db2661ceSRobert Watson { 481db2661ceSRobert Watson 482db2661ceSRobert Watson if (source->ml_flags & MAC_LOMAC_FLAG_SINGLE) 4833f1a7a90SRobert Watson lomac_copy_single(source, dest); 484db2661ceSRobert Watson if (source->ml_flags & MAC_LOMAC_FLAG_AUX) 4853f1a7a90SRobert Watson lomac_copy_auxsingle(source, dest); 486db2661ceSRobert Watson if (source->ml_flags & MAC_LOMAC_FLAG_RANGE) 4873f1a7a90SRobert Watson lomac_copy_range(source, dest); 488db2661ceSRobert Watson } 489db2661ceSRobert Watson 4903f1a7a90SRobert Watson static int lomac_to_string(struct sbuf *sb, struct mac_lomac *ml); 491db2661ceSRobert Watson 492db2661ceSRobert Watson static int 493db2661ceSRobert Watson maybe_demote(struct mac_lomac *subjlabel, struct mac_lomac *objlabel, 49478007886SRobert Watson const char *actionname, const char *objname, struct vnode *vp) 495db2661ceSRobert Watson { 496f51e5803SRobert Watson struct sbuf subjlabel_sb, subjtext_sb, objlabel_sb; 497f51e5803SRobert Watson char *subjlabeltext, *objlabeltext, *subjtext; 498f51e5803SRobert Watson struct mac_lomac cached_subjlabel; 499f51e5803SRobert Watson struct mac_lomac_proc *subj; 500db2661ceSRobert Watson struct vattr va; 501db2661ceSRobert Watson struct proc *p; 502db2661ceSRobert Watson pid_t pgid; 503db2661ceSRobert Watson 504eca8a663SRobert Watson subj = PSLOT(curthread->td_proc->p_label); 505f51e5803SRobert Watson 506db2661ceSRobert Watson p = curthread->td_proc; 507db2661ceSRobert Watson mtx_lock(&subj->mtx); 508db2661ceSRobert Watson if (subj->mac_lomac.ml_flags & MAC_LOMAC_FLAG_UPDATE) { 509db2661ceSRobert Watson /* 5103f1a7a90SRobert Watson * Check to see if the pending demotion would be more or less 5113f1a7a90SRobert Watson * severe than this one, and keep the more severe. This can 5123f1a7a90SRobert Watson * only happen for a multi-threaded application. 513db2661ceSRobert Watson */ 5143f1a7a90SRobert Watson if (lomac_dominate_single(objlabel, &subj->mac_lomac)) { 515db2661ceSRobert Watson mtx_unlock(&subj->mtx); 516db2661ceSRobert Watson return (0); 517db2661ceSRobert Watson } 518db2661ceSRobert Watson } 519db2661ceSRobert Watson bzero(&subj->mac_lomac, sizeof(subj->mac_lomac)); 520db2661ceSRobert Watson /* 521db2661ceSRobert Watson * Always demote the single label. 522db2661ceSRobert Watson */ 5233f1a7a90SRobert Watson lomac_copy_single(objlabel, &subj->mac_lomac); 524db2661ceSRobert Watson /* 5253f1a7a90SRobert Watson * Start with the original range, then minimize each side of the 5263f1a7a90SRobert Watson * range to the point of not dominating the object. The high side 5273f1a7a90SRobert Watson * will always be demoted, of course. 528db2661ceSRobert Watson */ 5293f1a7a90SRobert Watson lomac_copy_range(subjlabel, &subj->mac_lomac); 5303f1a7a90SRobert Watson if (!lomac_dominate_element(&objlabel->ml_single, 531db2661ceSRobert Watson &subj->mac_lomac.ml_rangelow)) 532db2661ceSRobert Watson subj->mac_lomac.ml_rangelow = objlabel->ml_single; 533db2661ceSRobert Watson subj->mac_lomac.ml_rangehigh = objlabel->ml_single; 534db2661ceSRobert Watson subj->mac_lomac.ml_flags |= MAC_LOMAC_FLAG_UPDATE; 535c6d31b83SKonstantin Belousov ast_sched(curthread, TDA_MAC); 536f51e5803SRobert Watson 537f51e5803SRobert Watson /* 5383f1a7a90SRobert Watson * Avoid memory allocation while holding a mutex; cache the label. 539f51e5803SRobert Watson */ 5403f1a7a90SRobert Watson lomac_copy_single(&subj->mac_lomac, &cached_subjlabel); 541db2661ceSRobert Watson mtx_unlock(&subj->mtx); 542f51e5803SRobert Watson 543f51e5803SRobert Watson sbuf_new(&subjlabel_sb, NULL, 0, SBUF_AUTOEXTEND); 5443f1a7a90SRobert Watson lomac_to_string(&subjlabel_sb, subjlabel); 545f51e5803SRobert Watson sbuf_finish(&subjlabel_sb); 546f51e5803SRobert Watson subjlabeltext = sbuf_data(&subjlabel_sb); 547f51e5803SRobert Watson 548f51e5803SRobert Watson sbuf_new(&subjtext_sb, NULL, 0, SBUF_AUTOEXTEND); 5493f1a7a90SRobert Watson lomac_to_string(&subjtext_sb, &subj->mac_lomac); 550f51e5803SRobert Watson sbuf_finish(&subjtext_sb); 551f51e5803SRobert Watson subjtext = sbuf_data(&subjtext_sb); 552f51e5803SRobert Watson 553f51e5803SRobert Watson sbuf_new(&objlabel_sb, NULL, 0, SBUF_AUTOEXTEND); 5543f1a7a90SRobert Watson lomac_to_string(&objlabel_sb, objlabel); 555f51e5803SRobert Watson sbuf_finish(&objlabel_sb); 556f51e5803SRobert Watson objlabeltext = sbuf_data(&objlabel_sb); 557f51e5803SRobert Watson 558db2661ceSRobert Watson pgid = p->p_pgrp->pg_id; /* XXX could be stale? */ 5590359a12eSAttilio Rao if (vp != NULL && VOP_GETATTR(vp, &va, curthread->td_ucred) == 0) { 560db2661ceSRobert Watson log(LOG_INFO, "LOMAC: level-%s subject p%dg%du%d:%s demoted to" 561dde58752SGleb Kurtsou " level %s after %s a level-%s %s (inode=%ju, " 562db2661ceSRobert Watson "mountpount=%s)\n", 563db2661ceSRobert Watson subjlabeltext, p->p_pid, pgid, curthread->td_ucred->cr_uid, 564db2661ceSRobert Watson p->p_comm, subjtext, actionname, objlabeltext, objname, 565dde58752SGleb Kurtsou (uintmax_t)va.va_fileid, vp->v_mount->mnt_stat.f_mntonname); 566db2661ceSRobert Watson } else { 567db2661ceSRobert Watson log(LOG_INFO, "LOMAC: level-%s subject p%dg%du%d:%s demoted to" 568db2661ceSRobert Watson " level %s after %s a level-%s %s\n", 569db2661ceSRobert Watson subjlabeltext, p->p_pid, pgid, curthread->td_ucred->cr_uid, 570db2661ceSRobert Watson p->p_comm, subjtext, actionname, objlabeltext, objname); 571db2661ceSRobert Watson } 572db2661ceSRobert Watson 573f51e5803SRobert Watson sbuf_delete(&subjlabel_sb); 574f51e5803SRobert Watson sbuf_delete(&subjtext_sb); 575f51e5803SRobert Watson sbuf_delete(&objlabel_sb); 576f51e5803SRobert Watson 577db2661ceSRobert Watson return (0); 578db2661ceSRobert Watson } 579db2661ceSRobert Watson 580db2661ceSRobert Watson /* 5813f1a7a90SRobert Watson * Relabel "to" to "from" only if "from" is a valid label (contains at least 5823f1a7a90SRobert Watson * a single), as for a relabel operation which may or may not involve a 5833f1a7a90SRobert Watson * relevant label. 584db2661ceSRobert Watson */ 5857496ed81SRobert Watson static void 586db2661ceSRobert Watson try_relabel(struct mac_lomac *from, struct mac_lomac *to) 587db2661ceSRobert Watson { 588db2661ceSRobert Watson 589db2661ceSRobert Watson if (from->ml_flags & MAC_LOMAC_FLAG_SINGLE) { 590db2661ceSRobert Watson bzero(to, sizeof(*to)); 5913f1a7a90SRobert Watson lomac_copy(from, to); 592db2661ceSRobert Watson } 593db2661ceSRobert Watson } 594db2661ceSRobert Watson 595c6d31b83SKonstantin Belousov static void 596c6d31b83SKonstantin Belousov ast_mac(struct thread *td, int tda __unused) 597c6d31b83SKonstantin Belousov { 598c6d31b83SKonstantin Belousov mac_thread_userret(td); 599c6d31b83SKonstantin Belousov } 600c6d31b83SKonstantin Belousov 601db2661ceSRobert Watson /* 602db2661ceSRobert Watson * Policy module operations. 603db2661ceSRobert Watson */ 604db2661ceSRobert Watson static void 605c6d31b83SKonstantin Belousov lomac_init(struct mac_policy_conf *conf __unused) 606db2661ceSRobert Watson { 607c6d31b83SKonstantin Belousov ast_register(TDA_MAC, ASTR_ASTF_REQUIRED, 0, ast_mac); 608c6d31b83SKonstantin Belousov } 609db2661ceSRobert Watson 610c6d31b83SKonstantin Belousov static void 611c6d31b83SKonstantin Belousov lomac_fini(struct mac_policy_conf *conf __unused) 612c6d31b83SKonstantin Belousov { 613c6d31b83SKonstantin Belousov ast_deregister(TDA_MAC); 614db2661ceSRobert Watson } 615db2661ceSRobert Watson 616db2661ceSRobert Watson /* 617db2661ceSRobert Watson * Label operations. 618db2661ceSRobert Watson */ 619db2661ceSRobert Watson static void 6203f1a7a90SRobert Watson lomac_init_label(struct label *label) 621db2661ceSRobert Watson { 622db2661ceSRobert Watson 6231477f588SAlexander Kabaev SLOT_SET(label, lomac_alloc(M_WAITOK)); 624db2661ceSRobert Watson } 625db2661ceSRobert Watson 626db2661ceSRobert Watson static int 6273f1a7a90SRobert Watson lomac_init_label_waitcheck(struct label *label, int flag) 628db2661ceSRobert Watson { 629db2661ceSRobert Watson 6301477f588SAlexander Kabaev SLOT_SET(label, lomac_alloc(flag)); 631db2661ceSRobert Watson if (SLOT(label) == NULL) 632db2661ceSRobert Watson return (ENOMEM); 633db2661ceSRobert Watson 634db2661ceSRobert Watson return (0); 635db2661ceSRobert Watson } 636db2661ceSRobert Watson 637db2661ceSRobert Watson static void 6383f1a7a90SRobert Watson lomac_destroy_label(struct label *label) 639db2661ceSRobert Watson { 640db2661ceSRobert Watson 641db2661ceSRobert Watson lomac_free(SLOT(label)); 6421477f588SAlexander Kabaev SLOT_SET(label, NULL); 643db2661ceSRobert Watson } 644db2661ceSRobert Watson 645f51e5803SRobert Watson static int 6463f1a7a90SRobert Watson lomac_element_to_string(struct sbuf *sb, struct mac_lomac_element *element) 647db2661ceSRobert Watson { 648db2661ceSRobert Watson 649db2661ceSRobert Watson switch (element->mle_type) { 650db2661ceSRobert Watson case MAC_LOMAC_TYPE_HIGH: 651f51e5803SRobert Watson return (sbuf_printf(sb, "high")); 652db2661ceSRobert Watson 653db2661ceSRobert Watson case MAC_LOMAC_TYPE_LOW: 654f51e5803SRobert Watson return (sbuf_printf(sb, "low")); 655db2661ceSRobert Watson 656db2661ceSRobert Watson case MAC_LOMAC_TYPE_EQUAL: 657f51e5803SRobert Watson return (sbuf_printf(sb, "equal")); 658db2661ceSRobert Watson 659db2661ceSRobert Watson case MAC_LOMAC_TYPE_GRADE: 660f51e5803SRobert Watson return (sbuf_printf(sb, "%d", element->mle_grade)); 661db2661ceSRobert Watson 662db2661ceSRobert Watson default: 6633f1a7a90SRobert Watson panic("lomac_element_to_string: invalid type (%d)", 664db2661ceSRobert Watson element->mle_type); 665db2661ceSRobert Watson } 666db2661ceSRobert Watson } 667db2661ceSRobert Watson 668db2661ceSRobert Watson static int 6693f1a7a90SRobert Watson lomac_to_string(struct sbuf *sb, struct mac_lomac *ml) 670db2661ceSRobert Watson { 671db2661ceSRobert Watson 6723f1a7a90SRobert Watson if (ml->ml_flags & MAC_LOMAC_FLAG_SINGLE) { 6733f1a7a90SRobert Watson if (lomac_element_to_string(sb, &ml->ml_single) == -1) 674f51e5803SRobert Watson return (EINVAL); 675db2661ceSRobert Watson } 676db2661ceSRobert Watson 6773f1a7a90SRobert Watson if (ml->ml_flags & MAC_LOMAC_FLAG_AUX) { 678f51e5803SRobert Watson if (sbuf_putc(sb, '[') == -1) 679f51e5803SRobert Watson return (EINVAL); 680db2661ceSRobert Watson 6813f1a7a90SRobert Watson if (lomac_element_to_string(sb, &ml->ml_auxsingle) == -1) 682f51e5803SRobert Watson return (EINVAL); 683db2661ceSRobert Watson 684f51e5803SRobert Watson if (sbuf_putc(sb, ']') == -1) 685f51e5803SRobert Watson return (EINVAL); 686db2661ceSRobert Watson } 687db2661ceSRobert Watson 6883f1a7a90SRobert Watson if (ml->ml_flags & MAC_LOMAC_FLAG_RANGE) { 689f51e5803SRobert Watson if (sbuf_putc(sb, '(') == -1) 690f51e5803SRobert Watson return (EINVAL); 691db2661ceSRobert Watson 6923f1a7a90SRobert Watson if (lomac_element_to_string(sb, &ml->ml_rangelow) == -1) 693f51e5803SRobert Watson return (EINVAL); 694db2661ceSRobert Watson 695f51e5803SRobert Watson if (sbuf_putc(sb, '-') == -1) 696f51e5803SRobert Watson return (EINVAL); 697db2661ceSRobert Watson 6983f1a7a90SRobert Watson if (lomac_element_to_string(sb, &ml->ml_rangehigh) == -1) 699f51e5803SRobert Watson return (EINVAL); 700db2661ceSRobert Watson 7018a4b86b9SRobert Watson if (sbuf_putc(sb, ')') == -1) 702f51e5803SRobert Watson return (EINVAL); 703db2661ceSRobert Watson } 704db2661ceSRobert Watson 705db2661ceSRobert Watson return (0); 706db2661ceSRobert Watson } 707db2661ceSRobert Watson 708db2661ceSRobert Watson static int 7093f1a7a90SRobert Watson lomac_externalize_label(struct label *label, char *element_name, 710f51e5803SRobert Watson struct sbuf *sb, int *claimed) 711db2661ceSRobert Watson { 7123f1a7a90SRobert Watson struct mac_lomac *ml; 713db2661ceSRobert Watson 714db2661ceSRobert Watson if (strcmp(MAC_LOMAC_LABEL_NAME, element_name) != 0) 715db2661ceSRobert Watson return (0); 716db2661ceSRobert Watson 717db2661ceSRobert Watson (*claimed)++; 718db2661ceSRobert Watson 7193f1a7a90SRobert Watson ml = SLOT(label); 720db2661ceSRobert Watson 7213f1a7a90SRobert Watson return (lomac_to_string(sb, ml)); 722db2661ceSRobert Watson } 723db2661ceSRobert Watson 724db2661ceSRobert Watson static int 7253f1a7a90SRobert Watson lomac_parse_element(struct mac_lomac_element *element, char *string) 726db2661ceSRobert Watson { 727db2661ceSRobert Watson 7283f1a7a90SRobert Watson if (strcmp(string, "high") == 0 || strcmp(string, "hi") == 0) { 729db2661ceSRobert Watson element->mle_type = MAC_LOMAC_TYPE_HIGH; 730db2661ceSRobert Watson element->mle_grade = MAC_LOMAC_TYPE_UNDEF; 7313f1a7a90SRobert Watson } else if (strcmp(string, "low") == 0 || strcmp(string, "lo") == 0) { 732db2661ceSRobert Watson element->mle_type = MAC_LOMAC_TYPE_LOW; 733db2661ceSRobert Watson element->mle_grade = MAC_LOMAC_TYPE_UNDEF; 73495b85ca3SRobert Watson } else if (strcmp(string, "equal") == 0 || 73595b85ca3SRobert Watson strcmp(string, "eq") == 0) { 736db2661ceSRobert Watson element->mle_type = MAC_LOMAC_TYPE_EQUAL; 737db2661ceSRobert Watson element->mle_grade = MAC_LOMAC_TYPE_UNDEF; 738db2661ceSRobert Watson } else { 739db2661ceSRobert Watson char *p0, *p1; 740db2661ceSRobert Watson int d; 741db2661ceSRobert Watson 742db2661ceSRobert Watson p0 = string; 743db2661ceSRobert Watson d = strtol(p0, &p1, 10); 744db2661ceSRobert Watson 745db2661ceSRobert Watson if (d < 0 || d > 65535) 746db2661ceSRobert Watson return (EINVAL); 747db2661ceSRobert Watson element->mle_type = MAC_LOMAC_TYPE_GRADE; 748db2661ceSRobert Watson element->mle_grade = d; 749db2661ceSRobert Watson 750db2661ceSRobert Watson if (p1 == p0 || *p1 != '\0') 751db2661ceSRobert Watson return (EINVAL); 752db2661ceSRobert Watson } 753db2661ceSRobert Watson 754db2661ceSRobert Watson return (0); 755db2661ceSRobert Watson } 756db2661ceSRobert Watson 757db2661ceSRobert Watson /* 7583f1a7a90SRobert Watson * Note: destructively consumes the string, make a local copy before calling 7593f1a7a90SRobert Watson * if that's a problem. 760db2661ceSRobert Watson */ 761db2661ceSRobert Watson static int 7623f1a7a90SRobert Watson lomac_parse(struct mac_lomac *ml, char *string) 763db2661ceSRobert Watson { 764db2661ceSRobert Watson char *range, *rangeend, *rangehigh, *rangelow, *single, *auxsingle, 765db2661ceSRobert Watson *auxsingleend; 766db2661ceSRobert Watson int error; 767db2661ceSRobert Watson 768db2661ceSRobert Watson /* Do we have a range? */ 769db2661ceSRobert Watson single = string; 770dc15eac0SEd Schouten range = strchr(string, '('); 771db2661ceSRobert Watson if (range == single) 772db2661ceSRobert Watson single = NULL; 773dc15eac0SEd Schouten auxsingle = strchr(string, '['); 774db2661ceSRobert Watson if (auxsingle == single) 775db2661ceSRobert Watson single = NULL; 776db2661ceSRobert Watson if (range != NULL && auxsingle != NULL) 777db2661ceSRobert Watson return (EINVAL); 778db2661ceSRobert Watson rangelow = rangehigh = NULL; 779db2661ceSRobert Watson if (range != NULL) { 780db2661ceSRobert Watson /* Nul terminate the end of the single string. */ 781db2661ceSRobert Watson *range = '\0'; 782db2661ceSRobert Watson range++; 783db2661ceSRobert Watson rangelow = range; 784dc15eac0SEd Schouten rangehigh = strchr(rangelow, '-'); 785db2661ceSRobert Watson if (rangehigh == NULL) 786db2661ceSRobert Watson return (EINVAL); 787db2661ceSRobert Watson rangehigh++; 788db2661ceSRobert Watson if (*rangelow == '\0' || *rangehigh == '\0') 789db2661ceSRobert Watson return (EINVAL); 790dc15eac0SEd Schouten rangeend = strchr(rangehigh, ')'); 791db2661ceSRobert Watson if (rangeend == NULL) 792db2661ceSRobert Watson return (EINVAL); 793db2661ceSRobert Watson if (*(rangeend + 1) != '\0') 794db2661ceSRobert Watson return (EINVAL); 795db2661ceSRobert Watson /* Nul terminate the ends of the ranges. */ 796db2661ceSRobert Watson *(rangehigh - 1) = '\0'; 797db2661ceSRobert Watson *rangeend = '\0'; 798db2661ceSRobert Watson } 799db2661ceSRobert Watson KASSERT((rangelow != NULL && rangehigh != NULL) || 800db2661ceSRobert Watson (rangelow == NULL && rangehigh == NULL), 8013f1a7a90SRobert Watson ("lomac_internalize_label: range mismatch")); 802db2661ceSRobert Watson if (auxsingle != NULL) { 803db2661ceSRobert Watson /* Nul terminate the end of the single string. */ 804db2661ceSRobert Watson *auxsingle = '\0'; 805db2661ceSRobert Watson auxsingle++; 806dc15eac0SEd Schouten auxsingleend = strchr(auxsingle, ']'); 807db2661ceSRobert Watson if (auxsingleend == NULL) 808db2661ceSRobert Watson return (EINVAL); 809db2661ceSRobert Watson if (*(auxsingleend + 1) != '\0') 810db2661ceSRobert Watson return (EINVAL); 811db2661ceSRobert Watson /* Nul terminate the end of the auxsingle. */ 812db2661ceSRobert Watson *auxsingleend = '\0'; 813db2661ceSRobert Watson } 814db2661ceSRobert Watson 8153f1a7a90SRobert Watson bzero(ml, sizeof(*ml)); 816db2661ceSRobert Watson if (single != NULL) { 8173f1a7a90SRobert Watson error = lomac_parse_element(&ml->ml_single, single); 818db2661ceSRobert Watson if (error) 819db2661ceSRobert Watson return (error); 8203f1a7a90SRobert Watson ml->ml_flags |= MAC_LOMAC_FLAG_SINGLE; 821db2661ceSRobert Watson } 822db2661ceSRobert Watson 823db2661ceSRobert Watson if (auxsingle != NULL) { 82495b85ca3SRobert Watson error = lomac_parse_element(&ml->ml_auxsingle, auxsingle); 825db2661ceSRobert Watson if (error) 826db2661ceSRobert Watson return (error); 8273f1a7a90SRobert Watson ml->ml_flags |= MAC_LOMAC_FLAG_AUX; 828db2661ceSRobert Watson } 829db2661ceSRobert Watson 830db2661ceSRobert Watson if (rangelow != NULL) { 8313f1a7a90SRobert Watson error = lomac_parse_element(&ml->ml_rangelow, rangelow); 832db2661ceSRobert Watson if (error) 833db2661ceSRobert Watson return (error); 8343f1a7a90SRobert Watson error = lomac_parse_element(&ml->ml_rangehigh, rangehigh); 835db2661ceSRobert Watson if (error) 836db2661ceSRobert Watson return (error); 8373f1a7a90SRobert Watson ml->ml_flags |= MAC_LOMAC_FLAG_RANGE; 838db2661ceSRobert Watson } 839db2661ceSRobert Watson 8403f1a7a90SRobert Watson error = lomac_valid(ml); 841db2661ceSRobert Watson if (error) 842db2661ceSRobert Watson return (error); 843db2661ceSRobert Watson 844db2661ceSRobert Watson return (0); 845db2661ceSRobert Watson } 846db2661ceSRobert Watson 847db2661ceSRobert Watson static int 8483f1a7a90SRobert Watson lomac_internalize_label(struct label *label, char *element_name, 849db2661ceSRobert Watson char *element_data, int *claimed) 850db2661ceSRobert Watson { 8513f1a7a90SRobert Watson struct mac_lomac *ml, ml_temp; 852db2661ceSRobert Watson int error; 853db2661ceSRobert Watson 854db2661ceSRobert Watson if (strcmp(MAC_LOMAC_LABEL_NAME, element_name) != 0) 855db2661ceSRobert Watson return (0); 856db2661ceSRobert Watson 857db2661ceSRobert Watson (*claimed)++; 858db2661ceSRobert Watson 8593f1a7a90SRobert Watson error = lomac_parse(&ml_temp, element_data); 860db2661ceSRobert Watson if (error) 861db2661ceSRobert Watson return (error); 862db2661ceSRobert Watson 8633f1a7a90SRobert Watson ml = SLOT(label); 8643f1a7a90SRobert Watson *ml = ml_temp; 865db2661ceSRobert Watson 866db2661ceSRobert Watson return (0); 867db2661ceSRobert Watson } 868db2661ceSRobert Watson 869db2661ceSRobert Watson static void 8703f1a7a90SRobert Watson lomac_copy_label(struct label *src, struct label *dest) 871db2661ceSRobert Watson { 872db2661ceSRobert Watson 873db2661ceSRobert Watson *SLOT(dest) = *SLOT(src); 874db2661ceSRobert Watson } 875db2661ceSRobert Watson 876db2661ceSRobert Watson /* 877eb320b0eSRobert Watson * Object-specific entry point implementations are sorted alphabetically by 878eb320b0eSRobert Watson * object type name and then by operation. 879db2661ceSRobert Watson */ 880db2661ceSRobert Watson static int 8813f1a7a90SRobert Watson lomac_bpfdesc_check_receive(struct bpf_d *d, struct label *dlabel, 88278007886SRobert Watson struct ifnet *ifp, struct label *ifplabel) 883db2661ceSRobert Watson { 884db2661ceSRobert Watson struct mac_lomac *a, *b; 885db2661ceSRobert Watson 8863f1a7a90SRobert Watson if (!lomac_enabled) 887db2661ceSRobert Watson return (0); 888db2661ceSRobert Watson 88978007886SRobert Watson a = SLOT(dlabel); 89078007886SRobert Watson b = SLOT(ifplabel); 891db2661ceSRobert Watson 8923f1a7a90SRobert Watson if (lomac_equal_single(a, b)) 893db2661ceSRobert Watson return (0); 894db2661ceSRobert Watson return (EACCES); 895db2661ceSRobert Watson } 896db2661ceSRobert Watson 897eb320b0eSRobert Watson static void 898eb320b0eSRobert Watson lomac_bpfdesc_create(struct ucred *cred, struct bpf_d *d, 899eb320b0eSRobert Watson struct label *dlabel) 900eb320b0eSRobert Watson { 901eb320b0eSRobert Watson struct mac_lomac *source, *dest; 902eb320b0eSRobert Watson 903eb320b0eSRobert Watson source = SLOT(cred->cr_label); 904eb320b0eSRobert Watson dest = SLOT(dlabel); 905eb320b0eSRobert Watson 906eb320b0eSRobert Watson lomac_copy_single(source, dest); 907eb320b0eSRobert Watson } 908eb320b0eSRobert Watson 909eb320b0eSRobert Watson static void 910eb320b0eSRobert Watson lomac_bpfdesc_create_mbuf(struct bpf_d *d, struct label *dlabel, 911eb320b0eSRobert Watson struct mbuf *m, struct label *mlabel) 912eb320b0eSRobert Watson { 913eb320b0eSRobert Watson struct mac_lomac *source, *dest; 914eb320b0eSRobert Watson 915eb320b0eSRobert Watson source = SLOT(dlabel); 916eb320b0eSRobert Watson dest = SLOT(mlabel); 917eb320b0eSRobert Watson 918eb320b0eSRobert Watson lomac_copy_single(source, dest); 919eb320b0eSRobert Watson } 920eb320b0eSRobert Watson 921db2661ceSRobert Watson static int 9223f1a7a90SRobert Watson lomac_cred_check_relabel(struct ucred *cred, struct label *newlabel) 923db2661ceSRobert Watson { 924db2661ceSRobert Watson struct mac_lomac *subj, *new; 925db2661ceSRobert Watson int error; 926db2661ceSRobert Watson 927eca8a663SRobert Watson subj = SLOT(cred->cr_label); 928db2661ceSRobert Watson new = SLOT(newlabel); 929db2661ceSRobert Watson 930db2661ceSRobert Watson /* 9313f1a7a90SRobert Watson * If there is a LOMAC label update for the credential, it may be an 9323f1a7a90SRobert Watson * update of the single, range, or both. 933db2661ceSRobert Watson */ 934db2661ceSRobert Watson error = lomac_atmostflags(new, MAC_LOMAC_FLAGS_BOTH); 935db2661ceSRobert Watson if (error) 936db2661ceSRobert Watson return (error); 937db2661ceSRobert Watson 938db2661ceSRobert Watson /* 939db2661ceSRobert Watson * If the LOMAC label is to be changed, authorize as appropriate. 940db2661ceSRobert Watson */ 941db2661ceSRobert Watson if (new->ml_flags & MAC_LOMAC_FLAGS_BOTH) { 942db2661ceSRobert Watson /* 94384bdb083SRobert Watson * Fill in the missing parts from the previous label. 944db2661ceSRobert Watson */ 94584bdb083SRobert Watson if ((new->ml_flags & MAC_LOMAC_FLAG_SINGLE) == 0) 9463f1a7a90SRobert Watson lomac_copy_single(subj, new); 94784bdb083SRobert Watson if ((new->ml_flags & MAC_LOMAC_FLAG_RANGE) == 0) 9483f1a7a90SRobert Watson lomac_copy_range(subj, new); 949db2661ceSRobert Watson 950db2661ceSRobert Watson /* 9513f1a7a90SRobert Watson * To change the LOMAC range on a credential, the new range 9523f1a7a90SRobert Watson * label must be in the current range. 953db2661ceSRobert Watson */ 9543f1a7a90SRobert Watson if (!lomac_range_in_range(new, subj)) 95584bdb083SRobert Watson return (EPERM); 95684bdb083SRobert Watson 95784bdb083SRobert Watson /* 9583f1a7a90SRobert Watson * To change the LOMAC single label on a credential, the new 9593f1a7a90SRobert Watson * single label must be in the new range. Implicitly from 9603f1a7a90SRobert Watson * the previous check, the new single is in the old range. 96184bdb083SRobert Watson */ 9623f1a7a90SRobert Watson if (!lomac_single_in_range(new, new)) 963db2661ceSRobert Watson return (EPERM); 964db2661ceSRobert Watson 965db2661ceSRobert Watson /* 9663f1a7a90SRobert Watson * To have EQUAL in any component of the new credential LOMAC 9673f1a7a90SRobert Watson * label, the subject must already have EQUAL in their label. 968db2661ceSRobert Watson */ 9693f1a7a90SRobert Watson if (lomac_contains_equal(new)) { 9703f1a7a90SRobert Watson error = lomac_subject_privileged(subj); 971db2661ceSRobert Watson if (error) 972db2661ceSRobert Watson return (error); 973db2661ceSRobert Watson } 974db2661ceSRobert Watson 975db2661ceSRobert Watson /* 9763f1a7a90SRobert Watson * XXXMAC: Additional consistency tests regarding the single 9773f1a7a90SRobert Watson * and range of the new label might be performed here. 978db2661ceSRobert Watson */ 979db2661ceSRobert Watson } 980db2661ceSRobert Watson 981db2661ceSRobert Watson return (0); 982db2661ceSRobert Watson } 983db2661ceSRobert Watson 984db2661ceSRobert Watson static int 9853f1a7a90SRobert Watson lomac_cred_check_visible(struct ucred *cr1, struct ucred *cr2) 986db2661ceSRobert Watson { 987db2661ceSRobert Watson struct mac_lomac *subj, *obj; 988db2661ceSRobert Watson 9893f1a7a90SRobert Watson if (!lomac_enabled) 990db2661ceSRobert Watson return (0); 991db2661ceSRobert Watson 99278007886SRobert Watson subj = SLOT(cr1->cr_label); 99378007886SRobert Watson obj = SLOT(cr2->cr_label); 994db2661ceSRobert Watson 995db2661ceSRobert Watson /* XXX: range */ 9963f1a7a90SRobert Watson if (!lomac_dominate_single(obj, subj)) 997db2661ceSRobert Watson return (ESRCH); 998db2661ceSRobert Watson 999db2661ceSRobert Watson return (0); 1000db2661ceSRobert Watson } 1001212ab0cfSRobert Watson 1002212ab0cfSRobert Watson static void 1003212ab0cfSRobert Watson lomac_cred_create_init(struct ucred *cred) 1004212ab0cfSRobert Watson { 1005212ab0cfSRobert Watson struct mac_lomac *dest; 1006212ab0cfSRobert Watson 1007212ab0cfSRobert Watson dest = SLOT(cred->cr_label); 1008212ab0cfSRobert Watson 1009212ab0cfSRobert Watson lomac_set_single(dest, MAC_LOMAC_TYPE_HIGH, 0); 1010212ab0cfSRobert Watson lomac_set_range(dest, MAC_LOMAC_TYPE_LOW, 0, MAC_LOMAC_TYPE_HIGH, 0); 1011212ab0cfSRobert Watson } 1012212ab0cfSRobert Watson 1013212ab0cfSRobert Watson static void 1014212ab0cfSRobert Watson lomac_cred_create_swapper(struct ucred *cred) 1015212ab0cfSRobert Watson { 1016212ab0cfSRobert Watson struct mac_lomac *dest; 1017212ab0cfSRobert Watson 1018212ab0cfSRobert Watson dest = SLOT(cred->cr_label); 1019212ab0cfSRobert Watson 1020212ab0cfSRobert Watson lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0); 1021212ab0cfSRobert Watson lomac_set_range(dest, MAC_LOMAC_TYPE_LOW, 0, MAC_LOMAC_TYPE_HIGH, 0); 1022212ab0cfSRobert Watson } 1023212ab0cfSRobert Watson 1024eb320b0eSRobert Watson static void 1025eb320b0eSRobert Watson lomac_cred_relabel(struct ucred *cred, struct label *newlabel) 1026eb320b0eSRobert Watson { 1027eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1028eb320b0eSRobert Watson 1029eb320b0eSRobert Watson source = SLOT(newlabel); 1030eb320b0eSRobert Watson dest = SLOT(cred->cr_label); 1031eb320b0eSRobert Watson 1032eb320b0eSRobert Watson try_relabel(source, dest); 1033eb320b0eSRobert Watson } 1034eb320b0eSRobert Watson 1035eb320b0eSRobert Watson static void 1036eb320b0eSRobert Watson lomac_devfs_create_device(struct ucred *cred, struct mount *mp, 1037eb320b0eSRobert Watson struct cdev *dev, struct devfs_dirent *de, struct label *delabel) 1038eb320b0eSRobert Watson { 1039eb320b0eSRobert Watson struct mac_lomac *ml; 10407870adb6SEd Schouten const char *dn; 1041eb320b0eSRobert Watson int lomac_type; 1042eb320b0eSRobert Watson 1043eb320b0eSRobert Watson ml = SLOT(delabel); 10447870adb6SEd Schouten dn = devtoname(dev); 10457870adb6SEd Schouten if (strcmp(dn, "null") == 0 || 10467870adb6SEd Schouten strcmp(dn, "zero") == 0 || 10477870adb6SEd Schouten strcmp(dn, "random") == 0 || 10487870adb6SEd Schouten strncmp(dn, "fd/", strlen("fd/")) == 0 || 10497870adb6SEd Schouten strncmp(dn, "ttyv", strlen("ttyv")) == 0) 1050eb320b0eSRobert Watson lomac_type = MAC_LOMAC_TYPE_EQUAL; 1051eb320b0eSRobert Watson else if (ptys_equal && 10527870adb6SEd Schouten (strncmp(dn, "ttyp", strlen("ttyp")) == 0 || 10537870adb6SEd Schouten strncmp(dn, "pts/", strlen("pts/")) == 0 || 10547870adb6SEd Schouten strncmp(dn, "ptyp", strlen("ptyp")) == 0)) 1055eb320b0eSRobert Watson lomac_type = MAC_LOMAC_TYPE_EQUAL; 1056eb320b0eSRobert Watson else 1057eb320b0eSRobert Watson lomac_type = MAC_LOMAC_TYPE_HIGH; 1058eb320b0eSRobert Watson lomac_set_single(ml, lomac_type, 0); 1059eb320b0eSRobert Watson } 1060eb320b0eSRobert Watson 1061eb320b0eSRobert Watson static void 1062eb320b0eSRobert Watson lomac_devfs_create_directory(struct mount *mp, char *dirname, int dirnamelen, 1063eb320b0eSRobert Watson struct devfs_dirent *de, struct label *delabel) 1064eb320b0eSRobert Watson { 1065eb320b0eSRobert Watson struct mac_lomac *ml; 1066eb320b0eSRobert Watson 1067eb320b0eSRobert Watson ml = SLOT(delabel); 1068eb320b0eSRobert Watson lomac_set_single(ml, MAC_LOMAC_TYPE_HIGH, 0); 1069eb320b0eSRobert Watson } 1070eb320b0eSRobert Watson 1071eb320b0eSRobert Watson static void 1072eb320b0eSRobert Watson lomac_devfs_create_symlink(struct ucred *cred, struct mount *mp, 1073eb320b0eSRobert Watson struct devfs_dirent *dd, struct label *ddlabel, struct devfs_dirent *de, 1074eb320b0eSRobert Watson struct label *delabel) 1075eb320b0eSRobert Watson { 1076eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1077eb320b0eSRobert Watson 1078eb320b0eSRobert Watson source = SLOT(cred->cr_label); 1079eb320b0eSRobert Watson dest = SLOT(delabel); 1080eb320b0eSRobert Watson 1081eb320b0eSRobert Watson lomac_copy_single(source, dest); 1082eb320b0eSRobert Watson } 1083eb320b0eSRobert Watson 1084eb320b0eSRobert Watson static void 1085eb320b0eSRobert Watson lomac_devfs_update(struct mount *mp, struct devfs_dirent *de, 1086eb320b0eSRobert Watson struct label *delabel, struct vnode *vp, struct label *vplabel) 1087eb320b0eSRobert Watson { 1088eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1089eb320b0eSRobert Watson 1090eb320b0eSRobert Watson source = SLOT(vplabel); 1091eb320b0eSRobert Watson dest = SLOT(delabel); 1092eb320b0eSRobert Watson 1093eb320b0eSRobert Watson lomac_copy(source, dest); 1094eb320b0eSRobert Watson } 1095eb320b0eSRobert Watson 1096eb320b0eSRobert Watson static void 1097eb320b0eSRobert Watson lomac_devfs_vnode_associate(struct mount *mp, struct label *mplabel, 1098eb320b0eSRobert Watson struct devfs_dirent *de, struct label *delabel, struct vnode *vp, 1099eb320b0eSRobert Watson struct label *vplabel) 1100eb320b0eSRobert Watson { 1101eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1102eb320b0eSRobert Watson 1103eb320b0eSRobert Watson source = SLOT(delabel); 1104eb320b0eSRobert Watson dest = SLOT(vplabel); 1105eb320b0eSRobert Watson 1106eb320b0eSRobert Watson lomac_copy_single(source, dest); 1107eb320b0eSRobert Watson } 1108db2661ceSRobert Watson 1109db2661ceSRobert Watson static int 11103f1a7a90SRobert Watson lomac_ifnet_check_relabel(struct ucred *cred, struct ifnet *ifp, 111178007886SRobert Watson struct label *ifplabel, struct label *newlabel) 1112db2661ceSRobert Watson { 1113db2661ceSRobert Watson struct mac_lomac *subj, *new; 1114db2661ceSRobert Watson int error; 1115db2661ceSRobert Watson 1116eca8a663SRobert Watson subj = SLOT(cred->cr_label); 1117db2661ceSRobert Watson new = SLOT(newlabel); 1118db2661ceSRobert Watson 1119db2661ceSRobert Watson /* 11203f1a7a90SRobert Watson * If there is a LOMAC label update for the interface, it may be an 11213f1a7a90SRobert Watson * update of the single, range, or both. 1122db2661ceSRobert Watson */ 1123db2661ceSRobert Watson error = lomac_atmostflags(new, MAC_LOMAC_FLAGS_BOTH); 1124db2661ceSRobert Watson if (error) 1125db2661ceSRobert Watson return (error); 1126db2661ceSRobert Watson 1127db2661ceSRobert Watson /* 1128db2661ceSRobert Watson * Relabling network interfaces requires LOMAC privilege. 1129db2661ceSRobert Watson */ 11303f1a7a90SRobert Watson error = lomac_subject_privileged(subj); 1131db2661ceSRobert Watson if (error) 1132db2661ceSRobert Watson return (error); 1133db2661ceSRobert Watson 1134db2661ceSRobert Watson /* 1135db2661ceSRobert Watson * If the LOMAC label is to be changed, authorize as appropriate. 1136db2661ceSRobert Watson */ 1137db2661ceSRobert Watson if (new->ml_flags & MAC_LOMAC_FLAGS_BOTH) { 1138db2661ceSRobert Watson /* 113984bdb083SRobert Watson * Fill in the missing parts from the previous label. 114084bdb083SRobert Watson */ 114184bdb083SRobert Watson if ((new->ml_flags & MAC_LOMAC_FLAG_SINGLE) == 0) 11423f1a7a90SRobert Watson lomac_copy_single(subj, new); 114384bdb083SRobert Watson if ((new->ml_flags & MAC_LOMAC_FLAG_RANGE) == 0) 11443f1a7a90SRobert Watson lomac_copy_range(subj, new); 114584bdb083SRobert Watson 114684bdb083SRobert Watson /* 1147db2661ceSRobert Watson * Rely on the traditional superuser status for the LOMAC 1148db2661ceSRobert Watson * interface relabel requirements. XXXMAC: This will go 1149db2661ceSRobert Watson * away. 1150acd3428bSRobert Watson * 1151acd3428bSRobert Watson * XXXRW: This is also redundant to a higher layer check. 1152db2661ceSRobert Watson */ 1153cc426dd3SMateusz Guzik error = priv_check_cred(cred, PRIV_NET_SETIFMAC); 1154db2661ceSRobert Watson if (error) 1155db2661ceSRobert Watson return (EPERM); 1156db2661ceSRobert Watson 1157db2661ceSRobert Watson /* 1158db2661ceSRobert Watson * XXXMAC: Additional consistency tests regarding the single 1159db2661ceSRobert Watson * and the range of the new label might be performed here. 1160db2661ceSRobert Watson */ 1161db2661ceSRobert Watson } 1162db2661ceSRobert Watson 1163db2661ceSRobert Watson return (0); 1164db2661ceSRobert Watson } 1165db2661ceSRobert Watson 1166db2661ceSRobert Watson static int 11673f1a7a90SRobert Watson lomac_ifnet_check_transmit(struct ifnet *ifp, struct label *ifplabel, 116878007886SRobert Watson struct mbuf *m, struct label *mlabel) 1169db2661ceSRobert Watson { 1170db2661ceSRobert Watson struct mac_lomac *p, *i; 1171db2661ceSRobert Watson 11723f1a7a90SRobert Watson if (!lomac_enabled) 1173db2661ceSRobert Watson return (0); 1174db2661ceSRobert Watson 117578007886SRobert Watson p = SLOT(mlabel); 117678007886SRobert Watson i = SLOT(ifplabel); 1177db2661ceSRobert Watson 11783f1a7a90SRobert Watson return (lomac_single_in_range(p, i) ? 0 : EACCES); 1179db2661ceSRobert Watson } 1180db2661ceSRobert Watson 1181eb320b0eSRobert Watson static void 1182eb320b0eSRobert Watson lomac_ifnet_create(struct ifnet *ifp, struct label *ifplabel) 1183eb320b0eSRobert Watson { 1184eb320b0eSRobert Watson char tifname[IFNAMSIZ], *p, *q; 1185eb320b0eSRobert Watson char tiflist[sizeof(trusted_interfaces)]; 1186eb320b0eSRobert Watson struct mac_lomac *dest; 1187eb320b0eSRobert Watson int len, grade; 1188eb320b0eSRobert Watson 1189eb320b0eSRobert Watson dest = SLOT(ifplabel); 1190eb320b0eSRobert Watson 1191*30af2c13SJustin Hibbits if (if_gettype(ifp) == IFT_LOOP) { 1192eb320b0eSRobert Watson grade = MAC_LOMAC_TYPE_EQUAL; 1193eb320b0eSRobert Watson goto set; 1194eb320b0eSRobert Watson } 1195eb320b0eSRobert Watson 1196eb320b0eSRobert Watson if (trust_all_interfaces) { 1197eb320b0eSRobert Watson grade = MAC_LOMAC_TYPE_HIGH; 1198eb320b0eSRobert Watson goto set; 1199eb320b0eSRobert Watson } 1200eb320b0eSRobert Watson 1201eb320b0eSRobert Watson grade = MAC_LOMAC_TYPE_LOW; 1202eb320b0eSRobert Watson 1203eb320b0eSRobert Watson if (trusted_interfaces[0] == '\0' || 1204eb320b0eSRobert Watson !strvalid(trusted_interfaces, sizeof(trusted_interfaces))) 1205eb320b0eSRobert Watson goto set; 1206eb320b0eSRobert Watson 1207eb320b0eSRobert Watson bzero(tiflist, sizeof(tiflist)); 1208eb320b0eSRobert Watson for (p = trusted_interfaces, q = tiflist; *p != '\0'; p++, q++) 1209eb320b0eSRobert Watson if(*p != ' ' && *p != '\t') 1210eb320b0eSRobert Watson *q = *p; 1211eb320b0eSRobert Watson 1212eb320b0eSRobert Watson for (p = q = tiflist;; p++) { 1213eb320b0eSRobert Watson if (*p == ',' || *p == '\0') { 1214eb320b0eSRobert Watson len = p - q; 1215eb320b0eSRobert Watson if (len < IFNAMSIZ) { 1216eb320b0eSRobert Watson bzero(tifname, sizeof(tifname)); 1217eb320b0eSRobert Watson bcopy(q, tifname, len); 1218*30af2c13SJustin Hibbits if (strcmp(tifname, if_name(ifp)) == 0) { 1219eb320b0eSRobert Watson grade = MAC_LOMAC_TYPE_HIGH; 1220eb320b0eSRobert Watson break; 1221eb320b0eSRobert Watson } 1222eb320b0eSRobert Watson } 1223eb320b0eSRobert Watson else { 1224eb320b0eSRobert Watson *p = '\0'; 1225eb320b0eSRobert Watson printf("MAC/LOMAC warning: interface name " 1226eb320b0eSRobert Watson "\"%s\" is too long (must be < %d)\n", 1227eb320b0eSRobert Watson q, IFNAMSIZ); 1228eb320b0eSRobert Watson } 1229eb320b0eSRobert Watson if (*p == '\0') 1230eb320b0eSRobert Watson break; 1231eb320b0eSRobert Watson q = p + 1; 1232eb320b0eSRobert Watson } 1233eb320b0eSRobert Watson } 1234eb320b0eSRobert Watson set: 1235eb320b0eSRobert Watson lomac_set_single(dest, grade, 0); 1236eb320b0eSRobert Watson lomac_set_range(dest, grade, 0, grade, 0); 1237eb320b0eSRobert Watson } 1238eb320b0eSRobert Watson 1239eb320b0eSRobert Watson static void 1240eb320b0eSRobert Watson lomac_ifnet_create_mbuf(struct ifnet *ifp, struct label *ifplabel, 1241eb320b0eSRobert Watson struct mbuf *m, struct label *mlabel) 1242eb320b0eSRobert Watson { 1243eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1244eb320b0eSRobert Watson 1245eb320b0eSRobert Watson source = SLOT(ifplabel); 1246eb320b0eSRobert Watson dest = SLOT(mlabel); 1247eb320b0eSRobert Watson 1248eb320b0eSRobert Watson lomac_copy_single(source, dest); 1249eb320b0eSRobert Watson } 1250eb320b0eSRobert Watson 1251eb320b0eSRobert Watson static void 1252eb320b0eSRobert Watson lomac_ifnet_relabel(struct ucred *cred, struct ifnet *ifp, 1253eb320b0eSRobert Watson struct label *ifplabel, struct label *newlabel) 1254eb320b0eSRobert Watson { 1255eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1256eb320b0eSRobert Watson 1257eb320b0eSRobert Watson source = SLOT(newlabel); 1258eb320b0eSRobert Watson dest = SLOT(ifplabel); 1259eb320b0eSRobert Watson 1260eb320b0eSRobert Watson try_relabel(source, dest); 1261eb320b0eSRobert Watson } 1262eb320b0eSRobert Watson 1263db2661ceSRobert Watson static int 12643f1a7a90SRobert Watson lomac_inpcb_check_deliver(struct inpcb *inp, struct label *inplabel, 1265a557af22SRobert Watson struct mbuf *m, struct label *mlabel) 1266a557af22SRobert Watson { 1267a557af22SRobert Watson struct mac_lomac *p, *i; 1268a557af22SRobert Watson 12693f1a7a90SRobert Watson if (!lomac_enabled) 1270a557af22SRobert Watson return (0); 1271a557af22SRobert Watson 1272a557af22SRobert Watson p = SLOT(mlabel); 1273a557af22SRobert Watson i = SLOT(inplabel); 1274a557af22SRobert Watson 12753f1a7a90SRobert Watson return (lomac_equal_single(p, i) ? 0 : EACCES); 1276a557af22SRobert Watson } 1277a557af22SRobert Watson 12787fb179baSBjoern A. Zeeb static int 12797fb179baSBjoern A. Zeeb lomac_inpcb_check_visible(struct ucred *cred, struct inpcb *inp, 12807fb179baSBjoern A. Zeeb struct label *inplabel) 12817fb179baSBjoern A. Zeeb { 12827fb179baSBjoern A. Zeeb struct mac_lomac *subj, *obj; 12837fb179baSBjoern A. Zeeb 12847fb179baSBjoern A. Zeeb if (!lomac_enabled) 12857fb179baSBjoern A. Zeeb return (0); 12867fb179baSBjoern A. Zeeb 12877fb179baSBjoern A. Zeeb subj = SLOT(cred->cr_label); 12887fb179baSBjoern A. Zeeb obj = SLOT(inplabel); 12897fb179baSBjoern A. Zeeb 12907fb179baSBjoern A. Zeeb if (!lomac_dominate_single(obj, subj)) 12917fb179baSBjoern A. Zeeb return (ENOENT); 12927fb179baSBjoern A. Zeeb 12937fb179baSBjoern A. Zeeb return (0); 12947fb179baSBjoern A. Zeeb } 12957fb179baSBjoern A. Zeeb 1296eb320b0eSRobert Watson static void 1297eb320b0eSRobert Watson lomac_inpcb_create(struct socket *so, struct label *solabel, 1298eb320b0eSRobert Watson struct inpcb *inp, struct label *inplabel) 1299eb320b0eSRobert Watson { 1300eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1301eb320b0eSRobert Watson 1302eb320b0eSRobert Watson source = SLOT(solabel); 1303eb320b0eSRobert Watson dest = SLOT(inplabel); 1304eb320b0eSRobert Watson 1305eb320b0eSRobert Watson lomac_copy_single(source, dest); 1306eb320b0eSRobert Watson } 1307eb320b0eSRobert Watson 1308eb320b0eSRobert Watson static void 1309eb320b0eSRobert Watson lomac_inpcb_create_mbuf(struct inpcb *inp, struct label *inplabel, 1310eb320b0eSRobert Watson struct mbuf *m, struct label *mlabel) 1311eb320b0eSRobert Watson { 1312eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1313eb320b0eSRobert Watson 1314eb320b0eSRobert Watson source = SLOT(inplabel); 1315eb320b0eSRobert Watson dest = SLOT(mlabel); 1316eb320b0eSRobert Watson 1317eb320b0eSRobert Watson lomac_copy_single(source, dest); 1318eb320b0eSRobert Watson } 1319eb320b0eSRobert Watson 1320eb320b0eSRobert Watson static void 1321eb320b0eSRobert Watson lomac_inpcb_sosetlabel(struct socket *so, struct label *solabel, 1322eb320b0eSRobert Watson struct inpcb *inp, struct label *inplabel) 1323eb320b0eSRobert Watson { 1324eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1325eb320b0eSRobert Watson 13263de40469SRobert Watson SOCK_LOCK_ASSERT(so); 13273de40469SRobert Watson 1328eb320b0eSRobert Watson source = SLOT(solabel); 1329eb320b0eSRobert Watson dest = SLOT(inplabel); 1330eb320b0eSRobert Watson 1331eb320b0eSRobert Watson lomac_copy_single(source, dest); 1332eb320b0eSRobert Watson } 1333eb320b0eSRobert Watson 1334eb320b0eSRobert Watson static void 1335048e1287SRobert Watson lomac_ip6q_create(struct mbuf *m, struct label *mlabel, struct ip6q *q6, 1336048e1287SRobert Watson struct label *q6label) 1337048e1287SRobert Watson { 1338048e1287SRobert Watson struct mac_lomac *source, *dest; 1339048e1287SRobert Watson 1340048e1287SRobert Watson source = SLOT(mlabel); 1341048e1287SRobert Watson dest = SLOT(q6label); 1342048e1287SRobert Watson 1343048e1287SRobert Watson lomac_copy_single(source, dest); 1344048e1287SRobert Watson } 1345048e1287SRobert Watson 1346048e1287SRobert Watson static int 1347048e1287SRobert Watson lomac_ip6q_match(struct mbuf *m, struct label *mlabel, struct ip6q *q6, 1348048e1287SRobert Watson struct label *q6label) 1349048e1287SRobert Watson { 1350048e1287SRobert Watson struct mac_lomac *a, *b; 1351048e1287SRobert Watson 1352048e1287SRobert Watson a = SLOT(q6label); 1353048e1287SRobert Watson b = SLOT(mlabel); 1354048e1287SRobert Watson 1355048e1287SRobert Watson return (lomac_equal_single(a, b)); 1356048e1287SRobert Watson } 1357048e1287SRobert Watson 1358048e1287SRobert Watson static void 1359048e1287SRobert Watson lomac_ip6q_reassemble(struct ip6q *q6, struct label *q6label, struct mbuf *m, 1360048e1287SRobert Watson struct label *mlabel) 1361048e1287SRobert Watson { 1362048e1287SRobert Watson struct mac_lomac *source, *dest; 1363048e1287SRobert Watson 1364048e1287SRobert Watson source = SLOT(q6label); 1365048e1287SRobert Watson dest = SLOT(mlabel); 1366048e1287SRobert Watson 1367048e1287SRobert Watson /* Just use the head, since we require them all to match. */ 1368048e1287SRobert Watson lomac_copy_single(source, dest); 1369048e1287SRobert Watson } 1370048e1287SRobert Watson 1371048e1287SRobert Watson static void 1372048e1287SRobert Watson lomac_ip6q_update(struct mbuf *m, struct label *mlabel, struct ip6q *q6, 1373048e1287SRobert Watson struct label *q6label) 1374048e1287SRobert Watson { 1375048e1287SRobert Watson 1376048e1287SRobert Watson /* NOOP: we only accept matching labels, so no need to update */ 1377048e1287SRobert Watson } 1378048e1287SRobert Watson 1379048e1287SRobert Watson static void 138037f44cb4SRobert Watson lomac_ipq_create(struct mbuf *m, struct label *mlabel, struct ipq *q, 138137f44cb4SRobert Watson struct label *qlabel) 1382eb320b0eSRobert Watson { 1383eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1384eb320b0eSRobert Watson 1385eb320b0eSRobert Watson source = SLOT(mlabel); 138637f44cb4SRobert Watson dest = SLOT(qlabel); 1387eb320b0eSRobert Watson 1388eb320b0eSRobert Watson lomac_copy_single(source, dest); 1389eb320b0eSRobert Watson } 1390eb320b0eSRobert Watson 1391eb320b0eSRobert Watson static int 139237f44cb4SRobert Watson lomac_ipq_match(struct mbuf *m, struct label *mlabel, struct ipq *q, 139337f44cb4SRobert Watson struct label *qlabel) 1394eb320b0eSRobert Watson { 1395eb320b0eSRobert Watson struct mac_lomac *a, *b; 1396eb320b0eSRobert Watson 139737f44cb4SRobert Watson a = SLOT(qlabel); 1398eb320b0eSRobert Watson b = SLOT(mlabel); 1399eb320b0eSRobert Watson 1400eb320b0eSRobert Watson return (lomac_equal_single(a, b)); 1401eb320b0eSRobert Watson } 1402eb320b0eSRobert Watson 1403eb320b0eSRobert Watson static void 140437f44cb4SRobert Watson lomac_ipq_reassemble(struct ipq *q, struct label *qlabel, struct mbuf *m, 140537f44cb4SRobert Watson struct label *mlabel) 1406eb320b0eSRobert Watson { 1407eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1408eb320b0eSRobert Watson 140937f44cb4SRobert Watson source = SLOT(qlabel); 1410eb320b0eSRobert Watson dest = SLOT(mlabel); 1411eb320b0eSRobert Watson 1412eb320b0eSRobert Watson /* Just use the head, since we require them all to match. */ 1413eb320b0eSRobert Watson lomac_copy_single(source, dest); 1414eb320b0eSRobert Watson } 1415eb320b0eSRobert Watson 1416eb320b0eSRobert Watson static void 141737f44cb4SRobert Watson lomac_ipq_update(struct mbuf *m, struct label *mlabel, struct ipq *q, 141837f44cb4SRobert Watson struct label *qlabel) 1419eb320b0eSRobert Watson { 1420eb320b0eSRobert Watson 1421eb320b0eSRobert Watson /* NOOP: we only accept matching labels, so no need to update */ 1422eb320b0eSRobert Watson } 1423eb320b0eSRobert Watson 1424a557af22SRobert Watson static int 14253f1a7a90SRobert Watson lomac_kld_check_load(struct ucred *cred, struct vnode *vp, 142678007886SRobert Watson struct label *vplabel) 1427db2661ceSRobert Watson { 1428db2661ceSRobert Watson struct mac_lomac *subj, *obj; 1429db2661ceSRobert Watson 14303f1a7a90SRobert Watson if (!lomac_enabled) 1431db2661ceSRobert Watson return (0); 1432db2661ceSRobert Watson 1433eca8a663SRobert Watson subj = SLOT(cred->cr_label); 143478007886SRobert Watson obj = SLOT(vplabel); 1435db2661ceSRobert Watson 14363f1a7a90SRobert Watson if (lomac_subject_privileged(subj)) 1437db2661ceSRobert Watson return (EPERM); 1438db2661ceSRobert Watson 14393f1a7a90SRobert Watson if (!lomac_high_single(obj)) 1440db2661ceSRobert Watson return (EACCES); 1441db2661ceSRobert Watson 1442db2661ceSRobert Watson return (0); 1443db2661ceSRobert Watson } 1444db2661ceSRobert Watson 1445eb320b0eSRobert Watson static void 1446eb320b0eSRobert Watson lomac_mount_create(struct ucred *cred, struct mount *mp, 1447eb320b0eSRobert Watson struct label *mplabel) 1448eb320b0eSRobert Watson { 1449eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1450eb320b0eSRobert Watson 1451eb320b0eSRobert Watson source = SLOT(cred->cr_label); 1452eb320b0eSRobert Watson dest = SLOT(mplabel); 1453eb320b0eSRobert Watson lomac_copy_single(source, dest); 1454eb320b0eSRobert Watson } 1455eb320b0eSRobert Watson 1456eb320b0eSRobert Watson static void 1457eb320b0eSRobert Watson lomac_netinet_arp_send(struct ifnet *ifp, struct label *ifplabel, 1458eb320b0eSRobert Watson struct mbuf *m, struct label *mlabel) 1459eb320b0eSRobert Watson { 1460eb320b0eSRobert Watson struct mac_lomac *dest; 1461eb320b0eSRobert Watson 1462eb320b0eSRobert Watson dest = SLOT(mlabel); 1463eb320b0eSRobert Watson 1464eb320b0eSRobert Watson lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0); 1465eb320b0eSRobert Watson } 1466eb320b0eSRobert Watson 1467eb320b0eSRobert Watson static void 1468eb320b0eSRobert Watson lomac_netinet_firewall_reply(struct mbuf *mrecv, struct label *mrecvlabel, 1469eb320b0eSRobert Watson struct mbuf *msend, struct label *msendlabel) 1470eb320b0eSRobert Watson { 1471eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1472eb320b0eSRobert Watson 1473eb320b0eSRobert Watson source = SLOT(mrecvlabel); 1474eb320b0eSRobert Watson dest = SLOT(msendlabel); 1475eb320b0eSRobert Watson 1476eb320b0eSRobert Watson lomac_copy_single(source, dest); 1477eb320b0eSRobert Watson } 1478eb320b0eSRobert Watson 1479eb320b0eSRobert Watson static void 1480eb320b0eSRobert Watson lomac_netinet_firewall_send(struct mbuf *m, struct label *mlabel) 1481eb320b0eSRobert Watson { 1482eb320b0eSRobert Watson struct mac_lomac *dest; 1483eb320b0eSRobert Watson 1484eb320b0eSRobert Watson dest = SLOT(mlabel); 1485eb320b0eSRobert Watson 1486bc5ade0dSPedro F. Giffuni /* XXX: where is the label for the firewall really coming from? */ 1487eb320b0eSRobert Watson lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0); 1488eb320b0eSRobert Watson } 1489eb320b0eSRobert Watson 1490eb320b0eSRobert Watson static void 1491eb320b0eSRobert Watson lomac_netinet_fragment(struct mbuf *m, struct label *mlabel, 1492eb320b0eSRobert Watson struct mbuf *frag, struct label *fraglabel) 1493eb320b0eSRobert Watson { 1494eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1495eb320b0eSRobert Watson 1496eb320b0eSRobert Watson source = SLOT(mlabel); 1497eb320b0eSRobert Watson dest = SLOT(fraglabel); 1498eb320b0eSRobert Watson 1499eb320b0eSRobert Watson lomac_copy_single(source, dest); 1500eb320b0eSRobert Watson } 1501eb320b0eSRobert Watson 1502eb320b0eSRobert Watson static void 1503eb320b0eSRobert Watson lomac_netinet_icmp_reply(struct mbuf *mrecv, struct label *mrecvlabel, 1504eb320b0eSRobert Watson struct mbuf *msend, struct label *msendlabel) 1505eb320b0eSRobert Watson { 1506eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1507eb320b0eSRobert Watson 1508eb320b0eSRobert Watson source = SLOT(mrecvlabel); 1509eb320b0eSRobert Watson dest = SLOT(msendlabel); 1510eb320b0eSRobert Watson 1511eb320b0eSRobert Watson lomac_copy_single(source, dest); 1512eb320b0eSRobert Watson } 1513eb320b0eSRobert Watson 1514eb320b0eSRobert Watson static void 1515eb320b0eSRobert Watson lomac_netinet_igmp_send(struct ifnet *ifp, struct label *ifplabel, 1516eb320b0eSRobert Watson struct mbuf *m, struct label *mlabel) 1517eb320b0eSRobert Watson { 1518eb320b0eSRobert Watson struct mac_lomac *dest; 1519eb320b0eSRobert Watson 1520eb320b0eSRobert Watson dest = SLOT(mlabel); 1521eb320b0eSRobert Watson 1522eb320b0eSRobert Watson lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0); 1523eb320b0eSRobert Watson } 1524eb320b0eSRobert Watson 1525eb320b0eSRobert Watson static void 1526eb320b0eSRobert Watson lomac_netinet6_nd6_send(struct ifnet *ifp, struct label *ifplabel, 1527eb320b0eSRobert Watson struct mbuf *m, struct label *mlabel) 1528eb320b0eSRobert Watson { 1529eb320b0eSRobert Watson struct mac_lomac *dest; 1530eb320b0eSRobert Watson 1531eb320b0eSRobert Watson dest = SLOT(mlabel); 1532eb320b0eSRobert Watson 1533eb320b0eSRobert Watson lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0); 1534eb320b0eSRobert Watson } 1535eb320b0eSRobert Watson 1536db2661ceSRobert Watson static int 15373f1a7a90SRobert Watson lomac_pipe_check_ioctl(struct ucred *cred, struct pipepair *pp, 153878007886SRobert Watson struct label *pplabel, unsigned long cmd, void /* caddr_t */ *data) 1539db2661ceSRobert Watson { 1540db2661ceSRobert Watson 15413f1a7a90SRobert Watson if (!lomac_enabled) 1542db2661ceSRobert Watson return (0); 1543db2661ceSRobert Watson 1544db2661ceSRobert Watson /* XXX: This will be implemented soon... */ 1545db2661ceSRobert Watson 1546db2661ceSRobert Watson return (0); 1547db2661ceSRobert Watson } 1548db2661ceSRobert Watson 1549db2661ceSRobert Watson static int 15503f1a7a90SRobert Watson lomac_pipe_check_read(struct ucred *cred, struct pipepair *pp, 155178007886SRobert Watson struct label *pplabel) 1552db2661ceSRobert Watson { 1553db2661ceSRobert Watson struct mac_lomac *subj, *obj; 1554db2661ceSRobert Watson 15553f1a7a90SRobert Watson if (!lomac_enabled) 1556db2661ceSRobert Watson return (0); 1557db2661ceSRobert Watson 1558eca8a663SRobert Watson subj = SLOT(cred->cr_label); 155978007886SRobert Watson obj = SLOT(pplabel); 1560db2661ceSRobert Watson 15613f1a7a90SRobert Watson if (!lomac_dominate_single(obj, subj)) 1562db2661ceSRobert Watson return (maybe_demote(subj, obj, "reading", "pipe", NULL)); 1563db2661ceSRobert Watson 1564db2661ceSRobert Watson return (0); 1565db2661ceSRobert Watson } 1566db2661ceSRobert Watson 1567db2661ceSRobert Watson static int 15683f1a7a90SRobert Watson lomac_pipe_check_relabel(struct ucred *cred, struct pipepair *pp, 156978007886SRobert Watson struct label *pplabel, struct label *newlabel) 1570db2661ceSRobert Watson { 1571db2661ceSRobert Watson struct mac_lomac *subj, *obj, *new; 1572db2661ceSRobert Watson int error; 1573db2661ceSRobert Watson 1574db2661ceSRobert Watson new = SLOT(newlabel); 1575eca8a663SRobert Watson subj = SLOT(cred->cr_label); 157678007886SRobert Watson obj = SLOT(pplabel); 1577db2661ceSRobert Watson 1578db2661ceSRobert Watson /* 15793f1a7a90SRobert Watson * If there is a LOMAC label update for a pipe, it must be a single 15803f1a7a90SRobert Watson * update. 1581db2661ceSRobert Watson */ 1582db2661ceSRobert Watson error = lomac_atmostflags(new, MAC_LOMAC_FLAG_SINGLE); 1583db2661ceSRobert Watson if (error) 1584db2661ceSRobert Watson return (error); 1585db2661ceSRobert Watson 1586db2661ceSRobert Watson /* 1587db2661ceSRobert Watson * To perform a relabel of a pipe (LOMAC label or not), LOMAC must 1588db2661ceSRobert Watson * authorize the relabel. 1589db2661ceSRobert Watson */ 15903f1a7a90SRobert Watson if (!lomac_single_in_range(obj, subj)) 1591db2661ceSRobert Watson return (EPERM); 1592db2661ceSRobert Watson 1593db2661ceSRobert Watson /* 1594db2661ceSRobert Watson * If the LOMAC label is to be changed, authorize as appropriate. 1595db2661ceSRobert Watson */ 1596db2661ceSRobert Watson if (new->ml_flags & MAC_LOMAC_FLAG_SINGLE) { 1597db2661ceSRobert Watson /* 1598db2661ceSRobert Watson * To change the LOMAC label on a pipe, the new pipe label 1599db2661ceSRobert Watson * must be in the subject range. 1600db2661ceSRobert Watson */ 16013f1a7a90SRobert Watson if (!lomac_single_in_range(new, subj)) 1602db2661ceSRobert Watson return (EPERM); 1603db2661ceSRobert Watson 1604db2661ceSRobert Watson /* 1605db2661ceSRobert Watson * To change the LOMAC label on a pipe to be EQUAL, the 1606db2661ceSRobert Watson * subject must have appropriate privilege. 1607db2661ceSRobert Watson */ 16083f1a7a90SRobert Watson if (lomac_contains_equal(new)) { 16093f1a7a90SRobert Watson error = lomac_subject_privileged(subj); 1610db2661ceSRobert Watson if (error) 1611db2661ceSRobert Watson return (error); 1612db2661ceSRobert Watson } 1613db2661ceSRobert Watson } 1614db2661ceSRobert Watson 1615db2661ceSRobert Watson return (0); 1616db2661ceSRobert Watson } 1617db2661ceSRobert Watson 1618db2661ceSRobert Watson static int 16193f1a7a90SRobert Watson lomac_pipe_check_write(struct ucred *cred, struct pipepair *pp, 162078007886SRobert Watson struct label *pplabel) 1621db2661ceSRobert Watson { 1622db2661ceSRobert Watson struct mac_lomac *subj, *obj; 1623db2661ceSRobert Watson 16243f1a7a90SRobert Watson if (!lomac_enabled) 1625db2661ceSRobert Watson return (0); 1626db2661ceSRobert Watson 1627eca8a663SRobert Watson subj = SLOT(cred->cr_label); 162878007886SRobert Watson obj = SLOT(pplabel); 1629db2661ceSRobert Watson 16303f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 1631db2661ceSRobert Watson return (EACCES); 1632db2661ceSRobert Watson 1633db2661ceSRobert Watson return (0); 1634db2661ceSRobert Watson } 1635db2661ceSRobert Watson 1636eb320b0eSRobert Watson static void 1637eb320b0eSRobert Watson lomac_pipe_create(struct ucred *cred, struct pipepair *pp, 1638eb320b0eSRobert Watson struct label *pplabel) 1639db2661ceSRobert Watson { 1640eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1641db2661ceSRobert Watson 1642eb320b0eSRobert Watson source = SLOT(cred->cr_label); 1643eb320b0eSRobert Watson dest = SLOT(pplabel); 1644db2661ceSRobert Watson 1645eb320b0eSRobert Watson lomac_copy_single(source, dest); 1646db2661ceSRobert Watson } 1647db2661ceSRobert Watson 1648eb320b0eSRobert Watson static void 1649eb320b0eSRobert Watson lomac_pipe_relabel(struct ucred *cred, struct pipepair *pp, 1650eb320b0eSRobert Watson struct label *pplabel, struct label *newlabel) 1651db2661ceSRobert Watson { 1652eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1653db2661ceSRobert Watson 1654eb320b0eSRobert Watson source = SLOT(newlabel); 1655eb320b0eSRobert Watson dest = SLOT(pplabel); 1656db2661ceSRobert Watson 1657eb320b0eSRobert Watson try_relabel(source, dest); 1658db2661ceSRobert Watson } 1659db2661ceSRobert Watson 1660c14d15aeSRobert Watson /* 1661c14d15aeSRobert Watson * Some system privileges are allowed regardless of integrity grade; others 1662c14d15aeSRobert Watson * are allowed only when running with privilege with respect to the LOMAC 1663c14d15aeSRobert Watson * policy as they might otherwise allow bypassing of the integrity policy. 1664c14d15aeSRobert Watson */ 1665c14d15aeSRobert Watson static int 16663f1a7a90SRobert Watson lomac_priv_check(struct ucred *cred, int priv) 1667c14d15aeSRobert Watson { 1668c14d15aeSRobert Watson struct mac_lomac *subj; 1669c14d15aeSRobert Watson int error; 1670c14d15aeSRobert Watson 16713f1a7a90SRobert Watson if (!lomac_enabled) 1672c14d15aeSRobert Watson return (0); 1673c14d15aeSRobert Watson 1674c14d15aeSRobert Watson /* 1675c14d15aeSRobert Watson * Exempt only specific privileges from the LOMAC integrity policy. 1676c14d15aeSRobert Watson */ 1677c14d15aeSRobert Watson switch (priv) { 1678c14d15aeSRobert Watson case PRIV_KTRACE: 1679c14d15aeSRobert Watson case PRIV_MSGBUF: 1680c14d15aeSRobert Watson 1681c14d15aeSRobert Watson /* 1682c14d15aeSRobert Watson * Allow processes to manipulate basic process audit properties, and 1683c14d15aeSRobert Watson * to submit audit records. 1684c14d15aeSRobert Watson */ 1685c14d15aeSRobert Watson case PRIV_AUDIT_GETAUDIT: 1686c14d15aeSRobert Watson case PRIV_AUDIT_SETAUDIT: 1687c14d15aeSRobert Watson case PRIV_AUDIT_SUBMIT: 1688c14d15aeSRobert Watson 1689c14d15aeSRobert Watson /* 1690c14d15aeSRobert Watson * Allow processes to manipulate their regular UNIX credentials. 1691c14d15aeSRobert Watson */ 1692c14d15aeSRobert Watson case PRIV_CRED_SETUID: 1693c14d15aeSRobert Watson case PRIV_CRED_SETEUID: 1694c14d15aeSRobert Watson case PRIV_CRED_SETGID: 1695c14d15aeSRobert Watson case PRIV_CRED_SETEGID: 1696c14d15aeSRobert Watson case PRIV_CRED_SETGROUPS: 1697c14d15aeSRobert Watson case PRIV_CRED_SETREUID: 1698c14d15aeSRobert Watson case PRIV_CRED_SETREGID: 1699c14d15aeSRobert Watson case PRIV_CRED_SETRESUID: 1700c14d15aeSRobert Watson case PRIV_CRED_SETRESGID: 1701c14d15aeSRobert Watson 1702c14d15aeSRobert Watson /* 1703c14d15aeSRobert Watson * Allow processes to perform system monitoring. 1704c14d15aeSRobert Watson */ 1705c14d15aeSRobert Watson case PRIV_SEEOTHERGIDS: 1706c14d15aeSRobert Watson case PRIV_SEEOTHERUIDS: 1707c14d15aeSRobert Watson break; 1708c14d15aeSRobert Watson 1709c14d15aeSRobert Watson /* 1710c14d15aeSRobert Watson * Allow access to general process debugging facilities. We 1711c14d15aeSRobert Watson * separately control debugging based on MAC label. 1712c14d15aeSRobert Watson */ 1713c14d15aeSRobert Watson case PRIV_DEBUG_DIFFCRED: 1714c14d15aeSRobert Watson case PRIV_DEBUG_SUGID: 1715c14d15aeSRobert Watson case PRIV_DEBUG_UNPRIV: 1716c14d15aeSRobert Watson 1717c14d15aeSRobert Watson /* 1718c14d15aeSRobert Watson * Allow manipulating jails. 1719c14d15aeSRobert Watson */ 1720c14d15aeSRobert Watson case PRIV_JAIL_ATTACH: 1721c14d15aeSRobert Watson 1722c14d15aeSRobert Watson /* 1723c14d15aeSRobert Watson * Allow privilege with respect to the Partition policy, but not the 1724c14d15aeSRobert Watson * Privs policy. 1725c14d15aeSRobert Watson */ 1726c14d15aeSRobert Watson case PRIV_MAC_PARTITION: 1727c14d15aeSRobert Watson 1728c14d15aeSRobert Watson /* 1729c14d15aeSRobert Watson * Allow privilege with respect to process resource limits and login 1730c14d15aeSRobert Watson * context. 1731c14d15aeSRobert Watson */ 1732c14d15aeSRobert Watson case PRIV_PROC_LIMIT: 1733c14d15aeSRobert Watson case PRIV_PROC_SETLOGIN: 1734c14d15aeSRobert Watson case PRIV_PROC_SETRLIMIT: 1735c14d15aeSRobert Watson 1736c14d15aeSRobert Watson /* 1737c14d15aeSRobert Watson * Allow System V and POSIX IPC privileges. 1738c14d15aeSRobert Watson */ 1739c14d15aeSRobert Watson case PRIV_IPC_READ: 1740c14d15aeSRobert Watson case PRIV_IPC_WRITE: 1741c14d15aeSRobert Watson case PRIV_IPC_ADMIN: 1742c14d15aeSRobert Watson case PRIV_IPC_MSGSIZE: 1743c14d15aeSRobert Watson case PRIV_MQ_ADMIN: 1744c14d15aeSRobert Watson 1745c14d15aeSRobert Watson /* 1746c14d15aeSRobert Watson * Allow certain scheduler manipulations -- possibly this should be 1747c14d15aeSRobert Watson * controlled by more fine-grained policy, as potentially low 1748c14d15aeSRobert Watson * integrity processes can deny CPU to higher integrity ones. 1749c14d15aeSRobert Watson */ 1750c14d15aeSRobert Watson case PRIV_SCHED_DIFFCRED: 1751c14d15aeSRobert Watson case PRIV_SCHED_SETPRIORITY: 1752c14d15aeSRobert Watson case PRIV_SCHED_RTPRIO: 1753c14d15aeSRobert Watson case PRIV_SCHED_SETPOLICY: 1754c14d15aeSRobert Watson case PRIV_SCHED_SET: 1755c14d15aeSRobert Watson case PRIV_SCHED_SETPARAM: 1756a20a2450SFlorian Walpen case PRIV_SCHED_IDPRIO: 1757c14d15aeSRobert Watson 1758c14d15aeSRobert Watson /* 1759c14d15aeSRobert Watson * More IPC privileges. 1760c14d15aeSRobert Watson */ 1761c14d15aeSRobert Watson case PRIV_SEM_WRITE: 1762c14d15aeSRobert Watson 1763c14d15aeSRobert Watson /* 1764c14d15aeSRobert Watson * Allow signaling privileges subject to integrity policy. 1765c14d15aeSRobert Watson */ 1766c14d15aeSRobert Watson case PRIV_SIGNAL_DIFFCRED: 1767c14d15aeSRobert Watson case PRIV_SIGNAL_SUGID: 1768c14d15aeSRobert Watson 1769c14d15aeSRobert Watson /* 1770c14d15aeSRobert Watson * Allow access to only limited sysctls from lower integrity levels; 1771c14d15aeSRobert Watson * piggy-back on the Jail definition. 1772c14d15aeSRobert Watson */ 1773c14d15aeSRobert Watson case PRIV_SYSCTL_WRITEJAIL: 1774c14d15aeSRobert Watson 1775c14d15aeSRobert Watson /* 1776c14d15aeSRobert Watson * Allow TTY-based privileges, subject to general device access using 1777c14d15aeSRobert Watson * labels on TTY device nodes, but not console privilege. 1778c14d15aeSRobert Watson */ 1779c14d15aeSRobert Watson case PRIV_TTY_DRAINWAIT: 1780c14d15aeSRobert Watson case PRIV_TTY_DTRWAIT: 1781c14d15aeSRobert Watson case PRIV_TTY_EXCLUSIVE: 1782c14d15aeSRobert Watson case PRIV_TTY_STI: 1783c14d15aeSRobert Watson case PRIV_TTY_SETA: 1784c14d15aeSRobert Watson 1785c14d15aeSRobert Watson /* 1786c14d15aeSRobert Watson * Grant most VFS privileges, as almost all are in practice bounded 1787c14d15aeSRobert Watson * by more specific checks using labels. 1788c14d15aeSRobert Watson */ 1789c14d15aeSRobert Watson case PRIV_VFS_READ: 1790c14d15aeSRobert Watson case PRIV_VFS_WRITE: 1791c14d15aeSRobert Watson case PRIV_VFS_ADMIN: 1792c14d15aeSRobert Watson case PRIV_VFS_EXEC: 1793c14d15aeSRobert Watson case PRIV_VFS_LOOKUP: 1794c14d15aeSRobert Watson case PRIV_VFS_CHFLAGS_DEV: 1795c14d15aeSRobert Watson case PRIV_VFS_CHOWN: 1796c14d15aeSRobert Watson case PRIV_VFS_CHROOT: 1797c14d15aeSRobert Watson case PRIV_VFS_RETAINSUGID: 1798c14d15aeSRobert Watson case PRIV_VFS_EXCEEDQUOTA: 1799c14d15aeSRobert Watson case PRIV_VFS_FCHROOT: 1800c14d15aeSRobert Watson case PRIV_VFS_FHOPEN: 1801c14d15aeSRobert Watson case PRIV_VFS_FHSTATFS: 1802c14d15aeSRobert Watson case PRIV_VFS_GENERATION: 1803c14d15aeSRobert Watson case PRIV_VFS_GETFH: 1804c14d15aeSRobert Watson case PRIV_VFS_GETQUOTA: 1805c14d15aeSRobert Watson case PRIV_VFS_LINK: 1806c14d15aeSRobert Watson case PRIV_VFS_MOUNT: 1807c14d15aeSRobert Watson case PRIV_VFS_MOUNT_OWNER: 1808c14d15aeSRobert Watson case PRIV_VFS_MOUNT_PERM: 1809c14d15aeSRobert Watson case PRIV_VFS_MOUNT_SUIDDIR: 1810c14d15aeSRobert Watson case PRIV_VFS_MOUNT_NONUSER: 1811c14d15aeSRobert Watson case PRIV_VFS_SETGID: 1812c14d15aeSRobert Watson case PRIV_VFS_STICKYFILE: 1813c14d15aeSRobert Watson case PRIV_VFS_SYSFLAGS: 1814c14d15aeSRobert Watson case PRIV_VFS_UNMOUNT: 1815c14d15aeSRobert Watson 1816c14d15aeSRobert Watson /* 1817c14d15aeSRobert Watson * Allow VM privileges; it would be nice if these were subject to 1818c14d15aeSRobert Watson * resource limits. 1819c14d15aeSRobert Watson */ 1820c14d15aeSRobert Watson case PRIV_VM_MADV_PROTECT: 1821c14d15aeSRobert Watson case PRIV_VM_MLOCK: 1822c14d15aeSRobert Watson case PRIV_VM_MUNLOCK: 18233364c323SKonstantin Belousov case PRIV_VM_SWAP_NOQUOTA: 18243364c323SKonstantin Belousov case PRIV_VM_SWAP_NORLIMIT: 1825c14d15aeSRobert Watson 1826c14d15aeSRobert Watson /* 1827c14d15aeSRobert Watson * Allow some but not all network privileges. In general, dont allow 1828c14d15aeSRobert Watson * reconfiguring the network stack, just normal use. 1829c14d15aeSRobert Watson */ 1830c14d15aeSRobert Watson case PRIV_NETINET_RESERVEDPORT: 1831c14d15aeSRobert Watson case PRIV_NETINET_RAW: 1832c14d15aeSRobert Watson case PRIV_NETINET_REUSEPORT: 1833c14d15aeSRobert Watson break; 1834c14d15aeSRobert Watson 1835c14d15aeSRobert Watson /* 1836c14d15aeSRobert Watson * All remaining system privileges are allow only if the process 1837c14d15aeSRobert Watson * holds privilege with respect to the LOMAC policy. 1838c14d15aeSRobert Watson */ 1839c14d15aeSRobert Watson default: 1840c14d15aeSRobert Watson subj = SLOT(cred->cr_label); 18413f1a7a90SRobert Watson error = lomac_subject_privileged(subj); 1842c14d15aeSRobert Watson if (error) 1843c14d15aeSRobert Watson return (error); 1844c14d15aeSRobert Watson } 1845c14d15aeSRobert Watson return (0); 1846c14d15aeSRobert Watson } 1847c14d15aeSRobert Watson 1848eb320b0eSRobert Watson static int 1849eb320b0eSRobert Watson lomac_proc_check_debug(struct ucred *cred, struct proc *p) 1850eb320b0eSRobert Watson { 1851eb320b0eSRobert Watson struct mac_lomac *subj, *obj; 1852eb320b0eSRobert Watson 1853eb320b0eSRobert Watson if (!lomac_enabled) 1854eb320b0eSRobert Watson return (0); 1855eb320b0eSRobert Watson 1856eb320b0eSRobert Watson subj = SLOT(cred->cr_label); 1857eb320b0eSRobert Watson obj = SLOT(p->p_ucred->cr_label); 1858eb320b0eSRobert Watson 1859eb320b0eSRobert Watson /* XXX: range checks */ 1860eb320b0eSRobert Watson if (!lomac_dominate_single(obj, subj)) 1861eb320b0eSRobert Watson return (ESRCH); 1862eb320b0eSRobert Watson if (!lomac_subject_dominate(subj, obj)) 1863eb320b0eSRobert Watson return (EACCES); 1864eb320b0eSRobert Watson 1865eb320b0eSRobert Watson return (0); 1866eb320b0eSRobert Watson } 1867eb320b0eSRobert Watson 1868eb320b0eSRobert Watson static int 1869eb320b0eSRobert Watson lomac_proc_check_sched(struct ucred *cred, struct proc *p) 1870eb320b0eSRobert Watson { 1871eb320b0eSRobert Watson struct mac_lomac *subj, *obj; 1872eb320b0eSRobert Watson 1873eb320b0eSRobert Watson if (!lomac_enabled) 1874eb320b0eSRobert Watson return (0); 1875eb320b0eSRobert Watson 1876eb320b0eSRobert Watson subj = SLOT(cred->cr_label); 1877eb320b0eSRobert Watson obj = SLOT(p->p_ucred->cr_label); 1878eb320b0eSRobert Watson 1879eb320b0eSRobert Watson /* XXX: range checks */ 1880eb320b0eSRobert Watson if (!lomac_dominate_single(obj, subj)) 1881eb320b0eSRobert Watson return (ESRCH); 1882eb320b0eSRobert Watson if (!lomac_subject_dominate(subj, obj)) 1883eb320b0eSRobert Watson return (EACCES); 1884eb320b0eSRobert Watson 1885eb320b0eSRobert Watson return (0); 1886eb320b0eSRobert Watson } 1887eb320b0eSRobert Watson 1888eb320b0eSRobert Watson static int 1889eb320b0eSRobert Watson lomac_proc_check_signal(struct ucred *cred, struct proc *p, int signum) 1890eb320b0eSRobert Watson { 1891eb320b0eSRobert Watson struct mac_lomac *subj, *obj; 1892eb320b0eSRobert Watson 1893eb320b0eSRobert Watson if (!lomac_enabled) 1894eb320b0eSRobert Watson return (0); 1895eb320b0eSRobert Watson 1896eb320b0eSRobert Watson subj = SLOT(cred->cr_label); 1897eb320b0eSRobert Watson obj = SLOT(p->p_ucred->cr_label); 1898eb320b0eSRobert Watson 1899eb320b0eSRobert Watson /* XXX: range checks */ 1900eb320b0eSRobert Watson if (!lomac_dominate_single(obj, subj)) 1901eb320b0eSRobert Watson return (ESRCH); 1902eb320b0eSRobert Watson if (!lomac_subject_dominate(subj, obj)) 1903eb320b0eSRobert Watson return (EACCES); 1904eb320b0eSRobert Watson 1905eb320b0eSRobert Watson return (0); 1906eb320b0eSRobert Watson } 1907eb320b0eSRobert Watson 1908eb320b0eSRobert Watson static void 1909eb320b0eSRobert Watson lomac_proc_destroy_label(struct label *label) 1910eb320b0eSRobert Watson { 1911eb320b0eSRobert Watson 1912eb320b0eSRobert Watson mtx_destroy(&PSLOT(label)->mtx); 19131ede983cSDag-Erling Smørgrav free(PSLOT(label), M_LOMAC); 1914eb320b0eSRobert Watson PSLOT_SET(label, NULL); 1915eb320b0eSRobert Watson } 1916eb320b0eSRobert Watson 1917eb320b0eSRobert Watson static void 1918eb320b0eSRobert Watson lomac_proc_init_label(struct label *label) 1919eb320b0eSRobert Watson { 1920eb320b0eSRobert Watson 1921eb320b0eSRobert Watson PSLOT_SET(label, malloc(sizeof(struct mac_lomac_proc), M_LOMAC, 1922eb320b0eSRobert Watson M_ZERO | M_WAITOK)); 1923eb320b0eSRobert Watson mtx_init(&PSLOT(label)->mtx, "MAC/Lomac proc lock", NULL, MTX_DEF); 1924eb320b0eSRobert Watson } 1925eb320b0eSRobert Watson 1926eb320b0eSRobert Watson static int 1927eb320b0eSRobert Watson lomac_socket_check_deliver(struct socket *so, struct label *solabel, 1928eb320b0eSRobert Watson struct mbuf *m, struct label *mlabel) 1929eb320b0eSRobert Watson { 1930eb320b0eSRobert Watson struct mac_lomac *p, *s; 19313de40469SRobert Watson int error; 1932eb320b0eSRobert Watson 1933eb320b0eSRobert Watson if (!lomac_enabled) 1934eb320b0eSRobert Watson return (0); 1935eb320b0eSRobert Watson 1936eb320b0eSRobert Watson p = SLOT(mlabel); 1937eb320b0eSRobert Watson s = SLOT(solabel); 1938eb320b0eSRobert Watson 19393de40469SRobert Watson SOCK_LOCK(so); 19403de40469SRobert Watson error = lomac_equal_single(p, s) ? 0 : EACCES; 19413de40469SRobert Watson SOCK_UNLOCK(so); 19423de40469SRobert Watson return (error); 1943eb320b0eSRobert Watson } 1944eb320b0eSRobert Watson 1945eb320b0eSRobert Watson static int 1946eb320b0eSRobert Watson lomac_socket_check_relabel(struct ucred *cred, struct socket *so, 1947eb320b0eSRobert Watson struct label *solabel, struct label *newlabel) 1948eb320b0eSRobert Watson { 1949eb320b0eSRobert Watson struct mac_lomac *subj, *obj, *new; 1950eb320b0eSRobert Watson int error; 1951eb320b0eSRobert Watson 19523de40469SRobert Watson SOCK_LOCK_ASSERT(so); 19533de40469SRobert Watson 1954eb320b0eSRobert Watson new = SLOT(newlabel); 1955eb320b0eSRobert Watson subj = SLOT(cred->cr_label); 1956eb320b0eSRobert Watson obj = SLOT(solabel); 1957eb320b0eSRobert Watson 1958eb320b0eSRobert Watson /* 1959eb320b0eSRobert Watson * If there is a LOMAC label update for the socket, it may be an 1960eb320b0eSRobert Watson * update of single. 1961eb320b0eSRobert Watson */ 1962eb320b0eSRobert Watson error = lomac_atmostflags(new, MAC_LOMAC_FLAG_SINGLE); 1963eb320b0eSRobert Watson if (error) 1964eb320b0eSRobert Watson return (error); 1965eb320b0eSRobert Watson 1966eb320b0eSRobert Watson /* 1967eb320b0eSRobert Watson * To relabel a socket, the old socket single must be in the subject 1968eb320b0eSRobert Watson * range. 1969eb320b0eSRobert Watson */ 1970eb320b0eSRobert Watson if (!lomac_single_in_range(obj, subj)) 1971eb320b0eSRobert Watson return (EPERM); 1972eb320b0eSRobert Watson 1973eb320b0eSRobert Watson /* 1974eb320b0eSRobert Watson * If the LOMAC label is to be changed, authorize as appropriate. 1975eb320b0eSRobert Watson */ 1976eb320b0eSRobert Watson if (new->ml_flags & MAC_LOMAC_FLAG_SINGLE) { 1977eb320b0eSRobert Watson /* 1978eb320b0eSRobert Watson * To relabel a socket, the new socket single must be in the 1979eb320b0eSRobert Watson * subject range. 1980eb320b0eSRobert Watson */ 1981eb320b0eSRobert Watson if (!lomac_single_in_range(new, subj)) 1982eb320b0eSRobert Watson return (EPERM); 1983eb320b0eSRobert Watson 1984eb320b0eSRobert Watson /* 1985eb320b0eSRobert Watson * To change the LOMAC label on the socket to contain EQUAL, 1986eb320b0eSRobert Watson * the subject must have appropriate privilege. 1987eb320b0eSRobert Watson */ 1988eb320b0eSRobert Watson if (lomac_contains_equal(new)) { 1989eb320b0eSRobert Watson error = lomac_subject_privileged(subj); 1990eb320b0eSRobert Watson if (error) 1991eb320b0eSRobert Watson return (error); 1992eb320b0eSRobert Watson } 1993eb320b0eSRobert Watson } 1994eb320b0eSRobert Watson 1995eb320b0eSRobert Watson return (0); 1996eb320b0eSRobert Watson } 1997eb320b0eSRobert Watson 1998eb320b0eSRobert Watson static int 1999eb320b0eSRobert Watson lomac_socket_check_visible(struct ucred *cred, struct socket *so, 2000eb320b0eSRobert Watson struct label *solabel) 2001eb320b0eSRobert Watson { 2002eb320b0eSRobert Watson struct mac_lomac *subj, *obj; 2003eb320b0eSRobert Watson 2004eb320b0eSRobert Watson if (!lomac_enabled) 2005eb320b0eSRobert Watson return (0); 2006eb320b0eSRobert Watson 2007eb320b0eSRobert Watson subj = SLOT(cred->cr_label); 2008eb320b0eSRobert Watson obj = SLOT(solabel); 2009eb320b0eSRobert Watson 20103de40469SRobert Watson SOCK_LOCK(so); 20113de40469SRobert Watson if (!lomac_dominate_single(obj, subj)) { 20123de40469SRobert Watson SOCK_UNLOCK(so); 2013eb320b0eSRobert Watson return (ENOENT); 20143de40469SRobert Watson } 20153de40469SRobert Watson SOCK_UNLOCK(so); 2016eb320b0eSRobert Watson 2017eb320b0eSRobert Watson return (0); 2018eb320b0eSRobert Watson } 2019eb320b0eSRobert Watson 2020eb320b0eSRobert Watson static void 2021eb320b0eSRobert Watson lomac_socket_create(struct ucred *cred, struct socket *so, 2022eb320b0eSRobert Watson struct label *solabel) 2023eb320b0eSRobert Watson { 2024eb320b0eSRobert Watson struct mac_lomac *source, *dest; 2025eb320b0eSRobert Watson 2026eb320b0eSRobert Watson source = SLOT(cred->cr_label); 2027eb320b0eSRobert Watson dest = SLOT(solabel); 2028eb320b0eSRobert Watson 2029eb320b0eSRobert Watson lomac_copy_single(source, dest); 2030eb320b0eSRobert Watson } 2031eb320b0eSRobert Watson 2032eb320b0eSRobert Watson static void 2033eb320b0eSRobert Watson lomac_socket_create_mbuf(struct socket *so, struct label *solabel, 2034eb320b0eSRobert Watson struct mbuf *m, struct label *mlabel) 2035eb320b0eSRobert Watson { 2036eb320b0eSRobert Watson struct mac_lomac *source, *dest; 2037eb320b0eSRobert Watson 2038eb320b0eSRobert Watson source = SLOT(solabel); 2039eb320b0eSRobert Watson dest = SLOT(mlabel); 2040eb320b0eSRobert Watson 20413de40469SRobert Watson SOCK_LOCK(so); 2042eb320b0eSRobert Watson lomac_copy_single(source, dest); 20433de40469SRobert Watson SOCK_UNLOCK(so); 2044eb320b0eSRobert Watson } 2045eb320b0eSRobert Watson 2046eb320b0eSRobert Watson static void 2047eb320b0eSRobert Watson lomac_socket_newconn(struct socket *oldso, struct label *oldsolabel, 2048eb320b0eSRobert Watson struct socket *newso, struct label *newsolabel) 2049eb320b0eSRobert Watson { 20503de40469SRobert Watson struct mac_lomac source, *dest; 2051eb320b0eSRobert Watson 20523de40469SRobert Watson SOCK_LOCK(oldso); 20533de40469SRobert Watson source = *SLOT(oldsolabel); 20543de40469SRobert Watson SOCK_UNLOCK(oldso); 20553de40469SRobert Watson 2056eb320b0eSRobert Watson dest = SLOT(newsolabel); 2057eb320b0eSRobert Watson 20583de40469SRobert Watson SOCK_LOCK(newso); 20593de40469SRobert Watson lomac_copy_single(&source, dest); 20603de40469SRobert Watson SOCK_UNLOCK(newso); 2061eb320b0eSRobert Watson } 2062eb320b0eSRobert Watson 2063eb320b0eSRobert Watson static void 2064eb320b0eSRobert Watson lomac_socket_relabel(struct ucred *cred, struct socket *so, 2065eb320b0eSRobert Watson struct label *solabel, struct label *newlabel) 2066eb320b0eSRobert Watson { 2067eb320b0eSRobert Watson struct mac_lomac *source, *dest; 2068eb320b0eSRobert Watson 20693de40469SRobert Watson SOCK_LOCK_ASSERT(so); 20703de40469SRobert Watson 2071eb320b0eSRobert Watson source = SLOT(newlabel); 2072eb320b0eSRobert Watson dest = SLOT(solabel); 2073eb320b0eSRobert Watson 2074eb320b0eSRobert Watson try_relabel(source, dest); 2075eb320b0eSRobert Watson } 2076eb320b0eSRobert Watson 2077eb320b0eSRobert Watson static void 2078eb320b0eSRobert Watson lomac_socketpeer_set_from_mbuf(struct mbuf *m, struct label *mlabel, 2079eb320b0eSRobert Watson struct socket *so, struct label *sopeerlabel) 2080eb320b0eSRobert Watson { 2081eb320b0eSRobert Watson struct mac_lomac *source, *dest; 2082eb320b0eSRobert Watson 2083eb320b0eSRobert Watson source = SLOT(mlabel); 2084eb320b0eSRobert Watson dest = SLOT(sopeerlabel); 2085eb320b0eSRobert Watson 20863de40469SRobert Watson SOCK_LOCK(so); 2087eb320b0eSRobert Watson lomac_copy_single(source, dest); 20883de40469SRobert Watson SOCK_UNLOCK(so); 2089eb320b0eSRobert Watson } 2090eb320b0eSRobert Watson 2091eb320b0eSRobert Watson static void 2092eb320b0eSRobert Watson lomac_socketpeer_set_from_socket(struct socket *oldso, 2093eb320b0eSRobert Watson struct label *oldsolabel, struct socket *newso, 2094eb320b0eSRobert Watson struct label *newsopeerlabel) 2095eb320b0eSRobert Watson { 20963de40469SRobert Watson struct mac_lomac source, *dest; 2097eb320b0eSRobert Watson 20983de40469SRobert Watson SOCK_LOCK(oldso); 20993de40469SRobert Watson source = *SLOT(oldsolabel); 21003de40469SRobert Watson SOCK_UNLOCK(oldso); 21013de40469SRobert Watson 2102eb320b0eSRobert Watson dest = SLOT(newsopeerlabel); 2103eb320b0eSRobert Watson 21043de40469SRobert Watson SOCK_LOCK(newso); 21053de40469SRobert Watson lomac_copy_single(&source, dest); 21063de40469SRobert Watson SOCK_UNLOCK(newso); 2107eb320b0eSRobert Watson } 2108eb320b0eSRobert Watson 2109eb320b0eSRobert Watson static void 2110eb320b0eSRobert Watson lomac_syncache_create(struct label *label, struct inpcb *inp) 2111eb320b0eSRobert Watson { 2112eb320b0eSRobert Watson struct mac_lomac *source, *dest; 2113eb320b0eSRobert Watson 2114eb320b0eSRobert Watson source = SLOT(inp->inp_label); 2115eb320b0eSRobert Watson dest = SLOT(label); 2116eb320b0eSRobert Watson lomac_copy(source, dest); 2117eb320b0eSRobert Watson } 2118eb320b0eSRobert Watson 2119eb320b0eSRobert Watson static void 2120eb320b0eSRobert Watson lomac_syncache_create_mbuf(struct label *sc_label, struct mbuf *m, 2121eb320b0eSRobert Watson struct label *mlabel) 2122eb320b0eSRobert Watson { 2123eb320b0eSRobert Watson struct mac_lomac *source, *dest; 2124eb320b0eSRobert Watson 2125eb320b0eSRobert Watson source = SLOT(sc_label); 2126eb320b0eSRobert Watson dest = SLOT(mlabel); 2127eb320b0eSRobert Watson lomac_copy(source, dest); 2128eb320b0eSRobert Watson } 2129c14d15aeSRobert Watson 2130db2661ceSRobert Watson static int 21313f1a7a90SRobert Watson lomac_system_check_acct(struct ucred *cred, struct vnode *vp, 213278007886SRobert Watson struct label *vplabel) 213318717f69SRobert Watson { 213418717f69SRobert Watson struct mac_lomac *subj, *obj; 213518717f69SRobert Watson 21363f1a7a90SRobert Watson if (!lomac_enabled) 213718717f69SRobert Watson return (0); 213818717f69SRobert Watson 213918717f69SRobert Watson subj = SLOT(cred->cr_label); 214078007886SRobert Watson obj = SLOT(vplabel); 214118717f69SRobert Watson 21423f1a7a90SRobert Watson if (lomac_subject_privileged(subj)) 214318717f69SRobert Watson return (EPERM); 214418717f69SRobert Watson 21453f1a7a90SRobert Watson if (!lomac_high_single(obj)) 214618717f69SRobert Watson return (EACCES); 214718717f69SRobert Watson 214818717f69SRobert Watson return (0); 214918717f69SRobert Watson } 215018717f69SRobert Watson 215118717f69SRobert Watson static int 21523f1a7a90SRobert Watson lomac_system_check_auditctl(struct ucred *cred, struct vnode *vp, 215378007886SRobert Watson struct label *vplabel) 215418717f69SRobert Watson { 215518717f69SRobert Watson struct mac_lomac *subj, *obj; 215618717f69SRobert Watson 21573f1a7a90SRobert Watson if (!lomac_enabled) 215818717f69SRobert Watson return (0); 215918717f69SRobert Watson 216018717f69SRobert Watson subj = SLOT(cred->cr_label); 216178007886SRobert Watson obj = SLOT(vplabel); 216218717f69SRobert Watson 21633f1a7a90SRobert Watson if (lomac_subject_privileged(subj)) 216418717f69SRobert Watson return (EPERM); 216518717f69SRobert Watson 21663f1a7a90SRobert Watson if (!lomac_high_single(obj)) 216718717f69SRobert Watson return (EACCES); 216818717f69SRobert Watson 216918717f69SRobert Watson return (0); 217018717f69SRobert Watson } 217118717f69SRobert Watson 217218717f69SRobert Watson static int 21733f1a7a90SRobert Watson lomac_system_check_swapoff(struct ucred *cred, struct vnode *vp, 217478007886SRobert Watson struct label *vplabel) 217518717f69SRobert Watson { 217618717f69SRobert Watson struct mac_lomac *subj; 217718717f69SRobert Watson 21783f1a7a90SRobert Watson if (!lomac_enabled) 217918717f69SRobert Watson return (0); 218018717f69SRobert Watson 218118717f69SRobert Watson subj = SLOT(cred->cr_label); 218218717f69SRobert Watson 21833f1a7a90SRobert Watson if (lomac_subject_privileged(subj)) 218418717f69SRobert Watson return (EPERM); 218518717f69SRobert Watson 218618717f69SRobert Watson return (0); 218718717f69SRobert Watson } 218818717f69SRobert Watson 218918717f69SRobert Watson static int 21903f1a7a90SRobert Watson lomac_system_check_swapon(struct ucred *cred, struct vnode *vp, 219178007886SRobert Watson struct label *vplabel) 2192db2661ceSRobert Watson { 2193db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2194db2661ceSRobert Watson 21953f1a7a90SRobert Watson if (!lomac_enabled) 2196db2661ceSRobert Watson return (0); 2197db2661ceSRobert Watson 2198eca8a663SRobert Watson subj = SLOT(cred->cr_label); 219978007886SRobert Watson obj = SLOT(vplabel); 2200db2661ceSRobert Watson 22013f1a7a90SRobert Watson if (lomac_subject_privileged(subj)) 2202db2661ceSRobert Watson return (EPERM); 2203db2661ceSRobert Watson 22043f1a7a90SRobert Watson if (!lomac_high_single(obj)) 2205db2661ceSRobert Watson return (EACCES); 2206db2661ceSRobert Watson 2207db2661ceSRobert Watson return (0); 2208db2661ceSRobert Watson } 2209db2661ceSRobert Watson 2210db2661ceSRobert Watson static int 22113f1a7a90SRobert Watson lomac_system_check_sysctl(struct ucred *cred, struct sysctl_oid *oidp, 221263dba32bSPawel Jakub Dawidek void *arg1, int arg2, struct sysctl_req *req) 2213db2661ceSRobert Watson { 2214db2661ceSRobert Watson struct mac_lomac *subj; 2215db2661ceSRobert Watson 22163f1a7a90SRobert Watson if (!lomac_enabled) 2217db2661ceSRobert Watson return (0); 2218db2661ceSRobert Watson 2219eca8a663SRobert Watson subj = SLOT(cred->cr_label); 2220db2661ceSRobert Watson 2221db2661ceSRobert Watson /* 22223f1a7a90SRobert Watson * Treat sysctl variables without CTLFLAG_ANYBODY flag as lomac/high, 22233f1a7a90SRobert Watson * but also require privilege to change them. 2224db2661ceSRobert Watson */ 222563dba32bSPawel Jakub Dawidek if (req->newptr != NULL && (oidp->oid_kind & CTLFLAG_ANYBODY) == 0) { 2226db2661ceSRobert Watson #ifdef notdef 22273f1a7a90SRobert Watson if (!lomac_subject_dominate_high(subj)) 2228db2661ceSRobert Watson return (EACCES); 2229db2661ceSRobert Watson #endif 2230db2661ceSRobert Watson 22313f1a7a90SRobert Watson if (lomac_subject_privileged(subj)) 2232db2661ceSRobert Watson return (EPERM); 2233db2661ceSRobert Watson } 2234db2661ceSRobert Watson 2235db2661ceSRobert Watson return (0); 2236db2661ceSRobert Watson } 2237db2661ceSRobert Watson 2238eb320b0eSRobert Watson static void 2239eb320b0eSRobert Watson lomac_thread_userret(struct thread *td) 2240eb320b0eSRobert Watson { 2241eb320b0eSRobert Watson struct proc *p = td->td_proc; 2242eb320b0eSRobert Watson struct mac_lomac_proc *subj = PSLOT(p->p_label); 2243eb320b0eSRobert Watson struct ucred *newcred, *oldcred; 2244eb320b0eSRobert Watson int dodrop; 2245eb320b0eSRobert Watson 2246eb320b0eSRobert Watson mtx_lock(&subj->mtx); 2247eb320b0eSRobert Watson if (subj->mac_lomac.ml_flags & MAC_LOMAC_FLAG_UPDATE) { 2248eb320b0eSRobert Watson dodrop = 0; 2249eb320b0eSRobert Watson mtx_unlock(&subj->mtx); 2250eb320b0eSRobert Watson newcred = crget(); 2251eb320b0eSRobert Watson PROC_LOCK(p); 2252eb320b0eSRobert Watson mtx_lock(&subj->mtx); 2253eb320b0eSRobert Watson /* 2254eb320b0eSRobert Watson * Check if we lost the race while allocating the cred. 2255eb320b0eSRobert Watson */ 2256eb320b0eSRobert Watson if ((subj->mac_lomac.ml_flags & MAC_LOMAC_FLAG_UPDATE) == 0) { 2257eb320b0eSRobert Watson crfree(newcred); 2258eb320b0eSRobert Watson goto out; 2259eb320b0eSRobert Watson } 2260eb320b0eSRobert Watson oldcred = p->p_ucred; 2261eb320b0eSRobert Watson crcopy(newcred, oldcred); 2262eb320b0eSRobert Watson crhold(newcred); 2263eb320b0eSRobert Watson lomac_copy(&subj->mac_lomac, SLOT(newcred->cr_label)); 2264daf63fd2SMateusz Guzik proc_set_cred(p, newcred); 2265eb320b0eSRobert Watson crfree(oldcred); 2266eb320b0eSRobert Watson dodrop = 1; 2267eb320b0eSRobert Watson out: 2268eb320b0eSRobert Watson mtx_unlock(&subj->mtx); 2269eb320b0eSRobert Watson PROC_UNLOCK(p); 2270eb320b0eSRobert Watson if (dodrop) 22719215889dSRobert Watson mac_proc_vm_revoke(curthread); 2272eb320b0eSRobert Watson } else { 2273eb320b0eSRobert Watson mtx_unlock(&subj->mtx); 2274eb320b0eSRobert Watson } 2275eb320b0eSRobert Watson } 2276eb320b0eSRobert Watson 2277eb320b0eSRobert Watson static int 2278eb320b0eSRobert Watson lomac_vnode_associate_extattr(struct mount *mp, struct label *mplabel, 2279eb320b0eSRobert Watson struct vnode *vp, struct label *vplabel) 2280eb320b0eSRobert Watson { 2281eb320b0eSRobert Watson struct mac_lomac ml_temp, *source, *dest; 2282eb320b0eSRobert Watson int buflen, error; 2283eb320b0eSRobert Watson 2284eb320b0eSRobert Watson source = SLOT(mplabel); 2285eb320b0eSRobert Watson dest = SLOT(vplabel); 2286eb320b0eSRobert Watson 2287eb320b0eSRobert Watson buflen = sizeof(ml_temp); 2288eb320b0eSRobert Watson bzero(&ml_temp, buflen); 2289eb320b0eSRobert Watson 2290eb320b0eSRobert Watson error = vn_extattr_get(vp, IO_NODELOCKED, MAC_LOMAC_EXTATTR_NAMESPACE, 2291eb320b0eSRobert Watson MAC_LOMAC_EXTATTR_NAME, &buflen, (char *)&ml_temp, curthread); 2292eb320b0eSRobert Watson if (error == ENOATTR || error == EOPNOTSUPP) { 2293eb320b0eSRobert Watson /* Fall back to the mntlabel. */ 2294eb320b0eSRobert Watson lomac_copy_single(source, dest); 2295eb320b0eSRobert Watson return (0); 2296eb320b0eSRobert Watson } else if (error) 2297eb320b0eSRobert Watson return (error); 2298eb320b0eSRobert Watson 2299eb320b0eSRobert Watson if (buflen != sizeof(ml_temp)) { 2300eb320b0eSRobert Watson if (buflen != sizeof(ml_temp) - sizeof(ml_temp.ml_auxsingle)) { 2301eb320b0eSRobert Watson printf("lomac_vnode_associate_extattr: bad size %d\n", 2302eb320b0eSRobert Watson buflen); 2303eb320b0eSRobert Watson return (EPERM); 2304eb320b0eSRobert Watson } 2305eb320b0eSRobert Watson bzero(&ml_temp.ml_auxsingle, sizeof(ml_temp.ml_auxsingle)); 2306eb320b0eSRobert Watson buflen = sizeof(ml_temp); 2307eb320b0eSRobert Watson (void)vn_extattr_set(vp, IO_NODELOCKED, 2308eb320b0eSRobert Watson MAC_LOMAC_EXTATTR_NAMESPACE, MAC_LOMAC_EXTATTR_NAME, 2309eb320b0eSRobert Watson buflen, (char *)&ml_temp, curthread); 2310eb320b0eSRobert Watson } 2311eb320b0eSRobert Watson if (lomac_valid(&ml_temp) != 0) { 2312eb320b0eSRobert Watson printf("lomac_vnode_associate_extattr: invalid\n"); 2313eb320b0eSRobert Watson return (EPERM); 2314eb320b0eSRobert Watson } 2315eb320b0eSRobert Watson if ((ml_temp.ml_flags & MAC_LOMAC_FLAGS_BOTH) != 2316eb320b0eSRobert Watson MAC_LOMAC_FLAG_SINGLE) { 2317eb320b0eSRobert Watson printf("lomac_vnode_associate_extattr: not single\n"); 2318eb320b0eSRobert Watson return (EPERM); 2319eb320b0eSRobert Watson } 2320eb320b0eSRobert Watson 2321eb320b0eSRobert Watson lomac_copy_single(&ml_temp, dest); 2322eb320b0eSRobert Watson return (0); 2323eb320b0eSRobert Watson } 2324eb320b0eSRobert Watson 2325eb320b0eSRobert Watson static void 2326eb320b0eSRobert Watson lomac_vnode_associate_singlelabel(struct mount *mp, struct label *mplabel, 2327eb320b0eSRobert Watson struct vnode *vp, struct label *vplabel) 2328eb320b0eSRobert Watson { 2329eb320b0eSRobert Watson struct mac_lomac *source, *dest; 2330eb320b0eSRobert Watson 2331eb320b0eSRobert Watson source = SLOT(mplabel); 2332eb320b0eSRobert Watson dest = SLOT(vplabel); 2333eb320b0eSRobert Watson 2334eb320b0eSRobert Watson lomac_copy_single(source, dest); 2335eb320b0eSRobert Watson } 2336eb320b0eSRobert Watson 2337db2661ceSRobert Watson static int 23383f1a7a90SRobert Watson lomac_vnode_check_create(struct ucred *cred, struct vnode *dvp, 233978007886SRobert Watson struct label *dvplabel, struct componentname *cnp, struct vattr *vap) 2340db2661ceSRobert Watson { 2341db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2342db2661ceSRobert Watson 23433f1a7a90SRobert Watson if (!lomac_enabled) 2344db2661ceSRobert Watson return (0); 2345db2661ceSRobert Watson 2346eca8a663SRobert Watson subj = SLOT(cred->cr_label); 234778007886SRobert Watson obj = SLOT(dvplabel); 2348db2661ceSRobert Watson 23493f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2350db2661ceSRobert Watson return (EACCES); 2351db2661ceSRobert Watson if (obj->ml_flags & MAC_LOMAC_FLAG_AUX && 23523f1a7a90SRobert Watson !lomac_dominate_element(&subj->ml_single, &obj->ml_auxsingle)) 2353db2661ceSRobert Watson return (EACCES); 2354db2661ceSRobert Watson 2355db2661ceSRobert Watson return (0); 2356db2661ceSRobert Watson } 2357db2661ceSRobert Watson 2358db2661ceSRobert Watson static int 23593f1a7a90SRobert Watson lomac_vnode_check_deleteacl(struct ucred *cred, struct vnode *vp, 236078007886SRobert Watson struct label *vplabel, acl_type_t type) 2361db2661ceSRobert Watson { 2362db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2363db2661ceSRobert Watson 23643f1a7a90SRobert Watson if (!lomac_enabled) 2365db2661ceSRobert Watson return (0); 2366db2661ceSRobert Watson 2367eca8a663SRobert Watson subj = SLOT(cred->cr_label); 236878007886SRobert Watson obj = SLOT(vplabel); 2369db2661ceSRobert Watson 23703f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2371db2661ceSRobert Watson return (EACCES); 2372db2661ceSRobert Watson 2373db2661ceSRobert Watson return (0); 2374db2661ceSRobert Watson } 2375db2661ceSRobert Watson 2376db2661ceSRobert Watson static int 23773f1a7a90SRobert Watson lomac_vnode_check_link(struct ucred *cred, struct vnode *dvp, 237878007886SRobert Watson struct label *dvplabel, struct vnode *vp, struct label *vplabel, 2379db2661ceSRobert Watson struct componentname *cnp) 2380db2661ceSRobert Watson { 2381db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2382db2661ceSRobert Watson 23833f1a7a90SRobert Watson if (!lomac_enabled) 2384db2661ceSRobert Watson return (0); 2385db2661ceSRobert Watson 2386eca8a663SRobert Watson subj = SLOT(cred->cr_label); 238778007886SRobert Watson obj = SLOT(dvplabel); 2388db2661ceSRobert Watson 23893f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2390db2661ceSRobert Watson return (EACCES); 2391db2661ceSRobert Watson 239278007886SRobert Watson obj = SLOT(vplabel); 2393db2661ceSRobert Watson 23943f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2395db2661ceSRobert Watson return (EACCES); 2396db2661ceSRobert Watson 2397db2661ceSRobert Watson return (0); 2398db2661ceSRobert Watson } 2399db2661ceSRobert Watson 2400db2661ceSRobert Watson static int 24013f1a7a90SRobert Watson lomac_vnode_check_mmap(struct ucred *cred, struct vnode *vp, 240278007886SRobert Watson struct label *vplabel, int prot, int flags) 2403db2661ceSRobert Watson { 2404db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2405db2661ceSRobert Watson 2406db2661ceSRobert Watson /* 2407db2661ceSRobert Watson * Rely on the use of open()-time protections to handle 2408db2661ceSRobert Watson * non-revocation cases. 2409db2661ceSRobert Watson */ 24103f1a7a90SRobert Watson if (!lomac_enabled) 2411db2661ceSRobert Watson return (0); 2412db2661ceSRobert Watson 2413eca8a663SRobert Watson subj = SLOT(cred->cr_label); 241478007886SRobert Watson obj = SLOT(vplabel); 2415db2661ceSRobert Watson 2416c92163dcSChristian S.J. Peron if (((prot & VM_PROT_WRITE) != 0) && ((flags & MAP_SHARED) != 0)) { 24173f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2418db2661ceSRobert Watson return (EACCES); 2419db2661ceSRobert Watson } 2420db2661ceSRobert Watson if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) { 24213f1a7a90SRobert Watson if (!lomac_dominate_single(obj, subj)) 2422db2661ceSRobert Watson return (maybe_demote(subj, obj, "mapping", "file", vp)); 2423db2661ceSRobert Watson } 2424db2661ceSRobert Watson 2425db2661ceSRobert Watson return (0); 2426db2661ceSRobert Watson } 2427db2661ceSRobert Watson 2428db2661ceSRobert Watson static void 24293f1a7a90SRobert Watson lomac_vnode_check_mmap_downgrade(struct ucred *cred, struct vnode *vp, 243078007886SRobert Watson struct label *vplabel, /* XXX vm_prot_t */ int *prot) 2431db2661ceSRobert Watson { 2432db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2433db2661ceSRobert Watson 2434db2661ceSRobert Watson /* 2435db2661ceSRobert Watson * Rely on the use of open()-time protections to handle 2436db2661ceSRobert Watson * non-revocation cases. 2437db2661ceSRobert Watson */ 24383f1a7a90SRobert Watson if (!lomac_enabled || !revocation_enabled) 2439db2661ceSRobert Watson return; 2440db2661ceSRobert Watson 2441eca8a663SRobert Watson subj = SLOT(cred->cr_label); 244278007886SRobert Watson obj = SLOT(vplabel); 2443db2661ceSRobert Watson 24443f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2445db2661ceSRobert Watson *prot &= ~VM_PROT_WRITE; 2446db2661ceSRobert Watson } 2447db2661ceSRobert Watson 2448db2661ceSRobert Watson static int 24493f1a7a90SRobert Watson lomac_vnode_check_open(struct ucred *cred, struct vnode *vp, 245015bc6b2bSEdward Tomasz Napierala struct label *vplabel, accmode_t accmode) 2451db2661ceSRobert Watson { 2452db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2453db2661ceSRobert Watson 24543f1a7a90SRobert Watson if (!lomac_enabled) 2455db2661ceSRobert Watson return (0); 2456db2661ceSRobert Watson 2457eca8a663SRobert Watson subj = SLOT(cred->cr_label); 245878007886SRobert Watson obj = SLOT(vplabel); 2459db2661ceSRobert Watson 2460db2661ceSRobert Watson /* XXX privilege override for admin? */ 24613a597bfcSEdward Tomasz Napierala if (accmode & VMODIFY_PERMS) { 24623f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2463db2661ceSRobert Watson return (EACCES); 2464db2661ceSRobert Watson } 2465db2661ceSRobert Watson 2466db2661ceSRobert Watson return (0); 2467db2661ceSRobert Watson } 2468db2661ceSRobert Watson 2469db2661ceSRobert Watson static int 24703f1a7a90SRobert Watson lomac_vnode_check_read(struct ucred *active_cred, struct ucred *file_cred, 247178007886SRobert Watson struct vnode *vp, struct label *vplabel) 2472db2661ceSRobert Watson { 2473db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2474db2661ceSRobert Watson 24753f1a7a90SRobert Watson if (!lomac_enabled || !revocation_enabled) 2476db2661ceSRobert Watson return (0); 2477db2661ceSRobert Watson 2478eca8a663SRobert Watson subj = SLOT(active_cred->cr_label); 247978007886SRobert Watson obj = SLOT(vplabel); 2480db2661ceSRobert Watson 24813f1a7a90SRobert Watson if (!lomac_dominate_single(obj, subj)) 2482db2661ceSRobert Watson return (maybe_demote(subj, obj, "reading", "file", vp)); 2483db2661ceSRobert Watson 2484db2661ceSRobert Watson return (0); 2485db2661ceSRobert Watson } 2486db2661ceSRobert Watson 2487db2661ceSRobert Watson static int 24883f1a7a90SRobert Watson lomac_vnode_check_relabel(struct ucred *cred, struct vnode *vp, 248978007886SRobert Watson struct label *vplabel, struct label *newlabel) 2490db2661ceSRobert Watson { 2491db2661ceSRobert Watson struct mac_lomac *old, *new, *subj; 2492db2661ceSRobert Watson int error; 2493db2661ceSRobert Watson 249478007886SRobert Watson old = SLOT(vplabel); 2495db2661ceSRobert Watson new = SLOT(newlabel); 2496eca8a663SRobert Watson subj = SLOT(cred->cr_label); 2497db2661ceSRobert Watson 2498db2661ceSRobert Watson /* 2499db2661ceSRobert Watson * If there is a LOMAC label update for the vnode, it must be a 2500db2661ceSRobert Watson * single label, with an optional explicit auxiliary single. 2501db2661ceSRobert Watson */ 2502db2661ceSRobert Watson error = lomac_atmostflags(new, 2503db2661ceSRobert Watson MAC_LOMAC_FLAG_SINGLE | MAC_LOMAC_FLAG_AUX); 2504db2661ceSRobert Watson if (error) 2505db2661ceSRobert Watson return (error); 2506db2661ceSRobert Watson 2507db2661ceSRobert Watson /* 2508db2661ceSRobert Watson * To perform a relabel of the vnode (LOMAC label or not), LOMAC must 2509db2661ceSRobert Watson * authorize the relabel. 2510db2661ceSRobert Watson */ 25113f1a7a90SRobert Watson if (!lomac_single_in_range(old, subj)) 2512db2661ceSRobert Watson return (EPERM); 2513db2661ceSRobert Watson 2514db2661ceSRobert Watson /* 2515db2661ceSRobert Watson * If the LOMAC label is to be changed, authorize as appropriate. 2516db2661ceSRobert Watson */ 2517db2661ceSRobert Watson if (new->ml_flags & MAC_LOMAC_FLAG_SINGLE) { 2518db2661ceSRobert Watson /* 2519db2661ceSRobert Watson * To change the LOMAC label on a vnode, the new vnode label 2520db2661ceSRobert Watson * must be in the subject range. 2521db2661ceSRobert Watson */ 25223f1a7a90SRobert Watson if (!lomac_single_in_range(new, subj)) 2523db2661ceSRobert Watson return (EPERM); 2524db2661ceSRobert Watson 2525db2661ceSRobert Watson /* 25263f1a7a90SRobert Watson * To change the LOMAC label on the vnode to be EQUAL, the 25273f1a7a90SRobert Watson * subject must have appropriate privilege. 2528db2661ceSRobert Watson */ 25293f1a7a90SRobert Watson if (lomac_contains_equal(new)) { 25303f1a7a90SRobert Watson error = lomac_subject_privileged(subj); 2531db2661ceSRobert Watson if (error) 2532db2661ceSRobert Watson return (error); 2533db2661ceSRobert Watson } 2534db2661ceSRobert Watson } 2535db2661ceSRobert Watson if (new->ml_flags & MAC_LOMAC_FLAG_AUX) { 2536db2661ceSRobert Watson /* 253784bdb083SRobert Watson * Fill in the missing parts from the previous label. 253884bdb083SRobert Watson */ 253984bdb083SRobert Watson if ((new->ml_flags & MAC_LOMAC_FLAG_SINGLE) == 0) 25403f1a7a90SRobert Watson lomac_copy_single(subj, new); 254184bdb083SRobert Watson 254284bdb083SRobert Watson /* 2543db2661ceSRobert Watson * To change the auxiliary LOMAC label on a vnode, the new 2544db2661ceSRobert Watson * vnode label must be in the subject range. 2545db2661ceSRobert Watson */ 25463f1a7a90SRobert Watson if (!lomac_auxsingle_in_range(new, subj)) 2547db2661ceSRobert Watson return (EPERM); 2548db2661ceSRobert Watson 2549db2661ceSRobert Watson /* 2550db2661ceSRobert Watson * To change the auxiliary LOMAC label on the vnode to be 2551db2661ceSRobert Watson * EQUAL, the subject must have appropriate privilege. 2552db2661ceSRobert Watson */ 25533f1a7a90SRobert Watson if (lomac_contains_equal(new)) { 25543f1a7a90SRobert Watson error = lomac_subject_privileged(subj); 2555db2661ceSRobert Watson if (error) 2556db2661ceSRobert Watson return (error); 2557db2661ceSRobert Watson } 2558db2661ceSRobert Watson } 2559db2661ceSRobert Watson 2560db2661ceSRobert Watson return (0); 2561db2661ceSRobert Watson } 2562db2661ceSRobert Watson 2563db2661ceSRobert Watson static int 25643f1a7a90SRobert Watson lomac_vnode_check_rename_from(struct ucred *cred, struct vnode *dvp, 256578007886SRobert Watson struct label *dvplabel, struct vnode *vp, struct label *vplabel, 2566db2661ceSRobert Watson struct componentname *cnp) 2567db2661ceSRobert Watson { 2568db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2569db2661ceSRobert Watson 25703f1a7a90SRobert Watson if (!lomac_enabled) 2571db2661ceSRobert Watson return (0); 2572db2661ceSRobert Watson 2573eca8a663SRobert Watson subj = SLOT(cred->cr_label); 257478007886SRobert Watson obj = SLOT(dvplabel); 2575db2661ceSRobert Watson 25763f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2577db2661ceSRobert Watson return (EACCES); 2578db2661ceSRobert Watson 257978007886SRobert Watson obj = SLOT(vplabel); 2580db2661ceSRobert Watson 25813f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2582db2661ceSRobert Watson return (EACCES); 2583db2661ceSRobert Watson 2584db2661ceSRobert Watson return (0); 2585db2661ceSRobert Watson } 2586db2661ceSRobert Watson 2587db2661ceSRobert Watson static int 25883f1a7a90SRobert Watson lomac_vnode_check_rename_to(struct ucred *cred, struct vnode *dvp, 258978007886SRobert Watson struct label *dvplabel, struct vnode *vp, struct label *vplabel, 259078007886SRobert Watson int samedir, struct componentname *cnp) 2591db2661ceSRobert Watson { 2592db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2593db2661ceSRobert Watson 25943f1a7a90SRobert Watson if (!lomac_enabled) 2595db2661ceSRobert Watson return (0); 2596db2661ceSRobert Watson 2597eca8a663SRobert Watson subj = SLOT(cred->cr_label); 259878007886SRobert Watson obj = SLOT(dvplabel); 2599db2661ceSRobert Watson 26003f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2601db2661ceSRobert Watson return (EACCES); 2602db2661ceSRobert Watson 2603db2661ceSRobert Watson if (vp != NULL) { 260478007886SRobert Watson obj = SLOT(vplabel); 2605db2661ceSRobert Watson 26063f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2607db2661ceSRobert Watson return (EACCES); 2608db2661ceSRobert Watson } 2609db2661ceSRobert Watson 2610db2661ceSRobert Watson return (0); 2611db2661ceSRobert Watson } 2612db2661ceSRobert Watson 2613db2661ceSRobert Watson static int 26143f1a7a90SRobert Watson lomac_vnode_check_revoke(struct ucred *cred, struct vnode *vp, 261578007886SRobert Watson struct label *vplabel) 2616db2661ceSRobert Watson { 2617db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2618db2661ceSRobert Watson 26193f1a7a90SRobert Watson if (!lomac_enabled) 2620db2661ceSRobert Watson return (0); 2621db2661ceSRobert Watson 2622eca8a663SRobert Watson subj = SLOT(cred->cr_label); 262378007886SRobert Watson obj = SLOT(vplabel); 2624db2661ceSRobert Watson 26253f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2626db2661ceSRobert Watson return (EACCES); 2627db2661ceSRobert Watson 2628db2661ceSRobert Watson return (0); 2629db2661ceSRobert Watson } 2630db2661ceSRobert Watson 2631db2661ceSRobert Watson static int 26323f1a7a90SRobert Watson lomac_vnode_check_setacl(struct ucred *cred, struct vnode *vp, 263378007886SRobert Watson struct label *vplabel, acl_type_t type, struct acl *acl) 2634db2661ceSRobert Watson { 2635db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2636db2661ceSRobert Watson 26373f1a7a90SRobert Watson if (!lomac_enabled) 2638db2661ceSRobert Watson return (0); 2639db2661ceSRobert Watson 2640eca8a663SRobert Watson subj = SLOT(cred->cr_label); 264178007886SRobert Watson obj = SLOT(vplabel); 2642db2661ceSRobert Watson 26433f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2644db2661ceSRobert Watson return (EACCES); 2645db2661ceSRobert Watson 2646db2661ceSRobert Watson return (0); 2647db2661ceSRobert Watson } 2648db2661ceSRobert Watson 2649db2661ceSRobert Watson static int 26503f1a7a90SRobert Watson lomac_vnode_check_setextattr(struct ucred *cred, struct vnode *vp, 2651fefd0ac8SRobert Watson struct label *vplabel, int attrnamespace, const char *name) 2652db2661ceSRobert Watson { 2653db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2654db2661ceSRobert Watson 26553f1a7a90SRobert Watson if (!lomac_enabled) 2656db2661ceSRobert Watson return (0); 2657db2661ceSRobert Watson 2658eca8a663SRobert Watson subj = SLOT(cred->cr_label); 265978007886SRobert Watson obj = SLOT(vplabel); 2660db2661ceSRobert Watson 26613f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2662db2661ceSRobert Watson return (EACCES); 2663db2661ceSRobert Watson 2664db2661ceSRobert Watson /* XXX: protect the MAC EA in a special way? */ 2665db2661ceSRobert Watson 2666db2661ceSRobert Watson return (0); 2667db2661ceSRobert Watson } 2668db2661ceSRobert Watson 2669db2661ceSRobert Watson static int 26703f1a7a90SRobert Watson lomac_vnode_check_setflags(struct ucred *cred, struct vnode *vp, 267178007886SRobert Watson struct label *vplabel, u_long flags) 2672db2661ceSRobert Watson { 2673db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2674db2661ceSRobert Watson 26753f1a7a90SRobert Watson if (!lomac_enabled) 2676db2661ceSRobert Watson return (0); 2677db2661ceSRobert Watson 2678eca8a663SRobert Watson subj = SLOT(cred->cr_label); 267978007886SRobert Watson obj = SLOT(vplabel); 2680db2661ceSRobert Watson 26813f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2682db2661ceSRobert Watson return (EACCES); 2683db2661ceSRobert Watson 2684db2661ceSRobert Watson return (0); 2685db2661ceSRobert Watson } 2686db2661ceSRobert Watson 2687db2661ceSRobert Watson static int 26883f1a7a90SRobert Watson lomac_vnode_check_setmode(struct ucred *cred, struct vnode *vp, 268978007886SRobert Watson struct label *vplabel, mode_t mode) 2690db2661ceSRobert Watson { 2691db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2692db2661ceSRobert Watson 26933f1a7a90SRobert Watson if (!lomac_enabled) 2694db2661ceSRobert Watson return (0); 2695db2661ceSRobert Watson 2696eca8a663SRobert Watson subj = SLOT(cred->cr_label); 269778007886SRobert Watson obj = SLOT(vplabel); 2698db2661ceSRobert Watson 26993f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2700db2661ceSRobert Watson return (EACCES); 2701db2661ceSRobert Watson 2702db2661ceSRobert Watson return (0); 2703db2661ceSRobert Watson } 2704db2661ceSRobert Watson 2705db2661ceSRobert Watson static int 27063f1a7a90SRobert Watson lomac_vnode_check_setowner(struct ucred *cred, struct vnode *vp, 270778007886SRobert Watson struct label *vplabel, uid_t uid, gid_t gid) 2708db2661ceSRobert Watson { 2709db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2710db2661ceSRobert Watson 27113f1a7a90SRobert Watson if (!lomac_enabled) 2712db2661ceSRobert Watson return (0); 2713db2661ceSRobert Watson 2714eca8a663SRobert Watson subj = SLOT(cred->cr_label); 271578007886SRobert Watson obj = SLOT(vplabel); 2716db2661ceSRobert Watson 27173f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2718db2661ceSRobert Watson return (EACCES); 2719db2661ceSRobert Watson 2720db2661ceSRobert Watson return (0); 2721db2661ceSRobert Watson } 2722db2661ceSRobert Watson 2723db2661ceSRobert Watson static int 27243f1a7a90SRobert Watson lomac_vnode_check_setutimes(struct ucred *cred, struct vnode *vp, 272578007886SRobert Watson struct label *vplabel, struct timespec atime, struct timespec mtime) 2726db2661ceSRobert Watson { 2727db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2728db2661ceSRobert Watson 27293f1a7a90SRobert Watson if (!lomac_enabled) 2730db2661ceSRobert Watson return (0); 2731db2661ceSRobert Watson 2732eca8a663SRobert Watson subj = SLOT(cred->cr_label); 273378007886SRobert Watson obj = SLOT(vplabel); 2734db2661ceSRobert Watson 27353f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2736db2661ceSRobert Watson return (EACCES); 2737db2661ceSRobert Watson 2738db2661ceSRobert Watson return (0); 2739db2661ceSRobert Watson } 2740db2661ceSRobert Watson 2741db2661ceSRobert Watson static int 27423f1a7a90SRobert Watson lomac_vnode_check_unlink(struct ucred *cred, struct vnode *dvp, 274345e0f3d6SRobert Watson struct label *dvplabel, struct vnode *vp, struct label *vplabel, 274445e0f3d6SRobert Watson struct componentname *cnp) 274545e0f3d6SRobert Watson { 274645e0f3d6SRobert Watson struct mac_lomac *subj, *obj; 274745e0f3d6SRobert Watson 27483f1a7a90SRobert Watson if (!lomac_enabled) 274945e0f3d6SRobert Watson return (0); 275045e0f3d6SRobert Watson 275145e0f3d6SRobert Watson subj = SLOT(cred->cr_label); 275245e0f3d6SRobert Watson obj = SLOT(dvplabel); 275345e0f3d6SRobert Watson 27543f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 275545e0f3d6SRobert Watson return (EACCES); 275645e0f3d6SRobert Watson 275745e0f3d6SRobert Watson obj = SLOT(vplabel); 275845e0f3d6SRobert Watson 27593f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 276045e0f3d6SRobert Watson return (EACCES); 276145e0f3d6SRobert Watson 276245e0f3d6SRobert Watson return (0); 276345e0f3d6SRobert Watson } 276445e0f3d6SRobert Watson 276545e0f3d6SRobert Watson static int 27663f1a7a90SRobert Watson lomac_vnode_check_write(struct ucred *active_cred, 276778007886SRobert Watson struct ucred *file_cred, struct vnode *vp, struct label *vplabel) 2768db2661ceSRobert Watson { 2769db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2770db2661ceSRobert Watson 27713f1a7a90SRobert Watson if (!lomac_enabled || !revocation_enabled) 2772db2661ceSRobert Watson return (0); 2773db2661ceSRobert Watson 2774eca8a663SRobert Watson subj = SLOT(active_cred->cr_label); 277578007886SRobert Watson obj = SLOT(vplabel); 2776db2661ceSRobert Watson 27773f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2778db2661ceSRobert Watson return (EACCES); 2779db2661ceSRobert Watson 2780db2661ceSRobert Watson return (0); 2781db2661ceSRobert Watson } 2782db2661ceSRobert Watson 2783eb320b0eSRobert Watson static int 2784eb320b0eSRobert Watson lomac_vnode_create_extattr(struct ucred *cred, struct mount *mp, 2785eb320b0eSRobert Watson struct label *mplabel, struct vnode *dvp, struct label *dvplabel, 2786eb320b0eSRobert Watson struct vnode *vp, struct label *vplabel, struct componentname *cnp) 2787db2661ceSRobert Watson { 2788eb320b0eSRobert Watson struct mac_lomac *source, *dest, *dir, temp; 2789eb320b0eSRobert Watson size_t buflen; 2790eb320b0eSRobert Watson int error; 2791db2661ceSRobert Watson 2792eb320b0eSRobert Watson buflen = sizeof(temp); 2793eb320b0eSRobert Watson bzero(&temp, buflen); 2794eb320b0eSRobert Watson 2795eb320b0eSRobert Watson source = SLOT(cred->cr_label); 2796eb320b0eSRobert Watson dest = SLOT(vplabel); 2797eb320b0eSRobert Watson dir = SLOT(dvplabel); 2798eb320b0eSRobert Watson if (dir->ml_flags & MAC_LOMAC_FLAG_AUX) { 2799eb320b0eSRobert Watson lomac_copy_auxsingle(dir, &temp); 2800eb320b0eSRobert Watson lomac_set_single(&temp, dir->ml_auxsingle.mle_type, 2801eb320b0eSRobert Watson dir->ml_auxsingle.mle_grade); 2802db2661ceSRobert Watson } else { 2803eb320b0eSRobert Watson lomac_copy_single(source, &temp); 2804db2661ceSRobert Watson } 2805eb320b0eSRobert Watson 2806eb320b0eSRobert Watson error = vn_extattr_set(vp, IO_NODELOCKED, MAC_LOMAC_EXTATTR_NAMESPACE, 2807eb320b0eSRobert Watson MAC_LOMAC_EXTATTR_NAME, buflen, (char *)&temp, curthread); 2808eb320b0eSRobert Watson if (error == 0) 2809eb320b0eSRobert Watson lomac_copy(&temp, dest); 2810eb320b0eSRobert Watson return (error); 2811eb320b0eSRobert Watson } 2812eb320b0eSRobert Watson 2813eb320b0eSRobert Watson static void 2814eb320b0eSRobert Watson lomac_vnode_execve_transition(struct ucred *old, struct ucred *new, 2815eb320b0eSRobert Watson struct vnode *vp, struct label *vplabel, struct label *interpvplabel, 2816eb320b0eSRobert Watson struct image_params *imgp, struct label *execlabel) 2817eb320b0eSRobert Watson { 2818eb320b0eSRobert Watson struct mac_lomac *source, *dest, *obj, *robj; 2819eb320b0eSRobert Watson 2820eb320b0eSRobert Watson source = SLOT(old->cr_label); 2821eb320b0eSRobert Watson dest = SLOT(new->cr_label); 2822eb320b0eSRobert Watson obj = SLOT(vplabel); 2823eb320b0eSRobert Watson robj = interpvplabel != NULL ? SLOT(interpvplabel) : obj; 2824eb320b0eSRobert Watson 2825eb320b0eSRobert Watson lomac_copy(source, dest); 2826eb320b0eSRobert Watson /* 2827eb320b0eSRobert Watson * If there's an auxiliary label on the real object, respect it and 2828eb320b0eSRobert Watson * assume that this level should be assumed immediately if a higher 2829eb320b0eSRobert Watson * level is currently in place. 2830eb320b0eSRobert Watson */ 2831eb320b0eSRobert Watson if (robj->ml_flags & MAC_LOMAC_FLAG_AUX && 2832eb320b0eSRobert Watson !lomac_dominate_element(&robj->ml_auxsingle, &dest->ml_single) 2833eb320b0eSRobert Watson && lomac_auxsingle_in_range(robj, dest)) 2834eb320b0eSRobert Watson lomac_set_single(dest, robj->ml_auxsingle.mle_type, 2835eb320b0eSRobert Watson robj->ml_auxsingle.mle_grade); 2836eb320b0eSRobert Watson /* 2837eb320b0eSRobert Watson * Restructuring to use the execve transitioning mechanism instead of 2838eb320b0eSRobert Watson * the normal demotion mechanism here would be difficult, so just 2839eb320b0eSRobert Watson * copy the label over and perform standard demotion. This is also 2840eb320b0eSRobert Watson * non-optimal because it will result in the intermediate label "new" 2841eb320b0eSRobert Watson * being created and immediately recycled. 2842eb320b0eSRobert Watson */ 2843eb320b0eSRobert Watson if (lomac_enabled && revocation_enabled && 2844eb320b0eSRobert Watson !lomac_dominate_single(obj, source)) 2845eb320b0eSRobert Watson (void)maybe_demote(source, obj, "executing", "file", vp); 2846eb320b0eSRobert Watson } 2847eb320b0eSRobert Watson 2848eb320b0eSRobert Watson static int 2849eb320b0eSRobert Watson lomac_vnode_execve_will_transition(struct ucred *old, struct vnode *vp, 2850eb320b0eSRobert Watson struct label *vplabel, struct label *interpvplabel, 2851eb320b0eSRobert Watson struct image_params *imgp, struct label *execlabel) 2852eb320b0eSRobert Watson { 2853eb320b0eSRobert Watson struct mac_lomac *subj, *obj, *robj; 2854eb320b0eSRobert Watson 2855eb320b0eSRobert Watson if (!lomac_enabled || !revocation_enabled) 2856eb320b0eSRobert Watson return (0); 2857eb320b0eSRobert Watson 2858eb320b0eSRobert Watson subj = SLOT(old->cr_label); 2859eb320b0eSRobert Watson obj = SLOT(vplabel); 2860eb320b0eSRobert Watson robj = interpvplabel != NULL ? SLOT(interpvplabel) : obj; 2861eb320b0eSRobert Watson 2862eb320b0eSRobert Watson return ((robj->ml_flags & MAC_LOMAC_FLAG_AUX && 2863eb320b0eSRobert Watson !lomac_dominate_element(&robj->ml_auxsingle, &subj->ml_single) 2864eb320b0eSRobert Watson && lomac_auxsingle_in_range(robj, subj)) || 2865eb320b0eSRobert Watson !lomac_dominate_single(obj, subj)); 2866eb320b0eSRobert Watson } 2867eb320b0eSRobert Watson 2868eb320b0eSRobert Watson static void 2869eb320b0eSRobert Watson lomac_vnode_relabel(struct ucred *cred, struct vnode *vp, 2870eb320b0eSRobert Watson struct label *vplabel, struct label *newlabel) 2871eb320b0eSRobert Watson { 2872eb320b0eSRobert Watson struct mac_lomac *source, *dest; 2873eb320b0eSRobert Watson 2874eb320b0eSRobert Watson source = SLOT(newlabel); 2875eb320b0eSRobert Watson dest = SLOT(vplabel); 2876eb320b0eSRobert Watson 2877eb320b0eSRobert Watson try_relabel(source, dest); 2878eb320b0eSRobert Watson } 2879eb320b0eSRobert Watson 2880eb320b0eSRobert Watson static int 2881eb320b0eSRobert Watson lomac_vnode_setlabel_extattr(struct ucred *cred, struct vnode *vp, 2882eb320b0eSRobert Watson struct label *vplabel, struct label *intlabel) 2883eb320b0eSRobert Watson { 2884eb320b0eSRobert Watson struct mac_lomac *source, temp; 2885eb320b0eSRobert Watson size_t buflen; 2886eb320b0eSRobert Watson int error; 2887eb320b0eSRobert Watson 2888eb320b0eSRobert Watson buflen = sizeof(temp); 2889eb320b0eSRobert Watson bzero(&temp, buflen); 2890eb320b0eSRobert Watson 2891eb320b0eSRobert Watson source = SLOT(intlabel); 2892eb320b0eSRobert Watson if ((source->ml_flags & MAC_LOMAC_FLAG_SINGLE) == 0) 2893eb320b0eSRobert Watson return (0); 2894eb320b0eSRobert Watson 2895eb320b0eSRobert Watson lomac_copy_single(source, &temp); 2896eb320b0eSRobert Watson error = vn_extattr_set(vp, IO_NODELOCKED, MAC_LOMAC_EXTATTR_NAMESPACE, 2897eb320b0eSRobert Watson MAC_LOMAC_EXTATTR_NAME, buflen, (char *)&temp, curthread); 2898eb320b0eSRobert Watson return (error); 2899db2661ceSRobert Watson } 2900db2661ceSRobert Watson 29013f1a7a90SRobert Watson static struct mac_policy_ops lomac_ops = 2902db2661ceSRobert Watson { 29033f1a7a90SRobert Watson .mpo_init = lomac_init, 2904c6d31b83SKonstantin Belousov .mpo_destroy = lomac_fini, 2905eb320b0eSRobert Watson 2906eb320b0eSRobert Watson .mpo_bpfdesc_check_receive = lomac_bpfdesc_check_receive, 2907eb320b0eSRobert Watson .mpo_bpfdesc_create = lomac_bpfdesc_create, 2908eb320b0eSRobert Watson .mpo_bpfdesc_create_mbuf = lomac_bpfdesc_create_mbuf, 29093f1a7a90SRobert Watson .mpo_bpfdesc_destroy_label = lomac_destroy_label, 2910eb320b0eSRobert Watson .mpo_bpfdesc_init_label = lomac_init_label, 2911eb320b0eSRobert Watson 2912eb320b0eSRobert Watson .mpo_cred_check_relabel = lomac_cred_check_relabel, 2913eb320b0eSRobert Watson .mpo_cred_check_visible = lomac_cred_check_visible, 29143f1a7a90SRobert Watson .mpo_cred_copy_label = lomac_copy_label, 2915212ab0cfSRobert Watson .mpo_cred_create_swapper = lomac_cred_create_swapper, 2916212ab0cfSRobert Watson .mpo_cred_create_init = lomac_cred_create_init, 2917eb320b0eSRobert Watson .mpo_cred_destroy_label = lomac_destroy_label, 29183f1a7a90SRobert Watson .mpo_cred_externalize_label = lomac_externalize_label, 2919eb320b0eSRobert Watson .mpo_cred_init_label = lomac_init_label, 29203f1a7a90SRobert Watson .mpo_cred_internalize_label = lomac_internalize_label, 2921eb320b0eSRobert Watson .mpo_cred_relabel = lomac_cred_relabel, 2922eb320b0eSRobert Watson 29233f1a7a90SRobert Watson .mpo_devfs_create_device = lomac_devfs_create_device, 29243f1a7a90SRobert Watson .mpo_devfs_create_directory = lomac_devfs_create_directory, 29253f1a7a90SRobert Watson .mpo_devfs_create_symlink = lomac_devfs_create_symlink, 2926eb320b0eSRobert Watson .mpo_devfs_destroy_label = lomac_destroy_label, 2927eb320b0eSRobert Watson .mpo_devfs_init_label = lomac_init_label, 29283f1a7a90SRobert Watson .mpo_devfs_update = lomac_devfs_update, 29293f1a7a90SRobert Watson .mpo_devfs_vnode_associate = lomac_devfs_vnode_associate, 2930eb320b0eSRobert Watson 29313f1a7a90SRobert Watson .mpo_ifnet_check_relabel = lomac_ifnet_check_relabel, 29323f1a7a90SRobert Watson .mpo_ifnet_check_transmit = lomac_ifnet_check_transmit, 2933eb320b0eSRobert Watson .mpo_ifnet_copy_label = lomac_copy_label, 2934eb320b0eSRobert Watson .mpo_ifnet_create = lomac_ifnet_create, 2935eb320b0eSRobert Watson .mpo_ifnet_create_mbuf = lomac_ifnet_create_mbuf, 2936eb320b0eSRobert Watson .mpo_ifnet_destroy_label = lomac_destroy_label, 2937eb320b0eSRobert Watson .mpo_ifnet_externalize_label = lomac_externalize_label, 2938eb320b0eSRobert Watson .mpo_ifnet_init_label = lomac_init_label, 2939eb320b0eSRobert Watson .mpo_ifnet_internalize_label = lomac_internalize_label, 2940eb320b0eSRobert Watson .mpo_ifnet_relabel = lomac_ifnet_relabel, 2941eb320b0eSRobert Watson 2942eb320b0eSRobert Watson .mpo_syncache_create = lomac_syncache_create, 2943eb320b0eSRobert Watson .mpo_syncache_destroy_label = lomac_destroy_label, 2944eb320b0eSRobert Watson .mpo_syncache_init_label = lomac_init_label_waitcheck, 2945eb320b0eSRobert Watson 29463f1a7a90SRobert Watson .mpo_inpcb_check_deliver = lomac_inpcb_check_deliver, 29477fb179baSBjoern A. Zeeb .mpo_inpcb_check_visible = lomac_inpcb_check_visible, 2948eb320b0eSRobert Watson .mpo_inpcb_create = lomac_inpcb_create, 2949eb320b0eSRobert Watson .mpo_inpcb_create_mbuf = lomac_inpcb_create_mbuf, 2950eb320b0eSRobert Watson .mpo_inpcb_destroy_label = lomac_destroy_label, 2951eb320b0eSRobert Watson .mpo_inpcb_init_label = lomac_init_label_waitcheck, 2952eb320b0eSRobert Watson .mpo_inpcb_sosetlabel = lomac_inpcb_sosetlabel, 2953eb320b0eSRobert Watson 2954048e1287SRobert Watson .mpo_ip6q_create = lomac_ip6q_create, 2955048e1287SRobert Watson .mpo_ip6q_destroy_label = lomac_destroy_label, 2956048e1287SRobert Watson .mpo_ip6q_init_label = lomac_init_label_waitcheck, 2957048e1287SRobert Watson .mpo_ip6q_match = lomac_ip6q_match, 2958048e1287SRobert Watson .mpo_ip6q_reassemble = lomac_ip6q_reassemble, 2959048e1287SRobert Watson .mpo_ip6q_update = lomac_ip6q_update, 2960048e1287SRobert Watson 2961eb320b0eSRobert Watson .mpo_ipq_create = lomac_ipq_create, 2962eb320b0eSRobert Watson .mpo_ipq_destroy_label = lomac_destroy_label, 2963eb320b0eSRobert Watson .mpo_ipq_init_label = lomac_init_label_waitcheck, 2964eb320b0eSRobert Watson .mpo_ipq_match = lomac_ipq_match, 2965eb320b0eSRobert Watson .mpo_ipq_reassemble = lomac_ipq_reassemble, 2966eb320b0eSRobert Watson .mpo_ipq_update = lomac_ipq_update, 2967eb320b0eSRobert Watson 29683f1a7a90SRobert Watson .mpo_kld_check_load = lomac_kld_check_load, 2969eb320b0eSRobert Watson 2970eb320b0eSRobert Watson .mpo_mbuf_copy_label = lomac_copy_label, 2971eb320b0eSRobert Watson .mpo_mbuf_destroy_label = lomac_destroy_label, 2972eb320b0eSRobert Watson .mpo_mbuf_init_label = lomac_init_label_waitcheck, 2973eb320b0eSRobert Watson 2974eb320b0eSRobert Watson .mpo_mount_create = lomac_mount_create, 2975eb320b0eSRobert Watson .mpo_mount_destroy_label = lomac_destroy_label, 2976eb320b0eSRobert Watson .mpo_mount_init_label = lomac_init_label, 2977eb320b0eSRobert Watson 2978eb320b0eSRobert Watson .mpo_netinet_arp_send = lomac_netinet_arp_send, 2979eb320b0eSRobert Watson .mpo_netinet_firewall_reply = lomac_netinet_firewall_reply, 2980eb320b0eSRobert Watson .mpo_netinet_firewall_send = lomac_netinet_firewall_send, 2981eb320b0eSRobert Watson .mpo_netinet_fragment = lomac_netinet_fragment, 2982eb320b0eSRobert Watson .mpo_netinet_icmp_reply = lomac_netinet_icmp_reply, 2983eb320b0eSRobert Watson .mpo_netinet_igmp_send = lomac_netinet_igmp_send, 2984eb320b0eSRobert Watson 2985eb320b0eSRobert Watson .mpo_netinet6_nd6_send = lomac_netinet6_nd6_send, 2986eb320b0eSRobert Watson 29873f1a7a90SRobert Watson .mpo_pipe_check_ioctl = lomac_pipe_check_ioctl, 29883f1a7a90SRobert Watson .mpo_pipe_check_read = lomac_pipe_check_read, 29893f1a7a90SRobert Watson .mpo_pipe_check_relabel = lomac_pipe_check_relabel, 29903f1a7a90SRobert Watson .mpo_pipe_check_write = lomac_pipe_check_write, 2991eb320b0eSRobert Watson .mpo_pipe_copy_label = lomac_copy_label, 2992eb320b0eSRobert Watson .mpo_pipe_create = lomac_pipe_create, 2993eb320b0eSRobert Watson .mpo_pipe_destroy_label = lomac_destroy_label, 2994eb320b0eSRobert Watson .mpo_pipe_externalize_label = lomac_externalize_label, 2995eb320b0eSRobert Watson .mpo_pipe_init_label = lomac_init_label, 2996eb320b0eSRobert Watson .mpo_pipe_internalize_label = lomac_internalize_label, 2997eb320b0eSRobert Watson .mpo_pipe_relabel = lomac_pipe_relabel, 2998eb320b0eSRobert Watson 2999eb320b0eSRobert Watson .mpo_priv_check = lomac_priv_check, 3000eb320b0eSRobert Watson 30013f1a7a90SRobert Watson .mpo_proc_check_debug = lomac_proc_check_debug, 30023f1a7a90SRobert Watson .mpo_proc_check_sched = lomac_proc_check_sched, 30033f1a7a90SRobert Watson .mpo_proc_check_signal = lomac_proc_check_signal, 3004eb320b0eSRobert Watson .mpo_proc_destroy_label = lomac_proc_destroy_label, 3005eb320b0eSRobert Watson .mpo_proc_init_label = lomac_proc_init_label, 3006eb320b0eSRobert Watson 30073f1a7a90SRobert Watson .mpo_socket_check_deliver = lomac_socket_check_deliver, 30083f1a7a90SRobert Watson .mpo_socket_check_relabel = lomac_socket_check_relabel, 30093f1a7a90SRobert Watson .mpo_socket_check_visible = lomac_socket_check_visible, 3010eb320b0eSRobert Watson .mpo_socket_copy_label = lomac_copy_label, 3011eb320b0eSRobert Watson .mpo_socket_create = lomac_socket_create, 3012eb320b0eSRobert Watson .mpo_socket_create_mbuf = lomac_socket_create_mbuf, 3013eb320b0eSRobert Watson .mpo_socket_destroy_label = lomac_destroy_label, 3014eb320b0eSRobert Watson .mpo_socket_externalize_label = lomac_externalize_label, 3015eb320b0eSRobert Watson .mpo_socket_init_label = lomac_init_label_waitcheck, 3016eb320b0eSRobert Watson .mpo_socket_internalize_label = lomac_internalize_label, 3017eb320b0eSRobert Watson .mpo_socket_newconn = lomac_socket_newconn, 3018eb320b0eSRobert Watson .mpo_socket_relabel = lomac_socket_relabel, 3019eb320b0eSRobert Watson 3020eb320b0eSRobert Watson .mpo_socketpeer_destroy_label = lomac_destroy_label, 3021eb320b0eSRobert Watson .mpo_socketpeer_externalize_label = lomac_externalize_label, 3022eb320b0eSRobert Watson .mpo_socketpeer_init_label = lomac_init_label_waitcheck, 3023eb320b0eSRobert Watson .mpo_socketpeer_set_from_mbuf = lomac_socketpeer_set_from_mbuf, 3024eb320b0eSRobert Watson .mpo_socketpeer_set_from_socket = lomac_socketpeer_set_from_socket, 3025eb320b0eSRobert Watson 3026eb320b0eSRobert Watson .mpo_syncache_create_mbuf = lomac_syncache_create_mbuf, 3027eb320b0eSRobert Watson 30283f1a7a90SRobert Watson .mpo_system_check_acct = lomac_system_check_acct, 30293f1a7a90SRobert Watson .mpo_system_check_auditctl = lomac_system_check_auditctl, 30303f1a7a90SRobert Watson .mpo_system_check_swapoff = lomac_system_check_swapoff, 30313f1a7a90SRobert Watson .mpo_system_check_swapon = lomac_system_check_swapon, 30323f1a7a90SRobert Watson .mpo_system_check_sysctl = lomac_system_check_sysctl, 3033eb320b0eSRobert Watson 3034eb320b0eSRobert Watson .mpo_thread_userret = lomac_thread_userret, 3035eb320b0eSRobert Watson 3036eb320b0eSRobert Watson .mpo_vnode_associate_extattr = lomac_vnode_associate_extattr, 3037eb320b0eSRobert Watson .mpo_vnode_associate_singlelabel = lomac_vnode_associate_singlelabel, 30383f1a7a90SRobert Watson .mpo_vnode_check_access = lomac_vnode_check_open, 30393f1a7a90SRobert Watson .mpo_vnode_check_create = lomac_vnode_check_create, 30403f1a7a90SRobert Watson .mpo_vnode_check_deleteacl = lomac_vnode_check_deleteacl, 30413f1a7a90SRobert Watson .mpo_vnode_check_link = lomac_vnode_check_link, 30423f1a7a90SRobert Watson .mpo_vnode_check_mmap = lomac_vnode_check_mmap, 30433f1a7a90SRobert Watson .mpo_vnode_check_mmap_downgrade = lomac_vnode_check_mmap_downgrade, 30443f1a7a90SRobert Watson .mpo_vnode_check_open = lomac_vnode_check_open, 30453f1a7a90SRobert Watson .mpo_vnode_check_read = lomac_vnode_check_read, 30463f1a7a90SRobert Watson .mpo_vnode_check_relabel = lomac_vnode_check_relabel, 30473f1a7a90SRobert Watson .mpo_vnode_check_rename_from = lomac_vnode_check_rename_from, 30483f1a7a90SRobert Watson .mpo_vnode_check_rename_to = lomac_vnode_check_rename_to, 30493f1a7a90SRobert Watson .mpo_vnode_check_revoke = lomac_vnode_check_revoke, 30503f1a7a90SRobert Watson .mpo_vnode_check_setacl = lomac_vnode_check_setacl, 30513f1a7a90SRobert Watson .mpo_vnode_check_setextattr = lomac_vnode_check_setextattr, 30523f1a7a90SRobert Watson .mpo_vnode_check_setflags = lomac_vnode_check_setflags, 30533f1a7a90SRobert Watson .mpo_vnode_check_setmode = lomac_vnode_check_setmode, 30543f1a7a90SRobert Watson .mpo_vnode_check_setowner = lomac_vnode_check_setowner, 30553f1a7a90SRobert Watson .mpo_vnode_check_setutimes = lomac_vnode_check_setutimes, 30563f1a7a90SRobert Watson .mpo_vnode_check_unlink = lomac_vnode_check_unlink, 30573f1a7a90SRobert Watson .mpo_vnode_check_write = lomac_vnode_check_write, 3058eb320b0eSRobert Watson .mpo_vnode_copy_label = lomac_copy_label, 3059eb320b0eSRobert Watson .mpo_vnode_create_extattr = lomac_vnode_create_extattr, 3060eb320b0eSRobert Watson .mpo_vnode_destroy_label = lomac_destroy_label, 3061eb320b0eSRobert Watson .mpo_vnode_execve_transition = lomac_vnode_execve_transition, 3062eb320b0eSRobert Watson .mpo_vnode_execve_will_transition = lomac_vnode_execve_will_transition, 3063eb320b0eSRobert Watson .mpo_vnode_externalize_label = lomac_externalize_label, 3064eb320b0eSRobert Watson .mpo_vnode_init_label = lomac_init_label, 3065eb320b0eSRobert Watson .mpo_vnode_internalize_label = lomac_internalize_label, 3066eb320b0eSRobert Watson .mpo_vnode_relabel = lomac_vnode_relabel, 3067eb320b0eSRobert Watson .mpo_vnode_setlabel_extattr = lomac_vnode_setlabel_extattr, 3068db2661ceSRobert Watson }; 3069db2661ceSRobert Watson 30703f1a7a90SRobert Watson MAC_POLICY_SET(&lomac_ops, mac_lomac, "TrustedBSD MAC/LOMAC", 30719162f64bSRobert Watson MPC_LOADTIME_FLAG_NOTLATE, &lomac_slot); 3072