summaryrefslogtreecommitdiffstats
path: root/README.md
AgeCommit message (Expand)AuthorFilesLines
2019-05-13Fix the headline of meta-agl document.Li Xiaoming1-2/+2
2018-08-01Remove porter reference from meta-aglRonan Le Martret1-54/+33
2018-01-23bblayers.conf: Remove meta-ruby and meta-efl layerChanghyeok Bae1-1/+0
2017-03-03Add dependency to imagesRonan1-4/+2
2016-12-05Merge meta-agl-security into meta-aglStephane Desneux1-4/+0
2016-08-05Rewrite and restructure readme filesJan-Simon Moeller1-272/+97
2015-10-02Reworking packagegroups of AGL DistributionTadao Tanikawa1-24/+24
2015-09-22Update layer dependencies and build instructionsTadao Tanikawa1-22/+108
2015-08-19Add new Yocto layer for common packages to IVI systemsTadao Tanikawa1-6/+14
2015-08-14Update commit id for meta-renesas in README.md0.2015.33Tadao Tanikawa1-2/+2
2015-08-08Appended more detailed build procedure for R-Car M2 porter boardTadao Tanikawa1-27/+103
2015-08-07Support R-Car M2 porter boardTadao Tanikawa1-2/+83
2015-07-23Fix typo in README.mdTadao Tanikawa1-1/+1
2015-07-22Fix line feed code README.mdTadao Tanikawa1-87/+87
2015-07-22Mini-manual of `meta-agl`Tadao Tanikawa1-0/+87
id='n261' href='#n261'>261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 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