diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-07 01:16:16 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-07 01:16:16 +0300 |
commit | 0fb3ca447ddabcfb8dc7e0f719955e500b170cbd (patch) | |
tree | 57e516541b7650149c468a9567152164b12c75e3 /fs/pstore/platform.c | |
parent | 3940ee36a0565ea7fb848e3c798afe22efd0b90a (diff) | |
parent | f88baf68ebe5b2efced64725fd98548af9b8f510 (diff) | |
download | linux-0fb3ca447ddabcfb8dc7e0f719955e500b170cbd.tar.xz |
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
Diffstat (limited to 'fs/pstore/platform.c')
-rw-r--r-- | fs/pstore/platform.c | 53 |
1 files changed, 46 insertions, 7 deletions
diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c index 16ecca5b72d8..14984d902a99 100644 --- a/fs/pstore/platform.c +++ b/fs/pstore/platform.c @@ -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); - pstore_register_kmsg(); - - if ((psi->flags & PSTORE_FLAGS_FRAGILE) == 0) { + if (psi->flags & PSTORE_FLAGS_DMESG) + pstore_register_kmsg(); + 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,12 +726,14 @@ 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(); - } - pstore_unregister_kmsg(); + if (psi->flags & PSTORE_FLAGS_DMESG) + pstore_unregister_kmsg(); free_buf_for_compression(); |