
Avoiding dereferencing a null pointer using one fix in the Linux kernel as an example
The idea is as follows. So that there is no dereferencing of the null pointer, it is necessary that there is no null pointer. Your KO. It so happened that once I fixed a small problem in the Linux kernel, but it was not the current kernel branch, but stable. In the current, at that time, this problem was also fixed, but in a different way.
The problem was simple and very common. One thread frees the buffer while the second continues to use it. Race condition. How to avoid this situation? You can force one thread to wait while the second uses the buffer, the solution is simple, but not effective, sometimes cumbersome.
First option
My decision was different, but why, in fact, wait until the buffer is free to erase it right away? Let's leave it alone, a buffer of small 512 bytes of weather will not do. Delete all other buffers that are not currently in use, and leave the last one. This will greatly facilitate the process of synchronizing two kernel threads, you just won’t have to think about it. And the data that remains in the buffer, in any case, can be, because arrive there by interruption, and even if we freed the last buffer, at the same time, by interruption, it is possible to allocate a new buffer and write new data there. Thus, we obtain an effective and simpler solution than a solution in the forehead. I had to remove the first fix and add my own, which made the fix much more than it should have been.
Second option
The problem was simple and very common. One thread frees the buffer while the second continues to use it. Race condition. How to avoid this situation? You can force one thread to wait while the second uses the buffer, the solution is simple, but not effective, sometimes cumbersome.
First option
My decision was different, but why, in fact, wait until the buffer is free to erase it right away? Let's leave it alone, a buffer of small 512 bytes of weather will not do. Delete all other buffers that are not currently in use, and leave the last one. This will greatly facilitate the process of synchronizing two kernel threads, you just won’t have to think about it. And the data that remains in the buffer, in any case, can be, because arrive there by interruption, and even if we freed the last buffer, at the same time, by interruption, it is possible to allocate a new buffer and write new data there. Thus, we obtain an effective and simpler solution than a solution in the forehead. I had to remove the first fix and add my own, which made the fix much more than it should have been.
Second option
The original version.
To remove the “if”, it would be nice to allocate the first buffer when opening the device file, and not when the first data appears, but this would complicate the “patch”.
---
diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c
index 6c9b7cd..4f02f9c 100644
--- a/drivers/tty/tty_buffer.c
+++ b/drivers/tty/tty_buffer.c
@@ -114,11 +114,14 @@ static void __tty_buffer_flush(struct tty_struct *tty)
{
struct tty_buffer *thead;
- while ((thead = tty->buf.head) != NULL) {
- tty->buf.head = thead->next;
- tty_buffer_free(tty, thead);
+ if (tty->buf.head == NULL)
+ return;
+ while ((thead = tty->buf.head->next) != NULL) {
+ tty_buffer_free(tty, tty->buf.head);
+ tty->buf.head = thead;
}
- tty->buf.tail = NULL;
+ WARN_ON(tty->buf.head != tty->buf.tail);
+ tty->buf.head->read = tty->buf.head->commit;
}
/**
To remove the “if”, it would be nice to allocate the first buffer when opening the device file, and not when the first data appears, but this would complicate the “patch”.
My opinion on Linux kernel development
Is it good to patch holes with the first method or bad? It seems to me that it’s bad, the process of making changes to the kernel itself looks like some kind of race, who managed to make changes and the consequences, then we'll figure it out. It seems to me that there are too many such corrections in the kernel, which further confuses the code that is not so simple.