Skip to content

Commit 6ada903

Browse files
author
Marek Surovič
authored
Merge pull request #6478 from trailofbits/6477-add-stdout-stderr-as-optional-taint-sinks-behind-a-cli-flag
Adds `stdout` and `stderr` as taint sinks
2 parents 7d0e60c + 156d0d3 commit 6ada903

File tree

7 files changed

+84
-7
lines changed

7 files changed

+84
-7
lines changed

polytracker/include/taintdag/taint.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ const source_index_t source_index_mask = max_source_index;
4646

4747
// Use the remaining bits for source file offset
4848
const size_t source_offset_bits = storage_bits - source_index_bits - 2;
49-
using source_offset_t = storage_t;
49+
using source_offset_t = int64_t;
5050
const source_offset_t max_source_offset =
5151
(static_cast<source_offset_t>(1) << source_offset_bits) - 1;
5252

polytracker/src/polytracker/main.cpp

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
DECLARE_EARLY_CONSTRUCT(std::unordered_set<std::string>, target_sources);
2626
DECLARE_EARLY_CONSTRUCT(taintdag::PolyTracker, polytracker_tdag);
2727
DECLARE_EARLY_CONSTRUCT(std::string, polytracker_db_name);
28+
DECLARE_EARLY_CONSTRUCT(std::string, polytracker_stderr_sink);
29+
DECLARE_EARLY_CONSTRUCT(std::string, polytracker_stdout_sink);
2830

2931
uint64_t byte_start = 0;
3032
uint64_t byte_end = 0;
@@ -55,6 +57,9 @@ void polytracker_parse_env() {
5557
if (auto pdb = getenv("POLYDB")) {
5658
get_polytracker_db_name() = pdb;
5759
}
60+
61+
get_polytracker_stdout_sink() = getenv("POLYTRACKER_STDOUT_SINK");
62+
get_polytracker_stderr_sink() = getenv("POLYTRACKER_STDERR_SINK");
5863
}
5964

6065
/*
@@ -71,12 +76,22 @@ void polytracker_get_settings() {
7176
}
7277

7378
void polytracker_end() {
79+
if (int f = fileno(stdout); f >= 0) {
80+
get_polytracker_tdag().close_file(f);
81+
}
82+
if (int f = fileno(stderr); f >= 0) {
83+
get_polytracker_tdag().close_file(f);
84+
}
7485
// Explicitly destroy the PolyTracker instance to flush mapping to disk
7586
get_polytracker_tdag().~PolyTracker();
7687
}
7788

7889
void polytracker_print_settings() {
79-
printf("POLYDB: %s\n", get_polytracker_db_name().c_str());
90+
printf("POLYDB: %s\n", get_polytracker_db_name().c_str());
91+
printf("POLYTRACKER_STDOUT_SINK: %s\n",
92+
get_polytracker_stdout_sink().c_str());
93+
printf("POLYTRACKER_STDERR_SINK: %s\n",
94+
get_polytracker_stderr_sink().c_str());
8095
}
8196

8297
void polytracker_start(func_mapping const *globals, uint64_t globals_count,
@@ -96,6 +111,14 @@ void polytracker_start(func_mapping const *globals, uint64_t globals_count,
96111
"instrumentation.\n");
97112
}
98113

114+
if (int f = fileno(stdout); f >= 0 && get_polytracker_stdout_sink() == "1") {
115+
get_polytracker_tdag().open_file(f, "/dev/stdout");
116+
}
117+
118+
if (int f = fileno(stderr); f >= 0 && get_polytracker_stderr_sink() == "1") {
119+
get_polytracker_tdag().open_file(f, "/dev/stderr");
120+
}
121+
99122
// Set up the atexit call
100123
atexit(polytracker_end);
101124
}

polytracker/src/taint_sources/write_taints.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@ EXT_C_FUNC ssize_t __dfsw_write(int fd, void *buf, size_t count,
2727
dfsan_label *ret_label) {
2828
auto current_offset = lseek(fd, 0, SEEK_CUR);
2929
auto write_count = write(fd, buf, count);
30-
if (write_count > 0)
30+
if (write_count > 0) {
3131
get_polytracker_tdag().taint_sink(fd, current_offset, buf, write_count);
32-
32+
}
3333
*ret_label = 0;
3434
return write_count;
3535
}
@@ -42,9 +42,10 @@ EXT_C_FUNC size_t __dfsw_fwrite(void *buf, size_t size, size_t count,
4242
auto current_offset = ftell(stream);
4343
auto write_count = fwrite(buf, size, count, stream);
4444
auto fd = fileno(stream);
45-
if (write_count > 0)
45+
if (write_count > 0) {
4646
get_polytracker_tdag().taint_sink(fd, current_offset, buf,
4747
write_count * size);
48+
}
4849
*ret_label = 0;
4950
return write_count;
5051
}

polytracker/taint_dag.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
)
1313
from pathlib import Path
1414
from mmap import mmap, PROT_READ
15-
from ctypes import Structure, c_uint64, c_int32, c_uint32, c_uint8, sizeof
15+
from ctypes import Structure, c_int64, c_uint64, c_int32, c_uint32, c_uint8, sizeof
1616

1717
from .plugins import Command
1818
from .repl import PolyTrackerREPL
@@ -102,7 +102,7 @@ def __repr__(self) -> str:
102102

103103
class TDSink(Structure):
104104
_pack_ = 1
105-
_fields_ = [("fdidx", c_uint8), ("offset", c_uint64), ("label", c_uint32)]
105+
_fields_ = [("fdidx", c_uint8), ("offset", c_int64), ("label", c_uint32)]
106106

107107
def __repr__(self) -> str:
108108
return f"TDSink fdidx: {self.fdidx} offset: {self.offset} label: {self.label}"

tests/test_stdio.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#include <stdint.h>
2+
#include <stdio.h>
3+
4+
int main(int argc, char *argv[]) {
5+
if (argc < 1) {
6+
return 1;
7+
}
8+
9+
FILE *f = fopen(argv[1], "r");
10+
if (!f) {
11+
return 2;
12+
}
13+
14+
char arr[2];
15+
fread(&arr, sizeof(arr), 1, f);
16+
if (arr[0] == '{') {
17+
uint16_t val = (uint16_t)*arr;
18+
val += 1;
19+
fwrite(&val, sizeof(char), 1, stdout);
20+
fwrite(&val, sizeof(char), 1, stderr);
21+
}
22+
23+
return 0;
24+
}

tests/test_stdio.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import pytest
2+
3+
from pathlib import Path
4+
from polytracker import taint_dag, ProgramTrace
5+
6+
7+
@pytest.fixture
8+
def set_env_vars(monkeypatch):
9+
monkeypatch.setenv("POLYTRACKER_STDOUT_SINK", "1")
10+
monkeypatch.setenv("POLYTRACKER_STDERR_SINK", "1")
11+
12+
13+
@pytest.mark.program_trace("test_stdio.cpp")
14+
def test_stdio(set_env_vars, program_trace: ProgramTrace):
15+
assert isinstance(program_trace, taint_dag.TDProgramTrace)
16+
stdout = Path("/dev/stdout")
17+
stderr = Path("/dev/stderr")
18+
headers = list(program_trace.tdfile.fd_headers)
19+
paths = list(map(lambda h: h[0], headers))
20+
assert len(paths) == 3
21+
assert stdout in paths
22+
assert stderr in paths
23+
sinks = list(program_trace.tdfile.sinks)
24+
assert len(sinks) == 2
25+
assert paths[sinks[0].fdidx] == stdout
26+
assert paths[sinks[1].fdidx] == stderr

tests/tracing.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from os import getenv
12
import pytest
23
from shutil import copyfile
34
from subprocess import CalledProcessError
@@ -102,6 +103,8 @@ def validate_execute_target(
102103
"POLYDB": to_native_path(db_path),
103104
"POLYTRACE": "1",
104105
"POLYFUNC": "1",
106+
"POLYTRACKER_STDOUT_SINK": getenv("POLYTRACKER_STDOUT_SINK", "0"),
107+
"POLYTRACKER_STDERR_SINK": getenv("POLYTRACKER_STDERR_SINK", "0"),
105108
}
106109
if taint_all:
107110
del env["POLYPATH"]

0 commit comments

Comments
 (0)