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