Skip to content

Commit a0de49d

Browse files
ZideChen0wenlingz
authored andcommitted
hv: fix potential buffer overflow in sbl_init_vm_boot_info()
To merge the multiboot bootargs within sbl_init_vm_boot_info(), buffer overflow could happen when it doesn't provide correct 'dmax' argument to strncpy_s(). Also, currently it doesn't check the availability of the dest buffer before overwriting '\0' with a whitespace, which theoretically the dest string could end up with no null terminator within it's array boundary. This patch also creates a separate function to merge the cmdline strings, because after the above fixes some lines in sbl_init_vm_boot_info() function could have up to 7 tabs in front of the first character, which looks messy and sbl_init_vm_boot_info() is getting too complicated. Tracked-On: #2806 Signed-off-by: Zide Chen <zide.chen@intel.com> Acked-by: Anthony Xu <anthony.xu@intel.com> Reviewed-by: Eddie Dong <eddie.dong@intel.com>
1 parent 93ed2af commit a0de49d

File tree

1 file changed

+46
-25
lines changed

1 file changed

+46
-25
lines changed

hypervisor/boot/sbl/multiboot.c

Lines changed: 46 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,48 @@ static void parse_other_modules(struct acrn_vm *vm, const struct multiboot_modul
8282
}
8383
}
8484

85+
/**
86+
* @pre vm != NULL && cmdline != NULL && cmdstr != NULL
87+
*/
88+
static void merge_cmdline(const struct acrn_vm *vm, const char *cmdline, const char *cmdstr)
89+
{
90+
char *cmd_dst = kernel_cmdline;
91+
uint32_t cmdline_len, cmdstr_len;
92+
uint32_t dst_avail; /* available room for cmd_dst[] */
93+
uint32_t dst_len; /* the actual number of characters that are copied */
94+
95+
/*
96+
* Append seed argument for SOS
97+
* seed_arg string ends with a white space and '\0', so no aditional delimiter is needed
98+
*/
99+
append_seed_arg(cmd_dst, is_sos_vm(vm));
100+
dst_len = strnlen_s(cmd_dst, MEM_2K);
101+
dst_avail = MEM_2K + 1U - dst_len;
102+
cmd_dst += dst_len;
103+
104+
cmdline_len = strnlen_s(cmdline, MEM_2K);
105+
cmdstr_len = strnlen_s(cmdstr, MEM_2K);
106+
107+
/* reserve one character for the delimiter between 2 strings (one white space) */
108+
if ((cmdline_len + cmdstr_len + 1U) >= dst_avail) {
109+
panic("Multiboot bootarg string too long");
110+
} else {
111+
/* copy mbi->mi_cmdline */
112+
(void)strncpy_s(cmd_dst, dst_avail, cmdline, cmdline_len);
113+
dst_len = strnlen_s(cmd_dst, dst_avail);
114+
dst_avail -= dst_len;
115+
cmd_dst += dst_len;
116+
117+
/* overwrite '\0' with a white space */
118+
(void)strncpy_s(cmd_dst, dst_avail, " ", 1U);
119+
dst_avail -= 1U;
120+
cmd_dst += 1U;
121+
122+
/* copy mods[].mm_string */
123+
(void)strncpy_s(cmd_dst, dst_avail, cmdstr, cmdstr_len);
124+
}
125+
}
126+
85127
static void *get_kernel_load_addr(void *kernel_src_addr)
86128
{
87129
struct zero_page *zeropage;
@@ -155,34 +197,13 @@ int32_t sbl_init_vm_boot_info(struct acrn_vm *vm)
155197
vm->sw.kernel_info.kernel_load_addr =
156198
get_kernel_load_addr(vm->sw.kernel_info.kernel_src_addr);
157199

158-
/*
159-
* If there is cmdline from mbi->mi_cmdline, merge it with
160-
* mods[0].mm_string
161-
*/
162200
if ((mbi->mi_flags & MULTIBOOT_INFO_HAS_CMDLINE) != 0U) {
163-
char *cmd_src, *cmd_dst;
164-
uint32_t off = 0U;
165-
166-
cmd_dst = kernel_cmdline;
167-
cmd_src = (char *)hpa2hva((uint64_t)mbi->mi_cmdline);
168-
169201
/*
170-
* Append seed argument for SOS
202+
* If there is cmdline from mbi->mi_cmdline, merge it with
203+
* mods[0].mm_string
171204
*/
172-
append_seed_arg(cmd_dst, is_sos_vm(vm));
173-
off = strnlen_s(cmd_dst, MEM_2K);
174-
175-
cmd_dst += off;
176-
(void)strncpy_s(cmd_dst, MEM_2K + 1U - off, (const char *)cmd_src,
177-
strnlen_s(cmd_src, MEM_2K - off));
178-
off = strnlen_s(cmd_dst, MEM_2K - off);
179-
cmd_dst[off] = ' '; /* insert space */
180-
off += 1U;
181-
182-
cmd_dst += off;
183-
cmd_src = (char *)hpa2hva((uint64_t)mods[0].mm_string);
184-
(void)strncpy_s(cmd_dst, MEM_2K + 1U - off, cmd_src,
185-
strnlen_s(cmd_src, MEM_2K - off));
205+
merge_cmdline(vm, hpa2hva((uint64_t)mbi->mi_cmdline),
206+
hpa2hva((uint64_t)mods[0].mm_string));
186207

187208
vm->sw.linux_info.bootargs_src_addr = kernel_cmdline;
188209
vm->sw.linux_info.bootargs_size = strnlen_s(kernel_cmdline, MEM_2K);

0 commit comments

Comments
 (0)