Skip to content

Commit 9cd1c8a

Browse files
martonillesqkaiser
authored andcommitted
fix(yaffs): fixed hardlink and symlink handling
Also added support for v1 hardlinks as v1 also supports hardlinks, though the field name is a bit different.
1 parent a2f8540 commit 9cd1c8a

File tree

8 files changed

+24
-11
lines changed

8 files changed

+24
-11
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
version https://git-lfs.github.com/spec/v1
2+
oid sha256:93e487e7ed1a160db8c599cc1fdca058baa6024dd27c329f1d55f823bee9215b
3+
size 4752
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
version https://git-lfs.github.com/spec/v1
2+
oid sha256:434728a410a78f56fc1b5899c3593436e61ab0c731e9072d95e96db290205e53
3+
size 8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../file
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
version https://git-lfs.github.com/spec/v1
2+
oid sha256:434728a410a78f56fc1b5899c3593436e61ab0c731e9072d95e96db290205e53
3+
size 8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
version https://git-lfs.github.com/spec/v1
2+
oid sha256:434728a410a78f56fc1b5899c3593436e61ab0c731e9072d95e96db290205e53
3+
size 8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
file
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
dir/hardlink

unblob/handlers/filesystem/yaffs.py

+9-11
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ class YAFFSEntry:
186186
sum_no_longer_used: int = attr.ib(default=0)
187187
name: str = attr.ib(default="")
188188
alias: str = attr.ib(default="")
189+
equiv_id: int = attr.ib(default=0)
189190
file_size: int = attr.ib(default=0)
190191
st_mode: int = attr.ib(default=0)
191192
st_uid: int = attr.ib(default=0)
@@ -210,7 +211,6 @@ def __str__(self):
210211
@attr.define(kw_only=True)
211212
class YAFFS2Entry(YAFFSEntry):
212213
chksum: int = attr.ib(default=0)
213-
equiv_id: int = attr.ib(default=0)
214214
st_rdev: int = attr.ib(default=0)
215215
win_ctime: List[int] = attr.ib(default=[])
216216
win_mtime: List[int] = attr.ib(default=[])
@@ -526,7 +526,7 @@ def extract_entry(self, entry: YAFFSEntry, outdir: Path): # noqa: C901
526526
for chunk in self.get_file_bytes(entry):
527527
f.write(chunk)
528528
elif entry.object_type == YaffsObjectType.SYMLINK:
529-
if not is_safe_path(outdir, out_path / Path(entry.alias)):
529+
if not is_safe_path(outdir, out_path.parent / Path(entry.alias)):
530530
logger.warning(
531531
"Potential path traversal attempt through symlink",
532532
outdir=outdir,
@@ -536,21 +536,18 @@ def extract_entry(self, entry: YAFFSEntry, outdir: Path): # noqa: C901
536536
logger.debug("creating symlink", file_path=out_path, _verbosity=3)
537537
out_path.symlink_to(Path(entry.alias))
538538
elif entry.object_type == YaffsObjectType.HARDLINK:
539-
if not isinstance(entry, YAFFS2Entry):
540-
logger.warning("non YAFFS2 hardlink object", entry=entry)
541-
return
542-
543539
logger.debug("creating hardlink", file_path=out_path, _verbosity=3)
544-
src_entry = self.file_entries[entry.equiv_id]
545-
src_path = self.resolve_path(src_entry)
546-
if not is_safe_path(outdir, out_path / src_path):
540+
dst_entry = self.file_entries[entry.equiv_id].data
541+
dst_path = self.resolve_path(dst_entry)
542+
if not is_safe_path(outdir, dst_path):
547543
logger.warning(
548544
"Potential path traversal attempt through hardlink",
549545
outdir=outdir,
550-
path=src_path,
546+
path=dst_path,
551547
)
552548
return
553-
src_path.link_to(out_path)
549+
dst_full_path = outdir / dst_path
550+
dst_full_path.link_to(out_path)
554551

555552

556553
class YAFFS2Parser(YAFFSParser):
@@ -699,6 +696,7 @@ def build_entry(self, header: Instance, chunk: YAFFSChunk) -> YAFFSEntry:
699696
name=snull(header.name[0:128]).decode("utf-8"),
700697
alias=snull(header.alias.replace(b"\xFF", b"")).decode("utf-8"),
701698
file_size=header.file_size,
699+
equiv_id=header.equivalent_object_id,
702700
)
703701

704702
def get_chunks(self, object_id: int) -> Iterable[YAFFS1Chunk]:

0 commit comments

Comments
 (0)