struct Request {
int
version;
int
pid;
void
*
remote;
void
*
local;
size_t size;
ssize_t result;
};
struct dentry
*
vmrw_file
=
NULL;
static
ssize_t fop_read(struct
file
*
file
, char
*
req_buffer, size_t size, loff_t
*
offset)
{
struct Request req;
if
(size !
=
sizeof(struct Request)) {
return
-
EBADMSG;
}
copy_from_user(&req, req_buffer, size);
if
(req.version !
=
VMRW_VERSION) {
return
-
EBADMSG;
}
struct pid
*
pid
=
find_get_pid(req.pid);
if
(pid
=
=
NULL) {
return
-
ENOENT;
}
struct task_struct
*
task
=
get_pid_task(pid, PIDTYPE_PID);
if
(task
=
=
NULL) {
return
-
ENOENT;
}
struct mm_struct
*
mm
=
get_task_mm(task);
if
(mm
=
=
NULL) {
return
-
ENOENT;
}
pt_entry_t
*
mm_pgd
=
*
(pt_entry_t
*
*
)((char
*
)mm
+
rti.mm_pgd_offset);
/
/
/
/
typedef void (
*
show_pte_t)(unsigned
long
addr);
/
/
void
*
kallsyms_lookup_name(const char
*
name);
/
/
show_pte_t show_pte
=
(show_pte_t)kallsyms_lookup_name(
"show_pte"
);
/
/
show_pte((uintptr_t)req.remote);
/
/
size_t remain
=
req.size;
uint64_t src
=
(uintptr_t)req.remote;
char
*
dst
=
(char
*
)req.local;
DEBUG_LOG(
"= read %016llx %lu to %016llx\n"
, req.remote, req.size, req.local);
while
(remain) {
void
*
page
=
resolve_page(mm_pgd, src);
if
(page
=
=
NULL) {
DEBUG_LOG(
"+ invalid page %016llx\n"
, src);
break
;
}
void
*
page_ptr
=
((char
*
)page
+
__offset_in_page(src));
size_t page_sz
=
__MIN(
0x1000
-
__offset_in_page(src), remain);
DEBUG_LOG(
"! copy %016llx %lu to %016llx\n"
, page_ptr, page_sz, dst);
unsigned
long
r
=
copy_to_user(dst, page_ptr, page_sz);
if
(r !
=
0
) {
remain
-
=
page_sz
-
r;
break
;
}
remain
-
=
page_sz;
src
+
=
page_sz;
dst
+
=
page_sz;
}
req.result
=
req.size
-
remain;
copy_to_user(req_buffer, &req, sizeof(struct Request));
mmput(mm);
return
sizeof(struct Request);
}
static
ssize_t fop_write(struct
file
*
file
, const char
*
ptr, size_t size, loff_t
*
offset)
{
return
-
EPERM;
}
struct file_operations vmrw_fop
=
{
.owner
=
&__this_module,
.read
=
fop_read,
.write
=
fop_write
};
int
TEXT_INIT module_init() {
DEBUG_LOG(
"vmrw init\n"
);
vmrw_file
=
debugfs_create_file(__this_module.name,
0600
, NULL, NULL, &vmrw_fop);
if
(vmrw_file
=
=
NULL) {
pr_error(
"failed to create vmrw debugfs file\n"
);
}
return
0
;
}
void TEXT_EXIT module_exit() {
DEBUG_LOG(
"vmrw exit\n"
);
debugfs_remove_recursive(vmrw_file);
vmrw_file
=
NULL;
}