Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0fb3ca44 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull pstore updates from Kees Cook:

 - Fix bug in module unloading

 - Switch to always using spinlock over cmpxchg

 - Explicitly define pstore backend's supported modes

 - Remove bounce buffer from pmsg

 - Switch to using memcpy_to/fromio()

 - Error checking improvements

* tag 'pstore-v4.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux:
  ramoops: move spin_lock_init after kmalloc error checking
  pstore/ram: Use memcpy_fromio() to save old buffer
  pstore/ram: Use memcpy_toio instead of memcpy
  pstore/pmsg: drop bounce buffer
  pstore/ram: Set pstore flags dynamically
  pstore: Split pstore fragile flags
  pstore/core: drop cmpxchg based updates
  pstore/ramoops: fixup driver removal
parents 3940ee36 f88baf68
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -938,7 +938,7 @@ static int erst_clearer(enum pstore_type_id type, u64 id, int count,
static struct pstore_info erst_info = {
	.owner		= THIS_MODULE,
	.name		= "erst",
	.flags		= PSTORE_FLAGS_FRAGILE,
	.flags		= PSTORE_FLAGS_DMESG,
	.open		= erst_open_pstore,
	.close		= erst_close_pstore,
	.read		= erst_reader,
+1 −1
Original line number Diff line number Diff line
@@ -380,7 +380,7 @@ static int efi_pstore_erase(enum pstore_type_id type, u64 id, int count,
static struct pstore_info efi_pstore_info = {
	.owner		= THIS_MODULE,
	.name		= "efi",
	.flags		= PSTORE_FLAGS_FRAGILE,
	.flags		= PSTORE_FLAGS_DMESG,
	.open		= efi_pstore_open,
	.close		= efi_pstore_close,
	.read		= efi_pstore_read,
+46 −7
Original line number Diff line number Diff line
@@ -623,6 +623,40 @@ static int pstore_write_compat(enum pstore_type_id type,
			     size, psi);
}

static int pstore_write_buf_user_compat(enum pstore_type_id type,
			       enum kmsg_dump_reason reason,
			       u64 *id, unsigned int part,
			       const char __user *buf,
			       bool compressed, size_t size,
			       struct pstore_info *psi)
{
	unsigned long flags = 0;
	size_t i, bufsize = size;
	long ret = 0;

	if (unlikely(!access_ok(VERIFY_READ, buf, size)))
		return -EFAULT;
	if (bufsize > psinfo->bufsize)
		bufsize = psinfo->bufsize;
	spin_lock_irqsave(&psinfo->buf_lock, flags);
	for (i = 0; i < size; ) {
		size_t c = min(size - i, bufsize);

		ret = __copy_from_user(psinfo->buf, buf + i, c);
		if (unlikely(ret != 0)) {
			ret = -EFAULT;
			break;
		}
		ret = psi->write_buf(type, reason, id, part, psinfo->buf,
				     compressed, c, psi);
		if (unlikely(ret < 0))
			break;
		i += c;
	}
	spin_unlock_irqrestore(&psinfo->buf_lock, flags);
	return unlikely(ret < 0) ? ret : size;
}

/*
 * platform specific persistent storage driver registers with
 * us here. If pstore is already mounted, call the platform
@@ -645,6 +679,8 @@ int pstore_register(struct pstore_info *psi)

	if (!psi->write)
		psi->write = pstore_write_compat;
	if (!psi->write_buf_user)
		psi->write_buf_user = pstore_write_buf_user_compat;
	psinfo = psi;
	mutex_init(&psinfo->read_mutex);
	spin_unlock(&pstore_lock);
@@ -659,13 +695,14 @@ int pstore_register(struct pstore_info *psi)
	if (pstore_is_mounted())
		pstore_get_records(0);

	if (psi->flags & PSTORE_FLAGS_DMESG)
		pstore_register_kmsg();

	if ((psi->flags & PSTORE_FLAGS_FRAGILE) == 0) {
	if (psi->flags & PSTORE_FLAGS_CONSOLE)
		pstore_register_console();
	if (psi->flags & PSTORE_FLAGS_FTRACE)
		pstore_register_ftrace();
	if (psi->flags & PSTORE_FLAGS_PMSG)
		pstore_register_pmsg();
	}

	if (pstore_update_ms >= 0) {
		pstore_timer.expires = jiffies +
@@ -689,11 +726,13 @@ EXPORT_SYMBOL_GPL(pstore_register);

void pstore_unregister(struct pstore_info *psi)
{
	if ((psi->flags & PSTORE_FLAGS_FRAGILE) == 0) {
	if (psi->flags & PSTORE_FLAGS_PMSG)
		pstore_unregister_pmsg();
	if (psi->flags & PSTORE_FLAGS_FTRACE)
		pstore_unregister_ftrace();
	if (psi->flags & PSTORE_FLAGS_CONSOLE)
		pstore_unregister_console();
	}
	if (psi->flags & PSTORE_FLAGS_DMESG)
		pstore_unregister_kmsg();

	free_buf_for_compression();
+6 −29
Original line number Diff line number Diff line
@@ -19,48 +19,25 @@
#include "internal.h"

static DEFINE_MUTEX(pmsg_lock);
#define PMSG_MAX_BOUNCE_BUFFER_SIZE (2*PAGE_SIZE)

static ssize_t write_pmsg(struct file *file, const char __user *buf,
			  size_t count, loff_t *ppos)
{
	size_t i, buffer_size;
	char *buffer;
	u64 id;
	int ret;

	if (!count)
		return 0;

	/* check outside lock, page in any data. write_buf_user also checks */
	if (!access_ok(VERIFY_READ, buf, count))
		return -EFAULT;

	buffer_size = count;
	if (buffer_size > PMSG_MAX_BOUNCE_BUFFER_SIZE)
		buffer_size = PMSG_MAX_BOUNCE_BUFFER_SIZE;
	buffer = vmalloc(buffer_size);
	if (!buffer)
		return -ENOMEM;

	mutex_lock(&pmsg_lock);
	for (i = 0; i < count; ) {
		size_t c = min(count - i, buffer_size);
		u64 id;
		long ret;

		ret = __copy_from_user(buffer, buf + i, c);
		if (unlikely(ret != 0)) {
			mutex_unlock(&pmsg_lock);
			vfree(buffer);
			return -EFAULT;
		}
		psinfo->write_buf(PSTORE_TYPE_PMSG, 0, &id, 0, buffer, 0, c,
	ret = psinfo->write_buf_user(PSTORE_TYPE_PMSG, 0, &id, 0, buf, 0, count,
				     psinfo);

		i += c;
	}

	mutex_unlock(&pmsg_lock);
	vfree(buffer);
	return count;
	return ret ? ret : count;
}

static const struct file_operations pmsg_fops = {
+40 −6
Original line number Diff line number Diff line
@@ -331,6 +331,24 @@ static int notrace ramoops_pstore_write_buf(enum pstore_type_id type,
	return 0;
}

static int notrace ramoops_pstore_write_buf_user(enum pstore_type_id type,
						 enum kmsg_dump_reason reason,
						 u64 *id, unsigned int part,
						 const char __user *buf,
						 bool compressed, size_t size,
						 struct pstore_info *psi)
{
	if (type == PSTORE_TYPE_PMSG) {
		struct ramoops_context *cxt = psi->data;

		if (!cxt->mprz)
			return -ENOMEM;
		return persistent_ram_write_user(cxt->mprz, buf, size);
	}

	return -EINVAL;
}

static int ramoops_pstore_erase(enum pstore_type_id type, u64 id, int count,
				struct timespec time, struct pstore_info *psi)
{
@@ -369,6 +387,7 @@ static struct ramoops_context oops_cxt = {
		.open	= ramoops_pstore_open,
		.read	= ramoops_pstore_read,
		.write_buf	= ramoops_pstore_write_buf,
		.write_buf_user	= ramoops_pstore_write_buf_user,
		.erase	= ramoops_pstore_erase,
	},
};
@@ -377,13 +396,14 @@ static void ramoops_free_przs(struct ramoops_context *cxt)
{
	int i;

	cxt->max_dump_cnt = 0;
	if (!cxt->przs)
		return;

	for (i = 0; !IS_ERR_OR_NULL(cxt->przs[i]); i++)
	for (i = 0; i < cxt->max_dump_cnt; i++)
		persistent_ram_free(cxt->przs[i]);

	kfree(cxt->przs);
	cxt->max_dump_cnt = 0;
}

static int ramoops_init_przs(struct device *dev, struct ramoops_context *cxt,
@@ -408,7 +428,7 @@ static int ramoops_init_przs(struct device *dev, struct ramoops_context *cxt,
			     GFP_KERNEL);
	if (!cxt->przs) {
		dev_err(dev, "failed to initialize a prz array for dumps\n");
		goto fail_prz;
		goto fail_mem;
	}

	for (i = 0; i < cxt->max_dump_cnt; i++) {
@@ -419,6 +439,11 @@ static int ramoops_init_przs(struct device *dev, struct ramoops_context *cxt,
			err = PTR_ERR(cxt->przs[i]);
			dev_err(dev, "failed to request mem region (0x%zx@0x%llx): %d\n",
				cxt->record_size, (unsigned long long)*paddr, err);

			while (i > 0) {
				i--;
				persistent_ram_free(cxt->przs[i]);
			}
			goto fail_prz;
		}
		*paddr += cxt->record_size;
@@ -426,7 +451,9 @@ static int ramoops_init_przs(struct device *dev, struct ramoops_context *cxt,

	return 0;
fail_prz:
	ramoops_free_przs(cxt);
	kfree(cxt->przs);
fail_mem:
	cxt->max_dump_cnt = 0;
	return err;
}

@@ -608,12 +635,20 @@ static int ramoops_probe(struct platform_device *pdev)
		cxt->pstore.bufsize = 1024; /* LOG_LINE_MAX */
	cxt->pstore.bufsize = max(cxt->record_size, cxt->pstore.bufsize);
	cxt->pstore.buf = kmalloc(cxt->pstore.bufsize, GFP_KERNEL);
	spin_lock_init(&cxt->pstore.buf_lock);
	if (!cxt->pstore.buf) {
		pr_err("cannot allocate pstore buffer\n");
		err = -ENOMEM;
		goto fail_clear;
	}
	spin_lock_init(&cxt->pstore.buf_lock);

	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) {
@@ -659,7 +694,6 @@ static int ramoops_remove(struct platform_device *pdev)
	struct ramoops_context *cxt = &oops_cxt;

	pstore_unregister(&cxt->pstore);
	cxt->max_dump_cnt = 0;

	kfree(cxt->pstore.buf);
	cxt->pstore.bufsize = 0;
Loading