From 4572046d03020004065dbe8e5161a86bafb423a8 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Tue, 6 Jun 2017 15:30:09 +0100 Subject: [PATCH 2/4] sysdeps: Add a cached accessor for our own Linux security label Signed-off-by: Simon McVittie --- dbus/dbus-credentials.h | 1 + dbus/dbus-sysdeps-unix.c | 9 +++--- dbus/dbus-sysdeps-unix.h | 4 +++ dbus/dbus-sysdeps-util-unix.c | 69 +++++++++++++++++++++++++++++++++++++++++++ dbus/dbus-sysdeps-util-win.c | 14 +++++++++ dbus/dbus-sysdeps.h | 2 ++ 6 files changed, 95 insertions(+), 4 deletions(-) diff --git a/dbus/dbus-credentials.h b/dbus/dbus-credentials.h index 6bf6c2b1..3284a3fe 100644 --- a/dbus/dbus-credentials.h +++ b/dbus/dbus-credentials.h @@ -69,6 +69,7 @@ DBUS_PRIVATE_EXPORT dbus_uid_t _dbus_credentials_get_unix_uid (DBusCredentials *credentials); DBUS_PRIVATE_EXPORT const char* _dbus_credentials_get_windows_sid (DBusCredentials *credentials); +DBUS_PRIVATE_EXPORT const char * _dbus_credentials_get_linux_security_label (DBusCredentials *credentials); void * _dbus_credentials_get_adt_audit_data (DBusCredentials *credentials); dbus_int32_t _dbus_credentials_get_adt_audit_data_size (DBusCredentials *credentials); diff --git a/dbus/dbus-sysdeps-unix.c b/dbus/dbus-sysdeps-unix.c index 8b6ac306..d0a54d8d 100644 --- a/dbus/dbus-sysdeps-unix.c +++ b/dbus/dbus-sysdeps-unix.c @@ -1746,9 +1746,9 @@ write_credentials_byte (int server_fd, } /* return FALSE on OOM, TRUE otherwise, even if no credentials were found */ -static dbus_bool_t -add_linux_security_label_to_credentials (int client_fd, - DBusCredentials *credentials) +dbus_bool_t +_dbus_add_linux_security_label_to_credentials (int client_fd, + DBusCredentials *credentials) { #if defined(__linux__) && defined(SO_PEERSEC) DBusString buf; @@ -2171,7 +2171,8 @@ _dbus_read_credentials_socket (DBusSocket client_fd, } } - if (!add_linux_security_label_to_credentials (client_fd.fd, credentials)) + if (!_dbus_add_linux_security_label_to_credentials (client_fd.fd, + credentials)) { _DBUS_SET_OOM (error); return FALSE; diff --git a/dbus/dbus-sysdeps-unix.h b/dbus/dbus-sysdeps-unix.h index 279cae27..3afcb0c3 100644 --- a/dbus/dbus-sysdeps-unix.h +++ b/dbus/dbus-sysdeps-unix.h @@ -165,6 +165,10 @@ DBUS_PRIVATE_EXPORT dbus_bool_t _dbus_ensure_standard_fds (DBusEnsureStandardFdsFlags flags, const char **error_str_p); +DBUS_PRIVATE_EXPORT +dbus_bool_t _dbus_add_linux_security_label_to_credentials (int client_fd, + DBusCredentials *credentials); + /** @} */ DBUS_END_DECLS diff --git a/dbus/dbus-sysdeps-util-unix.c b/dbus/dbus-sysdeps-util-unix.c index 5d08c0ba..58f34b10 100644 --- a/dbus/dbus-sysdeps-util-unix.c +++ b/dbus/dbus-sysdeps-util-unix.c @@ -25,6 +25,8 @@ #include #include "dbus-sysdeps.h" #include "dbus-sysdeps-unix.h" + +#include "dbus-credentials.h" #include "dbus-internals.h" #include "dbus-list.h" #include "dbus-pipe.h" @@ -1509,3 +1511,70 @@ _dbus_get_session_config_file (DBusString *str) return _dbus_string_append (str, DBUS_SESSION_CONFIG_FILE); } + +/** + * Copy the Linux security label of this process. This is NULL on all + * non-Linux platforms, and on Linux if no LSM is in use. + * + * @returns #FALSE if no memory + */ +dbus_bool_t +_dbus_get_self_linux_security_label (const char **label_p) +{ +#ifdef __linux__ + static DBusCredentials *credentials; +#endif + + _dbus_assert (label_p != NULL); + *label_p = NULL; + +#ifdef __linux__ + if (credentials == NULL) + { + int socks[2]; + + credentials = _dbus_credentials_new (); + + if (credentials == NULL) + return FALSE; + + /* + * Reading from /proc/self/attr/current seems appealing, but it has + * some problems: + * + * - Under AppArmor, it has a trailing newline, which is not consistent + * with the result of getsockopt(., SOL_SOCKET, SO_PEERSEC, ...); + * and in general we want to guarantee that we return exactly the + * same thing as that getsockopt + * - Pseudo-files in /proc have size 0 according to stat, with which + * _dbus_file_get_contents() is not compatible + * + * But we already know how to get this information from a socket + * with getsockopt(), so cheat and do it that way... + */ + + /* If we can't make a socket to ourselves, assume we have no special + * credentials */ + if (socketpair (AF_UNIX, SOCK_STREAM, 0, socks) != 0) + return TRUE; + + _dbus_fd_set_close_on_exec (socks[0]); + _dbus_fd_set_close_on_exec (socks[1]); + + if (!_dbus_add_linux_security_label_to_credentials (socks[0], + credentials)) + { + close (socks[0]); + close (socks[1]); + return FALSE; + } + + close (socks[0]); + close (socks[1]); + } + + *label_p = _dbus_credentials_get_linux_security_label (credentials); +#endif + + return TRUE; +} diff --git a/dbus/dbus-sysdeps-util-win.c b/dbus/dbus-sysdeps-util-win.c index 05bd976d..61ae4d3d 100644 --- a/dbus/dbus-sysdeps-util-win.c +++ b/dbus/dbus-sysdeps-util-win.c @@ -1666,3 +1666,17 @@ _dbus_get_session_config_file (DBusString *str) return _dbus_get_config_file_name(str, "session.conf"); } + +/** + * Get the Linux security label of this process. This is NULL on all + * non-Linux platforms, and on Linux if no LSM is in use. + * + * @returns #FALSE if no memory + */ +dbus_bool_t +_dbus_get_self_linux_security_label (const char **label_p) +{ + _dbus_assert (label_p != NULL); + *label_p = NULL; + return TRUE; +} diff --git a/dbus/dbus-sysdeps.h b/dbus/dbus-sysdeps.h index 5ed4c45e..39d917e1 100644 --- a/dbus/dbus-sysdeps.h +++ b/dbus/dbus-sysdeps.h @@ -683,6 +683,8 @@ dbus_bool_t _dbus_rlimit_restore_fd_limit (DBusRLimit *saved, DBusError *error); void _dbus_rlimit_free (DBusRLimit *lim); +dbus_bool_t _dbus_get_self_linux_security_label (const char **label); + /** @} */ DBUS_END_DECLS -- 2.11.0