Update several example code for newer kernel

Known issues with current example code:
If you using newer kernel(e.g linux 5.11.x) to compile the example code,
you may meet following error:
1. syscall.c:83:50: error: ‘ksys_close’ undeclared;
2. cryptosk.c:17:24: error: field ‘sg’ has incomplete type
3. cryptosk.c:143:9: error: implicit declaration of function
‘get_random_bytes’
4. error: macro "DECLARE_TASKLET" passed 3 arguments, but takes just 2

Solutions/workaround:
1. In syscall.c, replace #include <linux/syscalls.h> with
#include <linux/fdtable.h> and replace  ksys_close with close_fd
if the kernel version >= 5.11. [1][2]
2. Add #include <linux/scatterlist.h> into cryptosk.c
3. Add #include <linux/random.h> into cryptosk.c
4. In bottomhalf.c and example_tasklet.c, replace DECLARE_TASKLET
with DECLARE_TASKLET_OLD and dispose third argument(0L). [3]

[1] - https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=1572bfdf21d4d50e51941498ffe0b56c2289f783
[2] - https://www.mail-archive.com/meta-arago@arago-project.org//msg11939.html
[3] - https://patchwork.kernel.org/project/kernel-hardening/patch/20200716030847.1564131-3-keescook@chromium.org/
This commit is contained in:
fennecJ 2021-08-23 21:30:43 +08:00
parent bd8342bc14
commit 870b26fa2d
7 changed files with 42 additions and 7 deletions

3
.gitignore vendored
View File

@ -2,6 +2,7 @@
*.o
*.ko
*cmd
*.dwo
*.swp
*.symvers
*.mod
@ -31,4 +32,4 @@ lkmpg.pdf
*.xref
# format checks
expected-format
expected-format

View File

@ -9,7 +9,7 @@ $(PROJ).pdf: lkmpg.tex
html: lkmpg.tex html.cfg
sed $ 's/\t/ /g' lkmpg.tex > lkmpg-for-ht.tex
make4ht --shell-escape --utf8 --format html5 --config html.cfg --output-dir html lkmpg-for-ht.tex
make4ht --shell-escape --utf8 --format html5 --config html.cfg --output-dir html lkmpg-for-ht.tex "fn-in"
ln -sf lkmpg-for-ht.html html/index.html
rm -f lkmpg-for-ht.tex lkmpg-for-ht.xref lkmpg-for-ht.tmp lkmpg-for-ht.html lkmpg-for-ht.css lkmpg-for-ht.4ct lkmpg-for-ht.4tc lkmpg-for-ht.dvi lkmpg-for-ht.lg lkmpg-for-ht.idv lkmpg*.svg lkmpg-for-ht.log lkmpg-for-ht.aux
rm -rf _minted-$(PROJ) _minted-lkmpg-for-ht

View File

@ -14,6 +14,13 @@
#include <linux/kernel.h>
#include <linux/module.h>
/* Macro DECLARE_TASKLET_OLD exists for compatibiity.
* See https://lwn.net/Articles/830964/
*/
#ifndef DECLARE_TASKLET_OLD
#define DECLARE_TASKLET_OLD(arg1, arg2) DECLARE_TASKLET(arg1, arg2, 0L)
#endif
static int button_irqs[] = {-1, -1};
/* Define GPIOs for LEDs.
@ -38,7 +45,7 @@ static void bottomhalf_tasklet_fn(unsigned long data)
pr_info("Bottom half tasklet ends\n");
}
DECLARE_TASKLET(buttontask, bottomhalf_tasklet_fn, 0L);
DECLARE_TASKLET_OLD(buttontask, bottomhalf_tasklet_fn);
/* interrupt function triggered when a button is pressed */
static irqreturn_t button_isr(int irq, void *data)

View File

@ -4,6 +4,8 @@
#include <crypto/internal/skcipher.h>
#include <linux/crypto.h>
#include <linux/module.h>
#include <linux/random.h>
#include <linux/scatterlist.h>
#define SYMMETRIC_KEY_LENGTH 32
#define CIPHER_BLOCK_SIZE 16

View File

@ -6,6 +6,13 @@
#include <linux/kernel.h>
#include <linux/module.h>
/* Macro DECLARE_TASKLET_OLD exists for compatibiity.
* See https://lwn.net/Articles/830964/
*/
#ifndef DECLARE_TASKLET_OLD
#define DECLARE_TASKLET_OLD(arg1, arg2) DECLARE_TASKLET(arg1, arg2, 0L)
#endif
static void tasklet_fn(unsigned long data)
{
pr_info("Example tasklet starts\n");
@ -13,7 +20,7 @@ static void tasklet_fn(unsigned long data)
pr_info("Example tasklet ends\n");
}
DECLARE_TASKLET(mytask, tasklet_fn, 0L);
DECLARE_TASKLET_OLD(mytask, tasklet_fn);
static int example_tasklet_init(void)
{

View File

@ -14,8 +14,8 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h> /* which will have params */
#include <linux/syscalls.h>
#include <linux/unistd.h> /* The list of system calls */
#include <linux/unistd.h> /* The list of system calls */
#include <linux/version.h>
/* For the current (process) structure, we need this to know who the
* current user is.
@ -23,6 +23,15 @@
#include <linux/sched.h>
#include <linux/uaccess.h>
/* The in-kernel calls to the ksys_close() syscall were removed in Linux v5.11+.
*/
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 11, 0))
#include <linux/syscalls.h> /* ksys_close() wrapper for backward compatibility */
#define close_fd ksys_close
#else
#include <linux/fdtable.h> /* For close_fd */
#endif
unsigned long **sys_call_table;
unsigned long original_cr0;
@ -80,7 +89,7 @@ static unsigned long **aquire_sys_call_table(void)
while (offset < ULLONG_MAX) {
sct = (unsigned long **) offset;
if (sct[__NR_close] == (unsigned long *) ksys_close)
if (sct[__NR_close] == (unsigned long *) close_fd)
return sct;
offset += sizeof(void *);

View File

@ -1421,6 +1421,15 @@ Example tasklet starts
Example tasklet init continues...
Example tasklet ends
\end{verbatim}
Although tasklet is easy to use, it comes with several defators, and developers are discussing about getting rid of tasklet in linux kernel.
The tasklet callback runs in atomic context, inside a software interrupt, meaning that it cannot sleep or access user-space data, so not all work can be done in a tasklet handler.
Also, the kernel only allows one instance of any given tasklet to be running at any given time; multiple different tasklet callbacks can run in parallel.
In recent kernels, tasklets can be replaced by workqueues, timers, or threaded interrupts.\footnote{The goal of threaded interrupts is to push more of the work to separate threads, so that the minimum needed for acknowledging an interrupt is reduced, and therefore the time spent handling the interrupt (where it can't handle any other interrupts at the same time) is reduced.
See https://lwn.net/Articles/302043/}
While the removal of tasklets remains a longer-term goal, the current kernel contains more than a hundred uses of tasklets.
Now developers are proceeding with the API changes and the macro \cpp|DECLARE_TASKLET_OLD| exists for compatibiity.
For further information, see \url{https://lwn.net/Articles/830964/}.
\subsection{Work queues}
\label{sec:workqueue}