pstore/ram: Run without kernel crash dump region
The ram pstore backend has always had the crash dumper frontend enabled unconditionally. However, it was possible to effectively disable it by setting a record_size=0. All the machinery would run (storing dumps to the temporary crash buffer), but 0 bytes would ultimately get stored due to there being no przs allocated for dumps. Commit89d328f637
("pstore/ram: Correctly calculate usable PRZ bytes"), however, assumed that there would always be at least one allocated dprz for calculating the size of the temporary crash buffer. This was, of course, not the case when record_size=0, and would lead to a NULL deref trying to find the dprz buffer size: BUG: unable to handle kernel NULL pointer dereference at (null) ... IP: ramoops_probe+0x285/0x37e (fs/pstore/ram.c:808) cxt->pstore.bufsize = cxt->dprzs[0]->buffer_size; Instead, we need to only enable the frontends based on the success of the prz initialization and only take the needed actions when those zones are available. (This also fixes a possible error in detecting if the ftrace frontend should be enabled.) Reported-and-tested-by: Yaro Slav <yaro330@gmail.com> Fixes:89d328f637
("pstore/ram: Correctly calculate usable PRZ bytes") Cc: stable@vger.kernel.org Signed-off-by: Kees Cook <keescook@chromium.org>
This commit is contained in:
Родитель
a9fb94a99b
Коммит
8880fa32c5
|
@ -608,7 +608,8 @@ int pstore_register(struct pstore_info *psi)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
allocate_buf_for_compression();
|
||||
if (psi->flags & PSTORE_FLAGS_DMESG)
|
||||
allocate_buf_for_compression();
|
||||
|
||||
if (pstore_is_mounted())
|
||||
pstore_get_records(0);
|
||||
|
|
|
@ -799,27 +799,37 @@ static int ramoops_probe(struct platform_device *pdev)
|
|||
goto fail_init_mprz;
|
||||
|
||||
cxt->pstore.data = cxt;
|
||||
/*
|
||||
* Prepare frontend flags based on which areas are initialized.
|
||||
* For ramoops_init_przs() cases, the "max count" variable tells
|
||||
* if there are regions present. For ramoops_init_prz() cases,
|
||||
* the single region size is how to check.
|
||||
*/
|
||||
cxt->pstore.flags = 0;
|
||||
if (cxt->max_dump_cnt)
|
||||
cxt->pstore.flags |= PSTORE_FLAGS_DMESG;
|
||||
if (cxt->console_size)
|
||||
cxt->pstore.flags |= PSTORE_FLAGS_CONSOLE;
|
||||
if (cxt->max_ftrace_cnt)
|
||||
cxt->pstore.flags |= PSTORE_FLAGS_FTRACE;
|
||||
if (cxt->pmsg_size)
|
||||
cxt->pstore.flags |= PSTORE_FLAGS_PMSG;
|
||||
|
||||
/*
|
||||
* Since bufsize is only used for dmesg crash dumps, it
|
||||
* must match the size of the dprz record (after PRZ header
|
||||
* and ECC bytes have been accounted for).
|
||||
*/
|
||||
cxt->pstore.bufsize = cxt->dprzs[0]->buffer_size;
|
||||
cxt->pstore.buf = kzalloc(cxt->pstore.bufsize, GFP_KERNEL);
|
||||
if (!cxt->pstore.buf) {
|
||||
pr_err("cannot allocate pstore crash dump buffer\n");
|
||||
err = -ENOMEM;
|
||||
goto fail_clear;
|
||||
if (cxt->pstore.flags & PSTORE_FLAGS_DMESG) {
|
||||
cxt->pstore.bufsize = cxt->dprzs[0]->buffer_size;
|
||||
cxt->pstore.buf = kzalloc(cxt->pstore.bufsize, GFP_KERNEL);
|
||||
if (!cxt->pstore.buf) {
|
||||
pr_err("cannot allocate pstore crash dump buffer\n");
|
||||
err = -ENOMEM;
|
||||
goto fail_clear;
|
||||
}
|
||||
}
|
||||
|
||||
cxt->pstore.flags = PSTORE_FLAGS_DMESG;
|
||||
if (cxt->console_size)
|
||||
cxt->pstore.flags |= PSTORE_FLAGS_CONSOLE;
|
||||
if (cxt->ftrace_size)
|
||||
cxt->pstore.flags |= PSTORE_FLAGS_FTRACE;
|
||||
if (cxt->pmsg_size)
|
||||
cxt->pstore.flags |= PSTORE_FLAGS_PMSG;
|
||||
|
||||
err = pstore_register(&cxt->pstore);
|
||||
if (err) {
|
||||
pr_err("registering with pstore failed\n");
|
||||
|
|
Загрузка…
Ссылка в новой задаче