Skip to content

Commit

Permalink
linux: enable network namespacing by default (if available)
Browse files Browse the repository at this point in the history
  • Loading branch information
robertswiecki committed Mar 29, 2020
1 parent f614932 commit 0930d19
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 35 deletions.
32 changes: 30 additions & 2 deletions cmdline.c
Expand Up @@ -159,6 +159,30 @@ bool cmdlineAddEnv(honggfuzz_t* hfuzz, char* env) {
return false;
}

tristate_t cmdlineParseTriState(const char* optname, const char* optarg) {
if (!optarg) {
LOG_F("Option '--%s' needs an argument (true|false|maybe)", optname);
}
/* Probably '-' belong to the next option */
if (optarg[0] == '-') {
LOG_F("Option '--%s' needs an argument (true|false|maybe)", optname);
}
if ((strcasecmp(optarg, "0") == 0) || (strcasecmp(optarg, "false") == 0) ||
(strcasecmp(optarg, "n") == 0) || (strcasecmp(optarg, "no") == 0)) {
return false;
}
if ((strcasecmp(optarg, "1") == 0) || (strcasecmp(optarg, "true") == 0) ||
(strcasecmp(optarg, "y") == 0) || (strcasecmp(optarg, "yes") == 0)) {
return true;
}
if ((strcasecmp(optarg, "-1") == 0) || (strcasecmp(optarg, "maybe") == 0) ||
(strcasecmp(optarg, "m") == 0) || (strcasecmp(optarg, "if_supported") == 0)) {
return true;
}
LOG_F("Unknown value for option --%s=%s. Use true, false or maybe", optname, optarg);
return false;
}

bool cmdlineParseTrueFalse(const char* optname, const char* optarg) {
if (!optarg) {
LOG_F("Option '--%s' needs an argument (true|false)", optname);
Expand Down Expand Up @@ -406,6 +430,7 @@ bool cmdlineParse(int argc, char* argv[], honggfuzz_t* hfuzz) {
.symsWlCnt = 0,
.symsWl = NULL,
.cloneFlags = 0,
.useNetNs = HF_MAYBE,
.kernelOnly = false,
.useClone = true,
},
Expand Down Expand Up @@ -488,7 +513,7 @@ bool cmdlineParse(int argc, char* argv[], honggfuzz_t* hfuzz) {
{ { "linux_perf_bts_edge", no_argument, NULL, 0x513 }, "Use Intel BTS to count unique edges" },
{ { "linux_perf_ipt_block", no_argument, NULL, 0x514 }, "Use Intel Processor Trace to count unique blocks (requires libipt.so)" },
{ { "linux_perf_kernel_only", no_argument, NULL, 0x515 }, "Gather kernel-only coverage with Intel PT and with Intel BTS" },
{ { "linux_ns_net", no_argument, NULL, 0x0530 }, "Use Linux NET namespace isolation" },
{ { "linux_ns_net", required_argument, NULL, 0x0530 }, "Use Linux NET namespace isolation (yes/no/maybe [default:maybe/if_supported])" },
{ { "linux_ns_pid", no_argument, NULL, 0x0531 }, "Use Linux PID namespace isolation" },
{ { "linux_ns_ipc", no_argument, NULL, 0x0532 }, "Use Linux IPC namespace isolation" },
#endif // defined(_HF_ARCH_LINUX)
Expand Down Expand Up @@ -711,7 +736,10 @@ bool cmdlineParse(int argc, char* argv[], honggfuzz_t* hfuzz) {
hfuzz->linux.kernelOnly = true;
break;
case 0x530:
hfuzz->linux.cloneFlags |= (CLONE_NEWUSER | CLONE_NEWNET);
hfuzz->linux.useNetNs = cmdlineParseTriState(opts[opt_index].name, optarg);
if (hfuzz->linux.useNetNs == HF_YES) {
hfuzz->linux.cloneFlags |= (CLONE_NEWUSER | CLONE_NEWNET);
}
break;
case 0x531:
hfuzz->linux.cloneFlags |= (CLONE_NEWUSER | CLONE_NEWPID);
Expand Down
7 changes: 7 additions & 0 deletions honggfuzz.h
Expand Up @@ -132,6 +132,12 @@ typedef enum {
_HF_STATE_DYNAMIC_MINIMIZE,
} fuzzState_t;

typedef enum {
HF_MAYBE = -1,
HF_NO = 0,
HF_YES = 1,
} tristate_t;

struct _dynfile_t {
size_t size;
uint64_t cov[4];
Expand Down Expand Up @@ -300,6 +306,7 @@ typedef struct {
char** symsWl;
size_t symsWlCnt;
uintptr_t cloneFlags;
tristate_t useNetNs;
bool kernelOnly;
bool useClone;
} linux;
Expand Down
43 changes: 19 additions & 24 deletions input.c
Expand Up @@ -440,27 +440,31 @@ bool input_inDynamicCorpus(run_t* run, const char* fname) {
return false;
}

static inline unsigned input_slowFactor(run_t* run, dynfile_t* dynfile) {
/* Slower the input, lower the chance of it being tested */
uint64_t msec_per_run = ((uint64_t)(time(NULL) - run->global->timing.timeStart) * 1000);
msec_per_run /= ATOMIC_GET(run->global->cnts.mutationsCnt);
msec_per_run /= run->global->threads.threadsMax;
/* Cap this to 1-10 ms */
msec_per_run = HF_CAP(msec_per_run, 1, 10);

unsigned slow_factor = (unsigned)(dynfile->timeExecMillis / msec_per_run);
return HF_MIN(slow_factor, 20);
}

static inline unsigned input_skipFactor(run_t* run, dynfile_t* dynfile, unsigned* slow_factor) {
int penalty = 1;

{
/* Slower the input, lower the chance of it being tested */
uint64_t msec_per_run = ((uint64_t)(time(NULL) - run->global->timing.timeStart) * 1000);
msec_per_run /= ATOMIC_GET(run->global->cnts.mutationsCnt);
msec_per_run /= run->global->threads.threadsMax;
/* Cap this to 1-10 ms */
msec_per_run = HF_CAP(msec_per_run, 1, 10);

*slow_factor = (unsigned)(dynfile->timeExecMillis / msec_per_run);
*slow_factor = HF_MIN(*slow_factor, 20);
penalty += (*slow_factor - 3);
*slow_factor = input_slowFactor(run, dynfile);
penalty += HF_CAP(((int)*slow_factor - 3), -15, 30);
}

{
/* Older inputs -> lower chance of being tested */
const int scaleMap[] = {
[99 ... 200] = -5,
[96 ... 98] = -2,
[99 ... 200] = -10,
[96 ... 98] = -3,
[91 ... 95] = -1,
[81 ... 90] = 0,
[71 ... 80] = 1,
Expand All @@ -475,22 +479,13 @@ static inline unsigned input_skipFactor(run_t* run, dynfile_t* dynfile, unsigned

{
/* If the input wasn't source of other inputs so far, make it less likely to be tested */
switch (dynfile->refs) {
case 0:
penalty += 5;
break;
case 1:
break;
default:
penalty -= HF_MIN(dynfile->refs * 5, 20);
break;
}
penalty += HF_CAP((2 - (int)dynfile->refs * 5), -15, 15);
}

{
/* Add penalty for the input being too big - 0 is for 1kB input */
/* Add penalty for the input being too big - 0 is for 256B input */
if (dynfile->size > 0) {
penalty += (util_Log2(dynfile->size) - 10);
penalty += HF_CAP(((int)util_Log2(dynfile->size) - 8), -15, 15);
}
}

Expand Down
23 changes: 15 additions & 8 deletions linux/arch.c
Expand Up @@ -98,21 +98,28 @@ pid_t arch_fork(run_t* run) {
}

bool arch_launchChild(run_t* run) {
if ((run->global->linux.cloneFlags & CLONE_NEWNET) && (nsIfaceUp("lo") == false)) {
if ((run->global->linux.cloneFlags & CLONE_NEWNET) && !nsIfaceUp("lo")) {
LOG_W("Cannot bring interface 'lo' up");
}

/*
* Make it attach-able by ptrace()
*/
/* Try to enable network namespacing if requested */
if (run->global->linux.useNetNs == HF_MAYBE) {
if (unshare(CLONE_NEWUSER | CLONE_NEWNET) == -1) {
PLOG_D("unshare((CLONE_NEWUSER|CLONE_NEWNS) failed");
} else if (!nsIfaceUp("lo")) {
LOG_E("Network namespacing enabled, but couldn't bring interface 'lo' up");
return false;
}
LOG_D("Network namespacing enabled, and the 'lo' interface is set up");
}

/* Make it attach-able by ptrace() */
if (prctl(PR_SET_DUMPABLE, 1UL, 0UL, 0UL, 0UL) == -1) {
PLOG_E("prctl(PR_SET_DUMPABLE, 1)");
return false;
}

/*
* Kill a process which corrupts its own heap (with ABRT)
*/
/* Kill rocess which corrupts its own heap (with ABRT) */
if (setenv("MALLOC_CHECK_", "7", 0) == -1) {
PLOG_E("setenv(MALLOC_CHECK_=7) failed");
return false;
Expand All @@ -137,7 +144,7 @@ bool arch_launchChild(run_t* run) {
PLOG_D("personality(ADDR_NO_RANDOMIZE) failed");
}

/* alarms persist across execve(), so disable it here */
/* Alarms persist across execve(), so disable them here */
alarm(0);

/* Wait for the ptrace to attach now */
Expand Down
2 changes: 1 addition & 1 deletion mangle.c
Expand Up @@ -874,7 +874,7 @@ void mangle_mangleContent(run_t* run, unsigned slow_factor) {
break;
default:
/* Give it a good shake-up, if it's a slow input */
changesCnt = HF_MIN(slow_factor, 15);
changesCnt = HF_MIN(slow_factor, 20);
changesCnt = HF_MAX(changesCnt, run->global->mutate.mutationsPerRun);
break;
}
Expand Down

0 comments on commit 0930d19

Please sign in to comment.