@@ -64,6 +64,16 @@ extern int sqfs_opt_proc(void* data, const char* arg, int key, struct fuse_args*
64
64
#include <libgen.h>
65
65
#include <dirent.h>
66
66
#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
67
77
68
78
const char * fusermountPath = NULL ;
69
79
@@ -1459,6 +1469,97 @@ void set_portable_home_and_config(char* basepath) {
1459
1469
}
1460
1470
}
1461
1471
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
+
1462
1563
int main (int argc , char * argv []) {
1463
1564
const bool verbose = (getenv ("VERBOSE" ) != NULL );
1464
1565
if (verbose ) {
@@ -1832,6 +1933,15 @@ int main(int argc, char* argv[]) {
1832
1933
1833
1934
set_portable_home_and_config (fullpath );
1834
1935
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
+
1835
1945
/* Original working directory */
1836
1946
char cwd [1024 ];
1837
1947
if (getcwd (cwd , sizeof (cwd )) != NULL ) {
0 commit comments