Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

efi/libstub/file: Merge file name buffers to reduce stack usage

Arnd reports that commit

9302c1bb8e47 ("efi/libstub: Rewrite file I/O routine")

reworks the file I/O routines in a way that triggers the following
warning:

drivers/firmware/efi/libstub/file.c:240:1: warning: the frame size
of 1200 bytes is larger than 1024 bytes [-Wframe-larger-than=]

We can work around this issue dropping an instance of efi_char16_t[256]
from the stack frame, and reusing the 'filename' field of the file info
struct that we use to obtain file information from EFI (which contains
the file name even though we already know it since we used it to open
the file in the first place)

Reported-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Link: https://lore.kernel.org/r/20200409130434.6736-8-ardb@kernel.org

authored by

Ard Biesheuvel and committed by
Ingo Molnar
464fb126 8b84769a

+14 -13
+14 -13
drivers/firmware/efi/libstub/file.c
··· 29 29 */ 30 30 #define EFI_READ_CHUNK_SIZE SZ_1M 31 31 32 + struct finfo { 33 + efi_file_info_t info; 34 + efi_char16_t filename[MAX_FILENAME_SIZE]; 35 + }; 36 + 32 37 static efi_status_t efi_open_file(efi_file_protocol_t *volume, 33 - efi_char16_t *filename_16, 38 + struct finfo *fi, 34 39 efi_file_protocol_t **handle, 35 40 unsigned long *file_size) 36 41 { 37 - struct { 38 - efi_file_info_t info; 39 - efi_char16_t filename[MAX_FILENAME_SIZE]; 40 - } finfo; 41 42 efi_guid_t info_guid = EFI_FILE_INFO_ID; 42 43 efi_file_protocol_t *fh; 43 44 unsigned long info_sz; 44 45 efi_status_t status; 45 46 46 - status = volume->open(volume, &fh, filename_16, EFI_FILE_MODE_READ, 0); 47 + status = volume->open(volume, &fh, fi->filename, EFI_FILE_MODE_READ, 0); 47 48 if (status != EFI_SUCCESS) { 48 49 pr_efi_err("Failed to open file: "); 49 - efi_char16_printk(filename_16); 50 + efi_char16_printk(fi->filename); 50 51 efi_printk("\n"); 51 52 return status; 52 53 } 53 54 54 - info_sz = sizeof(finfo); 55 - status = fh->get_info(fh, &info_guid, &info_sz, &finfo); 55 + info_sz = sizeof(struct finfo); 56 + status = fh->get_info(fh, &info_guid, &info_sz, fi); 56 57 if (status != EFI_SUCCESS) { 57 58 pr_efi_err("Failed to get file info\n"); 58 59 fh->close(fh); ··· 61 60 } 62 61 63 62 *handle = fh; 64 - *file_size = finfo.info.file_size; 63 + *file_size = fi->info.file_size; 65 64 return EFI_SUCCESS; 66 65 } 67 66 ··· 147 146 148 147 alloc_addr = alloc_size = 0; 149 148 do { 150 - efi_char16_t filename[MAX_FILENAME_SIZE]; 149 + struct finfo fi; 151 150 unsigned long size; 152 151 void *addr; 153 152 154 153 offset = find_file_option(cmdline, cmdline_len, 155 154 optstr, optstr_size, 156 - filename, ARRAY_SIZE(filename)); 155 + fi.filename, ARRAY_SIZE(fi.filename)); 157 156 158 157 if (!offset) 159 158 break; ··· 167 166 return status; 168 167 } 169 168 170 - status = efi_open_file(volume, filename, &file, &size); 169 + status = efi_open_file(volume, &fi, &file, &size); 171 170 if (status != EFI_SUCCESS) 172 171 goto err_close_volume; 173 172