@@ -64,6 +64,16 @@ extern int sqfs_opt_proc(void* data, const char* arg, int key, struct fuse_args*
6464#include <libgen.h>
6565#include <dirent.h>
6666#include <ctype.h>
67+ #include <sys/syscall.h>
68+
69+ #if defined(SYS_capget ) && defined(SYS_capset )
70+ #define USE_CAPABILITIES
71+ #endif
72+
73+ #ifdef USE_CAPABILITIES
74+ #include <sys/prctl.h>
75+ #include <linux/capability.h>
76+ #endif
6777
6878const char * fusermountPath = NULL ;
6979
@@ -1459,6 +1469,97 @@ void set_portable_home_and_config(char* basepath) {
14591469 }
14601470}
14611471
1472+ #ifdef USE_CAPABILITIES
1473+ int appimage_adjust_capabilities ()
1474+ {
1475+ struct __user_cap_header_struct hdr ;
1476+ struct __user_cap_data_struct data [_LINUX_CAPABILITY_U32S_3 ];
1477+ int res , datacnt ;
1478+
1479+ hdr .version = 0 ;
1480+ hdr .pid = 0 ;
1481+ res = syscall (SYS_capget , & hdr , NULL );
1482+ if (res )
1483+ {
1484+ if (errno != EINVAL || hdr .version == 0 )
1485+ {
1486+ fprintf (stderr , "SYS_capget syscall failed with %d\n" , errno );
1487+ return -1 ;
1488+ }
1489+ }
1490+ else if (hdr .version == 0 )
1491+ {
1492+ fprintf (stderr , "Failed to query capability version\n" );
1493+ return -1 ;
1494+ }
1495+
1496+ //fprintf(stderr, "Linux capability version: %x\n", hdr.version);
1497+
1498+ switch (hdr .version )
1499+ {
1500+ case _LINUX_CAPABILITY_VERSION_1 :
1501+ datacnt = _LINUX_CAPABILITY_U32S_1 ;
1502+ break ;
1503+ case _LINUX_CAPABILITY_VERSION_2 :
1504+ datacnt = _LINUX_CAPABILITY_U32S_2 ;
1505+ break ;
1506+ case _LINUX_CAPABILITY_VERSION_3 :
1507+ datacnt = _LINUX_CAPABILITY_U32S_3 ;
1508+ break ;
1509+ default :
1510+ fprintf (stderr , "Unknown Linux capability version: %x; forcing version 3\n" , hdr .version );
1511+ datacnt = _LINUX_CAPABILITY_U32S_3 ;
1512+ hdr .version = _LINUX_CAPABILITY_VERSION_3 ;
1513+ }
1514+
1515+ res = syscall (SYS_capget , & hdr , & data );
1516+ if (res )
1517+ {
1518+ fprintf (stderr , "Failed to query capabilities; error: %d\n" , errno );
1519+ return -1 ;
1520+ }
1521+
1522+ //for (int i = 0; i < datacnt; ++i)
1523+ //{
1524+ // fprintf(stderr, "Set %d: eff = %08x, perm = %08x, inh = %08x\n", i, data[i].effective, data[i].permitted, data[i].inheritable);
1525+ //}
1526+
1527+ for (int i = 0 ; i < datacnt ; ++ i )
1528+ {
1529+ data [i ].inheritable |= data [i ].permitted ;
1530+ }
1531+
1532+ res = syscall (SYS_capset , & hdr , & data );
1533+ if (res )
1534+ {
1535+ fprintf (stderr , "Failed to set capabilities; error: %d\n" , errno );
1536+ return -1 ;
1537+ }
1538+
1539+ /* now we can set up the ambient set */
1540+ for (int i = 0 ; i < datacnt ; ++ i )
1541+ {
1542+ for (int j = 0 ; j < 32 ; ++ j )
1543+ {
1544+ int capval = i * 32 + j ;
1545+ int capbit = 1 << j ;
1546+
1547+ if ((data [i ].permitted & capbit ) && (data [i ].inheritable & capbit ))
1548+ {
1549+ res = prctl (PR_CAP_AMBIENT , PR_CAP_AMBIENT_RAISE , capval , 0 , 0 );
1550+ if (res )
1551+ {
1552+ fprintf (stderr , "Failed to set ambient capability %d; error: %d\n" , capval , errno );
1553+ return -1 ;
1554+ }
1555+ }
1556+ }
1557+ }
1558+
1559+ return 0 ;
1560+ }
1561+ #endif
1562+
14621563int main (int argc , char * argv []) {
14631564 const bool verbose = (getenv ("VERBOSE" ) != NULL );
14641565 if (verbose ) {
@@ -1832,6 +1933,15 @@ int main(int argc, char* argv[]) {
18321933
18331934 set_portable_home_and_config (fullpath );
18341935
1936+ #ifdef USE_CAPABILITIES
1937+ /* Ensure that capabilities for the AppImage are applied to the children (Note: we won't consider
1938+ this failing as an error as the application might still work for the usecase intended by the user) */
1939+ if (appimage_adjust_capabilities ())
1940+ {
1941+ fprintf (stderr , "Warning: failed to forward capabilities\n" );
1942+ }
1943+ #endif
1944+
18351945 /* Original working directory */
18361946 char cwd [1024 ];
18371947 if (getcwd (cwd , sizeof (cwd )) != NULL ) {
0 commit comments