Skip to content

Commit 5c276a8

Browse files
committed
[WIP] fuzzer: attach security labels to programs
Signed-off-by: Rares Constantin <[email protected]>
1 parent 0ac7291 commit 5c276a8

File tree

13 files changed

+188
-97
lines changed

13 files changed

+188
-97
lines changed

executor/common.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ typedef signed int ssize_t;
3434
#else
3535
#include <endian.h> // for htobe*.
3636
#endif
37+
#include <fstream>
3738
#include <stdint.h>
3839
#include <stdio.h> // for fmt arguments
3940
#include <stdlib.h>
@@ -601,6 +602,15 @@ static void execute_one(void);
601602
#define WAIT_FLAGS 0
602603
#endif
603604

605+
void enforce_policy(bool enforce)
606+
{
607+
std::ofstream outFile("/sys/fs/selinux/enforce");
608+
if (outFile.is_open()) {
609+
outFile << (enforce ? "1" : "0");
610+
outFile.close();
611+
}
612+
}
613+
604614
#if SYZ_EXECUTOR_USES_FORK_SERVER
605615
#include <signal.h>
606616
#include <sys/types.h>
@@ -636,6 +646,7 @@ static void loop(void)
636646
if (!flag_snapshot)
637647
receive_execute();
638648
#endif
649+
enforce_policy(flag_enforce_policy);
639650
int pid = fork();
640651
if (pid < 0)
641652
fail("clone failed");
@@ -737,6 +748,7 @@ static void loop(void)
737748
errno = 0;
738749
fail("child failed");
739750
}
751+
enforce_policy(false);
740752
reply_execute(0);
741753
#endif
742754
#if SYZ_EXECUTOR || SYZ_USE_TMP_DIR

executor/common_linux.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4455,7 +4455,7 @@ static void getcon(char* context, size_t context_size)
44554455
// - Uses fail() instead of returning an error code
44564456
static void setcon(const char* context)
44574457
{
4458-
char new_context[512];
4458+
char new_context[512] = {0};
44594459

44604460
// Attempt to write the new context
44614461
int fd = open(SELINUX_CONTEXT_FILE, O_WRONLY);
@@ -4470,7 +4470,7 @@ static void setcon(const char* context)
44704470
close(fd);
44714471

44724472
if (bytes_written != (ssize_t)strlen(context))
4473-
failmsg("setcon: could not write entire context", "wrote=%zi, expected=%zu", bytes_written, strlen(context));
4473+
failmsg("setcon: could not write entire context", "context: %s, wrote=%zi, expected=%zu", context, bytes_written, strlen(context));
44744474

44754475
// Validate the transition by checking the context
44764476
getcon(new_context, sizeof(new_context));

executor/executor.cc

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,7 @@ static bool flag_nic_vf;
273273
static bool flag_vhci_injection;
274274
static bool flag_wifi;
275275
static bool flag_delay_kcov_mmap;
276+
static bool flag_enforce_policy;
276277

277278
static bool flag_collect_cover;
278279
static bool flag_collect_signal;
@@ -296,6 +297,8 @@ static uint64 slowdown_scale;
296297
// or we already execute programs.
297298
static bool in_execute_one = false;
298299

300+
static bool flag_apply_seclabel = false;
301+
299302
#define SYZ_EXECUTOR 1
300303
#include "common.h"
301304

@@ -306,6 +309,7 @@ const uint64 instr_eof = -1;
306309
const uint64 instr_copyin = -2;
307310
const uint64 instr_copyout = -3;
308311
const uint64 instr_setprops = -4;
312+
const uint64 instr_seclabel = -5;
309313

310314
const uint64 arg_const = 0;
311315
const uint64 arg_addr32 = 1;
@@ -847,6 +851,7 @@ void parse_handshake(const handshake_req& req)
847851
flag_wifi = (bool)(req.flags & rpc::ExecEnv::EnableWifi);
848852
flag_delay_kcov_mmap = (bool)(req.flags & rpc::ExecEnv::DelayKcovMmap);
849853
flag_nic_vf = (bool)(req.flags & rpc::ExecEnv::EnableNicVF);
854+
flag_enforce_policy = (bool)(req.flags & rpc::ExecEnv::EnforcePolicy);
850855
}
851856

852857
void receive_execute()
@@ -869,13 +874,14 @@ void parse_execute(const execute_req& req)
869874
flag_dedup_cover = req.exec_flags & (uint64)rpc::ExecFlag::DedupCover;
870875
flag_comparisons = req.exec_flags & (uint64)rpc::ExecFlag::CollectComps;
871876
flag_threaded = req.exec_flags & (uint64)rpc::ExecFlag::Threaded;
877+
flag_apply_seclabel = req.exec_flags & (uint64)rpc::ExecFlag::SetDynamicSecLabel;
872878
all_call_signal = req.all_call_signal;
873879
all_extra_signal = req.all_extra_signal;
874880

875881
debug("[%llums] exec opts: reqid=%llu type=%llu procid=%llu threaded=%d cover=%d comps=%d dedup=%d signal=%d "
876-
" sandbox=%d/%d/%d/%d timeouts=%llu/%llu/%llu kernel_64_bit=%d\n",
882+
" seclabel=%d sandbox=%d/%d/%d/%d timeouts=%llu/%llu/%llu kernel_64_bit=%d\n",
877883
current_time_ms() - start_time_ms, request_id, (uint64)request_type, procid, flag_threaded, flag_collect_cover,
878-
flag_comparisons, flag_dedup_cover, flag_collect_signal, flag_sandbox_none, flag_sandbox_setuid,
884+
flag_comparisons, flag_dedup_cover, flag_collect_signal, flag_apply_seclabel, flag_sandbox_none, flag_sandbox_setuid,
879885
flag_sandbox_namespace, flag_sandbox_android, syscall_timeout_ms, program_timeout_ms, slowdown_scale,
880886
is_kernel_64_bit);
881887
if (syscall_timeout_ms == 0 || program_timeout_ms <= syscall_timeout_ms || slowdown_scale == 0)
@@ -970,6 +976,22 @@ void execute_one()
970976
memset(&call_props, 0, sizeof(call_props));
971977

972978
read_input(&input_pos); // total number of calls
979+
#if GOOS_linux
980+
// The first call should be seclabel instruction if `flag_apply_seclabel` is true.
981+
if (flag_apply_seclabel) {
982+
uint64 call_num = read_input(&input_pos);
983+
if (call_num != instr_seclabel) {
984+
fail("the first call is not a seclabel instruction\n");
985+
}
986+
uint64 size = read_input(&input_pos);
987+
char seclabel[64]{};
988+
memcpy(seclabel, input_pos, size);
989+
setcon(seclabel);
990+
input_pos += size;
991+
992+
debug("applied security label: %s\n", seclabel);
993+
}
994+
#endif
973995
for (;;) {
974996
uint64 call_num = read_input(&input_pos);
975997
if (call_num == instr_eof)

pkg/flatrpc/flatrpc.fbs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ enum ExecEnv : uint64 (bit_flags) {
142142
SandboxSetuid, // impersonate nobody user
143143
SandboxNamespace, // use namespaces for sandboxing
144144
SandboxAndroid, // use Android sandboxing for the untrusted_app domain
145+
EnforcePolicy, // enforce the loaded SELinux policy
145146
ExtraCover, // collect extra coverage
146147
EnableTun, // setup and use /dev/tun for packet injection
147148
EnableNetDev, // setup more network devices for testing
@@ -161,6 +162,7 @@ enum ExecFlag : uint64 (bit_flags) {
161162
DedupCover, // deduplicate coverage in executor
162163
CollectComps, // collect KCOV comparisons
163164
Threaded, // use multiple threads to mitigate blocked syscalls
165+
SetDynamicSecLabel,
164166
}
165167

166168
struct ExecOptsRaw {

pkg/flatrpc/flatrpc.go

Lines changed: 32 additions & 26 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/flatrpc/flatrpc.h

Lines changed: 30 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -566,23 +566,24 @@ enum class ExecEnv : uint64_t {
566566
SandboxSetuid = 32ULL,
567567
SandboxNamespace = 64ULL,
568568
SandboxAndroid = 128ULL,
569-
ExtraCover = 256ULL,
570-
EnableTun = 512ULL,
571-
EnableNetDev = 1024ULL,
572-
EnableNetReset = 2048ULL,
573-
EnableCgroups = 4096ULL,
574-
EnableCloseFds = 8192ULL,
575-
EnableDevlinkPCI = 16384ULL,
576-
EnableVhciInjection = 32768ULL,
577-
EnableWifi = 65536ULL,
578-
DelayKcovMmap = 131072ULL,
579-
EnableNicVF = 262144ULL,
569+
EnforcePolicy = 256ULL,
570+
ExtraCover = 512ULL,
571+
EnableTun = 1024ULL,
572+
EnableNetDev = 2048ULL,
573+
EnableNetReset = 4096ULL,
574+
EnableCgroups = 8192ULL,
575+
EnableCloseFds = 16384ULL,
576+
EnableDevlinkPCI = 32768ULL,
577+
EnableVhciInjection = 65536ULL,
578+
EnableWifi = 131072ULL,
579+
DelayKcovMmap = 262144ULL,
580+
EnableNicVF = 524288ULL,
580581
NONE = 0,
581-
ANY = 524287ULL
582+
ANY = 1048575ULL
582583
};
583584
FLATBUFFERS_DEFINE_BITMASK_OPERATORS(ExecEnv, uint64_t)
584585

585-
inline const ExecEnv (&EnumValuesExecEnv())[19] {
586+
inline const ExecEnv (&EnumValuesExecEnv())[20] {
586587
static const ExecEnv values[] = {
587588
ExecEnv::Debug,
588589
ExecEnv::Signal,
@@ -592,6 +593,7 @@ inline const ExecEnv (&EnumValuesExecEnv())[19] {
592593
ExecEnv::SandboxSetuid,
593594
ExecEnv::SandboxNamespace,
594595
ExecEnv::SandboxAndroid,
596+
ExecEnv::EnforcePolicy,
595597
ExecEnv::ExtraCover,
596598
ExecEnv::EnableTun,
597599
ExecEnv::EnableNetDev,
@@ -617,6 +619,7 @@ inline const char *EnumNameExecEnv(ExecEnv e) {
617619
case ExecEnv::SandboxSetuid: return "SandboxSetuid";
618620
case ExecEnv::SandboxNamespace: return "SandboxNamespace";
619621
case ExecEnv::SandboxAndroid: return "SandboxAndroid";
622+
case ExecEnv::EnforcePolicy: return "EnforcePolicy";
620623
case ExecEnv::ExtraCover: return "ExtraCover";
621624
case ExecEnv::EnableTun: return "EnableTun";
622625
case ExecEnv::EnableNetDev: return "EnableNetDev";
@@ -638,49 +641,34 @@ enum class ExecFlag : uint64_t {
638641
DedupCover = 4ULL,
639642
CollectComps = 8ULL,
640643
Threaded = 16ULL,
644+
SetDynamicSecLabel = 32ULL,
641645
NONE = 0,
642-
ANY = 31ULL
646+
ANY = 63ULL
643647
};
644648
FLATBUFFERS_DEFINE_BITMASK_OPERATORS(ExecFlag, uint64_t)
645649

646-
inline const ExecFlag (&EnumValuesExecFlag())[5] {
650+
inline const ExecFlag (&EnumValuesExecFlag())[6] {
647651
static const ExecFlag values[] = {
648652
ExecFlag::CollectSignal,
649653
ExecFlag::CollectCover,
650654
ExecFlag::DedupCover,
651655
ExecFlag::CollectComps,
652-
ExecFlag::Threaded
656+
ExecFlag::Threaded,
657+
ExecFlag::SetDynamicSecLabel
653658
};
654659
return values;
655660
}
656661

657-
inline const char * const *EnumNamesExecFlag() {
658-
static const char * const names[17] = {
659-
"CollectSignal",
660-
"CollectCover",
661-
"",
662-
"DedupCover",
663-
"",
664-
"",
665-
"",
666-
"CollectComps",
667-
"",
668-
"",
669-
"",
670-
"",
671-
"",
672-
"",
673-
"",
674-
"Threaded",
675-
nullptr
676-
};
677-
return names;
678-
}
679-
680662
inline const char *EnumNameExecFlag(ExecFlag e) {
681-
if (flatbuffers::IsOutRange(e, ExecFlag::CollectSignal, ExecFlag::Threaded)) return "";
682-
const size_t index = static_cast<size_t>(e) - static_cast<size_t>(ExecFlag::CollectSignal);
683-
return EnumNamesExecFlag()[index];
663+
switch (e) {
664+
case ExecFlag::CollectSignal: return "CollectSignal";
665+
case ExecFlag::CollectCover: return "CollectCover";
666+
case ExecFlag::DedupCover: return "DedupCover";
667+
case ExecFlag::CollectComps: return "CollectComps";
668+
case ExecFlag::Threaded: return "Threaded";
669+
case ExecFlag::SetDynamicSecLabel: return "SetDynamicSecLabel";
670+
default: return "";
671+
}
684672
}
685673

686674
enum class CallFlag : uint8_t {

0 commit comments

Comments
 (0)