You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Since sys_open is deprecated and some architectures don't support it.
We switch the implementation to sys_openat.
Moreover, in some architectures like x86-64, the prototype of syscall,
for example, openat(), might have been changed to struct pt_regs [1]
but we cannot promise that so support the two types
(sys_openat and pt_regs).
Also, to prevent other untraced tasks print out the information, add
the uid checking in our_sys_openat().
[1] https://lore.kernel.org/lkml/[email protected]/Close#159
Copy file name to clipboardExpand all lines: lkmpg.tex
+10-10Lines changed: 10 additions & 10 deletions
Original file line number
Diff line number
Diff line change
@@ -1529,24 +1529,24 @@ \section{System Calls}
1529
1529
1530
1530
The source code here is an example of such a kernel module.
1531
1531
We want to ``spy'' on a certain user, and to \cpp|pr_info()| a message whenever that user opens a file.
1532
-
Towards this end, we replace the system call to open a file with our own function, called \cpp|our_sys_open|.
1532
+
Towards this end, we replace the system call to open a file with our own function, called \cpp|our_sys_openat|.
1533
1533
This function checks the uid (user's id) of the current process, and if it is equal to the uid we spy on, it calls \cpp|pr_info()| to display the name of the file to be opened.
1534
-
Then, either way, it calls the original \cpp|open()| function with the same parameters, to actually open the file.
1534
+
Then, either way, it calls the original \cpp|openat()| function with the same parameters, to actually open the file.
1535
1535
1536
1536
The \cpp|init_module| function replaces the appropriate location in \cpp|sys_call_table| and keeps the original pointer in a variable.
1537
1537
The \cpp|cleanup_module| function uses that variable to restore everything back to normal.
1538
1538
This approach is dangerous, because of the possibility of two kernel modules changing the same system call.
1539
-
Imagine we have two kernel modules, A and B. A's open system call will be \cpp|A_open| and B's will be \cpp|B_open|.
1540
-
Now, when A is inserted into the kernel, the system call is replaced with \cpp|A_open|, which will call the original \cpp|sys_open| when it is done.
1541
-
Next, B is inserted into the kernel, which replaces the system call with \cpp|B_open|, which will call what it thinks is the original system call, \cpp|A_open|, when it's done.
1539
+
Imagine we have two kernel modules, A and B. A's openat system call will be \cpp|A_openat| and B's will be \cpp|B_openat|.
1540
+
Now, when A is inserted into the kernel, the system call is replaced with \cpp|A_openat|, which will call the original \cpp|sys_openat| when it is done.
1541
+
Next, B is inserted into the kernel, which replaces the system call with \cpp|B_openat|, which will call what it thinks is the original system call, \cpp|A_openat|, when it's done.
1542
1542
1543
-
Now, if B is removed first, everything will be well --- it will simply restore the system call to \cpp|A_open|, which calls the original.
1543
+
Now, if B is removed first, everything will be well --- it will simply restore the system call to \cpp|A_openat|, which calls the original.
1544
1544
However, if A is removed and then B is removed, the system will crash.
1545
-
A's removal will restore the system call to the original, \cpp|sys_open|, cutting B out of the loop.
1546
-
Then, when B is removed, it will restore the system call to what it thinks is the original, \cpp|A_open|, which is no longer in memory.
1545
+
A's removal will restore the system call to the original, \cpp|sys_openat|, cutting B out of the loop.
1546
+
Then, when B is removed, it will restore the system call to what it thinks is the original, \cpp|A_openat|, which is no longer in memory.
1547
1547
At first glance, it appears we could solve this particular problem by checking if the system call is equal to our open function and if so not changing it at all (so that B won't change the system call when it is removed), but that will cause an even worse problem.
1548
-
When A is removed, it sees that the system call was changed to \cpp|B_open| so that it is no longer pointing to \cpp|A_open|, so it will not restore it to \cpp|sys_open| before it is removed from memory.
1549
-
Unfortunately, \cpp|B_open| will still try to call \cpp|A_open| which is no longer there, so that even without removing B the system would crash.
1548
+
When A is removed, it sees that the system call was changed to \cpp|B_openat| so that it is no longer pointing to \cpp|A_openat|, so it will not restore it to \cpp|sys_openat| before it is removed from memory.
1549
+
Unfortunately, \cpp|B_openat| will still try to call \cpp|A_openat| which is no longer there, so that even without removing B the system would crash.
1550
1550
1551
1551
Note that all the related problems make syscall stealing unfeasible for production use.
1552
1552
In order to keep people from doing potential harmful things \cpp|sys_call_table| is no longer exported.
0 commit comments