From 1c0241059f70e035cc1189d2bbc55ebf16dcc1d6 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Mon, 18 Jul 2011 10:10:22 +0800 Subject: [PATCH] Kernel - Fixed a possible infinite loop in VFS_ParsePath - Restricted paths from symlinks to MAX_PATH_LEN characters (255 atm) --- Kernel/vfs/open.c | 67 ++++++++++++++++++++++++----------------------- 1 file changed, 34 insertions(+), 33 deletions(-) diff --git a/Kernel/vfs/open.c b/Kernel/vfs/open.c index 5d1d9fa7..02c9266f 100644 --- a/Kernel/vfs/open.c +++ b/Kernel/vfs/open.c @@ -11,6 +11,8 @@ // === CONSTANTS === #define OPEN_MOUNT_ROOT 1 #define MAX_PATH_SLASHES 256 +#define MAX_NESTED_LINKS 4 +#define MAX_PATH_LEN 255 // === IMPORTS === extern tVFS_Node gVFS_MemRoot; @@ -167,12 +169,13 @@ char *VFS_GetAbsPath(const char *Path) */ tVFS_Node *VFS_ParsePath(const char *Path, char **TruePath) { - tVFS_Mount *mnt; - tVFS_Mount *longestMount = gVFS_RootMount; // Root is first + tVFS_Mount *mnt, *longestMount; int cmp, retLength = 0; int ofs, nextSlash; + int iNestedLinks = 0; tVFS_Node *curNode, *tmpNode; char *tmp; + char path_buffer[MAX_PATH_LEN+1]; ENTER("sPath pTruePath", Path, TruePath); @@ -186,7 +189,8 @@ tVFS_Node *VFS_ParsePath(const char *Path, char **TruePath) LEAVE('p', curNode); return curNode; } - + +restart_parse: // For root we always fast return if(Path[0] == '/' && Path[1] == '\0') { if(TruePath) { @@ -197,13 +201,14 @@ tVFS_Node *VFS_ParsePath(const char *Path, char **TruePath) return gVFS_RootMount->RootNode; } - // Check if there is an`ything mounted + // Check if there is anything mounted if(!gVFS_Mounts) { Warning("WTF! There's nothing mounted?"); return NULL; } // Find Mountpoint + longestMount = gVFS_RootMount; for(mnt = gVFS_Mounts; mnt; mnt = mnt->Next) @@ -240,7 +245,8 @@ tVFS_Node *VFS_ParsePath(const char *Path, char **TruePath) // Initialise String if(TruePath) { - *TruePath = malloc( mnt->MountPointLen+1 ); + // Assumes that the resultant path (here) will not be > strlen(Path) + 1 + *TruePath = malloc( strlen(Path) + 1 ); strcpy(*TruePath, mnt->MountPoint); retLength = mnt->MountPointLen; } @@ -315,44 +321,39 @@ tVFS_Node *VFS_ParsePath(const char *Path, char **TruePath) Warning("VFS_ParsePath - Read of node %p is NULL (%s)", curNode, Path); if(curNode->Close) curNode->Close(curNode); - // No need to free *TruePath, see above + // No need to free *TruePath, it should already be NULL LEAVE('n'); return NULL; } - tmp = malloc( curNode->Size + 1 ); - if(!tmp) { - Log_Warning("VFS", "VFS_ParsePath - Malloc failure"); - // No need to free *TruePath, see above + if(iNestedLinks > MAX_NESTED_LINKS) { + if(curNode->Close) curNode->Close(curNode); LEAVE('n'); return NULL; } - curNode->Read( curNode, 0, curNode->Size, tmp ); - tmp[ curNode->Size ] = '\0'; // Parse Symlink Path - curNode = VFS_ParsePath(tmp, TruePath); - if(TruePath) - LOG("VFS", "*TruePath='%s'", *TruePath); - - // Error Check - if(!curNode) { - Log_Debug("VFS", "Symlink fail '%s'", tmp); - free(tmp); // Free temp string - if(TruePath) free(TruePath); - LEAVE('n'); - return NULL; + // - Just update the path variable and restart the function + // > Count nested symlinks and limit to some value (counteracts loops) + { + int remlen = strlen(Path) - (ofs + nextSlash); + if( curNode->Size + remlen > MAX_PATH_LEN ) { + if(curNode->Close) curNode->Close(curNode); + Log_Warning("VFS", "VFS_ParsePath - Symlinked path too long"); + LEAVE('n'); + return NULL; + } + curNode->Read( curNode, 0, curNode->Size, path_buffer ); + path_buffer[ curNode->Size ] = '\0'; + strcat(path_buffer, &Path[ofs+nextSlash]); + + Path = path_buffer; + iNestedLinks ++; } - // Free temp link - free(tmp); - - // Set Path Variable - if(TruePath) { - retLength = strlen(*TruePath); - } - - continue; + + // EVIL: Goto :) + goto restart_parse; } // Handle Non-Directories @@ -421,7 +422,7 @@ tVFS_Node *VFS_ParsePath(const char *Path, char **TruePath) tmp = realloc(*TruePath, retLength + strlen(&Path[ofs]) + 1 + 1); // Check if allocation succeeded if(!tmp) { - Warning("VFS_ParsePath - Unable to reallocate true path buffer"); + Log_Warning("VFS", "VFS_ParsePath - Unable to reallocate true path buffer"); free(*TruePath); if(tmpNode->Close) tmpNode->Close(curNode); LEAVE('n'); -- 2.20.1