Skip to content

Commit 0fb3ca4

Browse files
committed
Merge tag 'pstore-v4.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux
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
2 parents 3940ee3 + f88baf6 commit 0fb3ca4

File tree

8 files changed

+162
-96
lines changed

8 files changed

+162
-96
lines changed

drivers/acpi/apei/erst.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -938,7 +938,7 @@ static int erst_clearer(enum pstore_type_id type, u64 id, int count,
938938
static struct pstore_info erst_info = {
939939
.owner = THIS_MODULE,
940940
.name = "erst",
941-
.flags = PSTORE_FLAGS_FRAGILE,
941+
.flags = PSTORE_FLAGS_DMESG,
942942
.open = erst_open_pstore,
943943
.close = erst_close_pstore,
944944
.read = erst_reader,

drivers/firmware/efi/efi-pstore.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,7 @@ static int efi_pstore_erase(enum pstore_type_id type, u64 id, int count,
380380
static struct pstore_info efi_pstore_info = {
381381
.owner = THIS_MODULE,
382382
.name = "efi",
383-
.flags = PSTORE_FLAGS_FRAGILE,
383+
.flags = PSTORE_FLAGS_DMESG,
384384
.open = efi_pstore_open,
385385
.close = efi_pstore_close,
386386
.read = efi_pstore_read,

fs/pstore/platform.c

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,40 @@ static int pstore_write_compat(enum pstore_type_id type,
623623
size, psi);
624624
}
625625

626+
static int pstore_write_buf_user_compat(enum pstore_type_id type,
627+
enum kmsg_dump_reason reason,
628+
u64 *id, unsigned int part,
629+
const char __user *buf,
630+
bool compressed, size_t size,
631+
struct pstore_info *psi)
632+
{
633+
unsigned long flags = 0;
634+
size_t i, bufsize = size;
635+
long ret = 0;
636+
637+
if (unlikely(!access_ok(VERIFY_READ, buf, size)))
638+
return -EFAULT;
639+
if (bufsize > psinfo->bufsize)
640+
bufsize = psinfo->bufsize;
641+
spin_lock_irqsave(&psinfo->buf_lock, flags);
642+
for (i = 0; i < size; ) {
643+
size_t c = min(size - i, bufsize);
644+
645+
ret = __copy_from_user(psinfo->buf, buf + i, c);
646+
if (unlikely(ret != 0)) {
647+
ret = -EFAULT;
648+
break;
649+
}
650+
ret = psi->write_buf(type, reason, id, part, psinfo->buf,
651+
compressed, c, psi);
652+
if (unlikely(ret < 0))
653+
break;
654+
i += c;
655+
}
656+
spin_unlock_irqrestore(&psinfo->buf_lock, flags);
657+
return unlikely(ret < 0) ? ret : size;
658+
}
659+
626660
/*
627661
* platform specific persistent storage driver registers with
628662
* us here. If pstore is already mounted, call the platform
@@ -645,6 +679,8 @@ int pstore_register(struct pstore_info *psi)
645679

646680
if (!psi->write)
647681
psi->write = pstore_write_compat;
682+
if (!psi->write_buf_user)
683+
psi->write_buf_user = pstore_write_buf_user_compat;
648684
psinfo = psi;
649685
mutex_init(&psinfo->read_mutex);
650686
spin_unlock(&pstore_lock);
@@ -659,13 +695,14 @@ int pstore_register(struct pstore_info *psi)
659695
if (pstore_is_mounted())
660696
pstore_get_records(0);
661697

662-
pstore_register_kmsg();
663-
664-
if ((psi->flags & PSTORE_FLAGS_FRAGILE) == 0) {
698+
if (psi->flags & PSTORE_FLAGS_DMESG)
699+
pstore_register_kmsg();
700+
if (psi->flags & PSTORE_FLAGS_CONSOLE)
665701
pstore_register_console();
702+
if (psi->flags & PSTORE_FLAGS_FTRACE)
666703
pstore_register_ftrace();
704+
if (psi->flags & PSTORE_FLAGS_PMSG)
667705
pstore_register_pmsg();
668-
}
669706

670707
if (pstore_update_ms >= 0) {
671708
pstore_timer.expires = jiffies +
@@ -689,12 +726,14 @@ EXPORT_SYMBOL_GPL(pstore_register);
689726

690727
void pstore_unregister(struct pstore_info *psi)
691728
{
692-
if ((psi->flags & PSTORE_FLAGS_FRAGILE) == 0) {
729+
if (psi->flags & PSTORE_FLAGS_PMSG)
693730
pstore_unregister_pmsg();
731+
if (psi->flags & PSTORE_FLAGS_FTRACE)
694732
pstore_unregister_ftrace();
733+
if (psi->flags & PSTORE_FLAGS_CONSOLE)
695734
pstore_unregister_console();
696-
}
697-
pstore_unregister_kmsg();
735+
if (psi->flags & PSTORE_FLAGS_DMESG)
736+
pstore_unregister_kmsg();
698737

699738
free_buf_for_compression();
700739

fs/pstore/pmsg.c

Lines changed: 6 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -19,48 +19,25 @@
1919
#include "internal.h"
2020

2121
static DEFINE_MUTEX(pmsg_lock);
22-
#define PMSG_MAX_BOUNCE_BUFFER_SIZE (2*PAGE_SIZE)
2322

2423
static ssize_t write_pmsg(struct file *file, const char __user *buf,
2524
size_t count, loff_t *ppos)
2625
{
27-
size_t i, buffer_size;
28-
char *buffer;
26+
u64 id;
27+
int ret;
2928

3029
if (!count)
3130
return 0;
3231

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

36-
buffer_size = count;
37-
if (buffer_size > PMSG_MAX_BOUNCE_BUFFER_SIZE)
38-
buffer_size = PMSG_MAX_BOUNCE_BUFFER_SIZE;
39-
buffer = vmalloc(buffer_size);
40-
if (!buffer)
41-
return -ENOMEM;
42-
4336
mutex_lock(&pmsg_lock);
44-
for (i = 0; i < count; ) {
45-
size_t c = min(count - i, buffer_size);
46-
u64 id;
47-
long ret;
48-
49-
ret = __copy_from_user(buffer, buf + i, c);
50-
if (unlikely(ret != 0)) {
51-
mutex_unlock(&pmsg_lock);
52-
vfree(buffer);
53-
return -EFAULT;
54-
}
55-
psinfo->write_buf(PSTORE_TYPE_PMSG, 0, &id, 0, buffer, 0, c,
56-
psinfo);
57-
58-
i += c;
59-
}
60-
37+
ret = psinfo->write_buf_user(PSTORE_TYPE_PMSG, 0, &id, 0, buf, 0, count,
38+
psinfo);
6139
mutex_unlock(&pmsg_lock);
62-
vfree(buffer);
63-
return count;
40+
return ret ? ret : count;
6441
}
6542

6643
static const struct file_operations pmsg_fops = {

fs/pstore/ram.c

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,24 @@ static int notrace ramoops_pstore_write_buf(enum pstore_type_id type,
331331
return 0;
332332
}
333333

334+
static int notrace ramoops_pstore_write_buf_user(enum pstore_type_id type,
335+
enum kmsg_dump_reason reason,
336+
u64 *id, unsigned int part,
337+
const char __user *buf,
338+
bool compressed, size_t size,
339+
struct pstore_info *psi)
340+
{
341+
if (type == PSTORE_TYPE_PMSG) {
342+
struct ramoops_context *cxt = psi->data;
343+
344+
if (!cxt->mprz)
345+
return -ENOMEM;
346+
return persistent_ram_write_user(cxt->mprz, buf, size);
347+
}
348+
349+
return -EINVAL;
350+
}
351+
334352
static int ramoops_pstore_erase(enum pstore_type_id type, u64 id, int count,
335353
struct timespec time, struct pstore_info *psi)
336354
{
@@ -369,6 +387,7 @@ static struct ramoops_context oops_cxt = {
369387
.open = ramoops_pstore_open,
370388
.read = ramoops_pstore_read,
371389
.write_buf = ramoops_pstore_write_buf,
390+
.write_buf_user = ramoops_pstore_write_buf_user,
372391
.erase = ramoops_pstore_erase,
373392
},
374393
};
@@ -377,13 +396,14 @@ static void ramoops_free_przs(struct ramoops_context *cxt)
377396
{
378397
int i;
379398

380-
cxt->max_dump_cnt = 0;
381399
if (!cxt->przs)
382400
return;
383401

384-
for (i = 0; !IS_ERR_OR_NULL(cxt->przs[i]); i++)
402+
for (i = 0; i < cxt->max_dump_cnt; i++)
385403
persistent_ram_free(cxt->przs[i]);
404+
386405
kfree(cxt->przs);
406+
cxt->max_dump_cnt = 0;
387407
}
388408

389409
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,
408428
GFP_KERNEL);
409429
if (!cxt->przs) {
410430
dev_err(dev, "failed to initialize a prz array for dumps\n");
411-
goto fail_prz;
431+
goto fail_mem;
412432
}
413433

414434
for (i = 0; i < cxt->max_dump_cnt; i++) {
@@ -419,14 +439,21 @@ static int ramoops_init_przs(struct device *dev, struct ramoops_context *cxt,
419439
err = PTR_ERR(cxt->przs[i]);
420440
dev_err(dev, "failed to request mem region (0x%zx@0x%llx): %d\n",
421441
cxt->record_size, (unsigned long long)*paddr, err);
442+
443+
while (i > 0) {
444+
i--;
445+
persistent_ram_free(cxt->przs[i]);
446+
}
422447
goto fail_prz;
423448
}
424449
*paddr += cxt->record_size;
425450
}
426451

427452
return 0;
428453
fail_prz:
429-
ramoops_free_przs(cxt);
454+
kfree(cxt->przs);
455+
fail_mem:
456+
cxt->max_dump_cnt = 0;
430457
return err;
431458
}
432459

@@ -608,12 +635,20 @@ static int ramoops_probe(struct platform_device *pdev)
608635
cxt->pstore.bufsize = 1024; /* LOG_LINE_MAX */
609636
cxt->pstore.bufsize = max(cxt->record_size, cxt->pstore.bufsize);
610637
cxt->pstore.buf = kmalloc(cxt->pstore.bufsize, GFP_KERNEL);
611-
spin_lock_init(&cxt->pstore.buf_lock);
612638
if (!cxt->pstore.buf) {
613639
pr_err("cannot allocate pstore buffer\n");
614640
err = -ENOMEM;
615641
goto fail_clear;
616642
}
643+
spin_lock_init(&cxt->pstore.buf_lock);
644+
645+
cxt->pstore.flags = PSTORE_FLAGS_DMESG;
646+
if (cxt->console_size)
647+
cxt->pstore.flags |= PSTORE_FLAGS_CONSOLE;
648+
if (cxt->ftrace_size)
649+
cxt->pstore.flags |= PSTORE_FLAGS_FTRACE;
650+
if (cxt->pmsg_size)
651+
cxt->pstore.flags |= PSTORE_FLAGS_PMSG;
617652

618653
err = pstore_register(&cxt->pstore);
619654
if (err) {
@@ -659,7 +694,6 @@ static int ramoops_remove(struct platform_device *pdev)
659694
struct ramoops_context *cxt = &oops_cxt;
660695

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

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

0 commit comments

Comments
 (0)