summaryrefslogtreecommitdiffstats
path: root/meta-security/recipes-core/dbus-cynara/dbus-cynara/0003-Add-LSM-agnostic-support-for-LinuxSecurityLabel-cred.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-security/recipes-core/dbus-cynara/dbus-cynara/0003-Add-LSM-agnostic-support-for-LinuxSecurityLabel-cred.patch')
-rw-r--r--meta-security/recipes-core/dbus-cynara/dbus-cynara/0003-Add-LSM-agnostic-support-for-LinuxSecurityLabel-cred.patch515
1 files changed, 515 insertions, 0 deletions
diff --git a/meta-security/recipes-core/dbus-cynara/dbus-cynara/0003-Add-LSM-agnostic-support-for-LinuxSecurityLabel-cred.patch b/meta-security/recipes-core/dbus-cynara/dbus-cynara/0003-Add-LSM-agnostic-support-for-LinuxSecurityLabel-cred.patch
new file mode 100644
index 000000000..fcb85504d
--- /dev/null
+++ b/meta-security/recipes-core/dbus-cynara/dbus-cynara/0003-Add-LSM-agnostic-support-for-LinuxSecurityLabel-cred.patch
@@ -0,0 +1,515 @@
+From 9da49d4eb6982c659fec988231baef8cd1b05be2 Mon Sep 17 00:00:00 2001
+From: Simon McVittie <simon.mcvittie@collabora.co.uk>
+Date: Wed, 11 Feb 2015 13:19:15 +0000
+Subject: [PATCH 3/8] Add LSM-agnostic support for LinuxSecurityLabel
+ credential
+
+Bug: https://bugs.freedesktop.org/show_bug.cgi?id=89041
+Change-Id: I70512843d1a7661c87461b1b6d86fbfbda934ad5
+Reviewed-by: Philip Withnall <philip.withnall@collabora.co.uk>
+Acked-by: Stephen Smalley <sds@tycho.nsa.gov> (for SELinux)
+Acked-by: John Johansen <john.johansen@canonical.com> (for AppArmor)
+Acked-by: Casey Schaufler <casey@schaufler-ca.com> (for Smack)
+Tested-by: Tyler Hicks <tyhicks@canonical.com>
+---
+ bus/driver.c | 19 ++++++++
+ dbus/dbus-auth.c | 11 +++--
+ dbus/dbus-connection-internal.h | 3 ++
+ dbus/dbus-connection.c | 26 ++++++++++
+ dbus/dbus-credentials.c | 68 ++++++++++++++++++++++++++
+ dbus/dbus-credentials.h | 4 ++
+ dbus/dbus-sysdeps-unix.c | 105 ++++++++++++++++++++++++++++++++++++++++
+ dbus/dbus-transport.c | 27 +++++++++++
+ dbus/dbus-transport.h | 3 ++
+ 9 files changed, 262 insertions(+), 4 deletions(-)
+
+diff --git a/bus/driver.c b/bus/driver.c
+index 888c7ca..11706f8 100644
+--- a/bus/driver.c
++++ b/bus/driver.c
+@@ -34,6 +34,7 @@
+ #include "utils.h"
+
+ #include <dbus/dbus-asv-util.h>
++#include <dbus/dbus-connection-internal.h>
+ #include <dbus/dbus-string.h>
+ #include <dbus/dbus-internals.h>
+ #include <dbus/dbus-message.h>
+@@ -1567,6 +1568,7 @@ bus_driver_handle_get_connection_credentials (DBusConnection *connection,
+ DBusMessageIter reply_iter;
+ DBusMessageIter array_iter;
+ unsigned long ulong_val;
++ char *s;
+ const char *service;
+
+ _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+@@ -1601,6 +1603,23 @@ bus_driver_handle_get_connection_credentials (DBusConnection *connection,
+ goto oom;
+ }
+
++ if (_dbus_connection_get_linux_security_label (conn, &s))
++ {
++ if (s == NULL)
++ goto oom;
++
++ /* use the GVariant bytestring convention for strings of unknown
++ * encoding: include the \0 in the payload, for zero-copy reading */
++ if (!_dbus_asv_add_byte_array (&array_iter, "LinuxSecurityLabel",
++ s, strlen (s) + 1))
++ {
++ dbus_free (s);
++ goto oom;
++ }
++
++ dbus_free (s);
++ }
++
+ if (!_dbus_asv_close (&reply_iter, &array_iter))
+ goto oom;
+
+diff --git a/dbus/dbus-auth.c b/dbus/dbus-auth.c
+index 6a07665..aee877d 100644
+--- a/dbus/dbus-auth.c
++++ b/dbus/dbus-auth.c
+@@ -1102,20 +1102,23 @@ handle_server_data_external_mech (DBusAuth *auth,
+ auth->desired_identity))
+ return FALSE;
+
+- /* also copy process ID from the socket credentials
++ /* also copy misc process info from the socket credentials
+ */
+ if (!_dbus_credentials_add_credential (auth->authorized_identity,
+ DBUS_CREDENTIAL_UNIX_PROCESS_ID,
+ auth->credentials))
+ return FALSE;
+
+- /* also copy audit data from the socket credentials
+- */
+ if (!_dbus_credentials_add_credential (auth->authorized_identity,
+ DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID,
+ auth->credentials))
+ return FALSE;
+-
++
++ if (!_dbus_credentials_add_credential (auth->authorized_identity,
++ DBUS_CREDENTIAL_LINUX_SECURITY_LABEL,
++ auth->credentials))
++ return FALSE;
++
+ if (!send_ok (auth))
+ return FALSE;
+
+diff --git a/dbus/dbus-connection-internal.h b/dbus/dbus-connection-internal.h
+index 2897404..64ef336 100644
+--- a/dbus/dbus-connection-internal.h
++++ b/dbus/dbus-connection-internal.h
+@@ -107,6 +107,9 @@ void _dbus_connection_set_pending_fds_function (DBusConnectio
+ DBusPendingFdsChangeFunction callback,
+ void *data);
+
++dbus_bool_t _dbus_connection_get_linux_security_label (DBusConnection *connection,
++ char **label_p);
++
+ /* if DBUS_ENABLE_STATS */
+ void _dbus_connection_get_stats (DBusConnection *connection,
+ dbus_uint32_t *in_messages,
+diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c
+index b574207..8952b75 100644
+--- a/dbus/dbus-connection.c
++++ b/dbus/dbus-connection.c
+@@ -5322,6 +5322,32 @@ dbus_connection_set_unix_user_function (DBusConnection *connection,
+ (* old_free_function) (old_data);
+ }
+
++/* Same calling convention as dbus_connection_get_windows_user */
++dbus_bool_t
++_dbus_connection_get_linux_security_label (DBusConnection *connection,
++ char **label_p)
++{
++ dbus_bool_t result;
++
++ _dbus_assert (connection != NULL);
++ _dbus_assert (label_p != NULL);
++
++ CONNECTION_LOCK (connection);
++
++ if (!_dbus_transport_try_to_authenticate (connection->transport))
++ result = FALSE;
++ else
++ result = _dbus_transport_get_linux_security_label (connection->transport,
++ label_p);
++#ifndef __linux__
++ _dbus_assert (!result);
++#endif
++
++ CONNECTION_UNLOCK (connection);
++
++ return result;
++}
++
+ /**
+ * Gets the Windows user SID of the connection if known. Returns
+ * #TRUE if the ID is filled in. Always returns #FALSE on non-Windows
+diff --git a/dbus/dbus-credentials.c b/dbus/dbus-credentials.c
+index 7325125..151bb00 100644
+--- a/dbus/dbus-credentials.c
++++ b/dbus/dbus-credentials.c
+@@ -50,6 +50,7 @@ struct DBusCredentials {
+ dbus_uid_t unix_uid;
+ dbus_pid_t pid;
+ char *windows_sid;
++ char *linux_security_label;
+ void *adt_audit_data;
+ dbus_int32_t adt_audit_data_size;
+ };
+@@ -79,6 +80,7 @@ _dbus_credentials_new (void)
+ creds->unix_uid = DBUS_UID_UNSET;
+ creds->pid = DBUS_PID_UNSET;
+ creds->windows_sid = NULL;
++ creds->linux_security_label = NULL;
+ creds->adt_audit_data = NULL;
+ creds->adt_audit_data_size = 0;
+
+@@ -133,6 +135,7 @@ _dbus_credentials_unref (DBusCredentials *credentials)
+ if (credentials->refcount == 0)
+ {
+ dbus_free (credentials->windows_sid);
++ dbus_free (credentials->linux_security_label);
+ dbus_free (credentials->adt_audit_data);
+ dbus_free (credentials);
+ }
+@@ -193,6 +196,30 @@ _dbus_credentials_add_windows_sid (DBusCredentials *credentials,
+ }
+
+ /**
++ * Add a Linux security label, as used by LSMs such as SELinux, Smack and
++ * AppArmor, to the credentials.
++ *
++ * @param credentials the object
++ * @param label the label
++ * @returns #FALSE if no memory
++ */
++dbus_bool_t
++_dbus_credentials_add_linux_security_label (DBusCredentials *credentials,
++ const char *label)
++{
++ char *copy;
++
++ copy = _dbus_strdup (label);
++ if (copy == NULL)
++ return FALSE;
++
++ dbus_free (credentials->linux_security_label);
++ credentials->linux_security_label = copy;
++
++ return TRUE;
++}
++
++/**
+ * Add ADT audit data to the credentials.
+ *
+ * @param credentials the object
+@@ -236,6 +263,8 @@ _dbus_credentials_include (DBusCredentials *credentials,
+ return credentials->unix_uid != DBUS_UID_UNSET;
+ case DBUS_CREDENTIAL_WINDOWS_SID:
+ return credentials->windows_sid != NULL;
++ case DBUS_CREDENTIAL_LINUX_SECURITY_LABEL:
++ return credentials->linux_security_label != NULL;
+ case DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID:
+ return credentials->adt_audit_data != NULL;
+ }
+@@ -284,6 +313,19 @@ _dbus_credentials_get_windows_sid (DBusCredentials *credentials)
+ }
+
+ /**
++ * Gets the Linux security label (as used by LSMs) from the credentials,
++ * or #NULL if the credentials object doesn't contain a security label.
++ *
++ * @param credentials the object
++ * @returns the security label
++ */
++const char *
++_dbus_credentials_get_linux_security_label (DBusCredentials *credentials)
++{
++ return credentials->linux_security_label;
++}
++
++/**
+ * Gets the ADT audit data in the credentials, or #NULL if
+ * the credentials object doesn't contain ADT audit data.
+ *
+@@ -329,6 +371,10 @@ _dbus_credentials_are_superset (DBusCredentials *credentials,
+ (possible_subset->windows_sid == NULL ||
+ (credentials->windows_sid && strcmp (possible_subset->windows_sid,
+ credentials->windows_sid) == 0)) &&
++ (possible_subset->linux_security_label == NULL ||
++ (credentials->linux_security_label != NULL &&
++ strcmp (possible_subset->linux_security_label,
++ credentials->linux_security_label) == 0)) &&
+ (possible_subset->adt_audit_data == NULL ||
+ (credentials->adt_audit_data && memcmp (possible_subset->adt_audit_data,
+ credentials->adt_audit_data,
+@@ -348,6 +394,7 @@ _dbus_credentials_are_empty (DBusCredentials *credentials)
+ credentials->pid == DBUS_PID_UNSET &&
+ credentials->unix_uid == DBUS_UID_UNSET &&
+ credentials->windows_sid == NULL &&
++ credentials->linux_security_label == NULL &&
+ credentials->adt_audit_data == NULL;
+ }
+
+@@ -388,6 +435,9 @@ _dbus_credentials_add_credentials (DBusCredentials *credentials,
+ DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID,
+ other_credentials) &&
+ _dbus_credentials_add_credential (credentials,
++ DBUS_CREDENTIAL_LINUX_SECURITY_LABEL,
++ other_credentials) &&
++ _dbus_credentials_add_credential (credentials,
+ DBUS_CREDENTIAL_WINDOWS_SID,
+ other_credentials);
+ }
+@@ -427,6 +477,13 @@ _dbus_credentials_add_credential (DBusCredentials *credentials,
+ if (!_dbus_credentials_add_windows_sid (credentials, other_credentials->windows_sid))
+ return FALSE;
+ }
++ else if (which == DBUS_CREDENTIAL_LINUX_SECURITY_LABEL &&
++ other_credentials->linux_security_label != NULL)
++ {
++ if (!_dbus_credentials_add_linux_security_label (credentials,
++ other_credentials->linux_security_label))
++ return FALSE;
++ }
+ else if (which == DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID &&
+ other_credentials->adt_audit_data != NULL)
+ {
+@@ -449,6 +506,8 @@ _dbus_credentials_clear (DBusCredentials *credentials)
+ credentials->unix_uid = DBUS_UID_UNSET;
+ dbus_free (credentials->windows_sid);
+ credentials->windows_sid = NULL;
++ dbus_free (credentials->linux_security_label);
++ credentials->linux_security_label = NULL;
+ dbus_free (credentials->adt_audit_data);
+ credentials->adt_audit_data = NULL;
+ credentials->adt_audit_data_size = 0;
+@@ -540,6 +599,15 @@ _dbus_credentials_to_string_append (DBusCredentials *credentials,
+ else
+ join = FALSE;
+
++ if (credentials->linux_security_label != NULL)
++ {
++ if (!_dbus_string_append_printf (string, "%slsm='%s'",
++ join ? " " : "",
++ credentials->linux_security_label))
++ goto oom;
++ join = TRUE;
++ }
++
+ return TRUE;
+ oom:
+ return FALSE;
+diff --git a/dbus/dbus-credentials.h b/dbus/dbus-credentials.h
+index abcc4bb..ab74eac 100644
+--- a/dbus/dbus-credentials.h
++++ b/dbus/dbus-credentials.h
+@@ -34,6 +34,7 @@ typedef enum {
+ DBUS_CREDENTIAL_UNIX_PROCESS_ID,
+ DBUS_CREDENTIAL_UNIX_USER_ID,
+ DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID,
++ DBUS_CREDENTIAL_LINUX_SECURITY_LABEL,
+ DBUS_CREDENTIAL_WINDOWS_SID
+ } DBusCredentialType;
+
+@@ -47,6 +48,8 @@ dbus_bool_t _dbus_credentials_add_unix_uid (DBusCredentials
+ dbus_uid_t uid);
+ dbus_bool_t _dbus_credentials_add_windows_sid (DBusCredentials *credentials,
+ const char *windows_sid);
++dbus_bool_t _dbus_credentials_add_linux_security_label (DBusCredentials *credentials,
++ const char *label);
+ dbus_bool_t _dbus_credentials_add_adt_audit_data (DBusCredentials *credentials,
+ void *audit_data,
+ dbus_int32_t size);
+@@ -55,6 +58,7 @@ dbus_bool_t _dbus_credentials_include (DBusCredentials
+ dbus_pid_t _dbus_credentials_get_pid (DBusCredentials *credentials);
+ dbus_uid_t _dbus_credentials_get_unix_uid (DBusCredentials *credentials);
+ const char* _dbus_credentials_get_windows_sid (DBusCredentials *credentials);
++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);
+ dbus_bool_t _dbus_credentials_are_superset (DBusCredentials *credentials,
+diff --git a/dbus/dbus-sysdeps-unix.c b/dbus/dbus-sysdeps-unix.c
+index fe891ab..61af423 100644
+--- a/dbus/dbus-sysdeps-unix.c
++++ b/dbus/dbus-sysdeps-unix.c
+@@ -1639,6 +1639,105 @@ 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)
++{
++#if defined(__linux__) && defined(SO_PEERSEC)
++ DBusString buf;
++ socklen_t len = 1024;
++ dbus_bool_t oom = FALSE;
++
++ if (!_dbus_string_init_preallocated (&buf, len) ||
++ !_dbus_string_set_length (&buf, len))
++ return FALSE;
++
++ while (getsockopt (client_fd, SOL_SOCKET, SO_PEERSEC,
++ _dbus_string_get_data (&buf), &len) < 0)
++ {
++ int e = errno;
++
++ _dbus_verbose ("getsockopt failed with %s, len now %lu\n",
++ _dbus_strerror (e), (unsigned long) len);
++
++ if (e != ERANGE || len <= _dbus_string_get_length (&buf))
++ {
++ _dbus_verbose ("Failed to getsockopt(SO_PEERSEC): %s\n",
++ _dbus_strerror (e));
++ goto out;
++ }
++
++ /* If not enough space, len is updated to be enough.
++ * Try again with a large enough buffer. */
++ if (!_dbus_string_set_length (&buf, len))
++ {
++ oom = TRUE;
++ goto out;
++ }
++
++ _dbus_verbose ("will try again with %lu\n", (unsigned long) len);
++ }
++
++ if (len <= 0)
++ {
++ _dbus_verbose ("getsockopt(SO_PEERSEC) yielded <= 0 bytes: %lu\n",
++ (unsigned long) len);
++ goto out;
++ }
++
++ if (len > _dbus_string_get_length (&buf))
++ {
++ _dbus_verbose ("%lu > %d", (unsigned long) len,
++ _dbus_string_get_length (&buf));
++ _dbus_assert_not_reached ("getsockopt(SO_PEERSEC) overflowed");
++ }
++
++ if (_dbus_string_get_byte (&buf, len - 1) == 0)
++ {
++ /* the kernel included the trailing \0 in its count,
++ * but DBusString always has an extra \0 after the data anyway */
++ _dbus_verbose ("subtracting trailing \\0\n");
++ len--;
++ }
++
++ if (!_dbus_string_set_length (&buf, len))
++ {
++ _dbus_assert_not_reached ("shortening string should not lead to OOM");
++ oom = TRUE;
++ goto out;
++ }
++
++ if (strlen (_dbus_string_get_const_data (&buf)) != len)
++ {
++ /* LSM people on the linux-security-module@ mailing list say this
++ * should never happen: the label should be a bytestring with
++ * an optional trailing \0 */
++ _dbus_verbose ("security label from kernel had an embedded \\0, "
++ "ignoring it\n");
++ goto out;
++ }
++
++ _dbus_verbose ("getsockopt(SO_PEERSEC): %lu bytes excluding \\0: %s\n",
++ (unsigned long) len,
++ _dbus_string_get_const_data (&buf));
++
++ if (!_dbus_credentials_add_linux_security_label (credentials,
++ _dbus_string_get_const_data (&buf)))
++ {
++ oom = TRUE;
++ goto out;
++ }
++
++out:
++ _dbus_string_free (&buf);
++ return !oom;
++#else
++ /* no error */
++ return TRUE;
++#endif
++}
++
+ /**
+ * Reads a single byte which must be nul (an error occurs otherwise),
+ * and reads unix credentials if available. Clears the credentials
+@@ -1922,6 +2021,12 @@ _dbus_read_credentials_socket (int client_fd,
+ }
+ }
+
++ if (!add_linux_security_label_to_credentials (client_fd, credentials))
++ {
++ _DBUS_SET_OOM (error);
++ return FALSE;
++ }
++
+ return TRUE;
+ }
+
+diff --git a/dbus/dbus-transport.c b/dbus/dbus-transport.c
+index e9dcc56..a43e7bb 100644
+--- a/dbus/dbus-transport.c
++++ b/dbus/dbus-transport.c
+@@ -1425,6 +1425,33 @@ _dbus_transport_set_unix_user_function (DBusTransport *transport,
+ transport->free_unix_user_data = free_data_function;
+ }
+
++dbus_bool_t
++_dbus_transport_get_linux_security_label (DBusTransport *transport,
++ char **label_p)
++{
++ DBusCredentials *auth_identity;
++
++ *label_p = NULL;
++
++ if (!transport->authenticated)
++ return FALSE;
++
++ auth_identity = _dbus_auth_get_identity (transport->auth);
++
++ if (_dbus_credentials_include (auth_identity,
++ DBUS_CREDENTIAL_LINUX_SECURITY_LABEL))
++ {
++ /* If no memory, we are supposed to return TRUE and set NULL */
++ *label_p = _dbus_strdup (_dbus_credentials_get_linux_security_label (auth_identity));
++
++ return TRUE;
++ }
++ else
++ {
++ return FALSE;
++ }
++}
++
+ /**
+ * See dbus_connection_get_windows_user().
+ *
+diff --git a/dbus/dbus-transport.h b/dbus/dbus-transport.h
+index 39c74c4..843f231 100644
+--- a/dbus/dbus-transport.h
++++ b/dbus/dbus-transport.h
+@@ -87,6 +87,9 @@ void _dbus_transport_set_unix_user_function (DBusTransport
+ DBusFreeFunction *old_free_data_function);
+ dbus_bool_t _dbus_transport_get_windows_user (DBusTransport *transport,
+ char **windows_sid_p);
++dbus_bool_t _dbus_transport_get_linux_security_label (DBusTransport *transport,
++ char **label_p);
++
+ void _dbus_transport_set_windows_user_function (DBusTransport *transport,
+ DBusAllowWindowsUserFunction function,
+ void *data,
+--
+2.1.4
+