xref: /third_party/eudev/src/shared/smack-util.c (revision 99ca880a)
1/***
2  This file is part of eudev, forked from systemd.
3
4  Copyright 2013 Intel Corporation
5
6  Author: Auke Kok <auke-jan.h.kok@intel.com>
7
8  systemd is free software; you can redistribute it and/or modify it
9  under the terms of the GNU Lesser General Public License as published by
10  the Free Software Foundation; either version 2.1 of the License, or
11  (at your option) any later version.
12
13  systemd is distributed in the hope that it will be useful, but
14  WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  Lesser General Public License for more details.
17
18  You should have received a copy of the GNU Lesser General Public License
19  along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
22#ifdef HAVE_XATTR
23#include <attr/xattr.h>
24#endif
25
26#include "util.h"
27#include "process-util.h"
28#include "path-util.h"
29#include "fileio.h"
30#include "smack-util.h"
31
32#define SMACK_FLOOR_LABEL "_"
33#define SMACK_STAR_LABEL  "*"
34
35bool mac_smack_use(void) {
36#ifdef HAVE_SMACK
37        static int cached_use = -1;
38
39        if (cached_use < 0)
40                cached_use = access("/sys/fs/smackfs/", F_OK) >= 0;
41
42        return cached_use;
43#else
44        return false;
45#endif
46}
47
48int mac_smack_apply(const char *path, const char *label) {
49        int r = 0;
50
51        assert(path);
52
53#ifdef HAVE_SMACK
54        if (!mac_smack_use())
55                return 0;
56
57        if (label)
58                r = lsetxattr(path, "security.SMACK64", label, strlen(label), 0);
59        else
60                r = lremovexattr(path, "security.SMACK64");
61        if (r < 0)
62                return -errno;
63#endif
64
65        return r;
66}
67
68int mac_smack_apply_fd(int fd, const char *label) {
69        int r = 0;
70
71        assert(fd >= 0);
72
73#ifdef HAVE_SMACK
74        if (!mac_smack_use())
75                return 0;
76
77        if (label)
78                r = fsetxattr(fd, "security.SMACK64", label, strlen(label), 0);
79        else
80                r = fremovexattr(fd, "security.SMACK64");
81        if (r < 0)
82                return -errno;
83#endif
84
85        return r;
86}
87
88int mac_smack_apply_ip_out_fd(int fd, const char *label) {
89        int r = 0;
90
91        assert(fd >= 0);
92
93#ifdef HAVE_SMACK
94        if (!mac_smack_use())
95                return 0;
96
97        if (label)
98                r = fsetxattr(fd, "security.SMACK64IPOUT", label, strlen(label), 0);
99        else
100                r = fremovexattr(fd, "security.SMACK64IPOUT");
101        if (r < 0)
102                return -errno;
103#endif
104
105        return r;
106}
107
108int mac_smack_apply_ip_in_fd(int fd, const char *label) {
109        int r = 0;
110
111        assert(fd >= 0);
112
113#ifdef HAVE_SMACK
114        if (!mac_smack_use())
115                return 0;
116
117        if (label)
118                r = fsetxattr(fd, "security.SMACK64IPIN", label, strlen(label), 0);
119        else
120                r = fremovexattr(fd, "security.SMACK64IPIN");
121        if (r < 0)
122                return -errno;
123#endif
124
125        return r;
126}
127
128int mac_smack_apply_pid(pid_t pid, const char *label) {
129
130#ifdef HAVE_SMACK
131        const char *p;
132#endif
133        int r = 0;
134
135        assert(label);
136
137#ifdef HAVE_SMACK
138        if (!mac_smack_use())
139                return 0;
140
141        p = procfs_file_alloca(pid, "attr/current");
142        r = write_string_file(p, label);
143        if (r < 0)
144                return r;
145#endif
146
147        return r;
148}
149
150int mac_smack_fix(const char *path, bool ignore_enoent, bool ignore_erofs) {
151
152#ifdef HAVE_SMACK
153        struct stat st;
154#endif
155        int r = 0;
156
157        assert(path);
158
159#ifdef HAVE_SMACK
160        if (!mac_smack_use())
161                return 0;
162
163        /*
164         * Path must be in /dev and must exist
165         */
166        if (!path_startswith(path, "/dev"))
167                return 0;
168
169        r = lstat(path, &st);
170        if (r >= 0) {
171                const char *label;
172
173                /*
174                 * Label directories and character devices "*".
175                 * Label symlinks "_".
176                 * Don't change anything else.
177                 */
178
179                if (S_ISDIR(st.st_mode))
180                        label = SMACK_STAR_LABEL;
181                else if (S_ISLNK(st.st_mode))
182                        label = SMACK_FLOOR_LABEL;
183                else if (S_ISCHR(st.st_mode))
184                        label = SMACK_STAR_LABEL;
185                else
186                        return 0;
187
188                r = lsetxattr(path, "security.SMACK64", label, strlen(label), 0);
189
190                /* If the FS doesn't support labels, then exit without warning */
191                if (r < 0 && errno == EOPNOTSUPP)
192                        return 0;
193        }
194
195        if (r < 0) {
196                /* Ignore ENOENT in some cases */
197                if (ignore_enoent && errno == ENOENT)
198                        return 0;
199
200                if (ignore_erofs && errno == EROFS)
201                        return 0;
202
203                r = log_debug_errno(errno, "Unable to fix SMACK label of %s: %m", path);
204        }
205#endif
206
207        return r;
208}
209