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