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