2 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
6 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
7 /* All Rights Reserved */
10 * Copyright (c) 1980, 1986, 1990 The Regents of the University of California.
11 * All rights reserved.
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.
28 #pragma ident "%Z%%M% %I% %E% SMI"
32 #include <sys/param.h>
33 #include <sys/types.h>
34 #include <sys/mntent.h>
36 #include <sys/fs/ufs_acl.h>
37 #include <sys/fs/ufs_fs.h>
38 #include <sys/vnode.h>
40 #include <sys/fs/ufs_inode.h>
44 * We can be run on multiple filesystems (processed serially), so
45 * these need to be re-initialized each time we start the pass.
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 */
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);
62 struct inodesc curino
;
63 struct shadowclientinfo
*sci
;
64 struct shadowclients
*scc
;
65 int64_t acl_size_limit
;
69 * Sort the acl list into disk block order.
71 qsort((char *)aclpsort
, (int)aclplast
, sizeof (*aclpsort
), aclblksort
);
73 * Scan all the acl inodes, finding the largest acl file.
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.
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)).
85 acl_size_limit
= sizeof (ufs_acl_t
) * (4 * MAX_ACL_ENTRIES
+ 8);
89 for (inumber
= 0; inumber
< aclplast
; inumber
++) {
90 aclp
= aclpsort
[inumber
];
91 if ((int64_t)aclp
->i_isize
> acl_size_limit
) {
93 "ACL I=%d is excessively large (%lld > %lld)",
95 (longlong_t
)aclp
->i_isize
,
96 (longlong_t
)acl_size_limit
);
98 (void) printf(" (IGNORING)\n");
99 } else if (reply("CLEAR") == 1) {
100 freeino(inumber
, TI_PARENT
);
103 (void) printf("IGNORING SHADOW I=%d\n",
108 if ((int64_t)aclp
->i_isize
> maxaclsize
)
109 maxaclsize
= (int64_t)aclp
->i_isize
;
112 maxaclsize
= ((maxaclsize
/ sblock
.fs_bsize
) + 1) * sblock
.fs_bsize
;
116 if (aclbuf
!= NULL
) {
117 free((void *)aclbuf
);
119 if ((aclbuf
= malloc(maxaclsize
)) == NULL
) {
120 errexit("cannot alloc %lld bytes for aclbuf\n",
121 (longlong_t
)maxaclsize
);
124 * Scan all the acl inodes, checking contents
126 for (inumber
= 0; inumber
< aclplast
; inumber
++) {
127 aclp
= aclpsort
[inumber
];
128 if ((int64_t)aclp
->i_isize
> acl_size_limit
) {
131 if ((statemap
[aclp
->i_number
] & STMASK
) != SSTATE
) {
134 dp
= ginode(aclp
->i_number
);
135 init_inodesc(&curino
);
137 curino
.id_type
= ACL
;
138 curino
.id_func
= pass3bcheck
;
139 curino
.id_number
= aclp
->i_number
;
140 curino
.id_filesize
= aclp
->i_isize
;
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
;
150 (void) printf("ACL I=%d BAD/CORRUPT", aclp
->i_number
);
151 if (preen
|| reply("CLEAR") == 1) {
154 freeino(aclp
->i_number
, TI_PARENT
);
161 * Now scan all shadow inodes, checking that any inodes that previously
162 * had an acl still have an acl.
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
);
174 free((void *)aclbuf
);
179 clear_shadow_client(struct shadowclientinfo
*sci
, struct shadowclients
*scc
,
182 int suppress_update
= 0;
184 struct inodesc ldesc
;
187 (void) printf("I=%d HAS BAD/CLEARED ACL I=%d",
188 scc
->client
[client
], sci
->shadow
);
189 if (preen
|| reply("FIX") == 1) {
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
201 dp
= ginode(scc
->client
[client
]);
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
212 LINK_RANGE(flow
, lncntp
[dp
->di_shadow
], 1);
214 LINK_CLEAR(flow
, scc
->client
[client
], dp
->di_mode
,
216 if (statemap
[scc
->client
[client
]] == USTATE
)
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.
226 if (!suppress_update
)
227 TRACK_LNCNTP(sci
->shadow
, lncntp
[sci
->shadow
]++);
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.
238 pass3bcheck(struct inodesc
*idesc
)
243 if (aclbufoff
== idesc
->id_filesize
) {
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) {
258 (void) memmove((void *)(aclbuf
+ aclbufoff
), (void *)bp
->b_un
.b_buf
,
266 * Routine to sort disk blocks.
269 aclblksort(const void *pp1
, const void *pp2
)
271 const struct inoinfo
**aclpp1
= (const struct inoinfo
**)pp1
;
272 const struct inoinfo
**aclpp2
= (const struct inoinfo
**)pp2
;
274 return ((*aclpp1
)->i_blks
[0] - (*aclpp2
)->i_blks
[0]);
278 * Scan a chunk of a shadow file. Return zero if no ACLs were found,
279 * or when all that were found were valid.
282 bufchk(char *buf
, int64_t len
, fsck_ino_t inum
)
285 ufs_acl_t
*ufsaclp
= NULL
;
288 struct type_counts_s
{
301 } type_counts
[3]; /* indexed by FSD_ACL and FSD_DFACL */
302 struct type_counts_s
*tcp
, *tcp_all
, *tcp_def
, *tcp_norm
;
305 caddr_t end
= buf
+ len
;
307 int64_t min_recsz
= FSD_RECSZ(fsdp
, sizeof (*fsdp
));
308 struct shadowclientinfo
*sci
;
309 struct shadowclients
*scc
;
314 * check we have a non-zero length for this shadow inode
317 pwarn("ACL I=%d HAS ZERO LENGTH\n", inum
);
321 (void) memset(type_counts
, 0, sizeof (type_counts
));
323 /* LINTED pointer cast alignment (aligned buffer always passed in) */
324 for (fsdp
= (ufs_fsd_t
*)buf
;
326 /* LINTED as per the above */
327 fsdp
= (ufs_fsd_t
*)((caddr_t
)fsdp
+ recsz
)) {
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",
334 if (reply("CLEAR SHADOW INODE") == 1) {
335 freeino(inum
, TI_PARENT
);
338 * Bad size can cause the kernel to
339 * go traipsing off into never-never land.
346 switch (fsdp
->fsd_type
) {
347 case FSD_FREE
: /* ignore empty slots */
352 * Subtract out the two ints in the fsd_type,
353 * leaving us just the size of fsd_data[].
355 numacls
= (fsdp
->fsd_size
- 2 * sizeof (int)) /
357 tcp
= &type_counts
[fsdp
->fsd_type
];
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 */
366 case GROUP_OBJ
: /* Group */
369 case OTHER_OBJ
: /* Other */
372 case CLASS_OBJ
: /* Mask */
375 case DEF_USER_OBJ
: /* Default Owner */
376 tcp
->ndef_user_objs
++;
378 case DEF_GROUP_OBJ
: /* Default Group */
379 tcp
->ndef_group_objs
++;
381 case DEF_OTHER_OBJ
: /* Default Other */
382 tcp
->ndef_other_objs
++;
384 case DEF_CLASS_OBJ
: /* Default Mask */
385 tcp
->ndef_class_objs
++;
387 case USER
: /* Users */
390 case GROUP
: /* Groups */
393 case DEF_USER
: /* Default Users */
396 case DEF_GROUP
: /* Default Groups */
403 if ((ufsaclp
->acl_perm
& ~07) != 0) {
405 * Caller will report inode, etc
407 pwarn("Bad permission 0%o in ACL\n",
416 if (fsdp
->fsd_type
>= FSD_RESERVED3
&&
417 fsdp
->fsd_type
<= FSD_RESERVED7
)
421 pwarn("%s FSD type %d in shadow inode %d",
422 bad
, fsdp
->fsd_type
, inum
);
424 * This is relatively harmless, since the
425 * kernel will ignore any entries it doesn't
426 * recognize. Don't bother with iscorrupt.
429 (void) printf(" (IGNORED)\n");
430 } else if (reply("IGNORE") == 0) {
431 if (reply("CLEAR SHADOW INODE") == 1) {
432 freeino(inum
, TI_PARENT
);
439 if ((caddr_t
)fsdp
!= (buf
+ len
)) {
443 /* If we didn't find any acls, ignore the unknown attribute */
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.
452 tcp
= &type_counts
[FSD_DFACL
];
454 (tcp
->nuser_objs
!= 0 ||
455 tcp
->ngroup_objs
!= 0 ||
456 tcp
->nother_objs
!= 0 ||
457 tcp
->nclass_objs
!= 0 ||
459 tcp
->ngroups
!= 0)) {
460 (void) printf("NOTE: ACL I=%d has miscategorized ACLs. ",
462 (void) printf("This is harmless, but not normal.\n");
466 * Similarly for default ACLs in FSD_ACL records.
468 tcp
= &type_counts
[FSD_ACL
];
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.",
478 (void) printf(" This is harmless, but not normal.\n");
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.
486 tcp_all
= &type_counts
[0];
487 tcp_norm
= &type_counts
[FSD_ACL
];
488 tcp_def
= &type_counts
[FSD_DFACL
];
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
;
508 * Check relationships among acls
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) {
517 if (tcp_all
->ngroups
&& !tcp_all
->nclass_objs
) {
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) {
529 * Check relationships among default acls
531 numdefs
= tcp_all
->ndef_other_objs
+ tcp_all
->ndef_user_objs
+
532 tcp_all
->ndef_group_objs
;
534 if (numdefs
!= 0 && numdefs
!= 3) {
539 * If there are default acls, then the shadow inode's clients
540 * must be a directory or an xattr directory.
543 /* This is an ACL so find it's clients */
544 for (sci
= shadowclientinfo
; sci
!= NULL
; sci
= sci
->next
)
545 if (sci
->shadow
== inum
)
547 if ((sci
== NULL
) || (sci
->clients
== NULL
))
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
;
554 target
= scc
->client
[numtargets
];
555 if (!INO_IS_DVALID(target
))
561 if (tcp_all
->ndef_groups
&& !tcp_all
->ndef_class_objs
) {
565 if ((tcp_all
->ndef_users
|| tcp_all
->ndef_groups
) &&
566 ((numdefs
!= 3) && !tcp_all
->ndef_class_objs
)) {