1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 3*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 4*7c478bd9Sstevel@tonic-gate */ 5*7c478bd9Sstevel@tonic-gate 6*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 7*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 8*7c478bd9Sstevel@tonic-gate 9*7c478bd9Sstevel@tonic-gate /* 10*7c478bd9Sstevel@tonic-gate * Copyright (c) 1980, 1986, 1990 The Regents of the University of California. 11*7c478bd9Sstevel@tonic-gate * All rights reserved. 12*7c478bd9Sstevel@tonic-gate * 13*7c478bd9Sstevel@tonic-gate * Redistribution and use in source and binary forms are permitted 14*7c478bd9Sstevel@tonic-gate * provided that: (1) source distributions retain this entire copyright 15*7c478bd9Sstevel@tonic-gate * notice and comment, and (2) distributions including binaries display 16*7c478bd9Sstevel@tonic-gate * the following acknowledgement: ``This product includes software 17*7c478bd9Sstevel@tonic-gate * developed by the University of California, Berkeley and its contributors'' 18*7c478bd9Sstevel@tonic-gate * in the documentation or other materials provided with the distribution 19*7c478bd9Sstevel@tonic-gate * and in all advertising materials mentioning features or use of this 20*7c478bd9Sstevel@tonic-gate * software. Neither the name of the University nor the names of its 21*7c478bd9Sstevel@tonic-gate * contributors may be used to endorse or promote products derived 22*7c478bd9Sstevel@tonic-gate * from this software without specific prior written permission. 23*7c478bd9Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 24*7c478bd9Sstevel@tonic-gate * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 25*7c478bd9Sstevel@tonic-gate * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 26*7c478bd9Sstevel@tonic-gate */ 27*7c478bd9Sstevel@tonic-gate 28*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate #include <stdio.h> 31*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 32*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 33*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 34*7c478bd9Sstevel@tonic-gate #include <sys/mntent.h> 35*7c478bd9Sstevel@tonic-gate #include <sys/acl.h> 36*7c478bd9Sstevel@tonic-gate #include <sys/fs/ufs_acl.h> 37*7c478bd9Sstevel@tonic-gate 38*7c478bd9Sstevel@tonic-gate #define bcopy(f, t, n) memcpy(t, f, n) 39*7c478bd9Sstevel@tonic-gate #define bzero(s, n) memset(s, 0, n) 40*7c478bd9Sstevel@tonic-gate #define bcmp(s, d, n) memcmp(s, d, n) 41*7c478bd9Sstevel@tonic-gate 42*7c478bd9Sstevel@tonic-gate #define index(s, r) strchr(s, r) 43*7c478bd9Sstevel@tonic-gate #define rindex(s, r) strrchr(s, r) 44*7c478bd9Sstevel@tonic-gate 45*7c478bd9Sstevel@tonic-gate #include <sys/fs/ufs_fs.h> 46*7c478bd9Sstevel@tonic-gate #include <sys/vnode.h> 47*7c478bd9Sstevel@tonic-gate #include <string.h> 48*7c478bd9Sstevel@tonic-gate #include <sys/fs/ufs_inode.h> 49*7c478bd9Sstevel@tonic-gate #include "fsck.h" 50*7c478bd9Sstevel@tonic-gate 51*7c478bd9Sstevel@tonic-gate int pass3bcheck(struct inodesc *); 52*7c478bd9Sstevel@tonic-gate int aclblksort(); 53*7c478bd9Sstevel@tonic-gate void dodump(char *, int); 54*7c478bd9Sstevel@tonic-gate int bufchk(char *, int64_t); 55*7c478bd9Sstevel@tonic-gate void listshadows(void); 56*7c478bd9Sstevel@tonic-gate 57*7c478bd9Sstevel@tonic-gate pass3b() 58*7c478bd9Sstevel@tonic-gate { 59*7c478bd9Sstevel@tonic-gate ino_t inumber; 60*7c478bd9Sstevel@tonic-gate struct dinode *dp; 61*7c478bd9Sstevel@tonic-gate struct aclinfo *aclp; 62*7c478bd9Sstevel@tonic-gate struct inodesc curino; 63*7c478bd9Sstevel@tonic-gate char pathbuf[MAXPATHLEN + 1]; 64*7c478bd9Sstevel@tonic-gate int64_t maxaclsize = 0; 65*7c478bd9Sstevel@tonic-gate struct shadowclientinfo *sci; 66*7c478bd9Sstevel@tonic-gate struct shadowclients *scc; 67*7c478bd9Sstevel@tonic-gate int i; 68*7c478bd9Sstevel@tonic-gate 69*7c478bd9Sstevel@tonic-gate /* 70*7c478bd9Sstevel@tonic-gate * Sort the acl list into disk block order. 71*7c478bd9Sstevel@tonic-gate */ 72*7c478bd9Sstevel@tonic-gate qsort((char *)aclpsort, (int)aclplast, sizeof (*aclpsort), aclblksort); 73*7c478bd9Sstevel@tonic-gate /* 74*7c478bd9Sstevel@tonic-gate * Scan all the acl inodes, finding the largest acl file. 75*7c478bd9Sstevel@tonic-gate */ 76*7c478bd9Sstevel@tonic-gate for (inumber = 0; inumber < aclplast; inumber++) { 77*7c478bd9Sstevel@tonic-gate aclp = aclpsort[inumber]; 78*7c478bd9Sstevel@tonic-gate /* ACL file will not be >=2GB */ 79*7c478bd9Sstevel@tonic-gate if ((int64_t)aclp->i_isize > maxaclsize) 80*7c478bd9Sstevel@tonic-gate maxaclsize = (int64_t)aclp->i_isize; 81*7c478bd9Sstevel@tonic-gate } 82*7c478bd9Sstevel@tonic-gate maxaclsize = ((maxaclsize / sblock.fs_bsize) + 1) * 83*7c478bd9Sstevel@tonic-gate sblock.fs_bsize; 84*7c478bd9Sstevel@tonic-gate if ((aclbuf = malloc(maxaclsize)) == NULL) { 85*7c478bd9Sstevel@tonic-gate printf("cannot alloc %ld bytes for aclbuf\n", maxaclsize); 86*7c478bd9Sstevel@tonic-gate return (1); 87*7c478bd9Sstevel@tonic-gate } 88*7c478bd9Sstevel@tonic-gate /* 89*7c478bd9Sstevel@tonic-gate * Scan all the acl inodes, checking contents 90*7c478bd9Sstevel@tonic-gate */ 91*7c478bd9Sstevel@tonic-gate for (inumber = 0; inumber < aclplast; inumber++) { 92*7c478bd9Sstevel@tonic-gate aclp = aclpsort[inumber]; 93*7c478bd9Sstevel@tonic-gate dp = ginode(aclp->i_number); 94*7c478bd9Sstevel@tonic-gate curino.id_fix = FIX; 95*7c478bd9Sstevel@tonic-gate curino.id_type = ACL; 96*7c478bd9Sstevel@tonic-gate curino.id_func = pass3bcheck; 97*7c478bd9Sstevel@tonic-gate curino.id_number = aclp->i_number; 98*7c478bd9Sstevel@tonic-gate curino.id_filesize = aclp->i_isize; 99*7c478bd9Sstevel@tonic-gate aclbufoff = 0; 100*7c478bd9Sstevel@tonic-gate bzero(aclbuf, (size_t)maxaclsize); 101*7c478bd9Sstevel@tonic-gate if ((ckinode(dp, &curino) & KEEPON) == 0 || 102*7c478bd9Sstevel@tonic-gate bufchk(aclbuf, (int64_t)aclp->i_isize)) { 103*7c478bd9Sstevel@tonic-gate if (dp->di_nlink <= 0) { 104*7c478bd9Sstevel@tonic-gate statemap[aclp->i_number] = FSTATE; 105*7c478bd9Sstevel@tonic-gate continue; 106*7c478bd9Sstevel@tonic-gate } 107*7c478bd9Sstevel@tonic-gate printf("ACL I=%d BAD/CORRUPT", aclp->i_number); 108*7c478bd9Sstevel@tonic-gate if (preen || reply("CLEAR") == 1) { 109*7c478bd9Sstevel@tonic-gate if (preen) 110*7c478bd9Sstevel@tonic-gate printf("\n"); 111*7c478bd9Sstevel@tonic-gate freeino(aclp->i_number); 112*7c478bd9Sstevel@tonic-gate } 113*7c478bd9Sstevel@tonic-gate } 114*7c478bd9Sstevel@tonic-gate } 115*7c478bd9Sstevel@tonic-gate /* 116*7c478bd9Sstevel@tonic-gate * Now scan all shadow inodes, checking that any inodes that previously 117*7c478bd9Sstevel@tonic-gate * had an acl still have an acl. 118*7c478bd9Sstevel@tonic-gate */ 119*7c478bd9Sstevel@tonic-gate for (sci = shadowclientinfo; sci; sci = sci->next) { 120*7c478bd9Sstevel@tonic-gate if (statemap[sci->shadow] != SSTATE) { 121*7c478bd9Sstevel@tonic-gate for (scc = sci->clients; scc; scc = scc->next) { 122*7c478bd9Sstevel@tonic-gate for (i = 0; i < scc->nclients; i++) { 123*7c478bd9Sstevel@tonic-gate printf("I=%d HAS BAD/CLEARED ACL I=%d", 124*7c478bd9Sstevel@tonic-gate scc->client[i], sci->shadow); 125*7c478bd9Sstevel@tonic-gate if (preen || reply("FIX") == 1) { 126*7c478bd9Sstevel@tonic-gate if (preen) 127*7c478bd9Sstevel@tonic-gate printf("\n"); 128*7c478bd9Sstevel@tonic-gate dp = ginode(scc->client[i]); 129*7c478bd9Sstevel@tonic-gate dp->di_mode &= IFMT; 130*7c478bd9Sstevel@tonic-gate dp->di_smode = dp->di_mode; 131*7c478bd9Sstevel@tonic-gate /* 132*7c478bd9Sstevel@tonic-gate * Decrement link count - 133*7c478bd9Sstevel@tonic-gate * pass1 made sure the shadow 134*7c478bd9Sstevel@tonic-gate * inode # is a valid inode 135*7c478bd9Sstevel@tonic-gate * number. 136*7c478bd9Sstevel@tonic-gate */ 137*7c478bd9Sstevel@tonic-gate lncntp[dp->di_shadow]++; 138*7c478bd9Sstevel@tonic-gate dp->di_shadow = 0; 139*7c478bd9Sstevel@tonic-gate inodirty(); 140*7c478bd9Sstevel@tonic-gate } 141*7c478bd9Sstevel@tonic-gate } 142*7c478bd9Sstevel@tonic-gate } 143*7c478bd9Sstevel@tonic-gate } 144*7c478bd9Sstevel@tonic-gate } 145*7c478bd9Sstevel@tonic-gate /* listshadows(); */ 146*7c478bd9Sstevel@tonic-gate } 147*7c478bd9Sstevel@tonic-gate 148*7c478bd9Sstevel@tonic-gate /* 149*7c478bd9Sstevel@tonic-gate * Collect all the (data) blocks of an acl file into a buffer. 150*7c478bd9Sstevel@tonic-gate * Later we'll scan the buffer and validate the acl data. 151*7c478bd9Sstevel@tonic-gate */ 152*7c478bd9Sstevel@tonic-gate int 153*7c478bd9Sstevel@tonic-gate pass3bcheck(struct inodesc *idesc) 154*7c478bd9Sstevel@tonic-gate { 155*7c478bd9Sstevel@tonic-gate struct bufarea *bp; 156*7c478bd9Sstevel@tonic-gate int size, bsize; 157*7c478bd9Sstevel@tonic-gate 158*7c478bd9Sstevel@tonic-gate if (aclbufoff == idesc->id_filesize) { 159*7c478bd9Sstevel@tonic-gate return (STOP); 160*7c478bd9Sstevel@tonic-gate } 161*7c478bd9Sstevel@tonic-gate bsize = size = sblock.fs_fsize * idesc->id_numfrags; 162*7c478bd9Sstevel@tonic-gate if ((size + aclbufoff) > idesc->id_filesize) 163*7c478bd9Sstevel@tonic-gate size = idesc->id_filesize - aclbufoff; 164*7c478bd9Sstevel@tonic-gate bp = getdatablk(idesc->id_blkno, bsize); 165*7c478bd9Sstevel@tonic-gate bcopy(bp->b_un.b_buf, aclbuf + aclbufoff, (size_t)size); 166*7c478bd9Sstevel@tonic-gate aclbufoff += size; 167*7c478bd9Sstevel@tonic-gate brelse(bp); 168*7c478bd9Sstevel@tonic-gate return (KEEPON); 169*7c478bd9Sstevel@tonic-gate } 170*7c478bd9Sstevel@tonic-gate 171*7c478bd9Sstevel@tonic-gate /* 172*7c478bd9Sstevel@tonic-gate * Routine to sort disk blocks. 173*7c478bd9Sstevel@tonic-gate */ 174*7c478bd9Sstevel@tonic-gate aclblksort(aclpp1, aclpp2) 175*7c478bd9Sstevel@tonic-gate struct aclinfo **aclpp1, **aclpp2; 176*7c478bd9Sstevel@tonic-gate { 177*7c478bd9Sstevel@tonic-gate 178*7c478bd9Sstevel@tonic-gate return ((*aclpp1)->i_blks[0] - (*aclpp2)->i_blks[0]); 179*7c478bd9Sstevel@tonic-gate } 180*7c478bd9Sstevel@tonic-gate 181*7c478bd9Sstevel@tonic-gate int 182*7c478bd9Sstevel@tonic-gate bufchk(char *buf, int64_t len) 183*7c478bd9Sstevel@tonic-gate { 184*7c478bd9Sstevel@tonic-gate ufs_fsd_t *fsdp; 185*7c478bd9Sstevel@tonic-gate ufs_acl_t *ufsaclp = NULL; 186*7c478bd9Sstevel@tonic-gate int numacls; 187*7c478bd9Sstevel@tonic-gate int i; 188*7c478bd9Sstevel@tonic-gate int nuser_objs = 0; 189*7c478bd9Sstevel@tonic-gate int ngroup_objs = 0; 190*7c478bd9Sstevel@tonic-gate int nother_objs = 0; 191*7c478bd9Sstevel@tonic-gate int nclass_objs = 0; 192*7c478bd9Sstevel@tonic-gate int ndef_user_objs = 0; 193*7c478bd9Sstevel@tonic-gate int ndef_group_objs = 0; 194*7c478bd9Sstevel@tonic-gate int ndef_other_objs = 0; 195*7c478bd9Sstevel@tonic-gate int ndef_class_objs = 0; 196*7c478bd9Sstevel@tonic-gate int nusers = 0; 197*7c478bd9Sstevel@tonic-gate int ngroups = 0; 198*7c478bd9Sstevel@tonic-gate int ndef_users = 0; 199*7c478bd9Sstevel@tonic-gate int ndef_groups = 0; 200*7c478bd9Sstevel@tonic-gate int numdefs = 0; 201*7c478bd9Sstevel@tonic-gate 202*7c478bd9Sstevel@tonic-gate for (fsdp = (ufs_fsd_t *)buf; 203*7c478bd9Sstevel@tonic-gate (caddr_t)fsdp < (buf + len) && 204*7c478bd9Sstevel@tonic-gate ((caddr_t)fsdp + fsdp->fsd_size) <= (buf + len); 205*7c478bd9Sstevel@tonic-gate fsdp = (ufs_fsd_t *)((caddr_t)fsdp + 206*7c478bd9Sstevel@tonic-gate FSD_RECSZ(fsdp, fsdp->fsd_size))) { 207*7c478bd9Sstevel@tonic-gate switch (fsdp->fsd_type) { 208*7c478bd9Sstevel@tonic-gate case FSD_ACL: 209*7c478bd9Sstevel@tonic-gate case FSD_DFACL: 210*7c478bd9Sstevel@tonic-gate numacls = (fsdp->fsd_size - 2 * sizeof (int)) / 211*7c478bd9Sstevel@tonic-gate sizeof (ufs_acl_t); 212*7c478bd9Sstevel@tonic-gate for (ufsaclp = (ufs_acl_t *)fsdp->fsd_data; 213*7c478bd9Sstevel@tonic-gate numacls; ufsaclp++) { 214*7c478bd9Sstevel@tonic-gate switch (ufsaclp->acl_tag) { 215*7c478bd9Sstevel@tonic-gate case USER_OBJ: /* Owner */ 216*7c478bd9Sstevel@tonic-gate nuser_objs++; 217*7c478bd9Sstevel@tonic-gate break; 218*7c478bd9Sstevel@tonic-gate case GROUP_OBJ: /* Group */ 219*7c478bd9Sstevel@tonic-gate ngroup_objs++; 220*7c478bd9Sstevel@tonic-gate break; 221*7c478bd9Sstevel@tonic-gate case OTHER_OBJ: /* Other */ 222*7c478bd9Sstevel@tonic-gate nother_objs++; 223*7c478bd9Sstevel@tonic-gate break; 224*7c478bd9Sstevel@tonic-gate case CLASS_OBJ: /* Mask */ 225*7c478bd9Sstevel@tonic-gate nclass_objs++; 226*7c478bd9Sstevel@tonic-gate break; 227*7c478bd9Sstevel@tonic-gate case DEF_USER_OBJ: /* Default Owner */ 228*7c478bd9Sstevel@tonic-gate ndef_user_objs++; 229*7c478bd9Sstevel@tonic-gate break; 230*7c478bd9Sstevel@tonic-gate case DEF_GROUP_OBJ: /* Default Group */ 231*7c478bd9Sstevel@tonic-gate ndef_group_objs++; 232*7c478bd9Sstevel@tonic-gate break; 233*7c478bd9Sstevel@tonic-gate case DEF_OTHER_OBJ: /* Default Other */ 234*7c478bd9Sstevel@tonic-gate ndef_other_objs++; 235*7c478bd9Sstevel@tonic-gate break; 236*7c478bd9Sstevel@tonic-gate case DEF_CLASS_OBJ: /* Default Mask */ 237*7c478bd9Sstevel@tonic-gate ndef_class_objs++; 238*7c478bd9Sstevel@tonic-gate break; 239*7c478bd9Sstevel@tonic-gate case USER: /* Users */ 240*7c478bd9Sstevel@tonic-gate nusers++; 241*7c478bd9Sstevel@tonic-gate break; 242*7c478bd9Sstevel@tonic-gate case GROUP: /* Groups */ 243*7c478bd9Sstevel@tonic-gate ngroups++; 244*7c478bd9Sstevel@tonic-gate break; 245*7c478bd9Sstevel@tonic-gate case DEF_USER: /* Default Users */ 246*7c478bd9Sstevel@tonic-gate ndef_users++; 247*7c478bd9Sstevel@tonic-gate break; 248*7c478bd9Sstevel@tonic-gate case DEF_GROUP: /* Default Groups */ 249*7c478bd9Sstevel@tonic-gate ndef_groups++; 250*7c478bd9Sstevel@tonic-gate break; 251*7c478bd9Sstevel@tonic-gate default: 252*7c478bd9Sstevel@tonic-gate return (1); 253*7c478bd9Sstevel@tonic-gate } 254*7c478bd9Sstevel@tonic-gate /* 255*7c478bd9Sstevel@tonic-gate * if ((ufsaclp->acl_perm & ~07) != 0) { 256*7c478bd9Sstevel@tonic-gate * return (1); 257*7c478bd9Sstevel@tonic-gate * } 258*7c478bd9Sstevel@tonic-gate */ 259*7c478bd9Sstevel@tonic-gate numacls--; 260*7c478bd9Sstevel@tonic-gate } 261*7c478bd9Sstevel@tonic-gate break; 262*7c478bd9Sstevel@tonic-gate default: 263*7c478bd9Sstevel@tonic-gate break; 264*7c478bd9Sstevel@tonic-gate } 265*7c478bd9Sstevel@tonic-gate } 266*7c478bd9Sstevel@tonic-gate if ((caddr_t)fsdp != (buf + len)) { 267*7c478bd9Sstevel@tonic-gate return (1); 268*7c478bd9Sstevel@tonic-gate } 269*7c478bd9Sstevel@tonic-gate 270*7c478bd9Sstevel@tonic-gate /* If we didn't find any acls, ignore the unknown attribute */ 271*7c478bd9Sstevel@tonic-gate if (ufsaclp == NULL) 272*7c478bd9Sstevel@tonic-gate return (0); 273*7c478bd9Sstevel@tonic-gate 274*7c478bd9Sstevel@tonic-gate /* Check relationships amoung acls */ 275*7c478bd9Sstevel@tonic-gate if (nuser_objs != 1 || ngroup_objs != 1 || 276*7c478bd9Sstevel@tonic-gate nother_objs != 1 || nclass_objs > 1) { 277*7c478bd9Sstevel@tonic-gate return (1); 278*7c478bd9Sstevel@tonic-gate } 279*7c478bd9Sstevel@tonic-gate if (ngroups && !nclass_objs) { 280*7c478bd9Sstevel@tonic-gate return (1); 281*7c478bd9Sstevel@tonic-gate } 282*7c478bd9Sstevel@tonic-gate if (ndef_other_objs > 1 || ndef_user_objs > 1 || 283*7c478bd9Sstevel@tonic-gate ndef_group_objs > 1 || ndef_class_objs > 1) { 284*7c478bd9Sstevel@tonic-gate return (1); 285*7c478bd9Sstevel@tonic-gate } 286*7c478bd9Sstevel@tonic-gate 287*7c478bd9Sstevel@tonic-gate /* Check relationships amoung default acls */ 288*7c478bd9Sstevel@tonic-gate numdefs = ndef_other_objs + ndef_user_objs + ndef_group_objs; 289*7c478bd9Sstevel@tonic-gate if (numdefs != 0 && numdefs != 3) { 290*7c478bd9Sstevel@tonic-gate return (1); 291*7c478bd9Sstevel@tonic-gate } 292*7c478bd9Sstevel@tonic-gate if (ndef_groups && !ndef_class_objs) { 293*7c478bd9Sstevel@tonic-gate return (1); 294*7c478bd9Sstevel@tonic-gate } 295*7c478bd9Sstevel@tonic-gate if ((ndef_users || ndef_groups) && 296*7c478bd9Sstevel@tonic-gate ((numdefs != 3) && !ndef_class_objs)) { 297*7c478bd9Sstevel@tonic-gate return (1); 298*7c478bd9Sstevel@tonic-gate } 299*7c478bd9Sstevel@tonic-gate return (0); 300*7c478bd9Sstevel@tonic-gate } 301