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
|
#include <stdlib.h>
#include <stdio.h>
#include <stddef.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include "procfs.h"
int procfs_open(pid_t pid) {
char path[2048];
sprintf(path, "/proc/%d/mem", pid);
return open(path, O_RDWR);
}
ssize_t procfs_maps(pid_t pid, struct procfs_map **maps) {
char path[2048];
sprintf(path, "/proc/%d/maps", pid);
FILE *f = fopen(path, "r");
if (!f) return -1;
int n = 0;
int capacity = 2;
*maps = calloc(capacity, sizeof(**maps));
if (!*maps) return -1;
while (1) {
void *base, *max;
char prot_str[4];
int matches = fscanf(f, "%p-%p %4c", &base, &max, prot_str);
if (matches == EOF) goto eof;
if (matches < 3) goto err;
int prot = 0;
for (int i = 0; i < 4; i++) {
switch (prot_str[i]) {
case 'r':
prot |= PROT_READ;
break;
case 'w':
prot |= PROT_WRITE;
break;
case 'x':
prot |= PROT_EXEC;
break;
default:
break;
}
}
if (prot == 0) prot = PROT_NONE;
int c;
while ((c = getc(f)) != '\n')
if (c == EOF) goto eof;
n++;
if (n > capacity) {
capacity <<= 1;
struct procfs_map *r = reallocarray(*maps, capacity, sizeof(*r));
if (!r) goto err;
*maps = r;
}
(*maps)[n - 1] = (struct procfs_map) {
(uintptr_t) base, (uintptr_t) max, prot
};
}
eof:
if (ferror(f)) goto err;
if (n == 0) free(*maps);
return n;
err:
free(*maps);
return -1;
}
int read_mem(int fd, uintptr_t addr, uint8_t *data, size_t size) {
if (lseek(fd, addr, SEEK_SET) == -1) return -1;
size_t n = 0;
while (n < size) {
ssize_t result = read(fd, data + n, size - n);
if (result == -1) return -1;
n += result;
}
return 0;
}
int write_mem(int fd, uintptr_t addr, uint8_t *data, size_t size) {
if (lseek(fd, addr, SEEK_SET) == -1) return -1;
size_t n = 0;
while (n < size) {
ssize_t result = write(fd, data + n, size - n);
if (result == -1) return -1;
n += result;
}
return 0;
}
int read_page(int fd, uintptr_t index, uint8_t *data) {
return read_mem(fd, index * PAGE_SIZE, data, PAGE_SIZE);
}
|