1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 Copyright © 2013 Intel Corporation
5 Author: Auke Kok <auke-jan.h.kok@intel.com>
11 #include <sys/xattr.h>
14 #include "alloc-util.h"
19 #include "path-util.h"
20 #include "process-util.h"
21 #include "smack-util.h"
22 #include "stdio-util.h"
23 #include "string-table.h"
24 #include "xattr-util.h"
27 bool mac_smack_use(void) {
28 static int cached_use
= -1;
31 cached_use
= access("/sys/fs/smackfs/", F_OK
) >= 0;
36 static const char* const smack_attr_table
[_SMACK_ATTR_MAX
] = {
37 [SMACK_ATTR_ACCESS
] = "security.SMACK64",
38 [SMACK_ATTR_EXEC
] = "security.SMACK64EXEC",
39 [SMACK_ATTR_MMAP
] = "security.SMACK64MMAP",
40 [SMACK_ATTR_TRANSMUTE
] = "security.SMACK64TRANSMUTE",
41 [SMACK_ATTR_IPIN
] = "security.SMACK64IPIN",
42 [SMACK_ATTR_IPOUT
] = "security.SMACK64IPOUT",
45 DEFINE_STRING_TABLE_LOOKUP(smack_attr
, SmackAttr
);
47 int mac_smack_read(const char *path
, SmackAttr attr
, char **label
) {
49 assert(attr
>= 0 && attr
< _SMACK_ATTR_MAX
);
55 return getxattr_malloc(path
, smack_attr_to_string(attr
), label
, true);
58 int mac_smack_read_fd(int fd
, SmackAttr attr
, char **label
) {
60 assert(attr
>= 0 && attr
< _SMACK_ATTR_MAX
);
66 return fgetxattr_malloc(fd
, smack_attr_to_string(attr
), label
);
69 int mac_smack_apply(const char *path
, SmackAttr attr
, const char *label
) {
73 assert(attr
>= 0 && attr
< _SMACK_ATTR_MAX
);
79 r
= lsetxattr(path
, smack_attr_to_string(attr
), label
, strlen(label
), 0);
81 r
= lremovexattr(path
, smack_attr_to_string(attr
));
88 int mac_smack_apply_fd(int fd
, SmackAttr attr
, const char *label
) {
92 assert(attr
>= 0 && attr
< _SMACK_ATTR_MAX
);
98 r
= fsetxattr(fd
, smack_attr_to_string(attr
), label
, strlen(label
), 0);
100 r
= fremovexattr(fd
, smack_attr_to_string(attr
));
107 int mac_smack_apply_pid(pid_t pid
, const char *label
) {
113 if (!mac_smack_use())
116 p
= procfs_file_alloca(pid
, "attr/current");
117 r
= write_string_file(p
, label
, WRITE_STRING_FILE_DISABLE_BUFFER
);
124 static int smack_fix_fd(int fd
, const char *abspath
, LabelFixFlags flags
) {
125 char procfs_path
[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)];
130 /* The caller should have done the sanity checks. */
132 assert(path_is_absolute(abspath
));
134 /* Path must be in /dev. */
135 if (!path_startswith(abspath
, "/dev"))
138 if (fstat(fd
, &st
) < 0)
142 * Label directories and character devices "*".
143 * Label symlinks "_".
144 * Don't change anything else.
147 if (S_ISDIR(st
.st_mode
))
148 label
= SMACK_STAR_LABEL
;
149 else if (S_ISLNK(st
.st_mode
))
150 label
= SMACK_FLOOR_LABEL
;
151 else if (S_ISCHR(st
.st_mode
))
152 label
= SMACK_STAR_LABEL
;
156 xsprintf(procfs_path
, "/proc/self/fd/%i", fd
);
157 if (setxattr(procfs_path
, "security.SMACK64", label
, strlen(label
), 0) < 0) {
158 _cleanup_free_
char *old_label
= NULL
;
162 /* If the FS doesn't support labels, then exit without warning */
163 if (r
== -EOPNOTSUPP
)
166 /* It the FS is read-only and we were told to ignore failures caused by that, suppress error */
167 if (r
== -EROFS
&& (flags
& LABEL_IGNORE_EROFS
))
170 /* If the old label is identical to the new one, suppress any kind of error */
171 if (getxattr_malloc(procfs_path
, "security.SMACK64", &old_label
, false) >= 0 &&
172 streq(old_label
, label
))
175 return log_debug_errno(r
, "Unable to fix SMACK label of %s: %m", abspath
);
181 int mac_smack_fix_at(int dirfd
, const char *path
, LabelFixFlags flags
) {
182 _cleanup_free_
char *p
= NULL
;
183 _cleanup_close_
int fd
= -1;
188 if (!mac_smack_use())
191 fd
= openat(dirfd
, path
, O_NOFOLLOW
|O_CLOEXEC
|O_PATH
);
193 if ((flags
& LABEL_IGNORE_ENOENT
) && errno
== ENOENT
)
199 if (!path_is_absolute(path
)) {
200 r
= fd_get_path(fd
, &p
);
206 return smack_fix_fd(fd
, path
, flags
);
209 int mac_smack_fix_container(const char *path
, const char *inside_path
, LabelFixFlags flags
) {
210 _cleanup_free_
char *abspath
= NULL
;
211 _cleanup_close_
int fd
= -1;
216 if (!mac_smack_use())
219 r
= path_make_absolute_cwd(path
, &abspath
);
223 fd
= open(abspath
, O_NOFOLLOW
|O_CLOEXEC
|O_PATH
);
225 if ((flags
& LABEL_IGNORE_ENOENT
) && errno
== ENOENT
)
231 return smack_fix_fd(fd
, inside_path
, flags
);
234 int mac_smack_copy(const char *dest
, const char *src
) {
236 _cleanup_free_
char *label
= NULL
;
241 r
= mac_smack_read(src
, SMACK_ATTR_ACCESS
, &label
);
245 r
= mac_smack_apply(dest
, SMACK_ATTR_ACCESS
, label
);
253 bool mac_smack_use(void) {
257 int mac_smack_read(const char *path
, SmackAttr attr
, char **label
) {
261 int mac_smack_read_fd(int fd
, SmackAttr attr
, char **label
) {
265 int mac_smack_apply(const char *path
, SmackAttr attr
, const char *label
) {
269 int mac_smack_apply_fd(int fd
, SmackAttr attr
, const char *label
) {
273 int mac_smack_apply_pid(pid_t pid
, const char *label
) {
277 int mac_smack_fix_container(const char *path
, const char *inside_path
, LabelFixFlags flags
) {
281 int mac_smack_fix_at(int dirfd
, const char *path
, LabelFixFlags flags
) {
285 int mac_smack_copy(const char *dest
, const char *src
) {