Replace rand() implementation - fixes threading lockups
[tpg/acess2.git] / Kernel / syscalls.c
index 5774dbe..d286d21 100644 (file)
@@ -4,11 +4,20 @@
  */
 #define DEBUG  0
 
-#include <common.h>
+#include <acess.h>
 #include <syscalls.h>
 #include <proc.h>
 #include <errno.h>
 
+#define CHECK_NUM_NULLOK(v,size)       \
+       if((v)&&!Syscall_Valid((size),(Uint)(v))){ret=-1;err=-EINVAL;break;}
+#define CHECK_STR_NULLOK(v)    \
+       if((v)&&!Syscall_ValidString((Uint)(v))){ret=-1;err=-EINVAL;break;}
+#define CHECK_NUM_NONULL(v,size)       \
+       if(!(v)||!Syscall_Valid((size),(Uint)(v))){ret=-1;err=-EINVAL;break;}
+#define CHECK_STR_NONULL(v)    \
+       if(!(v)||!Syscall_ValidString((Uint)(v))){ret=-1;err=-EINVAL;break;}
+
 // === IMPORTS ===
 extern int     Proc_Clone(Uint *Err, Uint Flags);
 extern int     Threads_WaitTID(int TID, int *status);
@@ -16,14 +25,10 @@ extern Uint Proc_SendMessage(Uint *Err, Uint Dest, Uint Length, void *Data);
 extern int     Proc_GetMessage(Uint *Err, Uint *Source, void *Buffer);
 extern int     Proc_Execve(char *File, char **ArgV, char **EnvP);
 extern Uint    Binary_Load(char *file, Uint *entryPoint);
-extern int     VFS_FInfo(int FD, void *Dest, int MaxACLs);
-extern int     VFS_GetACL(int FD, void *Dest);
-extern int     VFS_ChDir(char *Dest);
 extern int     Threads_SetName(char *NewName);
-extern int     Threads_GetPID();
-extern int     Threads_GetTID();
-extern int     Threads_GetUID();
-extern int     Threads_GetGID();
+extern int     Threads_SetUID(Uint *errno, tUID ID);
+extern int     Threads_SetGID(Uint *errno, tGID ID);
+extern int     Threads_SetFaultHandler(Uint Handler);
 
 // === PROTOTYPES ===
  int   Syscall_ValidString(Uint Addr);
@@ -34,12 +39,18 @@ extern int  Threads_GetGID();
 void SyscallHandler(tSyscallRegs *Regs)
 {
        Uint64  ret = 0;
-       Uint    err = 0;
-       #if DEBUG
-       ENTER("iThread iNum", Threads_GetTID(), Regs->Num);
-       if(Regs->Num < NUM_SYSCALLS)
-               LOG("Syscall %s", cSYSCALL_NAMES[Regs->Num]);
-       LOG("Arg1: 0x%x, Arg2: 0x%x, Arg3: 0x%x", Regs->Arg1, Regs->Arg2, Regs->Arg3);
+       Uint    err = -EOK;
+        int    callNum = Regs->Num;
+       
+       #if DEBUG < 2
+       if(callNum != SYS_READ && callNum != SYS_WRITE) {
+       #endif
+       ENTER("iThread iNum", Threads_GetTID(), callNum);
+       if(callNum < NUM_SYSCALLS)
+               LOG("Syscall %s", cSYSCALL_NAMES[callNum]);
+       LOG("Arg1: 0x%x, Arg2: 0x%x, Arg3: 0x%x, Arg4: 0x%x", Regs->Arg1, Regs->Arg2, Regs->Arg3, Regs->Arg4);
+       #if DEBUG < 2
+       }
        #endif
        
        switch(Regs->Num)
@@ -53,6 +64,11 @@ void SyscallHandler(tSyscallRegs *Regs)
        // -- Yield current timeslice
        case SYS_YIELD: Threads_Yield();        break;
        
+       // -- Set Error Handler
+       case SYS_SETFAULTHANDLER:
+               Threads_SetFaultHandler(Regs->Arg1);
+               break;
+       
        // -- Clone the current thread
        case SYS_CLONE:
                // Call clone system call
@@ -70,6 +86,9 @@ void SyscallHandler(tSyscallRegs *Regs)
        
        // -- Wait for a thread
        case SYS_WAITTID:
+               // Sanity Check (Status can be NULL)
+               CHECK_NUM_NULLOK( Regs->Arg2, sizeof(int) );
+               // TID, *Status
                ret = Threads_WaitTID(Regs->Arg1, (void*)Regs->Arg2);
                break;
        
@@ -96,43 +115,78 @@ void SyscallHandler(tSyscallRegs *Regs)
        case SYS_GETGID:        ret = Threads_GetGID(); break;
        
        // -- Set User/Group IDs
-       case SYS_SETUID:        Log("Setting User ID to %i", Regs->Arg1);       break;
-       case SYS_SETGID:        Log("Setting Group ID to %i", Regs->Arg1);      break;
+       case SYS_SETUID:        ret = Threads_SetUID(&err, Regs->Arg1); break;
+       case SYS_SETGID:        ret = Threads_SetGID(&err, Regs->Arg1); break;
        
        // -- Send Message
        case SYS_SENDMSG:
+               CHECK_NUM_NONULL(Regs->Arg3, Regs->Arg2);
+               // Destination, Size, *Data
                ret = Proc_SendMessage(&err, Regs->Arg1, Regs->Arg2, (void*)Regs->Arg3);
                break;
        // -- Check for messages
        case SYS_GETMSG:
+               CHECK_NUM_NULLOK(Regs->Arg1, sizeof(Uint));
+               if( Regs->Arg2 && Regs->Arg2 != -1 && !MM_IsUser(Regs->Arg2) ) {
+                       err = -EINVAL;  ret = -1;       break;
+               }
+               // *Source, *Data
                ret = Proc_GetMessage(&err, (Uint*)Regs->Arg1, (void*)Regs->Arg2);
                break;
        
+       // -- Get the current timestamp
+       case SYS_GETTIME:
+               ret = now();
+               break;
+       
        // -- Set the thread's name
        case SYS_SETNAME:
-               // Sanity Check
-               if(!Regs->Arg1) {       ret = -1;       err = -EINVAL;  break;  }
-               Threads_SetName( (void*)Regs->Arg1 );
+               CHECK_STR_NONULL(Regs->Arg1);
+               Threads_SetName( (char*)Regs->Arg1 );
                break;
        
        // ---
        // Binary Control
        // ---
+       // -- Replace the current process with another
        case SYS_EXECVE:
-               if( !Syscall_ValidString(Regs->Arg1) ) {
-                       err = -EINVAL;
-                       ret = -1;
-                       break;
+               CHECK_STR_NONULL(Regs->Arg1);
+               // Check the argument arrays
+               {
+                        int    i;
+                       char    **tmp = (char**)Regs->Arg2;
+                       // Check ArgV (traverse array checking all string pointers)
+                       CHECK_NUM_NONULL( tmp, sizeof(char**) );
+                       //Log("tmp = %p", tmp);
+                       for(i=0;tmp[i];i++) {
+                               CHECK_NUM_NONULL( &tmp[i], sizeof(char*) );
+                               CHECK_STR_NONULL( tmp[i] );
+                       }
+                       // Check EnvP also
+                       // - EnvP can be NULL
+                       if( Regs->Arg3 )
+                       {
+                               tmp = (char**)Regs->Arg3;
+                               //Log("tmp = %p", tmp);
+                               for(i=0;tmp[i];i++) {
+                                       CHECK_NUM_NULLOK( &tmp[i], sizeof(char*) );
+                                       CHECK_STR_NONULL( tmp[i] );
+                               }
+                       }
                }
-               ret = Proc_Execve((char*)Regs->Arg1, (char**)Regs->Arg2, (char**)Regs->Arg3);
+               LEAVE('s', "Assuming 0");
+               // Path, **Argv, **Envp
+               ret = Proc_Execve( (char*)Regs->Arg1, (char**)Regs->Arg2, (char**)Regs->Arg3 );
                break;
+       // -- Load a binary into the current process
        case SYS_LOADBIN:
                if( !Syscall_ValidString(Regs->Arg1)
                ||  !Syscall_Valid(sizeof(Uint), Regs->Arg2) ) {
                        err = -EINVAL;
-                       ret = -1;
+                       ret = 0;
                        break;
                }
+               // Path, *Entrypoint
                ret = Binary_Load((char*)Regs->Arg1, (Uint*)Regs->Arg2);
                break;
        
@@ -145,36 +199,46 @@ void SyscallHandler(tSyscallRegs *Regs)
                        ret = -1;
                        break;
                }
+               LOG("VFS_Open(\"%s\", 0x%x)", (char*)Regs->Arg1, Regs->Arg2 | VFS_OPENFLAG_USER);
                ret = VFS_Open((char*)Regs->Arg1, Regs->Arg2 | VFS_OPENFLAG_USER);
                break;
        
        case SYS_CLOSE:
+               LOG("VFS_Close(%i)", Regs->Arg1);
                VFS_Close( Regs->Arg1 );
                break;
        
-       case SYS_WRITE:
-               #if BITS < 64
-               ret = VFS_Write( Regs->Arg1, Regs->Arg2|((Uint64)Regs->Arg3<<32), (void*)Regs->Arg4 );
+       case SYS_SEEK:
+               #if BITS == 64
+               ret = VFS_Seek( Regs->Arg1, Regs->Arg2, Regs->Arg3 );
                #else
-               ret = VFS_Write( Regs->Arg1, Regs->Arg2, (void*)Regs->Arg3 );
+               ret = VFS_Seek( Regs->Arg1, Regs->Arg2|(((Uint64)Regs->Arg3)<<32), Regs->Arg4 );
                #endif
                break;
+               
+       case SYS_TELL:
+               ret = VFS_Tell( Regs->Arg1 );
+               break;
+       
+       case SYS_WRITE:
+               CHECK_NUM_NONULL( Regs->Arg3, Regs->Arg2 );
+               ret = VFS_Write( Regs->Arg1, Regs->Arg2, (void*)Regs->Arg3 );
+               break;
        
        case SYS_READ:
-               #if BITS < 64
-               ret = VFS_Read( Regs->Arg1, Regs->Arg2|((Uint64)Regs->Arg3<<32), (void*)Regs->Arg4 );
-               #else
+               CHECK_NUM_NONULL( Regs->Arg3, Regs->Arg2 );
                ret = VFS_Read( Regs->Arg1, Regs->Arg2, (void*)Regs->Arg3 );
-               #endif
                break;
        
        case SYS_FINFO:
+               CHECK_NUM_NONULL( Regs->Arg2, sizeof(tFInfo) + Regs->Arg3*sizeof(tVFS_ACL) );
+               // FP, Dest, MaxACLs
                ret = VFS_FInfo( Regs->Arg1, (void*)Regs->Arg2, Regs->Arg3 );
                break;
        
        // Get ACL Value
        case SYS_GETACL:
-               if( !Syscall_Valid(8, Regs->Arg1) ) {
+               if( !Syscall_Valid(sizeof(tVFS_ACL), Regs->Arg1) ) {
                        err = -EINVAL;
                        ret = -1;
                        break;
@@ -184,7 +248,7 @@ void SyscallHandler(tSyscallRegs *Regs)
        
        // Read Directory
        case SYS_READDIR:
-               if( !Syscall_ValidString(Regs->Arg2) ) {
+               if( !Syscall_Valid(8, Regs->Arg2) ) {
                        err = -EINVAL;
                        ret = -1;
                        break;
@@ -192,6 +256,16 @@ void SyscallHandler(tSyscallRegs *Regs)
                ret = VFS_ReadDir( Regs->Arg1, (void*)Regs->Arg2 );
                break;
        
+       // Open a file that is a entry in an open directory
+       case SYS_OPENCHILD:
+               if( !Syscall_ValidString(Regs->Arg2) ) {
+                       err = -EINVAL;
+                       ret = -1;
+                       break;
+               }
+               ret = VFS_OpenChild( &err, Regs->Arg1, (char*)Regs->Arg2, Regs->Arg3);
+               break;
+       
        // Change Directory
        case SYS_CHDIR:
                if( !Syscall_ValidString(Regs->Arg1) ) {
@@ -202,11 +276,44 @@ void SyscallHandler(tSyscallRegs *Regs)
                ret = VFS_ChDir( (void*)Regs->Arg1 );
                break;
        
+       // IO Control
+       case SYS_IOCTL:
+               // All sanity checking should be done by the driver
+               ret = VFS_IOCtl( Regs->Arg1, Regs->Arg2, (void*)Regs->Arg3 );
+               break;
+       
+       // Mount a filesystem
+       case SYS_MOUNT:
+               // Only root can mount filesystems
+               if(Threads_GetUID() != 0) {
+                       err = -EACCES;
+                       ret = -1;
+                       break;
+               }
+               // Sanity check the paths
+               if(!Syscall_ValidString(Regs->Arg1)
+               || !Syscall_ValidString(Regs->Arg2)
+               || !Syscall_ValidString(Regs->Arg3)
+               || !Syscall_ValidString(Regs->Arg4) ) {
+                       err = -EINVAL;
+                       ret = -1;
+                       break;
+               }
+               ret = VFS_Mount(
+                       (char*)Regs->Arg1,      // Device
+                       (char*)Regs->Arg2,      // Mount point
+                       (char*)Regs->Arg3,      // Filesystem
+                       (char*)Regs->Arg4       // Options
+                       );
+               break;
+       
        // -- Debug
+       //#if DEBUG_BUILD
        case SYS_DEBUG:
                Log((char*)Regs->Arg1,
                        Regs->Arg2, Regs->Arg3, Regs->Arg4, Regs->Arg5, Regs->Arg6);
                break;
+       //#endif
        
        // -- Default (Return Error)
        default:
@@ -217,6 +324,11 @@ void SyscallHandler(tSyscallRegs *Regs)
                ret = -1;
                break;
        }
+       
+       if(err != 0) {
+               LOG("ID: %i, Return errno = %i", Regs->Num, err);
+       }
+       
        #if BITS < 64
        Regs->Return = ret&0xFFFFFFFF;
        Regs->RetHi = ret >> 32;
@@ -225,8 +337,17 @@ void SyscallHandler(tSyscallRegs *Regs)
        #endif
        Regs->Error = err;
        #if DEBUG
-       LOG("SyscallHandler: err = %i", err);
-       LEAVE('x', ret);
+       # if DEBUG < 2
+       if( callNum != SYS_READ && callNum != SYS_WRITE ) {
+       # endif
+       LOG("err = %i", err);
+       if(Regs->Num != SYS_EXECVE)
+               LEAVE('x', ret);
+       else
+               LOG("Actual %i", ret);
+       # if DEBUG < 2
+       }
+       # endif
        #endif
 }
 
@@ -236,18 +357,10 @@ void SyscallHandler(tSyscallRegs *Regs)
  */
 int Syscall_ValidString(Uint Addr)
 {
-       // Check 1st page
-       if(!MM_GetPhysAddr(Addr))       return 0;
+       // Check if the memory is user memory
+       if(!MM_IsUser(Addr))    return 0;
        
-       // Traverse String
-       while(*(char*)Addr)
-       {
-               if(!MM_GetPhysAddr(Addr))       return 0;
-               // Increment string pointer
-               Addr ++;
-       }
-       
-       return 1;
+       return CheckString( (char*)Addr );
 }
 
 /**
@@ -256,10 +369,7 @@ int Syscall_ValidString(Uint Addr)
  */
 int Syscall_Valid(int Size, Uint Addr)
 {
-       while(Size--)
-       {
-               if(!MM_GetPhysAddr(Addr))       return 0;
-               Addr ++;
-       }
-       return 1;
+       if(!MM_IsUser(Addr))    return 0;
+       
+       return CheckMem( (void*)Addr, Size );
 }

UCC git Repository :: git.ucc.asn.au