@@ -61,6 +61,9 @@ extern int sqfs_opt_proc(void* data, const char* arg, int key, struct fuse_args*
6161#include <fnmatch.h>
6262#include <sys/mman.h>
6363#include <stdint.h>
64+ #include <sys/prctl.h>
65+ #include <linux/capability.h>
66+ #include <sys/syscall.h>
6467
6568typedef struct {
6669 uint32_t lo ;
@@ -1331,6 +1334,97 @@ char* appimage_hexlify(const char* bytes, const size_t numBytes) {
13311334 return hexlified ;
13321335}
13331336
1337+ int appimage_adjust_capabilities ()
1338+ {
1339+ struct __user_cap_header_struct hdr ;
1340+ struct __user_cap_data_struct data [_LINUX_CAPABILITY_U32S_3 ];
1341+ int res , datacnt ;
1342+ unsigned long long capeff , capperm , capinh ;
1343+ pid_t p ;
1344+
1345+ hdr .version = 0 ;
1346+ hdr .pid = 0 ;
1347+ res = syscall (SYS_capget , & hdr , NULL );
1348+ if (res )
1349+ {
1350+ if (errno != EINVAL || hdr .version == 0 )
1351+ {
1352+ fprintf (stderr , "SYS_capget syscall failed with %d\n" , errno );
1353+ return -1 ;
1354+ }
1355+ }
1356+ else if (hdr .version == 0 )
1357+ {
1358+ fprintf (stderr , "Failed to query capability version\n" );
1359+ return -1 ;
1360+ }
1361+
1362+ //fprintf(stderr, "Linux capability version: %x\n", hdr.version);
1363+
1364+ switch (hdr .version )
1365+ {
1366+ case _LINUX_CAPABILITY_VERSION_1 :
1367+ datacnt = _LINUX_CAPABILITY_U32S_1 ;
1368+ break ;
1369+ case _LINUX_CAPABILITY_VERSION_2 :
1370+ datacnt = _LINUX_CAPABILITY_U32S_2 ;
1371+ break ;
1372+ case _LINUX_CAPABILITY_VERSION_3 :
1373+ datacnt = _LINUX_CAPABILITY_U32S_3 ;
1374+ break ;
1375+ default :
1376+ fprintf (stderr , "Unknown Linux capability version: %x; forcing version 3\n" , hdr .version );
1377+ datacnt = _LINUX_CAPABILITY_U32S_3 ;
1378+ hdr .version = _LINUX_CAPABILITY_VERSION_3 ;
1379+ }
1380+
1381+ res = syscall (SYS_capget , & hdr , & data );
1382+ if (res )
1383+ {
1384+ fprintf (stderr , "Failed to query capabilities; error: %d\n" , errno );
1385+ return -1 ;
1386+ }
1387+
1388+ //for (int i = 0; i < datacnt; ++i)
1389+ //{
1390+ // fprintf(stderr, "Set %d: eff = %08x, perm = %08x, inh = %08x\n", i, data[i].effective, data[i].permitted, data[i].inheritable);
1391+ //}
1392+
1393+ for (int i = 0 ; i < datacnt ; ++ i )
1394+ {
1395+ data [i ].inheritable |= data [i ].permitted ;
1396+ }
1397+
1398+ res = syscall (SYS_capset , & hdr , & data );
1399+ if (res )
1400+ {
1401+ fprintf (stderr , "Failed to set capabilities; error: %d\n" , errno );
1402+ return -1 ;
1403+ }
1404+
1405+ /* now we can set up the ambient set */
1406+ for (int i = 0 ; i < datacnt ; ++ i )
1407+ {
1408+ for (int j = 0 ; j < 32 ; ++ j )
1409+ {
1410+ int capval = i * 32 + j ;
1411+ int capbit = 1 << j ;
1412+
1413+ if ((data [i ].permitted & capbit ) && (data [i ].inheritable & capbit ))
1414+ {
1415+ res = prctl (PR_CAP_AMBIENT , PR_CAP_AMBIENT_RAISE , capval , 0 , 0 );
1416+ if (res )
1417+ {
1418+ fprintf (stderr , "Failed to set ambient capability %d; error: %d\n" , capval , errno );
1419+ return 1 ;
1420+ }
1421+ }
1422+ }
1423+ }
1424+
1425+ return 0 ;
1426+ }
1427+
13341428int main (int argc , char * argv []) {
13351429 char appimage_path [PATH_MAX ];
13361430 char argv0_path [PATH_MAX ];
@@ -1704,6 +1798,9 @@ int main(int argc, char* argv[]) {
17041798 setenv ("XDG_CONFIG_HOME" , portable_config_dir , 1 );
17051799 }
17061800
1801+ /* Ensure that capabilities for the AppImage are applied to the children */
1802+ appimage_adjust_capabilities ();
1803+
17071804 /* Original working directory */
17081805 char cwd [1024 ];
17091806 if (getcwd (cwd , sizeof (cwd )) != NULL ) {
0 commit comments