@@ -61,6 +61,9 @@ extern int sqfs_opt_proc(void* data, const char* arg, int key, struct fuse_args*
61
61
#include <fnmatch.h>
62
62
#include <sys/mman.h>
63
63
#include <stdint.h>
64
+ #include <sys/prctl.h>
65
+ #include <linux/capability.h>
66
+ #include <sys/syscall.h>
64
67
65
68
typedef struct {
66
69
uint32_t lo ;
@@ -1331,6 +1334,97 @@ char* appimage_hexlify(const char* bytes, const size_t numBytes) {
1331
1334
return hexlified ;
1332
1335
}
1333
1336
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
+
1334
1428
int main (int argc , char * argv []) {
1335
1429
char appimage_path [PATH_MAX ];
1336
1430
char argv0_path [PATH_MAX ];
@@ -1704,6 +1798,9 @@ int main(int argc, char* argv[]) {
1704
1798
setenv ("XDG_CONFIG_HOME" , portable_config_dir , 1 );
1705
1799
}
1706
1800
1801
+ /* Ensure that capabilities for the AppImage are applied to the children */
1802
+ appimage_adjust_capabilities ();
1803
+
1707
1804
/* Original working directory */
1708
1805
char cwd [1024 ];
1709
1806
if (getcwd (cwd , sizeof (cwd )) != NULL ) {
0 commit comments