dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / common / secflags / secflags.c
blob3c9ee571eac835ca448372919621c8ca41c3826f
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.
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.
12 /* Copyright 2015, Richard Lowe. */
14 #include <sys/secflags.h>
15 #include <sys/types.h>
17 #if defined(_KERNEL)
18 #include <sys/kmem.h>
19 #include <sys/sunddi.h>
20 #else
21 #include "lint.h" /* libc header */
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <strings.h>
25 #endif
27 secflagset_t
28 secflag_to_bit(secflag_t secflag)
30 return (1 << secflag);
33 boolean_t
34 secflag_isset(secflagset_t flags, secflag_t sf)
36 return ((flags & secflag_to_bit(sf)) != 0);
39 void
40 secflag_clear(secflagset_t *flags, secflag_t sf)
42 *flags &= ~secflag_to_bit(sf);
45 void
46 secflag_set(secflagset_t *flags, secflag_t sf)
48 *flags |= secflag_to_bit(sf);
51 boolean_t
52 secflags_isempty(secflagset_t flags)
54 return (flags == 0);
57 void
58 secflags_zero(secflagset_t *flags)
60 *flags = 0;
63 void
64 secflags_fullset(secflagset_t *flags)
66 *flags = PROC_SEC_MASK;
69 void
70 secflags_copy(secflagset_t *dst, const secflagset_t *src)
72 *dst = *src;
75 boolean_t
76 secflags_issubset(secflagset_t a, secflagset_t b)
78 return (!(a & ~b));
81 boolean_t
82 secflags_issuperset(secflagset_t a, secflagset_t b)
84 return (secflags_issubset(b, a));
87 boolean_t
88 secflags_intersection(secflagset_t a, secflagset_t b)
90 return (a & b);
93 void
94 secflags_union(secflagset_t *a, const secflagset_t *b)
96 *a |= *b;
99 void
100 secflags_difference(secflagset_t *a, const secflagset_t *b)
102 *a &= ~*b;
105 boolean_t
106 psecflags_validate_delta(const psecflags_t *sf, const secflagdelta_t *delta)
108 if (delta->psd_ass_active) {
110 * If there's a bit in lower not in args, or a bit args not in
111 * upper
113 if (!secflags_issubset(delta->psd_assign, sf->psf_upper) ||
114 !secflags_issuperset(delta->psd_assign, sf->psf_lower)) {
115 return (B_FALSE);
118 if (!secflags_issubset(delta->psd_assign, PROC_SEC_MASK))
119 return (B_FALSE);
120 } else {
121 /* If we're adding a bit not in upper */
122 if (!secflags_isempty(delta->psd_add)) {
123 if (!secflags_issubset(delta->psd_add, sf->psf_upper)) {
124 return (B_FALSE);
128 /* If we're removing a bit that's in lower */
129 if (!secflags_isempty(delta->psd_rem)) {
130 if (secflags_intersection(delta->psd_rem,
131 sf->psf_lower)) {
132 return (B_FALSE);
136 if (!secflags_issubset(delta->psd_add, PROC_SEC_MASK) ||
137 !secflags_issubset(delta->psd_rem, PROC_SEC_MASK))
138 return (B_FALSE);
141 return (B_TRUE);
144 boolean_t
145 psecflags_validate(const psecflags_t *sf)
147 if (!secflags_issubset(sf->psf_lower, PROC_SEC_MASK) ||
148 !secflags_issubset(sf->psf_inherit, PROC_SEC_MASK) ||
149 !secflags_issubset(sf->psf_effective, PROC_SEC_MASK) ||
150 !secflags_issubset(sf->psf_upper, PROC_SEC_MASK))
151 return (B_FALSE);
153 if (!secflags_issubset(sf->psf_lower, sf->psf_inherit))
154 return (B_FALSE);
155 if (!secflags_issubset(sf->psf_lower, sf->psf_upper))
156 return (B_FALSE);
157 if (!secflags_issubset(sf->psf_inherit, sf->psf_upper))
158 return (B_FALSE);
160 return (B_TRUE);
163 void
164 psecflags_default(psecflags_t *sf)
166 secflags_fullset(&sf->psf_effective);
167 secflags_fullset(&sf->psf_inherit);
168 secflags_zero(&sf->psf_lower);
169 secflags_fullset(&sf->psf_upper);
172 static struct flagdesc {
173 secflag_t value;
174 const char *name;
175 } flagdescs[] = {
176 { PROC_SEC_ASLR, "aslr" },
177 { PROC_SEC_FORBIDNULLMAP, "forbidnullmap" },
178 { PROC_SEC_NOEXECSTACK, "noexecstack" },
179 { 0x0, NULL }
182 boolean_t
183 secflag_by_name(const char *str, secflag_t *ret)
185 struct flagdesc *fd;
187 for (fd = flagdescs; fd->name != NULL; fd++) {
188 if (strcasecmp(str, fd->name) == 0) {
189 *ret = fd->value;
190 return (B_TRUE);
194 return (B_FALSE);
197 const char *
198 secflag_to_str(secflag_t sf)
200 struct flagdesc *fd;
202 for (fd = flagdescs; fd->name != NULL; fd++) {
203 if (sf == fd->value)
204 return (fd->name);
207 return (NULL);
210 void
211 secflags_to_str(secflagset_t flags, char *buf, size_t buflen)
213 struct flagdesc *fd;
215 if (buflen >= 1)
216 buf[0] = '\0';
218 if (flags == 0) {
219 (void) strlcpy(buf, "none", buflen);
220 return;
223 for (fd = flagdescs; fd->name != NULL; fd++) {
224 if (secflag_isset(flags, fd->value)) {
225 if (buf[0] != '\0')
226 (void) strlcat(buf, ",", buflen);
227 (void) strlcat(buf, fd->name, buflen);
230 secflag_clear(&flags, fd->value);
233 if (flags != 0) { /* unknown flags */
234 char hexbuf[19]; /* 0x%16 PRIx64 */
236 (void) snprintf(hexbuf, sizeof (hexbuf), "0x%16" PRIx64, flags);
237 if (buf[0] != '\0')
238 (void) strlcat(buf, ",", buflen);
239 (void) strlcat(buf, hexbuf, buflen);