Commit 059c4a34 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull pstore updates from Kees Cook:
 "A small collection of bug fixes, refactorings, and general
  improvements:

   - Reporting improvements and return path fixes (Guilherme G. Piccoli,
     Wang Yufen, Kees Cook)

   - Clean up kmsg_bytes module parameter usage (Guilherme G. Piccoli)

   - Add Guilherme to pstore MAINTAINERS entry

   - Choose friendlier allocation flags (Qiujun Huang, Stephen Boyd)"

* tag 'pstore-v6.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux:
  pstore: Avoid kcore oops by vmap()ing with VM_IOREMAP
  pstore/ram: Fix error return code in ramoops_probe()
  pstore: Alert on backend write error
  MAINTAINERS: Update pstore maintainers
  pstore/ram: Set freed addresses to NULL
  pstore/ram: Move internal definitions out of kernel-wide include
  pstore/ram: Move pmsg init earlier
  pstore/ram: Consolidate kfree() paths
  efi: pstore: Follow convention for the efi-pstore backend name
  pstore: Inform unregistered backend names as well
  pstore: Expose kmsg_bytes as a module parameter
  pstore: Improve error reporting in case of backend overlap
  pstore/zone: Use GFP_ATOMIC to allocate zone buffer
parents 3a28c2c8 e6b84274
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -16661,10 +16661,10 @@ F: net/psample
PSTORE FILESYSTEM
M:	Kees Cook <keescook@chromium.org>
M:	Anton Vorontsov <anton@enomsg.org>
M:	Colin Cross <ccross@android.com>
M:	Tony Luck <tony.luck@intel.com>
S:	Maintained
R:	Tony Luck <tony.luck@intel.com>
R:	Guilherme G. Piccoli <gpiccoli@igalia.com>
L:	linux-hardening@vger.kernel.org
S:	Supported
T:	git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git for-next/pstore
F:	Documentation/admin-guide/ramoops.rst
F:	Documentation/admin-guide/pstore-blk.rst
+1 −1
Original line number Diff line number Diff line
@@ -207,7 +207,7 @@ static int efi_pstore_erase(struct pstore_record *record)

static struct pstore_info efi_pstore_info = {
	.owner		= THIS_MODULE,
	.name		= "efi",
	.name		= KBUILD_MODNAME,
	.flags		= PSTORE_FLAGS_DMESG,
	.open		= efi_pstore_open,
	.close		= efi_pstore_close,
+20 −5
Original line number Diff line number Diff line
@@ -89,6 +89,11 @@ static char *compress =
module_param(compress, charp, 0444);
MODULE_PARM_DESC(compress, "compression to use");

/* How much of the kernel log to snapshot */
unsigned long kmsg_bytes = CONFIG_PSTORE_DEFAULT_KMSG_BYTES;
module_param(kmsg_bytes, ulong, 0444);
MODULE_PARM_DESC(kmsg_bytes, "amount of kernel log to snapshot (in bytes)");

/* Compression parameters */
static struct crypto_comp *tfm;

@@ -100,9 +105,6 @@ struct pstore_zbackend {
static char *big_oops_buf;
static size_t big_oops_buf_sz;

/* How much of the console log to snapshot */
unsigned long kmsg_bytes = CONFIG_PSTORE_DEFAULT_KMSG_BYTES;

void pstore_set_kmsg_bytes(int bytes)
{
	kmsg_bytes = bytes;
@@ -391,6 +393,7 @@ static void pstore_dump(struct kmsg_dumper *dumper,
	const char	*why;
	unsigned int	part = 1;
	unsigned long	flags = 0;
	int		saved_ret = 0;
	int		ret;

	why = kmsg_dump_reason_str(reason);
@@ -461,12 +464,21 @@ static void pstore_dump(struct kmsg_dumper *dumper,
		if (ret == 0 && reason == KMSG_DUMP_OOPS) {
			pstore_new_entry = 1;
			pstore_timer_kick();
		} else {
			/* Preserve only the first non-zero returned value. */
			if (!saved_ret)
				saved_ret = ret;
		}

		total += record.size;
		part++;
	}
	spin_unlock_irqrestore(&psinfo->buf_lock, flags);

	if (saved_ret) {
		pr_err_once("backend (%s) writing error (%d)\n", psinfo->name,
			    saved_ret);
	}
}

static struct kmsg_dumper pstore_dumper = {
@@ -562,8 +574,9 @@ static int pstore_write_user_compat(struct pstore_record *record,
int pstore_register(struct pstore_info *psi)
{
	if (backend && strcmp(backend, psi->name)) {
		pr_warn("ignoring unexpected backend '%s'\n", psi->name);
		return -EPERM;
		pr_warn("backend '%s' already in use: ignoring '%s'\n",
			backend, psi->name);
		return -EBUSY;
	}

	/* Sanity check flags. */
@@ -662,6 +675,8 @@ void pstore_unregister(struct pstore_info *psi)
	psinfo = NULL;
	kfree(backend);
	backend = NULL;

	pr_info("Unregistered %s as persistent store backend\n", psi->name);
	mutex_unlock(&psinfo_lock);
}
EXPORT_SYMBOL_GPL(pstore_unregister);
+25 −19
Original line number Diff line number Diff line
@@ -18,10 +18,11 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/compiler.h>
#include <linux/pstore_ram.h>
#include <linux/of.h>
#include <linux/of_address.h>

#include "internal.h"
#include "ram_internal.h"

#define RAMOOPS_KERNMSG_HDR "===="
#define MIN_MEM_SIZE 4096UL
@@ -451,20 +452,28 @@ static void ramoops_free_przs(struct ramoops_context *cxt)
{
	int i;

	/* Free pmsg PRZ */
	persistent_ram_free(&cxt->mprz);

	/* Free console PRZ */
	persistent_ram_free(&cxt->cprz);

	/* Free dump PRZs */
	if (cxt->dprzs) {
		for (i = 0; i < cxt->max_dump_cnt; i++)
			persistent_ram_free(cxt->dprzs[i]);
			persistent_ram_free(&cxt->dprzs[i]);

		kfree(cxt->dprzs);
		cxt->dprzs = NULL;
		cxt->max_dump_cnt = 0;
	}

	/* Free ftrace PRZs */
	if (cxt->fprzs) {
		for (i = 0; i < cxt->max_ftrace_cnt; i++)
			persistent_ram_free(cxt->fprzs[i]);
			persistent_ram_free(&cxt->fprzs[i]);
		kfree(cxt->fprzs);
		cxt->fprzs = NULL;
		cxt->max_ftrace_cnt = 0;
	}
}
@@ -548,9 +557,10 @@ static int ramoops_init_przs(const char *name,

			while (i > 0) {
				i--;
				persistent_ram_free(prz_ar[i]);
				persistent_ram_free(&prz_ar[i]);
			}
			kfree(prz_ar);
			prz_ar = NULL;
			goto fail;
		}
		*paddr += zone_sz;
@@ -735,6 +745,7 @@ static int ramoops_probe(struct platform_device *pdev)
	/* Make sure we didn't get bogus platform data pointer. */
	if (!pdata) {
		pr_err("NULL platform data\n");
		err = -EINVAL;
		goto fail_out;
	}

@@ -742,6 +753,7 @@ static int ramoops_probe(struct platform_device *pdev)
			!pdata->ftrace_size && !pdata->pmsg_size)) {
		pr_err("The memory size and the record/console size must be "
			"non-zero\n");
		err = -EINVAL;
		goto fail_out;
	}

@@ -772,12 +784,17 @@ static int ramoops_probe(struct platform_device *pdev)
				dump_mem_sz, cxt->record_size,
				&cxt->max_dump_cnt, 0, 0);
	if (err)
		goto fail_out;
		goto fail_init;

	err = ramoops_init_prz("console", dev, cxt, &cxt->cprz, &paddr,
			       cxt->console_size, 0);
	if (err)
		goto fail_init_cprz;
		goto fail_init;

	err = ramoops_init_prz("pmsg", dev, cxt, &cxt->mprz, &paddr,
				cxt->pmsg_size, 0);
	if (err)
		goto fail_init;

	cxt->max_ftrace_cnt = (cxt->flags & RAMOOPS_FLAG_FTRACE_PER_CPU)
				? nr_cpu_ids
@@ -788,12 +805,7 @@ static int ramoops_probe(struct platform_device *pdev)
				(cxt->flags & RAMOOPS_FLAG_FTRACE_PER_CPU)
					? PRZ_FLAG_NO_LOCK : 0);
	if (err)
		goto fail_init_fprz;

	err = ramoops_init_prz("pmsg", dev, cxt, &cxt->mprz, &paddr,
				cxt->pmsg_size, 0);
	if (err)
		goto fail_init_mprz;
		goto fail_init;

	cxt->pstore.data = cxt;
	/*
@@ -857,11 +869,7 @@ static int ramoops_probe(struct platform_device *pdev)
	kfree(cxt->pstore.buf);
fail_clear:
	cxt->pstore.bufsize = 0;
	persistent_ram_free(cxt->mprz);
fail_init_mprz:
fail_init_fprz:
	persistent_ram_free(cxt->cprz);
fail_init_cprz:
fail_init:
	ramoops_free_przs(cxt);
fail_out:
	return err;
@@ -876,8 +884,6 @@ static int ramoops_remove(struct platform_device *pdev)
	kfree(cxt->pstore.buf);
	cxt->pstore.bufsize = 0;

	persistent_ram_free(cxt->mprz);
	persistent_ram_free(cxt->cprz);
	ramoops_free_przs(cxt);

	return 0;
+16 −4
Original line number Diff line number Diff line
@@ -13,13 +13,14 @@
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/memblock.h>
#include <linux/pstore_ram.h>
#include <linux/rslib.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/vmalloc.h>
#include <asm/page.h>

#include "ram_internal.h"

/**
 * struct persistent_ram_buffer - persistent circular RAM buffer
 *
@@ -439,7 +440,11 @@ static void *persistent_ram_vmap(phys_addr_t start, size_t size,
		phys_addr_t addr = page_start + i * PAGE_SIZE;
		pages[i] = pfn_to_page(addr >> PAGE_SHIFT);
	}
	vaddr = vmap(pages, page_count, VM_MAP, prot);
	/*
	 * VM_IOREMAP used here to bypass this region during vread()
	 * and kmap_atomic() (i.e. kcore) to avoid __va() failures.
	 */
	vaddr = vmap(pages, page_count, VM_MAP | VM_IOREMAP, prot);
	kfree(pages);

	/*
@@ -543,8 +548,14 @@ static int persistent_ram_post_init(struct persistent_ram_zone *prz, u32 sig,
	return 0;
}

void persistent_ram_free(struct persistent_ram_zone *prz)
void persistent_ram_free(struct persistent_ram_zone **_prz)
{
	struct persistent_ram_zone *prz;

	if (!_prz)
		return;

	prz = *_prz;
	if (!prz)
		return;

@@ -568,6 +579,7 @@ void persistent_ram_free(struct persistent_ram_zone *prz)
	persistent_ram_free_old(prz);
	kfree(prz->label);
	kfree(prz);
	*_prz = NULL;
}

struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size,
@@ -604,6 +616,6 @@ struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size,

	return prz;
err:
	persistent_ram_free(prz);
	persistent_ram_free(&prz);
	return ERR_PTR(ret);
}
Loading