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