forked from m000/dtracker
-
Notifications
You must be signed in to change notification settings - Fork 0
/
provlog.H
160 lines (136 loc) · 4.86 KB
/
provlog.H
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#ifndef DTRACKER_PROVLOG_H
#define DTRACKER_PROVLOG_H
#include <iostream>
#include <fstream>
#include <string>
#include <array>
#include <set>
#include <map> // ?
#include <pin.H>
#include <unistd.h>
#include <fcntl.h>
#include "dtracker.H"
/* Maximum open files per process. */
#define MAX_OPEN_FILES 1024
/* macros related to stdin/stdout/stderr */
#define STDFD_MAX ( MAX( MAX(STDIN_FILENO, STDOUT_FILENO), STDERR_FILENO ) + 1 )
#define IS_STDFD(fd) ( (fd == STDOUT_FILENO) || (fd == STDIN_FILENO) || (fd == STDERR_FILENO) )
/**** data types and externals ************************************/
namespace PROVLOG {
typedef UINT32 ufd_t;
/*
* UFDMap maps program fds (as used by the program) to ufds.
* Normal fds are not suitable for use as taint marks in taint flow
* analysis becaƒuse are "recycled" by the os. This will eventually
* lead to misattribution of some data.
*
* Unlike fds which are recycled by the OS, ufds increase monotonically.
* This makes ufds suitable for use in taint flow analysis.
*/
class UFDMap {
public:
ufd_t operator[](int fd) {
if (this->map[fd] == 0)
this->map[fd] = this->next++;
return this->map[fd];
}
ufd_t del(int fd) {
ufd_t ufd = map[fd];
map[fd] = 0;
return ufd;
}
private:
ufd_t next = 1;
std::array<ufd_t, MAX_OPEN_FILES> map;
};
extern UFDMap ufdmap;
} // namespace PROVLOG
/* Set of watched fds. */
extern std::set<int> fdset;
/* Counters for stdin/stdout/stderr. */
extern off_t stdcount[STDFD_MAX];
/* Current executable name and pid. */
extern std::string exename;
extern pid_t pid;
/**** output macros and inlines ***********************************/
typedef struct {
enum {NONE, SEQ, REP} type;
ssize_t start;
ssize_t length;
} range_info_t;
static const char * range_type_strings[] __attribute__((unused)) = { "NONE", "SEQ", "REP" };
#ifdef USE_LIBDFT_TAG_SET_FDOFF
typedef std::map<tag_traits<tag_t>::inner_type, range_info_t> range_map_t;
#endif
namespace PROVLOG {
/* Raw provenance output stream. */
extern std::ofstream rawProvStream;
/* inline functions for raw provenance logging */
static inline void open(const ufd_t ufd, const std::string & fdname, const int flags, const int created) {
rawProvStream << "o:ufd" << ufd << ":" << fdname << std::endl;
// Unless the the O_WRONLY flag is on, the file descriptor can be read.
if (! (flags&O_WRONLY) )
rawProvStream << "u:" << exename << ":" << fdname << std::endl;
// Emit a generated line if needed.
if (flags & (O_WRONLY|O_RDWR)) {
if (created) {
rawProvStream << "#g:created" << std::endl;
rawProvStream << "g:c:" << exename << ":" << fdname << std::endl;
}
else if (flags & O_TRUNC) {
rawProvStream << "#g:truncated" << std::endl;
rawProvStream << "g:t:" << exename << ":" << fdname << std::endl;
}
else {
// Updated means that it is opened for writing.
// TODO: Currently this is translated to a wasGeneratedBy edge only
// if some tainted bytes are written.
rawProvStream << "#g:updated" << std::endl;
rawProvStream << "g:u:" << exename << ":" << fdname << std::endl;
}
}
// TODO: (low urgency) emit a truncation line if O_TRUNC is included in the flags
}
static inline void close(const ufd_t ufd) {
rawProvStream << "c:ufd" << ufd << std::endl;
}
static inline void exec(const std::string & exename, pid_t pid) {
rawProvStream << "x:" << pid << ":" << exename << std::endl;
}
#ifdef USE_LIBDFT_TAG_BITSET
// used for DLIBDFT_TAG_TYPE=libdft_tag_bitset
// cpp doesn't support string comparison in conditionals
// define this guard macro at the location of use
static inline void write(const ufd_t ufd_origin, const ufd_t ufd_dest, const off_t write_begin, const off_t length) {
const char *range_type = length > 1 ? range_type_strings[range_info_t::REP] : range_type_strings[range_info_t::NONE];
rawProvStream << "w:" << range_type <<
":ufd" << ufd_dest << ":" << write_begin <<
":ufd" << ufd_origin << ":" << 0 <<
":" << length << std::endl;
}
#endif
#ifdef USE_LIBDFT_TAG_SET_FDOFF
// used for DLIBDFT_TAG_TYPE=libdft_tag_set_fdoff
// cpp doesn't support string comparison in conditionals
// define this guard macro at the location of use
static inline void write_range(const ufd_t ofd, const off_t write_begin, const range_map_t::key_type last, const range_map_t::mapped_type & info) {
switch(info.type) {
case range_info_t::SEQ:
rawProvStream << "w:" << range_type_strings[info.type] <<
":ufd" << ofd << ":" << (write_begin+info.start) <<
":ufd" << last.first << ":" << (last.second-(info.length-1)) <<
":" << info.length << std::endl;
break;
case range_info_t::NONE:
case range_info_t::REP:
rawProvStream << "w:" << range_type_strings[info.type] <<
":ufd" << ofd << ":" << (write_begin+info.start) <<
":ufd" << last.first << ":" << last.second <<
":" << info.length << std::endl;
break;
}
}
#endif
} // namespace PROVLOG
#endif
/* vim: set noet ts=4 sts=4 sw=4 ai : */