mirror of
https://gitlab.freedesktop.org/dbus/dbus.git
synced 2026-04-14 05:20:39 +02:00
Merge branch 'containers-minimum-101354'
Add experimental support for creating extra servers at runtime, to be used by app containers like Flatpak or Snap. This API is still subject to change and is not compiled in by default. Bug: https://bugs.freedesktop.org/show_bug.cgi?id=101354
This commit is contained in:
commit
065e2249ac
30 changed files with 4013 additions and 32 deletions
8
NEWS
8
NEWS
|
|
@ -8,6 +8,11 @@ a 1.14.0 stable release at an unspecified point in the future.
|
|||
|
||||
Enhancements:
|
||||
|
||||
• Add experimental support for creating extra servers at runtime, to
|
||||
be used by app containers like Flatpak or Snap. This API is still
|
||||
subject to change and is not compiled in by default.
|
||||
(fd.o #101354, Simon McVittie)
|
||||
|
||||
• Improve automated test logging (fd.o #103601, Simon McVittie)
|
||||
|
||||
Fixes:
|
||||
|
|
@ -32,9 +37,6 @@ Fixes:
|
|||
|
||||
Internal changes:
|
||||
|
||||
• Preparations for future support for restricted sockets used by
|
||||
app containers like Flatpak (fd.o #101354, Simon McVittie)
|
||||
|
||||
• Harden the nonce-tcp: transport against resource leaks and
|
||||
use-after-free (fd.o #103597, Simon McVittie)
|
||||
|
||||
|
|
|
|||
|
|
@ -117,6 +117,9 @@ DBUS_ENABLE_DOXYGEN_DOCS:BOOL=OFF
|
|||
// enable bus daemon usage statistics
|
||||
DBUS_ENABLE_STATS:BOOL=OFF
|
||||
|
||||
// enable restricted servers for app containers
|
||||
DBUS_ENABLE_CONTAINERS:BOOL=OFF
|
||||
|
||||
// support verbose debug mode
|
||||
DBUS_ENABLE_VERBOSE_MODE:BOOL=ON
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ AM_CPPFLAGS = \
|
|||
$(EXPAT_CFLAGS) \
|
||||
$(APPARMOR_CFLAGS) \
|
||||
-DDBUS_SYSTEM_CONFIG_FILE=\""$(dbusdatadir)/system.conf"\" \
|
||||
-DDBUS_RUNSTATEDIR=\""$(runstatedir)"\" \
|
||||
-DDBUS_COMPILATION \
|
||||
$(NULL)
|
||||
|
||||
|
|
@ -97,6 +98,8 @@ BUS_SOURCES= \
|
|||
config-parser-common.h \
|
||||
connection.c \
|
||||
connection.h \
|
||||
containers.c \
|
||||
containers.h \
|
||||
desktop-file.c \
|
||||
desktop-file.h \
|
||||
$(DIR_WATCH_SOURCE) \
|
||||
|
|
|
|||
84
bus/bus.c
84
bus/bus.c
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
#include "activation.h"
|
||||
#include "connection.h"
|
||||
#include "containers.h"
|
||||
#include "services.h"
|
||||
#include "utils.h"
|
||||
#include "policy.h"
|
||||
|
|
@ -69,6 +70,7 @@ struct BusContext
|
|||
BusMatchmaker *matchmaker;
|
||||
BusLimits limits;
|
||||
DBusRLimit *initial_fd_limit;
|
||||
BusContainers *containers;
|
||||
unsigned int fork : 1;
|
||||
unsigned int syslog : 1;
|
||||
unsigned int keep_umask : 1;
|
||||
|
|
@ -100,7 +102,8 @@ server_get_context (DBusServer *server)
|
|||
|
||||
bd = BUS_SERVER_DATA (server);
|
||||
|
||||
/* every DBusServer in the dbus-daemon has gone through setup_server() */
|
||||
/* every DBusServer in the dbus-daemon's main loop has gone through
|
||||
* bus_context_setup_server() */
|
||||
_dbus_assert (bd != NULL);
|
||||
|
||||
context = bd->context;
|
||||
|
|
@ -173,8 +176,14 @@ new_connection_callback (DBusServer *server,
|
|||
DBusConnection *new_connection,
|
||||
void *data)
|
||||
{
|
||||
BusContext *context = data;
|
||||
/* If this fails it logs a warning, so we don't need to do that */
|
||||
bus_context_add_incoming_connection (data, new_connection);
|
||||
}
|
||||
|
||||
dbus_bool_t
|
||||
bus_context_add_incoming_connection (BusContext *context,
|
||||
DBusConnection *new_connection)
|
||||
{
|
||||
/* If this fails it logs a warning, so we don't need to do that */
|
||||
if (!bus_connections_setup_connection (context->connections, new_connection))
|
||||
{
|
||||
|
|
@ -184,6 +193,8 @@ new_connection_callback (DBusServer *server,
|
|||
* in general.
|
||||
*/
|
||||
dbus_connection_close (new_connection);
|
||||
/* on OOM, we won't have ref'd the connection so it will die. */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
dbus_connection_set_max_received_size (new_connection,
|
||||
|
|
@ -201,7 +212,7 @@ new_connection_callback (DBusServer *server,
|
|||
dbus_connection_set_allow_anonymous (new_connection,
|
||||
context->allow_anonymous);
|
||||
|
||||
/* on OOM, we won't have ref'd the connection so it will die. */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -217,6 +228,25 @@ setup_server (BusContext *context,
|
|||
DBusServer *server,
|
||||
char **auth_mechanisms,
|
||||
DBusError *error)
|
||||
{
|
||||
if (!bus_context_setup_server (context, server, error))
|
||||
return FALSE;
|
||||
|
||||
if (!dbus_server_set_auth_mechanisms (server, (const char**) auth_mechanisms))
|
||||
{
|
||||
BUS_SET_OOM (error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
dbus_server_set_new_connection_function (server, new_connection_callback,
|
||||
context, NULL);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
dbus_bool_t
|
||||
bus_context_setup_server (BusContext *context,
|
||||
DBusServer *server,
|
||||
DBusError *error)
|
||||
{
|
||||
BusServerData *bd;
|
||||
|
||||
|
|
@ -232,16 +262,6 @@ setup_server (BusContext *context,
|
|||
|
||||
bd->context = context;
|
||||
|
||||
if (!dbus_server_set_auth_mechanisms (server, (const char**) auth_mechanisms))
|
||||
{
|
||||
BUS_SET_OOM (error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
dbus_server_set_new_connection_function (server,
|
||||
new_connection_callback,
|
||||
context, NULL);
|
||||
|
||||
if (!dbus_server_set_watch_functions (server,
|
||||
add_server_watch,
|
||||
remove_server_watch,
|
||||
|
|
@ -887,6 +907,14 @@ bus_context_new (const DBusString *config_file,
|
|||
goto failed;
|
||||
}
|
||||
|
||||
context->containers = bus_containers_new ();
|
||||
|
||||
if (context->containers == NULL)
|
||||
{
|
||||
BUS_SET_OOM (error);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
/* check user before we fork */
|
||||
if (context->user != NULL)
|
||||
{
|
||||
|
|
@ -1102,6 +1130,9 @@ bus_context_shutdown (BusContext *context)
|
|||
|
||||
link = _dbus_list_get_next_link (&context->servers, link);
|
||||
}
|
||||
|
||||
if (context->containers != NULL)
|
||||
bus_containers_stop_listening (context->containers);
|
||||
}
|
||||
|
||||
BusContext *
|
||||
|
|
@ -1172,6 +1203,7 @@ bus_context_unref (BusContext *context)
|
|||
context->matchmaker = NULL;
|
||||
}
|
||||
|
||||
bus_clear_containers (&context->containers);
|
||||
dbus_free (context->config_file);
|
||||
dbus_free (context->log_prefix);
|
||||
dbus_free (context->type);
|
||||
|
|
@ -1282,6 +1314,12 @@ bus_context_get_policy (BusContext *context)
|
|||
return context->policy;
|
||||
}
|
||||
|
||||
BusContainers *
|
||||
bus_context_get_containers (BusContext *context)
|
||||
{
|
||||
return context->containers;
|
||||
}
|
||||
|
||||
BusClientPolicy*
|
||||
bus_context_create_client_policy (BusContext *context,
|
||||
DBusConnection *connection,
|
||||
|
|
@ -1359,6 +1397,26 @@ bus_context_get_reply_timeout (BusContext *context)
|
|||
return context->limits.reply_timeout;
|
||||
}
|
||||
|
||||
int bus_context_get_max_containers (BusContext *context)
|
||||
{
|
||||
return context->limits.max_containers;
|
||||
}
|
||||
|
||||
int bus_context_get_max_containers_per_user (BusContext *context)
|
||||
{
|
||||
return context->limits.max_containers_per_user;
|
||||
}
|
||||
|
||||
int bus_context_get_max_container_metadata_bytes (BusContext *context)
|
||||
{
|
||||
return context->limits.max_container_metadata_bytes;
|
||||
}
|
||||
|
||||
int bus_context_get_max_connections_per_container (BusContext *context)
|
||||
{
|
||||
return context->limits.max_connections_per_container;
|
||||
}
|
||||
|
||||
DBusRLimit *
|
||||
bus_context_get_initial_fd_limit (BusContext *context)
|
||||
{
|
||||
|
|
|
|||
15
bus/bus.h
15
bus/bus.h
|
|
@ -45,6 +45,7 @@ typedef struct BusTransaction BusTransaction;
|
|||
typedef struct BusMatchmaker BusMatchmaker;
|
||||
typedef struct BusMatchRule BusMatchRule;
|
||||
typedef struct BusActivationEntry BusActivationEntry;
|
||||
typedef struct BusContainers BusContainers;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
|
@ -65,6 +66,10 @@ typedef struct
|
|||
int max_match_rules_per_connection; /**< Max number of match rules for a single connection */
|
||||
int max_replies_per_connection; /**< Max number of replies that can be pending for each connection */
|
||||
int reply_timeout; /**< How long to wait before timing out a reply */
|
||||
int max_containers; /**< Max number of restricted servers for app-containers */
|
||||
int max_containers_per_user; /**< Max number of restricted servers for app-containers, per user */
|
||||
int max_connections_per_container; /**< Max number of connections per restricted server */
|
||||
int max_container_metadata_bytes; /**< Max number of bytes of metadata per restricted server */
|
||||
} BusLimits;
|
||||
|
||||
typedef enum
|
||||
|
|
@ -106,6 +111,7 @@ dbus_bool_t bus_context_allow_unix_user (BusContext
|
|||
dbus_bool_t bus_context_allow_windows_user (BusContext *context,
|
||||
const char *windows_sid);
|
||||
BusPolicy* bus_context_get_policy (BusContext *context);
|
||||
BusContainers *bus_context_get_containers (BusContext *context);
|
||||
|
||||
BusClientPolicy* bus_context_create_client_policy (BusContext *context,
|
||||
DBusConnection *connection,
|
||||
|
|
@ -121,6 +127,10 @@ int bus_context_get_max_services_per_connection (BusContext
|
|||
int bus_context_get_max_match_rules_per_connection (BusContext *context);
|
||||
int bus_context_get_max_replies_per_connection (BusContext *context);
|
||||
int bus_context_get_reply_timeout (BusContext *context);
|
||||
int bus_context_get_max_containers (BusContext *context);
|
||||
int bus_context_get_max_containers_per_user (BusContext *context);
|
||||
int bus_context_get_max_container_metadata_bytes (BusContext *context);
|
||||
int bus_context_get_max_connections_per_container (BusContext *context);
|
||||
DBusRLimit * bus_context_get_initial_fd_limit (BusContext *context);
|
||||
dbus_bool_t bus_context_get_using_syslog (BusContext *context);
|
||||
void bus_context_log (BusContext *context,
|
||||
|
|
@ -145,6 +155,11 @@ dbus_bool_t bus_context_check_security_policy (BusContext
|
|||
BusActivationEntry *activation_entry,
|
||||
DBusError *error);
|
||||
void bus_context_check_all_watches (BusContext *context);
|
||||
dbus_bool_t bus_context_setup_server (BusContext *context,
|
||||
DBusServer *server,
|
||||
DBusError *error);
|
||||
dbus_bool_t bus_context_add_incoming_connection (BusContext *context,
|
||||
DBusConnection *new_connection);
|
||||
|
||||
#ifdef DBUS_ENABLE_EMBEDDED_TESTS
|
||||
void bus_context_quiet_log_begin (BusContext *context);
|
||||
|
|
|
|||
|
|
@ -481,7 +481,10 @@ bus_config_parser_new (const DBusString *basedir,
|
|||
else
|
||||
{
|
||||
|
||||
/* Make up some numbers! woot! */
|
||||
/* Make up some numbers! woot!
|
||||
* Please keep these hard-coded values in sync with the comments
|
||||
* in bus/system.conf.in. */
|
||||
|
||||
parser->limits.max_incoming_bytes = _DBUS_ONE_MEGABYTE * 127;
|
||||
parser->limits.max_outgoing_bytes = _DBUS_ONE_MEGABYTE * 127;
|
||||
parser->limits.max_message_size = _DBUS_ONE_MEGABYTE * 32;
|
||||
|
|
@ -514,12 +517,21 @@ bus_config_parser_new (const DBusString *basedir,
|
|||
|
||||
parser->limits.max_incomplete_connections = 64;
|
||||
parser->limits.max_connections_per_user = 256;
|
||||
parser->limits.max_containers_per_user = 16;
|
||||
|
||||
/* Note that max_completed_connections / max_connections_per_user
|
||||
* is the number of users that would have to work together to
|
||||
* DOS all the other users.
|
||||
* DOS all the other users. The same applies to containers.
|
||||
*/
|
||||
parser->limits.max_completed_connections = 2048;
|
||||
parser->limits.max_containers = 512;
|
||||
/* Similarly max_connections_per_user / max_connections_per_container
|
||||
* is the number of app-containers per user that would have to work
|
||||
* together to DoS all the other processes of that user */
|
||||
parser->limits.max_connections_per_container = 8;
|
||||
/* Someone trying to do a denial of service attack can make us store
|
||||
* this much data per app-container */
|
||||
parser->limits.max_container_metadata_bytes = 4096;
|
||||
|
||||
parser->limits.max_pending_activations = 512;
|
||||
parser->limits.max_services_per_connection = 512;
|
||||
|
|
@ -2177,6 +2189,30 @@ set_limit (BusConfigParser *parser,
|
|||
must_be_int = TRUE;
|
||||
parser->limits.max_replies_per_connection = value;
|
||||
}
|
||||
else if (strcmp (name, "max_containers") == 0)
|
||||
{
|
||||
must_be_positive = TRUE;
|
||||
must_be_int = TRUE;
|
||||
parser->limits.max_containers = value;
|
||||
}
|
||||
else if (strcmp (name, "max_containers_per_user") == 0)
|
||||
{
|
||||
must_be_positive = TRUE;
|
||||
must_be_int = TRUE;
|
||||
parser->limits.max_containers_per_user = value;
|
||||
}
|
||||
else if (strcmp (name, "max_container_metadata_bytes") == 0)
|
||||
{
|
||||
must_be_positive = TRUE;
|
||||
must_be_int = TRUE;
|
||||
parser->limits.max_container_metadata_bytes = value;
|
||||
}
|
||||
else if (strcmp (name, "max_connections_per_container") == 0)
|
||||
{
|
||||
must_be_positive = TRUE;
|
||||
must_be_int = TRUE;
|
||||
parser->limits.max_connections_per_container = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
dbus_set_error (error, DBUS_ERROR_FAILED,
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@
|
|||
|
||||
#include <config.h>
|
||||
#include "connection.h"
|
||||
|
||||
#include "containers.h"
|
||||
#include "dispatch.h"
|
||||
#include "policy.h"
|
||||
#include "services.h"
|
||||
|
|
@ -306,6 +308,9 @@ bus_connection_disconnected (DBusConnection *connection)
|
|||
d->link_in_monitors = NULL;
|
||||
}
|
||||
|
||||
bus_containers_remove_connection (bus_context_get_containers (d->connections->context),
|
||||
connection);
|
||||
|
||||
if (d->link_in_connection_list != NULL)
|
||||
{
|
||||
if (d->name != NULL)
|
||||
|
|
@ -583,6 +588,9 @@ cache_peer_loginfo_string (BusConnectionData *d,
|
|||
unsigned long pid;
|
||||
char *windows_sid = NULL, *security_label = NULL;
|
||||
dbus_bool_t prev_added;
|
||||
const char *container = NULL;
|
||||
const char *container_type = NULL;
|
||||
const char *container_name = NULL;
|
||||
|
||||
if (!_dbus_string_init (&loginfo_buf))
|
||||
return FALSE;
|
||||
|
|
@ -654,6 +662,29 @@ cache_peer_loginfo_string (BusConnectionData *d,
|
|||
prev_added = TRUE;
|
||||
}
|
||||
|
||||
if (bus_containers_connection_is_contained (connection, &container,
|
||||
&container_type,
|
||||
&container_name))
|
||||
{
|
||||
dbus_bool_t did_append;
|
||||
|
||||
if (prev_added)
|
||||
{
|
||||
if (!_dbus_string_append_byte (&loginfo_buf, ' '))
|
||||
goto oom;
|
||||
}
|
||||
|
||||
did_append = _dbus_string_append_printf (&loginfo_buf,
|
||||
"container=%s %s=\"%s\")",
|
||||
container,
|
||||
container_type,
|
||||
container_name);
|
||||
if (!did_append)
|
||||
goto oom;
|
||||
else
|
||||
prev_added = TRUE;
|
||||
}
|
||||
|
||||
if (!_dbus_string_steal_data (&loginfo_buf, &(d->cached_loginfo_string)))
|
||||
goto oom;
|
||||
|
||||
|
|
|
|||
1392
bus/containers.c
Normal file
1392
bus/containers.c
Normal file
File diff suppressed because it is too large
Load diff
71
bus/containers.h
Normal file
71
bus/containers.h
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
/* containers.h - restricted bus servers for containers
|
||||
*
|
||||
* Copyright © 2017 Collabora Ltd.
|
||||
*
|
||||
* Licensed under the Academic Free License version 2.1
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef BUS_CONTAINERS_H
|
||||
#define BUS_CONTAINERS_H
|
||||
|
||||
#include "bus.h"
|
||||
|
||||
#include <dbus/dbus-macros.h>
|
||||
|
||||
BusContainers *bus_containers_new (void);
|
||||
BusContainers *bus_containers_ref (BusContainers *self);
|
||||
void bus_containers_unref (BusContainers *self);
|
||||
void bus_containers_stop_listening (BusContainers *self);
|
||||
|
||||
dbus_bool_t bus_containers_handle_add_server (DBusConnection *connection,
|
||||
BusTransaction *transaction,
|
||||
DBusMessage *message,
|
||||
DBusError *error);
|
||||
dbus_bool_t bus_containers_handle_stop_instance (DBusConnection *connection,
|
||||
BusTransaction *transaction,
|
||||
DBusMessage *message,
|
||||
DBusError *error);
|
||||
dbus_bool_t bus_containers_handle_stop_listening (DBusConnection *connection,
|
||||
BusTransaction *transaction,
|
||||
DBusMessage *message,
|
||||
DBusError *error);
|
||||
dbus_bool_t bus_containers_handle_get_instance_info (DBusConnection *connection,
|
||||
BusTransaction *transaction,
|
||||
DBusMessage *message,
|
||||
DBusError *error);
|
||||
dbus_bool_t bus_containers_handle_get_connection_instance (DBusConnection *connection,
|
||||
BusTransaction *transaction,
|
||||
DBusMessage *message,
|
||||
DBusError *error);
|
||||
dbus_bool_t bus_containers_supported_arguments_getter (BusContext *context,
|
||||
DBusMessageIter *var_iter);
|
||||
|
||||
void bus_containers_remove_connection (BusContainers *self,
|
||||
DBusConnection *connection);
|
||||
dbus_bool_t bus_containers_connection_is_contained (DBusConnection *connection,
|
||||
const char **path,
|
||||
const char **type,
|
||||
const char **name);
|
||||
|
||||
static inline void
|
||||
bus_clear_containers (BusContainers **containers_p)
|
||||
{
|
||||
_dbus_clear_pointer_impl (BusContainers, containers_p, bus_containers_unref);
|
||||
}
|
||||
|
||||
#endif /* multiple-inclusion guard */
|
||||
120
bus/driver.c
120
bus/driver.c
|
|
@ -26,6 +26,7 @@
|
|||
#include "activation.h"
|
||||
#include "apparmor.h"
|
||||
#include "connection.h"
|
||||
#include "containers.h"
|
||||
#include "driver.h"
|
||||
#include "dispatch.h"
|
||||
#include "services.h"
|
||||
|
|
@ -109,6 +110,28 @@ bus_driver_get_conn_helper (DBusConnection *connection,
|
|||
return BUS_DRIVER_FOUND_PEER;
|
||||
}
|
||||
|
||||
static dbus_bool_t
|
||||
bus_driver_check_caller_is_not_container (DBusConnection *connection,
|
||||
BusTransaction *transaction,
|
||||
DBusMessage *message,
|
||||
DBusError *error)
|
||||
{
|
||||
if (bus_containers_connection_is_contained (connection, NULL, NULL, NULL))
|
||||
{
|
||||
const char *method = dbus_message_get_member (message);
|
||||
|
||||
bus_context_log_and_set_error (bus_transaction_get_context (transaction),
|
||||
DBUS_SYSTEM_LOG_SECURITY, error, DBUS_ERROR_ACCESS_DENIED,
|
||||
"rejected attempt to call %s by connection %s (%s) in "
|
||||
"container", method,
|
||||
nonnull (bus_connection_get_name (connection), "(inactive)"),
|
||||
bus_connection_get_loginfo (connection));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Log a security warning and set error unless the uid of the connection
|
||||
* is either the uid of this process, or on Unix, uid 0 (root).
|
||||
|
|
@ -128,7 +151,16 @@ bus_driver_check_caller_is_privileged (DBusConnection *connection,
|
|||
{
|
||||
#ifdef DBUS_UNIX
|
||||
unsigned long uid;
|
||||
#elif defined(DBUS_WIN)
|
||||
char *windows_sid = NULL;
|
||||
dbus_bool_t ret = FALSE;
|
||||
#endif
|
||||
|
||||
if (!bus_driver_check_caller_is_not_container (connection, transaction,
|
||||
message, error))
|
||||
return FALSE;
|
||||
|
||||
#ifdef DBUS_UNIX
|
||||
if (!dbus_connection_get_unix_user (connection, &uid))
|
||||
{
|
||||
const char *method = dbus_message_get_member (message);
|
||||
|
|
@ -168,9 +200,6 @@ bus_driver_check_caller_is_privileged (DBusConnection *connection,
|
|||
|
||||
return TRUE;
|
||||
#elif defined(DBUS_WIN)
|
||||
char *windows_sid = NULL;
|
||||
dbus_bool_t ret = FALSE;
|
||||
|
||||
if (!dbus_connection_get_windows_user (connection, &windows_sid))
|
||||
{
|
||||
const char *method = dbus_message_get_member (message);
|
||||
|
|
@ -1886,7 +1915,10 @@ bus_driver_handle_get_connection_credentials (DBusConnection *connection,
|
|||
DBusMessageIter array_iter;
|
||||
unsigned long ulong_uid, ulong_pid;
|
||||
char *s;
|
||||
const char *name;
|
||||
const char *path;
|
||||
const char *service;
|
||||
const char *type;
|
||||
BusDriverFound found;
|
||||
|
||||
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
|
||||
|
|
@ -1974,6 +2006,19 @@ bus_driver_handle_get_connection_credentials (DBusConnection *connection,
|
|||
dbus_free (s);
|
||||
}
|
||||
|
||||
if (found == BUS_DRIVER_FOUND_PEER &&
|
||||
bus_containers_connection_is_contained (conn, &path, &type, &name))
|
||||
{
|
||||
if (!_dbus_asv_add_object_path (&array_iter,
|
||||
DBUS_INTERFACE_CONTAINERS1 ".Instance",
|
||||
path) ||
|
||||
!_dbus_asv_add_string (&array_iter,
|
||||
DBUS_INTERFACE_CONTAINERS1 ".Type", type) ||
|
||||
!_dbus_asv_add_string (&array_iter,
|
||||
DBUS_INTERFACE_CONTAINERS1 ".Name", name))
|
||||
goto oom;
|
||||
}
|
||||
|
||||
if (!_dbus_asv_close (&reply_iter, &array_iter))
|
||||
goto oom;
|
||||
|
||||
|
|
@ -2368,9 +2413,15 @@ typedef enum
|
|||
|
||||
/* If set, callers must be privileged. On Unix, the uid of the connection
|
||||
* must either be the uid of this process, or 0 (root). On Windows,
|
||||
* the SID of the connection must be the SID of this process. */
|
||||
* the SID of the connection must be the SID of this process.
|
||||
*
|
||||
* This flag effectively implies METHOD_FLAG_NO_CONTAINERS, because
|
||||
* containers are never privileged. */
|
||||
METHOD_FLAG_PRIVILEGED = (1 << 1),
|
||||
|
||||
/* If set, callers must not be associated with a container instance. */
|
||||
METHOD_FLAG_NO_CONTAINERS = (1 << 2),
|
||||
|
||||
METHOD_FLAG_NONE = 0
|
||||
} MethodFlags;
|
||||
|
||||
|
|
@ -2517,6 +2568,27 @@ static const MessageHandler introspectable_message_handlers[] = {
|
|||
{ NULL, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
#ifdef DBUS_ENABLE_CONTAINERS
|
||||
static const MessageHandler containers_message_handlers[] = {
|
||||
{ "AddServer", "ssa{sv}a{sv}", "oays", bus_containers_handle_add_server,
|
||||
METHOD_FLAG_NO_CONTAINERS },
|
||||
{ "StopInstance", "o", "", bus_containers_handle_stop_instance,
|
||||
METHOD_FLAG_NO_CONTAINERS },
|
||||
{ "StopListening", "o", "", bus_containers_handle_stop_listening,
|
||||
METHOD_FLAG_NO_CONTAINERS },
|
||||
{ "GetConnectionInstance", "s", "ossa{sv}",
|
||||
bus_containers_handle_get_connection_instance,
|
||||
METHOD_FLAG_NONE },
|
||||
{ "GetInstanceInfo", "o", "ssa{sv}", bus_containers_handle_get_instance_info,
|
||||
METHOD_FLAG_NONE },
|
||||
{ NULL, NULL, NULL, NULL }
|
||||
};
|
||||
static const PropertyHandler containers_property_handlers[] = {
|
||||
{ "SupportedArguments", "as", bus_containers_supported_arguments_getter },
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
#endif
|
||||
|
||||
static const MessageHandler monitoring_message_handlers[] = {
|
||||
{ "BecomeMonitor", "asu", "", bus_driver_handle_become_monitor,
|
||||
METHOD_FLAG_PRIVILEGED },
|
||||
|
|
@ -2526,9 +2598,9 @@ static const MessageHandler monitoring_message_handlers[] = {
|
|||
#ifdef DBUS_ENABLE_VERBOSE_MODE
|
||||
static const MessageHandler verbose_message_handlers[] = {
|
||||
{ "EnableVerbose", "", "", bus_driver_handle_enable_verbose,
|
||||
METHOD_FLAG_NONE },
|
||||
METHOD_FLAG_NO_CONTAINERS },
|
||||
{ "DisableVerbose", "", "", bus_driver_handle_disable_verbose,
|
||||
METHOD_FLAG_NONE },
|
||||
METHOD_FLAG_NO_CONTAINERS },
|
||||
{ NULL, NULL, NULL, NULL }
|
||||
};
|
||||
#endif
|
||||
|
|
@ -2536,11 +2608,11 @@ static const MessageHandler verbose_message_handlers[] = {
|
|||
#ifdef DBUS_ENABLE_STATS
|
||||
static const MessageHandler stats_message_handlers[] = {
|
||||
{ "GetStats", "", "a{sv}", bus_stats_handle_get_stats,
|
||||
METHOD_FLAG_NONE },
|
||||
METHOD_FLAG_NO_CONTAINERS },
|
||||
{ "GetConnectionStats", "s", "a{sv}", bus_stats_handle_get_connection_stats,
|
||||
METHOD_FLAG_NONE },
|
||||
METHOD_FLAG_NO_CONTAINERS },
|
||||
{ "GetAllMatchRules", "", "a{sas}", bus_stats_handle_get_all_match_rules,
|
||||
METHOD_FLAG_NONE },
|
||||
METHOD_FLAG_NO_CONTAINERS },
|
||||
{ NULL, NULL, NULL, NULL }
|
||||
};
|
||||
#endif
|
||||
|
|
@ -2620,6 +2692,13 @@ static InterfaceHandler interface_handlers[] = {
|
|||
#ifdef DBUS_ENABLE_STATS
|
||||
{ BUS_INTERFACE_STATS, stats_message_handlers, NULL,
|
||||
INTERFACE_FLAG_NONE },
|
||||
#endif
|
||||
#ifdef DBUS_ENABLE_CONTAINERS
|
||||
{ DBUS_INTERFACE_CONTAINERS1, containers_message_handlers,
|
||||
" <signal name=\"InstanceRemoved\">\n"
|
||||
" <arg type=\"o\" name=\"path\"/>\n"
|
||||
" </signal>\n",
|
||||
INTERFACE_FLAG_NONE, containers_property_handlers },
|
||||
#endif
|
||||
{ DBUS_INTERFACE_PEER, peer_message_handlers, NULL,
|
||||
/* Not in the Interfaces property because it's a pseudo-interface
|
||||
|
|
@ -2913,12 +2992,25 @@ bus_driver_handle_message (DBusConnection *connection,
|
|||
|
||||
_dbus_verbose ("Found driver handler for %s\n", name);
|
||||
|
||||
if ((mh->flags & METHOD_FLAG_PRIVILEGED) &&
|
||||
!bus_driver_check_caller_is_privileged (connection, transaction,
|
||||
message, error))
|
||||
if (mh->flags & METHOD_FLAG_PRIVILEGED)
|
||||
{
|
||||
_DBUS_ASSERT_ERROR_IS_SET (error);
|
||||
return FALSE;
|
||||
if (!bus_driver_check_caller_is_privileged (connection,
|
||||
transaction, message,
|
||||
error))
|
||||
{
|
||||
_DBUS_ASSERT_ERROR_IS_SET (error);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else if (mh->flags & METHOD_FLAG_NO_CONTAINERS)
|
||||
{
|
||||
if (!bus_driver_check_caller_is_not_container (connection,
|
||||
transaction,
|
||||
message, error))
|
||||
{
|
||||
_DBUS_ASSERT_ERROR_IS_SET (error);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(is_canonical_path || (mh->flags & METHOD_FLAG_ANY_PATH)))
|
||||
|
|
|
|||
|
|
@ -76,5 +76,11 @@
|
|||
<limit name="max_names_per_connection">50000</limit>
|
||||
<limit name="max_match_rules_per_connection">50000</limit>
|
||||
<limit name="max_replies_per_connection">50000</limit>
|
||||
<limit name="max_containers">10000</limit>
|
||||
<limit name="max_containers_per_user">10000</limit>
|
||||
<limit name="max_container_metadata_bytes">1000000000</limit>
|
||||
<!-- This is relatively low so that app-containers (which we do not fully
|
||||
trust) do not cause DoS. -->
|
||||
<limit name="max_connections_per_container">16</limit>
|
||||
|
||||
</busconfig>
|
||||
|
|
|
|||
|
|
@ -69,6 +69,8 @@
|
|||
send_interface="org.freedesktop.DBus.Introspectable"/>
|
||||
<allow send_destination="org.freedesktop.DBus"
|
||||
send_interface="org.freedesktop.DBus.Properties"/>
|
||||
<allow send_destination="org.freedesktop.DBus"
|
||||
send_interface="org.freedesktop.DBus.Containers1"/>
|
||||
<!-- But disallow some specific bus services -->
|
||||
<deny send_destination="org.freedesktop.DBus"
|
||||
send_interface="org.freedesktop.DBus"
|
||||
|
|
@ -124,6 +126,10 @@
|
|||
<!-- <limit name="max_names_per_connection">512</limit> -->
|
||||
<!-- <limit name="max_match_rules_per_connection">512</limit> -->
|
||||
<!-- <limit name="max_replies_per_connection">128</limit> -->
|
||||
<!-- <limit name="max_containers">512</limit> -->
|
||||
<!-- <limit name="max_containers_per_user">16</limit> -->
|
||||
<!-- <limit name="max_container_metadata_bytes">4096</limit> -->
|
||||
<!-- <limit name="max_connections_per_container">8</limit> -->
|
||||
|
||||
<!-- Config files are placed here that among other things, punch
|
||||
holes in the above policy for specific services. -->
|
||||
|
|
|
|||
|
|
@ -3,3 +3,7 @@
|
|||
# Make ${localstatedir}/lib/dbus/machine-id a symlink to /etc/machine-id
|
||||
# if it does not already exist
|
||||
L @EXPANDED_LOCALSTATEDIR@/lib/dbus/machine-id - - - - /etc/machine-id
|
||||
|
||||
# Create ${runstatedir}/dbus/containers owned by the system bus user.
|
||||
# org.freedesktop.DBus.Containers1 uses this to create sockets.
|
||||
d @EXPANDED_RUNSTATEDIR@/dbus/containers 0755 @DBUS_USER@ - - -
|
||||
|
|
|
|||
|
|
@ -128,6 +128,7 @@ endif(NOT WIN32)
|
|||
option (DBUS_DISABLE_ASSERT "Disable assertion checking" OFF)
|
||||
|
||||
option (DBUS_ENABLE_STATS "enable bus daemon usage statistics" OFF)
|
||||
option (DBUS_ENABLE_CONTAINERS "enable restricted servers for app-containers" OFF)
|
||||
|
||||
if(WIN32)
|
||||
set(FD_SETSIZE "8192" CACHE STRING "The maximum number of connections that can be handled at once")
|
||||
|
|
|
|||
|
|
@ -52,6 +52,8 @@ set (BUS_SOURCES
|
|||
# ${BUS_DIR}/config-parser-trivial.c
|
||||
${BUS_DIR}/connection.c
|
||||
${BUS_DIR}/connection.h
|
||||
${BUS_DIR}/containers.c
|
||||
${BUS_DIR}/containers.h
|
||||
${BUS_DIR}/desktop-file.c
|
||||
${BUS_DIR}/desktop-file.h
|
||||
${BUS_DIR}/dir-watch.h
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#cmakedefine DBUS_RUNSTATEDIR "@DBUS_RUNSTATEDIR@"
|
||||
|
||||
#cmakedefine DBUS_ENABLE_STATS
|
||||
#cmakedefine DBUS_ENABLE_CONTAINERS
|
||||
|
||||
#define TEST_LISTEN "@TEST_LISTEN@"
|
||||
|
||||
|
|
|
|||
11
configure.ac
11
configure.ac
|
|
@ -1762,6 +1762,16 @@ AC_ARG_ENABLE([user-session],
|
|||
AM_CONDITIONAL([DBUS_ENABLE_USER_SESSION],
|
||||
[test "x$enable_user_session" = xyes])
|
||||
|
||||
AC_ARG_ENABLE([containers],
|
||||
[AS_HELP_STRING([--enable-containers],
|
||||
[enable restricted servers for app containers])],
|
||||
[], [enable_containers=no])
|
||||
AS_IF([test "x$enable_containers" = xyes && test "x$dbus_unix" != xyes],
|
||||
[AC_MSG_ERROR([Restricted servers for app containers require Unix])])
|
||||
AS_IF([test "x$enable_containers" = xyes],
|
||||
[AC_DEFINE([DBUS_ENABLE_CONTAINERS], [1],
|
||||
[Define to enable restricted servers for app containers])])
|
||||
|
||||
AC_CONFIG_FILES([
|
||||
Doxyfile
|
||||
dbus/Version
|
||||
|
|
@ -1842,6 +1852,7 @@ echo "
|
|||
Building assertions: ${enable_asserts}
|
||||
Building checks: ${enable_checks}
|
||||
Building bus stats API: ${enable_stats}
|
||||
Building container API: ${enable_containers}
|
||||
Building SELinux support: ${have_selinux}
|
||||
Building AppArmor support: ${have_apparmor}
|
||||
Building inotify support: ${have_inotify}
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ DBUS_PRIVATE_EXPORT
|
|||
void _dbus_hash_iter_remove_entry (DBusHashIter *iter);
|
||||
DBUS_PRIVATE_EXPORT
|
||||
void* _dbus_hash_iter_get_value (DBusHashIter *iter);
|
||||
DBUS_PRIVATE_EXPORT
|
||||
void _dbus_hash_iter_set_value (DBusHashIter *iter,
|
||||
void *value);
|
||||
DBUS_PRIVATE_EXPORT
|
||||
|
|
@ -96,6 +97,7 @@ DBUS_PRIVATE_EXPORT
|
|||
const char* _dbus_hash_iter_get_string_key (DBusHashIter *iter);
|
||||
DBUS_PRIVATE_EXPORT
|
||||
uintptr_t _dbus_hash_iter_get_uintptr_key (DBusHashIter *iter);
|
||||
DBUS_PRIVATE_EXPORT
|
||||
dbus_bool_t _dbus_hash_iter_lookup (DBusHashTable *table,
|
||||
void *key,
|
||||
dbus_bool_t create_if_not_found,
|
||||
|
|
|
|||
|
|
@ -376,6 +376,7 @@ void _dbus_unlock (DBusGlobalLock lock);
|
|||
DBUS_PRIVATE_EXPORT
|
||||
dbus_bool_t _dbus_threads_init_debug (void);
|
||||
|
||||
DBUS_PRIVATE_EXPORT
|
||||
dbus_bool_t _dbus_address_append_escaped (DBusString *escaped,
|
||||
const DBusString *unescaped);
|
||||
|
||||
|
|
|
|||
|
|
@ -455,6 +455,9 @@ extern "C" {
|
|||
* but could have succeeded if an interactive authorization step was
|
||||
* allowed. */
|
||||
#define DBUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED "org.freedesktop.DBus.Error.InteractiveAuthorizationRequired"
|
||||
/** The connection is not from a container, or the specified container instance
|
||||
* does not exist. */
|
||||
#define DBUS_ERROR_NOT_CONTAINER "org.freedesktop.DBus.Error.NotContainer"
|
||||
|
||||
/* XML introspection format */
|
||||
|
||||
|
|
|
|||
|
|
@ -86,6 +86,8 @@ typedef enum
|
|||
*/
|
||||
/** The interface exported by the object with #DBUS_SERVICE_DBUS and #DBUS_PATH_DBUS */
|
||||
#define DBUS_INTERFACE_DBUS "org.freedesktop.DBus"
|
||||
/** The restricted container interface exported by the dbus-daemon */
|
||||
#define DBUS_INTERFACE_CONTAINERS1 "org.freedesktop.DBus.Containers1"
|
||||
/** The monitoring interface exported by the dbus-daemon */
|
||||
#define DBUS_INTERFACE_MONITORING "org.freedesktop.DBus.Monitoring"
|
||||
|
||||
|
|
|
|||
|
|
@ -749,6 +749,14 @@ Available limit names are:</para>
|
|||
(number of calls-in-progress)
|
||||
"reply_timeout" : milliseconds (thousandths)
|
||||
until a method call times out
|
||||
"max_containers" : max number of restricted servers for use
|
||||
in app-containers, in total
|
||||
"max_containers_per_user" : max number of app-containers per Unix uid
|
||||
"max_container_metadata_bytes": max number of bytes of metadata to store
|
||||
for each app-container
|
||||
"max_connections_per_container": max number of (authenticated or
|
||||
unauthenticated) connections to each
|
||||
app-container
|
||||
</literallayout> <!-- .fi -->
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -6416,6 +6416,44 @@
|
|||
</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry>org.freedesktop.DBus.Containers1.Instance</entry>
|
||||
<entry>OBJECT_PATH</entry>
|
||||
<entry>
|
||||
The container instance object path of the server through
|
||||
which this connection is connected, as returned by
|
||||
<literal>AddServer</literal>. Omitted from the
|
||||
dictionary if this connection is not via a container's
|
||||
server.
|
||||
</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry>org.freedesktop.DBus.Containers1.Type</entry>
|
||||
<entry>STRING</entry>
|
||||
<entry>
|
||||
The container technology that created the container
|
||||
instance, as passed to <literal>AddServer</literal>.
|
||||
Omitted from the dictionary if this connection is not
|
||||
via a container's server. For example, a typical value
|
||||
for a Flatpak application would be
|
||||
<literal>org.flatpak</literal>.
|
||||
</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry>org.freedesktop.DBus.Containers1.Name</entry>
|
||||
<entry>STRING</entry>
|
||||
<entry>
|
||||
The contained app name for the container instance,
|
||||
as passed to <literal>AddServer</literal>. Omitted
|
||||
from the dictionary if this connection is not via a
|
||||
container's server. For example, a typical value for
|
||||
a Flatpak application would be
|
||||
<literal>org.gnome.Weather</literal>.
|
||||
</entry>
|
||||
</row>
|
||||
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
|
|
@ -6647,6 +6685,520 @@
|
|||
</para>
|
||||
</sect3>
|
||||
|
||||
<sect3 id="bus-messages-containers1-add-server">
|
||||
<title><literal>org.freedesktop.DBus.Containers1.AddServer</literal></title>
|
||||
<para>
|
||||
As a method:
|
||||
<programlisting>
|
||||
AddServer (in STRING container_type,
|
||||
in STRING container_name,
|
||||
in DICT<STRING,VARIANT> metadata,
|
||||
in DICT<STRING,VARIANT> named_arguments,
|
||||
out OBJECT_PATH container_instance,
|
||||
out ARRAY<BYTE> socket_path,
|
||||
out STRING connectable_address)
|
||||
</programlisting>
|
||||
Message arguments:
|
||||
<informaltable>
|
||||
<tgroup cols="3">
|
||||
<thead>
|
||||
<row>
|
||||
<entry>Argument</entry>
|
||||
<entry>Type</entry>
|
||||
<entry>Description</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>0</entry>
|
||||
<entry>STRING</entry>
|
||||
<entry>
|
||||
Reversed domain name identifying a container manager
|
||||
or container technology, such as
|
||||
<literal>org.flatpak</literal> or
|
||||
<literal>io.snapcraft</literal>. It must follow the
|
||||
same syntactic rules as a
|
||||
<link linkend="message-protocol-names-interface">D-Bus
|
||||
interface name</link>.
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>1</entry>
|
||||
<entry>STRING</entry>
|
||||
<entry>
|
||||
Some unique identifier for an application or
|
||||
container, whose meaning is defined by the
|
||||
maintainers of the container type. If the container
|
||||
type does not have a concept of identifying or
|
||||
naming its applications or containers by a string,
|
||||
using the empty string here is suggested.
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>2</entry>
|
||||
<entry>DICT<STRING,VARIANT></entry>
|
||||
<entry>
|
||||
Metadata describing the application or container, with the
|
||||
keys and values defined by the maintainers of the container
|
||||
type.
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>3</entry>
|
||||
<entry>DICT<STRING,VARIANT></entry>
|
||||
<entry>
|
||||
Additional arguments that extend this method.
|
||||
The only named arguments that are allowed are the ones
|
||||
listed in the
|
||||
<literal>org.freedesktop.DBus.Containers1.SupportedArguments</literal>
|
||||
property. All other named arguments are an error.
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>4</entry>
|
||||
<entry>OBJECT_PATH</entry>
|
||||
<entry>
|
||||
An opaque object path identifying the new container
|
||||
instance.
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>5</entry>
|
||||
<entry>ARRAY<BYTE></entry>
|
||||
<entry>
|
||||
The absolute filesystem path of the resulting
|
||||
<literal>AF_UNIX</literal> socket, followed by a single
|
||||
zero (nul) byte, for example
|
||||
<literal>/run/user/1000/dbus-12345vwxyz\x00</literal>
|
||||
where \x00 represents the terminating zero byte.
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>6</entry>
|
||||
<entry>STRING</entry>
|
||||
<entry>
|
||||
A connectable D-Bus address, for example
|
||||
<literal>unix:path=/run/user/1000/dbus-12345vwxyz</literal>.
|
||||
</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Set up a new server socket for use in an application container.
|
||||
Clients can connect to that socket, and the result will be as
|
||||
though they had connected to the message bus, with a few differences.
|
||||
The intention is that a container manager will call this method
|
||||
to get a new server socket, bind-mount the server socket
|
||||
into a location that is accessible by the confined (sandboxed)
|
||||
application, and ensure that the normal message bus socket is
|
||||
<emphasis>not</emphasis> accessible by the confined application.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Each call to this method creates a new
|
||||
<firstterm>container instance</firstterm>, identified by an object
|
||||
path. Even if the specified container type and name are the
|
||||
same as for a pre-existing container instance, each call
|
||||
creates a new server with a new unique object path, because
|
||||
the new container instance might represent a different
|
||||
version of the confined application with different
|
||||
characteristics and restrictions. The message bus may provide
|
||||
an object at the given object path, but is not required to
|
||||
do so.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Metadata from the first three arguments is stored by the message
|
||||
bus, but not interpreted; software that interacts with the
|
||||
container manager can use this metadata.
|
||||
<!-- TODO: Clarify how the trust model works here. See
|
||||
<https://bugs.freedesktop.org/show_bug.cgi?id=100344#c15>-->
|
||||
The method call may fail with the error
|
||||
<literal>org.freedesktop.DBus.Error.LimitsExceeded</literal>
|
||||
if the caller provides more metadata than the message bus
|
||||
is willing to store.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The last argument (the <firstterm>named arguments</firstterm>)
|
||||
will be used in future versions of this specification to modify
|
||||
the behaviour of this method call; all keys in this dictionary not
|
||||
containing <literal>.</literal> are reserved by this specification
|
||||
for this purpose. It can also contain implementation-specific
|
||||
arguments for a particular message bus implementation, which
|
||||
should start with a reversed domain name in the same way as
|
||||
interface names. For example, GLib's gdbus-daemon might use
|
||||
<literal>org.gtk.GDBus.SomeArgument</literal> if it used this
|
||||
extension point.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
In the most basic form of a call to this method, the new server
|
||||
socket is an <literal>AF_UNIX</literal> socket at a path chosen
|
||||
by the message bus and returned from the method. Future versions
|
||||
of this specification are likely to provide a way for the
|
||||
message bus implementation to receive a socket from the caller
|
||||
and arrange for it to listen for connections, using the named
|
||||
arguments dictionary.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Connections to the new server socket are said to be
|
||||
<firstterm>confined</firstterm>. The message bus may prevent
|
||||
confined connections from calling certain security-sensitive methods,
|
||||
and may apply lower limits to these connections. However, container
|
||||
managers and services must not rely on confined connections having
|
||||
any particular filtering applied to them by the message bus.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
In the most basic form of a call to this method, the server
|
||||
socket will cease to listen for new connections (in the same
|
||||
way as if <literal>StopListening</literal> had been called
|
||||
successfully) when the caller of this method disconnects from
|
||||
the bus. Any confined connections that are already active are
|
||||
unaffected. Future versions of this specification are likely
|
||||
to provide a way for the caller to alter this behaviour by
|
||||
specifying named arguments.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The container instance object path remains valid for as
|
||||
long as one or more confined connection via the same server
|
||||
socket remain open, or there is a way for the server socket
|
||||
to produce new connections in future (in other words,
|
||||
either it is preparing to listen for new connections, or
|
||||
it is currently listening for new connections). When the
|
||||
container instance has ceased to listen for new connections
|
||||
and no longer has any confined connections, the object path
|
||||
becomes invalid, and API calls that specify it will fail with
|
||||
the <literal>org.freedesktop.DBus.Error.NotContainer</literal>
|
||||
error.
|
||||
</para>
|
||||
</sect3>
|
||||
|
||||
<sect3 id="bus-messages-containers1-stop-instance">
|
||||
<title><literal>org.freedesktop.DBus.Containers1.StopInstance</literal></title>
|
||||
<para>
|
||||
As a method:
|
||||
<programlisting>
|
||||
StopInstance (in OBJECT_PATH container_instance)
|
||||
</programlisting>
|
||||
Message arguments:
|
||||
<informaltable>
|
||||
<tgroup cols="3">
|
||||
<thead>
|
||||
<row>
|
||||
<entry>Argument</entry>
|
||||
<entry>Type</entry>
|
||||
<entry>Description</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>0</entry>
|
||||
<entry>OBJECT_PATH</entry>
|
||||
<entry>
|
||||
The opaque object path that was returned from the
|
||||
<literal>AddServer</literal> method, identifying a
|
||||
container instance.
|
||||
</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Terminate the container instance. The server will stop
|
||||
listening for new connections, and any existing connections to
|
||||
that server will be disconnected. When all connections have
|
||||
been disconnected, the instance will cease to exist.
|
||||
</para>
|
||||
<para>
|
||||
If the given object path does not represent a valid container
|
||||
instance (see
|
||||
<xref linkend="bus-messages-containers1-add-server"/>), the
|
||||
<literal>org.freedesktop.DBus.Error.NotContainer</literal>
|
||||
error is returned. In particular, if this method is called
|
||||
twice, the second call will fail in this way.
|
||||
</para>
|
||||
<para>
|
||||
If the given container instance exists but the caller of this
|
||||
method is not allowed to stop it (for example because the
|
||||
caller is in a container instance or because its user ID does
|
||||
not match the user ID of the creator of the container
|
||||
instance),
|
||||
the <literal>org.freedesktop.DBus.Error.AccessDenied</literal>
|
||||
error is returned and nothing is stopped.
|
||||
</para>
|
||||
</sect3>
|
||||
|
||||
<sect3 id="bus-messages-containers1-stop-listening">
|
||||
<title><literal>org.freedesktop.DBus.Containers1.StopListening</literal></title>
|
||||
<para>
|
||||
As a method:
|
||||
<programlisting>
|
||||
StopListening (in OBJECT_PATH container_instance)
|
||||
</programlisting>
|
||||
Message arguments:
|
||||
<informaltable>
|
||||
<tgroup cols="3">
|
||||
<thead>
|
||||
<row>
|
||||
<entry>Argument</entry>
|
||||
<entry>Type</entry>
|
||||
<entry>Description</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>0</entry>
|
||||
<entry>OBJECT_PATH</entry>
|
||||
<entry>
|
||||
The opaque object path that was returned from the
|
||||
<literal>AddServer</literal> method, identifying a
|
||||
container instance.
|
||||
</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Stop listening for new connections to the server in the given
|
||||
container instance, but do not disconnect any existing
|
||||
connections.
|
||||
</para>
|
||||
<para>
|
||||
If this method is called more than once, while the container
|
||||
instance still exists because connections to it are still
|
||||
open, the second and subsequent calls will be successful but
|
||||
will have no practical effect.
|
||||
</para>
|
||||
<para>
|
||||
If the given object path does not represent a valid container
|
||||
instance (see
|
||||
<xref linkend="bus-messages-containers1-add-server"/>), the
|
||||
<literal>org.freedesktop.DBus.Error.NotContainer</literal>
|
||||
error is returned. In particular, this will happen if the
|
||||
container instance already stopped listening, and all
|
||||
connections to it (if any) were already closed.
|
||||
</para>
|
||||
<para>
|
||||
If the given container instance exists but the caller of this
|
||||
method is not allowed to stop it (for example because the
|
||||
caller is in a container instance or because its user ID does
|
||||
not match the user ID of the creator of the container
|
||||
instance),
|
||||
the <literal>org.freedesktop.DBus.Error.AccessDenied</literal>
|
||||
error is returned and nothing is stopped.
|
||||
</para>
|
||||
</sect3>
|
||||
|
||||
<sect3 id="bus-messages-containers1-get-connection-instance">
|
||||
<title><literal>org.freedesktop.DBus.Containers1.GetConnectionInstance</literal></title>
|
||||
<para>
|
||||
As a method:
|
||||
<programlisting>
|
||||
GetConnectionInstance (in STRING bus_name,
|
||||
out OBJECT_PATH container_instance,
|
||||
out STRING container_type,
|
||||
out STRING container_name,
|
||||
out DICT<STRING,VARIANT> metadata)
|
||||
</programlisting>
|
||||
Message arguments:
|
||||
<informaltable>
|
||||
<tgroup cols="3">
|
||||
<thead>
|
||||
<row>
|
||||
<entry>Argument</entry>
|
||||
<entry>Type</entry>
|
||||
<entry>Description</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>0</entry>
|
||||
<entry>STRING</entry>
|
||||
<entry>
|
||||
Unique or well-known bus name of the connection to
|
||||
query, such as <literal>:12.34</literal> or
|
||||
<literal>com.example.tea</literal>.
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>1</entry>
|
||||
<entry>OBJECT_PATH</entry>
|
||||
<entry>
|
||||
The opaque object path that was returned from the
|
||||
<literal>AddServer</literal> method, identifying a
|
||||
container instance.
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>2</entry>
|
||||
<entry>STRING</entry>
|
||||
<entry>
|
||||
Reversed domain name identifying a container
|
||||
manager or container technology, as passed to the
|
||||
<literal>AddServer</literal> method, such as
|
||||
<literal>org.flatpak</literal> or
|
||||
<literal>io.snapcraft</literal>.
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>3</entry>
|
||||
<entry>STRING</entry>
|
||||
<entry>
|
||||
Some unique identifier for an application or container,
|
||||
whose meaning is defined by the maintainers of the
|
||||
container type.
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>4</entry>
|
||||
<entry>DICT<STRING,VARIANT></entry>
|
||||
<entry>
|
||||
Metadata describing the application or container, with the
|
||||
keys and values defined by the maintainers of the container
|
||||
type.
|
||||
</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
If the given unique or well-known bus name is a connection to a
|
||||
container server, return information about that container instance.
|
||||
If the bus name exists but is not confined (in other words, if it
|
||||
is a direct connection to the main message bus socket), the
|
||||
<literal>org.freedesktop.DBus.Error.NotContainer</literal> error
|
||||
is returned instead. If the given bus name has no owner at all, the
|
||||
<literal>org.freedesktop.DBus.Error.NameHasNoOwner</literal> error
|
||||
is returned instead.
|
||||
</para>
|
||||
</sect3>
|
||||
|
||||
<sect3 id="bus-messages-containers1-get-instance-info">
|
||||
<title><literal>org.freedesktop.DBus.Containers1.GetInstanceInfo</literal></title>
|
||||
<para>
|
||||
As a method:
|
||||
<programlisting>
|
||||
GetInstanceInfo (in OBJECT_PATH container_instance,
|
||||
out STRING container_type,
|
||||
out STRING container_name,
|
||||
out DICT<STRING,VARIANT> metadata)
|
||||
</programlisting>
|
||||
Message arguments:
|
||||
<informaltable>
|
||||
<tgroup cols="3">
|
||||
<thead>
|
||||
<row>
|
||||
<entry>Argument</entry>
|
||||
<entry>Type</entry>
|
||||
<entry>Description</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>0</entry>
|
||||
<entry>OBJECT_PATH</entry>
|
||||
<entry>
|
||||
The opaque object path that was returned from the
|
||||
<literal>AddServer</literal> method, identifying a
|
||||
container instance.
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>1</entry>
|
||||
<entry>STRING</entry>
|
||||
<entry>
|
||||
Reversed domain name identifying a container
|
||||
manager or container technology, as passed to the
|
||||
<literal>AddServer</literal> method, such as
|
||||
<literal>org.flatpak</literal> or
|
||||
<literal>io.snapcraft</literal>.
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>2</entry>
|
||||
<entry>STRING</entry>
|
||||
<entry>
|
||||
Some unique identifier for an application or container,
|
||||
whose meaning is defined by the maintainers of the
|
||||
container type.
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>3</entry>
|
||||
<entry>DICT<STRING,VARIANT></entry>
|
||||
<entry>
|
||||
Metadata describing the application or container, with the
|
||||
keys and values defined by the maintainers of the container
|
||||
type.
|
||||
</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
If the given object path represents a valid container instance,
|
||||
(see <xref linkend="bus-messages-containers1-add-server"/>),
|
||||
return information about it. Otherwise, the
|
||||
<literal>org.freedesktop.DBus.Error.NotContainer</literal> error
|
||||
is returned.
|
||||
</para>
|
||||
</sect3>
|
||||
|
||||
<sect3 id="bus-messages-containers1-instance-removed">
|
||||
<title><literal>org.freedesktop.DBus.Containers1.InstanceRemoved</literal></title>
|
||||
<para>
|
||||
As a signal emitted by the message bus:
|
||||
<programlisting>
|
||||
InstanceRemoved (OBJECT_PATH container_instance)
|
||||
</programlisting>
|
||||
Message arguments:
|
||||
<informaltable>
|
||||
<tgroup cols="3">
|
||||
<thead>
|
||||
<row>
|
||||
<entry>Argument</entry>
|
||||
<entry>Type</entry>
|
||||
<entry>Description</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>0</entry>
|
||||
<entry>OBJECT_PATH</entry>
|
||||
<entry>
|
||||
The opaque object path that was returned from the
|
||||
<literal>AddServer</literal> method, identifying a
|
||||
container instance.
|
||||
</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Emitted when a container instance ceases to exist. A container
|
||||
instance continues to exist as long as it is listening for
|
||||
new connections, or as long as connections to the instance
|
||||
are open, whichever is longer.
|
||||
</para>
|
||||
</sect3>
|
||||
|
||||
<sect3 id="bus-messages-become-monitor">
|
||||
<title><literal>org.freedesktop.DBus.Monitoring.BecomeMonitor</literal></title>
|
||||
<para>
|
||||
|
|
|
|||
|
|
@ -181,6 +181,7 @@ installable_helpers += \
|
|||
$(NULL)
|
||||
|
||||
installable_tests += \
|
||||
test-containers \
|
||||
test-sd-activation \
|
||||
$(NULL)
|
||||
|
||||
|
|
@ -286,6 +287,12 @@ test_apparmor_activation_LDADD = \
|
|||
$(NULL)
|
||||
endif
|
||||
|
||||
test_containers_SOURCES = containers.c
|
||||
test_containers_LDADD = \
|
||||
libdbus-testutils.la \
|
||||
$(GLIB_LIBS) \
|
||||
$(NULL)
|
||||
|
||||
test_corrupt_SOURCES = corrupt.c
|
||||
test_corrupt_LDADD = \
|
||||
libdbus-testutils.la \
|
||||
|
|
@ -422,8 +429,10 @@ in_data = \
|
|||
data/valid-config-files/finite-timeout.conf.in \
|
||||
data/valid-config-files/forbidding.conf.in \
|
||||
data/valid-config-files/incoming-limit.conf.in \
|
||||
data/valid-config-files/limit-containers.conf.in \
|
||||
data/valid-config-files/max-completed-connections.conf.in \
|
||||
data/valid-config-files/max-connections-per-user.conf.in \
|
||||
data/valid-config-files/max-containers.conf.in \
|
||||
data/valid-config-files/max-match-rules-per-connection.conf.in \
|
||||
data/valid-config-files/max-names-per-connection.conf.in \
|
||||
data/valid-config-files/max-replies-per-connection.conf.in \
|
||||
|
|
|
|||
1620
test/containers.c
Normal file
1620
test/containers.c
Normal file
File diff suppressed because it is too large
Load diff
21
test/data/valid-config-files/limit-containers.conf.in
Normal file
21
test/data/valid-config-files/limit-containers.conf.in
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN"
|
||||
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
|
||||
<busconfig>
|
||||
<!-- Our well-known bus type, don't change this -->
|
||||
<type>session</type>
|
||||
<listen>@TEST_LISTEN@</listen>
|
||||
|
||||
<policy context="default">
|
||||
<!-- Allow everything to be sent -->
|
||||
<allow send_destination="*" eavesdrop="true"/>
|
||||
<!-- Allow everything to be received -->
|
||||
<allow eavesdrop="true"/>
|
||||
<!-- Allow anyone to own anything -->
|
||||
<allow own="*"/>
|
||||
</policy>
|
||||
|
||||
<limit name="max_containers">5</limit>
|
||||
<limit name="max_containers_per_user">3</limit>
|
||||
<limit name="max_container_metadata_bytes">4096</limit>
|
||||
<limit name="max_connections_per_container">3</limit>
|
||||
</busconfig>
|
||||
18
test/data/valid-config-files/max-containers.conf.in
Normal file
18
test/data/valid-config-files/max-containers.conf.in
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN"
|
||||
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
|
||||
<busconfig>
|
||||
<!-- Our well-known bus type, don't change this -->
|
||||
<type>session</type>
|
||||
<listen>@TEST_LISTEN@</listen>
|
||||
|
||||
<policy context="default">
|
||||
<!-- Allow everything to be sent -->
|
||||
<allow send_destination="*" eavesdrop="true"/>
|
||||
<!-- Allow everything to be received -->
|
||||
<allow eavesdrop="true"/>
|
||||
<!-- Allow anyone to own anything -->
|
||||
<allow own="*"/>
|
||||
</policy>
|
||||
|
||||
<limit name="max_containers">3</limit>
|
||||
</busconfig>
|
||||
|
|
@ -507,6 +507,10 @@ test_creds (Fixture *f,
|
|||
g_assert_not_reached ();
|
||||
#endif
|
||||
}
|
||||
else if (g_str_has_prefix (name, DBUS_INTERFACE_CONTAINERS1 "."))
|
||||
{
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
dbus_message_iter_next (&arr_iter);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -187,6 +187,11 @@ test_monitor (Fixture *f,
|
|||
dbus_clear_message (&m);
|
||||
}
|
||||
|
||||
/*
|
||||
* Assert that AddServer() can be called by the owner of the bus
|
||||
* (TEST_USER_MESSAGEBUS) or by root, but cannot be called by other
|
||||
* users for now.
|
||||
*/
|
||||
static void
|
||||
teardown (Fixture *f,
|
||||
gconstpointer context G_GNUC_UNUSED)
|
||||
|
|
|
|||
|
|
@ -127,6 +127,7 @@ case "$ci_buildsys" in
|
|||
set "$@" --enable-developer --enable-tests
|
||||
# Enable optional features that are off by default
|
||||
if [ "$ci_host" != mingw ]; then
|
||||
set "$@" --enable-containers
|
||||
set "$@" --enable-user-session
|
||||
fi
|
||||
shift
|
||||
|
|
@ -153,6 +154,7 @@ case "$ci_buildsys" in
|
|||
set "$@" --disable-libaudit --without-valgrind
|
||||
# Disable optional features, some of which are on by
|
||||
# default
|
||||
set "$@" --disable-containers
|
||||
set "$@" --disable-stats
|
||||
set "$@" --disable-user-session
|
||||
shift
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue