Skip to content

Commit 3b9ecd5

Browse files
aviraxp5ec1cffYlarod
authored
Dev (#2886)
Signed-off-by: Wang Han <[email protected]> Co-authored-by: 5ec1cff <[email protected]> Co-authored-by: 5ec1cff <[email protected]> Co-authored-by: Ylarod <[email protected]>
1 parent 8d66807 commit 3b9ecd5

File tree

13 files changed

+491
-114
lines changed

13 files changed

+491
-114
lines changed

kernel/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ kernelsu-objs += feature.o
1010
kernelsu-objs += ksud.o
1111
kernelsu-objs += embed_ksud.o
1212
kernelsu-objs += seccomp_cache.o
13+
kernelsu-objs += file_wrapper.o
1314

1415
kernelsu-objs += selinux/selinux.o
1516
kernelsu-objs += selinux/sepolicy.o

kernel/file_wrapper.c

Lines changed: 347 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,347 @@
1+
#include <linux/export.h>
2+
#include <linux/anon_inodes.h>
3+
#include <linux/capability.h>
4+
#include <linux/cred.h>
5+
#include <linux/err.h>
6+
#include <linux/file.h>
7+
#include <linux/fs.h>
8+
#include <linux/seq_file.h>
9+
#include <linux/slab.h>
10+
#include <linux/uaccess.h>
11+
#include <linux/version.h>
12+
13+
#include "allowlist.h"
14+
#include "klog.h" // IWYU pragma: keep
15+
#include "ksu.h"
16+
#include "ksud.h"
17+
#include "manager.h"
18+
#include "selinux/selinux.h"
19+
#include "core_hook.h"
20+
#include "objsec.h"
21+
22+
#include "file_wrapper.h"
23+
24+
static loff_t ksu_wrapper_llseek(struct file *fp, loff_t off, int flags) {
25+
struct ksu_file_wrapper* data = fp->private_data;
26+
struct file* orig = data->orig;
27+
return orig->f_op->llseek(data->orig, off, flags);
28+
}
29+
30+
static ssize_t ksu_wrapper_read(struct file *fp, char __user *ptr, size_t sz, loff_t *off) {
31+
struct ksu_file_wrapper* data = fp->private_data;
32+
struct file* orig = data->orig;
33+
return orig->f_op->read(orig, ptr, sz, off);
34+
}
35+
36+
static ssize_t ksu_wrapper_write(struct file *fp, const char __user *ptr, size_t sz, loff_t *off) {
37+
struct ksu_file_wrapper* data = fp->private_data;
38+
struct file* orig = data->orig;
39+
return orig->f_op->write(orig, ptr, sz, off);
40+
}
41+
42+
static ssize_t ksu_wrapper_read_iter(struct kiocb *iocb, struct iov_iter *iovi) {
43+
struct ksu_file_wrapper* data = iocb->ki_filp->private_data;
44+
struct file* orig = data->orig;
45+
iocb->ki_filp = orig;
46+
return orig->f_op->read_iter(iocb, iovi);
47+
}
48+
49+
static ssize_t ksu_wrapper_write_iter(struct kiocb *iocb, struct iov_iter *iovi) {
50+
struct ksu_file_wrapper* data = iocb->ki_filp->private_data;
51+
struct file* orig = data->orig;
52+
iocb->ki_filp = orig;
53+
return orig->f_op->write_iter(iocb, iovi);
54+
}
55+
56+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0)
57+
static int ksu_wrapper_iopoll(struct kiocb *kiocb, struct io_comp_batch* icb, unsigned int v) {
58+
struct ksu_file_wrapper* data = kiocb->ki_filp->private_data;
59+
struct file* orig = data->orig;
60+
kiocb->ki_filp = orig;
61+
return orig->f_op->iopoll(kiocb, icb, v);
62+
}
63+
#else
64+
static int ksu_wrapper_iopoll(struct kiocb *kiocb, bool spin) {
65+
struct ksu_file_wrapper* data = kiocb->ki_filp->private_data;
66+
struct file* orig = data->orig;
67+
kiocb->ki_filp = orig;
68+
return orig->f_op->iopoll(kiocb, spin);
69+
}
70+
#endif
71+
72+
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 6, 0)
73+
static int ksu_wrapper_iterate (struct file *fp, struct dir_context *dc) {
74+
struct ksu_file_wrapper* data = fp->private_data;
75+
struct file* orig = data->orig;
76+
return orig->f_op->iterate(orig, dc);
77+
}
78+
#endif
79+
80+
static int ksu_wrapper_iterate_shared(struct file *fp, struct dir_context *dc) {
81+
struct ksu_file_wrapper* data = fp->private_data;
82+
struct file* orig = data->orig;
83+
return orig->f_op->iterate_shared(orig, dc);
84+
}
85+
86+
static __poll_t ksu_wrapper_poll(struct file *fp, struct poll_table_struct *pts) {
87+
struct ksu_file_wrapper* data = fp->private_data;
88+
struct file* orig = data->orig;
89+
return orig->f_op->poll(orig, pts);
90+
}
91+
92+
static long ksu_wrapper_unlocked_ioctl(struct file *fp, unsigned int cmd, unsigned long arg) {
93+
struct ksu_file_wrapper* data = fp->private_data;
94+
struct file* orig = data->orig;
95+
return orig->f_op->unlocked_ioctl(orig, cmd, arg);
96+
}
97+
98+
static long ksu_wrapper_compat_ioctl(struct file *fp, unsigned int cmd, unsigned long arg) {
99+
struct ksu_file_wrapper* data = fp->private_data;
100+
struct file* orig = data->orig;
101+
return orig->f_op->compat_ioctl(orig, cmd, arg);
102+
}
103+
104+
static int ksu_wrapper_mmap(struct file *fp, struct vm_area_struct * vma) {
105+
struct ksu_file_wrapper* data = fp->private_data;
106+
struct file* orig = data->orig;
107+
return orig->f_op->mmap(orig, vma);
108+
}
109+
110+
// static unsigned long mmap_supported_flags {}
111+
112+
static int ksu_wrapper_open(struct inode *ino, struct file *fp) {
113+
struct ksu_file_wrapper* data = fp->private_data;
114+
struct file* orig = data->orig;
115+
struct inode *orig_ino = file_inode(orig);
116+
return orig->f_op->open(orig_ino, orig);
117+
}
118+
119+
static int ksu_wrapper_flush(struct file *fp, fl_owner_t id) {
120+
struct ksu_file_wrapper* data = fp->private_data;
121+
struct file* orig = data->orig;
122+
return orig->f_op->flush(orig, id);
123+
}
124+
125+
126+
static int ksu_wrapper_fsync(struct file *fp, loff_t off1, loff_t off2, int datasync) {
127+
struct ksu_file_wrapper* data = fp->private_data;
128+
struct file* orig = data->orig;
129+
return orig->f_op->fsync(orig, off1, off2, datasync);
130+
}
131+
132+
static int ksu_wrapper_fasync(int arg, struct file *fp, int arg2) {
133+
struct ksu_file_wrapper* data = fp->private_data;
134+
struct file* orig = data->orig;
135+
return orig->f_op->fasync(arg, orig, arg2);
136+
}
137+
138+
static int ksu_wrapper_lock(struct file *fp, int arg1, struct file_lock *fl) {
139+
struct ksu_file_wrapper* data = fp->private_data;
140+
struct file* orig = data->orig;
141+
return orig->f_op->lock(orig, arg1, fl);
142+
}
143+
144+
145+
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 6, 0)
146+
static ssize_t ksu_wrapper_sendpage(struct file *fp, struct page *pg, int arg1, size_t sz, loff_t *off, int arg2) {
147+
struct ksu_file_wrapper* data = fp->private_data;
148+
struct file* orig = data->orig;
149+
if (orig->f_op->sendpage) {
150+
return orig->f_op->sendpage(orig, pg, arg1, sz, off, arg2);
151+
}
152+
return -EINVAL;
153+
}
154+
#endif
155+
156+
static unsigned long ksu_wrapper_get_unmapped_area(struct file *fp, unsigned long arg1, unsigned long arg2, unsigned long arg3, unsigned long arg4) {
157+
struct ksu_file_wrapper* data = fp->private_data;
158+
struct file* orig = data->orig;
159+
if (orig->f_op->get_unmapped_area) {
160+
return orig->f_op->get_unmapped_area(orig, arg1, arg2, arg3, arg4);
161+
}
162+
return -EINVAL;
163+
}
164+
165+
// static int ksu_wrapper_check_flags(int arg) {}
166+
167+
static int ksu_wrapper_flock(struct file *fp, int arg1, struct file_lock *fl) {
168+
struct ksu_file_wrapper* data = fp->private_data;
169+
struct file* orig = data->orig;
170+
if (orig->f_op->flock) {
171+
return orig->f_op->flock(orig, arg1, fl);
172+
}
173+
return -EINVAL;
174+
}
175+
176+
static ssize_t ksu_wrapper_splice_write(struct pipe_inode_info * pii, struct file *fp, loff_t *off, size_t sz, unsigned int arg1) {
177+
struct ksu_file_wrapper* data = fp->private_data;
178+
struct file* orig = data->orig;
179+
if (orig->f_op->splice_write) {
180+
return orig->f_op->splice_write(pii, orig, off, sz, arg1);
181+
}
182+
return -EINVAL;
183+
}
184+
185+
static ssize_t ksu_wrapper_splice_read(struct file *fp, loff_t *off, struct pipe_inode_info *pii, size_t sz, unsigned int arg1) {
186+
struct ksu_file_wrapper* data = fp->private_data;
187+
struct file* orig = data->orig;
188+
if (orig->f_op->splice_read) {
189+
return orig->f_op->splice_read(orig, off, pii, sz, arg1);
190+
}
191+
return -EINVAL;
192+
}
193+
194+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 6, 0)
195+
void ksu_wrapper_splice_eof(struct file *fp) {
196+
struct ksu_file_wrapper* data = fp->private_data;
197+
struct file* orig = data->orig;
198+
if (orig->f_op->splice_eof) {
199+
return orig->f_op->splice_eof(orig);
200+
}
201+
}
202+
#endif
203+
204+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 12, 0)
205+
static int ksu_wrapper_setlease(struct file *fp, int arg1, struct file_lease **fl, void **p) {
206+
struct ksu_file_wrapper* data = fp->private_data;
207+
struct file* orig = data->orig;
208+
if (orig->f_op->setlease) {
209+
return orig->f_op->setlease(orig, arg1, fl, p);
210+
}
211+
return -EINVAL;
212+
}
213+
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(6, 6, 0)
214+
static int ksu_wrapper_setlease(struct file *fp, int arg1, struct file_lock **fl, void **p) {
215+
struct ksu_file_wrapper* data = fp->private_data;
216+
struct file* orig = data->orig;
217+
if (orig->f_op->setlease) {
218+
return orig->f_op->setlease(orig, arg1, fl, p);
219+
}
220+
return -EINVAL;
221+
}
222+
#else
223+
static int ksu_wrapper_setlease(struct file *fp, long arg1, struct file_lock **fl, void **p) {
224+
struct ksu_file_wrapper* data = fp->private_data;
225+
struct file* orig = data->orig;
226+
if (orig->f_op->setlease) {
227+
return orig->f_op->setlease(orig, arg1, fl, p);
228+
}
229+
return -EINVAL;
230+
}
231+
#endif
232+
233+
static long ksu_wrapper_fallocate(struct file *fp, int mode, loff_t offset, loff_t len) {
234+
struct ksu_file_wrapper* data = fp->private_data;
235+
struct file* orig = data->orig;
236+
if (orig->f_op->fallocate) {
237+
return orig->f_op->fallocate(orig, mode, offset, len);
238+
}
239+
return -EINVAL;
240+
}
241+
242+
static void ksu_wrapper_show_fdinfo(struct seq_file *m, struct file *f) {
243+
struct ksu_file_wrapper* data = m->file->private_data;
244+
struct file* orig = data->orig;
245+
if (orig->f_op->show_fdinfo) {
246+
orig->f_op->show_fdinfo(m, orig);
247+
}
248+
}
249+
250+
static ssize_t ksu_wrapper_copy_file_range(struct file *f1, loff_t off1, struct file *f2,
251+
loff_t off2, size_t sz, unsigned int flags) {
252+
// TODO: determine which file to use
253+
struct ksu_file_wrapper* data = f1->private_data;
254+
struct file* orig = data->orig;
255+
if (orig->f_op->copy_file_range) {
256+
return orig->f_op->copy_file_range(orig, off1, f2, off2, sz, flags);
257+
}
258+
return -EINVAL;
259+
}
260+
261+
static loff_t ksu_wrapper_remap_file_range(struct file *file_in, loff_t pos_in,
262+
struct file *file_out, loff_t pos_out,
263+
loff_t len, unsigned int remap_flags) {
264+
// TODO: determine which file to use
265+
struct ksu_file_wrapper* data = file_in->private_data;
266+
struct file* orig = data->orig;
267+
if (orig->f_op->remap_file_range) {
268+
return orig->f_op->remap_file_range(orig, pos_in, file_out, pos_out, len, remap_flags);
269+
}
270+
return -EINVAL;
271+
}
272+
273+
static int ksu_wrapper_fadvise(struct file *fp, loff_t off1, loff_t off2, int flags) {
274+
struct ksu_file_wrapper* data = fp->private_data;
275+
struct file* orig = data->orig;
276+
if (orig->f_op->fadvise) {
277+
return orig->f_op->fadvise(orig, off1, off2, flags);
278+
}
279+
return -EINVAL;
280+
}
281+
282+
static int ksu_wrapper_release(struct inode *inode, struct file *filp) {
283+
ksu_delete_file_wrapper(filp->private_data);
284+
return 0;
285+
}
286+
287+
struct ksu_file_wrapper* ksu_create_file_wrapper(struct file* fp) {
288+
struct ksu_file_wrapper* p = kcalloc(sizeof(struct ksu_file_wrapper), 1, GFP_KERNEL);
289+
if (!p) {
290+
return NULL;
291+
}
292+
293+
get_file(fp);
294+
295+
p->orig = fp;
296+
p->ops.owner = THIS_MODULE;
297+
p->ops.llseek = fp->f_op->llseek ? ksu_wrapper_llseek : NULL;
298+
p->ops.read = fp->f_op->read ? ksu_wrapper_read : NULL;
299+
p->ops.write = fp->f_op->write ? ksu_wrapper_write : NULL;
300+
p->ops.read_iter = fp->f_op->read_iter ? ksu_wrapper_read_iter : NULL;
301+
p->ops.write_iter = fp->f_op->write_iter ? ksu_wrapper_write_iter : NULL;
302+
p->ops.iopoll = fp->f_op->iopoll ? ksu_wrapper_iopoll : NULL;
303+
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 6, 0)
304+
p->ops.iterate = fp->f_op->iterate ? ksu_wrapper_iterate : NULL;
305+
#endif
306+
p->ops.iterate_shared = fp->f_op->iterate_shared ? ksu_wrapper_iterate_shared : NULL;
307+
p->ops.poll = fp->f_op->poll ? ksu_wrapper_poll : NULL;
308+
p->ops.unlocked_ioctl = fp->f_op->unlocked_ioctl ? ksu_wrapper_unlocked_ioctl : NULL;
309+
p->ops.compat_ioctl = fp->f_op->compat_ioctl ? ksu_wrapper_compat_ioctl : NULL;
310+
p->ops.mmap = fp->f_op->mmap ? ksu_wrapper_mmap : NULL;
311+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 12, 0)
312+
p->ops.fop_flags = fp->f_op->fop_flags;
313+
#else
314+
p->ops.mmap_supported_flags = fp->f_op->mmap_supported_flags;
315+
#endif
316+
p->ops.open = fp->f_op->open ? ksu_wrapper_open : NULL;
317+
p->ops.flush = fp->f_op->flush ? ksu_wrapper_flush : NULL;
318+
p->ops.release = ksu_wrapper_release;
319+
p->ops.fsync = fp->f_op->fsync ? ksu_wrapper_fsync : NULL;
320+
p->ops.fasync = fp->f_op->fasync ? ksu_wrapper_fasync : NULL;
321+
p->ops.lock = fp->f_op->lock ? ksu_wrapper_lock : NULL;
322+
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 6, 0)
323+
p->ops.sendpage = fp->f_op->sendpage ? ksu_wrapper_sendpage : NULL;
324+
#endif
325+
p->ops.get_unmapped_area = fp->f_op->get_unmapped_area ? ksu_wrapper_get_unmapped_area : NULL;
326+
p->ops.check_flags = fp->f_op->check_flags;
327+
p->ops.flock = fp->f_op->flock ? ksu_wrapper_flock : NULL;
328+
p->ops.splice_write = fp->f_op->splice_write ? ksu_wrapper_splice_write : NULL;
329+
p->ops.splice_read = fp->f_op->splice_read ? ksu_wrapper_splice_read : NULL;
330+
p->ops.setlease = fp->f_op->setlease ? ksu_wrapper_setlease : NULL;
331+
p->ops.fallocate = fp->f_op->fallocate ? ksu_wrapper_fallocate : NULL;
332+
p->ops.show_fdinfo = fp->f_op->show_fdinfo ? ksu_wrapper_show_fdinfo : NULL;
333+
p->ops.copy_file_range = fp->f_op->copy_file_range ? ksu_wrapper_copy_file_range : NULL;
334+
p->ops.remap_file_range = fp->f_op->remap_file_range ? ksu_wrapper_remap_file_range : NULL;
335+
p->ops.fadvise = fp->f_op->fadvise ? ksu_wrapper_fadvise : NULL;
336+
337+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 6, 0)
338+
p->ops.splice_eof = fp->f_op->splice_eof ? ksu_wrapper_splice_eof : NULL;
339+
#endif
340+
341+
return p;
342+
}
343+
344+
void ksu_delete_file_wrapper(struct ksu_file_wrapper* data) {
345+
fput((struct file*) data->orig);
346+
kfree(data);
347+
}

kernel/file_wrapper.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#ifndef KSU_FILE_WRAPPER_H
2+
#define KSU_FILE_WRAPPER_H
3+
4+
#include <linux/file.h>
5+
#include <linux/fs.h>
6+
7+
struct ksu_file_wrapper {
8+
struct file* orig;
9+
struct file_operations ops;
10+
};
11+
12+
struct ksu_file_wrapper* ksu_create_file_wrapper(struct file* fp);
13+
void ksu_delete_file_wrapper(struct ksu_file_wrapper* data);
14+
#endif // KSU_FILE_WRAPPER_H

kernel/ksu.h

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,6 @@
55
#include <linux/workqueue.h>
66

77
#define KERNEL_SU_VERSION KSU_VERSION
8-
#define KERNEL_SU_OPTION 0xDEADBEEF
9-
10-
#define CMD_GRANT_ROOT 0
11-
#define CMD_BECOME_MANAGER 1
12-
#define CMD_GET_VERSION 2
13-
#define CMD_ALLOW_SU 3
14-
#define CMD_DENY_SU 4
15-
#define CMD_GET_ALLOW_LIST 5
16-
#define CMD_GET_DENY_LIST 6
17-
#define CMD_REPORT_EVENT 7
18-
#define CMD_SET_SEPOLICY 8
19-
#define CMD_CHECK_SAFEMODE 9
20-
#define CMD_GET_APP_PROFILE 10
21-
#define CMD_SET_APP_PROFILE 11
22-
#define CMD_UID_GRANTED_ROOT 12
23-
#define CMD_UID_SHOULD_UMOUNT 13
24-
#define CMD_IS_SU_ENABLED 14
25-
#define CMD_ENABLE_SU 15
26-
#define CMD_GET_MANAGER_UID 16
278

289
#define EVENT_POST_FS_DATA 1
2910
#define EVENT_BOOT_COMPLETED 2

0 commit comments

Comments
 (0)