Add input validation to iosuhax

== DETAILS

I believe this should (at least partially) resolve #6025.

In my own testing, I haven't been able to reproduce the DSI error,
but I have encountered the black-screen crashes and could reliably
(but not predictably) reproduce the crash by simply switching
between cores.

Looking at the DSI error, the crash occurs within iosuhax. So, I looked
at that code.. and basically none of the input pointers are validated.

Yikes.

This commit adds pointer sanity checking to all of the iosuhax code.

== TESTING

When I did a test build, I noticed two things:

1. No more black screen crashes!
2. In lieu of the crash, it looks like the network logging dies. RA itself
   seems to continue working just fine.
This commit is contained in:
gblues 2018-01-06 14:37:36 -08:00
parent 9b52164b00
commit f9b548492e
3 changed files with 232 additions and 10 deletions

View File

@ -101,6 +101,9 @@ int IOSUHAX_memwrite(uint32_t address, const uint8_t * buffer, uint32_t size)
if(iosuhaxHandle < 0)
return iosuhaxHandle;
if(!buffer)
return -1;
uint32_t *io_buf = (uint32_t*)memalign(0x20, size + 4);
if(!io_buf)
return -2;
@ -119,6 +122,9 @@ int IOSUHAX_memread(uint32_t address, uint8_t * out_buffer, uint32_t size)
if(iosuhaxHandle < 0)
return iosuhaxHandle;
if(!out_buffer || !size)
return -1;
return IOS_Ioctl(iosuhaxHandle, IOCTL_MEM_READ, &address, sizeof(address), out_buffer, size);
}
@ -127,6 +133,9 @@ int IOSUHAX_memcpy(uint32_t dst, uint32_t src, uint32_t size)
if(iosuhaxHandle < 0)
return iosuhaxHandle;
if(!dst || !src || !size)
return -1;
uint32_t io_buf[3];
io_buf[0] = dst;
io_buf[1] = src;
@ -190,6 +199,9 @@ int IOSUHAX_FSA_Mount(int fsaFd, const char* device_path, const char* volume_pat
if(iosuhaxHandle < 0)
return iosuhaxHandle;
if(!device_path || !volume_path || !arg_string)
return -1;
const int input_cnt = 6;
int io_buf_size = (sizeof(uint32_t) * input_cnt) + strlen(device_path) + strlen(volume_path) + arg_string_len + 3;
@ -230,6 +242,9 @@ int IOSUHAX_FSA_Unmount(int fsaFd, const char* path, uint32_t flags)
if(iosuhaxHandle < 0)
return iosuhaxHandle;
if(!path)
return -1;
const int input_cnt = 3;
int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(path) + 1;
@ -261,6 +276,9 @@ int IOSUHAX_FSA_FlushVolume(int fsaFd, const char *volume_path)
if(iosuhaxHandle < 0)
return iosuhaxHandle;
if(!volume_path)
return -1;
const int input_cnt = 2;
int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(volume_path) + 1;
@ -291,6 +309,9 @@ int IOSUHAX_FSA_GetDeviceInfo(int fsaFd, const char* device_path, int type, uint
if(iosuhaxHandle < 0)
return iosuhaxHandle;
if(!device_path || !out_data)
return -1;
const int input_cnt = 3;
int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(device_path) + 1;
@ -323,6 +344,9 @@ int IOSUHAX_FSA_MakeDir(int fsaFd, const char* path, uint32_t flags)
if(iosuhaxHandle < 0)
return iosuhaxHandle;
if(!path)
return -1;
const int input_cnt = 3;
int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(path) + 1;
@ -353,6 +377,9 @@ int IOSUHAX_FSA_OpenDir(int fsaFd, const char* path, int* outHandle)
if(iosuhaxHandle < 0)
return iosuhaxHandle;
if(!path)
return -1;
const int input_cnt = 2;
int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(path) + 1;
@ -384,6 +411,9 @@ int IOSUHAX_FSA_ReadDir(int fsaFd, int handle, directoryEntry_s* out_data)
if(iosuhaxHandle < 0)
return iosuhaxHandle;
if(!out_data)
return -1;
const int input_cnt = 2;
int io_buf_size = sizeof(uint32_t) * input_cnt;
@ -481,6 +511,9 @@ int IOSUHAX_FSA_ChangeDir(int fsaFd, const char *path)
if(iosuhaxHandle < 0)
return iosuhaxHandle;
if(!path)
return -1;
const int input_cnt = 2;
int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(path) + 1;
@ -511,6 +544,9 @@ int IOSUHAX_FSA_OpenFile(int fsaFd, const char* path, const char* mode, int* out
if(iosuhaxHandle < 0)
return iosuhaxHandle;
if(!path || !mode || !outHandle)
return -1;
const int input_cnt = 3;
int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(path) + strlen(mode) + 2;
@ -544,6 +580,9 @@ int IOSUHAX_FSA_ReadFile(int fsaFd, void* data, uint32_t size, uint32_t cnt, int
if(iosuhaxHandle < 0)
return iosuhaxHandle;
if(!data)
return -1;
const int input_cnt = 5;
int io_buf_size = sizeof(uint32_t) * input_cnt;
@ -590,6 +629,9 @@ int IOSUHAX_FSA_WriteFile(int fsaFd, const void* data, uint32_t size, uint32_t c
if(iosuhaxHandle < 0)
return iosuhaxHandle;
if(!data)
return -1;
const int input_cnt = 5;
int io_buf_size = ((sizeof(uint32_t) * input_cnt + size * cnt + 0x40) + 0x3F) & ~0x3F;
@ -623,6 +665,9 @@ int IOSUHAX_FSA_StatFile(int fsaFd, int fileHandle, fileStat_s* out_data)
if(iosuhaxHandle < 0)
return iosuhaxHandle;
if(!out_data)
return -1;
const int input_cnt = 2;
int io_buf_size = sizeof(uint32_t) * input_cnt;
@ -722,6 +767,9 @@ int IOSUHAX_FSA_GetStat(int fsaFd, const char *path, fileStat_s* out_data)
if(iosuhaxHandle < 0)
return iosuhaxHandle;
if(!path || !out_data)
return -1;
const int input_cnt = 2;
int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(path) + 1;
@ -763,6 +811,9 @@ int IOSUHAX_FSA_Remove(int fsaFd, const char *path)
if(iosuhaxHandle < 0)
return iosuhaxHandle;
if(!path)
return -1;
const int input_cnt = 2;
int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(path) + 1;
@ -793,6 +844,9 @@ int IOSUHAX_FSA_ChangeMode(int fsaFd, const char* path, int mode)
if(iosuhaxHandle < 0)
return iosuhaxHandle;
if(!path)
return -1;
const int input_cnt = 3;
int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(path) + 1;
@ -824,6 +878,9 @@ int IOSUHAX_FSA_RawOpen(int fsaFd, const char* device_path, int* outHandle)
if(iosuhaxHandle < 0)
return iosuhaxHandle;
if(!device_path && !outHandle)
return -1;
const int input_cnt = 2;
int io_buf_size = sizeof(uint32_t) * input_cnt + strlen(device_path) + 1;
@ -857,6 +914,9 @@ int IOSUHAX_FSA_RawRead(int fsaFd, void* data, uint32_t block_size, uint32_t blo
if(iosuhaxHandle < 0)
return iosuhaxHandle;
if(!data)
return -1;
const int input_cnt = 6;
int io_buf_size = sizeof(uint32_t) * input_cnt;
@ -904,6 +964,9 @@ int IOSUHAX_FSA_RawWrite(int fsaFd, const void* data, uint32_t block_size, uint3
if(iosuhaxHandle < 0)
return iosuhaxHandle;
if(!data)
return -1;
const int input_cnt = 6;
int io_buf_size = ((sizeof(uint32_t) * input_cnt + block_size * block_cnt + 0x40) + 0x3F) & ~0x3F;

View File

@ -63,6 +63,9 @@ static fs_dev_private_t *fs_dev_get_device_data(const char *path)
char name[128] = {0};
int i;
if(!path)
return NULL;
/* Get the device name from the path */
strncpy(name, path, 127);
strtok(name, ":/");
@ -86,7 +89,7 @@ static fs_dev_private_t *fs_dev_get_device_data(const char *path)
static char *fs_dev_real_path (const char *path, fs_dev_private_t *dev)
{
/* Sanity check */
if (!path)
if (!path || !dev)
return NULL;
/* Move the path pointer to the start of the actual path */
@ -108,12 +111,20 @@ static char *fs_dev_real_path (const char *path, fs_dev_private_t *dev)
static int fs_dev_open_r (struct _reent *r, void *fileStruct, const char *path, int flags, int mode)
{
fs_dev_private_t *dev = fs_dev_get_device_data(path);
if(!r)
return -1;
if(!dev) {
r->_errno = ENODEV;
return -1;
}
fs_dev_file_state_t *file = (fs_dev_file_state_t *)fileStruct;
if(!file) {
r->_errno = EINVAL;
return -1;
}
file->dev = dev;
/* Determine which mode the file is opened for */
@ -178,10 +189,18 @@ static int fs_dev_open_r (struct _reent *r, void *fileStruct, const char *path,
return -1;
}
static int fs_dev_close_r (struct _reent *r, void *fd)
{
fs_dev_file_state_t *file = (fs_dev_file_state_t *)fd;
if(!r)
return -1;
if(!file) {
r->_errno = EINVAL;
return -1;
}
if(!file->dev) {
r->_errno = ENODEV;
return -1;
@ -204,6 +223,15 @@ static int fs_dev_close_r (struct _reent *r, void *fd)
static off_t fs_dev_seek_r (struct _reent *r, void* fd, off_t pos, int dir)
{
fs_dev_file_state_t *file = (fs_dev_file_state_t *)fd;
if(!r)
return 0;
if(!file) {
r->_errno = EINVAL;
return 0;
}
if(!file->dev) {
r->_errno = ENODEV;
return 0;
@ -242,6 +270,15 @@ static off_t fs_dev_seek_r (struct _reent *r, void* fd, off_t pos, int dir)
static ssize_t fs_dev_write_r (struct _reent *r, void *fd, const char *ptr, size_t len)
{
fs_dev_file_state_t *file = (fs_dev_file_state_t *)fd;
if(!r)
return 0;
if(!file) {
r->_errno = EINVAL;
return 0;
}
if(!file->dev) {
r->_errno = ENODEV;
return 0;
@ -286,7 +323,16 @@ static ssize_t fs_dev_write_r (struct _reent *r, void *fd, const char *ptr, size
static ssize_t fs_dev_read_r (struct _reent *r, void *fd, char *ptr, size_t len)
{
if(!r)
return 0;
fs_dev_file_state_t *file = (fs_dev_file_state_t *)fd;
if(!file) {
r->_errno = EINVAL;
return 0;
}
if(!file->dev) {
r->_errno = ENODEV;
return 0;
@ -333,6 +379,15 @@ static ssize_t fs_dev_read_r (struct _reent *r, void *fd, char *ptr, size_t len)
static int fs_dev_fstat_r (struct _reent *r, void *fd, struct stat *st)
{
fs_dev_file_state_t *file = (fs_dev_file_state_t *)fd;
if(!r)
return -1;
if(!file) {
r->_errno = EINVAL;
return -1;
}
if(!file->dev) {
r->_errno = ENODEV;
return -1;
@ -371,6 +426,15 @@ static int fs_dev_fstat_r (struct _reent *r, void *fd, struct stat *st)
static int fs_dev_ftruncate_r (struct _reent *r, void *fd, off_t len)
{
fs_dev_file_state_t *file = (fs_dev_file_state_t *)fd;
if(!r)
return -1;
if(!file) {
r->_errno = EINVAL;
return -1;
}
if(!file->dev) {
r->_errno = ENODEV;
return -1;
@ -384,6 +448,15 @@ static int fs_dev_ftruncate_r (struct _reent *r, void *fd, off_t len)
static int fs_dev_fsync_r (struct _reent *r, void *fd)
{
fs_dev_file_state_t *file = (fs_dev_file_state_t *)fd;
if(!r)
return -1;
if(!file) {
r->_errno = EINVAL;
return -1;
}
if(!file->dev) {
r->_errno = ENODEV;
return -1;
@ -397,6 +470,10 @@ static int fs_dev_fsync_r (struct _reent *r, void *fd)
static int fs_dev_stat_r (struct _reent *r, const char *path, struct stat *st)
{
fs_dev_private_t *dev = fs_dev_get_device_data(path);
if(!r)
return -1;
if(!dev) {
r->_errno = ENODEV;
return -1;
@ -447,6 +524,9 @@ static int fs_dev_stat_r (struct _reent *r, const char *path, struct stat *st)
static int fs_dev_link_r (struct _reent *r, const char *existing, const char *newLink)
{
if(!r)
return -1;
r->_errno = ENOTSUP;
return -1;
}
@ -454,6 +534,10 @@ static int fs_dev_link_r (struct _reent *r, const char *existing, const char *ne
static int fs_dev_unlink_r (struct _reent *r, const char *name)
{
fs_dev_private_t *dev = fs_dev_get_device_data(name);
if(!r)
return -1;
if(!dev) {
r->_errno = ENODEV;
return -1;
@ -485,6 +569,10 @@ static int fs_dev_unlink_r (struct _reent *r, const char *name)
static int fs_dev_chdir_r (struct _reent *r, const char *name)
{
fs_dev_private_t *dev = fs_dev_get_device_data(name);
if(!r)
return -1;
if(!dev) {
r->_errno = ENODEV;
return -1;
@ -516,11 +604,20 @@ static int fs_dev_chdir_r (struct _reent *r, const char *name)
static int fs_dev_rename_r (struct _reent *r, const char *oldName, const char *newName)
{
fs_dev_private_t *dev = fs_dev_get_device_data(oldName);
if(!r)
return -1;
if(!dev) {
r->_errno = ENODEV;
return -1;
}
if(!newName) {
r->_errno = EINVAL;
return -1;
}
OSLockMutex(dev->pMutex);
char *real_oldpath = fs_dev_real_path(oldName, dev);
@ -557,6 +654,10 @@ static int fs_dev_rename_r (struct _reent *r, const char *oldName, const char *n
static int fs_dev_mkdir_r (struct _reent *r, const char *path, int mode)
{
fs_dev_private_t *dev = fs_dev_get_device_data(path);
if(!r)
return -1;
if(!dev) {
r->_errno = ENODEV;
return -1;
@ -588,6 +689,10 @@ static int fs_dev_mkdir_r (struct _reent *r, const char *path, int mode)
static int fs_dev_chmod_r (struct _reent *r, const char *path, int mode)
{
fs_dev_private_t *dev = fs_dev_get_device_data(path);
if(!r)
return -1;
if(!dev) {
r->_errno = ENODEV;
return -1;
@ -619,11 +724,20 @@ static int fs_dev_chmod_r (struct _reent *r, const char *path, int mode)
static int fs_dev_statvfs_r (struct _reent *r, const char *path, struct statvfs *buf)
{
fs_dev_private_t *dev = fs_dev_get_device_data(path);
if(!r)
return -1;
if(!dev) {
r->_errno = ENODEV;
return -1;
}
if(!buf) {
r->_errno = EINVAL;
return -1;
}
OSLockMutex(dev->pMutex);
// Zero out the stat buffer
@ -683,11 +797,20 @@ static int fs_dev_statvfs_r (struct _reent *r, const char *path, struct statvfs
static DIR_ITER *fs_dev_diropen_r (struct _reent *r, DIR_ITER *dirState, const char *path)
{
fs_dev_private_t *dev = fs_dev_get_device_data(path);
if(!r)
return NULL;
if(!dev) {
r->_errno = ENODEV;
return NULL;
}
if(!dirState) {
r->_errno = EINVAL;
return NULL;
}
fs_dev_dir_entry_t *dirIter = (fs_dev_dir_entry_t *)dirState->dirStruct;
OSLockMutex(dev->pMutex);
@ -721,7 +844,18 @@ static DIR_ITER *fs_dev_diropen_r (struct _reent *r, DIR_ITER *dirState, const c
static int fs_dev_dirclose_r (struct _reent *r, DIR_ITER *dirState)
{
fs_dev_dir_entry_t *dirIter = (fs_dev_dir_entry_t *)dirState->dirStruct;
fs_dev_dir_entry_t *dirIter;
if(!r)
return -1;
if(!dirState) {
r->_errno = EINVAL;
return -1;
}
dirIter = (fs_dev_dir_entry_t *)dirState->dirStruct;
if(!dirIter->dev) {
r->_errno = ENODEV;
return -1;
@ -743,7 +877,18 @@ static int fs_dev_dirclose_r (struct _reent *r, DIR_ITER *dirState)
static int fs_dev_dirreset_r (struct _reent *r, DIR_ITER *dirState)
{
fs_dev_dir_entry_t *dirIter = (fs_dev_dir_entry_t *)dirState->dirStruct;
fs_dev_dir_entry_t *dirIter;
if(!r)
return -1;
if(!dirState) {
r->_errno = EINVAL;
return -1;
}
dirIter = (fs_dev_dir_entry_t *)dirState->dirStruct;
if(!dirIter->dev) {
r->_errno = ENODEV;
return -1;
@ -765,7 +910,18 @@ static int fs_dev_dirreset_r (struct _reent *r, DIR_ITER *dirState)
static int fs_dev_dirnext_r (struct _reent *r, DIR_ITER *dirState, char *filename, struct stat *st)
{
fs_dev_dir_entry_t *dirIter = (fs_dev_dir_entry_t *)dirState->dirStruct;
fs_dev_dir_entry_t *dirIter;
if(!r)
return -1;
if(!dirState) {
r->_errno = EINVAL;
return -1;
}
dirIter = (fs_dev_dir_entry_t *)dirState->dirStruct;
if(!dirIter->dev) {
r->_errno = ENODEV;
return -1;
@ -845,7 +1001,7 @@ static int fs_dev_add_device (const char *name, const char *mount_path, int fsaF
int i;
// Sanity check
if (!name) {
if (!name || !mount_path) {
errno = EINVAL;
return -1;
}
@ -915,6 +1071,9 @@ static int fs_dev_remove_device (const char *path)
char name[128] = {0};
int i;
if(!path)
return -1;
// Get the device name from the path
strncpy(name, path, 127);
strtok(name, ":/");

View File

@ -141,7 +141,7 @@ static bool IOSUHAX_sdio_shutdown(void)
static bool IOSUHAX_sdio_readSectors(uint32_t sector, uint32_t numSectors, void* buffer)
{
if(!IOSUHAX_sdio_isInserted())
if(!IOSUHAX_sdio_isInserted() || !buffer)
return false;
int res = IOSUHAX_FSA_RawRead(fsaFdSd, buffer, 512, numSectors, sector, sdioFd);
@ -155,7 +155,7 @@ static bool IOSUHAX_sdio_readSectors(uint32_t sector, uint32_t numSectors, void*
static bool IOSUHAX_sdio_writeSectors(uint32_t sector, uint32_t numSectors, const void* buffer)
{
if(!IOSUHAX_sdio_isInserted())
if(!IOSUHAX_sdio_isInserted() || !buffer)
return false;
int res = IOSUHAX_FSA_RawWrite(fsaFdSd, buffer, 512, numSectors, sector, sdioFd);
@ -223,7 +223,7 @@ static bool IOSUHAX_usb_shutdown(void)
static bool IOSUHAX_usb_readSectors(uint32_t sector, uint32_t numSectors, void* buffer)
{
if(!IOSUHAX_usb_isInserted())
if(!IOSUHAX_usb_isInserted() || !buffer)
return false;
int res = IOSUHAX_FSA_RawRead(fsaFdUsb, buffer, 512, numSectors, sector, usbFd);
@ -237,7 +237,7 @@ static bool IOSUHAX_usb_readSectors(uint32_t sector, uint32_t numSectors, void*
static bool IOSUHAX_usb_writeSectors(uint32_t sector, uint32_t numSectors, const void* buffer)
{
if(!IOSUHAX_usb_isInserted())
if(!IOSUHAX_usb_isInserted() || !buffer)
return false;
int res = IOSUHAX_FSA_RawWrite(fsaFdUsb, buffer, 512, numSectors, sector, usbFd);