What is the role of LIST_POISON1 and LIST_POISON2?
Hi, When I read the code of list_del(), I find LIST_POISON1 and LIST_POISON2: static inline void list_del(struct list_head *entry) { __list_del(entry->prev, entry->next); entry->next = LIST_POISON1; entry->prev = LIST_POISON2; } Why not set entry->next and entry->prev to NULL ? Thank you!
On Fri, 04 Mar 2016 13:02:02 +0800, Navy Cheng said:
Hi,
When I read the code of list_del(), I find LIST_POISON1 and LIST_POISON2:
static inline void list_del(struct list_head *entry) { __list_del(entry->prev, entry->next); entry->next = LIST_POISON1; entry->prev = LIST_POISON2; }
Why not set entry->next and entry->prev to NULL ?
To more easily detect different classes of list corruption, use-after-free, and other programming errors. If ->next and ->prev are NULL, it may be the result of following a bad pointer. If they're equal to POISON 1 and 2, you're almost certainly looking at a once-valid pointer that is a use-after-free situation. It's easy to end up pointing at a zeroed page. The chances of pointing at some random data that happens to be POISON 1/2 is much lower. See the code in lib/list_debug.c
On Fri, Mar 04, 2016 at 02:07:26AM -0500, Valdis.Kletnieks@vt.edu wrote:
On Fri, 04 Mar 2016 13:02:02 +0800, Navy Cheng said:
Hi,
When I read the code of list_del(), I find LIST_POISON1 and LIST_POISON2:
static inline void list_del(struct list_head *entry) { __list_del(entry->prev, entry->next); entry->next = LIST_POISON1; entry->prev = LIST_POISON2; }
Why not set entry->next and entry->prev to NULL ?
To more easily detect different classes of list corruption, use-after-free, and other programming errors. If ->next and ->prev are NULL, it may be the result of following a bad pointer. If they're equal to POISON 1 and 2, you're almost certainly looking at a once-valid pointer that is a use-after-free situation. It's easy to end up pointing at a zeroed page. The chances of pointing at some random data that happens to be POISON 1/2 is much lower.
See the code in lib/list_debug.c
Thank you, but I don't quite understand. Could you give an example or tell me some books and documnets about this?
On Fri, Mar 4, 2016 at 5:01 AM, Navy Cheng <navych@126.com> wrote:
On Fri, Mar 04, 2016 at 02:07:26AM -0500, Valdis.Kletnieks@vt.edu wrote:
On Fri, 04 Mar 2016 13:02:02 +0800, Navy Cheng said:
Hi,
When I read the code of list_del(), I find LIST_POISON1 and LIST_POISON2:
static inline void list_del(struct list_head *entry) { __list_del(entry->prev, entry->next); entry->next = LIST_POISON1; entry->prev = LIST_POISON2; }
Why not set entry->next and entry->prev to NULL ?
To more easily detect different classes of list corruption, use-after-free, and other programming errors. If ->next and ->prev are NULL, it may be the result of following a bad pointer. If they're equal to POISON 1 and 2, you're almost certainly looking at a once-valid pointer that is a use-after-free situation. It's easy to end up pointing at a zeroed page. The chances of pointing at some random data that happens to be POISON 1/2 is much lower.
See the code in lib/list_debug.c
It's like when you find a pointer to 0xdeadbeef you will know that it is some uninitialized value which is more helpful in debugging. If its a NULL, it will be difficult to know if the pointer is uninitialized.
_______________________________________________ Kernelnewbies mailing list Kernelnewbies@kernelnewbies.org http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
participants (3)
-
Navy Cheng -
Valdis.Kletnieks@vt.edu -
Vasu M