lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Date: Mon,  1 Apr 2024 11:47:19 +0200
From: Pali Rohár <pali@...nel.org>
To: x86@...nel.org,
	linux-kernel@...r.kernel.org
Subject: [PATCH v2] x86/boot: This program cannot be run in DOS mode.$

There is a well known requirement which everybody knows: Every PE binary
executed in DOS must print legendary and famous message to the computer
screen:

  This program cannot be run in DOS mode.

Linux kernel binary bzImage with enabled config option CONFIG_EFI_STUB is
bootable EFI binary. Every bootable EFI binary is in PE format. So bzImage
is also PE binary, but currently it does not meet that error message
requirement.

So fix this issue by properly filling all fields in the MZ DOS header part
of PE binary. And add a simple code which prints the required message on
the computer screen to fulfil the requirement.

In this case the required message "This program cannot be run in DOS mode."
is not fully truth as for example LOADLIN.EXE application can run Linux
kernel from DOS mode. So extend error message and prints additional line:

  Use DOS loader LOADLIN.EXE.

For sure it helps users to know what they should do when they unexpectedly
try to run Linux kernel from DOS mode.

Note that DOS strings are not null-terminated but rather dollar-terminated.
Therefore it is required to pay for printing this error message in $$$.

Signed-off-by: Pali Rohár <pali@...nel.org>

---
Changes in v2:

Due to big popularity of the first version, now after years I'm sending a
second version of this patch. Second version fixes booting issue by not
moving content of PE header (it is not needed now as the PE code after
years evolved) and patch is rebased on the top of the master branch.
---
 arch/x86/boot/header.S | 60 ++++++++++++++++++++++++++++++++++++------
 1 file changed, 52 insertions(+), 8 deletions(-)

diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S
index b5c79f43359b..b0a8d89b510c 100644
--- a/arch/x86/boot/header.S
+++ b/arch/x86/boot/header.S
@@ -42,14 +42,58 @@ SYSSEG		= 0x1000		/* historical load address >> 4 */
 	.code16
 	.section ".bstext", "ax"
 #ifdef CONFIG_EFI_STUB
-	# "MZ", MS-DOS header
-	.word	MZ_MAGIC
-	.org	0x38
-	#
-	# Offset to the PE header.
-	#
-	.long	LINUX_PE_MAGIC
-	.long	pe_header
+dos_header:
+	# "MZ", DOS header
+	.word	MZ_MAGIC                        # e_magic - Magic number
+	.word	(pe_header-dos_header)%512      # e_cblp - Bytes on last page of file
+	.word	(pe_header-dos_header+511)/512  # e_cp - Pages in file
+	.word	0                               # e_crlc - Relocations
+	.word	(dos_start-dos_header+15)/16    # e_cparhdr - Size of header in paragraphs
+	.word	0                               # e_minalloc - Minimum extra paragraphs needed
+	.word	0xffff                          # e_maxalloc - Maximum extra paragraphs needed
+	.word	0                               # e_ss - Initial (relative) SS value
+	.word	0xb8                            # e_sp - Initial SP value
+	.word	0                               # e_csum - Checksum
+	.word	0                               # e_ip - Initial IP value
+	.word	0                               # e_cs - Initial (relative) CS value
+	.word	dos_start-dos_header            # e_lfarlc - File address of relocation table
+	.word	0                               # e_ovno - Overlay number
+	.word	1                               # e_ver - Linker version, 1 for DOS compatibility
+	.word	0                               # e_res[1] - reserved
+	.word	0                               # e_flags - Old exe header flags, behavior bits
+	.word	0                               # e_res[3] - reserved
+	.word	0                               # e_oemid - OEM identifier
+	.word	0                               # e_oeminfo - OEM information
+	.word	0                               # e_res2[0] - reserved
+	.word	0                               # e_res2[1] - reserved
+	.word	0                               # e_res2[2] - reserved
+	.word	0                               # e_res2[3] - reserved
+	.word	0                               # e_res2[4] - reserved
+	.word	0                               # e_res2[5] - reserved
+	.word	0                               # e_res2[6] - reserved
+	.word	0                               # e_res2[7] - reserved
+	.long	LINUX_PE_MAGIC                  # e_res2[8], e_res2[9] - unknown
+	.long	pe_header-dos_header            # e_lfanew - File address of new exe header
+
+	# DOS start code (must be paragraph aligned)
+	.balign	16, 0
+dos_start:
+	# Print dos_msg string (ds:dx)
+	push	%cs
+	pop	%ds
+	mov	$(dos_msg-dos_start), %dx
+	mov	$0x09, %ah
+	int	$0x21
+
+	# Terminate program
+	mov	$0x4c01, %ax
+	int	$0x21
+
+dos_msg:
+	.ascii	"This program cannot be run in DOS mode.\r\n"
+	.ascii	"Use DOS loader LOADLIN.EXE.\r\r\n"
+	.ascii	"$"
+
 pe_header:
 	.long	PE_MAGIC
 
-- 
2.20.1


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ