summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorKees Cook <keescook@chromium.org>2016-08-17 17:42:10 -0400
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>2016-10-31 16:01:57 -0400
commit0cd340dcb05c4a43742fe156f36737bb2a321bfd (patch)
tree1e45dac53b3a090f28e2e11a5328f0f5a8b4d6a0 /lib
parent54acd4397d7e7a725c94101180cd9f38ef701acc (diff)
list: Split list_del() debug checking into separate function
Similar to the list_add() debug consolidation, this commit consolidates the debug checking performed during CONFIG_DEBUG_LIST into a new __list_del_entry_valid() function, and stops list updates when corruption is found. Refactored from same hardening in PaX and Grsecurity. Signed-off-by: Kees Cook <keescook@chromium.org> Acked-by: Steven Rostedt <rostedt@goodmis.org> Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Acked-by: Rik van Riel <riel@redhat.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/list_debug.c53
1 files changed, 23 insertions, 30 deletions
diff --git a/lib/list_debug.c b/lib/list_debug.c
index d0b89b9d0736..276565fca2a6 100644
--- a/lib/list_debug.c
+++ b/lib/list_debug.c
@@ -39,41 +39,34 @@ bool __list_add_valid(struct list_head *new, struct list_head *prev,
39} 39}
40EXPORT_SYMBOL(__list_add_valid); 40EXPORT_SYMBOL(__list_add_valid);
41 41
42void __list_del_entry(struct list_head *entry) 42bool __list_del_entry_valid(struct list_head *entry)
43{ 43{
44 struct list_head *prev, *next; 44 struct list_head *prev, *next;
45 45
46 prev = entry->prev; 46 prev = entry->prev;
47 next = entry->next; 47 next = entry->next;
48 48
49 if (WARN(next == LIST_POISON1, 49 if (unlikely(next == LIST_POISON1)) {
50 "list_del corruption, %p->next is LIST_POISON1 (%p)\n", 50 WARN(1, "list_del corruption, %p->next is LIST_POISON1 (%p)\n",
51 entry, LIST_POISON1) || 51 entry, LIST_POISON1);
52 WARN(prev == LIST_POISON2, 52 return false;
53 "list_del corruption, %p->prev is LIST_POISON2 (%p)\n", 53 }
54 entry, LIST_POISON2) || 54 if (unlikely(prev == LIST_POISON2)) {
55 WARN(prev->next != entry, 55 WARN(1, "list_del corruption, %p->prev is LIST_POISON2 (%p)\n",
56 "list_del corruption. prev->next should be %p, " 56 entry, LIST_POISON2);
57 "but was %p\n", entry, prev->next) || 57 return false;
58 WARN(next->prev != entry, 58 }
59 "list_del corruption. next->prev should be %p, " 59 if (unlikely(prev->next != entry)) {
60 "but was %p\n", entry, next->prev)) 60 WARN(1, "list_del corruption. prev->next should be %p, but was %p\n",
61 return; 61 entry, prev->next);
62 62 return false;
63 __list_del(prev, next); 63 }
64} 64 if (unlikely(next->prev != entry)) {
65EXPORT_SYMBOL(__list_del_entry); 65 WARN(1, "list_del corruption. next->prev should be %p, but was %p\n",
66 entry, next->prev);
67 return false;
68 }
69 return true;
66 70
67/**
68 * list_del - deletes entry from list.
69 * @entry: the element to delete from the list.
70 * Note: list_empty on entry does not return true after this, the entry is
71 * in an undefined state.
72 */
73void list_del(struct list_head *entry)
74{
75 __list_del_entry(entry);
76 entry->next = LIST_POISON1;
77 entry->prev = LIST_POISON2;
78} 71}
79EXPORT_SYMBOL(list_del); 72EXPORT_SYMBOL(__list_del_entry_valid);