diff options
author | Cristian Cadar <c.cadar@imperial.ac.uk> | 2023-06-09 23:06:41 +0100 |
---|---|---|
committer | MartinNowack <2443641+MartinNowack@users.noreply.github.com> | 2023-06-11 19:23:24 +0100 |
commit | c10e9e926700773e01f44fbb1917deac7be2aaea (patch) | |
tree | 7abfceec757330360ec5d4be383e4c7a5a8933b7 | |
parent | dab1c0fa376771be1c3cdd5b8d564484755907dd (diff) | |
download | klee-c10e9e926700773e01f44fbb1917deac7be2aaea.tar.gz |
Rewrote has_permission in the POSIX runtime. We now only return with permission error a single time in symbolic execution mode.
The rewrite also fixes a bug reported in #1230. Rewrote the FilePerm.c test accordingly.
-rw-r--r-- | runtime/POSIX/fd.c | 32 | ||||
-rw-r--r-- | test/Runtime/POSIX/FilePerm.c | 15 |
2 files changed, 19 insertions, 28 deletions
diff --git a/runtime/POSIX/fd.c b/runtime/POSIX/fd.c index be13a40b..b41d4e32 100644 --- a/runtime/POSIX/fd.c +++ b/runtime/POSIX/fd.c @@ -106,32 +106,18 @@ mode_t umask(mode_t mask) { /* Returns 1 if the process has the access rights specified by 'flags' - to the file with stat 's'. Returns 0 otherwise*/ + to the file with stat 's', and returns 0 otherwise. + We allow access if any user has access to the file, so we ignore + s->st_uid / geteuid() and s->st_gid / getegid(). */ static int has_permission(int flags, struct stat64 *s) { - int write_access, read_access; mode_t mode = s->st_mode; - - if (flags & O_RDONLY || flags & O_RDWR) - read_access = 1; - else read_access = 0; - - if (flags & O_WRONLY || flags & O_RDWR) - write_access = 1; - else write_access = 0; - - /* XXX: We don't worry about process uid and gid for now. - We allow access if any user has access to the file. */ -#if 0 - uid_t uid = s->st_uid; - uid_t euid = geteuid(); - gid_t gid = s->st_gid; - gid_t egid = getegid(); -#endif - - if (read_access && ((mode & S_IRUSR) | (mode & S_IRGRP) | (mode & S_IROTH))) - return 0; + int read_request = ((flags & O_RDONLY) | (flags & O_RDWR)) ? 1 : 0; + int write_request = ((flags & O_WRONLY) | (flags & O_RDWR)) ? 1 : 0; - if (write_access && !((mode & S_IWUSR) | (mode & S_IWGRP) | (mode & S_IWOTH))) + /* It is important to do this check using only bitwise operators so that we + return 0 a single time in symbolic execution mode. */ + if ((read_request & !((mode & S_IRUSR) | (mode & S_IRGRP) | (mode & S_IROTH))) | + (write_request & !((mode & S_IWUSR) | (mode & S_IWGRP) | (mode & S_IWOTH)))) return 0; return 1; diff --git a/test/Runtime/POSIX/FilePerm.c b/test/Runtime/POSIX/FilePerm.c index 418e3717..5fc9924f 100644 --- a/test/Runtime/POSIX/FilePerm.c +++ b/test/Runtime/POSIX/FilePerm.c @@ -1,21 +1,26 @@ +/* This test checks that when opening a symbolic file in R/W mode, we return exactly twice: + once successfully, and the other time with a permission error */ + // RUN: %clang %s -emit-llvm %O0opt -c -o %t.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --posix-runtime %t.bc --sym-files 1 10 --sym-stdout 2>%t.log +// RUN: %klee --output-dir=%t.klee-out --posix-runtime %t.bc --sym-files 1 10 | FileCheck %s // RUN: test -f %t.klee-out/test000001.ktest // RUN: test -f %t.klee-out/test000002.ktest -// RUN: test -f %t.klee-out/test000003.ktest +// RUN: not test -f %t.klee-out/test000003.ktest #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> +#include <unistd.h> int main(int argc, char** argv) { int fd = open("A", O_RDWR); if (fd != -1) - fprintf(stderr, "File 'A' opened successfully\n"); - else fprintf(stderr, "Cannot open file 'A'\n"); - + printf("File 'A' opened successfully\n"); + // CHECK-DAG: File 'A' opened successfully + else printf("Cannot open file 'A'\n"); + // CHECK-DAG: Cannot open file 'A' if (fd != -1) close(fd); } |