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
pass3b(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
clear_shadow_client(struct shadowclientinfo * sci,struct shadowclients * scc,int client)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
pass3bcheck(struct inodesc * idesc)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
aclblksort(const void * pp1,const void * pp2)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
bufchk(char * buf,int64_t len,fsck_ino_t inum)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