aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZachary Amsden <zach@vmware.com>2006-01-06 03:11:55 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-06 11:33:35 -0500
commit5fe9fe3c6f9a1ae7aa224bb7a66eb9aad9e4abef (patch)
treeec120ce6e72700fe49720127bc76228c51bd406b
parent3fae1c37eea98097de34ba665796fea93b29f4aa (diff)
[PATCH] x86: Pnp byte granularity
The one remaining caller of set_limit, the PnP BIOS code, calls into the PnP BIOS, passing kernel parameters in and out. These parameteres may be passed from arbitrary kernel virtual memory, so they deserve strict protection to stop a bad BIOS from smashing beyond the object size. Unfortunately, the use of set_limit was badly botching this by setting the limit in terms of pages, when it really should have byte granularity. When doing this, I discovered my BIOS had the buggy code during the "get system device node" call: mov ax, es:[bx] Which is harmless, but has a trivial workaround. Signed-off-by: Zachary Amsden <zach@vmware.com> Cc: "Seth, Rohit" <rohit.seth@intel.com> Cc: Stephen Rothwell <sfr@canb.auug.org.au> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--arch/i386/kernel/head.S12
-rw-r--r--drivers/pnp/pnpbios/bioscalls.c5
-rw-r--r--include/asm-i386/system.h2
3 files changed, 11 insertions, 8 deletions
diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S
index 37b599fa4d1..58d2746670b 100644
--- a/arch/i386/kernel/head.S
+++ b/arch/i386/kernel/head.S
@@ -504,12 +504,12 @@ ENTRY(cpu_gdt_table)
504 .quad 0x0000000000000000 /* 0x80 TSS descriptor */ 504 .quad 0x0000000000000000 /* 0x80 TSS descriptor */
505 .quad 0x0000000000000000 /* 0x88 LDT descriptor */ 505 .quad 0x0000000000000000 /* 0x88 LDT descriptor */
506 506
507 /* Segments used for calling PnP BIOS */ 507 /* Segments used for calling PnP BIOS have byte granularity */
508 .quad 0x00c09a0000000000 /* 0x90 32-bit code */ 508 .quad 0x00409a0000000000 /* 0x90 32-bit code */
509 .quad 0x00809a0000000000 /* 0x98 16-bit code */ 509 .quad 0x00009a0000000000 /* 0x98 16-bit code */
510 .quad 0x0080920000000000 /* 0xa0 16-bit data */ 510 .quad 0x0000920000000000 /* 0xa0 16-bit data */
511 .quad 0x0080920000000000 /* 0xa8 16-bit data */ 511 .quad 0x0000920000000000 /* 0xa8 16-bit data */
512 .quad 0x0080920000000000 /* 0xb0 16-bit data */ 512 .quad 0x0000920000000000 /* 0xb0 16-bit data */
513 513
514 /* 514 /*
515 * The APM segments have byte granularity and their bases 515 * The APM segments have byte granularity and their bases
diff --git a/drivers/pnp/pnpbios/bioscalls.c b/drivers/pnp/pnpbios/bioscalls.c
index 37bacfcdbc5..a72126180e9 100644
--- a/drivers/pnp/pnpbios/bioscalls.c
+++ b/drivers/pnp/pnpbios/bioscalls.c
@@ -283,12 +283,15 @@ int pnp_bios_dev_node_info(struct pnp_dev_node_info *data)
283static int __pnp_bios_get_dev_node(u8 *nodenum, char boot, struct pnp_bios_node *data) 283static int __pnp_bios_get_dev_node(u8 *nodenum, char boot, struct pnp_bios_node *data)
284{ 284{
285 u16 status; 285 u16 status;
286 u16 tmp_nodenum;
286 if (!pnp_bios_present()) 287 if (!pnp_bios_present())
287 return PNP_FUNCTION_NOT_SUPPORTED; 288 return PNP_FUNCTION_NOT_SUPPORTED;
288 if ( !boot && pnpbios_dont_use_current_config ) 289 if ( !boot && pnpbios_dont_use_current_config )
289 return PNP_FUNCTION_NOT_SUPPORTED; 290 return PNP_FUNCTION_NOT_SUPPORTED;
291 tmp_nodenum = *nodenum;
290 status = call_pnp_bios(PNP_GET_SYS_DEV_NODE, 0, PNP_TS1, 0, PNP_TS2, boot ? 2 : 1, PNP_DS, 0, 292 status = call_pnp_bios(PNP_GET_SYS_DEV_NODE, 0, PNP_TS1, 0, PNP_TS2, boot ? 2 : 1, PNP_DS, 0,
291 nodenum, sizeof(char), data, 65536); 293 &tmp_nodenum, sizeof(tmp_nodenum), data, 65536);
294 *nodenum = tmp_nodenum;
292 return status; 295 return status;
293} 296}
294 297
diff --git a/include/asm-i386/system.h b/include/asm-i386/system.h
index 24cc0c8fe34..9c0593b7a94 100644
--- a/include/asm-i386/system.h
+++ b/include/asm-i386/system.h
@@ -54,7 +54,7 @@ __asm__ __volatile__ ("movw %%dx,%1\n\t" \
54 ); } while(0) 54 ); } while(0)
55 55
56#define set_base(ldt,base) _set_base( ((char *)&(ldt)) , (base) ) 56#define set_base(ldt,base) _set_base( ((char *)&(ldt)) , (base) )
57#define set_limit(ldt,limit) _set_limit( ((char *)&(ldt)) , ((limit)-1)>>12 ) 57#define set_limit(ldt,limit) _set_limit( ((char *)&(ldt)) , ((limit)-1) )
58 58
59/* 59/*
60 * Load a segment. Fall back on loading the zero 60 * Load a segment. Fall back on loading the zero