Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,9 @@ add_executable(moria
src/validators/esp32_part.cpp
src/validators/esp32_nvs.cpp
src/validators/legacy_fs.cpp
src/validators/littlefs.cpp
src/littlefs_parse.cpp
src/extract/littlefs.cpp
src/validators/luks.cpp
)
target_include_directories(moria PRIVATE src third_party)
Expand Down Expand Up @@ -218,6 +221,7 @@ if(Python3_Interpreter_FOUND)
test_extract
test_human_tree
test_partition
test_littlefs
test_partition_overlap
test_esp32_part
test_esp32_nvs
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,9 @@ moria does structural identification, extraction, and carving. Secret/credential
## License

MIT, see `LICENSE`.

Some on-disk format handling is a clean reimplementation of the algorithms in
other open-source projects, written independently against moria's own I/O layer
(no source copied): the UCL/NRV2B decompressor and CTO unfilters from UPX/UCL
(GPL-2.0, algorithms only), and the metadata-commit and CTZ skip-list layout of
[littlefs](https://github.com/littlefs-project/littlefs) (BSD-3-Clause).
23 changes: 23 additions & 0 deletions signatures/littlefs.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name = "littlefs"
category = "filesystem"

# LittleFS superblock: the ASCII magic "littlefs" sits at byte 8 of block 0 (it is
# the data of the superblock name tag). magic_offset=8 anchors ctx.offset on the
# block-0 (filesystem) start. The validator parses the superblock metadata pair,
# verifies the commit CRC32, and reads the geometry (version, block_size,
# block_count) from the inline-struct entry. Replaces the weak --broad
# littlefs_superblock magic (0xf00ffff7 @4) with a validated, CRC-checked signature.
magic_offset = 8
validator = "littlefs"
confidence = "structural"

[[magic]]
ascii = "littlefs"
endian = "little"

[doc]
description = "LittleFS: power-fail-safe flash filesystem (Zephyr/Mbed/ESP-IDF/nRF/STM32 MCUs)."
references = [
{ title = "littlefs SPEC", url = "https://github.com/littlefs-project/littlefs/blob/master/SPEC.md" },
{ title = "littlefs DESIGN", url = "https://github.com/littlefs-project/littlefs/blob/master/DESIGN.md" },
]
36 changes: 36 additions & 0 deletions src/extract/littlefs.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// littlefs.cpp — LittleFS extraction entry point. See extract/littlefs.hpp.
#include "extract/littlefs.hpp"

#include "extract/safepath.hpp"
#include "littlefs_parse.hpp"

namespace ft {

bool extract_littlefs(const Reader& r, const Finding& f, SafeRoot& root,
const std::string& subdir, Extracted& out) {
out.offset = f.offset;
out.type = "littlefs";
out.root = subdir;

LfsSuper s = lfs_read_super(r, f.offset);
if (!s.ok) {
out.status = "error:bad-superblock";
return true;
}
LfsStats st;
if (!lfs_extract(r, s, root, subdir, st)) {
out.status = "error:extract";
return true;
}
out.files = st.files;
out.dirs = st.dirs;
out.symlinks = 0;
out.bytes = st.bytes;
out.consumed = static_cast<size_t>(s.block_size) * s.block_count;
out.status = (st.crc_fail || st.truncated) ? "partial" : "ok";
if (st.crc_fail) out.warnings.push_back("some metadata/data failed CRC");
if (st.truncated) out.warnings.push_back("walk capped (depth/count/size guard)");
return true;
}

} // namespace ft
11 changes: 11 additions & 0 deletions src/extract/littlefs.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// littlefs.hpp — LittleFS extraction entry point.
#pragma once

#include "extract/manifest.hpp"

namespace ft {

bool extract_littlefs(const Reader& r, const Finding& f, SafeRoot& root,
const std::string& subdir, Extracted& out);

} // namespace ft
2 changes: 2 additions & 0 deletions src/extract/manifest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "extract/tar.hpp"
#include "extract/yaffs2.hpp"
#include "extract/ubifs.hpp"
#include "extract/littlefs.hpp"
#include "extract/uboot_env.hpp"
#include "extract/esp32_nvs.hpp"
#include "extract/uimage.hpp"
Expand Down Expand Up @@ -57,6 +58,7 @@ Extractor find_extractor(const std::string& type) {
if (type == "ntfs" || type == "ntfs_filesystem") return extract_ntfs;
if (type == "iso9660" || type == "iso") return extract_iso9660;
if (type == "uimage") return extract_uimage;
if (type == "littlefs") return extract_littlefs;
if (type == "uboot_env") return extract_uboot_env;
if (type == "esp32_nvs") return extract_esp32_nvs;
if (type == "rae_rfp") return extract_rae_rfp;
Expand Down
Loading
Loading