diff options
author | Daniel J Walsh <dwalsh@redhat.com> | 2010-07-28 09:39:54 -0400 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2010-08-03 23:45:22 +0200 |
commit | 56cf987fe74270bde4e16c7ec9e0414a9030723b (patch) | |
tree | ba36afd8f8da67dd0ed744997a2e4167e2883cc6 /src/util.c | |
parent | 8b33e5ca72def2b79ffcd9b7e96f8f40f6bd4a20 (diff) |
Systemd is causing mislabeled devices to be created and then attempting to read them.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
On 07/28/2010 05:57 AM, Kay Sievers wrote:
> On Wed, Jul 28, 2010 at 11:43, Lennart Poettering
> <lennart@poettering.net> wrote:
>> On Mon, 26.07.10 16:42, Daniel J Walsh (dwalsh@redhat.com) wrote:
>>> tcontext=system_u:object_r:device_t:s0 tclass=chr_file
>>> type=1400 audit(1280174589.476:7): avc: denied { read } for pid=1
>>> comm="systemd" name="autofs" dev=devtmpfs ino=9482
>>> scontext=system_u:system_r:init_t:s0
>>> tcontext=system_u:object_r:device_t:s0 tclass=chr_file
>>> type=1400 audit(1280174589.476:8): avc: denied { read } for pid=1
>>> comm="systemd" name="autofs" dev=devtmpfs ino=9482
>>> scontext=system_u:system_r:init_t:s0
>>> tcontext=system_u:object_r:device_t:s0 tclass=chr_file
>>>
>>> Lennart, we talked about this earlier. I think this is caused by the
>>> modprobe calls to create /dev/autofs. Since udev is not created at the
>>> point that init loads the kernel modules, the devices get created with
>>> the wrong label. Once udev starts the labels get fixed.
>>>
>>> I can allow init_t to read device_t chr_files.
>>
>> Hmm, I think a cleaner fix would be to make systemd relabel this device
>> properly before accessing it? Given that this is only one device this
>> should not be a problem for us to maintain, I think? How would the
>> fixing of the label work? Would we have to spawn restorecon for this, or
>> can we actually do this in C without too much work?
>
> I guess we can just do what udev is doing, and call setfilecon(), with
> a context of an earlier matchpathcon().
>
> Kay
> _______________________________________________
> systemd-devel mailing list
> systemd-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Here is the updated patch with a fix for the labeling of /dev/autofs
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.14 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org/
iEYEARECAAYFAkxQMyoACgkQrlYvE4MpobNviACfWgxsjW2xzz1qznFex8RVAQHf
gIEAmwRmRcLvGqYtwQaZ3WKIg8wmrwNk
=pC2e
Diffstat (limited to 'src/util.c')
-rw-r--r-- | src/util.c | 244 |
1 files changed, 241 insertions, 3 deletions
diff --git a/src/util.c b/src/util.c index da8a6c3336..2279efac49 100644 --- a/src/util.c +++ b/src/util.c @@ -56,6 +56,244 @@ #include "log.h" #include "strv.h" +#if HAVE_SELINUX +#include <selinux/selinux.h> +#include <selinux/label.h> + +static struct selabel_handle *label_hnd = NULL; + +static inline int use_selinux(void) { + static int use_selinux_ind = -1; + + if (use_selinux_ind == -1) + use_selinux_ind = (is_selinux_enabled() == 1); + + return use_selinux_ind; +} + +static int label_get_file_label_from_path( + const char *label, + const char *path, + const char *class, + security_context_t *fcon) { + + security_context_t dir_con = NULL; + security_class_t sclass; + int r = 0; + + r = getfilecon(path, &dir_con); + if (r >= 0) { + r = -1; + if ((sclass = string_to_security_class(class)) != 0) + r = security_compute_create((security_context_t) label, dir_con, sclass, fcon); + } + if (r < 0) + r = -errno; + + freecon(dir_con); + return r; +} + +#endif + +int label_init(void) { + int r = 0; + +#if HAVE_SELINUX + if (use_selinux()) { + label_hnd = selabel_open(SELABEL_CTX_FILE, NULL, 0); + if (!label_hnd) { + log_full(security_getenforce() == 1 ? LOG_ERR : LOG_DEBUG, "Failed to initialize SELinux context: %m"); + r = (security_getenforce() == 1) ? -errno : 0; + } + } +#endif + + return r; +} + +int label_fix(const char *path) { + int r = 0; +#if HAVE_SELINUX + struct stat st; + security_context_t fcon; + if (use_selinux()) { + r = lstat(path, &st); + + if (r == 0) { + r = selabel_lookup_raw(label_hnd, &fcon, path, st.st_mode); + + if (r == 0) { + r = setfilecon(path, fcon); + freecon(fcon); + } + } + if (r < 0) { + log_error("Unable to fix label of %s: %m", path); + r = (security_getenforce() == 1) ? -errno : 0; + } + } +#endif + return r; +} + +void label_finish(void) { + +#if HAVE_SELINUX + if (use_selinux()) + selabel_close(label_hnd); +#endif + +} + +int label_get_socket_label_from_exe( + const char *exe, + char **label) { + int r = 0; + +#if HAVE_SELINUX + security_context_t mycon = NULL, fcon = NULL; + security_class_t sclass; + + r = getcon(&mycon); + if (r < 0) + goto fail; + + r = getfilecon(exe, &fcon); + if (r < 0) + goto fail; + + sclass = string_to_security_class("process"); + r = security_compute_create(mycon, fcon, sclass, (security_context_t *) label); + if (r == 0) + log_debug("SELinux Socket context for %s will be set to %s", exe, *label); + +fail: + if (r< 0 && security_getenforce() == 1) + r = -errno; + + freecon(mycon); + freecon(fcon); +#endif + + return r; +} + +int label_fifofile_set(const char *label, const char *path) { + int r = 0; + +#if HAVE_SELINUX + security_context_t filecon = NULL; + if (use_selinux() && label) { + if (((r = label_get_file_label_from_path(label, path, "fifo_file", &filecon)) == 0)) { + if ((r = setfscreatecon(filecon)) < 0) { + log_error("Failed to set SELinux file context (%s) on %s: %m", label, path); + r = -errno; + } + + freecon(filecon); + } + + if (r < 0 && security_getenforce() == 0) + r = 0; + } +#endif + + return r; +} + +int label_socket_set(const char *label) { + +#if HAVE_SELINUX + if (use_selinux() && setsockcreatecon((security_context_t) label) < 0) { + log_error("Failed to set SELinux context (%s) on socket: %m", label); + if (security_getenforce() == 1) + return -errno; + } +#endif + + return 0; +} + +void label_file_clear(void) { + +#if HAVE_SELINUX + if (use_selinux()) + setfscreatecon(NULL); +#endif + + return; +} + +void label_free(const char *label) { + +#if HAVE_SELINUX + if (use_selinux()) + freecon((security_context_t) label); +#endif + + return; +} + +void label_socket_clear(void) { + +#if HAVE_SELINUX + if (use_selinux()) + setsockcreatecon(NULL); +#endif + + return; +} + +static int label_mkdir( + const char *path, + mode_t mode) { + +#if HAVE_SELINUX + int r; + security_context_t fcon = NULL; + + if (use_selinux()) { + if (path[0] == '/') { + r = selabel_lookup_raw(label_hnd, &fcon, path, mode); + } + else { + char *cwd = NULL; + char *newpath = NULL; + cwd = getcwd(NULL,0); + if ((! cwd) || (asprintf(&newpath, "%s/%s",cwd,path) < 0)) { + free(cwd); + return -errno; + } + r = selabel_lookup_raw(label_hnd, &fcon, newpath, mode); + free(cwd); + free(newpath); + } + + if (r == 0) + r = setfscreatecon(fcon); + + if ((r < 0) && (errno != ENOENT)) { + log_error("Failed to set security context %s for %s", fcon, path); + + if (security_getenforce() == 1) + goto finish; + } + } + r = mkdir(path, mode); + +finish: + if (use_selinux()) { + setfscreatecon(NULL); + freecon(fcon); + } + + return r; +#else + return mkdir(path, mode); +#endif +} + bool streq_ptr(const char *a, const char *b) { /* Like streq(), but tries to make sense of NULL pointers */ @@ -969,7 +1207,7 @@ char *file_in_same_dir(const char *path, const char *filename) { int safe_mkdir(const char *path, mode_t mode, uid_t uid, gid_t gid) { struct stat st; - if (mkdir(path, mode) >= 0) + if (label_mkdir(path, mode) >= 0) if (chmod_and_chown(path, mode, uid, gid) < 0) return -errno; @@ -1012,7 +1250,7 @@ int mkdir_parents(const char *path, mode_t mode) { if (!(t = strndup(path, e - path))) return -ENOMEM; - r = mkdir(t, mode); + r = label_mkdir(t, mode); free(t); if (r < 0 && errno != EEXIST) @@ -1028,7 +1266,7 @@ int mkdir_p(const char *path, mode_t mode) { if ((r = mkdir_parents(path, mode)) < 0) return r; - if (mkdir(path, mode) < 0 && errno != EEXIST) + if (label_mkdir(path, mode) < 0 && errno != EEXIST) return -errno; return 0; |