summaryrefslogtreecommitdiffstats
path: root/src/test/test-label.c
blob: 9d7ac18ba9a0dc10d015d011f8e497e89507f1d1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
/* SPDX-License-Identifier: LGPL-2.1-or-later */

#include <errno.h>
#include <stddef.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>

#include "errno-util.h"
#include "fd-util.h"
#include "fs-util.h"
#include "label.h"
#include "path-util.h"
#include "string-util.h"
#include "tests.h"

static struct stat buf;
static int check_path(int dir_fd, const char *path) {
        assert(path);
        assert(dir_fd >= 0 || dir_fd == AT_FDCWD);

        if (isempty(path))
                return -EINVAL;

        /* assume length of pathname is not greater than 40*/
        if (strlen(path) > 40)
                return -ENAMETOOLONG;

        /* assume a case where a specific label isn't allowed */
        if (path_equal(path, "/restricted_directory"))
                return -EACCES;
        return 0;
}

static int pre_labelling_func(int dir_fd, const char *path, mode_t mode) {
        int r;

        assert(mode != MODE_INVALID);
        r = check_path(dir_fd, path);
        if (r < 0)
                return log_error_errno(r, "Error in pathname =>: %m");

        return 0;
}

static int post_labelling_func(int dir_fd, const char *path) {
       int r;

        /* assume label policies that restrict certain labels */
        r = check_path(dir_fd, path);
        if (r < 0)
                return log_error_errno(r, "Error in pathname =>: %m");

        /* Set file data to buf */
        r = RET_NERRNO(fstatat(dir_fd, path, &buf, 0));
        if (r < 0)
                return log_error_errno(r, "Error in getting file status =>: %m");

        return 0; /* on success */
}

static int get_dir_fd(const char *dir_path, mode_t mode) {
        /* create a new directory and return its descriptor*/
        int dir_fd = -EBADF;

        assert(dir_path);
        dir_fd = RET_NERRNO(open_mkdir_at(AT_FDCWD, dir_path, O_CLOEXEC, mode));
        if (dir_fd < 0)
                return log_error_errno(dir_fd, "Error occurred while opening directory =>: %m");

        return dir_fd;
}

static int labelling_op(int dir_fd, const char *text, const char *path, mode_t mode) {
        /* Write some content into the file */
        ssize_t count;
        _cleanup_close_ int write_fd = -EBADF;
        int r;

        assert(text);
        assert(mode != MODE_INVALID);
        r = check_path(dir_fd, path);
        if (r < 0)
                return log_error_errno(r, "Error in pathname =>: %m");

        /* Open the file within the directory for writing*/
        write_fd = RET_NERRNO(openat(dir_fd, path, O_CLOEXEC|O_WRONLY|O_TRUNC|O_CREAT, 0644));
        if (write_fd < 0)
                return log_error_errno(write_fd, "Error in opening directory for writing =>: %m");

        /* Write data to the file*/
        count = RET_NERRNO(write(write_fd, text, strlen(text)));
        if (count < 0)
                return log_error_errno(count, "Error occurred while opening file for writing =>: %m");
        return 0;
}

TEST(label_ops_set) {
        static const LabelOps test_label_ops = {
                .pre = NULL,
                .post = NULL,
        };

        label_ops_reset();
        assert_se(label_ops_set(&test_label_ops) == 0);
        /* attempt to reset label_ops when already set */
        assert_se(label_ops_set(&test_label_ops) == -EBUSY);
}

TEST(label_ops_pre) {
        _cleanup_close_ int fd;
        static const LabelOps test_label_ops = {
                .pre = pre_labelling_func,
                .post = NULL,
        };

        label_ops_reset();
        label_ops_set(&test_label_ops);
        fd = get_dir_fd("file1.txt", 0755);
        assert_se(label_ops_pre(fd, "file1.txt", 0644) == 0);
        assert_se(label_ops_pre(fd, "/restricted_directory", 0644) == -EACCES);
        assert_se(label_ops_pre(fd, "", 0700) == -EINVAL);
        assert_se(label_ops_pre(fd, "/tmp", 0700) == 0);
        assert_se(label_ops_pre(fd, "wekrgoierhgoierhqgherhgwklegnlweehgorwfkryrit", 0644) == -ENAMETOOLONG);
}

TEST(label_ops_post) {
        _cleanup_close_ int fd = -EBADF;
        const char *text1, *text2;
        static const LabelOps test_label_ops = {
                .pre = NULL,
                .post = post_labelling_func,
        };

        label_ops_reset();
        label_ops_set(&test_label_ops);

        /* Open directory */
        fd = RET_NERRNO(get_dir_fd("label_test_dir", 0755));
        text1 = "Add initial texts to file for testing label operations to file1\n";

        assert(labelling_op(fd, text1, "file1.txt", 0644) == 0);
        assert_se(label_ops_post(fd, "file1.txt") == 0);
        assert_se(strlen(text1) == (size_t)buf.st_size);
        text2 = "Add text2 data to file2\n";

        assert(labelling_op(fd, text2, "file2.txt", 0644) == 0);
        assert_se(label_ops_post(fd, "file2.txt") == 0);
        assert_se(strlen(text2) == (size_t)buf.st_size);
        assert_se(label_ops_post(fd, "file3.txt") == -ENOENT);
        assert_se(label_ops_post(fd, "/abcd") == -ENOENT);
        assert_se(label_ops_post(fd, "/restricted_directory") == -EACCES);
        assert_se(label_ops_post(fd, "") == -EINVAL);
}

DEFINE_TEST_MAIN(LOG_INFO)