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 ASSERT(args->which != PSF_EFFECTIVE); 58 59 if (!psecflags_validate_delta(&p->p_secflags, args->delta)) { 60 ret = EINVAL; 61 goto out; 62 } 63 64 if (AU_AUDITING()) 65 audit_psecflags(p, args->which, args->delta); 66 67 switch (args->which) { 68 case PSF_INHERIT: 69 set = &p->p_secflags.psf_inherit; 70 break; 71 case PSF_LOWER: 72 set = &p->p_secflags.psf_lower; 73 break; 74 case PSF_UPPER: 75 set = &p->p_secflags.psf_upper; 76 break; 77 } 78 79 secflags_apply_delta(set, args->delta); 80 81 /* 82 * Add any flag now in the lower that is not in the inheritable. 83 */ 84 secflags_union(&p->p_secflags.psf_inherit, &p->p_secflags.psf_lower); 85 86 out: 87 mutex_exit(&p->p_lock); 88 return (ret); 89 } 90 91 int 92 psecflags(procset_t *psp, psecflagwhich_t which, secflagdelta_t *ap) 93 { 94 procset_t procset; 95 secflagdelta_t args; 96 int rv = 0; 97 struct psdargs psd = { 98 .which = which, 99 }; 100 101 /* Can never change the effective flags */ 102 if (psd.which == PSF_EFFECTIVE) 103 return (EINVAL); 104 105 if (copyin(psp, &procset, sizeof (procset)) != 0) 106 return (set_errno(EFAULT)); 107 108 if (copyin(ap, &args, sizeof (secflagdelta_t)) != 0) 109 return (set_errno(EFAULT)); 110 111 psd.delta = &args; 112 113 /* secflags are per-process, procset must be in terms of processes */ 114 if ((procset.p_lidtype == P_LWPID) || 115 (procset.p_ridtype == P_LWPID)) 116 return (set_errno(EINVAL)); 117 118 rv = dotoprocs(&procset, psecdo, (caddr_t)&psd); 119 120 return (rv ? set_errno(rv) : 0); 121 }