526 Commits
Author SHA1 Message Date
Ernesto A. Fernández 3721463ba7 0.2.1
This release gets apfs-label and mkapfs to run on systems with 16K
pages. Similar changes are also needed in the fsck, but that can wait
because it's only a testing tool for my own use.

Signed-off-by: Ernesto A. Fernández <ernesto@corellium.com>
v0.2.1
2025-06-02 16:50:22 -03:00
Ernesto A. Fernández 1e756b5096 mkapfs: get rid of mmap to support 16K pages
Following what was done to apfs-label, get rid of mmap in the mkfs to
avoid alignment issues.

Signed-off-by: Ernesto A. Fernández <ernesto@corellium.com>
2025-05-28 18:19:09 -03:00
Ernesto A. Fernández 27bce5cb32 apfs-label: fix memory leak in read_latest_super()
There are obvious memory leaks in read_latest_super(), plug them. Part
of the problem also exists in the driver, so I'll need to fix that next.

Signed-off-by: Ernesto A. Fernández <ernesto@corellium.com>
2025-05-27 21:01:44 -03:00
Ernesto A. Fernández 378544fb3c apfs-label: get rid of mmap to support 16K pages
Apparently apfs-label does not work for 16K page sizes:

  https://github.com/linux-apfs/apfsprogs/issues/21

The problem is that the offsets need to be page-aligned. Just get rid of
mmap entirely, for a tool like this there is no performance cost in just
reading everything into a buffer.

The same problem exists in the mkfs and fsck though. I will have to deal
with it next.

Signed-off-by: Ernesto A. Fernández <ernesto@corellium.com>
2025-05-27 20:37:12 -03:00
Integral da54ccefa0 apfsck: use DIV_ROUND_UP macro 2025-01-09 12:42:08 -03:00
Integral 49220da76f refactor: remove redundant MIN macro in spaceman.c 2025-01-09 12:37:50 -03:00
Ernesto A. Fernández a6f9ec1485 apfsck: implement more checks for fusion drives
I was hoping that this commit would include all layout checks for fusion
drives, but I couldn't quite figure out tenant records, or why there are
multiple different cache mechanisms. I'm having a hard time getting back
into this research, and I'm not even sure if there's any point to it at
all, so I'll just leave things as they are for now.

Signed-off-by: Ernesto A. Fernández <ernesto@corellium.com>
2025-01-08 19:45:52 -03:00
Ernesto A. Fernández 54fc1b615b 0.2.0
I've never made any releases for apfsprogs before because it was mostly
intended for my own use, to help me test the driver. But at this point a
few of the tools might actually be useful to others, and even the mkfs
is probably mature enough to be safe, so I guess I should start. I'm
using 0.2.0 because all of the man pages have been set to 0.1 until now.

Signed-off-by: Ernesto A. Fernández <ernesto@corellium.com>
v0.2.0
2024-11-06 19:51:38 -03:00
Ernesto A. Fernández 8c109f51a9 apfsck: check the block zero magic before all else
When I mistakenly run the fsck on a whole disk, instead of running it on
the apfs partition, I get a confusing "block size is too small" error
message. To avoid this noise, run no checks at all until we have
confirmed that we are working with an apfs filesystem. If not, explain
this clearly to the user.

Signed-off-by: Ernesto A. Fernández <ernesto@corellium.com>
2024-11-05 18:55:54 -03:00
Ernesto A. Fernández fab9b2109e mkapfs: actually use the fatal() function
The mkapfs has a fatal() function, but I keep forgetting about it and
calling fprintf() and exit() directly. Tidy this up.

Signed-off-by: Ernesto A. Fernández <ernesto@corellium.com>
2024-11-05 18:39:12 -03:00
Ernesto A. Fernández 9a13a8ffbe apfsck: update boundary checks for free_next array
Back when I was only working with relatively small disks I was under the
impression that ip_bm_free_next was just a fixed-length 256-bit field.
In reality it's an array of 16-bit fields, with 16 times as many entries
as the number of bitmap blocks needed to map the internal pool. Fix the
boundary checks in spaceman_256_from_off() and rename it accordingly.

Signed-off-by: Ernesto A. Fernández <ernesto@corellium.com>
2024-11-05 16:26:24 -03:00
Ernesto A. Fernández 8d63fb18bf Always mention the -v cli flag on usage()
The -v flag to print the version is mentioned when usage() gets called
for mkapfs and apfsck, but not for apfs-label and apfs-snap. Be
consistent about this.

Signed-off-by: Ernesto A. Fernández <ernesto@corellium.com>
2024-11-05 16:15:03 -03:00
Integral 51563c42f3 Fix exit code when GIT_COMMIT is not null (#14) 2024-11-05 16:05:35 -03:00
Ernesto A. Fernández e058ff11c5 makfs: update comment about the free_next list
I now understand how free_next actually works, so fix an outdated
comment from the mkfs that seems to imply that the tail block is in use.
Also use the macro for the invalid index instead of the magical number
0xFFFF.

Signed-off-by: Ernesto A. Fernández <ernesto@corellium.com>
2024-11-04 20:22:17 -03:00
Ernesto A. Fernández 00d1888564 mkapfs: allow choice of the tier 2 device size
Instead of forcing the tier 2 device to fill the whole disk, allow the
user to specify a block count, same as the main device. This may be
useful for ENOSPC tests at some point.

Signed-off-by: Ernesto A. Fernández <ernesto@corellium.com>
2024-11-04 19:18:13 -03:00
Integral 56c81b8d1f Replace exit(1) with exit(EXIT_FAILURE) to improve code portablility (#15)
* Replace exit(1) with exit(EXIT_FAILURE) to improve code portablility
2024-11-04 16:45:58 -03:00
Ernesto A. Fernández 5e234275a6 apfsck: let the free ip bitmap list go backwards
While implementing the correct ip bitmap list in the driver, I realized
that expecting all entries between two consecutive free bitmaps to be
used made everything stupidly complicated for no reason. So I just
implemented the list in the way that made sense: allocating new bitmaps
in the head and freeing the old ones in the tail, without worrying about
the direction of the jump for each link. The resulting images were
accepted by the official implementations, so I guess that was indeed the
right way.

My fsck does complain of course, so get rid of this silly check.
Instead, just count the free blocks so that we can later confirm that
every used block is marked as invalid.

Signed-off-by: Ernesto A. Fernández <ernesto@corellium.com>
2024-10-30 19:28:42 -03:00
Ernesto A. Fernández 52d9425738 apfsck: fix size checks for disks not used in full
I just noticed that the fsck reports corruption whenever my mkfs creates
a filesystem that doesn't use the whole disk. I don't test this much
because I don't need it right now, and I don't even know if the official
implementations accept it. But it's important to have it working for the
ENOSPC tests of xfstests, which will be important once I actually start
checking for ENOSPC before starting transactions.

Anyway, fix this to the best of my understanding right now, though I may
need to make more changes in the future once I finally get around to
testing these devices on macos.

Signed-off-by: Ernesto A. Fernández <ernesto@corellium.com>
2024-10-30 02:30:35 -03:00
Ernesto A. Fernández ca165ab34c apfsck: fix out-of-bounds write from last patch
The used_bitmaps array was allocated with one slot for each used ip
bitmap block, but it should also have a slot for the free tail. This
isn´t serious because I don't expect anyone to use this fsck other than
me (lots of similar issues probably exist), but it's causing the mkfs
tests to fail, so fix it.

Signed-off-by: Ernesto A. Fernández <ernesto@corellium.com>
2024-10-30 02:14:25 -03:00
Ernesto A. Fernández 6ab4fbaa8d apfsck: correct the ip bitmap list checks
I never fully understood how the ip bitmap list was supposed to work,
but now I'm noticing that the difference between what I do and what the
official driver does are bad enough to quickly corrupt the list when a
container moves back and forth. Of course this is only an issue for
filesystems above 1.32 TiB or so, but it's still pretty serious.

So, I thought about it harder and I'm pretty sure I finally figured it
out: the array entries for each free bitmap are actually kept in a
linked list, that starts in sm_ip_bm_free_head and ends in
sm_ip_bm_free_tail. All entries outside the list (that is, the entries
for the used blocks) are marked with the invalid index 0xFFFF. The tail
itself also gets 0xFFFF even though it's free, because it has no next
entry - so that accounts for the constant off-by-one weirdness in the
number of free blocks.

Signed-off-by: Ernesto A. Fernández <ernesto@corellium.com>
2024-10-25 17:15:11 -03:00
Ernesto A. Fernández d7c51ee27a apfsck: support wrapped ephemeral objects
As I explained before in commit 19b8d6d8 ("apfsck: verify order of
checkpoint mappings"), ephemeral objects (or at least the spaceman) can
wrap around. Add support for reading such objects to the fsck.

This is of course not possible using only mmap as we do now, so
ephemeral objects will need to be copied to allocated memory, and some
hacky changes are needed to free such memory correctly. Also a few
checks inside free_cpoint_map() have become redundant, so make sure they
happen in full inside parse_cpoint_map() and parse_cpoint_map_blocks()
instead.

For the record, this was all tested against an image created by my
driver after applying patch dfdafd2a07cf ("Wrap ephemeral objects around
if there is no room") and rigging it so that transactions would fail
after a wrapped-around object was discovered.

Signed-off-by: Ernesto A. Fernández <ernesto@corellium.com>
2024-10-23 18:06:42 -03:00
Ernesto A. Fernández 686adf33a5 mkapfs: readjust image sizes for testing
The spaceman includes the arrays of cib addresses inside its own block
or blocks, and for that purpose the spaceman struct reports the offset
of each array (one for the main device and one for tier 2). I always
assumed that the offset had to actually be within the boundaries of the
spaceman object, so even regular non-fusion drives would have to store a
single "null" entry in the tier 2 array. Now that I've actually
implemented fusion drives I accidentally got rid of that extra entry and
it turns out that the official implementation doesn't mind.

That said, my mkfs tests claim to work with images of the exact sizes
where the spaceman becomes multiblock, but this is no longer correct
because the spaceman has become slightly smaller. Adjust those two image
sizes by a single cib.

Signed-off-by: Ernesto A. Fernández <ernesto@corellium.com>
2024-10-21 19:32:22 -03:00
Ernesto A. Fernández ced6e8b8fc Avoid sigbus during fusion drive tests
After commit f523ce46 ("mkapfs: run tests on fusion drives as well"), I
noticed that a few fusion drive tests are crashing with sigbus, but I
got sidetracked by another issue and I only got to it now. The problem
is, of course, that with a large tier 2 disk the metadata may not fit in
the main device. This is not a bug, but it's a bit ugly to fail with
sigbus, so put some coarse space checks in place and fail cleanly when
the size difference is too crazy.

Also update the fusion drive tests so that they start checking for clean
failure in the odd cases.

Signed-off-by: Ernesto A. Fernández <ernesto@corellium.com>
2024-10-21 16:45:24 -03:00
Ernesto A. Fernández de8104f57a mkapfs: allocate ephemeral objects on runtime
As explained in the previous patch, ephemeral objects must be
consecutive and in the same order as their mappings. Since the spaceman
has a variable size and some objects are not needed for all kinds of
drives, stop hardcoding the block numbers and find them on runtime
instead.

Signed-off-by: Ernesto A. Fernández <ernesto@corellium.com>
2024-10-18 20:01:53 -03:00
Ernesto A. Fernández 19b8d6d835 apfsck: verify order of checkpoint mappings
I have recently noticed that Apple refuses to acknowledge drives that
were formatted by my mkfs, unless my driver wrote to them at least once.
The official fsck does not report any corruption, but after some
experiments it seems that the problem is that checkpoint mappings are
supposed to be in order, and not leave any holes.

For containers with a multiblock spaceman, the object itself is supposed
to wrap around, again leaving no holes. When the official driver mounts
a 7T container that wrapped around precisely when my driver unmounted
it, the last transaction gets silently discarded. This should be
extremely rare, but I need to fix it.

Start by putting the proper checks in place for the mappings.

Signed-off-by: Ernesto A. Fernández <ernesto@corellium.com>
2024-10-18 16:20:58 -03:00