[PATCH 1/3] erofs-utils: lib: tar: ignore useless fields of PAX extended headers

Gao Xiang hsiangkao at linux.alibaba.com
Thu Dec 26 15:58:06 AEDT 2024


Since some unknown writer just leaves zero-filled mtime, e.g.
registry.k8s.io/pause:3.6  --platform windows

Layer sha256: bc8517709e9cfff223cb034ff5be8fcbfa5409de286cdac9ae1b8878ebea6b84

Fixes: 95d315fd7958 ("erofs-utils: introduce tarerofs")
Signed-off-by: Gao Xiang <hsiangkao at linux.alibaba.com>
---
 lib/tar.c | 78 ++++++++++++++++++++++++++++++-------------------------
 1 file changed, 42 insertions(+), 36 deletions(-)

diff --git a/lib/tar.c b/lib/tar.c
index 0dd990e..12bf595 100644
--- a/lib/tar.c
+++ b/lib/tar.c
@@ -659,6 +659,7 @@ int tarerofs_parse_tar(struct erofs_inode *root, struct erofs_tarfile *tar)
 	struct erofs_sb_info *sbi = root->sbi;
 	bool whout, opq, e = false;
 	struct stat st;
+	mode_t mode;
 	erofs_off_t tar_offset, dataoff;
 
 	struct tar_header *th;
@@ -751,26 +752,6 @@ out_eot:
 		goto out;
 	}
 
-	st.st_mode = tarerofs_otoi(th->mode, sizeof(th->mode));
-	if (errno)
-		goto invalid_tar;
-
-	if (eh.use_uid) {
-		st.st_uid = eh.st.st_uid;
-	} else {
-		st.st_uid = tarerofs_parsenum(th->uid, sizeof(th->uid));
-		if (errno)
-			goto invalid_tar;
-	}
-
-	if (eh.use_gid) {
-		st.st_gid = eh.st.st_gid;
-	} else {
-		st.st_gid = tarerofs_parsenum(th->gid, sizeof(th->gid));
-		if (errno)
-			goto invalid_tar;
-	}
-
 	if (eh.use_size) {
 		st.st_size = eh.st.st_size;
 	} else {
@@ -779,16 +760,6 @@ out_eot:
 			goto invalid_tar;
 	}
 
-	if (eh.use_mtime) {
-		st.st_mtime = eh.st.st_mtime;
-		ST_MTIM_NSEC_SET(&st, ST_MTIM_NSEC(&eh.st));
-	} else {
-		st.st_mtime = tarerofs_parsenum(th->mtime, sizeof(th->mtime));
-		if (errno)
-			goto invalid_tar;
-		ST_MTIM_NSEC_SET(&st, 0);
-	}
-
 	if (th->typeflag <= '7' && !eh.path) {
 		eh.path = path;
 		j = 0;
@@ -810,28 +781,29 @@ out_eot:
 
 	dataoff = tar->offset;
 	tar->offset += st.st_size;
+	st.st_mode = 0;
 	switch(th->typeflag) {
 	case '0':
 	case '7':
 	case '1':
-		st.st_mode |= S_IFREG;
+		st.st_mode = S_IFREG;
 		if (tar->headeronly_mode || tar->ddtaridx_mode)
 			tar->offset -= st.st_size;
 		break;
 	case '2':
-		st.st_mode |= S_IFLNK;
+		st.st_mode = S_IFLNK;
 		break;
 	case '3':
-		st.st_mode |= S_IFCHR;
+		st.st_mode = S_IFCHR;
 		break;
 	case '4':
-		st.st_mode |= S_IFBLK;
+		st.st_mode = S_IFBLK;
 		break;
 	case '5':
-		st.st_mode |= S_IFDIR;
+		st.st_mode = S_IFDIR;
 		break;
 	case '6':
-		st.st_mode |= S_IFIFO;
+		st.st_mode = S_IFIFO;
 		break;
 	case 'g':
 		ret = tarerofs_parse_pax_header(&tar->ios, &tar->global,
@@ -876,6 +848,40 @@ out_eot:
 		goto out;
 	}
 
+	mode = tarerofs_otoi(th->mode, sizeof(th->mode));
+	if (errno)
+		goto invalid_tar;
+	if (__erofs_unlikely(mode & S_IFMT) &&
+	    (mode & S_IFMT) != (st.st_mode & S_IFMT))
+		erofs_warn("invalid ustar mode %05o @ %llu", mode, tar_offset);
+	st.st_mode |= mode & ~S_IFMT;
+
+	if (eh.use_uid) {
+		st.st_uid = eh.st.st_uid;
+	} else {
+		st.st_uid = tarerofs_parsenum(th->uid, sizeof(th->uid));
+		if (errno)
+			goto invalid_tar;
+	}
+
+	if (eh.use_gid) {
+		st.st_gid = eh.st.st_gid;
+	} else {
+		st.st_gid = tarerofs_parsenum(th->gid, sizeof(th->gid));
+		if (errno)
+			goto invalid_tar;
+	}
+
+	if (eh.use_mtime) {
+		st.st_mtime = eh.st.st_mtime;
+		ST_MTIM_NSEC_SET(&st, ST_MTIM_NSEC(&eh.st));
+	} else {
+		st.st_mtime = tarerofs_parsenum(th->mtime, sizeof(th->mtime));
+		if (errno)
+			goto invalid_tar;
+		ST_MTIM_NSEC_SET(&st, 0);
+	}
+
 	st.st_rdev = 0;
 	if (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode)) {
 		int major, minor;
-- 
2.39.3 (Apple Git-146)



More information about the Linux-erofs mailing list