]>
Commit | Line | Data |
---|---|---|
7a7567a2 GKH |
1 | From 8880fa32c557600f5f624084152668ed3c2ea51e Mon Sep 17 00:00:00 2001 |
2 | From: Kees Cook <keescook@chromium.org> | |
3 | Date: Thu, 30 May 2019 23:37:29 -0700 | |
4 | Subject: pstore/ram: Run without kernel crash dump region | |
5 | ||
6 | From: Kees Cook <keescook@chromium.org> | |
7 | ||
8 | commit 8880fa32c557600f5f624084152668ed3c2ea51e upstream. | |
9 | ||
10 | The ram pstore backend has always had the crash dumper frontend enabled | |
11 | unconditionally. However, it was possible to effectively disable it | |
12 | by setting a record_size=0. All the machinery would run (storing dumps | |
13 | to the temporary crash buffer), but 0 bytes would ultimately get stored | |
14 | due to there being no przs allocated for dumps. Commit 89d328f637b9 | |
15 | ("pstore/ram: Correctly calculate usable PRZ bytes"), however, assumed | |
16 | that there would always be at least one allocated dprz for calculating | |
17 | the size of the temporary crash buffer. This was, of course, not the | |
18 | case when record_size=0, and would lead to a NULL deref trying to find | |
19 | the dprz buffer size: | |
20 | ||
21 | BUG: unable to handle kernel NULL pointer dereference at (null) | |
22 | ... | |
23 | IP: ramoops_probe+0x285/0x37e (fs/pstore/ram.c:808) | |
24 | ||
25 | cxt->pstore.bufsize = cxt->dprzs[0]->buffer_size; | |
26 | ||
27 | Instead, we need to only enable the frontends based on the success of the | |
28 | prz initialization and only take the needed actions when those zones are | |
29 | available. (This also fixes a possible error in detecting if the ftrace | |
30 | frontend should be enabled.) | |
31 | ||
32 | Reported-and-tested-by: Yaro Slav <yaro330@gmail.com> | |
33 | Fixes: 89d328f637b9 ("pstore/ram: Correctly calculate usable PRZ bytes") | |
34 | Cc: stable@vger.kernel.org | |
35 | Signed-off-by: Kees Cook <keescook@chromium.org> | |
36 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
37 | ||
38 | --- | |
39 | fs/pstore/platform.c | 3 ++- | |
40 | fs/pstore/ram.c | 36 +++++++++++++++++++++++------------- | |
41 | 2 files changed, 25 insertions(+), 14 deletions(-) | |
42 | ||
43 | --- a/fs/pstore/platform.c | |
44 | +++ b/fs/pstore/platform.c | |
45 | @@ -608,7 +608,8 @@ int pstore_register(struct pstore_info * | |
46 | return -EINVAL; | |
47 | } | |
48 | ||
49 | - allocate_buf_for_compression(); | |
50 | + if (psi->flags & PSTORE_FLAGS_DMESG) | |
51 | + allocate_buf_for_compression(); | |
52 | ||
53 | if (pstore_is_mounted()) | |
54 | pstore_get_records(0); | |
55 | --- a/fs/pstore/ram.c | |
56 | +++ b/fs/pstore/ram.c | |
57 | @@ -800,26 +800,36 @@ static int ramoops_probe(struct platform | |
58 | ||
59 | cxt->pstore.data = cxt; | |
60 | /* | |
61 | - * Since bufsize is only used for dmesg crash dumps, it | |
62 | - * must match the size of the dprz record (after PRZ header | |
63 | - * and ECC bytes have been accounted for). | |
64 | + * Prepare frontend flags based on which areas are initialized. | |
65 | + * For ramoops_init_przs() cases, the "max count" variable tells | |
66 | + * if there are regions present. For ramoops_init_prz() cases, | |
67 | + * the single region size is how to check. | |
68 | */ | |
69 | - cxt->pstore.bufsize = cxt->dprzs[0]->buffer_size; | |
70 | - cxt->pstore.buf = kzalloc(cxt->pstore.bufsize, GFP_KERNEL); | |
71 | - if (!cxt->pstore.buf) { | |
72 | - pr_err("cannot allocate pstore crash dump buffer\n"); | |
73 | - err = -ENOMEM; | |
74 | - goto fail_clear; | |
75 | - } | |
76 | - | |
77 | - cxt->pstore.flags = PSTORE_FLAGS_DMESG; | |
78 | + cxt->pstore.flags = 0; | |
79 | + if (cxt->max_dump_cnt) | |
80 | + cxt->pstore.flags |= PSTORE_FLAGS_DMESG; | |
81 | if (cxt->console_size) | |
82 | cxt->pstore.flags |= PSTORE_FLAGS_CONSOLE; | |
83 | - if (cxt->ftrace_size) | |
84 | + if (cxt->max_ftrace_cnt) | |
85 | cxt->pstore.flags |= PSTORE_FLAGS_FTRACE; | |
86 | if (cxt->pmsg_size) | |
87 | cxt->pstore.flags |= PSTORE_FLAGS_PMSG; | |
88 | ||
89 | + /* | |
90 | + * Since bufsize is only used for dmesg crash dumps, it | |
91 | + * must match the size of the dprz record (after PRZ header | |
92 | + * and ECC bytes have been accounted for). | |
93 | + */ | |
94 | + if (cxt->pstore.flags & PSTORE_FLAGS_DMESG) { | |
95 | + cxt->pstore.bufsize = cxt->dprzs[0]->buffer_size; | |
96 | + cxt->pstore.buf = kzalloc(cxt->pstore.bufsize, GFP_KERNEL); | |
97 | + if (!cxt->pstore.buf) { | |
98 | + pr_err("cannot allocate pstore crash dump buffer\n"); | |
99 | + err = -ENOMEM; | |
100 | + goto fail_clear; | |
101 | + } | |
102 | + } | |
103 | + | |
104 | err = pstore_register(&cxt->pstore); | |
105 | if (err) { | |
106 | pr_err("registering with pstore failed\n"); |