📜 ⬆️ ⬇️

How to avoid null pointer dereferencing, using the example of a single patch in the Linux kernel

The idea is as follows. In order to avoid dereferencing the null pointer, it is necessary that there is no null pointer. Your co. 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 corrected, but differently.

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 efficient, sometimes cumbersome.

First option

My decision was different, but why actually wait until the buffer is free, to erase it right away? Let's leave it alone, a small buffer of 512 bytes of weather will not do. Remove all other buffers that are not currently in use, and leave the last one. This will make it much easier to synchronize the two threads of the kernel; you just won't have to think about it. And the data that will remain in the buffer, in any case, can be, because arrive there by interrupt, and even if we freed the last buffer, at the same moment, by interrupt, it is possible to allocate a new buffer and write new data there. Thus, we obtain an effective and simpler solution than a head-on solution. I had to remove the first patch and add my own, which made the patch much more than it should have been.
')
Second option
The initial version.
--- diff --git a/drivers/tty/tty_buffer.cb/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 good 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 the development of the Linux kernel
Is it good to patch holes with the first available method or badly? It seems to me that it is bad, the process of making changes to the core looks like some kind of race, who managed to make changes, and the consequences, then we will understand. It seems to me that there are too many such fixes in the kernel, which makes the code even more confusing and not so simple.

Source: https://habr.com/ru/post/254097/


All Articles