@@ -72,20 +72,6 @@ extern int sqfs_opt_proc(void* data, const char* arg, int key, struct fuse_args*
7272
7373const char * fusermountPath = NULL ;
7474
75- // Capability structures for namespace support
76- #define _LINUX_CAPABILITY_VERSION_3 0x20080522
77-
78- struct cap_header {
79- uint32_t version ;
80- int pid ;
81- };
82-
83- struct cap_data {
84- uint32_t effective ;
85- uint32_t permitted ;
86- uint32_t inheritable ;
87- };
88-
8975typedef struct {
9076 uint32_t lo ;
9177 uint32_t hi ;
@@ -434,38 +420,47 @@ int appimage_print_binary(char* fname, unsigned long offset, unsigned long lengt
434420}
435421
436422// Restore capabilities after entering user namespace
437- void restore_capabilities (void ) {
438- struct cap_header caps = {
423+ void restore_capabilities (bool verbose ) {
424+ struct __user_cap_header_struct caps = {
439425 .version = _LINUX_CAPABILITY_VERSION_3 ,
440426 .pid = 0
441427 };
442- struct cap_data cap_data [2 ] = {{0 , 0 , 0 }, {0 , 0 , 0 }};
428+ struct __user_cap_data_struct cap_data [2 ] = {{0 , 0 , 0 }, {0 , 0 , 0 }};
443429
444- if (syscall (SYS_capget , & caps , & cap_data ) == 0 ) {
445- FILE * f = fopen ("/proc/sys/kernel/cap_last_cap" , "r" );
446- uint32_t last_cap = 39 ; // default fallback
447- if (f != NULL ) {
448- if (fscanf (f , "%u" , & last_cap ) != 1 ) {
449- last_cap = 39 ;
450- }
451- fclose (f );
430+ if (syscall (SYS_capget , & caps , & cap_data ) != 0 ) {
431+ if (verbose ) {
432+ fprintf (stderr , "Warning: failed to get capabilities: %s\n" , strerror (errno ));
452433 }
453-
454- uint64_t all_caps = (1ULL << (last_cap + 1 )) - 1 ;
455- cap_data [0 ].effective = (uint32_t )(all_caps & 0xFFFFFFFF );
456- cap_data [0 ].permitted = (uint32_t )(all_caps & 0xFFFFFFFF );
457- cap_data [0 ].inheritable = (uint32_t )(all_caps & 0xFFFFFFFF );
458- cap_data [1 ].effective = (uint32_t )((all_caps >> 32 ) & 0xFFFFFFFF );
459- cap_data [1 ].permitted = (uint32_t )((all_caps >> 32 ) & 0xFFFFFFFF );
460- cap_data [1 ].inheritable = (uint32_t )((all_caps >> 32 ) & 0xFFFFFFFF );
461-
462- syscall (SYS_capset , & caps , & cap_data );
463-
464- for (uint32_t cap = 0 ; cap <= last_cap ; cap ++ ) {
465- prctl (PR_CAP_AMBIENT , PR_CAP_AMBIENT_RAISE , cap , 0 , 0 );
434+ return ;
435+ }
436+
437+ FILE * f = fopen ("/proc/sys/kernel/cap_last_cap" , "r" );
438+ uint32_t last_cap = 39 ; // default fallback
439+ if (f != NULL ) {
440+ if (fscanf (f , "%u" , & last_cap ) != 1 ) {
441+ last_cap = 39 ;
466442 }
467- } else {
468- fprintf (stderr , "Warning: failed to get capabilities: %s\n" , strerror (errno ));
443+ fclose (f );
444+ }
445+
446+ uint64_t all_caps = (1ULL << (last_cap + 1 )) - 1 ;
447+ cap_data [0 ].effective = (uint32_t )(all_caps & 0xFFFFFFFF );
448+ cap_data [0 ].permitted = (uint32_t )(all_caps & 0xFFFFFFFF );
449+ cap_data [0 ].inheritable = (uint32_t )(all_caps & 0xFFFFFFFF );
450+ cap_data [1 ].effective = (uint32_t )((all_caps >> 32 ) & 0xFFFFFFFF );
451+ cap_data [1 ].permitted = (uint32_t )((all_caps >> 32 ) & 0xFFFFFFFF );
452+ cap_data [1 ].inheritable = (uint32_t )((all_caps >> 32 ) & 0xFFFFFFFF );
453+
454+ if (syscall (SYS_capset , & caps , & cap_data ) != 0 ) {
455+ if (verbose ) {
456+ fprintf (stderr , "Warning: failed to set capabilities: %s\n" , strerror (errno ));
457+ }
458+ return ;
459+ }
460+
461+ for (uint32_t cap = 0 ; cap <= last_cap ; cap ++ ) {
462+ // Ignore failures for individual capabilities as some may not be available
463+ prctl (PR_CAP_AMBIENT , PR_CAP_AMBIENT_RAISE , cap , 0 , 0 );
469464 }
470465}
471466
@@ -562,7 +557,7 @@ bool try_unshare(uid_t uid, gid_t gid, const char* unshare_uid, const char* unsh
562557 }
563558 fclose (f );
564559
565- restore_capabilities ();
560+ restore_capabilities (verbose );
566561
567562 if (!try_make_mount_private ()) {
568563 fprintf (stderr , "Warning: failed to make mount private: %s\n" , strerror (errno ));
@@ -711,7 +706,10 @@ bool check_fuse(bool verbose, uid_t uid, gid_t gid, const char* unshare_uid_str,
711706 return true;
712707 }
713708
714- return true; // Return true anyway to let FUSE try
709+ // Both SUID fusermount and unshare failed, but we still return true
710+ // to let FUSE mounting be attempted (it may work with non-SUID fusermount
711+ // or the user may have other FUSE setup we don't detect)
712+ return true;
715713}
716714
717715/* Exit status to use when launching an AppImage fails.
@@ -1960,11 +1958,6 @@ int main(int argc, char* argv[]) {
19601958 exit (EXIT_EXECERROR );
19611959 }
19621960
1963- // Restore capabilities if we unshared successfully
1964- if (unshare_succeeded ) {
1965- restore_capabilities ();
1966- }
1967-
19681961 int dir_fd , res ;
19691962
19701963 size_t templen = strlen (temp_base );
0 commit comments