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