diff --git a/Kernel/Task.cpp b/Kernel/Task.cpp index 91fffcd15b..1e625fecf7 100644 --- a/Kernel/Task.cpp +++ b/Kernel/Task.cpp @@ -182,8 +182,16 @@ int Task::sys$munmap(void* addr, size_t size) return 0; } +#define VALIDATE_USER_BUFFER(b, s) \ + do { \ + LinearAddress laddr((dword)(b)); \ + if (!isValidAddressForUser(laddr) || !isValidAddressForUser(laddr.offset((s) - 1))) \ + return -EFAULT; \ + } while(0) + int Task::sys$gethostname(char* buffer, size_t size) { + VALIDATE_USER_BUFFER(buffer, size); auto hostname = getHostname(); if (size < (hostname.length() + 1)) return -ENAMETOOLONG; @@ -670,6 +678,7 @@ FileHandle* Task::fileHandleIfExists(int fd) ssize_t Task::sys$get_dir_entries(int fd, void* buffer, size_t size) { + VALIDATE_USER_BUFFER(buffer, size); auto* handle = fileHandleIfExists(fd); if (!handle) return -1; @@ -686,7 +695,7 @@ int Task::sys$seek(int fd, int offset) ssize_t Task::sys$read(int fd, void* outbuf, size_t nread) { - Task::checkSanity("Task::sys$read"); + VALIDATE_USER_BUFFER(outbuf, nread); #ifdef DEBUG_IO kprintf("Task::sys$read: called(%d, %p, %u)\n", fd, outbuf, nread); #endif @@ -726,6 +735,7 @@ int Task::sys$close(int fd) int Task::sys$lstat(const char* path, void* statbuf) { + VALIDATE_USER_BUFFER(statbuf, sizeof(stat)); auto handle = VirtualFileSystem::the().open(move(path), m_cwd.ptr()); if (!handle) return -1; @@ -735,6 +745,7 @@ int Task::sys$lstat(const char* path, void* statbuf) int Task::sys$chdir(const char* path) { + VALIDATE_USER_BUFFER(path, strlen(path)); auto handle = VirtualFileSystem::the().open(path, m_cwd.ptr()); if (!handle) return -ENOENT; // FIXME: More detailed error. @@ -748,6 +759,7 @@ int Task::sys$chdir(const char* path) int Task::sys$getcwd(char* buffer, size_t size) { // FIXME: Implement! + VALIDATE_USER_BUFFER(buffer, size); return -ENOTIMPL; } @@ -756,6 +768,7 @@ int Task::sys$open(const char* path, size_t pathLength) #ifdef DEBUG_IO kprintf("Task::sys$open(): PID=%u, path=%s {%u}\n", m_pid, path, pathLength); #endif + VALIDATE_USER_BUFFER(path, pathLength); if (m_fileHandles.size() >= m_maxFileHandles) return -EMFILE; auto handle = VirtualFileSystem::the().open(String(path, pathLength), m_cwd.ptr()); @@ -769,6 +782,7 @@ int Task::sys$open(const char* path, size_t pathLength) int Task::sys$uname(utsname* buf) { + VALIDATE_USER_BUFFER(buf, sizeof(utsname)); strcpy(buf->sysname, "Serenity"); strcpy(buf->release, "1.0-dev"); strcpy(buf->version, "FIXME"); @@ -807,6 +821,7 @@ int Task::sys$sleep(unsigned seconds) int Task::sys$gettimeofday(timeval* tv) { + VALIDATE_USER_BUFFER(tv, sizeof(tv)); InterruptDisabler disabler; auto now = RTC::now(); tv->tv_sec = now; diff --git a/Kernel/types.h b/Kernel/types.h index c7e135fbfb..34113c3e04 100644 --- a/Kernel/types.h +++ b/Kernel/types.h @@ -41,6 +41,33 @@ struct utsname { char machine[UTSNAME_ENTRY_LEN]; }; +typedef dword ino_t; +typedef signed_dword off_t; + +typedef dword dev_t; +typedef dword mode_t; +typedef dword nlink_t; +typedef dword blksize_t; +typedef dword blkcnt_t; +typedef dword time_t; +typedef dword suseconds_t; + +struct stat { + dev_t st_dev; /* ID of device containing file */ + ino_t st_ino; /* inode number */ + mode_t st_mode; /* protection */ + nlink_t st_nlink; /* number of hard links */ + uid_t st_uid; /* user ID of owner */ + gid_t st_gid; /* group ID of owner */ + dev_t st_rdev; /* device ID (if special file) */ + off_t st_size; /* total size, in bytes */ + blksize_t st_blksize; /* blocksize for file system I/O */ + blkcnt_t st_blocks; /* number of 512B blocks allocated */ + time_t st_atime; /* time of last access */ + time_t st_mtime; /* time of last modification */ + time_t st_ctime; /* time of last status change */ +}; + struct FarPtr { DWORD offset { 0 }; WORD selector { 0 };