# Node ID 693893fbee1f3b5946b3eaf495bcc1d7812373c7 # Parent baf743047c381c4bca28ad50d1cd37e239e0608a diff --git a/src/arch/x86/linux/process.cc b/src/arch/x86/linux/process.cc --- a/src/arch/x86/linux/process.cc +++ b/src/arch/x86/linux/process.cc @@ -477,7 +477,7 @@ /* 254 */ SyscallDesc("inotify_add_watch", unimplementedFunc), /* 255 */ SyscallDesc("inotify_rm_watch", unimplementedFunc), /* 256 */ SyscallDesc("migrate_pages", unimplementedFunc), - /* 257 */ SyscallDesc("openat", unimplementedFunc), + /* 257 */ SyscallDesc("openat", openatFunc), /* 258 */ SyscallDesc("mkdirat", unimplementedFunc), /* 259 */ SyscallDesc("mknodat", unimplementedFunc), /* 260 */ SyscallDesc("fchownat", unimplementedFunc), @@ -844,7 +844,7 @@ /* 292 */ SyscallDesc("inotify_add_watch", unimplementedFunc), /* 293 */ SyscallDesc("inotify_rm_watch", unimplementedFunc), /* 294 */ SyscallDesc("migrate_pages", unimplementedFunc), - /* 295 */ SyscallDesc("openat", unimplementedFunc), + /* 295 */ SyscallDesc("openat", openatFunc), /* 296 */ SyscallDesc("mkdirat", unimplementedFunc), /* 297 */ SyscallDesc("mknodat", unimplementedFunc), /* 298 */ SyscallDesc("fchownat", unimplementedFunc), diff --git a/src/kern/linux/linux.hh b/src/kern/linux/linux.hh --- a/src/kern/linux/linux.hh +++ b/src/kern/linux/linux.hh @@ -247,6 +247,7 @@ static int openSpecialFile(std::string path, Process *process, ThreadContext *tc); static std::string procMeminfo(Process *process, ThreadContext *tc); + static std::string etcPasswd(Process *process, ThreadContext *tc); // For futex system call static const unsigned TGT_FUTEX_WAIT = 0; diff --git a/src/kern/linux/linux.cc b/src/kern/linux/linux.cc --- a/src/kern/linux/linux.cc +++ b/src/kern/linux/linux.cc @@ -33,6 +33,7 @@ #include #include +#include "cpu/base.hh" #include "debug/SyscallVerbose.hh" #include "sim/process.hh" #include "sim/system.hh" @@ -41,21 +42,35 @@ Linux::openSpecialFile(std::string path, Process *process, ThreadContext *tc) { - DPRINTF(SyscallVerbose, "Opening special file: %s\n", path.c_str()); + DPRINTFR(SyscallVerbose, + "%d: %s: generic-open: opening special file: %s\n", + curTick(), tc->getCpuPtr()->name(), path.c_str()); + + bool matched = false; + std::string data; + if (path.compare(0, 13, "/proc/meminfo") == 0) { - std::string data = Linux::procMeminfo(process, tc); + data = Linux::procMeminfo(process, tc); + matched = true; + } else if (path.compare(0, 11, "/etc/passwd") == 0) { + data = Linux::etcPasswd(process, tc); + matched = true; + } + + if (matched) { FILE *f = tmpfile(); int fd = fileno(f); size_t ret M5_VAR_USED = fwrite(data.c_str(), 1, data.size(), f); assert(ret == data.size()); rewind(f); return fd; + } else { + warn("Attempting to open special file: %s. Ignoring. Simulation may " + "take un-expected code path or be non-deterministic until proper " + "handling is implemented.\n", path.c_str()); + errno = EACCES; + return -1; } - - warn("Attempting to open special file: %s. Ignoring. Simulation may" - " take un-expected code path or be non-deterministic until proper" - " handling is implemented.\n", path.c_str()); - return -1; } std::string @@ -66,3 +81,9 @@ process->system->freeMemSize() >> 10); } +std::string +Linux::etcPasswd(Process *process, ThreadContext *tc) +{ + return csprintf("gem5-user:x:1000:1000:gem5-user,,,:%s:/bin/bash\n", + process->getcwd()); +} diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh --- a/src/sim/syscall_emul.hh +++ b/src/sim/syscall_emul.hh @@ -560,80 +560,96 @@ } template -static SyscallReturn -openFunc(SyscallDesc *desc, int callnum, Process *process, - ThreadContext *tc, int index) +SyscallReturn +openImpl(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc, + bool isopenat) { + int index = 0; + + int tgt_dirfd = isopenat ? p->getSyscallArg(tc, index) : -1; + if (isopenat && (tgt_dirfd != OS::TGT_AT_FDCWD) && + p->fds[tgt_dirfd]->getSimFD() < 0) + return -EBADF; + std::string path; - if (!tc->getMemProxy().tryReadString(path, - process->getSyscallArg(tc, index))) + if (!tc->getMemProxy().tryReadString(path, p->getSyscallArg(tc, index))) return -EFAULT; - int tgtFlags = process->getSyscallArg(tc, index); - int mode = process->getSyscallArg(tc, index); - int hostFlags = 0; +#ifdef __CYGWIN32__ + int host_flags = O_BINARY; +#else + int host_flags = 0; +#endif - // translate open flags + int tgt_flags = p->getSyscallArg(tc, index); + int mode = p->getSyscallArg(tc, index); + + // Translate target flags into host flags. Flags exist which are not + // ported between architectures which can cause check failures. for (int i = 0; i < OS::NUM_OPEN_FLAGS; i++) { - if (tgtFlags & OS::openFlagTable[i].tgtFlag) { - tgtFlags &= ~OS::openFlagTable[i].tgtFlag; - hostFlags |= OS::openFlagTable[i].hostFlag; + if (tgt_flags & OS::openFlagTable[i].tgtFlag) { + tgt_flags &= ~OS::openFlagTable[i].tgtFlag; + host_flags |= OS::openFlagTable[i].hostFlag; } } - // any target flags left? - if (tgtFlags != 0) - warn("Syscall: open: cannot decode flags 0x%x", tgtFlags); + if (tgt_flags) { + warn("open%s: cannot decode flags 0x%x", + isopenat ? "at" : "", tgt_flags); + } #ifdef __CYGWIN32__ - hostFlags |= O_BINARY; + host_flags |= O_BINARY; #endif + if (!isopenat || tgt_dirfd == OS::TGT_AT_FDCWD) + path = p->fullPath(path); + else if (!startswith(path, "/")) { + FileFDPtr ffd = + std::dynamic_pointer_cast(p->fds[tgt_dirfd]); - // Adjust path for current working directory - path = process->fullPath(path); - - DPRINTF(SyscallVerbose, "opening file %s\n", path.c_str()); + if (ffd == nullptr || ffd->getSimFD() < 0) + return -EBADF; + path.insert(0, ffd->getFileName()); + } if (startswith(path, "/dev/")) { std::string filename = path.substr(strlen("/dev/")); - if (filename == "sysdev0") { - // This is a memory-mapped high-resolution timer device on Alpha. - // We don't support it, so just punt. - warn("Ignoring open(%s, ...)\n", path); - return -ENOENT; + EmulatedDriver *drv = p->findDriver(filename); + if (drv != NULL) { + // driver's open method will allocate a fd if necessary. + DPRINTF_SYSCALL(Verbose, "open%s: passing call to " + "driver open with path[%s]\n", + isopenat ? "at" : "", path.c_str()); + return drv->open(p, tc, mode, host_flags); } - EmulatedDriver *drv = process->findDriver(filename); - if (drv != NULL) { - // the driver's open method will allocate a fd from the - // process if necessary. - return drv->open(process, tc, mode, hostFlags); - } - - // fall through here for pass through to host devices, such as - // /dev/zero + // fall through here for pass through to host devices, such + // as /dev/zero } - int fd; - int local_errno; - if (startswith(path, "/proc/") || startswith(path, "/system/") || - startswith(path, "/platform/") || startswith(path, "/sys/")) { - // It's a proc/sys entry and requires special handling - fd = OS::openSpecialFile(path, process, tc); - local_errno = ENOENT; - } else { - // open the file - fd = open(path.c_str(), hostFlags, mode); - local_errno = errno; - } + int sim_fd = startswith(path, "/proc/") || startswith(path, "/system/") || + startswith(path, "/platform/") || startswith(path, "/sys/")|| + startswith(path, "/etc/passwd") ? + OS::openSpecialFile(path, p, tc) : + open(path.c_str(), host_flags, mode); - if (fd == -1) - return -local_errno; + if (sim_fd == -1) { + int local = -errno; + DPRINTF_SYSCALL(Verbose, "open%s: failed -> path:%s\n", + isopenat ? "at" : "", path.c_str()); + return local; + } - FileFDPtr ffd = - std::make_shared(fd, hostFlags, path.c_str(), false); - return process->fds.allocFD(ffd); + FileFDPtr fdp = std::make_shared(sim_fd, host_flags, + path.c_str(), 0); + int tgt_fd = p->fds.allocFD(fdp); + + DPRINTF_SYSCALL(Verbose, "open%s: opened sim_fd[%d], target_fd[%d] " + "-> path:%s\n", + isopenat ? "at" : "", sim_fd, tgt_fd, path.c_str()); + + return tgt_fd; } /// Target open() handler. @@ -642,7 +658,7 @@ openFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc) { - return openFunc(desc, callnum, process, tc, 0); + return openImpl(desc, callnum, process, tc, false); } /// Target openat() handler. @@ -651,11 +667,7 @@ openatFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc) { - int index = 0; - int dirfd = process->getSyscallArg(tc, index); - if (dirfd != OS::TGT_AT_FDCWD) - warn("openat: first argument not AT_FDCWD; unlikely to work"); - return openFunc(desc, callnum, process, tc, 1); + return openImpl(desc, callnum, process, tc, true); } /// Target unlinkat() handler.