summaryrefslogtreecommitdiffstats
path: root/src/shared/label-util.c
blob: 2c482daaf6c4d786ae19b5c43dea2453c24e1328 (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
/* SPDX-License-Identifier: LGPL-2.1-or-later */

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

#include "btrfs-util.h"
#include "fs-util.h"
#include "label.h"
#include "label-util.h"
#include "macro.h"
#include "selinux-util.h"
#include "smack-util.h"

int label_fix_full(
                int atfd,
                const char *inode_path, /* path of inode to apply label to */
                const char *label_path, /* path to use as database lookup key in label database (typically same as inode_path, but not always) */
                LabelFixFlags flags) {

        int r, q;

        if (atfd < 0 && atfd != AT_FDCWD)
                return -EBADF;

        if (!inode_path && atfd < 0) /* We need at least one of atfd and an inode path */
                return -EINVAL;

        /* If both atfd and inode_path are specified, we take the specified path relative to atfd which must be an fd to a dir.
         *
         * If only atfd is specified (and inode_path is NULL), we'll operated on the inode the atfd refers to.
         *
         * If atfd is AT_FDCWD then we'll operate on the inode the path refers to.
         */

        r = mac_selinux_fix_full(atfd, inode_path, label_path, flags);
        q = mac_smack_fix_full(atfd, inode_path, label_path, flags);
        if (r < 0)
                return r;
        if (q < 0)
                return q;

        return 0;
}

int symlink_label(const char *old_path, const char *new_path) {
        int r;

        assert(old_path);
        assert(new_path);

        r = mac_selinux_create_file_prepare(new_path, S_IFLNK);
        if (r < 0)
                return r;

        r = RET_NERRNO(symlink(old_path, new_path));
        mac_selinux_create_file_clear();

        if (r < 0)
                return r;

        return mac_smack_fix(new_path, 0);
}

int symlink_atomic_full_label(const char *from, const char *to, bool make_relative) {
        int r;

        assert(from);
        assert(to);

        r = mac_selinux_create_file_prepare(to, S_IFLNK);
        if (r < 0)
                return r;

        r = symlinkat_atomic_full(from, AT_FDCWD, to, make_relative);
        mac_selinux_create_file_clear();

        if (r < 0)
                return r;

        return mac_smack_fix(to, 0);
}

int mknodat_label(int dirfd, const char *pathname, mode_t mode, dev_t dev) {
        int r;

        assert(dirfd >= 0 || dirfd == AT_FDCWD);
        assert(pathname);

        r = mac_selinux_create_file_prepare_at(dirfd, pathname, mode);
        if (r < 0)
                return r;

        r = RET_NERRNO(mknodat(dirfd, pathname, mode, dev));
        mac_selinux_create_file_clear();

        if (r < 0)
                return r;

        return mac_smack_fix_full(dirfd, pathname, NULL, 0);
}

int btrfs_subvol_make_label(const char *path) {
        int r;

        assert(path);

        r = mac_selinux_create_file_prepare(path, S_IFDIR);
        if (r < 0)
                return r;

        r = btrfs_subvol_make(AT_FDCWD, path);
        mac_selinux_create_file_clear();

        if (r < 0)
                return r;

        return mac_smack_fix(path, 0);
}

static int init_internal(bool lazy) {
        int r;

        assert(!(mac_selinux_use() && mac_smack_use()));

        if (lazy)
                r = mac_selinux_init_lazy();
        else
                r = mac_selinux_init();
        if (r < 0)
                return r;

        return mac_smack_init();
}

int mac_init_lazy(void) {
        return init_internal(/* lazy=*/ true);
}

int mac_init(void) {
        return init_internal(/* lazy=*/ false);
}