1db2661ceSRobert Watson /*- 23de40469SRobert Watson * Copyright (c) 1999-2002, 2007-2009 Robert N. M. Watson 3c77cf2b1SRobert Watson * Copyright (c) 2001-2005 Networks Associates Technology, Inc. 430d239bcSRobert Watson * Copyright (c) 2006 SPARTA, Inc. 5db2661ceSRobert Watson * All rights reserved. 6db2661ceSRobert Watson * 7db2661ceSRobert Watson * This software was developed by Robert Watson for the TrustedBSD Project. 8db2661ceSRobert Watson * 9db2661ceSRobert Watson * This software was developed for the FreeBSD Project in part by NAI Labs, 10db2661ceSRobert Watson * the Security Research Division of Network Associates, Inc. under 11db2661ceSRobert Watson * DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA 12db2661ceSRobert Watson * CHATS research program. 13db2661ceSRobert Watson * 1430d239bcSRobert Watson * This software was enhanced by SPARTA ISSO under SPAWAR contract 1530d239bcSRobert Watson * N66001-04-C-6019 ("SEFOS"). 1630d239bcSRobert Watson * 17db2661ceSRobert Watson * Redistribution and use in source and binary forms, with or without 18db2661ceSRobert Watson * modification, are permitted provided that the following conditions 19db2661ceSRobert Watson * are met: 20db2661ceSRobert Watson * 1. Redistributions of source code must retain the above copyright 21db2661ceSRobert Watson * notice, this list of conditions and the following disclaimer. 22db2661ceSRobert Watson * 2. Redistributions in binary form must reproduce the above copyright 23db2661ceSRobert Watson * notice, this list of conditions and the following disclaimer in the 24db2661ceSRobert Watson * documentation and/or other materials provided with the distribution. 25db2661ceSRobert Watson * 26db2661ceSRobert Watson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 27db2661ceSRobert Watson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28db2661ceSRobert Watson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29db2661ceSRobert Watson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 30db2661ceSRobert Watson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31db2661ceSRobert Watson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32db2661ceSRobert Watson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33db2661ceSRobert Watson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34db2661ceSRobert Watson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35db2661ceSRobert Watson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36db2661ceSRobert Watson * SUCH DAMAGE. 37db2661ceSRobert Watson * 38db2661ceSRobert Watson * $FreeBSD$ 39db2661ceSRobert Watson */ 40db2661ceSRobert Watson 41db2661ceSRobert Watson /* 42db2661ceSRobert Watson * Developed by the TrustedBSD Project. 43c14d15aeSRobert Watson * 44db2661ceSRobert Watson * Low-watermark floating label mandatory integrity policy. 45db2661ceSRobert Watson */ 46db2661ceSRobert Watson 47db2661ceSRobert Watson #include <sys/types.h> 48db2661ceSRobert Watson #include <sys/param.h> 49db2661ceSRobert Watson #include <sys/acl.h> 50db2661ceSRobert Watson #include <sys/conf.h> 51db2661ceSRobert Watson #include <sys/extattr.h> 52db2661ceSRobert Watson #include <sys/kernel.h> 53db2661ceSRobert Watson #include <sys/malloc.h> 54c92163dcSChristian S.J. Peron #include <sys/mman.h> 55db2661ceSRobert Watson #include <sys/mount.h> 56acd3428bSRobert Watson #include <sys/priv.h> 57db2661ceSRobert Watson #include <sys/proc.h> 58f51e5803SRobert Watson #include <sys/sbuf.h> 59db2661ceSRobert Watson #include <sys/systm.h> 60db2661ceSRobert Watson #include <sys/sysproto.h> 61db2661ceSRobert Watson #include <sys/sysent.h> 62db2661ceSRobert Watson #include <sys/systm.h> 63db2661ceSRobert Watson #include <sys/vnode.h> 64db2661ceSRobert Watson #include <sys/file.h> 65db2661ceSRobert Watson #include <sys/socket.h> 66db2661ceSRobert Watson #include <sys/socketvar.h> 6736422989SPoul-Henning Kamp #include <sys/sx.h> 68db2661ceSRobert Watson #include <sys/pipe.h> 69db2661ceSRobert Watson #include <sys/sysctl.h> 70db2661ceSRobert Watson #include <sys/syslog.h> 71db2661ceSRobert Watson 72db2661ceSRobert Watson #include <fs/devfs/devfs.h> 73db2661ceSRobert Watson 74db2661ceSRobert Watson #include <net/bpfdesc.h> 75db2661ceSRobert Watson #include <net/if.h> 76db2661ceSRobert Watson #include <net/if_types.h> 77db2661ceSRobert Watson #include <net/if_var.h> 78db2661ceSRobert Watson 79db2661ceSRobert Watson #include <netinet/in.h> 80a557af22SRobert Watson #include <netinet/in_pcb.h> 81db2661ceSRobert Watson #include <netinet/ip_var.h> 82db2661ceSRobert Watson 83db2661ceSRobert Watson #include <vm/vm.h> 84db2661ceSRobert Watson 850efd6615SRobert Watson #include <security/mac/mac_policy.h> 86aed55708SRobert Watson #include <security/mac/mac_framework.h> 87db2661ceSRobert Watson #include <security/mac_lomac/mac_lomac.h> 88db2661ceSRobert Watson 89db2661ceSRobert Watson struct mac_lomac_proc { 90db2661ceSRobert Watson struct mac_lomac mac_lomac; 91db2661ceSRobert Watson struct mtx mtx; 92db2661ceSRobert Watson }; 93db2661ceSRobert Watson 94db2661ceSRobert Watson SYSCTL_DECL(_security_mac); 95db2661ceSRobert Watson 966472ac3dSEd Schouten static 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; 104*af3b2549SHans Petter Selasky SYSCTL_INT(_security_mac_lomac, OID_AUTO, enabled, CTLFLAG_RWTUN, 1053f1a7a90SRobert Watson &lomac_enabled, 0, "Enforce MAC/LOMAC policy"); 106db2661ceSRobert Watson 107db2661ceSRobert Watson static int destroyed_not_inited; 108db2661ceSRobert Watson SYSCTL_INT(_security_mac_lomac, OID_AUTO, destroyed_not_inited, CTLFLAG_RD, 109db2661ceSRobert Watson &destroyed_not_inited, 0, "Count of labels destroyed but not inited"); 110db2661ceSRobert Watson 111db2661ceSRobert Watson static int trust_all_interfaces = 0; 112*af3b2549SHans Petter Selasky SYSCTL_INT(_security_mac_lomac, OID_AUTO, trust_all_interfaces, CTLFLAG_RDTUN, 113db2661ceSRobert Watson &trust_all_interfaces, 0, "Consider all interfaces 'trusted' by MAC/LOMAC"); 114db2661ceSRobert Watson 115db2661ceSRobert Watson static char trusted_interfaces[128]; 116*af3b2549SHans Petter Selasky SYSCTL_STRING(_security_mac_lomac, OID_AUTO, trusted_interfaces, CTLFLAG_RDTUN, 117db2661ceSRobert Watson trusted_interfaces, 0, "Interfaces considered 'trusted' by MAC/LOMAC"); 118db2661ceSRobert Watson 119db2661ceSRobert Watson static int ptys_equal = 0; 120*af3b2549SHans Petter Selasky SYSCTL_INT(_security_mac_lomac, OID_AUTO, ptys_equal, CTLFLAG_RWTUN, 121db2661ceSRobert Watson &ptys_equal, 0, "Label pty devices as lomac/equal on create"); 122db2661ceSRobert Watson 123db2661ceSRobert Watson static int revocation_enabled = 1; 124*af3b2549SHans Petter Selasky SYSCTL_INT(_security_mac_lomac, OID_AUTO, revocation_enabled, CTLFLAG_RWTUN, 125db2661ceSRobert Watson &revocation_enabled, 0, "Revoke access to objects on relabel"); 126db2661ceSRobert Watson 1273f1a7a90SRobert Watson static int lomac_slot; 1283f1a7a90SRobert Watson #define SLOT(l) ((struct mac_lomac *)mac_label_get((l), lomac_slot)) 1293f1a7a90SRobert Watson #define SLOT_SET(l, val) mac_label_set((l), lomac_slot, (uintptr_t)(val)) 130db2661ceSRobert Watson #define PSLOT(l) ((struct mac_lomac_proc *) \ 1313f1a7a90SRobert Watson mac_label_get((l), lomac_slot)) 1323f1a7a90SRobert Watson #define PSLOT_SET(l, val) mac_label_set((l), lomac_slot, (uintptr_t)(val)) 133db2661ceSRobert Watson 134d745c852SEd Schouten static MALLOC_DEFINE(M_LOMAC, "mac_lomac_label", "MAC/LOMAC labels"); 135db2661ceSRobert Watson 136db2661ceSRobert Watson static struct mac_lomac * 137db2661ceSRobert Watson lomac_alloc(int flag) 138db2661ceSRobert Watson { 1393f1a7a90SRobert Watson struct mac_lomac *ml; 140db2661ceSRobert Watson 1413f1a7a90SRobert Watson ml = malloc(sizeof(*ml), M_LOMAC, M_ZERO | flag); 142db2661ceSRobert Watson 1433f1a7a90SRobert Watson return (ml); 144db2661ceSRobert Watson } 145db2661ceSRobert Watson 146db2661ceSRobert Watson static void 1473f1a7a90SRobert Watson lomac_free(struct mac_lomac *ml) 148db2661ceSRobert Watson { 149db2661ceSRobert Watson 1503f1a7a90SRobert Watson if (ml != NULL) 1513f1a7a90SRobert Watson free(ml, M_LOMAC); 152db2661ceSRobert Watson else 153db2661ceSRobert Watson atomic_add_int(&destroyed_not_inited, 1); 154db2661ceSRobert Watson } 155db2661ceSRobert Watson 156db2661ceSRobert Watson static int 1573f1a7a90SRobert Watson lomac_atmostflags(struct mac_lomac *ml, int flags) 158db2661ceSRobert Watson { 159db2661ceSRobert Watson 1603f1a7a90SRobert Watson if ((ml->ml_flags & flags) != ml->ml_flags) 161db2661ceSRobert Watson return (EINVAL); 162db2661ceSRobert Watson return (0); 163db2661ceSRobert Watson } 164db2661ceSRobert Watson 165db2661ceSRobert Watson static int 1663f1a7a90SRobert Watson lomac_dominate_element(struct mac_lomac_element *a, 167db2661ceSRobert Watson struct mac_lomac_element *b) 168db2661ceSRobert Watson { 169db2661ceSRobert Watson 170db2661ceSRobert Watson switch (a->mle_type) { 171db2661ceSRobert Watson case MAC_LOMAC_TYPE_EQUAL: 172db2661ceSRobert Watson case MAC_LOMAC_TYPE_HIGH: 173db2661ceSRobert Watson return (1); 174db2661ceSRobert Watson 175db2661ceSRobert Watson case MAC_LOMAC_TYPE_LOW: 176db2661ceSRobert Watson switch (b->mle_type) { 177db2661ceSRobert Watson case MAC_LOMAC_TYPE_GRADE: 178db2661ceSRobert Watson case MAC_LOMAC_TYPE_HIGH: 179db2661ceSRobert Watson return (0); 180db2661ceSRobert Watson 181db2661ceSRobert Watson case MAC_LOMAC_TYPE_EQUAL: 182db2661ceSRobert Watson case MAC_LOMAC_TYPE_LOW: 183db2661ceSRobert Watson return (1); 184db2661ceSRobert Watson 185db2661ceSRobert Watson default: 1863f1a7a90SRobert Watson panic("lomac_dominate_element: b->mle_type invalid"); 187db2661ceSRobert Watson } 188db2661ceSRobert Watson 189db2661ceSRobert Watson case MAC_LOMAC_TYPE_GRADE: 190db2661ceSRobert Watson switch (b->mle_type) { 191db2661ceSRobert Watson case MAC_LOMAC_TYPE_EQUAL: 192db2661ceSRobert Watson case MAC_LOMAC_TYPE_LOW: 193db2661ceSRobert Watson return (1); 194db2661ceSRobert Watson 195db2661ceSRobert Watson case MAC_LOMAC_TYPE_HIGH: 196db2661ceSRobert Watson return (0); 197db2661ceSRobert Watson 198db2661ceSRobert Watson case MAC_LOMAC_TYPE_GRADE: 199db2661ceSRobert Watson return (a->mle_grade >= b->mle_grade); 200db2661ceSRobert Watson 201db2661ceSRobert Watson default: 2023f1a7a90SRobert Watson panic("lomac_dominate_element: b->mle_type invalid"); 203db2661ceSRobert Watson } 204db2661ceSRobert Watson 205db2661ceSRobert Watson default: 2063f1a7a90SRobert Watson panic("lomac_dominate_element: a->mle_type invalid"); 207db2661ceSRobert Watson } 208db2661ceSRobert Watson } 209db2661ceSRobert Watson 210db2661ceSRobert Watson static int 2113f1a7a90SRobert Watson lomac_range_in_range(struct mac_lomac *rangea, struct mac_lomac *rangeb) 212db2661ceSRobert Watson { 213db2661ceSRobert Watson 2143f1a7a90SRobert Watson return (lomac_dominate_element(&rangeb->ml_rangehigh, 215db2661ceSRobert Watson &rangea->ml_rangehigh) && 2163f1a7a90SRobert Watson lomac_dominate_element(&rangea->ml_rangelow, 217db2661ceSRobert Watson &rangeb->ml_rangelow)); 218db2661ceSRobert Watson } 219db2661ceSRobert Watson 220db2661ceSRobert Watson static int 2213f1a7a90SRobert Watson lomac_single_in_range(struct mac_lomac *single, struct mac_lomac *range) 222db2661ceSRobert Watson { 223db2661ceSRobert Watson 224db2661ceSRobert Watson KASSERT((single->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0, 2253f1a7a90SRobert Watson ("lomac_single_in_range: a not single")); 226db2661ceSRobert Watson KASSERT((range->ml_flags & MAC_LOMAC_FLAG_RANGE) != 0, 2273f1a7a90SRobert Watson ("lomac_single_in_range: b not range")); 228db2661ceSRobert Watson 2293f1a7a90SRobert Watson return (lomac_dominate_element(&range->ml_rangehigh, 2303f1a7a90SRobert Watson &single->ml_single) && lomac_dominate_element(&single->ml_single, 231db2661ceSRobert Watson &range->ml_rangelow)); 232db2661ceSRobert Watson } 233db2661ceSRobert Watson 234db2661ceSRobert Watson static int 2353f1a7a90SRobert Watson lomac_auxsingle_in_range(struct mac_lomac *single, struct mac_lomac *range) 236db2661ceSRobert Watson { 237db2661ceSRobert Watson 238db2661ceSRobert Watson KASSERT((single->ml_flags & MAC_LOMAC_FLAG_AUX) != 0, 2393f1a7a90SRobert Watson ("lomac_single_in_range: a not auxsingle")); 240db2661ceSRobert Watson KASSERT((range->ml_flags & MAC_LOMAC_FLAG_RANGE) != 0, 2413f1a7a90SRobert Watson ("lomac_single_in_range: b not range")); 242db2661ceSRobert Watson 2433f1a7a90SRobert Watson return (lomac_dominate_element(&range->ml_rangehigh, 244db2661ceSRobert Watson &single->ml_auxsingle) && 2453f1a7a90SRobert Watson lomac_dominate_element(&single->ml_auxsingle, 246db2661ceSRobert Watson &range->ml_rangelow)); 247db2661ceSRobert Watson } 248db2661ceSRobert Watson 249db2661ceSRobert Watson static int 2503f1a7a90SRobert Watson lomac_dominate_single(struct mac_lomac *a, struct mac_lomac *b) 251db2661ceSRobert Watson { 252db2661ceSRobert Watson KASSERT((a->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0, 2533f1a7a90SRobert Watson ("lomac_dominate_single: a not single")); 254db2661ceSRobert Watson KASSERT((b->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0, 2553f1a7a90SRobert Watson ("lomac_dominate_single: b not single")); 256db2661ceSRobert Watson 2573f1a7a90SRobert Watson return (lomac_dominate_element(&a->ml_single, &b->ml_single)); 258db2661ceSRobert Watson } 259db2661ceSRobert Watson 260db2661ceSRobert Watson static int 2613f1a7a90SRobert Watson lomac_subject_dominate(struct mac_lomac *a, struct mac_lomac *b) 262db2661ceSRobert Watson { 263db2661ceSRobert Watson KASSERT((~a->ml_flags & 264db2661ceSRobert Watson (MAC_LOMAC_FLAG_SINGLE | MAC_LOMAC_FLAG_RANGE)) == 0, 2653f1a7a90SRobert Watson ("lomac_dominate_single: a not subject")); 266db2661ceSRobert Watson KASSERT((b->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0, 2673f1a7a90SRobert Watson ("lomac_dominate_single: b not single")); 268db2661ceSRobert Watson 2693f1a7a90SRobert Watson return (lomac_dominate_element(&a->ml_rangehigh, &b->ml_single)); 270db2661ceSRobert Watson } 271db2661ceSRobert Watson 272db2661ceSRobert Watson static int 2733f1a7a90SRobert Watson lomac_equal_element(struct mac_lomac_element *a, struct mac_lomac_element *b) 274db2661ceSRobert Watson { 275db2661ceSRobert Watson 276db2661ceSRobert Watson if (a->mle_type == MAC_LOMAC_TYPE_EQUAL || 277db2661ceSRobert Watson b->mle_type == MAC_LOMAC_TYPE_EQUAL) 278db2661ceSRobert Watson return (1); 279db2661ceSRobert Watson 280db2661ceSRobert Watson return (a->mle_type == b->mle_type && a->mle_grade == b->mle_grade); 281db2661ceSRobert Watson } 282db2661ceSRobert Watson 283db2661ceSRobert Watson static int 2843f1a7a90SRobert Watson lomac_equal_single(struct mac_lomac *a, struct mac_lomac *b) 285db2661ceSRobert Watson { 286db2661ceSRobert Watson 287db2661ceSRobert Watson KASSERT((a->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0, 2883f1a7a90SRobert Watson ("lomac_equal_single: a not single")); 289db2661ceSRobert Watson KASSERT((b->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0, 2903f1a7a90SRobert Watson ("lomac_equal_single: b not single")); 291db2661ceSRobert Watson 2923f1a7a90SRobert Watson return (lomac_equal_element(&a->ml_single, &b->ml_single)); 293db2661ceSRobert Watson } 294db2661ceSRobert Watson 295db2661ceSRobert Watson static int 2963f1a7a90SRobert Watson lomac_contains_equal(struct mac_lomac *ml) 297db2661ceSRobert Watson { 298db2661ceSRobert Watson 2993f1a7a90SRobert Watson if (ml->ml_flags & MAC_LOMAC_FLAG_SINGLE) 3003f1a7a90SRobert Watson if (ml->ml_single.mle_type == MAC_LOMAC_TYPE_EQUAL) 301db2661ceSRobert Watson return (1); 3023f1a7a90SRobert Watson if (ml->ml_flags & MAC_LOMAC_FLAG_AUX) 3033f1a7a90SRobert Watson if (ml->ml_auxsingle.mle_type == MAC_LOMAC_TYPE_EQUAL) 304db2661ceSRobert Watson return (1); 305db2661ceSRobert Watson 3063f1a7a90SRobert Watson if (ml->ml_flags & MAC_LOMAC_FLAG_RANGE) { 3073f1a7a90SRobert Watson if (ml->ml_rangelow.mle_type == MAC_LOMAC_TYPE_EQUAL) 308db2661ceSRobert Watson return (1); 3093f1a7a90SRobert Watson if (ml->ml_rangehigh.mle_type == MAC_LOMAC_TYPE_EQUAL) 310db2661ceSRobert Watson return (1); 311db2661ceSRobert Watson } 312db2661ceSRobert Watson 313db2661ceSRobert Watson return (0); 314db2661ceSRobert Watson } 315db2661ceSRobert Watson 316db2661ceSRobert Watson static int 3173f1a7a90SRobert Watson lomac_subject_privileged(struct mac_lomac *ml) 318db2661ceSRobert Watson { 319db2661ceSRobert Watson 3203f1a7a90SRobert Watson KASSERT((ml->ml_flags & MAC_LOMAC_FLAGS_BOTH) == 321db2661ceSRobert Watson MAC_LOMAC_FLAGS_BOTH, 3223f1a7a90SRobert Watson ("lomac_subject_privileged: subject doesn't have both labels")); 323db2661ceSRobert Watson 324db2661ceSRobert Watson /* If the single is EQUAL, it's ok. */ 3253f1a7a90SRobert Watson if (ml->ml_single.mle_type == MAC_LOMAC_TYPE_EQUAL) 326db2661ceSRobert Watson return (0); 327db2661ceSRobert Watson 328db2661ceSRobert Watson /* If either range endpoint is EQUAL, it's ok. */ 3293f1a7a90SRobert Watson if (ml->ml_rangelow.mle_type == MAC_LOMAC_TYPE_EQUAL || 3303f1a7a90SRobert Watson ml->ml_rangehigh.mle_type == MAC_LOMAC_TYPE_EQUAL) 331db2661ceSRobert Watson return (0); 332db2661ceSRobert Watson 333db2661ceSRobert Watson /* If the range is low-high, it's ok. */ 3343f1a7a90SRobert Watson if (ml->ml_rangelow.mle_type == MAC_LOMAC_TYPE_LOW && 3353f1a7a90SRobert Watson ml->ml_rangehigh.mle_type == MAC_LOMAC_TYPE_HIGH) 336db2661ceSRobert Watson return (0); 337db2661ceSRobert Watson 338db2661ceSRobert Watson /* It's not ok. */ 339db2661ceSRobert Watson return (EPERM); 340db2661ceSRobert Watson } 341db2661ceSRobert Watson 342db2661ceSRobert Watson static int 3433f1a7a90SRobert Watson lomac_high_single(struct mac_lomac *ml) 344db2661ceSRobert Watson { 345db2661ceSRobert Watson 3463f1a7a90SRobert Watson KASSERT((ml->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0, 3473f1a7a90SRobert Watson ("lomac_high_single: mac_lomac not single")); 348db2661ceSRobert Watson 3493f1a7a90SRobert Watson return (ml->ml_single.mle_type == MAC_LOMAC_TYPE_HIGH); 350db2661ceSRobert Watson } 351db2661ceSRobert Watson 352db2661ceSRobert Watson static int 3533f1a7a90SRobert Watson lomac_valid(struct mac_lomac *ml) 354db2661ceSRobert Watson { 355db2661ceSRobert Watson 3563f1a7a90SRobert Watson if (ml->ml_flags & MAC_LOMAC_FLAG_SINGLE) { 3573f1a7a90SRobert Watson switch (ml->ml_single.mle_type) { 358db2661ceSRobert Watson case MAC_LOMAC_TYPE_GRADE: 359db2661ceSRobert Watson case MAC_LOMAC_TYPE_EQUAL: 360db2661ceSRobert Watson case MAC_LOMAC_TYPE_HIGH: 361db2661ceSRobert Watson case MAC_LOMAC_TYPE_LOW: 362db2661ceSRobert Watson break; 363db2661ceSRobert Watson 364db2661ceSRobert Watson default: 365db2661ceSRobert Watson return (EINVAL); 366db2661ceSRobert Watson } 367db2661ceSRobert Watson } else { 3683f1a7a90SRobert Watson if (ml->ml_single.mle_type != MAC_LOMAC_TYPE_UNDEF) 369db2661ceSRobert Watson return (EINVAL); 370db2661ceSRobert Watson } 371db2661ceSRobert Watson 3723f1a7a90SRobert Watson if (ml->ml_flags & MAC_LOMAC_FLAG_AUX) { 3733f1a7a90SRobert Watson switch (ml->ml_auxsingle.mle_type) { 374db2661ceSRobert Watson case MAC_LOMAC_TYPE_GRADE: 375db2661ceSRobert Watson case MAC_LOMAC_TYPE_EQUAL: 376db2661ceSRobert Watson case MAC_LOMAC_TYPE_HIGH: 377db2661ceSRobert Watson case MAC_LOMAC_TYPE_LOW: 378db2661ceSRobert Watson break; 379db2661ceSRobert Watson 380db2661ceSRobert Watson default: 381db2661ceSRobert Watson return (EINVAL); 382db2661ceSRobert Watson } 383db2661ceSRobert Watson } else { 3843f1a7a90SRobert Watson if (ml->ml_auxsingle.mle_type != MAC_LOMAC_TYPE_UNDEF) 385db2661ceSRobert Watson return (EINVAL); 386db2661ceSRobert Watson } 387db2661ceSRobert Watson 3883f1a7a90SRobert Watson if (ml->ml_flags & MAC_LOMAC_FLAG_RANGE) { 3893f1a7a90SRobert Watson switch (ml->ml_rangelow.mle_type) { 390db2661ceSRobert Watson case MAC_LOMAC_TYPE_GRADE: 391db2661ceSRobert Watson case MAC_LOMAC_TYPE_EQUAL: 392db2661ceSRobert Watson case MAC_LOMAC_TYPE_HIGH: 393db2661ceSRobert Watson case MAC_LOMAC_TYPE_LOW: 394db2661ceSRobert Watson break; 395db2661ceSRobert Watson 396db2661ceSRobert Watson default: 397db2661ceSRobert Watson return (EINVAL); 398db2661ceSRobert Watson } 399db2661ceSRobert Watson 4003f1a7a90SRobert Watson switch (ml->ml_rangehigh.mle_type) { 401db2661ceSRobert Watson case MAC_LOMAC_TYPE_GRADE: 402db2661ceSRobert Watson case MAC_LOMAC_TYPE_EQUAL: 403db2661ceSRobert Watson case MAC_LOMAC_TYPE_HIGH: 404db2661ceSRobert Watson case MAC_LOMAC_TYPE_LOW: 405db2661ceSRobert Watson break; 406db2661ceSRobert Watson 407db2661ceSRobert Watson default: 408db2661ceSRobert Watson return (EINVAL); 409db2661ceSRobert Watson } 4103f1a7a90SRobert Watson if (!lomac_dominate_element(&ml->ml_rangehigh, 4113f1a7a90SRobert Watson &ml->ml_rangelow)) 412db2661ceSRobert Watson return (EINVAL); 413db2661ceSRobert Watson } else { 4143f1a7a90SRobert Watson if (ml->ml_rangelow.mle_type != MAC_LOMAC_TYPE_UNDEF || 4153f1a7a90SRobert Watson ml->ml_rangehigh.mle_type != MAC_LOMAC_TYPE_UNDEF) 416db2661ceSRobert Watson return (EINVAL); 417db2661ceSRobert Watson } 418db2661ceSRobert Watson 419db2661ceSRobert Watson return (0); 420db2661ceSRobert Watson } 421db2661ceSRobert Watson 422db2661ceSRobert Watson static void 4233f1a7a90SRobert Watson lomac_set_range(struct mac_lomac *ml, u_short typelow, u_short gradelow, 4243f1a7a90SRobert Watson u_short typehigh, u_short gradehigh) 425db2661ceSRobert Watson { 426db2661ceSRobert Watson 4273f1a7a90SRobert Watson ml->ml_rangelow.mle_type = typelow; 4283f1a7a90SRobert Watson ml->ml_rangelow.mle_grade = gradelow; 4293f1a7a90SRobert Watson ml->ml_rangehigh.mle_type = typehigh; 4303f1a7a90SRobert Watson ml->ml_rangehigh.mle_grade = gradehigh; 4313f1a7a90SRobert Watson ml->ml_flags |= MAC_LOMAC_FLAG_RANGE; 432db2661ceSRobert Watson } 433db2661ceSRobert Watson 434db2661ceSRobert Watson static void 4353f1a7a90SRobert Watson lomac_set_single(struct mac_lomac *ml, u_short type, u_short grade) 436db2661ceSRobert Watson { 437db2661ceSRobert Watson 4383f1a7a90SRobert Watson ml->ml_single.mle_type = type; 4393f1a7a90SRobert Watson ml->ml_single.mle_grade = grade; 4403f1a7a90SRobert Watson ml->ml_flags |= MAC_LOMAC_FLAG_SINGLE; 441db2661ceSRobert Watson } 442db2661ceSRobert Watson 443db2661ceSRobert Watson static void 4443f1a7a90SRobert Watson lomac_copy_range(struct mac_lomac *labelfrom, struct mac_lomac *labelto) 445db2661ceSRobert Watson { 446db2661ceSRobert Watson 447db2661ceSRobert Watson KASSERT((labelfrom->ml_flags & MAC_LOMAC_FLAG_RANGE) != 0, 4483f1a7a90SRobert Watson ("lomac_copy_range: labelfrom not range")); 449db2661ceSRobert Watson 450db2661ceSRobert Watson labelto->ml_rangelow = labelfrom->ml_rangelow; 451db2661ceSRobert Watson labelto->ml_rangehigh = labelfrom->ml_rangehigh; 452db2661ceSRobert Watson labelto->ml_flags |= MAC_LOMAC_FLAG_RANGE; 453db2661ceSRobert Watson } 454db2661ceSRobert Watson 455db2661ceSRobert Watson static void 4563f1a7a90SRobert Watson lomac_copy_single(struct mac_lomac *labelfrom, struct mac_lomac *labelto) 457db2661ceSRobert Watson { 458db2661ceSRobert Watson 459db2661ceSRobert Watson KASSERT((labelfrom->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0, 4603f1a7a90SRobert Watson ("lomac_copy_single: labelfrom not single")); 461db2661ceSRobert Watson 462db2661ceSRobert Watson labelto->ml_single = labelfrom->ml_single; 463db2661ceSRobert Watson labelto->ml_flags |= MAC_LOMAC_FLAG_SINGLE; 464db2661ceSRobert Watson } 465db2661ceSRobert Watson 466db2661ceSRobert Watson static void 4673f1a7a90SRobert Watson lomac_copy_auxsingle(struct mac_lomac *labelfrom, struct mac_lomac *labelto) 468db2661ceSRobert Watson { 469db2661ceSRobert Watson 470db2661ceSRobert Watson KASSERT((labelfrom->ml_flags & MAC_LOMAC_FLAG_AUX) != 0, 4713f1a7a90SRobert Watson ("lomac_copy_auxsingle: labelfrom not auxsingle")); 472db2661ceSRobert Watson 473db2661ceSRobert Watson labelto->ml_auxsingle = labelfrom->ml_auxsingle; 474db2661ceSRobert Watson labelto->ml_flags |= MAC_LOMAC_FLAG_AUX; 475db2661ceSRobert Watson } 476db2661ceSRobert Watson 477db2661ceSRobert Watson static void 4783f1a7a90SRobert Watson lomac_copy(struct mac_lomac *source, struct mac_lomac *dest) 479db2661ceSRobert Watson { 480db2661ceSRobert Watson 481db2661ceSRobert Watson if (source->ml_flags & MAC_LOMAC_FLAG_SINGLE) 4823f1a7a90SRobert Watson lomac_copy_single(source, dest); 483db2661ceSRobert Watson if (source->ml_flags & MAC_LOMAC_FLAG_AUX) 4843f1a7a90SRobert Watson lomac_copy_auxsingle(source, dest); 485db2661ceSRobert Watson if (source->ml_flags & MAC_LOMAC_FLAG_RANGE) 4863f1a7a90SRobert Watson lomac_copy_range(source, dest); 487db2661ceSRobert Watson } 488db2661ceSRobert Watson 4893f1a7a90SRobert Watson static int lomac_to_string(struct sbuf *sb, struct mac_lomac *ml); 490db2661ceSRobert Watson 491db2661ceSRobert Watson static int 492db2661ceSRobert Watson maybe_demote(struct mac_lomac *subjlabel, struct mac_lomac *objlabel, 49378007886SRobert Watson const char *actionname, const char *objname, struct vnode *vp) 494db2661ceSRobert Watson { 495f51e5803SRobert Watson struct sbuf subjlabel_sb, subjtext_sb, objlabel_sb; 496f51e5803SRobert Watson char *subjlabeltext, *objlabeltext, *subjtext; 497f51e5803SRobert Watson struct mac_lomac cached_subjlabel; 498f51e5803SRobert Watson struct mac_lomac_proc *subj; 499db2661ceSRobert Watson struct vattr va; 500db2661ceSRobert Watson struct proc *p; 501db2661ceSRobert Watson pid_t pgid; 502db2661ceSRobert Watson 503eca8a663SRobert Watson subj = PSLOT(curthread->td_proc->p_label); 504f51e5803SRobert Watson 505db2661ceSRobert Watson p = curthread->td_proc; 506db2661ceSRobert Watson mtx_lock(&subj->mtx); 507db2661ceSRobert Watson if (subj->mac_lomac.ml_flags & MAC_LOMAC_FLAG_UPDATE) { 508db2661ceSRobert Watson /* 5093f1a7a90SRobert Watson * Check to see if the pending demotion would be more or less 5103f1a7a90SRobert Watson * severe than this one, and keep the more severe. This can 5113f1a7a90SRobert Watson * only happen for a multi-threaded application. 512db2661ceSRobert Watson */ 5133f1a7a90SRobert Watson if (lomac_dominate_single(objlabel, &subj->mac_lomac)) { 514db2661ceSRobert Watson mtx_unlock(&subj->mtx); 515db2661ceSRobert Watson return (0); 516db2661ceSRobert Watson } 517db2661ceSRobert Watson } 518db2661ceSRobert Watson bzero(&subj->mac_lomac, sizeof(subj->mac_lomac)); 519db2661ceSRobert Watson /* 520db2661ceSRobert Watson * Always demote the single label. 521db2661ceSRobert Watson */ 5223f1a7a90SRobert Watson lomac_copy_single(objlabel, &subj->mac_lomac); 523db2661ceSRobert Watson /* 5243f1a7a90SRobert Watson * Start with the original range, then minimize each side of the 5253f1a7a90SRobert Watson * range to the point of not dominating the object. The high side 5263f1a7a90SRobert Watson * will always be demoted, of course. 527db2661ceSRobert Watson */ 5283f1a7a90SRobert Watson lomac_copy_range(subjlabel, &subj->mac_lomac); 5293f1a7a90SRobert Watson if (!lomac_dominate_element(&objlabel->ml_single, 530db2661ceSRobert Watson &subj->mac_lomac.ml_rangelow)) 531db2661ceSRobert Watson subj->mac_lomac.ml_rangelow = objlabel->ml_single; 532db2661ceSRobert Watson subj->mac_lomac.ml_rangehigh = objlabel->ml_single; 533db2661ceSRobert Watson subj->mac_lomac.ml_flags |= MAC_LOMAC_FLAG_UPDATE; 534982d11f8SJeff Roberson thread_lock(curthread); 535b61ce5b0SJeff Roberson curthread->td_flags |= TDF_ASTPENDING | TDF_MACPEND; 536982d11f8SJeff Roberson thread_unlock(curthread); 537f51e5803SRobert Watson 538f51e5803SRobert Watson /* 5393f1a7a90SRobert Watson * Avoid memory allocation while holding a mutex; cache the label. 540f51e5803SRobert Watson */ 5413f1a7a90SRobert Watson lomac_copy_single(&subj->mac_lomac, &cached_subjlabel); 542db2661ceSRobert Watson mtx_unlock(&subj->mtx); 543f51e5803SRobert Watson 544f51e5803SRobert Watson sbuf_new(&subjlabel_sb, NULL, 0, SBUF_AUTOEXTEND); 5453f1a7a90SRobert Watson lomac_to_string(&subjlabel_sb, subjlabel); 546f51e5803SRobert Watson sbuf_finish(&subjlabel_sb); 547f51e5803SRobert Watson subjlabeltext = sbuf_data(&subjlabel_sb); 548f51e5803SRobert Watson 549f51e5803SRobert Watson sbuf_new(&subjtext_sb, NULL, 0, SBUF_AUTOEXTEND); 5503f1a7a90SRobert Watson lomac_to_string(&subjtext_sb, &subj->mac_lomac); 551f51e5803SRobert Watson sbuf_finish(&subjtext_sb); 552f51e5803SRobert Watson subjtext = sbuf_data(&subjtext_sb); 553f51e5803SRobert Watson 554f51e5803SRobert Watson sbuf_new(&objlabel_sb, NULL, 0, SBUF_AUTOEXTEND); 5553f1a7a90SRobert Watson lomac_to_string(&objlabel_sb, objlabel); 556f51e5803SRobert Watson sbuf_finish(&objlabel_sb); 557f51e5803SRobert Watson objlabeltext = sbuf_data(&objlabel_sb); 558f51e5803SRobert Watson 559db2661ceSRobert Watson pgid = p->p_pgrp->pg_id; /* XXX could be stale? */ 5600359a12eSAttilio Rao if (vp != NULL && VOP_GETATTR(vp, &va, curthread->td_ucred) == 0) { 561db2661ceSRobert Watson log(LOG_INFO, "LOMAC: level-%s subject p%dg%du%d:%s demoted to" 562db2661ceSRobert Watson " level %s after %s a level-%s %s (inode=%ld, " 563db2661ceSRobert Watson "mountpount=%s)\n", 564db2661ceSRobert Watson subjlabeltext, p->p_pid, pgid, curthread->td_ucred->cr_uid, 565db2661ceSRobert Watson p->p_comm, subjtext, actionname, objlabeltext, objname, 56678007886SRobert Watson va.va_fileid, vp->v_mount->mnt_stat.f_mntonname); 567db2661ceSRobert Watson } else { 568db2661ceSRobert Watson log(LOG_INFO, "LOMAC: level-%s subject p%dg%du%d:%s demoted to" 569db2661ceSRobert Watson " level %s after %s a level-%s %s\n", 570db2661ceSRobert Watson subjlabeltext, p->p_pid, pgid, curthread->td_ucred->cr_uid, 571db2661ceSRobert Watson p->p_comm, subjtext, actionname, objlabeltext, objname); 572db2661ceSRobert Watson } 573db2661ceSRobert Watson 574f51e5803SRobert Watson sbuf_delete(&subjlabel_sb); 575f51e5803SRobert Watson sbuf_delete(&subjtext_sb); 576f51e5803SRobert Watson sbuf_delete(&objlabel_sb); 577f51e5803SRobert Watson 578db2661ceSRobert Watson return (0); 579db2661ceSRobert Watson } 580db2661ceSRobert Watson 581db2661ceSRobert Watson /* 5823f1a7a90SRobert Watson * Relabel "to" to "from" only if "from" is a valid label (contains at least 5833f1a7a90SRobert Watson * a single), as for a relabel operation which may or may not involve a 5843f1a7a90SRobert Watson * relevant label. 585db2661ceSRobert Watson */ 5867496ed81SRobert Watson static void 587db2661ceSRobert Watson try_relabel(struct mac_lomac *from, struct mac_lomac *to) 588db2661ceSRobert Watson { 589db2661ceSRobert Watson 590db2661ceSRobert Watson if (from->ml_flags & MAC_LOMAC_FLAG_SINGLE) { 591db2661ceSRobert Watson bzero(to, sizeof(*to)); 5923f1a7a90SRobert Watson lomac_copy(from, to); 593db2661ceSRobert Watson } 594db2661ceSRobert Watson } 595db2661ceSRobert Watson 596db2661ceSRobert Watson /* 597db2661ceSRobert Watson * Policy module operations. 598db2661ceSRobert Watson */ 599db2661ceSRobert Watson static void 6003f1a7a90SRobert Watson lomac_init(struct mac_policy_conf *conf) 601db2661ceSRobert Watson { 602db2661ceSRobert Watson 603db2661ceSRobert Watson } 604db2661ceSRobert Watson 605db2661ceSRobert Watson /* 606db2661ceSRobert Watson * Label operations. 607db2661ceSRobert Watson */ 608db2661ceSRobert Watson static void 6093f1a7a90SRobert Watson lomac_init_label(struct label *label) 610db2661ceSRobert Watson { 611db2661ceSRobert Watson 6121477f588SAlexander Kabaev SLOT_SET(label, lomac_alloc(M_WAITOK)); 613db2661ceSRobert Watson } 614db2661ceSRobert Watson 615db2661ceSRobert Watson static int 6163f1a7a90SRobert Watson lomac_init_label_waitcheck(struct label *label, int flag) 617db2661ceSRobert Watson { 618db2661ceSRobert Watson 6191477f588SAlexander Kabaev SLOT_SET(label, lomac_alloc(flag)); 620db2661ceSRobert Watson if (SLOT(label) == NULL) 621db2661ceSRobert Watson return (ENOMEM); 622db2661ceSRobert Watson 623db2661ceSRobert Watson return (0); 624db2661ceSRobert Watson } 625db2661ceSRobert Watson 626db2661ceSRobert Watson static void 6273f1a7a90SRobert Watson lomac_destroy_label(struct label *label) 628db2661ceSRobert Watson { 629db2661ceSRobert Watson 630db2661ceSRobert Watson lomac_free(SLOT(label)); 6311477f588SAlexander Kabaev SLOT_SET(label, NULL); 632db2661ceSRobert Watson } 633db2661ceSRobert Watson 634f51e5803SRobert Watson static int 6353f1a7a90SRobert Watson lomac_element_to_string(struct sbuf *sb, struct mac_lomac_element *element) 636db2661ceSRobert Watson { 637db2661ceSRobert Watson 638db2661ceSRobert Watson switch (element->mle_type) { 639db2661ceSRobert Watson case MAC_LOMAC_TYPE_HIGH: 640f51e5803SRobert Watson return (sbuf_printf(sb, "high")); 641db2661ceSRobert Watson 642db2661ceSRobert Watson case MAC_LOMAC_TYPE_LOW: 643f51e5803SRobert Watson return (sbuf_printf(sb, "low")); 644db2661ceSRobert Watson 645db2661ceSRobert Watson case MAC_LOMAC_TYPE_EQUAL: 646f51e5803SRobert Watson return (sbuf_printf(sb, "equal")); 647db2661ceSRobert Watson 648db2661ceSRobert Watson case MAC_LOMAC_TYPE_GRADE: 649f51e5803SRobert Watson return (sbuf_printf(sb, "%d", element->mle_grade)); 650db2661ceSRobert Watson 651db2661ceSRobert Watson default: 6523f1a7a90SRobert Watson panic("lomac_element_to_string: invalid type (%d)", 653db2661ceSRobert Watson element->mle_type); 654db2661ceSRobert Watson } 655db2661ceSRobert Watson } 656db2661ceSRobert Watson 657db2661ceSRobert Watson static int 6583f1a7a90SRobert Watson lomac_to_string(struct sbuf *sb, struct mac_lomac *ml) 659db2661ceSRobert Watson { 660db2661ceSRobert Watson 6613f1a7a90SRobert Watson if (ml->ml_flags & MAC_LOMAC_FLAG_SINGLE) { 6623f1a7a90SRobert Watson if (lomac_element_to_string(sb, &ml->ml_single) == -1) 663f51e5803SRobert Watson return (EINVAL); 664db2661ceSRobert Watson } 665db2661ceSRobert Watson 6663f1a7a90SRobert Watson if (ml->ml_flags & MAC_LOMAC_FLAG_AUX) { 667f51e5803SRobert Watson if (sbuf_putc(sb, '[') == -1) 668f51e5803SRobert Watson return (EINVAL); 669db2661ceSRobert Watson 6703f1a7a90SRobert Watson if (lomac_element_to_string(sb, &ml->ml_auxsingle) == -1) 671f51e5803SRobert Watson return (EINVAL); 672db2661ceSRobert Watson 673f51e5803SRobert Watson if (sbuf_putc(sb, ']') == -1) 674f51e5803SRobert Watson return (EINVAL); 675db2661ceSRobert Watson } 676db2661ceSRobert Watson 6773f1a7a90SRobert Watson if (ml->ml_flags & MAC_LOMAC_FLAG_RANGE) { 678f51e5803SRobert Watson if (sbuf_putc(sb, '(') == -1) 679f51e5803SRobert Watson return (EINVAL); 680db2661ceSRobert Watson 6813f1a7a90SRobert Watson if (lomac_element_to_string(sb, &ml->ml_rangelow) == -1) 682f51e5803SRobert Watson return (EINVAL); 683db2661ceSRobert Watson 684f51e5803SRobert Watson if (sbuf_putc(sb, '-') == -1) 685f51e5803SRobert Watson return (EINVAL); 686db2661ceSRobert Watson 6873f1a7a90SRobert Watson if (lomac_element_to_string(sb, &ml->ml_rangehigh) == -1) 688f51e5803SRobert Watson return (EINVAL); 689db2661ceSRobert Watson 6908a4b86b9SRobert Watson if (sbuf_putc(sb, ')') == -1) 691f51e5803SRobert Watson return (EINVAL); 692db2661ceSRobert Watson } 693db2661ceSRobert Watson 694db2661ceSRobert Watson return (0); 695db2661ceSRobert Watson } 696db2661ceSRobert Watson 697db2661ceSRobert Watson static int 6983f1a7a90SRobert Watson lomac_externalize_label(struct label *label, char *element_name, 699f51e5803SRobert Watson struct sbuf *sb, int *claimed) 700db2661ceSRobert Watson { 7013f1a7a90SRobert Watson struct mac_lomac *ml; 702db2661ceSRobert Watson 703db2661ceSRobert Watson if (strcmp(MAC_LOMAC_LABEL_NAME, element_name) != 0) 704db2661ceSRobert Watson return (0); 705db2661ceSRobert Watson 706db2661ceSRobert Watson (*claimed)++; 707db2661ceSRobert Watson 7083f1a7a90SRobert Watson ml = SLOT(label); 709db2661ceSRobert Watson 7103f1a7a90SRobert Watson return (lomac_to_string(sb, ml)); 711db2661ceSRobert Watson } 712db2661ceSRobert Watson 713db2661ceSRobert Watson static int 7143f1a7a90SRobert Watson lomac_parse_element(struct mac_lomac_element *element, char *string) 715db2661ceSRobert Watson { 716db2661ceSRobert Watson 7173f1a7a90SRobert Watson if (strcmp(string, "high") == 0 || strcmp(string, "hi") == 0) { 718db2661ceSRobert Watson element->mle_type = MAC_LOMAC_TYPE_HIGH; 719db2661ceSRobert Watson element->mle_grade = MAC_LOMAC_TYPE_UNDEF; 7203f1a7a90SRobert Watson } else if (strcmp(string, "low") == 0 || strcmp(string, "lo") == 0) { 721db2661ceSRobert Watson element->mle_type = MAC_LOMAC_TYPE_LOW; 722db2661ceSRobert Watson element->mle_grade = MAC_LOMAC_TYPE_UNDEF; 72395b85ca3SRobert Watson } else if (strcmp(string, "equal") == 0 || 72495b85ca3SRobert Watson strcmp(string, "eq") == 0) { 725db2661ceSRobert Watson element->mle_type = MAC_LOMAC_TYPE_EQUAL; 726db2661ceSRobert Watson element->mle_grade = MAC_LOMAC_TYPE_UNDEF; 727db2661ceSRobert Watson } else { 728db2661ceSRobert Watson char *p0, *p1; 729db2661ceSRobert Watson int d; 730db2661ceSRobert Watson 731db2661ceSRobert Watson p0 = string; 732db2661ceSRobert Watson d = strtol(p0, &p1, 10); 733db2661ceSRobert Watson 734db2661ceSRobert Watson if (d < 0 || d > 65535) 735db2661ceSRobert Watson return (EINVAL); 736db2661ceSRobert Watson element->mle_type = MAC_LOMAC_TYPE_GRADE; 737db2661ceSRobert Watson element->mle_grade = d; 738db2661ceSRobert Watson 739db2661ceSRobert Watson if (p1 == p0 || *p1 != '\0') 740db2661ceSRobert Watson return (EINVAL); 741db2661ceSRobert Watson } 742db2661ceSRobert Watson 743db2661ceSRobert Watson return (0); 744db2661ceSRobert Watson } 745db2661ceSRobert Watson 746db2661ceSRobert Watson /* 7473f1a7a90SRobert Watson * Note: destructively consumes the string, make a local copy before calling 7483f1a7a90SRobert Watson * if that's a problem. 749db2661ceSRobert Watson */ 750db2661ceSRobert Watson static int 7513f1a7a90SRobert Watson lomac_parse(struct mac_lomac *ml, char *string) 752db2661ceSRobert Watson { 753db2661ceSRobert Watson char *range, *rangeend, *rangehigh, *rangelow, *single, *auxsingle, 754db2661ceSRobert Watson *auxsingleend; 755db2661ceSRobert Watson int error; 756db2661ceSRobert Watson 757db2661ceSRobert Watson /* Do we have a range? */ 758db2661ceSRobert Watson single = string; 759dc15eac0SEd Schouten range = strchr(string, '('); 760db2661ceSRobert Watson if (range == single) 761db2661ceSRobert Watson single = NULL; 762dc15eac0SEd Schouten auxsingle = strchr(string, '['); 763db2661ceSRobert Watson if (auxsingle == single) 764db2661ceSRobert Watson single = NULL; 765db2661ceSRobert Watson if (range != NULL && auxsingle != NULL) 766db2661ceSRobert Watson return (EINVAL); 767db2661ceSRobert Watson rangelow = rangehigh = NULL; 768db2661ceSRobert Watson if (range != NULL) { 769db2661ceSRobert Watson /* Nul terminate the end of the single string. */ 770db2661ceSRobert Watson *range = '\0'; 771db2661ceSRobert Watson range++; 772db2661ceSRobert Watson rangelow = range; 773dc15eac0SEd Schouten rangehigh = strchr(rangelow, '-'); 774db2661ceSRobert Watson if (rangehigh == NULL) 775db2661ceSRobert Watson return (EINVAL); 776db2661ceSRobert Watson rangehigh++; 777db2661ceSRobert Watson if (*rangelow == '\0' || *rangehigh == '\0') 778db2661ceSRobert Watson return (EINVAL); 779dc15eac0SEd Schouten rangeend = strchr(rangehigh, ')'); 780db2661ceSRobert Watson if (rangeend == NULL) 781db2661ceSRobert Watson return (EINVAL); 782db2661ceSRobert Watson if (*(rangeend + 1) != '\0') 783db2661ceSRobert Watson return (EINVAL); 784db2661ceSRobert Watson /* Nul terminate the ends of the ranges. */ 785db2661ceSRobert Watson *(rangehigh - 1) = '\0'; 786db2661ceSRobert Watson *rangeend = '\0'; 787db2661ceSRobert Watson } 788db2661ceSRobert Watson KASSERT((rangelow != NULL && rangehigh != NULL) || 789db2661ceSRobert Watson (rangelow == NULL && rangehigh == NULL), 7903f1a7a90SRobert Watson ("lomac_internalize_label: range mismatch")); 791db2661ceSRobert Watson if (auxsingle != NULL) { 792db2661ceSRobert Watson /* Nul terminate the end of the single string. */ 793db2661ceSRobert Watson *auxsingle = '\0'; 794db2661ceSRobert Watson auxsingle++; 795dc15eac0SEd Schouten auxsingleend = strchr(auxsingle, ']'); 796db2661ceSRobert Watson if (auxsingleend == NULL) 797db2661ceSRobert Watson return (EINVAL); 798db2661ceSRobert Watson if (*(auxsingleend + 1) != '\0') 799db2661ceSRobert Watson return (EINVAL); 800db2661ceSRobert Watson /* Nul terminate the end of the auxsingle. */ 801db2661ceSRobert Watson *auxsingleend = '\0'; 802db2661ceSRobert Watson } 803db2661ceSRobert Watson 8043f1a7a90SRobert Watson bzero(ml, sizeof(*ml)); 805db2661ceSRobert Watson if (single != NULL) { 8063f1a7a90SRobert Watson error = lomac_parse_element(&ml->ml_single, single); 807db2661ceSRobert Watson if (error) 808db2661ceSRobert Watson return (error); 8093f1a7a90SRobert Watson ml->ml_flags |= MAC_LOMAC_FLAG_SINGLE; 810db2661ceSRobert Watson } 811db2661ceSRobert Watson 812db2661ceSRobert Watson if (auxsingle != NULL) { 81395b85ca3SRobert Watson error = lomac_parse_element(&ml->ml_auxsingle, auxsingle); 814db2661ceSRobert Watson if (error) 815db2661ceSRobert Watson return (error); 8163f1a7a90SRobert Watson ml->ml_flags |= MAC_LOMAC_FLAG_AUX; 817db2661ceSRobert Watson } 818db2661ceSRobert Watson 819db2661ceSRobert Watson if (rangelow != NULL) { 8203f1a7a90SRobert Watson error = lomac_parse_element(&ml->ml_rangelow, rangelow); 821db2661ceSRobert Watson if (error) 822db2661ceSRobert Watson return (error); 8233f1a7a90SRobert Watson error = lomac_parse_element(&ml->ml_rangehigh, rangehigh); 824db2661ceSRobert Watson if (error) 825db2661ceSRobert Watson return (error); 8263f1a7a90SRobert Watson ml->ml_flags |= MAC_LOMAC_FLAG_RANGE; 827db2661ceSRobert Watson } 828db2661ceSRobert Watson 8293f1a7a90SRobert Watson error = lomac_valid(ml); 830db2661ceSRobert Watson if (error) 831db2661ceSRobert Watson return (error); 832db2661ceSRobert Watson 833db2661ceSRobert Watson return (0); 834db2661ceSRobert Watson } 835db2661ceSRobert Watson 836db2661ceSRobert Watson static int 8373f1a7a90SRobert Watson lomac_internalize_label(struct label *label, char *element_name, 838db2661ceSRobert Watson char *element_data, int *claimed) 839db2661ceSRobert Watson { 8403f1a7a90SRobert Watson struct mac_lomac *ml, ml_temp; 841db2661ceSRobert Watson int error; 842db2661ceSRobert Watson 843db2661ceSRobert Watson if (strcmp(MAC_LOMAC_LABEL_NAME, element_name) != 0) 844db2661ceSRobert Watson return (0); 845db2661ceSRobert Watson 846db2661ceSRobert Watson (*claimed)++; 847db2661ceSRobert Watson 8483f1a7a90SRobert Watson error = lomac_parse(&ml_temp, element_data); 849db2661ceSRobert Watson if (error) 850db2661ceSRobert Watson return (error); 851db2661ceSRobert Watson 8523f1a7a90SRobert Watson ml = SLOT(label); 8533f1a7a90SRobert Watson *ml = ml_temp; 854db2661ceSRobert Watson 855db2661ceSRobert Watson return (0); 856db2661ceSRobert Watson } 857db2661ceSRobert Watson 858db2661ceSRobert Watson static void 8593f1a7a90SRobert Watson lomac_copy_label(struct label *src, struct label *dest) 860db2661ceSRobert Watson { 861db2661ceSRobert Watson 862db2661ceSRobert Watson *SLOT(dest) = *SLOT(src); 863db2661ceSRobert Watson } 864db2661ceSRobert Watson 865db2661ceSRobert Watson /* 866eb320b0eSRobert Watson * Object-specific entry point implementations are sorted alphabetically by 867eb320b0eSRobert Watson * object type name and then by operation. 868db2661ceSRobert Watson */ 869db2661ceSRobert Watson static int 8703f1a7a90SRobert Watson lomac_bpfdesc_check_receive(struct bpf_d *d, struct label *dlabel, 87178007886SRobert Watson struct ifnet *ifp, struct label *ifplabel) 872db2661ceSRobert Watson { 873db2661ceSRobert Watson struct mac_lomac *a, *b; 874db2661ceSRobert Watson 8753f1a7a90SRobert Watson if (!lomac_enabled) 876db2661ceSRobert Watson return (0); 877db2661ceSRobert Watson 87878007886SRobert Watson a = SLOT(dlabel); 87978007886SRobert Watson b = SLOT(ifplabel); 880db2661ceSRobert Watson 8813f1a7a90SRobert Watson if (lomac_equal_single(a, b)) 882db2661ceSRobert Watson return (0); 883db2661ceSRobert Watson return (EACCES); 884db2661ceSRobert Watson } 885db2661ceSRobert Watson 886eb320b0eSRobert Watson static void 887eb320b0eSRobert Watson lomac_bpfdesc_create(struct ucred *cred, struct bpf_d *d, 888eb320b0eSRobert Watson struct label *dlabel) 889eb320b0eSRobert Watson { 890eb320b0eSRobert Watson struct mac_lomac *source, *dest; 891eb320b0eSRobert Watson 892eb320b0eSRobert Watson source = SLOT(cred->cr_label); 893eb320b0eSRobert Watson dest = SLOT(dlabel); 894eb320b0eSRobert Watson 895eb320b0eSRobert Watson lomac_copy_single(source, dest); 896eb320b0eSRobert Watson } 897eb320b0eSRobert Watson 898eb320b0eSRobert Watson static void 899eb320b0eSRobert Watson lomac_bpfdesc_create_mbuf(struct bpf_d *d, struct label *dlabel, 900eb320b0eSRobert Watson struct mbuf *m, struct label *mlabel) 901eb320b0eSRobert Watson { 902eb320b0eSRobert Watson struct mac_lomac *source, *dest; 903eb320b0eSRobert Watson 904eb320b0eSRobert Watson source = SLOT(dlabel); 905eb320b0eSRobert Watson dest = SLOT(mlabel); 906eb320b0eSRobert Watson 907eb320b0eSRobert Watson lomac_copy_single(source, dest); 908eb320b0eSRobert Watson } 909eb320b0eSRobert Watson 910db2661ceSRobert Watson static int 9113f1a7a90SRobert Watson lomac_cred_check_relabel(struct ucred *cred, struct label *newlabel) 912db2661ceSRobert Watson { 913db2661ceSRobert Watson struct mac_lomac *subj, *new; 914db2661ceSRobert Watson int error; 915db2661ceSRobert Watson 916eca8a663SRobert Watson subj = SLOT(cred->cr_label); 917db2661ceSRobert Watson new = SLOT(newlabel); 918db2661ceSRobert Watson 919db2661ceSRobert Watson /* 9203f1a7a90SRobert Watson * If there is a LOMAC label update for the credential, it may be an 9213f1a7a90SRobert Watson * update of the single, range, or both. 922db2661ceSRobert Watson */ 923db2661ceSRobert Watson error = lomac_atmostflags(new, MAC_LOMAC_FLAGS_BOTH); 924db2661ceSRobert Watson if (error) 925db2661ceSRobert Watson return (error); 926db2661ceSRobert Watson 927db2661ceSRobert Watson /* 928db2661ceSRobert Watson * If the LOMAC label is to be changed, authorize as appropriate. 929db2661ceSRobert Watson */ 930db2661ceSRobert Watson if (new->ml_flags & MAC_LOMAC_FLAGS_BOTH) { 931db2661ceSRobert Watson /* 93284bdb083SRobert Watson * Fill in the missing parts from the previous label. 933db2661ceSRobert Watson */ 93484bdb083SRobert Watson if ((new->ml_flags & MAC_LOMAC_FLAG_SINGLE) == 0) 9353f1a7a90SRobert Watson lomac_copy_single(subj, new); 93684bdb083SRobert Watson if ((new->ml_flags & MAC_LOMAC_FLAG_RANGE) == 0) 9373f1a7a90SRobert Watson lomac_copy_range(subj, new); 938db2661ceSRobert Watson 939db2661ceSRobert Watson /* 9403f1a7a90SRobert Watson * To change the LOMAC range on a credential, the new range 9413f1a7a90SRobert Watson * label must be in the current range. 942db2661ceSRobert Watson */ 9433f1a7a90SRobert Watson if (!lomac_range_in_range(new, subj)) 94484bdb083SRobert Watson return (EPERM); 94584bdb083SRobert Watson 94684bdb083SRobert Watson /* 9473f1a7a90SRobert Watson * To change the LOMAC single label on a credential, the new 9483f1a7a90SRobert Watson * single label must be in the new range. Implicitly from 9493f1a7a90SRobert Watson * the previous check, the new single is in the old range. 95084bdb083SRobert Watson */ 9513f1a7a90SRobert Watson if (!lomac_single_in_range(new, new)) 952db2661ceSRobert Watson return (EPERM); 953db2661ceSRobert Watson 954db2661ceSRobert Watson /* 9553f1a7a90SRobert Watson * To have EQUAL in any component of the new credential LOMAC 9563f1a7a90SRobert Watson * label, the subject must already have EQUAL in their label. 957db2661ceSRobert Watson */ 9583f1a7a90SRobert Watson if (lomac_contains_equal(new)) { 9593f1a7a90SRobert Watson error = lomac_subject_privileged(subj); 960db2661ceSRobert Watson if (error) 961db2661ceSRobert Watson return (error); 962db2661ceSRobert Watson } 963db2661ceSRobert Watson 964db2661ceSRobert Watson /* 9653f1a7a90SRobert Watson * XXXMAC: Additional consistency tests regarding the single 9663f1a7a90SRobert Watson * and range of the new label might be performed here. 967db2661ceSRobert Watson */ 968db2661ceSRobert Watson } 969db2661ceSRobert Watson 970db2661ceSRobert Watson return (0); 971db2661ceSRobert Watson } 972db2661ceSRobert Watson 973db2661ceSRobert Watson static int 9743f1a7a90SRobert Watson lomac_cred_check_visible(struct ucred *cr1, struct ucred *cr2) 975db2661ceSRobert Watson { 976db2661ceSRobert Watson struct mac_lomac *subj, *obj; 977db2661ceSRobert Watson 9783f1a7a90SRobert Watson if (!lomac_enabled) 979db2661ceSRobert Watson return (0); 980db2661ceSRobert Watson 98178007886SRobert Watson subj = SLOT(cr1->cr_label); 98278007886SRobert Watson obj = SLOT(cr2->cr_label); 983db2661ceSRobert Watson 984db2661ceSRobert Watson /* XXX: range */ 9853f1a7a90SRobert Watson if (!lomac_dominate_single(obj, subj)) 986db2661ceSRobert Watson return (ESRCH); 987db2661ceSRobert Watson 988db2661ceSRobert Watson return (0); 989db2661ceSRobert Watson } 990212ab0cfSRobert Watson 991212ab0cfSRobert Watson static void 992212ab0cfSRobert Watson lomac_cred_create_init(struct ucred *cred) 993212ab0cfSRobert Watson { 994212ab0cfSRobert Watson struct mac_lomac *dest; 995212ab0cfSRobert Watson 996212ab0cfSRobert Watson dest = SLOT(cred->cr_label); 997212ab0cfSRobert Watson 998212ab0cfSRobert Watson lomac_set_single(dest, MAC_LOMAC_TYPE_HIGH, 0); 999212ab0cfSRobert Watson lomac_set_range(dest, MAC_LOMAC_TYPE_LOW, 0, MAC_LOMAC_TYPE_HIGH, 0); 1000212ab0cfSRobert Watson } 1001212ab0cfSRobert Watson 1002212ab0cfSRobert Watson static void 1003212ab0cfSRobert Watson lomac_cred_create_swapper(struct ucred *cred) 1004212ab0cfSRobert Watson { 1005212ab0cfSRobert Watson struct mac_lomac *dest; 1006212ab0cfSRobert Watson 1007212ab0cfSRobert Watson dest = SLOT(cred->cr_label); 1008212ab0cfSRobert Watson 1009212ab0cfSRobert Watson lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0); 1010212ab0cfSRobert Watson lomac_set_range(dest, MAC_LOMAC_TYPE_LOW, 0, MAC_LOMAC_TYPE_HIGH, 0); 1011212ab0cfSRobert Watson } 1012212ab0cfSRobert Watson 1013eb320b0eSRobert Watson static void 1014eb320b0eSRobert Watson lomac_cred_relabel(struct ucred *cred, struct label *newlabel) 1015eb320b0eSRobert Watson { 1016eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1017eb320b0eSRobert Watson 1018eb320b0eSRobert Watson source = SLOT(newlabel); 1019eb320b0eSRobert Watson dest = SLOT(cred->cr_label); 1020eb320b0eSRobert Watson 1021eb320b0eSRobert Watson try_relabel(source, dest); 1022eb320b0eSRobert Watson } 1023eb320b0eSRobert Watson 1024eb320b0eSRobert Watson static void 1025eb320b0eSRobert Watson lomac_devfs_create_device(struct ucred *cred, struct mount *mp, 1026eb320b0eSRobert Watson struct cdev *dev, struct devfs_dirent *de, struct label *delabel) 1027eb320b0eSRobert Watson { 1028eb320b0eSRobert Watson struct mac_lomac *ml; 10297870adb6SEd Schouten const char *dn; 1030eb320b0eSRobert Watson int lomac_type; 1031eb320b0eSRobert Watson 1032eb320b0eSRobert Watson ml = SLOT(delabel); 10337870adb6SEd Schouten dn = devtoname(dev); 10347870adb6SEd Schouten if (strcmp(dn, "null") == 0 || 10357870adb6SEd Schouten strcmp(dn, "zero") == 0 || 10367870adb6SEd Schouten strcmp(dn, "random") == 0 || 10377870adb6SEd Schouten strncmp(dn, "fd/", strlen("fd/")) == 0 || 10387870adb6SEd Schouten strncmp(dn, "ttyv", strlen("ttyv")) == 0) 1039eb320b0eSRobert Watson lomac_type = MAC_LOMAC_TYPE_EQUAL; 1040eb320b0eSRobert Watson else if (ptys_equal && 10417870adb6SEd Schouten (strncmp(dn, "ttyp", strlen("ttyp")) == 0 || 10427870adb6SEd Schouten strncmp(dn, "pts/", strlen("pts/")) == 0 || 10437870adb6SEd Schouten strncmp(dn, "ptyp", strlen("ptyp")) == 0)) 1044eb320b0eSRobert Watson lomac_type = MAC_LOMAC_TYPE_EQUAL; 1045eb320b0eSRobert Watson else 1046eb320b0eSRobert Watson lomac_type = MAC_LOMAC_TYPE_HIGH; 1047eb320b0eSRobert Watson lomac_set_single(ml, lomac_type, 0); 1048eb320b0eSRobert Watson } 1049eb320b0eSRobert Watson 1050eb320b0eSRobert Watson static void 1051eb320b0eSRobert Watson lomac_devfs_create_directory(struct mount *mp, char *dirname, int dirnamelen, 1052eb320b0eSRobert Watson struct devfs_dirent *de, struct label *delabel) 1053eb320b0eSRobert Watson { 1054eb320b0eSRobert Watson struct mac_lomac *ml; 1055eb320b0eSRobert Watson 1056eb320b0eSRobert Watson ml = SLOT(delabel); 1057eb320b0eSRobert Watson lomac_set_single(ml, MAC_LOMAC_TYPE_HIGH, 0); 1058eb320b0eSRobert Watson } 1059eb320b0eSRobert Watson 1060eb320b0eSRobert Watson static void 1061eb320b0eSRobert Watson lomac_devfs_create_symlink(struct ucred *cred, struct mount *mp, 1062eb320b0eSRobert Watson struct devfs_dirent *dd, struct label *ddlabel, struct devfs_dirent *de, 1063eb320b0eSRobert Watson struct label *delabel) 1064eb320b0eSRobert Watson { 1065eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1066eb320b0eSRobert Watson 1067eb320b0eSRobert Watson source = SLOT(cred->cr_label); 1068eb320b0eSRobert Watson dest = SLOT(delabel); 1069eb320b0eSRobert Watson 1070eb320b0eSRobert Watson lomac_copy_single(source, dest); 1071eb320b0eSRobert Watson } 1072eb320b0eSRobert Watson 1073eb320b0eSRobert Watson static void 1074eb320b0eSRobert Watson lomac_devfs_update(struct mount *mp, struct devfs_dirent *de, 1075eb320b0eSRobert Watson struct label *delabel, struct vnode *vp, struct label *vplabel) 1076eb320b0eSRobert Watson { 1077eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1078eb320b0eSRobert Watson 1079eb320b0eSRobert Watson source = SLOT(vplabel); 1080eb320b0eSRobert Watson dest = SLOT(delabel); 1081eb320b0eSRobert Watson 1082eb320b0eSRobert Watson lomac_copy(source, dest); 1083eb320b0eSRobert Watson } 1084eb320b0eSRobert Watson 1085eb320b0eSRobert Watson static void 1086eb320b0eSRobert Watson lomac_devfs_vnode_associate(struct mount *mp, struct label *mplabel, 1087eb320b0eSRobert Watson struct devfs_dirent *de, struct label *delabel, struct vnode *vp, 1088eb320b0eSRobert Watson struct label *vplabel) 1089eb320b0eSRobert Watson { 1090eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1091eb320b0eSRobert Watson 1092eb320b0eSRobert Watson source = SLOT(delabel); 1093eb320b0eSRobert Watson dest = SLOT(vplabel); 1094eb320b0eSRobert Watson 1095eb320b0eSRobert Watson lomac_copy_single(source, dest); 1096eb320b0eSRobert Watson } 1097db2661ceSRobert Watson 1098db2661ceSRobert Watson static int 10993f1a7a90SRobert Watson lomac_ifnet_check_relabel(struct ucred *cred, struct ifnet *ifp, 110078007886SRobert Watson struct label *ifplabel, struct label *newlabel) 1101db2661ceSRobert Watson { 1102db2661ceSRobert Watson struct mac_lomac *subj, *new; 1103db2661ceSRobert Watson int error; 1104db2661ceSRobert Watson 1105eca8a663SRobert Watson subj = SLOT(cred->cr_label); 1106db2661ceSRobert Watson new = SLOT(newlabel); 1107db2661ceSRobert Watson 1108db2661ceSRobert Watson /* 11093f1a7a90SRobert Watson * If there is a LOMAC label update for the interface, it may be an 11103f1a7a90SRobert Watson * update of the single, range, or both. 1111db2661ceSRobert Watson */ 1112db2661ceSRobert Watson error = lomac_atmostflags(new, MAC_LOMAC_FLAGS_BOTH); 1113db2661ceSRobert Watson if (error) 1114db2661ceSRobert Watson return (error); 1115db2661ceSRobert Watson 1116db2661ceSRobert Watson /* 1117db2661ceSRobert Watson * Relabling network interfaces requires LOMAC privilege. 1118db2661ceSRobert Watson */ 11193f1a7a90SRobert Watson error = lomac_subject_privileged(subj); 1120db2661ceSRobert Watson if (error) 1121db2661ceSRobert Watson return (error); 1122db2661ceSRobert Watson 1123db2661ceSRobert Watson /* 1124db2661ceSRobert Watson * If the LOMAC label is to be changed, authorize as appropriate. 1125db2661ceSRobert Watson */ 1126db2661ceSRobert Watson if (new->ml_flags & MAC_LOMAC_FLAGS_BOTH) { 1127db2661ceSRobert Watson /* 112884bdb083SRobert Watson * Fill in the missing parts from the previous label. 112984bdb083SRobert Watson */ 113084bdb083SRobert Watson if ((new->ml_flags & MAC_LOMAC_FLAG_SINGLE) == 0) 11313f1a7a90SRobert Watson lomac_copy_single(subj, new); 113284bdb083SRobert Watson if ((new->ml_flags & MAC_LOMAC_FLAG_RANGE) == 0) 11333f1a7a90SRobert Watson lomac_copy_range(subj, new); 113484bdb083SRobert Watson 113584bdb083SRobert Watson /* 1136db2661ceSRobert Watson * Rely on the traditional superuser status for the LOMAC 1137db2661ceSRobert Watson * interface relabel requirements. XXXMAC: This will go 1138db2661ceSRobert Watson * away. 1139acd3428bSRobert Watson * 1140acd3428bSRobert Watson * XXXRW: This is also redundant to a higher layer check. 1141db2661ceSRobert Watson */ 1142acd3428bSRobert Watson error = priv_check_cred(cred, PRIV_NET_SETIFMAC, 0); 1143db2661ceSRobert Watson if (error) 1144db2661ceSRobert Watson return (EPERM); 1145db2661ceSRobert Watson 1146db2661ceSRobert Watson /* 1147db2661ceSRobert Watson * XXXMAC: Additional consistency tests regarding the single 1148db2661ceSRobert Watson * and the range of the new label might be performed here. 1149db2661ceSRobert Watson */ 1150db2661ceSRobert Watson } 1151db2661ceSRobert Watson 1152db2661ceSRobert Watson return (0); 1153db2661ceSRobert Watson } 1154db2661ceSRobert Watson 1155db2661ceSRobert Watson static int 11563f1a7a90SRobert Watson lomac_ifnet_check_transmit(struct ifnet *ifp, struct label *ifplabel, 115778007886SRobert Watson struct mbuf *m, struct label *mlabel) 1158db2661ceSRobert Watson { 1159db2661ceSRobert Watson struct mac_lomac *p, *i; 1160db2661ceSRobert Watson 11613f1a7a90SRobert Watson if (!lomac_enabled) 1162db2661ceSRobert Watson return (0); 1163db2661ceSRobert Watson 116478007886SRobert Watson p = SLOT(mlabel); 116578007886SRobert Watson i = SLOT(ifplabel); 1166db2661ceSRobert Watson 11673f1a7a90SRobert Watson return (lomac_single_in_range(p, i) ? 0 : EACCES); 1168db2661ceSRobert Watson } 1169db2661ceSRobert Watson 1170eb320b0eSRobert Watson static void 1171eb320b0eSRobert Watson lomac_ifnet_create(struct ifnet *ifp, struct label *ifplabel) 1172eb320b0eSRobert Watson { 1173eb320b0eSRobert Watson char tifname[IFNAMSIZ], *p, *q; 1174eb320b0eSRobert Watson char tiflist[sizeof(trusted_interfaces)]; 1175eb320b0eSRobert Watson struct mac_lomac *dest; 1176eb320b0eSRobert Watson int len, grade; 1177eb320b0eSRobert Watson 1178eb320b0eSRobert Watson dest = SLOT(ifplabel); 1179eb320b0eSRobert Watson 1180eb320b0eSRobert Watson if (ifp->if_type == IFT_LOOP) { 1181eb320b0eSRobert Watson grade = MAC_LOMAC_TYPE_EQUAL; 1182eb320b0eSRobert Watson goto set; 1183eb320b0eSRobert Watson } 1184eb320b0eSRobert Watson 1185eb320b0eSRobert Watson if (trust_all_interfaces) { 1186eb320b0eSRobert Watson grade = MAC_LOMAC_TYPE_HIGH; 1187eb320b0eSRobert Watson goto set; 1188eb320b0eSRobert Watson } 1189eb320b0eSRobert Watson 1190eb320b0eSRobert Watson grade = MAC_LOMAC_TYPE_LOW; 1191eb320b0eSRobert Watson 1192eb320b0eSRobert Watson if (trusted_interfaces[0] == '\0' || 1193eb320b0eSRobert Watson !strvalid(trusted_interfaces, sizeof(trusted_interfaces))) 1194eb320b0eSRobert Watson goto set; 1195eb320b0eSRobert Watson 1196eb320b0eSRobert Watson bzero(tiflist, sizeof(tiflist)); 1197eb320b0eSRobert Watson for (p = trusted_interfaces, q = tiflist; *p != '\0'; p++, q++) 1198eb320b0eSRobert Watson if(*p != ' ' && *p != '\t') 1199eb320b0eSRobert Watson *q = *p; 1200eb320b0eSRobert Watson 1201eb320b0eSRobert Watson for (p = q = tiflist;; p++) { 1202eb320b0eSRobert Watson if (*p == ',' || *p == '\0') { 1203eb320b0eSRobert Watson len = p - q; 1204eb320b0eSRobert Watson if (len < IFNAMSIZ) { 1205eb320b0eSRobert Watson bzero(tifname, sizeof(tifname)); 1206eb320b0eSRobert Watson bcopy(q, tifname, len); 1207eb320b0eSRobert Watson if (strcmp(tifname, ifp->if_xname) == 0) { 1208eb320b0eSRobert Watson grade = MAC_LOMAC_TYPE_HIGH; 1209eb320b0eSRobert Watson break; 1210eb320b0eSRobert Watson } 1211eb320b0eSRobert Watson } 1212eb320b0eSRobert Watson else { 1213eb320b0eSRobert Watson *p = '\0'; 1214eb320b0eSRobert Watson printf("MAC/LOMAC warning: interface name " 1215eb320b0eSRobert Watson "\"%s\" is too long (must be < %d)\n", 1216eb320b0eSRobert Watson q, IFNAMSIZ); 1217eb320b0eSRobert Watson } 1218eb320b0eSRobert Watson if (*p == '\0') 1219eb320b0eSRobert Watson break; 1220eb320b0eSRobert Watson q = p + 1; 1221eb320b0eSRobert Watson } 1222eb320b0eSRobert Watson } 1223eb320b0eSRobert Watson set: 1224eb320b0eSRobert Watson lomac_set_single(dest, grade, 0); 1225eb320b0eSRobert Watson lomac_set_range(dest, grade, 0, grade, 0); 1226eb320b0eSRobert Watson } 1227eb320b0eSRobert Watson 1228eb320b0eSRobert Watson static void 1229eb320b0eSRobert Watson lomac_ifnet_create_mbuf(struct ifnet *ifp, struct label *ifplabel, 1230eb320b0eSRobert Watson struct mbuf *m, struct label *mlabel) 1231eb320b0eSRobert Watson { 1232eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1233eb320b0eSRobert Watson 1234eb320b0eSRobert Watson source = SLOT(ifplabel); 1235eb320b0eSRobert Watson dest = SLOT(mlabel); 1236eb320b0eSRobert Watson 1237eb320b0eSRobert Watson lomac_copy_single(source, dest); 1238eb320b0eSRobert Watson } 1239eb320b0eSRobert Watson 1240eb320b0eSRobert Watson static void 1241eb320b0eSRobert Watson lomac_ifnet_relabel(struct ucred *cred, struct ifnet *ifp, 1242eb320b0eSRobert Watson struct label *ifplabel, struct label *newlabel) 1243eb320b0eSRobert Watson { 1244eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1245eb320b0eSRobert Watson 1246eb320b0eSRobert Watson source = SLOT(newlabel); 1247eb320b0eSRobert Watson dest = SLOT(ifplabel); 1248eb320b0eSRobert Watson 1249eb320b0eSRobert Watson try_relabel(source, dest); 1250eb320b0eSRobert Watson } 1251eb320b0eSRobert Watson 1252db2661ceSRobert Watson static int 12533f1a7a90SRobert Watson lomac_inpcb_check_deliver(struct inpcb *inp, struct label *inplabel, 1254a557af22SRobert Watson struct mbuf *m, struct label *mlabel) 1255a557af22SRobert Watson { 1256a557af22SRobert Watson struct mac_lomac *p, *i; 1257a557af22SRobert Watson 12583f1a7a90SRobert Watson if (!lomac_enabled) 1259a557af22SRobert Watson return (0); 1260a557af22SRobert Watson 1261a557af22SRobert Watson p = SLOT(mlabel); 1262a557af22SRobert Watson i = SLOT(inplabel); 1263a557af22SRobert Watson 12643f1a7a90SRobert Watson return (lomac_equal_single(p, i) ? 0 : EACCES); 1265a557af22SRobert Watson } 1266a557af22SRobert Watson 12677fb179baSBjoern A. Zeeb static int 12687fb179baSBjoern A. Zeeb lomac_inpcb_check_visible(struct ucred *cred, struct inpcb *inp, 12697fb179baSBjoern A. Zeeb struct label *inplabel) 12707fb179baSBjoern A. Zeeb { 12717fb179baSBjoern A. Zeeb struct mac_lomac *subj, *obj; 12727fb179baSBjoern A. Zeeb 12737fb179baSBjoern A. Zeeb if (!lomac_enabled) 12747fb179baSBjoern A. Zeeb return (0); 12757fb179baSBjoern A. Zeeb 12767fb179baSBjoern A. Zeeb subj = SLOT(cred->cr_label); 12777fb179baSBjoern A. Zeeb obj = SLOT(inplabel); 12787fb179baSBjoern A. Zeeb 12797fb179baSBjoern A. Zeeb if (!lomac_dominate_single(obj, subj)) 12807fb179baSBjoern A. Zeeb return (ENOENT); 12817fb179baSBjoern A. Zeeb 12827fb179baSBjoern A. Zeeb return (0); 12837fb179baSBjoern A. Zeeb } 12847fb179baSBjoern A. Zeeb 1285eb320b0eSRobert Watson static void 1286eb320b0eSRobert Watson lomac_inpcb_create(struct socket *so, struct label *solabel, 1287eb320b0eSRobert Watson struct inpcb *inp, struct label *inplabel) 1288eb320b0eSRobert Watson { 1289eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1290eb320b0eSRobert Watson 1291eb320b0eSRobert Watson source = SLOT(solabel); 1292eb320b0eSRobert Watson dest = SLOT(inplabel); 1293eb320b0eSRobert Watson 1294eb320b0eSRobert Watson lomac_copy_single(source, dest); 1295eb320b0eSRobert Watson } 1296eb320b0eSRobert Watson 1297eb320b0eSRobert Watson static void 1298eb320b0eSRobert Watson lomac_inpcb_create_mbuf(struct inpcb *inp, struct label *inplabel, 1299eb320b0eSRobert Watson struct mbuf *m, struct label *mlabel) 1300eb320b0eSRobert Watson { 1301eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1302eb320b0eSRobert Watson 1303eb320b0eSRobert Watson source = SLOT(inplabel); 1304eb320b0eSRobert Watson dest = SLOT(mlabel); 1305eb320b0eSRobert Watson 1306eb320b0eSRobert Watson lomac_copy_single(source, dest); 1307eb320b0eSRobert Watson } 1308eb320b0eSRobert Watson 1309eb320b0eSRobert Watson static void 1310eb320b0eSRobert Watson lomac_inpcb_sosetlabel(struct socket *so, struct label *solabel, 1311eb320b0eSRobert Watson struct inpcb *inp, struct label *inplabel) 1312eb320b0eSRobert Watson { 1313eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1314eb320b0eSRobert Watson 13153de40469SRobert Watson SOCK_LOCK_ASSERT(so); 13163de40469SRobert Watson 1317eb320b0eSRobert Watson source = SLOT(solabel); 1318eb320b0eSRobert Watson dest = SLOT(inplabel); 1319eb320b0eSRobert Watson 1320eb320b0eSRobert Watson lomac_copy_single(source, dest); 1321eb320b0eSRobert Watson } 1322eb320b0eSRobert Watson 1323eb320b0eSRobert Watson static void 1324048e1287SRobert Watson lomac_ip6q_create(struct mbuf *m, struct label *mlabel, struct ip6q *q6, 1325048e1287SRobert Watson struct label *q6label) 1326048e1287SRobert Watson { 1327048e1287SRobert Watson struct mac_lomac *source, *dest; 1328048e1287SRobert Watson 1329048e1287SRobert Watson source = SLOT(mlabel); 1330048e1287SRobert Watson dest = SLOT(q6label); 1331048e1287SRobert Watson 1332048e1287SRobert Watson lomac_copy_single(source, dest); 1333048e1287SRobert Watson } 1334048e1287SRobert Watson 1335048e1287SRobert Watson static int 1336048e1287SRobert Watson lomac_ip6q_match(struct mbuf *m, struct label *mlabel, struct ip6q *q6, 1337048e1287SRobert Watson struct label *q6label) 1338048e1287SRobert Watson { 1339048e1287SRobert Watson struct mac_lomac *a, *b; 1340048e1287SRobert Watson 1341048e1287SRobert Watson a = SLOT(q6label); 1342048e1287SRobert Watson b = SLOT(mlabel); 1343048e1287SRobert Watson 1344048e1287SRobert Watson return (lomac_equal_single(a, b)); 1345048e1287SRobert Watson } 1346048e1287SRobert Watson 1347048e1287SRobert Watson static void 1348048e1287SRobert Watson lomac_ip6q_reassemble(struct ip6q *q6, struct label *q6label, struct mbuf *m, 1349048e1287SRobert Watson struct label *mlabel) 1350048e1287SRobert Watson { 1351048e1287SRobert Watson struct mac_lomac *source, *dest; 1352048e1287SRobert Watson 1353048e1287SRobert Watson source = SLOT(q6label); 1354048e1287SRobert Watson dest = SLOT(mlabel); 1355048e1287SRobert Watson 1356048e1287SRobert Watson /* Just use the head, since we require them all to match. */ 1357048e1287SRobert Watson lomac_copy_single(source, dest); 1358048e1287SRobert Watson } 1359048e1287SRobert Watson 1360048e1287SRobert Watson static void 1361048e1287SRobert Watson lomac_ip6q_update(struct mbuf *m, struct label *mlabel, struct ip6q *q6, 1362048e1287SRobert Watson struct label *q6label) 1363048e1287SRobert Watson { 1364048e1287SRobert Watson 1365048e1287SRobert Watson /* NOOP: we only accept matching labels, so no need to update */ 1366048e1287SRobert Watson } 1367048e1287SRobert Watson 1368048e1287SRobert Watson static void 136937f44cb4SRobert Watson lomac_ipq_create(struct mbuf *m, struct label *mlabel, struct ipq *q, 137037f44cb4SRobert Watson struct label *qlabel) 1371eb320b0eSRobert Watson { 1372eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1373eb320b0eSRobert Watson 1374eb320b0eSRobert Watson source = SLOT(mlabel); 137537f44cb4SRobert Watson dest = SLOT(qlabel); 1376eb320b0eSRobert Watson 1377eb320b0eSRobert Watson lomac_copy_single(source, dest); 1378eb320b0eSRobert Watson } 1379eb320b0eSRobert Watson 1380eb320b0eSRobert Watson static int 138137f44cb4SRobert Watson lomac_ipq_match(struct mbuf *m, struct label *mlabel, struct ipq *q, 138237f44cb4SRobert Watson struct label *qlabel) 1383eb320b0eSRobert Watson { 1384eb320b0eSRobert Watson struct mac_lomac *a, *b; 1385eb320b0eSRobert Watson 138637f44cb4SRobert Watson a = SLOT(qlabel); 1387eb320b0eSRobert Watson b = SLOT(mlabel); 1388eb320b0eSRobert Watson 1389eb320b0eSRobert Watson return (lomac_equal_single(a, b)); 1390eb320b0eSRobert Watson } 1391eb320b0eSRobert Watson 1392eb320b0eSRobert Watson static void 139337f44cb4SRobert Watson lomac_ipq_reassemble(struct ipq *q, struct label *qlabel, struct mbuf *m, 139437f44cb4SRobert Watson struct label *mlabel) 1395eb320b0eSRobert Watson { 1396eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1397eb320b0eSRobert Watson 139837f44cb4SRobert Watson source = SLOT(qlabel); 1399eb320b0eSRobert Watson dest = SLOT(mlabel); 1400eb320b0eSRobert Watson 1401eb320b0eSRobert Watson /* Just use the head, since we require them all to match. */ 1402eb320b0eSRobert Watson lomac_copy_single(source, dest); 1403eb320b0eSRobert Watson } 1404eb320b0eSRobert Watson 1405eb320b0eSRobert Watson static void 140637f44cb4SRobert Watson lomac_ipq_update(struct mbuf *m, struct label *mlabel, struct ipq *q, 140737f44cb4SRobert Watson struct label *qlabel) 1408eb320b0eSRobert Watson { 1409eb320b0eSRobert Watson 1410eb320b0eSRobert Watson /* NOOP: we only accept matching labels, so no need to update */ 1411eb320b0eSRobert Watson } 1412eb320b0eSRobert Watson 1413a557af22SRobert Watson static int 14143f1a7a90SRobert Watson lomac_kld_check_load(struct ucred *cred, struct vnode *vp, 141578007886SRobert Watson struct label *vplabel) 1416db2661ceSRobert Watson { 1417db2661ceSRobert Watson struct mac_lomac *subj, *obj; 1418db2661ceSRobert Watson 14193f1a7a90SRobert Watson if (!lomac_enabled) 1420db2661ceSRobert Watson return (0); 1421db2661ceSRobert Watson 1422eca8a663SRobert Watson subj = SLOT(cred->cr_label); 142378007886SRobert Watson obj = SLOT(vplabel); 1424db2661ceSRobert Watson 14253f1a7a90SRobert Watson if (lomac_subject_privileged(subj)) 1426db2661ceSRobert Watson return (EPERM); 1427db2661ceSRobert Watson 14283f1a7a90SRobert Watson if (!lomac_high_single(obj)) 1429db2661ceSRobert Watson return (EACCES); 1430db2661ceSRobert Watson 1431db2661ceSRobert Watson return (0); 1432db2661ceSRobert Watson } 1433db2661ceSRobert Watson 1434eb320b0eSRobert Watson static void 1435eb320b0eSRobert Watson lomac_mount_create(struct ucred *cred, struct mount *mp, 1436eb320b0eSRobert Watson struct label *mplabel) 1437eb320b0eSRobert Watson { 1438eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1439eb320b0eSRobert Watson 1440eb320b0eSRobert Watson source = SLOT(cred->cr_label); 1441eb320b0eSRobert Watson dest = SLOT(mplabel); 1442eb320b0eSRobert Watson lomac_copy_single(source, dest); 1443eb320b0eSRobert Watson } 1444eb320b0eSRobert Watson 1445eb320b0eSRobert Watson static void 1446eb320b0eSRobert Watson lomac_netinet_arp_send(struct ifnet *ifp, struct label *ifplabel, 1447eb320b0eSRobert Watson struct mbuf *m, struct label *mlabel) 1448eb320b0eSRobert Watson { 1449eb320b0eSRobert Watson struct mac_lomac *dest; 1450eb320b0eSRobert Watson 1451eb320b0eSRobert Watson dest = SLOT(mlabel); 1452eb320b0eSRobert Watson 1453eb320b0eSRobert Watson lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0); 1454eb320b0eSRobert Watson } 1455eb320b0eSRobert Watson 1456eb320b0eSRobert Watson static void 1457eb320b0eSRobert Watson lomac_netinet_firewall_reply(struct mbuf *mrecv, struct label *mrecvlabel, 1458eb320b0eSRobert Watson struct mbuf *msend, struct label *msendlabel) 1459eb320b0eSRobert Watson { 1460eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1461eb320b0eSRobert Watson 1462eb320b0eSRobert Watson source = SLOT(mrecvlabel); 1463eb320b0eSRobert Watson dest = SLOT(msendlabel); 1464eb320b0eSRobert Watson 1465eb320b0eSRobert Watson lomac_copy_single(source, dest); 1466eb320b0eSRobert Watson } 1467eb320b0eSRobert Watson 1468eb320b0eSRobert Watson static void 1469eb320b0eSRobert Watson lomac_netinet_firewall_send(struct mbuf *m, struct label *mlabel) 1470eb320b0eSRobert Watson { 1471eb320b0eSRobert Watson struct mac_lomac *dest; 1472eb320b0eSRobert Watson 1473eb320b0eSRobert Watson dest = SLOT(mlabel); 1474eb320b0eSRobert Watson 1475eb320b0eSRobert Watson /* XXX: where is the label for the firewall really comming from? */ 1476eb320b0eSRobert Watson lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0); 1477eb320b0eSRobert Watson } 1478eb320b0eSRobert Watson 1479eb320b0eSRobert Watson static void 1480eb320b0eSRobert Watson lomac_netinet_fragment(struct mbuf *m, struct label *mlabel, 1481eb320b0eSRobert Watson struct mbuf *frag, struct label *fraglabel) 1482eb320b0eSRobert Watson { 1483eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1484eb320b0eSRobert Watson 1485eb320b0eSRobert Watson source = SLOT(mlabel); 1486eb320b0eSRobert Watson dest = SLOT(fraglabel); 1487eb320b0eSRobert Watson 1488eb320b0eSRobert Watson lomac_copy_single(source, dest); 1489eb320b0eSRobert Watson } 1490eb320b0eSRobert Watson 1491eb320b0eSRobert Watson static void 1492eb320b0eSRobert Watson lomac_netinet_icmp_reply(struct mbuf *mrecv, struct label *mrecvlabel, 1493eb320b0eSRobert Watson struct mbuf *msend, struct label *msendlabel) 1494eb320b0eSRobert Watson { 1495eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1496eb320b0eSRobert Watson 1497eb320b0eSRobert Watson source = SLOT(mrecvlabel); 1498eb320b0eSRobert Watson dest = SLOT(msendlabel); 1499eb320b0eSRobert Watson 1500eb320b0eSRobert Watson lomac_copy_single(source, dest); 1501eb320b0eSRobert Watson } 1502eb320b0eSRobert Watson 1503eb320b0eSRobert Watson static void 1504eb320b0eSRobert Watson lomac_netinet_igmp_send(struct ifnet *ifp, struct label *ifplabel, 1505eb320b0eSRobert Watson struct mbuf *m, struct label *mlabel) 1506eb320b0eSRobert Watson { 1507eb320b0eSRobert Watson struct mac_lomac *dest; 1508eb320b0eSRobert Watson 1509eb320b0eSRobert Watson dest = SLOT(mlabel); 1510eb320b0eSRobert Watson 1511eb320b0eSRobert Watson lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0); 1512eb320b0eSRobert Watson } 1513eb320b0eSRobert Watson 1514eb320b0eSRobert Watson static void 1515eb320b0eSRobert Watson lomac_netinet6_nd6_send(struct ifnet *ifp, struct label *ifplabel, 1516eb320b0eSRobert Watson struct mbuf *m, struct label *mlabel) 1517eb320b0eSRobert Watson { 1518eb320b0eSRobert Watson struct mac_lomac *dest; 1519eb320b0eSRobert Watson 1520eb320b0eSRobert Watson dest = SLOT(mlabel); 1521eb320b0eSRobert Watson 1522eb320b0eSRobert Watson lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0); 1523eb320b0eSRobert Watson } 1524eb320b0eSRobert Watson 1525db2661ceSRobert Watson static int 15263f1a7a90SRobert Watson lomac_pipe_check_ioctl(struct ucred *cred, struct pipepair *pp, 152778007886SRobert Watson struct label *pplabel, unsigned long cmd, void /* caddr_t */ *data) 1528db2661ceSRobert Watson { 1529db2661ceSRobert Watson 15303f1a7a90SRobert Watson if (!lomac_enabled) 1531db2661ceSRobert Watson return (0); 1532db2661ceSRobert Watson 1533db2661ceSRobert Watson /* XXX: This will be implemented soon... */ 1534db2661ceSRobert Watson 1535db2661ceSRobert Watson return (0); 1536db2661ceSRobert Watson } 1537db2661ceSRobert Watson 1538db2661ceSRobert Watson static int 15393f1a7a90SRobert Watson lomac_pipe_check_read(struct ucred *cred, struct pipepair *pp, 154078007886SRobert Watson struct label *pplabel) 1541db2661ceSRobert Watson { 1542db2661ceSRobert Watson struct mac_lomac *subj, *obj; 1543db2661ceSRobert Watson 15443f1a7a90SRobert Watson if (!lomac_enabled) 1545db2661ceSRobert Watson return (0); 1546db2661ceSRobert Watson 1547eca8a663SRobert Watson subj = SLOT(cred->cr_label); 154878007886SRobert Watson obj = SLOT(pplabel); 1549db2661ceSRobert Watson 15503f1a7a90SRobert Watson if (!lomac_dominate_single(obj, subj)) 1551db2661ceSRobert Watson return (maybe_demote(subj, obj, "reading", "pipe", NULL)); 1552db2661ceSRobert Watson 1553db2661ceSRobert Watson return (0); 1554db2661ceSRobert Watson } 1555db2661ceSRobert Watson 1556db2661ceSRobert Watson static int 15573f1a7a90SRobert Watson lomac_pipe_check_relabel(struct ucred *cred, struct pipepair *pp, 155878007886SRobert Watson struct label *pplabel, struct label *newlabel) 1559db2661ceSRobert Watson { 1560db2661ceSRobert Watson struct mac_lomac *subj, *obj, *new; 1561db2661ceSRobert Watson int error; 1562db2661ceSRobert Watson 1563db2661ceSRobert Watson new = SLOT(newlabel); 1564eca8a663SRobert Watson subj = SLOT(cred->cr_label); 156578007886SRobert Watson obj = SLOT(pplabel); 1566db2661ceSRobert Watson 1567db2661ceSRobert Watson /* 15683f1a7a90SRobert Watson * If there is a LOMAC label update for a pipe, it must be a single 15693f1a7a90SRobert Watson * update. 1570db2661ceSRobert Watson */ 1571db2661ceSRobert Watson error = lomac_atmostflags(new, MAC_LOMAC_FLAG_SINGLE); 1572db2661ceSRobert Watson if (error) 1573db2661ceSRobert Watson return (error); 1574db2661ceSRobert Watson 1575db2661ceSRobert Watson /* 1576db2661ceSRobert Watson * To perform a relabel of a pipe (LOMAC label or not), LOMAC must 1577db2661ceSRobert Watson * authorize the relabel. 1578db2661ceSRobert Watson */ 15793f1a7a90SRobert Watson if (!lomac_single_in_range(obj, subj)) 1580db2661ceSRobert Watson return (EPERM); 1581db2661ceSRobert Watson 1582db2661ceSRobert Watson /* 1583db2661ceSRobert Watson * If the LOMAC label is to be changed, authorize as appropriate. 1584db2661ceSRobert Watson */ 1585db2661ceSRobert Watson if (new->ml_flags & MAC_LOMAC_FLAG_SINGLE) { 1586db2661ceSRobert Watson /* 1587db2661ceSRobert Watson * To change the LOMAC label on a pipe, the new pipe label 1588db2661ceSRobert Watson * must be in the subject range. 1589db2661ceSRobert Watson */ 15903f1a7a90SRobert Watson if (!lomac_single_in_range(new, subj)) 1591db2661ceSRobert Watson return (EPERM); 1592db2661ceSRobert Watson 1593db2661ceSRobert Watson /* 1594db2661ceSRobert Watson * To change the LOMAC label on a pipe to be EQUAL, the 1595db2661ceSRobert Watson * subject must have appropriate privilege. 1596db2661ceSRobert Watson */ 15973f1a7a90SRobert Watson if (lomac_contains_equal(new)) { 15983f1a7a90SRobert Watson error = lomac_subject_privileged(subj); 1599db2661ceSRobert Watson if (error) 1600db2661ceSRobert Watson return (error); 1601db2661ceSRobert Watson } 1602db2661ceSRobert Watson } 1603db2661ceSRobert Watson 1604db2661ceSRobert Watson return (0); 1605db2661ceSRobert Watson } 1606db2661ceSRobert Watson 1607db2661ceSRobert Watson static int 16083f1a7a90SRobert Watson lomac_pipe_check_write(struct ucred *cred, struct pipepair *pp, 160978007886SRobert Watson struct label *pplabel) 1610db2661ceSRobert Watson { 1611db2661ceSRobert Watson struct mac_lomac *subj, *obj; 1612db2661ceSRobert Watson 16133f1a7a90SRobert Watson if (!lomac_enabled) 1614db2661ceSRobert Watson return (0); 1615db2661ceSRobert Watson 1616eca8a663SRobert Watson subj = SLOT(cred->cr_label); 161778007886SRobert Watson obj = SLOT(pplabel); 1618db2661ceSRobert Watson 16193f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 1620db2661ceSRobert Watson return (EACCES); 1621db2661ceSRobert Watson 1622db2661ceSRobert Watson return (0); 1623db2661ceSRobert Watson } 1624db2661ceSRobert Watson 1625eb320b0eSRobert Watson static void 1626eb320b0eSRobert Watson lomac_pipe_create(struct ucred *cred, struct pipepair *pp, 1627eb320b0eSRobert Watson struct label *pplabel) 1628db2661ceSRobert Watson { 1629eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1630db2661ceSRobert Watson 1631eb320b0eSRobert Watson source = SLOT(cred->cr_label); 1632eb320b0eSRobert Watson dest = SLOT(pplabel); 1633db2661ceSRobert Watson 1634eb320b0eSRobert Watson lomac_copy_single(source, dest); 1635db2661ceSRobert Watson } 1636db2661ceSRobert Watson 1637eb320b0eSRobert Watson static void 1638eb320b0eSRobert Watson lomac_pipe_relabel(struct ucred *cred, struct pipepair *pp, 1639eb320b0eSRobert Watson struct label *pplabel, struct label *newlabel) 1640db2661ceSRobert Watson { 1641eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1642db2661ceSRobert Watson 1643eb320b0eSRobert Watson source = SLOT(newlabel); 1644eb320b0eSRobert Watson dest = SLOT(pplabel); 1645db2661ceSRobert Watson 1646eb320b0eSRobert Watson try_relabel(source, dest); 1647db2661ceSRobert Watson } 1648db2661ceSRobert Watson 1649c14d15aeSRobert Watson /* 1650c14d15aeSRobert Watson * Some system privileges are allowed regardless of integrity grade; others 1651c14d15aeSRobert Watson * are allowed only when running with privilege with respect to the LOMAC 1652c14d15aeSRobert Watson * policy as they might otherwise allow bypassing of the integrity policy. 1653c14d15aeSRobert Watson */ 1654c14d15aeSRobert Watson static int 16553f1a7a90SRobert Watson lomac_priv_check(struct ucred *cred, int priv) 1656c14d15aeSRobert Watson { 1657c14d15aeSRobert Watson struct mac_lomac *subj; 1658c14d15aeSRobert Watson int error; 1659c14d15aeSRobert Watson 16603f1a7a90SRobert Watson if (!lomac_enabled) 1661c14d15aeSRobert Watson return (0); 1662c14d15aeSRobert Watson 1663c14d15aeSRobert Watson /* 1664c14d15aeSRobert Watson * Exempt only specific privileges from the LOMAC integrity policy. 1665c14d15aeSRobert Watson */ 1666c14d15aeSRobert Watson switch (priv) { 1667c14d15aeSRobert Watson case PRIV_KTRACE: 1668c14d15aeSRobert Watson case PRIV_MSGBUF: 1669c14d15aeSRobert Watson 1670c14d15aeSRobert Watson /* 1671c14d15aeSRobert Watson * Allow processes to manipulate basic process audit properties, and 1672c14d15aeSRobert Watson * to submit audit records. 1673c14d15aeSRobert Watson */ 1674c14d15aeSRobert Watson case PRIV_AUDIT_GETAUDIT: 1675c14d15aeSRobert Watson case PRIV_AUDIT_SETAUDIT: 1676c14d15aeSRobert Watson case PRIV_AUDIT_SUBMIT: 1677c14d15aeSRobert Watson 1678c14d15aeSRobert Watson /* 1679c14d15aeSRobert Watson * Allow processes to manipulate their regular UNIX credentials. 1680c14d15aeSRobert Watson */ 1681c14d15aeSRobert Watson case PRIV_CRED_SETUID: 1682c14d15aeSRobert Watson case PRIV_CRED_SETEUID: 1683c14d15aeSRobert Watson case PRIV_CRED_SETGID: 1684c14d15aeSRobert Watson case PRIV_CRED_SETEGID: 1685c14d15aeSRobert Watson case PRIV_CRED_SETGROUPS: 1686c14d15aeSRobert Watson case PRIV_CRED_SETREUID: 1687c14d15aeSRobert Watson case PRIV_CRED_SETREGID: 1688c14d15aeSRobert Watson case PRIV_CRED_SETRESUID: 1689c14d15aeSRobert Watson case PRIV_CRED_SETRESGID: 1690c14d15aeSRobert Watson 1691c14d15aeSRobert Watson /* 1692c14d15aeSRobert Watson * Allow processes to perform system monitoring. 1693c14d15aeSRobert Watson */ 1694c14d15aeSRobert Watson case PRIV_SEEOTHERGIDS: 1695c14d15aeSRobert Watson case PRIV_SEEOTHERUIDS: 1696c14d15aeSRobert Watson break; 1697c14d15aeSRobert Watson 1698c14d15aeSRobert Watson /* 1699c14d15aeSRobert Watson * Allow access to general process debugging facilities. We 1700c14d15aeSRobert Watson * separately control debugging based on MAC label. 1701c14d15aeSRobert Watson */ 1702c14d15aeSRobert Watson case PRIV_DEBUG_DIFFCRED: 1703c14d15aeSRobert Watson case PRIV_DEBUG_SUGID: 1704c14d15aeSRobert Watson case PRIV_DEBUG_UNPRIV: 1705c14d15aeSRobert Watson 1706c14d15aeSRobert Watson /* 1707c14d15aeSRobert Watson * Allow manipulating jails. 1708c14d15aeSRobert Watson */ 1709c14d15aeSRobert Watson case PRIV_JAIL_ATTACH: 1710c14d15aeSRobert Watson 1711c14d15aeSRobert Watson /* 1712c14d15aeSRobert Watson * Allow privilege with respect to the Partition policy, but not the 1713c14d15aeSRobert Watson * Privs policy. 1714c14d15aeSRobert Watson */ 1715c14d15aeSRobert Watson case PRIV_MAC_PARTITION: 1716c14d15aeSRobert Watson 1717c14d15aeSRobert Watson /* 1718c14d15aeSRobert Watson * Allow privilege with respect to process resource limits and login 1719c14d15aeSRobert Watson * context. 1720c14d15aeSRobert Watson */ 1721c14d15aeSRobert Watson case PRIV_PROC_LIMIT: 1722c14d15aeSRobert Watson case PRIV_PROC_SETLOGIN: 1723c14d15aeSRobert Watson case PRIV_PROC_SETRLIMIT: 1724c14d15aeSRobert Watson 1725c14d15aeSRobert Watson /* 1726c14d15aeSRobert Watson * Allow System V and POSIX IPC privileges. 1727c14d15aeSRobert Watson */ 1728c14d15aeSRobert Watson case PRIV_IPC_READ: 1729c14d15aeSRobert Watson case PRIV_IPC_WRITE: 1730c14d15aeSRobert Watson case PRIV_IPC_ADMIN: 1731c14d15aeSRobert Watson case PRIV_IPC_MSGSIZE: 1732c14d15aeSRobert Watson case PRIV_MQ_ADMIN: 1733c14d15aeSRobert Watson 1734c14d15aeSRobert Watson /* 1735c14d15aeSRobert Watson * Allow certain scheduler manipulations -- possibly this should be 1736c14d15aeSRobert Watson * controlled by more fine-grained policy, as potentially low 1737c14d15aeSRobert Watson * integrity processes can deny CPU to higher integrity ones. 1738c14d15aeSRobert Watson */ 1739c14d15aeSRobert Watson case PRIV_SCHED_DIFFCRED: 1740c14d15aeSRobert Watson case PRIV_SCHED_SETPRIORITY: 1741c14d15aeSRobert Watson case PRIV_SCHED_RTPRIO: 1742c14d15aeSRobert Watson case PRIV_SCHED_SETPOLICY: 1743c14d15aeSRobert Watson case PRIV_SCHED_SET: 1744c14d15aeSRobert Watson case PRIV_SCHED_SETPARAM: 1745c14d15aeSRobert Watson 1746c14d15aeSRobert Watson /* 1747c14d15aeSRobert Watson * More IPC privileges. 1748c14d15aeSRobert Watson */ 1749c14d15aeSRobert Watson case PRIV_SEM_WRITE: 1750c14d15aeSRobert Watson 1751c14d15aeSRobert Watson /* 1752c14d15aeSRobert Watson * Allow signaling privileges subject to integrity policy. 1753c14d15aeSRobert Watson */ 1754c14d15aeSRobert Watson case PRIV_SIGNAL_DIFFCRED: 1755c14d15aeSRobert Watson case PRIV_SIGNAL_SUGID: 1756c14d15aeSRobert Watson 1757c14d15aeSRobert Watson /* 1758c14d15aeSRobert Watson * Allow access to only limited sysctls from lower integrity levels; 1759c14d15aeSRobert Watson * piggy-back on the Jail definition. 1760c14d15aeSRobert Watson */ 1761c14d15aeSRobert Watson case PRIV_SYSCTL_WRITEJAIL: 1762c14d15aeSRobert Watson 1763c14d15aeSRobert Watson /* 1764c14d15aeSRobert Watson * Allow TTY-based privileges, subject to general device access using 1765c14d15aeSRobert Watson * labels on TTY device nodes, but not console privilege. 1766c14d15aeSRobert Watson */ 1767c14d15aeSRobert Watson case PRIV_TTY_DRAINWAIT: 1768c14d15aeSRobert Watson case PRIV_TTY_DTRWAIT: 1769c14d15aeSRobert Watson case PRIV_TTY_EXCLUSIVE: 1770c14d15aeSRobert Watson case PRIV_TTY_STI: 1771c14d15aeSRobert Watson case PRIV_TTY_SETA: 1772c14d15aeSRobert Watson 1773c14d15aeSRobert Watson /* 1774c14d15aeSRobert Watson * Grant most VFS privileges, as almost all are in practice bounded 1775c14d15aeSRobert Watson * by more specific checks using labels. 1776c14d15aeSRobert Watson */ 1777c14d15aeSRobert Watson case PRIV_VFS_READ: 1778c14d15aeSRobert Watson case PRIV_VFS_WRITE: 1779c14d15aeSRobert Watson case PRIV_VFS_ADMIN: 1780c14d15aeSRobert Watson case PRIV_VFS_EXEC: 1781c14d15aeSRobert Watson case PRIV_VFS_LOOKUP: 1782c14d15aeSRobert Watson case PRIV_VFS_CHFLAGS_DEV: 1783c14d15aeSRobert Watson case PRIV_VFS_CHOWN: 1784c14d15aeSRobert Watson case PRIV_VFS_CHROOT: 1785c14d15aeSRobert Watson case PRIV_VFS_RETAINSUGID: 1786c14d15aeSRobert Watson case PRIV_VFS_EXCEEDQUOTA: 1787c14d15aeSRobert Watson case PRIV_VFS_FCHROOT: 1788c14d15aeSRobert Watson case PRIV_VFS_FHOPEN: 1789c14d15aeSRobert Watson case PRIV_VFS_FHSTATFS: 1790c14d15aeSRobert Watson case PRIV_VFS_GENERATION: 1791c14d15aeSRobert Watson case PRIV_VFS_GETFH: 1792c14d15aeSRobert Watson case PRIV_VFS_GETQUOTA: 1793c14d15aeSRobert Watson case PRIV_VFS_LINK: 1794c14d15aeSRobert Watson case PRIV_VFS_MOUNT: 1795c14d15aeSRobert Watson case PRIV_VFS_MOUNT_OWNER: 1796c14d15aeSRobert Watson case PRIV_VFS_MOUNT_PERM: 1797c14d15aeSRobert Watson case PRIV_VFS_MOUNT_SUIDDIR: 1798c14d15aeSRobert Watson case PRIV_VFS_MOUNT_NONUSER: 1799c14d15aeSRobert Watson case PRIV_VFS_SETGID: 1800c14d15aeSRobert Watson case PRIV_VFS_STICKYFILE: 1801c14d15aeSRobert Watson case PRIV_VFS_SYSFLAGS: 1802c14d15aeSRobert Watson case PRIV_VFS_UNMOUNT: 1803c14d15aeSRobert Watson 1804c14d15aeSRobert Watson /* 1805c14d15aeSRobert Watson * Allow VM privileges; it would be nice if these were subject to 1806c14d15aeSRobert Watson * resource limits. 1807c14d15aeSRobert Watson */ 1808c14d15aeSRobert Watson case PRIV_VM_MADV_PROTECT: 1809c14d15aeSRobert Watson case PRIV_VM_MLOCK: 1810c14d15aeSRobert Watson case PRIV_VM_MUNLOCK: 18113364c323SKonstantin Belousov case PRIV_VM_SWAP_NOQUOTA: 18123364c323SKonstantin Belousov case PRIV_VM_SWAP_NORLIMIT: 1813c14d15aeSRobert Watson 1814c14d15aeSRobert Watson /* 1815c14d15aeSRobert Watson * Allow some but not all network privileges. In general, dont allow 1816c14d15aeSRobert Watson * reconfiguring the network stack, just normal use. 1817c14d15aeSRobert Watson */ 1818c14d15aeSRobert Watson case PRIV_NETINET_RESERVEDPORT: 1819c14d15aeSRobert Watson case PRIV_NETINET_RAW: 1820c14d15aeSRobert Watson case PRIV_NETINET_REUSEPORT: 1821c14d15aeSRobert Watson break; 1822c14d15aeSRobert Watson 1823c14d15aeSRobert Watson /* 1824c14d15aeSRobert Watson * All remaining system privileges are allow only if the process 1825c14d15aeSRobert Watson * holds privilege with respect to the LOMAC policy. 1826c14d15aeSRobert Watson */ 1827c14d15aeSRobert Watson default: 1828c14d15aeSRobert Watson subj = SLOT(cred->cr_label); 18293f1a7a90SRobert Watson error = lomac_subject_privileged(subj); 1830c14d15aeSRobert Watson if (error) 1831c14d15aeSRobert Watson return (error); 1832c14d15aeSRobert Watson } 1833c14d15aeSRobert Watson return (0); 1834c14d15aeSRobert Watson } 1835c14d15aeSRobert Watson 1836eb320b0eSRobert Watson static int 1837eb320b0eSRobert Watson lomac_proc_check_debug(struct ucred *cred, struct proc *p) 1838eb320b0eSRobert Watson { 1839eb320b0eSRobert Watson struct mac_lomac *subj, *obj; 1840eb320b0eSRobert Watson 1841eb320b0eSRobert Watson if (!lomac_enabled) 1842eb320b0eSRobert Watson return (0); 1843eb320b0eSRobert Watson 1844eb320b0eSRobert Watson subj = SLOT(cred->cr_label); 1845eb320b0eSRobert Watson obj = SLOT(p->p_ucred->cr_label); 1846eb320b0eSRobert Watson 1847eb320b0eSRobert Watson /* XXX: range checks */ 1848eb320b0eSRobert Watson if (!lomac_dominate_single(obj, subj)) 1849eb320b0eSRobert Watson return (ESRCH); 1850eb320b0eSRobert Watson if (!lomac_subject_dominate(subj, obj)) 1851eb320b0eSRobert Watson return (EACCES); 1852eb320b0eSRobert Watson 1853eb320b0eSRobert Watson return (0); 1854eb320b0eSRobert Watson } 1855eb320b0eSRobert Watson 1856eb320b0eSRobert Watson static int 1857eb320b0eSRobert Watson lomac_proc_check_sched(struct ucred *cred, struct proc *p) 1858eb320b0eSRobert Watson { 1859eb320b0eSRobert Watson struct mac_lomac *subj, *obj; 1860eb320b0eSRobert Watson 1861eb320b0eSRobert Watson if (!lomac_enabled) 1862eb320b0eSRobert Watson return (0); 1863eb320b0eSRobert Watson 1864eb320b0eSRobert Watson subj = SLOT(cred->cr_label); 1865eb320b0eSRobert Watson obj = SLOT(p->p_ucred->cr_label); 1866eb320b0eSRobert Watson 1867eb320b0eSRobert Watson /* XXX: range checks */ 1868eb320b0eSRobert Watson if (!lomac_dominate_single(obj, subj)) 1869eb320b0eSRobert Watson return (ESRCH); 1870eb320b0eSRobert Watson if (!lomac_subject_dominate(subj, obj)) 1871eb320b0eSRobert Watson return (EACCES); 1872eb320b0eSRobert Watson 1873eb320b0eSRobert Watson return (0); 1874eb320b0eSRobert Watson } 1875eb320b0eSRobert Watson 1876eb320b0eSRobert Watson static int 1877eb320b0eSRobert Watson lomac_proc_check_signal(struct ucred *cred, struct proc *p, int signum) 1878eb320b0eSRobert Watson { 1879eb320b0eSRobert Watson struct mac_lomac *subj, *obj; 1880eb320b0eSRobert Watson 1881eb320b0eSRobert Watson if (!lomac_enabled) 1882eb320b0eSRobert Watson return (0); 1883eb320b0eSRobert Watson 1884eb320b0eSRobert Watson subj = SLOT(cred->cr_label); 1885eb320b0eSRobert Watson obj = SLOT(p->p_ucred->cr_label); 1886eb320b0eSRobert Watson 1887eb320b0eSRobert Watson /* XXX: range checks */ 1888eb320b0eSRobert Watson if (!lomac_dominate_single(obj, subj)) 1889eb320b0eSRobert Watson return (ESRCH); 1890eb320b0eSRobert Watson if (!lomac_subject_dominate(subj, obj)) 1891eb320b0eSRobert Watson return (EACCES); 1892eb320b0eSRobert Watson 1893eb320b0eSRobert Watson return (0); 1894eb320b0eSRobert Watson } 1895eb320b0eSRobert Watson 1896eb320b0eSRobert Watson static void 1897eb320b0eSRobert Watson lomac_proc_destroy_label(struct label *label) 1898eb320b0eSRobert Watson { 1899eb320b0eSRobert Watson 1900eb320b0eSRobert Watson mtx_destroy(&PSLOT(label)->mtx); 19011ede983cSDag-Erling Smørgrav free(PSLOT(label), M_LOMAC); 1902eb320b0eSRobert Watson PSLOT_SET(label, NULL); 1903eb320b0eSRobert Watson } 1904eb320b0eSRobert Watson 1905eb320b0eSRobert Watson static void 1906eb320b0eSRobert Watson lomac_proc_init_label(struct label *label) 1907eb320b0eSRobert Watson { 1908eb320b0eSRobert Watson 1909eb320b0eSRobert Watson PSLOT_SET(label, malloc(sizeof(struct mac_lomac_proc), M_LOMAC, 1910eb320b0eSRobert Watson M_ZERO | M_WAITOK)); 1911eb320b0eSRobert Watson mtx_init(&PSLOT(label)->mtx, "MAC/Lomac proc lock", NULL, MTX_DEF); 1912eb320b0eSRobert Watson } 1913eb320b0eSRobert Watson 1914eb320b0eSRobert Watson static int 1915eb320b0eSRobert Watson lomac_socket_check_deliver(struct socket *so, struct label *solabel, 1916eb320b0eSRobert Watson struct mbuf *m, struct label *mlabel) 1917eb320b0eSRobert Watson { 1918eb320b0eSRobert Watson struct mac_lomac *p, *s; 19193de40469SRobert Watson int error; 1920eb320b0eSRobert Watson 1921eb320b0eSRobert Watson if (!lomac_enabled) 1922eb320b0eSRobert Watson return (0); 1923eb320b0eSRobert Watson 1924eb320b0eSRobert Watson p = SLOT(mlabel); 1925eb320b0eSRobert Watson s = SLOT(solabel); 1926eb320b0eSRobert Watson 19273de40469SRobert Watson SOCK_LOCK(so); 19283de40469SRobert Watson error = lomac_equal_single(p, s) ? 0 : EACCES; 19293de40469SRobert Watson SOCK_UNLOCK(so); 19303de40469SRobert Watson return (error); 1931eb320b0eSRobert Watson } 1932eb320b0eSRobert Watson 1933eb320b0eSRobert Watson static int 1934eb320b0eSRobert Watson lomac_socket_check_relabel(struct ucred *cred, struct socket *so, 1935eb320b0eSRobert Watson struct label *solabel, struct label *newlabel) 1936eb320b0eSRobert Watson { 1937eb320b0eSRobert Watson struct mac_lomac *subj, *obj, *new; 1938eb320b0eSRobert Watson int error; 1939eb320b0eSRobert Watson 19403de40469SRobert Watson SOCK_LOCK_ASSERT(so); 19413de40469SRobert Watson 1942eb320b0eSRobert Watson new = SLOT(newlabel); 1943eb320b0eSRobert Watson subj = SLOT(cred->cr_label); 1944eb320b0eSRobert Watson obj = SLOT(solabel); 1945eb320b0eSRobert Watson 1946eb320b0eSRobert Watson /* 1947eb320b0eSRobert Watson * If there is a LOMAC label update for the socket, it may be an 1948eb320b0eSRobert Watson * update of single. 1949eb320b0eSRobert Watson */ 1950eb320b0eSRobert Watson error = lomac_atmostflags(new, MAC_LOMAC_FLAG_SINGLE); 1951eb320b0eSRobert Watson if (error) 1952eb320b0eSRobert Watson return (error); 1953eb320b0eSRobert Watson 1954eb320b0eSRobert Watson /* 1955eb320b0eSRobert Watson * To relabel a socket, the old socket single must be in the subject 1956eb320b0eSRobert Watson * range. 1957eb320b0eSRobert Watson */ 1958eb320b0eSRobert Watson if (!lomac_single_in_range(obj, subj)) 1959eb320b0eSRobert Watson return (EPERM); 1960eb320b0eSRobert Watson 1961eb320b0eSRobert Watson /* 1962eb320b0eSRobert Watson * If the LOMAC label is to be changed, authorize as appropriate. 1963eb320b0eSRobert Watson */ 1964eb320b0eSRobert Watson if (new->ml_flags & MAC_LOMAC_FLAG_SINGLE) { 1965eb320b0eSRobert Watson /* 1966eb320b0eSRobert Watson * To relabel a socket, the new socket single must be in the 1967eb320b0eSRobert Watson * subject range. 1968eb320b0eSRobert Watson */ 1969eb320b0eSRobert Watson if (!lomac_single_in_range(new, subj)) 1970eb320b0eSRobert Watson return (EPERM); 1971eb320b0eSRobert Watson 1972eb320b0eSRobert Watson /* 1973eb320b0eSRobert Watson * To change the LOMAC label on the socket to contain EQUAL, 1974eb320b0eSRobert Watson * the subject must have appropriate privilege. 1975eb320b0eSRobert Watson */ 1976eb320b0eSRobert Watson if (lomac_contains_equal(new)) { 1977eb320b0eSRobert Watson error = lomac_subject_privileged(subj); 1978eb320b0eSRobert Watson if (error) 1979eb320b0eSRobert Watson return (error); 1980eb320b0eSRobert Watson } 1981eb320b0eSRobert Watson } 1982eb320b0eSRobert Watson 1983eb320b0eSRobert Watson return (0); 1984eb320b0eSRobert Watson } 1985eb320b0eSRobert Watson 1986eb320b0eSRobert Watson static int 1987eb320b0eSRobert Watson lomac_socket_check_visible(struct ucred *cred, struct socket *so, 1988eb320b0eSRobert Watson struct label *solabel) 1989eb320b0eSRobert Watson { 1990eb320b0eSRobert Watson struct mac_lomac *subj, *obj; 1991eb320b0eSRobert Watson 1992eb320b0eSRobert Watson if (!lomac_enabled) 1993eb320b0eSRobert Watson return (0); 1994eb320b0eSRobert Watson 1995eb320b0eSRobert Watson subj = SLOT(cred->cr_label); 1996eb320b0eSRobert Watson obj = SLOT(solabel); 1997eb320b0eSRobert Watson 19983de40469SRobert Watson SOCK_LOCK(so); 19993de40469SRobert Watson if (!lomac_dominate_single(obj, subj)) { 20003de40469SRobert Watson SOCK_UNLOCK(so); 2001eb320b0eSRobert Watson return (ENOENT); 20023de40469SRobert Watson } 20033de40469SRobert Watson SOCK_UNLOCK(so); 2004eb320b0eSRobert Watson 2005eb320b0eSRobert Watson return (0); 2006eb320b0eSRobert Watson } 2007eb320b0eSRobert Watson 2008eb320b0eSRobert Watson static void 2009eb320b0eSRobert Watson lomac_socket_create(struct ucred *cred, struct socket *so, 2010eb320b0eSRobert Watson struct label *solabel) 2011eb320b0eSRobert Watson { 2012eb320b0eSRobert Watson struct mac_lomac *source, *dest; 2013eb320b0eSRobert Watson 2014eb320b0eSRobert Watson source = SLOT(cred->cr_label); 2015eb320b0eSRobert Watson dest = SLOT(solabel); 2016eb320b0eSRobert Watson 2017eb320b0eSRobert Watson lomac_copy_single(source, dest); 2018eb320b0eSRobert Watson } 2019eb320b0eSRobert Watson 2020eb320b0eSRobert Watson static void 2021eb320b0eSRobert Watson lomac_socket_create_mbuf(struct socket *so, struct label *solabel, 2022eb320b0eSRobert Watson struct mbuf *m, struct label *mlabel) 2023eb320b0eSRobert Watson { 2024eb320b0eSRobert Watson struct mac_lomac *source, *dest; 2025eb320b0eSRobert Watson 2026eb320b0eSRobert Watson source = SLOT(solabel); 2027eb320b0eSRobert Watson dest = SLOT(mlabel); 2028eb320b0eSRobert Watson 20293de40469SRobert Watson SOCK_LOCK(so); 2030eb320b0eSRobert Watson lomac_copy_single(source, dest); 20313de40469SRobert Watson SOCK_UNLOCK(so); 2032eb320b0eSRobert Watson } 2033eb320b0eSRobert Watson 2034eb320b0eSRobert Watson static void 2035eb320b0eSRobert Watson lomac_socket_newconn(struct socket *oldso, struct label *oldsolabel, 2036eb320b0eSRobert Watson struct socket *newso, struct label *newsolabel) 2037eb320b0eSRobert Watson { 20383de40469SRobert Watson struct mac_lomac source, *dest; 2039eb320b0eSRobert Watson 20403de40469SRobert Watson SOCK_LOCK(oldso); 20413de40469SRobert Watson source = *SLOT(oldsolabel); 20423de40469SRobert Watson SOCK_UNLOCK(oldso); 20433de40469SRobert Watson 2044eb320b0eSRobert Watson dest = SLOT(newsolabel); 2045eb320b0eSRobert Watson 20463de40469SRobert Watson SOCK_LOCK(newso); 20473de40469SRobert Watson lomac_copy_single(&source, dest); 20483de40469SRobert Watson SOCK_UNLOCK(newso); 2049eb320b0eSRobert Watson } 2050eb320b0eSRobert Watson 2051eb320b0eSRobert Watson static void 2052eb320b0eSRobert Watson lomac_socket_relabel(struct ucred *cred, struct socket *so, 2053eb320b0eSRobert Watson struct label *solabel, struct label *newlabel) 2054eb320b0eSRobert Watson { 2055eb320b0eSRobert Watson struct mac_lomac *source, *dest; 2056eb320b0eSRobert Watson 20573de40469SRobert Watson SOCK_LOCK_ASSERT(so); 20583de40469SRobert Watson 2059eb320b0eSRobert Watson source = SLOT(newlabel); 2060eb320b0eSRobert Watson dest = SLOT(solabel); 2061eb320b0eSRobert Watson 2062eb320b0eSRobert Watson try_relabel(source, dest); 2063eb320b0eSRobert Watson } 2064eb320b0eSRobert Watson 2065eb320b0eSRobert Watson static void 2066eb320b0eSRobert Watson lomac_socketpeer_set_from_mbuf(struct mbuf *m, struct label *mlabel, 2067eb320b0eSRobert Watson struct socket *so, struct label *sopeerlabel) 2068eb320b0eSRobert Watson { 2069eb320b0eSRobert Watson struct mac_lomac *source, *dest; 2070eb320b0eSRobert Watson 2071eb320b0eSRobert Watson source = SLOT(mlabel); 2072eb320b0eSRobert Watson dest = SLOT(sopeerlabel); 2073eb320b0eSRobert Watson 20743de40469SRobert Watson SOCK_LOCK(so); 2075eb320b0eSRobert Watson lomac_copy_single(source, dest); 20763de40469SRobert Watson SOCK_UNLOCK(so); 2077eb320b0eSRobert Watson } 2078eb320b0eSRobert Watson 2079eb320b0eSRobert Watson static void 2080eb320b0eSRobert Watson lomac_socketpeer_set_from_socket(struct socket *oldso, 2081eb320b0eSRobert Watson struct label *oldsolabel, struct socket *newso, 2082eb320b0eSRobert Watson struct label *newsopeerlabel) 2083eb320b0eSRobert Watson { 20843de40469SRobert Watson struct mac_lomac source, *dest; 2085eb320b0eSRobert Watson 20863de40469SRobert Watson SOCK_LOCK(oldso); 20873de40469SRobert Watson source = *SLOT(oldsolabel); 20883de40469SRobert Watson SOCK_UNLOCK(oldso); 20893de40469SRobert Watson 2090eb320b0eSRobert Watson dest = SLOT(newsopeerlabel); 2091eb320b0eSRobert Watson 20923de40469SRobert Watson SOCK_LOCK(newso); 20933de40469SRobert Watson lomac_copy_single(&source, dest); 20943de40469SRobert Watson SOCK_UNLOCK(newso); 2095eb320b0eSRobert Watson } 2096eb320b0eSRobert Watson 2097eb320b0eSRobert Watson static void 2098eb320b0eSRobert Watson lomac_syncache_create(struct label *label, struct inpcb *inp) 2099eb320b0eSRobert Watson { 2100eb320b0eSRobert Watson struct mac_lomac *source, *dest; 2101eb320b0eSRobert Watson 2102eb320b0eSRobert Watson source = SLOT(inp->inp_label); 2103eb320b0eSRobert Watson dest = SLOT(label); 2104eb320b0eSRobert Watson lomac_copy(source, dest); 2105eb320b0eSRobert Watson } 2106eb320b0eSRobert Watson 2107eb320b0eSRobert Watson static void 2108eb320b0eSRobert Watson lomac_syncache_create_mbuf(struct label *sc_label, struct mbuf *m, 2109eb320b0eSRobert Watson struct label *mlabel) 2110eb320b0eSRobert Watson { 2111eb320b0eSRobert Watson struct mac_lomac *source, *dest; 2112eb320b0eSRobert Watson 2113eb320b0eSRobert Watson source = SLOT(sc_label); 2114eb320b0eSRobert Watson dest = SLOT(mlabel); 2115eb320b0eSRobert Watson lomac_copy(source, dest); 2116eb320b0eSRobert Watson } 2117c14d15aeSRobert Watson 2118db2661ceSRobert Watson static int 21193f1a7a90SRobert Watson lomac_system_check_acct(struct ucred *cred, struct vnode *vp, 212078007886SRobert Watson struct label *vplabel) 212118717f69SRobert Watson { 212218717f69SRobert Watson struct mac_lomac *subj, *obj; 212318717f69SRobert Watson 21243f1a7a90SRobert Watson if (!lomac_enabled) 212518717f69SRobert Watson return (0); 212618717f69SRobert Watson 212718717f69SRobert Watson subj = SLOT(cred->cr_label); 212878007886SRobert Watson obj = SLOT(vplabel); 212918717f69SRobert Watson 21303f1a7a90SRobert Watson if (lomac_subject_privileged(subj)) 213118717f69SRobert Watson return (EPERM); 213218717f69SRobert Watson 21333f1a7a90SRobert Watson if (!lomac_high_single(obj)) 213418717f69SRobert Watson return (EACCES); 213518717f69SRobert Watson 213618717f69SRobert Watson return (0); 213718717f69SRobert Watson } 213818717f69SRobert Watson 213918717f69SRobert Watson static int 21403f1a7a90SRobert Watson lomac_system_check_auditctl(struct ucred *cred, struct vnode *vp, 214178007886SRobert Watson struct label *vplabel) 214218717f69SRobert Watson { 214318717f69SRobert Watson struct mac_lomac *subj, *obj; 214418717f69SRobert Watson 21453f1a7a90SRobert Watson if (!lomac_enabled) 214618717f69SRobert Watson return (0); 214718717f69SRobert Watson 214818717f69SRobert Watson subj = SLOT(cred->cr_label); 214978007886SRobert Watson obj = SLOT(vplabel); 215018717f69SRobert Watson 21513f1a7a90SRobert Watson if (lomac_subject_privileged(subj)) 215218717f69SRobert Watson return (EPERM); 215318717f69SRobert Watson 21543f1a7a90SRobert Watson if (!lomac_high_single(obj)) 215518717f69SRobert Watson return (EACCES); 215618717f69SRobert Watson 215718717f69SRobert Watson return (0); 215818717f69SRobert Watson } 215918717f69SRobert Watson 216018717f69SRobert Watson static int 21613f1a7a90SRobert Watson lomac_system_check_swapoff(struct ucred *cred, struct vnode *vp, 216278007886SRobert Watson struct label *vplabel) 216318717f69SRobert Watson { 216418717f69SRobert Watson struct mac_lomac *subj; 216518717f69SRobert Watson 21663f1a7a90SRobert Watson if (!lomac_enabled) 216718717f69SRobert Watson return (0); 216818717f69SRobert Watson 216918717f69SRobert Watson subj = SLOT(cred->cr_label); 217018717f69SRobert Watson 21713f1a7a90SRobert Watson if (lomac_subject_privileged(subj)) 217218717f69SRobert Watson return (EPERM); 217318717f69SRobert Watson 217418717f69SRobert Watson return (0); 217518717f69SRobert Watson } 217618717f69SRobert Watson 217718717f69SRobert Watson static int 21783f1a7a90SRobert Watson lomac_system_check_swapon(struct ucred *cred, struct vnode *vp, 217978007886SRobert Watson struct label *vplabel) 2180db2661ceSRobert Watson { 2181db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2182db2661ceSRobert Watson 21833f1a7a90SRobert Watson if (!lomac_enabled) 2184db2661ceSRobert Watson return (0); 2185db2661ceSRobert Watson 2186eca8a663SRobert Watson subj = SLOT(cred->cr_label); 218778007886SRobert Watson obj = SLOT(vplabel); 2188db2661ceSRobert Watson 21893f1a7a90SRobert Watson if (lomac_subject_privileged(subj)) 2190db2661ceSRobert Watson return (EPERM); 2191db2661ceSRobert Watson 21923f1a7a90SRobert Watson if (!lomac_high_single(obj)) 2193db2661ceSRobert Watson return (EACCES); 2194db2661ceSRobert Watson 2195db2661ceSRobert Watson return (0); 2196db2661ceSRobert Watson } 2197db2661ceSRobert Watson 2198db2661ceSRobert Watson static int 21993f1a7a90SRobert Watson lomac_system_check_sysctl(struct ucred *cred, struct sysctl_oid *oidp, 220063dba32bSPawel Jakub Dawidek void *arg1, int arg2, struct sysctl_req *req) 2201db2661ceSRobert Watson { 2202db2661ceSRobert Watson struct mac_lomac *subj; 2203db2661ceSRobert Watson 22043f1a7a90SRobert Watson if (!lomac_enabled) 2205db2661ceSRobert Watson return (0); 2206db2661ceSRobert Watson 2207eca8a663SRobert Watson subj = SLOT(cred->cr_label); 2208db2661ceSRobert Watson 2209db2661ceSRobert Watson /* 22103f1a7a90SRobert Watson * Treat sysctl variables without CTLFLAG_ANYBODY flag as lomac/high, 22113f1a7a90SRobert Watson * but also require privilege to change them. 2212db2661ceSRobert Watson */ 221363dba32bSPawel Jakub Dawidek if (req->newptr != NULL && (oidp->oid_kind & CTLFLAG_ANYBODY) == 0) { 2214db2661ceSRobert Watson #ifdef notdef 22153f1a7a90SRobert Watson if (!lomac_subject_dominate_high(subj)) 2216db2661ceSRobert Watson return (EACCES); 2217db2661ceSRobert Watson #endif 2218db2661ceSRobert Watson 22193f1a7a90SRobert Watson if (lomac_subject_privileged(subj)) 2220db2661ceSRobert Watson return (EPERM); 2221db2661ceSRobert Watson } 2222db2661ceSRobert Watson 2223db2661ceSRobert Watson return (0); 2224db2661ceSRobert Watson } 2225db2661ceSRobert Watson 2226eb320b0eSRobert Watson static void 2227eb320b0eSRobert Watson lomac_thread_userret(struct thread *td) 2228eb320b0eSRobert Watson { 2229eb320b0eSRobert Watson struct proc *p = td->td_proc; 2230eb320b0eSRobert Watson struct mac_lomac_proc *subj = PSLOT(p->p_label); 2231eb320b0eSRobert Watson struct ucred *newcred, *oldcred; 2232eb320b0eSRobert Watson int dodrop; 2233eb320b0eSRobert Watson 2234eb320b0eSRobert Watson mtx_lock(&subj->mtx); 2235eb320b0eSRobert Watson if (subj->mac_lomac.ml_flags & MAC_LOMAC_FLAG_UPDATE) { 2236eb320b0eSRobert Watson dodrop = 0; 2237eb320b0eSRobert Watson mtx_unlock(&subj->mtx); 2238eb320b0eSRobert Watson newcred = crget(); 2239eb320b0eSRobert Watson /* 22409215889dSRobert Watson * Prevent a lock order reversal in mac_proc_vm_revoke; 22419215889dSRobert Watson * ideally, the other user of subj->mtx wouldn't be holding 22429215889dSRobert Watson * Giant. 2243eb320b0eSRobert Watson */ 2244eb320b0eSRobert Watson mtx_lock(&Giant); 2245eb320b0eSRobert Watson PROC_LOCK(p); 2246eb320b0eSRobert Watson mtx_lock(&subj->mtx); 2247eb320b0eSRobert Watson /* 2248eb320b0eSRobert Watson * Check if we lost the race while allocating the cred. 2249eb320b0eSRobert Watson */ 2250eb320b0eSRobert Watson if ((subj->mac_lomac.ml_flags & MAC_LOMAC_FLAG_UPDATE) == 0) { 2251eb320b0eSRobert Watson crfree(newcred); 2252eb320b0eSRobert Watson goto out; 2253eb320b0eSRobert Watson } 2254eb320b0eSRobert Watson oldcred = p->p_ucred; 2255eb320b0eSRobert Watson crcopy(newcred, oldcred); 2256eb320b0eSRobert Watson crhold(newcred); 2257eb320b0eSRobert Watson lomac_copy(&subj->mac_lomac, SLOT(newcred->cr_label)); 2258eb320b0eSRobert Watson p->p_ucred = newcred; 2259eb320b0eSRobert Watson crfree(oldcred); 2260eb320b0eSRobert Watson dodrop = 1; 2261eb320b0eSRobert Watson out: 2262eb320b0eSRobert Watson mtx_unlock(&subj->mtx); 2263eb320b0eSRobert Watson PROC_UNLOCK(p); 2264eb320b0eSRobert Watson if (dodrop) 22659215889dSRobert Watson mac_proc_vm_revoke(curthread); 2266eb320b0eSRobert Watson mtx_unlock(&Giant); 2267eb320b0eSRobert Watson } else { 2268eb320b0eSRobert Watson mtx_unlock(&subj->mtx); 2269eb320b0eSRobert Watson } 2270eb320b0eSRobert Watson } 2271eb320b0eSRobert Watson 2272eb320b0eSRobert Watson static int 2273eb320b0eSRobert Watson lomac_vnode_associate_extattr(struct mount *mp, struct label *mplabel, 2274eb320b0eSRobert Watson struct vnode *vp, struct label *vplabel) 2275eb320b0eSRobert Watson { 2276eb320b0eSRobert Watson struct mac_lomac ml_temp, *source, *dest; 2277eb320b0eSRobert Watson int buflen, error; 2278eb320b0eSRobert Watson 2279eb320b0eSRobert Watson source = SLOT(mplabel); 2280eb320b0eSRobert Watson dest = SLOT(vplabel); 2281eb320b0eSRobert Watson 2282eb320b0eSRobert Watson buflen = sizeof(ml_temp); 2283eb320b0eSRobert Watson bzero(&ml_temp, buflen); 2284eb320b0eSRobert Watson 2285eb320b0eSRobert Watson error = vn_extattr_get(vp, IO_NODELOCKED, MAC_LOMAC_EXTATTR_NAMESPACE, 2286eb320b0eSRobert Watson MAC_LOMAC_EXTATTR_NAME, &buflen, (char *)&ml_temp, curthread); 2287eb320b0eSRobert Watson if (error == ENOATTR || error == EOPNOTSUPP) { 2288eb320b0eSRobert Watson /* Fall back to the mntlabel. */ 2289eb320b0eSRobert Watson lomac_copy_single(source, dest); 2290eb320b0eSRobert Watson return (0); 2291eb320b0eSRobert Watson } else if (error) 2292eb320b0eSRobert Watson return (error); 2293eb320b0eSRobert Watson 2294eb320b0eSRobert Watson if (buflen != sizeof(ml_temp)) { 2295eb320b0eSRobert Watson if (buflen != sizeof(ml_temp) - sizeof(ml_temp.ml_auxsingle)) { 2296eb320b0eSRobert Watson printf("lomac_vnode_associate_extattr: bad size %d\n", 2297eb320b0eSRobert Watson buflen); 2298eb320b0eSRobert Watson return (EPERM); 2299eb320b0eSRobert Watson } 2300eb320b0eSRobert Watson bzero(&ml_temp.ml_auxsingle, sizeof(ml_temp.ml_auxsingle)); 2301eb320b0eSRobert Watson buflen = sizeof(ml_temp); 2302eb320b0eSRobert Watson (void)vn_extattr_set(vp, IO_NODELOCKED, 2303eb320b0eSRobert Watson MAC_LOMAC_EXTATTR_NAMESPACE, MAC_LOMAC_EXTATTR_NAME, 2304eb320b0eSRobert Watson buflen, (char *)&ml_temp, curthread); 2305eb320b0eSRobert Watson } 2306eb320b0eSRobert Watson if (lomac_valid(&ml_temp) != 0) { 2307eb320b0eSRobert Watson printf("lomac_vnode_associate_extattr: invalid\n"); 2308eb320b0eSRobert Watson return (EPERM); 2309eb320b0eSRobert Watson } 2310eb320b0eSRobert Watson if ((ml_temp.ml_flags & MAC_LOMAC_FLAGS_BOTH) != 2311eb320b0eSRobert Watson MAC_LOMAC_FLAG_SINGLE) { 2312eb320b0eSRobert Watson printf("lomac_vnode_associate_extattr: not single\n"); 2313eb320b0eSRobert Watson return (EPERM); 2314eb320b0eSRobert Watson } 2315eb320b0eSRobert Watson 2316eb320b0eSRobert Watson lomac_copy_single(&ml_temp, dest); 2317eb320b0eSRobert Watson return (0); 2318eb320b0eSRobert Watson } 2319eb320b0eSRobert Watson 2320eb320b0eSRobert Watson static void 2321eb320b0eSRobert Watson lomac_vnode_associate_singlelabel(struct mount *mp, struct label *mplabel, 2322eb320b0eSRobert Watson struct vnode *vp, struct label *vplabel) 2323eb320b0eSRobert Watson { 2324eb320b0eSRobert Watson struct mac_lomac *source, *dest; 2325eb320b0eSRobert Watson 2326eb320b0eSRobert Watson source = SLOT(mplabel); 2327eb320b0eSRobert Watson dest = SLOT(vplabel); 2328eb320b0eSRobert Watson 2329eb320b0eSRobert Watson lomac_copy_single(source, dest); 2330eb320b0eSRobert Watson } 2331eb320b0eSRobert Watson 2332db2661ceSRobert Watson static int 23333f1a7a90SRobert Watson lomac_vnode_check_create(struct ucred *cred, struct vnode *dvp, 233478007886SRobert Watson struct label *dvplabel, struct componentname *cnp, struct vattr *vap) 2335db2661ceSRobert Watson { 2336db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2337db2661ceSRobert Watson 23383f1a7a90SRobert Watson if (!lomac_enabled) 2339db2661ceSRobert Watson return (0); 2340db2661ceSRobert Watson 2341eca8a663SRobert Watson subj = SLOT(cred->cr_label); 234278007886SRobert Watson obj = SLOT(dvplabel); 2343db2661ceSRobert Watson 23443f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2345db2661ceSRobert Watson return (EACCES); 2346db2661ceSRobert Watson if (obj->ml_flags & MAC_LOMAC_FLAG_AUX && 23473f1a7a90SRobert Watson !lomac_dominate_element(&subj->ml_single, &obj->ml_auxsingle)) 2348db2661ceSRobert Watson return (EACCES); 2349db2661ceSRobert Watson 2350db2661ceSRobert Watson return (0); 2351db2661ceSRobert Watson } 2352db2661ceSRobert Watson 2353db2661ceSRobert Watson static int 23543f1a7a90SRobert Watson lomac_vnode_check_deleteacl(struct ucred *cred, struct vnode *vp, 235578007886SRobert Watson struct label *vplabel, acl_type_t type) 2356db2661ceSRobert Watson { 2357db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2358db2661ceSRobert Watson 23593f1a7a90SRobert Watson if (!lomac_enabled) 2360db2661ceSRobert Watson return (0); 2361db2661ceSRobert Watson 2362eca8a663SRobert Watson subj = SLOT(cred->cr_label); 236378007886SRobert Watson obj = SLOT(vplabel); 2364db2661ceSRobert Watson 23653f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2366db2661ceSRobert Watson return (EACCES); 2367db2661ceSRobert Watson 2368db2661ceSRobert Watson return (0); 2369db2661ceSRobert Watson } 2370db2661ceSRobert Watson 2371db2661ceSRobert Watson static int 23723f1a7a90SRobert Watson lomac_vnode_check_link(struct ucred *cred, struct vnode *dvp, 237378007886SRobert Watson struct label *dvplabel, struct vnode *vp, struct label *vplabel, 2374db2661ceSRobert Watson struct componentname *cnp) 2375db2661ceSRobert Watson { 2376db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2377db2661ceSRobert Watson 23783f1a7a90SRobert Watson if (!lomac_enabled) 2379db2661ceSRobert Watson return (0); 2380db2661ceSRobert Watson 2381eca8a663SRobert Watson subj = SLOT(cred->cr_label); 238278007886SRobert Watson obj = SLOT(dvplabel); 2383db2661ceSRobert Watson 23843f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2385db2661ceSRobert Watson return (EACCES); 2386db2661ceSRobert Watson 238778007886SRobert Watson obj = SLOT(vplabel); 2388db2661ceSRobert Watson 23893f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2390db2661ceSRobert Watson return (EACCES); 2391db2661ceSRobert Watson 2392db2661ceSRobert Watson return (0); 2393db2661ceSRobert Watson } 2394db2661ceSRobert Watson 2395db2661ceSRobert Watson static int 23963f1a7a90SRobert Watson lomac_vnode_check_mmap(struct ucred *cred, struct vnode *vp, 239778007886SRobert Watson struct label *vplabel, int prot, int flags) 2398db2661ceSRobert Watson { 2399db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2400db2661ceSRobert Watson 2401db2661ceSRobert Watson /* 2402db2661ceSRobert Watson * Rely on the use of open()-time protections to handle 2403db2661ceSRobert Watson * non-revocation cases. 2404db2661ceSRobert Watson */ 24053f1a7a90SRobert Watson if (!lomac_enabled) 2406db2661ceSRobert Watson return (0); 2407db2661ceSRobert Watson 2408eca8a663SRobert Watson subj = SLOT(cred->cr_label); 240978007886SRobert Watson obj = SLOT(vplabel); 2410db2661ceSRobert Watson 2411c92163dcSChristian S.J. Peron if (((prot & VM_PROT_WRITE) != 0) && ((flags & MAP_SHARED) != 0)) { 24123f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2413db2661ceSRobert Watson return (EACCES); 2414db2661ceSRobert Watson } 2415db2661ceSRobert Watson if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) { 24163f1a7a90SRobert Watson if (!lomac_dominate_single(obj, subj)) 2417db2661ceSRobert Watson return (maybe_demote(subj, obj, "mapping", "file", vp)); 2418db2661ceSRobert Watson } 2419db2661ceSRobert Watson 2420db2661ceSRobert Watson return (0); 2421db2661ceSRobert Watson } 2422db2661ceSRobert Watson 2423db2661ceSRobert Watson static void 24243f1a7a90SRobert Watson lomac_vnode_check_mmap_downgrade(struct ucred *cred, struct vnode *vp, 242578007886SRobert Watson struct label *vplabel, /* XXX vm_prot_t */ int *prot) 2426db2661ceSRobert Watson { 2427db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2428db2661ceSRobert Watson 2429db2661ceSRobert Watson /* 2430db2661ceSRobert Watson * Rely on the use of open()-time protections to handle 2431db2661ceSRobert Watson * non-revocation cases. 2432db2661ceSRobert Watson */ 24333f1a7a90SRobert Watson if (!lomac_enabled || !revocation_enabled) 2434db2661ceSRobert Watson return; 2435db2661ceSRobert Watson 2436eca8a663SRobert Watson subj = SLOT(cred->cr_label); 243778007886SRobert Watson obj = SLOT(vplabel); 2438db2661ceSRobert Watson 24393f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2440db2661ceSRobert Watson *prot &= ~VM_PROT_WRITE; 2441db2661ceSRobert Watson } 2442db2661ceSRobert Watson 2443db2661ceSRobert Watson static int 24443f1a7a90SRobert Watson lomac_vnode_check_open(struct ucred *cred, struct vnode *vp, 244515bc6b2bSEdward Tomasz Napierala struct label *vplabel, accmode_t accmode) 2446db2661ceSRobert Watson { 2447db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2448db2661ceSRobert Watson 24493f1a7a90SRobert Watson if (!lomac_enabled) 2450db2661ceSRobert Watson return (0); 2451db2661ceSRobert Watson 2452eca8a663SRobert Watson subj = SLOT(cred->cr_label); 245378007886SRobert Watson obj = SLOT(vplabel); 2454db2661ceSRobert Watson 2455db2661ceSRobert Watson /* XXX privilege override for admin? */ 24563a597bfcSEdward Tomasz Napierala if (accmode & VMODIFY_PERMS) { 24573f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2458db2661ceSRobert Watson return (EACCES); 2459db2661ceSRobert Watson } 2460db2661ceSRobert Watson 2461db2661ceSRobert Watson return (0); 2462db2661ceSRobert Watson } 2463db2661ceSRobert Watson 2464db2661ceSRobert Watson static int 24653f1a7a90SRobert Watson lomac_vnode_check_read(struct ucred *active_cred, struct ucred *file_cred, 246678007886SRobert Watson struct vnode *vp, struct label *vplabel) 2467db2661ceSRobert Watson { 2468db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2469db2661ceSRobert Watson 24703f1a7a90SRobert Watson if (!lomac_enabled || !revocation_enabled) 2471db2661ceSRobert Watson return (0); 2472db2661ceSRobert Watson 2473eca8a663SRobert Watson subj = SLOT(active_cred->cr_label); 247478007886SRobert Watson obj = SLOT(vplabel); 2475db2661ceSRobert Watson 24763f1a7a90SRobert Watson if (!lomac_dominate_single(obj, subj)) 2477db2661ceSRobert Watson return (maybe_demote(subj, obj, "reading", "file", vp)); 2478db2661ceSRobert Watson 2479db2661ceSRobert Watson return (0); 2480db2661ceSRobert Watson } 2481db2661ceSRobert Watson 2482db2661ceSRobert Watson static int 24833f1a7a90SRobert Watson lomac_vnode_check_relabel(struct ucred *cred, struct vnode *vp, 248478007886SRobert Watson struct label *vplabel, struct label *newlabel) 2485db2661ceSRobert Watson { 2486db2661ceSRobert Watson struct mac_lomac *old, *new, *subj; 2487db2661ceSRobert Watson int error; 2488db2661ceSRobert Watson 248978007886SRobert Watson old = SLOT(vplabel); 2490db2661ceSRobert Watson new = SLOT(newlabel); 2491eca8a663SRobert Watson subj = SLOT(cred->cr_label); 2492db2661ceSRobert Watson 2493db2661ceSRobert Watson /* 2494db2661ceSRobert Watson * If there is a LOMAC label update for the vnode, it must be a 2495db2661ceSRobert Watson * single label, with an optional explicit auxiliary single. 2496db2661ceSRobert Watson */ 2497db2661ceSRobert Watson error = lomac_atmostflags(new, 2498db2661ceSRobert Watson MAC_LOMAC_FLAG_SINGLE | MAC_LOMAC_FLAG_AUX); 2499db2661ceSRobert Watson if (error) 2500db2661ceSRobert Watson return (error); 2501db2661ceSRobert Watson 2502db2661ceSRobert Watson /* 2503db2661ceSRobert Watson * To perform a relabel of the vnode (LOMAC label or not), LOMAC must 2504db2661ceSRobert Watson * authorize the relabel. 2505db2661ceSRobert Watson */ 25063f1a7a90SRobert Watson if (!lomac_single_in_range(old, subj)) 2507db2661ceSRobert Watson return (EPERM); 2508db2661ceSRobert Watson 2509db2661ceSRobert Watson /* 2510db2661ceSRobert Watson * If the LOMAC label is to be changed, authorize as appropriate. 2511db2661ceSRobert Watson */ 2512db2661ceSRobert Watson if (new->ml_flags & MAC_LOMAC_FLAG_SINGLE) { 2513db2661ceSRobert Watson /* 2514db2661ceSRobert Watson * To change the LOMAC label on a vnode, the new vnode label 2515db2661ceSRobert Watson * must be in the subject range. 2516db2661ceSRobert Watson */ 25173f1a7a90SRobert Watson if (!lomac_single_in_range(new, subj)) 2518db2661ceSRobert Watson return (EPERM); 2519db2661ceSRobert Watson 2520db2661ceSRobert Watson /* 25213f1a7a90SRobert Watson * To change the LOMAC label on the vnode to be EQUAL, the 25223f1a7a90SRobert Watson * subject must have appropriate privilege. 2523db2661ceSRobert Watson */ 25243f1a7a90SRobert Watson if (lomac_contains_equal(new)) { 25253f1a7a90SRobert Watson error = lomac_subject_privileged(subj); 2526db2661ceSRobert Watson if (error) 2527db2661ceSRobert Watson return (error); 2528db2661ceSRobert Watson } 2529db2661ceSRobert Watson } 2530db2661ceSRobert Watson if (new->ml_flags & MAC_LOMAC_FLAG_AUX) { 2531db2661ceSRobert Watson /* 253284bdb083SRobert Watson * Fill in the missing parts from the previous label. 253384bdb083SRobert Watson */ 253484bdb083SRobert Watson if ((new->ml_flags & MAC_LOMAC_FLAG_SINGLE) == 0) 25353f1a7a90SRobert Watson lomac_copy_single(subj, new); 253684bdb083SRobert Watson 253784bdb083SRobert Watson /* 2538db2661ceSRobert Watson * To change the auxiliary LOMAC label on a vnode, the new 2539db2661ceSRobert Watson * vnode label must be in the subject range. 2540db2661ceSRobert Watson */ 25413f1a7a90SRobert Watson if (!lomac_auxsingle_in_range(new, subj)) 2542db2661ceSRobert Watson return (EPERM); 2543db2661ceSRobert Watson 2544db2661ceSRobert Watson /* 2545db2661ceSRobert Watson * To change the auxiliary LOMAC label on the vnode to be 2546db2661ceSRobert Watson * EQUAL, the subject must have appropriate privilege. 2547db2661ceSRobert Watson */ 25483f1a7a90SRobert Watson if (lomac_contains_equal(new)) { 25493f1a7a90SRobert Watson error = lomac_subject_privileged(subj); 2550db2661ceSRobert Watson if (error) 2551db2661ceSRobert Watson return (error); 2552db2661ceSRobert Watson } 2553db2661ceSRobert Watson } 2554db2661ceSRobert Watson 2555db2661ceSRobert Watson return (0); 2556db2661ceSRobert Watson } 2557db2661ceSRobert Watson 2558db2661ceSRobert Watson static int 25593f1a7a90SRobert Watson lomac_vnode_check_rename_from(struct ucred *cred, struct vnode *dvp, 256078007886SRobert Watson struct label *dvplabel, struct vnode *vp, struct label *vplabel, 2561db2661ceSRobert Watson struct componentname *cnp) 2562db2661ceSRobert Watson { 2563db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2564db2661ceSRobert Watson 25653f1a7a90SRobert Watson if (!lomac_enabled) 2566db2661ceSRobert Watson return (0); 2567db2661ceSRobert Watson 2568eca8a663SRobert Watson subj = SLOT(cred->cr_label); 256978007886SRobert Watson obj = SLOT(dvplabel); 2570db2661ceSRobert Watson 25713f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2572db2661ceSRobert Watson return (EACCES); 2573db2661ceSRobert Watson 257478007886SRobert Watson obj = SLOT(vplabel); 2575db2661ceSRobert Watson 25763f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2577db2661ceSRobert Watson return (EACCES); 2578db2661ceSRobert Watson 2579db2661ceSRobert Watson return (0); 2580db2661ceSRobert Watson } 2581db2661ceSRobert Watson 2582db2661ceSRobert Watson static int 25833f1a7a90SRobert Watson lomac_vnode_check_rename_to(struct ucred *cred, struct vnode *dvp, 258478007886SRobert Watson struct label *dvplabel, struct vnode *vp, struct label *vplabel, 258578007886SRobert Watson int samedir, struct componentname *cnp) 2586db2661ceSRobert Watson { 2587db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2588db2661ceSRobert Watson 25893f1a7a90SRobert Watson if (!lomac_enabled) 2590db2661ceSRobert Watson return (0); 2591db2661ceSRobert Watson 2592eca8a663SRobert Watson subj = SLOT(cred->cr_label); 259378007886SRobert Watson obj = SLOT(dvplabel); 2594db2661ceSRobert Watson 25953f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2596db2661ceSRobert Watson return (EACCES); 2597db2661ceSRobert Watson 2598db2661ceSRobert Watson if (vp != NULL) { 259978007886SRobert Watson obj = SLOT(vplabel); 2600db2661ceSRobert Watson 26013f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2602db2661ceSRobert Watson return (EACCES); 2603db2661ceSRobert Watson } 2604db2661ceSRobert Watson 2605db2661ceSRobert Watson return (0); 2606db2661ceSRobert Watson } 2607db2661ceSRobert Watson 2608db2661ceSRobert Watson static int 26093f1a7a90SRobert Watson lomac_vnode_check_revoke(struct ucred *cred, struct vnode *vp, 261078007886SRobert Watson struct label *vplabel) 2611db2661ceSRobert Watson { 2612db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2613db2661ceSRobert Watson 26143f1a7a90SRobert Watson if (!lomac_enabled) 2615db2661ceSRobert Watson return (0); 2616db2661ceSRobert Watson 2617eca8a663SRobert Watson subj = SLOT(cred->cr_label); 261878007886SRobert Watson obj = SLOT(vplabel); 2619db2661ceSRobert Watson 26203f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2621db2661ceSRobert Watson return (EACCES); 2622db2661ceSRobert Watson 2623db2661ceSRobert Watson return (0); 2624db2661ceSRobert Watson } 2625db2661ceSRobert Watson 2626db2661ceSRobert Watson static int 26273f1a7a90SRobert Watson lomac_vnode_check_setacl(struct ucred *cred, struct vnode *vp, 262878007886SRobert Watson struct label *vplabel, acl_type_t type, struct acl *acl) 2629db2661ceSRobert Watson { 2630db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2631db2661ceSRobert Watson 26323f1a7a90SRobert Watson if (!lomac_enabled) 2633db2661ceSRobert Watson return (0); 2634db2661ceSRobert Watson 2635eca8a663SRobert Watson subj = SLOT(cred->cr_label); 263678007886SRobert Watson obj = SLOT(vplabel); 2637db2661ceSRobert Watson 26383f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2639db2661ceSRobert Watson return (EACCES); 2640db2661ceSRobert Watson 2641db2661ceSRobert Watson return (0); 2642db2661ceSRobert Watson } 2643db2661ceSRobert Watson 2644db2661ceSRobert Watson static int 26453f1a7a90SRobert Watson lomac_vnode_check_setextattr(struct ucred *cred, struct vnode *vp, 2646fefd0ac8SRobert Watson struct label *vplabel, int attrnamespace, const char *name) 2647db2661ceSRobert Watson { 2648db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2649db2661ceSRobert Watson 26503f1a7a90SRobert Watson if (!lomac_enabled) 2651db2661ceSRobert Watson return (0); 2652db2661ceSRobert Watson 2653eca8a663SRobert Watson subj = SLOT(cred->cr_label); 265478007886SRobert Watson obj = SLOT(vplabel); 2655db2661ceSRobert Watson 26563f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2657db2661ceSRobert Watson return (EACCES); 2658db2661ceSRobert Watson 2659db2661ceSRobert Watson /* XXX: protect the MAC EA in a special way? */ 2660db2661ceSRobert Watson 2661db2661ceSRobert Watson return (0); 2662db2661ceSRobert Watson } 2663db2661ceSRobert Watson 2664db2661ceSRobert Watson static int 26653f1a7a90SRobert Watson lomac_vnode_check_setflags(struct ucred *cred, struct vnode *vp, 266678007886SRobert Watson struct label *vplabel, u_long flags) 2667db2661ceSRobert Watson { 2668db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2669db2661ceSRobert Watson 26703f1a7a90SRobert Watson if (!lomac_enabled) 2671db2661ceSRobert Watson return (0); 2672db2661ceSRobert Watson 2673eca8a663SRobert Watson subj = SLOT(cred->cr_label); 267478007886SRobert Watson obj = SLOT(vplabel); 2675db2661ceSRobert Watson 26763f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2677db2661ceSRobert Watson return (EACCES); 2678db2661ceSRobert Watson 2679db2661ceSRobert Watson return (0); 2680db2661ceSRobert Watson } 2681db2661ceSRobert Watson 2682db2661ceSRobert Watson static int 26833f1a7a90SRobert Watson lomac_vnode_check_setmode(struct ucred *cred, struct vnode *vp, 268478007886SRobert Watson struct label *vplabel, mode_t mode) 2685db2661ceSRobert Watson { 2686db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2687db2661ceSRobert Watson 26883f1a7a90SRobert Watson if (!lomac_enabled) 2689db2661ceSRobert Watson return (0); 2690db2661ceSRobert Watson 2691eca8a663SRobert Watson subj = SLOT(cred->cr_label); 269278007886SRobert Watson obj = SLOT(vplabel); 2693db2661ceSRobert Watson 26943f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2695db2661ceSRobert Watson return (EACCES); 2696db2661ceSRobert Watson 2697db2661ceSRobert Watson return (0); 2698db2661ceSRobert Watson } 2699db2661ceSRobert Watson 2700db2661ceSRobert Watson static int 27013f1a7a90SRobert Watson lomac_vnode_check_setowner(struct ucred *cred, struct vnode *vp, 270278007886SRobert Watson struct label *vplabel, uid_t uid, gid_t gid) 2703db2661ceSRobert Watson { 2704db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2705db2661ceSRobert Watson 27063f1a7a90SRobert Watson if (!lomac_enabled) 2707db2661ceSRobert Watson return (0); 2708db2661ceSRobert Watson 2709eca8a663SRobert Watson subj = SLOT(cred->cr_label); 271078007886SRobert Watson obj = SLOT(vplabel); 2711db2661ceSRobert Watson 27123f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2713db2661ceSRobert Watson return (EACCES); 2714db2661ceSRobert Watson 2715db2661ceSRobert Watson return (0); 2716db2661ceSRobert Watson } 2717db2661ceSRobert Watson 2718db2661ceSRobert Watson static int 27193f1a7a90SRobert Watson lomac_vnode_check_setutimes(struct ucred *cred, struct vnode *vp, 272078007886SRobert Watson struct label *vplabel, struct timespec atime, struct timespec mtime) 2721db2661ceSRobert Watson { 2722db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2723db2661ceSRobert Watson 27243f1a7a90SRobert Watson if (!lomac_enabled) 2725db2661ceSRobert Watson return (0); 2726db2661ceSRobert Watson 2727eca8a663SRobert Watson subj = SLOT(cred->cr_label); 272878007886SRobert Watson obj = SLOT(vplabel); 2729db2661ceSRobert Watson 27303f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2731db2661ceSRobert Watson return (EACCES); 2732db2661ceSRobert Watson 2733db2661ceSRobert Watson return (0); 2734db2661ceSRobert Watson } 2735db2661ceSRobert Watson 2736db2661ceSRobert Watson static int 27373f1a7a90SRobert Watson lomac_vnode_check_unlink(struct ucred *cred, struct vnode *dvp, 273845e0f3d6SRobert Watson struct label *dvplabel, struct vnode *vp, struct label *vplabel, 273945e0f3d6SRobert Watson struct componentname *cnp) 274045e0f3d6SRobert Watson { 274145e0f3d6SRobert Watson struct mac_lomac *subj, *obj; 274245e0f3d6SRobert Watson 27433f1a7a90SRobert Watson if (!lomac_enabled) 274445e0f3d6SRobert Watson return (0); 274545e0f3d6SRobert Watson 274645e0f3d6SRobert Watson subj = SLOT(cred->cr_label); 274745e0f3d6SRobert Watson obj = SLOT(dvplabel); 274845e0f3d6SRobert Watson 27493f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 275045e0f3d6SRobert Watson return (EACCES); 275145e0f3d6SRobert Watson 275245e0f3d6SRobert Watson obj = SLOT(vplabel); 275345e0f3d6SRobert Watson 27543f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 275545e0f3d6SRobert Watson return (EACCES); 275645e0f3d6SRobert Watson 275745e0f3d6SRobert Watson return (0); 275845e0f3d6SRobert Watson } 275945e0f3d6SRobert Watson 276045e0f3d6SRobert Watson static int 27613f1a7a90SRobert Watson lomac_vnode_check_write(struct ucred *active_cred, 276278007886SRobert Watson struct ucred *file_cred, struct vnode *vp, struct label *vplabel) 2763db2661ceSRobert Watson { 2764db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2765db2661ceSRobert Watson 27663f1a7a90SRobert Watson if (!lomac_enabled || !revocation_enabled) 2767db2661ceSRobert Watson return (0); 2768db2661ceSRobert Watson 2769eca8a663SRobert Watson subj = SLOT(active_cred->cr_label); 277078007886SRobert Watson obj = SLOT(vplabel); 2771db2661ceSRobert Watson 27723f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2773db2661ceSRobert Watson return (EACCES); 2774db2661ceSRobert Watson 2775db2661ceSRobert Watson return (0); 2776db2661ceSRobert Watson } 2777db2661ceSRobert Watson 2778eb320b0eSRobert Watson static int 2779eb320b0eSRobert Watson lomac_vnode_create_extattr(struct ucred *cred, struct mount *mp, 2780eb320b0eSRobert Watson struct label *mplabel, struct vnode *dvp, struct label *dvplabel, 2781eb320b0eSRobert Watson struct vnode *vp, struct label *vplabel, struct componentname *cnp) 2782db2661ceSRobert Watson { 2783eb320b0eSRobert Watson struct mac_lomac *source, *dest, *dir, temp; 2784eb320b0eSRobert Watson size_t buflen; 2785eb320b0eSRobert Watson int error; 2786db2661ceSRobert Watson 2787eb320b0eSRobert Watson buflen = sizeof(temp); 2788eb320b0eSRobert Watson bzero(&temp, buflen); 2789eb320b0eSRobert Watson 2790eb320b0eSRobert Watson source = SLOT(cred->cr_label); 2791eb320b0eSRobert Watson dest = SLOT(vplabel); 2792eb320b0eSRobert Watson dir = SLOT(dvplabel); 2793eb320b0eSRobert Watson if (dir->ml_flags & MAC_LOMAC_FLAG_AUX) { 2794eb320b0eSRobert Watson lomac_copy_auxsingle(dir, &temp); 2795eb320b0eSRobert Watson lomac_set_single(&temp, dir->ml_auxsingle.mle_type, 2796eb320b0eSRobert Watson dir->ml_auxsingle.mle_grade); 2797db2661ceSRobert Watson } else { 2798eb320b0eSRobert Watson lomac_copy_single(source, &temp); 2799db2661ceSRobert Watson } 2800eb320b0eSRobert Watson 2801eb320b0eSRobert Watson error = vn_extattr_set(vp, IO_NODELOCKED, MAC_LOMAC_EXTATTR_NAMESPACE, 2802eb320b0eSRobert Watson MAC_LOMAC_EXTATTR_NAME, buflen, (char *)&temp, curthread); 2803eb320b0eSRobert Watson if (error == 0) 2804eb320b0eSRobert Watson lomac_copy(&temp, dest); 2805eb320b0eSRobert Watson return (error); 2806eb320b0eSRobert Watson } 2807eb320b0eSRobert Watson 2808eb320b0eSRobert Watson static void 2809eb320b0eSRobert Watson lomac_vnode_execve_transition(struct ucred *old, struct ucred *new, 2810eb320b0eSRobert Watson struct vnode *vp, struct label *vplabel, struct label *interpvplabel, 2811eb320b0eSRobert Watson struct image_params *imgp, struct label *execlabel) 2812eb320b0eSRobert Watson { 2813eb320b0eSRobert Watson struct mac_lomac *source, *dest, *obj, *robj; 2814eb320b0eSRobert Watson 2815eb320b0eSRobert Watson source = SLOT(old->cr_label); 2816eb320b0eSRobert Watson dest = SLOT(new->cr_label); 2817eb320b0eSRobert Watson obj = SLOT(vplabel); 2818eb320b0eSRobert Watson robj = interpvplabel != NULL ? SLOT(interpvplabel) : obj; 2819eb320b0eSRobert Watson 2820eb320b0eSRobert Watson lomac_copy(source, dest); 2821eb320b0eSRobert Watson /* 2822eb320b0eSRobert Watson * If there's an auxiliary label on the real object, respect it and 2823eb320b0eSRobert Watson * assume that this level should be assumed immediately if a higher 2824eb320b0eSRobert Watson * level is currently in place. 2825eb320b0eSRobert Watson */ 2826eb320b0eSRobert Watson if (robj->ml_flags & MAC_LOMAC_FLAG_AUX && 2827eb320b0eSRobert Watson !lomac_dominate_element(&robj->ml_auxsingle, &dest->ml_single) 2828eb320b0eSRobert Watson && lomac_auxsingle_in_range(robj, dest)) 2829eb320b0eSRobert Watson lomac_set_single(dest, robj->ml_auxsingle.mle_type, 2830eb320b0eSRobert Watson robj->ml_auxsingle.mle_grade); 2831eb320b0eSRobert Watson /* 2832eb320b0eSRobert Watson * Restructuring to use the execve transitioning mechanism instead of 2833eb320b0eSRobert Watson * the normal demotion mechanism here would be difficult, so just 2834eb320b0eSRobert Watson * copy the label over and perform standard demotion. This is also 2835eb320b0eSRobert Watson * non-optimal because it will result in the intermediate label "new" 2836eb320b0eSRobert Watson * being created and immediately recycled. 2837eb320b0eSRobert Watson */ 2838eb320b0eSRobert Watson if (lomac_enabled && revocation_enabled && 2839eb320b0eSRobert Watson !lomac_dominate_single(obj, source)) 2840eb320b0eSRobert Watson (void)maybe_demote(source, obj, "executing", "file", vp); 2841eb320b0eSRobert Watson } 2842eb320b0eSRobert Watson 2843eb320b0eSRobert Watson static int 2844eb320b0eSRobert Watson lomac_vnode_execve_will_transition(struct ucred *old, struct vnode *vp, 2845eb320b0eSRobert Watson struct label *vplabel, struct label *interpvplabel, 2846eb320b0eSRobert Watson struct image_params *imgp, struct label *execlabel) 2847eb320b0eSRobert Watson { 2848eb320b0eSRobert Watson struct mac_lomac *subj, *obj, *robj; 2849eb320b0eSRobert Watson 2850eb320b0eSRobert Watson if (!lomac_enabled || !revocation_enabled) 2851eb320b0eSRobert Watson return (0); 2852eb320b0eSRobert Watson 2853eb320b0eSRobert Watson subj = SLOT(old->cr_label); 2854eb320b0eSRobert Watson obj = SLOT(vplabel); 2855eb320b0eSRobert Watson robj = interpvplabel != NULL ? SLOT(interpvplabel) : obj; 2856eb320b0eSRobert Watson 2857eb320b0eSRobert Watson return ((robj->ml_flags & MAC_LOMAC_FLAG_AUX && 2858eb320b0eSRobert Watson !lomac_dominate_element(&robj->ml_auxsingle, &subj->ml_single) 2859eb320b0eSRobert Watson && lomac_auxsingle_in_range(robj, subj)) || 2860eb320b0eSRobert Watson !lomac_dominate_single(obj, subj)); 2861eb320b0eSRobert Watson } 2862eb320b0eSRobert Watson 2863eb320b0eSRobert Watson static void 2864eb320b0eSRobert Watson lomac_vnode_relabel(struct ucred *cred, struct vnode *vp, 2865eb320b0eSRobert Watson struct label *vplabel, struct label *newlabel) 2866eb320b0eSRobert Watson { 2867eb320b0eSRobert Watson struct mac_lomac *source, *dest; 2868eb320b0eSRobert Watson 2869eb320b0eSRobert Watson source = SLOT(newlabel); 2870eb320b0eSRobert Watson dest = SLOT(vplabel); 2871eb320b0eSRobert Watson 2872eb320b0eSRobert Watson try_relabel(source, dest); 2873eb320b0eSRobert Watson } 2874eb320b0eSRobert Watson 2875eb320b0eSRobert Watson static int 2876eb320b0eSRobert Watson lomac_vnode_setlabel_extattr(struct ucred *cred, struct vnode *vp, 2877eb320b0eSRobert Watson struct label *vplabel, struct label *intlabel) 2878eb320b0eSRobert Watson { 2879eb320b0eSRobert Watson struct mac_lomac *source, temp; 2880eb320b0eSRobert Watson size_t buflen; 2881eb320b0eSRobert Watson int error; 2882eb320b0eSRobert Watson 2883eb320b0eSRobert Watson buflen = sizeof(temp); 2884eb320b0eSRobert Watson bzero(&temp, buflen); 2885eb320b0eSRobert Watson 2886eb320b0eSRobert Watson source = SLOT(intlabel); 2887eb320b0eSRobert Watson if ((source->ml_flags & MAC_LOMAC_FLAG_SINGLE) == 0) 2888eb320b0eSRobert Watson return (0); 2889eb320b0eSRobert Watson 2890eb320b0eSRobert Watson lomac_copy_single(source, &temp); 2891eb320b0eSRobert Watson error = vn_extattr_set(vp, IO_NODELOCKED, MAC_LOMAC_EXTATTR_NAMESPACE, 2892eb320b0eSRobert Watson MAC_LOMAC_EXTATTR_NAME, buflen, (char *)&temp, curthread); 2893eb320b0eSRobert Watson return (error); 2894db2661ceSRobert Watson } 2895db2661ceSRobert Watson 28963f1a7a90SRobert Watson static struct mac_policy_ops lomac_ops = 2897db2661ceSRobert Watson { 28983f1a7a90SRobert Watson .mpo_init = lomac_init, 2899eb320b0eSRobert Watson 2900eb320b0eSRobert Watson .mpo_bpfdesc_check_receive = lomac_bpfdesc_check_receive, 2901eb320b0eSRobert Watson .mpo_bpfdesc_create = lomac_bpfdesc_create, 2902eb320b0eSRobert Watson .mpo_bpfdesc_create_mbuf = lomac_bpfdesc_create_mbuf, 29033f1a7a90SRobert Watson .mpo_bpfdesc_destroy_label = lomac_destroy_label, 2904eb320b0eSRobert Watson .mpo_bpfdesc_init_label = lomac_init_label, 2905eb320b0eSRobert Watson 2906eb320b0eSRobert Watson .mpo_cred_check_relabel = lomac_cred_check_relabel, 2907eb320b0eSRobert Watson .mpo_cred_check_visible = lomac_cred_check_visible, 29083f1a7a90SRobert Watson .mpo_cred_copy_label = lomac_copy_label, 2909212ab0cfSRobert Watson .mpo_cred_create_swapper = lomac_cred_create_swapper, 2910212ab0cfSRobert Watson .mpo_cred_create_init = lomac_cred_create_init, 2911eb320b0eSRobert Watson .mpo_cred_destroy_label = lomac_destroy_label, 29123f1a7a90SRobert Watson .mpo_cred_externalize_label = lomac_externalize_label, 2913eb320b0eSRobert Watson .mpo_cred_init_label = lomac_init_label, 29143f1a7a90SRobert Watson .mpo_cred_internalize_label = lomac_internalize_label, 2915eb320b0eSRobert Watson .mpo_cred_relabel = lomac_cred_relabel, 2916eb320b0eSRobert Watson 29173f1a7a90SRobert Watson .mpo_devfs_create_device = lomac_devfs_create_device, 29183f1a7a90SRobert Watson .mpo_devfs_create_directory = lomac_devfs_create_directory, 29193f1a7a90SRobert Watson .mpo_devfs_create_symlink = lomac_devfs_create_symlink, 2920eb320b0eSRobert Watson .mpo_devfs_destroy_label = lomac_destroy_label, 2921eb320b0eSRobert Watson .mpo_devfs_init_label = lomac_init_label, 29223f1a7a90SRobert Watson .mpo_devfs_update = lomac_devfs_update, 29233f1a7a90SRobert Watson .mpo_devfs_vnode_associate = lomac_devfs_vnode_associate, 2924eb320b0eSRobert Watson 29253f1a7a90SRobert Watson .mpo_ifnet_check_relabel = lomac_ifnet_check_relabel, 29263f1a7a90SRobert Watson .mpo_ifnet_check_transmit = lomac_ifnet_check_transmit, 2927eb320b0eSRobert Watson .mpo_ifnet_copy_label = lomac_copy_label, 2928eb320b0eSRobert Watson .mpo_ifnet_create = lomac_ifnet_create, 2929eb320b0eSRobert Watson .mpo_ifnet_create_mbuf = lomac_ifnet_create_mbuf, 2930eb320b0eSRobert Watson .mpo_ifnet_destroy_label = lomac_destroy_label, 2931eb320b0eSRobert Watson .mpo_ifnet_externalize_label = lomac_externalize_label, 2932eb320b0eSRobert Watson .mpo_ifnet_init_label = lomac_init_label, 2933eb320b0eSRobert Watson .mpo_ifnet_internalize_label = lomac_internalize_label, 2934eb320b0eSRobert Watson .mpo_ifnet_relabel = lomac_ifnet_relabel, 2935eb320b0eSRobert Watson 2936eb320b0eSRobert Watson .mpo_syncache_create = lomac_syncache_create, 2937eb320b0eSRobert Watson .mpo_syncache_destroy_label = lomac_destroy_label, 2938eb320b0eSRobert Watson .mpo_syncache_init_label = lomac_init_label_waitcheck, 2939eb320b0eSRobert Watson 29403f1a7a90SRobert Watson .mpo_inpcb_check_deliver = lomac_inpcb_check_deliver, 29417fb179baSBjoern A. Zeeb .mpo_inpcb_check_visible = lomac_inpcb_check_visible, 2942eb320b0eSRobert Watson .mpo_inpcb_create = lomac_inpcb_create, 2943eb320b0eSRobert Watson .mpo_inpcb_create_mbuf = lomac_inpcb_create_mbuf, 2944eb320b0eSRobert Watson .mpo_inpcb_destroy_label = lomac_destroy_label, 2945eb320b0eSRobert Watson .mpo_inpcb_init_label = lomac_init_label_waitcheck, 2946eb320b0eSRobert Watson .mpo_inpcb_sosetlabel = lomac_inpcb_sosetlabel, 2947eb320b0eSRobert Watson 2948048e1287SRobert Watson .mpo_ip6q_create = lomac_ip6q_create, 2949048e1287SRobert Watson .mpo_ip6q_destroy_label = lomac_destroy_label, 2950048e1287SRobert Watson .mpo_ip6q_init_label = lomac_init_label_waitcheck, 2951048e1287SRobert Watson .mpo_ip6q_match = lomac_ip6q_match, 2952048e1287SRobert Watson .mpo_ip6q_reassemble = lomac_ip6q_reassemble, 2953048e1287SRobert Watson .mpo_ip6q_update = lomac_ip6q_update, 2954048e1287SRobert Watson 2955eb320b0eSRobert Watson .mpo_ipq_create = lomac_ipq_create, 2956eb320b0eSRobert Watson .mpo_ipq_destroy_label = lomac_destroy_label, 2957eb320b0eSRobert Watson .mpo_ipq_init_label = lomac_init_label_waitcheck, 2958eb320b0eSRobert Watson .mpo_ipq_match = lomac_ipq_match, 2959eb320b0eSRobert Watson .mpo_ipq_reassemble = lomac_ipq_reassemble, 2960eb320b0eSRobert Watson .mpo_ipq_update = lomac_ipq_update, 2961eb320b0eSRobert Watson 29623f1a7a90SRobert Watson .mpo_kld_check_load = lomac_kld_check_load, 2963eb320b0eSRobert Watson 2964eb320b0eSRobert Watson .mpo_mbuf_copy_label = lomac_copy_label, 2965eb320b0eSRobert Watson .mpo_mbuf_destroy_label = lomac_destroy_label, 2966eb320b0eSRobert Watson .mpo_mbuf_init_label = lomac_init_label_waitcheck, 2967eb320b0eSRobert Watson 2968eb320b0eSRobert Watson .mpo_mount_create = lomac_mount_create, 2969eb320b0eSRobert Watson .mpo_mount_destroy_label = lomac_destroy_label, 2970eb320b0eSRobert Watson .mpo_mount_init_label = lomac_init_label, 2971eb320b0eSRobert Watson 2972eb320b0eSRobert Watson .mpo_netinet_arp_send = lomac_netinet_arp_send, 2973eb320b0eSRobert Watson .mpo_netinet_firewall_reply = lomac_netinet_firewall_reply, 2974eb320b0eSRobert Watson .mpo_netinet_firewall_send = lomac_netinet_firewall_send, 2975eb320b0eSRobert Watson .mpo_netinet_fragment = lomac_netinet_fragment, 2976eb320b0eSRobert Watson .mpo_netinet_icmp_reply = lomac_netinet_icmp_reply, 2977eb320b0eSRobert Watson .mpo_netinet_igmp_send = lomac_netinet_igmp_send, 2978eb320b0eSRobert Watson 2979eb320b0eSRobert Watson .mpo_netinet6_nd6_send = lomac_netinet6_nd6_send, 2980eb320b0eSRobert Watson 29813f1a7a90SRobert Watson .mpo_pipe_check_ioctl = lomac_pipe_check_ioctl, 29823f1a7a90SRobert Watson .mpo_pipe_check_read = lomac_pipe_check_read, 29833f1a7a90SRobert Watson .mpo_pipe_check_relabel = lomac_pipe_check_relabel, 29843f1a7a90SRobert Watson .mpo_pipe_check_write = lomac_pipe_check_write, 2985eb320b0eSRobert Watson .mpo_pipe_copy_label = lomac_copy_label, 2986eb320b0eSRobert Watson .mpo_pipe_create = lomac_pipe_create, 2987eb320b0eSRobert Watson .mpo_pipe_destroy_label = lomac_destroy_label, 2988eb320b0eSRobert Watson .mpo_pipe_externalize_label = lomac_externalize_label, 2989eb320b0eSRobert Watson .mpo_pipe_init_label = lomac_init_label, 2990eb320b0eSRobert Watson .mpo_pipe_internalize_label = lomac_internalize_label, 2991eb320b0eSRobert Watson .mpo_pipe_relabel = lomac_pipe_relabel, 2992eb320b0eSRobert Watson 2993eb320b0eSRobert Watson .mpo_priv_check = lomac_priv_check, 2994eb320b0eSRobert Watson 29953f1a7a90SRobert Watson .mpo_proc_check_debug = lomac_proc_check_debug, 29963f1a7a90SRobert Watson .mpo_proc_check_sched = lomac_proc_check_sched, 29973f1a7a90SRobert Watson .mpo_proc_check_signal = lomac_proc_check_signal, 2998eb320b0eSRobert Watson .mpo_proc_destroy_label = lomac_proc_destroy_label, 2999eb320b0eSRobert Watson .mpo_proc_init_label = lomac_proc_init_label, 3000eb320b0eSRobert Watson 30013f1a7a90SRobert Watson .mpo_socket_check_deliver = lomac_socket_check_deliver, 30023f1a7a90SRobert Watson .mpo_socket_check_relabel = lomac_socket_check_relabel, 30033f1a7a90SRobert Watson .mpo_socket_check_visible = lomac_socket_check_visible, 3004eb320b0eSRobert Watson .mpo_socket_copy_label = lomac_copy_label, 3005eb320b0eSRobert Watson .mpo_socket_create = lomac_socket_create, 3006eb320b0eSRobert Watson .mpo_socket_create_mbuf = lomac_socket_create_mbuf, 3007eb320b0eSRobert Watson .mpo_socket_destroy_label = lomac_destroy_label, 3008eb320b0eSRobert Watson .mpo_socket_externalize_label = lomac_externalize_label, 3009eb320b0eSRobert Watson .mpo_socket_init_label = lomac_init_label_waitcheck, 3010eb320b0eSRobert Watson .mpo_socket_internalize_label = lomac_internalize_label, 3011eb320b0eSRobert Watson .mpo_socket_newconn = lomac_socket_newconn, 3012eb320b0eSRobert Watson .mpo_socket_relabel = lomac_socket_relabel, 3013eb320b0eSRobert Watson 3014eb320b0eSRobert Watson .mpo_socketpeer_destroy_label = lomac_destroy_label, 3015eb320b0eSRobert Watson .mpo_socketpeer_externalize_label = lomac_externalize_label, 3016eb320b0eSRobert Watson .mpo_socketpeer_init_label = lomac_init_label_waitcheck, 3017eb320b0eSRobert Watson .mpo_socketpeer_set_from_mbuf = lomac_socketpeer_set_from_mbuf, 3018eb320b0eSRobert Watson .mpo_socketpeer_set_from_socket = lomac_socketpeer_set_from_socket, 3019eb320b0eSRobert Watson 3020eb320b0eSRobert Watson .mpo_syncache_create_mbuf = lomac_syncache_create_mbuf, 3021eb320b0eSRobert Watson 30223f1a7a90SRobert Watson .mpo_system_check_acct = lomac_system_check_acct, 30233f1a7a90SRobert Watson .mpo_system_check_auditctl = lomac_system_check_auditctl, 30243f1a7a90SRobert Watson .mpo_system_check_swapoff = lomac_system_check_swapoff, 30253f1a7a90SRobert Watson .mpo_system_check_swapon = lomac_system_check_swapon, 30263f1a7a90SRobert Watson .mpo_system_check_sysctl = lomac_system_check_sysctl, 3027eb320b0eSRobert Watson 3028eb320b0eSRobert Watson .mpo_thread_userret = lomac_thread_userret, 3029eb320b0eSRobert Watson 3030eb320b0eSRobert Watson .mpo_vnode_associate_extattr = lomac_vnode_associate_extattr, 3031eb320b0eSRobert Watson .mpo_vnode_associate_singlelabel = lomac_vnode_associate_singlelabel, 30323f1a7a90SRobert Watson .mpo_vnode_check_access = lomac_vnode_check_open, 30333f1a7a90SRobert Watson .mpo_vnode_check_create = lomac_vnode_check_create, 30343f1a7a90SRobert Watson .mpo_vnode_check_deleteacl = lomac_vnode_check_deleteacl, 30353f1a7a90SRobert Watson .mpo_vnode_check_link = lomac_vnode_check_link, 30363f1a7a90SRobert Watson .mpo_vnode_check_mmap = lomac_vnode_check_mmap, 30373f1a7a90SRobert Watson .mpo_vnode_check_mmap_downgrade = lomac_vnode_check_mmap_downgrade, 30383f1a7a90SRobert Watson .mpo_vnode_check_open = lomac_vnode_check_open, 30393f1a7a90SRobert Watson .mpo_vnode_check_read = lomac_vnode_check_read, 30403f1a7a90SRobert Watson .mpo_vnode_check_relabel = lomac_vnode_check_relabel, 30413f1a7a90SRobert Watson .mpo_vnode_check_rename_from = lomac_vnode_check_rename_from, 30423f1a7a90SRobert Watson .mpo_vnode_check_rename_to = lomac_vnode_check_rename_to, 30433f1a7a90SRobert Watson .mpo_vnode_check_revoke = lomac_vnode_check_revoke, 30443f1a7a90SRobert Watson .mpo_vnode_check_setacl = lomac_vnode_check_setacl, 30453f1a7a90SRobert Watson .mpo_vnode_check_setextattr = lomac_vnode_check_setextattr, 30463f1a7a90SRobert Watson .mpo_vnode_check_setflags = lomac_vnode_check_setflags, 30473f1a7a90SRobert Watson .mpo_vnode_check_setmode = lomac_vnode_check_setmode, 30483f1a7a90SRobert Watson .mpo_vnode_check_setowner = lomac_vnode_check_setowner, 30493f1a7a90SRobert Watson .mpo_vnode_check_setutimes = lomac_vnode_check_setutimes, 30503f1a7a90SRobert Watson .mpo_vnode_check_unlink = lomac_vnode_check_unlink, 30513f1a7a90SRobert Watson .mpo_vnode_check_write = lomac_vnode_check_write, 3052eb320b0eSRobert Watson .mpo_vnode_copy_label = lomac_copy_label, 3053eb320b0eSRobert Watson .mpo_vnode_create_extattr = lomac_vnode_create_extattr, 3054eb320b0eSRobert Watson .mpo_vnode_destroy_label = lomac_destroy_label, 3055eb320b0eSRobert Watson .mpo_vnode_execve_transition = lomac_vnode_execve_transition, 3056eb320b0eSRobert Watson .mpo_vnode_execve_will_transition = lomac_vnode_execve_will_transition, 3057eb320b0eSRobert Watson .mpo_vnode_externalize_label = lomac_externalize_label, 3058eb320b0eSRobert Watson .mpo_vnode_init_label = lomac_init_label, 3059eb320b0eSRobert Watson .mpo_vnode_internalize_label = lomac_internalize_label, 3060eb320b0eSRobert Watson .mpo_vnode_relabel = lomac_vnode_relabel, 3061eb320b0eSRobert Watson .mpo_vnode_setlabel_extattr = lomac_vnode_setlabel_extattr, 3062db2661ceSRobert Watson }; 3063db2661ceSRobert Watson 30643f1a7a90SRobert Watson MAC_POLICY_SET(&lomac_ops, mac_lomac, "TrustedBSD MAC/LOMAC", 30659162f64bSRobert Watson MPC_LOADTIME_FLAG_NOTLATE, &lomac_slot); 3066