1db2661ceSRobert Watson /*- 2048e1287SRobert Watson * Copyright (c) 1999-2002, 2007-2008 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 } 996212ab0cfSRobert Watson 997212ab0cfSRobert Watson static void 998212ab0cfSRobert Watson lomac_cred_create_init(struct ucred *cred) 999212ab0cfSRobert Watson { 1000212ab0cfSRobert Watson struct mac_lomac *dest; 1001212ab0cfSRobert Watson 1002212ab0cfSRobert Watson dest = SLOT(cred->cr_label); 1003212ab0cfSRobert Watson 1004212ab0cfSRobert Watson lomac_set_single(dest, MAC_LOMAC_TYPE_HIGH, 0); 1005212ab0cfSRobert Watson lomac_set_range(dest, MAC_LOMAC_TYPE_LOW, 0, MAC_LOMAC_TYPE_HIGH, 0); 1006212ab0cfSRobert Watson } 1007212ab0cfSRobert Watson 1008212ab0cfSRobert Watson static void 1009212ab0cfSRobert Watson lomac_cred_create_swapper(struct ucred *cred) 1010212ab0cfSRobert Watson { 1011212ab0cfSRobert Watson struct mac_lomac *dest; 1012212ab0cfSRobert Watson 1013212ab0cfSRobert Watson dest = SLOT(cred->cr_label); 1014212ab0cfSRobert Watson 1015212ab0cfSRobert Watson lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0); 1016212ab0cfSRobert Watson lomac_set_range(dest, MAC_LOMAC_TYPE_LOW, 0, MAC_LOMAC_TYPE_HIGH, 0); 1017212ab0cfSRobert Watson } 1018212ab0cfSRobert Watson 1019eb320b0eSRobert Watson static void 1020eb320b0eSRobert Watson lomac_cred_relabel(struct ucred *cred, struct label *newlabel) 1021eb320b0eSRobert Watson { 1022eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1023eb320b0eSRobert Watson 1024eb320b0eSRobert Watson source = SLOT(newlabel); 1025eb320b0eSRobert Watson dest = SLOT(cred->cr_label); 1026eb320b0eSRobert Watson 1027eb320b0eSRobert Watson try_relabel(source, dest); 1028eb320b0eSRobert Watson } 1029eb320b0eSRobert Watson 1030eb320b0eSRobert Watson static void 1031eb320b0eSRobert Watson lomac_devfs_create_device(struct ucred *cred, struct mount *mp, 1032eb320b0eSRobert Watson struct cdev *dev, struct devfs_dirent *de, struct label *delabel) 1033eb320b0eSRobert Watson { 1034eb320b0eSRobert Watson struct mac_lomac *ml; 1035eb320b0eSRobert Watson int lomac_type; 1036eb320b0eSRobert Watson 1037eb320b0eSRobert Watson ml = SLOT(delabel); 1038eb320b0eSRobert Watson if (strcmp(dev->si_name, "null") == 0 || 1039eb320b0eSRobert Watson strcmp(dev->si_name, "zero") == 0 || 1040eb320b0eSRobert Watson strcmp(dev->si_name, "random") == 0 || 1041eb320b0eSRobert Watson strncmp(dev->si_name, "fd/", strlen("fd/")) == 0 || 1042eb320b0eSRobert Watson strncmp(dev->si_name, "ttyv", strlen("ttyv")) == 0) 1043eb320b0eSRobert Watson lomac_type = MAC_LOMAC_TYPE_EQUAL; 1044eb320b0eSRobert Watson else if (ptys_equal && 1045eb320b0eSRobert Watson (strncmp(dev->si_name, "ttyp", strlen("ttyp")) == 0 || 1046eb320b0eSRobert Watson strncmp(dev->si_name, "ptyp", strlen("ptyp")) == 0)) 1047eb320b0eSRobert Watson lomac_type = MAC_LOMAC_TYPE_EQUAL; 1048eb320b0eSRobert Watson else 1049eb320b0eSRobert Watson lomac_type = MAC_LOMAC_TYPE_HIGH; 1050eb320b0eSRobert Watson lomac_set_single(ml, lomac_type, 0); 1051eb320b0eSRobert Watson } 1052eb320b0eSRobert Watson 1053eb320b0eSRobert Watson static void 1054eb320b0eSRobert Watson lomac_devfs_create_directory(struct mount *mp, char *dirname, int dirnamelen, 1055eb320b0eSRobert Watson struct devfs_dirent *de, struct label *delabel) 1056eb320b0eSRobert Watson { 1057eb320b0eSRobert Watson struct mac_lomac *ml; 1058eb320b0eSRobert Watson 1059eb320b0eSRobert Watson ml = SLOT(delabel); 1060eb320b0eSRobert Watson lomac_set_single(ml, MAC_LOMAC_TYPE_HIGH, 0); 1061eb320b0eSRobert Watson } 1062eb320b0eSRobert Watson 1063eb320b0eSRobert Watson static void 1064eb320b0eSRobert Watson lomac_devfs_create_symlink(struct ucred *cred, struct mount *mp, 1065eb320b0eSRobert Watson struct devfs_dirent *dd, struct label *ddlabel, struct devfs_dirent *de, 1066eb320b0eSRobert Watson struct label *delabel) 1067eb320b0eSRobert Watson { 1068eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1069eb320b0eSRobert Watson 1070eb320b0eSRobert Watson source = SLOT(cred->cr_label); 1071eb320b0eSRobert Watson dest = SLOT(delabel); 1072eb320b0eSRobert Watson 1073eb320b0eSRobert Watson lomac_copy_single(source, dest); 1074eb320b0eSRobert Watson } 1075eb320b0eSRobert Watson 1076eb320b0eSRobert Watson static void 1077eb320b0eSRobert Watson lomac_devfs_update(struct mount *mp, struct devfs_dirent *de, 1078eb320b0eSRobert Watson struct label *delabel, struct vnode *vp, struct label *vplabel) 1079eb320b0eSRobert Watson { 1080eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1081eb320b0eSRobert Watson 1082eb320b0eSRobert Watson source = SLOT(vplabel); 1083eb320b0eSRobert Watson dest = SLOT(delabel); 1084eb320b0eSRobert Watson 1085eb320b0eSRobert Watson lomac_copy(source, dest); 1086eb320b0eSRobert Watson } 1087eb320b0eSRobert Watson 1088eb320b0eSRobert Watson static void 1089eb320b0eSRobert Watson lomac_devfs_vnode_associate(struct mount *mp, struct label *mplabel, 1090eb320b0eSRobert Watson struct devfs_dirent *de, struct label *delabel, struct vnode *vp, 1091eb320b0eSRobert Watson struct label *vplabel) 1092eb320b0eSRobert Watson { 1093eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1094eb320b0eSRobert Watson 1095eb320b0eSRobert Watson source = SLOT(delabel); 1096eb320b0eSRobert Watson dest = SLOT(vplabel); 1097eb320b0eSRobert Watson 1098eb320b0eSRobert Watson lomac_copy_single(source, dest); 1099eb320b0eSRobert Watson } 1100db2661ceSRobert Watson 1101db2661ceSRobert Watson static int 11023f1a7a90SRobert Watson lomac_ifnet_check_relabel(struct ucred *cred, struct ifnet *ifp, 110378007886SRobert Watson struct label *ifplabel, struct label *newlabel) 1104db2661ceSRobert Watson { 1105db2661ceSRobert Watson struct mac_lomac *subj, *new; 1106db2661ceSRobert Watson int error; 1107db2661ceSRobert Watson 1108eca8a663SRobert Watson subj = SLOT(cred->cr_label); 1109db2661ceSRobert Watson new = SLOT(newlabel); 1110db2661ceSRobert Watson 1111db2661ceSRobert Watson /* 11123f1a7a90SRobert Watson * If there is a LOMAC label update for the interface, it may be an 11133f1a7a90SRobert Watson * update of the single, range, or both. 1114db2661ceSRobert Watson */ 1115db2661ceSRobert Watson error = lomac_atmostflags(new, MAC_LOMAC_FLAGS_BOTH); 1116db2661ceSRobert Watson if (error) 1117db2661ceSRobert Watson return (error); 1118db2661ceSRobert Watson 1119db2661ceSRobert Watson /* 1120db2661ceSRobert Watson * Relabling network interfaces requires LOMAC privilege. 1121db2661ceSRobert Watson */ 11223f1a7a90SRobert Watson error = lomac_subject_privileged(subj); 1123db2661ceSRobert Watson if (error) 1124db2661ceSRobert Watson return (error); 1125db2661ceSRobert Watson 1126db2661ceSRobert Watson /* 1127db2661ceSRobert Watson * If the LOMAC label is to be changed, authorize as appropriate. 1128db2661ceSRobert Watson */ 1129db2661ceSRobert Watson if (new->ml_flags & MAC_LOMAC_FLAGS_BOTH) { 1130db2661ceSRobert Watson /* 113184bdb083SRobert Watson * Fill in the missing parts from the previous label. 113284bdb083SRobert Watson */ 113384bdb083SRobert Watson if ((new->ml_flags & MAC_LOMAC_FLAG_SINGLE) == 0) 11343f1a7a90SRobert Watson lomac_copy_single(subj, new); 113584bdb083SRobert Watson if ((new->ml_flags & MAC_LOMAC_FLAG_RANGE) == 0) 11363f1a7a90SRobert Watson lomac_copy_range(subj, new); 113784bdb083SRobert Watson 113884bdb083SRobert Watson /* 1139db2661ceSRobert Watson * Rely on the traditional superuser status for the LOMAC 1140db2661ceSRobert Watson * interface relabel requirements. XXXMAC: This will go 1141db2661ceSRobert Watson * away. 1142acd3428bSRobert Watson * 1143acd3428bSRobert Watson * XXXRW: This is also redundant to a higher layer check. 1144db2661ceSRobert Watson */ 1145acd3428bSRobert Watson error = priv_check_cred(cred, PRIV_NET_SETIFMAC, 0); 1146db2661ceSRobert Watson if (error) 1147db2661ceSRobert Watson return (EPERM); 1148db2661ceSRobert Watson 1149db2661ceSRobert Watson /* 1150db2661ceSRobert Watson * XXXMAC: Additional consistency tests regarding the single 1151db2661ceSRobert Watson * and the range of the new label might be performed here. 1152db2661ceSRobert Watson */ 1153db2661ceSRobert Watson } 1154db2661ceSRobert Watson 1155db2661ceSRobert Watson return (0); 1156db2661ceSRobert Watson } 1157db2661ceSRobert Watson 1158db2661ceSRobert Watson static int 11593f1a7a90SRobert Watson lomac_ifnet_check_transmit(struct ifnet *ifp, struct label *ifplabel, 116078007886SRobert Watson struct mbuf *m, struct label *mlabel) 1161db2661ceSRobert Watson { 1162db2661ceSRobert Watson struct mac_lomac *p, *i; 1163db2661ceSRobert Watson 11643f1a7a90SRobert Watson if (!lomac_enabled) 1165db2661ceSRobert Watson return (0); 1166db2661ceSRobert Watson 116778007886SRobert Watson p = SLOT(mlabel); 116878007886SRobert Watson i = SLOT(ifplabel); 1169db2661ceSRobert Watson 11703f1a7a90SRobert Watson return (lomac_single_in_range(p, i) ? 0 : EACCES); 1171db2661ceSRobert Watson } 1172db2661ceSRobert Watson 1173eb320b0eSRobert Watson static void 1174eb320b0eSRobert Watson lomac_ifnet_create(struct ifnet *ifp, struct label *ifplabel) 1175eb320b0eSRobert Watson { 1176eb320b0eSRobert Watson char tifname[IFNAMSIZ], *p, *q; 1177eb320b0eSRobert Watson char tiflist[sizeof(trusted_interfaces)]; 1178eb320b0eSRobert Watson struct mac_lomac *dest; 1179eb320b0eSRobert Watson int len, grade; 1180eb320b0eSRobert Watson 1181eb320b0eSRobert Watson dest = SLOT(ifplabel); 1182eb320b0eSRobert Watson 1183eb320b0eSRobert Watson if (ifp->if_type == IFT_LOOP) { 1184eb320b0eSRobert Watson grade = MAC_LOMAC_TYPE_EQUAL; 1185eb320b0eSRobert Watson goto set; 1186eb320b0eSRobert Watson } 1187eb320b0eSRobert Watson 1188eb320b0eSRobert Watson if (trust_all_interfaces) { 1189eb320b0eSRobert Watson grade = MAC_LOMAC_TYPE_HIGH; 1190eb320b0eSRobert Watson goto set; 1191eb320b0eSRobert Watson } 1192eb320b0eSRobert Watson 1193eb320b0eSRobert Watson grade = MAC_LOMAC_TYPE_LOW; 1194eb320b0eSRobert Watson 1195eb320b0eSRobert Watson if (trusted_interfaces[0] == '\0' || 1196eb320b0eSRobert Watson !strvalid(trusted_interfaces, sizeof(trusted_interfaces))) 1197eb320b0eSRobert Watson goto set; 1198eb320b0eSRobert Watson 1199eb320b0eSRobert Watson bzero(tiflist, sizeof(tiflist)); 1200eb320b0eSRobert Watson for (p = trusted_interfaces, q = tiflist; *p != '\0'; p++, q++) 1201eb320b0eSRobert Watson if(*p != ' ' && *p != '\t') 1202eb320b0eSRobert Watson *q = *p; 1203eb320b0eSRobert Watson 1204eb320b0eSRobert Watson for (p = q = tiflist;; p++) { 1205eb320b0eSRobert Watson if (*p == ',' || *p == '\0') { 1206eb320b0eSRobert Watson len = p - q; 1207eb320b0eSRobert Watson if (len < IFNAMSIZ) { 1208eb320b0eSRobert Watson bzero(tifname, sizeof(tifname)); 1209eb320b0eSRobert Watson bcopy(q, tifname, len); 1210eb320b0eSRobert Watson if (strcmp(tifname, ifp->if_xname) == 0) { 1211eb320b0eSRobert Watson grade = MAC_LOMAC_TYPE_HIGH; 1212eb320b0eSRobert Watson break; 1213eb320b0eSRobert Watson } 1214eb320b0eSRobert Watson } 1215eb320b0eSRobert Watson else { 1216eb320b0eSRobert Watson *p = '\0'; 1217eb320b0eSRobert Watson printf("MAC/LOMAC warning: interface name " 1218eb320b0eSRobert Watson "\"%s\" is too long (must be < %d)\n", 1219eb320b0eSRobert Watson q, IFNAMSIZ); 1220eb320b0eSRobert Watson } 1221eb320b0eSRobert Watson if (*p == '\0') 1222eb320b0eSRobert Watson break; 1223eb320b0eSRobert Watson q = p + 1; 1224eb320b0eSRobert Watson } 1225eb320b0eSRobert Watson } 1226eb320b0eSRobert Watson set: 1227eb320b0eSRobert Watson lomac_set_single(dest, grade, 0); 1228eb320b0eSRobert Watson lomac_set_range(dest, grade, 0, grade, 0); 1229eb320b0eSRobert Watson } 1230eb320b0eSRobert Watson 1231eb320b0eSRobert Watson static void 1232eb320b0eSRobert Watson lomac_ifnet_create_mbuf(struct ifnet *ifp, struct label *ifplabel, 1233eb320b0eSRobert Watson struct mbuf *m, struct label *mlabel) 1234eb320b0eSRobert Watson { 1235eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1236eb320b0eSRobert Watson 1237eb320b0eSRobert Watson source = SLOT(ifplabel); 1238eb320b0eSRobert Watson dest = SLOT(mlabel); 1239eb320b0eSRobert Watson 1240eb320b0eSRobert Watson lomac_copy_single(source, dest); 1241eb320b0eSRobert Watson } 1242eb320b0eSRobert Watson 1243eb320b0eSRobert Watson static void 1244eb320b0eSRobert Watson lomac_ifnet_relabel(struct ucred *cred, struct ifnet *ifp, 1245eb320b0eSRobert Watson struct label *ifplabel, struct label *newlabel) 1246eb320b0eSRobert Watson { 1247eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1248eb320b0eSRobert Watson 1249eb320b0eSRobert Watson source = SLOT(newlabel); 1250eb320b0eSRobert Watson dest = SLOT(ifplabel); 1251eb320b0eSRobert Watson 1252eb320b0eSRobert Watson try_relabel(source, dest); 1253eb320b0eSRobert Watson } 1254eb320b0eSRobert Watson 1255db2661ceSRobert Watson static int 12563f1a7a90SRobert Watson lomac_inpcb_check_deliver(struct inpcb *inp, struct label *inplabel, 1257a557af22SRobert Watson struct mbuf *m, struct label *mlabel) 1258a557af22SRobert Watson { 1259a557af22SRobert Watson struct mac_lomac *p, *i; 1260a557af22SRobert Watson 12613f1a7a90SRobert Watson if (!lomac_enabled) 1262a557af22SRobert Watson return (0); 1263a557af22SRobert Watson 1264a557af22SRobert Watson p = SLOT(mlabel); 1265a557af22SRobert Watson i = SLOT(inplabel); 1266a557af22SRobert Watson 12673f1a7a90SRobert Watson return (lomac_equal_single(p, i) ? 0 : EACCES); 1268a557af22SRobert Watson } 1269a557af22SRobert Watson 12707fb179baSBjoern A. Zeeb static int 12717fb179baSBjoern A. Zeeb lomac_inpcb_check_visible(struct ucred *cred, struct inpcb *inp, 12727fb179baSBjoern A. Zeeb struct label *inplabel) 12737fb179baSBjoern A. Zeeb { 12747fb179baSBjoern A. Zeeb struct mac_lomac *subj, *obj; 12757fb179baSBjoern A. Zeeb 12767fb179baSBjoern A. Zeeb if (!lomac_enabled) 12777fb179baSBjoern A. Zeeb return (0); 12787fb179baSBjoern A. Zeeb 12797fb179baSBjoern A. Zeeb subj = SLOT(cred->cr_label); 12807fb179baSBjoern A. Zeeb obj = SLOT(inplabel); 12817fb179baSBjoern A. Zeeb 12827fb179baSBjoern A. Zeeb if (!lomac_dominate_single(obj, subj)) 12837fb179baSBjoern A. Zeeb return (ENOENT); 12847fb179baSBjoern A. Zeeb 12857fb179baSBjoern A. Zeeb return (0); 12867fb179baSBjoern A. Zeeb } 12877fb179baSBjoern A. Zeeb 1288eb320b0eSRobert Watson static void 1289eb320b0eSRobert Watson lomac_inpcb_create(struct socket *so, struct label *solabel, 1290eb320b0eSRobert Watson struct inpcb *inp, struct label *inplabel) 1291eb320b0eSRobert Watson { 1292eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1293eb320b0eSRobert Watson 1294eb320b0eSRobert Watson source = SLOT(solabel); 1295eb320b0eSRobert Watson dest = SLOT(inplabel); 1296eb320b0eSRobert Watson 1297eb320b0eSRobert Watson lomac_copy_single(source, dest); 1298eb320b0eSRobert Watson } 1299eb320b0eSRobert Watson 1300eb320b0eSRobert Watson static void 1301eb320b0eSRobert Watson lomac_inpcb_create_mbuf(struct inpcb *inp, struct label *inplabel, 1302eb320b0eSRobert Watson struct mbuf *m, struct label *mlabel) 1303eb320b0eSRobert Watson { 1304eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1305eb320b0eSRobert Watson 1306eb320b0eSRobert Watson source = SLOT(inplabel); 1307eb320b0eSRobert Watson dest = SLOT(mlabel); 1308eb320b0eSRobert Watson 1309eb320b0eSRobert Watson lomac_copy_single(source, dest); 1310eb320b0eSRobert Watson } 1311eb320b0eSRobert Watson 1312eb320b0eSRobert Watson static void 1313eb320b0eSRobert Watson lomac_inpcb_sosetlabel(struct socket *so, struct label *solabel, 1314eb320b0eSRobert Watson struct inpcb *inp, struct label *inplabel) 1315eb320b0eSRobert Watson { 1316eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1317eb320b0eSRobert Watson 1318eb320b0eSRobert Watson source = SLOT(solabel); 1319eb320b0eSRobert Watson dest = SLOT(inplabel); 1320eb320b0eSRobert Watson 1321eb320b0eSRobert Watson lomac_copy_single(source, dest); 1322eb320b0eSRobert Watson } 1323eb320b0eSRobert Watson 1324eb320b0eSRobert Watson static void 1325048e1287SRobert Watson lomac_ip6q_create(struct mbuf *m, struct label *mlabel, struct ip6q *q6, 1326048e1287SRobert Watson struct label *q6label) 1327048e1287SRobert Watson { 1328048e1287SRobert Watson struct mac_lomac *source, *dest; 1329048e1287SRobert Watson 1330048e1287SRobert Watson source = SLOT(mlabel); 1331048e1287SRobert Watson dest = SLOT(q6label); 1332048e1287SRobert Watson 1333048e1287SRobert Watson lomac_copy_single(source, dest); 1334048e1287SRobert Watson } 1335048e1287SRobert Watson 1336048e1287SRobert Watson static int 1337048e1287SRobert Watson lomac_ip6q_match(struct mbuf *m, struct label *mlabel, struct ip6q *q6, 1338048e1287SRobert Watson struct label *q6label) 1339048e1287SRobert Watson { 1340048e1287SRobert Watson struct mac_lomac *a, *b; 1341048e1287SRobert Watson 1342048e1287SRobert Watson a = SLOT(q6label); 1343048e1287SRobert Watson b = SLOT(mlabel); 1344048e1287SRobert Watson 1345048e1287SRobert Watson return (lomac_equal_single(a, b)); 1346048e1287SRobert Watson } 1347048e1287SRobert Watson 1348048e1287SRobert Watson static void 1349048e1287SRobert Watson lomac_ip6q_reassemble(struct ip6q *q6, struct label *q6label, struct mbuf *m, 1350048e1287SRobert Watson struct label *mlabel) 1351048e1287SRobert Watson { 1352048e1287SRobert Watson struct mac_lomac *source, *dest; 1353048e1287SRobert Watson 1354048e1287SRobert Watson source = SLOT(q6label); 1355048e1287SRobert Watson dest = SLOT(mlabel); 1356048e1287SRobert Watson 1357048e1287SRobert Watson /* Just use the head, since we require them all to match. */ 1358048e1287SRobert Watson lomac_copy_single(source, dest); 1359048e1287SRobert Watson } 1360048e1287SRobert Watson 1361048e1287SRobert Watson static void 1362048e1287SRobert Watson lomac_ip6q_update(struct mbuf *m, struct label *mlabel, struct ip6q *q6, 1363048e1287SRobert Watson struct label *q6label) 1364048e1287SRobert Watson { 1365048e1287SRobert Watson 1366048e1287SRobert Watson /* NOOP: we only accept matching labels, so no need to update */ 1367048e1287SRobert Watson } 1368048e1287SRobert Watson 1369048e1287SRobert Watson static void 137037f44cb4SRobert Watson lomac_ipq_create(struct mbuf *m, struct label *mlabel, struct ipq *q, 137137f44cb4SRobert Watson struct label *qlabel) 1372eb320b0eSRobert Watson { 1373eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1374eb320b0eSRobert Watson 1375eb320b0eSRobert Watson source = SLOT(mlabel); 137637f44cb4SRobert Watson dest = SLOT(qlabel); 1377eb320b0eSRobert Watson 1378eb320b0eSRobert Watson lomac_copy_single(source, dest); 1379eb320b0eSRobert Watson } 1380eb320b0eSRobert Watson 1381eb320b0eSRobert Watson static int 138237f44cb4SRobert Watson lomac_ipq_match(struct mbuf *m, struct label *mlabel, struct ipq *q, 138337f44cb4SRobert Watson struct label *qlabel) 1384eb320b0eSRobert Watson { 1385eb320b0eSRobert Watson struct mac_lomac *a, *b; 1386eb320b0eSRobert Watson 138737f44cb4SRobert Watson a = SLOT(qlabel); 1388eb320b0eSRobert Watson b = SLOT(mlabel); 1389eb320b0eSRobert Watson 1390eb320b0eSRobert Watson return (lomac_equal_single(a, b)); 1391eb320b0eSRobert Watson } 1392eb320b0eSRobert Watson 1393eb320b0eSRobert Watson static void 139437f44cb4SRobert Watson lomac_ipq_reassemble(struct ipq *q, struct label *qlabel, struct mbuf *m, 139537f44cb4SRobert Watson struct label *mlabel) 1396eb320b0eSRobert Watson { 1397eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1398eb320b0eSRobert Watson 139937f44cb4SRobert Watson source = SLOT(qlabel); 1400eb320b0eSRobert Watson dest = SLOT(mlabel); 1401eb320b0eSRobert Watson 1402eb320b0eSRobert Watson /* Just use the head, since we require them all to match. */ 1403eb320b0eSRobert Watson lomac_copy_single(source, dest); 1404eb320b0eSRobert Watson } 1405eb320b0eSRobert Watson 1406eb320b0eSRobert Watson static void 140737f44cb4SRobert Watson lomac_ipq_update(struct mbuf *m, struct label *mlabel, struct ipq *q, 140837f44cb4SRobert Watson struct label *qlabel) 1409eb320b0eSRobert Watson { 1410eb320b0eSRobert Watson 1411eb320b0eSRobert Watson /* NOOP: we only accept matching labels, so no need to update */ 1412eb320b0eSRobert Watson } 1413eb320b0eSRobert Watson 1414a557af22SRobert Watson static int 14153f1a7a90SRobert Watson lomac_kld_check_load(struct ucred *cred, struct vnode *vp, 141678007886SRobert Watson struct label *vplabel) 1417db2661ceSRobert Watson { 1418db2661ceSRobert Watson struct mac_lomac *subj, *obj; 1419db2661ceSRobert Watson 14203f1a7a90SRobert Watson if (!lomac_enabled) 1421db2661ceSRobert Watson return (0); 1422db2661ceSRobert Watson 1423eca8a663SRobert Watson subj = SLOT(cred->cr_label); 142478007886SRobert Watson obj = SLOT(vplabel); 1425db2661ceSRobert Watson 14263f1a7a90SRobert Watson if (lomac_subject_privileged(subj)) 1427db2661ceSRobert Watson return (EPERM); 1428db2661ceSRobert Watson 14293f1a7a90SRobert Watson if (!lomac_high_single(obj)) 1430db2661ceSRobert Watson return (EACCES); 1431db2661ceSRobert Watson 1432db2661ceSRobert Watson return (0); 1433db2661ceSRobert Watson } 1434db2661ceSRobert Watson 1435eb320b0eSRobert Watson static void 1436eb320b0eSRobert Watson lomac_mount_create(struct ucred *cred, struct mount *mp, 1437eb320b0eSRobert Watson struct label *mplabel) 1438eb320b0eSRobert Watson { 1439eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1440eb320b0eSRobert Watson 1441eb320b0eSRobert Watson source = SLOT(cred->cr_label); 1442eb320b0eSRobert Watson dest = SLOT(mplabel); 1443eb320b0eSRobert Watson lomac_copy_single(source, dest); 1444eb320b0eSRobert Watson } 1445eb320b0eSRobert Watson 1446eb320b0eSRobert Watson static void 1447eb320b0eSRobert Watson lomac_netatalk_aarp_send(struct ifnet *ifp, struct label *ifplabel, 1448eb320b0eSRobert Watson struct mbuf *m, struct label *mlabel) 1449eb320b0eSRobert Watson { 1450eb320b0eSRobert Watson struct mac_lomac *dest; 1451eb320b0eSRobert Watson 1452eb320b0eSRobert Watson dest = SLOT(mlabel); 1453eb320b0eSRobert Watson 1454eb320b0eSRobert Watson lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0); 1455eb320b0eSRobert Watson } 1456eb320b0eSRobert Watson 1457eb320b0eSRobert Watson static void 1458eb320b0eSRobert Watson lomac_netinet_arp_send(struct ifnet *ifp, struct label *ifplabel, 1459eb320b0eSRobert Watson struct mbuf *m, struct label *mlabel) 1460eb320b0eSRobert Watson { 1461eb320b0eSRobert Watson struct mac_lomac *dest; 1462eb320b0eSRobert Watson 1463eb320b0eSRobert Watson dest = SLOT(mlabel); 1464eb320b0eSRobert Watson 1465eb320b0eSRobert Watson lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0); 1466eb320b0eSRobert Watson } 1467eb320b0eSRobert Watson 1468eb320b0eSRobert Watson static void 1469eb320b0eSRobert Watson lomac_netinet_firewall_reply(struct mbuf *mrecv, struct label *mrecvlabel, 1470eb320b0eSRobert Watson struct mbuf *msend, struct label *msendlabel) 1471eb320b0eSRobert Watson { 1472eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1473eb320b0eSRobert Watson 1474eb320b0eSRobert Watson source = SLOT(mrecvlabel); 1475eb320b0eSRobert Watson dest = SLOT(msendlabel); 1476eb320b0eSRobert Watson 1477eb320b0eSRobert Watson lomac_copy_single(source, dest); 1478eb320b0eSRobert Watson } 1479eb320b0eSRobert Watson 1480eb320b0eSRobert Watson static void 1481eb320b0eSRobert Watson lomac_netinet_firewall_send(struct mbuf *m, struct label *mlabel) 1482eb320b0eSRobert Watson { 1483eb320b0eSRobert Watson struct mac_lomac *dest; 1484eb320b0eSRobert Watson 1485eb320b0eSRobert Watson dest = SLOT(mlabel); 1486eb320b0eSRobert Watson 1487eb320b0eSRobert Watson /* XXX: where is the label for the firewall really comming from? */ 1488eb320b0eSRobert Watson lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0); 1489eb320b0eSRobert Watson } 1490eb320b0eSRobert Watson 1491eb320b0eSRobert Watson static void 1492eb320b0eSRobert Watson lomac_netinet_fragment(struct mbuf *m, struct label *mlabel, 1493eb320b0eSRobert Watson struct mbuf *frag, struct label *fraglabel) 1494eb320b0eSRobert Watson { 1495eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1496eb320b0eSRobert Watson 1497eb320b0eSRobert Watson source = SLOT(mlabel); 1498eb320b0eSRobert Watson dest = SLOT(fraglabel); 1499eb320b0eSRobert Watson 1500eb320b0eSRobert Watson lomac_copy_single(source, dest); 1501eb320b0eSRobert Watson } 1502eb320b0eSRobert Watson 1503eb320b0eSRobert Watson static void 1504eb320b0eSRobert Watson lomac_netinet_icmp_reply(struct mbuf *mrecv, struct label *mrecvlabel, 1505eb320b0eSRobert Watson struct mbuf *msend, struct label *msendlabel) 1506eb320b0eSRobert Watson { 1507eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1508eb320b0eSRobert Watson 1509eb320b0eSRobert Watson source = SLOT(mrecvlabel); 1510eb320b0eSRobert Watson dest = SLOT(msendlabel); 1511eb320b0eSRobert Watson 1512eb320b0eSRobert Watson lomac_copy_single(source, dest); 1513eb320b0eSRobert Watson } 1514eb320b0eSRobert Watson 1515eb320b0eSRobert Watson static void 1516eb320b0eSRobert Watson lomac_netinet_igmp_send(struct ifnet *ifp, struct label *ifplabel, 1517eb320b0eSRobert Watson struct mbuf *m, struct label *mlabel) 1518eb320b0eSRobert Watson { 1519eb320b0eSRobert Watson struct mac_lomac *dest; 1520eb320b0eSRobert Watson 1521eb320b0eSRobert Watson dest = SLOT(mlabel); 1522eb320b0eSRobert Watson 1523eb320b0eSRobert Watson lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0); 1524eb320b0eSRobert Watson } 1525eb320b0eSRobert Watson 1526eb320b0eSRobert Watson static void 1527eb320b0eSRobert Watson lomac_netinet6_nd6_send(struct ifnet *ifp, struct label *ifplabel, 1528eb320b0eSRobert Watson struct mbuf *m, struct label *mlabel) 1529eb320b0eSRobert Watson { 1530eb320b0eSRobert Watson struct mac_lomac *dest; 1531eb320b0eSRobert Watson 1532eb320b0eSRobert Watson dest = SLOT(mlabel); 1533eb320b0eSRobert Watson 1534eb320b0eSRobert Watson lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0); 1535eb320b0eSRobert Watson } 1536eb320b0eSRobert Watson 1537db2661ceSRobert Watson static int 15383f1a7a90SRobert Watson lomac_pipe_check_ioctl(struct ucred *cred, struct pipepair *pp, 153978007886SRobert Watson struct label *pplabel, unsigned long cmd, void /* caddr_t */ *data) 1540db2661ceSRobert Watson { 1541db2661ceSRobert Watson 15423f1a7a90SRobert Watson if (!lomac_enabled) 1543db2661ceSRobert Watson return (0); 1544db2661ceSRobert Watson 1545db2661ceSRobert Watson /* XXX: This will be implemented soon... */ 1546db2661ceSRobert Watson 1547db2661ceSRobert Watson return (0); 1548db2661ceSRobert Watson } 1549db2661ceSRobert Watson 1550db2661ceSRobert Watson static int 15513f1a7a90SRobert Watson lomac_pipe_check_read(struct ucred *cred, struct pipepair *pp, 155278007886SRobert Watson struct label *pplabel) 1553db2661ceSRobert Watson { 1554db2661ceSRobert Watson struct mac_lomac *subj, *obj; 1555db2661ceSRobert Watson 15563f1a7a90SRobert Watson if (!lomac_enabled) 1557db2661ceSRobert Watson return (0); 1558db2661ceSRobert Watson 1559eca8a663SRobert Watson subj = SLOT(cred->cr_label); 156078007886SRobert Watson obj = SLOT(pplabel); 1561db2661ceSRobert Watson 15623f1a7a90SRobert Watson if (!lomac_dominate_single(obj, subj)) 1563db2661ceSRobert Watson return (maybe_demote(subj, obj, "reading", "pipe", NULL)); 1564db2661ceSRobert Watson 1565db2661ceSRobert Watson return (0); 1566db2661ceSRobert Watson } 1567db2661ceSRobert Watson 1568db2661ceSRobert Watson static int 15693f1a7a90SRobert Watson lomac_pipe_check_relabel(struct ucred *cred, struct pipepair *pp, 157078007886SRobert Watson struct label *pplabel, struct label *newlabel) 1571db2661ceSRobert Watson { 1572db2661ceSRobert Watson struct mac_lomac *subj, *obj, *new; 1573db2661ceSRobert Watson int error; 1574db2661ceSRobert Watson 1575db2661ceSRobert Watson new = SLOT(newlabel); 1576eca8a663SRobert Watson subj = SLOT(cred->cr_label); 157778007886SRobert Watson obj = SLOT(pplabel); 1578db2661ceSRobert Watson 1579db2661ceSRobert Watson /* 15803f1a7a90SRobert Watson * If there is a LOMAC label update for a pipe, it must be a single 15813f1a7a90SRobert Watson * update. 1582db2661ceSRobert Watson */ 1583db2661ceSRobert Watson error = lomac_atmostflags(new, MAC_LOMAC_FLAG_SINGLE); 1584db2661ceSRobert Watson if (error) 1585db2661ceSRobert Watson return (error); 1586db2661ceSRobert Watson 1587db2661ceSRobert Watson /* 1588db2661ceSRobert Watson * To perform a relabel of a pipe (LOMAC label or not), LOMAC must 1589db2661ceSRobert Watson * authorize the relabel. 1590db2661ceSRobert Watson */ 15913f1a7a90SRobert Watson if (!lomac_single_in_range(obj, subj)) 1592db2661ceSRobert Watson return (EPERM); 1593db2661ceSRobert Watson 1594db2661ceSRobert Watson /* 1595db2661ceSRobert Watson * If the LOMAC label is to be changed, authorize as appropriate. 1596db2661ceSRobert Watson */ 1597db2661ceSRobert Watson if (new->ml_flags & MAC_LOMAC_FLAG_SINGLE) { 1598db2661ceSRobert Watson /* 1599db2661ceSRobert Watson * To change the LOMAC label on a pipe, the new pipe label 1600db2661ceSRobert Watson * must be in the subject range. 1601db2661ceSRobert Watson */ 16023f1a7a90SRobert Watson if (!lomac_single_in_range(new, subj)) 1603db2661ceSRobert Watson return (EPERM); 1604db2661ceSRobert Watson 1605db2661ceSRobert Watson /* 1606db2661ceSRobert Watson * To change the LOMAC label on a pipe to be EQUAL, the 1607db2661ceSRobert Watson * subject must have appropriate privilege. 1608db2661ceSRobert Watson */ 16093f1a7a90SRobert Watson if (lomac_contains_equal(new)) { 16103f1a7a90SRobert Watson error = lomac_subject_privileged(subj); 1611db2661ceSRobert Watson if (error) 1612db2661ceSRobert Watson return (error); 1613db2661ceSRobert Watson } 1614db2661ceSRobert Watson } 1615db2661ceSRobert Watson 1616db2661ceSRobert Watson return (0); 1617db2661ceSRobert Watson } 1618db2661ceSRobert Watson 1619db2661ceSRobert Watson static int 16203f1a7a90SRobert Watson lomac_pipe_check_write(struct ucred *cred, struct pipepair *pp, 162178007886SRobert Watson struct label *pplabel) 1622db2661ceSRobert Watson { 1623db2661ceSRobert Watson struct mac_lomac *subj, *obj; 1624db2661ceSRobert Watson 16253f1a7a90SRobert Watson if (!lomac_enabled) 1626db2661ceSRobert Watson return (0); 1627db2661ceSRobert Watson 1628eca8a663SRobert Watson subj = SLOT(cred->cr_label); 162978007886SRobert Watson obj = SLOT(pplabel); 1630db2661ceSRobert Watson 16313f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 1632db2661ceSRobert Watson return (EACCES); 1633db2661ceSRobert Watson 1634db2661ceSRobert Watson return (0); 1635db2661ceSRobert Watson } 1636db2661ceSRobert Watson 1637eb320b0eSRobert Watson static void 1638eb320b0eSRobert Watson lomac_pipe_create(struct ucred *cred, struct pipepair *pp, 1639eb320b0eSRobert Watson struct label *pplabel) 1640db2661ceSRobert Watson { 1641eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1642db2661ceSRobert Watson 1643eb320b0eSRobert Watson source = SLOT(cred->cr_label); 1644eb320b0eSRobert Watson dest = SLOT(pplabel); 1645db2661ceSRobert Watson 1646eb320b0eSRobert Watson lomac_copy_single(source, dest); 1647db2661ceSRobert Watson } 1648db2661ceSRobert Watson 1649eb320b0eSRobert Watson static void 1650eb320b0eSRobert Watson lomac_pipe_relabel(struct ucred *cred, struct pipepair *pp, 1651eb320b0eSRobert Watson struct label *pplabel, struct label *newlabel) 1652db2661ceSRobert Watson { 1653eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1654db2661ceSRobert Watson 1655eb320b0eSRobert Watson source = SLOT(newlabel); 1656eb320b0eSRobert Watson dest = SLOT(pplabel); 1657db2661ceSRobert Watson 1658eb320b0eSRobert Watson try_relabel(source, dest); 1659db2661ceSRobert Watson } 1660db2661ceSRobert Watson 1661c14d15aeSRobert Watson /* 1662c14d15aeSRobert Watson * Some system privileges are allowed regardless of integrity grade; others 1663c14d15aeSRobert Watson * are allowed only when running with privilege with respect to the LOMAC 1664c14d15aeSRobert Watson * policy as they might otherwise allow bypassing of the integrity policy. 1665c14d15aeSRobert Watson */ 1666c14d15aeSRobert Watson static int 16673f1a7a90SRobert Watson lomac_priv_check(struct ucred *cred, int priv) 1668c14d15aeSRobert Watson { 1669c14d15aeSRobert Watson struct mac_lomac *subj; 1670c14d15aeSRobert Watson int error; 1671c14d15aeSRobert Watson 16723f1a7a90SRobert Watson if (!lomac_enabled) 1673c14d15aeSRobert Watson return (0); 1674c14d15aeSRobert Watson 1675c14d15aeSRobert Watson /* 1676c14d15aeSRobert Watson * Exempt only specific privileges from the LOMAC integrity policy. 1677c14d15aeSRobert Watson */ 1678c14d15aeSRobert Watson switch (priv) { 1679c14d15aeSRobert Watson case PRIV_KTRACE: 1680c14d15aeSRobert Watson case PRIV_MSGBUF: 1681c14d15aeSRobert Watson 1682c14d15aeSRobert Watson /* 1683c14d15aeSRobert Watson * Allow processes to manipulate basic process audit properties, and 1684c14d15aeSRobert Watson * to submit audit records. 1685c14d15aeSRobert Watson */ 1686c14d15aeSRobert Watson case PRIV_AUDIT_GETAUDIT: 1687c14d15aeSRobert Watson case PRIV_AUDIT_SETAUDIT: 1688c14d15aeSRobert Watson case PRIV_AUDIT_SUBMIT: 1689c14d15aeSRobert Watson 1690c14d15aeSRobert Watson /* 1691c14d15aeSRobert Watson * Allow processes to manipulate their regular UNIX credentials. 1692c14d15aeSRobert Watson */ 1693c14d15aeSRobert Watson case PRIV_CRED_SETUID: 1694c14d15aeSRobert Watson case PRIV_CRED_SETEUID: 1695c14d15aeSRobert Watson case PRIV_CRED_SETGID: 1696c14d15aeSRobert Watson case PRIV_CRED_SETEGID: 1697c14d15aeSRobert Watson case PRIV_CRED_SETGROUPS: 1698c14d15aeSRobert Watson case PRIV_CRED_SETREUID: 1699c14d15aeSRobert Watson case PRIV_CRED_SETREGID: 1700c14d15aeSRobert Watson case PRIV_CRED_SETRESUID: 1701c14d15aeSRobert Watson case PRIV_CRED_SETRESGID: 1702c14d15aeSRobert Watson 1703c14d15aeSRobert Watson /* 1704c14d15aeSRobert Watson * Allow processes to perform system monitoring. 1705c14d15aeSRobert Watson */ 1706c14d15aeSRobert Watson case PRIV_SEEOTHERGIDS: 1707c14d15aeSRobert Watson case PRIV_SEEOTHERUIDS: 1708c14d15aeSRobert Watson break; 1709c14d15aeSRobert Watson 1710c14d15aeSRobert Watson /* 1711c14d15aeSRobert Watson * Allow access to general process debugging facilities. We 1712c14d15aeSRobert Watson * separately control debugging based on MAC label. 1713c14d15aeSRobert Watson */ 1714c14d15aeSRobert Watson case PRIV_DEBUG_DIFFCRED: 1715c14d15aeSRobert Watson case PRIV_DEBUG_SUGID: 1716c14d15aeSRobert Watson case PRIV_DEBUG_UNPRIV: 1717c14d15aeSRobert Watson 1718c14d15aeSRobert Watson /* 1719c14d15aeSRobert Watson * Allow manipulating jails. 1720c14d15aeSRobert Watson */ 1721c14d15aeSRobert Watson case PRIV_JAIL_ATTACH: 1722c14d15aeSRobert Watson 1723c14d15aeSRobert Watson /* 1724c14d15aeSRobert Watson * Allow privilege with respect to the Partition policy, but not the 1725c14d15aeSRobert Watson * Privs policy. 1726c14d15aeSRobert Watson */ 1727c14d15aeSRobert Watson case PRIV_MAC_PARTITION: 1728c14d15aeSRobert Watson 1729c14d15aeSRobert Watson /* 1730c14d15aeSRobert Watson * Allow privilege with respect to process resource limits and login 1731c14d15aeSRobert Watson * context. 1732c14d15aeSRobert Watson */ 1733c14d15aeSRobert Watson case PRIV_PROC_LIMIT: 1734c14d15aeSRobert Watson case PRIV_PROC_SETLOGIN: 1735c14d15aeSRobert Watson case PRIV_PROC_SETRLIMIT: 1736c14d15aeSRobert Watson 1737c14d15aeSRobert Watson /* 1738c14d15aeSRobert Watson * Allow System V and POSIX IPC privileges. 1739c14d15aeSRobert Watson */ 1740c14d15aeSRobert Watson case PRIV_IPC_READ: 1741c14d15aeSRobert Watson case PRIV_IPC_WRITE: 1742c14d15aeSRobert Watson case PRIV_IPC_ADMIN: 1743c14d15aeSRobert Watson case PRIV_IPC_MSGSIZE: 1744c14d15aeSRobert Watson case PRIV_MQ_ADMIN: 1745c14d15aeSRobert Watson 1746c14d15aeSRobert Watson /* 1747c14d15aeSRobert Watson * Allow certain scheduler manipulations -- possibly this should be 1748c14d15aeSRobert Watson * controlled by more fine-grained policy, as potentially low 1749c14d15aeSRobert Watson * integrity processes can deny CPU to higher integrity ones. 1750c14d15aeSRobert Watson */ 1751c14d15aeSRobert Watson case PRIV_SCHED_DIFFCRED: 1752c14d15aeSRobert Watson case PRIV_SCHED_SETPRIORITY: 1753c14d15aeSRobert Watson case PRIV_SCHED_RTPRIO: 1754c14d15aeSRobert Watson case PRIV_SCHED_SETPOLICY: 1755c14d15aeSRobert Watson case PRIV_SCHED_SET: 1756c14d15aeSRobert Watson case PRIV_SCHED_SETPARAM: 1757c14d15aeSRobert Watson 1758c14d15aeSRobert Watson /* 1759c14d15aeSRobert Watson * More IPC privileges. 1760c14d15aeSRobert Watson */ 1761c14d15aeSRobert Watson case PRIV_SEM_WRITE: 1762c14d15aeSRobert Watson 1763c14d15aeSRobert Watson /* 1764c14d15aeSRobert Watson * Allow signaling privileges subject to integrity policy. 1765c14d15aeSRobert Watson */ 1766c14d15aeSRobert Watson case PRIV_SIGNAL_DIFFCRED: 1767c14d15aeSRobert Watson case PRIV_SIGNAL_SUGID: 1768c14d15aeSRobert Watson 1769c14d15aeSRobert Watson /* 1770c14d15aeSRobert Watson * Allow access to only limited sysctls from lower integrity levels; 1771c14d15aeSRobert Watson * piggy-back on the Jail definition. 1772c14d15aeSRobert Watson */ 1773c14d15aeSRobert Watson case PRIV_SYSCTL_WRITEJAIL: 1774c14d15aeSRobert Watson 1775c14d15aeSRobert Watson /* 1776c14d15aeSRobert Watson * Allow TTY-based privileges, subject to general device access using 1777c14d15aeSRobert Watson * labels on TTY device nodes, but not console privilege. 1778c14d15aeSRobert Watson */ 1779c14d15aeSRobert Watson case PRIV_TTY_DRAINWAIT: 1780c14d15aeSRobert Watson case PRIV_TTY_DTRWAIT: 1781c14d15aeSRobert Watson case PRIV_TTY_EXCLUSIVE: 1782c14d15aeSRobert Watson case PRIV_TTY_PRISON: 1783c14d15aeSRobert Watson case PRIV_TTY_STI: 1784c14d15aeSRobert Watson case PRIV_TTY_SETA: 1785c14d15aeSRobert Watson 1786c14d15aeSRobert Watson /* 1787c14d15aeSRobert Watson * Grant most VFS privileges, as almost all are in practice bounded 1788c14d15aeSRobert Watson * by more specific checks using labels. 1789c14d15aeSRobert Watson */ 1790c14d15aeSRobert Watson case PRIV_VFS_READ: 1791c14d15aeSRobert Watson case PRIV_VFS_WRITE: 1792c14d15aeSRobert Watson case PRIV_VFS_ADMIN: 1793c14d15aeSRobert Watson case PRIV_VFS_EXEC: 1794c14d15aeSRobert Watson case PRIV_VFS_LOOKUP: 1795c14d15aeSRobert Watson case PRIV_VFS_CHFLAGS_DEV: 1796c14d15aeSRobert Watson case PRIV_VFS_CHOWN: 1797c14d15aeSRobert Watson case PRIV_VFS_CHROOT: 1798c14d15aeSRobert Watson case PRIV_VFS_RETAINSUGID: 1799c14d15aeSRobert Watson case PRIV_VFS_EXCEEDQUOTA: 1800c14d15aeSRobert Watson case PRIV_VFS_FCHROOT: 1801c14d15aeSRobert Watson case PRIV_VFS_FHOPEN: 1802c14d15aeSRobert Watson case PRIV_VFS_FHSTATFS: 1803c14d15aeSRobert Watson case PRIV_VFS_GENERATION: 1804c14d15aeSRobert Watson case PRIV_VFS_GETFH: 1805c14d15aeSRobert Watson case PRIV_VFS_GETQUOTA: 1806c14d15aeSRobert Watson case PRIV_VFS_LINK: 1807c14d15aeSRobert Watson case PRIV_VFS_MOUNT: 1808c14d15aeSRobert Watson case PRIV_VFS_MOUNT_OWNER: 1809c14d15aeSRobert Watson case PRIV_VFS_MOUNT_PERM: 1810c14d15aeSRobert Watson case PRIV_VFS_MOUNT_SUIDDIR: 1811c14d15aeSRobert Watson case PRIV_VFS_MOUNT_NONUSER: 1812c14d15aeSRobert Watson case PRIV_VFS_SETGID: 1813c14d15aeSRobert Watson case PRIV_VFS_STICKYFILE: 1814c14d15aeSRobert Watson case PRIV_VFS_SYSFLAGS: 1815c14d15aeSRobert Watson case PRIV_VFS_UNMOUNT: 1816c14d15aeSRobert Watson 1817c14d15aeSRobert Watson /* 1818c14d15aeSRobert Watson * Allow VM privileges; it would be nice if these were subject to 1819c14d15aeSRobert Watson * resource limits. 1820c14d15aeSRobert Watson */ 1821c14d15aeSRobert Watson case PRIV_VM_MADV_PROTECT: 1822c14d15aeSRobert Watson case PRIV_VM_MLOCK: 1823c14d15aeSRobert Watson case PRIV_VM_MUNLOCK: 1824c14d15aeSRobert Watson 1825c14d15aeSRobert Watson /* 1826c14d15aeSRobert Watson * Allow some but not all network privileges. In general, dont allow 1827c14d15aeSRobert Watson * reconfiguring the network stack, just normal use. 1828c14d15aeSRobert Watson */ 1829c14d15aeSRobert Watson case PRIV_NETATALK_RESERVEDPORT: 1830c14d15aeSRobert Watson case PRIV_NETINET_RESERVEDPORT: 1831c14d15aeSRobert Watson case PRIV_NETINET_RAW: 1832c14d15aeSRobert Watson case PRIV_NETINET_REUSEPORT: 1833c14d15aeSRobert Watson case PRIV_NETIPX_RESERVEDPORT: 1834c14d15aeSRobert Watson case PRIV_NETIPX_RAW: 1835c14d15aeSRobert Watson break; 1836c14d15aeSRobert Watson 1837c14d15aeSRobert Watson /* 1838c14d15aeSRobert Watson * All remaining system privileges are allow only if the process 1839c14d15aeSRobert Watson * holds privilege with respect to the LOMAC policy. 1840c14d15aeSRobert Watson */ 1841c14d15aeSRobert Watson default: 1842c14d15aeSRobert Watson subj = SLOT(cred->cr_label); 18433f1a7a90SRobert Watson error = lomac_subject_privileged(subj); 1844c14d15aeSRobert Watson if (error) 1845c14d15aeSRobert Watson return (error); 1846c14d15aeSRobert Watson } 1847c14d15aeSRobert Watson return (0); 1848c14d15aeSRobert Watson } 1849c14d15aeSRobert Watson 1850eb320b0eSRobert Watson static int 1851eb320b0eSRobert Watson lomac_proc_check_debug(struct ucred *cred, struct proc *p) 1852eb320b0eSRobert Watson { 1853eb320b0eSRobert Watson struct mac_lomac *subj, *obj; 1854eb320b0eSRobert Watson 1855eb320b0eSRobert Watson if (!lomac_enabled) 1856eb320b0eSRobert Watson return (0); 1857eb320b0eSRobert Watson 1858eb320b0eSRobert Watson subj = SLOT(cred->cr_label); 1859eb320b0eSRobert Watson obj = SLOT(p->p_ucred->cr_label); 1860eb320b0eSRobert Watson 1861eb320b0eSRobert Watson /* XXX: range checks */ 1862eb320b0eSRobert Watson if (!lomac_dominate_single(obj, subj)) 1863eb320b0eSRobert Watson return (ESRCH); 1864eb320b0eSRobert Watson if (!lomac_subject_dominate(subj, obj)) 1865eb320b0eSRobert Watson return (EACCES); 1866eb320b0eSRobert Watson 1867eb320b0eSRobert Watson return (0); 1868eb320b0eSRobert Watson } 1869eb320b0eSRobert Watson 1870eb320b0eSRobert Watson static int 1871eb320b0eSRobert Watson lomac_proc_check_sched(struct ucred *cred, struct proc *p) 1872eb320b0eSRobert Watson { 1873eb320b0eSRobert Watson struct mac_lomac *subj, *obj; 1874eb320b0eSRobert Watson 1875eb320b0eSRobert Watson if (!lomac_enabled) 1876eb320b0eSRobert Watson return (0); 1877eb320b0eSRobert Watson 1878eb320b0eSRobert Watson subj = SLOT(cred->cr_label); 1879eb320b0eSRobert Watson obj = SLOT(p->p_ucred->cr_label); 1880eb320b0eSRobert Watson 1881eb320b0eSRobert Watson /* XXX: range checks */ 1882eb320b0eSRobert Watson if (!lomac_dominate_single(obj, subj)) 1883eb320b0eSRobert Watson return (ESRCH); 1884eb320b0eSRobert Watson if (!lomac_subject_dominate(subj, obj)) 1885eb320b0eSRobert Watson return (EACCES); 1886eb320b0eSRobert Watson 1887eb320b0eSRobert Watson return (0); 1888eb320b0eSRobert Watson } 1889eb320b0eSRobert Watson 1890eb320b0eSRobert Watson static int 1891eb320b0eSRobert Watson lomac_proc_check_signal(struct ucred *cred, struct proc *p, int signum) 1892eb320b0eSRobert Watson { 1893eb320b0eSRobert Watson struct mac_lomac *subj, *obj; 1894eb320b0eSRobert Watson 1895eb320b0eSRobert Watson if (!lomac_enabled) 1896eb320b0eSRobert Watson return (0); 1897eb320b0eSRobert Watson 1898eb320b0eSRobert Watson subj = SLOT(cred->cr_label); 1899eb320b0eSRobert Watson obj = SLOT(p->p_ucred->cr_label); 1900eb320b0eSRobert Watson 1901eb320b0eSRobert Watson /* XXX: range checks */ 1902eb320b0eSRobert Watson if (!lomac_dominate_single(obj, subj)) 1903eb320b0eSRobert Watson return (ESRCH); 1904eb320b0eSRobert Watson if (!lomac_subject_dominate(subj, obj)) 1905eb320b0eSRobert Watson return (EACCES); 1906eb320b0eSRobert Watson 1907eb320b0eSRobert Watson return (0); 1908eb320b0eSRobert Watson } 1909eb320b0eSRobert Watson 1910eb320b0eSRobert Watson static void 1911eb320b0eSRobert Watson lomac_proc_destroy_label(struct label *label) 1912eb320b0eSRobert Watson { 1913eb320b0eSRobert Watson 1914eb320b0eSRobert Watson mtx_destroy(&PSLOT(label)->mtx); 19151ede983cSDag-Erling Smørgrav free(PSLOT(label), M_LOMAC); 1916eb320b0eSRobert Watson PSLOT_SET(label, NULL); 1917eb320b0eSRobert Watson } 1918eb320b0eSRobert Watson 1919eb320b0eSRobert Watson static void 1920eb320b0eSRobert Watson lomac_proc_init_label(struct label *label) 1921eb320b0eSRobert Watson { 1922eb320b0eSRobert Watson 1923eb320b0eSRobert Watson PSLOT_SET(label, malloc(sizeof(struct mac_lomac_proc), M_LOMAC, 1924eb320b0eSRobert Watson M_ZERO | M_WAITOK)); 1925eb320b0eSRobert Watson mtx_init(&PSLOT(label)->mtx, "MAC/Lomac proc lock", NULL, MTX_DEF); 1926eb320b0eSRobert Watson } 1927eb320b0eSRobert Watson 1928eb320b0eSRobert Watson static int 1929eb320b0eSRobert Watson lomac_socket_check_deliver(struct socket *so, struct label *solabel, 1930eb320b0eSRobert Watson struct mbuf *m, struct label *mlabel) 1931eb320b0eSRobert Watson { 1932eb320b0eSRobert Watson struct mac_lomac *p, *s; 1933eb320b0eSRobert Watson 1934eb320b0eSRobert Watson if (!lomac_enabled) 1935eb320b0eSRobert Watson return (0); 1936eb320b0eSRobert Watson 1937eb320b0eSRobert Watson p = SLOT(mlabel); 1938eb320b0eSRobert Watson s = SLOT(solabel); 1939eb320b0eSRobert Watson 1940eb320b0eSRobert Watson return (lomac_equal_single(p, s) ? 0 : EACCES); 1941eb320b0eSRobert Watson } 1942eb320b0eSRobert Watson 1943eb320b0eSRobert Watson static int 1944eb320b0eSRobert Watson lomac_socket_check_relabel(struct ucred *cred, struct socket *so, 1945eb320b0eSRobert Watson struct label *solabel, struct label *newlabel) 1946eb320b0eSRobert Watson { 1947eb320b0eSRobert Watson struct mac_lomac *subj, *obj, *new; 1948eb320b0eSRobert Watson int error; 1949eb320b0eSRobert Watson 1950eb320b0eSRobert Watson new = SLOT(newlabel); 1951eb320b0eSRobert Watson subj = SLOT(cred->cr_label); 1952eb320b0eSRobert Watson obj = SLOT(solabel); 1953eb320b0eSRobert Watson 1954eb320b0eSRobert Watson /* 1955eb320b0eSRobert Watson * If there is a LOMAC label update for the socket, it may be an 1956eb320b0eSRobert Watson * update of single. 1957eb320b0eSRobert Watson */ 1958eb320b0eSRobert Watson error = lomac_atmostflags(new, MAC_LOMAC_FLAG_SINGLE); 1959eb320b0eSRobert Watson if (error) 1960eb320b0eSRobert Watson return (error); 1961eb320b0eSRobert Watson 1962eb320b0eSRobert Watson /* 1963eb320b0eSRobert Watson * To relabel a socket, the old socket single must be in the subject 1964eb320b0eSRobert Watson * range. 1965eb320b0eSRobert Watson */ 1966eb320b0eSRobert Watson if (!lomac_single_in_range(obj, subj)) 1967eb320b0eSRobert Watson return (EPERM); 1968eb320b0eSRobert Watson 1969eb320b0eSRobert Watson /* 1970eb320b0eSRobert Watson * If the LOMAC label is to be changed, authorize as appropriate. 1971eb320b0eSRobert Watson */ 1972eb320b0eSRobert Watson if (new->ml_flags & MAC_LOMAC_FLAG_SINGLE) { 1973eb320b0eSRobert Watson /* 1974eb320b0eSRobert Watson * To relabel a socket, the new socket single must be in the 1975eb320b0eSRobert Watson * subject range. 1976eb320b0eSRobert Watson */ 1977eb320b0eSRobert Watson if (!lomac_single_in_range(new, subj)) 1978eb320b0eSRobert Watson return (EPERM); 1979eb320b0eSRobert Watson 1980eb320b0eSRobert Watson /* 1981eb320b0eSRobert Watson * To change the LOMAC label on the socket to contain EQUAL, 1982eb320b0eSRobert Watson * the subject must have appropriate privilege. 1983eb320b0eSRobert Watson */ 1984eb320b0eSRobert Watson if (lomac_contains_equal(new)) { 1985eb320b0eSRobert Watson error = lomac_subject_privileged(subj); 1986eb320b0eSRobert Watson if (error) 1987eb320b0eSRobert Watson return (error); 1988eb320b0eSRobert Watson } 1989eb320b0eSRobert Watson } 1990eb320b0eSRobert Watson 1991eb320b0eSRobert Watson return (0); 1992eb320b0eSRobert Watson } 1993eb320b0eSRobert Watson 1994eb320b0eSRobert Watson static int 1995eb320b0eSRobert Watson lomac_socket_check_visible(struct ucred *cred, struct socket *so, 1996eb320b0eSRobert Watson struct label *solabel) 1997eb320b0eSRobert Watson { 1998eb320b0eSRobert Watson struct mac_lomac *subj, *obj; 1999eb320b0eSRobert Watson 2000eb320b0eSRobert Watson if (!lomac_enabled) 2001eb320b0eSRobert Watson return (0); 2002eb320b0eSRobert Watson 2003eb320b0eSRobert Watson subj = SLOT(cred->cr_label); 2004eb320b0eSRobert Watson obj = SLOT(solabel); 2005eb320b0eSRobert Watson 2006eb320b0eSRobert Watson if (!lomac_dominate_single(obj, subj)) 2007eb320b0eSRobert Watson return (ENOENT); 2008eb320b0eSRobert Watson 2009eb320b0eSRobert Watson return (0); 2010eb320b0eSRobert Watson } 2011eb320b0eSRobert Watson 2012eb320b0eSRobert Watson static void 2013eb320b0eSRobert Watson lomac_socket_create(struct ucred *cred, struct socket *so, 2014eb320b0eSRobert Watson struct label *solabel) 2015eb320b0eSRobert Watson { 2016eb320b0eSRobert Watson struct mac_lomac *source, *dest; 2017eb320b0eSRobert Watson 2018eb320b0eSRobert Watson source = SLOT(cred->cr_label); 2019eb320b0eSRobert Watson dest = SLOT(solabel); 2020eb320b0eSRobert Watson 2021eb320b0eSRobert Watson lomac_copy_single(source, dest); 2022eb320b0eSRobert Watson } 2023eb320b0eSRobert Watson 2024eb320b0eSRobert Watson static void 2025eb320b0eSRobert Watson lomac_socket_create_mbuf(struct socket *so, struct label *solabel, 2026eb320b0eSRobert Watson struct mbuf *m, struct label *mlabel) 2027eb320b0eSRobert Watson { 2028eb320b0eSRobert Watson struct mac_lomac *source, *dest; 2029eb320b0eSRobert Watson 2030eb320b0eSRobert Watson source = SLOT(solabel); 2031eb320b0eSRobert Watson dest = SLOT(mlabel); 2032eb320b0eSRobert Watson 2033eb320b0eSRobert Watson lomac_copy_single(source, dest); 2034eb320b0eSRobert Watson } 2035eb320b0eSRobert Watson 2036eb320b0eSRobert Watson static void 2037eb320b0eSRobert Watson lomac_socket_newconn(struct socket *oldso, struct label *oldsolabel, 2038eb320b0eSRobert Watson struct socket *newso, struct label *newsolabel) 2039eb320b0eSRobert Watson { 2040eb320b0eSRobert Watson struct mac_lomac *source, *dest; 2041eb320b0eSRobert Watson 2042eb320b0eSRobert Watson source = SLOT(oldsolabel); 2043eb320b0eSRobert Watson dest = SLOT(newsolabel); 2044eb320b0eSRobert Watson 2045eb320b0eSRobert Watson lomac_copy_single(source, dest); 2046eb320b0eSRobert Watson } 2047eb320b0eSRobert Watson 2048eb320b0eSRobert Watson static void 2049eb320b0eSRobert Watson lomac_socket_relabel(struct ucred *cred, struct socket *so, 2050eb320b0eSRobert Watson struct label *solabel, struct label *newlabel) 2051eb320b0eSRobert Watson { 2052eb320b0eSRobert Watson struct mac_lomac *source, *dest; 2053eb320b0eSRobert Watson 2054eb320b0eSRobert Watson source = SLOT(newlabel); 2055eb320b0eSRobert Watson dest = SLOT(solabel); 2056eb320b0eSRobert Watson 2057eb320b0eSRobert Watson try_relabel(source, dest); 2058eb320b0eSRobert Watson } 2059eb320b0eSRobert Watson 2060eb320b0eSRobert Watson static void 2061eb320b0eSRobert Watson lomac_socketpeer_set_from_mbuf(struct mbuf *m, struct label *mlabel, 2062eb320b0eSRobert Watson struct socket *so, struct label *sopeerlabel) 2063eb320b0eSRobert Watson { 2064eb320b0eSRobert Watson struct mac_lomac *source, *dest; 2065eb320b0eSRobert Watson 2066eb320b0eSRobert Watson source = SLOT(mlabel); 2067eb320b0eSRobert Watson dest = SLOT(sopeerlabel); 2068eb320b0eSRobert Watson 2069eb320b0eSRobert Watson lomac_copy_single(source, dest); 2070eb320b0eSRobert Watson } 2071eb320b0eSRobert Watson 2072eb320b0eSRobert Watson static void 2073eb320b0eSRobert Watson lomac_socketpeer_set_from_socket(struct socket *oldso, 2074eb320b0eSRobert Watson struct label *oldsolabel, struct socket *newso, 2075eb320b0eSRobert Watson struct label *newsopeerlabel) 2076eb320b0eSRobert Watson { 2077eb320b0eSRobert Watson struct mac_lomac *source, *dest; 2078eb320b0eSRobert Watson 2079eb320b0eSRobert Watson source = SLOT(oldsolabel); 2080eb320b0eSRobert Watson dest = SLOT(newsopeerlabel); 2081eb320b0eSRobert Watson 2082eb320b0eSRobert Watson lomac_copy_single(source, dest); 2083eb320b0eSRobert Watson } 2084eb320b0eSRobert Watson 2085eb320b0eSRobert Watson static void 2086eb320b0eSRobert Watson lomac_syncache_create(struct label *label, struct inpcb *inp) 2087eb320b0eSRobert Watson { 2088eb320b0eSRobert Watson struct mac_lomac *source, *dest; 2089eb320b0eSRobert Watson 2090eb320b0eSRobert Watson source = SLOT(inp->inp_label); 2091eb320b0eSRobert Watson dest = SLOT(label); 2092eb320b0eSRobert Watson lomac_copy(source, dest); 2093eb320b0eSRobert Watson } 2094eb320b0eSRobert Watson 2095eb320b0eSRobert Watson static void 2096eb320b0eSRobert Watson lomac_syncache_create_mbuf(struct label *sc_label, struct mbuf *m, 2097eb320b0eSRobert Watson struct label *mlabel) 2098eb320b0eSRobert Watson { 2099eb320b0eSRobert Watson struct mac_lomac *source, *dest; 2100eb320b0eSRobert Watson 2101eb320b0eSRobert Watson source = SLOT(sc_label); 2102eb320b0eSRobert Watson dest = SLOT(mlabel); 2103eb320b0eSRobert Watson lomac_copy(source, dest); 2104eb320b0eSRobert Watson } 2105c14d15aeSRobert Watson 2106db2661ceSRobert Watson static int 21073f1a7a90SRobert Watson lomac_system_check_acct(struct ucred *cred, struct vnode *vp, 210878007886SRobert Watson struct label *vplabel) 210918717f69SRobert Watson { 211018717f69SRobert Watson struct mac_lomac *subj, *obj; 211118717f69SRobert Watson 21123f1a7a90SRobert Watson if (!lomac_enabled) 211318717f69SRobert Watson return (0); 211418717f69SRobert Watson 211518717f69SRobert Watson subj = SLOT(cred->cr_label); 211678007886SRobert Watson obj = SLOT(vplabel); 211718717f69SRobert Watson 21183f1a7a90SRobert Watson if (lomac_subject_privileged(subj)) 211918717f69SRobert Watson return (EPERM); 212018717f69SRobert Watson 21213f1a7a90SRobert Watson if (!lomac_high_single(obj)) 212218717f69SRobert Watson return (EACCES); 212318717f69SRobert Watson 212418717f69SRobert Watson return (0); 212518717f69SRobert Watson } 212618717f69SRobert Watson 212718717f69SRobert Watson static int 21283f1a7a90SRobert Watson lomac_system_check_auditctl(struct ucred *cred, struct vnode *vp, 212978007886SRobert Watson struct label *vplabel) 213018717f69SRobert Watson { 213118717f69SRobert Watson struct mac_lomac *subj, *obj; 213218717f69SRobert Watson 21333f1a7a90SRobert Watson if (!lomac_enabled) 213418717f69SRobert Watson return (0); 213518717f69SRobert Watson 213618717f69SRobert Watson subj = SLOT(cred->cr_label); 213778007886SRobert Watson obj = SLOT(vplabel); 213818717f69SRobert Watson 21393f1a7a90SRobert Watson if (lomac_subject_privileged(subj)) 214018717f69SRobert Watson return (EPERM); 214118717f69SRobert Watson 21423f1a7a90SRobert Watson if (!lomac_high_single(obj)) 214318717f69SRobert Watson return (EACCES); 214418717f69SRobert Watson 214518717f69SRobert Watson return (0); 214618717f69SRobert Watson } 214718717f69SRobert Watson 214818717f69SRobert Watson static int 21493f1a7a90SRobert Watson lomac_system_check_swapoff(struct ucred *cred, struct vnode *vp, 215078007886SRobert Watson struct label *vplabel) 215118717f69SRobert Watson { 215218717f69SRobert Watson struct mac_lomac *subj; 215318717f69SRobert Watson 21543f1a7a90SRobert Watson if (!lomac_enabled) 215518717f69SRobert Watson return (0); 215618717f69SRobert Watson 215718717f69SRobert Watson subj = SLOT(cred->cr_label); 215818717f69SRobert Watson 21593f1a7a90SRobert Watson if (lomac_subject_privileged(subj)) 216018717f69SRobert Watson return (EPERM); 216118717f69SRobert Watson 216218717f69SRobert Watson return (0); 216318717f69SRobert Watson } 216418717f69SRobert Watson 216518717f69SRobert Watson static int 21663f1a7a90SRobert Watson lomac_system_check_swapon(struct ucred *cred, struct vnode *vp, 216778007886SRobert Watson struct label *vplabel) 2168db2661ceSRobert Watson { 2169db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2170db2661ceSRobert Watson 21713f1a7a90SRobert Watson if (!lomac_enabled) 2172db2661ceSRobert Watson return (0); 2173db2661ceSRobert Watson 2174eca8a663SRobert Watson subj = SLOT(cred->cr_label); 217578007886SRobert Watson obj = SLOT(vplabel); 2176db2661ceSRobert Watson 21773f1a7a90SRobert Watson if (lomac_subject_privileged(subj)) 2178db2661ceSRobert Watson return (EPERM); 2179db2661ceSRobert Watson 21803f1a7a90SRobert Watson if (!lomac_high_single(obj)) 2181db2661ceSRobert Watson return (EACCES); 2182db2661ceSRobert Watson 2183db2661ceSRobert Watson return (0); 2184db2661ceSRobert Watson } 2185db2661ceSRobert Watson 2186db2661ceSRobert Watson static int 21873f1a7a90SRobert Watson lomac_system_check_sysctl(struct ucred *cred, struct sysctl_oid *oidp, 218863dba32bSPawel Jakub Dawidek void *arg1, int arg2, struct sysctl_req *req) 2189db2661ceSRobert Watson { 2190db2661ceSRobert Watson struct mac_lomac *subj; 2191db2661ceSRobert Watson 21923f1a7a90SRobert Watson if (!lomac_enabled) 2193db2661ceSRobert Watson return (0); 2194db2661ceSRobert Watson 2195eca8a663SRobert Watson subj = SLOT(cred->cr_label); 2196db2661ceSRobert Watson 2197db2661ceSRobert Watson /* 21983f1a7a90SRobert Watson * Treat sysctl variables without CTLFLAG_ANYBODY flag as lomac/high, 21993f1a7a90SRobert Watson * but also require privilege to change them. 2200db2661ceSRobert Watson */ 220163dba32bSPawel Jakub Dawidek if (req->newptr != NULL && (oidp->oid_kind & CTLFLAG_ANYBODY) == 0) { 2202db2661ceSRobert Watson #ifdef notdef 22033f1a7a90SRobert Watson if (!lomac_subject_dominate_high(subj)) 2204db2661ceSRobert Watson return (EACCES); 2205db2661ceSRobert Watson #endif 2206db2661ceSRobert Watson 22073f1a7a90SRobert Watson if (lomac_subject_privileged(subj)) 2208db2661ceSRobert Watson return (EPERM); 2209db2661ceSRobert Watson } 2210db2661ceSRobert Watson 2211db2661ceSRobert Watson return (0); 2212db2661ceSRobert Watson } 2213db2661ceSRobert Watson 2214eb320b0eSRobert Watson static void 2215eb320b0eSRobert Watson lomac_thread_userret(struct thread *td) 2216eb320b0eSRobert Watson { 2217eb320b0eSRobert Watson struct proc *p = td->td_proc; 2218eb320b0eSRobert Watson struct mac_lomac_proc *subj = PSLOT(p->p_label); 2219eb320b0eSRobert Watson struct ucred *newcred, *oldcred; 2220eb320b0eSRobert Watson int dodrop; 2221eb320b0eSRobert Watson 2222eb320b0eSRobert Watson mtx_lock(&subj->mtx); 2223eb320b0eSRobert Watson if (subj->mac_lomac.ml_flags & MAC_LOMAC_FLAG_UPDATE) { 2224eb320b0eSRobert Watson dodrop = 0; 2225eb320b0eSRobert Watson mtx_unlock(&subj->mtx); 2226eb320b0eSRobert Watson newcred = crget(); 2227eb320b0eSRobert Watson /* 22289215889dSRobert Watson * Prevent a lock order reversal in mac_proc_vm_revoke; 22299215889dSRobert Watson * ideally, the other user of subj->mtx wouldn't be holding 22309215889dSRobert Watson * Giant. 2231eb320b0eSRobert Watson */ 2232eb320b0eSRobert Watson mtx_lock(&Giant); 2233eb320b0eSRobert Watson PROC_LOCK(p); 2234eb320b0eSRobert Watson mtx_lock(&subj->mtx); 2235eb320b0eSRobert Watson /* 2236eb320b0eSRobert Watson * Check if we lost the race while allocating the cred. 2237eb320b0eSRobert Watson */ 2238eb320b0eSRobert Watson if ((subj->mac_lomac.ml_flags & MAC_LOMAC_FLAG_UPDATE) == 0) { 2239eb320b0eSRobert Watson crfree(newcred); 2240eb320b0eSRobert Watson goto out; 2241eb320b0eSRobert Watson } 2242eb320b0eSRobert Watson oldcred = p->p_ucred; 2243eb320b0eSRobert Watson crcopy(newcred, oldcred); 2244eb320b0eSRobert Watson crhold(newcred); 2245eb320b0eSRobert Watson lomac_copy(&subj->mac_lomac, SLOT(newcred->cr_label)); 2246eb320b0eSRobert Watson p->p_ucred = newcred; 2247eb320b0eSRobert Watson crfree(oldcred); 2248eb320b0eSRobert Watson dodrop = 1; 2249eb320b0eSRobert Watson out: 2250eb320b0eSRobert Watson mtx_unlock(&subj->mtx); 2251eb320b0eSRobert Watson PROC_UNLOCK(p); 2252eb320b0eSRobert Watson if (dodrop) 22539215889dSRobert Watson mac_proc_vm_revoke(curthread); 2254eb320b0eSRobert Watson mtx_unlock(&Giant); 2255eb320b0eSRobert Watson } else { 2256eb320b0eSRobert Watson mtx_unlock(&subj->mtx); 2257eb320b0eSRobert Watson } 2258eb320b0eSRobert Watson } 2259eb320b0eSRobert Watson 2260eb320b0eSRobert Watson static int 2261eb320b0eSRobert Watson lomac_vnode_associate_extattr(struct mount *mp, struct label *mplabel, 2262eb320b0eSRobert Watson struct vnode *vp, struct label *vplabel) 2263eb320b0eSRobert Watson { 2264eb320b0eSRobert Watson struct mac_lomac ml_temp, *source, *dest; 2265eb320b0eSRobert Watson int buflen, error; 2266eb320b0eSRobert Watson 2267eb320b0eSRobert Watson source = SLOT(mplabel); 2268eb320b0eSRobert Watson dest = SLOT(vplabel); 2269eb320b0eSRobert Watson 2270eb320b0eSRobert Watson buflen = sizeof(ml_temp); 2271eb320b0eSRobert Watson bzero(&ml_temp, buflen); 2272eb320b0eSRobert Watson 2273eb320b0eSRobert Watson error = vn_extattr_get(vp, IO_NODELOCKED, MAC_LOMAC_EXTATTR_NAMESPACE, 2274eb320b0eSRobert Watson MAC_LOMAC_EXTATTR_NAME, &buflen, (char *)&ml_temp, curthread); 2275eb320b0eSRobert Watson if (error == ENOATTR || error == EOPNOTSUPP) { 2276eb320b0eSRobert Watson /* Fall back to the mntlabel. */ 2277eb320b0eSRobert Watson lomac_copy_single(source, dest); 2278eb320b0eSRobert Watson return (0); 2279eb320b0eSRobert Watson } else if (error) 2280eb320b0eSRobert Watson return (error); 2281eb320b0eSRobert Watson 2282eb320b0eSRobert Watson if (buflen != sizeof(ml_temp)) { 2283eb320b0eSRobert Watson if (buflen != sizeof(ml_temp) - sizeof(ml_temp.ml_auxsingle)) { 2284eb320b0eSRobert Watson printf("lomac_vnode_associate_extattr: bad size %d\n", 2285eb320b0eSRobert Watson buflen); 2286eb320b0eSRobert Watson return (EPERM); 2287eb320b0eSRobert Watson } 2288eb320b0eSRobert Watson bzero(&ml_temp.ml_auxsingle, sizeof(ml_temp.ml_auxsingle)); 2289eb320b0eSRobert Watson buflen = sizeof(ml_temp); 2290eb320b0eSRobert Watson (void)vn_extattr_set(vp, IO_NODELOCKED, 2291eb320b0eSRobert Watson MAC_LOMAC_EXTATTR_NAMESPACE, MAC_LOMAC_EXTATTR_NAME, 2292eb320b0eSRobert Watson buflen, (char *)&ml_temp, curthread); 2293eb320b0eSRobert Watson } 2294eb320b0eSRobert Watson if (lomac_valid(&ml_temp) != 0) { 2295eb320b0eSRobert Watson printf("lomac_vnode_associate_extattr: invalid\n"); 2296eb320b0eSRobert Watson return (EPERM); 2297eb320b0eSRobert Watson } 2298eb320b0eSRobert Watson if ((ml_temp.ml_flags & MAC_LOMAC_FLAGS_BOTH) != 2299eb320b0eSRobert Watson MAC_LOMAC_FLAG_SINGLE) { 2300eb320b0eSRobert Watson printf("lomac_vnode_associate_extattr: not single\n"); 2301eb320b0eSRobert Watson return (EPERM); 2302eb320b0eSRobert Watson } 2303eb320b0eSRobert Watson 2304eb320b0eSRobert Watson lomac_copy_single(&ml_temp, dest); 2305eb320b0eSRobert Watson return (0); 2306eb320b0eSRobert Watson } 2307eb320b0eSRobert Watson 2308eb320b0eSRobert Watson static void 2309eb320b0eSRobert Watson lomac_vnode_associate_singlelabel(struct mount *mp, struct label *mplabel, 2310eb320b0eSRobert Watson struct vnode *vp, struct label *vplabel) 2311eb320b0eSRobert Watson { 2312eb320b0eSRobert Watson struct mac_lomac *source, *dest; 2313eb320b0eSRobert Watson 2314eb320b0eSRobert Watson source = SLOT(mplabel); 2315eb320b0eSRobert Watson dest = SLOT(vplabel); 2316eb320b0eSRobert Watson 2317eb320b0eSRobert Watson lomac_copy_single(source, dest); 2318eb320b0eSRobert Watson } 2319eb320b0eSRobert Watson 2320db2661ceSRobert Watson static int 23213f1a7a90SRobert Watson lomac_vnode_check_create(struct ucred *cred, struct vnode *dvp, 232278007886SRobert Watson struct label *dvplabel, struct componentname *cnp, struct vattr *vap) 2323db2661ceSRobert Watson { 2324db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2325db2661ceSRobert Watson 23263f1a7a90SRobert Watson if (!lomac_enabled) 2327db2661ceSRobert Watson return (0); 2328db2661ceSRobert Watson 2329eca8a663SRobert Watson subj = SLOT(cred->cr_label); 233078007886SRobert Watson obj = SLOT(dvplabel); 2331db2661ceSRobert Watson 23323f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2333db2661ceSRobert Watson return (EACCES); 2334db2661ceSRobert Watson if (obj->ml_flags & MAC_LOMAC_FLAG_AUX && 23353f1a7a90SRobert Watson !lomac_dominate_element(&subj->ml_single, &obj->ml_auxsingle)) 2336db2661ceSRobert Watson return (EACCES); 2337db2661ceSRobert Watson 2338db2661ceSRobert Watson return (0); 2339db2661ceSRobert Watson } 2340db2661ceSRobert Watson 2341db2661ceSRobert Watson static int 23423f1a7a90SRobert Watson lomac_vnode_check_deleteacl(struct ucred *cred, struct vnode *vp, 234378007886SRobert Watson struct label *vplabel, acl_type_t type) 2344db2661ceSRobert Watson { 2345db2661ceSRobert Watson struct mac_lomac *subj, *obj; 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 23533f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2354db2661ceSRobert Watson return (EACCES); 2355db2661ceSRobert Watson 2356db2661ceSRobert Watson return (0); 2357db2661ceSRobert Watson } 2358db2661ceSRobert Watson 2359db2661ceSRobert Watson static int 23603f1a7a90SRobert Watson lomac_vnode_check_link(struct ucred *cred, struct vnode *dvp, 236178007886SRobert Watson struct label *dvplabel, struct vnode *vp, struct label *vplabel, 2362db2661ceSRobert Watson struct componentname *cnp) 2363db2661ceSRobert Watson { 2364db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2365db2661ceSRobert Watson 23663f1a7a90SRobert Watson if (!lomac_enabled) 2367db2661ceSRobert Watson return (0); 2368db2661ceSRobert Watson 2369eca8a663SRobert Watson subj = SLOT(cred->cr_label); 237078007886SRobert Watson obj = SLOT(dvplabel); 2371db2661ceSRobert Watson 23723f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2373db2661ceSRobert Watson return (EACCES); 2374db2661ceSRobert Watson 237578007886SRobert Watson obj = SLOT(vplabel); 2376db2661ceSRobert Watson 23773f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2378db2661ceSRobert Watson return (EACCES); 2379db2661ceSRobert Watson 2380db2661ceSRobert Watson return (0); 2381db2661ceSRobert Watson } 2382db2661ceSRobert Watson 2383db2661ceSRobert Watson static int 23843f1a7a90SRobert Watson lomac_vnode_check_mmap(struct ucred *cred, struct vnode *vp, 238578007886SRobert Watson struct label *vplabel, int prot, int flags) 2386db2661ceSRobert Watson { 2387db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2388db2661ceSRobert Watson 2389db2661ceSRobert Watson /* 2390db2661ceSRobert Watson * Rely on the use of open()-time protections to handle 2391db2661ceSRobert Watson * non-revocation cases. 2392db2661ceSRobert Watson */ 23933f1a7a90SRobert Watson if (!lomac_enabled) 2394db2661ceSRobert Watson return (0); 2395db2661ceSRobert Watson 2396eca8a663SRobert Watson subj = SLOT(cred->cr_label); 239778007886SRobert Watson obj = SLOT(vplabel); 2398db2661ceSRobert Watson 2399c92163dcSChristian S.J. Peron if (((prot & VM_PROT_WRITE) != 0) && ((flags & MAP_SHARED) != 0)) { 24003f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2401db2661ceSRobert Watson return (EACCES); 2402db2661ceSRobert Watson } 2403db2661ceSRobert Watson if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) { 24043f1a7a90SRobert Watson if (!lomac_dominate_single(obj, subj)) 2405db2661ceSRobert Watson return (maybe_demote(subj, obj, "mapping", "file", vp)); 2406db2661ceSRobert Watson } 2407db2661ceSRobert Watson 2408db2661ceSRobert Watson return (0); 2409db2661ceSRobert Watson } 2410db2661ceSRobert Watson 2411db2661ceSRobert Watson static void 24123f1a7a90SRobert Watson lomac_vnode_check_mmap_downgrade(struct ucred *cred, struct vnode *vp, 241378007886SRobert Watson struct label *vplabel, /* XXX vm_prot_t */ int *prot) 2414db2661ceSRobert Watson { 2415db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2416db2661ceSRobert Watson 2417db2661ceSRobert Watson /* 2418db2661ceSRobert Watson * Rely on the use of open()-time protections to handle 2419db2661ceSRobert Watson * non-revocation cases. 2420db2661ceSRobert Watson */ 24213f1a7a90SRobert Watson if (!lomac_enabled || !revocation_enabled) 2422db2661ceSRobert Watson return; 2423db2661ceSRobert Watson 2424eca8a663SRobert Watson subj = SLOT(cred->cr_label); 242578007886SRobert Watson obj = SLOT(vplabel); 2426db2661ceSRobert Watson 24273f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2428db2661ceSRobert Watson *prot &= ~VM_PROT_WRITE; 2429db2661ceSRobert Watson } 2430db2661ceSRobert Watson 2431db2661ceSRobert Watson static int 24323f1a7a90SRobert Watson lomac_vnode_check_open(struct ucred *cred, struct vnode *vp, 243315bc6b2bSEdward Tomasz Napierala struct label *vplabel, accmode_t accmode) 2434db2661ceSRobert Watson { 2435db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2436db2661ceSRobert Watson 24373f1a7a90SRobert Watson if (!lomac_enabled) 2438db2661ceSRobert Watson return (0); 2439db2661ceSRobert Watson 2440eca8a663SRobert Watson subj = SLOT(cred->cr_label); 244178007886SRobert Watson obj = SLOT(vplabel); 2442db2661ceSRobert Watson 2443db2661ceSRobert Watson /* XXX privilege override for admin? */ 244415bc6b2bSEdward Tomasz Napierala if (accmode & (VWRITE | VAPPEND | VADMIN)) { 24453f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2446db2661ceSRobert Watson return (EACCES); 2447db2661ceSRobert Watson } 2448db2661ceSRobert Watson 2449db2661ceSRobert Watson return (0); 2450db2661ceSRobert Watson } 2451db2661ceSRobert Watson 2452db2661ceSRobert Watson static int 24533f1a7a90SRobert Watson lomac_vnode_check_read(struct ucred *active_cred, struct ucred *file_cred, 245478007886SRobert Watson struct vnode *vp, struct label *vplabel) 2455db2661ceSRobert Watson { 2456db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2457db2661ceSRobert Watson 24583f1a7a90SRobert Watson if (!lomac_enabled || !revocation_enabled) 2459db2661ceSRobert Watson return (0); 2460db2661ceSRobert Watson 2461eca8a663SRobert Watson subj = SLOT(active_cred->cr_label); 246278007886SRobert Watson obj = SLOT(vplabel); 2463db2661ceSRobert Watson 24643f1a7a90SRobert Watson if (!lomac_dominate_single(obj, subj)) 2465db2661ceSRobert Watson return (maybe_demote(subj, obj, "reading", "file", vp)); 2466db2661ceSRobert Watson 2467db2661ceSRobert Watson return (0); 2468db2661ceSRobert Watson } 2469db2661ceSRobert Watson 2470db2661ceSRobert Watson static int 24713f1a7a90SRobert Watson lomac_vnode_check_relabel(struct ucred *cred, struct vnode *vp, 247278007886SRobert Watson struct label *vplabel, struct label *newlabel) 2473db2661ceSRobert Watson { 2474db2661ceSRobert Watson struct mac_lomac *old, *new, *subj; 2475db2661ceSRobert Watson int error; 2476db2661ceSRobert Watson 247778007886SRobert Watson old = SLOT(vplabel); 2478db2661ceSRobert Watson new = SLOT(newlabel); 2479eca8a663SRobert Watson subj = SLOT(cred->cr_label); 2480db2661ceSRobert Watson 2481db2661ceSRobert Watson /* 2482db2661ceSRobert Watson * If there is a LOMAC label update for the vnode, it must be a 2483db2661ceSRobert Watson * single label, with an optional explicit auxiliary single. 2484db2661ceSRobert Watson */ 2485db2661ceSRobert Watson error = lomac_atmostflags(new, 2486db2661ceSRobert Watson MAC_LOMAC_FLAG_SINGLE | MAC_LOMAC_FLAG_AUX); 2487db2661ceSRobert Watson if (error) 2488db2661ceSRobert Watson return (error); 2489db2661ceSRobert Watson 2490db2661ceSRobert Watson /* 2491db2661ceSRobert Watson * To perform a relabel of the vnode (LOMAC label or not), LOMAC must 2492db2661ceSRobert Watson * authorize the relabel. 2493db2661ceSRobert Watson */ 24943f1a7a90SRobert Watson if (!lomac_single_in_range(old, subj)) 2495db2661ceSRobert Watson return (EPERM); 2496db2661ceSRobert Watson 2497db2661ceSRobert Watson /* 2498db2661ceSRobert Watson * If the LOMAC label is to be changed, authorize as appropriate. 2499db2661ceSRobert Watson */ 2500db2661ceSRobert Watson if (new->ml_flags & MAC_LOMAC_FLAG_SINGLE) { 2501db2661ceSRobert Watson /* 2502db2661ceSRobert Watson * To change the LOMAC label on a vnode, the new vnode label 2503db2661ceSRobert Watson * must be in the subject range. 2504db2661ceSRobert Watson */ 25053f1a7a90SRobert Watson if (!lomac_single_in_range(new, subj)) 2506db2661ceSRobert Watson return (EPERM); 2507db2661ceSRobert Watson 2508db2661ceSRobert Watson /* 25093f1a7a90SRobert Watson * To change the LOMAC label on the vnode to be EQUAL, the 25103f1a7a90SRobert Watson * subject must have appropriate privilege. 2511db2661ceSRobert Watson */ 25123f1a7a90SRobert Watson if (lomac_contains_equal(new)) { 25133f1a7a90SRobert Watson error = lomac_subject_privileged(subj); 2514db2661ceSRobert Watson if (error) 2515db2661ceSRobert Watson return (error); 2516db2661ceSRobert Watson } 2517db2661ceSRobert Watson } 2518db2661ceSRobert Watson if (new->ml_flags & MAC_LOMAC_FLAG_AUX) { 2519db2661ceSRobert Watson /* 252084bdb083SRobert Watson * Fill in the missing parts from the previous label. 252184bdb083SRobert Watson */ 252284bdb083SRobert Watson if ((new->ml_flags & MAC_LOMAC_FLAG_SINGLE) == 0) 25233f1a7a90SRobert Watson lomac_copy_single(subj, new); 252484bdb083SRobert Watson 252584bdb083SRobert Watson /* 2526db2661ceSRobert Watson * To change the auxiliary LOMAC label on a vnode, the new 2527db2661ceSRobert Watson * vnode label must be in the subject range. 2528db2661ceSRobert Watson */ 25293f1a7a90SRobert Watson if (!lomac_auxsingle_in_range(new, subj)) 2530db2661ceSRobert Watson return (EPERM); 2531db2661ceSRobert Watson 2532db2661ceSRobert Watson /* 2533db2661ceSRobert Watson * To change the auxiliary LOMAC label on the vnode to be 2534db2661ceSRobert Watson * EQUAL, the subject must have appropriate privilege. 2535db2661ceSRobert Watson */ 25363f1a7a90SRobert Watson if (lomac_contains_equal(new)) { 25373f1a7a90SRobert Watson error = lomac_subject_privileged(subj); 2538db2661ceSRobert Watson if (error) 2539db2661ceSRobert Watson return (error); 2540db2661ceSRobert Watson } 2541db2661ceSRobert Watson } 2542db2661ceSRobert Watson 2543db2661ceSRobert Watson return (0); 2544db2661ceSRobert Watson } 2545db2661ceSRobert Watson 2546db2661ceSRobert Watson static int 25473f1a7a90SRobert Watson lomac_vnode_check_rename_from(struct ucred *cred, struct vnode *dvp, 254878007886SRobert Watson struct label *dvplabel, struct vnode *vp, struct label *vplabel, 2549db2661ceSRobert Watson struct componentname *cnp) 2550db2661ceSRobert Watson { 2551db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2552db2661ceSRobert Watson 25533f1a7a90SRobert Watson if (!lomac_enabled) 2554db2661ceSRobert Watson return (0); 2555db2661ceSRobert Watson 2556eca8a663SRobert Watson subj = SLOT(cred->cr_label); 255778007886SRobert Watson obj = SLOT(dvplabel); 2558db2661ceSRobert Watson 25593f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2560db2661ceSRobert Watson return (EACCES); 2561db2661ceSRobert Watson 256278007886SRobert Watson obj = SLOT(vplabel); 2563db2661ceSRobert Watson 25643f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2565db2661ceSRobert Watson return (EACCES); 2566db2661ceSRobert Watson 2567db2661ceSRobert Watson return (0); 2568db2661ceSRobert Watson } 2569db2661ceSRobert Watson 2570db2661ceSRobert Watson static int 25713f1a7a90SRobert Watson lomac_vnode_check_rename_to(struct ucred *cred, struct vnode *dvp, 257278007886SRobert Watson struct label *dvplabel, struct vnode *vp, struct label *vplabel, 257378007886SRobert Watson int samedir, struct componentname *cnp) 2574db2661ceSRobert Watson { 2575db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2576db2661ceSRobert Watson 25773f1a7a90SRobert Watson if (!lomac_enabled) 2578db2661ceSRobert Watson return (0); 2579db2661ceSRobert Watson 2580eca8a663SRobert Watson subj = SLOT(cred->cr_label); 258178007886SRobert Watson obj = SLOT(dvplabel); 2582db2661ceSRobert Watson 25833f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2584db2661ceSRobert Watson return (EACCES); 2585db2661ceSRobert Watson 2586db2661ceSRobert Watson if (vp != NULL) { 258778007886SRobert Watson obj = SLOT(vplabel); 2588db2661ceSRobert Watson 25893f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2590db2661ceSRobert Watson return (EACCES); 2591db2661ceSRobert Watson } 2592db2661ceSRobert Watson 2593db2661ceSRobert Watson return (0); 2594db2661ceSRobert Watson } 2595db2661ceSRobert Watson 2596db2661ceSRobert Watson static int 25973f1a7a90SRobert Watson lomac_vnode_check_revoke(struct ucred *cred, struct vnode *vp, 259878007886SRobert Watson struct label *vplabel) 2599db2661ceSRobert Watson { 2600db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2601db2661ceSRobert Watson 26023f1a7a90SRobert Watson if (!lomac_enabled) 2603db2661ceSRobert Watson return (0); 2604db2661ceSRobert Watson 2605eca8a663SRobert Watson subj = SLOT(cred->cr_label); 260678007886SRobert Watson obj = SLOT(vplabel); 2607db2661ceSRobert Watson 26083f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2609db2661ceSRobert Watson return (EACCES); 2610db2661ceSRobert Watson 2611db2661ceSRobert Watson return (0); 2612db2661ceSRobert Watson } 2613db2661ceSRobert Watson 2614db2661ceSRobert Watson static int 26153f1a7a90SRobert Watson lomac_vnode_check_setacl(struct ucred *cred, struct vnode *vp, 261678007886SRobert Watson struct label *vplabel, acl_type_t type, struct acl *acl) 2617db2661ceSRobert Watson { 2618db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2619db2661ceSRobert Watson 26203f1a7a90SRobert Watson if (!lomac_enabled) 2621db2661ceSRobert Watson return (0); 2622db2661ceSRobert Watson 2623eca8a663SRobert Watson subj = SLOT(cred->cr_label); 262478007886SRobert Watson obj = SLOT(vplabel); 2625db2661ceSRobert Watson 26263f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2627db2661ceSRobert Watson return (EACCES); 2628db2661ceSRobert Watson 2629db2661ceSRobert Watson return (0); 2630db2661ceSRobert Watson } 2631db2661ceSRobert Watson 2632db2661ceSRobert Watson static int 26333f1a7a90SRobert Watson lomac_vnode_check_setextattr(struct ucred *cred, struct vnode *vp, 2634fefd0ac8SRobert Watson struct label *vplabel, int attrnamespace, const char *name) 2635db2661ceSRobert Watson { 2636db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2637db2661ceSRobert Watson 26383f1a7a90SRobert Watson if (!lomac_enabled) 2639db2661ceSRobert Watson return (0); 2640db2661ceSRobert Watson 2641eca8a663SRobert Watson subj = SLOT(cred->cr_label); 264278007886SRobert Watson obj = SLOT(vplabel); 2643db2661ceSRobert Watson 26443f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2645db2661ceSRobert Watson return (EACCES); 2646db2661ceSRobert Watson 2647db2661ceSRobert Watson /* XXX: protect the MAC EA in a special way? */ 2648db2661ceSRobert Watson 2649db2661ceSRobert Watson return (0); 2650db2661ceSRobert Watson } 2651db2661ceSRobert Watson 2652db2661ceSRobert Watson static int 26533f1a7a90SRobert Watson lomac_vnode_check_setflags(struct ucred *cred, struct vnode *vp, 265478007886SRobert Watson struct label *vplabel, u_long flags) 2655db2661ceSRobert Watson { 2656db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2657db2661ceSRobert Watson 26583f1a7a90SRobert Watson if (!lomac_enabled) 2659db2661ceSRobert Watson return (0); 2660db2661ceSRobert Watson 2661eca8a663SRobert Watson subj = SLOT(cred->cr_label); 266278007886SRobert Watson obj = SLOT(vplabel); 2663db2661ceSRobert Watson 26643f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2665db2661ceSRobert Watson return (EACCES); 2666db2661ceSRobert Watson 2667db2661ceSRobert Watson return (0); 2668db2661ceSRobert Watson } 2669db2661ceSRobert Watson 2670db2661ceSRobert Watson static int 26713f1a7a90SRobert Watson lomac_vnode_check_setmode(struct ucred *cred, struct vnode *vp, 267278007886SRobert Watson struct label *vplabel, mode_t mode) 2673db2661ceSRobert Watson { 2674db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2675db2661ceSRobert Watson 26763f1a7a90SRobert Watson if (!lomac_enabled) 2677db2661ceSRobert Watson return (0); 2678db2661ceSRobert Watson 2679eca8a663SRobert Watson subj = SLOT(cred->cr_label); 268078007886SRobert Watson obj = SLOT(vplabel); 2681db2661ceSRobert Watson 26823f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2683db2661ceSRobert Watson return (EACCES); 2684db2661ceSRobert Watson 2685db2661ceSRobert Watson return (0); 2686db2661ceSRobert Watson } 2687db2661ceSRobert Watson 2688db2661ceSRobert Watson static int 26893f1a7a90SRobert Watson lomac_vnode_check_setowner(struct ucred *cred, struct vnode *vp, 269078007886SRobert Watson struct label *vplabel, uid_t uid, gid_t gid) 2691db2661ceSRobert Watson { 2692db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2693db2661ceSRobert Watson 26943f1a7a90SRobert Watson if (!lomac_enabled) 2695db2661ceSRobert Watson return (0); 2696db2661ceSRobert Watson 2697eca8a663SRobert Watson subj = SLOT(cred->cr_label); 269878007886SRobert Watson obj = SLOT(vplabel); 2699db2661ceSRobert Watson 27003f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2701db2661ceSRobert Watson return (EACCES); 2702db2661ceSRobert Watson 2703db2661ceSRobert Watson return (0); 2704db2661ceSRobert Watson } 2705db2661ceSRobert Watson 2706db2661ceSRobert Watson static int 27073f1a7a90SRobert Watson lomac_vnode_check_setutimes(struct ucred *cred, struct vnode *vp, 270878007886SRobert Watson struct label *vplabel, struct timespec atime, struct timespec mtime) 2709db2661ceSRobert Watson { 2710db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2711db2661ceSRobert Watson 27123f1a7a90SRobert Watson if (!lomac_enabled) 2713db2661ceSRobert Watson return (0); 2714db2661ceSRobert Watson 2715eca8a663SRobert Watson subj = SLOT(cred->cr_label); 271678007886SRobert Watson obj = SLOT(vplabel); 2717db2661ceSRobert Watson 27183f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2719db2661ceSRobert Watson return (EACCES); 2720db2661ceSRobert Watson 2721db2661ceSRobert Watson return (0); 2722db2661ceSRobert Watson } 2723db2661ceSRobert Watson 2724db2661ceSRobert Watson static int 27253f1a7a90SRobert Watson lomac_vnode_check_unlink(struct ucred *cred, struct vnode *dvp, 272645e0f3d6SRobert Watson struct label *dvplabel, struct vnode *vp, struct label *vplabel, 272745e0f3d6SRobert Watson struct componentname *cnp) 272845e0f3d6SRobert Watson { 272945e0f3d6SRobert Watson struct mac_lomac *subj, *obj; 273045e0f3d6SRobert Watson 27313f1a7a90SRobert Watson if (!lomac_enabled) 273245e0f3d6SRobert Watson return (0); 273345e0f3d6SRobert Watson 273445e0f3d6SRobert Watson subj = SLOT(cred->cr_label); 273545e0f3d6SRobert Watson obj = SLOT(dvplabel); 273645e0f3d6SRobert Watson 27373f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 273845e0f3d6SRobert Watson return (EACCES); 273945e0f3d6SRobert Watson 274045e0f3d6SRobert Watson obj = SLOT(vplabel); 274145e0f3d6SRobert Watson 27423f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 274345e0f3d6SRobert Watson return (EACCES); 274445e0f3d6SRobert Watson 274545e0f3d6SRobert Watson return (0); 274645e0f3d6SRobert Watson } 274745e0f3d6SRobert Watson 274845e0f3d6SRobert Watson static int 27493f1a7a90SRobert Watson lomac_vnode_check_write(struct ucred *active_cred, 275078007886SRobert Watson struct ucred *file_cred, struct vnode *vp, struct label *vplabel) 2751db2661ceSRobert Watson { 2752db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2753db2661ceSRobert Watson 27543f1a7a90SRobert Watson if (!lomac_enabled || !revocation_enabled) 2755db2661ceSRobert Watson return (0); 2756db2661ceSRobert Watson 2757eca8a663SRobert Watson subj = SLOT(active_cred->cr_label); 275878007886SRobert Watson obj = SLOT(vplabel); 2759db2661ceSRobert Watson 27603f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2761db2661ceSRobert Watson return (EACCES); 2762db2661ceSRobert Watson 2763db2661ceSRobert Watson return (0); 2764db2661ceSRobert Watson } 2765db2661ceSRobert Watson 2766eb320b0eSRobert Watson static int 2767eb320b0eSRobert Watson lomac_vnode_create_extattr(struct ucred *cred, struct mount *mp, 2768eb320b0eSRobert Watson struct label *mplabel, struct vnode *dvp, struct label *dvplabel, 2769eb320b0eSRobert Watson struct vnode *vp, struct label *vplabel, struct componentname *cnp) 2770db2661ceSRobert Watson { 2771eb320b0eSRobert Watson struct mac_lomac *source, *dest, *dir, temp; 2772eb320b0eSRobert Watson size_t buflen; 2773eb320b0eSRobert Watson int error; 2774db2661ceSRobert Watson 2775eb320b0eSRobert Watson buflen = sizeof(temp); 2776eb320b0eSRobert Watson bzero(&temp, buflen); 2777eb320b0eSRobert Watson 2778eb320b0eSRobert Watson source = SLOT(cred->cr_label); 2779eb320b0eSRobert Watson dest = SLOT(vplabel); 2780eb320b0eSRobert Watson dir = SLOT(dvplabel); 2781eb320b0eSRobert Watson if (dir->ml_flags & MAC_LOMAC_FLAG_AUX) { 2782eb320b0eSRobert Watson lomac_copy_auxsingle(dir, &temp); 2783eb320b0eSRobert Watson lomac_set_single(&temp, dir->ml_auxsingle.mle_type, 2784eb320b0eSRobert Watson dir->ml_auxsingle.mle_grade); 2785db2661ceSRobert Watson } else { 2786eb320b0eSRobert Watson lomac_copy_single(source, &temp); 2787db2661ceSRobert Watson } 2788eb320b0eSRobert Watson 2789eb320b0eSRobert Watson error = vn_extattr_set(vp, IO_NODELOCKED, MAC_LOMAC_EXTATTR_NAMESPACE, 2790eb320b0eSRobert Watson MAC_LOMAC_EXTATTR_NAME, buflen, (char *)&temp, curthread); 2791eb320b0eSRobert Watson if (error == 0) 2792eb320b0eSRobert Watson lomac_copy(&temp, dest); 2793eb320b0eSRobert Watson return (error); 2794eb320b0eSRobert Watson } 2795eb320b0eSRobert Watson 2796eb320b0eSRobert Watson static void 2797eb320b0eSRobert Watson lomac_vnode_execve_transition(struct ucred *old, struct ucred *new, 2798eb320b0eSRobert Watson struct vnode *vp, struct label *vplabel, struct label *interpvplabel, 2799eb320b0eSRobert Watson struct image_params *imgp, struct label *execlabel) 2800eb320b0eSRobert Watson { 2801eb320b0eSRobert Watson struct mac_lomac *source, *dest, *obj, *robj; 2802eb320b0eSRobert Watson 2803eb320b0eSRobert Watson source = SLOT(old->cr_label); 2804eb320b0eSRobert Watson dest = SLOT(new->cr_label); 2805eb320b0eSRobert Watson obj = SLOT(vplabel); 2806eb320b0eSRobert Watson robj = interpvplabel != NULL ? SLOT(interpvplabel) : obj; 2807eb320b0eSRobert Watson 2808eb320b0eSRobert Watson lomac_copy(source, dest); 2809eb320b0eSRobert Watson /* 2810eb320b0eSRobert Watson * If there's an auxiliary label on the real object, respect it and 2811eb320b0eSRobert Watson * assume that this level should be assumed immediately if a higher 2812eb320b0eSRobert Watson * level is currently in place. 2813eb320b0eSRobert Watson */ 2814eb320b0eSRobert Watson if (robj->ml_flags & MAC_LOMAC_FLAG_AUX && 2815eb320b0eSRobert Watson !lomac_dominate_element(&robj->ml_auxsingle, &dest->ml_single) 2816eb320b0eSRobert Watson && lomac_auxsingle_in_range(robj, dest)) 2817eb320b0eSRobert Watson lomac_set_single(dest, robj->ml_auxsingle.mle_type, 2818eb320b0eSRobert Watson robj->ml_auxsingle.mle_grade); 2819eb320b0eSRobert Watson /* 2820eb320b0eSRobert Watson * Restructuring to use the execve transitioning mechanism instead of 2821eb320b0eSRobert Watson * the normal demotion mechanism here would be difficult, so just 2822eb320b0eSRobert Watson * copy the label over and perform standard demotion. This is also 2823eb320b0eSRobert Watson * non-optimal because it will result in the intermediate label "new" 2824eb320b0eSRobert Watson * being created and immediately recycled. 2825eb320b0eSRobert Watson */ 2826eb320b0eSRobert Watson if (lomac_enabled && revocation_enabled && 2827eb320b0eSRobert Watson !lomac_dominate_single(obj, source)) 2828eb320b0eSRobert Watson (void)maybe_demote(source, obj, "executing", "file", vp); 2829eb320b0eSRobert Watson } 2830eb320b0eSRobert Watson 2831eb320b0eSRobert Watson static int 2832eb320b0eSRobert Watson lomac_vnode_execve_will_transition(struct ucred *old, struct vnode *vp, 2833eb320b0eSRobert Watson struct label *vplabel, struct label *interpvplabel, 2834eb320b0eSRobert Watson struct image_params *imgp, struct label *execlabel) 2835eb320b0eSRobert Watson { 2836eb320b0eSRobert Watson struct mac_lomac *subj, *obj, *robj; 2837eb320b0eSRobert Watson 2838eb320b0eSRobert Watson if (!lomac_enabled || !revocation_enabled) 2839eb320b0eSRobert Watson return (0); 2840eb320b0eSRobert Watson 2841eb320b0eSRobert Watson subj = SLOT(old->cr_label); 2842eb320b0eSRobert Watson obj = SLOT(vplabel); 2843eb320b0eSRobert Watson robj = interpvplabel != NULL ? SLOT(interpvplabel) : obj; 2844eb320b0eSRobert Watson 2845eb320b0eSRobert Watson return ((robj->ml_flags & MAC_LOMAC_FLAG_AUX && 2846eb320b0eSRobert Watson !lomac_dominate_element(&robj->ml_auxsingle, &subj->ml_single) 2847eb320b0eSRobert Watson && lomac_auxsingle_in_range(robj, subj)) || 2848eb320b0eSRobert Watson !lomac_dominate_single(obj, subj)); 2849eb320b0eSRobert Watson } 2850eb320b0eSRobert Watson 2851eb320b0eSRobert Watson static void 2852eb320b0eSRobert Watson lomac_vnode_relabel(struct ucred *cred, struct vnode *vp, 2853eb320b0eSRobert Watson struct label *vplabel, struct label *newlabel) 2854eb320b0eSRobert Watson { 2855eb320b0eSRobert Watson struct mac_lomac *source, *dest; 2856eb320b0eSRobert Watson 2857eb320b0eSRobert Watson source = SLOT(newlabel); 2858eb320b0eSRobert Watson dest = SLOT(vplabel); 2859eb320b0eSRobert Watson 2860eb320b0eSRobert Watson try_relabel(source, dest); 2861eb320b0eSRobert Watson } 2862eb320b0eSRobert Watson 2863eb320b0eSRobert Watson static int 2864eb320b0eSRobert Watson lomac_vnode_setlabel_extattr(struct ucred *cred, struct vnode *vp, 2865eb320b0eSRobert Watson struct label *vplabel, struct label *intlabel) 2866eb320b0eSRobert Watson { 2867eb320b0eSRobert Watson struct mac_lomac *source, temp; 2868eb320b0eSRobert Watson size_t buflen; 2869eb320b0eSRobert Watson int error; 2870eb320b0eSRobert Watson 2871eb320b0eSRobert Watson buflen = sizeof(temp); 2872eb320b0eSRobert Watson bzero(&temp, buflen); 2873eb320b0eSRobert Watson 2874eb320b0eSRobert Watson source = SLOT(intlabel); 2875eb320b0eSRobert Watson if ((source->ml_flags & MAC_LOMAC_FLAG_SINGLE) == 0) 2876eb320b0eSRobert Watson return (0); 2877eb320b0eSRobert Watson 2878eb320b0eSRobert Watson lomac_copy_single(source, &temp); 2879eb320b0eSRobert Watson error = vn_extattr_set(vp, IO_NODELOCKED, MAC_LOMAC_EXTATTR_NAMESPACE, 2880eb320b0eSRobert Watson MAC_LOMAC_EXTATTR_NAME, buflen, (char *)&temp, curthread); 2881eb320b0eSRobert Watson return (error); 2882db2661ceSRobert Watson } 2883db2661ceSRobert Watson 28843f1a7a90SRobert Watson static struct mac_policy_ops lomac_ops = 2885db2661ceSRobert Watson { 28863f1a7a90SRobert Watson .mpo_init = lomac_init, 2887eb320b0eSRobert Watson 2888eb320b0eSRobert Watson .mpo_bpfdesc_check_receive = lomac_bpfdesc_check_receive, 2889eb320b0eSRobert Watson .mpo_bpfdesc_create = lomac_bpfdesc_create, 2890eb320b0eSRobert Watson .mpo_bpfdesc_create_mbuf = lomac_bpfdesc_create_mbuf, 28913f1a7a90SRobert Watson .mpo_bpfdesc_destroy_label = lomac_destroy_label, 2892eb320b0eSRobert Watson .mpo_bpfdesc_init_label = lomac_init_label, 2893eb320b0eSRobert Watson 2894eb320b0eSRobert Watson .mpo_cred_check_relabel = lomac_cred_check_relabel, 2895eb320b0eSRobert Watson .mpo_cred_check_visible = lomac_cred_check_visible, 28963f1a7a90SRobert Watson .mpo_cred_copy_label = lomac_copy_label, 2897212ab0cfSRobert Watson .mpo_cred_create_swapper = lomac_cred_create_swapper, 2898212ab0cfSRobert Watson .mpo_cred_create_init = lomac_cred_create_init, 2899eb320b0eSRobert Watson .mpo_cred_destroy_label = lomac_destroy_label, 29003f1a7a90SRobert Watson .mpo_cred_externalize_label = lomac_externalize_label, 2901eb320b0eSRobert Watson .mpo_cred_init_label = lomac_init_label, 29023f1a7a90SRobert Watson .mpo_cred_internalize_label = lomac_internalize_label, 2903eb320b0eSRobert Watson .mpo_cred_relabel = lomac_cred_relabel, 2904eb320b0eSRobert Watson 29053f1a7a90SRobert Watson .mpo_devfs_create_device = lomac_devfs_create_device, 29063f1a7a90SRobert Watson .mpo_devfs_create_directory = lomac_devfs_create_directory, 29073f1a7a90SRobert Watson .mpo_devfs_create_symlink = lomac_devfs_create_symlink, 2908eb320b0eSRobert Watson .mpo_devfs_destroy_label = lomac_destroy_label, 2909eb320b0eSRobert Watson .mpo_devfs_init_label = lomac_init_label, 29103f1a7a90SRobert Watson .mpo_devfs_update = lomac_devfs_update, 29113f1a7a90SRobert Watson .mpo_devfs_vnode_associate = lomac_devfs_vnode_associate, 2912eb320b0eSRobert Watson 29133f1a7a90SRobert Watson .mpo_ifnet_check_relabel = lomac_ifnet_check_relabel, 29143f1a7a90SRobert Watson .mpo_ifnet_check_transmit = lomac_ifnet_check_transmit, 2915eb320b0eSRobert Watson .mpo_ifnet_copy_label = lomac_copy_label, 2916eb320b0eSRobert Watson .mpo_ifnet_create = lomac_ifnet_create, 2917eb320b0eSRobert Watson .mpo_ifnet_create_mbuf = lomac_ifnet_create_mbuf, 2918eb320b0eSRobert Watson .mpo_ifnet_destroy_label = lomac_destroy_label, 2919eb320b0eSRobert Watson .mpo_ifnet_externalize_label = lomac_externalize_label, 2920eb320b0eSRobert Watson .mpo_ifnet_init_label = lomac_init_label, 2921eb320b0eSRobert Watson .mpo_ifnet_internalize_label = lomac_internalize_label, 2922eb320b0eSRobert Watson .mpo_ifnet_relabel = lomac_ifnet_relabel, 2923eb320b0eSRobert Watson 2924eb320b0eSRobert Watson .mpo_syncache_create = lomac_syncache_create, 2925eb320b0eSRobert Watson .mpo_syncache_destroy_label = lomac_destroy_label, 2926eb320b0eSRobert Watson .mpo_syncache_init_label = lomac_init_label_waitcheck, 2927eb320b0eSRobert Watson 29283f1a7a90SRobert Watson .mpo_inpcb_check_deliver = lomac_inpcb_check_deliver, 29297fb179baSBjoern A. Zeeb .mpo_inpcb_check_visible = lomac_inpcb_check_visible, 2930eb320b0eSRobert Watson .mpo_inpcb_create = lomac_inpcb_create, 2931eb320b0eSRobert Watson .mpo_inpcb_create_mbuf = lomac_inpcb_create_mbuf, 2932eb320b0eSRobert Watson .mpo_inpcb_destroy_label = lomac_destroy_label, 2933eb320b0eSRobert Watson .mpo_inpcb_init_label = lomac_init_label_waitcheck, 2934eb320b0eSRobert Watson .mpo_inpcb_sosetlabel = lomac_inpcb_sosetlabel, 2935eb320b0eSRobert Watson 2936048e1287SRobert Watson .mpo_ip6q_create = lomac_ip6q_create, 2937048e1287SRobert Watson .mpo_ip6q_destroy_label = lomac_destroy_label, 2938048e1287SRobert Watson .mpo_ip6q_init_label = lomac_init_label_waitcheck, 2939048e1287SRobert Watson .mpo_ip6q_match = lomac_ip6q_match, 2940048e1287SRobert Watson .mpo_ip6q_reassemble = lomac_ip6q_reassemble, 2941048e1287SRobert Watson .mpo_ip6q_update = lomac_ip6q_update, 2942048e1287SRobert Watson 2943eb320b0eSRobert Watson .mpo_ipq_create = lomac_ipq_create, 2944eb320b0eSRobert Watson .mpo_ipq_destroy_label = lomac_destroy_label, 2945eb320b0eSRobert Watson .mpo_ipq_init_label = lomac_init_label_waitcheck, 2946eb320b0eSRobert Watson .mpo_ipq_match = lomac_ipq_match, 2947eb320b0eSRobert Watson .mpo_ipq_reassemble = lomac_ipq_reassemble, 2948eb320b0eSRobert Watson .mpo_ipq_update = lomac_ipq_update, 2949eb320b0eSRobert Watson 29503f1a7a90SRobert Watson .mpo_kld_check_load = lomac_kld_check_load, 2951eb320b0eSRobert Watson 2952eb320b0eSRobert Watson .mpo_mbuf_copy_label = lomac_copy_label, 2953eb320b0eSRobert Watson .mpo_mbuf_destroy_label = lomac_destroy_label, 2954eb320b0eSRobert Watson .mpo_mbuf_init_label = lomac_init_label_waitcheck, 2955eb320b0eSRobert Watson 2956eb320b0eSRobert Watson .mpo_mount_create = lomac_mount_create, 2957eb320b0eSRobert Watson .mpo_mount_destroy_label = lomac_destroy_label, 2958eb320b0eSRobert Watson .mpo_mount_init_label = lomac_init_label, 2959eb320b0eSRobert Watson 2960eb320b0eSRobert Watson .mpo_netatalk_aarp_send = lomac_netatalk_aarp_send, 2961eb320b0eSRobert Watson 2962eb320b0eSRobert Watson .mpo_netinet_arp_send = lomac_netinet_arp_send, 2963eb320b0eSRobert Watson .mpo_netinet_firewall_reply = lomac_netinet_firewall_reply, 2964eb320b0eSRobert Watson .mpo_netinet_firewall_send = lomac_netinet_firewall_send, 2965eb320b0eSRobert Watson .mpo_netinet_fragment = lomac_netinet_fragment, 2966eb320b0eSRobert Watson .mpo_netinet_icmp_reply = lomac_netinet_icmp_reply, 2967eb320b0eSRobert Watson .mpo_netinet_igmp_send = lomac_netinet_igmp_send, 2968eb320b0eSRobert Watson 2969eb320b0eSRobert Watson .mpo_netinet6_nd6_send = lomac_netinet6_nd6_send, 2970eb320b0eSRobert Watson 29713f1a7a90SRobert Watson .mpo_pipe_check_ioctl = lomac_pipe_check_ioctl, 29723f1a7a90SRobert Watson .mpo_pipe_check_read = lomac_pipe_check_read, 29733f1a7a90SRobert Watson .mpo_pipe_check_relabel = lomac_pipe_check_relabel, 29743f1a7a90SRobert Watson .mpo_pipe_check_write = lomac_pipe_check_write, 2975eb320b0eSRobert Watson .mpo_pipe_copy_label = lomac_copy_label, 2976eb320b0eSRobert Watson .mpo_pipe_create = lomac_pipe_create, 2977eb320b0eSRobert Watson .mpo_pipe_destroy_label = lomac_destroy_label, 2978eb320b0eSRobert Watson .mpo_pipe_externalize_label = lomac_externalize_label, 2979eb320b0eSRobert Watson .mpo_pipe_init_label = lomac_init_label, 2980eb320b0eSRobert Watson .mpo_pipe_internalize_label = lomac_internalize_label, 2981eb320b0eSRobert Watson .mpo_pipe_relabel = lomac_pipe_relabel, 2982eb320b0eSRobert Watson 2983eb320b0eSRobert Watson .mpo_priv_check = lomac_priv_check, 2984eb320b0eSRobert Watson 29853f1a7a90SRobert Watson .mpo_proc_check_debug = lomac_proc_check_debug, 29863f1a7a90SRobert Watson .mpo_proc_check_sched = lomac_proc_check_sched, 29873f1a7a90SRobert Watson .mpo_proc_check_signal = lomac_proc_check_signal, 2988eb320b0eSRobert Watson .mpo_proc_destroy_label = lomac_proc_destroy_label, 2989eb320b0eSRobert Watson .mpo_proc_init_label = lomac_proc_init_label, 2990eb320b0eSRobert Watson 29913f1a7a90SRobert Watson .mpo_socket_check_deliver = lomac_socket_check_deliver, 29923f1a7a90SRobert Watson .mpo_socket_check_relabel = lomac_socket_check_relabel, 29933f1a7a90SRobert Watson .mpo_socket_check_visible = lomac_socket_check_visible, 2994eb320b0eSRobert Watson .mpo_socket_copy_label = lomac_copy_label, 2995eb320b0eSRobert Watson .mpo_socket_create = lomac_socket_create, 2996eb320b0eSRobert Watson .mpo_socket_create_mbuf = lomac_socket_create_mbuf, 2997eb320b0eSRobert Watson .mpo_socket_destroy_label = lomac_destroy_label, 2998eb320b0eSRobert Watson .mpo_socket_externalize_label = lomac_externalize_label, 2999eb320b0eSRobert Watson .mpo_socket_init_label = lomac_init_label_waitcheck, 3000eb320b0eSRobert Watson .mpo_socket_internalize_label = lomac_internalize_label, 3001eb320b0eSRobert Watson .mpo_socket_newconn = lomac_socket_newconn, 3002eb320b0eSRobert Watson .mpo_socket_relabel = lomac_socket_relabel, 3003eb320b0eSRobert Watson 3004eb320b0eSRobert Watson .mpo_socketpeer_destroy_label = lomac_destroy_label, 3005eb320b0eSRobert Watson .mpo_socketpeer_externalize_label = lomac_externalize_label, 3006eb320b0eSRobert Watson .mpo_socketpeer_init_label = lomac_init_label_waitcheck, 3007eb320b0eSRobert Watson .mpo_socketpeer_set_from_mbuf = lomac_socketpeer_set_from_mbuf, 3008eb320b0eSRobert Watson .mpo_socketpeer_set_from_socket = lomac_socketpeer_set_from_socket, 3009eb320b0eSRobert Watson 3010eb320b0eSRobert Watson .mpo_syncache_create_mbuf = lomac_syncache_create_mbuf, 3011eb320b0eSRobert Watson 30123f1a7a90SRobert Watson .mpo_system_check_acct = lomac_system_check_acct, 30133f1a7a90SRobert Watson .mpo_system_check_auditctl = lomac_system_check_auditctl, 30143f1a7a90SRobert Watson .mpo_system_check_swapoff = lomac_system_check_swapoff, 30153f1a7a90SRobert Watson .mpo_system_check_swapon = lomac_system_check_swapon, 30163f1a7a90SRobert Watson .mpo_system_check_sysctl = lomac_system_check_sysctl, 3017eb320b0eSRobert Watson 3018eb320b0eSRobert Watson .mpo_thread_userret = lomac_thread_userret, 3019eb320b0eSRobert Watson 3020eb320b0eSRobert Watson .mpo_vnode_associate_extattr = lomac_vnode_associate_extattr, 3021eb320b0eSRobert Watson .mpo_vnode_associate_singlelabel = lomac_vnode_associate_singlelabel, 30223f1a7a90SRobert Watson .mpo_vnode_check_access = lomac_vnode_check_open, 30233f1a7a90SRobert Watson .mpo_vnode_check_create = lomac_vnode_check_create, 30243f1a7a90SRobert Watson .mpo_vnode_check_deleteacl = lomac_vnode_check_deleteacl, 30253f1a7a90SRobert Watson .mpo_vnode_check_link = lomac_vnode_check_link, 30263f1a7a90SRobert Watson .mpo_vnode_check_mmap = lomac_vnode_check_mmap, 30273f1a7a90SRobert Watson .mpo_vnode_check_mmap_downgrade = lomac_vnode_check_mmap_downgrade, 30283f1a7a90SRobert Watson .mpo_vnode_check_open = lomac_vnode_check_open, 30293f1a7a90SRobert Watson .mpo_vnode_check_read = lomac_vnode_check_read, 30303f1a7a90SRobert Watson .mpo_vnode_check_relabel = lomac_vnode_check_relabel, 30313f1a7a90SRobert Watson .mpo_vnode_check_rename_from = lomac_vnode_check_rename_from, 30323f1a7a90SRobert Watson .mpo_vnode_check_rename_to = lomac_vnode_check_rename_to, 30333f1a7a90SRobert Watson .mpo_vnode_check_revoke = lomac_vnode_check_revoke, 30343f1a7a90SRobert Watson .mpo_vnode_check_setacl = lomac_vnode_check_setacl, 30353f1a7a90SRobert Watson .mpo_vnode_check_setextattr = lomac_vnode_check_setextattr, 30363f1a7a90SRobert Watson .mpo_vnode_check_setflags = lomac_vnode_check_setflags, 30373f1a7a90SRobert Watson .mpo_vnode_check_setmode = lomac_vnode_check_setmode, 30383f1a7a90SRobert Watson .mpo_vnode_check_setowner = lomac_vnode_check_setowner, 30393f1a7a90SRobert Watson .mpo_vnode_check_setutimes = lomac_vnode_check_setutimes, 30403f1a7a90SRobert Watson .mpo_vnode_check_unlink = lomac_vnode_check_unlink, 30413f1a7a90SRobert Watson .mpo_vnode_check_write = lomac_vnode_check_write, 3042eb320b0eSRobert Watson .mpo_vnode_copy_label = lomac_copy_label, 3043eb320b0eSRobert Watson .mpo_vnode_create_extattr = lomac_vnode_create_extattr, 3044eb320b0eSRobert Watson .mpo_vnode_destroy_label = lomac_destroy_label, 3045eb320b0eSRobert Watson .mpo_vnode_execve_transition = lomac_vnode_execve_transition, 3046eb320b0eSRobert Watson .mpo_vnode_execve_will_transition = lomac_vnode_execve_will_transition, 3047eb320b0eSRobert Watson .mpo_vnode_externalize_label = lomac_externalize_label, 3048eb320b0eSRobert Watson .mpo_vnode_init_label = lomac_init_label, 3049eb320b0eSRobert Watson .mpo_vnode_internalize_label = lomac_internalize_label, 3050eb320b0eSRobert Watson .mpo_vnode_relabel = lomac_vnode_relabel, 3051eb320b0eSRobert Watson .mpo_vnode_setlabel_extattr = lomac_vnode_setlabel_extattr, 3052db2661ceSRobert Watson }; 3053db2661ceSRobert Watson 30543f1a7a90SRobert Watson MAC_POLICY_SET(&lomac_ops, mac_lomac, "TrustedBSD MAC/LOMAC", 30559162f64bSRobert Watson MPC_LOADTIME_FLAG_NOTLATE, &lomac_slot); 3056