Skip to content

Commit 6ee6b8c

Browse files
committed
Apply currently effective Linux capabilities to the Inheritable set and then apply all the capabilities in both the Effective and Inheritable sets to the Ambient set, so that the child process (which can be unaware of capabilities) can have its capabilities set accordingly.
1 parent 9594e2b commit 6ee6b8c

File tree

1 file changed

+97
-0
lines changed

1 file changed

+97
-0
lines changed

src/runtime/runtime.c

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

6568
typedef 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+
13341428
int 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

Comments
 (0)