aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorCristian Cadar <c.cadar@imperial.ac.uk>2023-06-09 23:06:41 +0100
committerMartinNowack <2443641+MartinNowack@users.noreply.github.com>2023-06-11 19:23:24 +0100
commitc10e9e926700773e01f44fbb1917deac7be2aaea (patch)
tree7abfceec757330360ec5d4be383e4c7a5a8933b7
parentdab1c0fa376771be1c3cdd5b8d564484755907dd (diff)
downloadklee-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.c32
-rw-r--r--test/Runtime/POSIX/FilePerm.c15
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);
}