aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/rtas_flash.c
diff options
context:
space:
mode:
authorVasant Hegde <hegdevasant@linux.vnet.ibm.com>2013-05-07 12:54:47 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2013-05-14 00:36:26 -0400
commita94a14720eaf55c5f06d6ca7ecbe3f87f6864fc6 (patch)
tree3ae7ada761b9728120a84a8b078d5b8ce4de015d /arch/powerpc/kernel/rtas_flash.c
parent79c66ce8f6448a3295a32efeac88c9debd7f7094 (diff)
powerpc/rtas_flash: Fix validate_flash buffer overflow issue
ibm,validate-flash-image RTAS call output buffer contains 150 - 200 bytes of data on latest system. Presently we have output buffer size as 64 bytes and we use sprintf to copy data from RTAS buffer to local buffer. This causes kernel oops (see below call trace). This patch increases local buffer size to 256 and also uses snprintf instead of sprintf to copy data from RTAS buffer. Kernel call trace : ------------------- Oops: Kernel access of bad area, sig: 11 [#1] SMP NR_CPUS=1024 NUMA pSeries Modules linked in: nfs fscache lockd auth_rpcgss nfs_acl sunrpc fuse loop dm_mod ipv6 ipv6_lib usb_storage ehea(X) sr_mod qlge ses cdrom enclosure st be2net sg ext3 jbd mbcache usbhid hid ohci_hcd ehci_hcd usbcore qla2xxx usb_common sd_mod crc_t10dif scsi_dh_hp_sw scsi_dh_rdac scsi_dh_alua scsi_dh_emc scsi_dh lpfc scsi_transport_fc scsi_tgt ipr(X) libata scsi_mod Supported: Yes NIP: 4520323031333130 LR: 4520323031333130 CTR: 0000000000000000 REGS: c0000001b91779b0 TRAP: 0400 Tainted: G X (3.0.13-0.27-ppc64) MSR: 8000000040009032 <EE,ME,IR,DR> CR: 44022488 XER: 20000018 TASK = c0000001bca1aba0[4736] 'cat' THREAD: c0000001b9174000 CPU: 36 GPR00: 4520323031333130 c0000001b9177c30 c000000000f87c98 000000000000009b GPR04: c0000001b9177c4a 000000000000000b 3520323031333130 2032303133313031 GPR08: 3133313031350a4d 000000000000009b 0000000000000000 c0000000003664a4 GPR12: 0000000022022448 c000000003ee6c00 0000000000000002 00000000100e8a90 GPR16: 00000000100cb9d8 0000000010093370 000000001001d310 0000000000000000 GPR20: 0000000000008000 00000000100fae60 000000000000005e 0000000000000000 GPR24: 0000000010129350 46573738302e3030 2046573738302e30 300a4d4720323031 GPR28: 333130313520554e 4b4e4f574e0a4d47 2032303133313031 3520323031333130 NIP [4520323031333130] 0x4520323031333130 LR [4520323031333130] 0x4520323031333130 Call Trace: [c0000001b9177c30] [4520323031333130] 0x4520323031333130 (unreliable) Instruction dump: XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX Signed-off-by: Vasant Hegde <hegdevasant@linux.vnet.ibm.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/kernel/rtas_flash.c')
-rw-r--r--arch/powerpc/kernel/rtas_flash.c10
1 files changed, 6 insertions, 4 deletions
diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c
index 5b3022470126..2f3cdb01506d 100644
--- a/arch/powerpc/kernel/rtas_flash.c
+++ b/arch/powerpc/kernel/rtas_flash.c
@@ -89,6 +89,7 @@
89 89
90/* Array sizes */ 90/* Array sizes */
91#define VALIDATE_BUF_SIZE 4096 91#define VALIDATE_BUF_SIZE 4096
92#define VALIDATE_MSG_LEN 256
92#define RTAS_MSG_MAXLEN 64 93#define RTAS_MSG_MAXLEN 64
93 94
94/* Quirk - RTAS requires 4k list length and block size */ 95/* Quirk - RTAS requires 4k list length and block size */
@@ -466,7 +467,7 @@ static void validate_flash(struct rtas_validate_flash_t *args_buf)
466} 467}
467 468
468static int get_validate_flash_msg(struct rtas_validate_flash_t *args_buf, 469static int get_validate_flash_msg(struct rtas_validate_flash_t *args_buf,
469 char *msg) 470 char *msg, int msglen)
470{ 471{
471 int n; 472 int n;
472 473
@@ -474,7 +475,8 @@ static int get_validate_flash_msg(struct rtas_validate_flash_t *args_buf,
474 n = sprintf(msg, "%d\n", args_buf->update_results); 475 n = sprintf(msg, "%d\n", args_buf->update_results);
475 if ((args_buf->update_results >= VALIDATE_CUR_UNKNOWN) || 476 if ((args_buf->update_results >= VALIDATE_CUR_UNKNOWN) ||
476 (args_buf->update_results == VALIDATE_TMP_UPDATE)) 477 (args_buf->update_results == VALIDATE_TMP_UPDATE))
477 n += sprintf(msg + n, "%s\n", args_buf->buf); 478 n += snprintf(msg + n, msglen - n, "%s\n",
479 args_buf->buf);
478 } else { 480 } else {
479 n = sprintf(msg, "%d\n", args_buf->status); 481 n = sprintf(msg, "%d\n", args_buf->status);
480 } 482 }
@@ -486,11 +488,11 @@ static ssize_t validate_flash_read(struct file *file, char __user *buf,
486{ 488{
487 struct rtas_validate_flash_t *const args_buf = 489 struct rtas_validate_flash_t *const args_buf =
488 &rtas_validate_flash_data; 490 &rtas_validate_flash_data;
489 char msg[RTAS_MSG_MAXLEN]; 491 char msg[VALIDATE_MSG_LEN];
490 int msglen; 492 int msglen;
491 493
492 mutex_lock(&rtas_validate_flash_mutex); 494 mutex_lock(&rtas_validate_flash_mutex);
493 msglen = get_validate_flash_msg(args_buf, msg); 495 msglen = get_validate_flash_msg(args_buf, msg, VALIDATE_MSG_LEN);
494 mutex_unlock(&rtas_validate_flash_mutex); 496 mutex_unlock(&rtas_validate_flash_mutex);
495 497
496 return simple_read_from_buffer(buf, count, ppos, msg, msglen); 498 return simple_read_from_buffer(buf, count, ppos, msg, msglen);