diff --git a/sys/SConscript b/sys/SConscript index a314bc6..e586129 100644 --- a/sys/SConscript +++ b/sys/SConscript @@ -40,9 +40,9 @@ src_amd64 = [ src_common = [ "kern/copy.c", + "kern/bufcache.c", "kern/debug.c", "kern/disk.c", - "kern/diskcache.c", "kern/handle.c", "kern/ktime.c", "kern/ktimer.c", diff --git a/sys/amd64/machine.c b/sys/amd64/machine.c index 9d07cd0..2f538bf 100644 --- a/sys/amd64/machine.c +++ b/sys/amd64/machine.c @@ -17,7 +17,7 @@ #include #include -#include +#include #include #include @@ -163,7 +163,7 @@ void Machine_Init() PS2_Init(); PCI_Init(); IDE_Init(); - DiskCache_Init(); + BufCache_Init(); Disk *root = Disk_GetByID(0, 0); if (!root) diff --git a/sys/dev/console.c b/sys/dev/console.c index 2a25a02..9a09dc7 100644 --- a/sys/dev/console.c +++ b/sys/dev/console.c @@ -57,8 +57,17 @@ Console_Getc() Spinlock_Unlock(&consoles.keyLock); // Support serial debugging if interrupts are disabled - if (Serial_HasData()) - return Serial_Getc(); + if (Serial_HasData()) { + char key = Serial_Getc(); + switch (key) { + case '\r': + return '\n'; + case 0x7f: + return '\b'; + default: + return key; + } + } } } @@ -148,7 +157,7 @@ Console_Read(Handle *handle, void *buf, uint64_t off, uint64_t len) { char c = Console_Getc(); Console_Putc(c); - CopyOut(&c, b+i, 1); + Copy_Out(&c, b+i, 1); } return len; @@ -164,7 +173,7 @@ Console_Write(Handle *handle, void *buf, uint64_t off, uint64_t len) while (len > nbytes) { uint64_t chunksz = len > 512 ? 512 : len; - CopyIn(b + nbytes, &kbuf, chunksz); + Copy_In(b + nbytes, &kbuf, chunksz); nbytes += chunksz; for (i = 0; i < chunksz; i++) diff --git a/sys/fs/o2fs/o2fs.c b/sys/fs/o2fs/o2fs.c index bb04de7..91987f1 100644 --- a/sys/fs/o2fs/o2fs.c +++ b/sys/fs/o2fs/o2fs.c @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include #include #include @@ -43,7 +43,7 @@ O2FS_Mount(Disk *disk) { int status; VFS *fs = VFS_Alloc(); - DiskCacheEntry *entry; + BufCacheEntry *entry; SuperBlock *sb; ASSERT(sizeof(BDirEntry) == 512); @@ -51,7 +51,7 @@ O2FS_Mount(Disk *disk) if (!fs) return NULL; - status = DiskCache_Read(disk, 0, &entry); + status = BufCache_Read(disk, 0, &entry); if (status < 0) { Alert(o2fs, "O2FS: Disk cache read failed\n"); return NULL; @@ -61,13 +61,13 @@ O2FS_Mount(Disk *disk) sb = entry->buffer; if (memcmp(sb->magic, SUPERBLOCK_MAGIC, 8) != 0) { Alert(o2fs, "O2FS: Invalid file system\n"); - DiskCache_Release(entry); + BufCache_Release(entry); return NULL; } if (sb->versionMajor != O2FS_VERSION_MAJOR || sb->versionMinor != O2FS_VERSION_MINOR) { Alert(o2fs, "O2FS: Unsupported file system version\n"); - DiskCache_Release(entry); + BufCache_Release(entry); return NULL; } @@ -87,7 +87,7 @@ O2FS_Mount(Disk *disk) status = O2FS_GetRoot(fs, &fs->root); if (status < 0) { Alert(o2fs, "O2FS: Mount failed"); - DiskCache_Release(entry); + BufCache_Release(entry); return NULL; } @@ -107,9 +107,9 @@ O2FSLoadVNode(VFS *fs, ObjID *objid) int status; VNode *vn; BNode *bn; - DiskCacheEntry *entry; + BufCacheEntry *entry; - status = DiskCache_Read(fs->disk, objid->offset, &entry); + status = BufCache_Read(fs->disk, objid->offset, &entry); if (status < 0) { Alert(o2fs, "O2FS: disk read error\n"); return NULL; @@ -118,13 +118,13 @@ O2FSLoadVNode(VFS *fs, ObjID *objid) bn = entry->buffer; if (memcmp(&bn->magic, BNODE_MAGIC, 8) != 0) { Alert(o2fs, "O2FS: bad BNode magic\n"); - DiskCache_Release(entry); + BufCache_Release(entry); return NULL; } if (bn->versionMajor != O2FS_VERSION_MAJOR || bn->versionMinor != O2FS_VERSION_MINOR) { Alert(o2fs, "O2FS: unsupported BNode version\n"); - DiskCache_Release(entry); + BufCache_Release(entry); return NULL; } @@ -154,7 +154,7 @@ O2FSReleaseVNode(VNode *vn) { vn->refCount--; if (vn->refCount == 0) { - DiskCache_Release(vn->fsptr); + BufCache_Release(vn->fsptr); Spinlock_Destroy(&vn->lock); VNode_Free(vn); } @@ -165,7 +165,7 @@ O2FS_GetRoot(VFS *fs, VNode **dn) { int status; VNode *vn; - DiskCacheEntry *entry; + BufCacheEntry *entry; BNode *bn; if (fs->root) { @@ -174,7 +174,7 @@ O2FS_GetRoot(VFS *fs, VNode **dn) return 0; } - status = DiskCache_Read(fs->disk, fs->fsval, &entry); + status = BufCache_Read(fs->disk, fs->fsval, &entry); if (status < 0) { Alert(o2fs, "O2FS: disk read error\n"); return status; @@ -183,13 +183,13 @@ O2FS_GetRoot(VFS *fs, VNode **dn) bn = entry->buffer; if (memcmp(&bn->magic, BNODE_MAGIC, 8) != 0) { Alert(o2fs, "O2FS: bad BNode magic\n"); - DiskCache_Release(entry); + BufCache_Release(entry); return -1; } if (bn->versionMajor != O2FS_VERSION_MAJOR || bn->versionMinor != O2FS_VERSION_MINOR) { Alert(o2fs, "O2FS: unsupported BNode version\n"); - DiskCache_Release(entry); + BufCache_Release(entry); return -1; } @@ -217,9 +217,9 @@ O2FS_Lookup(VNode *dn, VNode **fn, const char *name) { int status; VFS *vfs = dn->vfs; - DiskCacheEntry *sbEntry = (DiskCacheEntry *)vfs->fsptr; + BufCacheEntry *sbEntry = (BufCacheEntry *)vfs->fsptr; SuperBlock *sb = sbEntry->buffer; - DiskCacheEntry *dirEntry = (DiskCacheEntry *)dn->fsptr; + BufCacheEntry *dirEntry = (BufCacheEntry *)dn->fsptr; BNode *dirBN = dirEntry->buffer; uint64_t blocks = (dirBN->size + sb->blockSize - 1) / sb->blockSize; uint64_t b; @@ -230,9 +230,9 @@ O2FS_Lookup(VNode *dn, VNode **fn, const char *name) // Read block int e; int entryPerBlock = sb->blockSize / sizeof(BDirEntry); - DiskCacheEntry *entry; + BufCacheEntry *entry; BDirEntry *dir; - status = DiskCache_Read(dn->disk, dirBN->direct[b].offset, &entry); + status = BufCache_Read(dn->disk, dirBN->direct[b].offset, &entry); if (status < 0) return status; @@ -248,7 +248,7 @@ O2FS_Lookup(VNode *dn, VNode **fn, const char *name) } } - DiskCache_Release(entry); + BufCache_Release(entry); } return -1; @@ -270,9 +270,9 @@ int O2FS_Stat(VNode *fn, struct stat *statinfo) { VFS *vfs = fn->vfs; - DiskCacheEntry *sbEntry = (DiskCacheEntry *)vfs->fsptr; + BufCacheEntry *sbEntry = (BufCacheEntry *)vfs->fsptr; SuperBlock *sb = sbEntry->buffer; - DiskCacheEntry *fileEntry = (DiskCacheEntry *)fn->fsptr; + BufCacheEntry *fileEntry = (BufCacheEntry *)fn->fsptr; BNode *fileBN = fileEntry->buffer; statinfo->st_size = fileBN->size; @@ -288,9 +288,9 @@ O2FS_Read(VNode *fn, void *buf, uint64_t off, uint64_t len) { int status; VFS *vfs = fn->vfs; - DiskCacheEntry *sbEntry = (DiskCacheEntry *)vfs->fsptr; + BufCacheEntry *sbEntry = (BufCacheEntry *)vfs->fsptr; SuperBlock *sb = sbEntry->buffer; - DiskCacheEntry *fileEntry = (DiskCacheEntry *)fn->fsptr; + BufCacheEntry *fileEntry = (BufCacheEntry *)fn->fsptr; BNode *fileBN = fileEntry->buffer; uint64_t blocks = (fileBN->size + sb->blockSize - 1) / sb->blockSize; uint64_t readBytes = 0; @@ -309,7 +309,7 @@ O2FS_Read(VNode *fn, void *buf, uint64_t off, uint64_t len) uint64_t b = off / sb->blockSize; uint64_t bOff = off % sb->blockSize; uint64_t bLen; - DiskCacheEntry *entry; + BufCacheEntry *entry; if (bOff + len > sb->blockSize) { bLen = sb->blockSize - bOff; @@ -317,12 +317,12 @@ O2FS_Read(VNode *fn, void *buf, uint64_t off, uint64_t len) bLen = len; } - status = DiskCache_Read(fn->disk, fileBN->direct[b].offset, &entry); + status = BufCache_Read(fn->disk, fileBN->direct[b].offset, &entry); if (status < 0) return status; memcpy(buf, entry->buffer + bOff, bLen); - DiskCache_Release(entry); + BufCache_Release(entry); readBytes += bLen; buf += bLen; @@ -348,7 +348,7 @@ O2FS_ReadDir(VNode *fn, void *buf, uint64_t len, uint64_t *off) { int count = 0; int status; - DiskCacheEntry *fileEntry = (DiskCacheEntry *)fn->fsptr; + BufCacheEntry *fileEntry = (BufCacheEntry *)fn->fsptr; BNode *fileBN = fileEntry->buffer; BDirEntry dirEntry; struct dirent de; @@ -370,7 +370,7 @@ O2FS_ReadDir(VNode *fn, void *buf, uint64_t len, uint64_t *off) // XXX: Validation and fill in all fields strcpy(de.d_name, (char *)dirEntry.name); - status = CopyOut(&de, (uintptr_t)buf, sizeof(de)); + status = Copy_Out(&de, (uintptr_t)buf, sizeof(de)); if (status != 0) return status; diff --git a/sys/include/bufcache.h b/sys/include/bufcache.h new file mode 100644 index 0000000..16a5bbb --- /dev/null +++ b/sys/include/bufcache.h @@ -0,0 +1,23 @@ + +#ifndef __SYS_BUFCACHE_H__ +#define __SYS_BUFCACHE_H__ + +#include + +typedef struct BufCacheEntry { + Disk *disk; + uint64_t diskOffset; + uint64_t refCount; + void *buffer; + TAILQ_ENTRY(BufCacheEntry) htEntry; + TAILQ_ENTRY(BufCacheEntry) lruEntry; +} BufCacheEntry; + +void BufCache_Init(); +int BufCache_Alloc(Disk *disk, uint64_t diskOffset, BufCacheEntry **entry); +void BufCache_Release(BufCacheEntry *entry); +int BufCache_Read(Disk *disk, uint64_t diskOffset, BufCacheEntry **entry); +int BufCache_Write(BufCacheEntry *entry); + +#endif /* __SYS_BUFCACHE_H__ */ + diff --git a/sys/include/diskcache.h b/sys/include/diskcache.h deleted file mode 100644 index b4b7f3f..0000000 --- a/sys/include/diskcache.h +++ /dev/null @@ -1,23 +0,0 @@ - -#ifndef __SYS_DISKCACHE_H__ -#define __SYS_DISKCACHE_H__ - -#include - -typedef struct DiskCacheEntry { - Disk *disk; - uint64_t diskOffset; - uint64_t refCount; - void *buffer; - TAILQ_ENTRY(DiskCacheEntry) htEntry; - TAILQ_ENTRY(DiskCacheEntry) lruEntry; -} DiskCacheEntry; - -void DiskCache_Init(); -int DiskCache_Alloc(Disk *disk, uint64_t diskOffset, DiskCacheEntry **entry); -void DiskCache_Release(DiskCacheEntry *entry); -int DiskCache_Read(Disk *disk, uint64_t diskOffset, DiskCacheEntry **entry); -int DiskCache_Write(DiskCacheEntry *entry); - -#endif /* __SYS_DISKCACHE_H__ */ - diff --git a/sys/include/syscall.h b/sys/include/syscall.h index 97df679..96a6615 100644 --- a/sys/include/syscall.h +++ b/sys/include/syscall.h @@ -28,6 +28,9 @@ #define SYSCALL_STAT 0x1D #define SYSCALL_READDIR 0x1E +// IPC +#define SYSCALL_PIPE 0x20 + // Threading #define SYSCALL_THREADCREATE 0x30 #define SYSCALL_GETTID 0x31 diff --git a/sys/include/thread.h b/sys/include/thread.h index b666383..7212625 100644 --- a/sys/include/thread.h +++ b/sys/include/thread.h @@ -123,11 +123,11 @@ uint64_t Handle_Add(Process *proc, Handle *handle); void Handle_Remove(Process *proc, Handle *handle); Handle *Handle_Lookup(Process *proc, uint64_t fd); -// CopyIn/CopyOut Functions -int CopyIn(uintptr_t fromuser, void *tokernel, uintptr_t len); -int CopyOut(void *fromkernel, uintptr_t touser, uintptr_t len); -int CopyStrIn(uintptr_t fromuser, void *tokernel, uintptr_t len); -int CopyStrOut(void *fromkernel, uintptr_t touser, uintptr_t len); +// Copy_In/Copy_Out Functions +int Copy_In(uintptr_t fromuser, void *tokernel, uintptr_t len); +int Copy_Out(void *fromkernel, uintptr_t touser, uintptr_t len); +int Copy_StrIn(uintptr_t fromuser, void *tokernel, uintptr_t len); +int Copy_StrOut(void *fromkernel, uintptr_t touser, uintptr_t len); #endif /* __SYS_THREAD_H__ */ diff --git a/sys/kern/diskcache.c b/sys/kern/bufcache.c similarity index 58% rename from sys/kern/diskcache.c rename to sys/kern/bufcache.c index 0f29fca..b164cc9 100644 --- a/sys/kern/diskcache.c +++ b/sys/kern/bufcache.c @@ -1,3 +1,7 @@ +/* + * Copyright (c) 2006-2022 Ali Mashtizadeh + * All rights reserved. + */ #include #include @@ -8,55 +12,55 @@ #include #include #include -#include +#include Spinlock cacheLock; XMem *diskBuf; -static TAILQ_HEAD(CacheHashTable, DiskCacheEntry) *hashTable; -static TAILQ_HEAD(LRUCacheList, DiskCacheEntry) lruList; +static TAILQ_HEAD(CacheHashTable, BufCacheEntry) *hashTable; +static TAILQ_HEAD(LRUCacheList, BufCacheEntry) lruList; static uint64_t cacheHit; static uint64_t cacheMiss; static uint64_t cacheAlloc; static Slab cacheEntrySlab; -DEFINE_SLAB(DiskCacheEntry, &cacheEntrySlab); +DEFINE_SLAB(BufCacheEntry, &cacheEntrySlab); #define CACHESIZE (16*1024*1024) #define HASHTABLEENTRIES 128 #define BLOCKSIZE (16*1024) void -DiskCache_Init() +BufCache_Init() { int i; - Spinlock_Init(&cacheLock, "DiskCache Lock", SPINLOCK_TYPE_NORMAL); + Spinlock_Init(&cacheLock, "BufCache Lock", SPINLOCK_TYPE_NORMAL); diskBuf = XMem_New(); if (!diskBuf) - Panic("DiskCache: Cannot create XMem region\n"); + Panic("BufCache: Cannot create XMem region\n"); if (!XMem_Allocate(diskBuf, CACHESIZE)) - Panic("DiskCache: Cannot back XMem region\n"); + Panic("BufCache: Cannot back XMem region\n"); TAILQ_INIT(&lruList); hashTable = PAlloc_AllocPage(); if (!hashTable) - Panic("DiskCache: Cannot allocate hash table\n"); + Panic("BufCache: Cannot allocate hash table\n"); for (i = 0; i < HASHTABLEENTRIES; i++) { - TAILQ_INIT(&hashTable[i]); + TAILQ_INIT(&hashTable[i]); } - Slab_Init(&cacheEntrySlab, "DiskCacheEntry Slab", sizeof(DiskCacheEntry), 16); + Slab_Init(&cacheEntrySlab, "BufCacheEntry Slab", sizeof(BufCacheEntry), 16); // Initialize cache uintptr_t bufBase = XMem_GetBase(diskBuf); for (i = 0; i < CACHESIZE/BLOCKSIZE; i++) { - DiskCacheEntry *e = DiskCacheEntry_Alloc(); + BufCacheEntry *e = BufCacheEntry_Alloc(); if (!e) { - Panic("DiskCache: Cannot allocate cache entry\n"); + Panic("BufCache: Cannot allocate cache entry\n"); } memset(e, 0, sizeof(*e)); @@ -71,10 +75,10 @@ DiskCache_Init() } static int -DiskCacheLookup(Disk *disk, uint64_t diskOffset, DiskCacheEntry **entry) +BufCacheLookup(Disk *disk, uint64_t diskOffset, BufCacheEntry **entry) { struct CacheHashTable *table; - DiskCacheEntry *e; + BufCacheEntry *e; // Check hash table table = &hashTable[diskOffset % HASHTABLEENTRIES]; @@ -94,15 +98,15 @@ DiskCacheLookup(Disk *disk, uint64_t diskOffset, DiskCacheEntry **entry) } static int -DiskCacheAlloc(Disk *disk, uint64_t diskOffset, DiskCacheEntry **entry) +BufCacheAlloc(Disk *disk, uint64_t diskOffset, BufCacheEntry **entry) { struct CacheHashTable *table; - DiskCacheEntry *e; + BufCacheEntry *e; // Allocate from LRU list e = TAILQ_FIRST(&lruList); if (e == NULL) { - kprintf("DiskCache: No space left!\n"); + kprintf("BufCache: No space left!\n"); return -1; } TAILQ_REMOVE(&lruList, e, lruEntry); @@ -126,16 +130,24 @@ DiskCacheAlloc(Disk *disk, uint64_t diskOffset, DiskCacheEntry **entry) return 0; } +/* + * BufCache_Alloc -- + * + * Allocate a buffer cache entry. + * + * Results: + * Returns 0 if successful and sets the entry, otherwise returns an error code. + */ int -DiskCache_Alloc(Disk *disk, uint64_t diskOffset, DiskCacheEntry **entry) +BufCache_Alloc(Disk *disk, uint64_t diskOffset, BufCacheEntry **entry) { int status; Spinlock_Lock(&cacheLock); - status = DiskCacheLookup(disk, diskOffset, entry); + status = BufCacheLookup(disk, diskOffset, entry); if (*entry == NULL) { - status = DiskCacheAlloc(disk, diskOffset, entry); + status = BufCacheAlloc(disk, diskOffset, entry); } cacheAlloc++; @@ -145,39 +157,56 @@ DiskCache_Alloc(Disk *disk, uint64_t diskOffset, DiskCacheEntry **entry) return status; } +/* + * BufCache_Release -- + * + * Release a buffer cache entry. If no other references are held the + * buffer cache entry is placed on the LRU list. + * + * Results: + * None. + */ void -DiskCache_Release(DiskCacheEntry *entry) +BufCache_Release(BufCacheEntry *entry) { Spinlock_Lock(&cacheLock); entry->refCount--; if (entry->refCount == 0) { - TAILQ_INSERT_TAIL(&lruList, entry, lruEntry); + TAILQ_INSERT_TAIL(&lruList, entry, lruEntry); } Spinlock_Unlock(&cacheLock); } +/* + * BufCache_Read -- + * + * Read block from disk into the buffer cache. + * + * Results: + * Returns 0 if successful, otherwise an error code is returned. + */ int -DiskCache_Read(Disk *disk, uint64_t diskOffset, DiskCacheEntry **entry) +BufCache_Read(Disk *disk, uint64_t diskOffset, BufCacheEntry **entry) { int status; void *buf; SGArray sga; Spinlock_Lock(&cacheLock); - status = DiskCacheLookup(disk, diskOffset, entry); + status = BufCacheLookup(disk, diskOffset, entry); if (*entry != NULL) { - cacheHit++; - Spinlock_Unlock(&cacheLock); - return status; + cacheHit++; + Spinlock_Unlock(&cacheLock); + return status; } cacheMiss++; - status = DiskCacheAlloc(disk, diskOffset, entry); + status = BufCacheAlloc(disk, diskOffset, entry); if (status != 0) { - Spinlock_Unlock(&cacheLock); - return status; + Spinlock_Unlock(&cacheLock); + return status; } buf = (*entry)->buffer; @@ -194,8 +223,16 @@ DiskCache_Read(Disk *disk, uint64_t diskOffset, DiskCacheEntry **entry) return status; } +/* + * BufCache_Write -- + * + * Write a buffer cache entry to disk. + * + * Results: + * Returns 0 if successful, otherwise an error code is returned. + */ int -DiskCache_Write(DiskCacheEntry *entry) +BufCache_Write(BufCacheEntry *entry) { void *buf = entry->buffer; SGArray sga; @@ -207,12 +244,12 @@ DiskCache_Write(DiskCacheEntry *entry) } static void -Debug_DiskCache(int argc, const char *argv[]) +Debug_BufCache(int argc, const char *argv[]) { kprintf("Hits: %lld\n", cacheHit); kprintf("Misses: %lld\n", cacheMiss); kprintf("Allocations: %lld\n", cacheAlloc); } -REGISTER_DBGCMD(diskcache, "Display disk cache statistics", Debug_DiskCache); +REGISTER_DBGCMD(diskcache, "Display disk cache statistics", Debug_BufCache); diff --git a/sys/kern/copy.c b/sys/kern/copy.c index 454fc88..0e53ab5 100644 --- a/sys/kern/copy.c +++ b/sys/kern/copy.c @@ -1,4 +1,6 @@ /* + * Copyright (c) 2006-2022 Ali Mashtizadeh + * All rights reserved. * Generic Copyin/Copyout routines */ @@ -13,84 +15,128 @@ extern int copy_unsafe(void *to_addr, void *from_addr, uintptr_t len); extern int copystr_unsafe(void *to_addr, void *from_addr, uintptr_t len); +/* + * Copy_In -- + * Safely copy memory from userspace. Prevents userspace pointers from + * reading kernel memory. + * + * Results: + * Returns EFAULT if the address is invalid or causes a fault. + * + * Side effects: + * Kernel page fault may have occurred. + */ int -CopyIn(uintptr_t fromuser, void *tokernel, uintptr_t len) +Copy_In(uintptr_t fromuser, void *tokernel, uintptr_t len) { if (len == 0) return 0; // Kernel space if (fromuser >= MEM_USERSPACE_TOP) { - kprintf("CopyIn: address exceeds userspace top\n"); + kprintf("Copy_In: address exceeds userspace top\n"); return EFAULT; } // Wrap around if (len > (MEM_USERSPACE_TOP - fromuser)) { - kprintf("CopyIn: length exceeds userspace top\n"); + kprintf("Copy_In: length exceeds userspace top\n"); return EFAULT; } return copy_unsafe(tokernel, (void *)fromuser, len); } +/* + * Copy_Out -- + * Safely copy memory to userspace. Prevents userspace pointers from + * writing kernel memory. + * + * Results: + * Returns EFAULT if the address is invalid or causes a fault. + * + * Side effects: + * Kernel page fault may have occurred. + */ int -CopyOut(void *fromkernel, uintptr_t touser, uintptr_t len) +Copy_Out(void *fromkernel, uintptr_t touser, uintptr_t len) { if (len == 0) return 0; // Kernel space if (touser >= MEM_USERSPACE_TOP) { - kprintf("CopyOut: address exceeds userspace top\n"); + kprintf("Copy_Out: address exceeds userspace top\n"); return EFAULT; } // Wrap around if (len > (MEM_USERSPACE_TOP - touser)) { - kprintf("CopyOut: length exceeds userspace top\n"); + kprintf("Copy_Out: length exceeds userspace top\n"); return EFAULT; } return copy_unsafe((void *)touser, fromkernel, len); } +/* + * Copy_StrIn -- + * Safely copy a string from userspace. Prevents userspace pointers from + * reading kernel memory. + * + * Results: + * Returns EFAULT if the address is invalid or causes a fault. + * + * Side effects: + * Kernel page fault may have occurred. + */ int -CopyStrIn(uintptr_t fromuser, void *tokernel, uintptr_t len) +Copy_StrIn(uintptr_t fromuser, void *tokernel, uintptr_t len) { if (len == 0) return 0; // Kernel space if (fromuser >= MEM_USERSPACE_TOP) { - kprintf("CopyStrIn: address exceeds userspace top\n"); + kprintf("Copy_StrIn: address exceeds userspace top\n"); return EFAULT; } // Wrap around if (len > (MEM_USERSPACE_TOP - fromuser)) { - kprintf("CopyStrIn: length exceeds userspace top\n"); + kprintf("Copy_StrIn: length exceeds userspace top\n"); return EFAULT; } return copystr_unsafe(tokernel, (void *)fromuser, len); } +/* + * Copy_StrOut -- + * Safely copy a string to userspace. Prevents userspace pointers from + * writing kernel memory. + * + * Results: + * Returns EFAULT if the address is invalid or causes a fault. + * + * Side effects: + * Kernel page fault may have occurred. + */ int -CopyStrOut(void *fromkernel, uintptr_t touser, uintptr_t len) +Copy_StrOut(void *fromkernel, uintptr_t touser, uintptr_t len) { if (len == 0) return 0; // Kernel space if (touser >= MEM_USERSPACE_TOP) { - kprintf("CopyStrOut: address exceeds userspace top\n"); + kprintf("Copy_StrOut: address exceeds userspace top\n"); return EFAULT; } // Wrap around if (len > (MEM_USERSPACE_TOP - touser)) { - kprintf("CopyStrOut: length exceeds userspace top\n"); + kprintf("Copy_StrOut: length exceeds userspace top\n"); return EFAULT; } diff --git a/sys/kern/syscall.c b/sys/kern/syscall.c index 5922153..82f4b1f 100644 --- a/sys/kern/syscall.c +++ b/sys/kern/syscall.c @@ -71,7 +71,7 @@ Syscall_Spawn(uint64_t user_path) Thread *thr; Thread *cur; - status = CopyStrIn(user_path, &path, sizeof(path)); + status = Copy_StrIn(user_path, &path, sizeof(path)); if (status != 0) return SYSCALL_PACK(status, 0); @@ -246,7 +246,7 @@ Syscall_Open(uint64_t user_path, uint64_t flags) int status; char path[256]; - status = CopyStrIn(user_path, &path, sizeof(path)); + status = Copy_StrIn(user_path, &path, sizeof(path)); if (status != 0) { Thread_Release(cur); return status; @@ -301,7 +301,7 @@ Syscall_Stat(uint64_t user_path, uint64_t user_stat) char path[256]; struct stat sb; - status = CopyStrIn(user_path, &path, sizeof(path)); + status = Copy_StrIn(user_path, &path, sizeof(path)); if (status != 0) { return status; } @@ -312,7 +312,7 @@ Syscall_Stat(uint64_t user_path, uint64_t user_stat) return status; } - status = CopyOut(&sb, user_stat, sizeof(struct stat)); + status = Copy_Out(&sb, user_stat, sizeof(struct stat)); if (status != 0) { return status; } @@ -333,7 +333,7 @@ Syscall_ReadDir(uint64_t fd, char *user_buf, size_t len, uintptr_t user_off) return -EBADF; } - status = CopyIn(user_off, &offset, sizeof(offset)); + status = Copy_In(user_off, &offset, sizeof(offset)); if (status != 0) { Thread_Release(cur); return status; @@ -350,7 +350,7 @@ Syscall_ReadDir(uint64_t fd, char *user_buf, size_t len, uintptr_t user_off) return rstatus; } - status = CopyOut(&offset, user_off, sizeof(offset)); + status = Copy_Out(&offset, user_off, sizeof(offset)); if (status != 0) { Thread_Release(cur); return status; @@ -480,7 +480,7 @@ Syscall_NICStat(uint64_t nicNo, uint64_t user_stat) return ENOENT; } - status = CopyOut(nic, user_stat, sizeof(NIC)); + status = Copy_Out(nic, user_stat, sizeof(NIC)); if (status != 0) { return status; } @@ -495,7 +495,7 @@ Syscall_NICSend(uint64_t nicNo, uint64_t user_mbuf) NIC *nic; MBuf mbuf; - status = CopyIn(user_mbuf, &mbuf, sizeof(mbuf)); + status = Copy_In(user_mbuf, &mbuf, sizeof(mbuf)); if (status != 0) { return SYSCALL_PACK(status, 0); } @@ -519,7 +519,7 @@ Syscall_NICRecv(uint64_t nicNo, uint64_t user_mbuf) NIC *nic; MBuf mbuf; - status = CopyIn(user_mbuf, &mbuf, sizeof(mbuf)); + status = Copy_In(user_mbuf, &mbuf, sizeof(mbuf)); if (status != 0) { return SYSCALL_PACK(status, 0); } @@ -542,7 +542,7 @@ Syscall_SysCtl(uint64_t user_node, uint64_t user_oldval, uint64_t user_newval) uint64_t status; char node[64]; - status = CopyStrIn(user_node, &node, sizeof(node)); + status = Copy_StrIn(user_node, &node, sizeof(node)); if (status != 0) { return status; } @@ -555,17 +555,17 @@ Syscall_SysCtl(uint64_t user_node, uint64_t user_oldval, uint64_t user_newval) switch (scType) { case SYSCTL_TYPE_STR: { SysCtlString *scStr = SysCtl_GetObject(node); - status = CopyOut(scStr, user_oldval, sizeof(*scStr)); + status = Copy_Out(scStr, user_oldval, sizeof(*scStr)); break; } case SYSCTL_TYPE_INT: { SysCtlInt *scInt = SysCtl_GetObject(node); - status = CopyOut(scInt, user_oldval, sizeof(*scInt)); + status = Copy_Out(scInt, user_oldval, sizeof(*scInt)); break; } case SYSCTL_TYPE_BOOL: { SysCtlBool *scBool = SysCtl_GetObject(node); - status = CopyOut(scBool, user_oldval, sizeof(scBool)); + status = Copy_Out(scBool, user_oldval, sizeof(scBool)); break; } default: { @@ -584,7 +584,7 @@ Syscall_SysCtl(uint64_t user_node, uint64_t user_oldval, uint64_t user_newval) switch (scType) { case SYSCTL_TYPE_STR: { SysCtlString scStr; - status = CopyIn(user_newval, &scStr, sizeof(scStr)); + status = Copy_In(user_newval, &scStr, sizeof(scStr)); if (status != 0) { return status; } @@ -593,7 +593,7 @@ Syscall_SysCtl(uint64_t user_node, uint64_t user_oldval, uint64_t user_newval) } case SYSCTL_TYPE_INT: { SysCtlInt scInt; - status = CopyIn(user_newval, &scInt, sizeof(scInt)); + status = Copy_In(user_newval, &scInt, sizeof(scInt)); if (status != 0) { return status; } @@ -602,7 +602,7 @@ Syscall_SysCtl(uint64_t user_node, uint64_t user_oldval, uint64_t user_newval) } case SYSCTL_TYPE_BOOL: { SysCtlBool scBool; - status = CopyIn(user_newval, &scBool, sizeof(scBool)); + status = Copy_In(user_newval, &scBool, sizeof(scBool)); if (status != 0) { return status; }