xref: /illumos-gate/usr/src/uts/common/c2/audit_path.c (revision 7c478bd9)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 1991-2003 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate /*
30*7c478bd9Sstevel@tonic-gate  * @(#)audit_path.c 2.7 92/02/16 SMI; SunOS CMW
31*7c478bd9Sstevel@tonic-gate  * @(#)audit_path.c 4.2.1.2 91/05/08 SMI; BSM Module
32*7c478bd9Sstevel@tonic-gate  *
33*7c478bd9Sstevel@tonic-gate  * This code does the audit path processes. Part of this is still in
34*7c478bd9Sstevel@tonic-gate  * audit.c and will be moved here when time permits.
35*7c478bd9Sstevel@tonic-gate  *
36*7c478bd9Sstevel@tonic-gate  * Note that audit debuging is enabled here. We will turn it off at
37*7c478bd9Sstevel@tonic-gate  * beta shipment.
38*7c478bd9Sstevel@tonic-gate  */
39*7c478bd9Sstevel@tonic-gate 
40*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
41*7c478bd9Sstevel@tonic-gate #include <sys/param.h>
42*7c478bd9Sstevel@tonic-gate #include <sys/systm.h>
43*7c478bd9Sstevel@tonic-gate #include <sys/user.h>
44*7c478bd9Sstevel@tonic-gate #include <sys/vnode.h>
45*7c478bd9Sstevel@tonic-gate #include <sys/vfs.h>
46*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h>		/* for KM_SLEEP */
47*7c478bd9Sstevel@tonic-gate #include <sys/proc.h>
48*7c478bd9Sstevel@tonic-gate #include <sys/uio.h>
49*7c478bd9Sstevel@tonic-gate #include <sys/file.h>
50*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
51*7c478bd9Sstevel@tonic-gate #include <sys/pathname.h>
52*7c478bd9Sstevel@tonic-gate #include <sys/acct.h>
53*7c478bd9Sstevel@tonic-gate #include <c2/audit.h>
54*7c478bd9Sstevel@tonic-gate #include <c2/audit_kernel.h>
55*7c478bd9Sstevel@tonic-gate #include <c2/audit_record.h>
56*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
57*7c478bd9Sstevel@tonic-gate #include <sys/atomic.h>
58*7c478bd9Sstevel@tonic-gate 
59*7c478bd9Sstevel@tonic-gate /*
60*7c478bd9Sstevel@tonic-gate  * allocate a new auditpath
61*7c478bd9Sstevel@tonic-gate  *	newsect = increment sections count,
62*7c478bd9Sstevel@tonic-gate  *	charincr = change in strings storage
63*7c478bd9Sstevel@tonic-gate  */
64*7c478bd9Sstevel@tonic-gate struct audit_path *
65*7c478bd9Sstevel@tonic-gate au_pathdup(const struct audit_path *oldapp, int newsect, int charincr)
66*7c478bd9Sstevel@tonic-gate {
67*7c478bd9Sstevel@tonic-gate 	struct audit_path	*newapp;
68*7c478bd9Sstevel@tonic-gate 	int	i, alloc_size, oldlen;
69*7c478bd9Sstevel@tonic-gate 	char	*oldcp, *newcp;
70*7c478bd9Sstevel@tonic-gate 
71*7c478bd9Sstevel@tonic-gate 	newsect = (newsect != 0);
72*7c478bd9Sstevel@tonic-gate 	oldcp = oldapp->audp_sect[0];
73*7c478bd9Sstevel@tonic-gate 	oldlen = (oldapp->audp_sect[oldapp->audp_cnt] - oldcp);
74*7c478bd9Sstevel@tonic-gate 	alloc_size = sizeof (struct audit_path) +
75*7c478bd9Sstevel@tonic-gate 	    (oldapp->audp_cnt + newsect) * sizeof (char *) +
76*7c478bd9Sstevel@tonic-gate 	    oldlen + charincr;
77*7c478bd9Sstevel@tonic-gate 
78*7c478bd9Sstevel@tonic-gate 	newapp = kmem_alloc(alloc_size, KM_SLEEP);
79*7c478bd9Sstevel@tonic-gate 	newapp->audp_ref = 1;
80*7c478bd9Sstevel@tonic-gate 	newapp->audp_size = alloc_size;
81*7c478bd9Sstevel@tonic-gate 
82*7c478bd9Sstevel@tonic-gate 	newapp->audp_cnt = oldapp->audp_cnt + newsect;
83*7c478bd9Sstevel@tonic-gate 	newcp = (char *)(&newapp->audp_sect[newapp->audp_cnt + 1]);
84*7c478bd9Sstevel@tonic-gate 	for (i = 0; i <= oldapp->audp_cnt; i++) {
85*7c478bd9Sstevel@tonic-gate 		newapp->audp_sect[i] = newcp +
86*7c478bd9Sstevel@tonic-gate 		    (oldapp->audp_sect[i] - oldcp);
87*7c478bd9Sstevel@tonic-gate 	}
88*7c478bd9Sstevel@tonic-gate 	/*
89*7c478bd9Sstevel@tonic-gate 	 * if this is a new section, set its end
90*7c478bd9Sstevel@tonic-gate 	 * if this is an extended section, reset its end
91*7c478bd9Sstevel@tonic-gate 	 */
92*7c478bd9Sstevel@tonic-gate 	newapp->audp_sect[newapp->audp_cnt] = newcp + oldlen + charincr;
93*7c478bd9Sstevel@tonic-gate 	/* copy all of the old strings */
94*7c478bd9Sstevel@tonic-gate 	bcopy(oldcp, newcp, oldlen);
95*7c478bd9Sstevel@tonic-gate 
96*7c478bd9Sstevel@tonic-gate 	return (newapp);
97*7c478bd9Sstevel@tonic-gate }
98*7c478bd9Sstevel@tonic-gate 
99*7c478bd9Sstevel@tonic-gate /*
100*7c478bd9Sstevel@tonic-gate  * increment audit path reference count
101*7c478bd9Sstevel@tonic-gate  */
102*7c478bd9Sstevel@tonic-gate void
103*7c478bd9Sstevel@tonic-gate au_pathhold(struct audit_path *app)
104*7c478bd9Sstevel@tonic-gate {
105*7c478bd9Sstevel@tonic-gate 	atomic_add_32(&app->audp_ref, 1);
106*7c478bd9Sstevel@tonic-gate }
107*7c478bd9Sstevel@tonic-gate 
108*7c478bd9Sstevel@tonic-gate /*
109*7c478bd9Sstevel@tonic-gate  * decrement audit path reference count
110*7c478bd9Sstevel@tonic-gate  */
111*7c478bd9Sstevel@tonic-gate void
112*7c478bd9Sstevel@tonic-gate au_pathrele(struct audit_path *app)
113*7c478bd9Sstevel@tonic-gate {
114*7c478bd9Sstevel@tonic-gate 	if (atomic_add_32_nv(&app->audp_ref, -1) > 0)
115*7c478bd9Sstevel@tonic-gate 		return;
116*7c478bd9Sstevel@tonic-gate 	kmem_free(app, app->audp_size);
117*7c478bd9Sstevel@tonic-gate }
118*7c478bd9Sstevel@tonic-gate 
119*7c478bd9Sstevel@tonic-gate 
120*7c478bd9Sstevel@tonic-gate int
121*7c478bd9Sstevel@tonic-gate au_token_size(m)
122*7c478bd9Sstevel@tonic-gate 	token_t *m;
123*7c478bd9Sstevel@tonic-gate {
124*7c478bd9Sstevel@tonic-gate 	int i;
125*7c478bd9Sstevel@tonic-gate 
126*7c478bd9Sstevel@tonic-gate 	if (m == (token_t *)0)
127*7c478bd9Sstevel@tonic-gate 		return (0);
128*7c478bd9Sstevel@tonic-gate 
129*7c478bd9Sstevel@tonic-gate 	for (i = 0; m != (token_t *)0; m = m->next_buf)
130*7c478bd9Sstevel@tonic-gate 		i += m->len;
131*7c478bd9Sstevel@tonic-gate 	return (i);
132*7c478bd9Sstevel@tonic-gate }
133*7c478bd9Sstevel@tonic-gate 
134*7c478bd9Sstevel@tonic-gate token_t *
135*7c478bd9Sstevel@tonic-gate au_set(cp, size)
136*7c478bd9Sstevel@tonic-gate 	caddr_t  cp;
137*7c478bd9Sstevel@tonic-gate 	uint_t    size;
138*7c478bd9Sstevel@tonic-gate {
139*7c478bd9Sstevel@tonic-gate 	au_buff_t *head;
140*7c478bd9Sstevel@tonic-gate 	au_buff_t *tail;
141*7c478bd9Sstevel@tonic-gate 	au_buff_t *m;
142*7c478bd9Sstevel@tonic-gate 	uint_t	l;
143*7c478bd9Sstevel@tonic-gate 
144*7c478bd9Sstevel@tonic-gate 	head = NULL;
145*7c478bd9Sstevel@tonic-gate 	tail = NULL;	/* only to satisfy lint */
146*7c478bd9Sstevel@tonic-gate 
147*7c478bd9Sstevel@tonic-gate 	while (size) {
148*7c478bd9Sstevel@tonic-gate 		m = au_get_buff();
149*7c478bd9Sstevel@tonic-gate 		l = MIN(size, AU_BUFSIZE);
150*7c478bd9Sstevel@tonic-gate 		bcopy(cp, memtod(m, char *), l);
151*7c478bd9Sstevel@tonic-gate 		m->len = l;
152*7c478bd9Sstevel@tonic-gate 
153*7c478bd9Sstevel@tonic-gate 		if (head)
154*7c478bd9Sstevel@tonic-gate 			tail->next_buf = m;	/* tail set if head set */
155*7c478bd9Sstevel@tonic-gate 		else
156*7c478bd9Sstevel@tonic-gate 			head = m;
157*7c478bd9Sstevel@tonic-gate 		tail = m;
158*7c478bd9Sstevel@tonic-gate 		size -= l;
159*7c478bd9Sstevel@tonic-gate 		cp += l;
160*7c478bd9Sstevel@tonic-gate 	}
161*7c478bd9Sstevel@tonic-gate 
162*7c478bd9Sstevel@tonic-gate 	return (head);
163*7c478bd9Sstevel@tonic-gate }
164*7c478bd9Sstevel@tonic-gate 
165*7c478bd9Sstevel@tonic-gate token_t *
166*7c478bd9Sstevel@tonic-gate au_append_token(chain, m)
167*7c478bd9Sstevel@tonic-gate 	token_t *chain;
168*7c478bd9Sstevel@tonic-gate 	token_t *m;
169*7c478bd9Sstevel@tonic-gate {
170*7c478bd9Sstevel@tonic-gate 	token_t *mbp;
171*7c478bd9Sstevel@tonic-gate 
172*7c478bd9Sstevel@tonic-gate 	if (chain == (token_t *)0)
173*7c478bd9Sstevel@tonic-gate 		return (m);
174*7c478bd9Sstevel@tonic-gate 
175*7c478bd9Sstevel@tonic-gate 	if (m == (token_t *)0)
176*7c478bd9Sstevel@tonic-gate 		return (chain);
177*7c478bd9Sstevel@tonic-gate 
178*7c478bd9Sstevel@tonic-gate 	for (mbp = chain; mbp->next_buf != (token_t *)0; mbp = mbp->next_buf)
179*7c478bd9Sstevel@tonic-gate 		;
180*7c478bd9Sstevel@tonic-gate 	mbp->next_buf = m;
181*7c478bd9Sstevel@tonic-gate 	return (chain);
182*7c478bd9Sstevel@tonic-gate }
183*7c478bd9Sstevel@tonic-gate 
184*7c478bd9Sstevel@tonic-gate 
185*7c478bd9Sstevel@tonic-gate void
186*7c478bd9Sstevel@tonic-gate audit_fixpath(struct audit_path *app, int len)
187*7c478bd9Sstevel@tonic-gate {
188*7c478bd9Sstevel@tonic-gate 	int id;		/* index of where we are in destination string */
189*7c478bd9Sstevel@tonic-gate 	int is;		/* index of where we are in source string */
190*7c478bd9Sstevel@tonic-gate 	int cnt;	/* # of levels in audit_path */
191*7c478bd9Sstevel@tonic-gate 	int slashseen;	/* have we seen a slash */
192*7c478bd9Sstevel@tonic-gate 	char *s;	/* start of top-level string */
193*7c478bd9Sstevel@tonic-gate 	char c;
194*7c478bd9Sstevel@tonic-gate 
195*7c478bd9Sstevel@tonic-gate 	cnt = app->audp_cnt;
196*7c478bd9Sstevel@tonic-gate 	s = app->audp_sect[cnt - 1];
197*7c478bd9Sstevel@tonic-gate 	is = (app->audp_sect[cnt] - s) - len;
198*7c478bd9Sstevel@tonic-gate 	if (is <= 2)
199*7c478bd9Sstevel@tonic-gate 		is = 0;	/* catch leading // or ./ */
200*7c478bd9Sstevel@tonic-gate 	slashseen = (is > 0);
201*7c478bd9Sstevel@tonic-gate 	for (id = is; ; is++) {
202*7c478bd9Sstevel@tonic-gate 		if ((c = s[is]) == '\0') {
203*7c478bd9Sstevel@tonic-gate 			/* that's all folks, we've reached the end of input */
204*7c478bd9Sstevel@tonic-gate 			if (id > 1 && s[id-1] == '/') {
205*7c478bd9Sstevel@tonic-gate 				/* remove terminating / */
206*7c478bd9Sstevel@tonic-gate 				--id;
207*7c478bd9Sstevel@tonic-gate 			}
208*7c478bd9Sstevel@tonic-gate 			s[id++] = '\0';
209*7c478bd9Sstevel@tonic-gate 			break;
210*7c478bd9Sstevel@tonic-gate 		}
211*7c478bd9Sstevel@tonic-gate 		if (slashseen) {
212*7c478bd9Sstevel@tonic-gate 			/* previous character was a / */
213*7c478bd9Sstevel@tonic-gate 			if (c == '/') {
214*7c478bd9Sstevel@tonic-gate 				/* another slash, ignore it */
215*7c478bd9Sstevel@tonic-gate 				continue;
216*7c478bd9Sstevel@tonic-gate 			}
217*7c478bd9Sstevel@tonic-gate 		} else if (c == '/') {
218*7c478bd9Sstevel@tonic-gate 			/* we see a /, just copy it and try again */
219*7c478bd9Sstevel@tonic-gate 			slashseen = 1;
220*7c478bd9Sstevel@tonic-gate 			s[id++] = c;
221*7c478bd9Sstevel@tonic-gate 			continue;
222*7c478bd9Sstevel@tonic-gate 		}
223*7c478bd9Sstevel@tonic-gate 		if (c == '.') {
224*7c478bd9Sstevel@tonic-gate 			if ((c = s[is+1]) == '\0') {
225*7c478bd9Sstevel@tonic-gate 				/* XXX/. seen */
226*7c478bd9Sstevel@tonic-gate 				if (id > 1)
227*7c478bd9Sstevel@tonic-gate 					id--;
228*7c478bd9Sstevel@tonic-gate 				continue;
229*7c478bd9Sstevel@tonic-gate 			}
230*7c478bd9Sstevel@tonic-gate 			if (c == '/') {
231*7c478bd9Sstevel@tonic-gate 				/* XXX/./ seen */
232*7c478bd9Sstevel@tonic-gate 				is += 1;
233*7c478bd9Sstevel@tonic-gate 				continue;
234*7c478bd9Sstevel@tonic-gate 			}
235*7c478bd9Sstevel@tonic-gate 			if (c == '.' && (s[is+2] == '\0' || s[is+2] == '/')) {
236*7c478bd9Sstevel@tonic-gate 				/* XXX/.. or XXX/../ seen */
237*7c478bd9Sstevel@tonic-gate 				is++;
238*7c478bd9Sstevel@tonic-gate 				if (id == 0 && cnt > 1) {
239*7c478bd9Sstevel@tonic-gate 					char	*s_attr;
240*7c478bd9Sstevel@tonic-gate 					/* .. refers to attributed object */
241*7c478bd9Sstevel@tonic-gate 					app->audp_cnt = --cnt;
242*7c478bd9Sstevel@tonic-gate 					s_attr = s;
243*7c478bd9Sstevel@tonic-gate 					s = app->audp_sect[cnt - 1];
244*7c478bd9Sstevel@tonic-gate 					id = s_attr - s;
245*7c478bd9Sstevel@tonic-gate 					is += id;
246*7c478bd9Sstevel@tonic-gate 					id--;
247*7c478bd9Sstevel@tonic-gate 					slashseen = 0;
248*7c478bd9Sstevel@tonic-gate 					continue;
249*7c478bd9Sstevel@tonic-gate 				}
250*7c478bd9Sstevel@tonic-gate 				/* backup over previous component */
251*7c478bd9Sstevel@tonic-gate 				if (id > 0)
252*7c478bd9Sstevel@tonic-gate 					id--;
253*7c478bd9Sstevel@tonic-gate 				while (id > 0 && s[id - 1] != '/')
254*7c478bd9Sstevel@tonic-gate 					id--;
255*7c478bd9Sstevel@tonic-gate 				continue;
256*7c478bd9Sstevel@tonic-gate 			}
257*7c478bd9Sstevel@tonic-gate 		}
258*7c478bd9Sstevel@tonic-gate 		/* copy component name and terminating /, if any */
259*7c478bd9Sstevel@tonic-gate 		for (;;) {
260*7c478bd9Sstevel@tonic-gate 			c = s[is++];
261*7c478bd9Sstevel@tonic-gate 			if (c == '\0' || c == '/')
262*7c478bd9Sstevel@tonic-gate 				break;
263*7c478bd9Sstevel@tonic-gate 			s[id++] = c;
264*7c478bd9Sstevel@tonic-gate 		}
265*7c478bd9Sstevel@tonic-gate 		/* back up to before terminating '\0' or / */
266*7c478bd9Sstevel@tonic-gate 		slashseen = 0;
267*7c478bd9Sstevel@tonic-gate 		is -= 2;
268*7c478bd9Sstevel@tonic-gate 	}
269*7c478bd9Sstevel@tonic-gate 	/* fill empty attribute directory reference */
270*7c478bd9Sstevel@tonic-gate 	if (id == 1 && cnt > 1) {
271*7c478bd9Sstevel@tonic-gate 		s[0] = '.';
272*7c478bd9Sstevel@tonic-gate 		s[1] = '\0';
273*7c478bd9Sstevel@tonic-gate 		id = 2;
274*7c478bd9Sstevel@tonic-gate 	}
275*7c478bd9Sstevel@tonic-gate 	/* correct end pointer */
276*7c478bd9Sstevel@tonic-gate 	app->audp_sect[cnt] = s + id;
277*7c478bd9Sstevel@tonic-gate }
278