File: | build-scan/../src/basic/selinux-util.c |
Warning: | line 325, column 11 Potential leak of memory pointed to by 'mycon' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* SPDX-License-Identifier: LGPL-2.1+ */ | |||
2 | ||||
3 | #include <errno(*__errno_location ()).h> | |||
4 | #include <malloc.h> | |||
5 | #include <stddef.h> | |||
6 | #include <string.h> | |||
7 | #include <sys/stat.h> | |||
8 | #include <sys/time.h> | |||
9 | #include <sys/un.h> | |||
10 | #include <syslog.h> | |||
11 | ||||
12 | #if HAVE_SELINUX1 | |||
13 | #include <selinux/avc.h> | |||
14 | #include <selinux/context.h> | |||
15 | #include <selinux/label.h> | |||
16 | #include <selinux/selinux.h> | |||
17 | #endif | |||
18 | ||||
19 | #include "alloc-util.h" | |||
20 | #include "fd-util.h" | |||
21 | #include "log.h" | |||
22 | #include "macro.h" | |||
23 | #include "path-util.h" | |||
24 | #include "selinux-util.h" | |||
25 | #include "stdio-util.h" | |||
26 | #include "time-util.h" | |||
27 | #include "util.h" | |||
28 | ||||
29 | #if HAVE_SELINUX1 | |||
30 | DEFINE_TRIVIAL_CLEANUP_FUNC(char*, freecon)static inline void freeconp(char* *p) { if (*p) freecon(*p); }; | |||
31 | DEFINE_TRIVIAL_CLEANUP_FUNC(context_t, context_free)static inline void context_freep(context_t *p) { if (*p) context_free (*p); }; | |||
32 | ||||
33 | #define _cleanup_freecon___attribute__((cleanup(freeconp))) _cleanup_(freeconp)__attribute__((cleanup(freeconp))) | |||
34 | #define _cleanup_context_free___attribute__((cleanup(context_freep))) _cleanup_(context_freep)__attribute__((cleanup(context_freep))) | |||
35 | ||||
36 | static int mac_selinux_reload(int seqno); | |||
37 | ||||
38 | static int cached_use = -1; | |||
39 | static struct selabel_handle *label_hnd = NULL((void*)0); | |||
40 | ||||
41 | #define log_enforcing(...)({ int _level = (((security_getenforce() == 1 ? 3 : 7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm (_realm) >= ((_level) & 0x07)) ? log_internal_realm((( _realm) << 10 | (_level)), _e, "../src/basic/selinux-util.c" , 41, __func__, ...) : -abs(_e); }) log_full(security_getenforce() == 1 ? LOG_ERR : LOG_DEBUG, __VA_ARGS__)({ int _level = (((security_getenforce() == 1 ? 3 : 7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm (_realm) >= ((_level) & 0x07)) ? log_internal_realm((( _realm) << 10 | (_level)), _e, "../src/basic/selinux-util.c" , 41, __func__, __VA_ARGS__) : -abs(_e); }) | |||
42 | #define log_enforcing_errno(r, ...)({ int _level = ((security_getenforce() == 1 ? 3 : 7)), _e = ( (r)), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm( _realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm ) << 10 | (_level)), _e, "../src/basic/selinux-util.c", 42, __func__, ...) : -abs(_e); }) log_full_errno(security_getenforce() == 1 ? LOG_ERR : LOG_DEBUG, r, __VA_ARGS__)({ int _level = ((security_getenforce() == 1 ? 3 : 7)), _e = ( (r)), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm( _realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm ) << 10 | (_level)), _e, "../src/basic/selinux-util.c", 42, __func__, __VA_ARGS__) : -abs(_e); }) | |||
43 | #endif | |||
44 | ||||
45 | bool_Bool mac_selinux_use(void) { | |||
46 | #if HAVE_SELINUX1 | |||
47 | if (cached_use < 0) | |||
48 | cached_use = is_selinux_enabled() > 0; | |||
49 | ||||
50 | return cached_use; | |||
51 | #else | |||
52 | return false0; | |||
53 | #endif | |||
54 | } | |||
55 | ||||
56 | void mac_selinux_retest(void) { | |||
57 | #if HAVE_SELINUX1 | |||
58 | cached_use = -1; | |||
59 | #endif | |||
60 | } | |||
61 | ||||
62 | int mac_selinux_init(void) { | |||
63 | int r = 0; | |||
64 | ||||
65 | #if HAVE_SELINUX1 | |||
66 | usec_t before_timestamp, after_timestamp; | |||
67 | struct mallinfo before_mallinfo, after_mallinfo; | |||
68 | ||||
69 | selinux_set_callback(SELINUX_CB_POLICYLOAD4, (union selinux_callback) mac_selinux_reload); | |||
70 | ||||
71 | if (label_hnd) | |||
72 | return 0; | |||
73 | ||||
74 | if (!mac_selinux_use()) | |||
75 | return 0; | |||
76 | ||||
77 | before_mallinfo = mallinfo(); | |||
78 | before_timestamp = now(CLOCK_MONOTONIC1); | |||
79 | ||||
80 | label_hnd = selabel_open(SELABEL_CTX_FILE0, NULL((void*)0), 0); | |||
81 | if (!label_hnd) { | |||
82 | log_enforcing_errno(errno, "Failed to initialize SELinux context: %m")({ int _level = ((security_getenforce() == 1 ? 3 : 7)), _e = ( ((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm (_realm) >= ((_level) & 0x07)) ? log_internal_realm((( _realm) << 10 | (_level)), _e, "../src/basic/selinux-util.c" , 82, __func__, "Failed to initialize SELinux context: %m") : -abs(_e); }); | |||
83 | r = security_getenforce() == 1 ? -errno(*__errno_location ()) : 0; | |||
84 | } else { | |||
85 | char timespan[FORMAT_TIMESPAN_MAX64]; | |||
86 | int l; | |||
87 | ||||
88 | after_timestamp = now(CLOCK_MONOTONIC1); | |||
89 | after_mallinfo = mallinfo(); | |||
90 | ||||
91 | l = after_mallinfo.uordblks > before_mallinfo.uordblks ? after_mallinfo.uordblks - before_mallinfo.uordblks : 0; | |||
92 | ||||
93 | log_debug("Successfully loaded SELinux database in %s, size on heap is %iK.",({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/basic/selinux-util.c", 95, __func__, "Successfully loaded SELinux database in %s, size on heap is %iK." , format_timespan(timespan, sizeof(timespan), after_timestamp - before_timestamp, 0), (l+1023)/1024) : -abs(_e); }) | |||
94 | format_timespan(timespan, sizeof(timespan), after_timestamp - before_timestamp, 0),({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/basic/selinux-util.c", 95, __func__, "Successfully loaded SELinux database in %s, size on heap is %iK." , format_timespan(timespan, sizeof(timespan), after_timestamp - before_timestamp, 0), (l+1023)/1024) : -abs(_e); }) | |||
95 | (l+1023)/1024)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/basic/selinux-util.c", 95, __func__, "Successfully loaded SELinux database in %s, size on heap is %iK." , format_timespan(timespan, sizeof(timespan), after_timestamp - before_timestamp, 0), (l+1023)/1024) : -abs(_e); }); | |||
96 | } | |||
97 | #endif | |||
98 | ||||
99 | return r; | |||
100 | } | |||
101 | ||||
102 | void mac_selinux_finish(void) { | |||
103 | ||||
104 | #if HAVE_SELINUX1 | |||
105 | if (!label_hnd) | |||
106 | return; | |||
107 | ||||
108 | selabel_close(label_hnd); | |||
109 | label_hnd = NULL((void*)0); | |||
110 | #endif | |||
111 | } | |||
112 | ||||
113 | #if HAVE_SELINUX1 | |||
114 | static int mac_selinux_reload(int seqno) { | |||
115 | struct selabel_handle *backup_label_hnd; | |||
116 | ||||
117 | if (!label_hnd) | |||
118 | return 0; | |||
119 | ||||
120 | backup_label_hnd = TAKE_PTR(label_hnd)({ typeof(label_hnd) _ptr_ = (label_hnd); (label_hnd) = ((void *)0); _ptr_; }); | |||
121 | ||||
122 | /* try to initialize new handle | |||
123 | * on success close backup | |||
124 | * on failure restore backup */ | |||
125 | if (mac_selinux_init() == 0) | |||
126 | selabel_close(backup_label_hnd); | |||
127 | else | |||
128 | label_hnd = backup_label_hnd; | |||
129 | ||||
130 | return 0; | |||
131 | } | |||
132 | #endif | |||
133 | ||||
134 | int mac_selinux_fix(const char *path, LabelFixFlags flags) { | |||
135 | ||||
136 | #if HAVE_SELINUX1 | |||
137 | char procfs_path[STRLEN("/proc/self/fd/")(sizeof("""/proc/self/fd/""") - 1) + DECIMAL_STR_MAX(int)(2+(sizeof(int) <= 1 ? 3 : sizeof(int) <= 2 ? 5 : sizeof (int) <= 4 ? 10 : sizeof(int) <= 8 ? 20 : sizeof(int[-2 *(sizeof(int) > 8)])))]; | |||
138 | _cleanup_freecon___attribute__((cleanup(freeconp))) char* fcon = NULL((void*)0); | |||
139 | _cleanup_close___attribute__((cleanup(closep))) int fd = -1; | |||
140 | struct stat st; | |||
141 | int r; | |||
142 | ||||
143 | assert(path)do { if ((__builtin_expect(!!(!(path)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("path"), "../src/basic/selinux-util.c", 143 , __PRETTY_FUNCTION__); } while (0); | |||
144 | ||||
145 | /* if mac_selinux_init() wasn't called before we are a NOOP */ | |||
146 | if (!label_hnd) | |||
147 | return 0; | |||
148 | ||||
149 | /* Open the file as O_PATH, to pin it while we determine and adjust the label */ | |||
150 | fd = open(path, O_NOFOLLOW0400000|O_CLOEXEC02000000|O_PATH010000000); | |||
151 | if (fd < 0) { | |||
152 | if ((flags & LABEL_IGNORE_ENOENT) && errno(*__errno_location ()) == ENOENT2) | |||
153 | return 0; | |||
154 | ||||
155 | return -errno(*__errno_location ()); | |||
156 | } | |||
157 | ||||
158 | if (fstat(fd, &st) < 0) | |||
159 | return -errno(*__errno_location ()); | |||
160 | ||||
161 | /* Check for policy reload so 'label_hnd' is kept up-to-date by callbacks */ | |||
162 | (void) avc_netlink_check_nb(); | |||
163 | ||||
164 | if (selabel_lookup_raw(label_hnd, &fcon, path, st.st_mode) < 0) { | |||
165 | r = -errno(*__errno_location ()); | |||
166 | ||||
167 | /* If there's no label to set, then exit without warning */ | |||
168 | if (r == -ENOENT2) | |||
169 | return 0; | |||
170 | ||||
171 | goto fail; | |||
172 | } | |||
173 | ||||
174 | xsprintf(procfs_path, "/proc/self/fd/%i", fd)do { if ((__builtin_expect(!!(!(((size_t) snprintf(procfs_path , __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p (typeof(procfs_path), typeof(&*(procfs_path))), sizeof(procfs_path )/sizeof((procfs_path)[0]), ((void)0))), "/proc/self/fd/%i", fd ) < (__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p (typeof(procfs_path), typeof(&*(procfs_path))), sizeof(procfs_path )/sizeof((procfs_path)[0]), ((void)0))))))),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("xsprintf: " "procfs_path" "[] must be big enough" ), "../src/basic/selinux-util.c", 174, __PRETTY_FUNCTION__); } while (0); | |||
175 | if (setfilecon_raw(procfs_path, fcon) < 0) { | |||
176 | _cleanup_freecon___attribute__((cleanup(freeconp))) char *oldcon = NULL((void*)0); | |||
177 | ||||
178 | r = -errno(*__errno_location ()); | |||
179 | ||||
180 | /* If the FS doesn't support labels, then exit without warning */ | |||
181 | if (r == -EOPNOTSUPP95) | |||
182 | return 0; | |||
183 | ||||
184 | /* It the FS is read-only and we were told to ignore failures caused by that, suppress error */ | |||
185 | if (r == -EROFS30 && (flags & LABEL_IGNORE_EROFS)) | |||
186 | return 0; | |||
187 | ||||
188 | /* If the old label is identical to the new one, suppress any kind of error */ | |||
189 | if (getfilecon_raw(procfs_path, &oldcon) >= 0 && streq(fcon, oldcon)(strcmp((fcon),(oldcon)) == 0)) | |||
190 | return 0; | |||
191 | ||||
192 | goto fail; | |||
193 | } | |||
194 | ||||
195 | return 0; | |||
196 | ||||
197 | fail: | |||
198 | log_enforcing_errno(r, "Unable to fix SELinux security context of %s: %m", path)({ int _level = ((security_getenforce() == 1 ? 3 : 7)), _e = ( (r)), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm( _realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm ) << 10 | (_level)), _e, "../src/basic/selinux-util.c", 198, __func__, "Unable to fix SELinux security context of %s: %m" , path) : -abs(_e); }); | |||
199 | if (security_getenforce() == 1) | |||
200 | return r; | |||
201 | #endif | |||
202 | ||||
203 | return 0; | |||
204 | } | |||
205 | ||||
206 | int mac_selinux_apply(const char *path, const char *label) { | |||
207 | ||||
208 | #if HAVE_SELINUX1 | |||
209 | if (!mac_selinux_use()) | |||
210 | return 0; | |||
211 | ||||
212 | assert(path)do { if ((__builtin_expect(!!(!(path)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("path"), "../src/basic/selinux-util.c", 212 , __PRETTY_FUNCTION__); } while (0); | |||
213 | assert(label)do { if ((__builtin_expect(!!(!(label)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("label"), "../src/basic/selinux-util.c", 213, __PRETTY_FUNCTION__); } while (0); | |||
214 | ||||
215 | if (setfilecon(path, label) < 0) { | |||
216 | log_enforcing_errno(errno, "Failed to set SELinux security context %s on path %s: %m", label, path)({ int _level = ((security_getenforce() == 1 ? 3 : 7)), _e = ( ((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm (_realm) >= ((_level) & 0x07)) ? log_internal_realm((( _realm) << 10 | (_level)), _e, "../src/basic/selinux-util.c" , 216, __func__, "Failed to set SELinux security context %s on path %s: %m" , label, path) : -abs(_e); }); | |||
217 | if (security_getenforce() > 0) | |||
218 | return -errno(*__errno_location ()); | |||
219 | } | |||
220 | #endif | |||
221 | return 0; | |||
222 | } | |||
223 | ||||
224 | int mac_selinux_get_create_label_from_exe(const char *exe, char **label) { | |||
225 | int r = -EOPNOTSUPP95; | |||
226 | ||||
227 | #if HAVE_SELINUX1 | |||
228 | _cleanup_freecon___attribute__((cleanup(freeconp))) char *mycon = NULL((void*)0), *fcon = NULL((void*)0); | |||
229 | security_class_t sclass; | |||
230 | ||||
231 | assert(exe)do { if ((__builtin_expect(!!(!(exe)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("exe"), "../src/basic/selinux-util.c", 231 , __PRETTY_FUNCTION__); } while (0); | |||
232 | assert(label)do { if ((__builtin_expect(!!(!(label)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("label"), "../src/basic/selinux-util.c", 232, __PRETTY_FUNCTION__); } while (0); | |||
233 | ||||
234 | if (!mac_selinux_use()) | |||
235 | return -EOPNOTSUPP95; | |||
236 | ||||
237 | r = getcon_raw(&mycon); | |||
238 | if (r < 0) | |||
239 | return -errno(*__errno_location ()); | |||
240 | ||||
241 | r = getfilecon_raw(exe, &fcon); | |||
242 | if (r < 0) | |||
243 | return -errno(*__errno_location ()); | |||
244 | ||||
245 | sclass = string_to_security_class("process"); | |||
246 | r = security_compute_create_raw(mycon, fcon, sclass, label); | |||
247 | if (r < 0) | |||
248 | return -errno(*__errno_location ()); | |||
249 | #endif | |||
250 | ||||
251 | return r; | |||
252 | } | |||
253 | ||||
254 | int mac_selinux_get_our_label(char **label) { | |||
255 | int r = -EOPNOTSUPP95; | |||
256 | ||||
257 | assert(label)do { if ((__builtin_expect(!!(!(label)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("label"), "../src/basic/selinux-util.c", 257, __PRETTY_FUNCTION__); } while (0); | |||
258 | ||||
259 | #if HAVE_SELINUX1 | |||
260 | if (!mac_selinux_use()) | |||
261 | return -EOPNOTSUPP95; | |||
262 | ||||
263 | r = getcon_raw(label); | |||
264 | if (r < 0) | |||
265 | return -errno(*__errno_location ()); | |||
266 | #endif | |||
267 | ||||
268 | return r; | |||
269 | } | |||
270 | ||||
271 | int mac_selinux_get_child_mls_label(int socket_fd, const char *exe, const char *exec_label, char **label) { | |||
272 | int r = -EOPNOTSUPP95; | |||
273 | ||||
274 | #if HAVE_SELINUX1 | |||
275 | _cleanup_freecon___attribute__((cleanup(freeconp))) char *mycon = NULL((void*)0), *peercon = NULL((void*)0), *fcon = NULL((void*)0); | |||
276 | _cleanup_context_free___attribute__((cleanup(context_freep))) context_t pcon = NULL((void*)0), bcon = NULL((void*)0); | |||
277 | security_class_t sclass; | |||
278 | const char *range = NULL((void*)0); | |||
279 | ||||
280 | assert(socket_fd >= 0)do { if ((__builtin_expect(!!(!(socket_fd >= 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("socket_fd >= 0"), "../src/basic/selinux-util.c" , 280, __PRETTY_FUNCTION__); } while (0); | |||
| ||||
281 | assert(exe)do { if ((__builtin_expect(!!(!(exe)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("exe"), "../src/basic/selinux-util.c", 281 , __PRETTY_FUNCTION__); } while (0); | |||
282 | assert(label)do { if ((__builtin_expect(!!(!(label)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("label"), "../src/basic/selinux-util.c", 282, __PRETTY_FUNCTION__); } while (0); | |||
283 | ||||
284 | if (!mac_selinux_use()) | |||
285 | return -EOPNOTSUPP95; | |||
286 | ||||
287 | r = getcon_raw(&mycon); | |||
288 | if (r < 0) | |||
289 | return -errno(*__errno_location ()); | |||
290 | ||||
291 | r = getpeercon_raw(socket_fd, &peercon); | |||
292 | if (r < 0) | |||
293 | return -errno(*__errno_location ()); | |||
294 | ||||
295 | if (!exec_label) { | |||
296 | /* If there is no context set for next exec let's use context | |||
297 | of target executable */ | |||
298 | r = getfilecon_raw(exe, &fcon); | |||
299 | if (r < 0) | |||
300 | return -errno(*__errno_location ()); | |||
301 | } | |||
302 | ||||
303 | bcon = context_new(mycon); | |||
304 | if (!bcon) | |||
305 | return -ENOMEM12; | |||
306 | ||||
307 | pcon = context_new(peercon); | |||
308 | if (!pcon) | |||
309 | return -ENOMEM12; | |||
310 | ||||
311 | range = context_range_get(pcon); | |||
312 | if (!range) | |||
313 | return -errno(*__errno_location ()); | |||
314 | ||||
315 | r = context_range_set(bcon, range); | |||
316 | if (r) | |||
317 | return -errno(*__errno_location ()); | |||
318 | ||||
319 | freecon(mycon); | |||
320 | mycon = strdup(context_str(bcon)); | |||
321 | if (!mycon) | |||
322 | return -ENOMEM12; | |||
323 | ||||
324 | sclass = string_to_security_class("process"); | |||
325 | r = security_compute_create_raw(mycon, fcon, sclass, label); | |||
| ||||
326 | if (r < 0) | |||
327 | return -errno(*__errno_location ()); | |||
328 | #endif | |||
329 | ||||
330 | return r; | |||
331 | } | |||
332 | ||||
333 | char* mac_selinux_free(char *label) { | |||
334 | ||||
335 | #if HAVE_SELINUX1 | |||
336 | if (!label) | |||
337 | return NULL((void*)0); | |||
338 | ||||
339 | if (!mac_selinux_use()) | |||
340 | return NULL((void*)0); | |||
341 | ||||
342 | freecon(label); | |||
343 | #endif | |||
344 | ||||
345 | return NULL((void*)0); | |||
346 | } | |||
347 | ||||
348 | #if HAVE_SELINUX1 | |||
349 | static int selinux_create_file_prepare_abspath(const char *abspath, mode_t mode) { | |||
350 | _cleanup_freecon___attribute__((cleanup(freeconp))) char *filecon = NULL((void*)0); | |||
351 | _cleanup_free___attribute__((cleanup(freep))) char *path = NULL((void*)0); | |||
352 | int r; | |||
353 | ||||
354 | assert(abspath)do { if ((__builtin_expect(!!(!(abspath)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("abspath"), "../src/basic/selinux-util.c" , 354, __PRETTY_FUNCTION__); } while (0); | |||
355 | assert(path_is_absolute(abspath))do { if ((__builtin_expect(!!(!(path_is_absolute(abspath))),0 ))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("path_is_absolute(abspath)" ), "../src/basic/selinux-util.c", 355, __PRETTY_FUNCTION__); } while (0); | |||
356 | ||||
357 | /* Check for policy reload so 'label_hnd' is kept up-to-date by callbacks */ | |||
358 | (void) avc_netlink_check_nb(); | |||
359 | ||||
360 | r = selabel_lookup_raw(label_hnd, &filecon, abspath, mode); | |||
361 | if (r < 0) { | |||
362 | /* No context specified by the policy? Proceed without setting it. */ | |||
363 | if (errno(*__errno_location ()) == ENOENT2) | |||
364 | return 0; | |||
365 | ||||
366 | log_enforcing_errno(errno, "Failed to determine SELinux security context for %s: %m", abspath)({ int _level = ((security_getenforce() == 1 ? 3 : 7)), _e = ( ((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm (_realm) >= ((_level) & 0x07)) ? log_internal_realm((( _realm) << 10 | (_level)), _e, "../src/basic/selinux-util.c" , 366, __func__, "Failed to determine SELinux security context for %s: %m" , abspath) : -abs(_e); }); | |||
367 | } else { | |||
368 | if (setfscreatecon_raw(filecon) >= 0) | |||
369 | return 0; /* Success! */ | |||
370 | ||||
371 | log_enforcing_errno(errno, "Failed to set SELinux security context %s for %s: %m", filecon, abspath)({ int _level = ((security_getenforce() == 1 ? 3 : 7)), _e = ( ((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm (_realm) >= ((_level) & 0x07)) ? log_internal_realm((( _realm) << 10 | (_level)), _e, "../src/basic/selinux-util.c" , 371, __func__, "Failed to set SELinux security context %s for %s: %m" , filecon, abspath) : -abs(_e); }); | |||
372 | } | |||
373 | ||||
374 | if (security_getenforce() > 0) | |||
375 | return -errno(*__errno_location ()); | |||
376 | ||||
377 | return 0; | |||
378 | } | |||
379 | #endif | |||
380 | ||||
381 | int mac_selinux_create_file_prepare_at(int dirfd, const char *path, mode_t mode) { | |||
382 | int r = 0; | |||
383 | ||||
384 | #if HAVE_SELINUX1 | |||
385 | _cleanup_free___attribute__((cleanup(freep))) char *abspath = NULL((void*)0); | |||
386 | _cleanup_close___attribute__((cleanup(closep))) int fd = -1; | |||
387 | ||||
388 | assert(path)do { if ((__builtin_expect(!!(!(path)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("path"), "../src/basic/selinux-util.c", 388 , __PRETTY_FUNCTION__); } while (0); | |||
389 | ||||
390 | if (!label_hnd) | |||
391 | return 0; | |||
392 | ||||
393 | if (!path_is_absolute(path)) { | |||
394 | _cleanup_free___attribute__((cleanup(freep))) char *p = NULL((void*)0); | |||
395 | ||||
396 | if (dirfd == AT_FDCWD-100) | |||
397 | r = safe_getcwd(&p); | |||
398 | else | |||
399 | r = fd_get_path(dirfd, &p); | |||
400 | if (r < 0) | |||
401 | return r; | |||
402 | ||||
403 | abspath = path_join(NULL((void*)0), p, path); | |||
404 | if (!abspath) | |||
405 | return -ENOMEM12; | |||
406 | ||||
407 | path = abspath; | |||
408 | } | |||
409 | ||||
410 | r = selinux_create_file_prepare_abspath(path, mode); | |||
411 | #endif | |||
412 | return r; | |||
413 | } | |||
414 | ||||
415 | int mac_selinux_create_file_prepare(const char *path, mode_t mode) { | |||
416 | int r = 0; | |||
417 | ||||
418 | #if HAVE_SELINUX1 | |||
419 | _cleanup_free___attribute__((cleanup(freep))) char *abspath = NULL((void*)0); | |||
420 | ||||
421 | assert(path)do { if ((__builtin_expect(!!(!(path)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("path"), "../src/basic/selinux-util.c", 421 , __PRETTY_FUNCTION__); } while (0); | |||
422 | ||||
423 | if (!label_hnd) | |||
424 | return 0; | |||
425 | ||||
426 | r = path_make_absolute_cwd(path, &abspath); | |||
427 | if (r < 0) | |||
428 | return r; | |||
429 | ||||
430 | r = selinux_create_file_prepare_abspath(abspath, mode); | |||
431 | #endif | |||
432 | return r; | |||
433 | } | |||
434 | ||||
435 | void mac_selinux_create_file_clear(void) { | |||
436 | ||||
437 | #if HAVE_SELINUX1 | |||
438 | PROTECT_ERRNO__attribute__((cleanup(_reset_errno_))) __attribute__((unused )) int _saved_errno_ = (*__errno_location ()); | |||
439 | ||||
440 | if (!mac_selinux_use()) | |||
441 | return; | |||
442 | ||||
443 | setfscreatecon_raw(NULL((void*)0)); | |||
444 | #endif | |||
445 | } | |||
446 | ||||
447 | int mac_selinux_create_socket_prepare(const char *label) { | |||
448 | ||||
449 | #if HAVE_SELINUX1 | |||
450 | if (!mac_selinux_use()) | |||
451 | return 0; | |||
452 | ||||
453 | assert(label)do { if ((__builtin_expect(!!(!(label)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("label"), "../src/basic/selinux-util.c", 453, __PRETTY_FUNCTION__); } while (0); | |||
454 | ||||
455 | if (setsockcreatecon(label) < 0) { | |||
456 | log_enforcing_errno(errno, "Failed to set SELinux security context %s for sockets: %m", label)({ int _level = ((security_getenforce() == 1 ? 3 : 7)), _e = ( ((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm (_realm) >= ((_level) & 0x07)) ? log_internal_realm((( _realm) << 10 | (_level)), _e, "../src/basic/selinux-util.c" , 456, __func__, "Failed to set SELinux security context %s for sockets: %m" , label) : -abs(_e); }); | |||
457 | ||||
458 | if (security_getenforce() == 1) | |||
459 | return -errno(*__errno_location ()); | |||
460 | } | |||
461 | #endif | |||
462 | ||||
463 | return 0; | |||
464 | } | |||
465 | ||||
466 | void mac_selinux_create_socket_clear(void) { | |||
467 | ||||
468 | #if HAVE_SELINUX1 | |||
469 | PROTECT_ERRNO__attribute__((cleanup(_reset_errno_))) __attribute__((unused )) int _saved_errno_ = (*__errno_location ()); | |||
470 | ||||
471 | if (!mac_selinux_use()) | |||
472 | return; | |||
473 | ||||
474 | setsockcreatecon_raw(NULL((void*)0)); | |||
475 | #endif | |||
476 | } | |||
477 | ||||
478 | int mac_selinux_bind(int fd, const struct sockaddr *addr, socklen_t addrlen) { | |||
479 | ||||
480 | /* Binds a socket and label its file system object according to the SELinux policy */ | |||
481 | ||||
482 | #if HAVE_SELINUX1 | |||
483 | _cleanup_freecon___attribute__((cleanup(freeconp))) char *fcon = NULL((void*)0); | |||
484 | const struct sockaddr_un *un; | |||
485 | bool_Bool context_changed = false0; | |||
486 | char *path; | |||
487 | int r; | |||
488 | ||||
489 | assert(fd >= 0)do { if ((__builtin_expect(!!(!(fd >= 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("fd >= 0"), "../src/basic/selinux-util.c" , 489, __PRETTY_FUNCTION__); } while (0); | |||
490 | assert(addr)do { if ((__builtin_expect(!!(!(addr)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("addr"), "../src/basic/selinux-util.c", 490 , __PRETTY_FUNCTION__); } while (0); | |||
491 | assert(addrlen >= sizeof(sa_family_t))do { if ((__builtin_expect(!!(!(addrlen >= sizeof(sa_family_t ))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("addrlen >= sizeof(sa_family_t)" ), "../src/basic/selinux-util.c", 491, __PRETTY_FUNCTION__); } while (0); | |||
492 | ||||
493 | if (!label_hnd) | |||
494 | goto skipped; | |||
495 | ||||
496 | /* Filter out non-local sockets */ | |||
497 | if (addr->sa_family != AF_UNIX1) | |||
498 | goto skipped; | |||
499 | ||||
500 | /* Filter out anonymous sockets */ | |||
501 | if (addrlen < offsetof(struct sockaddr_un, sun_path)__builtin_offsetof(struct sockaddr_un, sun_path) + 1) | |||
502 | goto skipped; | |||
503 | ||||
504 | /* Filter out abstract namespace sockets */ | |||
505 | un = (const struct sockaddr_un*) addr; | |||
506 | if (un->sun_path[0] == 0) | |||
507 | goto skipped; | |||
508 | ||||
509 | path = strndupa(un->sun_path, addrlen - offsetof(struct sockaddr_un, sun_path))(__extension__ ({ const char *__old = (un->sun_path); size_t __len = strnlen (__old, (addrlen - __builtin_offsetof(struct sockaddr_un, sun_path))); char *__new = (char *) __builtin_alloca (__len + 1); __new[__len] = '\0'; (char *) memcpy (__new, __old , __len); })); | |||
510 | ||||
511 | /* Check for policy reload so 'label_hnd' is kept up-to-date by callbacks */ | |||
512 | (void) avc_netlink_check_nb(); | |||
513 | ||||
514 | if (path_is_absolute(path)) | |||
515 | r = selabel_lookup_raw(label_hnd, &fcon, path, S_IFSOCK0140000); | |||
516 | else { | |||
517 | _cleanup_free___attribute__((cleanup(freep))) char *newpath = NULL((void*)0); | |||
518 | ||||
519 | r = path_make_absolute_cwd(path, &newpath); | |||
520 | if (r < 0) | |||
521 | return r; | |||
522 | ||||
523 | r = selabel_lookup_raw(label_hnd, &fcon, newpath, S_IFSOCK0140000); | |||
524 | } | |||
525 | ||||
526 | if (r < 0) { | |||
527 | /* No context specified by the policy? Proceed without setting it */ | |||
528 | if (errno(*__errno_location ()) == ENOENT2) | |||
529 | goto skipped; | |||
530 | ||||
531 | log_enforcing_errno(errno, "Failed to determine SELinux security context for %s: %m", path)({ int _level = ((security_getenforce() == 1 ? 3 : 7)), _e = ( ((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm (_realm) >= ((_level) & 0x07)) ? log_internal_realm((( _realm) << 10 | (_level)), _e, "../src/basic/selinux-util.c" , 531, __func__, "Failed to determine SELinux security context for %s: %m" , path) : -abs(_e); }); | |||
532 | if (security_getenforce() > 0) | |||
533 | return -errno(*__errno_location ()); | |||
534 | ||||
535 | } else { | |||
536 | if (setfscreatecon_raw(fcon) < 0) { | |||
537 | log_enforcing_errno(errno, "Failed to set SELinux security context %s for %s: %m", fcon, path)({ int _level = ((security_getenforce() == 1 ? 3 : 7)), _e = ( ((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm (_realm) >= ((_level) & 0x07)) ? log_internal_realm((( _realm) << 10 | (_level)), _e, "../src/basic/selinux-util.c" , 537, __func__, "Failed to set SELinux security context %s for %s: %m" , fcon, path) : -abs(_e); }); | |||
538 | if (security_getenforce() > 0) | |||
539 | return -errno(*__errno_location ()); | |||
540 | } else | |||
541 | context_changed = true1; | |||
542 | } | |||
543 | ||||
544 | r = bind(fd, addr, addrlen) < 0 ? -errno(*__errno_location ()) : 0; | |||
545 | ||||
546 | if (context_changed) | |||
547 | setfscreatecon_raw(NULL((void*)0)); | |||
548 | ||||
549 | return r; | |||
550 | ||||
551 | skipped: | |||
552 | #endif | |||
553 | if (bind(fd, addr, addrlen) < 0) | |||
554 | return -errno(*__errno_location ()); | |||
555 | ||||
556 | return 0; | |||
557 | } |