chiark / gitweb /
condition: properly allow passing back errors from condition checks
[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 #define SMACK_FLOOR_LABEL "_"
31 #define SMACK_STAR_LABEL  "*"
32
33 bool mac_smack_use(void) {
34 #ifdef HAVE_SMACK
35         static int cached_use = -1;
36
37         if (cached_use < 0)
38                 cached_use = access("/sys/fs/smackfs/", F_OK) >= 0;
39
40         return cached_use;
41 #else
42         return false;
43 #endif
44 }
45
46 int mac_smack_apply(const char *path, const char *label) {
47         int r = 0;
48
49         assert(path);
50
51 #ifdef HAVE_SMACK
52         if (!mac_smack_use())
53                 return 0;
54
55         if (label)
56                 r = lsetxattr(path, "security.SMACK64", label, strlen(label), 0);
57         else
58                 r = lremovexattr(path, "security.SMACK64");
59         if (r < 0)
60                 return -errno;
61 #endif
62
63         return r;
64 }
65
66 int mac_smack_apply_fd(int fd, const char *label) {
67         int r = 0;
68
69         assert(fd >= 0);
70
71 #ifdef HAVE_SMACK
72         if (!mac_smack_use())
73                 return 0;
74
75         if (label)
76                 r = fsetxattr(fd, "security.SMACK64", label, strlen(label), 0);
77         else
78                 r = fremovexattr(fd, "security.SMACK64");
79         if (r < 0)
80                 return -errno;
81 #endif
82
83         return r;
84 }
85
86 int mac_smack_apply_ip_out_fd(int fd, const char *label) {
87         int r = 0;
88
89         assert(fd >= 0);
90
91 #ifdef HAVE_SMACK
92         if (!mac_smack_use())
93                 return 0;
94
95         if (label)
96                 r = fsetxattr(fd, "security.SMACK64IPOUT", label, strlen(label), 0);
97         else
98                 r = fremovexattr(fd, "security.SMACK64IPOUT");
99         if (r < 0)
100                 return -errno;
101 #endif
102
103         return r;
104 }
105
106 int mac_smack_apply_ip_in_fd(int fd, const char *label) {
107         int r = 0;
108
109         assert(fd >= 0);
110
111 #ifdef HAVE_SMACK
112         if (!mac_smack_use())
113                 return 0;
114
115         if (label)
116                 r = fsetxattr(fd, "security.SMACK64IPIN", label, strlen(label), 0);
117         else
118                 r = fremovexattr(fd, "security.SMACK64IPIN");
119         if (r < 0)
120                 return -errno;
121 #endif
122
123         return r;
124 }
125
126 int mac_smack_fix(const char *path, bool ignore_enoent, bool ignore_erofs) {
127         int r = 0;
128
129 #ifdef HAVE_SMACK
130         struct stat st;
131
132         assert(path);
133
134         if (!mac_smack_use())
135                 return 0;
136
137         /*
138          * Path must be in /dev and must exist
139          */
140         if (!path_startswith(path, "/dev"))
141                 return 0;
142
143         r = lstat(path, &st);
144         if (r >= 0) {
145                 const char *label;
146
147                 /*
148                  * Label directories and character devices "*".
149                  * Label symlinks "_".
150                  * Don't change anything else.
151                  */
152
153                 if (S_ISDIR(st.st_mode))
154                         label = SMACK_STAR_LABEL;
155                 else if (S_ISLNK(st.st_mode))
156                         label = SMACK_FLOOR_LABEL;
157                 else if (S_ISCHR(st.st_mode))
158                         label = SMACK_STAR_LABEL;
159                 else
160                         return 0;
161
162                 r = lsetxattr(path, "security.SMACK64", label, strlen(label), 0);
163
164                 /* If the FS doesn't support labels, then exit without warning */
165                 if (r < 0 && errno == ENOTSUP)
166                         return 0;
167         }
168
169         if (r < 0) {
170                 /* Ignore ENOENT in some cases */
171                 if (ignore_enoent && errno == ENOENT)
172                         return 0;
173
174                 if (ignore_erofs && errno == EROFS)
175                         return 0;
176
177                 log_debug("Unable to fix SMACK label of %s: %m", path);
178                 r = -errno;
179         }
180 #endif
181
182         return r;
183 }