소스 검색

[pcbios] Inhibit INT 15 memory map hiding on brain-dead BIOSes

Some really moronic BIOSes bring up the PXE stack via the UNDI loader
entry point during POST, and then don't bother to unload it before
overwriting the code and data segments.  If this happens, we really
don't want to leave INT 15 hooked, because that will cause any loaded
OS to die horribly as soon as it attempts to fetch the system memory
map.

We use a heuristic to detect whether or not we are being loaded at the
top of free base memory.  If we determine that we are being loaded at
some other arbitrary location in base memory, then we assume that it's
not safe to hook INT 15.
tags/v0.9.4
Michael Brown 15 년 전
부모
커밋
887d77c27a
1개의 변경된 파일27개의 추가작업 그리고 0개의 파일을 삭제
  1. 27
    0
      src/arch/i386/firmware/pcbios/hidemem.c

+ 27
- 0
src/arch/i386/firmware/pcbios/hidemem.c 파일 보기

@@ -64,6 +64,10 @@ extern struct segoff __text16 ( int15_vector );
64 64
 /* The linker defines these symbols for us */
65 65
 extern char _text[];
66 66
 extern char _end[];
67
+extern char _text16_size[];
68
+#define _text16_size ( ( unsigned int ) _text16_size )
69
+extern char _data16_size[];
70
+#define _data16_size ( ( unsigned int ) _data16_size )
67 71
 
68 72
 /**
69 73
  * Hide region of memory from system memory map
@@ -123,6 +127,9 @@ void hide_text ( void ) {
123 127
  */
124 128
 static void hide_etherboot ( void ) {
125 129
 	struct memory_map memmap;
130
+	unsigned int rm_ds_top;
131
+	unsigned int rm_cs_top;
132
+	unsigned int fbms;
126 133
 
127 134
 	/* Dump memory map before mangling */
128 135
 	DBG ( "Hiding gPXE from system memory map\n" );
@@ -133,6 +140,26 @@ static void hide_etherboot ( void ) {
133 140
 	hide_umalloc ( virt_to_phys ( _text ), virt_to_phys ( _text ) );
134 141
 	hide_text();
135 142
 
143
+	/* Some really moronic BIOSes bring up the PXE stack via the
144
+	 * UNDI loader entry point and then don't bother to unload it
145
+	 * before overwriting the code and data segments.  If this
146
+	 * happens, we really don't want to leave INT 15 hooked,
147
+	 * because that will cause any loaded OS to die horribly as
148
+	 * soon as it attempts to fetch the system memory map.
149
+	 *
150
+	 * We use a heuristic to guess whether or not we are being
151
+	 * loaded sensibly.
152
+	 */
153
+	rm_cs_top = ( ( ( rm_cs << 4 ) + _text16_size + 1024 - 1 ) >> 10 );
154
+	rm_ds_top = ( ( ( rm_ds << 4 ) + _data16_size + 1024 - 1 ) >> 10 );
155
+	fbms = get_fbms();
156
+	if ( ( rm_cs_top < fbms ) && ( rm_ds_top < fbms ) ) {
157
+		DBG ( "Detected potentially unsafe UNDI load at CS=%04x "
158
+		      "DS=%04x FBMS=%dkB\n", rm_cs, rm_ds, fbms );
159
+		DBG ( "Disabling INT 15 memory hiding\n" );
160
+		return;
161
+	}
162
+
136 163
 	/* Hook INT 15 */
137 164
 	hook_bios_interrupt ( 0x15, ( unsigned int ) int15,
138 165
 			      &int15_vector );

Loading…
취소
저장