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