list_debug.c 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. /*
  2. * Copyright 2006, Red Hat, Inc., Dave Jones
  3. * Released under the General Public License (GPL).
  4. *
  5. * This file contains the linked list validation for DEBUG_LIST.
  6. */
  7. #include <linux/export.h>
  8. #include <linux/list.h>
  9. #include <linux/bug.h>
  10. #include <linux/kernel.h>
  11. #include <linux/rculist.h>
  12. /*
  13. * Check that the data structures for the list manipulations are reasonably
  14. * valid. Failures here indicate memory corruption (and possibly an exploit
  15. * attempt).
  16. */
  17. bool __list_add_valid(struct list_head *new, struct list_head *prev,
  18. struct list_head *next)
  19. {
  20. if (unlikely(next->prev != prev)) {
  21. WARN(1, "list_add corruption. next->prev should be prev (%p), but was %p. (next=%p).\n",
  22. prev, next->prev, next);
  23. return false;
  24. }
  25. if (unlikely(prev->next != next)) {
  26. WARN(1, "list_add corruption. prev->next should be next (%p), but was %p. (prev=%p).\n",
  27. next, prev->next, prev);
  28. return false;
  29. }
  30. if (unlikely(new == prev || new == next)) {
  31. WARN(1, "list_add double add: new=%p, prev=%p, next=%p.\n",
  32. new, prev, next);
  33. return false;
  34. }
  35. return true;
  36. }
  37. EXPORT_SYMBOL(__list_add_valid);
  38. bool __list_del_entry_valid(struct list_head *entry)
  39. {
  40. struct list_head *prev, *next;
  41. prev = entry->prev;
  42. next = entry->next;
  43. if (unlikely(next == LIST_POISON1)) {
  44. WARN(1, "list_del corruption, %p->next is LIST_POISON1 (%p)\n",
  45. entry, LIST_POISON1);
  46. return false;
  47. }
  48. if (unlikely(prev == LIST_POISON2)) {
  49. WARN(1, "list_del corruption, %p->prev is LIST_POISON2 (%p)\n",
  50. entry, LIST_POISON2);
  51. return false;
  52. }
  53. if (unlikely(prev->next != entry)) {
  54. WARN(1, "list_del corruption. prev->next should be %p, but was %p\n",
  55. entry, prev->next);
  56. return false;
  57. }
  58. if (unlikely(next->prev != entry)) {
  59. WARN(1, "list_del corruption. next->prev should be %p, but was %p\n",
  60. entry, next->prev);
  61. return false;
  62. }
  63. return true;
  64. }
  65. EXPORT_SYMBOL(__list_del_entry_valid);