catalinux / srh (public) (License: GPLv3) (since 2016-02-04) (hash sha1)
srh = Stop Row Hammer
Try to stop the row hammer attacks. It is a work in progress.
List of commits:
Subject Hash Author Date (UTC)
Checkpoint 41f58214060ec445e871366111c68ee150412c79 Catalin(ux) M. BOIE 2015-03-16 17:46:50
Checkpoint - I am able to detect attack1! 6d5349c93a2a5412fa4b6382056c2378e8d2ecb4 Catalin(ux) M. BOIE 2015-03-15 22:44:59
Checkpoint before using mmap 91d01917a463f031770ea08cec9a50f6a5ac5708 Catalin(ux) M. BOIE 2015-03-14 22:27:15
First version fe8b5ebc6a823d2045bce201a9638283db2c6ead Catalin(ux) M. BOIE 2015-03-12 17:58:12
Commit 41f58214060ec445e871366111c68ee150412c79 - Checkpoint
Author: Catalin(ux) M. BOIE
Author date (UTC): 2015-03-16 17:46
Committer name: Catalin(ux) M. BOIE
Committer date (UTC): 2015-03-16 17:46
Parent(s): 6d5349c93a2a5412fa4b6382056c2378e8d2ecb4
Signing key:
Tree: f8d65ed86c494cc901799795f4a6ce4f6fe7fe1d
File Lines added Lines deleted
TODO 3 0
attack1.c 7 1
srhd.c 160 38
File TODO changed (mode: 100644) (index 0217d5d..e4a55fc)
1 1 [ ] Investigate MOVNTQ [ ] Investigate MOVNTQ
2 2 [ ] Take care of CPU hotplug. [ ] Take care of CPU hotplug.
3 3 [ ] What about code running in guest kernel an attacker can change. [ ] What about code running in guest kernel an attacker can change.
4 [ ] Now, create a has table for pid/tid and add history data. Also, add a
5 sorted queue to suspend/continue programs.
6 [ ] madvise throws data from cache?
4 7 [ ] [ ]
File attack1.c changed (mode: 100644) (index 4c63aa5..3d34cde)
1 #include <stdio.h>
2 #include <sys/types.h>
3 #include <unistd.h>
4
1 5 static int k; static int k;
2 6
3 7 int main(void) int main(void)
4 8 { {
5 9 int i, j; int i, j;
6 10
7 for (i = 0; i < 1000 * 1000 * 1000; i++) {
11 fprintf(stderr, "my pid is %d\n", getpid());
12
13 for (i = 0; i < 10 * 1000 * 1000; i++) {
8 14 asm volatile("clflush (%0)" : : "r" (&i) : "memory"); asm volatile("clflush (%0)" : : "r" (&i) : "memory");
9 15 } }
10 16
File srhd.c changed (mode: 100644) (index 716ee13..4af0777)
9 9 #include <sched.h> #include <sched.h>
10 10 #include <linux/perf_event.h> #include <linux/perf_event.h>
11 11 #include <asm/unistd.h> #include <asm/unistd.h>
12 #include <sys/epoll.h>
13 #include <signal.h>
12 14
13 15 #define barrier() asm volatile ("" ::: "memory") #define barrier() asm volatile ("" ::: "memory")
14 16
15 #define MMAP_BUF_SIZE 16 /* in pages */
17 #define MMAP_BUF_SIZE 8 /* in pages */
16 18
17 19 static unsigned long page_size; static unsigned long page_size;
18 20
 
... ... static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid,
27 29 /* /*
28 30 * Registers a counter * Registers a counter
29 31 */ */
30 static int register_event(const __u32 type, __u64 config, void **m)
32 static int register_event(const unsigned int cpu, const __u32 type,
33 __u64 config, void **m)
31 34 { {
32 35 int fd; int fd;
33 36 struct perf_event_attr attr; struct perf_event_attr attr;
 
... ... static int register_event(const __u32 type, __u64 config, void **m)
37 40 attr.sample_type = PERF_SAMPLE_IP attr.sample_type = PERF_SAMPLE_IP
38 41 | PERF_SAMPLE_TID | PERF_SAMPLE_TID
39 42 | PERF_SAMPLE_ADDR | PERF_SAMPLE_ADDR
40 | PERF_SAMPLE_PERIOD;
41 attr.sample_period = 1000 * 1000;
42 attr.enable_on_exec = 1;
43 attr.disabled = 1;
43 | PERF_SAMPLE_PERIOD
44 | PERF_SAMPLE_CPU;
45 attr.sample_period = 1000;
46 //attr.enable_on_exec = 1;
47 attr.disabled = 0;
44 48 attr.exclude_kernel = 1; attr.exclude_kernel = 1;
45 49 //attr.exclude_hv = 1; //attr.exclude_hv = 1;
46
50 //attr.mmap = 1;
51 //attr.mmap2 = 1;
52 //attr.comm = 1;
53 attr.wakeup_events = 1;
47 54 attr.type = type; attr.type = type;
48 55 attr.config = config; attr.config = config;
49 56
50 fd = perf_event_open(&attr, -1 /* pid */, 0 /* cpu */,
57 fd = perf_event_open(&attr, -1 /* pid */, cpu,
51 58 -1 /* group_fd */, PERF_FLAG_FD_CLOEXEC); -1 /* group_fd */, PERF_FLAG_FD_CLOEXEC);
52 59 if (fd == -1) { if (fd == -1) {
53 60 fprintf(stderr, "Cannot call perf_event_open, config %llx\n", fprintf(stderr, "Cannot call perf_event_open, config %llx\n",
 
... ... static int register_event(const __u32 type, __u64 config, void **m)
55 62 exit(1); exit(1);
56 63 } }
57 64
58 *m = mmap(NULL, 1 + MMAP_BUF_SIZE * page_size,
65 *m = mmap(NULL, (1 + MMAP_BUF_SIZE) * page_size,
59 66 PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
60 if (!*m) {
67 fprintf(stderr, "cpu=%d fd=%d *m=%p\n", cpu, fd, *m);
68 if (*m == MAP_FAILED) {
61 69 fprintf(stderr, "Cannot mmap (%s)!\n", strerror(errno)); fprintf(stderr, "Cannot mmap (%s)!\n", strerror(errno));
62 70 exit(1); exit(1);
63 71 } }
 
... ... static int check(void *m)
73 81 { {
74 82 struct perf_event_mmap_page *mp; struct perf_event_mmap_page *mp;
75 83 struct perf_event_header *h; struct perf_event_header *h;
76 void *p;
77 unsigned long long *p_ip, *p_addr, *p_period;
78 unsigned int *p_pid, *p_tid;
84 void *p, *q;
85 unsigned long long *p_ip, *p_addr, *p_period, *p_len, *p_pgoff;
86 unsigned long long *p_time;
87 unsigned int *p_pid, *p_ppid, *p_tid, *p_ptid, *p_cpu;
79 88 unsigned int version, seq, index; unsigned int version, seq, index;
80 89 unsigned long long count, head, tail, rest; unsigned long long count, head, tail, rest;
90 char *filename, *comm;
81 91
82 92 mp = m; mp = m;
83 93 do { do {
 
... ... static int check(void *m)
102 112 p = m + page_size + tail; p = m + page_size + tail;
103 113 rest = head - tail; rest = head - tail;
104 114 while (rest > 0) { while (rest > 0) {
105 h = p;
115 q = p;
116 h = q;
106 117 fprintf(stderr, "\th: type=%u misc=%hu size=%hu rest=%llu\n", fprintf(stderr, "\th: type=%u misc=%hu size=%hu rest=%llu\n",
107 118 h->type, h->misc, h->size, rest); h->type, h->misc, h->size, rest);
108 p += sizeof(struct perf_event_header);
119 q += sizeof(struct perf_event_header);
109 120
110 121 switch (h->type) { switch (h->type) {
122 case PERF_RECORD_MMAP:
123 p_pid = q; q += 4;
124 p_tid = q; q += 4;
125 p_addr = q; q += 8;
126 p_len = q; q += 8;
127 p_pgoff = q; q += 8;
128 filename = q;
129 fprintf(stderr, "\tmmap pid=%u tid=%u addr=%llx"
130 " len=%llu pgoff=%llx filename=%s.\n",
131 *p_pid, *p_tid, *p_addr,
132 *p_len, *p_pgoff, filename);
133 break;
134
111 135 case PERF_RECORD_SAMPLE: case PERF_RECORD_SAMPLE:
112 p_ip = p; p += 8;
113 p_pid = p; p += 4;
114 p_tid = p; p += 4;
115 p_addr = p; p += 8;
116 p_period = p; p += 8;
117 fprintf(stderr, "\tsample! ip=0x%llx pid=%u"
118 " tid=%u addr=%llx period=%llu\n",
119 *p_ip, *p_pid, *p_tid, *p_addr, *p_period);
136 p_ip = q; q += 8;
137 p_pid = q; q += 4;
138 p_tid = q; q += 4;
139 p_addr = q; q += 8;
140 p_cpu = q; q += 8;
141 p_period = q; q += 8;
142 fprintf(stderr, "\tsample ip=0x%llx pid=%u"
143 " tid=%u addr=%llx period=%llu cpu=%u\n",
144 *p_ip, *p_pid, *p_tid, *p_addr, *p_period, *p_cpu);
145 break;
146
147 case PERF_RECORD_EXIT:
148 p_pid = q; q += 4;
149 p_ppid = q; q += 4;
150 p_tid = q; q += 4;
151 p_ptid = q; q += 4;
152 p_time = q; q += 8;
153 fprintf(stderr, "\texit pid=%u ppid=%u tid=%u"
154 " ptid=%u time=%llu\n",
155 *p_pid, *p_ppid, *p_tid, *p_ptid,
156 *p_time);
157 break;
158
159 case PERF_RECORD_COMM:
160 p_pid = q; q += 4;
161 p_tid = q; q += 4;
162 comm = q;
163 fprintf(stderr, "\tcomm pid=%u tid=%u comm=%s\n",
164 *p_pid, *p_tid, comm);
165 break;
166
167 case PERF_RECORD_MMAP2:
168 p_pid = q; q += 4;
169 p_tid = q; q += 4;
170 p_addr = q; q += 8;
171 p_len = q; q += 8;
172 p_pgoff = q; q += 8;
173 q += 4; /* maj */
174 q += 4; /* min */
175 q += 8; /* ino */
176 q += 8; /* ino_generation */
177 q += 4; /* prot */
178 q += 4; /* flags */
179 filename = p;
180 fprintf(stderr, "\tmmap pid=%u tid=%u addr=%llx"
181 " len=%llu pgoff=%llx filename=%s.\n",
182 *p_pid, *p_tid, *p_addr,
183 *p_len, *p_pgoff, filename);
184 break;
185
186 case PERF_RECORD_FORK:
187 p_pid = q; q += 4;
188 p_ppid = q; q += 4;
189 p_tid = q; q += 4;
190 p_ptid = q; q += 4;
191 p_time = q; q += 8;
192 fprintf(stderr, "\tfork pid=%u ppid=%u tid=%u"
193 " ptid=%u time=%llu\n",
194 *p_pid, *p_ppid, *p_tid, *p_ptid,
195 *p_time);
120 196 break; break;
121 197
122 198 default: default:
123 fprintf(stderr, "Unknown type %u\n", h->type);
199 fprintf(stderr, "\tUnknown type %u\n", h->type);
200 break;
124 201 } }
202 p += h->size;
125 203 rest -= h->size; rest -= h->size;
126 204 } }
127 205 mp->data_tail = head; mp->data_tail = head;
 
... ... static int check(void *m)
132 210 int main(void) int main(void)
133 211 { {
134 212 struct sched_param param; struct sched_param param;
135 int fd1, fd2, nr_cpus;
136 void *m1, *m2;
213 int fd1, fd2[2], nr_cpus, r, efd, i, fd;
214 void *m1, *m2[2];
215 struct epoll_event ee;
137 216
138 217 nr_cpus = sysconf(_SC_NPROCESSORS_ONLN); nr_cpus = sysconf(_SC_NPROCESSORS_ONLN);
139 218 fprintf(stderr, "%d cpu(s) online.\n", nr_cpus); fprintf(stderr, "%d cpu(s) online.\n", nr_cpus);
 
... ... int main(void)
148 227 return 1; return 1;
149 228 } }
150 229
151 fd1 = register_event(PERF_TYPE_HW_CACHE, PERF_COUNT_HW_CACHE_LL
230 efd = epoll_create1(EPOLL_CLOEXEC);
231 if (efd == -1) {
232 fprintf(stderr, "Cannot create epoll fd (%s)!\n",
233 strerror(errno));
234 return 1;
235 }
236
237 /*
238 fd1 = register_event(0, PERF_TYPE_HW_CACHE, PERF_COUNT_HW_CACHE_LL
152 239 | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_OP_READ << 8)
153 240 | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16), &m1); | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16), &m1);
154 fd2 = register_event(PERF_TYPE_HW_CACHE, PERF_COUNT_HW_CACHE_LL
155 | (PERF_COUNT_HW_CACHE_OP_READ << 8)
156 | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16), &m2);
241 */
242
243 for (i = 0; i < 2; i++) {
244 fd2[i] = register_event(i, PERF_TYPE_HW_CACHE, PERF_COUNT_HW_CACHE_LL
245 | (PERF_COUNT_HW_CACHE_OP_READ << 8)
246 | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16), &m2[i]);
247 fprintf(stderr, "fd2[%d]=%d m2[%d]=%p\n",
248 i, fd2[i], i, m2[i]);
249
250 memset(&ee, 0, sizeof(struct epoll_event));
251 ee.events = EPOLLIN;
252 ee.data.fd = fd2[i];
253 r = epoll_ctl(efd, EPOLL_CTL_ADD, fd2[i], &ee);
254 if (r != 0) {
255 fprintf(stderr, "Canot add fd to epoll (%s)!\n",
256 strerror(errno));
257 return 1;
258 }
259 }
157 260
158 261 //ioctl(fd1, PERF_EVENT_IOC_RESET, 0); //ioctl(fd1, PERF_EVENT_IOC_RESET, 0);
159 ioctl(fd2, PERF_EVENT_IOC_RESET, 0);
262 //ioctl(fd2, PERF_EVENT_IOC_RESET, 0);
160 263 //ioctl(fd1, PERF_EVENT_IOC_ENABLE, 0); //ioctl(fd1, PERF_EVENT_IOC_ENABLE, 0);
161 ioctl(fd2, PERF_EVENT_IOC_ENABLE, 0);
264 //ioctl(fd2, PERF_EVENT_IOC_ENABLE, 0);
162 265
163 266 while (1) { while (1) {
164 fprintf(stderr, "Checking...\n");
165 check(m2);
166 usleep(1000 * 1000);
267 r = epoll_wait(efd, &ee, 1, 1000);
268 if (r == -1) {
269 if (errno == EINTR)
270 continue;
271
272 fprintf(stderr, "Cannot wait (%s)!\n", strerror(errno));
273 return 1;
274 }
275
276 if (r == 0)
277 continue;
278
279 fd = ee.data.fd;
280 for (i = 0; i < 2; i++) {
281 if (fd == fd2[i])
282 break;
283 }
284 //fprintf(stderr, "Got an event fd=%d i=%d\n", fd, i);
285 check(m2[i]);
167 286 } }
168 ioctl(fd1, PERF_EVENT_IOC_DISABLE, 0);
169 ioctl(fd2, PERF_EVENT_IOC_DISABLE, 0);
287 //ioctl(fd1, PERF_EVENT_IOC_DISABLE, 0);
288 //ioctl(fd2, PERF_EVENT_IOC_DISABLE, 0);
170 289
171 290 munmap(m1, 0); /* TODO: 0 is correct? */ munmap(m1, 0); /* TODO: 0 is correct? */
172 291 munmap(m2, 0); munmap(m2, 0);
173 292
174 293 close(fd1); close(fd1);
175 close(fd2);
294 for (i = 0; i < 2; i++)
295 close(fd2[i]);
296
297 close(efd);
176 298
177 299 return 0; return 0;
178 300 } }
Hints:
Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://rocketgit.com/user/catalinux/srh

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@ssh.rocketgit.com/user/catalinux/srh

Clone this repository using git:
git clone git://git.rocketgit.com/user/catalinux/srh

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a merge request:
... clone the repository ...
... make some changes and some commits ...
git push origin main