Skip to content

Commit

Permalink
pstore/ram: Run without kernel crash dump region
Browse files Browse the repository at this point in the history
commit 8880fa3 upstream.

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. Commit 89d328f
("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: 89d328f ("pstore/ram: Correctly calculate usable PRZ bytes")
Cc: stable@vger.kernel.org
Signed-off-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
kees authored and gregkh committed Jun 11, 2019
1 parent aa73a3b commit f4d0227
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 14 deletions.
3 changes: 2 additions & 1 deletion fs/pstore/platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -583,7 +583,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);
Expand Down
36 changes: 23 additions & 13 deletions fs/pstore/ram.c
Original file line number Diff line number Diff line change
Expand Up @@ -803,26 +803,36 @@ static int ramoops_probe(struct platform_device *pdev)

cxt->pstore.data = cxt;
/*
* 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).
* 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.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;
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->ftrace_size)
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).
*/
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;
}
}

err = pstore_register(&cxt->pstore);
if (err) {
pr_err("registering with pstore failed\n");
Expand Down

0 comments on commit f4d0227

Please sign in to comment.