diff options
author | Linus Torvalds | 2017-07-05 11:43:47 -0700 |
---|---|---|
committer | Linus Torvalds | 2017-07-05 11:43:47 -0700 |
commit | 2cc7b4ca7d01a844651d34b79ff8d778c7e9a875 (patch) | |
tree | 5bd92864d02c4d4b6edb02a313fbeb3d1217a58b /drivers/firmware | |
parent | e24dd9ee5399747b71c1d982a484fc7601795f31 (diff) | |
parent | 0752e4028c003fba1e2b44c4b3cf6a4482e931b6 (diff) |
Merge tag 'pstore-v4.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux
Pull pstore updates from Kees Cook:
"Various fixes and tweaks for the pstore subsystem.
Highlights:
- use memdup_user() instead of open-coded copies (Geliang Tang)
- fix record memory leak during initialization (Douglas Anderson)
- avoid confused compressed record warning (Ankit Kumar)
- prepopulate record timestamp and remove redundant logic from
backends"
* tag 'pstore-v4.13-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux:
powerpc/nvram: use memdup_user
pstore: use memdup_user
pstore: Fix format string to use %u for record id
pstore: Populate pstore record->time field
pstore: Create common record initializer
efi-pstore: Refactor erase routine
pstore: Avoid potential infinite loop
pstore: Fix leaked pstore_record in pstore_get_backend_records()
pstore: Don't warn if data is uncompressed and type is not PSTORE_TYPE_DMESG
Diffstat (limited to 'drivers/firmware')
-rw-r--r-- | drivers/firmware/efi/efi-pstore.c | 87 |
1 files changed, 38 insertions, 49 deletions
diff --git a/drivers/firmware/efi/efi-pstore.c b/drivers/firmware/efi/efi-pstore.c index ef1fafdad400..5a0fa939d70f 100644 --- a/drivers/firmware/efi/efi-pstore.c +++ b/drivers/firmware/efi/efi-pstore.c @@ -4,7 +4,7 @@ #include <linux/slab.h> #include <linux/ucs2_string.h> -#define DUMP_NAME_LEN 52 +#define DUMP_NAME_LEN 66 static bool efivars_pstore_disable = IS_ENABLED(CONFIG_EFI_VARS_PSTORE_DEFAULT_DISABLE); @@ -244,12 +244,12 @@ static int efi_pstore_write(struct pstore_record *record) efi_guid_t vendor = LINUX_EFI_CRASH_GUID; int i, ret = 0; - record->time.tv_sec = get_seconds(); - record->time.tv_nsec = 0; - record->id = generic_id(record->time.tv_sec, record->part, record->count); + /* Since we copy the entire length of name, make sure it is wiped. */ + memset(name, 0, sizeof(name)); + snprintf(name, sizeof(name), "dump-type%u-%u-%d-%lu-%c", record->type, record->part, record->count, record->time.tv_sec, record->compressed ? 'C' : 'D'); @@ -267,44 +267,20 @@ static int efi_pstore_write(struct pstore_record *record) return ret; }; -struct pstore_erase_data { - struct pstore_record *record; - efi_char16_t *name; -}; - /* * Clean up an entry with the same name */ static int efi_pstore_erase_func(struct efivar_entry *entry, void *data) { - struct pstore_erase_data *ed = data; + efi_char16_t *efi_name = data; efi_guid_t vendor = LINUX_EFI_CRASH_GUID; - efi_char16_t efi_name_old[DUMP_NAME_LEN]; - efi_char16_t *efi_name = ed->name; - unsigned long ucs2_len = ucs2_strlen(ed->name); - char name_old[DUMP_NAME_LEN]; - int i; + unsigned long ucs2_len = ucs2_strlen(efi_name); if (efi_guidcmp(entry->var.VendorGuid, vendor)) return 0; - if (ucs2_strncmp(entry->var.VariableName, - efi_name, (size_t)ucs2_len)) { - /* - * Check if an old format, which doesn't support - * holding multiple logs, remains. - */ - snprintf(name_old, sizeof(name_old), "dump-type%u-%u-%lu", - ed->record->type, ed->record->part, - ed->record->time.tv_sec); - - for (i = 0; i < DUMP_NAME_LEN; i++) - efi_name_old[i] = name_old[i]; - - if (ucs2_strncmp(entry->var.VariableName, efi_name_old, - ucs2_strlen(efi_name_old))) - return 0; - } + if (ucs2_strncmp(entry->var.VariableName, efi_name, (size_t)ucs2_len)) + return 0; if (entry->scanning) { /* @@ -321,35 +297,48 @@ static int efi_pstore_erase_func(struct efivar_entry *entry, void *data) return 1; } -static int efi_pstore_erase(struct pstore_record *record) +static int efi_pstore_erase_name(const char *name) { - struct pstore_erase_data edata; struct efivar_entry *entry = NULL; - char name[DUMP_NAME_LEN]; efi_char16_t efi_name[DUMP_NAME_LEN]; int found, i; - snprintf(name, sizeof(name), "dump-type%u-%u-%d-%lu", - record->type, record->part, record->count, - record->time.tv_sec); - - for (i = 0; i < DUMP_NAME_LEN; i++) + for (i = 0; i < DUMP_NAME_LEN; i++) { efi_name[i] = name[i]; - - edata.record = record; - edata.name = efi_name; + if (name[i] == '\0') + break; + } if (efivar_entry_iter_begin()) return -EINTR; - found = __efivar_entry_iter(efi_pstore_erase_func, &efivar_sysfs_list, &edata, &entry); - if (found && !entry->scanning) { - efivar_entry_iter_end(); + found = __efivar_entry_iter(efi_pstore_erase_func, &efivar_sysfs_list, + efi_name, &entry); + efivar_entry_iter_end(); + + if (found && !entry->scanning) efivar_unregister(entry); - } else - efivar_entry_iter_end(); - return 0; + return found ? 0 : -ENOENT; +} + +static int efi_pstore_erase(struct pstore_record *record) +{ + char name[DUMP_NAME_LEN]; + int ret; + + snprintf(name, sizeof(name), "dump-type%u-%u-%d-%lu", + record->type, record->part, record->count, + record->time.tv_sec); + ret = efi_pstore_erase_name(name); + if (ret != -ENOENT) + return ret; + + snprintf(name, sizeof(name), "dump-type%u-%u-%lu", + record->type, record->part, record->time.tv_sec); + ret = efi_pstore_erase_name(name); + + return ret; } static struct pstore_info efi_pstore_info = { |