Skip to content

Commit 61d35ce

Browse files
authored
Merge pull request #125 from benfogle/118-clean-up-const-usage
Replace magic numbers with constants in linux.rs
2 parents 9ed8d0a + e30e203 commit 61d35ce

File tree

1 file changed

+62
-23
lines changed

1 file changed

+62
-23
lines changed

mythril/src/linux.rs

+62-23
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,36 +88,37 @@ 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]);
70-
let (real_addr, cmdline_addr, prot_addr) =
71-
if protocol < 0x200 || (kernel[0x211] & 0x01) == 0 {
72-
(0x90000, 0x9a000 - cmdline.len() as i32, 0x10000)
73-
} else if protocol < 0x202 {
74-
(0x90000, 0x9a000 - cmdline.len() as i32, 0x100000)
75-
} else {
76-
(0x10000, 0x20000, 0x100000)
77-
};
101+
let protocol = LittleEndian::read_u16(&kernel[offsets::BOOTP_VERSION]);
102+
let (real_addr, cmdline_addr, prot_addr) = if protocol < 0x200
103+
|| (kernel[offsets::LOAD_FLAGS] & LoadFlags::LOADED_HIGH.bits()) == 0
104+
{
105+
(0x90000, 0x9a000 - cmdline.len() as i32, 0x10000)
106+
} else if protocol < 0x202 {
107+
(0x90000, 0x9a000 - cmdline.len() as i32, 0x100000)
108+
} else {
109+
(0x10000, 0x20000, 0x100000)
110+
};
78111

79112
info!("Protocol = 0x{:x}", protocol);
80113

81114
let mut initrd_max = if protocol >= 0x20c
82-
&& (LittleEndian::read_u32(&kernel[0x236..0x236 + 4])
115+
&& (LittleEndian::read_u16(&kernel[offsets::XLOAD_FLAGS])
83116
& XLoadFlags::CAN_BE_LOADED_ABOVE_4G.bits())
84117
!= 0
85118
{
86119
0xffffffff
87120
} else if protocol >= 0x203 {
88-
LittleEndian::read_u32(&kernel[0x22c..0x22c + 4])
121+
LittleEndian::read_u32(&kernel[offsets::INITRD_ADDR_MAX])
89122
} else {
90123
0x37ffffff
91124
};
@@ -101,11 +134,17 @@ pub fn load_linux(
101134
builder.add_i32(FwCfgSelector::CMDLINE_SIZE, cmdline.len() as i32);
102135

103136
if protocol >= 0x202 {
104-
LittleEndian::write_i32(&mut kernel[0x228..0x228 + 4], cmdline_addr);
137+
LittleEndian::write_i32(
138+
&mut kernel[offsets::CMD_LINE_PTR],
139+
cmdline_addr,
140+
);
105141
} else {
106-
LittleEndian::write_u16(&mut kernel[0x20..0x20 + 2], 0xa33f);
142+
LittleEndian::write_u16(
143+
&mut kernel[offsets::OLD_CMD_LINE_MAGIC],
144+
OLD_CMD_LINE_MAGIC_VALUE,
145+
);
107146
LittleEndian::write_i16(
108-
&mut kernel[0x22..0x22 + 2],
147+
&mut kernel[offsets::OLD_CMD_LINE_OFFSET],
109148
(cmdline_addr - real_addr) as i16,
110149
);
111150
}
@@ -115,14 +154,14 @@ pub fn load_linux(
115154
// loader type
116155
// TODO: change this from QEMU probably
117156
if protocol >= 0x200 {
118-
kernel[0x210] = 0xB0;
157+
kernel[offsets::TYPE_OF_LOADER] = QEMU_LOADER;
119158
}
120159

121160
// Heap
122161
if protocol >= 0x201 {
123-
kernel[0x211] |= 0x80;
162+
kernel[offsets::LOAD_FLAGS] |= LoadFlags::CAN_USE_HEAP.bits();
124163
LittleEndian::write_i16(
125-
&mut kernel[0x224..0x224 + 2],
164+
&mut kernel[offsets::HEAP_END_PTR],
126165
(cmdline_addr - real_addr - 0x200) as i16,
127166
);
128167
}
@@ -145,13 +184,13 @@ pub fn load_linux(
145184
builder.add_i32(FwCfgSelector::INITRD_ADDR, initrd_addr);
146185
builder.add_i32(FwCfgSelector::INITRD_SIZE, initramfs.len() as i32);
147186
builder.add_bytes(FwCfgSelector::INITRD_DATA, initramfs);
148-
LittleEndian::write_i32(&mut kernel[0x218..0x218 + 4], initrd_addr);
187+
LittleEndian::write_i32(&mut kernel[offsets::RAMDISK_IMAGE], initrd_addr);
149188
LittleEndian::write_i32(
150-
&mut kernel[0x21c..0x21c + 4],
189+
&mut kernel[offsets::RAMDISK_SIZE],
151190
initramfs.len() as i32,
152191
);
153192

154-
let setup_size = match kernel[0x1f1] {
193+
let setup_size = match kernel[offsets::SETUP_SECTS] {
155194
// For legacy compat, setup size 0 is really 4 sectors
156195
0 => 4 + 1,
157196
size => size + 1,

0 commit comments

Comments
 (0)