aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/pseries
diff options
context:
space:
mode:
authorAruna Balakrishnaiah <aruna@linux.vnet.ibm.com>2013-08-08 13:03:49 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2013-08-09 04:06:40 -0400
commit7e76f34fa103677a27d96a7cfef8ce61389a32de (patch)
treefe4ceca869426702d81b5dbf0a924adbd9708725 /arch/powerpc/platforms/pseries
parent4e90a2a7375e86827541bda9393414c03e7721c6 (diff)
powerpc/pseries: Fix buffer overflow when reading from pstore
When reading from pstore there is a buffer overflow during decompression due to the header added in unzip_oops. Remove unzip_oops and call pstore_decompress directly in nvram_pstore_read. Allocate buffer of size report_length of the oops header as header will not be deallocated in pstore. Since we have 'openssl' command line tool to decompress the compressed data, dump the compressed data in case decompression fails instead of not dumping anything. Signed-off-by: Aruna Balakrishnaiah <aruna@linux.vnet.ibm.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/platforms/pseries')
-rw-r--r--arch/powerpc/platforms/pseries/nvram.c70
1 files changed, 24 insertions, 46 deletions
diff --git a/arch/powerpc/platforms/pseries/nvram.c b/arch/powerpc/platforms/pseries/nvram.c
index 9f8671a44551..893f36053c97 100644
--- a/arch/powerpc/platforms/pseries/nvram.c
+++ b/arch/powerpc/platforms/pseries/nvram.c
@@ -569,35 +569,6 @@ error:
569 return ret; 569 return ret;
570} 570}
571 571
572static int unzip_oops(char *oops_buf, char *big_buf)
573{
574 struct oops_log_info *oops_hdr = (struct oops_log_info *)oops_buf;
575 u64 timestamp = oops_hdr->timestamp;
576 char *big_oops_data = NULL;
577 char *oops_data_buf = NULL;
578 size_t big_oops_data_sz;
579 int unzipped_len;
580
581 big_oops_data = big_buf + sizeof(struct oops_log_info);
582 big_oops_data_sz = big_oops_buf_sz - sizeof(struct oops_log_info);
583 oops_data_buf = oops_buf + sizeof(struct oops_log_info);
584
585 unzipped_len = nvram_decompress(oops_data_buf, big_oops_data,
586 oops_hdr->report_length,
587 big_oops_data_sz);
588
589 if (unzipped_len < 0) {
590 pr_err("nvram: decompression failed; returned %d\n",
591 unzipped_len);
592 return -1;
593 }
594 oops_hdr = (struct oops_log_info *)big_buf;
595 oops_hdr->version = OOPS_HDR_VERSION;
596 oops_hdr->report_length = (u16) unzipped_len;
597 oops_hdr->timestamp = timestamp;
598 return 0;
599}
600
601static int nvram_pstore_open(struct pstore_info *psi) 572static int nvram_pstore_open(struct pstore_info *psi)
602{ 573{
603 /* Reset the iterator to start reading partitions again */ 574 /* Reset the iterator to start reading partitions again */
@@ -685,10 +656,9 @@ static ssize_t nvram_pstore_read(u64 *id, enum pstore_type_id *type,
685 unsigned int err_type, id_no, size = 0; 656 unsigned int err_type, id_no, size = 0;
686 struct nvram_os_partition *part = NULL; 657 struct nvram_os_partition *part = NULL;
687 char *buff = NULL, *big_buff = NULL; 658 char *buff = NULL, *big_buff = NULL;
688 int rc, sig = 0; 659 int sig = 0;
689 loff_t p; 660 loff_t p;
690 661
691read_partition:
692 read_type++; 662 read_type++;
693 663
694 switch (nvram_type_ids[read_type]) { 664 switch (nvram_type_ids[read_type]) {
@@ -749,30 +719,36 @@ read_partition:
749 *id = id_no; 719 *id = id_no;
750 720
751 if (nvram_type_ids[read_type] == PSTORE_TYPE_DMESG) { 721 if (nvram_type_ids[read_type] == PSTORE_TYPE_DMESG) {
722 int length, unzipped_len;
723
752 oops_hdr = (struct oops_log_info *)buff; 724 oops_hdr = (struct oops_log_info *)buff;
753 *buf = buff + sizeof(*oops_hdr); 725 length = oops_hdr->report_length;
726 *buf = kmalloc(length, GFP_KERNEL);
727 if (*buf == NULL)
728 return -ENOMEM;
729 memcpy(*buf, buff + sizeof(*oops_hdr), length);
730 time->tv_sec = oops_hdr->timestamp;
731 time->tv_nsec = 0;
732 kfree(buff);
754 733
755 if (err_type == ERR_TYPE_KERNEL_PANIC_GZ) { 734 if (err_type == ERR_TYPE_KERNEL_PANIC_GZ) {
756 big_buff = kmalloc(big_oops_buf_sz, GFP_KERNEL); 735 big_buff = kmalloc(big_oops_buf_sz, GFP_KERNEL);
757 if (!big_buff) 736 if (!big_buff)
758 return -ENOMEM; 737 return -ENOMEM;
759 738
760 rc = unzip_oops(buff, big_buff); 739 unzipped_len = nvram_decompress(*buf, big_buff,
740 length, big_oops_buf_sz);
761 741
762 if (rc != 0) { 742 if (unzipped_len < 0) {
763 kfree(buff); 743 pr_err("nvram: decompression failed, returned "
744 "rc %d\n", unzipped_len);
764 kfree(big_buff); 745 kfree(big_buff);
765 goto read_partition; 746 } else {
747 *buf = big_buff;
748 length = unzipped_len;
766 } 749 }
767
768 oops_hdr = (struct oops_log_info *)big_buff;
769 *buf = big_buff + sizeof(*oops_hdr);
770 kfree(buff);
771 } 750 }
772 751 return length;
773 time->tv_sec = oops_hdr->timestamp;
774 time->tv_nsec = 0;
775 return oops_hdr->report_length;
776 } 752 }
777 753
778 *buf = buff; 754 *buf = buff;
@@ -816,6 +792,7 @@ static int nvram_pstore_init(void)
816static void __init nvram_init_oops_partition(int rtas_partition_exists) 792static void __init nvram_init_oops_partition(int rtas_partition_exists)
817{ 793{
818 int rc; 794 int rc;
795 size_t size;
819 796
820 rc = pseries_nvram_init_os_partition(&oops_log_partition); 797 rc = pseries_nvram_init_os_partition(&oops_log_partition);
821 if (rc != 0) { 798 if (rc != 0) {
@@ -844,8 +821,9 @@ static void __init nvram_init_oops_partition(int rtas_partition_exists)
844 big_oops_buf_sz = (oops_data_sz * 100) / 45; 821 big_oops_buf_sz = (oops_data_sz * 100) / 45;
845 big_oops_buf = kmalloc(big_oops_buf_sz, GFP_KERNEL); 822 big_oops_buf = kmalloc(big_oops_buf_sz, GFP_KERNEL);
846 if (big_oops_buf) { 823 if (big_oops_buf) {
847 stream.workspace = kmalloc(zlib_deflate_workspacesize( 824 size = max(zlib_deflate_workspacesize(WINDOW_BITS, MEM_LEVEL),
848 WINDOW_BITS, MEM_LEVEL), GFP_KERNEL); 825 zlib_inflate_workspacesize());
826 stream.workspace = kmalloc(size, GFP_KERNEL);
849 if (!stream.workspace) { 827 if (!stream.workspace) {
850 pr_err("nvram: No memory for compression workspace; " 828 pr_err("nvram: No memory for compression workspace; "
851 "skipping compression of %s partition data\n", 829 "skipping compression of %s partition data\n",