1// Copyright 2017 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <dirent.h>
6#include <dlfcn.h>
7#include <errno.h>
8#include <fcntl.h>
9#include <string.h>
10#include <unistd.h>
11#include <unittest/unittest.h>
12
13#define GOOD_SYMBOL     "zx_syscall_test_0"
14#define BAD_SYMBOL      "zx_syscall_test_1"
15
16bool vdso_open_test(void) {
17    BEGIN_TEST;
18
19    int vdso_dir_fd = open("/boot/kernel/vdso", O_RDONLY | O_DIRECTORY);
20    ASSERT_GE(vdso_dir_fd, 0, "open of vdso directory failed");
21
22    DIR* dir = fdopendir(dup(vdso_dir_fd));
23    ASSERT_NONNULL(dir, "fdopendir failed");
24
25    const struct dirent* d;
26    int vdso_files_found = 0;
27    while ((d = readdir(dir)) != NULL) {
28        if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
29            continue;
30
31        ++vdso_files_found;
32        // Test that we can open for read.
33        int fd = openat(vdso_dir_fd, d->d_name, O_RDONLY);
34        EXPECT_GE(fd, 0, d->d_name);
35        EXPECT_EQ(close(fd), 0, "");
36
37        // Test that we cannot open for write.
38        EXPECT_EQ(openat(vdso_dir_fd, d->d_name, O_RDWR), -1,
39                  "opening vDSO file for writing");
40        EXPECT_EQ(errno, EACCES, "opening vDSO file for writing");
41    }
42
43    EXPECT_GT(vdso_files_found, 1, "didn't find vDSO files");
44
45    EXPECT_EQ(closedir(dir), 0, "");
46    EXPECT_EQ(close(vdso_dir_fd), 0, "");
47
48    END_TEST;
49}
50
51bool vdso_missing_test_syscall1_test(void) {
52    BEGIN_TEST;
53
54    void* dso = dlopen("libzircon.so", RTLD_LOCAL | RTLD_NOLOAD);
55    ASSERT_NONNULL(dso, dlerror());
56
57    EXPECT_NONNULL(dlsym(dso, GOOD_SYMBOL), dlerror());
58
59    EXPECT_NULL(dlsym(dso, BAD_SYMBOL), BAD_SYMBOL " symbol found in vDSO");
60
61    EXPECT_EQ(dlclose(dso), 0, "");
62
63    END_TEST;
64}
65
66BEGIN_TEST_CASE(vdso_variant_tests)
67RUN_TEST(vdso_open_test)
68RUN_TEST(vdso_missing_test_syscall1_test)
69END_TEST_CASE(vdso_variant_tests)
70
71int main(int argc, char** argv) {
72    return unittest_run_all_tests(argc, argv) ? 0 : -1;
73}
74