1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* Copyright 2015, Richard Lowe. */ 13 14 #include <sys/ddi.h> 15 #include <sys/errno.h> 16 #include <sys/policy.h> 17 #include <sys/proc.h> 18 #include <sys/procset.h> 19 #include <sys/systm.h> 20 #include <sys/types.h> 21 #include <c2/audit.h> 22 23 struct psdargs { 24 psecflagwhich_t which; 25 const secflagdelta_t *delta; 26 }; 27 28 void 29 secflags_apply_delta(secflagset_t *set, const secflagdelta_t *delta) 30 { 31 if (delta->psd_ass_active) { 32 secflags_copy(set, &delta->psd_assign); 33 } else { 34 if (!secflags_isempty(delta->psd_add)) { 35 secflags_union(set, &delta->psd_add); 36 } 37 if (!secflags_isempty(delta->psd_rem)) { 38 secflags_difference(set, &delta->psd_rem); 39 } 40 } 41 } 42 43 44 static int 45 psecdo(proc_t *p, struct psdargs *args) 46 { 47 secflagset_t *set; 48 int ret = 0; 49 50 mutex_enter(&p->p_lock); 51 52 if (secpolicy_psecflags(CRED(), p, curproc) != 0) { 53 ret = EPERM; 54 goto out; 55 } 56 57 if (!psecflags_validate_delta(&p->p_secflags, args->delta)) { 58 ret = EINVAL; 59 goto out; 60 } 61 62 if (AU_AUDITING()) 63 audit_psecflags(p, args->which, args->delta); 64 65 switch (args->which) { 66 case PSF_INHERIT: 67 set = &p->p_secflags.psf_inherit; 68 break; 69 case PSF_LOWER: 70 set = &p->p_secflags.psf_lower; 71 break; 72 case PSF_UPPER: 73 set = &p->p_secflags.psf_upper; 74 break; 75 default: 76 ASSERT(0); 77 goto out; 78 } 79 80 secflags_apply_delta(set, args->delta); 81 82 /* 83 * Add any flag now in the lower that is not in the inheritable. 84 */ 85 secflags_union(&p->p_secflags.psf_inherit, &p->p_secflags.psf_lower); 86 87 out: 88 mutex_exit(&p->p_lock); 89 return (ret); 90 } 91 92 int 93 psecflags(procset_t *psp, psecflagwhich_t which, secflagdelta_t *ap) 94 { 95 procset_t procset; 96 secflagdelta_t args; 97 int rv = 0; 98 struct psdargs psd = { 99 .which = which, 100 }; 101 102 /* Can never change the effective flags */ 103 if (psd.which == PSF_EFFECTIVE) 104 return (EINVAL); 105 106 if (copyin(psp, &procset, sizeof (procset)) != 0) 107 return (set_errno(EFAULT)); 108 109 if (copyin(ap, &args, sizeof (secflagdelta_t)) != 0) 110 return (set_errno(EFAULT)); 111 112 psd.delta = &args; 113 114 /* secflags are per-process, procset must be in terms of processes */ 115 if ((procset.p_lidtype == P_LWPID) || 116 (procset.p_ridtype == P_LWPID)) 117 return (set_errno(EINVAL)); 118 119 rv = dotoprocs(&procset, psecdo, (caddr_t)&psd); 120 121 return (rv ? set_errno(rv) : 0); 122 } 123