199ca880aSopenharmony_ci/*** 299ca880aSopenharmony_ci This file is part of eudev, forked from systemd. 399ca880aSopenharmony_ci 499ca880aSopenharmony_ci Copyright 2010 Lennart Poettering 599ca880aSopenharmony_ci 699ca880aSopenharmony_ci systemd is free software; you can redistribute it and/or modify it 799ca880aSopenharmony_ci under the terms of the GNU Lesser General Public License as published by 899ca880aSopenharmony_ci the Free Software Foundation; either version 2.1 of the License, or 999ca880aSopenharmony_ci (at your option) any later version. 1099ca880aSopenharmony_ci 1199ca880aSopenharmony_ci systemd is distributed in the hope that it will be useful, but 1299ca880aSopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 1399ca880aSopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1499ca880aSopenharmony_ci Lesser General Public License for more details. 1599ca880aSopenharmony_ci 1699ca880aSopenharmony_ci You should have received a copy of the GNU Lesser General Public License 1799ca880aSopenharmony_ci along with systemd; If not, see <http://www.gnu.org/licenses/>. 1899ca880aSopenharmony_ci***/ 1999ca880aSopenharmony_ci 2099ca880aSopenharmony_ci#include <errno.h> 2199ca880aSopenharmony_ci#include <unistd.h> 2299ca880aSopenharmony_ci#include <malloc.h> 2399ca880aSopenharmony_ci#include <sys/un.h> 2499ca880aSopenharmony_ci 2599ca880aSopenharmony_ci#ifdef HAVE_SELINUX 2699ca880aSopenharmony_ci#include <selinux/selinux.h> 2799ca880aSopenharmony_ci#include <selinux/label.h> 2899ca880aSopenharmony_ci#include <selinux/context.h> 2999ca880aSopenharmony_ci#endif 3099ca880aSopenharmony_ci 3199ca880aSopenharmony_ci#include "strv.h" 3299ca880aSopenharmony_ci#include "path-util.h" 3399ca880aSopenharmony_ci#include "selinux-util.h" 3499ca880aSopenharmony_ci#include "missing.h" 3599ca880aSopenharmony_ci 3699ca880aSopenharmony_ci#ifdef HAVE_SELINUX 3799ca880aSopenharmony_ciDEFINE_TRIVIAL_CLEANUP_FUNC(security_context_t, freecon); 3899ca880aSopenharmony_ciDEFINE_TRIVIAL_CLEANUP_FUNC(context_t, context_free); 3999ca880aSopenharmony_ci 4099ca880aSopenharmony_ci#define _cleanup_security_context_free_ _cleanup_(freeconp) 4199ca880aSopenharmony_ci#define _cleanup_context_free_ _cleanup_(context_freep) 4299ca880aSopenharmony_ci 4399ca880aSopenharmony_cistatic int cached_use = -1; 4499ca880aSopenharmony_cistatic struct selabel_handle *label_hnd = NULL; 4599ca880aSopenharmony_ci 4699ca880aSopenharmony_ci#define log_enforcing(...) log_full(security_getenforce() == 1 ? LOG_ERR : LOG_DEBUG, __VA_ARGS__) 4799ca880aSopenharmony_ci#endif 4899ca880aSopenharmony_ci 4999ca880aSopenharmony_cibool mac_selinux_use(void) { 5099ca880aSopenharmony_ci#ifdef HAVE_SELINUX 5199ca880aSopenharmony_ci if (cached_use < 0) 5299ca880aSopenharmony_ci cached_use = is_selinux_enabled() > 0; 5399ca880aSopenharmony_ci 5499ca880aSopenharmony_ci return cached_use; 5599ca880aSopenharmony_ci#else 5699ca880aSopenharmony_ci return false; 5799ca880aSopenharmony_ci#endif 5899ca880aSopenharmony_ci} 5999ca880aSopenharmony_ci 6099ca880aSopenharmony_civoid mac_selinux_retest(void) { 6199ca880aSopenharmony_ci#ifdef HAVE_SELINUX 6299ca880aSopenharmony_ci cached_use = -1; 6399ca880aSopenharmony_ci#endif 6499ca880aSopenharmony_ci} 6599ca880aSopenharmony_ci 6699ca880aSopenharmony_ciint mac_selinux_init(const char *prefix) { 6799ca880aSopenharmony_ci int r = 0; 6899ca880aSopenharmony_ci 6999ca880aSopenharmony_ci#ifdef HAVE_SELINUX 7099ca880aSopenharmony_ci usec_t before_timestamp, after_timestamp; 7199ca880aSopenharmony_ci 7299ca880aSopenharmony_ci#ifdef HAVE_MALLINFO 7399ca880aSopenharmony_ci struct mallinfo before_mallinfo, after_mallinfo; 7499ca880aSopenharmony_ci#endif 7599ca880aSopenharmony_ci 7699ca880aSopenharmony_ci if (!mac_selinux_use()) 7799ca880aSopenharmony_ci return 0; 7899ca880aSopenharmony_ci 7999ca880aSopenharmony_ci if (label_hnd) 8099ca880aSopenharmony_ci return 0; 8199ca880aSopenharmony_ci 8299ca880aSopenharmony_ci#ifdef HAVE_MALLINFO 8399ca880aSopenharmony_ci before_mallinfo = mallinfo(); 8499ca880aSopenharmony_ci#endif 8599ca880aSopenharmony_ci 8699ca880aSopenharmony_ci before_timestamp = now(CLOCK_MONOTONIC); 8799ca880aSopenharmony_ci 8899ca880aSopenharmony_ci if (prefix) { 8999ca880aSopenharmony_ci struct selinux_opt options[] = { 9099ca880aSopenharmony_ci { .type = SELABEL_OPT_SUBSET, .value = prefix }, 9199ca880aSopenharmony_ci }; 9299ca880aSopenharmony_ci 9399ca880aSopenharmony_ci label_hnd = selabel_open(SELABEL_CTX_FILE, options, ELEMENTSOF(options)); 9499ca880aSopenharmony_ci } else 9599ca880aSopenharmony_ci label_hnd = selabel_open(SELABEL_CTX_FILE, NULL, 0); 9699ca880aSopenharmony_ci 9799ca880aSopenharmony_ci if (!label_hnd) { 9899ca880aSopenharmony_ci log_enforcing("Failed to initialize SELinux context: %m"); 9999ca880aSopenharmony_ci r = security_getenforce() == 1 ? -errno : 0; 10099ca880aSopenharmony_ci } else { 10199ca880aSopenharmony_ci char timespan[FORMAT_TIMESPAN_MAX]; 10299ca880aSopenharmony_ci 10399ca880aSopenharmony_ci#ifdef HAVE_MALLINFO 10499ca880aSopenharmony_ci int l; 10599ca880aSopenharmony_ci#endif 10699ca880aSopenharmony_ci 10799ca880aSopenharmony_ci after_timestamp = now(CLOCK_MONOTONIC); 10899ca880aSopenharmony_ci 10999ca880aSopenharmony_ci#ifdef HAVE_MALLINFO 11099ca880aSopenharmony_ci after_mallinfo = mallinfo(); 11199ca880aSopenharmony_ci 11299ca880aSopenharmony_ci l = after_mallinfo.uordblks > before_mallinfo.uordblks ? after_mallinfo.uordblks - before_mallinfo.uordblks : 0; 11399ca880aSopenharmony_ci 11499ca880aSopenharmony_ci log_debug("Successfully loaded SELinux database in %s, size on heap is %iK.", 11599ca880aSopenharmony_ci format_timespan(timespan, sizeof(timespan), after_timestamp - before_timestamp, 0), 11699ca880aSopenharmony_ci (l+1023)/1024); 11799ca880aSopenharmony_ci#else 11899ca880aSopenharmony_ci log_debug("Successfully loaded SELinux database in %s", 11999ca880aSopenharmony_ci format_timespan(timespan, sizeof(timespan), after_timestamp - before_timestamp, 0)); 12099ca880aSopenharmony_ci#endif 12199ca880aSopenharmony_ci } 12299ca880aSopenharmony_ci#endif 12399ca880aSopenharmony_ci 12499ca880aSopenharmony_ci return r; 12599ca880aSopenharmony_ci} 12699ca880aSopenharmony_ci 12799ca880aSopenharmony_civoid mac_selinux_finish(void) { 12899ca880aSopenharmony_ci 12999ca880aSopenharmony_ci#ifdef HAVE_SELINUX 13099ca880aSopenharmony_ci if (!label_hnd) 13199ca880aSopenharmony_ci return; 13299ca880aSopenharmony_ci 13399ca880aSopenharmony_ci selabel_close(label_hnd); 13499ca880aSopenharmony_ci label_hnd = NULL; 13599ca880aSopenharmony_ci#endif 13699ca880aSopenharmony_ci} 13799ca880aSopenharmony_ci 13899ca880aSopenharmony_ciint mac_selinux_fix(const char *path, bool ignore_enoent, bool ignore_erofs) { 13999ca880aSopenharmony_ci 14099ca880aSopenharmony_ci#ifdef HAVE_SELINUX 14199ca880aSopenharmony_ci struct stat st; 14299ca880aSopenharmony_ci int r; 14399ca880aSopenharmony_ci 14499ca880aSopenharmony_ci assert(path); 14599ca880aSopenharmony_ci 14699ca880aSopenharmony_ci /* if mac_selinux_init() wasn't called before we are a NOOP */ 14799ca880aSopenharmony_ci if (!label_hnd) 14899ca880aSopenharmony_ci return 0; 14999ca880aSopenharmony_ci 15099ca880aSopenharmony_ci r = lstat(path, &st); 15199ca880aSopenharmony_ci if (r >= 0) { 15299ca880aSopenharmony_ci _cleanup_security_context_free_ security_context_t fcon = NULL; 15399ca880aSopenharmony_ci 15499ca880aSopenharmony_ci r = selabel_lookup_raw(label_hnd, &fcon, path, st.st_mode); 15599ca880aSopenharmony_ci 15699ca880aSopenharmony_ci /* If there's no label to set, then exit without warning */ 15799ca880aSopenharmony_ci if (r < 0 && errno == ENOENT) 15899ca880aSopenharmony_ci return 0; 15999ca880aSopenharmony_ci 16099ca880aSopenharmony_ci if (r >= 0) { 16199ca880aSopenharmony_ci r = lsetfilecon(path, fcon); 16299ca880aSopenharmony_ci 16399ca880aSopenharmony_ci /* If the FS doesn't support labels, then exit without warning */ 16499ca880aSopenharmony_ci if (r < 0 && errno == EOPNOTSUPP) 16599ca880aSopenharmony_ci return 0; 16699ca880aSopenharmony_ci } 16799ca880aSopenharmony_ci } 16899ca880aSopenharmony_ci 16999ca880aSopenharmony_ci if (r < 0) { 17099ca880aSopenharmony_ci /* Ignore ENOENT in some cases */ 17199ca880aSopenharmony_ci if (ignore_enoent && errno == ENOENT) 17299ca880aSopenharmony_ci return 0; 17399ca880aSopenharmony_ci 17499ca880aSopenharmony_ci if (ignore_erofs && errno == EROFS) 17599ca880aSopenharmony_ci return 0; 17699ca880aSopenharmony_ci 17799ca880aSopenharmony_ci log_enforcing("Unable to fix SELinux security context of %s: %m", path); 17899ca880aSopenharmony_ci if (security_getenforce() == 1) 17999ca880aSopenharmony_ci return -errno; 18099ca880aSopenharmony_ci } 18199ca880aSopenharmony_ci#endif 18299ca880aSopenharmony_ci 18399ca880aSopenharmony_ci return 0; 18499ca880aSopenharmony_ci} 18599ca880aSopenharmony_ci 18699ca880aSopenharmony_ciint mac_selinux_apply(const char *path, const char *label) { 18799ca880aSopenharmony_ci 18899ca880aSopenharmony_ci#ifdef HAVE_SELINUX 18999ca880aSopenharmony_ci assert(path); 19099ca880aSopenharmony_ci assert(label); 19199ca880aSopenharmony_ci 19299ca880aSopenharmony_ci if (!mac_selinux_use()) 19399ca880aSopenharmony_ci return 0; 19499ca880aSopenharmony_ci 19599ca880aSopenharmony_ci if (setfilecon(path, (security_context_t) label) < 0) { 19699ca880aSopenharmony_ci log_enforcing("Failed to set SELinux security context %s on path %s: %m", label, path); 19799ca880aSopenharmony_ci if (security_getenforce() == 1) 19899ca880aSopenharmony_ci return -errno; 19999ca880aSopenharmony_ci } 20099ca880aSopenharmony_ci#endif 20199ca880aSopenharmony_ci return 0; 20299ca880aSopenharmony_ci} 20399ca880aSopenharmony_ci 20499ca880aSopenharmony_ciint mac_selinux_get_create_label_from_exe(const char *exe, char **label) { 20599ca880aSopenharmony_ci int r = -EOPNOTSUPP; 20699ca880aSopenharmony_ci 20799ca880aSopenharmony_ci#ifdef HAVE_SELINUX 20899ca880aSopenharmony_ci _cleanup_security_context_free_ security_context_t mycon = NULL, fcon = NULL; 20999ca880aSopenharmony_ci security_class_t sclass; 21099ca880aSopenharmony_ci 21199ca880aSopenharmony_ci assert(exe); 21299ca880aSopenharmony_ci assert(label); 21399ca880aSopenharmony_ci 21499ca880aSopenharmony_ci if (!mac_selinux_use()) 21599ca880aSopenharmony_ci return -EOPNOTSUPP; 21699ca880aSopenharmony_ci 21799ca880aSopenharmony_ci r = getcon(&mycon); 21899ca880aSopenharmony_ci if (r < 0) 21999ca880aSopenharmony_ci return -errno; 22099ca880aSopenharmony_ci 22199ca880aSopenharmony_ci r = getfilecon(exe, &fcon); 22299ca880aSopenharmony_ci if (r < 0) 22399ca880aSopenharmony_ci return -errno; 22499ca880aSopenharmony_ci 22599ca880aSopenharmony_ci sclass = string_to_security_class("process"); 22699ca880aSopenharmony_ci r = security_compute_create(mycon, fcon, sclass, (security_context_t *) label); 22799ca880aSopenharmony_ci if (r < 0) 22899ca880aSopenharmony_ci return -errno; 22999ca880aSopenharmony_ci#endif 23099ca880aSopenharmony_ci 23199ca880aSopenharmony_ci return r; 23299ca880aSopenharmony_ci} 23399ca880aSopenharmony_ci 23499ca880aSopenharmony_ciint mac_selinux_get_our_label(char **label) { 23599ca880aSopenharmony_ci int r = -EOPNOTSUPP; 23699ca880aSopenharmony_ci 23799ca880aSopenharmony_ci assert(label); 23899ca880aSopenharmony_ci 23999ca880aSopenharmony_ci#ifdef HAVE_SELINUX 24099ca880aSopenharmony_ci if (!mac_selinux_use()) 24199ca880aSopenharmony_ci return -EOPNOTSUPP; 24299ca880aSopenharmony_ci 24399ca880aSopenharmony_ci r = getcon(label); 24499ca880aSopenharmony_ci if (r < 0) 24599ca880aSopenharmony_ci return -errno; 24699ca880aSopenharmony_ci#endif 24799ca880aSopenharmony_ci 24899ca880aSopenharmony_ci return r; 24999ca880aSopenharmony_ci} 25099ca880aSopenharmony_ci 25199ca880aSopenharmony_ciint mac_selinux_get_child_mls_label(int socket_fd, const char *exe, const char *exec_label, char **label) { 25299ca880aSopenharmony_ci int r = -EOPNOTSUPP; 25399ca880aSopenharmony_ci 25499ca880aSopenharmony_ci#ifdef HAVE_SELINUX 25599ca880aSopenharmony_ci _cleanup_security_context_free_ security_context_t mycon = NULL, peercon = NULL, fcon = NULL; 25699ca880aSopenharmony_ci _cleanup_context_free_ context_t pcon = NULL, bcon = NULL; 25799ca880aSopenharmony_ci security_class_t sclass; 25899ca880aSopenharmony_ci const char *range = NULL; 25999ca880aSopenharmony_ci 26099ca880aSopenharmony_ci assert(socket_fd >= 0); 26199ca880aSopenharmony_ci assert(exe); 26299ca880aSopenharmony_ci assert(label); 26399ca880aSopenharmony_ci 26499ca880aSopenharmony_ci if (!mac_selinux_use()) 26599ca880aSopenharmony_ci return -EOPNOTSUPP; 26699ca880aSopenharmony_ci 26799ca880aSopenharmony_ci r = getcon(&mycon); 26899ca880aSopenharmony_ci if (r < 0) 26999ca880aSopenharmony_ci return -errno; 27099ca880aSopenharmony_ci 27199ca880aSopenharmony_ci r = getpeercon(socket_fd, &peercon); 27299ca880aSopenharmony_ci if (r < 0) 27399ca880aSopenharmony_ci return -errno; 27499ca880aSopenharmony_ci 27599ca880aSopenharmony_ci if (!exec_label) { 27699ca880aSopenharmony_ci /* If there is no context set for next exec let's use context 27799ca880aSopenharmony_ci of target executable */ 27899ca880aSopenharmony_ci r = getfilecon(exe, &fcon); 27999ca880aSopenharmony_ci if (r < 0) 28099ca880aSopenharmony_ci return -errno; 28199ca880aSopenharmony_ci } 28299ca880aSopenharmony_ci 28399ca880aSopenharmony_ci bcon = context_new(mycon); 28499ca880aSopenharmony_ci if (!bcon) 28599ca880aSopenharmony_ci return -ENOMEM; 28699ca880aSopenharmony_ci 28799ca880aSopenharmony_ci pcon = context_new(peercon); 28899ca880aSopenharmony_ci if (!pcon) 28999ca880aSopenharmony_ci return -ENOMEM; 29099ca880aSopenharmony_ci 29199ca880aSopenharmony_ci range = context_range_get(pcon); 29299ca880aSopenharmony_ci if (!range) 29399ca880aSopenharmony_ci return -errno; 29499ca880aSopenharmony_ci 29599ca880aSopenharmony_ci r = context_range_set(bcon, range); 29699ca880aSopenharmony_ci if (r) 29799ca880aSopenharmony_ci return -errno; 29899ca880aSopenharmony_ci 29999ca880aSopenharmony_ci freecon(mycon); 30099ca880aSopenharmony_ci mycon = strdup(context_str(bcon)); 30199ca880aSopenharmony_ci if (!mycon) 30299ca880aSopenharmony_ci return -ENOMEM; 30399ca880aSopenharmony_ci 30499ca880aSopenharmony_ci sclass = string_to_security_class("process"); 30599ca880aSopenharmony_ci r = security_compute_create(mycon, fcon, sclass, (security_context_t *) label); 30699ca880aSopenharmony_ci if (r < 0) 30799ca880aSopenharmony_ci return -errno; 30899ca880aSopenharmony_ci#endif 30999ca880aSopenharmony_ci 31099ca880aSopenharmony_ci return r; 31199ca880aSopenharmony_ci} 31299ca880aSopenharmony_ci 31399ca880aSopenharmony_civoid mac_selinux_free(char *label) { 31499ca880aSopenharmony_ci 31599ca880aSopenharmony_ci#ifdef HAVE_SELINUX 31699ca880aSopenharmony_ci if (!mac_selinux_use()) 31799ca880aSopenharmony_ci return; 31899ca880aSopenharmony_ci 31999ca880aSopenharmony_ci freecon((security_context_t) label); 32099ca880aSopenharmony_ci#endif 32199ca880aSopenharmony_ci} 32299ca880aSopenharmony_ci 32399ca880aSopenharmony_ciint mac_selinux_create_file_prepare(const char *path, mode_t mode) { 32499ca880aSopenharmony_ci int r = 0; 32599ca880aSopenharmony_ci 32699ca880aSopenharmony_ci#ifdef HAVE_SELINUX 32799ca880aSopenharmony_ci _cleanup_security_context_free_ security_context_t filecon = NULL; 32899ca880aSopenharmony_ci 32999ca880aSopenharmony_ci assert(path); 33099ca880aSopenharmony_ci 33199ca880aSopenharmony_ci if (!label_hnd) 33299ca880aSopenharmony_ci return 0; 33399ca880aSopenharmony_ci 33499ca880aSopenharmony_ci if (path_is_absolute(path)) 33599ca880aSopenharmony_ci r = selabel_lookup_raw(label_hnd, &filecon, path, mode); 33699ca880aSopenharmony_ci else { 33799ca880aSopenharmony_ci _cleanup_free_ char *newpath; 33899ca880aSopenharmony_ci 33999ca880aSopenharmony_ci newpath = path_make_absolute_cwd(path); 34099ca880aSopenharmony_ci if (!newpath) 34199ca880aSopenharmony_ci return -ENOMEM; 34299ca880aSopenharmony_ci 34399ca880aSopenharmony_ci r = selabel_lookup_raw(label_hnd, &filecon, newpath, mode); 34499ca880aSopenharmony_ci } 34599ca880aSopenharmony_ci 34699ca880aSopenharmony_ci /* No context specified by the policy? Proceed without setting it. */ 34799ca880aSopenharmony_ci if (r < 0 && errno == ENOENT) 34899ca880aSopenharmony_ci return 0; 34999ca880aSopenharmony_ci 35099ca880aSopenharmony_ci if (r < 0) 35199ca880aSopenharmony_ci r = -errno; 35299ca880aSopenharmony_ci else { 35399ca880aSopenharmony_ci r = setfscreatecon(filecon); 35499ca880aSopenharmony_ci if (r < 0) { 35599ca880aSopenharmony_ci log_enforcing("Failed to set SELinux security context %s for %s: %m", filecon, path); 35699ca880aSopenharmony_ci r = -errno; 35799ca880aSopenharmony_ci } 35899ca880aSopenharmony_ci } 35999ca880aSopenharmony_ci 36099ca880aSopenharmony_ci if (r < 0 && security_getenforce() == 0) 36199ca880aSopenharmony_ci r = 0; 36299ca880aSopenharmony_ci#endif 36399ca880aSopenharmony_ci 36499ca880aSopenharmony_ci return r; 36599ca880aSopenharmony_ci} 36699ca880aSopenharmony_ci 36799ca880aSopenharmony_civoid mac_selinux_create_file_clear(void) { 36899ca880aSopenharmony_ci 36999ca880aSopenharmony_ci#ifdef HAVE_SELINUX 37099ca880aSopenharmony_ci PROTECT_ERRNO; 37199ca880aSopenharmony_ci 37299ca880aSopenharmony_ci if (!mac_selinux_use()) 37399ca880aSopenharmony_ci return; 37499ca880aSopenharmony_ci 37599ca880aSopenharmony_ci setfscreatecon(NULL); 37699ca880aSopenharmony_ci#endif 37799ca880aSopenharmony_ci} 37899ca880aSopenharmony_ci 37999ca880aSopenharmony_ciint mac_selinux_create_socket_prepare(const char *label) { 38099ca880aSopenharmony_ci 38199ca880aSopenharmony_ci#ifdef HAVE_SELINUX 38299ca880aSopenharmony_ci if (!mac_selinux_use()) 38399ca880aSopenharmony_ci return 0; 38499ca880aSopenharmony_ci 38599ca880aSopenharmony_ci assert(label); 38699ca880aSopenharmony_ci 38799ca880aSopenharmony_ci if (setsockcreatecon((security_context_t) label) < 0) { 38899ca880aSopenharmony_ci log_enforcing("Failed to set SELinux security context %s for sockets: %m", label); 38999ca880aSopenharmony_ci 39099ca880aSopenharmony_ci if (security_getenforce() == 1) 39199ca880aSopenharmony_ci return -errno; 39299ca880aSopenharmony_ci } 39399ca880aSopenharmony_ci#endif 39499ca880aSopenharmony_ci 39599ca880aSopenharmony_ci return 0; 39699ca880aSopenharmony_ci} 39799ca880aSopenharmony_ci 39899ca880aSopenharmony_civoid mac_selinux_create_socket_clear(void) { 39999ca880aSopenharmony_ci 40099ca880aSopenharmony_ci#ifdef HAVE_SELINUX 40199ca880aSopenharmony_ci PROTECT_ERRNO; 40299ca880aSopenharmony_ci 40399ca880aSopenharmony_ci if (!mac_selinux_use()) 40499ca880aSopenharmony_ci return; 40599ca880aSopenharmony_ci 40699ca880aSopenharmony_ci setsockcreatecon(NULL); 40799ca880aSopenharmony_ci#endif 40899ca880aSopenharmony_ci} 40999ca880aSopenharmony_ci 41099ca880aSopenharmony_ciint mac_selinux_mkdir(const char *path, mode_t mode) { 41199ca880aSopenharmony_ci 41299ca880aSopenharmony_ci /* Creates a directory and labels it according to the SELinux policy */ 41399ca880aSopenharmony_ci 41499ca880aSopenharmony_ci#ifdef HAVE_SELINUX 41599ca880aSopenharmony_ci _cleanup_security_context_free_ security_context_t fcon = NULL; 41699ca880aSopenharmony_ci int r; 41799ca880aSopenharmony_ci 41899ca880aSopenharmony_ci assert(path); 41999ca880aSopenharmony_ci 42099ca880aSopenharmony_ci if (!label_hnd) 42199ca880aSopenharmony_ci goto skipped; 42299ca880aSopenharmony_ci 42399ca880aSopenharmony_ci if (path_is_absolute(path)) 42499ca880aSopenharmony_ci r = selabel_lookup_raw(label_hnd, &fcon, path, S_IFDIR); 42599ca880aSopenharmony_ci else { 42699ca880aSopenharmony_ci _cleanup_free_ char *newpath; 42799ca880aSopenharmony_ci 42899ca880aSopenharmony_ci newpath = path_make_absolute_cwd(path); 42999ca880aSopenharmony_ci if (!newpath) 43099ca880aSopenharmony_ci return -ENOMEM; 43199ca880aSopenharmony_ci 43299ca880aSopenharmony_ci r = selabel_lookup_raw(label_hnd, &fcon, newpath, S_IFDIR); 43399ca880aSopenharmony_ci } 43499ca880aSopenharmony_ci 43599ca880aSopenharmony_ci if (r == 0) 43699ca880aSopenharmony_ci r = setfscreatecon(fcon); 43799ca880aSopenharmony_ci 43899ca880aSopenharmony_ci if (r < 0 && errno != ENOENT) { 43999ca880aSopenharmony_ci log_enforcing("Failed to set SELinux security context %s for %s: %m", fcon, path); 44099ca880aSopenharmony_ci 44199ca880aSopenharmony_ci if (security_getenforce() == 1) { 44299ca880aSopenharmony_ci r = -errno; 44399ca880aSopenharmony_ci goto finish; 44499ca880aSopenharmony_ci } 44599ca880aSopenharmony_ci } 44699ca880aSopenharmony_ci 44799ca880aSopenharmony_ci r = mkdir(path, mode); 44899ca880aSopenharmony_ci if (r < 0) 44999ca880aSopenharmony_ci r = -errno; 45099ca880aSopenharmony_ci 45199ca880aSopenharmony_cifinish: 45299ca880aSopenharmony_ci setfscreatecon(NULL); 45399ca880aSopenharmony_ci return r; 45499ca880aSopenharmony_ci 45599ca880aSopenharmony_ciskipped: 45699ca880aSopenharmony_ci#endif 45799ca880aSopenharmony_ci return mkdir(path, mode) < 0 ? -errno : 0; 45899ca880aSopenharmony_ci} 45999ca880aSopenharmony_ci 46099ca880aSopenharmony_ciint mac_selinux_bind(int fd, const struct sockaddr *addr, socklen_t addrlen) { 46199ca880aSopenharmony_ci 46299ca880aSopenharmony_ci /* Binds a socket and label its file system object according to the SELinux policy */ 46399ca880aSopenharmony_ci 46499ca880aSopenharmony_ci#ifdef HAVE_SELINUX 46599ca880aSopenharmony_ci _cleanup_security_context_free_ security_context_t fcon = NULL; 46699ca880aSopenharmony_ci const struct sockaddr_un *un; 46799ca880aSopenharmony_ci char *path; 46899ca880aSopenharmony_ci int r; 46999ca880aSopenharmony_ci 47099ca880aSopenharmony_ci assert(fd >= 0); 47199ca880aSopenharmony_ci assert(addr); 47299ca880aSopenharmony_ci assert(addrlen >= sizeof(sa_family_t)); 47399ca880aSopenharmony_ci 47499ca880aSopenharmony_ci if (!label_hnd) 47599ca880aSopenharmony_ci goto skipped; 47699ca880aSopenharmony_ci 47799ca880aSopenharmony_ci /* Filter out non-local sockets */ 47899ca880aSopenharmony_ci if (addr->sa_family != AF_UNIX) 47999ca880aSopenharmony_ci goto skipped; 48099ca880aSopenharmony_ci 48199ca880aSopenharmony_ci /* Filter out anonymous sockets */ 48299ca880aSopenharmony_ci if (addrlen < sizeof(sa_family_t) + 1) 48399ca880aSopenharmony_ci goto skipped; 48499ca880aSopenharmony_ci 48599ca880aSopenharmony_ci /* Filter out abstract namespace sockets */ 48699ca880aSopenharmony_ci un = (const struct sockaddr_un*) addr; 48799ca880aSopenharmony_ci if (un->sun_path[0] == 0) 48899ca880aSopenharmony_ci goto skipped; 48999ca880aSopenharmony_ci 49099ca880aSopenharmony_ci path = strndupa(un->sun_path, addrlen - offsetof(struct sockaddr_un, sun_path)); 49199ca880aSopenharmony_ci 49299ca880aSopenharmony_ci if (path_is_absolute(path)) 49399ca880aSopenharmony_ci r = selabel_lookup_raw(label_hnd, &fcon, path, S_IFSOCK); 49499ca880aSopenharmony_ci else { 49599ca880aSopenharmony_ci _cleanup_free_ char *newpath; 49699ca880aSopenharmony_ci 49799ca880aSopenharmony_ci newpath = path_make_absolute_cwd(path); 49899ca880aSopenharmony_ci if (!newpath) 49999ca880aSopenharmony_ci return -ENOMEM; 50099ca880aSopenharmony_ci 50199ca880aSopenharmony_ci r = selabel_lookup_raw(label_hnd, &fcon, newpath, S_IFSOCK); 50299ca880aSopenharmony_ci } 50399ca880aSopenharmony_ci 50499ca880aSopenharmony_ci if (r == 0) 50599ca880aSopenharmony_ci r = setfscreatecon(fcon); 50699ca880aSopenharmony_ci 50799ca880aSopenharmony_ci if (r < 0 && errno != ENOENT) { 50899ca880aSopenharmony_ci log_enforcing("Failed to set SELinux security context %s for %s: %m", fcon, path); 50999ca880aSopenharmony_ci 51099ca880aSopenharmony_ci if (security_getenforce() == 1) { 51199ca880aSopenharmony_ci r = -errno; 51299ca880aSopenharmony_ci goto finish; 51399ca880aSopenharmony_ci } 51499ca880aSopenharmony_ci } 51599ca880aSopenharmony_ci 51699ca880aSopenharmony_ci r = bind(fd, addr, addrlen); 51799ca880aSopenharmony_ci if (r < 0) 51899ca880aSopenharmony_ci r = -errno; 51999ca880aSopenharmony_ci 52099ca880aSopenharmony_cifinish: 52199ca880aSopenharmony_ci setfscreatecon(NULL); 52299ca880aSopenharmony_ci return r; 52399ca880aSopenharmony_ci 52499ca880aSopenharmony_ciskipped: 52599ca880aSopenharmony_ci#endif 52699ca880aSopenharmony_ci return bind(fd, addr, addrlen) < 0 ? -errno : 0; 52799ca880aSopenharmony_ci} 528