xref: /illumos-gate/usr/src/uts/common/os/privs.awk (revision a5f69788de7ac07553de47f7fec8c05a9a94c105)
1#
2# Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
3# Use is subject to license terms.
4#
5# CDDL HEADER START
6#
7# The contents of this file are subject to the terms of the
8# Common Development and Distribution License, Version 1.0 only
9# (the "License").  You may not use this file except in compliance
10# with the License.
11#
12# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
13# or http://www.opensolaris.org/os/licensing.
14# See the License for the specific language governing permissions
15# and limitations under the License.
16#
17# When distributing Covered Code, include this CDDL HEADER in each
18# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
19# If applicable, add the following below this CDDL HEADER, with the
20# fields enclosed by brackets "[]" replaced with your own identifying
21# information: Portions Copyright [yyyy] [name of copyright owner]
22#
23# CDDL HEADER END
24#
25#ident	"%Z%%M%	%I%	%E% SMI"
26#
27# This file generates three different C files:
28#
29#	<sys/priv_const.h>
30#		An implementation private set of manifest integer constant
31#		for privileges and privilege sets and manifest constants for
32#		set size, number of sets, number of privileges
33#
34#	os/priv_const.c
35#		A C source file containing the set names, privilege names
36#		arrays for the name <-> number mappings
37#
38#	<sys/priv_names.h>
39#		A public header file containing the PRIV_* defines
40#		that map to strings; these are for convenience.
41#		(it's easy to misspell a string, harder to misspell a
42#		manifest constant)
43#
44#	/etc/security/priv_names
45#		A privilege name to explanation mapping.
46#
47#
48# The files are output on the awk variable privhfile, pubhfile, cfile,
49# and pnamesfile respectively
50#
51# The input file should contain a standard Sun comment and ident string
52# which is copied verbatim and lines of
53#
54#	[keyword] privilege	PRIV_<privilege>
55#	set			PRIV_<set>
56#
57# Which are converted to privileges and privilege sets
58#
59
60
61BEGIN	{
62	# Number of privileges read
63	npriv = 0
64
65	# Number of privilege sets
66	nset = 0
67
68	# Length of all strings concatenated, including \0
69	privbytes = 0
70	setbytes = 0
71
72	# Number of reserved privilege slots
73	slack = 10
74
75	privhcmt = \
76	" * Privilege constant definitions; these constants are subject to\n" \
77	" * change, including renumbering, without notice and should not be\n" \
78	" * used in any code.  Privilege names must be used instead.\n" \
79	" * Privileges and privilege sets must not be stored in binary\n" \
80	" * form; privileges and privileges sets must be converted to\n" \
81	" * textual representation before being committed to persistent store."
82
83	ccmt = \
84	" * Privilege name table and size definitions."
85
86	pubhcmt = \
87	" * Privilege constant definitions.  Privileges and privilege sets\n" \
88	" * are only known by name and should be mapped at runtime."
89
90	pnamescmt = \
91	"#\n" \
92	"# Privilege name explanation file\n" \
93	"# The format of entries is a privilege name starting at the\n" \
94	"# beginning of a line directly folowed by a new line followed\n" \
95	"# by several lines of texts starting with white space terminated\n" \
96	"# by a line with a single newline or not starting with white space\n" \
97	"#\n"
98}
99
100#
101# Privilege strings are represented as lower case strings;
102# PRIV_ is stripped from the strings.
103#
104/^([A-Za-z]* )?privilege / {
105	if (NF == 3) {
106		key = toupper($1)
107		priv = toupper($3)
108		if (set[key] != "")
109			set[key] = set[key] ";"
110		set[key] = set[key] "\\\n\t\tPRIV_ASSERT((set), " priv ")"
111	} else {
112		priv = toupper($2);
113	}
114	privs[npriv] = tolower(substr(priv, 6));
115	inset = 0
116	inpriv = 1
117
118	privind[npriv] = privbytes;
119
120	tabs = (32 - length(priv) - 1)/8
121	# length + \0 - PRIV_
122	privbytes += length(priv) - 4
123	pdef[npriv] = "#define\t" priv substr("\t\t\t\t\t", 1, tabs)
124
125	npriv++
126	next
127}
128
129#
130# Set strings are represented as strings with an initial cap;
131# PRIV_ is stripped from the strings.
132#
133/^set / {
134	$2 = toupper($2)
135	sets[nset] = toupper(substr($2, 6, 1)) tolower(substr($2, 7));
136	inset = 1
137	inpriv = 0
138
139	setind[nset] = setbytes
140
141	# length + \0 - PRIV_
142	setbytes += length($2) - 4
143	tabs = (32 - length($2) - 1)/8
144	sdef[nset] = "#define\t" $2 substr("\t\t\t\t\t", 1, tabs)
145
146	nset++
147	next
148}
149
150/INSERT COMMENT/ {
151	acmt = " *\n * THIS FILE WAS GENERATED; DO NOT EDIT"
152	if (cfile) {
153		print ccmt > cfile
154		print acmt > cfile
155	}
156	if (privhfile) {
157		print privhcmt > privhfile
158		print acmt > privhfile
159	}
160	if (pubhfile) {
161		print pubhcmt > pubhfile
162		print acmt > pubhfile
163	}
164	next
165}
166/^#pragma/ {
167	pragma = $0;
168	if (pnamesfile) {
169		print "#" substr($0, 9) > pnamesfile
170	}
171	next;
172}
173
174/^#/ && ! /^#pragma/{
175	# Comments, ignore
176	next
177}
178
179{
180	#
181	# Comments describing privileges and sets follow the definitions.
182	#
183	if (inset || inpriv) {
184		sub("^[ 	]*", "")
185		sub("[ 	]*$", "")
186		if (/^$/) next;
187	}
188	if (inset) {
189		setcmt[nset - 1] = setcmt[nset - 1] " * " $0 "\n"
190		next
191	} else if (inpriv) {
192		sub("^[ 	]*", "")
193		privcmt[npriv - 1] = privcmt[npriv - 1] " * " $0 "\n"
194		privncmt[npriv - 1] = privncmt[npriv - 1] "\t" $0 "\n"
195		next
196	}
197
198	if (cfile)
199		print > cfile
200	if (privhfile)
201		print > privhfile
202	if (pubhfile)
203		print > pubhfile
204	if (pnamesfile) {
205		sub("^/\\*", "#")
206		sub("^ \\*/", "")
207		sub("^ \\*", "#")
208		if (/^$/) next;
209		print > pnamesfile
210	}
211}
212
213END	{
214
215	if (!pubhfile && !privhfile && !cfile && !pnamesfile) {
216		print "Output file parameter not set" > "/dev/stderr"
217		exit 1
218	}
219
220	setsize = int((npriv + slack)/(8 * 4)) + 1
221	maxnpriv = setsize * 8 * 4
222	# Assume allocated privileges are on average "NSDQ" bytes larger.
223	maxprivbytes = int((privbytes / npriv + 5.5)) * (maxnpriv - npriv)
224	maxprivbytes += privbytes
225
226	if (cfile) {
227		print "\n" > cfile
228		print pragma "\n"> cfile
229		print "#include <sys/types.h>" > cfile
230		print "#include <sys/priv_const.h>" > cfile
231		print "#include <sys/priv_impl.h>" > cfile
232		print "#include <sys/priv.h>" > cfile
233		print "#include <sys/sysmacros.h>" > cfile
234		print "\n" > cfile
235		#
236		# Create the entire priv info structure here.
237		# When adding privileges, the kernel needs to update
238		# too many fields as the number of privileges is kept in
239		# many places.
240		#
241		print \
242		    "static struct _info {\n" \
243		    "	priv_impl_info_t	impl_info;\n" \
244		    "	priv_info_t		settype;\n" \
245		    "	int			nsets;\n" \
246		    "	const char		sets[" setbytes "];\n" \
247		    "	priv_info_t		privtype;\n" \
248		    "	int			nprivs;\n" \
249		    "	char			privs[" maxprivbytes "];\n" \
250		    "	priv_info_t		sysset;\n" \
251		    "	priv_set_t		basicset;\n" \
252		    "} info = {\n" \
253		    "	{ sizeof (priv_impl_info_t), 0, PRIV_NSET, " \
254			"PRIV_SETSIZE, " npriv ",\n" \
255			"\t\tsizeof (priv_info_uint_t),\n" \
256			"\t\tsizeof (info) - sizeof (info.impl_info)},\n" \
257		    "	{ PRIV_INFO_SETNAMES,\n" \
258		    "	    offsetof(struct _info, privtype) - " \
259		    "offsetof(struct _info, settype)},\n\tPRIV_NSET," > cfile
260
261		sep = "\t\""
262		len = 9;
263		for (i = 0; i < nset; i++) {
264			if (len + length(sets[i]) > 80) {
265				sep = "\\0\"\n\t\""
266				len = 9
267			}
268			printf sep sets[i]  > cfile
269			len += length(sets[i]) + length(sep);
270			sep = "\\0"
271		}
272		print "\\0\"," > cfile
273
274		print "\t{ PRIV_INFO_PRIVNAMES,\n\t    " \
275			"offsetof(struct _info, sysset) - " \
276			"offsetof(struct _info, privtype)},\n\t" npriv "," \
277			> cfile
278
279		sep = "\t\""
280		len = 9;
281		for (i = 0; i < npriv; i++) {
282			if (len + length(privs[i]) > 80) {
283				sep = "\\0\"\n\t\""
284				len = 9
285			}
286			printf sep privs[i]  > cfile
287			len += length(privs[i]) + length(sep);
288			sep = "\\0"
289		}
290		print "\\0\"," > cfile
291
292		print "\t{ PRIV_INFO_BASICPRIVS, sizeof (info) - " \
293			"offsetof(struct _info, sysset)},"  > cfile
294
295		print "};\n" > cfile
296
297		print "\nconst char *priv_names[" maxnpriv "] =\n{" > cfile
298		for (i = 0; i < npriv; i++)
299			print "\t&info.privs[" privind[i] "]," > cfile
300
301		print "};\n" > cfile
302
303		print "\nconst char *priv_setnames[" nset "] =\n{" > cfile
304		for (i = 0; i < nset; i++)
305			print "\t&info.sets[" setind[i] "]," > cfile
306
307		print "};\n" > cfile
308
309		print "int nprivs = " npriv ";" > cfile
310		print "int privbytes = " privbytes ";" > cfile
311		print "int maxprivbytes = " maxprivbytes ";" > cfile
312		print "size_t privinfosize = sizeof (info);" > cfile
313		print "char *priv_str = info.privs;" > cfile
314		print "priv_set_t *priv_basic = &info.basicset;" > cfile
315		print "priv_impl_info_t *priv_info = &info.impl_info;" > cfile
316		print "priv_info_names_t *priv_ninfo = " \
317			"(priv_info_names_t *)&info.privtype;" > cfile
318		close(cfile)
319	}
320
321	# Kernel private
322	if (privhfile) {
323		print "#ifndef _SYS_PRIV_CONST_H" > privhfile
324		print "#define\t_SYS_PRIV_CONST_H\n" > privhfile
325		print pragma "\n"> privhfile
326		print "\n#include <sys/types.h>\n\n" > privhfile
327		print "#ifdef __cplusplus\nextern \"C\" {\n#endif\n" > privhfile
328
329		print "#if defined(_KERNEL) || defined(_KMEMUSER)" > privhfile
330		print "#define\tPRIV_NSET\t\t\t  " nset > privhfile
331		print "#define\tPRIV_SETSIZE\t\t\t  " setsize > privhfile
332		print "#endif\n\n#ifdef _KERNEL" > privhfile
333		print "#define\t__PRIV_CONST_IMPL\n" > privhfile
334		print "extern const char *priv_names[];" > privhfile
335		print "extern const char *priv_setnames[];" > privhfile
336
337		print "extern int nprivs;" > privhfile
338		print "extern int privbytes;" > privhfile
339		print "extern int maxprivbytes;" > privhfile
340		print "extern size_t privinfosize;" > privhfile
341		print "extern char *priv_str;" > privhfile
342		print "extern struct priv_set *priv_basic;" > privhfile
343		print "extern struct priv_impl_info *priv_info;" > privhfile
344		print "extern struct priv_info_names *priv_ninfo;" > privhfile
345
346		print "\n/* Privileges */" > privhfile
347
348		for (i = 0; i < npriv; i++)
349			print pdef[i] sprintf("%3d", i) > privhfile
350
351		print "\n/* Privilege sets */" > privhfile
352		for (i = 0; i < nset; i++)
353			print sdef[i] sprintf("%3d", i) > privhfile
354
355		print "\n#define\tMAX_PRIVILEGE\t\t\t "  setsize * 32 \
356			> privhfile
357
358		# Special privilege categories.
359		for (s in set)
360			print "\n#define\tPRIV_" s "_ASSERT(set)" set[s] \
361				> privhfile
362
363		print "\n#endif /* _KERNEL */" > privhfile
364		print "\n#ifdef __cplusplus\n}\n#endif" > privhfile
365		print "\n#endif /* _SYS_PRIV_CONST_H */" > privhfile
366		close(privhfile)
367	}
368
369	if (pubhfile) {
370		cast="((const char *)"
371		print "#ifndef _SYS_PRIV_NAMES_H" > pubhfile
372		print "#define\t_SYS_PRIV_NAMES_H\n" > pubhfile
373
374		print pragma "\n" > pubhfile
375		print "#ifdef __cplusplus\nextern \"C\" {\n#endif\n" > pubhfile
376
377		print "#ifndef __PRIV_CONST_IMPL" > pubhfile
378		print "/*\n * Privilege names\n */" > pubhfile
379		for (i = 0; i < npriv; i++) {
380			print "/*\n" privcmt[i] " */" > pubhfile
381			print pdef[i] cast "\"" privs[i] "\")\n" > pubhfile
382		}
383
384		print "" > pubhfile
385
386		print "/*\n * Privilege set names\n */" > pubhfile
387		for (i = 0; i < nset; i++) {
388			print "/*\n" setcmt[i] " */" > pubhfile
389			print sdef[i] cast "\"" sets[i] "\")\n" > pubhfile
390		}
391
392		print "\n#endif /* __PRIV_CONST_IMPL */" > pubhfile
393		print "\n#ifdef __cplusplus\n}\n#endif" > pubhfile
394		print "\n#endif /* _SYS_PRIV_NAMES_H */" > pubhfile
395		close(pubhfile)
396	}
397
398	if (pnamesfile) {
399		print pnamescmt > pnamesfile
400		for (i = 0; i < npriv; i++) {
401			print privs[i] > pnamesfile
402			print privncmt[i] > pnamesfile
403		}
404	}
405
406}
407