Skip to content

Commit f3e06fd

Browse files
committed
[WIP] fuzzer: attach security labels to programs
Signed-off-by: Rares Constantin <rarescon@google.com>
1 parent 0ac7291 commit f3e06fd

File tree

14 files changed

+129
-50
lines changed

14 files changed

+129
-50
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: 19 additions & 1 deletion
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;
@@ -306,6 +307,7 @@ const uint64 instr_eof = -1;
306307
const uint64 instr_copyin = -2;
307308
const uint64 instr_copyout = -3;
308309
const uint64 instr_setprops = -4;
310+
const uint64 instr_seclabel = -5;
309311

310312
const uint64 arg_const = 0;
311313
const uint64 arg_addr32 = 1;
@@ -847,6 +849,7 @@ void parse_handshake(const handshake_req& req)
847849
flag_wifi = (bool)(req.flags & rpc::ExecEnv::EnableWifi);
848850
flag_delay_kcov_mmap = (bool)(req.flags & rpc::ExecEnv::DelayKcovMmap);
849851
flag_nic_vf = (bool)(req.flags & rpc::ExecEnv::EnableNicVF);
852+
flag_enforce_policy = (bool)(req.flags & rpc::ExecEnv::EnforcePolicy);
850853
}
851854

852855
void receive_execute()
@@ -970,10 +973,25 @@ void execute_one()
970973
memset(&call_props, 0, sizeof(call_props));
971974

972975
read_input(&input_pos); // total number of calls
973-
for (;;) {
976+
for (int index = 0;; index++) {
974977
uint64 call_num = read_input(&input_pos);
975978
if (call_num == instr_eof)
976979
break;
980+
#if GOOS_linux
981+
if (call_num == instr_seclabel) {
982+
if (index) {
983+
fail("seclabel instruction is not the first call\n");
984+
}
985+
uint64 size = read_input(&input_pos);
986+
char seclabel[64]{};
987+
memcpy(seclabel, input_pos, size);
988+
setcon(seclabel);
989+
input_pos += size;
990+
991+
debug("applied security label: %s\n", seclabel);
992+
continue;
993+
}
994+
#endif
977995
if (call_num == instr_copyin) {
978996
char* addr = (char*)(read_input(&input_pos) + SYZ_DATA_OFFSET);
979997
uint64 typ = read_input(&input_pos);

pkg/flatrpc/flatrpc.fbs

Lines changed: 1 addition & 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

pkg/flatrpc/flatrpc.go

Lines changed: 14 additions & 11 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: 16 additions & 13 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";

pkg/fuzzer/fuzzer.go

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -208,20 +208,22 @@ func (fuzzer *Fuzzer) processResult(req *queue.Request, res *queue.Result, flags
208208
}
209209

210210
type Config struct {
211-
Debug bool
212-
Corpus *corpus.Corpus
213-
Logf func(level int, msg string, args ...interface{})
214-
Snapshot bool
215-
Coverage bool
216-
FaultInjection bool
217-
Comparisons bool
218-
Collide bool
219-
EnabledCalls map[*prog.Syscall]bool
220-
NoMutateCalls map[int]bool
221-
FetchRawCover bool
222-
NewInputFilter func(call string) bool
223-
PatchTest bool
224-
ModeKFuzzTest bool
211+
Debug bool
212+
Corpus *corpus.Corpus
213+
Logf func(level int, msg string, args ...interface{})
214+
Snapshot bool
215+
Coverage bool
216+
FaultInjection bool
217+
Comparisons bool
218+
Collide bool
219+
EnabledCalls map[*prog.Syscall]bool
220+
NoMutateCalls map[int]bool
221+
FetchRawCover bool
222+
Sandbox string
223+
AttachSecLabels bool
224+
NewInputFilter func(call string) bool
225+
PatchTest bool
226+
ModeKFuzzTest bool
225227
}
226228

227229
func (fuzzer *Fuzzer) triageProgCall(p *prog.Prog, info *flatrpc.CallInfo, call int, triage *map[int]*triageCall) {
@@ -371,6 +373,13 @@ func (fuzzer *Fuzzer) AddCandidates(candidates []Candidate) {
371373
Stat: fuzzer.statExecCandidate,
372374
Important: true,
373375
}
376+
req.Prog.SecLabel = ""
377+
if fuzzer.Config.AttachSecLabels {
378+
req.Prog.SecLabel = "user_u:user_r:user_t:s0"
379+
if fuzzer.Config.Sandbox == "android" {
380+
req.Prog.SecLabel = "u:r:untrusted_app:s0:c512,c768"
381+
}
382+
}
374383
fuzzer.enqueue(fuzzer.candidateQueue, req, candidate.Flags|progCandidate, 0)
375384
}
376385
}
@@ -472,6 +481,9 @@ func DefaultExecOpts(cfg *mgrconfig.Config, features flatrpc.Feature, debug bool
472481
if cfg.Cover {
473482
env |= flatrpc.ExecEnvSignal
474483
}
484+
if cfg.Experimental.EnforcePolicy {
485+
env |= flatrpc.ExecEnvEnforcePolicy
486+
}
475487
sandbox, err := flatrpc.SandboxToFlags(cfg.Sandbox)
476488
if err != nil {
477489
panic(fmt.Sprintf("failed to parse sandbox: %v", err))

pkg/fuzzer/job.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,13 @@ func genProgRequest(fuzzer *Fuzzer, rnd *rand.Rand) *queue.Request {
4545
p := fuzzer.target.Generate(rnd,
4646
fuzzer.RecommendedCalls(),
4747
fuzzer.ChoiceTable())
48+
p.SecLabel = ""
49+
if fuzzer.Config.AttachSecLabels {
50+
p.SecLabel = "user_u:user_r:user_t:s0"
51+
if fuzzer.Config.Sandbox == "android" {
52+
p.SecLabel = "u:r:untrusted_app:s0:c512,c768"
53+
}
54+
}
4855
return &queue.Request{
4956
Prog: p,
5057
ExecOpts: setFlags(flatrpc.ExecFlagCollectSignal),

pkg/mgrconfig/config.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,12 @@ type Experimental struct {
258258

259259
// Enable dynamic discovery and fuzzing of KFuzzTest targets.
260260
EnableKFuzzTest bool `json:"enable_kfuzztest"`
261+
262+
// Enables the policy enforcement for programs that request this before running syscalls.
263+
EnforcePolicy bool `json:"enforce_policy"`
264+
265+
// Allows the fuzzer to attach a security label to each program.
266+
AttachSecLabels bool `json:"attach_seclabels"`
261267
}
262268

263269
type FocusArea struct {

pkg/rpcserver/runner.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,7 @@ func (runner *Runner) sendRequest(req *queue.Request) error {
329329
avoid |= uint64(1 << id.Proc)
330330
}
331331
}
332+
332333
msg := &flatrpc.HostMessage{
333334
Msg: &flatrpc.HostMessages{
334335
Type: flatrpc.HostMessagesRawExecRequest,

0 commit comments

Comments
 (0)