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 96*7029da5cSPawel Biernacki static SYSCTL_NODE(_security_mac, OID_AUTO, lomac, 97*7029da5cSPawel Biernacki CTLFLAG_RW | CTLFLAG_MPSAFE, 0, 98db2661ceSRobert Watson "TrustedBSD mac_lomac policy controls"); 99db2661ceSRobert Watson 1003f1a7a90SRobert Watson static int lomac_label_size = sizeof(struct mac_lomac); 101db2661ceSRobert Watson SYSCTL_INT(_security_mac_lomac, OID_AUTO, label_size, CTLFLAG_RD, 1023f1a7a90SRobert Watson &lomac_label_size, 0, "Size of struct mac_lomac"); 103db2661ceSRobert Watson 1043f1a7a90SRobert Watson static int lomac_enabled = 1; 105af3b2549SHans Petter Selasky SYSCTL_INT(_security_mac_lomac, OID_AUTO, enabled, CTLFLAG_RWTUN, 1063f1a7a90SRobert Watson &lomac_enabled, 0, "Enforce MAC/LOMAC policy"); 107db2661ceSRobert Watson 108db2661ceSRobert Watson static int destroyed_not_inited; 109db2661ceSRobert Watson SYSCTL_INT(_security_mac_lomac, OID_AUTO, destroyed_not_inited, CTLFLAG_RD, 110db2661ceSRobert Watson &destroyed_not_inited, 0, "Count of labels destroyed but not inited"); 111db2661ceSRobert Watson 112db2661ceSRobert Watson static int trust_all_interfaces = 0; 113af3b2549SHans Petter Selasky SYSCTL_INT(_security_mac_lomac, OID_AUTO, trust_all_interfaces, CTLFLAG_RDTUN, 114db2661ceSRobert Watson &trust_all_interfaces, 0, "Consider all interfaces 'trusted' by MAC/LOMAC"); 115db2661ceSRobert Watson 116db2661ceSRobert Watson static char trusted_interfaces[128]; 117af3b2549SHans Petter Selasky SYSCTL_STRING(_security_mac_lomac, OID_AUTO, trusted_interfaces, CTLFLAG_RDTUN, 118db2661ceSRobert Watson trusted_interfaces, 0, "Interfaces considered 'trusted' by MAC/LOMAC"); 119db2661ceSRobert Watson 120db2661ceSRobert Watson static int ptys_equal = 0; 121af3b2549SHans Petter Selasky SYSCTL_INT(_security_mac_lomac, OID_AUTO, ptys_equal, CTLFLAG_RWTUN, 122db2661ceSRobert Watson &ptys_equal, 0, "Label pty devices as lomac/equal on create"); 123db2661ceSRobert Watson 124db2661ceSRobert Watson static int revocation_enabled = 1; 125af3b2549SHans Petter Selasky SYSCTL_INT(_security_mac_lomac, OID_AUTO, revocation_enabled, CTLFLAG_RWTUN, 126db2661ceSRobert Watson &revocation_enabled, 0, "Revoke access to objects on relabel"); 127db2661ceSRobert Watson 1283f1a7a90SRobert Watson static int lomac_slot; 1293f1a7a90SRobert Watson #define SLOT(l) ((struct mac_lomac *)mac_label_get((l), lomac_slot)) 1303f1a7a90SRobert Watson #define SLOT_SET(l, val) mac_label_set((l), lomac_slot, (uintptr_t)(val)) 131db2661ceSRobert Watson #define PSLOT(l) ((struct mac_lomac_proc *) \ 1323f1a7a90SRobert Watson mac_label_get((l), lomac_slot)) 1333f1a7a90SRobert Watson #define PSLOT_SET(l, val) mac_label_set((l), lomac_slot, (uintptr_t)(val)) 134db2661ceSRobert Watson 135d745c852SEd Schouten static MALLOC_DEFINE(M_LOMAC, "mac_lomac_label", "MAC/LOMAC labels"); 136db2661ceSRobert Watson 137db2661ceSRobert Watson static struct mac_lomac * 138db2661ceSRobert Watson lomac_alloc(int flag) 139db2661ceSRobert Watson { 1403f1a7a90SRobert Watson struct mac_lomac *ml; 141db2661ceSRobert Watson 1423f1a7a90SRobert Watson ml = malloc(sizeof(*ml), M_LOMAC, M_ZERO | flag); 143db2661ceSRobert Watson 1443f1a7a90SRobert Watson return (ml); 145db2661ceSRobert Watson } 146db2661ceSRobert Watson 147db2661ceSRobert Watson static void 1483f1a7a90SRobert Watson lomac_free(struct mac_lomac *ml) 149db2661ceSRobert Watson { 150db2661ceSRobert Watson 1513f1a7a90SRobert Watson if (ml != NULL) 1523f1a7a90SRobert Watson free(ml, M_LOMAC); 153db2661ceSRobert Watson else 154db2661ceSRobert Watson atomic_add_int(&destroyed_not_inited, 1); 155db2661ceSRobert Watson } 156db2661ceSRobert Watson 157db2661ceSRobert Watson static int 1583f1a7a90SRobert Watson lomac_atmostflags(struct mac_lomac *ml, int flags) 159db2661ceSRobert Watson { 160db2661ceSRobert Watson 1613f1a7a90SRobert Watson if ((ml->ml_flags & flags) != ml->ml_flags) 162db2661ceSRobert Watson return (EINVAL); 163db2661ceSRobert Watson return (0); 164db2661ceSRobert Watson } 165db2661ceSRobert Watson 166db2661ceSRobert Watson static int 1673f1a7a90SRobert Watson lomac_dominate_element(struct mac_lomac_element *a, 168db2661ceSRobert Watson struct mac_lomac_element *b) 169db2661ceSRobert Watson { 170db2661ceSRobert Watson 171db2661ceSRobert Watson switch (a->mle_type) { 172db2661ceSRobert Watson case MAC_LOMAC_TYPE_EQUAL: 173db2661ceSRobert Watson case MAC_LOMAC_TYPE_HIGH: 174db2661ceSRobert Watson return (1); 175db2661ceSRobert Watson 176db2661ceSRobert Watson case MAC_LOMAC_TYPE_LOW: 177db2661ceSRobert Watson switch (b->mle_type) { 178db2661ceSRobert Watson case MAC_LOMAC_TYPE_GRADE: 179db2661ceSRobert Watson case MAC_LOMAC_TYPE_HIGH: 180db2661ceSRobert Watson return (0); 181db2661ceSRobert Watson 182db2661ceSRobert Watson case MAC_LOMAC_TYPE_EQUAL: 183db2661ceSRobert Watson case MAC_LOMAC_TYPE_LOW: 184db2661ceSRobert Watson return (1); 185db2661ceSRobert Watson 186db2661ceSRobert Watson default: 1873f1a7a90SRobert Watson panic("lomac_dominate_element: b->mle_type invalid"); 188db2661ceSRobert Watson } 189db2661ceSRobert Watson 190db2661ceSRobert Watson case MAC_LOMAC_TYPE_GRADE: 191db2661ceSRobert Watson switch (b->mle_type) { 192db2661ceSRobert Watson case MAC_LOMAC_TYPE_EQUAL: 193db2661ceSRobert Watson case MAC_LOMAC_TYPE_LOW: 194db2661ceSRobert Watson return (1); 195db2661ceSRobert Watson 196db2661ceSRobert Watson case MAC_LOMAC_TYPE_HIGH: 197db2661ceSRobert Watson return (0); 198db2661ceSRobert Watson 199db2661ceSRobert Watson case MAC_LOMAC_TYPE_GRADE: 200db2661ceSRobert Watson return (a->mle_grade >= b->mle_grade); 201db2661ceSRobert Watson 202db2661ceSRobert Watson default: 2033f1a7a90SRobert Watson panic("lomac_dominate_element: b->mle_type invalid"); 204db2661ceSRobert Watson } 205db2661ceSRobert Watson 206db2661ceSRobert Watson default: 2073f1a7a90SRobert Watson panic("lomac_dominate_element: a->mle_type invalid"); 208db2661ceSRobert Watson } 209db2661ceSRobert Watson } 210db2661ceSRobert Watson 211db2661ceSRobert Watson static int 2123f1a7a90SRobert Watson lomac_range_in_range(struct mac_lomac *rangea, struct mac_lomac *rangeb) 213db2661ceSRobert Watson { 214db2661ceSRobert Watson 2153f1a7a90SRobert Watson return (lomac_dominate_element(&rangeb->ml_rangehigh, 216db2661ceSRobert Watson &rangea->ml_rangehigh) && 2173f1a7a90SRobert Watson lomac_dominate_element(&rangea->ml_rangelow, 218db2661ceSRobert Watson &rangeb->ml_rangelow)); 219db2661ceSRobert Watson } 220db2661ceSRobert Watson 221db2661ceSRobert Watson static int 2223f1a7a90SRobert Watson lomac_single_in_range(struct mac_lomac *single, struct mac_lomac *range) 223db2661ceSRobert Watson { 224db2661ceSRobert Watson 225db2661ceSRobert Watson KASSERT((single->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0, 2263f1a7a90SRobert Watson ("lomac_single_in_range: a not single")); 227db2661ceSRobert Watson KASSERT((range->ml_flags & MAC_LOMAC_FLAG_RANGE) != 0, 2283f1a7a90SRobert Watson ("lomac_single_in_range: b not range")); 229db2661ceSRobert Watson 2303f1a7a90SRobert Watson return (lomac_dominate_element(&range->ml_rangehigh, 2313f1a7a90SRobert Watson &single->ml_single) && lomac_dominate_element(&single->ml_single, 232db2661ceSRobert Watson &range->ml_rangelow)); 233db2661ceSRobert Watson } 234db2661ceSRobert Watson 235db2661ceSRobert Watson static int 2363f1a7a90SRobert Watson lomac_auxsingle_in_range(struct mac_lomac *single, struct mac_lomac *range) 237db2661ceSRobert Watson { 238db2661ceSRobert Watson 239db2661ceSRobert Watson KASSERT((single->ml_flags & MAC_LOMAC_FLAG_AUX) != 0, 2403f1a7a90SRobert Watson ("lomac_single_in_range: a not auxsingle")); 241db2661ceSRobert Watson KASSERT((range->ml_flags & MAC_LOMAC_FLAG_RANGE) != 0, 2423f1a7a90SRobert Watson ("lomac_single_in_range: b not range")); 243db2661ceSRobert Watson 2443f1a7a90SRobert Watson return (lomac_dominate_element(&range->ml_rangehigh, 245db2661ceSRobert Watson &single->ml_auxsingle) && 2463f1a7a90SRobert Watson lomac_dominate_element(&single->ml_auxsingle, 247db2661ceSRobert Watson &range->ml_rangelow)); 248db2661ceSRobert Watson } 249db2661ceSRobert Watson 250db2661ceSRobert Watson static int 2513f1a7a90SRobert Watson lomac_dominate_single(struct mac_lomac *a, struct mac_lomac *b) 252db2661ceSRobert Watson { 253db2661ceSRobert Watson KASSERT((a->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0, 2543f1a7a90SRobert Watson ("lomac_dominate_single: a not single")); 255db2661ceSRobert Watson KASSERT((b->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0, 2563f1a7a90SRobert Watson ("lomac_dominate_single: b not single")); 257db2661ceSRobert Watson 2583f1a7a90SRobert Watson return (lomac_dominate_element(&a->ml_single, &b->ml_single)); 259db2661ceSRobert Watson } 260db2661ceSRobert Watson 261db2661ceSRobert Watson static int 2623f1a7a90SRobert Watson lomac_subject_dominate(struct mac_lomac *a, struct mac_lomac *b) 263db2661ceSRobert Watson { 264db2661ceSRobert Watson KASSERT((~a->ml_flags & 265db2661ceSRobert Watson (MAC_LOMAC_FLAG_SINGLE | MAC_LOMAC_FLAG_RANGE)) == 0, 2663f1a7a90SRobert Watson ("lomac_dominate_single: a not subject")); 267db2661ceSRobert Watson KASSERT((b->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0, 2683f1a7a90SRobert Watson ("lomac_dominate_single: b not single")); 269db2661ceSRobert Watson 2703f1a7a90SRobert Watson return (lomac_dominate_element(&a->ml_rangehigh, &b->ml_single)); 271db2661ceSRobert Watson } 272db2661ceSRobert Watson 273db2661ceSRobert Watson static int 2743f1a7a90SRobert Watson lomac_equal_element(struct mac_lomac_element *a, struct mac_lomac_element *b) 275db2661ceSRobert Watson { 276db2661ceSRobert Watson 277db2661ceSRobert Watson if (a->mle_type == MAC_LOMAC_TYPE_EQUAL || 278db2661ceSRobert Watson b->mle_type == MAC_LOMAC_TYPE_EQUAL) 279db2661ceSRobert Watson return (1); 280db2661ceSRobert Watson 281db2661ceSRobert Watson return (a->mle_type == b->mle_type && a->mle_grade == b->mle_grade); 282db2661ceSRobert Watson } 283db2661ceSRobert Watson 284db2661ceSRobert Watson static int 2853f1a7a90SRobert Watson lomac_equal_single(struct mac_lomac *a, struct mac_lomac *b) 286db2661ceSRobert Watson { 287db2661ceSRobert Watson 288db2661ceSRobert Watson KASSERT((a->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0, 2893f1a7a90SRobert Watson ("lomac_equal_single: a not single")); 290db2661ceSRobert Watson KASSERT((b->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0, 2913f1a7a90SRobert Watson ("lomac_equal_single: b not single")); 292db2661ceSRobert Watson 2933f1a7a90SRobert Watson return (lomac_equal_element(&a->ml_single, &b->ml_single)); 294db2661ceSRobert Watson } 295db2661ceSRobert Watson 296db2661ceSRobert Watson static int 2973f1a7a90SRobert Watson lomac_contains_equal(struct mac_lomac *ml) 298db2661ceSRobert Watson { 299db2661ceSRobert Watson 3003f1a7a90SRobert Watson if (ml->ml_flags & MAC_LOMAC_FLAG_SINGLE) 3013f1a7a90SRobert Watson if (ml->ml_single.mle_type == MAC_LOMAC_TYPE_EQUAL) 302db2661ceSRobert Watson return (1); 3033f1a7a90SRobert Watson if (ml->ml_flags & MAC_LOMAC_FLAG_AUX) 3043f1a7a90SRobert Watson if (ml->ml_auxsingle.mle_type == MAC_LOMAC_TYPE_EQUAL) 305db2661ceSRobert Watson return (1); 306db2661ceSRobert Watson 3073f1a7a90SRobert Watson if (ml->ml_flags & MAC_LOMAC_FLAG_RANGE) { 3083f1a7a90SRobert Watson if (ml->ml_rangelow.mle_type == MAC_LOMAC_TYPE_EQUAL) 309db2661ceSRobert Watson return (1); 3103f1a7a90SRobert Watson if (ml->ml_rangehigh.mle_type == MAC_LOMAC_TYPE_EQUAL) 311db2661ceSRobert Watson return (1); 312db2661ceSRobert Watson } 313db2661ceSRobert Watson 314db2661ceSRobert Watson return (0); 315db2661ceSRobert Watson } 316db2661ceSRobert Watson 317db2661ceSRobert Watson static int 3183f1a7a90SRobert Watson lomac_subject_privileged(struct mac_lomac *ml) 319db2661ceSRobert Watson { 320db2661ceSRobert Watson 3213f1a7a90SRobert Watson KASSERT((ml->ml_flags & MAC_LOMAC_FLAGS_BOTH) == 322db2661ceSRobert Watson MAC_LOMAC_FLAGS_BOTH, 3233f1a7a90SRobert Watson ("lomac_subject_privileged: subject doesn't have both labels")); 324db2661ceSRobert Watson 325db2661ceSRobert Watson /* If the single is EQUAL, it's ok. */ 3263f1a7a90SRobert Watson if (ml->ml_single.mle_type == MAC_LOMAC_TYPE_EQUAL) 327db2661ceSRobert Watson return (0); 328db2661ceSRobert Watson 329db2661ceSRobert Watson /* If either range endpoint is EQUAL, it's ok. */ 3303f1a7a90SRobert Watson if (ml->ml_rangelow.mle_type == MAC_LOMAC_TYPE_EQUAL || 3313f1a7a90SRobert Watson ml->ml_rangehigh.mle_type == MAC_LOMAC_TYPE_EQUAL) 332db2661ceSRobert Watson return (0); 333db2661ceSRobert Watson 334db2661ceSRobert Watson /* If the range is low-high, it's ok. */ 3353f1a7a90SRobert Watson if (ml->ml_rangelow.mle_type == MAC_LOMAC_TYPE_LOW && 3363f1a7a90SRobert Watson ml->ml_rangehigh.mle_type == MAC_LOMAC_TYPE_HIGH) 337db2661ceSRobert Watson return (0); 338db2661ceSRobert Watson 339db2661ceSRobert Watson /* It's not ok. */ 340db2661ceSRobert Watson return (EPERM); 341db2661ceSRobert Watson } 342db2661ceSRobert Watson 343db2661ceSRobert Watson static int 3443f1a7a90SRobert Watson lomac_high_single(struct mac_lomac *ml) 345db2661ceSRobert Watson { 346db2661ceSRobert Watson 3473f1a7a90SRobert Watson KASSERT((ml->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0, 3483f1a7a90SRobert Watson ("lomac_high_single: mac_lomac not single")); 349db2661ceSRobert Watson 3503f1a7a90SRobert Watson return (ml->ml_single.mle_type == MAC_LOMAC_TYPE_HIGH); 351db2661ceSRobert Watson } 352db2661ceSRobert Watson 353db2661ceSRobert Watson static int 3543f1a7a90SRobert Watson lomac_valid(struct mac_lomac *ml) 355db2661ceSRobert Watson { 356db2661ceSRobert Watson 3573f1a7a90SRobert Watson if (ml->ml_flags & MAC_LOMAC_FLAG_SINGLE) { 3583f1a7a90SRobert Watson switch (ml->ml_single.mle_type) { 359db2661ceSRobert Watson case MAC_LOMAC_TYPE_GRADE: 360db2661ceSRobert Watson case MAC_LOMAC_TYPE_EQUAL: 361db2661ceSRobert Watson case MAC_LOMAC_TYPE_HIGH: 362db2661ceSRobert Watson case MAC_LOMAC_TYPE_LOW: 363db2661ceSRobert Watson break; 364db2661ceSRobert Watson 365db2661ceSRobert Watson default: 366db2661ceSRobert Watson return (EINVAL); 367db2661ceSRobert Watson } 368db2661ceSRobert Watson } else { 3693f1a7a90SRobert Watson if (ml->ml_single.mle_type != MAC_LOMAC_TYPE_UNDEF) 370db2661ceSRobert Watson return (EINVAL); 371db2661ceSRobert Watson } 372db2661ceSRobert Watson 3733f1a7a90SRobert Watson if (ml->ml_flags & MAC_LOMAC_FLAG_AUX) { 3743f1a7a90SRobert Watson switch (ml->ml_auxsingle.mle_type) { 375db2661ceSRobert Watson case MAC_LOMAC_TYPE_GRADE: 376db2661ceSRobert Watson case MAC_LOMAC_TYPE_EQUAL: 377db2661ceSRobert Watson case MAC_LOMAC_TYPE_HIGH: 378db2661ceSRobert Watson case MAC_LOMAC_TYPE_LOW: 379db2661ceSRobert Watson break; 380db2661ceSRobert Watson 381db2661ceSRobert Watson default: 382db2661ceSRobert Watson return (EINVAL); 383db2661ceSRobert Watson } 384db2661ceSRobert Watson } else { 3853f1a7a90SRobert Watson if (ml->ml_auxsingle.mle_type != MAC_LOMAC_TYPE_UNDEF) 386db2661ceSRobert Watson return (EINVAL); 387db2661ceSRobert Watson } 388db2661ceSRobert Watson 3893f1a7a90SRobert Watson if (ml->ml_flags & MAC_LOMAC_FLAG_RANGE) { 3903f1a7a90SRobert Watson switch (ml->ml_rangelow.mle_type) { 391db2661ceSRobert Watson case MAC_LOMAC_TYPE_GRADE: 392db2661ceSRobert Watson case MAC_LOMAC_TYPE_EQUAL: 393db2661ceSRobert Watson case MAC_LOMAC_TYPE_HIGH: 394db2661ceSRobert Watson case MAC_LOMAC_TYPE_LOW: 395db2661ceSRobert Watson break; 396db2661ceSRobert Watson 397db2661ceSRobert Watson default: 398db2661ceSRobert Watson return (EINVAL); 399db2661ceSRobert Watson } 400db2661ceSRobert Watson 4013f1a7a90SRobert Watson switch (ml->ml_rangehigh.mle_type) { 402db2661ceSRobert Watson case MAC_LOMAC_TYPE_GRADE: 403db2661ceSRobert Watson case MAC_LOMAC_TYPE_EQUAL: 404db2661ceSRobert Watson case MAC_LOMAC_TYPE_HIGH: 405db2661ceSRobert Watson case MAC_LOMAC_TYPE_LOW: 406db2661ceSRobert Watson break; 407db2661ceSRobert Watson 408db2661ceSRobert Watson default: 409db2661ceSRobert Watson return (EINVAL); 410db2661ceSRobert Watson } 4113f1a7a90SRobert Watson if (!lomac_dominate_element(&ml->ml_rangehigh, 4123f1a7a90SRobert Watson &ml->ml_rangelow)) 413db2661ceSRobert Watson return (EINVAL); 414db2661ceSRobert Watson } else { 4153f1a7a90SRobert Watson if (ml->ml_rangelow.mle_type != MAC_LOMAC_TYPE_UNDEF || 4163f1a7a90SRobert Watson ml->ml_rangehigh.mle_type != MAC_LOMAC_TYPE_UNDEF) 417db2661ceSRobert Watson return (EINVAL); 418db2661ceSRobert Watson } 419db2661ceSRobert Watson 420db2661ceSRobert Watson return (0); 421db2661ceSRobert Watson } 422db2661ceSRobert Watson 423db2661ceSRobert Watson static void 4243f1a7a90SRobert Watson lomac_set_range(struct mac_lomac *ml, u_short typelow, u_short gradelow, 4253f1a7a90SRobert Watson u_short typehigh, u_short gradehigh) 426db2661ceSRobert Watson { 427db2661ceSRobert Watson 4283f1a7a90SRobert Watson ml->ml_rangelow.mle_type = typelow; 4293f1a7a90SRobert Watson ml->ml_rangelow.mle_grade = gradelow; 4303f1a7a90SRobert Watson ml->ml_rangehigh.mle_type = typehigh; 4313f1a7a90SRobert Watson ml->ml_rangehigh.mle_grade = gradehigh; 4323f1a7a90SRobert Watson ml->ml_flags |= MAC_LOMAC_FLAG_RANGE; 433db2661ceSRobert Watson } 434db2661ceSRobert Watson 435db2661ceSRobert Watson static void 4363f1a7a90SRobert Watson lomac_set_single(struct mac_lomac *ml, u_short type, u_short grade) 437db2661ceSRobert Watson { 438db2661ceSRobert Watson 4393f1a7a90SRobert Watson ml->ml_single.mle_type = type; 4403f1a7a90SRobert Watson ml->ml_single.mle_grade = grade; 4413f1a7a90SRobert Watson ml->ml_flags |= MAC_LOMAC_FLAG_SINGLE; 442db2661ceSRobert Watson } 443db2661ceSRobert Watson 444db2661ceSRobert Watson static void 4453f1a7a90SRobert Watson lomac_copy_range(struct mac_lomac *labelfrom, struct mac_lomac *labelto) 446db2661ceSRobert Watson { 447db2661ceSRobert Watson 448db2661ceSRobert Watson KASSERT((labelfrom->ml_flags & MAC_LOMAC_FLAG_RANGE) != 0, 4493f1a7a90SRobert Watson ("lomac_copy_range: labelfrom not range")); 450db2661ceSRobert Watson 451db2661ceSRobert Watson labelto->ml_rangelow = labelfrom->ml_rangelow; 452db2661ceSRobert Watson labelto->ml_rangehigh = labelfrom->ml_rangehigh; 453db2661ceSRobert Watson labelto->ml_flags |= MAC_LOMAC_FLAG_RANGE; 454db2661ceSRobert Watson } 455db2661ceSRobert Watson 456db2661ceSRobert Watson static void 4573f1a7a90SRobert Watson lomac_copy_single(struct mac_lomac *labelfrom, struct mac_lomac *labelto) 458db2661ceSRobert Watson { 459db2661ceSRobert Watson 460db2661ceSRobert Watson KASSERT((labelfrom->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0, 4613f1a7a90SRobert Watson ("lomac_copy_single: labelfrom not single")); 462db2661ceSRobert Watson 463db2661ceSRobert Watson labelto->ml_single = labelfrom->ml_single; 464db2661ceSRobert Watson labelto->ml_flags |= MAC_LOMAC_FLAG_SINGLE; 465db2661ceSRobert Watson } 466db2661ceSRobert Watson 467db2661ceSRobert Watson static void 4683f1a7a90SRobert Watson lomac_copy_auxsingle(struct mac_lomac *labelfrom, struct mac_lomac *labelto) 469db2661ceSRobert Watson { 470db2661ceSRobert Watson 471db2661ceSRobert Watson KASSERT((labelfrom->ml_flags & MAC_LOMAC_FLAG_AUX) != 0, 4723f1a7a90SRobert Watson ("lomac_copy_auxsingle: labelfrom not auxsingle")); 473db2661ceSRobert Watson 474db2661ceSRobert Watson labelto->ml_auxsingle = labelfrom->ml_auxsingle; 475db2661ceSRobert Watson labelto->ml_flags |= MAC_LOMAC_FLAG_AUX; 476db2661ceSRobert Watson } 477db2661ceSRobert Watson 478db2661ceSRobert Watson static void 4793f1a7a90SRobert Watson lomac_copy(struct mac_lomac *source, struct mac_lomac *dest) 480db2661ceSRobert Watson { 481db2661ceSRobert Watson 482db2661ceSRobert Watson if (source->ml_flags & MAC_LOMAC_FLAG_SINGLE) 4833f1a7a90SRobert Watson lomac_copy_single(source, dest); 484db2661ceSRobert Watson if (source->ml_flags & MAC_LOMAC_FLAG_AUX) 4853f1a7a90SRobert Watson lomac_copy_auxsingle(source, dest); 486db2661ceSRobert Watson if (source->ml_flags & MAC_LOMAC_FLAG_RANGE) 4873f1a7a90SRobert Watson lomac_copy_range(source, dest); 488db2661ceSRobert Watson } 489db2661ceSRobert Watson 4903f1a7a90SRobert Watson static int lomac_to_string(struct sbuf *sb, struct mac_lomac *ml); 491db2661ceSRobert Watson 492db2661ceSRobert Watson static int 493db2661ceSRobert Watson maybe_demote(struct mac_lomac *subjlabel, struct mac_lomac *objlabel, 49478007886SRobert Watson const char *actionname, const char *objname, struct vnode *vp) 495db2661ceSRobert Watson { 496f51e5803SRobert Watson struct sbuf subjlabel_sb, subjtext_sb, objlabel_sb; 497f51e5803SRobert Watson char *subjlabeltext, *objlabeltext, *subjtext; 498f51e5803SRobert Watson struct mac_lomac cached_subjlabel; 499f51e5803SRobert Watson struct mac_lomac_proc *subj; 500db2661ceSRobert Watson struct vattr va; 501db2661ceSRobert Watson struct proc *p; 502db2661ceSRobert Watson pid_t pgid; 503db2661ceSRobert Watson 504eca8a663SRobert Watson subj = PSLOT(curthread->td_proc->p_label); 505f51e5803SRobert Watson 506db2661ceSRobert Watson p = curthread->td_proc; 507db2661ceSRobert Watson mtx_lock(&subj->mtx); 508db2661ceSRobert Watson if (subj->mac_lomac.ml_flags & MAC_LOMAC_FLAG_UPDATE) { 509db2661ceSRobert Watson /* 5103f1a7a90SRobert Watson * Check to see if the pending demotion would be more or less 5113f1a7a90SRobert Watson * severe than this one, and keep the more severe. This can 5123f1a7a90SRobert Watson * only happen for a multi-threaded application. 513db2661ceSRobert Watson */ 5143f1a7a90SRobert Watson if (lomac_dominate_single(objlabel, &subj->mac_lomac)) { 515db2661ceSRobert Watson mtx_unlock(&subj->mtx); 516db2661ceSRobert Watson return (0); 517db2661ceSRobert Watson } 518db2661ceSRobert Watson } 519db2661ceSRobert Watson bzero(&subj->mac_lomac, sizeof(subj->mac_lomac)); 520db2661ceSRobert Watson /* 521db2661ceSRobert Watson * Always demote the single label. 522db2661ceSRobert Watson */ 5233f1a7a90SRobert Watson lomac_copy_single(objlabel, &subj->mac_lomac); 524db2661ceSRobert Watson /* 5253f1a7a90SRobert Watson * Start with the original range, then minimize each side of the 5263f1a7a90SRobert Watson * range to the point of not dominating the object. The high side 5273f1a7a90SRobert Watson * will always be demoted, of course. 528db2661ceSRobert Watson */ 5293f1a7a90SRobert Watson lomac_copy_range(subjlabel, &subj->mac_lomac); 5303f1a7a90SRobert Watson if (!lomac_dominate_element(&objlabel->ml_single, 531db2661ceSRobert Watson &subj->mac_lomac.ml_rangelow)) 532db2661ceSRobert Watson subj->mac_lomac.ml_rangelow = objlabel->ml_single; 533db2661ceSRobert Watson subj->mac_lomac.ml_rangehigh = objlabel->ml_single; 534db2661ceSRobert Watson subj->mac_lomac.ml_flags |= MAC_LOMAC_FLAG_UPDATE; 535982d11f8SJeff Roberson thread_lock(curthread); 536b61ce5b0SJeff Roberson curthread->td_flags |= TDF_ASTPENDING | TDF_MACPEND; 537982d11f8SJeff Roberson thread_unlock(curthread); 538f51e5803SRobert Watson 539f51e5803SRobert Watson /* 5403f1a7a90SRobert Watson * Avoid memory allocation while holding a mutex; cache the label. 541f51e5803SRobert Watson */ 5423f1a7a90SRobert Watson lomac_copy_single(&subj->mac_lomac, &cached_subjlabel); 543db2661ceSRobert Watson mtx_unlock(&subj->mtx); 544f51e5803SRobert Watson 545f51e5803SRobert Watson sbuf_new(&subjlabel_sb, NULL, 0, SBUF_AUTOEXTEND); 5463f1a7a90SRobert Watson lomac_to_string(&subjlabel_sb, subjlabel); 547f51e5803SRobert Watson sbuf_finish(&subjlabel_sb); 548f51e5803SRobert Watson subjlabeltext = sbuf_data(&subjlabel_sb); 549f51e5803SRobert Watson 550f51e5803SRobert Watson sbuf_new(&subjtext_sb, NULL, 0, SBUF_AUTOEXTEND); 5513f1a7a90SRobert Watson lomac_to_string(&subjtext_sb, &subj->mac_lomac); 552f51e5803SRobert Watson sbuf_finish(&subjtext_sb); 553f51e5803SRobert Watson subjtext = sbuf_data(&subjtext_sb); 554f51e5803SRobert Watson 555f51e5803SRobert Watson sbuf_new(&objlabel_sb, NULL, 0, SBUF_AUTOEXTEND); 5563f1a7a90SRobert Watson lomac_to_string(&objlabel_sb, objlabel); 557f51e5803SRobert Watson sbuf_finish(&objlabel_sb); 558f51e5803SRobert Watson objlabeltext = sbuf_data(&objlabel_sb); 559f51e5803SRobert Watson 560db2661ceSRobert Watson pgid = p->p_pgrp->pg_id; /* XXX could be stale? */ 5610359a12eSAttilio Rao if (vp != NULL && VOP_GETATTR(vp, &va, curthread->td_ucred) == 0) { 562db2661ceSRobert Watson log(LOG_INFO, "LOMAC: level-%s subject p%dg%du%d:%s demoted to" 563dde58752SGleb Kurtsou " level %s after %s a level-%s %s (inode=%ju, " 564db2661ceSRobert Watson "mountpount=%s)\n", 565db2661ceSRobert Watson subjlabeltext, p->p_pid, pgid, curthread->td_ucred->cr_uid, 566db2661ceSRobert Watson p->p_comm, subjtext, actionname, objlabeltext, objname, 567dde58752SGleb Kurtsou (uintmax_t)va.va_fileid, vp->v_mount->mnt_stat.f_mntonname); 568db2661ceSRobert Watson } else { 569db2661ceSRobert Watson log(LOG_INFO, "LOMAC: level-%s subject p%dg%du%d:%s demoted to" 570db2661ceSRobert Watson " level %s after %s a level-%s %s\n", 571db2661ceSRobert Watson subjlabeltext, p->p_pid, pgid, curthread->td_ucred->cr_uid, 572db2661ceSRobert Watson p->p_comm, subjtext, actionname, objlabeltext, objname); 573db2661ceSRobert Watson } 574db2661ceSRobert Watson 575f51e5803SRobert Watson sbuf_delete(&subjlabel_sb); 576f51e5803SRobert Watson sbuf_delete(&subjtext_sb); 577f51e5803SRobert Watson sbuf_delete(&objlabel_sb); 578f51e5803SRobert Watson 579db2661ceSRobert Watson return (0); 580db2661ceSRobert Watson } 581db2661ceSRobert Watson 582db2661ceSRobert Watson /* 5833f1a7a90SRobert Watson * Relabel "to" to "from" only if "from" is a valid label (contains at least 5843f1a7a90SRobert Watson * a single), as for a relabel operation which may or may not involve a 5853f1a7a90SRobert Watson * relevant label. 586db2661ceSRobert Watson */ 5877496ed81SRobert Watson static void 588db2661ceSRobert Watson try_relabel(struct mac_lomac *from, struct mac_lomac *to) 589db2661ceSRobert Watson { 590db2661ceSRobert Watson 591db2661ceSRobert Watson if (from->ml_flags & MAC_LOMAC_FLAG_SINGLE) { 592db2661ceSRobert Watson bzero(to, sizeof(*to)); 5933f1a7a90SRobert Watson lomac_copy(from, to); 594db2661ceSRobert Watson } 595db2661ceSRobert Watson } 596db2661ceSRobert Watson 597db2661ceSRobert Watson /* 598db2661ceSRobert Watson * Policy module operations. 599db2661ceSRobert Watson */ 600db2661ceSRobert Watson static void 6013f1a7a90SRobert Watson lomac_init(struct mac_policy_conf *conf) 602db2661ceSRobert Watson { 603db2661ceSRobert Watson 604db2661ceSRobert Watson } 605db2661ceSRobert Watson 606db2661ceSRobert Watson /* 607db2661ceSRobert Watson * Label operations. 608db2661ceSRobert Watson */ 609db2661ceSRobert Watson static void 6103f1a7a90SRobert Watson lomac_init_label(struct label *label) 611db2661ceSRobert Watson { 612db2661ceSRobert Watson 6131477f588SAlexander Kabaev SLOT_SET(label, lomac_alloc(M_WAITOK)); 614db2661ceSRobert Watson } 615db2661ceSRobert Watson 616db2661ceSRobert Watson static int 6173f1a7a90SRobert Watson lomac_init_label_waitcheck(struct label *label, int flag) 618db2661ceSRobert Watson { 619db2661ceSRobert Watson 6201477f588SAlexander Kabaev SLOT_SET(label, lomac_alloc(flag)); 621db2661ceSRobert Watson if (SLOT(label) == NULL) 622db2661ceSRobert Watson return (ENOMEM); 623db2661ceSRobert Watson 624db2661ceSRobert Watson return (0); 625db2661ceSRobert Watson } 626db2661ceSRobert Watson 627db2661ceSRobert Watson static void 6283f1a7a90SRobert Watson lomac_destroy_label(struct label *label) 629db2661ceSRobert Watson { 630db2661ceSRobert Watson 631db2661ceSRobert Watson lomac_free(SLOT(label)); 6321477f588SAlexander Kabaev SLOT_SET(label, NULL); 633db2661ceSRobert Watson } 634db2661ceSRobert Watson 635f51e5803SRobert Watson static int 6363f1a7a90SRobert Watson lomac_element_to_string(struct sbuf *sb, struct mac_lomac_element *element) 637db2661ceSRobert Watson { 638db2661ceSRobert Watson 639db2661ceSRobert Watson switch (element->mle_type) { 640db2661ceSRobert Watson case MAC_LOMAC_TYPE_HIGH: 641f51e5803SRobert Watson return (sbuf_printf(sb, "high")); 642db2661ceSRobert Watson 643db2661ceSRobert Watson case MAC_LOMAC_TYPE_LOW: 644f51e5803SRobert Watson return (sbuf_printf(sb, "low")); 645db2661ceSRobert Watson 646db2661ceSRobert Watson case MAC_LOMAC_TYPE_EQUAL: 647f51e5803SRobert Watson return (sbuf_printf(sb, "equal")); 648db2661ceSRobert Watson 649db2661ceSRobert Watson case MAC_LOMAC_TYPE_GRADE: 650f51e5803SRobert Watson return (sbuf_printf(sb, "%d", element->mle_grade)); 651db2661ceSRobert Watson 652db2661ceSRobert Watson default: 6533f1a7a90SRobert Watson panic("lomac_element_to_string: invalid type (%d)", 654db2661ceSRobert Watson element->mle_type); 655db2661ceSRobert Watson } 656db2661ceSRobert Watson } 657db2661ceSRobert Watson 658db2661ceSRobert Watson static int 6593f1a7a90SRobert Watson lomac_to_string(struct sbuf *sb, struct mac_lomac *ml) 660db2661ceSRobert Watson { 661db2661ceSRobert Watson 6623f1a7a90SRobert Watson if (ml->ml_flags & MAC_LOMAC_FLAG_SINGLE) { 6633f1a7a90SRobert Watson if (lomac_element_to_string(sb, &ml->ml_single) == -1) 664f51e5803SRobert Watson return (EINVAL); 665db2661ceSRobert Watson } 666db2661ceSRobert Watson 6673f1a7a90SRobert Watson if (ml->ml_flags & MAC_LOMAC_FLAG_AUX) { 668f51e5803SRobert Watson if (sbuf_putc(sb, '[') == -1) 669f51e5803SRobert Watson return (EINVAL); 670db2661ceSRobert Watson 6713f1a7a90SRobert Watson if (lomac_element_to_string(sb, &ml->ml_auxsingle) == -1) 672f51e5803SRobert Watson return (EINVAL); 673db2661ceSRobert Watson 674f51e5803SRobert Watson if (sbuf_putc(sb, ']') == -1) 675f51e5803SRobert Watson return (EINVAL); 676db2661ceSRobert Watson } 677db2661ceSRobert Watson 6783f1a7a90SRobert Watson if (ml->ml_flags & MAC_LOMAC_FLAG_RANGE) { 679f51e5803SRobert Watson if (sbuf_putc(sb, '(') == -1) 680f51e5803SRobert Watson return (EINVAL); 681db2661ceSRobert Watson 6823f1a7a90SRobert Watson if (lomac_element_to_string(sb, &ml->ml_rangelow) == -1) 683f51e5803SRobert Watson return (EINVAL); 684db2661ceSRobert Watson 685f51e5803SRobert Watson if (sbuf_putc(sb, '-') == -1) 686f51e5803SRobert Watson return (EINVAL); 687db2661ceSRobert Watson 6883f1a7a90SRobert Watson if (lomac_element_to_string(sb, &ml->ml_rangehigh) == -1) 689f51e5803SRobert Watson return (EINVAL); 690db2661ceSRobert Watson 6918a4b86b9SRobert Watson if (sbuf_putc(sb, ')') == -1) 692f51e5803SRobert Watson return (EINVAL); 693db2661ceSRobert Watson } 694db2661ceSRobert Watson 695db2661ceSRobert Watson return (0); 696db2661ceSRobert Watson } 697db2661ceSRobert Watson 698db2661ceSRobert Watson static int 6993f1a7a90SRobert Watson lomac_externalize_label(struct label *label, char *element_name, 700f51e5803SRobert Watson struct sbuf *sb, int *claimed) 701db2661ceSRobert Watson { 7023f1a7a90SRobert Watson struct mac_lomac *ml; 703db2661ceSRobert Watson 704db2661ceSRobert Watson if (strcmp(MAC_LOMAC_LABEL_NAME, element_name) != 0) 705db2661ceSRobert Watson return (0); 706db2661ceSRobert Watson 707db2661ceSRobert Watson (*claimed)++; 708db2661ceSRobert Watson 7093f1a7a90SRobert Watson ml = SLOT(label); 710db2661ceSRobert Watson 7113f1a7a90SRobert Watson return (lomac_to_string(sb, ml)); 712db2661ceSRobert Watson } 713db2661ceSRobert Watson 714db2661ceSRobert Watson static int 7153f1a7a90SRobert Watson lomac_parse_element(struct mac_lomac_element *element, char *string) 716db2661ceSRobert Watson { 717db2661ceSRobert Watson 7183f1a7a90SRobert Watson if (strcmp(string, "high") == 0 || strcmp(string, "hi") == 0) { 719db2661ceSRobert Watson element->mle_type = MAC_LOMAC_TYPE_HIGH; 720db2661ceSRobert Watson element->mle_grade = MAC_LOMAC_TYPE_UNDEF; 7213f1a7a90SRobert Watson } else if (strcmp(string, "low") == 0 || strcmp(string, "lo") == 0) { 722db2661ceSRobert Watson element->mle_type = MAC_LOMAC_TYPE_LOW; 723db2661ceSRobert Watson element->mle_grade = MAC_LOMAC_TYPE_UNDEF; 72495b85ca3SRobert Watson } else if (strcmp(string, "equal") == 0 || 72595b85ca3SRobert Watson strcmp(string, "eq") == 0) { 726db2661ceSRobert Watson element->mle_type = MAC_LOMAC_TYPE_EQUAL; 727db2661ceSRobert Watson element->mle_grade = MAC_LOMAC_TYPE_UNDEF; 728db2661ceSRobert Watson } else { 729db2661ceSRobert Watson char *p0, *p1; 730db2661ceSRobert Watson int d; 731db2661ceSRobert Watson 732db2661ceSRobert Watson p0 = string; 733db2661ceSRobert Watson d = strtol(p0, &p1, 10); 734db2661ceSRobert Watson 735db2661ceSRobert Watson if (d < 0 || d > 65535) 736db2661ceSRobert Watson return (EINVAL); 737db2661ceSRobert Watson element->mle_type = MAC_LOMAC_TYPE_GRADE; 738db2661ceSRobert Watson element->mle_grade = d; 739db2661ceSRobert Watson 740db2661ceSRobert Watson if (p1 == p0 || *p1 != '\0') 741db2661ceSRobert Watson return (EINVAL); 742db2661ceSRobert Watson } 743db2661ceSRobert Watson 744db2661ceSRobert Watson return (0); 745db2661ceSRobert Watson } 746db2661ceSRobert Watson 747db2661ceSRobert Watson /* 7483f1a7a90SRobert Watson * Note: destructively consumes the string, make a local copy before calling 7493f1a7a90SRobert Watson * if that's a problem. 750db2661ceSRobert Watson */ 751db2661ceSRobert Watson static int 7523f1a7a90SRobert Watson lomac_parse(struct mac_lomac *ml, char *string) 753db2661ceSRobert Watson { 754db2661ceSRobert Watson char *range, *rangeend, *rangehigh, *rangelow, *single, *auxsingle, 755db2661ceSRobert Watson *auxsingleend; 756db2661ceSRobert Watson int error; 757db2661ceSRobert Watson 758db2661ceSRobert Watson /* Do we have a range? */ 759db2661ceSRobert Watson single = string; 760dc15eac0SEd Schouten range = strchr(string, '('); 761db2661ceSRobert Watson if (range == single) 762db2661ceSRobert Watson single = NULL; 763dc15eac0SEd Schouten auxsingle = strchr(string, '['); 764db2661ceSRobert Watson if (auxsingle == single) 765db2661ceSRobert Watson single = NULL; 766db2661ceSRobert Watson if (range != NULL && auxsingle != NULL) 767db2661ceSRobert Watson return (EINVAL); 768db2661ceSRobert Watson rangelow = rangehigh = NULL; 769db2661ceSRobert Watson if (range != NULL) { 770db2661ceSRobert Watson /* Nul terminate the end of the single string. */ 771db2661ceSRobert Watson *range = '\0'; 772db2661ceSRobert Watson range++; 773db2661ceSRobert Watson rangelow = range; 774dc15eac0SEd Schouten rangehigh = strchr(rangelow, '-'); 775db2661ceSRobert Watson if (rangehigh == NULL) 776db2661ceSRobert Watson return (EINVAL); 777db2661ceSRobert Watson rangehigh++; 778db2661ceSRobert Watson if (*rangelow == '\0' || *rangehigh == '\0') 779db2661ceSRobert Watson return (EINVAL); 780dc15eac0SEd Schouten rangeend = strchr(rangehigh, ')'); 781db2661ceSRobert Watson if (rangeend == NULL) 782db2661ceSRobert Watson return (EINVAL); 783db2661ceSRobert Watson if (*(rangeend + 1) != '\0') 784db2661ceSRobert Watson return (EINVAL); 785db2661ceSRobert Watson /* Nul terminate the ends of the ranges. */ 786db2661ceSRobert Watson *(rangehigh - 1) = '\0'; 787db2661ceSRobert Watson *rangeend = '\0'; 788db2661ceSRobert Watson } 789db2661ceSRobert Watson KASSERT((rangelow != NULL && rangehigh != NULL) || 790db2661ceSRobert Watson (rangelow == NULL && rangehigh == NULL), 7913f1a7a90SRobert Watson ("lomac_internalize_label: range mismatch")); 792db2661ceSRobert Watson if (auxsingle != NULL) { 793db2661ceSRobert Watson /* Nul terminate the end of the single string. */ 794db2661ceSRobert Watson *auxsingle = '\0'; 795db2661ceSRobert Watson auxsingle++; 796dc15eac0SEd Schouten auxsingleend = strchr(auxsingle, ']'); 797db2661ceSRobert Watson if (auxsingleend == NULL) 798db2661ceSRobert Watson return (EINVAL); 799db2661ceSRobert Watson if (*(auxsingleend + 1) != '\0') 800db2661ceSRobert Watson return (EINVAL); 801db2661ceSRobert Watson /* Nul terminate the end of the auxsingle. */ 802db2661ceSRobert Watson *auxsingleend = '\0'; 803db2661ceSRobert Watson } 804db2661ceSRobert Watson 8053f1a7a90SRobert Watson bzero(ml, sizeof(*ml)); 806db2661ceSRobert Watson if (single != NULL) { 8073f1a7a90SRobert Watson error = lomac_parse_element(&ml->ml_single, single); 808db2661ceSRobert Watson if (error) 809db2661ceSRobert Watson return (error); 8103f1a7a90SRobert Watson ml->ml_flags |= MAC_LOMAC_FLAG_SINGLE; 811db2661ceSRobert Watson } 812db2661ceSRobert Watson 813db2661ceSRobert Watson if (auxsingle != NULL) { 81495b85ca3SRobert Watson error = lomac_parse_element(&ml->ml_auxsingle, auxsingle); 815db2661ceSRobert Watson if (error) 816db2661ceSRobert Watson return (error); 8173f1a7a90SRobert Watson ml->ml_flags |= MAC_LOMAC_FLAG_AUX; 818db2661ceSRobert Watson } 819db2661ceSRobert Watson 820db2661ceSRobert Watson if (rangelow != NULL) { 8213f1a7a90SRobert Watson error = lomac_parse_element(&ml->ml_rangelow, rangelow); 822db2661ceSRobert Watson if (error) 823db2661ceSRobert Watson return (error); 8243f1a7a90SRobert Watson error = lomac_parse_element(&ml->ml_rangehigh, rangehigh); 825db2661ceSRobert Watson if (error) 826db2661ceSRobert Watson return (error); 8273f1a7a90SRobert Watson ml->ml_flags |= MAC_LOMAC_FLAG_RANGE; 828db2661ceSRobert Watson } 829db2661ceSRobert Watson 8303f1a7a90SRobert Watson error = lomac_valid(ml); 831db2661ceSRobert Watson if (error) 832db2661ceSRobert Watson return (error); 833db2661ceSRobert Watson 834db2661ceSRobert Watson return (0); 835db2661ceSRobert Watson } 836db2661ceSRobert Watson 837db2661ceSRobert Watson static int 8383f1a7a90SRobert Watson lomac_internalize_label(struct label *label, char *element_name, 839db2661ceSRobert Watson char *element_data, int *claimed) 840db2661ceSRobert Watson { 8413f1a7a90SRobert Watson struct mac_lomac *ml, ml_temp; 842db2661ceSRobert Watson int error; 843db2661ceSRobert Watson 844db2661ceSRobert Watson if (strcmp(MAC_LOMAC_LABEL_NAME, element_name) != 0) 845db2661ceSRobert Watson return (0); 846db2661ceSRobert Watson 847db2661ceSRobert Watson (*claimed)++; 848db2661ceSRobert Watson 8493f1a7a90SRobert Watson error = lomac_parse(&ml_temp, element_data); 850db2661ceSRobert Watson if (error) 851db2661ceSRobert Watson return (error); 852db2661ceSRobert Watson 8533f1a7a90SRobert Watson ml = SLOT(label); 8543f1a7a90SRobert Watson *ml = ml_temp; 855db2661ceSRobert Watson 856db2661ceSRobert Watson return (0); 857db2661ceSRobert Watson } 858db2661ceSRobert Watson 859db2661ceSRobert Watson static void 8603f1a7a90SRobert Watson lomac_copy_label(struct label *src, struct label *dest) 861db2661ceSRobert Watson { 862db2661ceSRobert Watson 863db2661ceSRobert Watson *SLOT(dest) = *SLOT(src); 864db2661ceSRobert Watson } 865db2661ceSRobert Watson 866db2661ceSRobert Watson /* 867eb320b0eSRobert Watson * Object-specific entry point implementations are sorted alphabetically by 868eb320b0eSRobert Watson * object type name and then by operation. 869db2661ceSRobert Watson */ 870db2661ceSRobert Watson static int 8713f1a7a90SRobert Watson lomac_bpfdesc_check_receive(struct bpf_d *d, struct label *dlabel, 87278007886SRobert Watson struct ifnet *ifp, struct label *ifplabel) 873db2661ceSRobert Watson { 874db2661ceSRobert Watson struct mac_lomac *a, *b; 875db2661ceSRobert Watson 8763f1a7a90SRobert Watson if (!lomac_enabled) 877db2661ceSRobert Watson return (0); 878db2661ceSRobert Watson 87978007886SRobert Watson a = SLOT(dlabel); 88078007886SRobert Watson b = SLOT(ifplabel); 881db2661ceSRobert Watson 8823f1a7a90SRobert Watson if (lomac_equal_single(a, b)) 883db2661ceSRobert Watson return (0); 884db2661ceSRobert Watson return (EACCES); 885db2661ceSRobert Watson } 886db2661ceSRobert Watson 887eb320b0eSRobert Watson static void 888eb320b0eSRobert Watson lomac_bpfdesc_create(struct ucred *cred, struct bpf_d *d, 889eb320b0eSRobert Watson struct label *dlabel) 890eb320b0eSRobert Watson { 891eb320b0eSRobert Watson struct mac_lomac *source, *dest; 892eb320b0eSRobert Watson 893eb320b0eSRobert Watson source = SLOT(cred->cr_label); 894eb320b0eSRobert Watson dest = SLOT(dlabel); 895eb320b0eSRobert Watson 896eb320b0eSRobert Watson lomac_copy_single(source, dest); 897eb320b0eSRobert Watson } 898eb320b0eSRobert Watson 899eb320b0eSRobert Watson static void 900eb320b0eSRobert Watson lomac_bpfdesc_create_mbuf(struct bpf_d *d, struct label *dlabel, 901eb320b0eSRobert Watson struct mbuf *m, struct label *mlabel) 902eb320b0eSRobert Watson { 903eb320b0eSRobert Watson struct mac_lomac *source, *dest; 904eb320b0eSRobert Watson 905eb320b0eSRobert Watson source = SLOT(dlabel); 906eb320b0eSRobert Watson dest = SLOT(mlabel); 907eb320b0eSRobert Watson 908eb320b0eSRobert Watson lomac_copy_single(source, dest); 909eb320b0eSRobert Watson } 910eb320b0eSRobert Watson 911db2661ceSRobert Watson static int 9123f1a7a90SRobert Watson lomac_cred_check_relabel(struct ucred *cred, struct label *newlabel) 913db2661ceSRobert Watson { 914db2661ceSRobert Watson struct mac_lomac *subj, *new; 915db2661ceSRobert Watson int error; 916db2661ceSRobert Watson 917eca8a663SRobert Watson subj = SLOT(cred->cr_label); 918db2661ceSRobert Watson new = SLOT(newlabel); 919db2661ceSRobert Watson 920db2661ceSRobert Watson /* 9213f1a7a90SRobert Watson * If there is a LOMAC label update for the credential, it may be an 9223f1a7a90SRobert Watson * update of the single, range, or both. 923db2661ceSRobert Watson */ 924db2661ceSRobert Watson error = lomac_atmostflags(new, MAC_LOMAC_FLAGS_BOTH); 925db2661ceSRobert Watson if (error) 926db2661ceSRobert Watson return (error); 927db2661ceSRobert Watson 928db2661ceSRobert Watson /* 929db2661ceSRobert Watson * If the LOMAC label is to be changed, authorize as appropriate. 930db2661ceSRobert Watson */ 931db2661ceSRobert Watson if (new->ml_flags & MAC_LOMAC_FLAGS_BOTH) { 932db2661ceSRobert Watson /* 93384bdb083SRobert Watson * Fill in the missing parts from the previous label. 934db2661ceSRobert Watson */ 93584bdb083SRobert Watson if ((new->ml_flags & MAC_LOMAC_FLAG_SINGLE) == 0) 9363f1a7a90SRobert Watson lomac_copy_single(subj, new); 93784bdb083SRobert Watson if ((new->ml_flags & MAC_LOMAC_FLAG_RANGE) == 0) 9383f1a7a90SRobert Watson lomac_copy_range(subj, new); 939db2661ceSRobert Watson 940db2661ceSRobert Watson /* 9413f1a7a90SRobert Watson * To change the LOMAC range on a credential, the new range 9423f1a7a90SRobert Watson * label must be in the current range. 943db2661ceSRobert Watson */ 9443f1a7a90SRobert Watson if (!lomac_range_in_range(new, subj)) 94584bdb083SRobert Watson return (EPERM); 94684bdb083SRobert Watson 94784bdb083SRobert Watson /* 9483f1a7a90SRobert Watson * To change the LOMAC single label on a credential, the new 9493f1a7a90SRobert Watson * single label must be in the new range. Implicitly from 9503f1a7a90SRobert Watson * the previous check, the new single is in the old range. 95184bdb083SRobert Watson */ 9523f1a7a90SRobert Watson if (!lomac_single_in_range(new, new)) 953db2661ceSRobert Watson return (EPERM); 954db2661ceSRobert Watson 955db2661ceSRobert Watson /* 9563f1a7a90SRobert Watson * To have EQUAL in any component of the new credential LOMAC 9573f1a7a90SRobert Watson * label, the subject must already have EQUAL in their label. 958db2661ceSRobert Watson */ 9593f1a7a90SRobert Watson if (lomac_contains_equal(new)) { 9603f1a7a90SRobert Watson error = lomac_subject_privileged(subj); 961db2661ceSRobert Watson if (error) 962db2661ceSRobert Watson return (error); 963db2661ceSRobert Watson } 964db2661ceSRobert Watson 965db2661ceSRobert Watson /* 9663f1a7a90SRobert Watson * XXXMAC: Additional consistency tests regarding the single 9673f1a7a90SRobert Watson * and range of the new label might be performed here. 968db2661ceSRobert Watson */ 969db2661ceSRobert Watson } 970db2661ceSRobert Watson 971db2661ceSRobert Watson return (0); 972db2661ceSRobert Watson } 973db2661ceSRobert Watson 974db2661ceSRobert Watson static int 9753f1a7a90SRobert Watson lomac_cred_check_visible(struct ucred *cr1, struct ucred *cr2) 976db2661ceSRobert Watson { 977db2661ceSRobert Watson struct mac_lomac *subj, *obj; 978db2661ceSRobert Watson 9793f1a7a90SRobert Watson if (!lomac_enabled) 980db2661ceSRobert Watson return (0); 981db2661ceSRobert Watson 98278007886SRobert Watson subj = SLOT(cr1->cr_label); 98378007886SRobert Watson obj = SLOT(cr2->cr_label); 984db2661ceSRobert Watson 985db2661ceSRobert Watson /* XXX: range */ 9863f1a7a90SRobert Watson if (!lomac_dominate_single(obj, subj)) 987db2661ceSRobert Watson return (ESRCH); 988db2661ceSRobert Watson 989db2661ceSRobert Watson return (0); 990db2661ceSRobert Watson } 991212ab0cfSRobert Watson 992212ab0cfSRobert Watson static void 993212ab0cfSRobert Watson lomac_cred_create_init(struct ucred *cred) 994212ab0cfSRobert Watson { 995212ab0cfSRobert Watson struct mac_lomac *dest; 996212ab0cfSRobert Watson 997212ab0cfSRobert Watson dest = SLOT(cred->cr_label); 998212ab0cfSRobert Watson 999212ab0cfSRobert Watson lomac_set_single(dest, MAC_LOMAC_TYPE_HIGH, 0); 1000212ab0cfSRobert Watson lomac_set_range(dest, MAC_LOMAC_TYPE_LOW, 0, MAC_LOMAC_TYPE_HIGH, 0); 1001212ab0cfSRobert Watson } 1002212ab0cfSRobert Watson 1003212ab0cfSRobert Watson static void 1004212ab0cfSRobert Watson lomac_cred_create_swapper(struct ucred *cred) 1005212ab0cfSRobert Watson { 1006212ab0cfSRobert Watson struct mac_lomac *dest; 1007212ab0cfSRobert Watson 1008212ab0cfSRobert Watson dest = SLOT(cred->cr_label); 1009212ab0cfSRobert Watson 1010212ab0cfSRobert Watson lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0); 1011212ab0cfSRobert Watson lomac_set_range(dest, MAC_LOMAC_TYPE_LOW, 0, MAC_LOMAC_TYPE_HIGH, 0); 1012212ab0cfSRobert Watson } 1013212ab0cfSRobert Watson 1014eb320b0eSRobert Watson static void 1015eb320b0eSRobert Watson lomac_cred_relabel(struct ucred *cred, struct label *newlabel) 1016eb320b0eSRobert Watson { 1017eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1018eb320b0eSRobert Watson 1019eb320b0eSRobert Watson source = SLOT(newlabel); 1020eb320b0eSRobert Watson dest = SLOT(cred->cr_label); 1021eb320b0eSRobert Watson 1022eb320b0eSRobert Watson try_relabel(source, dest); 1023eb320b0eSRobert Watson } 1024eb320b0eSRobert Watson 1025eb320b0eSRobert Watson static void 1026eb320b0eSRobert Watson lomac_devfs_create_device(struct ucred *cred, struct mount *mp, 1027eb320b0eSRobert Watson struct cdev *dev, struct devfs_dirent *de, struct label *delabel) 1028eb320b0eSRobert Watson { 1029eb320b0eSRobert Watson struct mac_lomac *ml; 10307870adb6SEd Schouten const char *dn; 1031eb320b0eSRobert Watson int lomac_type; 1032eb320b0eSRobert Watson 1033eb320b0eSRobert Watson ml = SLOT(delabel); 10347870adb6SEd Schouten dn = devtoname(dev); 10357870adb6SEd Schouten if (strcmp(dn, "null") == 0 || 10367870adb6SEd Schouten strcmp(dn, "zero") == 0 || 10377870adb6SEd Schouten strcmp(dn, "random") == 0 || 10387870adb6SEd Schouten strncmp(dn, "fd/", strlen("fd/")) == 0 || 10397870adb6SEd Schouten strncmp(dn, "ttyv", strlen("ttyv")) == 0) 1040eb320b0eSRobert Watson lomac_type = MAC_LOMAC_TYPE_EQUAL; 1041eb320b0eSRobert Watson else if (ptys_equal && 10427870adb6SEd Schouten (strncmp(dn, "ttyp", strlen("ttyp")) == 0 || 10437870adb6SEd Schouten strncmp(dn, "pts/", strlen("pts/")) == 0 || 10447870adb6SEd Schouten strncmp(dn, "ptyp", strlen("ptyp")) == 0)) 1045eb320b0eSRobert Watson lomac_type = MAC_LOMAC_TYPE_EQUAL; 1046eb320b0eSRobert Watson else 1047eb320b0eSRobert Watson lomac_type = MAC_LOMAC_TYPE_HIGH; 1048eb320b0eSRobert Watson lomac_set_single(ml, lomac_type, 0); 1049eb320b0eSRobert Watson } 1050eb320b0eSRobert Watson 1051eb320b0eSRobert Watson static void 1052eb320b0eSRobert Watson lomac_devfs_create_directory(struct mount *mp, char *dirname, int dirnamelen, 1053eb320b0eSRobert Watson struct devfs_dirent *de, struct label *delabel) 1054eb320b0eSRobert Watson { 1055eb320b0eSRobert Watson struct mac_lomac *ml; 1056eb320b0eSRobert Watson 1057eb320b0eSRobert Watson ml = SLOT(delabel); 1058eb320b0eSRobert Watson lomac_set_single(ml, MAC_LOMAC_TYPE_HIGH, 0); 1059eb320b0eSRobert Watson } 1060eb320b0eSRobert Watson 1061eb320b0eSRobert Watson static void 1062eb320b0eSRobert Watson lomac_devfs_create_symlink(struct ucred *cred, struct mount *mp, 1063eb320b0eSRobert Watson struct devfs_dirent *dd, struct label *ddlabel, struct devfs_dirent *de, 1064eb320b0eSRobert Watson struct label *delabel) 1065eb320b0eSRobert Watson { 1066eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1067eb320b0eSRobert Watson 1068eb320b0eSRobert Watson source = SLOT(cred->cr_label); 1069eb320b0eSRobert Watson dest = SLOT(delabel); 1070eb320b0eSRobert Watson 1071eb320b0eSRobert Watson lomac_copy_single(source, dest); 1072eb320b0eSRobert Watson } 1073eb320b0eSRobert Watson 1074eb320b0eSRobert Watson static void 1075eb320b0eSRobert Watson lomac_devfs_update(struct mount *mp, struct devfs_dirent *de, 1076eb320b0eSRobert Watson struct label *delabel, struct vnode *vp, struct label *vplabel) 1077eb320b0eSRobert Watson { 1078eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1079eb320b0eSRobert Watson 1080eb320b0eSRobert Watson source = SLOT(vplabel); 1081eb320b0eSRobert Watson dest = SLOT(delabel); 1082eb320b0eSRobert Watson 1083eb320b0eSRobert Watson lomac_copy(source, dest); 1084eb320b0eSRobert Watson } 1085eb320b0eSRobert Watson 1086eb320b0eSRobert Watson static void 1087eb320b0eSRobert Watson lomac_devfs_vnode_associate(struct mount *mp, struct label *mplabel, 1088eb320b0eSRobert Watson struct devfs_dirent *de, struct label *delabel, struct vnode *vp, 1089eb320b0eSRobert Watson struct label *vplabel) 1090eb320b0eSRobert Watson { 1091eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1092eb320b0eSRobert Watson 1093eb320b0eSRobert Watson source = SLOT(delabel); 1094eb320b0eSRobert Watson dest = SLOT(vplabel); 1095eb320b0eSRobert Watson 1096eb320b0eSRobert Watson lomac_copy_single(source, dest); 1097eb320b0eSRobert Watson } 1098db2661ceSRobert Watson 1099db2661ceSRobert Watson static int 11003f1a7a90SRobert Watson lomac_ifnet_check_relabel(struct ucred *cred, struct ifnet *ifp, 110178007886SRobert Watson struct label *ifplabel, struct label *newlabel) 1102db2661ceSRobert Watson { 1103db2661ceSRobert Watson struct mac_lomac *subj, *new; 1104db2661ceSRobert Watson int error; 1105db2661ceSRobert Watson 1106eca8a663SRobert Watson subj = SLOT(cred->cr_label); 1107db2661ceSRobert Watson new = SLOT(newlabel); 1108db2661ceSRobert Watson 1109db2661ceSRobert Watson /* 11103f1a7a90SRobert Watson * If there is a LOMAC label update for the interface, it may be an 11113f1a7a90SRobert Watson * update of the single, range, or both. 1112db2661ceSRobert Watson */ 1113db2661ceSRobert Watson error = lomac_atmostflags(new, MAC_LOMAC_FLAGS_BOTH); 1114db2661ceSRobert Watson if (error) 1115db2661ceSRobert Watson return (error); 1116db2661ceSRobert Watson 1117db2661ceSRobert Watson /* 1118db2661ceSRobert Watson * Relabling network interfaces requires LOMAC privilege. 1119db2661ceSRobert Watson */ 11203f1a7a90SRobert Watson error = lomac_subject_privileged(subj); 1121db2661ceSRobert Watson if (error) 1122db2661ceSRobert Watson return (error); 1123db2661ceSRobert Watson 1124db2661ceSRobert Watson /* 1125db2661ceSRobert Watson * If the LOMAC label is to be changed, authorize as appropriate. 1126db2661ceSRobert Watson */ 1127db2661ceSRobert Watson if (new->ml_flags & MAC_LOMAC_FLAGS_BOTH) { 1128db2661ceSRobert Watson /* 112984bdb083SRobert Watson * Fill in the missing parts from the previous label. 113084bdb083SRobert Watson */ 113184bdb083SRobert Watson if ((new->ml_flags & MAC_LOMAC_FLAG_SINGLE) == 0) 11323f1a7a90SRobert Watson lomac_copy_single(subj, new); 113384bdb083SRobert Watson if ((new->ml_flags & MAC_LOMAC_FLAG_RANGE) == 0) 11343f1a7a90SRobert Watson lomac_copy_range(subj, new); 113584bdb083SRobert Watson 113684bdb083SRobert Watson /* 1137db2661ceSRobert Watson * Rely on the traditional superuser status for the LOMAC 1138db2661ceSRobert Watson * interface relabel requirements. XXXMAC: This will go 1139db2661ceSRobert Watson * away. 1140acd3428bSRobert Watson * 1141acd3428bSRobert Watson * XXXRW: This is also redundant to a higher layer check. 1142db2661ceSRobert Watson */ 1143cc426dd3SMateusz Guzik error = priv_check_cred(cred, PRIV_NET_SETIFMAC); 1144db2661ceSRobert Watson if (error) 1145db2661ceSRobert Watson return (EPERM); 1146db2661ceSRobert Watson 1147db2661ceSRobert Watson /* 1148db2661ceSRobert Watson * XXXMAC: Additional consistency tests regarding the single 1149db2661ceSRobert Watson * and the range of the new label might be performed here. 1150db2661ceSRobert Watson */ 1151db2661ceSRobert Watson } 1152db2661ceSRobert Watson 1153db2661ceSRobert Watson return (0); 1154db2661ceSRobert Watson } 1155db2661ceSRobert Watson 1156db2661ceSRobert Watson static int 11573f1a7a90SRobert Watson lomac_ifnet_check_transmit(struct ifnet *ifp, struct label *ifplabel, 115878007886SRobert Watson struct mbuf *m, struct label *mlabel) 1159db2661ceSRobert Watson { 1160db2661ceSRobert Watson struct mac_lomac *p, *i; 1161db2661ceSRobert Watson 11623f1a7a90SRobert Watson if (!lomac_enabled) 1163db2661ceSRobert Watson return (0); 1164db2661ceSRobert Watson 116578007886SRobert Watson p = SLOT(mlabel); 116678007886SRobert Watson i = SLOT(ifplabel); 1167db2661ceSRobert Watson 11683f1a7a90SRobert Watson return (lomac_single_in_range(p, i) ? 0 : EACCES); 1169db2661ceSRobert Watson } 1170db2661ceSRobert Watson 1171eb320b0eSRobert Watson static void 1172eb320b0eSRobert Watson lomac_ifnet_create(struct ifnet *ifp, struct label *ifplabel) 1173eb320b0eSRobert Watson { 1174eb320b0eSRobert Watson char tifname[IFNAMSIZ], *p, *q; 1175eb320b0eSRobert Watson char tiflist[sizeof(trusted_interfaces)]; 1176eb320b0eSRobert Watson struct mac_lomac *dest; 1177eb320b0eSRobert Watson int len, grade; 1178eb320b0eSRobert Watson 1179eb320b0eSRobert Watson dest = SLOT(ifplabel); 1180eb320b0eSRobert Watson 1181eb320b0eSRobert Watson if (ifp->if_type == IFT_LOOP) { 1182eb320b0eSRobert Watson grade = MAC_LOMAC_TYPE_EQUAL; 1183eb320b0eSRobert Watson goto set; 1184eb320b0eSRobert Watson } 1185eb320b0eSRobert Watson 1186eb320b0eSRobert Watson if (trust_all_interfaces) { 1187eb320b0eSRobert Watson grade = MAC_LOMAC_TYPE_HIGH; 1188eb320b0eSRobert Watson goto set; 1189eb320b0eSRobert Watson } 1190eb320b0eSRobert Watson 1191eb320b0eSRobert Watson grade = MAC_LOMAC_TYPE_LOW; 1192eb320b0eSRobert Watson 1193eb320b0eSRobert Watson if (trusted_interfaces[0] == '\0' || 1194eb320b0eSRobert Watson !strvalid(trusted_interfaces, sizeof(trusted_interfaces))) 1195eb320b0eSRobert Watson goto set; 1196eb320b0eSRobert Watson 1197eb320b0eSRobert Watson bzero(tiflist, sizeof(tiflist)); 1198eb320b0eSRobert Watson for (p = trusted_interfaces, q = tiflist; *p != '\0'; p++, q++) 1199eb320b0eSRobert Watson if(*p != ' ' && *p != '\t') 1200eb320b0eSRobert Watson *q = *p; 1201eb320b0eSRobert Watson 1202eb320b0eSRobert Watson for (p = q = tiflist;; p++) { 1203eb320b0eSRobert Watson if (*p == ',' || *p == '\0') { 1204eb320b0eSRobert Watson len = p - q; 1205eb320b0eSRobert Watson if (len < IFNAMSIZ) { 1206eb320b0eSRobert Watson bzero(tifname, sizeof(tifname)); 1207eb320b0eSRobert Watson bcopy(q, tifname, len); 1208eb320b0eSRobert Watson if (strcmp(tifname, ifp->if_xname) == 0) { 1209eb320b0eSRobert Watson grade = MAC_LOMAC_TYPE_HIGH; 1210eb320b0eSRobert Watson break; 1211eb320b0eSRobert Watson } 1212eb320b0eSRobert Watson } 1213eb320b0eSRobert Watson else { 1214eb320b0eSRobert Watson *p = '\0'; 1215eb320b0eSRobert Watson printf("MAC/LOMAC warning: interface name " 1216eb320b0eSRobert Watson "\"%s\" is too long (must be < %d)\n", 1217eb320b0eSRobert Watson q, IFNAMSIZ); 1218eb320b0eSRobert Watson } 1219eb320b0eSRobert Watson if (*p == '\0') 1220eb320b0eSRobert Watson break; 1221eb320b0eSRobert Watson q = p + 1; 1222eb320b0eSRobert Watson } 1223eb320b0eSRobert Watson } 1224eb320b0eSRobert Watson set: 1225eb320b0eSRobert Watson lomac_set_single(dest, grade, 0); 1226eb320b0eSRobert Watson lomac_set_range(dest, grade, 0, grade, 0); 1227eb320b0eSRobert Watson } 1228eb320b0eSRobert Watson 1229eb320b0eSRobert Watson static void 1230eb320b0eSRobert Watson lomac_ifnet_create_mbuf(struct ifnet *ifp, struct label *ifplabel, 1231eb320b0eSRobert Watson struct mbuf *m, struct label *mlabel) 1232eb320b0eSRobert Watson { 1233eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1234eb320b0eSRobert Watson 1235eb320b0eSRobert Watson source = SLOT(ifplabel); 1236eb320b0eSRobert Watson dest = SLOT(mlabel); 1237eb320b0eSRobert Watson 1238eb320b0eSRobert Watson lomac_copy_single(source, dest); 1239eb320b0eSRobert Watson } 1240eb320b0eSRobert Watson 1241eb320b0eSRobert Watson static void 1242eb320b0eSRobert Watson lomac_ifnet_relabel(struct ucred *cred, struct ifnet *ifp, 1243eb320b0eSRobert Watson struct label *ifplabel, struct label *newlabel) 1244eb320b0eSRobert Watson { 1245eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1246eb320b0eSRobert Watson 1247eb320b0eSRobert Watson source = SLOT(newlabel); 1248eb320b0eSRobert Watson dest = SLOT(ifplabel); 1249eb320b0eSRobert Watson 1250eb320b0eSRobert Watson try_relabel(source, dest); 1251eb320b0eSRobert Watson } 1252eb320b0eSRobert Watson 1253db2661ceSRobert Watson static int 12543f1a7a90SRobert Watson lomac_inpcb_check_deliver(struct inpcb *inp, struct label *inplabel, 1255a557af22SRobert Watson struct mbuf *m, struct label *mlabel) 1256a557af22SRobert Watson { 1257a557af22SRobert Watson struct mac_lomac *p, *i; 1258a557af22SRobert Watson 12593f1a7a90SRobert Watson if (!lomac_enabled) 1260a557af22SRobert Watson return (0); 1261a557af22SRobert Watson 1262a557af22SRobert Watson p = SLOT(mlabel); 1263a557af22SRobert Watson i = SLOT(inplabel); 1264a557af22SRobert Watson 12653f1a7a90SRobert Watson return (lomac_equal_single(p, i) ? 0 : EACCES); 1266a557af22SRobert Watson } 1267a557af22SRobert Watson 12687fb179baSBjoern A. Zeeb static int 12697fb179baSBjoern A. Zeeb lomac_inpcb_check_visible(struct ucred *cred, struct inpcb *inp, 12707fb179baSBjoern A. Zeeb struct label *inplabel) 12717fb179baSBjoern A. Zeeb { 12727fb179baSBjoern A. Zeeb struct mac_lomac *subj, *obj; 12737fb179baSBjoern A. Zeeb 12747fb179baSBjoern A. Zeeb if (!lomac_enabled) 12757fb179baSBjoern A. Zeeb return (0); 12767fb179baSBjoern A. Zeeb 12777fb179baSBjoern A. Zeeb subj = SLOT(cred->cr_label); 12787fb179baSBjoern A. Zeeb obj = SLOT(inplabel); 12797fb179baSBjoern A. Zeeb 12807fb179baSBjoern A. Zeeb if (!lomac_dominate_single(obj, subj)) 12817fb179baSBjoern A. Zeeb return (ENOENT); 12827fb179baSBjoern A. Zeeb 12837fb179baSBjoern A. Zeeb return (0); 12847fb179baSBjoern A. Zeeb } 12857fb179baSBjoern A. Zeeb 1286eb320b0eSRobert Watson static void 1287eb320b0eSRobert Watson lomac_inpcb_create(struct socket *so, struct label *solabel, 1288eb320b0eSRobert Watson struct inpcb *inp, struct label *inplabel) 1289eb320b0eSRobert Watson { 1290eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1291eb320b0eSRobert Watson 1292eb320b0eSRobert Watson source = SLOT(solabel); 1293eb320b0eSRobert Watson dest = SLOT(inplabel); 1294eb320b0eSRobert Watson 1295eb320b0eSRobert Watson lomac_copy_single(source, dest); 1296eb320b0eSRobert Watson } 1297eb320b0eSRobert Watson 1298eb320b0eSRobert Watson static void 1299eb320b0eSRobert Watson lomac_inpcb_create_mbuf(struct inpcb *inp, struct label *inplabel, 1300eb320b0eSRobert Watson struct mbuf *m, struct label *mlabel) 1301eb320b0eSRobert Watson { 1302eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1303eb320b0eSRobert Watson 1304eb320b0eSRobert Watson source = SLOT(inplabel); 1305eb320b0eSRobert Watson dest = SLOT(mlabel); 1306eb320b0eSRobert Watson 1307eb320b0eSRobert Watson lomac_copy_single(source, dest); 1308eb320b0eSRobert Watson } 1309eb320b0eSRobert Watson 1310eb320b0eSRobert Watson static void 1311eb320b0eSRobert Watson lomac_inpcb_sosetlabel(struct socket *so, struct label *solabel, 1312eb320b0eSRobert Watson struct inpcb *inp, struct label *inplabel) 1313eb320b0eSRobert Watson { 1314eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1315eb320b0eSRobert Watson 13163de40469SRobert Watson SOCK_LOCK_ASSERT(so); 13173de40469SRobert Watson 1318eb320b0eSRobert Watson source = SLOT(solabel); 1319eb320b0eSRobert Watson dest = SLOT(inplabel); 1320eb320b0eSRobert Watson 1321eb320b0eSRobert Watson lomac_copy_single(source, dest); 1322eb320b0eSRobert Watson } 1323eb320b0eSRobert Watson 1324eb320b0eSRobert Watson static void 1325048e1287SRobert Watson lomac_ip6q_create(struct mbuf *m, struct label *mlabel, struct ip6q *q6, 1326048e1287SRobert Watson struct label *q6label) 1327048e1287SRobert Watson { 1328048e1287SRobert Watson struct mac_lomac *source, *dest; 1329048e1287SRobert Watson 1330048e1287SRobert Watson source = SLOT(mlabel); 1331048e1287SRobert Watson dest = SLOT(q6label); 1332048e1287SRobert Watson 1333048e1287SRobert Watson lomac_copy_single(source, dest); 1334048e1287SRobert Watson } 1335048e1287SRobert Watson 1336048e1287SRobert Watson static int 1337048e1287SRobert Watson lomac_ip6q_match(struct mbuf *m, struct label *mlabel, struct ip6q *q6, 1338048e1287SRobert Watson struct label *q6label) 1339048e1287SRobert Watson { 1340048e1287SRobert Watson struct mac_lomac *a, *b; 1341048e1287SRobert Watson 1342048e1287SRobert Watson a = SLOT(q6label); 1343048e1287SRobert Watson b = SLOT(mlabel); 1344048e1287SRobert Watson 1345048e1287SRobert Watson return (lomac_equal_single(a, b)); 1346048e1287SRobert Watson } 1347048e1287SRobert Watson 1348048e1287SRobert Watson static void 1349048e1287SRobert Watson lomac_ip6q_reassemble(struct ip6q *q6, struct label *q6label, struct mbuf *m, 1350048e1287SRobert Watson struct label *mlabel) 1351048e1287SRobert Watson { 1352048e1287SRobert Watson struct mac_lomac *source, *dest; 1353048e1287SRobert Watson 1354048e1287SRobert Watson source = SLOT(q6label); 1355048e1287SRobert Watson dest = SLOT(mlabel); 1356048e1287SRobert Watson 1357048e1287SRobert Watson /* Just use the head, since we require them all to match. */ 1358048e1287SRobert Watson lomac_copy_single(source, dest); 1359048e1287SRobert Watson } 1360048e1287SRobert Watson 1361048e1287SRobert Watson static void 1362048e1287SRobert Watson lomac_ip6q_update(struct mbuf *m, struct label *mlabel, struct ip6q *q6, 1363048e1287SRobert Watson struct label *q6label) 1364048e1287SRobert Watson { 1365048e1287SRobert Watson 1366048e1287SRobert Watson /* NOOP: we only accept matching labels, so no need to update */ 1367048e1287SRobert Watson } 1368048e1287SRobert Watson 1369048e1287SRobert Watson static void 137037f44cb4SRobert Watson lomac_ipq_create(struct mbuf *m, struct label *mlabel, struct ipq *q, 137137f44cb4SRobert Watson struct label *qlabel) 1372eb320b0eSRobert Watson { 1373eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1374eb320b0eSRobert Watson 1375eb320b0eSRobert Watson source = SLOT(mlabel); 137637f44cb4SRobert Watson dest = SLOT(qlabel); 1377eb320b0eSRobert Watson 1378eb320b0eSRobert Watson lomac_copy_single(source, dest); 1379eb320b0eSRobert Watson } 1380eb320b0eSRobert Watson 1381eb320b0eSRobert Watson static int 138237f44cb4SRobert Watson lomac_ipq_match(struct mbuf *m, struct label *mlabel, struct ipq *q, 138337f44cb4SRobert Watson struct label *qlabel) 1384eb320b0eSRobert Watson { 1385eb320b0eSRobert Watson struct mac_lomac *a, *b; 1386eb320b0eSRobert Watson 138737f44cb4SRobert Watson a = SLOT(qlabel); 1388eb320b0eSRobert Watson b = SLOT(mlabel); 1389eb320b0eSRobert Watson 1390eb320b0eSRobert Watson return (lomac_equal_single(a, b)); 1391eb320b0eSRobert Watson } 1392eb320b0eSRobert Watson 1393eb320b0eSRobert Watson static void 139437f44cb4SRobert Watson lomac_ipq_reassemble(struct ipq *q, struct label *qlabel, struct mbuf *m, 139537f44cb4SRobert Watson struct label *mlabel) 1396eb320b0eSRobert Watson { 1397eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1398eb320b0eSRobert Watson 139937f44cb4SRobert Watson source = SLOT(qlabel); 1400eb320b0eSRobert Watson dest = SLOT(mlabel); 1401eb320b0eSRobert Watson 1402eb320b0eSRobert Watson /* Just use the head, since we require them all to match. */ 1403eb320b0eSRobert Watson lomac_copy_single(source, dest); 1404eb320b0eSRobert Watson } 1405eb320b0eSRobert Watson 1406eb320b0eSRobert Watson static void 140737f44cb4SRobert Watson lomac_ipq_update(struct mbuf *m, struct label *mlabel, struct ipq *q, 140837f44cb4SRobert Watson struct label *qlabel) 1409eb320b0eSRobert Watson { 1410eb320b0eSRobert Watson 1411eb320b0eSRobert Watson /* NOOP: we only accept matching labels, so no need to update */ 1412eb320b0eSRobert Watson } 1413eb320b0eSRobert Watson 1414a557af22SRobert Watson static int 14153f1a7a90SRobert Watson lomac_kld_check_load(struct ucred *cred, struct vnode *vp, 141678007886SRobert Watson struct label *vplabel) 1417db2661ceSRobert Watson { 1418db2661ceSRobert Watson struct mac_lomac *subj, *obj; 1419db2661ceSRobert Watson 14203f1a7a90SRobert Watson if (!lomac_enabled) 1421db2661ceSRobert Watson return (0); 1422db2661ceSRobert Watson 1423eca8a663SRobert Watson subj = SLOT(cred->cr_label); 142478007886SRobert Watson obj = SLOT(vplabel); 1425db2661ceSRobert Watson 14263f1a7a90SRobert Watson if (lomac_subject_privileged(subj)) 1427db2661ceSRobert Watson return (EPERM); 1428db2661ceSRobert Watson 14293f1a7a90SRobert Watson if (!lomac_high_single(obj)) 1430db2661ceSRobert Watson return (EACCES); 1431db2661ceSRobert Watson 1432db2661ceSRobert Watson return (0); 1433db2661ceSRobert Watson } 1434db2661ceSRobert Watson 1435eb320b0eSRobert Watson static void 1436eb320b0eSRobert Watson lomac_mount_create(struct ucred *cred, struct mount *mp, 1437eb320b0eSRobert Watson struct label *mplabel) 1438eb320b0eSRobert Watson { 1439eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1440eb320b0eSRobert Watson 1441eb320b0eSRobert Watson source = SLOT(cred->cr_label); 1442eb320b0eSRobert Watson dest = SLOT(mplabel); 1443eb320b0eSRobert Watson lomac_copy_single(source, dest); 1444eb320b0eSRobert Watson } 1445eb320b0eSRobert Watson 1446eb320b0eSRobert Watson static void 1447eb320b0eSRobert Watson lomac_netinet_arp_send(struct ifnet *ifp, struct label *ifplabel, 1448eb320b0eSRobert Watson struct mbuf *m, struct label *mlabel) 1449eb320b0eSRobert Watson { 1450eb320b0eSRobert Watson struct mac_lomac *dest; 1451eb320b0eSRobert Watson 1452eb320b0eSRobert Watson dest = SLOT(mlabel); 1453eb320b0eSRobert Watson 1454eb320b0eSRobert Watson lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0); 1455eb320b0eSRobert Watson } 1456eb320b0eSRobert Watson 1457eb320b0eSRobert Watson static void 1458eb320b0eSRobert Watson lomac_netinet_firewall_reply(struct mbuf *mrecv, struct label *mrecvlabel, 1459eb320b0eSRobert Watson struct mbuf *msend, struct label *msendlabel) 1460eb320b0eSRobert Watson { 1461eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1462eb320b0eSRobert Watson 1463eb320b0eSRobert Watson source = SLOT(mrecvlabel); 1464eb320b0eSRobert Watson dest = SLOT(msendlabel); 1465eb320b0eSRobert Watson 1466eb320b0eSRobert Watson lomac_copy_single(source, dest); 1467eb320b0eSRobert Watson } 1468eb320b0eSRobert Watson 1469eb320b0eSRobert Watson static void 1470eb320b0eSRobert Watson lomac_netinet_firewall_send(struct mbuf *m, struct label *mlabel) 1471eb320b0eSRobert Watson { 1472eb320b0eSRobert Watson struct mac_lomac *dest; 1473eb320b0eSRobert Watson 1474eb320b0eSRobert Watson dest = SLOT(mlabel); 1475eb320b0eSRobert Watson 1476bc5ade0dSPedro F. Giffuni /* XXX: where is the label for the firewall really coming from? */ 1477eb320b0eSRobert Watson lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0); 1478eb320b0eSRobert Watson } 1479eb320b0eSRobert Watson 1480eb320b0eSRobert Watson static void 1481eb320b0eSRobert Watson lomac_netinet_fragment(struct mbuf *m, struct label *mlabel, 1482eb320b0eSRobert Watson struct mbuf *frag, struct label *fraglabel) 1483eb320b0eSRobert Watson { 1484eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1485eb320b0eSRobert Watson 1486eb320b0eSRobert Watson source = SLOT(mlabel); 1487eb320b0eSRobert Watson dest = SLOT(fraglabel); 1488eb320b0eSRobert Watson 1489eb320b0eSRobert Watson lomac_copy_single(source, dest); 1490eb320b0eSRobert Watson } 1491eb320b0eSRobert Watson 1492eb320b0eSRobert Watson static void 1493eb320b0eSRobert Watson lomac_netinet_icmp_reply(struct mbuf *mrecv, struct label *mrecvlabel, 1494eb320b0eSRobert Watson struct mbuf *msend, struct label *msendlabel) 1495eb320b0eSRobert Watson { 1496eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1497eb320b0eSRobert Watson 1498eb320b0eSRobert Watson source = SLOT(mrecvlabel); 1499eb320b0eSRobert Watson dest = SLOT(msendlabel); 1500eb320b0eSRobert Watson 1501eb320b0eSRobert Watson lomac_copy_single(source, dest); 1502eb320b0eSRobert Watson } 1503eb320b0eSRobert Watson 1504eb320b0eSRobert Watson static void 1505eb320b0eSRobert Watson lomac_netinet_igmp_send(struct ifnet *ifp, struct label *ifplabel, 1506eb320b0eSRobert Watson struct mbuf *m, struct label *mlabel) 1507eb320b0eSRobert Watson { 1508eb320b0eSRobert Watson struct mac_lomac *dest; 1509eb320b0eSRobert Watson 1510eb320b0eSRobert Watson dest = SLOT(mlabel); 1511eb320b0eSRobert Watson 1512eb320b0eSRobert Watson lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0); 1513eb320b0eSRobert Watson } 1514eb320b0eSRobert Watson 1515eb320b0eSRobert Watson static void 1516eb320b0eSRobert Watson lomac_netinet6_nd6_send(struct ifnet *ifp, struct label *ifplabel, 1517eb320b0eSRobert Watson struct mbuf *m, struct label *mlabel) 1518eb320b0eSRobert Watson { 1519eb320b0eSRobert Watson struct mac_lomac *dest; 1520eb320b0eSRobert Watson 1521eb320b0eSRobert Watson dest = SLOT(mlabel); 1522eb320b0eSRobert Watson 1523eb320b0eSRobert Watson lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0); 1524eb320b0eSRobert Watson } 1525eb320b0eSRobert Watson 1526db2661ceSRobert Watson static int 15273f1a7a90SRobert Watson lomac_pipe_check_ioctl(struct ucred *cred, struct pipepair *pp, 152878007886SRobert Watson struct label *pplabel, unsigned long cmd, void /* caddr_t */ *data) 1529db2661ceSRobert Watson { 1530db2661ceSRobert Watson 15313f1a7a90SRobert Watson if (!lomac_enabled) 1532db2661ceSRobert Watson return (0); 1533db2661ceSRobert Watson 1534db2661ceSRobert Watson /* XXX: This will be implemented soon... */ 1535db2661ceSRobert Watson 1536db2661ceSRobert Watson return (0); 1537db2661ceSRobert Watson } 1538db2661ceSRobert Watson 1539db2661ceSRobert Watson static int 15403f1a7a90SRobert Watson lomac_pipe_check_read(struct ucred *cred, struct pipepair *pp, 154178007886SRobert Watson struct label *pplabel) 1542db2661ceSRobert Watson { 1543db2661ceSRobert Watson struct mac_lomac *subj, *obj; 1544db2661ceSRobert Watson 15453f1a7a90SRobert Watson if (!lomac_enabled) 1546db2661ceSRobert Watson return (0); 1547db2661ceSRobert Watson 1548eca8a663SRobert Watson subj = SLOT(cred->cr_label); 154978007886SRobert Watson obj = SLOT(pplabel); 1550db2661ceSRobert Watson 15513f1a7a90SRobert Watson if (!lomac_dominate_single(obj, subj)) 1552db2661ceSRobert Watson return (maybe_demote(subj, obj, "reading", "pipe", NULL)); 1553db2661ceSRobert Watson 1554db2661ceSRobert Watson return (0); 1555db2661ceSRobert Watson } 1556db2661ceSRobert Watson 1557db2661ceSRobert Watson static int 15583f1a7a90SRobert Watson lomac_pipe_check_relabel(struct ucred *cred, struct pipepair *pp, 155978007886SRobert Watson struct label *pplabel, struct label *newlabel) 1560db2661ceSRobert Watson { 1561db2661ceSRobert Watson struct mac_lomac *subj, *obj, *new; 1562db2661ceSRobert Watson int error; 1563db2661ceSRobert Watson 1564db2661ceSRobert Watson new = SLOT(newlabel); 1565eca8a663SRobert Watson subj = SLOT(cred->cr_label); 156678007886SRobert Watson obj = SLOT(pplabel); 1567db2661ceSRobert Watson 1568db2661ceSRobert Watson /* 15693f1a7a90SRobert Watson * If there is a LOMAC label update for a pipe, it must be a single 15703f1a7a90SRobert Watson * update. 1571db2661ceSRobert Watson */ 1572db2661ceSRobert Watson error = lomac_atmostflags(new, MAC_LOMAC_FLAG_SINGLE); 1573db2661ceSRobert Watson if (error) 1574db2661ceSRobert Watson return (error); 1575db2661ceSRobert Watson 1576db2661ceSRobert Watson /* 1577db2661ceSRobert Watson * To perform a relabel of a pipe (LOMAC label or not), LOMAC must 1578db2661ceSRobert Watson * authorize the relabel. 1579db2661ceSRobert Watson */ 15803f1a7a90SRobert Watson if (!lomac_single_in_range(obj, subj)) 1581db2661ceSRobert Watson return (EPERM); 1582db2661ceSRobert Watson 1583db2661ceSRobert Watson /* 1584db2661ceSRobert Watson * If the LOMAC label is to be changed, authorize as appropriate. 1585db2661ceSRobert Watson */ 1586db2661ceSRobert Watson if (new->ml_flags & MAC_LOMAC_FLAG_SINGLE) { 1587db2661ceSRobert Watson /* 1588db2661ceSRobert Watson * To change the LOMAC label on a pipe, the new pipe label 1589db2661ceSRobert Watson * must be in the subject range. 1590db2661ceSRobert Watson */ 15913f1a7a90SRobert Watson if (!lomac_single_in_range(new, subj)) 1592db2661ceSRobert Watson return (EPERM); 1593db2661ceSRobert Watson 1594db2661ceSRobert Watson /* 1595db2661ceSRobert Watson * To change the LOMAC label on a pipe to be EQUAL, the 1596db2661ceSRobert Watson * subject must have appropriate privilege. 1597db2661ceSRobert Watson */ 15983f1a7a90SRobert Watson if (lomac_contains_equal(new)) { 15993f1a7a90SRobert Watson error = lomac_subject_privileged(subj); 1600db2661ceSRobert Watson if (error) 1601db2661ceSRobert Watson return (error); 1602db2661ceSRobert Watson } 1603db2661ceSRobert Watson } 1604db2661ceSRobert Watson 1605db2661ceSRobert Watson return (0); 1606db2661ceSRobert Watson } 1607db2661ceSRobert Watson 1608db2661ceSRobert Watson static int 16093f1a7a90SRobert Watson lomac_pipe_check_write(struct ucred *cred, struct pipepair *pp, 161078007886SRobert Watson struct label *pplabel) 1611db2661ceSRobert Watson { 1612db2661ceSRobert Watson struct mac_lomac *subj, *obj; 1613db2661ceSRobert Watson 16143f1a7a90SRobert Watson if (!lomac_enabled) 1615db2661ceSRobert Watson return (0); 1616db2661ceSRobert Watson 1617eca8a663SRobert Watson subj = SLOT(cred->cr_label); 161878007886SRobert Watson obj = SLOT(pplabel); 1619db2661ceSRobert Watson 16203f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 1621db2661ceSRobert Watson return (EACCES); 1622db2661ceSRobert Watson 1623db2661ceSRobert Watson return (0); 1624db2661ceSRobert Watson } 1625db2661ceSRobert Watson 1626eb320b0eSRobert Watson static void 1627eb320b0eSRobert Watson lomac_pipe_create(struct ucred *cred, struct pipepair *pp, 1628eb320b0eSRobert Watson struct label *pplabel) 1629db2661ceSRobert Watson { 1630eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1631db2661ceSRobert Watson 1632eb320b0eSRobert Watson source = SLOT(cred->cr_label); 1633eb320b0eSRobert Watson dest = SLOT(pplabel); 1634db2661ceSRobert Watson 1635eb320b0eSRobert Watson lomac_copy_single(source, dest); 1636db2661ceSRobert Watson } 1637db2661ceSRobert Watson 1638eb320b0eSRobert Watson static void 1639eb320b0eSRobert Watson lomac_pipe_relabel(struct ucred *cred, struct pipepair *pp, 1640eb320b0eSRobert Watson struct label *pplabel, struct label *newlabel) 1641db2661ceSRobert Watson { 1642eb320b0eSRobert Watson struct mac_lomac *source, *dest; 1643db2661ceSRobert Watson 1644eb320b0eSRobert Watson source = SLOT(newlabel); 1645eb320b0eSRobert Watson dest = SLOT(pplabel); 1646db2661ceSRobert Watson 1647eb320b0eSRobert Watson try_relabel(source, dest); 1648db2661ceSRobert Watson } 1649db2661ceSRobert Watson 1650c14d15aeSRobert Watson /* 1651c14d15aeSRobert Watson * Some system privileges are allowed regardless of integrity grade; others 1652c14d15aeSRobert Watson * are allowed only when running with privilege with respect to the LOMAC 1653c14d15aeSRobert Watson * policy as they might otherwise allow bypassing of the integrity policy. 1654c14d15aeSRobert Watson */ 1655c14d15aeSRobert Watson static int 16563f1a7a90SRobert Watson lomac_priv_check(struct ucred *cred, int priv) 1657c14d15aeSRobert Watson { 1658c14d15aeSRobert Watson struct mac_lomac *subj; 1659c14d15aeSRobert Watson int error; 1660c14d15aeSRobert Watson 16613f1a7a90SRobert Watson if (!lomac_enabled) 1662c14d15aeSRobert Watson return (0); 1663c14d15aeSRobert Watson 1664c14d15aeSRobert Watson /* 1665c14d15aeSRobert Watson * Exempt only specific privileges from the LOMAC integrity policy. 1666c14d15aeSRobert Watson */ 1667c14d15aeSRobert Watson switch (priv) { 1668c14d15aeSRobert Watson case PRIV_KTRACE: 1669c14d15aeSRobert Watson case PRIV_MSGBUF: 1670c14d15aeSRobert Watson 1671c14d15aeSRobert Watson /* 1672c14d15aeSRobert Watson * Allow processes to manipulate basic process audit properties, and 1673c14d15aeSRobert Watson * to submit audit records. 1674c14d15aeSRobert Watson */ 1675c14d15aeSRobert Watson case PRIV_AUDIT_GETAUDIT: 1676c14d15aeSRobert Watson case PRIV_AUDIT_SETAUDIT: 1677c14d15aeSRobert Watson case PRIV_AUDIT_SUBMIT: 1678c14d15aeSRobert Watson 1679c14d15aeSRobert Watson /* 1680c14d15aeSRobert Watson * Allow processes to manipulate their regular UNIX credentials. 1681c14d15aeSRobert Watson */ 1682c14d15aeSRobert Watson case PRIV_CRED_SETUID: 1683c14d15aeSRobert Watson case PRIV_CRED_SETEUID: 1684c14d15aeSRobert Watson case PRIV_CRED_SETGID: 1685c14d15aeSRobert Watson case PRIV_CRED_SETEGID: 1686c14d15aeSRobert Watson case PRIV_CRED_SETGROUPS: 1687c14d15aeSRobert Watson case PRIV_CRED_SETREUID: 1688c14d15aeSRobert Watson case PRIV_CRED_SETREGID: 1689c14d15aeSRobert Watson case PRIV_CRED_SETRESUID: 1690c14d15aeSRobert Watson case PRIV_CRED_SETRESGID: 1691c14d15aeSRobert Watson 1692c14d15aeSRobert Watson /* 1693c14d15aeSRobert Watson * Allow processes to perform system monitoring. 1694c14d15aeSRobert Watson */ 1695c14d15aeSRobert Watson case PRIV_SEEOTHERGIDS: 1696c14d15aeSRobert Watson case PRIV_SEEOTHERUIDS: 1697c14d15aeSRobert Watson break; 1698c14d15aeSRobert Watson 1699c14d15aeSRobert Watson /* 1700c14d15aeSRobert Watson * Allow access to general process debugging facilities. We 1701c14d15aeSRobert Watson * separately control debugging based on MAC label. 1702c14d15aeSRobert Watson */ 1703c14d15aeSRobert Watson case PRIV_DEBUG_DIFFCRED: 1704c14d15aeSRobert Watson case PRIV_DEBUG_SUGID: 1705c14d15aeSRobert Watson case PRIV_DEBUG_UNPRIV: 1706c14d15aeSRobert Watson 1707c14d15aeSRobert Watson /* 1708c14d15aeSRobert Watson * Allow manipulating jails. 1709c14d15aeSRobert Watson */ 1710c14d15aeSRobert Watson case PRIV_JAIL_ATTACH: 1711c14d15aeSRobert Watson 1712c14d15aeSRobert Watson /* 1713c14d15aeSRobert Watson * Allow privilege with respect to the Partition policy, but not the 1714c14d15aeSRobert Watson * Privs policy. 1715c14d15aeSRobert Watson */ 1716c14d15aeSRobert Watson case PRIV_MAC_PARTITION: 1717c14d15aeSRobert Watson 1718c14d15aeSRobert Watson /* 1719c14d15aeSRobert Watson * Allow privilege with respect to process resource limits and login 1720c14d15aeSRobert Watson * context. 1721c14d15aeSRobert Watson */ 1722c14d15aeSRobert Watson case PRIV_PROC_LIMIT: 1723c14d15aeSRobert Watson case PRIV_PROC_SETLOGIN: 1724c14d15aeSRobert Watson case PRIV_PROC_SETRLIMIT: 1725c14d15aeSRobert Watson 1726c14d15aeSRobert Watson /* 1727c14d15aeSRobert Watson * Allow System V and POSIX IPC privileges. 1728c14d15aeSRobert Watson */ 1729c14d15aeSRobert Watson case PRIV_IPC_READ: 1730c14d15aeSRobert Watson case PRIV_IPC_WRITE: 1731c14d15aeSRobert Watson case PRIV_IPC_ADMIN: 1732c14d15aeSRobert Watson case PRIV_IPC_MSGSIZE: 1733c14d15aeSRobert Watson case PRIV_MQ_ADMIN: 1734c14d15aeSRobert Watson 1735c14d15aeSRobert Watson /* 1736c14d15aeSRobert Watson * Allow certain scheduler manipulations -- possibly this should be 1737c14d15aeSRobert Watson * controlled by more fine-grained policy, as potentially low 1738c14d15aeSRobert Watson * integrity processes can deny CPU to higher integrity ones. 1739c14d15aeSRobert Watson */ 1740c14d15aeSRobert Watson case PRIV_SCHED_DIFFCRED: 1741c14d15aeSRobert Watson case PRIV_SCHED_SETPRIORITY: 1742c14d15aeSRobert Watson case PRIV_SCHED_RTPRIO: 1743c14d15aeSRobert Watson case PRIV_SCHED_SETPOLICY: 1744c14d15aeSRobert Watson case PRIV_SCHED_SET: 1745c14d15aeSRobert Watson case PRIV_SCHED_SETPARAM: 1746c14d15aeSRobert Watson 1747c14d15aeSRobert Watson /* 1748c14d15aeSRobert Watson * More IPC privileges. 1749c14d15aeSRobert Watson */ 1750c14d15aeSRobert Watson case PRIV_SEM_WRITE: 1751c14d15aeSRobert Watson 1752c14d15aeSRobert Watson /* 1753c14d15aeSRobert Watson * Allow signaling privileges subject to integrity policy. 1754c14d15aeSRobert Watson */ 1755c14d15aeSRobert Watson case PRIV_SIGNAL_DIFFCRED: 1756c14d15aeSRobert Watson case PRIV_SIGNAL_SUGID: 1757c14d15aeSRobert Watson 1758c14d15aeSRobert Watson /* 1759c14d15aeSRobert Watson * Allow access to only limited sysctls from lower integrity levels; 1760c14d15aeSRobert Watson * piggy-back on the Jail definition. 1761c14d15aeSRobert Watson */ 1762c14d15aeSRobert Watson case PRIV_SYSCTL_WRITEJAIL: 1763c14d15aeSRobert Watson 1764c14d15aeSRobert Watson /* 1765c14d15aeSRobert Watson * Allow TTY-based privileges, subject to general device access using 1766c14d15aeSRobert Watson * labels on TTY device nodes, but not console privilege. 1767c14d15aeSRobert Watson */ 1768c14d15aeSRobert Watson case PRIV_TTY_DRAINWAIT: 1769c14d15aeSRobert Watson case PRIV_TTY_DTRWAIT: 1770c14d15aeSRobert Watson case PRIV_TTY_EXCLUSIVE: 1771c14d15aeSRobert Watson case PRIV_TTY_STI: 1772c14d15aeSRobert Watson case PRIV_TTY_SETA: 1773c14d15aeSRobert Watson 1774c14d15aeSRobert Watson /* 1775c14d15aeSRobert Watson * Grant most VFS privileges, as almost all are in practice bounded 1776c14d15aeSRobert Watson * by more specific checks using labels. 1777c14d15aeSRobert Watson */ 1778c14d15aeSRobert Watson case PRIV_VFS_READ: 1779c14d15aeSRobert Watson case PRIV_VFS_WRITE: 1780c14d15aeSRobert Watson case PRIV_VFS_ADMIN: 1781c14d15aeSRobert Watson case PRIV_VFS_EXEC: 1782c14d15aeSRobert Watson case PRIV_VFS_LOOKUP: 1783c14d15aeSRobert Watson case PRIV_VFS_CHFLAGS_DEV: 1784c14d15aeSRobert Watson case PRIV_VFS_CHOWN: 1785c14d15aeSRobert Watson case PRIV_VFS_CHROOT: 1786c14d15aeSRobert Watson case PRIV_VFS_RETAINSUGID: 1787c14d15aeSRobert Watson case PRIV_VFS_EXCEEDQUOTA: 1788c14d15aeSRobert Watson case PRIV_VFS_FCHROOT: 1789c14d15aeSRobert Watson case PRIV_VFS_FHOPEN: 1790c14d15aeSRobert Watson case PRIV_VFS_FHSTATFS: 1791c14d15aeSRobert Watson case PRIV_VFS_GENERATION: 1792c14d15aeSRobert Watson case PRIV_VFS_GETFH: 1793c14d15aeSRobert Watson case PRIV_VFS_GETQUOTA: 1794c14d15aeSRobert Watson case PRIV_VFS_LINK: 1795c14d15aeSRobert Watson case PRIV_VFS_MOUNT: 1796c14d15aeSRobert Watson case PRIV_VFS_MOUNT_OWNER: 1797c14d15aeSRobert Watson case PRIV_VFS_MOUNT_PERM: 1798c14d15aeSRobert Watson case PRIV_VFS_MOUNT_SUIDDIR: 1799c14d15aeSRobert Watson case PRIV_VFS_MOUNT_NONUSER: 1800c14d15aeSRobert Watson case PRIV_VFS_SETGID: 1801c14d15aeSRobert Watson case PRIV_VFS_STICKYFILE: 1802c14d15aeSRobert Watson case PRIV_VFS_SYSFLAGS: 1803c14d15aeSRobert Watson case PRIV_VFS_UNMOUNT: 1804c14d15aeSRobert Watson 1805c14d15aeSRobert Watson /* 1806c14d15aeSRobert Watson * Allow VM privileges; it would be nice if these were subject to 1807c14d15aeSRobert Watson * resource limits. 1808c14d15aeSRobert Watson */ 1809c14d15aeSRobert Watson case PRIV_VM_MADV_PROTECT: 1810c14d15aeSRobert Watson case PRIV_VM_MLOCK: 1811c14d15aeSRobert Watson case PRIV_VM_MUNLOCK: 18123364c323SKonstantin Belousov case PRIV_VM_SWAP_NOQUOTA: 18133364c323SKonstantin Belousov case PRIV_VM_SWAP_NORLIMIT: 1814c14d15aeSRobert Watson 1815c14d15aeSRobert Watson /* 1816c14d15aeSRobert Watson * Allow some but not all network privileges. In general, dont allow 1817c14d15aeSRobert Watson * reconfiguring the network stack, just normal use. 1818c14d15aeSRobert Watson */ 1819c14d15aeSRobert Watson case PRIV_NETINET_RESERVEDPORT: 1820c14d15aeSRobert Watson case PRIV_NETINET_RAW: 1821c14d15aeSRobert Watson case PRIV_NETINET_REUSEPORT: 1822c14d15aeSRobert Watson break; 1823c14d15aeSRobert Watson 1824c14d15aeSRobert Watson /* 1825c14d15aeSRobert Watson * All remaining system privileges are allow only if the process 1826c14d15aeSRobert Watson * holds privilege with respect to the LOMAC policy. 1827c14d15aeSRobert Watson */ 1828c14d15aeSRobert Watson default: 1829c14d15aeSRobert Watson subj = SLOT(cred->cr_label); 18303f1a7a90SRobert Watson error = lomac_subject_privileged(subj); 1831c14d15aeSRobert Watson if (error) 1832c14d15aeSRobert Watson return (error); 1833c14d15aeSRobert Watson } 1834c14d15aeSRobert Watson return (0); 1835c14d15aeSRobert Watson } 1836c14d15aeSRobert Watson 1837eb320b0eSRobert Watson static int 1838eb320b0eSRobert Watson lomac_proc_check_debug(struct ucred *cred, struct proc *p) 1839eb320b0eSRobert Watson { 1840eb320b0eSRobert Watson struct mac_lomac *subj, *obj; 1841eb320b0eSRobert Watson 1842eb320b0eSRobert Watson if (!lomac_enabled) 1843eb320b0eSRobert Watson return (0); 1844eb320b0eSRobert Watson 1845eb320b0eSRobert Watson subj = SLOT(cred->cr_label); 1846eb320b0eSRobert Watson obj = SLOT(p->p_ucred->cr_label); 1847eb320b0eSRobert Watson 1848eb320b0eSRobert Watson /* XXX: range checks */ 1849eb320b0eSRobert Watson if (!lomac_dominate_single(obj, subj)) 1850eb320b0eSRobert Watson return (ESRCH); 1851eb320b0eSRobert Watson if (!lomac_subject_dominate(subj, obj)) 1852eb320b0eSRobert Watson return (EACCES); 1853eb320b0eSRobert Watson 1854eb320b0eSRobert Watson return (0); 1855eb320b0eSRobert Watson } 1856eb320b0eSRobert Watson 1857eb320b0eSRobert Watson static int 1858eb320b0eSRobert Watson lomac_proc_check_sched(struct ucred *cred, struct proc *p) 1859eb320b0eSRobert Watson { 1860eb320b0eSRobert Watson struct mac_lomac *subj, *obj; 1861eb320b0eSRobert Watson 1862eb320b0eSRobert Watson if (!lomac_enabled) 1863eb320b0eSRobert Watson return (0); 1864eb320b0eSRobert Watson 1865eb320b0eSRobert Watson subj = SLOT(cred->cr_label); 1866eb320b0eSRobert Watson obj = SLOT(p->p_ucred->cr_label); 1867eb320b0eSRobert Watson 1868eb320b0eSRobert Watson /* XXX: range checks */ 1869eb320b0eSRobert Watson if (!lomac_dominate_single(obj, subj)) 1870eb320b0eSRobert Watson return (ESRCH); 1871eb320b0eSRobert Watson if (!lomac_subject_dominate(subj, obj)) 1872eb320b0eSRobert Watson return (EACCES); 1873eb320b0eSRobert Watson 1874eb320b0eSRobert Watson return (0); 1875eb320b0eSRobert Watson } 1876eb320b0eSRobert Watson 1877eb320b0eSRobert Watson static int 1878eb320b0eSRobert Watson lomac_proc_check_signal(struct ucred *cred, struct proc *p, int signum) 1879eb320b0eSRobert Watson { 1880eb320b0eSRobert Watson struct mac_lomac *subj, *obj; 1881eb320b0eSRobert Watson 1882eb320b0eSRobert Watson if (!lomac_enabled) 1883eb320b0eSRobert Watson return (0); 1884eb320b0eSRobert Watson 1885eb320b0eSRobert Watson subj = SLOT(cred->cr_label); 1886eb320b0eSRobert Watson obj = SLOT(p->p_ucred->cr_label); 1887eb320b0eSRobert Watson 1888eb320b0eSRobert Watson /* XXX: range checks */ 1889eb320b0eSRobert Watson if (!lomac_dominate_single(obj, subj)) 1890eb320b0eSRobert Watson return (ESRCH); 1891eb320b0eSRobert Watson if (!lomac_subject_dominate(subj, obj)) 1892eb320b0eSRobert Watson return (EACCES); 1893eb320b0eSRobert Watson 1894eb320b0eSRobert Watson return (0); 1895eb320b0eSRobert Watson } 1896eb320b0eSRobert Watson 1897eb320b0eSRobert Watson static void 1898eb320b0eSRobert Watson lomac_proc_destroy_label(struct label *label) 1899eb320b0eSRobert Watson { 1900eb320b0eSRobert Watson 1901eb320b0eSRobert Watson mtx_destroy(&PSLOT(label)->mtx); 19021ede983cSDag-Erling Smørgrav free(PSLOT(label), M_LOMAC); 1903eb320b0eSRobert Watson PSLOT_SET(label, NULL); 1904eb320b0eSRobert Watson } 1905eb320b0eSRobert Watson 1906eb320b0eSRobert Watson static void 1907eb320b0eSRobert Watson lomac_proc_init_label(struct label *label) 1908eb320b0eSRobert Watson { 1909eb320b0eSRobert Watson 1910eb320b0eSRobert Watson PSLOT_SET(label, malloc(sizeof(struct mac_lomac_proc), M_LOMAC, 1911eb320b0eSRobert Watson M_ZERO | M_WAITOK)); 1912eb320b0eSRobert Watson mtx_init(&PSLOT(label)->mtx, "MAC/Lomac proc lock", NULL, MTX_DEF); 1913eb320b0eSRobert Watson } 1914eb320b0eSRobert Watson 1915eb320b0eSRobert Watson static int 1916eb320b0eSRobert Watson lomac_socket_check_deliver(struct socket *so, struct label *solabel, 1917eb320b0eSRobert Watson struct mbuf *m, struct label *mlabel) 1918eb320b0eSRobert Watson { 1919eb320b0eSRobert Watson struct mac_lomac *p, *s; 19203de40469SRobert Watson int error; 1921eb320b0eSRobert Watson 1922eb320b0eSRobert Watson if (!lomac_enabled) 1923eb320b0eSRobert Watson return (0); 1924eb320b0eSRobert Watson 1925eb320b0eSRobert Watson p = SLOT(mlabel); 1926eb320b0eSRobert Watson s = SLOT(solabel); 1927eb320b0eSRobert Watson 19283de40469SRobert Watson SOCK_LOCK(so); 19293de40469SRobert Watson error = lomac_equal_single(p, s) ? 0 : EACCES; 19303de40469SRobert Watson SOCK_UNLOCK(so); 19313de40469SRobert Watson return (error); 1932eb320b0eSRobert Watson } 1933eb320b0eSRobert Watson 1934eb320b0eSRobert Watson static int 1935eb320b0eSRobert Watson lomac_socket_check_relabel(struct ucred *cred, struct socket *so, 1936eb320b0eSRobert Watson struct label *solabel, struct label *newlabel) 1937eb320b0eSRobert Watson { 1938eb320b0eSRobert Watson struct mac_lomac *subj, *obj, *new; 1939eb320b0eSRobert Watson int error; 1940eb320b0eSRobert Watson 19413de40469SRobert Watson SOCK_LOCK_ASSERT(so); 19423de40469SRobert Watson 1943eb320b0eSRobert Watson new = SLOT(newlabel); 1944eb320b0eSRobert Watson subj = SLOT(cred->cr_label); 1945eb320b0eSRobert Watson obj = SLOT(solabel); 1946eb320b0eSRobert Watson 1947eb320b0eSRobert Watson /* 1948eb320b0eSRobert Watson * If there is a LOMAC label update for the socket, it may be an 1949eb320b0eSRobert Watson * update of single. 1950eb320b0eSRobert Watson */ 1951eb320b0eSRobert Watson error = lomac_atmostflags(new, MAC_LOMAC_FLAG_SINGLE); 1952eb320b0eSRobert Watson if (error) 1953eb320b0eSRobert Watson return (error); 1954eb320b0eSRobert Watson 1955eb320b0eSRobert Watson /* 1956eb320b0eSRobert Watson * To relabel a socket, the old socket single must be in the subject 1957eb320b0eSRobert Watson * range. 1958eb320b0eSRobert Watson */ 1959eb320b0eSRobert Watson if (!lomac_single_in_range(obj, subj)) 1960eb320b0eSRobert Watson return (EPERM); 1961eb320b0eSRobert Watson 1962eb320b0eSRobert Watson /* 1963eb320b0eSRobert Watson * If the LOMAC label is to be changed, authorize as appropriate. 1964eb320b0eSRobert Watson */ 1965eb320b0eSRobert Watson if (new->ml_flags & MAC_LOMAC_FLAG_SINGLE) { 1966eb320b0eSRobert Watson /* 1967eb320b0eSRobert Watson * To relabel a socket, the new socket single must be in the 1968eb320b0eSRobert Watson * subject range. 1969eb320b0eSRobert Watson */ 1970eb320b0eSRobert Watson if (!lomac_single_in_range(new, subj)) 1971eb320b0eSRobert Watson return (EPERM); 1972eb320b0eSRobert Watson 1973eb320b0eSRobert Watson /* 1974eb320b0eSRobert Watson * To change the LOMAC label on the socket to contain EQUAL, 1975eb320b0eSRobert Watson * the subject must have appropriate privilege. 1976eb320b0eSRobert Watson */ 1977eb320b0eSRobert Watson if (lomac_contains_equal(new)) { 1978eb320b0eSRobert Watson error = lomac_subject_privileged(subj); 1979eb320b0eSRobert Watson if (error) 1980eb320b0eSRobert Watson return (error); 1981eb320b0eSRobert Watson } 1982eb320b0eSRobert Watson } 1983eb320b0eSRobert Watson 1984eb320b0eSRobert Watson return (0); 1985eb320b0eSRobert Watson } 1986eb320b0eSRobert Watson 1987eb320b0eSRobert Watson static int 1988eb320b0eSRobert Watson lomac_socket_check_visible(struct ucred *cred, struct socket *so, 1989eb320b0eSRobert Watson struct label *solabel) 1990eb320b0eSRobert Watson { 1991eb320b0eSRobert Watson struct mac_lomac *subj, *obj; 1992eb320b0eSRobert Watson 1993eb320b0eSRobert Watson if (!lomac_enabled) 1994eb320b0eSRobert Watson return (0); 1995eb320b0eSRobert Watson 1996eb320b0eSRobert Watson subj = SLOT(cred->cr_label); 1997eb320b0eSRobert Watson obj = SLOT(solabel); 1998eb320b0eSRobert Watson 19993de40469SRobert Watson SOCK_LOCK(so); 20003de40469SRobert Watson if (!lomac_dominate_single(obj, subj)) { 20013de40469SRobert Watson SOCK_UNLOCK(so); 2002eb320b0eSRobert Watson return (ENOENT); 20033de40469SRobert Watson } 20043de40469SRobert Watson SOCK_UNLOCK(so); 2005eb320b0eSRobert Watson 2006eb320b0eSRobert Watson return (0); 2007eb320b0eSRobert Watson } 2008eb320b0eSRobert Watson 2009eb320b0eSRobert Watson static void 2010eb320b0eSRobert Watson lomac_socket_create(struct ucred *cred, struct socket *so, 2011eb320b0eSRobert Watson struct label *solabel) 2012eb320b0eSRobert Watson { 2013eb320b0eSRobert Watson struct mac_lomac *source, *dest; 2014eb320b0eSRobert Watson 2015eb320b0eSRobert Watson source = SLOT(cred->cr_label); 2016eb320b0eSRobert Watson dest = SLOT(solabel); 2017eb320b0eSRobert Watson 2018eb320b0eSRobert Watson lomac_copy_single(source, dest); 2019eb320b0eSRobert Watson } 2020eb320b0eSRobert Watson 2021eb320b0eSRobert Watson static void 2022eb320b0eSRobert Watson lomac_socket_create_mbuf(struct socket *so, struct label *solabel, 2023eb320b0eSRobert Watson struct mbuf *m, struct label *mlabel) 2024eb320b0eSRobert Watson { 2025eb320b0eSRobert Watson struct mac_lomac *source, *dest; 2026eb320b0eSRobert Watson 2027eb320b0eSRobert Watson source = SLOT(solabel); 2028eb320b0eSRobert Watson dest = SLOT(mlabel); 2029eb320b0eSRobert Watson 20303de40469SRobert Watson SOCK_LOCK(so); 2031eb320b0eSRobert Watson lomac_copy_single(source, dest); 20323de40469SRobert Watson SOCK_UNLOCK(so); 2033eb320b0eSRobert Watson } 2034eb320b0eSRobert Watson 2035eb320b0eSRobert Watson static void 2036eb320b0eSRobert Watson lomac_socket_newconn(struct socket *oldso, struct label *oldsolabel, 2037eb320b0eSRobert Watson struct socket *newso, struct label *newsolabel) 2038eb320b0eSRobert Watson { 20393de40469SRobert Watson struct mac_lomac source, *dest; 2040eb320b0eSRobert Watson 20413de40469SRobert Watson SOCK_LOCK(oldso); 20423de40469SRobert Watson source = *SLOT(oldsolabel); 20433de40469SRobert Watson SOCK_UNLOCK(oldso); 20443de40469SRobert Watson 2045eb320b0eSRobert Watson dest = SLOT(newsolabel); 2046eb320b0eSRobert Watson 20473de40469SRobert Watson SOCK_LOCK(newso); 20483de40469SRobert Watson lomac_copy_single(&source, dest); 20493de40469SRobert Watson SOCK_UNLOCK(newso); 2050eb320b0eSRobert Watson } 2051eb320b0eSRobert Watson 2052eb320b0eSRobert Watson static void 2053eb320b0eSRobert Watson lomac_socket_relabel(struct ucred *cred, struct socket *so, 2054eb320b0eSRobert Watson struct label *solabel, struct label *newlabel) 2055eb320b0eSRobert Watson { 2056eb320b0eSRobert Watson struct mac_lomac *source, *dest; 2057eb320b0eSRobert Watson 20583de40469SRobert Watson SOCK_LOCK_ASSERT(so); 20593de40469SRobert Watson 2060eb320b0eSRobert Watson source = SLOT(newlabel); 2061eb320b0eSRobert Watson dest = SLOT(solabel); 2062eb320b0eSRobert Watson 2063eb320b0eSRobert Watson try_relabel(source, dest); 2064eb320b0eSRobert Watson } 2065eb320b0eSRobert Watson 2066eb320b0eSRobert Watson static void 2067eb320b0eSRobert Watson lomac_socketpeer_set_from_mbuf(struct mbuf *m, struct label *mlabel, 2068eb320b0eSRobert Watson struct socket *so, struct label *sopeerlabel) 2069eb320b0eSRobert Watson { 2070eb320b0eSRobert Watson struct mac_lomac *source, *dest; 2071eb320b0eSRobert Watson 2072eb320b0eSRobert Watson source = SLOT(mlabel); 2073eb320b0eSRobert Watson dest = SLOT(sopeerlabel); 2074eb320b0eSRobert Watson 20753de40469SRobert Watson SOCK_LOCK(so); 2076eb320b0eSRobert Watson lomac_copy_single(source, dest); 20773de40469SRobert Watson SOCK_UNLOCK(so); 2078eb320b0eSRobert Watson } 2079eb320b0eSRobert Watson 2080eb320b0eSRobert Watson static void 2081eb320b0eSRobert Watson lomac_socketpeer_set_from_socket(struct socket *oldso, 2082eb320b0eSRobert Watson struct label *oldsolabel, struct socket *newso, 2083eb320b0eSRobert Watson struct label *newsopeerlabel) 2084eb320b0eSRobert Watson { 20853de40469SRobert Watson struct mac_lomac source, *dest; 2086eb320b0eSRobert Watson 20873de40469SRobert Watson SOCK_LOCK(oldso); 20883de40469SRobert Watson source = *SLOT(oldsolabel); 20893de40469SRobert Watson SOCK_UNLOCK(oldso); 20903de40469SRobert Watson 2091eb320b0eSRobert Watson dest = SLOT(newsopeerlabel); 2092eb320b0eSRobert Watson 20933de40469SRobert Watson SOCK_LOCK(newso); 20943de40469SRobert Watson lomac_copy_single(&source, dest); 20953de40469SRobert Watson SOCK_UNLOCK(newso); 2096eb320b0eSRobert Watson } 2097eb320b0eSRobert Watson 2098eb320b0eSRobert Watson static void 2099eb320b0eSRobert Watson lomac_syncache_create(struct label *label, struct inpcb *inp) 2100eb320b0eSRobert Watson { 2101eb320b0eSRobert Watson struct mac_lomac *source, *dest; 2102eb320b0eSRobert Watson 2103eb320b0eSRobert Watson source = SLOT(inp->inp_label); 2104eb320b0eSRobert Watson dest = SLOT(label); 2105eb320b0eSRobert Watson lomac_copy(source, dest); 2106eb320b0eSRobert Watson } 2107eb320b0eSRobert Watson 2108eb320b0eSRobert Watson static void 2109eb320b0eSRobert Watson lomac_syncache_create_mbuf(struct label *sc_label, struct mbuf *m, 2110eb320b0eSRobert Watson struct label *mlabel) 2111eb320b0eSRobert Watson { 2112eb320b0eSRobert Watson struct mac_lomac *source, *dest; 2113eb320b0eSRobert Watson 2114eb320b0eSRobert Watson source = SLOT(sc_label); 2115eb320b0eSRobert Watson dest = SLOT(mlabel); 2116eb320b0eSRobert Watson lomac_copy(source, dest); 2117eb320b0eSRobert Watson } 2118c14d15aeSRobert Watson 2119db2661ceSRobert Watson static int 21203f1a7a90SRobert Watson lomac_system_check_acct(struct ucred *cred, struct vnode *vp, 212178007886SRobert Watson struct label *vplabel) 212218717f69SRobert Watson { 212318717f69SRobert Watson struct mac_lomac *subj, *obj; 212418717f69SRobert Watson 21253f1a7a90SRobert Watson if (!lomac_enabled) 212618717f69SRobert Watson return (0); 212718717f69SRobert Watson 212818717f69SRobert Watson subj = SLOT(cred->cr_label); 212978007886SRobert Watson obj = SLOT(vplabel); 213018717f69SRobert Watson 21313f1a7a90SRobert Watson if (lomac_subject_privileged(subj)) 213218717f69SRobert Watson return (EPERM); 213318717f69SRobert Watson 21343f1a7a90SRobert Watson if (!lomac_high_single(obj)) 213518717f69SRobert Watson return (EACCES); 213618717f69SRobert Watson 213718717f69SRobert Watson return (0); 213818717f69SRobert Watson } 213918717f69SRobert Watson 214018717f69SRobert Watson static int 21413f1a7a90SRobert Watson lomac_system_check_auditctl(struct ucred *cred, struct vnode *vp, 214278007886SRobert Watson struct label *vplabel) 214318717f69SRobert Watson { 214418717f69SRobert Watson struct mac_lomac *subj, *obj; 214518717f69SRobert Watson 21463f1a7a90SRobert Watson if (!lomac_enabled) 214718717f69SRobert Watson return (0); 214818717f69SRobert Watson 214918717f69SRobert Watson subj = SLOT(cred->cr_label); 215078007886SRobert Watson obj = SLOT(vplabel); 215118717f69SRobert Watson 21523f1a7a90SRobert Watson if (lomac_subject_privileged(subj)) 215318717f69SRobert Watson return (EPERM); 215418717f69SRobert Watson 21553f1a7a90SRobert Watson if (!lomac_high_single(obj)) 215618717f69SRobert Watson return (EACCES); 215718717f69SRobert Watson 215818717f69SRobert Watson return (0); 215918717f69SRobert Watson } 216018717f69SRobert Watson 216118717f69SRobert Watson static int 21623f1a7a90SRobert Watson lomac_system_check_swapoff(struct ucred *cred, struct vnode *vp, 216378007886SRobert Watson struct label *vplabel) 216418717f69SRobert Watson { 216518717f69SRobert Watson struct mac_lomac *subj; 216618717f69SRobert Watson 21673f1a7a90SRobert Watson if (!lomac_enabled) 216818717f69SRobert Watson return (0); 216918717f69SRobert Watson 217018717f69SRobert Watson subj = SLOT(cred->cr_label); 217118717f69SRobert Watson 21723f1a7a90SRobert Watson if (lomac_subject_privileged(subj)) 217318717f69SRobert Watson return (EPERM); 217418717f69SRobert Watson 217518717f69SRobert Watson return (0); 217618717f69SRobert Watson } 217718717f69SRobert Watson 217818717f69SRobert Watson static int 21793f1a7a90SRobert Watson lomac_system_check_swapon(struct ucred *cred, struct vnode *vp, 218078007886SRobert Watson struct label *vplabel) 2181db2661ceSRobert Watson { 2182db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2183db2661ceSRobert Watson 21843f1a7a90SRobert Watson if (!lomac_enabled) 2185db2661ceSRobert Watson return (0); 2186db2661ceSRobert Watson 2187eca8a663SRobert Watson subj = SLOT(cred->cr_label); 218878007886SRobert Watson obj = SLOT(vplabel); 2189db2661ceSRobert Watson 21903f1a7a90SRobert Watson if (lomac_subject_privileged(subj)) 2191db2661ceSRobert Watson return (EPERM); 2192db2661ceSRobert Watson 21933f1a7a90SRobert Watson if (!lomac_high_single(obj)) 2194db2661ceSRobert Watson return (EACCES); 2195db2661ceSRobert Watson 2196db2661ceSRobert Watson return (0); 2197db2661ceSRobert Watson } 2198db2661ceSRobert Watson 2199db2661ceSRobert Watson static int 22003f1a7a90SRobert Watson lomac_system_check_sysctl(struct ucred *cred, struct sysctl_oid *oidp, 220163dba32bSPawel Jakub Dawidek void *arg1, int arg2, struct sysctl_req *req) 2202db2661ceSRobert Watson { 2203db2661ceSRobert Watson struct mac_lomac *subj; 2204db2661ceSRobert Watson 22053f1a7a90SRobert Watson if (!lomac_enabled) 2206db2661ceSRobert Watson return (0); 2207db2661ceSRobert Watson 2208eca8a663SRobert Watson subj = SLOT(cred->cr_label); 2209db2661ceSRobert Watson 2210db2661ceSRobert Watson /* 22113f1a7a90SRobert Watson * Treat sysctl variables without CTLFLAG_ANYBODY flag as lomac/high, 22123f1a7a90SRobert Watson * but also require privilege to change them. 2213db2661ceSRobert Watson */ 221463dba32bSPawel Jakub Dawidek if (req->newptr != NULL && (oidp->oid_kind & CTLFLAG_ANYBODY) == 0) { 2215db2661ceSRobert Watson #ifdef notdef 22163f1a7a90SRobert Watson if (!lomac_subject_dominate_high(subj)) 2217db2661ceSRobert Watson return (EACCES); 2218db2661ceSRobert Watson #endif 2219db2661ceSRobert Watson 22203f1a7a90SRobert Watson if (lomac_subject_privileged(subj)) 2221db2661ceSRobert Watson return (EPERM); 2222db2661ceSRobert Watson } 2223db2661ceSRobert Watson 2224db2661ceSRobert Watson return (0); 2225db2661ceSRobert Watson } 2226db2661ceSRobert Watson 2227eb320b0eSRobert Watson static void 2228eb320b0eSRobert Watson lomac_thread_userret(struct thread *td) 2229eb320b0eSRobert Watson { 2230eb320b0eSRobert Watson struct proc *p = td->td_proc; 2231eb320b0eSRobert Watson struct mac_lomac_proc *subj = PSLOT(p->p_label); 2232eb320b0eSRobert Watson struct ucred *newcred, *oldcred; 2233eb320b0eSRobert Watson int dodrop; 2234eb320b0eSRobert Watson 2235eb320b0eSRobert Watson mtx_lock(&subj->mtx); 2236eb320b0eSRobert Watson if (subj->mac_lomac.ml_flags & MAC_LOMAC_FLAG_UPDATE) { 2237eb320b0eSRobert Watson dodrop = 0; 2238eb320b0eSRobert Watson mtx_unlock(&subj->mtx); 2239eb320b0eSRobert Watson newcred = crget(); 2240eb320b0eSRobert Watson /* 22419215889dSRobert Watson * Prevent a lock order reversal in mac_proc_vm_revoke; 22429215889dSRobert Watson * ideally, the other user of subj->mtx wouldn't be holding 22439215889dSRobert Watson * Giant. 2244eb320b0eSRobert Watson */ 2245eb320b0eSRobert Watson mtx_lock(&Giant); 2246eb320b0eSRobert Watson PROC_LOCK(p); 2247eb320b0eSRobert Watson mtx_lock(&subj->mtx); 2248eb320b0eSRobert Watson /* 2249eb320b0eSRobert Watson * Check if we lost the race while allocating the cred. 2250eb320b0eSRobert Watson */ 2251eb320b0eSRobert Watson if ((subj->mac_lomac.ml_flags & MAC_LOMAC_FLAG_UPDATE) == 0) { 2252eb320b0eSRobert Watson crfree(newcred); 2253eb320b0eSRobert Watson goto out; 2254eb320b0eSRobert Watson } 2255eb320b0eSRobert Watson oldcred = p->p_ucred; 2256eb320b0eSRobert Watson crcopy(newcred, oldcred); 2257eb320b0eSRobert Watson crhold(newcred); 2258eb320b0eSRobert Watson lomac_copy(&subj->mac_lomac, SLOT(newcred->cr_label)); 2259daf63fd2SMateusz Guzik proc_set_cred(p, newcred); 2260eb320b0eSRobert Watson crfree(oldcred); 2261eb320b0eSRobert Watson dodrop = 1; 2262eb320b0eSRobert Watson out: 2263eb320b0eSRobert Watson mtx_unlock(&subj->mtx); 2264eb320b0eSRobert Watson PROC_UNLOCK(p); 2265eb320b0eSRobert Watson if (dodrop) 22669215889dSRobert Watson mac_proc_vm_revoke(curthread); 2267eb320b0eSRobert Watson mtx_unlock(&Giant); 2268eb320b0eSRobert Watson } else { 2269eb320b0eSRobert Watson mtx_unlock(&subj->mtx); 2270eb320b0eSRobert Watson } 2271eb320b0eSRobert Watson } 2272eb320b0eSRobert Watson 2273eb320b0eSRobert Watson static int 2274eb320b0eSRobert Watson lomac_vnode_associate_extattr(struct mount *mp, struct label *mplabel, 2275eb320b0eSRobert Watson struct vnode *vp, struct label *vplabel) 2276eb320b0eSRobert Watson { 2277eb320b0eSRobert Watson struct mac_lomac ml_temp, *source, *dest; 2278eb320b0eSRobert Watson int buflen, error; 2279eb320b0eSRobert Watson 2280eb320b0eSRobert Watson source = SLOT(mplabel); 2281eb320b0eSRobert Watson dest = SLOT(vplabel); 2282eb320b0eSRobert Watson 2283eb320b0eSRobert Watson buflen = sizeof(ml_temp); 2284eb320b0eSRobert Watson bzero(&ml_temp, buflen); 2285eb320b0eSRobert Watson 2286eb320b0eSRobert Watson error = vn_extattr_get(vp, IO_NODELOCKED, MAC_LOMAC_EXTATTR_NAMESPACE, 2287eb320b0eSRobert Watson MAC_LOMAC_EXTATTR_NAME, &buflen, (char *)&ml_temp, curthread); 2288eb320b0eSRobert Watson if (error == ENOATTR || error == EOPNOTSUPP) { 2289eb320b0eSRobert Watson /* Fall back to the mntlabel. */ 2290eb320b0eSRobert Watson lomac_copy_single(source, dest); 2291eb320b0eSRobert Watson return (0); 2292eb320b0eSRobert Watson } else if (error) 2293eb320b0eSRobert Watson return (error); 2294eb320b0eSRobert Watson 2295eb320b0eSRobert Watson if (buflen != sizeof(ml_temp)) { 2296eb320b0eSRobert Watson if (buflen != sizeof(ml_temp) - sizeof(ml_temp.ml_auxsingle)) { 2297eb320b0eSRobert Watson printf("lomac_vnode_associate_extattr: bad size %d\n", 2298eb320b0eSRobert Watson buflen); 2299eb320b0eSRobert Watson return (EPERM); 2300eb320b0eSRobert Watson } 2301eb320b0eSRobert Watson bzero(&ml_temp.ml_auxsingle, sizeof(ml_temp.ml_auxsingle)); 2302eb320b0eSRobert Watson buflen = sizeof(ml_temp); 2303eb320b0eSRobert Watson (void)vn_extattr_set(vp, IO_NODELOCKED, 2304eb320b0eSRobert Watson MAC_LOMAC_EXTATTR_NAMESPACE, MAC_LOMAC_EXTATTR_NAME, 2305eb320b0eSRobert Watson buflen, (char *)&ml_temp, curthread); 2306eb320b0eSRobert Watson } 2307eb320b0eSRobert Watson if (lomac_valid(&ml_temp) != 0) { 2308eb320b0eSRobert Watson printf("lomac_vnode_associate_extattr: invalid\n"); 2309eb320b0eSRobert Watson return (EPERM); 2310eb320b0eSRobert Watson } 2311eb320b0eSRobert Watson if ((ml_temp.ml_flags & MAC_LOMAC_FLAGS_BOTH) != 2312eb320b0eSRobert Watson MAC_LOMAC_FLAG_SINGLE) { 2313eb320b0eSRobert Watson printf("lomac_vnode_associate_extattr: not single\n"); 2314eb320b0eSRobert Watson return (EPERM); 2315eb320b0eSRobert Watson } 2316eb320b0eSRobert Watson 2317eb320b0eSRobert Watson lomac_copy_single(&ml_temp, dest); 2318eb320b0eSRobert Watson return (0); 2319eb320b0eSRobert Watson } 2320eb320b0eSRobert Watson 2321eb320b0eSRobert Watson static void 2322eb320b0eSRobert Watson lomac_vnode_associate_singlelabel(struct mount *mp, struct label *mplabel, 2323eb320b0eSRobert Watson struct vnode *vp, struct label *vplabel) 2324eb320b0eSRobert Watson { 2325eb320b0eSRobert Watson struct mac_lomac *source, *dest; 2326eb320b0eSRobert Watson 2327eb320b0eSRobert Watson source = SLOT(mplabel); 2328eb320b0eSRobert Watson dest = SLOT(vplabel); 2329eb320b0eSRobert Watson 2330eb320b0eSRobert Watson lomac_copy_single(source, dest); 2331eb320b0eSRobert Watson } 2332eb320b0eSRobert Watson 2333db2661ceSRobert Watson static int 23343f1a7a90SRobert Watson lomac_vnode_check_create(struct ucred *cred, struct vnode *dvp, 233578007886SRobert Watson struct label *dvplabel, struct componentname *cnp, struct vattr *vap) 2336db2661ceSRobert Watson { 2337db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2338db2661ceSRobert Watson 23393f1a7a90SRobert Watson if (!lomac_enabled) 2340db2661ceSRobert Watson return (0); 2341db2661ceSRobert Watson 2342eca8a663SRobert Watson subj = SLOT(cred->cr_label); 234378007886SRobert Watson obj = SLOT(dvplabel); 2344db2661ceSRobert Watson 23453f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2346db2661ceSRobert Watson return (EACCES); 2347db2661ceSRobert Watson if (obj->ml_flags & MAC_LOMAC_FLAG_AUX && 23483f1a7a90SRobert Watson !lomac_dominate_element(&subj->ml_single, &obj->ml_auxsingle)) 2349db2661ceSRobert Watson return (EACCES); 2350db2661ceSRobert Watson 2351db2661ceSRobert Watson return (0); 2352db2661ceSRobert Watson } 2353db2661ceSRobert Watson 2354db2661ceSRobert Watson static int 23553f1a7a90SRobert Watson lomac_vnode_check_deleteacl(struct ucred *cred, struct vnode *vp, 235678007886SRobert Watson struct label *vplabel, acl_type_t type) 2357db2661ceSRobert Watson { 2358db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2359db2661ceSRobert Watson 23603f1a7a90SRobert Watson if (!lomac_enabled) 2361db2661ceSRobert Watson return (0); 2362db2661ceSRobert Watson 2363eca8a663SRobert Watson subj = SLOT(cred->cr_label); 236478007886SRobert Watson obj = SLOT(vplabel); 2365db2661ceSRobert Watson 23663f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2367db2661ceSRobert Watson return (EACCES); 2368db2661ceSRobert Watson 2369db2661ceSRobert Watson return (0); 2370db2661ceSRobert Watson } 2371db2661ceSRobert Watson 2372db2661ceSRobert Watson static int 23733f1a7a90SRobert Watson lomac_vnode_check_link(struct ucred *cred, struct vnode *dvp, 237478007886SRobert Watson struct label *dvplabel, struct vnode *vp, struct label *vplabel, 2375db2661ceSRobert Watson struct componentname *cnp) 2376db2661ceSRobert Watson { 2377db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2378db2661ceSRobert Watson 23793f1a7a90SRobert Watson if (!lomac_enabled) 2380db2661ceSRobert Watson return (0); 2381db2661ceSRobert Watson 2382eca8a663SRobert Watson subj = SLOT(cred->cr_label); 238378007886SRobert Watson obj = SLOT(dvplabel); 2384db2661ceSRobert Watson 23853f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2386db2661ceSRobert Watson return (EACCES); 2387db2661ceSRobert Watson 238878007886SRobert Watson obj = SLOT(vplabel); 2389db2661ceSRobert Watson 23903f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2391db2661ceSRobert Watson return (EACCES); 2392db2661ceSRobert Watson 2393db2661ceSRobert Watson return (0); 2394db2661ceSRobert Watson } 2395db2661ceSRobert Watson 2396db2661ceSRobert Watson static int 23973f1a7a90SRobert Watson lomac_vnode_check_mmap(struct ucred *cred, struct vnode *vp, 239878007886SRobert Watson struct label *vplabel, int prot, int flags) 2399db2661ceSRobert Watson { 2400db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2401db2661ceSRobert Watson 2402db2661ceSRobert Watson /* 2403db2661ceSRobert Watson * Rely on the use of open()-time protections to handle 2404db2661ceSRobert Watson * non-revocation cases. 2405db2661ceSRobert Watson */ 24063f1a7a90SRobert Watson if (!lomac_enabled) 2407db2661ceSRobert Watson return (0); 2408db2661ceSRobert Watson 2409eca8a663SRobert Watson subj = SLOT(cred->cr_label); 241078007886SRobert Watson obj = SLOT(vplabel); 2411db2661ceSRobert Watson 2412c92163dcSChristian S.J. Peron if (((prot & VM_PROT_WRITE) != 0) && ((flags & MAP_SHARED) != 0)) { 24133f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2414db2661ceSRobert Watson return (EACCES); 2415db2661ceSRobert Watson } 2416db2661ceSRobert Watson if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) { 24173f1a7a90SRobert Watson if (!lomac_dominate_single(obj, subj)) 2418db2661ceSRobert Watson return (maybe_demote(subj, obj, "mapping", "file", vp)); 2419db2661ceSRobert Watson } 2420db2661ceSRobert Watson 2421db2661ceSRobert Watson return (0); 2422db2661ceSRobert Watson } 2423db2661ceSRobert Watson 2424db2661ceSRobert Watson static void 24253f1a7a90SRobert Watson lomac_vnode_check_mmap_downgrade(struct ucred *cred, struct vnode *vp, 242678007886SRobert Watson struct label *vplabel, /* XXX vm_prot_t */ int *prot) 2427db2661ceSRobert Watson { 2428db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2429db2661ceSRobert Watson 2430db2661ceSRobert Watson /* 2431db2661ceSRobert Watson * Rely on the use of open()-time protections to handle 2432db2661ceSRobert Watson * non-revocation cases. 2433db2661ceSRobert Watson */ 24343f1a7a90SRobert Watson if (!lomac_enabled || !revocation_enabled) 2435db2661ceSRobert Watson return; 2436db2661ceSRobert Watson 2437eca8a663SRobert Watson subj = SLOT(cred->cr_label); 243878007886SRobert Watson obj = SLOT(vplabel); 2439db2661ceSRobert Watson 24403f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2441db2661ceSRobert Watson *prot &= ~VM_PROT_WRITE; 2442db2661ceSRobert Watson } 2443db2661ceSRobert Watson 2444db2661ceSRobert Watson static int 24453f1a7a90SRobert Watson lomac_vnode_check_open(struct ucred *cred, struct vnode *vp, 244615bc6b2bSEdward Tomasz Napierala struct label *vplabel, accmode_t accmode) 2447db2661ceSRobert Watson { 2448db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2449db2661ceSRobert Watson 24503f1a7a90SRobert Watson if (!lomac_enabled) 2451db2661ceSRobert Watson return (0); 2452db2661ceSRobert Watson 2453eca8a663SRobert Watson subj = SLOT(cred->cr_label); 245478007886SRobert Watson obj = SLOT(vplabel); 2455db2661ceSRobert Watson 2456db2661ceSRobert Watson /* XXX privilege override for admin? */ 24573a597bfcSEdward Tomasz Napierala if (accmode & VMODIFY_PERMS) { 24583f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2459db2661ceSRobert Watson return (EACCES); 2460db2661ceSRobert Watson } 2461db2661ceSRobert Watson 2462db2661ceSRobert Watson return (0); 2463db2661ceSRobert Watson } 2464db2661ceSRobert Watson 2465db2661ceSRobert Watson static int 24663f1a7a90SRobert Watson lomac_vnode_check_read(struct ucred *active_cred, struct ucred *file_cred, 246778007886SRobert Watson struct vnode *vp, struct label *vplabel) 2468db2661ceSRobert Watson { 2469db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2470db2661ceSRobert Watson 24713f1a7a90SRobert Watson if (!lomac_enabled || !revocation_enabled) 2472db2661ceSRobert Watson return (0); 2473db2661ceSRobert Watson 2474eca8a663SRobert Watson subj = SLOT(active_cred->cr_label); 247578007886SRobert Watson obj = SLOT(vplabel); 2476db2661ceSRobert Watson 24773f1a7a90SRobert Watson if (!lomac_dominate_single(obj, subj)) 2478db2661ceSRobert Watson return (maybe_demote(subj, obj, "reading", "file", vp)); 2479db2661ceSRobert Watson 2480db2661ceSRobert Watson return (0); 2481db2661ceSRobert Watson } 2482db2661ceSRobert Watson 2483db2661ceSRobert Watson static int 24843f1a7a90SRobert Watson lomac_vnode_check_relabel(struct ucred *cred, struct vnode *vp, 248578007886SRobert Watson struct label *vplabel, struct label *newlabel) 2486db2661ceSRobert Watson { 2487db2661ceSRobert Watson struct mac_lomac *old, *new, *subj; 2488db2661ceSRobert Watson int error; 2489db2661ceSRobert Watson 249078007886SRobert Watson old = SLOT(vplabel); 2491db2661ceSRobert Watson new = SLOT(newlabel); 2492eca8a663SRobert Watson subj = SLOT(cred->cr_label); 2493db2661ceSRobert Watson 2494db2661ceSRobert Watson /* 2495db2661ceSRobert Watson * If there is a LOMAC label update for the vnode, it must be a 2496db2661ceSRobert Watson * single label, with an optional explicit auxiliary single. 2497db2661ceSRobert Watson */ 2498db2661ceSRobert Watson error = lomac_atmostflags(new, 2499db2661ceSRobert Watson MAC_LOMAC_FLAG_SINGLE | MAC_LOMAC_FLAG_AUX); 2500db2661ceSRobert Watson if (error) 2501db2661ceSRobert Watson return (error); 2502db2661ceSRobert Watson 2503db2661ceSRobert Watson /* 2504db2661ceSRobert Watson * To perform a relabel of the vnode (LOMAC label or not), LOMAC must 2505db2661ceSRobert Watson * authorize the relabel. 2506db2661ceSRobert Watson */ 25073f1a7a90SRobert Watson if (!lomac_single_in_range(old, subj)) 2508db2661ceSRobert Watson return (EPERM); 2509db2661ceSRobert Watson 2510db2661ceSRobert Watson /* 2511db2661ceSRobert Watson * If the LOMAC label is to be changed, authorize as appropriate. 2512db2661ceSRobert Watson */ 2513db2661ceSRobert Watson if (new->ml_flags & MAC_LOMAC_FLAG_SINGLE) { 2514db2661ceSRobert Watson /* 2515db2661ceSRobert Watson * To change the LOMAC label on a vnode, the new vnode label 2516db2661ceSRobert Watson * must be in the subject range. 2517db2661ceSRobert Watson */ 25183f1a7a90SRobert Watson if (!lomac_single_in_range(new, subj)) 2519db2661ceSRobert Watson return (EPERM); 2520db2661ceSRobert Watson 2521db2661ceSRobert Watson /* 25223f1a7a90SRobert Watson * To change the LOMAC label on the vnode to be EQUAL, the 25233f1a7a90SRobert Watson * subject must have appropriate privilege. 2524db2661ceSRobert Watson */ 25253f1a7a90SRobert Watson if (lomac_contains_equal(new)) { 25263f1a7a90SRobert Watson error = lomac_subject_privileged(subj); 2527db2661ceSRobert Watson if (error) 2528db2661ceSRobert Watson return (error); 2529db2661ceSRobert Watson } 2530db2661ceSRobert Watson } 2531db2661ceSRobert Watson if (new->ml_flags & MAC_LOMAC_FLAG_AUX) { 2532db2661ceSRobert Watson /* 253384bdb083SRobert Watson * Fill in the missing parts from the previous label. 253484bdb083SRobert Watson */ 253584bdb083SRobert Watson if ((new->ml_flags & MAC_LOMAC_FLAG_SINGLE) == 0) 25363f1a7a90SRobert Watson lomac_copy_single(subj, new); 253784bdb083SRobert Watson 253884bdb083SRobert Watson /* 2539db2661ceSRobert Watson * To change the auxiliary LOMAC label on a vnode, the new 2540db2661ceSRobert Watson * vnode label must be in the subject range. 2541db2661ceSRobert Watson */ 25423f1a7a90SRobert Watson if (!lomac_auxsingle_in_range(new, subj)) 2543db2661ceSRobert Watson return (EPERM); 2544db2661ceSRobert Watson 2545db2661ceSRobert Watson /* 2546db2661ceSRobert Watson * To change the auxiliary LOMAC label on the vnode to be 2547db2661ceSRobert Watson * EQUAL, the subject must have appropriate privilege. 2548db2661ceSRobert Watson */ 25493f1a7a90SRobert Watson if (lomac_contains_equal(new)) { 25503f1a7a90SRobert Watson error = lomac_subject_privileged(subj); 2551db2661ceSRobert Watson if (error) 2552db2661ceSRobert Watson return (error); 2553db2661ceSRobert Watson } 2554db2661ceSRobert Watson } 2555db2661ceSRobert Watson 2556db2661ceSRobert Watson return (0); 2557db2661ceSRobert Watson } 2558db2661ceSRobert Watson 2559db2661ceSRobert Watson static int 25603f1a7a90SRobert Watson lomac_vnode_check_rename_from(struct ucred *cred, struct vnode *dvp, 256178007886SRobert Watson struct label *dvplabel, struct vnode *vp, struct label *vplabel, 2562db2661ceSRobert Watson struct componentname *cnp) 2563db2661ceSRobert Watson { 2564db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2565db2661ceSRobert Watson 25663f1a7a90SRobert Watson if (!lomac_enabled) 2567db2661ceSRobert Watson return (0); 2568db2661ceSRobert Watson 2569eca8a663SRobert Watson subj = SLOT(cred->cr_label); 257078007886SRobert Watson obj = SLOT(dvplabel); 2571db2661ceSRobert Watson 25723f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2573db2661ceSRobert Watson return (EACCES); 2574db2661ceSRobert Watson 257578007886SRobert Watson obj = SLOT(vplabel); 2576db2661ceSRobert Watson 25773f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2578db2661ceSRobert Watson return (EACCES); 2579db2661ceSRobert Watson 2580db2661ceSRobert Watson return (0); 2581db2661ceSRobert Watson } 2582db2661ceSRobert Watson 2583db2661ceSRobert Watson static int 25843f1a7a90SRobert Watson lomac_vnode_check_rename_to(struct ucred *cred, struct vnode *dvp, 258578007886SRobert Watson struct label *dvplabel, struct vnode *vp, struct label *vplabel, 258678007886SRobert Watson int samedir, struct componentname *cnp) 2587db2661ceSRobert Watson { 2588db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2589db2661ceSRobert Watson 25903f1a7a90SRobert Watson if (!lomac_enabled) 2591db2661ceSRobert Watson return (0); 2592db2661ceSRobert Watson 2593eca8a663SRobert Watson subj = SLOT(cred->cr_label); 259478007886SRobert Watson obj = SLOT(dvplabel); 2595db2661ceSRobert Watson 25963f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2597db2661ceSRobert Watson return (EACCES); 2598db2661ceSRobert Watson 2599db2661ceSRobert Watson if (vp != NULL) { 260078007886SRobert Watson obj = SLOT(vplabel); 2601db2661ceSRobert Watson 26023f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2603db2661ceSRobert Watson return (EACCES); 2604db2661ceSRobert Watson } 2605db2661ceSRobert Watson 2606db2661ceSRobert Watson return (0); 2607db2661ceSRobert Watson } 2608db2661ceSRobert Watson 2609db2661ceSRobert Watson static int 26103f1a7a90SRobert Watson lomac_vnode_check_revoke(struct ucred *cred, struct vnode *vp, 261178007886SRobert Watson struct label *vplabel) 2612db2661ceSRobert Watson { 2613db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2614db2661ceSRobert Watson 26153f1a7a90SRobert Watson if (!lomac_enabled) 2616db2661ceSRobert Watson return (0); 2617db2661ceSRobert Watson 2618eca8a663SRobert Watson subj = SLOT(cred->cr_label); 261978007886SRobert Watson obj = SLOT(vplabel); 2620db2661ceSRobert Watson 26213f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2622db2661ceSRobert Watson return (EACCES); 2623db2661ceSRobert Watson 2624db2661ceSRobert Watson return (0); 2625db2661ceSRobert Watson } 2626db2661ceSRobert Watson 2627db2661ceSRobert Watson static int 26283f1a7a90SRobert Watson lomac_vnode_check_setacl(struct ucred *cred, struct vnode *vp, 262978007886SRobert Watson struct label *vplabel, acl_type_t type, struct acl *acl) 2630db2661ceSRobert Watson { 2631db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2632db2661ceSRobert Watson 26333f1a7a90SRobert Watson if (!lomac_enabled) 2634db2661ceSRobert Watson return (0); 2635db2661ceSRobert Watson 2636eca8a663SRobert Watson subj = SLOT(cred->cr_label); 263778007886SRobert Watson obj = SLOT(vplabel); 2638db2661ceSRobert Watson 26393f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2640db2661ceSRobert Watson return (EACCES); 2641db2661ceSRobert Watson 2642db2661ceSRobert Watson return (0); 2643db2661ceSRobert Watson } 2644db2661ceSRobert Watson 2645db2661ceSRobert Watson static int 26463f1a7a90SRobert Watson lomac_vnode_check_setextattr(struct ucred *cred, struct vnode *vp, 2647fefd0ac8SRobert Watson struct label *vplabel, int attrnamespace, const char *name) 2648db2661ceSRobert Watson { 2649db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2650db2661ceSRobert Watson 26513f1a7a90SRobert Watson if (!lomac_enabled) 2652db2661ceSRobert Watson return (0); 2653db2661ceSRobert Watson 2654eca8a663SRobert Watson subj = SLOT(cred->cr_label); 265578007886SRobert Watson obj = SLOT(vplabel); 2656db2661ceSRobert Watson 26573f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2658db2661ceSRobert Watson return (EACCES); 2659db2661ceSRobert Watson 2660db2661ceSRobert Watson /* XXX: protect the MAC EA in a special way? */ 2661db2661ceSRobert Watson 2662db2661ceSRobert Watson return (0); 2663db2661ceSRobert Watson } 2664db2661ceSRobert Watson 2665db2661ceSRobert Watson static int 26663f1a7a90SRobert Watson lomac_vnode_check_setflags(struct ucred *cred, struct vnode *vp, 266778007886SRobert Watson struct label *vplabel, u_long flags) 2668db2661ceSRobert Watson { 2669db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2670db2661ceSRobert Watson 26713f1a7a90SRobert Watson if (!lomac_enabled) 2672db2661ceSRobert Watson return (0); 2673db2661ceSRobert Watson 2674eca8a663SRobert Watson subj = SLOT(cred->cr_label); 267578007886SRobert Watson obj = SLOT(vplabel); 2676db2661ceSRobert Watson 26773f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2678db2661ceSRobert Watson return (EACCES); 2679db2661ceSRobert Watson 2680db2661ceSRobert Watson return (0); 2681db2661ceSRobert Watson } 2682db2661ceSRobert Watson 2683db2661ceSRobert Watson static int 26843f1a7a90SRobert Watson lomac_vnode_check_setmode(struct ucred *cred, struct vnode *vp, 268578007886SRobert Watson struct label *vplabel, mode_t mode) 2686db2661ceSRobert Watson { 2687db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2688db2661ceSRobert Watson 26893f1a7a90SRobert Watson if (!lomac_enabled) 2690db2661ceSRobert Watson return (0); 2691db2661ceSRobert Watson 2692eca8a663SRobert Watson subj = SLOT(cred->cr_label); 269378007886SRobert Watson obj = SLOT(vplabel); 2694db2661ceSRobert Watson 26953f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2696db2661ceSRobert Watson return (EACCES); 2697db2661ceSRobert Watson 2698db2661ceSRobert Watson return (0); 2699db2661ceSRobert Watson } 2700db2661ceSRobert Watson 2701db2661ceSRobert Watson static int 27023f1a7a90SRobert Watson lomac_vnode_check_setowner(struct ucred *cred, struct vnode *vp, 270378007886SRobert Watson struct label *vplabel, uid_t uid, gid_t gid) 2704db2661ceSRobert Watson { 2705db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2706db2661ceSRobert Watson 27073f1a7a90SRobert Watson if (!lomac_enabled) 2708db2661ceSRobert Watson return (0); 2709db2661ceSRobert Watson 2710eca8a663SRobert Watson subj = SLOT(cred->cr_label); 271178007886SRobert Watson obj = SLOT(vplabel); 2712db2661ceSRobert Watson 27133f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2714db2661ceSRobert Watson return (EACCES); 2715db2661ceSRobert Watson 2716db2661ceSRobert Watson return (0); 2717db2661ceSRobert Watson } 2718db2661ceSRobert Watson 2719db2661ceSRobert Watson static int 27203f1a7a90SRobert Watson lomac_vnode_check_setutimes(struct ucred *cred, struct vnode *vp, 272178007886SRobert Watson struct label *vplabel, struct timespec atime, struct timespec mtime) 2722db2661ceSRobert Watson { 2723db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2724db2661ceSRobert Watson 27253f1a7a90SRobert Watson if (!lomac_enabled) 2726db2661ceSRobert Watson return (0); 2727db2661ceSRobert Watson 2728eca8a663SRobert Watson subj = SLOT(cred->cr_label); 272978007886SRobert Watson obj = SLOT(vplabel); 2730db2661ceSRobert Watson 27313f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2732db2661ceSRobert Watson return (EACCES); 2733db2661ceSRobert Watson 2734db2661ceSRobert Watson return (0); 2735db2661ceSRobert Watson } 2736db2661ceSRobert Watson 2737db2661ceSRobert Watson static int 27383f1a7a90SRobert Watson lomac_vnode_check_unlink(struct ucred *cred, struct vnode *dvp, 273945e0f3d6SRobert Watson struct label *dvplabel, struct vnode *vp, struct label *vplabel, 274045e0f3d6SRobert Watson struct componentname *cnp) 274145e0f3d6SRobert Watson { 274245e0f3d6SRobert Watson struct mac_lomac *subj, *obj; 274345e0f3d6SRobert Watson 27443f1a7a90SRobert Watson if (!lomac_enabled) 274545e0f3d6SRobert Watson return (0); 274645e0f3d6SRobert Watson 274745e0f3d6SRobert Watson subj = SLOT(cred->cr_label); 274845e0f3d6SRobert Watson obj = SLOT(dvplabel); 274945e0f3d6SRobert Watson 27503f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 275145e0f3d6SRobert Watson return (EACCES); 275245e0f3d6SRobert Watson 275345e0f3d6SRobert Watson obj = SLOT(vplabel); 275445e0f3d6SRobert Watson 27553f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 275645e0f3d6SRobert Watson return (EACCES); 275745e0f3d6SRobert Watson 275845e0f3d6SRobert Watson return (0); 275945e0f3d6SRobert Watson } 276045e0f3d6SRobert Watson 276145e0f3d6SRobert Watson static int 27623f1a7a90SRobert Watson lomac_vnode_check_write(struct ucred *active_cred, 276378007886SRobert Watson struct ucred *file_cred, struct vnode *vp, struct label *vplabel) 2764db2661ceSRobert Watson { 2765db2661ceSRobert Watson struct mac_lomac *subj, *obj; 2766db2661ceSRobert Watson 27673f1a7a90SRobert Watson if (!lomac_enabled || !revocation_enabled) 2768db2661ceSRobert Watson return (0); 2769db2661ceSRobert Watson 2770eca8a663SRobert Watson subj = SLOT(active_cred->cr_label); 277178007886SRobert Watson obj = SLOT(vplabel); 2772db2661ceSRobert Watson 27733f1a7a90SRobert Watson if (!lomac_subject_dominate(subj, obj)) 2774db2661ceSRobert Watson return (EACCES); 2775db2661ceSRobert Watson 2776db2661ceSRobert Watson return (0); 2777db2661ceSRobert Watson } 2778db2661ceSRobert Watson 2779eb320b0eSRobert Watson static int 2780eb320b0eSRobert Watson lomac_vnode_create_extattr(struct ucred *cred, struct mount *mp, 2781eb320b0eSRobert Watson struct label *mplabel, struct vnode *dvp, struct label *dvplabel, 2782eb320b0eSRobert Watson struct vnode *vp, struct label *vplabel, struct componentname *cnp) 2783db2661ceSRobert Watson { 2784eb320b0eSRobert Watson struct mac_lomac *source, *dest, *dir, temp; 2785eb320b0eSRobert Watson size_t buflen; 2786eb320b0eSRobert Watson int error; 2787db2661ceSRobert Watson 2788eb320b0eSRobert Watson buflen = sizeof(temp); 2789eb320b0eSRobert Watson bzero(&temp, buflen); 2790eb320b0eSRobert Watson 2791eb320b0eSRobert Watson source = SLOT(cred->cr_label); 2792eb320b0eSRobert Watson dest = SLOT(vplabel); 2793eb320b0eSRobert Watson dir = SLOT(dvplabel); 2794eb320b0eSRobert Watson if (dir->ml_flags & MAC_LOMAC_FLAG_AUX) { 2795eb320b0eSRobert Watson lomac_copy_auxsingle(dir, &temp); 2796eb320b0eSRobert Watson lomac_set_single(&temp, dir->ml_auxsingle.mle_type, 2797eb320b0eSRobert Watson dir->ml_auxsingle.mle_grade); 2798db2661ceSRobert Watson } else { 2799eb320b0eSRobert Watson lomac_copy_single(source, &temp); 2800db2661ceSRobert Watson } 2801eb320b0eSRobert Watson 2802eb320b0eSRobert Watson error = vn_extattr_set(vp, IO_NODELOCKED, MAC_LOMAC_EXTATTR_NAMESPACE, 2803eb320b0eSRobert Watson MAC_LOMAC_EXTATTR_NAME, buflen, (char *)&temp, curthread); 2804eb320b0eSRobert Watson if (error == 0) 2805eb320b0eSRobert Watson lomac_copy(&temp, dest); 2806eb320b0eSRobert Watson return (error); 2807eb320b0eSRobert Watson } 2808eb320b0eSRobert Watson 2809eb320b0eSRobert Watson static void 2810eb320b0eSRobert Watson lomac_vnode_execve_transition(struct ucred *old, struct ucred *new, 2811eb320b0eSRobert Watson struct vnode *vp, struct label *vplabel, struct label *interpvplabel, 2812eb320b0eSRobert Watson struct image_params *imgp, struct label *execlabel) 2813eb320b0eSRobert Watson { 2814eb320b0eSRobert Watson struct mac_lomac *source, *dest, *obj, *robj; 2815eb320b0eSRobert Watson 2816eb320b0eSRobert Watson source = SLOT(old->cr_label); 2817eb320b0eSRobert Watson dest = SLOT(new->cr_label); 2818eb320b0eSRobert Watson obj = SLOT(vplabel); 2819eb320b0eSRobert Watson robj = interpvplabel != NULL ? SLOT(interpvplabel) : obj; 2820eb320b0eSRobert Watson 2821eb320b0eSRobert Watson lomac_copy(source, dest); 2822eb320b0eSRobert Watson /* 2823eb320b0eSRobert Watson * If there's an auxiliary label on the real object, respect it and 2824eb320b0eSRobert Watson * assume that this level should be assumed immediately if a higher 2825eb320b0eSRobert Watson * level is currently in place. 2826eb320b0eSRobert Watson */ 2827eb320b0eSRobert Watson if (robj->ml_flags & MAC_LOMAC_FLAG_AUX && 2828eb320b0eSRobert Watson !lomac_dominate_element(&robj->ml_auxsingle, &dest->ml_single) 2829eb320b0eSRobert Watson && lomac_auxsingle_in_range(robj, dest)) 2830eb320b0eSRobert Watson lomac_set_single(dest, robj->ml_auxsingle.mle_type, 2831eb320b0eSRobert Watson robj->ml_auxsingle.mle_grade); 2832eb320b0eSRobert Watson /* 2833eb320b0eSRobert Watson * Restructuring to use the execve transitioning mechanism instead of 2834eb320b0eSRobert Watson * the normal demotion mechanism here would be difficult, so just 2835eb320b0eSRobert Watson * copy the label over and perform standard demotion. This is also 2836eb320b0eSRobert Watson * non-optimal because it will result in the intermediate label "new" 2837eb320b0eSRobert Watson * being created and immediately recycled. 2838eb320b0eSRobert Watson */ 2839eb320b0eSRobert Watson if (lomac_enabled && revocation_enabled && 2840eb320b0eSRobert Watson !lomac_dominate_single(obj, source)) 2841eb320b0eSRobert Watson (void)maybe_demote(source, obj, "executing", "file", vp); 2842eb320b0eSRobert Watson } 2843eb320b0eSRobert Watson 2844eb320b0eSRobert Watson static int 2845eb320b0eSRobert Watson lomac_vnode_execve_will_transition(struct ucred *old, struct vnode *vp, 2846eb320b0eSRobert Watson struct label *vplabel, struct label *interpvplabel, 2847eb320b0eSRobert Watson struct image_params *imgp, struct label *execlabel) 2848eb320b0eSRobert Watson { 2849eb320b0eSRobert Watson struct mac_lomac *subj, *obj, *robj; 2850eb320b0eSRobert Watson 2851eb320b0eSRobert Watson if (!lomac_enabled || !revocation_enabled) 2852eb320b0eSRobert Watson return (0); 2853eb320b0eSRobert Watson 2854eb320b0eSRobert Watson subj = SLOT(old->cr_label); 2855eb320b0eSRobert Watson obj = SLOT(vplabel); 2856eb320b0eSRobert Watson robj = interpvplabel != NULL ? SLOT(interpvplabel) : obj; 2857eb320b0eSRobert Watson 2858eb320b0eSRobert Watson return ((robj->ml_flags & MAC_LOMAC_FLAG_AUX && 2859eb320b0eSRobert Watson !lomac_dominate_element(&robj->ml_auxsingle, &subj->ml_single) 2860eb320b0eSRobert Watson && lomac_auxsingle_in_range(robj, subj)) || 2861eb320b0eSRobert Watson !lomac_dominate_single(obj, subj)); 2862eb320b0eSRobert Watson } 2863eb320b0eSRobert Watson 2864eb320b0eSRobert Watson static void 2865eb320b0eSRobert Watson lomac_vnode_relabel(struct ucred *cred, struct vnode *vp, 2866eb320b0eSRobert Watson struct label *vplabel, struct label *newlabel) 2867eb320b0eSRobert Watson { 2868eb320b0eSRobert Watson struct mac_lomac *source, *dest; 2869eb320b0eSRobert Watson 2870eb320b0eSRobert Watson source = SLOT(newlabel); 2871eb320b0eSRobert Watson dest = SLOT(vplabel); 2872eb320b0eSRobert Watson 2873eb320b0eSRobert Watson try_relabel(source, dest); 2874eb320b0eSRobert Watson } 2875eb320b0eSRobert Watson 2876eb320b0eSRobert Watson static int 2877eb320b0eSRobert Watson lomac_vnode_setlabel_extattr(struct ucred *cred, struct vnode *vp, 2878eb320b0eSRobert Watson struct label *vplabel, struct label *intlabel) 2879eb320b0eSRobert Watson { 2880eb320b0eSRobert Watson struct mac_lomac *source, temp; 2881eb320b0eSRobert Watson size_t buflen; 2882eb320b0eSRobert Watson int error; 2883eb320b0eSRobert Watson 2884eb320b0eSRobert Watson buflen = sizeof(temp); 2885eb320b0eSRobert Watson bzero(&temp, buflen); 2886eb320b0eSRobert Watson 2887eb320b0eSRobert Watson source = SLOT(intlabel); 2888eb320b0eSRobert Watson if ((source->ml_flags & MAC_LOMAC_FLAG_SINGLE) == 0) 2889eb320b0eSRobert Watson return (0); 2890eb320b0eSRobert Watson 2891eb320b0eSRobert Watson lomac_copy_single(source, &temp); 2892eb320b0eSRobert Watson error = vn_extattr_set(vp, IO_NODELOCKED, MAC_LOMAC_EXTATTR_NAMESPACE, 2893eb320b0eSRobert Watson MAC_LOMAC_EXTATTR_NAME, buflen, (char *)&temp, curthread); 2894eb320b0eSRobert Watson return (error); 2895db2661ceSRobert Watson } 2896db2661ceSRobert Watson 28973f1a7a90SRobert Watson static struct mac_policy_ops lomac_ops = 2898db2661ceSRobert Watson { 28993f1a7a90SRobert Watson .mpo_init = lomac_init, 2900eb320b0eSRobert Watson 2901eb320b0eSRobert Watson .mpo_bpfdesc_check_receive = lomac_bpfdesc_check_receive, 2902eb320b0eSRobert Watson .mpo_bpfdesc_create = lomac_bpfdesc_create, 2903eb320b0eSRobert Watson .mpo_bpfdesc_create_mbuf = lomac_bpfdesc_create_mbuf, 29043f1a7a90SRobert Watson .mpo_bpfdesc_destroy_label = lomac_destroy_label, 2905eb320b0eSRobert Watson .mpo_bpfdesc_init_label = lomac_init_label, 2906eb320b0eSRobert Watson 2907eb320b0eSRobert Watson .mpo_cred_check_relabel = lomac_cred_check_relabel, 2908eb320b0eSRobert Watson .mpo_cred_check_visible = lomac_cred_check_visible, 29093f1a7a90SRobert Watson .mpo_cred_copy_label = lomac_copy_label, 2910212ab0cfSRobert Watson .mpo_cred_create_swapper = lomac_cred_create_swapper, 2911212ab0cfSRobert Watson .mpo_cred_create_init = lomac_cred_create_init, 2912eb320b0eSRobert Watson .mpo_cred_destroy_label = lomac_destroy_label, 29133f1a7a90SRobert Watson .mpo_cred_externalize_label = lomac_externalize_label, 2914eb320b0eSRobert Watson .mpo_cred_init_label = lomac_init_label, 29153f1a7a90SRobert Watson .mpo_cred_internalize_label = lomac_internalize_label, 2916eb320b0eSRobert Watson .mpo_cred_relabel = lomac_cred_relabel, 2917eb320b0eSRobert Watson 29183f1a7a90SRobert Watson .mpo_devfs_create_device = lomac_devfs_create_device, 29193f1a7a90SRobert Watson .mpo_devfs_create_directory = lomac_devfs_create_directory, 29203f1a7a90SRobert Watson .mpo_devfs_create_symlink = lomac_devfs_create_symlink, 2921eb320b0eSRobert Watson .mpo_devfs_destroy_label = lomac_destroy_label, 2922eb320b0eSRobert Watson .mpo_devfs_init_label = lomac_init_label, 29233f1a7a90SRobert Watson .mpo_devfs_update = lomac_devfs_update, 29243f1a7a90SRobert Watson .mpo_devfs_vnode_associate = lomac_devfs_vnode_associate, 2925eb320b0eSRobert Watson 29263f1a7a90SRobert Watson .mpo_ifnet_check_relabel = lomac_ifnet_check_relabel, 29273f1a7a90SRobert Watson .mpo_ifnet_check_transmit = lomac_ifnet_check_transmit, 2928eb320b0eSRobert Watson .mpo_ifnet_copy_label = lomac_copy_label, 2929eb320b0eSRobert Watson .mpo_ifnet_create = lomac_ifnet_create, 2930eb320b0eSRobert Watson .mpo_ifnet_create_mbuf = lomac_ifnet_create_mbuf, 2931eb320b0eSRobert Watson .mpo_ifnet_destroy_label = lomac_destroy_label, 2932eb320b0eSRobert Watson .mpo_ifnet_externalize_label = lomac_externalize_label, 2933eb320b0eSRobert Watson .mpo_ifnet_init_label = lomac_init_label, 2934eb320b0eSRobert Watson .mpo_ifnet_internalize_label = lomac_internalize_label, 2935eb320b0eSRobert Watson .mpo_ifnet_relabel = lomac_ifnet_relabel, 2936eb320b0eSRobert Watson 2937eb320b0eSRobert Watson .mpo_syncache_create = lomac_syncache_create, 2938eb320b0eSRobert Watson .mpo_syncache_destroy_label = lomac_destroy_label, 2939eb320b0eSRobert Watson .mpo_syncache_init_label = lomac_init_label_waitcheck, 2940eb320b0eSRobert Watson 29413f1a7a90SRobert Watson .mpo_inpcb_check_deliver = lomac_inpcb_check_deliver, 29427fb179baSBjoern A. Zeeb .mpo_inpcb_check_visible = lomac_inpcb_check_visible, 2943eb320b0eSRobert Watson .mpo_inpcb_create = lomac_inpcb_create, 2944eb320b0eSRobert Watson .mpo_inpcb_create_mbuf = lomac_inpcb_create_mbuf, 2945eb320b0eSRobert Watson .mpo_inpcb_destroy_label = lomac_destroy_label, 2946eb320b0eSRobert Watson .mpo_inpcb_init_label = lomac_init_label_waitcheck, 2947eb320b0eSRobert Watson .mpo_inpcb_sosetlabel = lomac_inpcb_sosetlabel, 2948eb320b0eSRobert Watson 2949048e1287SRobert Watson .mpo_ip6q_create = lomac_ip6q_create, 2950048e1287SRobert Watson .mpo_ip6q_destroy_label = lomac_destroy_label, 2951048e1287SRobert Watson .mpo_ip6q_init_label = lomac_init_label_waitcheck, 2952048e1287SRobert Watson .mpo_ip6q_match = lomac_ip6q_match, 2953048e1287SRobert Watson .mpo_ip6q_reassemble = lomac_ip6q_reassemble, 2954048e1287SRobert Watson .mpo_ip6q_update = lomac_ip6q_update, 2955048e1287SRobert Watson 2956eb320b0eSRobert Watson .mpo_ipq_create = lomac_ipq_create, 2957eb320b0eSRobert Watson .mpo_ipq_destroy_label = lomac_destroy_label, 2958eb320b0eSRobert Watson .mpo_ipq_init_label = lomac_init_label_waitcheck, 2959eb320b0eSRobert Watson .mpo_ipq_match = lomac_ipq_match, 2960eb320b0eSRobert Watson .mpo_ipq_reassemble = lomac_ipq_reassemble, 2961eb320b0eSRobert Watson .mpo_ipq_update = lomac_ipq_update, 2962eb320b0eSRobert Watson 29633f1a7a90SRobert Watson .mpo_kld_check_load = lomac_kld_check_load, 2964eb320b0eSRobert Watson 2965eb320b0eSRobert Watson .mpo_mbuf_copy_label = lomac_copy_label, 2966eb320b0eSRobert Watson .mpo_mbuf_destroy_label = lomac_destroy_label, 2967eb320b0eSRobert Watson .mpo_mbuf_init_label = lomac_init_label_waitcheck, 2968eb320b0eSRobert Watson 2969eb320b0eSRobert Watson .mpo_mount_create = lomac_mount_create, 2970eb320b0eSRobert Watson .mpo_mount_destroy_label = lomac_destroy_label, 2971eb320b0eSRobert Watson .mpo_mount_init_label = lomac_init_label, 2972eb320b0eSRobert Watson 2973eb320b0eSRobert Watson .mpo_netinet_arp_send = lomac_netinet_arp_send, 2974eb320b0eSRobert Watson .mpo_netinet_firewall_reply = lomac_netinet_firewall_reply, 2975eb320b0eSRobert Watson .mpo_netinet_firewall_send = lomac_netinet_firewall_send, 2976eb320b0eSRobert Watson .mpo_netinet_fragment = lomac_netinet_fragment, 2977eb320b0eSRobert Watson .mpo_netinet_icmp_reply = lomac_netinet_icmp_reply, 2978eb320b0eSRobert Watson .mpo_netinet_igmp_send = lomac_netinet_igmp_send, 2979eb320b0eSRobert Watson 2980eb320b0eSRobert Watson .mpo_netinet6_nd6_send = lomac_netinet6_nd6_send, 2981eb320b0eSRobert Watson 29823f1a7a90SRobert Watson .mpo_pipe_check_ioctl = lomac_pipe_check_ioctl, 29833f1a7a90SRobert Watson .mpo_pipe_check_read = lomac_pipe_check_read, 29843f1a7a90SRobert Watson .mpo_pipe_check_relabel = lomac_pipe_check_relabel, 29853f1a7a90SRobert Watson .mpo_pipe_check_write = lomac_pipe_check_write, 2986eb320b0eSRobert Watson .mpo_pipe_copy_label = lomac_copy_label, 2987eb320b0eSRobert Watson .mpo_pipe_create = lomac_pipe_create, 2988eb320b0eSRobert Watson .mpo_pipe_destroy_label = lomac_destroy_label, 2989eb320b0eSRobert Watson .mpo_pipe_externalize_label = lomac_externalize_label, 2990eb320b0eSRobert Watson .mpo_pipe_init_label = lomac_init_label, 2991eb320b0eSRobert Watson .mpo_pipe_internalize_label = lomac_internalize_label, 2992eb320b0eSRobert Watson .mpo_pipe_relabel = lomac_pipe_relabel, 2993eb320b0eSRobert Watson 2994eb320b0eSRobert Watson .mpo_priv_check = lomac_priv_check, 2995eb320b0eSRobert Watson 29963f1a7a90SRobert Watson .mpo_proc_check_debug = lomac_proc_check_debug, 29973f1a7a90SRobert Watson .mpo_proc_check_sched = lomac_proc_check_sched, 29983f1a7a90SRobert Watson .mpo_proc_check_signal = lomac_proc_check_signal, 2999eb320b0eSRobert Watson .mpo_proc_destroy_label = lomac_proc_destroy_label, 3000eb320b0eSRobert Watson .mpo_proc_init_label = lomac_proc_init_label, 3001eb320b0eSRobert Watson 30023f1a7a90SRobert Watson .mpo_socket_check_deliver = lomac_socket_check_deliver, 30033f1a7a90SRobert Watson .mpo_socket_check_relabel = lomac_socket_check_relabel, 30043f1a7a90SRobert Watson .mpo_socket_check_visible = lomac_socket_check_visible, 3005eb320b0eSRobert Watson .mpo_socket_copy_label = lomac_copy_label, 3006eb320b0eSRobert Watson .mpo_socket_create = lomac_socket_create, 3007eb320b0eSRobert Watson .mpo_socket_create_mbuf = lomac_socket_create_mbuf, 3008eb320b0eSRobert Watson .mpo_socket_destroy_label = lomac_destroy_label, 3009eb320b0eSRobert Watson .mpo_socket_externalize_label = lomac_externalize_label, 3010eb320b0eSRobert Watson .mpo_socket_init_label = lomac_init_label_waitcheck, 3011eb320b0eSRobert Watson .mpo_socket_internalize_label = lomac_internalize_label, 3012eb320b0eSRobert Watson .mpo_socket_newconn = lomac_socket_newconn, 3013eb320b0eSRobert Watson .mpo_socket_relabel = lomac_socket_relabel, 3014eb320b0eSRobert Watson 3015eb320b0eSRobert Watson .mpo_socketpeer_destroy_label = lomac_destroy_label, 3016eb320b0eSRobert Watson .mpo_socketpeer_externalize_label = lomac_externalize_label, 3017eb320b0eSRobert Watson .mpo_socketpeer_init_label = lomac_init_label_waitcheck, 3018eb320b0eSRobert Watson .mpo_socketpeer_set_from_mbuf = lomac_socketpeer_set_from_mbuf, 3019eb320b0eSRobert Watson .mpo_socketpeer_set_from_socket = lomac_socketpeer_set_from_socket, 3020eb320b0eSRobert Watson 3021eb320b0eSRobert Watson .mpo_syncache_create_mbuf = lomac_syncache_create_mbuf, 3022eb320b0eSRobert Watson 30233f1a7a90SRobert Watson .mpo_system_check_acct = lomac_system_check_acct, 30243f1a7a90SRobert Watson .mpo_system_check_auditctl = lomac_system_check_auditctl, 30253f1a7a90SRobert Watson .mpo_system_check_swapoff = lomac_system_check_swapoff, 30263f1a7a90SRobert Watson .mpo_system_check_swapon = lomac_system_check_swapon, 30273f1a7a90SRobert Watson .mpo_system_check_sysctl = lomac_system_check_sysctl, 3028eb320b0eSRobert Watson 3029eb320b0eSRobert Watson .mpo_thread_userret = lomac_thread_userret, 3030eb320b0eSRobert Watson 3031eb320b0eSRobert Watson .mpo_vnode_associate_extattr = lomac_vnode_associate_extattr, 3032eb320b0eSRobert Watson .mpo_vnode_associate_singlelabel = lomac_vnode_associate_singlelabel, 30333f1a7a90SRobert Watson .mpo_vnode_check_access = lomac_vnode_check_open, 30343f1a7a90SRobert Watson .mpo_vnode_check_create = lomac_vnode_check_create, 30353f1a7a90SRobert Watson .mpo_vnode_check_deleteacl = lomac_vnode_check_deleteacl, 30363f1a7a90SRobert Watson .mpo_vnode_check_link = lomac_vnode_check_link, 30373f1a7a90SRobert Watson .mpo_vnode_check_mmap = lomac_vnode_check_mmap, 30383f1a7a90SRobert Watson .mpo_vnode_check_mmap_downgrade = lomac_vnode_check_mmap_downgrade, 30393f1a7a90SRobert Watson .mpo_vnode_check_open = lomac_vnode_check_open, 30403f1a7a90SRobert Watson .mpo_vnode_check_read = lomac_vnode_check_read, 30413f1a7a90SRobert Watson .mpo_vnode_check_relabel = lomac_vnode_check_relabel, 30423f1a7a90SRobert Watson .mpo_vnode_check_rename_from = lomac_vnode_check_rename_from, 30433f1a7a90SRobert Watson .mpo_vnode_check_rename_to = lomac_vnode_check_rename_to, 30443f1a7a90SRobert Watson .mpo_vnode_check_revoke = lomac_vnode_check_revoke, 30453f1a7a90SRobert Watson .mpo_vnode_check_setacl = lomac_vnode_check_setacl, 30463f1a7a90SRobert Watson .mpo_vnode_check_setextattr = lomac_vnode_check_setextattr, 30473f1a7a90SRobert Watson .mpo_vnode_check_setflags = lomac_vnode_check_setflags, 30483f1a7a90SRobert Watson .mpo_vnode_check_setmode = lomac_vnode_check_setmode, 30493f1a7a90SRobert Watson .mpo_vnode_check_setowner = lomac_vnode_check_setowner, 30503f1a7a90SRobert Watson .mpo_vnode_check_setutimes = lomac_vnode_check_setutimes, 30513f1a7a90SRobert Watson .mpo_vnode_check_unlink = lomac_vnode_check_unlink, 30523f1a7a90SRobert Watson .mpo_vnode_check_write = lomac_vnode_check_write, 3053eb320b0eSRobert Watson .mpo_vnode_copy_label = lomac_copy_label, 3054eb320b0eSRobert Watson .mpo_vnode_create_extattr = lomac_vnode_create_extattr, 3055eb320b0eSRobert Watson .mpo_vnode_destroy_label = lomac_destroy_label, 3056eb320b0eSRobert Watson .mpo_vnode_execve_transition = lomac_vnode_execve_transition, 3057eb320b0eSRobert Watson .mpo_vnode_execve_will_transition = lomac_vnode_execve_will_transition, 3058eb320b0eSRobert Watson .mpo_vnode_externalize_label = lomac_externalize_label, 3059eb320b0eSRobert Watson .mpo_vnode_init_label = lomac_init_label, 3060eb320b0eSRobert Watson .mpo_vnode_internalize_label = lomac_internalize_label, 3061eb320b0eSRobert Watson .mpo_vnode_relabel = lomac_vnode_relabel, 3062eb320b0eSRobert Watson .mpo_vnode_setlabel_extattr = lomac_vnode_setlabel_extattr, 3063db2661ceSRobert Watson }; 3064db2661ceSRobert Watson 30653f1a7a90SRobert Watson MAC_POLICY_SET(&lomac_ops, mac_lomac, "TrustedBSD MAC/LOMAC", 30669162f64bSRobert Watson MPC_LOADTIME_FLAG_NOTLATE, &lomac_slot); 3067