efi_loader: EFI_FILE_PROTOCOL.Write() check args
Check the parameters passed to Write(): * cannot write to directories (UEFI SCT 2017, 5.7.3.5.15) * cannot write to file opened read only (UEFI SCT 2017, 5.7.3.5.16) Add missing comments. Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
This commit is contained in:
parent
2f760735c1
commit
b0f1c728c8
@ -1,8 +1,8 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0+
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
/*
|
/*
|
||||||
* EFI utils
|
* EFI_FILE_PROTOCOL
|
||||||
*
|
*
|
||||||
* Copyright (c) 2017 Rob Clark
|
* Copyright (c) 2017 Rob Clark
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <common.h>
|
#include <common.h>
|
||||||
@ -28,6 +28,7 @@ struct file_handle {
|
|||||||
struct file_system *fs;
|
struct file_system *fs;
|
||||||
loff_t offset; /* current file position/cursor */
|
loff_t offset; /* current file position/cursor */
|
||||||
int isdir;
|
int isdir;
|
||||||
|
u64 open_mode;
|
||||||
|
|
||||||
/* for reading a directory: */
|
/* for reading a directory: */
|
||||||
struct fs_dir_stream *dirs;
|
struct fs_dir_stream *dirs;
|
||||||
@ -161,13 +162,13 @@ static int efi_create_file(struct file_handle *fh, u64 attributes)
|
|||||||
* @file_name: path of the file to be opened. '\', '.', or '..' may
|
* @file_name: path of the file to be opened. '\', '.', or '..' may
|
||||||
* be used as modifiers. A leading backslash indicates an
|
* be used as modifiers. A leading backslash indicates an
|
||||||
* absolute path.
|
* absolute path.
|
||||||
* @mode: bit mask indicating the access mode (read, write,
|
* @open_mode: bit mask indicating the access mode (read, write,
|
||||||
* create)
|
* create)
|
||||||
* @attributes: attributes for newly created file
|
* @attributes: attributes for newly created file
|
||||||
* Returns: handle to the opened file or NULL
|
* Returns: handle to the opened file or NULL
|
||||||
*/
|
*/
|
||||||
static struct efi_file_handle *file_open(struct file_system *fs,
|
static struct efi_file_handle *file_open(struct file_system *fs,
|
||||||
struct file_handle *parent, u16 *file_name, u64 mode,
|
struct file_handle *parent, u16 *file_name, u64 open_mode,
|
||||||
u64 attributes)
|
u64 attributes)
|
||||||
{
|
{
|
||||||
struct file_handle *fh;
|
struct file_handle *fh;
|
||||||
@ -190,6 +191,7 @@ static struct efi_file_handle *file_open(struct file_system *fs,
|
|||||||
/* +2 is for null and '/' */
|
/* +2 is for null and '/' */
|
||||||
fh = calloc(1, sizeof(*fh) + plen + (flen * MAX_UTF8_PER_UTF16) + 2);
|
fh = calloc(1, sizeof(*fh) + plen + (flen * MAX_UTF8_PER_UTF16) + 2);
|
||||||
|
|
||||||
|
fh->open_mode = open_mode;
|
||||||
fh->base = efi_file_handle_protocol;
|
fh->base = efi_file_handle_protocol;
|
||||||
fh->fs = fs;
|
fh->fs = fs;
|
||||||
|
|
||||||
@ -218,9 +220,11 @@ static struct efi_file_handle *file_open(struct file_system *fs,
|
|||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if (!exists) {
|
if (!exists) {
|
||||||
if (!(mode & EFI_FILE_MODE_CREATE) ||
|
if (!(open_mode & EFI_FILE_MODE_CREATE) ||
|
||||||
efi_create_file(fh, attributes))
|
efi_create_file(fh, attributes))
|
||||||
goto error;
|
goto error;
|
||||||
|
if (set_blk_dev(fh))
|
||||||
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* figure out if file is a directory: */
|
/* figure out if file is a directory: */
|
||||||
@ -434,6 +438,19 @@ error:
|
|||||||
return EFI_EXIT(ret);
|
return EFI_EXIT(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* efi_file_write() - write to file
|
||||||
|
*
|
||||||
|
* This function implements the Write() service of the EFI_FILE_PROTOCOL.
|
||||||
|
*
|
||||||
|
* See the Unified Extensible Firmware Interface (UEFI) specification for
|
||||||
|
* details.
|
||||||
|
*
|
||||||
|
* @file: file handle
|
||||||
|
* @buffer_size: number of bytes to write
|
||||||
|
* @buffer: buffer with the bytes to write
|
||||||
|
* Return: status code
|
||||||
|
*/
|
||||||
static efi_status_t EFIAPI efi_file_write(struct efi_file_handle *file,
|
static efi_status_t EFIAPI efi_file_write(struct efi_file_handle *file,
|
||||||
efi_uintn_t *buffer_size,
|
efi_uintn_t *buffer_size,
|
||||||
void *buffer)
|
void *buffer)
|
||||||
@ -444,21 +461,35 @@ static efi_status_t EFIAPI efi_file_write(struct efi_file_handle *file,
|
|||||||
|
|
||||||
EFI_ENTRY("%p, %p, %p", file, buffer_size, buffer);
|
EFI_ENTRY("%p, %p, %p", file, buffer_size, buffer);
|
||||||
|
|
||||||
if (set_blk_dev(fh)) {
|
if (!file || !buffer_size || !buffer) {
|
||||||
ret = EFI_DEVICE_ERROR;
|
ret = EFI_INVALID_PARAMETER;
|
||||||
goto error;
|
goto out;
|
||||||
|
}
|
||||||
|
if (fh->isdir) {
|
||||||
|
ret = EFI_UNSUPPORTED;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (!(fh->open_mode & EFI_FILE_MODE_WRITE)) {
|
||||||
|
ret = EFI_ACCESS_DENIED;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!*buffer_size)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (set_blk_dev(fh)) {
|
||||||
|
ret = EFI_DEVICE_ERROR;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
if (fs_write(fh->path, map_to_sysmem(buffer), fh->offset, *buffer_size,
|
if (fs_write(fh->path, map_to_sysmem(buffer), fh->offset, *buffer_size,
|
||||||
&actwrite)) {
|
&actwrite)) {
|
||||||
ret = EFI_DEVICE_ERROR;
|
ret = EFI_DEVICE_ERROR;
|
||||||
goto error;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
*buffer_size = actwrite;
|
*buffer_size = actwrite;
|
||||||
fh->offset += actwrite;
|
fh->offset += actwrite;
|
||||||
|
|
||||||
error:
|
out:
|
||||||
return EFI_EXIT(ret);
|
return EFI_EXIT(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user