Skip to content

Commit 1925e0a

Browse files
author
Benjamin Fogle
committed
Replace magic numbers with constants in linux.rs
1 parent 9ed8d0a commit 1925e0a

File tree

1 file changed

+49
-16
lines changed

1 file changed

+49
-16
lines changed

mythril/src/linux.rs

+49-16
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,45 @@ use crate::virtdev::qemu_fw_cfg::{FwCfgSelector, QemuFwCfgBuilder};
44
use bitflags::bitflags;
55
use byteorder::{ByteOrder, LittleEndian};
66

7+
// These come mostly from https://www.kernel.org/doc/Documentation/x86/boot.txt
8+
mod offsets {
9+
use core::ops::Range;
10+
pub const OLD_CMD_LINE_MAGIC: Range<usize> = 0x20..0x22;
11+
pub const SETUP_SECTS: usize = 0x1f1;
12+
pub const OLD_CMD_LINE_OFFSET: Range<usize> = 0x22..0x24;
13+
pub const HEADER_MAGIC: Range<usize> = 0x202..0x206;
14+
pub const BOOTP_VERSION: Range<usize> = 0x206..0x208;
15+
pub const TYPE_OF_LOADER: usize = 0x210;
16+
pub const LOAD_FLAGS: usize = 0x211;
17+
pub const RAMDISK_IMAGE: Range<usize> = 0x218..0x21c;
18+
pub const RAMDISK_SIZE: Range<usize> = 0x21c..0x220;
19+
pub const HEAP_END_PTR: Range<usize> = 0x224..0x226;
20+
pub const CMD_LINE_PTR: Range<usize> = 0x228..0x22c;
21+
pub const INITRD_ADDR_MAX: Range<usize> = 0x22c..0x230;
22+
pub const XLOAD_FLAGS: Range<usize> = 0x236..0x238;
23+
}
24+
25+
const HEADER_MAGIC_VALUE: u32 = 0x53726448; // "HdrS"
26+
const OLD_CMD_LINE_MAGIC_VALUE: u16 = 0xa33f;
27+
const QEMU_LOADER: u8 = 0xb0;
28+
729
// This blob is taken from QEMU. See:
830
// https://github.com/qemu/qemu/blob/887adde81d1f1f3897f1688d37ec6851b4fdad86/pc-bios/optionrom/linuxboot_dma.c
931
pub const LINUXBOOT_DMA_ROM: &'static [u8] =
1032
include_bytes!("blob/linuxboot_dma.bin");
1133

1234
bitflags! {
13-
pub struct XLoadFlags: u32 {
35+
pub struct LoadFlags: u8 {
36+
const LOADED_HIGH = 1 << 0;
37+
const KASLR = 1 << 1;
38+
const QUIET = 1 << 5;
39+
const KEEP_SEGMENTS = 1 << 6;
40+
const CAN_USE_HEAP = 1 << 7;
41+
}
42+
}
43+
44+
bitflags! {
45+
pub struct XLoadFlags: u16 {
1446
const KERNEL_64 = 1 << 0;
1547
const CAN_BE_LOADED_ABOVE_4G = 1 << 1;
1648
const EFI_HANDOVER_32 = 1 << 2;
@@ -56,19 +88,19 @@ pub fn load_linux(
5688
)));
5789
}
5890

59-
let magic = LittleEndian::read_u32(&kernel[0x202..0x202 + 4]);
91+
let magic = LittleEndian::read_u32(&kernel[offsets::HEADER_MAGIC]);
6092

6193
// HdrS
62-
if magic != 0x53726448 {
94+
if magic != HEADER_MAGIC_VALUE {
6395
return Err(Error::InvalidValue(format!(
6496
"Invalid kernel image (bad magic = 0x{:x})",
6597
magic
6698
)));
6799
}
68100

69-
let protocol = LittleEndian::read_u16(&kernel[0x206..0x206 + 2]);
101+
let protocol = LittleEndian::read_u16(&kernel[offsets::BOOTP_VERSION]);
70102
let (real_addr, cmdline_addr, prot_addr) =
71-
if protocol < 0x200 || (kernel[0x211] & 0x01) == 0 {
103+
if protocol < 0x200 || (kernel[offsets::LOAD_FLAGS] & LoadFlags::LOADED_HIGH.bits()) == 0 {
72104
(0x90000, 0x9a000 - cmdline.len() as i32, 0x10000)
73105
} else if protocol < 0x202 {
74106
(0x90000, 0x9a000 - cmdline.len() as i32, 0x100000)
@@ -79,13 +111,13 @@ pub fn load_linux(
79111
info!("Protocol = 0x{:x}", protocol);
80112

81113
let mut initrd_max = if protocol >= 0x20c
82-
&& (LittleEndian::read_u32(&kernel[0x236..0x236 + 4])
114+
&& (LittleEndian::read_u16(&kernel[offsets::XLOAD_FLAGS])
83115
& XLoadFlags::CAN_BE_LOADED_ABOVE_4G.bits())
84116
!= 0
85117
{
86118
0xffffffff
87119
} else if protocol >= 0x203 {
88-
LittleEndian::read_u32(&kernel[0x22c..0x22c + 4])
120+
LittleEndian::read_u32(&kernel[offsets::INITRD_ADDR_MAX])
89121
} else {
90122
0x37ffffff
91123
};
@@ -101,11 +133,12 @@ pub fn load_linux(
101133
builder.add_i32(FwCfgSelector::CMDLINE_SIZE, cmdline.len() as i32);
102134

103135
if protocol >= 0x202 {
104-
LittleEndian::write_i32(&mut kernel[0x228..0x228 + 4], cmdline_addr);
136+
LittleEndian::write_i32(&mut kernel[offsets::CMD_LINE_PTR], cmdline_addr);
105137
} else {
106-
LittleEndian::write_u16(&mut kernel[0x20..0x20 + 2], 0xa33f);
138+
LittleEndian::write_u16(&mut kernel[offsets::OLD_CMD_LINE_MAGIC],
139+
OLD_CMD_LINE_MAGIC_VALUE);
107140
LittleEndian::write_i16(
108-
&mut kernel[0x22..0x22 + 2],
141+
&mut kernel[offsets::OLD_CMD_LINE_OFFSET],
109142
(cmdline_addr - real_addr) as i16,
110143
);
111144
}
@@ -115,14 +148,14 @@ pub fn load_linux(
115148
// loader type
116149
// TODO: change this from QEMU probably
117150
if protocol >= 0x200 {
118-
kernel[0x210] = 0xB0;
151+
kernel[offsets::TYPE_OF_LOADER] = QEMU_LOADER;
119152
}
120153

121154
// Heap
122155
if protocol >= 0x201 {
123-
kernel[0x211] |= 0x80;
156+
kernel[offsets::LOAD_FLAGS] |= LoadFlags::CAN_USE_HEAP.bits();
124157
LittleEndian::write_i16(
125-
&mut kernel[0x224..0x224 + 2],
158+
&mut kernel[offsets::HEAP_END_PTR],
126159
(cmdline_addr - real_addr - 0x200) as i16,
127160
);
128161
}
@@ -145,13 +178,13 @@ pub fn load_linux(
145178
builder.add_i32(FwCfgSelector::INITRD_ADDR, initrd_addr);
146179
builder.add_i32(FwCfgSelector::INITRD_SIZE, initramfs.len() as i32);
147180
builder.add_bytes(FwCfgSelector::INITRD_DATA, initramfs);
148-
LittleEndian::write_i32(&mut kernel[0x218..0x218 + 4], initrd_addr);
181+
LittleEndian::write_i32(&mut kernel[offsets::RAMDISK_IMAGE], initrd_addr);
149182
LittleEndian::write_i32(
150-
&mut kernel[0x21c..0x21c + 4],
183+
&mut kernel[offsets::RAMDISK_SIZE],
151184
initramfs.len() as i32,
152185
);
153186

154-
let setup_size = match kernel[0x1f1] {
187+
let setup_size = match kernel[offsets::SETUP_SECTS] {
155188
// For legacy compat, setup size 0 is really 4 sectors
156189
0 => 4 + 1,
157190
size => size + 1,

0 commit comments

Comments
 (0)