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