1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2000-2002,2004-2005 Silicon Graphics, Inc.
9 #include "err_protos.h"
10 #include "attr_repair.h"
17 static int xfs_acl_valid(struct xfs_mount
*mp
, struct xfs_acl
*daclp
);
18 static int xfs_mac_valid(xfs_mac_label_t
*lp
);
21 * da node check/verify functions that the attribute tree relies on are first in
22 * the file before the actual attribute code. This used to be shared with the
23 * dir v1 code, but that format is no longer supported yb the userspace
24 * utilities and hence is now specific to the attribute tree implementation.
27 typedef unsigned char da_freemap_t
;
30 * Allocate a freespace map for directory or attr leaf blocks (1 bit per byte)
31 * 1 == used, 0 == free.
34 alloc_da_freemap(struct xfs_mount
*mp
)
36 return calloc(1, mp
->m_sb
.sb_blocksize
/ NBBY
);
40 * Set the he range [start, stop) in the directory freemap.
42 * Returns 1 if there is a conflict or 0 if everything's good.
44 * Within a char, the lowest bit of the char represents the byte with
45 * the smallest address
48 set_da_freemap(xfs_mount_t
*mp
, da_freemap_t
*map
, int start
, int stop
)
50 const da_freemap_t mask
= 0x1;
55 * allow == relation since [x, x) claims 1 byte
57 do_warn(_("bad range claimed [%d, %d) in da block\n"),
62 if (stop
> mp
->m_sb
.sb_blocksize
) {
64 _("byte range end [%d %d) in da block larger than blocksize %d\n"),
65 start
, stop
, mp
->m_sb
.sb_blocksize
);
69 for (i
= start
; i
< stop
; i
++) {
70 if (map
[i
/ NBBY
] & (mask
<< i
% NBBY
)) {
71 do_warn(_("multiply claimed byte %d in da block\n"), i
);
74 map
[i
/ NBBY
] |= (mask
<< i
% NBBY
);
81 * For attribute repair, there are 3 formats to worry about. First, is
82 * shortform attributes which reside in the inode. Second is the leaf
83 * form, and lastly the btree. Much of this models after the directory
84 * structure so code resembles the directory repair cases.
85 * For shortform case, if an attribute looks corrupt, it is removed.
86 * If that leaves the shortform down to 0 attributes, it's okay and
87 * will appear to just have a null attribute fork. Some checks are done
88 * for validity of the value field based on what the security needs are.
89 * Calls will be made to xfs_mac_valid or xfs_acl_valid routines if the
90 * security attributes exist. They will be cleared if invalid.
91 * No other values will be checked. The DMF folks do not have current
92 * requirements, but may in the future.
94 * For leaf block attributes, it requires more processing. One sticky
95 * point is that the attributes can be local (within the leaf) or
96 * remote (outside the leaf in other blocks). Thinking of local only
97 * if you get a bad attribute, and want to delete just one, it's a-okay
98 * if it remains large enough to still be a leaf block attribute. Otherwise,
99 * it may have to be converted to shortform. How to convert this and when
100 * is an issue. This call is happening in Phase3. Phase5 will capture empty
101 * blocks, but Phase6 allows you to use the libxfs library which knows
102 * how to handle attributes in the kernel for converting formats. What we
103 * could do is mark an attribute to be cleared now, but in phase6 somehow
104 * have it cleared for real and then the format changed to shortform if
105 * applicable. Since this requires more work than I anticipate can be
106 * accomplished for the next release, we will instead just say any bad
107 * attribute in the leaf block will make the entire attribute fork be
108 * cleared. The simplest way to do that is to ignore the leaf format, and
109 * call clear_dinode_attr to just make a shortform attribute fork with
112 * Another issue with handling repair on leaf attributes is the remote
113 * blocks. To make sure that they look good and are not used multiple times
114 * by the attribute fork, some mechanism to keep track of all them is necessary.
115 * Do this in the future, time permitting. For now, note that there is no
116 * check for remote blocks and their allocations.
118 * For btree formatted attributes, the model can follow directories. That
119 * would mean go down the tree to the leftmost leaf. From there moving down
120 * the links and processing each. They would call back up the tree, to verify
121 * that the tree structure is okay. Any problems will result in the attribute
122 * fork being emptied and put in shortform format.
126 * This routine just checks what security needs are for attribute values
127 * only called when root flag is set, otherwise these names could exist in
128 * in user attribute land without a conflict.
129 * If value is non-zero, then a remote attribute is being passed in
133 struct xfs_mount
*mp
,
139 /* for proper alignment issues, get the structs and memmove the values */
140 xfs_mac_label_t macl
;
144 if ((namelen
== SGI_ACL_FILE_SIZE
&&
145 strncmp(namevalue
, SGI_ACL_FILE
, SGI_ACL_FILE_SIZE
) == 0) ||
146 (namelen
== SGI_ACL_DEFAULT_SIZE
&&
147 strncmp(namevalue
, SGI_ACL_DEFAULT
, SGI_ACL_DEFAULT_SIZE
) == 0)) {
149 valuep
= malloc(valuelen
);
151 do_error(_("No memory for ACL check!\n"));
152 memcpy(valuep
, namevalue
+ namelen
, valuelen
);
156 if (xfs_acl_valid(mp
, valuep
) != 0) {
159 _("entry contains illegal value in attribute named SGI_ACL_FILE "
160 "or SGI_ACL_DEFAULT\n"));
166 } else if (strncmp(namevalue
, SGI_MAC_FILE
, SGI_MAC_FILE_SIZE
) == 0) {
168 memset(&macl
, 0, sizeof(xfs_mac_label_t
));
169 memmove(&macl
, namevalue
+namelen
, valuelen
);
174 if (xfs_mac_valid((xfs_mac_label_t
*)valuep
) != 1) { /* 1 is valid */
176 * if sysconf says MAC enabled,
177 * temp = mac_from_text("msenhigh/mintlow", NULL)
178 * copy it to value, update valuelen, totsize
179 * This causes pushing up or down of all following
180 * attributes, forcing a attribute format change!!
185 _("entry contains illegal value in attribute named SGI_MAC_LABEL\n"));
187 } else if (strncmp(namevalue
, SGI_CAP_FILE
, SGI_CAP_FILE_SIZE
) == 0) {
188 if ( valuelen
!= sizeof(xfs_cap_set_t
)) {
191 _("entry contains illegal value in attribute named SGI_CAP_FILE\n"));
200 * this routine validates the attributes in shortform format.
201 * a non-zero return repair value means certain attributes are bogus
202 * and were cleared if possible. Warnings do not generate error conditions
203 * if you cannot modify the structures. repair is set to 1, if anything
207 process_shortform_attr(
208 struct xfs_mount
*mp
,
213 xfs_attr_shortform_t
*asf
;
214 xfs_attr_sf_entry_t
*currententry
, *nextentry
, *tempentry
;
216 int currentsize
, remainingspace
;
220 asf
= (xfs_attr_shortform_t
*) XFS_DFORK_APTR(dip
);
222 /* Assumption: hdr.totsize is less than a leaf block and was checked
223 * by lclinode for valid sizes. Check the count though.
225 if (asf
->hdr
.count
== 0)
226 /* then the total size should just be the header length */
227 if (be16_to_cpu(asf
->hdr
.totsize
) != sizeof(xfs_attr_sf_hdr_t
)) {
228 /* whoops there's a discrepancy. Clear the hdr */
231 _("there are no attributes in the fork for inode %" PRIu64
"\n"),
234 cpu_to_be16(sizeof(xfs_attr_sf_hdr_t
));
239 _("would junk the attribute fork since count is 0 for inode %" PRIu64
"\n"),
245 currentsize
= sizeof(xfs_attr_sf_hdr_t
);
246 remainingspace
= be16_to_cpu(asf
->hdr
.totsize
) - currentsize
;
247 nextentry
= &asf
->list
[0];
248 for (i
= 0; i
< asf
->hdr
.count
; i
++) {
249 currententry
= nextentry
;
252 /* don't go off the end if the hdr.count was off */
253 if ((currentsize
+ (sizeof(xfs_attr_sf_entry_t
) - 1)) >
254 be16_to_cpu(asf
->hdr
.totsize
))
255 break; /* get out and reset count and totSize */
257 /* if the namelen is 0, can't get to the rest of the entries */
258 if (currententry
->namelen
== 0) {
259 do_warn(_("zero length name entry in attribute fork,"));
262 _(" truncating attributes for inode %" PRIu64
" to %d\n"), ino
, i
);
264 break; /* and then update hdr fields */
267 _(" would truncate attributes for inode %" PRIu64
" to %d\n"), ino
, i
);
271 /* It's okay to have a 0 length valuelen, but do a
272 * rough check to make sure we haven't gone outside of
275 if (remainingspace
< currententry
->namelen
||
276 ((remainingspace
- currententry
->
277 namelen
) < currententry
->valuelen
)) {
279 _("name or value attribute lengths are too large,\n"));
282 _(" truncating attributes for inode %" PRIu64
" to %d\n"),
285 break; /* and then update hdr fields */
288 _(" would truncate attributes for inode %" PRIu64
" to %d\n"),
295 /* namecheck checks for / and null terminated for file names.
296 * attributes names currently follow the same rules.
298 if (namecheck((char *)¤tentry
->nameval
[0],
299 currententry
->namelen
)) {
301 _("entry contains illegal character in shortform attribute name\n"));
305 if (currententry
->flags
& XFS_ATTR_INCOMPLETE
) {
307 _("entry has INCOMPLETE flag on in shortform attribute\n"));
311 /* Only check values for root security attributes */
312 if (currententry
->flags
& XFS_ATTR_ROOT
)
313 junkit
|= valuecheck(mp
,
314 (char *)¤tentry
->nameval
[0],
315 NULL
, currententry
->namelen
,
316 currententry
->valuelen
);
318 remainingspace
= remainingspace
-
319 XFS_ATTR_SF_ENTSIZE(currententry
);
323 /* get rid of only this entry */
325 _("removing attribute entry %d for inode %" PRIu64
"\n"),
327 tempentry
= (xfs_attr_sf_entry_t
*)
328 ((intptr_t) currententry
+
329 XFS_ATTR_SF_ENTSIZE(currententry
));
330 memmove(currententry
,tempentry
,remainingspace
);
332 i
--; /* no worries, it will wrap back to 0 */
334 continue; /* go back up now */
337 _("would remove attribute entry %d for inode %" PRIu64
"\n"),
342 /* Let's get ready for the next entry... */
343 nextentry
= (xfs_attr_sf_entry_t
*)((intptr_t) nextentry
+
344 XFS_ATTR_SF_ENTSIZE(currententry
));
345 currentsize
= currentsize
+ XFS_ATTR_SF_ENTSIZE(currententry
);
349 if (asf
->hdr
.count
!= i
) {
352 _("would have corrected attribute entry count in inode %" PRIu64
" from %d to %d\n"),
353 ino
, asf
->hdr
.count
, i
);
356 _("corrected attribute entry count in inode %" PRIu64
", was %d, now %d\n"),
357 ino
, asf
->hdr
.count
, i
);
363 /* ASSUMPTION: currentsize <= totsize */
364 if (be16_to_cpu(asf
->hdr
.totsize
) != currentsize
) {
367 _("would have corrected attribute totsize in inode %" PRIu64
" from %d to %d\n"),
368 ino
, be16_to_cpu(asf
->hdr
.totsize
),
372 _("corrected attribute entry totsize in inode %" PRIu64
", was %d, now %d\n"),
373 ino
, be16_to_cpu(asf
->hdr
.totsize
),
375 asf
->hdr
.totsize
= cpu_to_be16(currentsize
);
383 /* This routine brings in blocks from disk one by one and assembles them
384 * in the value buffer. If get_bmapi gets smarter later to return an extent
385 * or list of extents, that would be great. For now, we don't expect too
386 * many blocks per remote value, so one by one is sufficient.
389 rmtval_get(xfs_mount_t
*mp
, xfs_ino_t ino
, blkmap_t
*blkmap
,
390 xfs_dablk_t blocknum
, int valuelen
, char* value
)
394 int clearit
= 0, i
= 0, length
= 0, amountdone
= 0;
397 if (xfs_sb_version_hascrc(&mp
->m_sb
))
398 hdrsize
= sizeof(struct xfs_attr3_rmt_hdr
);
400 /* ASSUMPTION: valuelen is a valid number, so use it for looping */
401 /* Note that valuelen is not a multiple of blocksize */
402 while (amountdone
< valuelen
) {
403 bno
= blkmap_get(blkmap
, blocknum
+ i
);
404 if (bno
== NULLFSBLOCK
) {
406 _("remote block for attributes of inode %" PRIu64
" is missing\n"), ino
);
410 bp
= libxfs_readbuf(mp
->m_dev
, XFS_FSB_TO_DADDR(mp
, bno
),
411 XFS_FSB_TO_BB(mp
, 1), 0,
412 &xfs_attr3_rmt_buf_ops
);
415 _("can't read remote block for attributes of inode %" PRIu64
"\n"), ino
);
420 if (bp
->b_error
== -EFSBADCRC
|| bp
->b_error
== -EFSCORRUPTED
) {
422 _("Corrupt remote block for attributes of inode %" PRIu64
"\n"), ino
);
428 ASSERT(mp
->m_sb
.sb_blocksize
== bp
->b_bcount
);
430 length
= min(bp
->b_bcount
- hdrsize
, valuelen
- amountdone
);
431 memmove(value
, bp
->b_addr
+ hdrsize
, length
);
432 amountdone
+= length
;
440 /* The block is read in. The magic number and forward / backward
441 * links are checked by the caller process_leaf_attr.
442 * If any problems occur the routine returns with non-zero. In
443 * this case the next step is to clear the attribute fork, by
444 * changing it to shortform and zeroing it out. Forkoff need not
449 process_leaf_attr_local(
450 struct xfs_mount
*mp
,
451 xfs_attr_leafblock_t
*leaf
,
453 xfs_attr_leaf_entry_t
*entry
,
454 xfs_dahash_t last_hashval
,
458 xfs_attr_leaf_name_local_t
*local
;
460 local
= xfs_attr3_leaf_name_local(leaf
, i
);
461 if (local
->namelen
== 0 || namecheck((char *)&local
->nameval
[0],
464 _("attribute entry %d in attr block %u, inode %" PRIu64
" has bad name (namelen = %d)\n"),
465 i
, da_bno
, ino
, local
->namelen
);
469 /* Check on the hash value. Checking order of values
470 * is not necessary, since one wrong clears the whole
471 * fork. If the ordering's wrong, it's caught here or
472 * the kernel code has a bug with transaction logging
473 * or attributes itself. Being paranoid, let's check
474 * ordering anyway in case both the name value and the
475 * hashvalue were wrong but matched. Unlikely, however.
477 if (be32_to_cpu(entry
->hashval
) != libxfs_da_hashname(
478 &local
->nameval
[0], local
->namelen
) ||
479 be32_to_cpu(entry
->hashval
) < last_hashval
) {
481 _("bad hashvalue for attribute entry %d in attr block %u, inode %" PRIu64
"\n"),
486 /* Only check values for root security attributes */
487 if (entry
->flags
& XFS_ATTR_ROOT
) {
488 if (valuecheck(mp
, (char *)&local
->nameval
[0], NULL
,
489 local
->namelen
, be16_to_cpu(local
->valuelen
))) {
491 _("bad security value for attribute entry %d in attr block %u, inode %" PRIu64
"\n"),
496 return xfs_attr_leaf_entsize_local(local
->namelen
,
497 be16_to_cpu(local
->valuelen
));
501 process_leaf_attr_remote(
502 xfs_attr_leafblock_t
*leaf
,
504 xfs_attr_leaf_entry_t
*entry
,
505 xfs_dahash_t last_hashval
,
511 xfs_attr_leaf_name_remote_t
*remotep
;
514 remotep
= xfs_attr3_leaf_name_remote(leaf
, i
);
516 if (remotep
->namelen
== 0 || namecheck((char *)&remotep
->name
[0],
518 be32_to_cpu(entry
->hashval
) !=
519 libxfs_da_hashname((unsigned char *)&remotep
->name
[0],
521 be32_to_cpu(entry
->hashval
) < last_hashval
||
522 be32_to_cpu(remotep
->valueblk
) == 0) {
524 _("inconsistent remote attribute entry %d in attr block %u, ino %" PRIu64
"\n"), i
, da_bno
, ino
);
528 value
= malloc(be32_to_cpu(remotep
->valuelen
));
531 _("cannot malloc enough for remotevalue attribute for inode %" PRIu64
"\n"),
533 do_warn(_("SKIPPING this remote attribute\n"));
536 if (rmtval_get(mp
, ino
, blkmap
, be32_to_cpu(remotep
->valueblk
),
537 be32_to_cpu(remotep
->valuelen
), value
)) {
539 _("remote attribute get failed for entry %d, inode %" PRIu64
"\n"),
543 if ((entry
->flags
& XFS_ATTR_ROOT
) &&
544 valuecheck(mp
, (char *)&remotep
->name
[0], value
, remotep
->namelen
,
545 be32_to_cpu(remotep
->valuelen
))) {
547 _("remote attribute value check failed for entry %d, inode %" PRIu64
"\n"),
553 return xfs_attr_leaf_entsize_remote(remotep
->namelen
);
561 process_leaf_attr_block(
563 xfs_attr_leafblock_t
*leaf
,
567 xfs_dahash_t last_hashval
,
568 xfs_dahash_t
*current_hashval
,
571 xfs_attr_leaf_entry_t
*entry
;
572 int i
, start
, stop
, clearit
, usedbs
, firstb
, thissize
;
573 da_freemap_t
*attr_freemap
;
574 struct xfs_attr3_icleaf_hdr leafhdr
;
576 xfs_attr3_leaf_hdr_from_disk(mp
->m_attr_geo
, &leafhdr
, leaf
);
577 clearit
= usedbs
= 0;
578 firstb
= mp
->m_sb
.sb_blocksize
;
579 stop
= xfs_attr3_leaf_hdr_size(leaf
);
581 /* does the count look sorta valid? */
582 if (!leafhdr
.count
||
583 leafhdr
.count
* sizeof(xfs_attr_leaf_entry_t
) + stop
>
584 mp
->m_sb
.sb_blocksize
) {
586 _("bad attribute count %d in attr block %u, inode %" PRIu64
"\n"),
587 leafhdr
.count
, da_bno
, ino
);
591 attr_freemap
= alloc_da_freemap(mp
);
592 (void) set_da_freemap(mp
, attr_freemap
, 0, stop
);
594 /* go thru each entry checking for problems */
595 for (i
= 0, entry
= xfs_attr3_leaf_entryp(leaf
);
596 i
< leafhdr
.count
; i
++, entry
++) {
598 /* check if index is within some boundary. */
599 if (be16_to_cpu(entry
->nameidx
) > mp
->m_sb
.sb_blocksize
) {
601 _("bad attribute nameidx %d in attr block %u, inode %" PRIu64
"\n"),
602 be16_to_cpu(entry
->nameidx
), da_bno
, ino
);
607 if (entry
->flags
& XFS_ATTR_INCOMPLETE
) {
608 /* we are inconsistent state. get rid of us */
610 _("attribute entry #%d in attr block %u, inode %" PRIu64
" is INCOMPLETE\n"),
616 /* mark the entry used */
617 start
= (intptr_t)entry
- (intptr_t)leaf
;
618 stop
= start
+ sizeof(xfs_attr_leaf_entry_t
);
619 if (set_da_freemap(mp
, attr_freemap
, start
, stop
)) {
621 _("attribute entry %d in attr block %u, inode %" PRIu64
" claims already used space\n"),
624 break; /* got an overlap */
627 if (entry
->flags
& XFS_ATTR_LOCAL
)
628 thissize
= process_leaf_attr_local(mp
, leaf
, i
, entry
,
629 last_hashval
, da_bno
, ino
);
631 thissize
= process_leaf_attr_remote(leaf
, i
, entry
,
632 last_hashval
, da_bno
, ino
,
639 *current_hashval
= last_hashval
= be32_to_cpu(entry
->hashval
);
641 if (set_da_freemap(mp
, attr_freemap
, be16_to_cpu(entry
->nameidx
),
642 be16_to_cpu(entry
->nameidx
) + thissize
)) {
644 _("attribute entry %d in attr block %u, inode %" PRIu64
" claims used space\n"),
647 break; /* got an overlap */
650 if (be16_to_cpu(entry
->nameidx
) < firstb
)
651 firstb
= be16_to_cpu(entry
->nameidx
);
656 /* verify the header information is correct */
658 /* if the holes flag is set, don't reset first_used unless it's
659 * pointing to used bytes. we're being conservative here
660 * since the block will get compacted anyhow by the kernel.
663 if ((leafhdr
.holes
== 0 &&
664 firstb
!= leafhdr
.firstused
) ||
665 leafhdr
.firstused
> firstb
) {
668 _("- resetting first used heap value from %d to %d in "
669 "block %u of attribute fork of inode %" PRIu64
"\n"),
671 firstb
, da_bno
, ino
);
672 leafhdr
.firstused
= firstb
;
676 _("- would reset first used value from %d to %d in "
677 "block %u of attribute fork of inode %" PRIu64
"\n"),
679 firstb
, da_bno
, ino
);
683 if (usedbs
!= leafhdr
.usedbytes
) {
686 _("- resetting usedbytes cnt from %d to %d in "
687 "block %u of attribute fork of inode %" PRIu64
"\n"),
689 usedbs
, da_bno
, ino
);
690 leafhdr
.usedbytes
= usedbs
;
694 _("- would reset usedbytes cnt from %d to %d in "
695 "block %u of attribute fork of %" PRIu64
"\n"),
697 usedbs
, da_bno
, ino
);
701 /* there's a lot of work in process_leaf_dir_block to go thru
702 * checking for holes and compacting if appropiate. I don't think
703 * attributes need all that, so let's just leave the holes. If
704 * we discover later that this is a good place to do compaction
705 * we can add it then.
709 * If we're just going to zap the block, don't pretend like we
710 * repaired it, because repairing the block stops the clear
716 xfs_attr3_leaf_hdr_to_disk(mp
->m_attr_geo
, leaf
, &leafhdr
);
719 return (clearit
); /* and repair */
724 * returns 0 if the attribute fork is ok, 1 if it has to be junked.
727 process_leaf_attr_level(xfs_mount_t
*mp
,
728 da_bt_cursor_t
*da_cursor
)
731 xfs_attr_leafblock_t
*leaf
;
734 xfs_fsblock_t dev_bno
;
736 xfs_dablk_t prev_bno
;
737 xfs_dahash_t current_hashval
= 0;
738 xfs_dahash_t greatest_hashval
;
739 struct xfs_attr3_icleaf_hdr leafhdr
;
741 da_bno
= da_cursor
->level
[0].bno
;
742 ino
= da_cursor
->ino
;
744 * 0 is the root block and no block
745 * pointer can point to the root block of the btree
749 _("btree cycle detected in attribute fork for inode %" PRIu64
"\n"),
758 dev_bno
= blkmap_get(da_cursor
->blkmap
, da_bno
);
759 if (dev_bno
== NULLFSBLOCK
) {
761 _("can't map block %u for attribute fork for inode %" PRIu64
"\n"),
766 bp
= libxfs_readbuf(mp
->m_dev
, XFS_FSB_TO_DADDR(mp
, dev_bno
),
767 XFS_FSB_TO_BB(mp
, 1), 0,
768 &xfs_attr3_leaf_buf_ops
);
771 _("can't read file block %u (fsbno %" PRIu64
") for attribute fork of inode %" PRIu64
"\n"),
772 da_bno
, dev_bno
, ino
);
777 xfs_attr3_leaf_hdr_from_disk(mp
->m_attr_geo
, &leafhdr
, leaf
);
779 /* check magic number for leaf directory btree block */
780 if (!(leafhdr
.magic
== XFS_ATTR_LEAF_MAGIC
||
781 leafhdr
.magic
== XFS_ATTR3_LEAF_MAGIC
)) {
783 _("bad attribute leaf magic %#x for inode %" PRIu64
"\n"),
790 * for each block, process the block, verify its path,
791 * then get next block. update cursor values along the way
793 if (process_leaf_attr_block(mp
, leaf
, da_bno
, ino
,
794 da_cursor
->blkmap
, current_hashval
,
795 &greatest_hashval
, &repair
)) {
801 * index can be set to hdr.count so match the
802 * indexes of the interior blocks -- which at the
803 * end of the block will point to 1 after the final
804 * real entry in the block
806 da_cursor
->level
[0].hashval
= greatest_hashval
;
807 da_cursor
->level
[0].bp
= bp
;
808 da_cursor
->level
[0].bno
= da_bno
;
809 da_cursor
->level
[0].index
= leafhdr
.count
;
810 da_cursor
->level
[0].dirty
= repair
;
812 if (leafhdr
.back
!= prev_bno
) {
814 _("bad sibling back pointer for block %u in attribute fork for inode %" PRIu64
"\n"),
821 da_bno
= leafhdr
.forw
;
824 if (verify_da_path(mp
, da_cursor
, 0, XFS_ATTR_FORK
)) {
830 current_hashval
= greatest_hashval
;
832 * If block looks ok but CRC didn't match, make sure to
835 if (!no_modify
&& bp
->b_error
== -EFSBADCRC
)
838 if (repair
&& !no_modify
)
839 libxfs_writebuf(bp
, 0);
842 } while (da_bno
!= 0);
844 if (verify_final_da_path(mp
, da_cursor
, 0, XFS_ATTR_FORK
)) {
846 * verify the final path up (right-hand-side) if still ok
849 _("bad hash path in attribute fork for inode %" PRIu64
"\n"),
854 /* releases all buffers holding interior btree blocks */
855 release_da_cursor(mp
, da_cursor
, 0);
859 /* release all buffers holding interior btree blocks */
860 err_release_da_cursor(mp
, da_cursor
, 0);
866 * a node directory is a true btree -- where the attribute fork
867 * has gotten big enough that it is represented as a non-trivial (e.g.
868 * has more than just a block) btree.
870 * Note that if we run into any problems, we will trash the attribute fork.
872 * returns 0 if things are ok, 1 if bad
873 * Note this code has been based off process_node_dir.
884 da_bt_cursor_t da_cursor
;
887 * try again -- traverse down left-side of tree until we hit
888 * the left-most leaf block setting up the btree cursor along
889 * the way. Then walk the leaf blocks left-to-right, calling
890 * a parent-verification routine each time we traverse a block.
892 memset(&da_cursor
, 0, sizeof(da_bt_cursor_t
));
893 da_cursor
.active
= 0;
896 da_cursor
.greatest_bno
= 0;
897 da_cursor
.blkmap
= blkmap
;
900 * now process interior node. don't have any buffers held in this path.
902 error
= traverse_int_dablock(mp
, &da_cursor
, &bno
, XFS_ATTR_FORK
);
904 return(1); /* 0 means unsuccessful */
907 * now pass cursor and bno into leaf-block processing routine
908 * the leaf dir level routine checks the interior paths
909 * up to the root including the final right-most path.
912 return (process_leaf_attr_level(mp
, &da_cursor
));
915 /* check v5 metadata */
918 struct xfs_mount
*mp
,
922 struct xfs_da3_blkinfo
*info
= bp
->b_addr
;
924 if (info
->hdr
.magic
!= cpu_to_be16(XFS_ATTR3_LEAF_MAGIC
) &&
925 info
->hdr
.magic
!= cpu_to_be16(XFS_DA3_NODE_MAGIC
))
929 if (be64_to_cpu(info
->owner
) != ino
) {
931 _("expected owner inode %" PRIu64
", got %llu, attr block %" PRIu64
"\n"),
932 ino
, (unsigned long long)be64_to_cpu(info
->owner
),
936 /* verify block number */
937 if (be64_to_cpu(info
->blkno
) != bp
->b_bn
) {
939 _("expected block %" PRIu64
", got %llu, inode %" PRIu64
"attr block\n"),
940 bp
->b_bn
, (unsigned long long)be64_to_cpu(info
->blkno
),
945 if (platform_uuid_compare(&info
->uuid
, &mp
->m_sb
.sb_meta_uuid
) != 0) {
947 _("wrong FS UUID, inode %" PRIu64
" attr block %" PRIu64
"\n"),
956 * Start processing for a leaf or fuller btree.
957 * A leaf directory is one where the attribute fork is too big for
958 * the inode but is small enough to fit into one btree block
959 * outside the inode. This code is modelled after process_leaf_dir_block.
961 * returns 0 if things are ok, 1 if bad (attributes needs to be junked)
962 * repair is set, if anything was changed, but attributes can live thru it
965 process_longform_attr(
970 int *repair
) /* out - 1 if something was fixed */
972 xfs_attr_leafblock_t
*leaf
;
975 xfs_dahash_t next_hashval
;
977 struct xfs_attr3_icleaf_hdr leafhdr
;
982 bno
= blkmap_get(blkmap
, 0);
984 if ( bno
== NULLFSBLOCK
) {
985 if (dip
->di_aformat
== XFS_DINODE_FMT_EXTENTS
&&
986 be16_to_cpu(dip
->di_anextents
) == 0)
987 return(0); /* the kernel can handle this state */
989 _("block 0 of inode %" PRIu64
" attribute fork is missing\n"),
993 /* FIX FOR bug 653709 -- EKN */
994 if (mp
->m_sb
.sb_agcount
< XFS_FSB_TO_AGNO(mp
, bno
)) {
996 _("agno of attribute fork of inode %" PRIu64
" out of regular partition\n"), ino
);
1000 bp
= libxfs_readbuf(mp
->m_dev
, XFS_FSB_TO_DADDR(mp
, bno
),
1001 XFS_FSB_TO_BB(mp
, 1), 0, &xfs_da3_node_buf_ops
);
1004 _("can't read block 0 of inode %" PRIu64
" attribute fork\n"),
1008 if (bp
->b_error
== -EFSBADCRC
)
1011 /* is this block sane? */
1012 if (__check_attr_header(mp
, bp
, ino
)) {
1018 /* verify leaf block */
1020 xfs_attr3_leaf_hdr_from_disk(mp
->m_attr_geo
, &leafhdr
, leaf
);
1022 /* check sibling pointers in leaf block or root block 0 before
1023 * we have to release the btree block
1025 if (leafhdr
.forw
!= 0 || leafhdr
.back
!= 0) {
1028 _("clearing forw/back pointers in block 0 for attributes in inode %" PRIu64
"\n"),
1033 xfs_attr3_leaf_hdr_to_disk(mp
->m_attr_geo
,
1037 _("would clear forw/back pointers in block 0 for attributes in inode %" PRIu64
"\n"), ino
);
1042 * use magic number to tell us what type of attribute this is.
1043 * it's possible to have a node or leaf attribute in either an
1044 * extent format or btree format attribute fork.
1046 switch (leafhdr
.magic
) {
1047 case XFS_ATTR_LEAF_MAGIC
: /* leaf-form attribute */
1048 case XFS_ATTR3_LEAF_MAGIC
:
1049 if (process_leaf_attr_block(mp
, leaf
, 0, ino
, blkmap
,
1050 0, &next_hashval
, repair
)) {
1052 /* the block is bad. lose the attribute fork. */
1056 *repair
= *repair
|| repairlinks
;
1059 case XFS_DA_NODE_MAGIC
: /* btree-form attribute */
1060 case XFS_DA3_NODE_MAGIC
:
1061 /* must do this now, to release block 0 before the traversal */
1062 if ((*repair
|| repairlinks
) && !no_modify
) {
1064 libxfs_writebuf(bp
, 0);
1067 error
= process_node_attr(mp
, ino
, dip
, blkmap
); /* + repair */
1073 _("bad attribute leaf magic # %#x for dir ino %" PRIu64
"\n"),
1074 be16_to_cpu(leaf
->hdr
.info
.magic
), ino
);
1080 if (*repair
&& !no_modify
)
1081 libxfs_writebuf(bp
, 0);
1085 return(0); /* repair may be set */
1091 struct xfs_mount
*mp
,
1092 struct xfs_icacl
**aclp
,
1093 struct xfs_acl
*dacl
)
1095 struct xfs_icacl
*acl
;
1096 struct xfs_icacl_entry
*ace
;
1097 struct xfs_acl_entry
*dace
;
1101 count
= be32_to_cpu(dacl
->acl_cnt
);
1102 if (count
> XFS_ACL_MAX_ENTRIES(mp
)) {
1103 do_warn(_("Too many ACL entries, count %d\n"), count
);
1109 acl
= malloc(sizeof(struct xfs_icacl
) +
1110 count
* sizeof(struct xfs_icacl_entry
));
1112 do_warn(_("cannot malloc enough for ACL attribute\n"));
1113 do_warn(_("SKIPPING this ACL\n"));
1118 acl
->acl_cnt
= count
;
1119 for (i
= 0; i
< count
; i
++) {
1120 ace
= &acl
->acl_entry
[i
];
1121 dace
= &dacl
->acl_entry
[i
];
1123 ace
->ae_tag
= be32_to_cpu(dace
->ae_tag
);
1124 ace
->ae_id
= be32_to_cpu(dace
->ae_id
);
1125 ace
->ae_perm
= be16_to_cpu(dace
->ae_perm
);
1133 * returns 1 if attributes got cleared
1134 * and 0 if things are ok.
1142 int *repair
) /* returned if we did repair */
1145 __u8 aformat
= dip
->di_aformat
;
1147 xfs_attr_shortform_t
*asf
;
1149 asf
= (xfs_attr_shortform_t
*) XFS_DFORK_APTR(dip
);
1152 if (aformat
== XFS_DINODE_FMT_LOCAL
) {
1153 ASSERT(be16_to_cpu(asf
->hdr
.totsize
) <=
1154 XFS_DFORK_ASIZE(dip
, mp
));
1155 err
= process_shortform_attr(mp
, ino
, dip
, repair
);
1156 } else if (aformat
== XFS_DINODE_FMT_EXTENTS
||
1157 aformat
== XFS_DINODE_FMT_BTREE
) {
1158 err
= process_longform_attr(mp
, ino
, dip
, blkmap
,
1160 /* if err, convert this to shortform and clear it */
1161 /* if repair and no error, it's taken care of */
1163 do_warn(_("illegal attribute format %d, ino %" PRIu64
"\n"),
1167 return (err
); /* and repair */
1175 struct xfs_mount
*mp
,
1176 struct xfs_acl
*daclp
)
1178 struct xfs_icacl
*aclp
= NULL
;
1179 struct xfs_icacl_entry
*entry
, *e
;
1180 int user
= 0, group
= 0, other
= 0, mask
= 0, mask_required
= 0;
1186 switch (xfs_acl_from_disk(mp
, &aclp
, daclp
)) {
1195 for (i
= 0; i
< aclp
->acl_cnt
; i
++) {
1196 entry
= &aclp
->acl_entry
[i
];
1197 if (entry
->ae_perm
& ~(ACL_READ
|ACL_WRITE
|ACL_EXECUTE
))
1199 switch (entry
->ae_tag
) {
1214 for (j
= i
+ 1; j
< aclp
->acl_cnt
; j
++) {
1215 e
= &aclp
->acl_entry
[j
];
1216 if (e
->ae_id
== entry
->ae_id
&&
1217 e
->ae_tag
== entry
->ae_tag
)
1230 if (!user
|| !group
|| !other
|| (mask_required
&& !mask
))
1241 * Check a category or division set to ensure that all values are in
1242 * ascending order and each division or category appears only once.
1245 __check_setvalue(const unsigned short *list
, unsigned short count
)
1249 for (i
= 1; i
< count
; i
++)
1250 if (list
[i
] <= list
[i
-1])
1257 * Check the validity of a MAC label.
1260 xfs_mac_valid(xfs_mac_label_t
*lp
)
1266 * if the total category set and division set is greater than 250
1269 if ((lp
->ml_catcount
+ lp
->ml_divcount
) > XFS_MAC_MAX_SETS
)
1273 * check whether the msentype value is valid, and do they have
1274 * appropriate level, category association.
1276 switch (lp
->ml_msen_type
) {
1277 case XFS_MSEN_ADMIN_LABEL
:
1278 case XFS_MSEN_EQUAL_LABEL
:
1279 case XFS_MSEN_HIGH_LABEL
:
1280 case XFS_MSEN_MLD_HIGH_LABEL
:
1281 case XFS_MSEN_LOW_LABEL
:
1282 case XFS_MSEN_MLD_LOW_LABEL
:
1283 if (lp
->ml_level
!= 0 || lp
->ml_catcount
> 0 )
1286 case XFS_MSEN_TCSEC_LABEL
:
1287 case XFS_MSEN_MLD_LABEL
:
1288 if (lp
->ml_catcount
> 0 &&
1289 __check_setvalue(lp
->ml_list
,
1290 lp
->ml_catcount
) == -1)
1293 case XFS_MSEN_UNKNOWN_LABEL
:
1299 * check whether the minttype value is valid, and do they have
1300 * appropriate grade, division association.
1302 switch (lp
->ml_mint_type
) {
1303 case XFS_MINT_BIBA_LABEL
:
1304 if (lp
->ml_divcount
> 0 &&
1305 __check_setvalue(lp
->ml_list
+ lp
->ml_catcount
,
1306 lp
->ml_divcount
) == -1)
1309 case XFS_MINT_EQUAL_LABEL
:
1310 case XFS_MINT_HIGH_LABEL
:
1311 case XFS_MINT_LOW_LABEL
:
1312 if (lp
->ml_grade
!= 0 || lp
->ml_divcount
> 0 )