diff options
Diffstat (limited to 'runtime/POSIX')
-rw-r--r-- | runtime/POSIX/fd.c | 183 | ||||
-rw-r--r-- | runtime/POSIX/fd.h | 1 | ||||
-rw-r--r-- | runtime/POSIX/fd_32.c | 47 | ||||
-rw-r--r-- | runtime/POSIX/fd_64.c | 24 | ||||
-rw-r--r-- | runtime/POSIX/stubs.c | 45 | ||||
l--------- | runtime/POSIX/testing-dir/a | 1 | ||||
l--------- | runtime/POSIX/testing-dir/b | 1 | ||||
-rwxr-xr-x | runtime/POSIX/testing-dir/c | 2 | ||||
-rw-r--r-- | runtime/POSIX/testing-dir/d | 0 | ||||
-rw-r--r-- | runtime/POSIX/testing-env | 27 |
10 files changed, 247 insertions, 84 deletions
diff --git a/runtime/POSIX/fd.c b/runtime/POSIX/fd.c index b9a848d0..1c75cd76 100644 --- a/runtime/POSIX/fd.c +++ b/runtime/POSIX/fd.c @@ -35,7 +35,7 @@ void klee_warning(const char*); void klee_warning_once(const char*); int klee_get_errno(void); -/* Returns pointer to the symbolic file structure is the pathname is symbolic */ +/* Returns pointer to the symbolic file structure fs the pathname is symbolic */ static exe_disk_file_t *__get_sym_file(const char *pathname) { char c = pathname[0]; unsigned i; @@ -198,6 +198,108 @@ int __fd_open(const char *pathname, int flags, mode_t mode) { return fd; } +int __fd_openat(int basefd, const char *pathname, int flags, mode_t mode) { + exe_file_t *f; + int fd; + if (basefd != AT_FDCWD) { + exe_file_t *bf = __get_file(basefd); + + if (!bf) { + errno = EBADF; + return -1; + } else if (bf->dfile) { + klee_warning("symbolic file descriptor, ignoring (ENOENT)"); + errno = ENOENT; + return -1; + } + basefd = bf->fd; + } + + if (__get_sym_file(pathname)) { + /* for a symbolic file, it doesn't matter if/where it exists on disk */ + return __fd_open(pathname, flags, mode); + } + + for (fd = 0; fd < MAX_FDS; ++fd) + if (!(__exe_env.fds[fd].flags & eOpen)) + break; + if (fd == MAX_FDS) { + errno = EMFILE; + return -1; + } + + f = &__exe_env.fds[fd]; + + /* Should be the case if file was available, but just in case. */ + memset(f, 0, sizeof *f); + + int os_fd = syscall(__NR_openat, (long)basefd, __concretize_string(pathname), (long)flags, mode); + if (os_fd == -1) { + errno = klee_get_errno(); + return -1; + } + + f->fd = os_fd; + f->flags = eOpen; + if ((flags & O_ACCMODE) == O_RDONLY) { + f->flags |= eReadable; + } else if ((flags & O_ACCMODE) == O_WRONLY) { + f->flags |= eWriteable; + } else { /* XXX What actually happens here if != O_RDWR. */ + f->flags |= eReadable | eWriteable; + } + + return fd; +} + + +int utimes(const char *path, const struct timeval times[2]) { + exe_disk_file_t *dfile = __get_sym_file(path); + + if (dfile) { + /* don't bother with usecs */ + dfile->stat->st_atime = times[0].tv_sec; + dfile->stat->st_mtime = times[1].tv_sec; +#ifdef _BSD_SOURCE + dfile->stat->st_atim.tv_nsec = 1000000000ll * times[0].tv_sec; + dfile->stat->st_mtim.tv_nsec = 1000000000ll * times[1].tv_sec; +#endif + return 0; + } + int r = syscall(__NR_utimes, __concretize_string(path), times); + if (r == -1) + errno = klee_get_errno(); + + return r; +} + + +int futimesat(int fd, const char* path, const struct timeval times[2]) { + if (fd != AT_FDCWD) { + exe_file_t *f = __get_file(fd); + + if (!f) { + errno = EBADF; + return -1; + } else if (f->dfile) { + klee_warning("symbolic file descriptor, ignoring (ENOENT)"); + errno = ENOENT; + return -1; + } + fd = f->fd; + } + if (__get_sym_file(path)) { + return utimes(path, times); + } + + int r = syscall(__NR_futimesat, (long)fd, + (path ? __concretize_string(path) : NULL), + times); + if (r == -1) + errno = klee_get_errno(); + return r; +} + int close(int fd) { static int n_calls = 0; exe_file_t *f; @@ -387,15 +489,15 @@ off64_t __fd_lseek(int fd, off64_t offset, int whence) { the offset, but really directories should only be SEEK_SET, so this solves the problem. */ if (whence == SEEK_SET) { - new_off = syscall(__NR_lseek, f->fd, (int) offset, SEEK_SET); + new_off = syscall(__NR_lseek, f->fd, offset, SEEK_SET); } else { - new_off = syscall(__NR_lseek, f->fd, (int) f->off, SEEK_SET); + new_off = syscall(__NR_lseek, f->fd, f->off, SEEK_SET); /* If we can't seek to start off, just return same error. Probably ESPIPE. */ if (new_off != -1) { assert(new_off == f->off); - new_off = syscall(__NR_lseek, f->fd, (int) offset, whence); + new_off = syscall(__NR_lseek, f->fd, offset, whence); } } @@ -446,6 +548,42 @@ int __fd_stat(const char *path, struct stat64 *buf) { } } +int fstatat(int fd, const char *path, struct stat *buf, int flags) { + if (fd != AT_FDCWD) { + exe_file_t *f = __get_file(fd); + + if (!f) { + errno = EBADF; + return -1; + } else if (f->dfile) { + klee_warning("symbolic file descriptor, ignoring (ENOENT)"); + errno = ENOENT; + return -1; + } + fd = f->fd; + } + exe_disk_file_t *dfile = __get_sym_file(path); + if (dfile) { + memcpy(buf, dfile->stat, sizeof(*dfile->stat)); + return 0; + } + +#if (defined __NR_newfstatat) && (__NR_newfstatat != 0) + int r = syscall(__NR_newfstatat, (long)fd, + (path ? __concretize_string(path) : NULL), + buf, (long)flags); +#else + int r = syscall(__NR_fstatat64, (long)fd, + (path ? __concretize_string(path) : NULL), + buf, (long)flags); +#endif + + if (r == -1) + errno = klee_get_errno(); + return r; +} + + int __fd_lstat(const char *path, struct stat64 *buf) { exe_disk_file_t *dfile = __get_sym_file(path); if (dfile) { @@ -680,7 +818,7 @@ int __fd_getdents(unsigned int fd, struct dirent64 *dirp, unsigned int count) { errno = EBADF; return -1; } - + if (f->dfile) { klee_warning("symbolic file, ignoring (EINVAL)"); errno = EINVAL; @@ -688,7 +826,7 @@ int __fd_getdents(unsigned int fd, struct dirent64 *dirp, unsigned int count) { } else { if ((unsigned long) f->off < 4096u) { /* Return our dirents */ - unsigned i, pad, bytes=0; + off64_t i, pad, bytes=0; /* What happens for bad offsets? */ i = f->off / sizeof(*dirp); @@ -718,10 +856,12 @@ int __fd_getdents(unsigned int fd, struct dirent64 *dirp, unsigned int count) { dirp->d_off = 4096; bytes += dirp->d_reclen; f->off = pad; + return bytes; } else { - unsigned os_pos = f->off - 4096; - int res, s; + off64_t os_pos = f->off - 4096; + int res; + off64_t s = 0; /* For reasons which I really don't understand, if I don't memset this then sometimes the kernel returns d_ino==0 for @@ -731,14 +871,13 @@ int __fd_getdents(unsigned int fd, struct dirent64 *dirp, unsigned int count) { Even more bizarre, interchanging the memset and the seek also case strange behavior. Really should be debugged properly. */ memset(dirp, 0, count); - s = syscall(__NR_lseek, f->fd, (int) os_pos, SEEK_SET); + s = syscall(__NR_lseek, f->fd, os_pos, SEEK_SET); assert(s != (off64_t) -1); res = syscall(__NR_getdents64, f->fd, dirp, count); if (res == -1) { errno = klee_get_errno(); } else { int pos = 0; - f->off = syscall(__NR_lseek, f->fd, 0, SEEK_CUR) + 4096; /* Patch offsets */ @@ -747,6 +886,7 @@ int __fd_getdents(unsigned int fd, struct dirent64 *dirp, unsigned int count) { struct dirent64 *dp = (struct dirent64*) ((char*) dirp + pos); dp->d_off += 4096; pos += dp->d_reclen; + } } return res; @@ -1096,6 +1236,29 @@ int unlink(const char *pathname) { return -1; } +int unlinkat(int dirfd, const char *pathname, int flags) { + /* similar to unlink. keep them separated though to avoid + problems if unlink changes to actually delete files */ + exe_disk_file_t *dfile = __get_sym_file(pathname); + if (dfile) { + /* XXX check access */ + if (S_ISREG(dfile->stat->st_mode)) { + dfile->stat->st_ino = 0; + return 0; + } else if (S_ISDIR(dfile->stat->st_mode)) { + errno = EISDIR; + return -1; + } else { + errno = EPERM; + return -1; + } + } + + klee_warning("ignoring (EPERM)"); + errno = EPERM; + return -1; +} + ssize_t readlink(const char *path, char *buf, size_t bufsize) { exe_disk_file_t *dfile = __get_sym_file(path); if (dfile) { diff --git a/runtime/POSIX/fd.h b/runtime/POSIX/fd.h index f2780143..cb86295c 100644 --- a/runtime/POSIX/fd.h +++ b/runtime/POSIX/fd.h @@ -79,6 +79,7 @@ void klee_init_env(int *argcPtr, char ***argvPtr); /* *** */ int __fd_open(const char *pathname, int flags, mode_t mode); +int __fd_openat(int basefd, const char *pathname, int flags, mode_t mode); off64_t __fd_lseek(int fd, off64_t offset, int whence); int __fd_stat(const char *path, struct stat64 *buf); int __fd_lstat(const char *path, struct stat64 *buf); diff --git a/runtime/POSIX/fd_32.c b/runtime/POSIX/fd_32.c index 6246f057..36c5d41f 100644 --- a/runtime/POSIX/fd_32.c +++ b/runtime/POSIX/fd_32.c @@ -6,7 +6,18 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// +// Contains 32bit definitions of posix file functions +//===--- +#if __GNUC__ +#if __x86_64__ || __ppc64__ +#define ENV64 +#else +#define ENV32 +#endif +#endif + +#include "klee/Config/Version.h" #define _LARGEFILE64_SOURCE #include "fd.h" @@ -41,6 +52,12 @@ static void __stat64_to_stat(struct stat64 *a, struct stat *b) { b->st_ctime = a->st_ctime; b->st_blksize = a->st_blksize; b->st_blocks = a->st_blocks; +#ifdef _BSD_SOURCE + b->st_atim.tv_nsec = a->st_atim.tv_nsec; + b->st_mtim.tv_nsec = a->st_mtim.tv_nsec; + b->st_ctim.tv_nsec = a->st_ctim.tv_nsec; +#endif + } /***/ @@ -59,6 +76,20 @@ int open(const char *pathname, int flags, ...) { return __fd_open(pathname, flags, mode); } +int openat(int fd, const char *pathname, int flags, ...) { + mode_t mode = 0; + + if (flags & O_CREAT) { + /* get mode */ + va_list ap; + va_start(ap, flags); + mode = va_arg(ap, mode_t); + va_end(ap); + } + + return __fd_openat(fd, pathname, flags, mode); +} + off_t lseek(int fd, off_t off, int whence) { return (off_t) __fd_lseek(fd, off, whence); } @@ -173,19 +204,3 @@ __attribute__((weak)) int open64(const char *pathname, int flags, ...) { return __fd_open(pathname, flags, mode); } - -__attribute__((weak)) off64_t lseek64(int fd, off64_t off, int whence) { - return __fd_lseek(fd, off, whence); -} - -__attribute__((weak)) int stat64(const char *path, struct stat64 *buf) { - return __fd_stat(path, buf); -} - -__attribute__((weak)) int lstat64(const char *path, struct stat64 *buf) { - return __fd_lstat(path, buf); -} - -__attribute__((weak)) int fstat64(int fd, struct stat64 *buf) { - return __fd_fstat(fd, buf); -} diff --git a/runtime/POSIX/fd_64.c b/runtime/POSIX/fd_64.c index d0710caf..03fccc49 100644 --- a/runtime/POSIX/fd_64.c +++ b/runtime/POSIX/fd_64.c @@ -7,6 +7,16 @@ // //===----------------------------------------------------------------------===// +#if __GNUC__ +#if __x86_64__ || __ppc64__ +#define ENV64 +#else +#define ENV32 +#endif +#endif + + +#include "klee/Config/Version.h" #define _LARGEFILE64_SOURCE #define _FILE_OFFSET_BITS 64 #include "fd.h" @@ -46,6 +56,20 @@ int open(const char *pathname, int flags, ...) { return __fd_open(pathname, flags, mode); } +int openat(int fd, const char *pathname, int flags, ...) { + mode_t mode = 0; + + if (flags & O_CREAT) { + /* get mode */ + va_list ap; + va_start(ap, flags); + mode = va_arg(ap, mode_t); + va_end(ap); + } + + return __fd_openat(fd, pathname, flags, mode); +} + off64_t lseek(int fd, off64_t offset, int whence) { return __fd_lseek(fd, offset, whence); } diff --git a/runtime/POSIX/stubs.c b/runtime/POSIX/stubs.c index 3a9d380c..99e2e768 100644 --- a/runtime/POSIX/stubs.c +++ b/runtime/POSIX/stubs.c @@ -7,19 +7,21 @@ // //===----------------------------------------------------------------------===// -#include <string.h> -#include <stdio.h> +#define _XOPEN_SOURCE 700 + #include <errno.h> +#include <limits.h> #include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> #include <time.h> +#include <unistd.h> #include <utime.h> #include <utmp.h> -#include <unistd.h> -#include <limits.h> -#include <stdlib.h> #include <sys/mman.h> -#include <sys/stat.h> #include <sys/resource.h> +#include <sys/stat.h> #include <sys/times.h> #include <sys/types.h> #include <sys/wait.h> @@ -31,20 +33,20 @@ void klee_warning_once(const char*); /* Silent ignore */ -int __syscall_rt_sigaction(int signum, const struct sigaction *act, +int __syscall_rt_sigaction(int signum, const struct sigaction *act, struct sigaction *oldact, size_t _something) __attribute__((weak)); -int __syscall_rt_sigaction(int signum, const struct sigaction *act, +int __syscall_rt_sigaction(int signum, const struct sigaction *act, struct sigaction *oldact, size_t _something) { klee_warning_once("silently ignoring"); return 0; } -int sigaction(int signum, const struct sigaction *act, +int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact) __attribute__((weak)); -int sigaction(int signum, const struct sigaction *act, +int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact) { klee_warning_once("silently ignoring"); return 0; @@ -122,21 +124,21 @@ int link(const char *oldpath, const char *newpath) __attribute__((weak)); int link(const char *oldpath, const char *newpath) { klee_warning("ignoring (EPERM)"); errno = EPERM; - return -1; + return -1; } int symlink(const char *oldpath, const char *newpath) __attribute__((weak)); int symlink(const char *oldpath, const char *newpath) { klee_warning("ignoring (EPERM)"); errno = EPERM; - return -1; + return -1; } int rename(const char *oldpath, const char *newpath) __attribute__((weak)); int rename(const char *oldpath, const char *newpath) { klee_warning("ignoring (EPERM)"); errno = EPERM; - return -1; + return -1; } int nanosleep(const struct timespec *req, struct timespec *rem) __attribute__((weak)); @@ -222,13 +224,6 @@ int utime(const char *filename, const struct utimbuf *buf) { return -1; } -int utimes(const char *filename, const struct timeval times[2]) __attribute__((weak)); -int utimes(const char *filename, const struct timeval times[2]) { - klee_warning("ignoring (EPERM)"); - errno = EPERM; - return -1; -} - int futimes(int fd, const struct timeval times[2]) __attribute__((weak)); int futimes(int fd, const struct timeval times[2]) { klee_warning("ignoring (EBADF)"); @@ -253,17 +248,13 @@ unsigned int gnu_dev_minor(unsigned long long int __dev) { unsigned long long int gnu_dev_makedev(unsigned int __major, unsigned int __minor) __attribute__((weak)); unsigned long long int gnu_dev_makedev(unsigned int __major, unsigned int __minor) { return ((__minor & 0xff) | ((__major & 0xfff) << 8) - | (((unsigned long long int) (__minor & ~0xff)) << 12) - | (((unsigned long long int) (__major & ~0xfff)) << 32)); + | (((unsigned long long int) (__minor & ~0xff)) << 12) + | (((unsigned long long int) (__major & ~0xfff)) << 32)); } char *canonicalize_file_name (const char *name) __attribute__((weak)); char *canonicalize_file_name (const char *name) { - char *res = malloc(PATH_MAX); - char *rp_res = realpath(name, res); - if (!rp_res) - free(res); - return rp_res; + return realpath(name, NULL); } int getloadavg(double loadavg[], int nelem) __attribute__((weak)); diff --git a/runtime/POSIX/testing-dir/a b/runtime/POSIX/testing-dir/a deleted file mode 120000 index dc1dc0cd..00000000 --- a/runtime/POSIX/testing-dir/a +++ /dev/null @@ -1 +0,0 @@ -/dev/null \ No newline at end of file diff --git a/runtime/POSIX/testing-dir/b b/runtime/POSIX/testing-dir/b deleted file mode 120000 index b9251ec6..00000000 --- a/runtime/POSIX/testing-dir/b +++ /dev/null @@ -1 +0,0 @@ -/dev/random \ No newline at end of file diff --git a/runtime/POSIX/testing-dir/c b/runtime/POSIX/testing-dir/c deleted file mode 100755 index 2b45f6a5..00000000 --- a/runtime/POSIX/testing-dir/c +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -echo "Hello world!" diff --git a/runtime/POSIX/testing-dir/d b/runtime/POSIX/testing-dir/d deleted file mode 100644 index e69de29b..00000000 --- a/runtime/POSIX/testing-dir/d +++ /dev/null diff --git a/runtime/POSIX/testing-env b/runtime/POSIX/testing-env deleted file mode 100644 index 5a6e8eb8..00000000 --- a/runtime/POSIX/testing-env +++ /dev/null @@ -1,27 +0,0 @@ -# This file is sourced prior to running the testing environment, make -# sure to quote things. - -export TERM="xterm" -export SHELL="/bin/bash" -export LS_COLORS="no=00:fi=00:di=01;34:ln=01;36:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:su=37;41:sg=30;43:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.gz=01;31:*.bz2=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.avi=01;35:*.fli=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.flac=01;35:*.mp3=01;35:*.mpc=01;35:*.ogg=01;35:*.wav=01;35:" -export PATH="/usr/local/bin:/usr/bin:/bin" -export COLORTERM="gnome-terminal" -export LC_ALL=C -export TABSIZE=8 -export COLUMNS=80 - -# 1 BLOCK_SIZE -# 2 COLUMNS -# 1 DF_BLOCK_SIZE -# 1 DU_BLOCK_SIZE -# 1 HOME -# 1 LS_BLOCK_SIZE -# 1 LS_COLORS -# 11 POSIXLY_CORRECT -# 1 QUOTING_STYLE -# 3 SHELL -# 4 SIMPLE_BACKUP_SUFFIX -# 1 TABSIZE -# 2 TERM -# 2 TIME_STYLE -# 4 TMPDIR |