Coverage Report

Created: 2019-06-19 13:33

/src/systemd/src/shared/base-filesystem.c
Line
Count
Source (jump to first uncovered line)
1
/* SPDX-License-Identifier: LGPL-2.1+ */
2
3
#include <errno.h>
4
#include <fcntl.h>
5
#include <stdbool.h>
6
#include <stdlib.h>
7
#include <sys/stat.h>
8
#include <syslog.h>
9
#include <unistd.h>
10
11
#include "alloc-util.h"
12
#include "base-filesystem.h"
13
#include "fd-util.h"
14
#include "log.h"
15
#include "macro.h"
16
#include "nulstr-util.h"
17
#include "path-util.h"
18
#include "string-util.h"
19
#include "umask-util.h"
20
#include "user-util.h"
21
22
typedef struct BaseFilesystem {
23
        const char *dir;
24
        mode_t mode;
25
        const char *target;
26
        const char *exists;
27
        bool ignore_failure;
28
} BaseFilesystem;
29
30
static const BaseFilesystem table[] = {
31
        { "bin",      0, "usr/bin\0",                  NULL },
32
        { "lib",      0, "usr/lib\0",                  NULL },
33
        { "root",  0755, NULL,                         NULL, true },
34
        { "sbin",     0, "usr/sbin\0",                 NULL },
35
        { "usr",   0755, NULL,                         NULL },
36
        { "var",   0755, NULL,                         NULL },
37
        { "etc",   0755, NULL,                         NULL },
38
        { "proc",  0755, NULL,                         NULL, true },
39
        { "sys",   0755, NULL,                         NULL, true },
40
        { "dev",   0755, NULL,                         NULL, true },
41
#if defined(__i386__) || defined(__x86_64__)
42
        { "lib64",    0, "usr/lib/x86_64-linux-gnu\0"
43
                         "usr/lib64\0",                "ld-linux-x86-64.so.2" },
44
#endif
45
};
46
47
0
int base_filesystem_create(const char *root, uid_t uid, gid_t gid) {
48
0
        _cleanup_close_ int fd = -1;
49
0
        size_t i;
50
0
        int r;
51
0
52
0
        fd = open(root, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW);
53
0
        if (fd < 0)
54
0
                return log_error_errno(errno, "Failed to open root file system: %m");
55
0
56
0
        for (i = 0; i < ELEMENTSOF(table); i ++) {
57
0
                if (faccessat(fd, table[i].dir, F_OK, AT_SYMLINK_NOFOLLOW) >= 0)
58
0
                        continue;
59
0
60
0
                if (table[i].target) {
61
0
                        const char *target = NULL, *s;
62
0
63
0
                        /* check if one of the targets exists */
64
0
                        NULSTR_FOREACH(s, table[i].target) {
65
0
                                if (faccessat(fd, s, F_OK, AT_SYMLINK_NOFOLLOW) < 0)
66
0
                                        continue;
67
0
68
0
                                /* check if a specific file exists at the target path */
69
0
                                if (table[i].exists) {
70
0
                                        _cleanup_free_ char *p = NULL;
71
0
72
0
                                        p = path_join(s, table[i].exists);
73
0
                                        if (!p)
74
0
                                                return log_oom();
75
0
76
0
                                        if (faccessat(fd, p, F_OK, AT_SYMLINK_NOFOLLOW) < 0)
77
0
                                                continue;
78
0
                                }
79
0
80
0
                                target = s;
81
0
                                break;
82
0
                        }
83
0
84
0
                        if (!target)
85
0
                                continue;
86
0
87
0
                        if (symlinkat(target, fd, table[i].dir) < 0) {
88
0
                                log_full_errno(IN_SET(errno, EEXIST, EROFS) || table[i].ignore_failure ? LOG_DEBUG : LOG_ERR, errno,
89
0
                                               "Failed to create symlink at %s/%s: %m", root, table[i].dir);
90
0
91
0
                                if (IN_SET(errno, EEXIST, EROFS) || table[i].ignore_failure)
92
0
                                        continue;
93
0
94
0
                                return -errno;
95
0
                        }
96
0
97
0
                        if (uid_is_valid(uid) || gid_is_valid(gid)) {
98
0
                                if (fchownat(fd, table[i].dir, uid, gid, AT_SYMLINK_NOFOLLOW) < 0)
99
0
                                        return log_error_errno(errno, "Failed to chown symlink at %s/%s: %m", root, table[i].dir);
100
0
                        }
101
0
102
0
                        continue;
103
0
                }
104
0
105
0
                RUN_WITH_UMASK(0000)
106
0
                        r = mkdirat(fd, table[i].dir, table[i].mode);
107
0
                if (r < 0) {
108
0
                        log_full_errno(IN_SET(errno, EEXIST, EROFS) || table[i].ignore_failure ? LOG_DEBUG : LOG_ERR, errno,
109
0
                                       "Failed to create directory at %s/%s: %m", root, table[i].dir);
110
0
111
0
                        if (IN_SET(errno, EEXIST, EROFS) || table[i].ignore_failure)
112
0
                                continue;
113
0
114
0
                        return -errno;
115
0
                }
116
0
117
0
                if (uid != UID_INVALID || gid != UID_INVALID) {
118
0
                        if (fchownat(fd, table[i].dir, uid, gid, AT_SYMLINK_NOFOLLOW) < 0)
119
0
                                return log_error_errno(errno, "Failed to chown directory at %s/%s: %m", root, table[i].dir);
120
0
                }
121
0
        }
122
0
123
0
        return 0;
124
0
}