Skip to content

Commit 30cee1e

Browse files
maninder42akpm00
authored andcommitted
lib/list_debug.c: add object information in case of invalid object
As of now during link list corruption it prints about cluprit address and its wrong value, but sometime it is not enough to catch the actual issue point. If it prints allocation and free path of that corrupted node, it will be a lot easier to find and fix the issues. Adding the same information when data mismatch is found in link list debug data: [ 14.243055] slab kmalloc-32 start ffff0000cda19320 data offset 32 pointer offset 8 size 32 allocated at add_to_list+0x28/0xb0 [ 14.245259] __kmalloc_cache_noprof+0x1c4/0x358 [ 14.245572] add_to_list+0x28/0xb0 ... [ 14.248632] do_el0_svc_compat+0x1c/0x34 [ 14.249018] el0_svc_compat+0x2c/0x80 [ 14.249244] Free path: [ 14.249410] kfree+0x24c/0x2f0 [ 14.249724] do_force_corruption+0xbc/0x100 ... [ 14.252266] el0_svc_common.constprop.0+0x40/0xe0 [ 14.252540] do_el0_svc_compat+0x1c/0x34 [ 14.252763] el0_svc_compat+0x2c/0x80 [ 14.253071] ------------[ cut here ]------------ [ 14.253303] list_del corruption. next->prev should be ffff0000cda192a8, but was 6b6b6b6b6b6b6b6b. (next=ffff0000cda19348) [ 14.254255] WARNING: CPU: 3 PID: 84 at lib/list_debug.c:65 __list_del_entry_valid_or_report+0x158/0x164 Moved prototype of mem_dump_obj() to bug.h, as mm.h can not be included in bug.h. Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Maninder Singh <[email protected]> Acked-by: Jan Kara <[email protected]> Cc: Al Viro <[email protected]> Cc: Christian Brauner <[email protected]> Cc: Marco Elver <[email protected]> Cc: Rohit Thapliyal <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent 553e775 commit 30cee1e

File tree

5 files changed

+22
-20
lines changed

5 files changed

+22
-20
lines changed

fs/open.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1504,7 +1504,7 @@ static int filp_flush(struct file *filp, fl_owner_t id)
15041504
{
15051505
int retval = 0;
15061506

1507-
if (CHECK_DATA_CORRUPTION(file_count(filp) == 0,
1507+
if (CHECK_DATA_CORRUPTION(file_count(filp) == 0, filp,
15081508
"VFS: Close: file count is 0 (f_op=%ps)",
15091509
filp->f_op)) {
15101510
return 0;

fs/super.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -647,7 +647,7 @@ void generic_shutdown_super(struct super_block *sb)
647647
*/
648648
fscrypt_destroy_keyring(sb);
649649

650-
if (CHECK_DATA_CORRUPTION(!list_empty(&sb->s_inodes),
650+
if (CHECK_DATA_CORRUPTION(!list_empty(&sb->s_inodes), NULL,
651651
"VFS: Busy inodes after unmount of %s (%s)",
652652
sb->s_id, sb->s_type->name)) {
653653
/*

include/linux/bug.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,15 +73,23 @@ static inline void generic_bug_clear_once(void) {}
7373

7474
#endif /* CONFIG_GENERIC_BUG */
7575

76+
#ifdef CONFIG_PRINTK
77+
void mem_dump_obj(void *object);
78+
#else
79+
static inline void mem_dump_obj(void *object) {}
80+
#endif
81+
7682
/*
7783
* Since detected data corruption should stop operation on the affected
7884
* structures. Return value must be checked and sanely acted on by caller.
7985
*/
8086
static inline __must_check bool check_data_corruption(bool v) { return v; }
81-
#define CHECK_DATA_CORRUPTION(condition, fmt, ...) \
87+
#define CHECK_DATA_CORRUPTION(condition, addr, fmt, ...) \
8288
check_data_corruption(({ \
8389
bool corruption = unlikely(condition); \
8490
if (corruption) { \
91+
if (addr) \
92+
mem_dump_obj(addr); \
8593
if (IS_ENABLED(CONFIG_BUG_ON_DATA_CORRUPTION)) { \
8694
pr_err(fmt, ##__VA_ARGS__); \
8795
BUG(); \

include/linux/mm.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4084,12 +4084,6 @@ unsigned long wp_shared_mapping_range(struct address_space *mapping,
40844084

40854085
extern int sysctl_nr_trim_pages;
40864086

4087-
#ifdef CONFIG_PRINTK
4088-
void mem_dump_obj(void *object);
4089-
#else
4090-
static inline void mem_dump_obj(void *object) {}
4091-
#endif
4092-
40934087
#ifdef CONFIG_ANON_VMA_NAME
40944088
int madvise_set_anon_name(struct mm_struct *mm, unsigned long start,
40954089
unsigned long len_in,

lib/list_debug.c

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,17 @@ __list_valid_slowpath
2222
bool __list_add_valid_or_report(struct list_head *new, struct list_head *prev,
2323
struct list_head *next)
2424
{
25-
if (CHECK_DATA_CORRUPTION(prev == NULL,
25+
if (CHECK_DATA_CORRUPTION(prev == NULL, NULL,
2626
"list_add corruption. prev is NULL.\n") ||
27-
CHECK_DATA_CORRUPTION(next == NULL,
27+
CHECK_DATA_CORRUPTION(next == NULL, NULL,
2828
"list_add corruption. next is NULL.\n") ||
29-
CHECK_DATA_CORRUPTION(next->prev != prev,
29+
CHECK_DATA_CORRUPTION(next->prev != prev, next,
3030
"list_add corruption. next->prev should be prev (%px), but was %px. (next=%px).\n",
3131
prev, next->prev, next) ||
32-
CHECK_DATA_CORRUPTION(prev->next != next,
32+
CHECK_DATA_CORRUPTION(prev->next != next, prev,
3333
"list_add corruption. prev->next should be next (%px), but was %px. (prev=%px).\n",
3434
next, prev->next, prev) ||
35-
CHECK_DATA_CORRUPTION(new == prev || new == next,
35+
CHECK_DATA_CORRUPTION(new == prev || new == next, NULL,
3636
"list_add double add: new=%px, prev=%px, next=%px.\n",
3737
new, prev, next))
3838
return false;
@@ -49,20 +49,20 @@ bool __list_del_entry_valid_or_report(struct list_head *entry)
4949
prev = entry->prev;
5050
next = entry->next;
5151

52-
if (CHECK_DATA_CORRUPTION(next == NULL,
52+
if (CHECK_DATA_CORRUPTION(next == NULL, NULL,
5353
"list_del corruption, %px->next is NULL\n", entry) ||
54-
CHECK_DATA_CORRUPTION(prev == NULL,
54+
CHECK_DATA_CORRUPTION(prev == NULL, NULL,
5555
"list_del corruption, %px->prev is NULL\n", entry) ||
56-
CHECK_DATA_CORRUPTION(next == LIST_POISON1,
56+
CHECK_DATA_CORRUPTION(next == LIST_POISON1, next,
5757
"list_del corruption, %px->next is LIST_POISON1 (%px)\n",
5858
entry, LIST_POISON1) ||
59-
CHECK_DATA_CORRUPTION(prev == LIST_POISON2,
59+
CHECK_DATA_CORRUPTION(prev == LIST_POISON2, prev,
6060
"list_del corruption, %px->prev is LIST_POISON2 (%px)\n",
6161
entry, LIST_POISON2) ||
62-
CHECK_DATA_CORRUPTION(prev->next != entry,
62+
CHECK_DATA_CORRUPTION(prev->next != entry, prev,
6363
"list_del corruption. prev->next should be %px, but was %px. (prev=%px)\n",
6464
entry, prev->next, prev) ||
65-
CHECK_DATA_CORRUPTION(next->prev != entry,
65+
CHECK_DATA_CORRUPTION(next->prev != entry, next,
6666
"list_del corruption. next->prev should be %px, but was %px. (next=%px)\n",
6767
entry, next->prev, next))
6868
return false;

0 commit comments

Comments
 (0)