From 1614e92179abe91283fc397c37f6244fe0019072 Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Wed, 8 May 2019 08:48:31 -0700 Subject: pstore/ram: Improve backward compatibility with older Chromebooks When you try to run an upstream kernel on an old ARM-based Chromebook you'll find that console-ramoops doesn't work. Old ARM-based Chromebooks, before ("ramoops: support upstream {console,pmsg,ftrace}-size properties") used to create a "ramoops" node at the top level that looked like: / { ramoops { compatible = "ramoops"; reg = <...>; record-size = <...>; dump-oops; }; }; ...and these Chromebooks assumed that the downstream kernel would make console_size / pmsg_size match the record size. The above ramoops node was added by the firmware so it's not easy to make any changes. Let's match the expected behavior, but only for those using the old backward-compatible way of working where ramoops is right under the root node. NOTE: if there are some out-of-tree devices that had ramoops at the top level, left everything but the record size as 0, and somehow doesn't want this behavior, we can try to add more conditions here. Signed-off-by: Douglas Anderson Signed-off-by: Kees Cook --- fs/pstore/ram.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c index 5b7709894415..2bb3468fc93a 100644 --- a/fs/pstore/ram.c +++ b/fs/pstore/ram.c @@ -655,6 +655,7 @@ static int ramoops_parse_dt(struct platform_device *pdev, struct ramoops_platform_data *pdata) { struct device_node *of_node = pdev->dev.of_node; + struct device_node *parent_node; struct resource *res; u32 value; int ret; @@ -689,6 +690,26 @@ static int ramoops_parse_dt(struct platform_device *pdev, #undef parse_size + /* + * Some old Chromebooks relied on the kernel setting the + * console_size and pmsg_size to the record size since that's + * what the downstream kernel did. These same Chromebooks had + * "ramoops" straight under the root node which isn't + * according to the current upstream bindings (though it was + * arguably acceptable under a prior version of the bindings). + * Let's make those old Chromebooks work by detecting that + * we're not a child of "reserved-memory" and mimicking the + * expected behavior. + */ + parent_node = of_get_parent(of_node); + if (!of_node_name_eq(parent_node, "reserved-memory") && + !pdata->console_size && !pdata->ftrace_size && + !pdata->pmsg_size && !pdata->ecc_info.ecc_size) { + pdata->console_size = pdata->record_size; + pdata->pmsg_size = pdata->record_size; + } + of_node_put(parent_node); + return 0; } -- cgit From fa1af7583e8012c471ee45d5b1703123fe45a9f3 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 12 Jun 2019 17:20:33 +0200 Subject: pstore: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. Cc: Kees Cook Cc: Anton Vorontsov Cc: Colin Cross Cc: Tony Luck Cc: linux-kernel@vger.kernel.org Signed-off-by: Greg Kroah-Hartman Signed-off-by: Kees Cook --- fs/pstore/ftrace.c | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/fs/pstore/ftrace.c b/fs/pstore/ftrace.c index 8e0a17ce3180..bfbfc2698070 100644 --- a/fs/pstore/ftrace.c +++ b/fs/pstore/ftrace.c @@ -112,27 +112,13 @@ static struct dentry *pstore_ftrace_dir; void pstore_register_ftrace(void) { - struct dentry *file; - if (!psinfo->write) return; pstore_ftrace_dir = debugfs_create_dir("pstore", NULL); - if (!pstore_ftrace_dir) { - pr_err("%s: unable to create pstore directory\n", __func__); - return; - } - - file = debugfs_create_file("record_ftrace", 0600, pstore_ftrace_dir, - NULL, &pstore_knob_fops); - if (!file) { - pr_err("%s: unable to create record_ftrace file\n", __func__); - goto err_file; - } - return; -err_file: - debugfs_remove(pstore_ftrace_dir); + debugfs_create_file("record_ftrace", 0600, pstore_ftrace_dir, NULL, + &pstore_knob_fops); } void pstore_unregister_ftrace(void) -- cgit From 4c6d80e1144bdf48cae6b602ae30d41f3e5c76a9 Mon Sep 17 00:00:00 2001 From: Norbert Manthey Date: Fri, 5 Jul 2019 15:06:00 +0200 Subject: pstore: Fix double-free in pstore_mkfile() failure path The pstore_mkfile() function is passed a pointer to a struct pstore_record. On success it consumes this 'record' pointer and references it from the created inode. On failure, however, it may or may not free the record. There are even two different code paths which return -ENOMEM -- one of which does and the other doesn't free the record. Make the behaviour deterministic by never consuming and freeing the record when returning failure, allowing the caller to do the cleanup consistently. Signed-off-by: Norbert Manthey Link: https://lore.kernel.org/r/1562331960-26198-1-git-send-email-nmanthey@amazon.de Fixes: 83f70f0769ddd ("pstore: Do not duplicate record metadata") Fixes: 1dfff7dd67d1a ("pstore: Pass record contents instead of copying") Cc: stable@vger.kernel.org [kees: also move "private" allocation location, rename inode cleanup label] Signed-off-by: Kees Cook --- fs/pstore/inode.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/fs/pstore/inode.c b/fs/pstore/inode.c index 89a80b568a17..7fbe8f058220 100644 --- a/fs/pstore/inode.c +++ b/fs/pstore/inode.c @@ -318,22 +318,21 @@ int pstore_mkfile(struct dentry *root, struct pstore_record *record) goto fail; inode->i_mode = S_IFREG | 0444; inode->i_fop = &pstore_file_operations; - private = kzalloc(sizeof(*private), GFP_KERNEL); - if (!private) - goto fail_alloc; - private->record = record; - scnprintf(name, sizeof(name), "%s-%s-%llu%s", pstore_type_to_name(record->type), record->psi->name, record->id, record->compressed ? ".enc.z" : ""); + private = kzalloc(sizeof(*private), GFP_KERNEL); + if (!private) + goto fail_inode; + dentry = d_alloc_name(root, name); if (!dentry) goto fail_private; + private->record = record; inode->i_size = private->total_size = size; - inode->i_private = private; if (record->time.tv_sec) @@ -349,7 +348,7 @@ int pstore_mkfile(struct dentry *root, struct pstore_record *record) fail_private: free_pstore_private(private); -fail_alloc: +fail_inode: iput(inode); fail: -- cgit