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