LSPosed / MagiskOnWSALocal

Integrate Magisk root and Google Apps into WSA (Windows Subsystem for Android)
GNU Affero General Public License v3.0
9.49k stars 22.97k forks source link

[Feature Request] Reproducibly produce modified images. (e.g. system_ext.img) #348

Closed A2uria closed 1 year ago

A2uria commented 1 year ago

Is your feature request related to a problem?/你的请求是否与某个问题相关?

No.

Describe the solution you'd like/描述你想要的解决方案

Reproducibly produce patched raw ext2 images. (product.img, system_ext.img, etc.)

Additional context/其他信息

e2fsprogs provided environment variable E2FSPROGS_FAKE_TIME to produce reproducible ext2 images. Also, with environment variable E2FSCK_TIME, we can shrink the size of ext2 images while keep reproducibility.

Here is an example. I use debugfs to delete (inodes of) preinstalled amazon and shrink the fs. The hash of modified modified system_ext.img is always 6cfa7fb0805c69d6af2949eab4356ac9c06e8c36c0304e344a2ce420580ba85a. (original ebcc4c707ba97ea8855064231bbe045bcc6023a3f18aa9c024f6c334d0635ab2, from MicrosoftCorporationII.WindowsSubsystemForAndroid_2211.40000.11.0_neutral_~_8wekyb3d8bbwe.msixbundle)

Note that the major version should be greater than 2211, otherwise replace system_ext.img with product.img

export E2FSPROGS_FAKE_TIME=1230768000
debugfs -w -f system_ext.txt system_ext.img
export E2FSCK_TIME=1230768000
e2fsck -pf system_ext.img
resize2fs -M system_ext.img

Note that time_t 1230768000 is equivalent to timestamp 200901010000 (UTC).

Here's system_ext.txt.

rm /etc/permissions/privapp-permissions-venezia.xml
rm /framework/com.amazon.device.messaging.jar
rm /framework/oat/x86/com.amazon.device.messaging.odex
rm /framework/oat/x86/com.amazon.device.messaging.vdex
rm /framework/oat/x86_64/com.amazon.device.messaging.odex
rm /framework/oat/x86_64/com.amazon.device.messaging.vdex
rm /priv-app/amazon-adm-release/amazon-adm-release.apk
rm /priv-app/amazon-store-release/amazon-store-release.apk
rmdir /priv-app/amazon-adm-release
rmdir /priv-app/amazon-store-release

As far as I know, in MagiskOnWSALocal/scripts/build.sh#L739, you use find . -exec touch -hamt <timestamp> {} ';' to set every timestamp to 200901010000, but there are {a,c,m}time for each file, so just use -ht <timestamp> instead of -hamt <timestamp>.

Another important thing is that the timestamp is localized, so in China, timestamp 200901010000 would be shown as 200901010800, but when setting it to 200901010000, it would be shown as 200901010000, not 200901010800.

p.s. We may need e2fsprogs>=1.46.6-rc1 to do so. However, e2fsprogs=1.46.5 works fine for the example.

p.p.s. 用中文也行但是 repro 不好形容。

Howard20181 commented 1 year ago

保持hash一样有什么好处吗? 如果做其他修改比如复制文件进去就不行了

A2uria commented 1 year ago

保持hash一样有什么好处吗?

方便复现。

如果做其他修改比如复制文件进去就不行了

确实,但是在控制文件写入顺序及内容不变和不改变时间戳的条件下能实现可复现的构建。


稍微看了一下,build.sh#L739 这里不需要重新 touch 时间戳,构建过程本身存在不可复现的步骤,而且 find -exec touch ... 并不能保证所有节点的时间戳都为 200901010000。

p.s. /dev/XXXXXXXX?

Howard20181 commented 1 year ago

貌似是新加入的文件的时间才需要改 而且其实不改也没问题,没有影响

Best regards

, Howard


From: A2uria @.> Sent: Friday, January 13, 2023 10:09:19 PM To: LSPosed/MagiskOnWSALocal @.> Cc: Howard Wu @.>; Comment @.> Subject: Re: [LSPosed/MagiskOnWSALocal] [Feature Request] Reproducibly produce modified images. (e.g. system_ext.img) (Issue #348)

保持hash一样有什么好处吗?

方便复现。

如果做其他修改比如复制文件进去就不行了

确实,但是在控制文件写入顺序及内容不变和不改变时间戳的条件下能实现可复现的构建。


稍微看了一下,build.sh#L739https://github.com/LSPosed/MagiskOnWSALocal/blob/a5f46350b8ea12c1e25ab84f6f0bfe9fe217ff1e/scripts/build.sh#L739 这里不需要重新 touch 时间戳,构建过程本身存在不可复现的步骤,而且 find -exec touch ... 并不能保证所有节点的时间戳都为 200901010000。

p.s. /dev/XXXXXXXX?

― Reply to this email directly, view it on GitHubhttps://github.com/LSPosed/MagiskOnWSALocal/issues/348#issuecomment-1381912153, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AJRNWKYKMDJ6ZCEEAIGHHRTWSFOY7ANCNFSM6AAAAAATZKLNMQ. You are receiving this because you commented.Message ID: @.***>

Howard20181 commented 1 year ago

分区会记录上一次mount的时间,设置fake time没有用

Best regards

, Howard


From: Wu Howard @.> Sent: Friday, January 13, 2023 10:12:27 PM To: LSPosed/MagiskOnWSALocal @.>; LSPosed/MagiskOnWSALocal @.> Cc: Comment @.> Subject: Re: [LSPosed/MagiskOnWSALocal] [Feature Request] Reproducibly produce modified images. (e.g. system_ext.img) (Issue #348)

貌似是新加入的文件的时间才需要改 而且其实不改也没问题,没有影响

Best regards

, Howard


From: A2uria @.> Sent: Friday, January 13, 2023 10:09:19 PM To: LSPosed/MagiskOnWSALocal @.> Cc: Howard Wu @.>; Comment @.> Subject: Re: [LSPosed/MagiskOnWSALocal] [Feature Request] Reproducibly produce modified images. (e.g. system_ext.img) (Issue #348)

保持hash一样有什么好处吗?

方便复现。

如果做其他修改比如复制文件进去就不行了

确实,但是在控制文件写入顺序及内容不变和不改变时间戳的条件下能实现可复现的构建。


稍微看了一下,build.sh#L739https://github.com/LSPosed/MagiskOnWSALocal/blob/a5f46350b8ea12c1e25ab84f6f0bfe9fe217ff1e/scripts/build.sh#L739 这里不需要重新 touch 时间戳,构建过程本身存在不可复现的步骤,而且 find -exec touch ... 并不能保证所有节点的时间戳都为 200901010000。

p.s. /dev/XXXXXXXX?

― Reply to this email directly, view it on GitHubhttps://github.com/LSPosed/MagiskOnWSALocal/issues/348#issuecomment-1381912153, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AJRNWKYKMDJ6ZCEEAIGHHRTWSFOY7ANCNFSM6AAAAAATZKLNMQ. You are receiving this because you commented.Message ID: @.***>

A2uria commented 1 year ago

fake time 只适用于使用 libext2fs 的程序,文件系统挂载用的是内核的 ext2 实现当然没用,所以大概要自己造车轮了。

用 mount 的话底层 vfs 会更新 super->s_mtime 为 time(0) 即设置上次挂载的时间。

fuse2fs 里是这样实现的。

fs->super->s_mtime = time(NULL);

linux kernel 里的实现估计也差不多。

所以大概要基于 libext2fs 对 .img 进行写操作才能实现 .img 的 repro。

p.s. 理论上 smtime 和 i{a,c,m}time 需要设置为 fs->now 而非 time(0) 才能使时间戳一致,但是 vfs 中的 mkdir 等操作都不考虑 fs->now。

p.p.s. 这里随机设备名不可复现。

A2uria commented 1 year ago

fuse2fs 改了改实现了可复现的写操作。

这是用 fuse2fs 挂载后不做任何改动直接 umount 的结果,仅 fs->super->s_kbytes_written 有改动。

$ radiff2 -x a.img b.img
  offset     0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF    0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF
0x00000000  00000000000000000000000000000000 ................   00000000000000000000000000000000 ................
0x00000010  00000000000000000000000000000000 ................   00000000000000000000000000000000 ................
...
0x00000570! 000000000000000085b9020000000000 ................   00000000000000008db9020000000000 ................
0x00000580  00000000000000000000000000000000 ................   00000000000000000000000000000000 ................
0x00000590  00000000000000000000000000000000 ................   00000000000000000000000000000000 ................
...

不做冗余操作的情况下 fs->super->s_kbytes_written 对最终文件系统的 hash 没有影响。

放一个 e2fsprogs 的 patch 在这里。

--- a/misc/fuse2fs.c
+++ b/misc/fuse2fs.c
@@ -435,26 +435,15 @@

 static void get_now(struct timespec *now)
 {
-#ifdef CLOCK_REALTIME
-   if (!clock_gettime(CLOCK_REALTIME, now))
-       return;
-#endif
-
-   now->tv_sec = time(NULL);
+   now->tv_sec = 1230768000;
    now->tv_nsec = 0;
 }

 static void increment_version(struct ext2_inode_large *inode)
 {
-   __u64 ver;
-
-   ver = inode->osd1.linux1.l_i_version;
+   inode->osd1.linux1.l_i_version = 0;
    if (EXT4_FITS_IN_INODE(inode, i_version_hi))
-       ver |= (__u64)inode->i_version_hi << 32;
-   ver++;
-   inode->osd1.linux1.l_i_version = ver;
-   if (EXT4_FITS_IN_INODE(inode, i_version_hi))
-       inode->i_version_hi = ver >> 32;
+       inode->i_version_hi = 0;
 }

 static void init_times(struct ext2_inode_large *inode)
@@ -744,8 +733,6 @@
    conn->want |= FUSE_CAP_IOCTL_DIR;
 #endif
    if (fs->flags & EXT2_FLAG_RW) {
-       fs->super->s_mnt_count++;
-       fs->super->s_mtime = time(NULL);
        fs->super->s_state &= ~EXT2_VALID_FS;
        ext2fs_mark_super_dirty(fs);
        err = ext2fs_flush2(fs, 0);
@@ -1009,7 +996,7 @@
        goto out2;
    }

-   inode.i_generation = ff->next_generation++;
+   inode.i_generation = 0;
    init_times(&inode);
    err = ext2fs_write_inode_full(fs, child, (struct ext2_inode *)&inode,
                      sizeof(inode));
@@ -1130,7 +1117,7 @@
    ext2fs_set_i_gid_high(inode, ctxt->gid >> 16);
    inode.i_mode = LINUX_S_IFDIR | (mode & ~(S_ISUID | fs->umask)) |
               parent_sgid;
-   inode.i_generation = ff->next_generation++;
+   inode.i_generation = 0;

    err = ext2fs_write_inode_full(fs, child, (struct ext2_inode *)&inode,
                      sizeof(inode));
@@ -1503,7 +1490,7 @@
    ext2fs_set_i_uid_high(inode, ctxt->uid >> 16);
    inode.i_gid = ctxt->gid;
    ext2fs_set_i_gid_high(inode, ctxt->gid >> 16);
-   inode.i_generation = ff->next_generation++;
+   inode.i_generation = 0;

    err = ext2fs_write_inode_full(fs, child, (struct ext2_inode *)&inode,
                      sizeof(inode));
@@ -2928,7 +2915,7 @@
        goto out2;
    }

-   inode.i_generation = ff->next_generation++;
+   inode.i_generation = 0;
    init_times(&inode);
    err = ext2fs_write_inode_full(fs, child, (struct ext2_inode *)&inode,
                      sizeof(inode));
Howard20181 commented 1 year ago

好麻烦,要改的地方很多 这个改动对这个项目没有很明显的改进 如果可以的话你PR

Best regards

, Howard


From: A2uria @.> Sent: Tuesday, January 17, 2023 11:17:26 AM To: LSPosed/MagiskOnWSALocal @.> Cc: Howard Wu @.>; Comment @.> Subject: Re: [LSPosed/MagiskOnWSALocal] [Feature Request] Reproducibly produce modified images. (e.g. system_ext.img) (Issue #348)

拿 fuse2fs 改了改实现了可复现的写操作。

这是用 fuse2fs 挂载后不做任何改动直接 umount 的结果,仅 fs->super->s_kbytes_written 有改动。

$ radiff2 -x a.img b.img

offset 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF

0x00000000 00000000000000000000000000000000 ................ 00000000000000000000000000000000 ................

0x00000010 00000000000000000000000000000000 ................ 00000000000000000000000000000000 ................

...

0x00000570! 000000000000000085b9020000000000 ................ 00000000000000008db9020000000000 ................

0x00000580 00000000000000000000000000000000 ................ 00000000000000000000000000000000 ................

0x00000590 00000000000000000000000000000000 ................ 00000000000000000000000000000000 ................

...

不做冗余操作的情况下 fs->super->s_kbytes_written 对最终文件系统的 hash 没有影响。

放一个 e2fsprogs 的 patch 在这里。

--- a/misc/fuse2fs.c

+++ b/misc/fuse2fs.c

@@ -435,26 +435,15 @@

static void get_now(struct timespec *now)

{

-#ifdef CLOCK_REALTIME

-#endif

-

@@ -744,8 +733,6 @@

    conn->want |= FUSE_CAP_IOCTL_DIR;

endif

    if (fs->flags & EXT2_FLAG_RW) {

@@ -1009,7 +996,7 @@

            goto out2;

    }

@@ -1130,7 +1117,7 @@

    ext2fs_set_i_gid_high(inode, ctxt->gid >> 16);

    inode.i_mode = LINUX_S_IFDIR | (mode & ~(S_ISUID | fs->umask)) |

                   parent_sgid;

@@ -1503,7 +1490,7 @@

    ext2fs_set_i_uid_high(inode, ctxt->uid >> 16);

    inode.i_gid = ctxt->gid;

    ext2fs_set_i_gid_high(inode, ctxt->gid >> 16);

@@ -2928,7 +2915,7 @@

            goto out2;

    }

― Reply to this email directly, view it on GitHubhttps://github.com/LSPosed/MagiskOnWSALocal/issues/348#issuecomment-1384783007, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AJRNWKY5NOHDRSO34Z7JQW3WSYFMNANCNFSM6AAAAAATZKLNMQ. You are receiving this because you commented.Message ID: @.***>

Howard20181 commented 1 year ago

把这个项目换成C++的或许就比较好改

Best regards

, Howard


From: Wu Howard @.> Sent: Tuesday, January 17, 2023 11:19:52 AM To: LSPosed/MagiskOnWSALocal @.>; LSPosed/MagiskOnWSALocal @.> Cc: Comment @.> Subject: Re: [LSPosed/MagiskOnWSALocal] [Feature Request] Reproducibly produce modified images. (e.g. system_ext.img) (Issue #348)

好麻烦,要改的地方很多 这个改动对这个项目没有很明显的改进 如果可以的话你PR

Best regards

, Howard


From: A2uria @.> Sent: Tuesday, January 17, 2023 11:17:26 AM To: LSPosed/MagiskOnWSALocal @.> Cc: Howard Wu @.>; Comment @.> Subject: Re: [LSPosed/MagiskOnWSALocal] [Feature Request] Reproducibly produce modified images. (e.g. system_ext.img) (Issue #348)

拿 fuse2fs 改了改实现了可复现的写操作。

这是用 fuse2fs 挂载后不做任何改动直接 umount 的结果,仅 fs->super->s_kbytes_written 有改动。

$ radiff2 -x a.img b.img

offset 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF

0x00000000 00000000000000000000000000000000 ................ 00000000000000000000000000000000 ................

0x00000010 00000000000000000000000000000000 ................ 00000000000000000000000000000000 ................

...

0x00000570! 000000000000000085b9020000000000 ................ 00000000000000008db9020000000000 ................

0x00000580 00000000000000000000000000000000 ................ 00000000000000000000000000000000 ................

0x00000590 00000000000000000000000000000000 ................ 00000000000000000000000000000000 ................

...

不做冗余操作的情况下 fs->super->s_kbytes_written 对最终文件系统的 hash 没有影响。

放一个 e2fsprogs 的 patch 在这里。

--- a/misc/fuse2fs.c

+++ b/misc/fuse2fs.c

@@ -435,26 +435,15 @@

static void get_now(struct timespec *now)

{

-#ifdef CLOCK_REALTIME

-#endif

-

@@ -744,8 +733,6 @@

    conn->want |= FUSE_CAP_IOCTL_DIR;

endif

    if (fs->flags & EXT2_FLAG_RW) {

@@ -1009,7 +996,7 @@

            goto out2;

    }

@@ -1130,7 +1117,7 @@

    ext2fs_set_i_gid_high(inode, ctxt->gid >> 16);

    inode.i_mode = LINUX_S_IFDIR | (mode & ~(S_ISUID | fs->umask)) |

                   parent_sgid;

@@ -1503,7 +1490,7 @@

    ext2fs_set_i_uid_high(inode, ctxt->uid >> 16);

    inode.i_gid = ctxt->gid;

    ext2fs_set_i_gid_high(inode, ctxt->gid >> 16);

@@ -2928,7 +2915,7 @@

            goto out2;

    }

― Reply to this email directly, view it on GitHubhttps://github.com/LSPosed/MagiskOnWSALocal/issues/348#issuecomment-1384783007, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AJRNWKY5NOHDRSO34Z7JQW3WSYFMNANCNFSM6AAAAAATZKLNMQ. You are receiving this because you commented.Message ID: @.***>

A2uria commented 1 year ago

编译还需要引入 build-esseniallibfuse-dev 等包,确实有点麻烦,要是有预编译 bin 的话会简单点。

有可能会自己写一遍,不过毕竟对 magisk 接触的比较少,估计还得看一看 magisk 的实现。

magisk/native/src/init/rootdir.cpp 关于 init.rc 的处理还得研究一下。