diff options
author | 2020-06-30 11:32:02 +0200 | |
---|---|---|
committer | 2020-06-30 11:32:02 +0200 | |
commit | 77346a704c913268a2dad68d59523fd85dc74088 (patch) | |
tree | 62c66bcb163b0db42a1fd0a397a6973e52f4ddce /mm/debug.c | |
parent | iommu/qcom: add optional 'tbu' clock for TLB invalidate (diff) | |
parent | Linux 5.8-rc3 (diff) | |
download | wireguard-linux-77346a704c913268a2dad68d59523fd85dc74088.tar.xz wireguard-linux-77346a704c913268a2dad68d59523fd85dc74088.zip |
Merge tag 'v5.8-rc3' into arm/qcom
Linux 5.8-rc3
Diffstat (limited to 'mm/debug.c')
-rw-r--r-- | mm/debug.c | 56 |
1 files changed, 50 insertions, 6 deletions
diff --git a/mm/debug.c b/mm/debug.c index 2189357f0987..4f376514744d 100644 --- a/mm/debug.c +++ b/mm/debug.c @@ -110,13 +110,57 @@ void __dump_page(struct page *page, const char *reason) else if (PageAnon(page)) type = "anon "; else if (mapping) { - if (mapping->host && mapping->host->i_dentry.first) { - struct dentry *dentry; - dentry = container_of(mapping->host->i_dentry.first, struct dentry, d_u.d_alias); - pr_warn("%ps name:\"%pd\"\n", mapping->a_ops, dentry); - } else - pr_warn("%ps\n", mapping->a_ops); + const struct inode *host; + const struct address_space_operations *a_ops; + const struct hlist_node *dentry_first; + const struct dentry *dentry_ptr; + struct dentry dentry; + + /* + * mapping can be invalid pointer and we don't want to crash + * accessing it, so probe everything depending on it carefully + */ + if (copy_from_kernel_nofault(&host, &mapping->host, + sizeof(struct inode *)) || + copy_from_kernel_nofault(&a_ops, &mapping->a_ops, + sizeof(struct address_space_operations *))) { + pr_warn("failed to read mapping->host or a_ops, mapping not a valid kernel address?\n"); + goto out_mapping; + } + + if (!host) { + pr_warn("mapping->a_ops:%ps\n", a_ops); + goto out_mapping; + } + + if (copy_from_kernel_nofault(&dentry_first, + &host->i_dentry.first, sizeof(struct hlist_node *))) { + pr_warn("mapping->a_ops:%ps with invalid mapping->host inode address %px\n", + a_ops, host); + goto out_mapping; + } + + if (!dentry_first) { + pr_warn("mapping->a_ops:%ps\n", a_ops); + goto out_mapping; + } + + dentry_ptr = container_of(dentry_first, struct dentry, d_u.d_alias); + if (copy_from_kernel_nofault(&dentry, dentry_ptr, + sizeof(struct dentry))) { + pr_warn("mapping->aops:%ps with invalid mapping->host->i_dentry.first %px\n", + a_ops, dentry_ptr); + } else { + /* + * if dentry is corrupted, the %pd handler may still + * crash, but it's unlikely that we reach here with a + * corrupted struct page + */ + pr_warn("mapping->aops:%ps dentry name:\"%pd\"\n", + a_ops, &dentry); + } } +out_mapping: BUILD_BUG_ON(ARRAY_SIZE(pageflag_names) != __NR_PAGEFLAGS + 1); pr_warn("%sflags: %#lx(%pGp)%s\n", type, page->flags, &page->flags, |