The procfile_write prints the content what user writes into. However,
when the content size is greater than or equal to PROCFS_MAX_SIZE,
procfile_write will print nothing, because the index for appending the
tail NULL character will be modulo to 0, which is an off-by-one error.
This fixes the problem by changing the upper bound of procfs_buffer_size
to (PROCFS_MAX_SIZE - 1), leaving one byte for NULL character. After
the change, we can discard the modulo because the range of
procfs_buffer_size is already between 0 and (PROCFS_MAX_SIZE - 1).
There is a subtle bug that if the atomic flag changes
between the time it was checked and the second time
it was checked, sleep.c would potentially block a
process that had specified O_NONBLOCK. This fixes
the bug by using atomic_cmpxchg instead of atomic_read.
For x86 architecture, the system call table cannot be used to invoke
a system call after commit 1e3ad78 since v6.9. This commit has been
backported to long term stable kernels, like v5.15.154+, v6.1.85+,
v6.6.26+ and v6.8.5+[1]. In this case, thanks to Kprobes, a hook can be
used instead on the system call entry to intercept the system call.
[1] https://stackoverflow.com/a/78607015
Co-authored-by: Hao Dong <hao.dong.work@outlook.com>
Add sudo to commands in Chapter 8 for example module interaction.
The "myvariables" in the module are set with 0660 permissions
via __ATTR(), preventing direct user access.
Options to fix this:
1. Instruct users to use 'sudo' to read/write files.
2. Relax the permission settings to 0666.
This commit adopts the sudo method to maintain security constraints.
7.4 The seq_file is missing the behavior that occurs when it
directly returns NULL after the start step.
Also, in the flowchart, the first decision where `return is NULL`
is `Yes` points to nothing, which is not defined in ISO 5807.
ISO 5807 section 10.3.1.2 states logic path of a decision,
"Each exit from a symbol be accompanied by the appropriate
condition values to show the logic path which it represents,
so that the conditions and the associated references are identified."
The behavior of pointing to nothing does not have associated
references and does not indicate the relation of this logic path.
Refs:
1. The Liunx Kernel Module Programming Guide
7.4 Manage /proc file with seq_file
2. ISO-5807-1985
When raw_copy_to_user() failed in vinput_read(), the function would set
'count' to -EFAULT and then subtract EFAULT from '*offset'. However,
modifying '*offset' on raw_copy_to_user() failure was incorrect. Fix
this behavior by changing count = -EFAULT to return -EFAULT.
When kzalloc fails to allocate memory and returns NULL, it leads to a
NULL pointer dereference error later on. Add a check for the return
value of kzalloc. When kzalloc fails to allocate memory, it prints an
error message and returns ERR_PTR(-ENOMEM).
The last parameter of request_threaded_irq must be a globally unique
cookie[1]. Usually this would be the device struct received by probe().
Since we are not using driver model, pass the gpio structs instead.
[1] https://docs.kernel.org/core-api/genericirq.html
Aquiring a spinlock makes the holder enter atomic context. Extra
attention is needed in atomic context. In particular, functions
that may sleep must not be used. Add this detail to the spinlock
section.
The past content in the crypto section lacks informative descriptions,
and there should be a proper procedure to demonstrate how Linux
cryptography works. Due to poor maintenance, let's drop the section.
The SA_xxx flags has been removed for years. Nowadays the kernel uses
the IRQF_xxx flags to specify IRQ behaviors. Adjust the descriptions
in the book accordingly.
The code 'case -EINPROGRESS || -EBUSY: ' is the same as
'case -115 || -16 :' at compiler time, as both error code are
implemented with macro like '#define EBUSY 16'.
The code above is essentially the same as 'case 1:'. In C, there is no
real boolean value. Boolean-like value will be converted to 1 or 0.
It does not matter too much if the '-EINPROGRESS || -EBUSY' is
calculated at build time or at runtime. In both case, it will compare
the 'rc' with 1 in the switch expression. It will not compare the
'rc' with any real error code number. When the code is really '-EBUSY',
the execution will fallback to the default branch.
And in practice, most of the compilers will do this simple compile-time
static calculation, and generate code like
static int test_skcipher_result(struct skcipher_def *sk, int rc)
{
switch (rc) {
case 0:
break;
case 1:
rc = wait_for_completion_interruptible(&sk->result.completion);
/* code removed for conciseness */
break;
default:
pr_info("skcipher encrypt returned with %d result %d\n", rc,
sk->result.err);
break;
}
init_completion(&sk->result.completion);
return rc;
}
A lot of distributions are emitting warnings when using egrep and fgrep
since these are deprecated.
Update occurrences of egrep to 'grep -E' keeping the same functionality
and making the code more portable without emitting warnings.