Skip to content

Commit 5085952

Browse files
probonopdTheAssassin
authored andcommitted
Find usermountN using execve and set FUSERMOUNT_PROG if not set
1 parent 1da180f commit 5085952

File tree

1 file changed

+104
-1
lines changed

1 file changed

+104
-1
lines changed

src/runtime/runtime.c

Lines changed: 104 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* as possible (one .c file) and use as few external dependencies
66
* as possible
77
*
8-
* Copyright (c) 2004-22 Simon Peter
8+
* Copyright (c) 2004-24 Simon Peter
99
* Portions Copyright (c) 2007 Alexander Larsson
1010
* Portions from WjCryptLib_Md5 originally written by Alexander Peslyak,
1111
modified by WaterJuice retaining Public Domain license
@@ -62,6 +62,10 @@ extern int sqfs_opt_proc(void* data, const char* arg, int key, struct fuse_args*
6262
#include <sys/mman.h>
6363
#include <stdint.h>
6464
#include <libgen.h>
65+
#include <dirent.h>
66+
#include <ctype.h>
67+
68+
const char* fusermountPath = NULL;
6569

6670
typedef struct {
6771
uint32_t lo;
@@ -405,6 +409,93 @@ int appimage_print_binary(char* fname, unsigned long offset, unsigned long lengt
405409
return 0;
406410
}
407411

412+
char* find_fusermount() {
413+
char* fusermount_base = "fusermount";
414+
415+
char* fusermount_path = getenv("PATH");
416+
if (fusermount_path == NULL) {
417+
return NULL;
418+
}
419+
420+
char* path_copy = strdup(fusermount_path);
421+
char* dir = strtok(path_copy, ":");
422+
423+
while (dir != NULL) {
424+
DIR* dir_ptr = opendir(dir);
425+
if (dir_ptr == NULL) {
426+
dir = strtok(NULL, ":");
427+
continue;
428+
}
429+
430+
struct dirent* entry;
431+
while ((entry = readdir(dir_ptr)) != NULL) {
432+
// Check if the entry starts with "fusermount"
433+
if (strncmp(entry->d_name, fusermount_base, 10) == 0) {
434+
// Check if the rest of the entry is a digit
435+
char* suffix = entry->d_name + 10;
436+
int j = 0;
437+
while (suffix[j] != '\0' && isdigit(suffix[j])) {
438+
j++;
439+
}
440+
441+
if (suffix[j] == '\0') {
442+
// Construct the full path of the entry
443+
char* fusermount_full_path = malloc(strlen(dir) + strlen(entry->d_name) + 2);
444+
sprintf(fusermount_full_path, "%s/%s", dir, entry->d_name);
445+
446+
// Check if the binary is setuid root
447+
struct stat sb;
448+
if (stat(fusermount_full_path, &sb) == -1) {
449+
perror("stat");
450+
free(fusermount_full_path);
451+
continue;
452+
}
453+
454+
if (sb.st_uid != 0 || (sb.st_mode & S_ISUID) == 0) {
455+
// Not setuid root, skip this binary
456+
free(fusermount_full_path);
457+
continue;
458+
}
459+
460+
pid_t pid = fork();
461+
if (pid == -1) {
462+
perror("fork");
463+
free(fusermount_full_path);
464+
continue;
465+
}
466+
467+
if (pid == 0) {
468+
// Child process
469+
char* args[] = {fusermount_full_path, "--version", NULL};
470+
execvp(fusermount_full_path, args);
471+
// If execvp returns, it means the executable was not found
472+
exit(1);
473+
} else {
474+
// Parent process
475+
int status;
476+
waitpid(pid, &status, 0);
477+
478+
if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
479+
// The executable was found and executed successfully
480+
closedir(dir_ptr);
481+
free(path_copy);
482+
return fusermount_full_path;
483+
}
484+
485+
free(fusermount_full_path);
486+
}
487+
}
488+
}
489+
}
490+
491+
closedir(dir_ptr);
492+
dir = strtok(NULL, ":");
493+
}
494+
495+
free(path_copy);
496+
return NULL;
497+
}
498+
408499
/* Exit status to use when launching an AppImage fails.
409500
* For applications that assign meanings to exit status codes (e.g. rsync),
410501
* we avoid "cluttering" pre-defined exit status codes by using 127 which
@@ -1600,6 +1691,18 @@ int main(int argc, char* argv[]) {
16001691
if (pid == 0) {
16011692
/* in child */
16021693

1694+
fusermountPath = getenv("FUSERMOUNT_PROG");
1695+
if (fusermountPath == NULL) {
1696+
char* new_prog = find_fusermount();
1697+
if (new_prog != NULL) {
1698+
setenv("FUSERMOUNT_PROG", new_prog, 1);
1699+
// printf("FUSERMOUNT_PROG set to %s\n", new_prog);
1700+
free(new_prog);
1701+
} else {
1702+
printf("Error: No suitable fusermount binary found on the $PATH\n");
1703+
}
1704+
}
1705+
16031706
char* child_argv[5];
16041707

16051708
/* close read pipe */

0 commit comments

Comments
 (0)