1 /* 2 * Copyright 2007 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 #include <sys/fs/ufs_fs.h> 38 #include <sys/vnode.h> 39 #include <string.h> 40 #include <sys/fs/ufs_inode.h> 41 #include "fsck.h" 42 43 /* 44 * We can be run on multiple filesystems (processed serially), so 45 * these need to be re-initialized each time we start the pass. 46 */ 47 static caddr_t aclbuf; /* hold acl's for parsing */ 48 static int64_t aclbufoff; /* offset into aclbuf */ 49 static int64_t maxaclsize; /* how big aclbuf is */ 50 51 static int aclblksort(const void *, const void *); 52 static int bufchk(char *, int64_t, fsck_ino_t); 53 static void clear_shadow_client(struct shadowclientinfo *, 54 struct shadowclients *, int); 55 56 void 57 pass3b(void) 58 { 59 fsck_ino_t inumber; 60 struct dinode *dp; 61 struct inoinfo *aclp; 62 struct inodesc curino; 63 struct shadowclientinfo *sci; 64 struct shadowclients *scc; 65 int64_t acl_size_limit; 66 int i; 67 68 /* 69 * Sort the acl list into disk block order. 70 */ 71 qsort((char *)aclpsort, (int)aclplast, sizeof (*aclpsort), aclblksort); 72 /* 73 * Scan all the acl inodes, finding the largest acl file. 74 * 75 * The largest legal size is (4 * MAX_ACL_ENTRIES + 8) entries. 76 * The four are the categories of specific users, specific 77 * groups, default specific users, and default specific groups. 78 * The eight are the entries for the owning user/group/other/class 79 * plus the equivalent defaults. 80 * 81 * We double this to allow for a truly worst-case but legal 82 * situation of every single acl having its own fsd_t wrapper. 83 * Doubling is a bit pessimistic (sizeof (acl_t) > sizeof (fsd_t)). 84 */ 85 acl_size_limit = sizeof (ufs_acl_t) * (4 * MAX_ACL_ENTRIES + 8); 86 acl_size_limit *= 2; 87 88 maxaclsize = 0; 89 for (inumber = 0; inumber < aclplast; inumber++) { 90 aclp = aclpsort[inumber]; 91 if ((int64_t)aclp->i_isize > acl_size_limit) { 92 (void) printf( 93 "ACL I=%d is excessively large (%lld > %lld)", 94 inumber, 95 (longlong_t)aclp->i_isize, 96 (longlong_t)acl_size_limit); 97 if (preen) { 98 (void) printf(" (IGNORING)\n"); 99 } else if (reply("CLEAR") == 1) { 100 freeino(inumber, TI_PARENT); 101 } else { 102 iscorrupt = 1; 103 (void) printf("IGNORING SHADOW I=%d\n", 104 inumber); 105 } 106 continue; 107 } 108 if ((int64_t)aclp->i_isize > maxaclsize) 109 maxaclsize = (int64_t)aclp->i_isize; 110 } 111 112 maxaclsize = ((maxaclsize / sblock.fs_bsize) + 1) * sblock.fs_bsize; 113 if (maxaclsize == 0) 114 goto noacls; 115 116 if (aclbuf != NULL) { 117 free((void *)aclbuf); 118 } 119 if ((aclbuf = malloc(maxaclsize)) == NULL) { 120 errexit("cannot alloc %lld bytes for aclbuf\n", 121 (longlong_t)maxaclsize); 122 } 123 /* 124 * Scan all the acl inodes, checking contents 125 */ 126 for (inumber = 0; inumber < aclplast; inumber++) { 127 aclp = aclpsort[inumber]; 128 if ((int64_t)aclp->i_isize > acl_size_limit) { 129 continue; 130 } 131 if ((statemap[aclp->i_number] & STMASK) != SSTATE) { 132 continue; 133 } 134 dp = ginode(aclp->i_number); 135 init_inodesc(&curino); 136 curino.id_fix = FIX; 137 curino.id_type = ACL; 138 curino.id_func = pass3bcheck; 139 curino.id_number = aclp->i_number; 140 curino.id_filesize = aclp->i_isize; 141 aclbufoff = 0; 142 (void) memset(aclbuf, 0, (size_t)maxaclsize); 143 if ((ckinode(dp, &curino, CKI_TRAVERSE) & KEEPON) == 0 || 144 bufchk(aclbuf, (int64_t)aclp->i_isize, aclp->i_number)) { 145 dp = ginode(aclp->i_number); /* defensive no-op */ 146 if (dp->di_nlink <= 0) { 147 statemap[aclp->i_number] = FSTATE; 148 continue; 149 } 150 (void) printf("ACL I=%d BAD/CORRUPT", aclp->i_number); 151 if (preen || reply("CLEAR") == 1) { 152 if (preen) 153 (void) printf("\n"); 154 freeino(aclp->i_number, TI_PARENT); 155 } else { 156 iscorrupt = 1; 157 } 158 } 159 } 160 /* 161 * Now scan all shadow inodes, checking that any inodes that previously 162 * had an acl still have an acl. 163 */ 164 noacls: 165 for (sci = shadowclientinfo; sci; sci = sci->next) { 166 if ((statemap[sci->shadow] & STMASK) != SSTATE) { 167 for (scc = sci->clients; scc; scc = scc->next) { 168 for (i = 0; i < scc->nclients; i++) { 169 clear_shadow_client(sci, scc, i); 170 } 171 } 172 } 173 } 174 free((void *)aclbuf); 175 aclbuf = NULL; 176 } 177 178 static void 179 clear_shadow_client(struct shadowclientinfo *sci, struct shadowclients *scc, 180 int client) 181 { 182 int suppress_update = 0; 183 caddr_t flow; 184 struct inodesc ldesc; 185 struct dinode *dp; 186 187 (void) printf("I=%d HAS BAD/CLEARED ACL I=%d", 188 scc->client[client], sci->shadow); 189 if (preen || reply("FIX") == 1) { 190 if (preen) 191 (void) printf("\n"); 192 193 /* 194 * If we clear the ACL, then the permissions should 195 * be as restrictive as possible until the user can 196 * set it to something reasonable. If we keep the 197 * ACL, then the permissions are pretty much 198 * irrelevant. So, just always clear the permission 199 * bits. 200 */ 201 dp = ginode(scc->client[client]); 202 dp->di_mode &= IFMT; 203 dp->di_shadow = 0; 204 inodirty(); 205 206 /* 207 * Decrement in-memory link count - pass1 made sure 208 * the shadow inode # is a valid inode number. But 209 * first, see if we're going to overflow our sixteen 210 * bits. 211 */ 212 LINK_RANGE(flow, lncntp[dp->di_shadow], 1); 213 if (flow != NULL) { 214 LINK_CLEAR(flow, scc->client[client], dp->di_mode, 215 &ldesc); 216 if (statemap[scc->client[client]] == USTATE) 217 suppress_update = 1; 218 } 219 220 /* 221 * We don't touch the shadow's on-disk link count, 222 * because we've already cleared its state in pass3b(). 223 * Here we're just trying to keep lncntp[] in sync, so 224 * we can detect spurious links. 225 */ 226 if (!suppress_update) 227 TRACK_LNCNTP(sci->shadow, lncntp[sci->shadow]++); 228 } else { 229 iscorrupt = 1; 230 } 231 } 232 233 /* 234 * Collect all the (data) blocks of an acl file into a buffer. 235 * Later we'll scan the buffer and validate the acl data. 236 */ 237 int 238 pass3bcheck(struct inodesc *idesc) 239 { 240 struct bufarea *bp; 241 size_t size, bsize; 242 243 if (aclbufoff == idesc->id_filesize) { 244 return (STOP); 245 } 246 bsize = size = sblock.fs_fsize * idesc->id_numfrags; 247 if ((size + aclbufoff) > idesc->id_filesize) 248 size = idesc->id_filesize - aclbufoff; 249 if (aclbufoff + size > maxaclsize) 250 errexit("acl size %lld exceeds maximum calculated " 251 "size of %lld bytes", 252 (longlong_t)aclbufoff + size, (longlong_t)maxaclsize); 253 bp = getdatablk(idesc->id_blkno, bsize); 254 if (bp->b_errs != 0) { 255 brelse(bp); 256 return (STOP); 257 } 258 (void) memmove((void *)(aclbuf + aclbufoff), (void *)bp->b_un.b_buf, 259 (size_t)size); 260 aclbufoff += size; 261 brelse(bp); 262 return (KEEPON); 263 } 264 265 /* 266 * Routine to sort disk blocks. 267 */ 268 static int 269 aclblksort(const void *pp1, const void *pp2) 270 { 271 const struct inoinfo **aclpp1 = (const struct inoinfo **)pp1; 272 const struct inoinfo **aclpp2 = (const struct inoinfo **)pp2; 273 274 return ((*aclpp1)->i_blks[0] - (*aclpp2)->i_blks[0]); 275 } 276 277 /* 278 * Scan a chunk of a shadow file. Return zero if no ACLs were found, 279 * or when all that were found were valid. 280 */ 281 static int 282 bufchk(char *buf, int64_t len, fsck_ino_t inum) 283 { 284 ufs_fsd_t *fsdp; 285 ufs_acl_t *ufsaclp = NULL; 286 int numacls; 287 int curacl; 288 struct type_counts_s { 289 int nuser_objs; 290 int ngroup_objs; 291 int nother_objs; 292 int nclass_objs; 293 int ndef_user_objs; 294 int ndef_group_objs; 295 int ndef_other_objs; 296 int ndef_class_objs; 297 int nusers; 298 int ngroups; 299 int ndef_users; 300 int ndef_groups; 301 } type_counts[3]; /* indexed by FSD_ACL and FSD_DFACL */ 302 struct type_counts_s *tcp, *tcp_all, *tcp_def, *tcp_norm; 303 int numdefs; 304 caddr_t bad; 305 caddr_t end = buf + len; 306 int64_t recsz = 0; 307 int64_t min_recsz = FSD_RECSZ(fsdp, sizeof (*fsdp)); 308 struct shadowclientinfo *sci; 309 struct shadowclients *scc; 310 fsck_ino_t target; 311 int numtargets = 0; 312 313 /* 314 * check we have a non-zero length for this shadow inode 315 */ 316 if (len == 0) { 317 pwarn("ACL I=%d HAS ZERO LENGTH\n", inum); 318 return (1); 319 } 320 321 (void) memset(type_counts, 0, sizeof (type_counts)); 322 323 /* LINTED pointer cast alignment (aligned buffer always passed in) */ 324 for (fsdp = (ufs_fsd_t *)buf; 325 (caddr_t)fsdp < end; 326 /* LINTED as per the above */ 327 fsdp = (ufs_fsd_t *)((caddr_t)fsdp + recsz)) { 328 329 recsz = FSD_RECSZ(fsdp, fsdp->fsd_size); 330 if ((recsz < min_recsz) || 331 (((caddr_t)fsdp + recsz) > (buf + len))) { 332 pwarn("Bad FSD entry size %lld in shadow inode %d", 333 recsz, inum); 334 if (reply("CLEAR SHADOW INODE") == 1) { 335 freeino(inum, TI_PARENT); 336 } else { 337 /* 338 * Bad size can cause the kernel to 339 * go traipsing off into never-never land. 340 */ 341 iscorrupt = 1; 342 } 343 return (0); 344 } 345 346 switch (fsdp->fsd_type) { 347 case FSD_FREE: /* ignore empty slots */ 348 break; 349 case FSD_ACL: 350 case FSD_DFACL: 351 /* 352 * Subtract out the two ints in the fsd_type, 353 * leaving us just the size of fsd_data[]. 354 */ 355 numacls = (fsdp->fsd_size - 2 * sizeof (int)) / 356 sizeof (ufs_acl_t); 357 tcp = &type_counts[fsdp->fsd_type]; 358 curacl = 0; 359 /* LINTED pointer cast alignment */ 360 for (ufsaclp = (ufs_acl_t *)fsdp->fsd_data; 361 numacls; ufsaclp++, curacl++) { 362 switch (ufsaclp->acl_tag) { 363 case USER_OBJ: /* Owner */ 364 tcp->nuser_objs++; 365 break; 366 case GROUP_OBJ: /* Group */ 367 tcp->ngroup_objs++; 368 break; 369 case OTHER_OBJ: /* Other */ 370 tcp->nother_objs++; 371 break; 372 case CLASS_OBJ: /* Mask */ 373 tcp->nclass_objs++; 374 break; 375 case DEF_USER_OBJ: /* Default Owner */ 376 tcp->ndef_user_objs++; 377 break; 378 case DEF_GROUP_OBJ: /* Default Group */ 379 tcp->ndef_group_objs++; 380 break; 381 case DEF_OTHER_OBJ: /* Default Other */ 382 tcp->ndef_other_objs++; 383 break; 384 case DEF_CLASS_OBJ: /* Default Mask */ 385 tcp->ndef_class_objs++; 386 break; 387 case USER: /* Users */ 388 tcp->nusers++; 389 break; 390 case GROUP: /* Groups */ 391 tcp->ngroups++; 392 break; 393 case DEF_USER: /* Default Users */ 394 tcp->ndef_users++; 395 break; 396 case DEF_GROUP: /* Default Groups */ 397 tcp->ndef_groups++; 398 break; 399 default: 400 return (1); 401 } 402 403 if ((ufsaclp->acl_perm & ~07) != 0) { 404 /* 405 * Caller will report inode, etc 406 */ 407 pwarn("Bad permission 0%o in ACL\n", 408 ufsaclp->acl_perm); 409 return (1); 410 } 411 412 numacls--; 413 } 414 break; 415 default: 416 if (fsdp->fsd_type >= FSD_RESERVED3 && 417 fsdp->fsd_type <= FSD_RESERVED7) 418 bad = "Unexpected"; 419 else 420 bad = "Unknown"; 421 pwarn("%s FSD type %d in shadow inode %d", 422 bad, fsdp->fsd_type, inum); 423 /* 424 * This is relatively harmless, since the 425 * kernel will ignore any entries it doesn't 426 * recognize. Don't bother with iscorrupt. 427 */ 428 if (preen) { 429 (void) printf(" (IGNORED)\n"); 430 } else if (reply("IGNORE") == 0) { 431 if (reply("CLEAR SHADOW INODE") == 1) { 432 freeino(inum, TI_PARENT); 433 } 434 return (0); 435 } 436 break; 437 } 438 } 439 if ((caddr_t)fsdp != (buf + len)) { 440 return (1); 441 } 442 443 /* If we didn't find any acls, ignore the unknown attribute */ 444 if (ufsaclp == NULL) 445 return (0); 446 447 /* 448 * Should only have default ACLs in FSD_DFACL records. 449 * However, the kernel can handle it, so just report that 450 * something odd might be going on. 451 */ 452 tcp = &type_counts[FSD_DFACL]; 453 if (verbose && 454 (tcp->nuser_objs != 0 || 455 tcp->ngroup_objs != 0 || 456 tcp->nother_objs != 0 || 457 tcp->nclass_objs != 0 || 458 tcp->nusers != 0 || 459 tcp->ngroups != 0)) { 460 (void) printf("NOTE: ACL I=%d has miscategorized ACLs. ", 461 inum); 462 (void) printf("This is harmless, but not normal.\n"); 463 } 464 465 /* 466 * Similarly for default ACLs in FSD_ACL records. 467 */ 468 tcp = &type_counts[FSD_ACL]; 469 if (verbose && 470 (tcp->ndef_user_objs != 0 || 471 tcp->ndef_group_objs != 0 || 472 tcp->ndef_other_objs != 0 || 473 tcp->ndef_class_objs != 0 || 474 tcp->ndef_users != 0 || 475 tcp->ndef_groups != 0)) { 476 (void) printf("NOTE: ACL I=%d has miscategorized ACLs.", 477 inum); 478 (void) printf(" This is harmless, but not normal.\n"); 479 } 480 481 /* 482 * Get consolidated totals, now that we're done with checking 483 * the segregation above. Assumes that neither FSD_ACL nor 484 * FSD_DFACL are zero. 485 */ 486 tcp_all = &type_counts[0]; 487 tcp_norm = &type_counts[FSD_ACL]; 488 tcp_def = &type_counts[FSD_DFACL]; 489 490 tcp_all->nuser_objs = tcp_def->nuser_objs + tcp_norm->nuser_objs; 491 tcp_all->ngroup_objs = tcp_def->ngroup_objs + tcp_norm->ngroup_objs; 492 tcp_all->nother_objs = tcp_def->nother_objs + tcp_norm->nother_objs; 493 tcp_all->nclass_objs = tcp_def->nclass_objs + tcp_norm->nclass_objs; 494 tcp_all->ndef_user_objs = 495 tcp_def->ndef_user_objs + tcp_norm->ndef_user_objs; 496 tcp_all->ndef_group_objs = 497 tcp_def->ndef_group_objs + tcp_norm->ndef_group_objs; 498 tcp_all->ndef_other_objs = 499 tcp_def->ndef_other_objs + tcp_norm->ndef_other_objs; 500 tcp_all->ndef_class_objs = 501 tcp_def->ndef_class_objs + tcp_norm->ndef_class_objs; 502 tcp_all->nusers = tcp_def->nusers + tcp_norm->nusers; 503 tcp_all->ngroups = tcp_def->ngroups + tcp_norm->ngroups; 504 tcp_all->ndef_users = tcp_def->ndef_users + tcp_norm->ndef_users; 505 tcp_all->ndef_groups = tcp_def->ndef_groups + tcp_norm->ndef_groups; 506 507 /* 508 * Check relationships among acls 509 */ 510 if (tcp_all->nuser_objs != 1 || 511 tcp_all->ngroup_objs != 1 || 512 tcp_all->nother_objs != 1 || 513 tcp_all->nclass_objs > 1) { 514 return (1); 515 } 516 517 if (tcp_all->ngroups && !tcp_all->nclass_objs) { 518 return (1); 519 } 520 521 if (tcp_all->ndef_user_objs > 1 || 522 tcp_all->ndef_group_objs > 1 || 523 tcp_all->ndef_other_objs > 1 || 524 tcp_all->ndef_class_objs > 1) { 525 return (1); 526 } 527 528 /* 529 * Check relationships among default acls 530 */ 531 numdefs = tcp_all->ndef_other_objs + tcp_all->ndef_user_objs + 532 tcp_all->ndef_group_objs; 533 534 if (numdefs != 0 && numdefs != 3) { 535 return (1); 536 } 537 538 /* 539 * If there are default acls, then the shadow inode's clients 540 * must be a directory or an xattr directory. 541 */ 542 if (numdefs != 0) { 543 /* This is an ACL so find it's clients */ 544 for (sci = shadowclientinfo; sci != NULL; sci = sci->next) 545 if (sci->shadow == inum) 546 break; 547 if ((sci == NULL) || (sci->clients == NULL)) 548 return (1); 549 550 /* Got shadow info, now look at clients */ 551 for (scc = sci->clients; scc != NULL; scc = scc->next) { 552 for (numtargets = 0; numtargets < scc->nclients; 553 numtargets++) { 554 target = scc->client[numtargets]; 555 if (!INO_IS_DVALID(target)) 556 return (1); 557 } 558 } 559 } 560 561 if (tcp_all->ndef_groups && !tcp_all->ndef_class_objs) { 562 return (1); 563 } 564 565 if ((tcp_all->ndef_users || tcp_all->ndef_groups) && 566 ((numdefs != 3) && !tcp_all->ndef_class_objs)) { 567 return (1); 568 } 569 570 return (0); 571 } 572