xref: /illumos-gate/usr/src/cmd/fs.d/ufs/fsck/pass3b.c (revision 0dee7919e2f2a6479d16b370af93747b9416b242)
1 /*
2  * Copyright 2005 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 
309 	(void) memset(type_counts, 0, sizeof (type_counts));
310 
311 	/* LINTED pointer cast alignment (aligned buffer always passed in) */
312 	for (fsdp = (ufs_fsd_t *)buf;
313 	    ((caddr_t)fsdp + recsz) <= end;
314 	    /* LINTED as per the above */
315 	    fsdp = (ufs_fsd_t *)((caddr_t)fsdp + recsz)) {
316 
317 		recsz = FSD_RECSZ(fsdp, fsdp->fsd_size);
318 		if ((recsz < min_recsz) ||
319 		    (((caddr_t)fsdp + recsz) > (buf + len))) {
320 			pwarn("Bad FSD entry size %lld in shadow inode %d",
321 			    recsz, inum);
322 			if (reply("CLEAR SHADOW INODE") == 1) {
323 				freeino(inum, TI_PARENT);
324 			} else {
325 				/*
326 				 * Bad size can cause the kernel to
327 				 * go traipsing off into never-never land.
328 				 */
329 				iscorrupt = 1;
330 			}
331 			return (0);
332 		}
333 
334 		switch (fsdp->fsd_type) {
335 		case FSD_FREE:	/* ignore empty slots */
336 			break;
337 		case FSD_ACL:
338 		case FSD_DFACL:
339 			/*
340 			 * Subtract out the two ints in the fsd_type,
341 			 * leaving us just the size of fsd_data[].
342 			 */
343 			numacls = (fsdp->fsd_size - 2 * sizeof (int)) /
344 							sizeof (ufs_acl_t);
345 			tcp = &type_counts[fsdp->fsd_type];
346 			curacl = 0;
347 			/* LINTED pointer cast alignment */
348 			for (ufsaclp = (ufs_acl_t *)fsdp->fsd_data;
349 						numacls; ufsaclp++, curacl++) {
350 				switch (ufsaclp->acl_tag) {
351 				case USER_OBJ:		/* Owner */
352 					tcp->nuser_objs++;
353 					break;
354 				case GROUP_OBJ:		/* Group */
355 					tcp->ngroup_objs++;
356 					break;
357 				case OTHER_OBJ:		/* Other */
358 					tcp->nother_objs++;
359 					break;
360 				case CLASS_OBJ:		/* Mask */
361 					tcp->nclass_objs++;
362 					break;
363 				case DEF_USER_OBJ:	/* Default Owner */
364 					tcp->ndef_user_objs++;
365 					break;
366 				case DEF_GROUP_OBJ:	/* Default Group */
367 					tcp->ndef_group_objs++;
368 					break;
369 				case DEF_OTHER_OBJ:	/* Default Other */
370 					tcp->ndef_other_objs++;
371 					break;
372 				case DEF_CLASS_OBJ:	/* Default Mask */
373 					tcp->ndef_class_objs++;
374 					break;
375 				case USER:		/* Users */
376 					tcp->nusers++;
377 					break;
378 				case GROUP:		/* Groups */
379 					tcp->ngroups++;
380 					break;
381 				case DEF_USER:		/* Default Users */
382 					tcp->ndef_users++;
383 					break;
384 				case DEF_GROUP:		/* Default Groups */
385 					tcp->ndef_groups++;
386 					break;
387 				default:
388 					return (1);
389 				}
390 
391 				if ((ufsaclp->acl_perm & ~07) != 0) {
392 					/*
393 					 * Caller will report inode, etc
394 					 */
395 					pwarn("Bad permission 0%o in ACL\n",
396 					    ufsaclp->acl_perm);
397 					return (1);
398 				}
399 
400 				numacls--;
401 			}
402 			break;
403 		default:
404 			if (fsdp->fsd_type >= FSD_RESERVED3 &&
405 			    fsdp->fsd_type <= FSD_RESERVED7)
406 				bad = "Unexpected";
407 			else
408 				bad = "Unknown";
409 			pwarn("%s FSD type %d in shadow inode %d",
410 			    bad, fsdp->fsd_type, inum);
411 			/*
412 			 * This is relatively harmless, since the
413 			 * kernel will ignore any entries it doesn't
414 			 * recognize.  Don't bother with iscorrupt.
415 			 */
416 			if (preen) {
417 				(void) printf(" (IGNORED)\n");
418 			} else if (reply("IGNORE") == 0) {
419 				if (reply("CLEAR SHADOW INODE") == 1) {
420 					freeino(inum, TI_PARENT);
421 				}
422 				return (0);
423 			}
424 			break;
425 		}
426 	}
427 	if ((caddr_t)fsdp != (buf + len)) {
428 		return (1);
429 	}
430 
431 	/* If we didn't find any acls, ignore the unknown attribute */
432 	if (ufsaclp == NULL)
433 		return (0);
434 
435 	/*
436 	 * Should only have default ACLs in FSD_DFACL records.
437 	 * However, the kernel can handle it, so just report that
438 	 * something odd might be going on.
439 	 */
440 	tcp = &type_counts[FSD_DFACL];
441 	if (verbose &&
442 	    (tcp->nuser_objs != 0 ||
443 	    tcp->ngroup_objs != 0 ||
444 	    tcp->nother_objs != 0 ||
445 	    tcp->nclass_objs != 0 ||
446 	    tcp->nusers != 0 ||
447 	    tcp->ngroups != 0)) {
448 		(void) printf("NOTE: ACL I=%d has miscategorized ACLs.  ",
449 		    inum);
450 		(void) printf("This is harmless, but not normal.\n");
451 	}
452 
453 	/*
454 	 * Similarly for default ACLs in FSD_ACL records.
455 	 */
456 	tcp = &type_counts[FSD_ACL];
457 	if (verbose &&
458 	    (tcp->ndef_user_objs != 0 ||
459 	    tcp->ndef_group_objs != 0 ||
460 	    tcp->ndef_other_objs != 0 ||
461 	    tcp->ndef_class_objs != 0 ||
462 	    tcp->ndef_users != 0 ||
463 	    tcp->ndef_groups != 0)) {
464 		(void) printf("NOTE: ACL I=%d has miscategorized ACLs.",
465 		    inum);
466 		(void) printf("  This is harmless, but not normal.\n");
467 	}
468 
469 	/*
470 	 * Get consolidated totals, now that we're done with checking
471 	 * the segregation above.  Assumes that neither FSD_ACL nor
472 	 * FSD_DFACL are zero.
473 	 */
474 	tcp_all = &type_counts[0];
475 	tcp_norm = &type_counts[FSD_ACL];
476 	tcp_def = &type_counts[FSD_DFACL];
477 
478 	tcp_all->nuser_objs = tcp_def->nuser_objs + tcp_norm->nuser_objs;
479 	tcp_all->ngroup_objs = tcp_def->ngroup_objs + tcp_norm->ngroup_objs;
480 	tcp_all->nother_objs = tcp_def->nother_objs + tcp_norm->nother_objs;
481 	tcp_all->nclass_objs = tcp_def->nclass_objs + tcp_norm->nclass_objs;
482 	tcp_all->ndef_user_objs =
483 		tcp_def->ndef_user_objs + tcp_norm->ndef_user_objs;
484 	tcp_all->ndef_group_objs =
485 		tcp_def->ndef_group_objs + tcp_norm->ndef_group_objs;
486 	tcp_all->ndef_other_objs =
487 		tcp_def->ndef_other_objs + tcp_norm->ndef_other_objs;
488 	tcp_all->ndef_class_objs =
489 		tcp_def->ndef_class_objs + tcp_norm->ndef_class_objs;
490 	tcp_all->nusers = tcp_def->nusers + tcp_norm->nusers;
491 	tcp_all->ngroups = tcp_def->ngroups + tcp_norm->ngroups;
492 	tcp_all->ndef_users = tcp_def->ndef_users + tcp_norm->ndef_users;
493 	tcp_all->ndef_groups = tcp_def->ndef_groups + tcp_norm->ndef_groups;
494 
495 	/*
496 	 * Check relationships among acls
497 	 */
498 	if (tcp_all->nuser_objs != 1 ||
499 	    tcp_all->ngroup_objs != 1 ||
500 	    tcp_all->nother_objs != 1 ||
501 	    tcp_all->nclass_objs > 1) {
502 		return (1);
503 	}
504 
505 	if (tcp_all->ngroups && !tcp_all->nclass_objs) {
506 		return (1);
507 	}
508 
509 	if (tcp_all->ndef_user_objs > 1 ||
510 	    tcp_all->ndef_group_objs > 1 ||
511 	    tcp_all->ndef_other_objs > 1 ||
512 	    tcp_all->ndef_class_objs > 1) {
513 		return (1);
514 	}
515 
516 	/*
517 	 * Check relationships among default acls
518 	 */
519 	numdefs = tcp_all->ndef_other_objs + tcp_all->ndef_user_objs +
520 		tcp_all->ndef_group_objs;
521 
522 	if (numdefs != 0 && numdefs != 3) {
523 		return (1);
524 	}
525 
526 	/*
527 	 * If there are default acls, we better be looking at something
528 	 * that's a directory or an xattr directory.
529 	 */
530 	if (numdefs != 0 && !INO_IS_DVALID(inum)) {
531 		return (1);
532 	}
533 
534 	if (tcp_all->ndef_groups && !tcp_all->ndef_class_objs) {
535 		return (1);
536 	}
537 
538 	if ((tcp_all->ndef_users || tcp_all->ndef_groups) &&
539 	    ((numdefs != 3) && !tcp_all->ndef_class_objs)) {
540 		return (1);
541 	}
542 
543 	return (0);
544 }
545