1db2661ceSRobert Watson /*- 218717f69SRobert Watson * Copyright (c) 1999-2002, 2007 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 96db2661ceSRobert Watson SYSCTL_NODE(_security_mac, OID_AUTO, lomac, CTLFLAG_RW, 0, 97db2661ceSRobert Watson "TrustedBSD mac_lomac policy controls"); 98db2661ceSRobert Watson 993f1a7a90SRobert Watson static int lomac_label_size = sizeof(struct mac_lomac); 100db2661ceSRobert Watson SYSCTL_INT(_security_mac_lomac, OID_AUTO, label_size, CTLFLAG_RD, 1013f1a7a90SRobert Watson &lomac_label_size, 0, "Size of struct mac_lomac"); 102db2661ceSRobert Watson 1033f1a7a90SRobert Watson static int lomac_enabled = 1; 104db2661ceSRobert Watson SYSCTL_INT(_security_mac_lomac, OID_AUTO, enabled, CTLFLAG_RW, 1053f1a7a90SRobert Watson &lomac_enabled, 0, "Enforce MAC/LOMAC policy"); 1063f1a7a90SRobert Watson TUNABLE_INT("security.mac.lomac.enabled", &lomac_enabled); 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; 113db2661ceSRobert Watson SYSCTL_INT(_security_mac_lomac, OID_AUTO, trust_all_interfaces, CTLFLAG_RD, 114db2661ceSRobert Watson &trust_all_interfaces, 0, "Consider all interfaces 'trusted' by MAC/LOMAC"); 115db2661ceSRobert Watson TUNABLE_INT("security.mac.lomac.trust_all_interfaces", &trust_all_interfaces); 116db2661ceSRobert Watson 117db2661ceSRobert Watson static char trusted_interfaces[128]; 118db2661ceSRobert Watson SYSCTL_STRING(_security_mac_lomac, OID_AUTO, trusted_interfaces, CTLFLAG_RD, 119db2661ceSRobert Watson trusted_interfaces, 0, "Interfaces considered 'trusted' by MAC/LOMAC"); 120db2661ceSRobert Watson TUNABLE_STR("security.mac.lomac.trusted_interfaces", trusted_interfaces, 121db2661ceSRobert Watson sizeof(trusted_interfaces)); 122db2661ceSRobert Watson 123db2661ceSRobert Watson static int ptys_equal = 0; 124db2661ceSRobert Watson SYSCTL_INT(_security_mac_lomac, OID_AUTO, ptys_equal, CTLFLAG_RW, 125db2661ceSRobert Watson &ptys_equal, 0, "Label pty devices as lomac/equal on create"); 126db2661ceSRobert Watson TUNABLE_INT("security.mac.lomac.ptys_equal", &ptys_equal); 127db2661ceSRobert Watson 128db2661ceSRobert Watson static int revocation_enabled = 1; 129db2661ceSRobert Watson SYSCTL_INT(_security_mac_lomac, OID_AUTO, revocation_enabled, CTLFLAG_RW, 130db2661ceSRobert Watson &revocation_enabled, 0, "Revoke access to objects on relabel"); 131db2661ceSRobert Watson TUNABLE_INT("security.mac.lomac.revocation_enabled", &revocation_enabled); 132db2661ceSRobert Watson 1333f1a7a90SRobert Watson static int lomac_slot; 1343f1a7a90SRobert Watson #define SLOT(l) ((struct mac_lomac *)mac_label_get((l), lomac_slot)) 1353f1a7a90SRobert Watson #define SLOT_SET(l, val) mac_label_set((l), lomac_slot, (uintptr_t)(val)) 136db2661ceSRobert Watson #define PSLOT(l) ((struct mac_lomac_proc *) \ 1373f1a7a90SRobert Watson mac_label_get((l), lomac_slot)) 1383f1a7a90SRobert Watson #define PSLOT_SET(l, val) mac_label_set((l), lomac_slot, (uintptr_t)(val)) 139db2661ceSRobert Watson 1403f1a7a90SRobert Watson MALLOC_DEFINE(M_LOMAC, "mac_lomac_label", "MAC/LOMAC labels"); 141db2661ceSRobert Watson 142db2661ceSRobert Watson static struct mac_lomac * 143db2661ceSRobert Watson lomac_alloc(int flag) 144db2661ceSRobert Watson { 1453f1a7a90SRobert Watson struct mac_lomac *ml; 146db2661ceSRobert Watson 1473f1a7a90SRobert Watson ml = malloc(sizeof(*ml), M_LOMAC, M_ZERO | flag); 148db2661ceSRobert Watson 1493f1a7a90SRobert Watson return (ml); 150db2661ceSRobert Watson } 151db2661ceSRobert Watson 152db2661ceSRobert Watson static void 1533f1a7a90SRobert Watson lomac_free(struct mac_lomac *ml) 154db2661ceSRobert Watson { 155db2661ceSRobert Watson 1563f1a7a90SRobert Watson if (ml != NULL) 1573f1a7a90SRobert Watson free(ml, M_LOMAC); 158db2661ceSRobert Watson else 159db2661ceSRobert Watson atomic_add_int(&destroyed_not_inited, 1); 160db2661ceSRobert Watson } 161db2661ceSRobert Watson 162db2661ceSRobert Watson static int 1633f1a7a90SRobert Watson lomac_atmostflags(struct mac_lomac *ml, int flags) 164db2661ceSRobert Watson { 165db2661ceSRobert Watson 1663f1a7a90SRobert Watson if ((ml->ml_flags & flags) != ml->ml_flags) 167db2661ceSRobert Watson return (EINVAL); 168db2661ceSRobert Watson return (0); 169db2661ceSRobert Watson } 170db2661ceSRobert Watson 171db2661ceSRobert Watson static int 1723f1a7a90SRobert Watson lomac_dominate_element(struct mac_lomac_element *a, 173db2661ceSRobert Watson struct mac_lomac_element *b) 174db2661ceSRobert Watson { 175db2661ceSRobert Watson 176db2661ceSRobert Watson switch (a->mle_type) { 177db2661ceSRobert Watson case MAC_LOMAC_TYPE_EQUAL: 178db2661ceSRobert Watson case MAC_LOMAC_TYPE_HIGH: 179db2661ceSRobert Watson return (1); 180db2661ceSRobert Watson 181db2661ceSRobert Watson case MAC_LOMAC_TYPE_LOW: 182db2661ceSRobert Watson switch (b->mle_type) { 183db2661ceSRobert Watson case MAC_LOMAC_TYPE_GRADE: 184db2661ceSRobert Watson case MAC_LOMAC_TYPE_HIGH: 185db2661ceSRobert Watson return (0); 186db2661ceSRobert Watson 187db2661ceSRobert Watson case MAC_LOMAC_TYPE_EQUAL: 188db2661ceSRobert Watson case MAC_LOMAC_TYPE_LOW: 189db2661ceSRobert Watson return (1); 190db2661ceSRobert Watson 191db2661ceSRobert Watson default: 1923f1a7a90SRobert Watson panic("lomac_dominate_element: b->mle_type invalid"); 193db2661ceSRobert Watson } 194db2661ceSRobert Watson 195db2661ceSRobert Watson case MAC_LOMAC_TYPE_GRADE: 196db2661ceSRobert Watson switch (b->mle_type) { 197db2661ceSRobert Watson case MAC_LOMAC_TYPE_EQUAL: 198db2661ceSRobert Watson case MAC_LOMAC_TYPE_LOW: 199db2661ceSRobert Watson return (1); 200db2661ceSRobert Watson 201db2661ceSRobert Watson case MAC_LOMAC_TYPE_HIGH: 202db2661ceSRobert Watson return (0); 203db2661ceSRobert Watson 204db2661ceSRobert Watson case MAC_LOMAC_TYPE_GRADE: 205db2661ceSRobert Watson return (a->mle_grade >= b->mle_grade); 206db2661ceSRobert Watson 207db2661ceSRobert Watson default: 2083f1a7a90SRobert Watson panic("lomac_dominate_element: b->mle_type invalid"); 209db2661ceSRobert Watson } 210db2661ceSRobert Watson 211db2661ceSRobert Watson default: 2123f1a7a90SRobert Watson panic("lomac_dominate_element: a->mle_type invalid"); 213db2661ceSRobert Watson } 214db2661ceSRobert Watson } 215db2661ceSRobert Watson 216db2661ceSRobert Watson static int 2173f1a7a90SRobert Watson lomac_range_in_range(struct mac_lomac *rangea, struct mac_lomac *rangeb) 218db2661ceSRobert Watson { 219db2661ceSRobert Watson 2203f1a7a90SRobert Watson return (lomac_dominate_element(&rangeb->ml_rangehigh, 221db2661ceSRobert Watson &rangea->ml_rangehigh) && 2223f1a7a90SRobert Watson lomac_dominate_element(&rangea->ml_rangelow, 223db2661ceSRobert Watson &rangeb->ml_rangelow)); 224db2661ceSRobert Watson } 225db2661ceSRobert Watson 226db2661ceSRobert Watson static int 2273f1a7a90SRobert Watson lomac_single_in_range(struct mac_lomac *single, struct mac_lomac *range) 228db2661ceSRobert Watson { 229db2661ceSRobert Watson 230db2661ceSRobert Watson KASSERT((single->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0, 2313f1a7a90SRobert Watson ("lomac_single_in_range: a not single")); 232db2661ceSRobert Watson KASSERT((range->ml_flags & MAC_LOMAC_FLAG_RANGE) != 0, 2333f1a7a90SRobert Watson ("lomac_single_in_range: b not range")); 234db2661ceSRobert Watson 2353f1a7a90SRobert Watson return (lomac_dominate_element(&range->ml_rangehigh, 2363f1a7a90SRobert Watson &single->ml_single) && lomac_dominate_element(&single->ml_single, 237db2661ceSRobert Watson &range->ml_rangelow)); 238db2661ceSRobert Watson } 239db2661ceSRobert Watson 240db2661ceSRobert Watson static int 2413f1a7a90SRobert Watson lomac_auxsingle_in_range(struct mac_lomac *single, struct mac_lomac *range) 242db2661ceSRobert Watson { 243db2661ceSRobert Watson 244db2661ceSRobert Watson KASSERT((single->ml_flags & MAC_LOMAC_FLAG_AUX) != 0, 2453f1a7a90SRobert Watson ("lomac_single_in_range: a not auxsingle")); 246db2661ceSRobert Watson KASSERT((range->ml_flags & MAC_LOMAC_FLAG_RANGE) != 0, 2473f1a7a90SRobert Watson ("lomac_single_in_range: b not range")); 248db2661ceSRobert Watson 2493f1a7a90SRobert Watson return (lomac_dominate_element(&range->ml_rangehigh, 250db2661ceSRobert Watson &single->ml_auxsingle) && 2513f1a7a90SRobert Watson lomac_dominate_element(&single->ml_auxsingle, 252db2661ceSRobert Watson &range->ml_rangelow)); 253db2661ceSRobert Watson } 254db2661ceSRobert Watson 255db2661ceSRobert Watson static int 2563f1a7a90SRobert Watson lomac_dominate_single(struct mac_lomac *a, struct mac_lomac *b) 257db2661ceSRobert Watson { 258db2661ceSRobert Watson KASSERT((a->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0, 2593f1a7a90SRobert Watson ("lomac_dominate_single: a not single")); 260db2661ceSRobert Watson KASSERT((b->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0, 2613f1a7a90SRobert Watson ("lomac_dominate_single: b not single")); 262db2661ceSRobert Watson 2633f1a7a90SRobert Watson return (lomac_dominate_element(&a->ml_single, &b->ml_single)); 264db2661ceSRobert Watson } 265db2661ceSRobert Watson 266db2661ceSRobert Watson static int 2673f1a7a90SRobert Watson lomac_subject_dominate(struct mac_lomac *a, struct mac_lomac *b) 268db2661ceSRobert Watson { 269db2661ceSRobert Watson KASSERT((~a->ml_flags & 270db2661ceSRobert Watson (MAC_LOMAC_FLAG_SINGLE | MAC_LOMAC_FLAG_RANGE)) == 0, 2713f1a7a90SRobert Watson ("lomac_dominate_single: a not subject")); 272db2661ceSRobert Watson KASSERT((b->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0, 2733f1a7a90SRobert Watson ("lomac_dominate_single: b not single")); 274db2661ceSRobert Watson 2753f1a7a90SRobert Watson return (lomac_dominate_element(&a->ml_rangehigh, &b->ml_single)); 276db2661ceSRobert Watson } 277db2661ceSRobert Watson 278db2661ceSRobert Watson static int 2793f1a7a90SRobert Watson lomac_equal_element(struct mac_lomac_element *a, struct mac_lomac_element *b) 280db2661ceSRobert Watson { 281db2661ceSRobert Watson 282db2661ceSRobert Watson if (a->mle_type == MAC_LOMAC_TYPE_EQUAL || 283db2661ceSRobert Watson b->mle_type == MAC_LOMAC_TYPE_EQUAL) 284db2661ceSRobert Watson return (1); 285db2661ceSRobert Watson 286db2661ceSRobert Watson return (a->mle_type == b->mle_type && a->mle_grade == b->mle_grade); 287db2661ceSRobert Watson } 288db2661ceSRobert Watson 289db2661ceSRobert Watson static int 2903f1a7a90SRobert Watson lomac_equal_single(struct mac_lomac *a, struct mac_lomac *b) 291db2661ceSRobert Watson { 292db2661ceSRobert Watson 293db2661ceSRobert Watson KASSERT((a->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0, 2943f1a7a90SRobert Watson ("lomac_equal_single: a not single")); 295db2661ceSRobert Watson KASSERT((b->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0, 2963f1a7a90SRobert Watson ("lomac_equal_single: b not single")); 297db2661ceSRobert Watson 2983f1a7a90SRobert Watson return (lomac_equal_element(&a->ml_single, &b->ml_single)); 299db2661ceSRobert Watson } 300db2661ceSRobert Watson 301db2661ceSRobert Watson static int 3023f1a7a90SRobert Watson lomac_contains_equal(struct mac_lomac *ml) 303db2661ceSRobert Watson { 304db2661ceSRobert Watson 3053f1a7a90SRobert Watson if (ml->ml_flags & MAC_LOMAC_FLAG_SINGLE) 3063f1a7a90SRobert Watson if (ml->ml_single.mle_type == MAC_LOMAC_TYPE_EQUAL) 307db2661ceSRobert Watson return (1); 3083f1a7a90SRobert Watson if (ml->ml_flags & MAC_LOMAC_FLAG_AUX) 3093f1a7a90SRobert Watson if (ml->ml_auxsingle.mle_type == MAC_LOMAC_TYPE_EQUAL) 310db2661ceSRobert Watson return (1); 311db2661ceSRobert Watson 3123f1a7a90SRobert Watson if (ml->ml_flags & MAC_LOMAC_FLAG_RANGE) { 3133f1a7a90SRobert Watson if (ml->ml_rangelow.mle_type == MAC_LOMAC_TYPE_EQUAL) 314db2661ceSRobert Watson return (1); 3153f1a7a90SRobert Watson if (ml->ml_rangehigh.mle_type == MAC_LOMAC_TYPE_EQUAL) 316db2661ceSRobert Watson return (1); 317db2661ceSRobert Watson } 318db2661ceSRobert Watson 319db2661ceSRobert Watson return (0); 320db2661ceSRobert Watson } 321db2661ceSRobert Watson 322db2661ceSRobert Watson static int 3233f1a7a90SRobert Watson lomac_subject_privileged(struct mac_lomac *ml) 324db2661ceSRobert Watson { 325db2661ceSRobert Watson 3263f1a7a90SRobert Watson KASSERT((ml->ml_flags & MAC_LOMAC_FLAGS_BOTH) == 327db2661ceSRobert Watson MAC_LOMAC_FLAGS_BOTH, 3283f1a7a90SRobert Watson ("lomac_subject_privileged: subject doesn't have both labels")); 329db2661ceSRobert Watson 330db2661ceSRobert Watson /* If the single is EQUAL, it's ok. */ 3313f1a7a90SRobert Watson if (ml->ml_single.mle_type == MAC_LOMAC_TYPE_EQUAL) 332db2661ceSRobert Watson return (0); 333db2661ceSRobert Watson 334db2661ceSRobert Watson /* If either range endpoint is EQUAL, it's ok. */ 3353f1a7a90SRobert Watson if (ml->ml_rangelow.mle_type == MAC_LOMAC_TYPE_EQUAL || 3363f1a7a90SRobert Watson ml->ml_rangehigh.mle_type == MAC_LOMAC_TYPE_EQUAL) 337db2661ceSRobert Watson return (0); 338db2661ceSRobert Watson 339db2661ceSRobert Watson /* If the range is low-high, it's ok. */ 3403f1a7a90SRobert Watson if (ml->ml_rangelow.mle_type == MAC_LOMAC_TYPE_LOW && 3413f1a7a90SRobert Watson ml->ml_rangehigh.mle_type == MAC_LOMAC_TYPE_HIGH) 342db2661ceSRobert Watson return (0); 343db2661ceSRobert Watson 344db2661ceSRobert Watson /* It's not ok. */ 345db2661ceSRobert Watson return (EPERM); 346db2661ceSRobert Watson } 347db2661ceSRobert Watson 348db2661ceSRobert Watson static int 3493f1a7a90SRobert Watson lomac_high_single(struct mac_lomac *ml) 350db2661ceSRobert Watson { 351db2661ceSRobert Watson 3523f1a7a90SRobert Watson KASSERT((ml->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0, 3533f1a7a90SRobert Watson ("lomac_high_single: mac_lomac not single")); 354db2661ceSRobert Watson 3553f1a7a90SRobert Watson return (ml->ml_single.mle_type == MAC_LOMAC_TYPE_HIGH); 356db2661ceSRobert Watson } 357db2661ceSRobert Watson 358db2661ceSRobert Watson static int 3593f1a7a90SRobert Watson lomac_valid(struct mac_lomac *ml) 360db2661ceSRobert Watson { 361db2661ceSRobert Watson 3623f1a7a90SRobert Watson if (ml->ml_flags & MAC_LOMAC_FLAG_SINGLE) { 3633f1a7a90SRobert Watson switch (ml->ml_single.mle_type) { 364db2661ceSRobert Watson case MAC_LOMAC_TYPE_GRADE: 365db2661ceSRobert Watson case MAC_LOMAC_TYPE_EQUAL: 366db2661ceSRobert Watson case MAC_LOMAC_TYPE_HIGH: 367db2661ceSRobert Watson case MAC_LOMAC_TYPE_LOW: 368db2661ceSRobert Watson break; 369db2661ceSRobert Watson 370db2661ceSRobert Watson default: 371db2661ceSRobert Watson return (EINVAL); 372db2661ceSRobert Watson } 373db2661ceSRobert Watson } else { 3743f1a7a90SRobert Watson if (ml->ml_single.mle_type != MAC_LOMAC_TYPE_UNDEF) 375db2661ceSRobert Watson return (EINVAL); 376db2661ceSRobert Watson } 377db2661ceSRobert Watson 3783f1a7a90SRobert Watson if (ml->ml_flags & MAC_LOMAC_FLAG_AUX) { 3793f1a7a90SRobert Watson switch (ml->ml_auxsingle.mle_type) { 380db2661ceSRobert Watson case MAC_LOMAC_TYPE_GRADE: 381db2661ceSRobert Watson case MAC_LOMAC_TYPE_EQUAL: 382db2661ceSRobert Watson case MAC_LOMAC_TYPE_HIGH: 383db2661ceSRobert Watson case MAC_LOMAC_TYPE_LOW: 384db2661ceSRobert Watson break; 385db2661ceSRobert Watson 386db2661ceSRobert Watson default: 387db2661ceSRobert Watson return (EINVAL); 388db2661ceSRobert Watson } 389db2661ceSRobert Watson } else { 3903f1a7a90SRobert Watson if (ml->ml_auxsingle.mle_type != MAC_LOMAC_TYPE_UNDEF) 391db2661ceSRobert Watson return (EINVAL); 392db2661ceSRobert Watson } 393db2661ceSRobert Watson 3943f1a7a90SRobert Watson if (ml->ml_flags & MAC_LOMAC_FLAG_RANGE) { 3953f1a7a90SRobert Watson switch (ml->ml_rangelow.mle_type) { 396db2661ceSRobert Watson case MAC_LOMAC_TYPE_GRADE: 397db2661ceSRobert Watson case MAC_LOMAC_TYPE_EQUAL: 398db2661ceSRobert Watson case MAC_LOMAC_TYPE_HIGH: 399db2661ceSRobert Watson case MAC_LOMAC_TYPE_LOW: 400db2661ceSRobert Watson break; 401db2661ceSRobert Watson 402db2661ceSRobert Watson default: 403db2661ceSRobert Watson return (EINVAL); 404db2661ceSRobert Watson } 405db2661ceSRobert Watson 4063f1a7a90SRobert Watson switch (ml->ml_rangehigh.mle_type) { 407db2661ceSRobert Watson case MAC_LOMAC_TYPE_GRADE: 408db2661ceSRobert Watson case MAC_LOMAC_TYPE_EQUAL: 409db2661ceSRobert Watson case MAC_LOMAC_TYPE_HIGH: 410db2661ceSRobert Watson case MAC_LOMAC_TYPE_LOW: 411db2661ceSRobert Watson break; 412db2661ceSRobert Watson 413db2661ceSRobert Watson default: 414db2661ceSRobert Watson return (EINVAL); 415db2661ceSRobert Watson } 4163f1a7a90SRobert Watson if (!lomac_dominate_element(&ml->ml_rangehigh, 4173f1a7a90SRobert Watson &ml->ml_rangelow)) 418db2661ceSRobert Watson return (EINVAL); 419db2661ceSRobert Watson } else { 4203f1a7a90SRobert Watson if (ml->ml_rangelow.mle_type != MAC_LOMAC_TYPE_UNDEF || 4213f1a7a90SRobert Watson ml->ml_rangehigh.mle_type != MAC_LOMAC_TYPE_UNDEF) 422db2661ceSRobert Watson return (EINVAL); 423db2661ceSRobert Watson } 424db2661ceSRobert Watson 425db2661ceSRobert Watson return (0); 426db2661ceSRobert Watson } 427db2661ceSRobert Watson 428db2661ceSRobert Watson static void 4293f1a7a90SRobert Watson lomac_set_range(struct mac_lomac *ml, u_short typelow, u_short gradelow, 4303f1a7a90SRobert Watson u_short typehigh, u_short gradehigh) 431db2661ceSRobert Watson { 432db2661ceSRobert Watson 4333f1a7a90SRobert Watson ml->ml_rangelow.mle_type = typelow; 4343f1a7a90SRobert Watson ml->ml_rangelow.mle_grade = gradelow; 4353f1a7a90SRobert Watson ml->ml_rangehigh.mle_type = typehigh; 4363f1a7a90SRobert Watson ml->ml_rangehigh.mle_grade = gradehigh; 4373f1a7a90SRobert Watson ml->ml_flags |= MAC_LOMAC_FLAG_RANGE; 438db2661ceSRobert Watson } 439db2661ceSRobert Watson 440db2661ceSRobert Watson static void 4413f1a7a90SRobert Watson lomac_set_single(struct mac_lomac *ml, u_short type, u_short grade) 442db2661ceSRobert Watson { 443db2661ceSRobert Watson 4443f1a7a90SRobert Watson ml->ml_single.mle_type = type; 4453f1a7a90SRobert Watson ml->ml_single.mle_grade = grade; 4463f1a7a90SRobert Watson ml->ml_flags |= MAC_LOMAC_FLAG_SINGLE; 447db2661ceSRobert Watson } 448db2661ceSRobert Watson 449db2661ceSRobert Watson static void 4503f1a7a90SRobert Watson lomac_copy_range(struct mac_lomac *labelfrom, struct mac_lomac *labelto) 451db2661ceSRobert Watson { 452db2661ceSRobert Watson 453db2661ceSRobert Watson KASSERT((labelfrom->ml_flags & MAC_LOMAC_FLAG_RANGE) != 0, 4543f1a7a90SRobert Watson ("lomac_copy_range: labelfrom not range")); 455db2661ceSRobert Watson 456db2661ceSRobert Watson labelto->ml_rangelow = labelfrom->ml_rangelow; 457db2661ceSRobert Watson labelto->ml_rangehigh = labelfrom->ml_rangehigh; 458db2661ceSRobert Watson labelto->ml_flags |= MAC_LOMAC_FLAG_RANGE; 459db2661ceSRobert Watson } 460db2661ceSRobert Watson 461db2661ceSRobert Watson static void 4623f1a7a90SRobert Watson lomac_copy_single(struct mac_lomac *labelfrom, struct mac_lomac *labelto) 463db2661ceSRobert Watson { 464db2661ceSRobert Watson 465db2661ceSRobert Watson KASSERT((labelfrom->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0, 4663f1a7a90SRobert Watson ("lomac_copy_single: labelfrom not single")); 467db2661ceSRobert Watson 468db2661ceSRobert Watson labelto->ml_single = labelfrom->ml_single; 469db2661ceSRobert Watson labelto->ml_flags |= MAC_LOMAC_FLAG_SINGLE; 470db2661ceSRobert Watson } 471db2661ceSRobert Watson 472db2661ceSRobert Watson static void 4733f1a7a90SRobert Watson lomac_copy_auxsingle(struct mac_lomac *labelfrom, struct mac_lomac *labelto) 474db2661ceSRobert Watson { 475db2661ceSRobert Watson 476db2661ceSRobert Watson KASSERT((labelfrom->ml_flags & MAC_LOMAC_FLAG_AUX) != 0, 4773f1a7a90SRobert Watson ("lomac_copy_auxsingle: labelfrom not auxsingle")); 478db2661ceSRobert Watson 479db2661ceSRobert Watson labelto->ml_auxsingle = labelfrom->ml_auxsingle; 480db2661ceSRobert Watson labelto->ml_flags |= MAC_LOMAC_FLAG_AUX; 481db2661ceSRobert Watson } 482db2661ceSRobert Watson 483db2661ceSRobert Watson static void 4843f1a7a90SRobert Watson lomac_copy(struct mac_lomac *source, struct mac_lomac *dest) 485db2661ceSRobert Watson { 486db2661ceSRobert Watson 487db2661ceSRobert Watson if (source->ml_flags & MAC_LOMAC_FLAG_SINGLE) 4883f1a7a90SRobert Watson lomac_copy_single(source, dest); 489db2661ceSRobert Watson if (source->ml_flags & MAC_LOMAC_FLAG_AUX) 4903f1a7a90SRobert Watson lomac_copy_auxsingle(source, dest); 491db2661ceSRobert Watson if (source->ml_flags & MAC_LOMAC_FLAG_RANGE) 4923f1a7a90SRobert Watson lomac_copy_range(source, dest); 493db2661ceSRobert Watson } 494db2661ceSRobert Watson 4953f1a7a90SRobert Watson static int lomac_to_string(struct sbuf *sb, struct mac_lomac *ml); 496db2661ceSRobert Watson 497db2661ceSRobert Watson static int 498db2661ceSRobert Watson maybe_demote(struct mac_lomac *subjlabel, struct mac_lomac *objlabel, 49978007886SRobert Watson const char *actionname, const char *objname, struct vnode *vp) 500db2661ceSRobert Watson { 501f51e5803SRobert Watson struct sbuf subjlabel_sb, subjtext_sb, objlabel_sb; 502f51e5803SRobert Watson char *subjlabeltext, *objlabeltext, *subjtext; 503f51e5803SRobert Watson struct mac_lomac cached_subjlabel; 504f51e5803SRobert Watson struct mac_lomac_proc *subj; 505db2661ceSRobert Watson struct vattr va; 506db2661ceSRobert Watson struct proc *p; 507db2661ceSRobert Watson pid_t pgid; 508db2661ceSRobert Watson 509eca8a663SRobert Watson subj = PSLOT(curthread->td_proc->p_label); 510f51e5803SRobert Watson 511db2661ceSRobert Watson p = curthread->td_proc; 512db2661ceSRobert Watson mtx_lock(&subj->mtx); 513db2661ceSRobert Watson if (subj->mac_lomac.ml_flags & MAC_LOMAC_FLAG_UPDATE) { 514db2661ceSRobert Watson /* 5153f1a7a90SRobert Watson * Check to see if the pending demotion would be more or less 5163f1a7a90SRobert Watson * severe than this one, and keep the more severe. This can 5173f1a7a90SRobert Watson * only happen for a multi-threaded application. 518db2661ceSRobert Watson */ 5193f1a7a90SRobert Watson if (lomac_dominate_single(objlabel, &subj->mac_lomac)) { 520db2661ceSRobert Watson mtx_unlock(&subj->mtx); 521db2661ceSRobert Watson return (0); 522db2661ceSRobert Watson } 523db2661ceSRobert Watson } 524db2661ceSRobert Watson bzero(&subj->mac_lomac, sizeof(subj->mac_lomac)); 525db2661ceSRobert Watson /* 526db2661ceSRobert Watson * Always demote the single label. 527db2661ceSRobert Watson */ 5283f1a7a90SRobert Watson lomac_copy_single(objlabel, &subj->mac_lomac); 529db2661ceSRobert Watson /* 5303f1a7a90SRobert Watson * Start with the original range, then minimize each side of the 5313f1a7a90SRobert Watson * range to the point of not dominating the object. The high side 5323f1a7a90SRobert Watson * will always be demoted, of course. 533db2661ceSRobert Watson */ 5343f1a7a90SRobert Watson lomac_copy_range(subjlabel, &subj->mac_lomac); 5353f1a7a90SRobert Watson if (!lomac_dominate_element(&objlabel->ml_single, 536db2661ceSRobert Watson &subj->mac_lomac.ml_rangelow)) 537db2661ceSRobert Watson subj->mac_lomac.ml_rangelow = objlabel->ml_single; 538db2661ceSRobert Watson subj->mac_lomac.ml_rangehigh = objlabel->ml_single; 539db2661ceSRobert Watson subj->mac_lomac.ml_flags |= MAC_LOMAC_FLAG_UPDATE; 540982d11f8SJeff Roberson thread_lock(curthread); 541b61ce5b0SJeff Roberson curthread->td_flags |= TDF_ASTPENDING | TDF_MACPEND; 542982d11f8SJeff Roberson thread_unlock(curthread); 543f51e5803SRobert Watson 544f51e5803SRobert Watson /* 5453f1a7a90SRobert Watson * Avoid memory allocation while holding a mutex; cache the label. 546f51e5803SRobert Watson */ 5473f1a7a90SRobert Watson lomac_copy_single(&subj->mac_lomac, &cached_subjlabel); 548db2661ceSRobert Watson mtx_unlock(&subj->mtx); 549f51e5803SRobert Watson 550f51e5803SRobert Watson sbuf_new(&subjlabel_sb, NULL, 0, SBUF_AUTOEXTEND); 5513f1a7a90SRobert Watson lomac_to_string(&subjlabel_sb, subjlabel); 552f51e5803SRobert Watson sbuf_finish(&subjlabel_sb); 553f51e5803SRobert Watson subjlabeltext = sbuf_data(&subjlabel_sb); 554f51e5803SRobert Watson 555f51e5803SRobert Watson sbuf_new(&subjtext_sb, NULL, 0, SBUF_AUTOEXTEND); 5563f1a7a90SRobert Watson lomac_to_string(&subjtext_sb, &subj->mac_lomac); 557f51e5803SRobert Watson sbuf_finish(&subjtext_sb); 558f51e5803SRobert Watson subjtext = sbuf_data(&subjtext_sb); 559f51e5803SRobert Watson 560f51e5803SRobert Watson sbuf_new(&objlabel_sb, NULL, 0, SBUF_AUTOEXTEND); 5613f1a7a90SRobert Watson lomac_to_string(&objlabel_sb, objlabel); 562f51e5803SRobert Watson sbuf_finish(&objlabel_sb); 563f51e5803SRobert Watson objlabeltext = sbuf_data(&objlabel_sb); 564f51e5803SRobert Watson 565db2661ceSRobert Watson pgid = p->p_pgrp->pg_id; /* XXX could be stale? */ 5660359a12eSAttilio Rao if (vp != NULL && VOP_GETATTR(vp, &va, curthread->td_ucred) == 0) { 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 (inode=%ld, " 569db2661ceSRobert Watson "mountpount=%s)\n", 570db2661ceSRobert Watson subjlabeltext, p->p_pid, pgid, curthread->td_ucred->cr_uid, 571db2661ceSRobert Watson p->p_comm, subjtext, actionname, objlabeltext, objname, 57278007886SRobert Watson va.va_fileid, vp->v_mount->mnt_stat.f_mntonname); 573db2661ceSRobert Watson } else { 574db2661ceSRobert Watson log(LOG_INFO, "LOMAC: level-%s subject p%dg%du%d:%s demoted to" 575db2661ceSRobert Watson " level %s after %s a level-%s %s\n", 576db2661ceSRobert Watson subjlabeltext, p->p_pid, pgid, curthread->td_ucred->cr_uid, 577db2661ceSRobert Watson p->p_comm, subjtext, actionname, objlabeltext, objname); 578db2661ceSRobert Watson } 579db2661ceSRobert Watson 580f51e5803SRobert Watson sbuf_delete(&subjlabel_sb); 581f51e5803SRobert Watson sbuf_delete(&subjtext_sb); 582f51e5803SRobert Watson sbuf_delete(&objlabel_sb); 583f51e5803SRobert Watson 584db2661ceSRobert Watson return (0); 585db2661ceSRobert Watson } 586db2661ceSRobert Watson 587db2661ceSRobert Watson /* 5883f1a7a90SRobert Watson * Relabel "to" to "from" only if "from" is a valid label (contains at least 5893f1a7a90SRobert Watson * a single), as for a relabel operation which may or may not involve a 5903f1a7a90SRobert Watson * relevant label. 591db2661ceSRobert Watson */ 5927496ed81SRobert Watson static void 593db2661ceSRobert Watson try_relabel(struct mac_lomac *from, struct mac_lomac *to) 594db2661ceSRobert Watson { 595db2661ceSRobert Watson 596db2661ceSRobert Watson if (from->ml_flags & MAC_LOMAC_FLAG_SINGLE) { 597db2661ceSRobert Watson bzero(to, sizeof(*to)); 5983f1a7a90SRobert Watson lomac_copy(from, to); 599db2661ceSRobert Watson } 600db2661ceSRobert Watson } 601db2661ceSRobert Watson 602db2661ceSRobert Watson /* 603db2661ceSRobert Watson * Policy module operations. 604db2661ceSRobert Watson */ 605db2661ceSRobert Watson static void 6063f1a7a90SRobert Watson lomac_init(struct mac_policy_conf *conf) 607db2661ceSRobert Watson { 608db2661ceSRobert Watson 609db2661ceSRobert Watson } 610db2661ceSRobert Watson 611db2661ceSRobert Watson /* 612db2661ceSRobert Watson * Label operations. 613db2661ceSRobert Watson */ 614db2661ceSRobert Watson static void 6153f1a7a90SRobert Watson lomac_init_label(struct label *label) 616db2661ceSRobert Watson { 617db2661ceSRobert Watson 6181477f588SAlexander Kabaev SLOT_SET(label, lomac_alloc(M_WAITOK)); 619db2661ceSRobert Watson } 620db2661ceSRobert Watson 621db2661ceSRobert Watson static int 6223f1a7a90SRobert Watson lomac_init_label_waitcheck(struct label *label, int flag) 623db2661ceSRobert Watson { 624db2661ceSRobert Watson 6251477f588SAlexander Kabaev SLOT_SET(label, lomac_alloc(flag)); 626db2661ceSRobert Watson if (SLOT(label) == NULL) 627db2661ceSRobert Watson return (ENOMEM); 628db2661ceSRobert Watson 629db2661ceSRobert Watson return (0); 630db2661ceSRobert Watson } 631db2661ceSRobert Watson 632db2661ceSRobert Watson static void 6333f1a7a90SRobert Watson lomac_destroy_label(struct label *label) 634db2661ceSRobert Watson { 635db2661ceSRobert Watson 636db2661ceSRobert Watson lomac_free(SLOT(label)); 6371477f588SAlexander Kabaev SLOT_SET(label, NULL); 638db2661ceSRobert Watson } 639db2661ceSRobert Watson 640f51e5803SRobert Watson static int 6413f1a7a90SRobert Watson lomac_element_to_string(struct sbuf *sb, struct mac_lomac_element *element) 642db2661ceSRobert Watson { 643db2661ceSRobert Watson 644db2661ceSRobert Watson switch (element->mle_type) { 645db2661ceSRobert Watson case MAC_LOMAC_TYPE_HIGH: 646f51e5803SRobert Watson return (sbuf_printf(sb, "high")); 647db2661ceSRobert Watson 648db2661ceSRobert Watson case MAC_LOMAC_TYPE_LOW: 649f51e5803SRobert Watson return (sbuf_printf(sb, "low")); 650db2661ceSRobert Watson 651db2661ceSRobert Watson case MAC_LOMAC_TYPE_EQUAL: 652f51e5803SRobert Watson return (sbuf_printf(sb, "equal")); 653db2661ceSRobert Watson 654db2661ceSRobert Watson case MAC_LOMAC_TYPE_GRADE: 655f51e5803SRobert Watson return (sbuf_printf(sb, "%d", element->mle_grade)); 656db2661ceSRobert Watson 657db2661ceSRobert Watson default: 6583f1a7a90SRobert Watson panic("lomac_element_to_string: invalid type (%d)", 659db2661ceSRobert Watson element->mle_type); 660db2661ceSRobert Watson } 661db2661ceSRobert Watson } 662db2661ceSRobert Watson 663db2661ceSRobert Watson static int 6643f1a7a90SRobert Watson lomac_to_string(struct sbuf *sb, struct mac_lomac *ml) 665db2661ceSRobert Watson { 666db2661ceSRobert Watson 6673f1a7a90SRobert Watson if (ml->ml_flags & MAC_LOMAC_FLAG_SINGLE) { 6683f1a7a90SRobert Watson if (lomac_element_to_string(sb, &ml->ml_single) == -1) 669f51e5803SRobert Watson return (EINVAL); 670db2661ceSRobert Watson } 671db2661ceSRobert Watson 6723f1a7a90SRobert Watson if (ml->ml_flags & MAC_LOMAC_FLAG_AUX) { 673f51e5803SRobert Watson if (sbuf_putc(sb, '[') == -1) 674f51e5803SRobert Watson return (EINVAL); 675db2661ceSRobert Watson 6763f1a7a90SRobert Watson if (lomac_element_to_string(sb, &ml->ml_auxsingle) == -1) 677f51e5803SRobert Watson return (EINVAL); 678db2661ceSRobert Watson 679f51e5803SRobert Watson if (sbuf_putc(sb, ']') == -1) 680f51e5803SRobert Watson return (EINVAL); 681db2661ceSRobert Watson } 682db2661ceSRobert Watson 6833f1a7a90SRobert Watson if (ml->ml_flags & MAC_LOMAC_FLAG_RANGE) { 684f51e5803SRobert Watson if (sbuf_putc(sb, '(') == -1) 685f51e5803SRobert Watson return (EINVAL); 686db2661ceSRobert Watson 6873f1a7a90SRobert Watson if (lomac_element_to_string(sb, &ml->ml_rangelow) == -1) 688f51e5803SRobert Watson return (EINVAL); 689db2661ceSRobert Watson 690f51e5803SRobert Watson if (sbuf_putc(sb, '-') == -1) 691f51e5803SRobert Watson return (EINVAL); 692db2661ceSRobert Watson 6933f1a7a90SRobert Watson if (lomac_element_to_string(sb, &ml->ml_rangehigh) == -1) 694f51e5803SRobert Watson return (EINVAL); 695db2661ceSRobert Watson 6968a4b86b9SRobert Watson if (sbuf_putc(sb, ')') == -1) 697f51e5803SRobert Watson return (EINVAL); 698db2661ceSRobert Watson } 699db2661ceSRobert Watson 700db2661ceSRobert Watson return (0); 701db2661ceSRobert Watson } 702db2661ceSRobert Watson 703db2661ceSRobert Watson static int 7043f1a7a90SRobert Watson lomac_externalize_label(struct label *label, char *element_name, 705f51e5803SRobert Watson struct sbuf *sb, int *claimed) 706db2661ceSRobert Watson { 7073f1a7a90SRobert Watson struct mac_lomac *ml; 708db2661ceSRobert Watson 709db2661ceSRobert Watson if (strcmp(MAC_LOMAC_LABEL_NAME, element_name) != 0) 710db2661ceSRobert Watson return (0); 711db2661ceSRobert Watson 712db2661ceSRobert Watson (*claimed)++; 713db2661ceSRobert Watson 7143f1a7a90SRobert Watson ml = SLOT(label); 715db2661ceSRobert Watson 7163f1a7a90SRobert Watson return (lomac_to_string(sb, ml)); 717db2661ceSRobert Watson } 718db2661ceSRobert Watson 719db2661ceSRobert Watson static int 7203f1a7a90SRobert Watson lomac_parse_element(struct mac_lomac_element *element, char *string) 721db2661ceSRobert Watson { 722db2661ceSRobert Watson 7233f1a7a90SRobert Watson if (strcmp(string, "high") == 0 || strcmp(string, "hi") == 0) { 724db2661ceSRobert Watson element->mle_type = MAC_LOMAC_TYPE_HIGH; 725db2661ceSRobert Watson element->mle_grade = MAC_LOMAC_TYPE_UNDEF; 7263f1a7a90SRobert Watson } else if (strcmp(string, "low") == 0 || strcmp(string, "lo") == 0) { 727db2661ceSRobert Watson element->mle_type = MAC_LOMAC_TYPE_LOW; 728db2661ceSRobert Watson element->mle_grade = MAC_LOMAC_TYPE_UNDEF; 72995b85ca3SRobert Watson } else if (strcmp(string, "equal") == 0 || 73095b85ca3SRobert Watson strcmp(string, "eq") == 0) { 731db2661ceSRobert Watson element->mle_type = MAC_LOMAC_TYPE_EQUAL; 732db2661ceSRobert Watson element->mle_grade = MAC_LOMAC_TYPE_UNDEF; 733db2661ceSRobert Watson } else { 734db2661ceSRobert Watson char *p0, *p1; 735db2661ceSRobert Watson int d; 736db2661ceSRobert Watson 737db2661ceSRobert Watson p0 = string; 738db2661ceSRobert Watson d = strtol(p0, &p1, 10); 739db2661ceSRobert Watson 740db2661ceSRobert Watson if (d < 0 || d > 65535) 741db2661ceSRobert Watson return (EINVAL); 742db2661ceSRobert Watson element->mle_type = MAC_LOMAC_TYPE_GRADE; 743db2661ceSRobert Watson element->mle_grade = d; 744db2661ceSRobert Watson 745db2661ceSRobert Watson if (p1 == p0 || *p1 != '\0') 746db2661ceSRobert Watson return (EINVAL); 747db2661ceSRobert Watson } 748db2661ceSRobert Watson 749db2661ceSRobert Watson return (0); 750db2661ceSRobert Watson } 751db2661ceSRobert Watson 752db2661ceSRobert Watson /* 7533f1a7a90SRobert Watson * Note: destructively consumes the string, make a local copy before calling 7543f1a7a90SRobert Watson * if that's a problem. 755db2661ceSRobert Watson */ 756db2661ceSRobert Watson static int 7573f1a7a90SRobert Watson lomac_parse(struct mac_lomac *ml, char *string) 758db2661ceSRobert Watson { 759db2661ceSRobert Watson char *range, *rangeend, *rangehigh, *rangelow, *single, *auxsingle, 760db2661ceSRobert Watson *auxsingleend; 761db2661ceSRobert Watson int error; 762db2661ceSRobert Watson 763db2661ceSRobert Watson /* Do we have a range? */ 764db2661ceSRobert Watson single = string; 765db2661ceSRobert Watson range = index(string, '('); 766db2661ceSRobert Watson if (range == single) 767db2661ceSRobert Watson single = NULL; 768db2661ceSRobert Watson auxsingle = index(string, '['); 769db2661ceSRobert Watson if (auxsingle == single) 770db2661ceSRobert Watson single = NULL; 771db2661ceSRobert Watson if (range != NULL && auxsingle != NULL) 772db2661ceSRobert Watson return (EINVAL); 773db2661ceSRobert Watson rangelow = rangehigh = NULL; 774db2661ceSRobert Watson if (range != NULL) { 775db2661ceSRobert Watson /* Nul terminate the end of the single string. */ 776db2661ceSRobert Watson *range = '\0'; 777db2661ceSRobert Watson range++; 778db2661ceSRobert Watson rangelow = range; 779db2661ceSRobert Watson rangehigh = index(rangelow, '-'); 780db2661ceSRobert Watson if (rangehigh == NULL) 781db2661ceSRobert Watson return (EINVAL); 782db2661ceSRobert Watson rangehigh++; 783db2661ceSRobert Watson if (*rangelow == '\0' || *rangehigh == '\0') 784db2661ceSRobert Watson return (EINVAL); 785db2661ceSRobert Watson rangeend = index(rangehigh, ')'); 786db2661ceSRobert Watson if (rangeend == NULL) 787db2661ceSRobert Watson return (EINVAL); 788db2661ceSRobert Watson if (*(rangeend + 1) != '\0') 789db2661ceSRobert Watson return (EINVAL); 790db2661ceSRobert Watson /* Nul terminate the ends of the ranges. */ 791db2661ceSRobert Watson *(rangehigh - 1) = '\0'; 792db2661ceSRobert Watson *rangeend = '\0'; 793db2661ceSRobert Watson } 794db2661ceSRobert Watson KASSERT((rangelow != NULL && rangehigh != NULL) || 795db2661ceSRobert Watson (rangelow == NULL && rangehigh == NULL), 7963f1a7a90SRobert Watson ("lomac_internalize_label: range mismatch")); 797db2661ceSRobert Watson if (auxsingle != NULL) { 798db2661ceSRobert Watson /* Nul terminate the end of the single string. */ 799db2661ceSRobert Watson *auxsingle = '\0'; 800db2661ceSRobert Watson auxsingle++; 801db2661ceSRobert Watson auxsingleend = index(auxsingle, ']'); 802db2661ceSRobert Watson if (auxsingleend == NULL) 803db2661ceSRobert Watson return (EINVAL); 804db2661ceSRobert Watson if (*(auxsingleend + 1) != '\0') 805db2661ceSRobert Watson return (EINVAL); 806db2661ceSRobert Watson /* Nul terminate the end of the auxsingle. */ 807db2661ceSRobert Watson *auxsingleend = '\0'; 808db2661ceSRobert Watson } 809db2661ceSRobert Watson 8103f1a7a90SRobert Watson bzero(ml, sizeof(*ml)); 811db2661ceSRobert Watson if (single != NULL) { 8123f1a7a90SRobert Watson error = lomac_parse_element(&ml->ml_single, single); 813db2661ceSRobert Watson if (error) 814db2661ceSRobert Watson return (error); 8153f1a7a90SRobert Watson ml->ml_flags |= MAC_LOMAC_FLAG_SINGLE; 816db2661ceSRobert Watson } 817db2661ceSRobert Watson 818db2661ceSRobert Watson if (auxsingle != NULL) { 81995b85ca3SRobert Watson error = lomac_parse_element(&ml->ml_auxsingle, auxsingle); 820db2661ceSRobert Watson if (error) 821db2661ceSRobert Watson return (error); 8223f1a7a90SRobert Watson ml->ml_flags |= MAC_LOMAC_FLAG_AUX; 823db2661ceSRobert Watson } 824db2661ceSRobert Watson 825db2661ceSRobert Watson if (rangelow != NULL) { 8263f1a7a90SRobert Watson error = lomac_parse_element(&ml->ml_rangelow, rangelow); 827db2661ceSRobert Watson if (error) 828db2661ceSRobert Watson return (error); 8293f1a7a90SRobert Watson error = lomac_parse_element(&ml->ml_rangehigh, rangehigh); 830db2661ceSRobert Watson if (error) 831db2661ceSRobert Watson return (error); 8323f1a7a90SRobert Watson ml->ml_flags |= MAC_LOMAC_FLAG_RANGE; 833db2661ceSRobert Watson } 834db2661ceSRobert Watson 8353f1a7a90SRobert Watson error = lomac_valid(ml); 836db2661ceSRobert Watson if (error) 837db2661ceSRobert Watson return (error); 838db2661ceSRobert Watson 839db2661ceSRobert Watson return (0); 840db2661ceSRobert Watson } 841db2661ceSRobert Watson 842db2661ceSRobert Watson static int 8433f1a7a90SRobert Watson lomac_internalize_label(struct label *label, char *element_name, 844db2661ceSRobert Watson char *element_data, int *claimed) 845db2661ceSRobert Watson { 8463f1a7a90SRobert Watson struct mac_lomac *ml, ml_temp; 847db2661ceSRobert Watson int error; 848db2661ceSRobert Watson 849db2661ceSRobert Watson if (strcmp(MAC_LOMAC_LABEL_NAME, element_name) != 0) 850db2661ceSRobert Watson return (0); 851db2661ceSRobert Watson 852db2661ceSRobert Watson (*claimed)++; 853db2661ceSRobert Watson 8543f1a7a90SRobert Watson error = lomac_parse(&ml_temp, element_data); 855db2661ceSRobert Watson if (error) 856db2661ceSRobert Watson return (error); 857db2661ceSRobert Watson 8583f1a7a90SRobert Watson ml = SLOT(label); 8593f1a7a90SRobert Watson *ml = ml_temp; 860db2661ceSRobert Watson 861db2661ceSRobert Watson return (0); 862db2661ceSRobert Watson } 863db2661ceSRobert Watson 864db2661ceSRobert Watson static void 8653f1a7a90SRobert Watson lomac_copy_label(struct label *src, struct label *dest) 866db2661ceSRobert Watson { 867db2661ceSRobert Watson 868db2661ceSRobert Watson *SLOT(dest) = *SLOT(src); 869db2661ceSRobert Watson } 870db2661ceSRobert Watson 871db2661ceSRobert Watson /* 872eb320b0eSRobert Watson * Object-specific entry point implementations are sorted alphabetically by 873eb320b0eSRobert Watson * object type name and then by operation. 874db2661ceSRobert Watson */ 875db2661ceSRobert Watson static int 8763f1a7a90SRobert Watson lomac_bpfdesc_check_receive(struct bpf_d *d, struct label *dlabel, 87778007886SRobert Watson struct ifnet *ifp, struct label *ifplabel) 878db2661ceSRobert Watson { 879db2661ceSRobert Watson struct mac_lomac *a, *b; 880db2661ceSRobert Watson 8813f1a7a90SRobert Watson if (!lomac_enabled) 882db2661ceSRobert Watson return (0); 883db2661ceSRobert Watson 88478007886SRobert Watson a = SLOT(dlabel); 88578007886SRobert Watson b = SLOT(ifplabel); 886db2661ceSRobert Watson 8873f1a7a90SRobert Watson if (lomac_equal_single(a, b)) 888db2661ceSRobert Watson return (0); 889db2661ceSRobert Watson return (EACCES); 890db2661ceSRobert Watson } 891db2661ceSRobert Watson 892eb320b0eSRobert Watson static void 893eb320b0eSRobert Watson lomac_bpfdesc_create(struct ucred *cred, struct bpf_d *d, 894eb320b0eSRobert Watson struct label *dlabel) 895eb320b0eSRobert Watson { 896eb320b0eSRobert Watson struct mac_lomac *source, *dest; 897eb320b0eSRobert Watson 898eb320b0eSRobert Watson source = SLOT(cred->cr_label); 899eb320b0eSRobert Watson dest = SLOT(dlabel); 900eb320b0eSRobert Watson 901eb320b0eSRobert Watson lomac_copy_single(source, dest); 902eb320b0eSRobert Watson } 903eb320b0eSRobert Watson 904eb320b0eSRobert Watson static void 905eb320b0eSRobert Watson lomac_bpfdesc_create_mbuf(struct bpf_d *d, struct label *dlabel, 906eb320b0eSRobert Watson struct mbuf *m, struct label *mlabel) 907eb320b0eSRobert Watson { 908eb320b0eSRobert Watson struct mac_lomac *source, *dest; 909eb320b0eSRobert Watson 910eb320b0eSRobert Watson source = SLOT(dlabel); 911eb320b0eSRobert Watson dest = SLOT(mlabel); 912eb320b0eSRobert Watson 913eb320b0eSRobert Watson lomac_copy_single(source, dest); 914eb320b0eSRobert Watson } 915eb320b0eSRobert Watson 916db2661ceSRobert Watson static int 9173f1a7a90SRobert Watson lomac_cred_check_relabel(struct ucred *cred, struct label *newlabel) 918db2661ceSRobert Watson { 919db2661ceSRobert Watson struct mac_lomac *subj, *new; 920db2661ceSRobert Watson int error; 921db2661ceSRobert Watson 922eca8a663SRobert Watson subj = SLOT(cred->cr_label); 923db2661ceSRobert Watson new = SLOT(newlabel); 924db2661ceSRobert Watson 925db2661ceSRobert Watson /* 9263f1a7a90SRobert Watson * If there is a LOMAC label update for the credential, it may be an 9273f1a7a90SRobert Watson * update of the single, range, or both. 928db2661ceSRobert Watson */ 929db2661ceSRobert Watson error = lomac_atmostflags(new, MAC_LOMAC_FLAGS_BOTH); 930db2661ceSRobert Watson if (error) 931db2661ceSRobert Watson return (error); 932db2661ceSRobert Watson 933db2661ceSRobert Watson /* 934db2661ceSRobert Watson * If the LOMAC label is to be changed, authorize as appropriate. 935db2661ceSRobert Watson */ 936db2661ceSRobert Watson if (new->ml_flags & MAC_LOMAC_FLAGS_BOTH) { 937db2661ceSRobert Watson /* 93884bdb083SRobert Watson * Fill in the missing parts from the previous label. 939db2661ceSRobert Watson */ 94084bdb083SRobert Watson if ((new->ml_flags & MAC_LOMAC_FLAG_SINGLE) == 0) 9413f1a7a90SRobert Watson lomac_copy_single(subj, new); 94284bdb083SRobert Watson if ((new->ml_flags & MAC_LOMAC_FLAG_RANGE) == 0) 9433f1a7a90SRobert Watson lomac_copy_range(subj, new); 944db2661ceSRobert Watson 945db2661ceSRobert Watson /* 9463f1a7a90SRobert Watson * To change the LOMAC range on a credential, the new range 9473f1a7a90SRobert Watson * label must be in the current range. 948db2661ceSRobert Watson */ 9493f1a7a90SRobert Watson if (!lomac_range_in_range(new, subj)) 95084bdb083SRobert Watson return (EPERM); 95184bdb083SRobert Watson 95284bdb083SRobert Watson /* 9533f1a7a90SRobert Watson * To change the LOMAC single label on a credential, the new 9543f1a7a90SRobert Watson * single label must be in the new range. Implicitly from 9553f1a7a90SRobert Watson * the previous check, the new single is in the old range. 95684bdb083SRobert Watson */ 9573f1a7a90SRobert Watson if (!lomac_single_in_range(new, new)) 958db2661ceSRobert Watson return (EPERM); 959db2661ceSRobert Watson 960db2661ceSRobert Watson /* 9613f1a7a90SRobert Watson * To have EQUAL in any component of the new credential LOMAC 9623f1a7a90SRobert Watson * label, the subject must already have EQUAL in their label. 963db2661ceSRobert Watson */ 9643f1a7a90SRobert Watson if (lomac_contains_equal(new)) { 9653f1a7a90SRobert Watson error = lomac_subject_privileged(subj); 966db2661ceSRobert Watson if (error) 967db2661ceSRobert Watson return (error); 968db2661ceSRobert Watson } 969db2661ceSRobert Watson 970db2661ceSRobert Watson /* 9713f1a7a90SRobert Watson * XXXMAC: Additional consistency tests regarding the single 9723f1a7a90SRobert Watson * and range of the new label might be performed here. 973db2661ceSRobert Watson */ 974db2661ceSRobert Watson } 975db2661ceSRobert Watson 976db2661ceSRobert Watson return (0); 977db2661ceSRobert Watson } 978db2661ceSRobert Watson 979db2661ceSRobert Watson static int 9803f1a7a90SRobert Watson lomac_cred_check_visible(struct ucred *cr1, struct ucred *cr2) 981db2661ceSRobert Watson { 982db2661ceSRobert Watson struct mac_lomac *subj, *obj; 983db2661ceSRobert Watson 9843f1a7a90SRobert Watson if (!lomac_enabled) 985db2661ceSRobert Watson return (0); 986db2661ceSRobert Watson 98778007886SRobert Watson subj = SLOT(cr1->cr_label); 98878007886SRobert Watson obj = SLOT(cr2->cr_label); 989db2661ceSRobert Watson 990db2661ceSRobert Watson /* XXX: range */ 9913f1a7a90SRobert Watson if (!lomac_dominate_single(obj, subj)) 992db2661ceSRobert Watson return (ESRCH); 993db2661ceSRobert Watson 994db2661ceSRobert Watson return (0); 995db2661ceSRobert Watson } 996eb320b0eSRobert Watson static void 997eb320b0eSRobert Watson lomac_cred_relabel(struct ucred *cred, struct label *newlabel) 998eb320b0eSRobert Watson { 999eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1000eb320b0eSRobert Watson 1001eb320b0eSRobert Watson source = SLOT(newlabel); 1002eb320b0eSRobert Watson dest = SLOT(cred->cr_label); 1003eb320b0eSRobert Watson 1004eb320b0eSRobert Watson try_relabel(source, dest); 1005eb320b0eSRobert Watson } 1006eb320b0eSRobert Watson 1007eb320b0eSRobert Watson static void 1008eb320b0eSRobert Watson lomac_devfs_create_device(struct ucred *cred, struct mount *mp, 1009eb320b0eSRobert Watson struct cdev *dev, struct devfs_dirent *de, struct label *delabel) 1010eb320b0eSRobert Watson { 1011eb320b0eSRobert Watson struct mac_lomac *ml; 1012eb320b0eSRobert Watson int lomac_type; 1013eb320b0eSRobert Watson 1014eb320b0eSRobert Watson ml = SLOT(delabel); 1015eb320b0eSRobert Watson if (strcmp(dev->si_name, "null") == 0 || 1016eb320b0eSRobert Watson strcmp(dev->si_name, "zero") == 0 || 1017eb320b0eSRobert Watson strcmp(dev->si_name, "random") == 0 || 1018eb320b0eSRobert Watson strncmp(dev->si_name, "fd/", strlen("fd/")) == 0 || 1019eb320b0eSRobert Watson strncmp(dev->si_name, "ttyv", strlen("ttyv")) == 0) 1020eb320b0eSRobert Watson lomac_type = MAC_LOMAC_TYPE_EQUAL; 1021eb320b0eSRobert Watson else if (ptys_equal && 1022eb320b0eSRobert Watson (strncmp(dev->si_name, "ttyp", strlen("ttyp")) == 0 || 1023eb320b0eSRobert Watson strncmp(dev->si_name, "ptyp", strlen("ptyp")) == 0)) 1024eb320b0eSRobert Watson lomac_type = MAC_LOMAC_TYPE_EQUAL; 1025eb320b0eSRobert Watson else 1026eb320b0eSRobert Watson lomac_type = MAC_LOMAC_TYPE_HIGH; 1027eb320b0eSRobert Watson lomac_set_single(ml, lomac_type, 0); 1028eb320b0eSRobert Watson } 1029eb320b0eSRobert Watson 1030eb320b0eSRobert Watson static void 1031eb320b0eSRobert Watson lomac_devfs_create_directory(struct mount *mp, char *dirname, int dirnamelen, 1032eb320b0eSRobert Watson struct devfs_dirent *de, struct label *delabel) 1033eb320b0eSRobert Watson { 1034eb320b0eSRobert Watson struct mac_lomac *ml; 1035eb320b0eSRobert Watson 1036eb320b0eSRobert Watson ml = SLOT(delabel); 1037eb320b0eSRobert Watson lomac_set_single(ml, MAC_LOMAC_TYPE_HIGH, 0); 1038eb320b0eSRobert Watson } 1039eb320b0eSRobert Watson 1040eb320b0eSRobert Watson static void 1041eb320b0eSRobert Watson lomac_devfs_create_symlink(struct ucred *cred, struct mount *mp, 1042eb320b0eSRobert Watson struct devfs_dirent *dd, struct label *ddlabel, struct devfs_dirent *de, 1043eb320b0eSRobert Watson struct label *delabel) 1044eb320b0eSRobert Watson { 1045eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1046eb320b0eSRobert Watson 1047eb320b0eSRobert Watson source = SLOT(cred->cr_label); 1048eb320b0eSRobert Watson dest = SLOT(delabel); 1049eb320b0eSRobert Watson 1050eb320b0eSRobert Watson lomac_copy_single(source, dest); 1051eb320b0eSRobert Watson } 1052eb320b0eSRobert Watson 1053eb320b0eSRobert Watson static void 1054eb320b0eSRobert Watson lomac_devfs_update(struct mount *mp, struct devfs_dirent *de, 1055eb320b0eSRobert Watson struct label *delabel, struct vnode *vp, struct label *vplabel) 1056eb320b0eSRobert Watson { 1057eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1058eb320b0eSRobert Watson 1059eb320b0eSRobert Watson source = SLOT(vplabel); 1060eb320b0eSRobert Watson dest = SLOT(delabel); 1061eb320b0eSRobert Watson 1062eb320b0eSRobert Watson lomac_copy(source, dest); 1063eb320b0eSRobert Watson } 1064eb320b0eSRobert Watson 1065eb320b0eSRobert Watson static void 1066eb320b0eSRobert Watson lomac_devfs_vnode_associate(struct mount *mp, struct label *mplabel, 1067eb320b0eSRobert Watson struct devfs_dirent *de, struct label *delabel, struct vnode *vp, 1068eb320b0eSRobert Watson struct label *vplabel) 1069eb320b0eSRobert Watson { 1070eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1071eb320b0eSRobert Watson 1072eb320b0eSRobert Watson source = SLOT(delabel); 1073eb320b0eSRobert Watson dest = SLOT(vplabel); 1074eb320b0eSRobert Watson 1075eb320b0eSRobert Watson lomac_copy_single(source, dest); 1076eb320b0eSRobert Watson } 1077db2661ceSRobert Watson 1078db2661ceSRobert Watson static int 10793f1a7a90SRobert Watson lomac_ifnet_check_relabel(struct ucred *cred, struct ifnet *ifp, 108078007886SRobert Watson struct label *ifplabel, struct label *newlabel) 1081db2661ceSRobert Watson { 1082db2661ceSRobert Watson struct mac_lomac *subj, *new; 1083db2661ceSRobert Watson int error; 1084db2661ceSRobert Watson 1085eca8a663SRobert Watson subj = SLOT(cred->cr_label); 1086db2661ceSRobert Watson new = SLOT(newlabel); 1087db2661ceSRobert Watson 1088db2661ceSRobert Watson /* 10893f1a7a90SRobert Watson * If there is a LOMAC label update for the interface, it may be an 10903f1a7a90SRobert Watson * update of the single, range, or both. 1091db2661ceSRobert Watson */ 1092db2661ceSRobert Watson error = lomac_atmostflags(new, MAC_LOMAC_FLAGS_BOTH); 1093db2661ceSRobert Watson if (error) 1094db2661ceSRobert Watson return (error); 1095db2661ceSRobert Watson 1096db2661ceSRobert Watson /* 1097db2661ceSRobert Watson * Relabling network interfaces requires LOMAC privilege. 1098db2661ceSRobert Watson */ 10993f1a7a90SRobert Watson error = lomac_subject_privileged(subj); 1100db2661ceSRobert Watson if (error) 1101db2661ceSRobert Watson return (error); 1102db2661ceSRobert Watson 1103db2661ceSRobert Watson /* 1104db2661ceSRobert Watson * If the LOMAC label is to be changed, authorize as appropriate. 1105db2661ceSRobert Watson */ 1106db2661ceSRobert Watson if (new->ml_flags & MAC_LOMAC_FLAGS_BOTH) { 1107db2661ceSRobert Watson /* 110884bdb083SRobert Watson * Fill in the missing parts from the previous label. 110984bdb083SRobert Watson */ 111084bdb083SRobert Watson if ((new->ml_flags & MAC_LOMAC_FLAG_SINGLE) == 0) 11113f1a7a90SRobert Watson lomac_copy_single(subj, new); 111284bdb083SRobert Watson if ((new->ml_flags & MAC_LOMAC_FLAG_RANGE) == 0) 11133f1a7a90SRobert Watson lomac_copy_range(subj, new); 111484bdb083SRobert Watson 111584bdb083SRobert Watson /* 1116db2661ceSRobert Watson * Rely on the traditional superuser status for the LOMAC 1117db2661ceSRobert Watson * interface relabel requirements. XXXMAC: This will go 1118db2661ceSRobert Watson * away. 1119acd3428bSRobert Watson * 1120acd3428bSRobert Watson * XXXRW: This is also redundant to a higher layer check. 1121db2661ceSRobert Watson */ 1122acd3428bSRobert Watson error = priv_check_cred(cred, PRIV_NET_SETIFMAC, 0); 1123db2661ceSRobert Watson if (error) 1124db2661ceSRobert Watson return (EPERM); 1125db2661ceSRobert Watson 1126db2661ceSRobert Watson /* 1127db2661ceSRobert Watson * XXXMAC: Additional consistency tests regarding the single 1128db2661ceSRobert Watson * and the range of the new label might be performed here. 1129db2661ceSRobert Watson */ 1130db2661ceSRobert Watson } 1131db2661ceSRobert Watson 1132db2661ceSRobert Watson return (0); 1133db2661ceSRobert Watson } 1134db2661ceSRobert Watson 1135db2661ceSRobert Watson static int 11363f1a7a90SRobert Watson lomac_ifnet_check_transmit(struct ifnet *ifp, struct label *ifplabel, 113778007886SRobert Watson struct mbuf *m, struct label *mlabel) 1138db2661ceSRobert Watson { 1139db2661ceSRobert Watson struct mac_lomac *p, *i; 1140db2661ceSRobert Watson 11413f1a7a90SRobert Watson if (!lomac_enabled) 1142db2661ceSRobert Watson return (0); 1143db2661ceSRobert Watson 114478007886SRobert Watson p = SLOT(mlabel); 114578007886SRobert Watson i = SLOT(ifplabel); 1146db2661ceSRobert Watson 11473f1a7a90SRobert Watson return (lomac_single_in_range(p, i) ? 0 : EACCES); 1148db2661ceSRobert Watson } 1149db2661ceSRobert Watson 1150eb320b0eSRobert Watson static void 1151eb320b0eSRobert Watson lomac_ifnet_create(struct ifnet *ifp, struct label *ifplabel) 1152eb320b0eSRobert Watson { 1153eb320b0eSRobert Watson char tifname[IFNAMSIZ], *p, *q; 1154eb320b0eSRobert Watson char tiflist[sizeof(trusted_interfaces)]; 1155eb320b0eSRobert Watson struct mac_lomac *dest; 1156eb320b0eSRobert Watson int len, grade; 1157eb320b0eSRobert Watson 1158eb320b0eSRobert Watson dest = SLOT(ifplabel); 1159eb320b0eSRobert Watson 1160eb320b0eSRobert Watson if (ifp->if_type == IFT_LOOP) { 1161eb320b0eSRobert Watson grade = MAC_LOMAC_TYPE_EQUAL; 1162eb320b0eSRobert Watson goto set; 1163eb320b0eSRobert Watson } 1164eb320b0eSRobert Watson 1165eb320b0eSRobert Watson if (trust_all_interfaces) { 1166eb320b0eSRobert Watson grade = MAC_LOMAC_TYPE_HIGH; 1167eb320b0eSRobert Watson goto set; 1168eb320b0eSRobert Watson } 1169eb320b0eSRobert Watson 1170eb320b0eSRobert Watson grade = MAC_LOMAC_TYPE_LOW; 1171eb320b0eSRobert Watson 1172eb320b0eSRobert Watson if (trusted_interfaces[0] == '\0' || 1173eb320b0eSRobert Watson !strvalid(trusted_interfaces, sizeof(trusted_interfaces))) 1174eb320b0eSRobert Watson goto set; 1175eb320b0eSRobert Watson 1176eb320b0eSRobert Watson bzero(tiflist, sizeof(tiflist)); 1177eb320b0eSRobert Watson for (p = trusted_interfaces, q = tiflist; *p != '\0'; p++, q++) 1178eb320b0eSRobert Watson if(*p != ' ' && *p != '\t') 1179eb320b0eSRobert Watson *q = *p; 1180eb320b0eSRobert Watson 1181eb320b0eSRobert Watson for (p = q = tiflist;; p++) { 1182eb320b0eSRobert Watson if (*p == ',' || *p == '\0') { 1183eb320b0eSRobert Watson len = p - q; 1184eb320b0eSRobert Watson if (len < IFNAMSIZ) { 1185eb320b0eSRobert Watson bzero(tifname, sizeof(tifname)); 1186eb320b0eSRobert Watson bcopy(q, tifname, len); 1187eb320b0eSRobert Watson if (strcmp(tifname, ifp->if_xname) == 0) { 1188eb320b0eSRobert Watson grade = MAC_LOMAC_TYPE_HIGH; 1189eb320b0eSRobert Watson break; 1190eb320b0eSRobert Watson } 1191eb320b0eSRobert Watson } 1192eb320b0eSRobert Watson else { 1193eb320b0eSRobert Watson *p = '\0'; 1194eb320b0eSRobert Watson printf("MAC/LOMAC warning: interface name " 1195eb320b0eSRobert Watson "\"%s\" is too long (must be < %d)\n", 1196eb320b0eSRobert Watson q, IFNAMSIZ); 1197eb320b0eSRobert Watson } 1198eb320b0eSRobert Watson if (*p == '\0') 1199eb320b0eSRobert Watson break; 1200eb320b0eSRobert Watson q = p + 1; 1201eb320b0eSRobert Watson } 1202eb320b0eSRobert Watson } 1203eb320b0eSRobert Watson set: 1204eb320b0eSRobert Watson lomac_set_single(dest, grade, 0); 1205eb320b0eSRobert Watson lomac_set_range(dest, grade, 0, grade, 0); 1206eb320b0eSRobert Watson } 1207eb320b0eSRobert Watson 1208eb320b0eSRobert Watson static void 1209eb320b0eSRobert Watson lomac_ifnet_create_mbuf(struct ifnet *ifp, struct label *ifplabel, 1210eb320b0eSRobert Watson struct mbuf *m, struct label *mlabel) 1211eb320b0eSRobert Watson { 1212eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1213eb320b0eSRobert Watson 1214eb320b0eSRobert Watson source = SLOT(ifplabel); 1215eb320b0eSRobert Watson dest = SLOT(mlabel); 1216eb320b0eSRobert Watson 1217eb320b0eSRobert Watson lomac_copy_single(source, dest); 1218eb320b0eSRobert Watson } 1219eb320b0eSRobert Watson 1220eb320b0eSRobert Watson static void 1221eb320b0eSRobert Watson lomac_ifnet_relabel(struct ucred *cred, struct ifnet *ifp, 1222eb320b0eSRobert Watson struct label *ifplabel, struct label *newlabel) 1223eb320b0eSRobert Watson { 1224eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1225eb320b0eSRobert Watson 1226eb320b0eSRobert Watson source = SLOT(newlabel); 1227eb320b0eSRobert Watson dest = SLOT(ifplabel); 1228eb320b0eSRobert Watson 1229eb320b0eSRobert Watson try_relabel(source, dest); 1230eb320b0eSRobert Watson } 1231eb320b0eSRobert Watson 1232db2661ceSRobert Watson static int 12333f1a7a90SRobert Watson lomac_inpcb_check_deliver(struct inpcb *inp, struct label *inplabel, 1234a557af22SRobert Watson struct mbuf *m, struct label *mlabel) 1235a557af22SRobert Watson { 1236a557af22SRobert Watson struct mac_lomac *p, *i; 1237a557af22SRobert Watson 12383f1a7a90SRobert Watson if (!lomac_enabled) 1239a557af22SRobert Watson return (0); 1240a557af22SRobert Watson 1241a557af22SRobert Watson p = SLOT(mlabel); 1242a557af22SRobert Watson i = SLOT(inplabel); 1243a557af22SRobert Watson 12443f1a7a90SRobert Watson return (lomac_equal_single(p, i) ? 0 : EACCES); 1245a557af22SRobert Watson } 1246a557af22SRobert Watson 12477fb179baSBjoern A. Zeeb static int 12487fb179baSBjoern A. Zeeb lomac_inpcb_check_visible(struct ucred *cred, struct inpcb *inp, 12497fb179baSBjoern A. Zeeb struct label *inplabel) 12507fb179baSBjoern A. Zeeb { 12517fb179baSBjoern A. Zeeb struct mac_lomac *subj, *obj; 12527fb179baSBjoern A. Zeeb 12537fb179baSBjoern A. Zeeb if (!lomac_enabled) 12547fb179baSBjoern A. Zeeb return (0); 12557fb179baSBjoern A. Zeeb 12567fb179baSBjoern A. Zeeb subj = SLOT(cred->cr_label); 12577fb179baSBjoern A. Zeeb obj = SLOT(inplabel); 12587fb179baSBjoern A. Zeeb 12597fb179baSBjoern A. Zeeb if (!lomac_dominate_single(obj, subj)) 12607fb179baSBjoern A. Zeeb return (ENOENT); 12617fb179baSBjoern A. Zeeb 12627fb179baSBjoern A. Zeeb return (0); 12637fb179baSBjoern A. Zeeb } 12647fb179baSBjoern A. Zeeb 1265eb320b0eSRobert Watson static void 1266eb320b0eSRobert Watson lomac_inpcb_create(struct socket *so, struct label *solabel, 1267eb320b0eSRobert Watson struct inpcb *inp, struct label *inplabel) 1268eb320b0eSRobert Watson { 1269eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1270eb320b0eSRobert Watson 1271eb320b0eSRobert Watson source = SLOT(solabel); 1272eb320b0eSRobert Watson dest = SLOT(inplabel); 1273eb320b0eSRobert Watson 1274eb320b0eSRobert Watson lomac_copy_single(source, dest); 1275eb320b0eSRobert Watson } 1276eb320b0eSRobert Watson 1277eb320b0eSRobert Watson static void 1278eb320b0eSRobert Watson lomac_inpcb_create_mbuf(struct inpcb *inp, struct label *inplabel, 1279eb320b0eSRobert Watson struct mbuf *m, struct label *mlabel) 1280eb320b0eSRobert Watson { 1281eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1282eb320b0eSRobert Watson 1283eb320b0eSRobert Watson source = SLOT(inplabel); 1284eb320b0eSRobert Watson dest = SLOT(mlabel); 1285eb320b0eSRobert Watson 1286eb320b0eSRobert Watson lomac_copy_single(source, dest); 1287eb320b0eSRobert Watson } 1288eb320b0eSRobert Watson 1289eb320b0eSRobert Watson static void 1290eb320b0eSRobert Watson lomac_inpcb_sosetlabel(struct socket *so, struct label *solabel, 1291eb320b0eSRobert Watson struct inpcb *inp, struct label *inplabel) 1292eb320b0eSRobert Watson { 1293eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1294eb320b0eSRobert Watson 1295eb320b0eSRobert Watson source = SLOT(solabel); 1296eb320b0eSRobert Watson dest = SLOT(inplabel); 1297eb320b0eSRobert Watson 1298eb320b0eSRobert Watson lomac_copy_single(source, dest); 1299eb320b0eSRobert Watson } 1300eb320b0eSRobert Watson 1301eb320b0eSRobert Watson static void 130237f44cb4SRobert Watson lomac_ipq_create(struct mbuf *m, struct label *mlabel, struct ipq *q, 130337f44cb4SRobert Watson struct label *qlabel) 1304eb320b0eSRobert Watson { 1305eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1306eb320b0eSRobert Watson 1307eb320b0eSRobert Watson source = SLOT(mlabel); 130837f44cb4SRobert Watson dest = SLOT(qlabel); 1309eb320b0eSRobert Watson 1310eb320b0eSRobert Watson lomac_copy_single(source, dest); 1311eb320b0eSRobert Watson } 1312eb320b0eSRobert Watson 1313eb320b0eSRobert Watson static int 131437f44cb4SRobert Watson lomac_ipq_match(struct mbuf *m, struct label *mlabel, struct ipq *q, 131537f44cb4SRobert Watson struct label *qlabel) 1316eb320b0eSRobert Watson { 1317eb320b0eSRobert Watson struct mac_lomac *a, *b; 1318eb320b0eSRobert Watson 131937f44cb4SRobert Watson a = SLOT(qlabel); 1320eb320b0eSRobert Watson b = SLOT(mlabel); 1321eb320b0eSRobert Watson 1322eb320b0eSRobert Watson return (lomac_equal_single(a, b)); 1323eb320b0eSRobert Watson } 1324eb320b0eSRobert Watson 1325eb320b0eSRobert Watson static void 132637f44cb4SRobert Watson lomac_ipq_reassemble(struct ipq *q, struct label *qlabel, struct mbuf *m, 132737f44cb4SRobert Watson struct label *mlabel) 1328eb320b0eSRobert Watson { 1329eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1330eb320b0eSRobert Watson 133137f44cb4SRobert Watson source = SLOT(qlabel); 1332eb320b0eSRobert Watson dest = SLOT(mlabel); 1333eb320b0eSRobert Watson 1334eb320b0eSRobert Watson /* Just use the head, since we require them all to match. */ 1335eb320b0eSRobert Watson lomac_copy_single(source, dest); 1336eb320b0eSRobert Watson } 1337eb320b0eSRobert Watson 1338eb320b0eSRobert Watson static void 133937f44cb4SRobert Watson lomac_ipq_update(struct mbuf *m, struct label *mlabel, struct ipq *q, 134037f44cb4SRobert Watson struct label *qlabel) 1341eb320b0eSRobert Watson { 1342eb320b0eSRobert Watson 1343eb320b0eSRobert Watson /* NOOP: we only accept matching labels, so no need to update */ 1344eb320b0eSRobert Watson } 1345eb320b0eSRobert Watson 1346a557af22SRobert Watson static int 13473f1a7a90SRobert Watson lomac_kld_check_load(struct ucred *cred, struct vnode *vp, 134878007886SRobert Watson struct label *vplabel) 1349db2661ceSRobert Watson { 1350db2661ceSRobert Watson struct mac_lomac *subj, *obj; 1351db2661ceSRobert Watson 13523f1a7a90SRobert Watson if (!lomac_enabled) 1353db2661ceSRobert Watson return (0); 1354db2661ceSRobert Watson 1355eca8a663SRobert Watson subj = SLOT(cred->cr_label); 135678007886SRobert Watson obj = SLOT(vplabel); 1357db2661ceSRobert Watson 13583f1a7a90SRobert Watson if (lomac_subject_privileged(subj)) 1359db2661ceSRobert Watson return (EPERM); 1360db2661ceSRobert Watson 13613f1a7a90SRobert Watson if (!lomac_high_single(obj)) 1362db2661ceSRobert Watson return (EACCES); 1363db2661ceSRobert Watson 1364db2661ceSRobert Watson return (0); 1365db2661ceSRobert Watson } 1366db2661ceSRobert Watson 1367eb320b0eSRobert Watson static void 1368eb320b0eSRobert Watson lomac_mount_create(struct ucred *cred, struct mount *mp, 1369eb320b0eSRobert Watson struct label *mplabel) 1370eb320b0eSRobert Watson { 1371eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1372eb320b0eSRobert Watson 1373eb320b0eSRobert Watson source = SLOT(cred->cr_label); 1374eb320b0eSRobert Watson dest = SLOT(mplabel); 1375eb320b0eSRobert Watson lomac_copy_single(source, dest); 1376eb320b0eSRobert Watson } 1377eb320b0eSRobert Watson 1378eb320b0eSRobert Watson static void 1379eb320b0eSRobert Watson lomac_netatalk_aarp_send(struct ifnet *ifp, struct label *ifplabel, 1380eb320b0eSRobert Watson struct mbuf *m, struct label *mlabel) 1381eb320b0eSRobert Watson { 1382eb320b0eSRobert Watson struct mac_lomac *dest; 1383eb320b0eSRobert Watson 1384eb320b0eSRobert Watson dest = SLOT(mlabel); 1385eb320b0eSRobert Watson 1386eb320b0eSRobert Watson lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0); 1387eb320b0eSRobert Watson } 1388eb320b0eSRobert Watson 1389eb320b0eSRobert Watson static void 1390eb320b0eSRobert Watson lomac_netinet_arp_send(struct ifnet *ifp, struct label *ifplabel, 1391eb320b0eSRobert Watson struct mbuf *m, struct label *mlabel) 1392eb320b0eSRobert Watson { 1393eb320b0eSRobert Watson struct mac_lomac *dest; 1394eb320b0eSRobert Watson 1395eb320b0eSRobert Watson dest = SLOT(mlabel); 1396eb320b0eSRobert Watson 1397eb320b0eSRobert Watson lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0); 1398eb320b0eSRobert Watson } 1399eb320b0eSRobert Watson 1400eb320b0eSRobert Watson static void 1401eb320b0eSRobert Watson lomac_netinet_firewall_reply(struct mbuf *mrecv, struct label *mrecvlabel, 1402eb320b0eSRobert Watson struct mbuf *msend, struct label *msendlabel) 1403eb320b0eSRobert Watson { 1404eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1405eb320b0eSRobert Watson 1406eb320b0eSRobert Watson source = SLOT(mrecvlabel); 1407eb320b0eSRobert Watson dest = SLOT(msendlabel); 1408eb320b0eSRobert Watson 1409eb320b0eSRobert Watson lomac_copy_single(source, dest); 1410eb320b0eSRobert Watson } 1411eb320b0eSRobert Watson 1412eb320b0eSRobert Watson static void 1413eb320b0eSRobert Watson lomac_netinet_firewall_send(struct mbuf *m, struct label *mlabel) 1414eb320b0eSRobert Watson { 1415eb320b0eSRobert Watson struct mac_lomac *dest; 1416eb320b0eSRobert Watson 1417eb320b0eSRobert Watson dest = SLOT(mlabel); 1418eb320b0eSRobert Watson 1419eb320b0eSRobert Watson /* XXX: where is the label for the firewall really comming from? */ 1420eb320b0eSRobert Watson lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0); 1421eb320b0eSRobert Watson } 1422eb320b0eSRobert Watson 1423eb320b0eSRobert Watson static void 1424eb320b0eSRobert Watson lomac_netinet_fragment(struct mbuf *m, struct label *mlabel, 1425eb320b0eSRobert Watson struct mbuf *frag, struct label *fraglabel) 1426eb320b0eSRobert Watson { 1427eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1428eb320b0eSRobert Watson 1429eb320b0eSRobert Watson source = SLOT(mlabel); 1430eb320b0eSRobert Watson dest = SLOT(fraglabel); 1431eb320b0eSRobert Watson 1432eb320b0eSRobert Watson lomac_copy_single(source, dest); 1433eb320b0eSRobert Watson } 1434eb320b0eSRobert Watson 1435eb320b0eSRobert Watson static void 1436eb320b0eSRobert Watson lomac_netinet_icmp_reply(struct mbuf *mrecv, struct label *mrecvlabel, 1437eb320b0eSRobert Watson struct mbuf *msend, struct label *msendlabel) 1438eb320b0eSRobert Watson { 1439eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1440eb320b0eSRobert Watson 1441eb320b0eSRobert Watson source = SLOT(mrecvlabel); 1442eb320b0eSRobert Watson dest = SLOT(msendlabel); 1443eb320b0eSRobert Watson 1444eb320b0eSRobert Watson lomac_copy_single(source, dest); 1445eb320b0eSRobert Watson } 1446eb320b0eSRobert Watson 1447eb320b0eSRobert Watson static void 1448eb320b0eSRobert Watson lomac_netinet_igmp_send(struct ifnet *ifp, struct label *ifplabel, 1449eb320b0eSRobert Watson struct mbuf *m, struct label *mlabel) 1450eb320b0eSRobert Watson { 1451eb320b0eSRobert Watson struct mac_lomac *dest; 1452eb320b0eSRobert Watson 1453eb320b0eSRobert Watson dest = SLOT(mlabel); 1454eb320b0eSRobert Watson 1455eb320b0eSRobert Watson lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0); 1456eb320b0eSRobert Watson } 1457eb320b0eSRobert Watson 1458eb320b0eSRobert Watson static void 1459eb320b0eSRobert Watson lomac_netinet6_nd6_send(struct ifnet *ifp, struct label *ifplabel, 1460eb320b0eSRobert Watson struct mbuf *m, struct label *mlabel) 1461eb320b0eSRobert Watson { 1462eb320b0eSRobert Watson struct mac_lomac *dest; 1463eb320b0eSRobert Watson 1464eb320b0eSRobert Watson dest = SLOT(mlabel); 1465eb320b0eSRobert Watson 1466eb320b0eSRobert Watson lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0); 1467eb320b0eSRobert Watson } 1468eb320b0eSRobert Watson 1469db2661ceSRobert Watson static int 14703f1a7a90SRobert Watson lomac_pipe_check_ioctl(struct ucred *cred, struct pipepair *pp, 147178007886SRobert Watson struct label *pplabel, unsigned long cmd, void /* caddr_t */ *data) 1472db2661ceSRobert Watson { 1473db2661ceSRobert Watson 14743f1a7a90SRobert Watson if (!lomac_enabled) 1475db2661ceSRobert Watson return (0); 1476db2661ceSRobert Watson 1477db2661ceSRobert Watson /* XXX: This will be implemented soon... */ 1478db2661ceSRobert Watson 1479db2661ceSRobert Watson return (0); 1480db2661ceSRobert Watson } 1481db2661ceSRobert Watson 1482db2661ceSRobert Watson static int 14833f1a7a90SRobert Watson lomac_pipe_check_read(struct ucred *cred, struct pipepair *pp, 148478007886SRobert Watson struct label *pplabel) 1485db2661ceSRobert Watson { 1486db2661ceSRobert Watson struct mac_lomac *subj, *obj; 1487db2661ceSRobert Watson 14883f1a7a90SRobert Watson if (!lomac_enabled) 1489db2661ceSRobert Watson return (0); 1490db2661ceSRobert Watson 1491eca8a663SRobert Watson subj = SLOT(cred->cr_label); 149278007886SRobert Watson obj = SLOT(pplabel); 1493db2661ceSRobert Watson 14943f1a7a90SRobert Watson if (!lomac_dominate_single(obj, subj)) 1495db2661ceSRobert Watson return (maybe_demote(subj, obj, "reading", "pipe", NULL)); 1496db2661ceSRobert Watson 1497db2661ceSRobert Watson return (0); 1498db2661ceSRobert Watson } 1499db2661ceSRobert Watson 1500db2661ceSRobert Watson static int 15013f1a7a90SRobert Watson lomac_pipe_check_relabel(struct ucred *cred, struct pipepair *pp, 150278007886SRobert Watson struct label *pplabel, struct label *newlabel) 1503db2661ceSRobert Watson { 1504db2661ceSRobert Watson struct mac_lomac *subj, *obj, *new; 1505db2661ceSRobert Watson int error; 1506db2661ceSRobert Watson 1507db2661ceSRobert Watson new = SLOT(newlabel); 1508eca8a663SRobert Watson subj = SLOT(cred->cr_label); 150978007886SRobert Watson obj = SLOT(pplabel); 1510db2661ceSRobert Watson 1511db2661ceSRobert Watson /* 15123f1a7a90SRobert Watson * If there is a LOMAC label update for a pipe, it must be a single 15133f1a7a90SRobert Watson * update. 1514db2661ceSRobert Watson */ 1515db2661ceSRobert Watson error = lomac_atmostflags(new, MAC_LOMAC_FLAG_SINGLE); 1516db2661ceSRobert Watson if (error) 1517db2661ceSRobert Watson return (error); 1518db2661ceSRobert Watson 1519db2661ceSRobert Watson /* 1520db2661ceSRobert Watson * To perform a relabel of a pipe (LOMAC label or not), LOMAC must 1521db2661ceSRobert Watson * authorize the relabel. 1522db2661ceSRobert Watson */ 15233f1a7a90SRobert Watson if (!lomac_single_in_range(obj, subj)) 1524db2661ceSRobert Watson return (EPERM); 1525db2661ceSRobert Watson 1526db2661ceSRobert Watson /* 1527db2661ceSRobert Watson * If the LOMAC label is to be changed, authorize as appropriate. 1528db2661ceSRobert Watson */ 1529db2661ceSRobert Watson if (new->ml_flags & MAC_LOMAC_FLAG_SINGLE) { 1530db2661ceSRobert Watson /* 1531db2661ceSRobert Watson * To change the LOMAC label on a pipe, the new pipe label 1532db2661ceSRobert Watson * must be in the subject range. 1533db2661ceSRobert Watson */ 15343f1a7a90SRobert Watson if (!lomac_single_in_range(new, subj)) 1535db2661ceSRobert Watson return (EPERM); 1536db2661ceSRobert Watson 1537db2661ceSRobert Watson /* 1538db2661ceSRobert Watson * To change the LOMAC label on a pipe to be EQUAL, the 1539db2661ceSRobert Watson * subject must have appropriate privilege. 1540db2661ceSRobert Watson */ 15413f1a7a90SRobert Watson if (lomac_contains_equal(new)) { 15423f1a7a90SRobert Watson error = lomac_subject_privileged(subj); 1543db2661ceSRobert Watson if (error) 1544db2661ceSRobert Watson return (error); 1545db2661ceSRobert Watson } 1546db2661ceSRobert Watson } 1547db2661ceSRobert Watson 1548db2661ceSRobert Watson return (0); 1549db2661ceSRobert Watson } 1550db2661ceSRobert Watson 1551db2661ceSRobert Watson static int 15523f1a7a90SRobert Watson lomac_pipe_check_write(struct ucred *cred, struct pipepair *pp, 155378007886SRobert Watson struct label *pplabel) 1554db2661ceSRobert Watson { 1555db2661ceSRobert Watson struct mac_lomac *subj, *obj; 1556db2661ceSRobert Watson 15573f1a7a90SRobert Watson if (!lomac_enabled) 1558db2661ceSRobert Watson return (0); 1559db2661ceSRobert Watson 1560eca8a663SRobert Watson subj = SLOT(cred->cr_label); 156178007886SRobert Watson obj = SLOT(pplabel); 1562db2661ceSRobert Watson 15633f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 1564db2661ceSRobert Watson return (EACCES); 1565db2661ceSRobert Watson 1566db2661ceSRobert Watson return (0); 1567db2661ceSRobert Watson } 1568db2661ceSRobert Watson 1569eb320b0eSRobert Watson static void 1570eb320b0eSRobert Watson lomac_pipe_create(struct ucred *cred, struct pipepair *pp, 1571eb320b0eSRobert Watson struct label *pplabel) 1572db2661ceSRobert Watson { 1573eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1574db2661ceSRobert Watson 1575eb320b0eSRobert Watson source = SLOT(cred->cr_label); 1576eb320b0eSRobert Watson dest = SLOT(pplabel); 1577db2661ceSRobert Watson 1578eb320b0eSRobert Watson lomac_copy_single(source, dest); 1579db2661ceSRobert Watson } 1580db2661ceSRobert Watson 1581eb320b0eSRobert Watson static void 1582eb320b0eSRobert Watson lomac_pipe_relabel(struct ucred *cred, struct pipepair *pp, 1583eb320b0eSRobert Watson struct label *pplabel, struct label *newlabel) 1584db2661ceSRobert Watson { 1585eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1586db2661ceSRobert Watson 1587eb320b0eSRobert Watson source = SLOT(newlabel); 1588eb320b0eSRobert Watson dest = SLOT(pplabel); 1589db2661ceSRobert Watson 1590eb320b0eSRobert Watson try_relabel(source, dest); 1591db2661ceSRobert Watson } 1592db2661ceSRobert Watson 1593c14d15aeSRobert Watson /* 1594c14d15aeSRobert Watson * Some system privileges are allowed regardless of integrity grade; others 1595c14d15aeSRobert Watson * are allowed only when running with privilege with respect to the LOMAC 1596c14d15aeSRobert Watson * policy as they might otherwise allow bypassing of the integrity policy. 1597c14d15aeSRobert Watson */ 1598c14d15aeSRobert Watson static int 15993f1a7a90SRobert Watson lomac_priv_check(struct ucred *cred, int priv) 1600c14d15aeSRobert Watson { 1601c14d15aeSRobert Watson struct mac_lomac *subj; 1602c14d15aeSRobert Watson int error; 1603c14d15aeSRobert Watson 16043f1a7a90SRobert Watson if (!lomac_enabled) 1605c14d15aeSRobert Watson return (0); 1606c14d15aeSRobert Watson 1607c14d15aeSRobert Watson /* 1608c14d15aeSRobert Watson * Exempt only specific privileges from the LOMAC integrity policy. 1609c14d15aeSRobert Watson */ 1610c14d15aeSRobert Watson switch (priv) { 1611c14d15aeSRobert Watson case PRIV_KTRACE: 1612c14d15aeSRobert Watson case PRIV_MSGBUF: 1613c14d15aeSRobert Watson 1614c14d15aeSRobert Watson /* 1615c14d15aeSRobert Watson * Allow processes to manipulate basic process audit properties, and 1616c14d15aeSRobert Watson * to submit audit records. 1617c14d15aeSRobert Watson */ 1618c14d15aeSRobert Watson case PRIV_AUDIT_GETAUDIT: 1619c14d15aeSRobert Watson case PRIV_AUDIT_SETAUDIT: 1620c14d15aeSRobert Watson case PRIV_AUDIT_SUBMIT: 1621c14d15aeSRobert Watson 1622c14d15aeSRobert Watson /* 1623c14d15aeSRobert Watson * Allow processes to manipulate their regular UNIX credentials. 1624c14d15aeSRobert Watson */ 1625c14d15aeSRobert Watson case PRIV_CRED_SETUID: 1626c14d15aeSRobert Watson case PRIV_CRED_SETEUID: 1627c14d15aeSRobert Watson case PRIV_CRED_SETGID: 1628c14d15aeSRobert Watson case PRIV_CRED_SETEGID: 1629c14d15aeSRobert Watson case PRIV_CRED_SETGROUPS: 1630c14d15aeSRobert Watson case PRIV_CRED_SETREUID: 1631c14d15aeSRobert Watson case PRIV_CRED_SETREGID: 1632c14d15aeSRobert Watson case PRIV_CRED_SETRESUID: 1633c14d15aeSRobert Watson case PRIV_CRED_SETRESGID: 1634c14d15aeSRobert Watson 1635c14d15aeSRobert Watson /* 1636c14d15aeSRobert Watson * Allow processes to perform system monitoring. 1637c14d15aeSRobert Watson */ 1638c14d15aeSRobert Watson case PRIV_SEEOTHERGIDS: 1639c14d15aeSRobert Watson case PRIV_SEEOTHERUIDS: 1640c14d15aeSRobert Watson break; 1641c14d15aeSRobert Watson 1642c14d15aeSRobert Watson /* 1643c14d15aeSRobert Watson * Allow access to general process debugging facilities. We 1644c14d15aeSRobert Watson * separately control debugging based on MAC label. 1645c14d15aeSRobert Watson */ 1646c14d15aeSRobert Watson case PRIV_DEBUG_DIFFCRED: 1647c14d15aeSRobert Watson case PRIV_DEBUG_SUGID: 1648c14d15aeSRobert Watson case PRIV_DEBUG_UNPRIV: 1649c14d15aeSRobert Watson 1650c14d15aeSRobert Watson /* 1651c14d15aeSRobert Watson * Allow manipulating jails. 1652c14d15aeSRobert Watson */ 1653c14d15aeSRobert Watson case PRIV_JAIL_ATTACH: 1654c14d15aeSRobert Watson 1655c14d15aeSRobert Watson /* 1656c14d15aeSRobert Watson * Allow privilege with respect to the Partition policy, but not the 1657c14d15aeSRobert Watson * Privs policy. 1658c14d15aeSRobert Watson */ 1659c14d15aeSRobert Watson case PRIV_MAC_PARTITION: 1660c14d15aeSRobert Watson 1661c14d15aeSRobert Watson /* 1662c14d15aeSRobert Watson * Allow privilege with respect to process resource limits and login 1663c14d15aeSRobert Watson * context. 1664c14d15aeSRobert Watson */ 1665c14d15aeSRobert Watson case PRIV_PROC_LIMIT: 1666c14d15aeSRobert Watson case PRIV_PROC_SETLOGIN: 1667c14d15aeSRobert Watson case PRIV_PROC_SETRLIMIT: 1668c14d15aeSRobert Watson 1669c14d15aeSRobert Watson /* 1670c14d15aeSRobert Watson * Allow System V and POSIX IPC privileges. 1671c14d15aeSRobert Watson */ 1672c14d15aeSRobert Watson case PRIV_IPC_READ: 1673c14d15aeSRobert Watson case PRIV_IPC_WRITE: 1674c14d15aeSRobert Watson case PRIV_IPC_ADMIN: 1675c14d15aeSRobert Watson case PRIV_IPC_MSGSIZE: 1676c14d15aeSRobert Watson case PRIV_MQ_ADMIN: 1677c14d15aeSRobert Watson 1678c14d15aeSRobert Watson /* 1679c14d15aeSRobert Watson * Allow certain scheduler manipulations -- possibly this should be 1680c14d15aeSRobert Watson * controlled by more fine-grained policy, as potentially low 1681c14d15aeSRobert Watson * integrity processes can deny CPU to higher integrity ones. 1682c14d15aeSRobert Watson */ 1683c14d15aeSRobert Watson case PRIV_SCHED_DIFFCRED: 1684c14d15aeSRobert Watson case PRIV_SCHED_SETPRIORITY: 1685c14d15aeSRobert Watson case PRIV_SCHED_RTPRIO: 1686c14d15aeSRobert Watson case PRIV_SCHED_SETPOLICY: 1687c14d15aeSRobert Watson case PRIV_SCHED_SET: 1688c14d15aeSRobert Watson case PRIV_SCHED_SETPARAM: 1689c14d15aeSRobert Watson 1690c14d15aeSRobert Watson /* 1691c14d15aeSRobert Watson * More IPC privileges. 1692c14d15aeSRobert Watson */ 1693c14d15aeSRobert Watson case PRIV_SEM_WRITE: 1694c14d15aeSRobert Watson 1695c14d15aeSRobert Watson /* 1696c14d15aeSRobert Watson * Allow signaling privileges subject to integrity policy. 1697c14d15aeSRobert Watson */ 1698c14d15aeSRobert Watson case PRIV_SIGNAL_DIFFCRED: 1699c14d15aeSRobert Watson case PRIV_SIGNAL_SUGID: 1700c14d15aeSRobert Watson 1701c14d15aeSRobert Watson /* 1702c14d15aeSRobert Watson * Allow access to only limited sysctls from lower integrity levels; 1703c14d15aeSRobert Watson * piggy-back on the Jail definition. 1704c14d15aeSRobert Watson */ 1705c14d15aeSRobert Watson case PRIV_SYSCTL_WRITEJAIL: 1706c14d15aeSRobert Watson 1707c14d15aeSRobert Watson /* 1708c14d15aeSRobert Watson * Allow TTY-based privileges, subject to general device access using 1709c14d15aeSRobert Watson * labels on TTY device nodes, but not console privilege. 1710c14d15aeSRobert Watson */ 1711c14d15aeSRobert Watson case PRIV_TTY_DRAINWAIT: 1712c14d15aeSRobert Watson case PRIV_TTY_DTRWAIT: 1713c14d15aeSRobert Watson case PRIV_TTY_EXCLUSIVE: 1714c14d15aeSRobert Watson case PRIV_TTY_PRISON: 1715c14d15aeSRobert Watson case PRIV_TTY_STI: 1716c14d15aeSRobert Watson case PRIV_TTY_SETA: 1717c14d15aeSRobert Watson 1718c14d15aeSRobert Watson /* 1719c14d15aeSRobert Watson * Grant most VFS privileges, as almost all are in practice bounded 1720c14d15aeSRobert Watson * by more specific checks using labels. 1721c14d15aeSRobert Watson */ 1722c14d15aeSRobert Watson case PRIV_VFS_READ: 1723c14d15aeSRobert Watson case PRIV_VFS_WRITE: 1724c14d15aeSRobert Watson case PRIV_VFS_ADMIN: 1725c14d15aeSRobert Watson case PRIV_VFS_EXEC: 1726c14d15aeSRobert Watson case PRIV_VFS_LOOKUP: 1727c14d15aeSRobert Watson case PRIV_VFS_CHFLAGS_DEV: 1728c14d15aeSRobert Watson case PRIV_VFS_CHOWN: 1729c14d15aeSRobert Watson case PRIV_VFS_CHROOT: 1730c14d15aeSRobert Watson case PRIV_VFS_RETAINSUGID: 1731c14d15aeSRobert Watson case PRIV_VFS_EXCEEDQUOTA: 1732c14d15aeSRobert Watson case PRIV_VFS_FCHROOT: 1733c14d15aeSRobert Watson case PRIV_VFS_FHOPEN: 1734c14d15aeSRobert Watson case PRIV_VFS_FHSTATFS: 1735c14d15aeSRobert Watson case PRIV_VFS_GENERATION: 1736c14d15aeSRobert Watson case PRIV_VFS_GETFH: 1737c14d15aeSRobert Watson case PRIV_VFS_GETQUOTA: 1738c14d15aeSRobert Watson case PRIV_VFS_LINK: 1739c14d15aeSRobert Watson case PRIV_VFS_MOUNT: 1740c14d15aeSRobert Watson case PRIV_VFS_MOUNT_OWNER: 1741c14d15aeSRobert Watson case PRIV_VFS_MOUNT_PERM: 1742c14d15aeSRobert Watson case PRIV_VFS_MOUNT_SUIDDIR: 1743c14d15aeSRobert Watson case PRIV_VFS_MOUNT_NONUSER: 1744c14d15aeSRobert Watson case PRIV_VFS_SETGID: 1745c14d15aeSRobert Watson case PRIV_VFS_STICKYFILE: 1746c14d15aeSRobert Watson case PRIV_VFS_SYSFLAGS: 1747c14d15aeSRobert Watson case PRIV_VFS_UNMOUNT: 1748c14d15aeSRobert Watson 1749c14d15aeSRobert Watson /* 1750c14d15aeSRobert Watson * Allow VM privileges; it would be nice if these were subject to 1751c14d15aeSRobert Watson * resource limits. 1752c14d15aeSRobert Watson */ 1753c14d15aeSRobert Watson case PRIV_VM_MADV_PROTECT: 1754c14d15aeSRobert Watson case PRIV_VM_MLOCK: 1755c14d15aeSRobert Watson case PRIV_VM_MUNLOCK: 1756c14d15aeSRobert Watson 1757c14d15aeSRobert Watson /* 1758c14d15aeSRobert Watson * Allow some but not all network privileges. In general, dont allow 1759c14d15aeSRobert Watson * reconfiguring the network stack, just normal use. 1760c14d15aeSRobert Watson */ 1761c14d15aeSRobert Watson case PRIV_NETATALK_RESERVEDPORT: 1762c14d15aeSRobert Watson case PRIV_NETINET_RESERVEDPORT: 1763c14d15aeSRobert Watson case PRIV_NETINET_RAW: 1764c14d15aeSRobert Watson case PRIV_NETINET_REUSEPORT: 1765c14d15aeSRobert Watson case PRIV_NETIPX_RESERVEDPORT: 1766c14d15aeSRobert Watson case PRIV_NETIPX_RAW: 1767c14d15aeSRobert Watson break; 1768c14d15aeSRobert Watson 1769c14d15aeSRobert Watson /* 1770c14d15aeSRobert Watson * All remaining system privileges are allow only if the process 1771c14d15aeSRobert Watson * holds privilege with respect to the LOMAC policy. 1772c14d15aeSRobert Watson */ 1773c14d15aeSRobert Watson default: 1774c14d15aeSRobert Watson subj = SLOT(cred->cr_label); 17753f1a7a90SRobert Watson error = lomac_subject_privileged(subj); 1776c14d15aeSRobert Watson if (error) 1777c14d15aeSRobert Watson return (error); 1778c14d15aeSRobert Watson } 1779c14d15aeSRobert Watson return (0); 1780c14d15aeSRobert Watson } 1781c14d15aeSRobert Watson 1782eb320b0eSRobert Watson static int 1783eb320b0eSRobert Watson lomac_proc_check_debug(struct ucred *cred, struct proc *p) 1784eb320b0eSRobert Watson { 1785eb320b0eSRobert Watson struct mac_lomac *subj, *obj; 1786eb320b0eSRobert Watson 1787eb320b0eSRobert Watson if (!lomac_enabled) 1788eb320b0eSRobert Watson return (0); 1789eb320b0eSRobert Watson 1790eb320b0eSRobert Watson subj = SLOT(cred->cr_label); 1791eb320b0eSRobert Watson obj = SLOT(p->p_ucred->cr_label); 1792eb320b0eSRobert Watson 1793eb320b0eSRobert Watson /* XXX: range checks */ 1794eb320b0eSRobert Watson if (!lomac_dominate_single(obj, subj)) 1795eb320b0eSRobert Watson return (ESRCH); 1796eb320b0eSRobert Watson if (!lomac_subject_dominate(subj, obj)) 1797eb320b0eSRobert Watson return (EACCES); 1798eb320b0eSRobert Watson 1799eb320b0eSRobert Watson return (0); 1800eb320b0eSRobert Watson } 1801eb320b0eSRobert Watson 1802eb320b0eSRobert Watson static int 1803eb320b0eSRobert Watson lomac_proc_check_sched(struct ucred *cred, struct proc *p) 1804eb320b0eSRobert Watson { 1805eb320b0eSRobert Watson struct mac_lomac *subj, *obj; 1806eb320b0eSRobert Watson 1807eb320b0eSRobert Watson if (!lomac_enabled) 1808eb320b0eSRobert Watson return (0); 1809eb320b0eSRobert Watson 1810eb320b0eSRobert Watson subj = SLOT(cred->cr_label); 1811eb320b0eSRobert Watson obj = SLOT(p->p_ucred->cr_label); 1812eb320b0eSRobert Watson 1813eb320b0eSRobert Watson /* XXX: range checks */ 1814eb320b0eSRobert Watson if (!lomac_dominate_single(obj, subj)) 1815eb320b0eSRobert Watson return (ESRCH); 1816eb320b0eSRobert Watson if (!lomac_subject_dominate(subj, obj)) 1817eb320b0eSRobert Watson return (EACCES); 1818eb320b0eSRobert Watson 1819eb320b0eSRobert Watson return (0); 1820eb320b0eSRobert Watson } 1821eb320b0eSRobert Watson 1822eb320b0eSRobert Watson static int 1823eb320b0eSRobert Watson lomac_proc_check_signal(struct ucred *cred, struct proc *p, int signum) 1824eb320b0eSRobert Watson { 1825eb320b0eSRobert Watson struct mac_lomac *subj, *obj; 1826eb320b0eSRobert Watson 1827eb320b0eSRobert Watson if (!lomac_enabled) 1828eb320b0eSRobert Watson return (0); 1829eb320b0eSRobert Watson 1830eb320b0eSRobert Watson subj = SLOT(cred->cr_label); 1831eb320b0eSRobert Watson obj = SLOT(p->p_ucred->cr_label); 1832eb320b0eSRobert Watson 1833eb320b0eSRobert Watson /* XXX: range checks */ 1834eb320b0eSRobert Watson if (!lomac_dominate_single(obj, subj)) 1835eb320b0eSRobert Watson return (ESRCH); 1836eb320b0eSRobert Watson if (!lomac_subject_dominate(subj, obj)) 1837eb320b0eSRobert Watson return (EACCES); 1838eb320b0eSRobert Watson 1839eb320b0eSRobert Watson return (0); 1840eb320b0eSRobert Watson } 1841eb320b0eSRobert Watson 1842eb320b0eSRobert Watson static void 1843eb320b0eSRobert Watson lomac_proc_create_init(struct ucred *cred) 1844eb320b0eSRobert Watson { 1845eb320b0eSRobert Watson struct mac_lomac *dest; 1846eb320b0eSRobert Watson 1847eb320b0eSRobert Watson dest = SLOT(cred->cr_label); 1848eb320b0eSRobert Watson 1849eb320b0eSRobert Watson lomac_set_single(dest, MAC_LOMAC_TYPE_HIGH, 0); 1850eb320b0eSRobert Watson lomac_set_range(dest, MAC_LOMAC_TYPE_LOW, 0, MAC_LOMAC_TYPE_HIGH, 0); 1851eb320b0eSRobert Watson } 1852eb320b0eSRobert Watson 1853eb320b0eSRobert Watson static void 1854eb320b0eSRobert Watson lomac_proc_create_swapper(struct ucred *cred) 1855eb320b0eSRobert Watson { 1856eb320b0eSRobert Watson struct mac_lomac *dest; 1857eb320b0eSRobert Watson 1858eb320b0eSRobert Watson dest = SLOT(cred->cr_label); 1859eb320b0eSRobert Watson 1860eb320b0eSRobert Watson lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0); 1861eb320b0eSRobert Watson lomac_set_range(dest, MAC_LOMAC_TYPE_LOW, 0, MAC_LOMAC_TYPE_HIGH, 0); 1862eb320b0eSRobert Watson } 1863eb320b0eSRobert Watson 1864eb320b0eSRobert Watson static void 1865eb320b0eSRobert Watson lomac_proc_destroy_label(struct label *label) 1866eb320b0eSRobert Watson { 1867eb320b0eSRobert Watson 1868eb320b0eSRobert Watson mtx_destroy(&PSLOT(label)->mtx); 18691ede983cSDag-Erling Smørgrav free(PSLOT(label), M_LOMAC); 1870eb320b0eSRobert Watson PSLOT_SET(label, NULL); 1871eb320b0eSRobert Watson } 1872eb320b0eSRobert Watson 1873eb320b0eSRobert Watson static void 1874eb320b0eSRobert Watson lomac_proc_init_label(struct label *label) 1875eb320b0eSRobert Watson { 1876eb320b0eSRobert Watson 1877eb320b0eSRobert Watson PSLOT_SET(label, malloc(sizeof(struct mac_lomac_proc), M_LOMAC, 1878eb320b0eSRobert Watson M_ZERO | M_WAITOK)); 1879eb320b0eSRobert Watson mtx_init(&PSLOT(label)->mtx, "MAC/Lomac proc lock", NULL, MTX_DEF); 1880eb320b0eSRobert Watson } 1881eb320b0eSRobert Watson 1882eb320b0eSRobert Watson static int 1883eb320b0eSRobert Watson lomac_socket_check_deliver(struct socket *so, struct label *solabel, 1884eb320b0eSRobert Watson struct mbuf *m, struct label *mlabel) 1885eb320b0eSRobert Watson { 1886eb320b0eSRobert Watson struct mac_lomac *p, *s; 1887eb320b0eSRobert Watson 1888eb320b0eSRobert Watson if (!lomac_enabled) 1889eb320b0eSRobert Watson return (0); 1890eb320b0eSRobert Watson 1891eb320b0eSRobert Watson p = SLOT(mlabel); 1892eb320b0eSRobert Watson s = SLOT(solabel); 1893eb320b0eSRobert Watson 1894eb320b0eSRobert Watson return (lomac_equal_single(p, s) ? 0 : EACCES); 1895eb320b0eSRobert Watson } 1896eb320b0eSRobert Watson 1897eb320b0eSRobert Watson static int 1898eb320b0eSRobert Watson lomac_socket_check_relabel(struct ucred *cred, struct socket *so, 1899eb320b0eSRobert Watson struct label *solabel, struct label *newlabel) 1900eb320b0eSRobert Watson { 1901eb320b0eSRobert Watson struct mac_lomac *subj, *obj, *new; 1902eb320b0eSRobert Watson int error; 1903eb320b0eSRobert Watson 1904eb320b0eSRobert Watson new = SLOT(newlabel); 1905eb320b0eSRobert Watson subj = SLOT(cred->cr_label); 1906eb320b0eSRobert Watson obj = SLOT(solabel); 1907eb320b0eSRobert Watson 1908eb320b0eSRobert Watson /* 1909eb320b0eSRobert Watson * If there is a LOMAC label update for the socket, it may be an 1910eb320b0eSRobert Watson * update of single. 1911eb320b0eSRobert Watson */ 1912eb320b0eSRobert Watson error = lomac_atmostflags(new, MAC_LOMAC_FLAG_SINGLE); 1913eb320b0eSRobert Watson if (error) 1914eb320b0eSRobert Watson return (error); 1915eb320b0eSRobert Watson 1916eb320b0eSRobert Watson /* 1917eb320b0eSRobert Watson * To relabel a socket, the old socket single must be in the subject 1918eb320b0eSRobert Watson * range. 1919eb320b0eSRobert Watson */ 1920eb320b0eSRobert Watson if (!lomac_single_in_range(obj, subj)) 1921eb320b0eSRobert Watson return (EPERM); 1922eb320b0eSRobert Watson 1923eb320b0eSRobert Watson /* 1924eb320b0eSRobert Watson * If the LOMAC label is to be changed, authorize as appropriate. 1925eb320b0eSRobert Watson */ 1926eb320b0eSRobert Watson if (new->ml_flags & MAC_LOMAC_FLAG_SINGLE) { 1927eb320b0eSRobert Watson /* 1928eb320b0eSRobert Watson * To relabel a socket, the new socket single must be in the 1929eb320b0eSRobert Watson * subject range. 1930eb320b0eSRobert Watson */ 1931eb320b0eSRobert Watson if (!lomac_single_in_range(new, subj)) 1932eb320b0eSRobert Watson return (EPERM); 1933eb320b0eSRobert Watson 1934eb320b0eSRobert Watson /* 1935eb320b0eSRobert Watson * To change the LOMAC label on the socket to contain EQUAL, 1936eb320b0eSRobert Watson * the subject must have appropriate privilege. 1937eb320b0eSRobert Watson */ 1938eb320b0eSRobert Watson if (lomac_contains_equal(new)) { 1939eb320b0eSRobert Watson error = lomac_subject_privileged(subj); 1940eb320b0eSRobert Watson if (error) 1941eb320b0eSRobert Watson return (error); 1942eb320b0eSRobert Watson } 1943eb320b0eSRobert Watson } 1944eb320b0eSRobert Watson 1945eb320b0eSRobert Watson return (0); 1946eb320b0eSRobert Watson } 1947eb320b0eSRobert Watson 1948eb320b0eSRobert Watson static int 1949eb320b0eSRobert Watson lomac_socket_check_visible(struct ucred *cred, struct socket *so, 1950eb320b0eSRobert Watson struct label *solabel) 1951eb320b0eSRobert Watson { 1952eb320b0eSRobert Watson struct mac_lomac *subj, *obj; 1953eb320b0eSRobert Watson 1954eb320b0eSRobert Watson if (!lomac_enabled) 1955eb320b0eSRobert Watson return (0); 1956eb320b0eSRobert Watson 1957eb320b0eSRobert Watson subj = SLOT(cred->cr_label); 1958eb320b0eSRobert Watson obj = SLOT(solabel); 1959eb320b0eSRobert Watson 1960eb320b0eSRobert Watson if (!lomac_dominate_single(obj, subj)) 1961eb320b0eSRobert Watson return (ENOENT); 1962eb320b0eSRobert Watson 1963eb320b0eSRobert Watson return (0); 1964eb320b0eSRobert Watson } 1965eb320b0eSRobert Watson 1966eb320b0eSRobert Watson static void 1967eb320b0eSRobert Watson lomac_socket_create(struct ucred *cred, struct socket *so, 1968eb320b0eSRobert Watson struct label *solabel) 1969eb320b0eSRobert Watson { 1970eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1971eb320b0eSRobert Watson 1972eb320b0eSRobert Watson source = SLOT(cred->cr_label); 1973eb320b0eSRobert Watson dest = SLOT(solabel); 1974eb320b0eSRobert Watson 1975eb320b0eSRobert Watson lomac_copy_single(source, dest); 1976eb320b0eSRobert Watson } 1977eb320b0eSRobert Watson 1978eb320b0eSRobert Watson static void 1979eb320b0eSRobert Watson lomac_socket_create_mbuf(struct socket *so, struct label *solabel, 1980eb320b0eSRobert Watson struct mbuf *m, struct label *mlabel) 1981eb320b0eSRobert Watson { 1982eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1983eb320b0eSRobert Watson 1984eb320b0eSRobert Watson source = SLOT(solabel); 1985eb320b0eSRobert Watson dest = SLOT(mlabel); 1986eb320b0eSRobert Watson 1987eb320b0eSRobert Watson lomac_copy_single(source, dest); 1988eb320b0eSRobert Watson } 1989eb320b0eSRobert Watson 1990eb320b0eSRobert Watson static void 1991eb320b0eSRobert Watson lomac_socket_newconn(struct socket *oldso, struct label *oldsolabel, 1992eb320b0eSRobert Watson struct socket *newso, struct label *newsolabel) 1993eb320b0eSRobert Watson { 1994eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1995eb320b0eSRobert Watson 1996eb320b0eSRobert Watson source = SLOT(oldsolabel); 1997eb320b0eSRobert Watson dest = SLOT(newsolabel); 1998eb320b0eSRobert Watson 1999eb320b0eSRobert Watson lomac_copy_single(source, dest); 2000eb320b0eSRobert Watson } 2001eb320b0eSRobert Watson 2002eb320b0eSRobert Watson static void 2003eb320b0eSRobert Watson lomac_socket_relabel(struct ucred *cred, struct socket *so, 2004eb320b0eSRobert Watson struct label *solabel, struct label *newlabel) 2005eb320b0eSRobert Watson { 2006eb320b0eSRobert Watson struct mac_lomac *source, *dest; 2007eb320b0eSRobert Watson 2008eb320b0eSRobert Watson source = SLOT(newlabel); 2009eb320b0eSRobert Watson dest = SLOT(solabel); 2010eb320b0eSRobert Watson 2011eb320b0eSRobert Watson try_relabel(source, dest); 2012eb320b0eSRobert Watson } 2013eb320b0eSRobert Watson 2014eb320b0eSRobert Watson static void 2015eb320b0eSRobert Watson lomac_socketpeer_set_from_mbuf(struct mbuf *m, struct label *mlabel, 2016eb320b0eSRobert Watson struct socket *so, struct label *sopeerlabel) 2017eb320b0eSRobert Watson { 2018eb320b0eSRobert Watson struct mac_lomac *source, *dest; 2019eb320b0eSRobert Watson 2020eb320b0eSRobert Watson source = SLOT(mlabel); 2021eb320b0eSRobert Watson dest = SLOT(sopeerlabel); 2022eb320b0eSRobert Watson 2023eb320b0eSRobert Watson lomac_copy_single(source, dest); 2024eb320b0eSRobert Watson } 2025eb320b0eSRobert Watson 2026eb320b0eSRobert Watson static void 2027eb320b0eSRobert Watson lomac_socketpeer_set_from_socket(struct socket *oldso, 2028eb320b0eSRobert Watson struct label *oldsolabel, struct socket *newso, 2029eb320b0eSRobert Watson struct label *newsopeerlabel) 2030eb320b0eSRobert Watson { 2031eb320b0eSRobert Watson struct mac_lomac *source, *dest; 2032eb320b0eSRobert Watson 2033eb320b0eSRobert Watson source = SLOT(oldsolabel); 2034eb320b0eSRobert Watson dest = SLOT(newsopeerlabel); 2035eb320b0eSRobert Watson 2036eb320b0eSRobert Watson lomac_copy_single(source, dest); 2037eb320b0eSRobert Watson } 2038eb320b0eSRobert Watson 2039eb320b0eSRobert Watson static void 2040eb320b0eSRobert Watson lomac_syncache_create(struct label *label, struct inpcb *inp) 2041eb320b0eSRobert Watson { 2042eb320b0eSRobert Watson struct mac_lomac *source, *dest; 2043eb320b0eSRobert Watson 2044eb320b0eSRobert Watson source = SLOT(inp->inp_label); 2045eb320b0eSRobert Watson dest = SLOT(label); 2046eb320b0eSRobert Watson lomac_copy(source, dest); 2047eb320b0eSRobert Watson } 2048eb320b0eSRobert Watson 2049eb320b0eSRobert Watson static void 2050eb320b0eSRobert Watson lomac_syncache_create_mbuf(struct label *sc_label, struct mbuf *m, 2051eb320b0eSRobert Watson struct label *mlabel) 2052eb320b0eSRobert Watson { 2053eb320b0eSRobert Watson struct mac_lomac *source, *dest; 2054eb320b0eSRobert Watson 2055eb320b0eSRobert Watson source = SLOT(sc_label); 2056eb320b0eSRobert Watson dest = SLOT(mlabel); 2057eb320b0eSRobert Watson lomac_copy(source, dest); 2058eb320b0eSRobert Watson } 2059c14d15aeSRobert Watson 2060db2661ceSRobert Watson static int 20613f1a7a90SRobert Watson lomac_system_check_acct(struct ucred *cred, struct vnode *vp, 206278007886SRobert Watson struct label *vplabel) 206318717f69SRobert Watson { 206418717f69SRobert Watson struct mac_lomac *subj, *obj; 206518717f69SRobert Watson 20663f1a7a90SRobert Watson if (!lomac_enabled) 206718717f69SRobert Watson return (0); 206818717f69SRobert Watson 206918717f69SRobert Watson subj = SLOT(cred->cr_label); 207078007886SRobert Watson obj = SLOT(vplabel); 207118717f69SRobert Watson 20723f1a7a90SRobert Watson if (lomac_subject_privileged(subj)) 207318717f69SRobert Watson return (EPERM); 207418717f69SRobert Watson 20753f1a7a90SRobert Watson if (!lomac_high_single(obj)) 207618717f69SRobert Watson return (EACCES); 207718717f69SRobert Watson 207818717f69SRobert Watson return (0); 207918717f69SRobert Watson } 208018717f69SRobert Watson 208118717f69SRobert Watson static int 20823f1a7a90SRobert Watson lomac_system_check_auditctl(struct ucred *cred, struct vnode *vp, 208378007886SRobert Watson struct label *vplabel) 208418717f69SRobert Watson { 208518717f69SRobert Watson struct mac_lomac *subj, *obj; 208618717f69SRobert Watson 20873f1a7a90SRobert Watson if (!lomac_enabled) 208818717f69SRobert Watson return (0); 208918717f69SRobert Watson 209018717f69SRobert Watson subj = SLOT(cred->cr_label); 209178007886SRobert Watson obj = SLOT(vplabel); 209218717f69SRobert Watson 20933f1a7a90SRobert Watson if (lomac_subject_privileged(subj)) 209418717f69SRobert Watson return (EPERM); 209518717f69SRobert Watson 20963f1a7a90SRobert Watson if (!lomac_high_single(obj)) 209718717f69SRobert Watson return (EACCES); 209818717f69SRobert Watson 209918717f69SRobert Watson return (0); 210018717f69SRobert Watson } 210118717f69SRobert Watson 210218717f69SRobert Watson static int 21033f1a7a90SRobert Watson lomac_system_check_swapoff(struct ucred *cred, struct vnode *vp, 210478007886SRobert Watson struct label *vplabel) 210518717f69SRobert Watson { 210618717f69SRobert Watson struct mac_lomac *subj; 210718717f69SRobert Watson 21083f1a7a90SRobert Watson if (!lomac_enabled) 210918717f69SRobert Watson return (0); 211018717f69SRobert Watson 211118717f69SRobert Watson subj = SLOT(cred->cr_label); 211218717f69SRobert Watson 21133f1a7a90SRobert Watson if (lomac_subject_privileged(subj)) 211418717f69SRobert Watson return (EPERM); 211518717f69SRobert Watson 211618717f69SRobert Watson return (0); 211718717f69SRobert Watson } 211818717f69SRobert Watson 211918717f69SRobert Watson static int 21203f1a7a90SRobert Watson lomac_system_check_swapon(struct ucred *cred, struct vnode *vp, 212178007886SRobert Watson struct label *vplabel) 2122db2661ceSRobert Watson { 2123db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2124db2661ceSRobert Watson 21253f1a7a90SRobert Watson if (!lomac_enabled) 2126db2661ceSRobert Watson return (0); 2127db2661ceSRobert Watson 2128eca8a663SRobert Watson subj = SLOT(cred->cr_label); 212978007886SRobert Watson obj = SLOT(vplabel); 2130db2661ceSRobert Watson 21313f1a7a90SRobert Watson if (lomac_subject_privileged(subj)) 2132db2661ceSRobert Watson return (EPERM); 2133db2661ceSRobert Watson 21343f1a7a90SRobert Watson if (!lomac_high_single(obj)) 2135db2661ceSRobert Watson return (EACCES); 2136db2661ceSRobert Watson 2137db2661ceSRobert Watson return (0); 2138db2661ceSRobert Watson } 2139db2661ceSRobert Watson 2140db2661ceSRobert Watson static int 21413f1a7a90SRobert Watson lomac_system_check_sysctl(struct ucred *cred, struct sysctl_oid *oidp, 214263dba32bSPawel Jakub Dawidek void *arg1, int arg2, struct sysctl_req *req) 2143db2661ceSRobert Watson { 2144db2661ceSRobert Watson struct mac_lomac *subj; 2145db2661ceSRobert Watson 21463f1a7a90SRobert Watson if (!lomac_enabled) 2147db2661ceSRobert Watson return (0); 2148db2661ceSRobert Watson 2149eca8a663SRobert Watson subj = SLOT(cred->cr_label); 2150db2661ceSRobert Watson 2151db2661ceSRobert Watson /* 21523f1a7a90SRobert Watson * Treat sysctl variables without CTLFLAG_ANYBODY flag as lomac/high, 21533f1a7a90SRobert Watson * but also require privilege to change them. 2154db2661ceSRobert Watson */ 215563dba32bSPawel Jakub Dawidek if (req->newptr != NULL && (oidp->oid_kind & CTLFLAG_ANYBODY) == 0) { 2156db2661ceSRobert Watson #ifdef notdef 21573f1a7a90SRobert Watson if (!lomac_subject_dominate_high(subj)) 2158db2661ceSRobert Watson return (EACCES); 2159db2661ceSRobert Watson #endif 2160db2661ceSRobert Watson 21613f1a7a90SRobert Watson if (lomac_subject_privileged(subj)) 2162db2661ceSRobert Watson return (EPERM); 2163db2661ceSRobert Watson } 2164db2661ceSRobert Watson 2165db2661ceSRobert Watson return (0); 2166db2661ceSRobert Watson } 2167db2661ceSRobert Watson 2168eb320b0eSRobert Watson static void 2169eb320b0eSRobert Watson lomac_thread_userret(struct thread *td) 2170eb320b0eSRobert Watson { 2171eb320b0eSRobert Watson struct proc *p = td->td_proc; 2172eb320b0eSRobert Watson struct mac_lomac_proc *subj = PSLOT(p->p_label); 2173eb320b0eSRobert Watson struct ucred *newcred, *oldcred; 2174eb320b0eSRobert Watson int dodrop; 2175eb320b0eSRobert Watson 2176eb320b0eSRobert Watson mtx_lock(&subj->mtx); 2177eb320b0eSRobert Watson if (subj->mac_lomac.ml_flags & MAC_LOMAC_FLAG_UPDATE) { 2178eb320b0eSRobert Watson dodrop = 0; 2179eb320b0eSRobert Watson mtx_unlock(&subj->mtx); 2180eb320b0eSRobert Watson newcred = crget(); 2181eb320b0eSRobert Watson /* 2182eb320b0eSRobert Watson * Prevent a lock order reversal in 2183eb320b0eSRobert Watson * mac_cred_mmapped_drop_perms; ideally, the other user of 2184eb320b0eSRobert Watson * subj->mtx wouldn't be holding Giant. 2185eb320b0eSRobert Watson */ 2186eb320b0eSRobert Watson mtx_lock(&Giant); 2187eb320b0eSRobert Watson PROC_LOCK(p); 2188eb320b0eSRobert Watson mtx_lock(&subj->mtx); 2189eb320b0eSRobert Watson /* 2190eb320b0eSRobert Watson * Check if we lost the race while allocating the cred. 2191eb320b0eSRobert Watson */ 2192eb320b0eSRobert Watson if ((subj->mac_lomac.ml_flags & MAC_LOMAC_FLAG_UPDATE) == 0) { 2193eb320b0eSRobert Watson crfree(newcred); 2194eb320b0eSRobert Watson goto out; 2195eb320b0eSRobert Watson } 2196eb320b0eSRobert Watson oldcred = p->p_ucred; 2197eb320b0eSRobert Watson crcopy(newcred, oldcred); 2198eb320b0eSRobert Watson crhold(newcred); 2199eb320b0eSRobert Watson lomac_copy(&subj->mac_lomac, SLOT(newcred->cr_label)); 2200eb320b0eSRobert Watson p->p_ucred = newcred; 2201eb320b0eSRobert Watson crfree(oldcred); 2202eb320b0eSRobert Watson dodrop = 1; 2203eb320b0eSRobert Watson out: 2204eb320b0eSRobert Watson mtx_unlock(&subj->mtx); 2205eb320b0eSRobert Watson PROC_UNLOCK(p); 2206eb320b0eSRobert Watson if (dodrop) 2207eb320b0eSRobert Watson mac_cred_mmapped_drop_perms(curthread, newcred); 2208eb320b0eSRobert Watson mtx_unlock(&Giant); 2209eb320b0eSRobert Watson } else { 2210eb320b0eSRobert Watson mtx_unlock(&subj->mtx); 2211eb320b0eSRobert Watson } 2212eb320b0eSRobert Watson } 2213eb320b0eSRobert Watson 2214eb320b0eSRobert Watson static int 2215eb320b0eSRobert Watson lomac_vnode_associate_extattr(struct mount *mp, struct label *mplabel, 2216eb320b0eSRobert Watson struct vnode *vp, struct label *vplabel) 2217eb320b0eSRobert Watson { 2218eb320b0eSRobert Watson struct mac_lomac ml_temp, *source, *dest; 2219eb320b0eSRobert Watson int buflen, error; 2220eb320b0eSRobert Watson 2221eb320b0eSRobert Watson source = SLOT(mplabel); 2222eb320b0eSRobert Watson dest = SLOT(vplabel); 2223eb320b0eSRobert Watson 2224eb320b0eSRobert Watson buflen = sizeof(ml_temp); 2225eb320b0eSRobert Watson bzero(&ml_temp, buflen); 2226eb320b0eSRobert Watson 2227eb320b0eSRobert Watson error = vn_extattr_get(vp, IO_NODELOCKED, MAC_LOMAC_EXTATTR_NAMESPACE, 2228eb320b0eSRobert Watson MAC_LOMAC_EXTATTR_NAME, &buflen, (char *)&ml_temp, curthread); 2229eb320b0eSRobert Watson if (error == ENOATTR || error == EOPNOTSUPP) { 2230eb320b0eSRobert Watson /* Fall back to the mntlabel. */ 2231eb320b0eSRobert Watson lomac_copy_single(source, dest); 2232eb320b0eSRobert Watson return (0); 2233eb320b0eSRobert Watson } else if (error) 2234eb320b0eSRobert Watson return (error); 2235eb320b0eSRobert Watson 2236eb320b0eSRobert Watson if (buflen != sizeof(ml_temp)) { 2237eb320b0eSRobert Watson if (buflen != sizeof(ml_temp) - sizeof(ml_temp.ml_auxsingle)) { 2238eb320b0eSRobert Watson printf("lomac_vnode_associate_extattr: bad size %d\n", 2239eb320b0eSRobert Watson buflen); 2240eb320b0eSRobert Watson return (EPERM); 2241eb320b0eSRobert Watson } 2242eb320b0eSRobert Watson bzero(&ml_temp.ml_auxsingle, sizeof(ml_temp.ml_auxsingle)); 2243eb320b0eSRobert Watson buflen = sizeof(ml_temp); 2244eb320b0eSRobert Watson (void)vn_extattr_set(vp, IO_NODELOCKED, 2245eb320b0eSRobert Watson MAC_LOMAC_EXTATTR_NAMESPACE, MAC_LOMAC_EXTATTR_NAME, 2246eb320b0eSRobert Watson buflen, (char *)&ml_temp, curthread); 2247eb320b0eSRobert Watson } 2248eb320b0eSRobert Watson if (lomac_valid(&ml_temp) != 0) { 2249eb320b0eSRobert Watson printf("lomac_vnode_associate_extattr: invalid\n"); 2250eb320b0eSRobert Watson return (EPERM); 2251eb320b0eSRobert Watson } 2252eb320b0eSRobert Watson if ((ml_temp.ml_flags & MAC_LOMAC_FLAGS_BOTH) != 2253eb320b0eSRobert Watson MAC_LOMAC_FLAG_SINGLE) { 2254eb320b0eSRobert Watson printf("lomac_vnode_associate_extattr: not single\n"); 2255eb320b0eSRobert Watson return (EPERM); 2256eb320b0eSRobert Watson } 2257eb320b0eSRobert Watson 2258eb320b0eSRobert Watson lomac_copy_single(&ml_temp, dest); 2259eb320b0eSRobert Watson return (0); 2260eb320b0eSRobert Watson } 2261eb320b0eSRobert Watson 2262eb320b0eSRobert Watson static void 2263eb320b0eSRobert Watson lomac_vnode_associate_singlelabel(struct mount *mp, struct label *mplabel, 2264eb320b0eSRobert Watson struct vnode *vp, struct label *vplabel) 2265eb320b0eSRobert Watson { 2266eb320b0eSRobert Watson struct mac_lomac *source, *dest; 2267eb320b0eSRobert Watson 2268eb320b0eSRobert Watson source = SLOT(mplabel); 2269eb320b0eSRobert Watson dest = SLOT(vplabel); 2270eb320b0eSRobert Watson 2271eb320b0eSRobert Watson lomac_copy_single(source, dest); 2272eb320b0eSRobert Watson } 2273eb320b0eSRobert Watson 2274db2661ceSRobert Watson static int 22753f1a7a90SRobert Watson lomac_vnode_check_create(struct ucred *cred, struct vnode *dvp, 227678007886SRobert Watson struct label *dvplabel, struct componentname *cnp, struct vattr *vap) 2277db2661ceSRobert Watson { 2278db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2279db2661ceSRobert Watson 22803f1a7a90SRobert Watson if (!lomac_enabled) 2281db2661ceSRobert Watson return (0); 2282db2661ceSRobert Watson 2283eca8a663SRobert Watson subj = SLOT(cred->cr_label); 228478007886SRobert Watson obj = SLOT(dvplabel); 2285db2661ceSRobert Watson 22863f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2287db2661ceSRobert Watson return (EACCES); 2288db2661ceSRobert Watson if (obj->ml_flags & MAC_LOMAC_FLAG_AUX && 22893f1a7a90SRobert Watson !lomac_dominate_element(&subj->ml_single, &obj->ml_auxsingle)) 2290db2661ceSRobert Watson return (EACCES); 2291db2661ceSRobert Watson 2292db2661ceSRobert Watson return (0); 2293db2661ceSRobert Watson } 2294db2661ceSRobert Watson 2295db2661ceSRobert Watson static int 22963f1a7a90SRobert Watson lomac_vnode_check_deleteacl(struct ucred *cred, struct vnode *vp, 229778007886SRobert Watson struct label *vplabel, acl_type_t type) 2298db2661ceSRobert Watson { 2299db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2300db2661ceSRobert Watson 23013f1a7a90SRobert Watson if (!lomac_enabled) 2302db2661ceSRobert Watson return (0); 2303db2661ceSRobert Watson 2304eca8a663SRobert Watson subj = SLOT(cred->cr_label); 230578007886SRobert Watson obj = SLOT(vplabel); 2306db2661ceSRobert Watson 23073f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2308db2661ceSRobert Watson return (EACCES); 2309db2661ceSRobert Watson 2310db2661ceSRobert Watson return (0); 2311db2661ceSRobert Watson } 2312db2661ceSRobert Watson 2313db2661ceSRobert Watson static int 23143f1a7a90SRobert Watson lomac_vnode_check_link(struct ucred *cred, struct vnode *dvp, 231578007886SRobert Watson struct label *dvplabel, struct vnode *vp, struct label *vplabel, 2316db2661ceSRobert Watson struct componentname *cnp) 2317db2661ceSRobert Watson { 2318db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2319db2661ceSRobert Watson 23203f1a7a90SRobert Watson if (!lomac_enabled) 2321db2661ceSRobert Watson return (0); 2322db2661ceSRobert Watson 2323eca8a663SRobert Watson subj = SLOT(cred->cr_label); 232478007886SRobert Watson obj = SLOT(dvplabel); 2325db2661ceSRobert Watson 23263f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2327db2661ceSRobert Watson return (EACCES); 2328db2661ceSRobert Watson 232978007886SRobert Watson obj = SLOT(vplabel); 2330db2661ceSRobert Watson 23313f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2332db2661ceSRobert Watson return (EACCES); 2333db2661ceSRobert Watson 2334db2661ceSRobert Watson return (0); 2335db2661ceSRobert Watson } 2336db2661ceSRobert Watson 2337db2661ceSRobert Watson static int 23383f1a7a90SRobert Watson lomac_vnode_check_mmap(struct ucred *cred, struct vnode *vp, 233978007886SRobert Watson struct label *vplabel, int prot, int flags) 2340db2661ceSRobert Watson { 2341db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2342db2661ceSRobert Watson 2343db2661ceSRobert Watson /* 2344db2661ceSRobert Watson * Rely on the use of open()-time protections to handle 2345db2661ceSRobert Watson * non-revocation cases. 2346db2661ceSRobert Watson */ 23473f1a7a90SRobert Watson if (!lomac_enabled) 2348db2661ceSRobert Watson return (0); 2349db2661ceSRobert Watson 2350eca8a663SRobert Watson subj = SLOT(cred->cr_label); 235178007886SRobert Watson obj = SLOT(vplabel); 2352db2661ceSRobert Watson 2353c92163dcSChristian S.J. Peron if (((prot & VM_PROT_WRITE) != 0) && ((flags & MAP_SHARED) != 0)) { 23543f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2355db2661ceSRobert Watson return (EACCES); 2356db2661ceSRobert Watson } 2357db2661ceSRobert Watson if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) { 23583f1a7a90SRobert Watson if (!lomac_dominate_single(obj, subj)) 2359db2661ceSRobert Watson return (maybe_demote(subj, obj, "mapping", "file", vp)); 2360db2661ceSRobert Watson } 2361db2661ceSRobert Watson 2362db2661ceSRobert Watson return (0); 2363db2661ceSRobert Watson } 2364db2661ceSRobert Watson 2365db2661ceSRobert Watson static void 23663f1a7a90SRobert Watson lomac_vnode_check_mmap_downgrade(struct ucred *cred, struct vnode *vp, 236778007886SRobert Watson struct label *vplabel, /* XXX vm_prot_t */ int *prot) 2368db2661ceSRobert Watson { 2369db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2370db2661ceSRobert Watson 2371db2661ceSRobert Watson /* 2372db2661ceSRobert Watson * Rely on the use of open()-time protections to handle 2373db2661ceSRobert Watson * non-revocation cases. 2374db2661ceSRobert Watson */ 23753f1a7a90SRobert Watson if (!lomac_enabled || !revocation_enabled) 2376db2661ceSRobert Watson return; 2377db2661ceSRobert Watson 2378eca8a663SRobert Watson subj = SLOT(cred->cr_label); 237978007886SRobert Watson obj = SLOT(vplabel); 2380db2661ceSRobert Watson 23813f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2382db2661ceSRobert Watson *prot &= ~VM_PROT_WRITE; 2383db2661ceSRobert Watson } 2384db2661ceSRobert Watson 2385db2661ceSRobert Watson static int 23863f1a7a90SRobert Watson lomac_vnode_check_open(struct ucred *cred, struct vnode *vp, 238778007886SRobert Watson struct label *vplabel, int acc_mode) 2388db2661ceSRobert Watson { 2389db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2390db2661ceSRobert Watson 23913f1a7a90SRobert Watson if (!lomac_enabled) 2392db2661ceSRobert Watson return (0); 2393db2661ceSRobert Watson 2394eca8a663SRobert Watson subj = SLOT(cred->cr_label); 239578007886SRobert Watson obj = SLOT(vplabel); 2396db2661ceSRobert Watson 2397db2661ceSRobert Watson /* XXX privilege override for admin? */ 2398db2661ceSRobert Watson if (acc_mode & (VWRITE | VAPPEND | VADMIN)) { 23993f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2400db2661ceSRobert Watson return (EACCES); 2401db2661ceSRobert Watson } 2402db2661ceSRobert Watson 2403db2661ceSRobert Watson return (0); 2404db2661ceSRobert Watson } 2405db2661ceSRobert Watson 2406db2661ceSRobert Watson static int 24073f1a7a90SRobert Watson lomac_vnode_check_read(struct ucred *active_cred, struct ucred *file_cred, 240878007886SRobert Watson struct vnode *vp, struct label *vplabel) 2409db2661ceSRobert Watson { 2410db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2411db2661ceSRobert Watson 24123f1a7a90SRobert Watson if (!lomac_enabled || !revocation_enabled) 2413db2661ceSRobert Watson return (0); 2414db2661ceSRobert Watson 2415eca8a663SRobert Watson subj = SLOT(active_cred->cr_label); 241678007886SRobert Watson obj = SLOT(vplabel); 2417db2661ceSRobert Watson 24183f1a7a90SRobert Watson if (!lomac_dominate_single(obj, subj)) 2419db2661ceSRobert Watson return (maybe_demote(subj, obj, "reading", "file", vp)); 2420db2661ceSRobert Watson 2421db2661ceSRobert Watson return (0); 2422db2661ceSRobert Watson } 2423db2661ceSRobert Watson 2424db2661ceSRobert Watson static int 24253f1a7a90SRobert Watson lomac_vnode_check_relabel(struct ucred *cred, struct vnode *vp, 242678007886SRobert Watson struct label *vplabel, struct label *newlabel) 2427db2661ceSRobert Watson { 2428db2661ceSRobert Watson struct mac_lomac *old, *new, *subj; 2429db2661ceSRobert Watson int error; 2430db2661ceSRobert Watson 243178007886SRobert Watson old = SLOT(vplabel); 2432db2661ceSRobert Watson new = SLOT(newlabel); 2433eca8a663SRobert Watson subj = SLOT(cred->cr_label); 2434db2661ceSRobert Watson 2435db2661ceSRobert Watson /* 2436db2661ceSRobert Watson * If there is a LOMAC label update for the vnode, it must be a 2437db2661ceSRobert Watson * single label, with an optional explicit auxiliary single. 2438db2661ceSRobert Watson */ 2439db2661ceSRobert Watson error = lomac_atmostflags(new, 2440db2661ceSRobert Watson MAC_LOMAC_FLAG_SINGLE | MAC_LOMAC_FLAG_AUX); 2441db2661ceSRobert Watson if (error) 2442db2661ceSRobert Watson return (error); 2443db2661ceSRobert Watson 2444db2661ceSRobert Watson /* 2445db2661ceSRobert Watson * To perform a relabel of the vnode (LOMAC label or not), LOMAC must 2446db2661ceSRobert Watson * authorize the relabel. 2447db2661ceSRobert Watson */ 24483f1a7a90SRobert Watson if (!lomac_single_in_range(old, subj)) 2449db2661ceSRobert Watson return (EPERM); 2450db2661ceSRobert Watson 2451db2661ceSRobert Watson /* 2452db2661ceSRobert Watson * If the LOMAC label is to be changed, authorize as appropriate. 2453db2661ceSRobert Watson */ 2454db2661ceSRobert Watson if (new->ml_flags & MAC_LOMAC_FLAG_SINGLE) { 2455db2661ceSRobert Watson /* 2456db2661ceSRobert Watson * To change the LOMAC label on a vnode, the new vnode label 2457db2661ceSRobert Watson * must be in the subject range. 2458db2661ceSRobert Watson */ 24593f1a7a90SRobert Watson if (!lomac_single_in_range(new, subj)) 2460db2661ceSRobert Watson return (EPERM); 2461db2661ceSRobert Watson 2462db2661ceSRobert Watson /* 24633f1a7a90SRobert Watson * To change the LOMAC label on the vnode to be EQUAL, the 24643f1a7a90SRobert Watson * subject must have appropriate privilege. 2465db2661ceSRobert Watson */ 24663f1a7a90SRobert Watson if (lomac_contains_equal(new)) { 24673f1a7a90SRobert Watson error = lomac_subject_privileged(subj); 2468db2661ceSRobert Watson if (error) 2469db2661ceSRobert Watson return (error); 2470db2661ceSRobert Watson } 2471db2661ceSRobert Watson } 2472db2661ceSRobert Watson if (new->ml_flags & MAC_LOMAC_FLAG_AUX) { 2473db2661ceSRobert Watson /* 247484bdb083SRobert Watson * Fill in the missing parts from the previous label. 247584bdb083SRobert Watson */ 247684bdb083SRobert Watson if ((new->ml_flags & MAC_LOMAC_FLAG_SINGLE) == 0) 24773f1a7a90SRobert Watson lomac_copy_single(subj, new); 247884bdb083SRobert Watson 247984bdb083SRobert Watson /* 2480db2661ceSRobert Watson * To change the auxiliary LOMAC label on a vnode, the new 2481db2661ceSRobert Watson * vnode label must be in the subject range. 2482db2661ceSRobert Watson */ 24833f1a7a90SRobert Watson if (!lomac_auxsingle_in_range(new, subj)) 2484db2661ceSRobert Watson return (EPERM); 2485db2661ceSRobert Watson 2486db2661ceSRobert Watson /* 2487db2661ceSRobert Watson * To change the auxiliary LOMAC label on the vnode to be 2488db2661ceSRobert Watson * EQUAL, the subject must have appropriate privilege. 2489db2661ceSRobert Watson */ 24903f1a7a90SRobert Watson if (lomac_contains_equal(new)) { 24913f1a7a90SRobert Watson error = lomac_subject_privileged(subj); 2492db2661ceSRobert Watson if (error) 2493db2661ceSRobert Watson return (error); 2494db2661ceSRobert Watson } 2495db2661ceSRobert Watson } 2496db2661ceSRobert Watson 2497db2661ceSRobert Watson return (0); 2498db2661ceSRobert Watson } 2499db2661ceSRobert Watson 2500db2661ceSRobert Watson static int 25013f1a7a90SRobert Watson lomac_vnode_check_rename_from(struct ucred *cred, struct vnode *dvp, 250278007886SRobert Watson struct label *dvplabel, struct vnode *vp, struct label *vplabel, 2503db2661ceSRobert Watson struct componentname *cnp) 2504db2661ceSRobert Watson { 2505db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2506db2661ceSRobert Watson 25073f1a7a90SRobert Watson if (!lomac_enabled) 2508db2661ceSRobert Watson return (0); 2509db2661ceSRobert Watson 2510eca8a663SRobert Watson subj = SLOT(cred->cr_label); 251178007886SRobert Watson obj = SLOT(dvplabel); 2512db2661ceSRobert Watson 25133f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2514db2661ceSRobert Watson return (EACCES); 2515db2661ceSRobert Watson 251678007886SRobert Watson obj = SLOT(vplabel); 2517db2661ceSRobert Watson 25183f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2519db2661ceSRobert Watson return (EACCES); 2520db2661ceSRobert Watson 2521db2661ceSRobert Watson return (0); 2522db2661ceSRobert Watson } 2523db2661ceSRobert Watson 2524db2661ceSRobert Watson static int 25253f1a7a90SRobert Watson lomac_vnode_check_rename_to(struct ucred *cred, struct vnode *dvp, 252678007886SRobert Watson struct label *dvplabel, struct vnode *vp, struct label *vplabel, 252778007886SRobert Watson int samedir, struct componentname *cnp) 2528db2661ceSRobert Watson { 2529db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2530db2661ceSRobert Watson 25313f1a7a90SRobert Watson if (!lomac_enabled) 2532db2661ceSRobert Watson return (0); 2533db2661ceSRobert Watson 2534eca8a663SRobert Watson subj = SLOT(cred->cr_label); 253578007886SRobert Watson obj = SLOT(dvplabel); 2536db2661ceSRobert Watson 25373f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2538db2661ceSRobert Watson return (EACCES); 2539db2661ceSRobert Watson 2540db2661ceSRobert Watson if (vp != NULL) { 254178007886SRobert Watson obj = SLOT(vplabel); 2542db2661ceSRobert Watson 25433f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2544db2661ceSRobert Watson return (EACCES); 2545db2661ceSRobert Watson } 2546db2661ceSRobert Watson 2547db2661ceSRobert Watson return (0); 2548db2661ceSRobert Watson } 2549db2661ceSRobert Watson 2550db2661ceSRobert Watson static int 25513f1a7a90SRobert Watson lomac_vnode_check_revoke(struct ucred *cred, struct vnode *vp, 255278007886SRobert Watson struct label *vplabel) 2553db2661ceSRobert Watson { 2554db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2555db2661ceSRobert Watson 25563f1a7a90SRobert Watson if (!lomac_enabled) 2557db2661ceSRobert Watson return (0); 2558db2661ceSRobert Watson 2559eca8a663SRobert Watson subj = SLOT(cred->cr_label); 256078007886SRobert Watson obj = SLOT(vplabel); 2561db2661ceSRobert Watson 25623f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2563db2661ceSRobert Watson return (EACCES); 2564db2661ceSRobert Watson 2565db2661ceSRobert Watson return (0); 2566db2661ceSRobert Watson } 2567db2661ceSRobert Watson 2568db2661ceSRobert Watson static int 25693f1a7a90SRobert Watson lomac_vnode_check_setacl(struct ucred *cred, struct vnode *vp, 257078007886SRobert Watson struct label *vplabel, acl_type_t type, struct acl *acl) 2571db2661ceSRobert Watson { 2572db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2573db2661ceSRobert Watson 25743f1a7a90SRobert Watson if (!lomac_enabled) 2575db2661ceSRobert Watson return (0); 2576db2661ceSRobert Watson 2577eca8a663SRobert Watson subj = SLOT(cred->cr_label); 257878007886SRobert Watson obj = SLOT(vplabel); 2579db2661ceSRobert Watson 25803f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2581db2661ceSRobert Watson return (EACCES); 2582db2661ceSRobert Watson 2583db2661ceSRobert Watson return (0); 2584db2661ceSRobert Watson } 2585db2661ceSRobert Watson 2586db2661ceSRobert Watson static int 25873f1a7a90SRobert Watson lomac_vnode_check_setextattr(struct ucred *cred, struct vnode *vp, 258878007886SRobert Watson struct label *vplabel, int attrnamespace, const char *name, 2589db2661ceSRobert Watson struct uio *uio) 2590db2661ceSRobert Watson { 2591db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2592db2661ceSRobert Watson 25933f1a7a90SRobert Watson if (!lomac_enabled) 2594db2661ceSRobert Watson return (0); 2595db2661ceSRobert Watson 2596eca8a663SRobert Watson subj = SLOT(cred->cr_label); 259778007886SRobert Watson obj = SLOT(vplabel); 2598db2661ceSRobert Watson 25993f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2600db2661ceSRobert Watson return (EACCES); 2601db2661ceSRobert Watson 2602db2661ceSRobert Watson /* XXX: protect the MAC EA in a special way? */ 2603db2661ceSRobert Watson 2604db2661ceSRobert Watson return (0); 2605db2661ceSRobert Watson } 2606db2661ceSRobert Watson 2607db2661ceSRobert Watson static int 26083f1a7a90SRobert Watson lomac_vnode_check_setflags(struct ucred *cred, struct vnode *vp, 260978007886SRobert Watson struct label *vplabel, u_long flags) 2610db2661ceSRobert Watson { 2611db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2612db2661ceSRobert Watson 26133f1a7a90SRobert Watson if (!lomac_enabled) 2614db2661ceSRobert Watson return (0); 2615db2661ceSRobert Watson 2616eca8a663SRobert Watson subj = SLOT(cred->cr_label); 261778007886SRobert Watson obj = SLOT(vplabel); 2618db2661ceSRobert Watson 26193f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2620db2661ceSRobert Watson return (EACCES); 2621db2661ceSRobert Watson 2622db2661ceSRobert Watson return (0); 2623db2661ceSRobert Watson } 2624db2661ceSRobert Watson 2625db2661ceSRobert Watson static int 26263f1a7a90SRobert Watson lomac_vnode_check_setmode(struct ucred *cred, struct vnode *vp, 262778007886SRobert Watson struct label *vplabel, mode_t mode) 2628db2661ceSRobert Watson { 2629db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2630db2661ceSRobert Watson 26313f1a7a90SRobert Watson if (!lomac_enabled) 2632db2661ceSRobert Watson return (0); 2633db2661ceSRobert Watson 2634eca8a663SRobert Watson subj = SLOT(cred->cr_label); 263578007886SRobert Watson obj = SLOT(vplabel); 2636db2661ceSRobert Watson 26373f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2638db2661ceSRobert Watson return (EACCES); 2639db2661ceSRobert Watson 2640db2661ceSRobert Watson return (0); 2641db2661ceSRobert Watson } 2642db2661ceSRobert Watson 2643db2661ceSRobert Watson static int 26443f1a7a90SRobert Watson lomac_vnode_check_setowner(struct ucred *cred, struct vnode *vp, 264578007886SRobert Watson struct label *vplabel, uid_t uid, gid_t gid) 2646db2661ceSRobert Watson { 2647db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2648db2661ceSRobert Watson 26493f1a7a90SRobert Watson if (!lomac_enabled) 2650db2661ceSRobert Watson return (0); 2651db2661ceSRobert Watson 2652eca8a663SRobert Watson subj = SLOT(cred->cr_label); 265378007886SRobert Watson obj = SLOT(vplabel); 2654db2661ceSRobert Watson 26553f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2656db2661ceSRobert Watson return (EACCES); 2657db2661ceSRobert Watson 2658db2661ceSRobert Watson return (0); 2659db2661ceSRobert Watson } 2660db2661ceSRobert Watson 2661db2661ceSRobert Watson static int 26623f1a7a90SRobert Watson lomac_vnode_check_setutimes(struct ucred *cred, struct vnode *vp, 266378007886SRobert Watson struct label *vplabel, struct timespec atime, struct timespec mtime) 2664db2661ceSRobert Watson { 2665db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2666db2661ceSRobert Watson 26673f1a7a90SRobert Watson if (!lomac_enabled) 2668db2661ceSRobert Watson return (0); 2669db2661ceSRobert Watson 2670eca8a663SRobert Watson subj = SLOT(cred->cr_label); 267178007886SRobert Watson obj = SLOT(vplabel); 2672db2661ceSRobert Watson 26733f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2674db2661ceSRobert Watson return (EACCES); 2675db2661ceSRobert Watson 2676db2661ceSRobert Watson return (0); 2677db2661ceSRobert Watson } 2678db2661ceSRobert Watson 2679db2661ceSRobert Watson static int 26803f1a7a90SRobert Watson lomac_vnode_check_unlink(struct ucred *cred, struct vnode *dvp, 268145e0f3d6SRobert Watson struct label *dvplabel, struct vnode *vp, struct label *vplabel, 268245e0f3d6SRobert Watson struct componentname *cnp) 268345e0f3d6SRobert Watson { 268445e0f3d6SRobert Watson struct mac_lomac *subj, *obj; 268545e0f3d6SRobert Watson 26863f1a7a90SRobert Watson if (!lomac_enabled) 268745e0f3d6SRobert Watson return (0); 268845e0f3d6SRobert Watson 268945e0f3d6SRobert Watson subj = SLOT(cred->cr_label); 269045e0f3d6SRobert Watson obj = SLOT(dvplabel); 269145e0f3d6SRobert Watson 26923f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 269345e0f3d6SRobert Watson return (EACCES); 269445e0f3d6SRobert Watson 269545e0f3d6SRobert Watson obj = SLOT(vplabel); 269645e0f3d6SRobert Watson 26973f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 269845e0f3d6SRobert Watson return (EACCES); 269945e0f3d6SRobert Watson 270045e0f3d6SRobert Watson return (0); 270145e0f3d6SRobert Watson } 270245e0f3d6SRobert Watson 270345e0f3d6SRobert Watson static int 27043f1a7a90SRobert Watson lomac_vnode_check_write(struct ucred *active_cred, 270578007886SRobert Watson struct ucred *file_cred, struct vnode *vp, struct label *vplabel) 2706db2661ceSRobert Watson { 2707db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2708db2661ceSRobert Watson 27093f1a7a90SRobert Watson if (!lomac_enabled || !revocation_enabled) 2710db2661ceSRobert Watson return (0); 2711db2661ceSRobert Watson 2712eca8a663SRobert Watson subj = SLOT(active_cred->cr_label); 271378007886SRobert Watson obj = SLOT(vplabel); 2714db2661ceSRobert Watson 27153f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2716db2661ceSRobert Watson return (EACCES); 2717db2661ceSRobert Watson 2718db2661ceSRobert Watson return (0); 2719db2661ceSRobert Watson } 2720db2661ceSRobert Watson 2721eb320b0eSRobert Watson static int 2722eb320b0eSRobert Watson lomac_vnode_create_extattr(struct ucred *cred, struct mount *mp, 2723eb320b0eSRobert Watson struct label *mplabel, struct vnode *dvp, struct label *dvplabel, 2724eb320b0eSRobert Watson struct vnode *vp, struct label *vplabel, struct componentname *cnp) 2725db2661ceSRobert Watson { 2726eb320b0eSRobert Watson struct mac_lomac *source, *dest, *dir, temp; 2727eb320b0eSRobert Watson size_t buflen; 2728eb320b0eSRobert Watson int error; 2729db2661ceSRobert Watson 2730eb320b0eSRobert Watson buflen = sizeof(temp); 2731eb320b0eSRobert Watson bzero(&temp, buflen); 2732eb320b0eSRobert Watson 2733eb320b0eSRobert Watson source = SLOT(cred->cr_label); 2734eb320b0eSRobert Watson dest = SLOT(vplabel); 2735eb320b0eSRobert Watson dir = SLOT(dvplabel); 2736eb320b0eSRobert Watson if (dir->ml_flags & MAC_LOMAC_FLAG_AUX) { 2737eb320b0eSRobert Watson lomac_copy_auxsingle(dir, &temp); 2738eb320b0eSRobert Watson lomac_set_single(&temp, dir->ml_auxsingle.mle_type, 2739eb320b0eSRobert Watson dir->ml_auxsingle.mle_grade); 2740db2661ceSRobert Watson } else { 2741eb320b0eSRobert Watson lomac_copy_single(source, &temp); 2742db2661ceSRobert Watson } 2743eb320b0eSRobert Watson 2744eb320b0eSRobert Watson error = vn_extattr_set(vp, IO_NODELOCKED, MAC_LOMAC_EXTATTR_NAMESPACE, 2745eb320b0eSRobert Watson MAC_LOMAC_EXTATTR_NAME, buflen, (char *)&temp, curthread); 2746eb320b0eSRobert Watson if (error == 0) 2747eb320b0eSRobert Watson lomac_copy(&temp, dest); 2748eb320b0eSRobert Watson return (error); 2749eb320b0eSRobert Watson } 2750eb320b0eSRobert Watson 2751eb320b0eSRobert Watson static void 2752eb320b0eSRobert Watson lomac_vnode_execve_transition(struct ucred *old, struct ucred *new, 2753eb320b0eSRobert Watson struct vnode *vp, struct label *vplabel, struct label *interpvplabel, 2754eb320b0eSRobert Watson struct image_params *imgp, struct label *execlabel) 2755eb320b0eSRobert Watson { 2756eb320b0eSRobert Watson struct mac_lomac *source, *dest, *obj, *robj; 2757eb320b0eSRobert Watson 2758eb320b0eSRobert Watson source = SLOT(old->cr_label); 2759eb320b0eSRobert Watson dest = SLOT(new->cr_label); 2760eb320b0eSRobert Watson obj = SLOT(vplabel); 2761eb320b0eSRobert Watson robj = interpvplabel != NULL ? SLOT(interpvplabel) : obj; 2762eb320b0eSRobert Watson 2763eb320b0eSRobert Watson lomac_copy(source, dest); 2764eb320b0eSRobert Watson /* 2765eb320b0eSRobert Watson * If there's an auxiliary label on the real object, respect it and 2766eb320b0eSRobert Watson * assume that this level should be assumed immediately if a higher 2767eb320b0eSRobert Watson * level is currently in place. 2768eb320b0eSRobert Watson */ 2769eb320b0eSRobert Watson if (robj->ml_flags & MAC_LOMAC_FLAG_AUX && 2770eb320b0eSRobert Watson !lomac_dominate_element(&robj->ml_auxsingle, &dest->ml_single) 2771eb320b0eSRobert Watson && lomac_auxsingle_in_range(robj, dest)) 2772eb320b0eSRobert Watson lomac_set_single(dest, robj->ml_auxsingle.mle_type, 2773eb320b0eSRobert Watson robj->ml_auxsingle.mle_grade); 2774eb320b0eSRobert Watson /* 2775eb320b0eSRobert Watson * Restructuring to use the execve transitioning mechanism instead of 2776eb320b0eSRobert Watson * the normal demotion mechanism here would be difficult, so just 2777eb320b0eSRobert Watson * copy the label over and perform standard demotion. This is also 2778eb320b0eSRobert Watson * non-optimal because it will result in the intermediate label "new" 2779eb320b0eSRobert Watson * being created and immediately recycled. 2780eb320b0eSRobert Watson */ 2781eb320b0eSRobert Watson if (lomac_enabled && revocation_enabled && 2782eb320b0eSRobert Watson !lomac_dominate_single(obj, source)) 2783eb320b0eSRobert Watson (void)maybe_demote(source, obj, "executing", "file", vp); 2784eb320b0eSRobert Watson } 2785eb320b0eSRobert Watson 2786eb320b0eSRobert Watson static int 2787eb320b0eSRobert Watson lomac_vnode_execve_will_transition(struct ucred *old, struct vnode *vp, 2788eb320b0eSRobert Watson struct label *vplabel, struct label *interpvplabel, 2789eb320b0eSRobert Watson struct image_params *imgp, struct label *execlabel) 2790eb320b0eSRobert Watson { 2791eb320b0eSRobert Watson struct mac_lomac *subj, *obj, *robj; 2792eb320b0eSRobert Watson 2793eb320b0eSRobert Watson if (!lomac_enabled || !revocation_enabled) 2794eb320b0eSRobert Watson return (0); 2795eb320b0eSRobert Watson 2796eb320b0eSRobert Watson subj = SLOT(old->cr_label); 2797eb320b0eSRobert Watson obj = SLOT(vplabel); 2798eb320b0eSRobert Watson robj = interpvplabel != NULL ? SLOT(interpvplabel) : obj; 2799eb320b0eSRobert Watson 2800eb320b0eSRobert Watson return ((robj->ml_flags & MAC_LOMAC_FLAG_AUX && 2801eb320b0eSRobert Watson !lomac_dominate_element(&robj->ml_auxsingle, &subj->ml_single) 2802eb320b0eSRobert Watson && lomac_auxsingle_in_range(robj, subj)) || 2803eb320b0eSRobert Watson !lomac_dominate_single(obj, subj)); 2804eb320b0eSRobert Watson } 2805eb320b0eSRobert Watson 2806eb320b0eSRobert Watson static void 2807eb320b0eSRobert Watson lomac_vnode_relabel(struct ucred *cred, struct vnode *vp, 2808eb320b0eSRobert Watson struct label *vplabel, struct label *newlabel) 2809eb320b0eSRobert Watson { 2810eb320b0eSRobert Watson struct mac_lomac *source, *dest; 2811eb320b0eSRobert Watson 2812eb320b0eSRobert Watson source = SLOT(newlabel); 2813eb320b0eSRobert Watson dest = SLOT(vplabel); 2814eb320b0eSRobert Watson 2815eb320b0eSRobert Watson try_relabel(source, dest); 2816eb320b0eSRobert Watson } 2817eb320b0eSRobert Watson 2818eb320b0eSRobert Watson static int 2819eb320b0eSRobert Watson lomac_vnode_setlabel_extattr(struct ucred *cred, struct vnode *vp, 2820eb320b0eSRobert Watson struct label *vplabel, struct label *intlabel) 2821eb320b0eSRobert Watson { 2822eb320b0eSRobert Watson struct mac_lomac *source, temp; 2823eb320b0eSRobert Watson size_t buflen; 2824eb320b0eSRobert Watson int error; 2825eb320b0eSRobert Watson 2826eb320b0eSRobert Watson buflen = sizeof(temp); 2827eb320b0eSRobert Watson bzero(&temp, buflen); 2828eb320b0eSRobert Watson 2829eb320b0eSRobert Watson source = SLOT(intlabel); 2830eb320b0eSRobert Watson if ((source->ml_flags & MAC_LOMAC_FLAG_SINGLE) == 0) 2831eb320b0eSRobert Watson return (0); 2832eb320b0eSRobert Watson 2833eb320b0eSRobert Watson lomac_copy_single(source, &temp); 2834eb320b0eSRobert Watson error = vn_extattr_set(vp, IO_NODELOCKED, MAC_LOMAC_EXTATTR_NAMESPACE, 2835eb320b0eSRobert Watson MAC_LOMAC_EXTATTR_NAME, buflen, (char *)&temp, curthread); 2836eb320b0eSRobert Watson return (error); 2837db2661ceSRobert Watson } 2838db2661ceSRobert Watson 28393f1a7a90SRobert Watson static struct mac_policy_ops lomac_ops = 2840db2661ceSRobert Watson { 28413f1a7a90SRobert Watson .mpo_init = lomac_init, 2842eb320b0eSRobert Watson 2843eb320b0eSRobert Watson .mpo_bpfdesc_check_receive = lomac_bpfdesc_check_receive, 2844eb320b0eSRobert Watson .mpo_bpfdesc_create = lomac_bpfdesc_create, 2845eb320b0eSRobert Watson .mpo_bpfdesc_create_mbuf = lomac_bpfdesc_create_mbuf, 28463f1a7a90SRobert Watson .mpo_bpfdesc_destroy_label = lomac_destroy_label, 2847eb320b0eSRobert Watson .mpo_bpfdesc_init_label = lomac_init_label, 2848eb320b0eSRobert Watson 2849eb320b0eSRobert Watson .mpo_cred_check_relabel = lomac_cred_check_relabel, 2850eb320b0eSRobert Watson .mpo_cred_check_visible = lomac_cred_check_visible, 28513f1a7a90SRobert Watson .mpo_cred_copy_label = lomac_copy_label, 2852eb320b0eSRobert Watson .mpo_cred_destroy_label = lomac_destroy_label, 28533f1a7a90SRobert Watson .mpo_cred_externalize_label = lomac_externalize_label, 2854eb320b0eSRobert Watson .mpo_cred_init_label = lomac_init_label, 28553f1a7a90SRobert Watson .mpo_cred_internalize_label = lomac_internalize_label, 2856eb320b0eSRobert Watson .mpo_cred_relabel = lomac_cred_relabel, 2857eb320b0eSRobert Watson 28583f1a7a90SRobert Watson .mpo_devfs_create_device = lomac_devfs_create_device, 28593f1a7a90SRobert Watson .mpo_devfs_create_directory = lomac_devfs_create_directory, 28603f1a7a90SRobert Watson .mpo_devfs_create_symlink = lomac_devfs_create_symlink, 2861eb320b0eSRobert Watson .mpo_devfs_destroy_label = lomac_destroy_label, 2862eb320b0eSRobert Watson .mpo_devfs_init_label = lomac_init_label, 28633f1a7a90SRobert Watson .mpo_devfs_update = lomac_devfs_update, 28643f1a7a90SRobert Watson .mpo_devfs_vnode_associate = lomac_devfs_vnode_associate, 2865eb320b0eSRobert Watson 28663f1a7a90SRobert Watson .mpo_ifnet_check_relabel = lomac_ifnet_check_relabel, 28673f1a7a90SRobert Watson .mpo_ifnet_check_transmit = lomac_ifnet_check_transmit, 2868eb320b0eSRobert Watson .mpo_ifnet_copy_label = lomac_copy_label, 2869eb320b0eSRobert Watson .mpo_ifnet_create = lomac_ifnet_create, 2870eb320b0eSRobert Watson .mpo_ifnet_create_mbuf = lomac_ifnet_create_mbuf, 2871eb320b0eSRobert Watson .mpo_ifnet_destroy_label = lomac_destroy_label, 2872eb320b0eSRobert Watson .mpo_ifnet_externalize_label = lomac_externalize_label, 2873eb320b0eSRobert Watson .mpo_ifnet_init_label = lomac_init_label, 2874eb320b0eSRobert Watson .mpo_ifnet_internalize_label = lomac_internalize_label, 2875eb320b0eSRobert Watson .mpo_ifnet_relabel = lomac_ifnet_relabel, 2876eb320b0eSRobert Watson 2877eb320b0eSRobert Watson .mpo_syncache_create = lomac_syncache_create, 2878eb320b0eSRobert Watson .mpo_syncache_destroy_label = lomac_destroy_label, 2879eb320b0eSRobert Watson .mpo_syncache_init_label = lomac_init_label_waitcheck, 2880eb320b0eSRobert Watson 28813f1a7a90SRobert Watson .mpo_inpcb_check_deliver = lomac_inpcb_check_deliver, 28827fb179baSBjoern A. Zeeb .mpo_inpcb_check_visible = lomac_inpcb_check_visible, 2883eb320b0eSRobert Watson .mpo_inpcb_create = lomac_inpcb_create, 2884eb320b0eSRobert Watson .mpo_inpcb_create_mbuf = lomac_inpcb_create_mbuf, 2885eb320b0eSRobert Watson .mpo_inpcb_destroy_label = lomac_destroy_label, 2886eb320b0eSRobert Watson .mpo_inpcb_init_label = lomac_init_label_waitcheck, 2887eb320b0eSRobert Watson .mpo_inpcb_sosetlabel = lomac_inpcb_sosetlabel, 2888eb320b0eSRobert Watson 2889eb320b0eSRobert Watson .mpo_ipq_create = lomac_ipq_create, 2890eb320b0eSRobert Watson .mpo_ipq_destroy_label = lomac_destroy_label, 2891eb320b0eSRobert Watson .mpo_ipq_init_label = lomac_init_label_waitcheck, 2892eb320b0eSRobert Watson .mpo_ipq_match = lomac_ipq_match, 2893eb320b0eSRobert Watson .mpo_ipq_reassemble = lomac_ipq_reassemble, 2894eb320b0eSRobert Watson .mpo_ipq_update = lomac_ipq_update, 2895eb320b0eSRobert Watson 28963f1a7a90SRobert Watson .mpo_kld_check_load = lomac_kld_check_load, 2897eb320b0eSRobert Watson 2898eb320b0eSRobert Watson .mpo_mbuf_copy_label = lomac_copy_label, 2899eb320b0eSRobert Watson .mpo_mbuf_destroy_label = lomac_destroy_label, 2900eb320b0eSRobert Watson .mpo_mbuf_init_label = lomac_init_label_waitcheck, 2901eb320b0eSRobert Watson 2902eb320b0eSRobert Watson .mpo_mount_create = lomac_mount_create, 2903eb320b0eSRobert Watson .mpo_mount_destroy_label = lomac_destroy_label, 2904eb320b0eSRobert Watson .mpo_mount_init_label = lomac_init_label, 2905eb320b0eSRobert Watson 2906eb320b0eSRobert Watson .mpo_netatalk_aarp_send = lomac_netatalk_aarp_send, 2907eb320b0eSRobert Watson 2908eb320b0eSRobert Watson .mpo_netinet_arp_send = lomac_netinet_arp_send, 2909eb320b0eSRobert Watson .mpo_netinet_firewall_reply = lomac_netinet_firewall_reply, 2910eb320b0eSRobert Watson .mpo_netinet_firewall_send = lomac_netinet_firewall_send, 2911eb320b0eSRobert Watson .mpo_netinet_fragment = lomac_netinet_fragment, 2912eb320b0eSRobert Watson .mpo_netinet_icmp_reply = lomac_netinet_icmp_reply, 2913eb320b0eSRobert Watson .mpo_netinet_igmp_send = lomac_netinet_igmp_send, 2914eb320b0eSRobert Watson 2915eb320b0eSRobert Watson .mpo_netinet6_nd6_send = lomac_netinet6_nd6_send, 2916eb320b0eSRobert Watson 29173f1a7a90SRobert Watson .mpo_pipe_check_ioctl = lomac_pipe_check_ioctl, 29183f1a7a90SRobert Watson .mpo_pipe_check_read = lomac_pipe_check_read, 29193f1a7a90SRobert Watson .mpo_pipe_check_relabel = lomac_pipe_check_relabel, 29203f1a7a90SRobert Watson .mpo_pipe_check_write = lomac_pipe_check_write, 2921eb320b0eSRobert Watson .mpo_pipe_copy_label = lomac_copy_label, 2922eb320b0eSRobert Watson .mpo_pipe_create = lomac_pipe_create, 2923eb320b0eSRobert Watson .mpo_pipe_destroy_label = lomac_destroy_label, 2924eb320b0eSRobert Watson .mpo_pipe_externalize_label = lomac_externalize_label, 2925eb320b0eSRobert Watson .mpo_pipe_init_label = lomac_init_label, 2926eb320b0eSRobert Watson .mpo_pipe_internalize_label = lomac_internalize_label, 2927eb320b0eSRobert Watson .mpo_pipe_relabel = lomac_pipe_relabel, 2928eb320b0eSRobert Watson 2929eb320b0eSRobert Watson .mpo_priv_check = lomac_priv_check, 2930eb320b0eSRobert Watson 29313f1a7a90SRobert Watson .mpo_proc_check_debug = lomac_proc_check_debug, 29323f1a7a90SRobert Watson .mpo_proc_check_sched = lomac_proc_check_sched, 29333f1a7a90SRobert Watson .mpo_proc_check_signal = lomac_proc_check_signal, 2934eb320b0eSRobert Watson .mpo_proc_create_swapper = lomac_proc_create_swapper, 2935eb320b0eSRobert Watson .mpo_proc_create_init = lomac_proc_create_init, 2936eb320b0eSRobert Watson .mpo_proc_destroy_label = lomac_proc_destroy_label, 2937eb320b0eSRobert Watson .mpo_proc_init_label = lomac_proc_init_label, 2938eb320b0eSRobert Watson 29393f1a7a90SRobert Watson .mpo_socket_check_deliver = lomac_socket_check_deliver, 29403f1a7a90SRobert Watson .mpo_socket_check_relabel = lomac_socket_check_relabel, 29413f1a7a90SRobert Watson .mpo_socket_check_visible = lomac_socket_check_visible, 2942eb320b0eSRobert Watson .mpo_socket_copy_label = lomac_copy_label, 2943eb320b0eSRobert Watson .mpo_socket_create = lomac_socket_create, 2944eb320b0eSRobert Watson .mpo_socket_create_mbuf = lomac_socket_create_mbuf, 2945eb320b0eSRobert Watson .mpo_socket_destroy_label = lomac_destroy_label, 2946eb320b0eSRobert Watson .mpo_socket_externalize_label = lomac_externalize_label, 2947eb320b0eSRobert Watson .mpo_socket_init_label = lomac_init_label_waitcheck, 2948eb320b0eSRobert Watson .mpo_socket_internalize_label = lomac_internalize_label, 2949eb320b0eSRobert Watson .mpo_socket_newconn = lomac_socket_newconn, 2950eb320b0eSRobert Watson .mpo_socket_relabel = lomac_socket_relabel, 2951eb320b0eSRobert Watson 2952eb320b0eSRobert Watson .mpo_socketpeer_destroy_label = lomac_destroy_label, 2953eb320b0eSRobert Watson .mpo_socketpeer_externalize_label = lomac_externalize_label, 2954eb320b0eSRobert Watson .mpo_socketpeer_init_label = lomac_init_label_waitcheck, 2955eb320b0eSRobert Watson .mpo_socketpeer_set_from_mbuf = lomac_socketpeer_set_from_mbuf, 2956eb320b0eSRobert Watson .mpo_socketpeer_set_from_socket = lomac_socketpeer_set_from_socket, 2957eb320b0eSRobert Watson 2958eb320b0eSRobert Watson .mpo_syncache_create_mbuf = lomac_syncache_create_mbuf, 2959eb320b0eSRobert Watson 29603f1a7a90SRobert Watson .mpo_system_check_acct = lomac_system_check_acct, 29613f1a7a90SRobert Watson .mpo_system_check_auditctl = lomac_system_check_auditctl, 29623f1a7a90SRobert Watson .mpo_system_check_swapoff = lomac_system_check_swapoff, 29633f1a7a90SRobert Watson .mpo_system_check_swapon = lomac_system_check_swapon, 29643f1a7a90SRobert Watson .mpo_system_check_sysctl = lomac_system_check_sysctl, 2965eb320b0eSRobert Watson 2966eb320b0eSRobert Watson .mpo_thread_userret = lomac_thread_userret, 2967eb320b0eSRobert Watson 2968eb320b0eSRobert Watson .mpo_vnode_associate_extattr = lomac_vnode_associate_extattr, 2969eb320b0eSRobert Watson .mpo_vnode_associate_singlelabel = lomac_vnode_associate_singlelabel, 29703f1a7a90SRobert Watson .mpo_vnode_check_access = lomac_vnode_check_open, 29713f1a7a90SRobert Watson .mpo_vnode_check_create = lomac_vnode_check_create, 29723f1a7a90SRobert Watson .mpo_vnode_check_deleteacl = lomac_vnode_check_deleteacl, 29733f1a7a90SRobert Watson .mpo_vnode_check_link = lomac_vnode_check_link, 29743f1a7a90SRobert Watson .mpo_vnode_check_mmap = lomac_vnode_check_mmap, 29753f1a7a90SRobert Watson .mpo_vnode_check_mmap_downgrade = lomac_vnode_check_mmap_downgrade, 29763f1a7a90SRobert Watson .mpo_vnode_check_open = lomac_vnode_check_open, 29773f1a7a90SRobert Watson .mpo_vnode_check_read = lomac_vnode_check_read, 29783f1a7a90SRobert Watson .mpo_vnode_check_relabel = lomac_vnode_check_relabel, 29793f1a7a90SRobert Watson .mpo_vnode_check_rename_from = lomac_vnode_check_rename_from, 29803f1a7a90SRobert Watson .mpo_vnode_check_rename_to = lomac_vnode_check_rename_to, 29813f1a7a90SRobert Watson .mpo_vnode_check_revoke = lomac_vnode_check_revoke, 29823f1a7a90SRobert Watson .mpo_vnode_check_setacl = lomac_vnode_check_setacl, 29833f1a7a90SRobert Watson .mpo_vnode_check_setextattr = lomac_vnode_check_setextattr, 29843f1a7a90SRobert Watson .mpo_vnode_check_setflags = lomac_vnode_check_setflags, 29853f1a7a90SRobert Watson .mpo_vnode_check_setmode = lomac_vnode_check_setmode, 29863f1a7a90SRobert Watson .mpo_vnode_check_setowner = lomac_vnode_check_setowner, 29873f1a7a90SRobert Watson .mpo_vnode_check_setutimes = lomac_vnode_check_setutimes, 29883f1a7a90SRobert Watson .mpo_vnode_check_unlink = lomac_vnode_check_unlink, 29893f1a7a90SRobert Watson .mpo_vnode_check_write = lomac_vnode_check_write, 2990eb320b0eSRobert Watson .mpo_vnode_copy_label = lomac_copy_label, 2991eb320b0eSRobert Watson .mpo_vnode_create_extattr = lomac_vnode_create_extattr, 2992eb320b0eSRobert Watson .mpo_vnode_destroy_label = lomac_destroy_label, 2993eb320b0eSRobert Watson .mpo_vnode_execve_transition = lomac_vnode_execve_transition, 2994eb320b0eSRobert Watson .mpo_vnode_execve_will_transition = lomac_vnode_execve_will_transition, 2995eb320b0eSRobert Watson .mpo_vnode_externalize_label = lomac_externalize_label, 2996eb320b0eSRobert Watson .mpo_vnode_init_label = lomac_init_label, 2997eb320b0eSRobert Watson .mpo_vnode_internalize_label = lomac_internalize_label, 2998eb320b0eSRobert Watson .mpo_vnode_relabel = lomac_vnode_relabel, 2999eb320b0eSRobert Watson .mpo_vnode_setlabel_extattr = lomac_vnode_setlabel_extattr, 3000db2661ceSRobert Watson }; 3001db2661ceSRobert Watson 30026356dba0SRobert Watson #define LOMAC_OBJECTS (MPC_OBJECT_CRED | \ 30036356dba0SRobert Watson /* MPC_OBJECT_PROC | */ \ 30046356dba0SRobert Watson MPC_OBJECT_VNODE | \ 30056356dba0SRobert Watson MPC_OBJECT_INPCB | \ 30066356dba0SRobert Watson MPC_OBJECT_SOCKET | \ 30076356dba0SRobert Watson MPC_OBJECT_DEVFS | \ 30086356dba0SRobert Watson MPC_OBJECT_MBUF | \ 30096356dba0SRobert Watson MPC_OBJECT_IPQ | \ 30106356dba0SRobert Watson MPC_OBJECT_IFNET | \ 30116356dba0SRobert Watson MPC_OBJECT_BPFDESC | \ 30126356dba0SRobert Watson MPC_OBJECT_PIPE | \ 30136356dba0SRobert Watson MPC_OBJECT_MOUNT | \ 30146356dba0SRobert Watson /* MPC_OBJECT_POSIXSEM | */ \ 30156356dba0SRobert Watson /* MPC_OBJECT_POSIXSHM | */ \ 30166356dba0SRobert Watson /* MPC_OBJECT_SYSVMSG | */ \ 30176356dba0SRobert Watson /* MPC_OBJECT_SYSVMSQ | */ \ 30186356dba0SRobert Watson /* MPC_OBJECT_SYSVSEM | */ \ 30196356dba0SRobert Watson /* MPC_OBJECT_SYSVSHM | */ \ 30206356dba0SRobert Watson MPC_OBJECT_SYNCACHE) 30216356dba0SRobert Watson 30223f1a7a90SRobert Watson MAC_POLICY_SET(&lomac_ops, mac_lomac, "TrustedBSD MAC/LOMAC", 30236356dba0SRobert Watson MPC_LOADTIME_FLAG_NOTLATE, &lomac_slot, LOMAC_OBJECTS); 3024