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