Hello everyone,
I'm in the process of rewriting AppImageKit for the JVM, and it's been straightforward and relatively easy so far. Got it actually working already and can successfully run the app images I built with my rewritten toolchain.
I have a question however. It concerns this section of appimagetool.c:
// calculate and embed MD5 digest
{
fprintf(stderr, "Embedding MD5 digest\n");
unsigned long digest_md5_offset = 0;
unsigned long digest_md5_length = 0;
bool rv = appimage_get_elf_section_offset_and_length(destination, ".digest_md5", &digest_md5_offset, &digest_md5_length);
if (!rv || digest_md5_offset == 0 || digest_md5_length == 0) {
die("Could not find section .digest_md5 in runtime");
}
static const unsigned long section_size = 16;
if (digest_md5_length < section_size) {
fprintf(
stderr,
".digest_md5 section in runtime's ELF header is too small"
"(found %lu bytes, minimum required: %lu bytes)\n",
digest_md5_length, section_size
);
exit(1);
}
char digest_buffer[section_size];
if (!appimage_type2_digest_md5(destination, digest_buffer)) {
die("Failed to calculate MD5 digest");
}
FILE* destinationfp = fopen(destination, "r+");
if (destinationfp == NULL) {
die("Failed to open AppImage for updating");
}
if (fseek(destinationfp, digest_md5_offset, SEEK_SET) != 0) {
fclose(destinationfp);
die("Failed to embed MD5 digest: could not seek to section offset");
}
if (fwrite(digest_buffer, sizeof(char), section_size, destinationfp) != section_size) {
fclose(destinationfp);
die("Failed to embed MD5 digest: write failed");
}
fclose(destinationfp);
}
It seems to me that it locates the .digest_md5 section of the embedded excecutable and recalculates and overwrites the checksum embedded there. While it seems generally sensible to have that checksum updated properly, I do not understand: where is this checksum actually used? My new toolchain doesn't yet implement this update mechanism and the resulting app images seem to run just fine. So it seems to me that the executable itself doesn't check its own checksum in the process of being executed? Is it up to the OS to check this in theory? Are there any known tools, that check this?
Thanks!
All reactions
Replies: 2 comments 3 replies
Hi @sebkur, one tool that actually checks the checksum is AppImageUpdate.
If your new tool is publicly available, let us know its URL so that we can link to it. Thanks!
All reactions
Thanks for your quick answer @probonopd
If your new tool is publicly available, let us know its URL so that we can link to it. Thanks!
I will do that!
one tool that actually checks the checksum is AppImageUpdate.
OK, interesting. Grepping a bit through that source code, I cannot find any reference to 'md5' though. Looking for 'digest', I do find some code that deals with calculating a sha256 checksum. On the other hand, I don't think AppImageKit updates a sha256 section by default, maybe only when using the 'sign' option?
All reactions
I think AppImageUpdate is using libappimage for this, maybe @TheAssassin can shed some light on it.
We should document it more clearly if it already hasn't been documented properly.
Here is another implementation I wrote some time ago:
All reactions
this seems relevant: AppImage/AppImageSpec#29
All reactions
@probonopd it took a while, but now I published my work here: https://github.com/mobanisto/appimage4j
I called it appimage4j, seemed like a reasonable name. It is a library for other projects to use and also provides a little command line utility. It can currently create AppImage packages from a properly prepared AppImage directory by creating a squashfs filesystem image and prepending the AppImage runtime. It can also do the reverse and unpack AppImage images. Then I also implemented a tool that dumps some information about the app image and the contained squashfs filesystem. Will be fun to create an AppImage out of the CLI tool itself, will do that soon.
Btw. my main motivation for doing all this is to include this into https://github.com/mobanisto/pinpit-gradle-plugin in order to allow Pinpit to produce AppImage binaries directly.
The whole endeavour took me a while because I first had to find and modernize an existing squashfs implementation for the JVM. Found this as a nice starting point and after a little bit of work, got it working to my needs for AppImages: https://github.com/topobyte/squashfs-tools