diff options
Diffstat (limited to 'drivers/acpi/apei/erst.c')
-rw-r--r-- | drivers/acpi/apei/erst.c | 31 |
1 files changed, 22 insertions, 9 deletions
diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c index 127408069ca7..631b9477b99c 100644 --- a/drivers/acpi/apei/erst.c +++ b/drivers/acpi/apei/erst.c | |||
@@ -932,7 +932,8 @@ static int erst_check_table(struct acpi_table_erst *erst_tab) | |||
932 | static int erst_open_pstore(struct pstore_info *psi); | 932 | static int erst_open_pstore(struct pstore_info *psi); |
933 | static int erst_close_pstore(struct pstore_info *psi); | 933 | static int erst_close_pstore(struct pstore_info *psi); |
934 | static ssize_t erst_reader(u64 *id, enum pstore_type_id *type, | 934 | static ssize_t erst_reader(u64 *id, enum pstore_type_id *type, |
935 | struct timespec *time, struct pstore_info *psi); | 935 | struct timespec *time, char **buf, |
936 | struct pstore_info *psi); | ||
936 | static int erst_writer(enum pstore_type_id type, u64 *id, unsigned int part, | 937 | static int erst_writer(enum pstore_type_id type, u64 *id, unsigned int part, |
937 | size_t size, struct pstore_info *psi); | 938 | size_t size, struct pstore_info *psi); |
938 | static int erst_clearer(enum pstore_type_id type, u64 id, | 939 | static int erst_clearer(enum pstore_type_id type, u64 id, |
@@ -986,17 +987,23 @@ static int erst_close_pstore(struct pstore_info *psi) | |||
986 | } | 987 | } |
987 | 988 | ||
988 | static ssize_t erst_reader(u64 *id, enum pstore_type_id *type, | 989 | static ssize_t erst_reader(u64 *id, enum pstore_type_id *type, |
989 | struct timespec *time, struct pstore_info *psi) | 990 | struct timespec *time, char **buf, |
991 | struct pstore_info *psi) | ||
990 | { | 992 | { |
991 | int rc; | 993 | int rc; |
992 | ssize_t len = 0; | 994 | ssize_t len = 0; |
993 | u64 record_id; | 995 | u64 record_id; |
994 | struct cper_pstore_record *rcd = (struct cper_pstore_record *) | 996 | struct cper_pstore_record *rcd; |
995 | (erst_info.buf - sizeof(*rcd)); | 997 | size_t rcd_len = sizeof(*rcd) + erst_info.bufsize; |
996 | 998 | ||
997 | if (erst_disable) | 999 | if (erst_disable) |
998 | return -ENODEV; | 1000 | return -ENODEV; |
999 | 1001 | ||
1002 | rcd = kmalloc(rcd_len, GFP_KERNEL); | ||
1003 | if (!rcd) { | ||
1004 | rc = -ENOMEM; | ||
1005 | goto out; | ||
1006 | } | ||
1000 | skip: | 1007 | skip: |
1001 | rc = erst_get_record_id_next(&reader_pos, &record_id); | 1008 | rc = erst_get_record_id_next(&reader_pos, &record_id); |
1002 | if (rc) | 1009 | if (rc) |
@@ -1004,22 +1011,27 @@ skip: | |||
1004 | 1011 | ||
1005 | /* no more record */ | 1012 | /* no more record */ |
1006 | if (record_id == APEI_ERST_INVALID_RECORD_ID) { | 1013 | if (record_id == APEI_ERST_INVALID_RECORD_ID) { |
1007 | rc = -1; | 1014 | rc = -EINVAL; |
1008 | goto out; | 1015 | goto out; |
1009 | } | 1016 | } |
1010 | 1017 | ||
1011 | len = erst_read(record_id, &rcd->hdr, sizeof(*rcd) + | 1018 | len = erst_read(record_id, &rcd->hdr, rcd_len); |
1012 | erst_info.bufsize); | ||
1013 | /* The record may be cleared by others, try read next record */ | 1019 | /* The record may be cleared by others, try read next record */ |
1014 | if (len == -ENOENT) | 1020 | if (len == -ENOENT) |
1015 | goto skip; | 1021 | goto skip; |
1016 | else if (len < 0) { | 1022 | else if (len < sizeof(*rcd)) { |
1017 | rc = -1; | 1023 | rc = -EIO; |
1018 | goto out; | 1024 | goto out; |
1019 | } | 1025 | } |
1020 | if (uuid_le_cmp(rcd->hdr.creator_id, CPER_CREATOR_PSTORE) != 0) | 1026 | if (uuid_le_cmp(rcd->hdr.creator_id, CPER_CREATOR_PSTORE) != 0) |
1021 | goto skip; | 1027 | goto skip; |
1022 | 1028 | ||
1029 | *buf = kmalloc(len, GFP_KERNEL); | ||
1030 | if (*buf == NULL) { | ||
1031 | rc = -ENOMEM; | ||
1032 | goto out; | ||
1033 | } | ||
1034 | memcpy(*buf, rcd->data, len - sizeof(*rcd)); | ||
1023 | *id = record_id; | 1035 | *id = record_id; |
1024 | if (uuid_le_cmp(rcd->sec_hdr.section_type, | 1036 | if (uuid_le_cmp(rcd->sec_hdr.section_type, |
1025 | CPER_SECTION_TYPE_DMESG) == 0) | 1037 | CPER_SECTION_TYPE_DMESG) == 0) |
@@ -1037,6 +1049,7 @@ skip: | |||
1037 | time->tv_nsec = 0; | 1049 | time->tv_nsec = 0; |
1038 | 1050 | ||
1039 | out: | 1051 | out: |
1052 | kfree(rcd); | ||
1040 | return (rc < 0) ? rc : (len - sizeof(*rcd)); | 1053 | return (rc < 0) ? rc : (len - sizeof(*rcd)); |
1041 | } | 1054 | } |
1042 | 1055 | ||