2017-11-18 17:09:20 +01:00
/* SPDX-License-Identifier: LGPL-2.1+ */
2010-02-03 13:03:47 +01:00
/***
This file is part of systemd .
Copyright 2010 Lennart Poettering
systemd is free software ; you can redistribute it and / or modify it
2012-04-12 00:20:58 +02:00
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation ; either version 2.1 of the License , or
2010-02-03 13:03:47 +01:00
( at your option ) any later version .
systemd 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
2012-04-12 00:20:58 +02:00
Lesser General Public License for more details .
2010-02-03 13:03:47 +01:00
2012-04-12 00:20:58 +02:00
You should have received a copy of the GNU Lesser General Public License
2010-02-03 13:03:47 +01:00
along with systemd ; If not , see < http : //www.gnu.org/licenses/>.
* * */
2010-02-01 03:33:24 +01:00
# include <errno.h>
2015-10-24 22:58:24 +02:00
# include <sys/epoll.h>
2010-02-01 03:33:24 +01:00
# include <unistd.h>
2013-11-19 21:12:59 +01:00
# include "sd-bus.h"
2015-10-24 22:58:24 +02:00
2015-10-27 03:01:06 +01:00
# include "alloc-util.h"
2015-10-24 22:58:24 +02:00
# include "bus-common-errors.h"
# include "bus-error.h"
# include "bus-internal.h"
# include "bus-util.h"
# include "dbus-cgroup.h"
2013-11-19 21:12:59 +01:00
# include "dbus-execute.h"
2015-10-24 22:58:24 +02:00
# include "dbus-job.h"
2013-11-19 21:12:59 +01:00
# include "dbus-kill.h"
2015-10-24 22:58:24 +02:00
# include "dbus-manager.h"
# include "dbus-unit.h"
2015-10-25 13:14:12 +01:00
# include "dbus.h"
# include "fd-util.h"
2017-12-27 18:22:31 +01:00
# include "fs-util.h"
2015-10-24 22:58:24 +02:00
# include "log.h"
# include "missing.h"
# include "mkdir.h"
2018-01-11 00:39:12 +01:00
# include "process-util.h"
2015-10-24 22:58:24 +02:00
# include "selinux-access.h"
2010-09-01 03:30:59 +02:00
# include "special.h"
2015-10-24 22:58:24 +02:00
# include "string-util.h"
# include "strv.h"
2013-11-19 21:12:59 +01:00
# include "strxcpyx.h"
2015-10-27 00:42:07 +01:00
# include "user-util.h"
2010-05-23 03:45:33 +02:00
2015-03-04 16:32:17 +01:00
# define CONNECTIONS_MAX 4096
2010-06-19 03:04:04 +02:00
2013-11-19 21:12:59 +01:00
static void destroy_bus ( Manager * m , sd_bus * * bus ) ;
int bus_send_queued_message ( Manager * m ) {
int r ;
2010-03-31 16:29:55 +02:00
assert ( m ) ;
2010-04-08 04:58:30 +02:00
2013-11-19 21:12:59 +01:00
if ( ! m - > queued_message )
return 0 ;
2010-03-31 16:29:55 +02:00
2013-11-19 21:12:59 +01:00
/* If we cannot get rid of this message we won't dispatch any
* D - Bus messages , so that we won ' t end up wanting to queue
* another message . */
2010-02-01 03:33:24 +01:00
2015-04-29 19:02:08 +02:00
r = sd_bus_send ( NULL , m - > queued_message , NULL ) ;
2013-11-19 21:12:59 +01:00
if ( r < 0 )
2014-11-28 13:19:16 +01:00
log_warning_errno ( r , " Failed to send queued message: %m " ) ;
2010-02-01 03:33:24 +01:00
2013-11-19 21:12:59 +01:00
m - > queued_message = sd_bus_message_unref ( m - > queued_message ) ;
2010-02-01 03:33:24 +01:00
2013-11-19 21:12:59 +01:00
return 0 ;
2010-02-01 03:33:24 +01:00
}
2016-05-04 20:43:23 +02:00
int bus_forward_agent_released ( Manager * m , const char * path ) {
int r ;
assert ( m ) ;
assert ( path ) ;
if ( ! MANAGER_IS_SYSTEM ( m ) )
return 0 ;
if ( ! m - > system_bus )
return 0 ;
/* If we are running a system instance we forward the agent message on the system bus, so that the user
* instances get notified about this , too */
r = sd_bus_emit_signal ( m - > system_bus ,
" /org/freedesktop/systemd1/agent " ,
" org.freedesktop.systemd1.Agent " ,
" Released " ,
" s " , path ) ;
if ( r < 0 )
2017-09-08 17:24:57 +02:00
return log_debug_errno ( r , " Failed to propagate agent release message: %m " ) ;
2016-05-04 20:43:23 +02:00
return 1 ;
}
2015-04-29 18:35:10 +02:00
static int signal_agent_released ( sd_bus_message * message , void * userdata , sd_bus_error * error ) {
tree-wide: expose "p"-suffix unref calls in public APIs to make gcc cleanup easy
GLIB has recently started to officially support the gcc cleanup
attribute in its public API, hence let's do the same for our APIs.
With this patch we'll define an xyz_unrefp() call for each public
xyz_unref() call, to make it easy to use inside a
__attribute__((cleanup())) expression. Then, all code is ported over to
make use of this.
The new calls are also documented in the man pages, with examples how to
use them (well, I only added docs where the _unref() call itself already
had docs, and the examples, only cover sd_bus_unrefp() and
sd_event_unrefp()).
This also renames sd_lldp_free() to sd_lldp_unref(), since that's how we
tend to call our destructors these days.
Note that this defines no public macro that wraps gcc's attribute and
makes it easier to use. While I think it's our duty in the library to
make our stuff easy to use, I figure it's not our duty to make gcc's own
features easy to use on its own. Most likely, client code which wants to
make use of this should define its own:
#define _cleanup_(function) __attribute__((cleanup(function)))
Or similar, to make the gcc feature easier to use.
Making this logic public has the benefit that we can remove three header
files whose only purpose was to define these functions internally.
See #2008.
2015-11-27 19:13:45 +01:00
_cleanup_ ( sd_bus_creds_unrefp ) sd_bus_creds * creds = NULL ;
2013-11-19 21:12:59 +01:00
Manager * m = userdata ;
2016-05-04 20:43:23 +02:00
const char * cgroup ;
2015-07-04 12:14:45 +02:00
uid_t sender_uid ;
2013-11-19 21:12:59 +01:00
int r ;
2010-02-01 03:33:24 +01:00
2013-11-19 21:12:59 +01:00
assert ( message ) ;
2010-02-01 03:33:24 +01:00
assert ( m ) ;
2015-07-04 12:14:45 +02:00
/* only accept org.freedesktop.systemd1.Agent from UID=0 */
r = sd_bus_query_sender_creds ( message , SD_BUS_CREDS_EUID , & creds ) ;
if ( r < 0 )
return r ;
r = sd_bus_creds_get_euid ( creds , & sender_uid ) ;
if ( r < 0 | | sender_uid ! = 0 )
return 0 ;
/* parse 'cgroup-empty' notification */
2013-11-19 21:12:59 +01:00
r = sd_bus_message_read ( message , " s " , & cgroup ) ;
if ( r < 0 ) {
bus_log_parse_error ( r ) ;
return 0 ;
}
2010-02-01 03:33:24 +01:00
2013-11-19 21:12:59 +01:00
manager_notify_cgroup_empty ( m , cgroup ) ;
return 0 ;
}
2010-02-01 03:33:24 +01:00
2015-04-29 18:35:10 +02:00
static int signal_disconnected ( sd_bus_message * message , void * userdata , sd_bus_error * error ) {
2013-11-19 21:12:59 +01:00
Manager * m = userdata ;
2015-04-29 18:35:10 +02:00
sd_bus * bus ;
2010-02-01 03:33:24 +01:00
2013-11-19 21:12:59 +01:00
assert ( message ) ;
assert ( m ) ;
2015-04-29 18:35:10 +02:00
assert_se ( bus = sd_bus_message_get_bus ( message ) ) ;
2010-02-01 03:33:24 +01:00
2013-11-19 21:12:59 +01:00
if ( bus = = m - > api_bus )
2018-02-07 15:00:32 +01:00
bus_done_api ( m ) ;
2013-11-19 21:12:59 +01:00
if ( bus = = m - > system_bus )
2018-02-07 15:00:32 +01:00
bus_done_system ( m ) ;
2013-11-19 21:12:59 +01:00
if ( set_remove ( m - > private_buses , bus ) ) {
log_debug ( " Got disconnect on private connection. " ) ;
destroy_bus ( m , & bus ) ;
2010-02-01 03:33:24 +01:00
}
2013-11-19 21:12:59 +01:00
return 0 ;
2010-02-01 03:33:24 +01:00
}
2015-04-29 18:35:10 +02:00
static int signal_activation_request ( sd_bus_message * message , void * userdata , sd_bus_error * ret_error ) {
tree-wide: expose "p"-suffix unref calls in public APIs to make gcc cleanup easy
GLIB has recently started to officially support the gcc cleanup
attribute in its public API, hence let's do the same for our APIs.
With this patch we'll define an xyz_unrefp() call for each public
xyz_unref() call, to make it easy to use inside a
__attribute__((cleanup())) expression. Then, all code is ported over to
make use of this.
The new calls are also documented in the man pages, with examples how to
use them (well, I only added docs where the _unref() call itself already
had docs, and the examples, only cover sd_bus_unrefp() and
sd_event_unrefp()).
This also renames sd_lldp_free() to sd_lldp_unref(), since that's how we
tend to call our destructors these days.
Note that this defines no public macro that wraps gcc's attribute and
makes it easier to use. While I think it's our duty in the library to
make our stuff easy to use, I figure it's not our duty to make gcc's own
features easy to use on its own. Most likely, client code which wants to
make use of this should define its own:
#define _cleanup_(function) __attribute__((cleanup(function)))
Or similar, to make the gcc feature easier to use.
Making this logic public has the benefit that we can remove three header
files whose only purpose was to define these functions internally.
See #2008.
2015-11-27 19:13:45 +01:00
_cleanup_ ( sd_bus_error_free ) sd_bus_error error = SD_BUS_ERROR_NULL ;
_cleanup_ ( sd_bus_message_unrefp ) sd_bus_message * reply = NULL ;
2013-11-19 21:12:59 +01:00
Manager * m = userdata ;
const char * name ;
Unit * u ;
int r ;
2010-02-01 03:33:24 +01:00
2013-11-19 21:12:59 +01:00
assert ( message ) ;
2010-02-01 03:33:24 +01:00
assert ( m ) ;
2013-11-19 21:12:59 +01:00
r = sd_bus_message_read ( message , " s " , & name ) ;
if ( r < 0 ) {
bus_log_parse_error ( r ) ;
return 0 ;
}
2010-02-01 03:33:24 +01:00
2013-11-19 21:12:59 +01:00
if ( manager_unit_inactive_or_pending ( m , SPECIAL_DBUS_SERVICE ) | |
manager_unit_inactive_or_pending ( m , SPECIAL_DBUS_SOCKET ) ) {
r = sd_bus_error_setf ( & error , BUS_ERROR_SHUTTING_DOWN , " Refusing activation, D-Bus is shutting down. " ) ;
goto failed ;
}
2010-02-01 03:33:24 +01:00
2013-11-19 21:12:59 +01:00
r = manager_load_unit ( m , name , NULL , & error , & u ) ;
if ( r < 0 )
goto failed ;
2010-02-01 03:33:24 +01:00
2013-11-19 21:12:59 +01:00
if ( u - > refuse_manual_start ) {
2017-01-24 04:06:05 +01:00
r = sd_bus_error_setf ( & error , BUS_ERROR_ONLY_BY_DEPENDENCY , " Operation refused, %s may be requested by dependency only (it is configured to refuse manual start/stop). " , u - > id ) ;
2013-11-19 21:12:59 +01:00
goto failed ;
2010-02-01 03:33:24 +01:00
}
2015-11-12 19:52:31 +01:00
r = manager_add_job ( m , JOB_START , u , JOB_REPLACE , & error , NULL ) ;
2013-11-19 21:12:59 +01:00
if ( r < 0 )
goto failed ;
2010-02-01 03:33:24 +01:00
2013-11-19 21:12:59 +01:00
/* Successfully queued, that's it for us */
2010-02-01 03:33:24 +01:00
return 0 ;
2013-11-19 21:12:59 +01:00
failed :
if ( ! sd_bus_error_is_set ( & error ) )
sd_bus_error_set_errno ( & error , r ) ;
2010-02-01 03:33:24 +01:00
2013-11-19 21:12:59 +01:00
log_debug ( " D-Bus activation failed for %s: %s " , name , bus_error_message ( & error , r ) ) ;
2010-02-01 03:33:24 +01:00
2015-04-29 19:10:09 +02:00
r = sd_bus_message_new_signal ( sd_bus_message_get_bus ( message ) , & reply , " /org/freedesktop/systemd1 " , " org.freedesktop.systemd1.Activator " , " ActivationFailure " ) ;
2013-11-19 21:12:59 +01:00
if ( r < 0 ) {
bus_log_create_error ( r ) ;
return 0 ;
}
2013-11-21 02:14:05 +01:00
r = sd_bus_message_append ( reply , " sss " , name , error . name , error . message ) ;
2013-11-19 21:12:59 +01:00
if ( r < 0 ) {
bus_log_create_error ( r ) ;
return 0 ;
}
2015-04-29 19:10:09 +02:00
r = sd_bus_send_to ( NULL , reply , " org.freedesktop.DBus " , NULL ) ;
2014-11-28 18:23:20 +01:00
if ( r < 0 )
return log_error_errno ( r , " Failed to respond with to bus activation request: %m " ) ;
2010-02-01 03:33:24 +01:00
2013-11-19 21:12:59 +01:00
return 0 ;
2010-02-01 03:33:24 +01:00
}
2017-10-03 10:41:51 +02:00
# if HAVE_SELINUX
2015-04-29 18:35:10 +02:00
static int mac_selinux_filter ( sd_bus_message * message , void * userdata , sd_bus_error * error ) {
2013-11-21 23:36:51 +01:00
Manager * m = userdata ;
const char * verb , * path ;
Unit * u = NULL ;
Job * j ;
int r ;
assert ( message ) ;
/* Our own method calls are all protected individually with
* selinux checks , but the built - in interfaces need to be
* protected too . */
if ( sd_bus_message_is_method_call ( message , " org.freedesktop.DBus.Properties " , " Set " ) )
verb = " reload " ;
else if ( sd_bus_message_is_method_call ( message , " org.freedesktop.DBus.Introspectable " , NULL ) | |
sd_bus_message_is_method_call ( message , " org.freedesktop.DBus.Properties " , NULL ) | |
sd_bus_message_is_method_call ( message , " org.freedesktop.DBus.ObjectManager " , NULL ) | |
sd_bus_message_is_method_call ( message , " org.freedesktop.DBus.Peer " , NULL ) )
verb = " status " ;
else
return 0 ;
path = sd_bus_message_get_path ( message ) ;
if ( object_path_startswith ( " /org/freedesktop/systemd1 " , path ) ) {
2014-10-24 14:15:25 +02:00
r = mac_selinux_access_check ( message , verb , error ) ;
2013-11-21 23:36:51 +01:00
if ( r < 0 )
return r ;
return 0 ;
}
if ( streq_ptr ( path , " /org/freedesktop/systemd1/unit/self " ) ) {
tree-wide: expose "p"-suffix unref calls in public APIs to make gcc cleanup easy
GLIB has recently started to officially support the gcc cleanup
attribute in its public API, hence let's do the same for our APIs.
With this patch we'll define an xyz_unrefp() call for each public
xyz_unref() call, to make it easy to use inside a
__attribute__((cleanup())) expression. Then, all code is ported over to
make use of this.
The new calls are also documented in the man pages, with examples how to
use them (well, I only added docs where the _unref() call itself already
had docs, and the examples, only cover sd_bus_unrefp() and
sd_event_unrefp()).
This also renames sd_lldp_free() to sd_lldp_unref(), since that's how we
tend to call our destructors these days.
Note that this defines no public macro that wraps gcc's attribute and
makes it easier to use. While I think it's our duty in the library to
make our stuff easy to use, I figure it's not our duty to make gcc's own
features easy to use on its own. Most likely, client code which wants to
make use of this should define its own:
#define _cleanup_(function) __attribute__((cleanup(function)))
Or similar, to make the gcc feature easier to use.
Making this logic public has the benefit that we can remove three header
files whose only purpose was to define these functions internally.
See #2008.
2015-11-27 19:13:45 +01:00
_cleanup_ ( sd_bus_creds_unrefp ) sd_bus_creds * creds = NULL ;
2013-11-21 23:36:51 +01:00
pid_t pid ;
2013-11-28 17:50:02 +01:00
r = sd_bus_query_sender_creds ( message , SD_BUS_CREDS_PID , & creds ) ;
if ( r < 0 )
return 0 ;
r = sd_bus_creds_get_pid ( creds , & pid ) ;
2013-11-21 23:36:51 +01:00
if ( r < 0 )
return 0 ;
u = manager_get_unit_by_pid ( m , pid ) ;
} else {
r = manager_get_job_from_dbus_path ( m , path , & j ) ;
if ( r > = 0 )
u = j - > unit ;
else
manager_load_unit_from_dbus_path ( m , path , NULL , & u ) ;
}
if ( ! u )
return 0 ;
2014-10-24 14:15:25 +02:00
r = mac_selinux_unit_access_check ( u , message , verb , error ) ;
2013-11-21 23:36:51 +01:00
if ( r < 0 )
return r ;
return 0 ;
}
2013-12-12 15:58:31 +01:00
# endif
2013-11-21 23:36:51 +01:00
2013-11-22 01:14:57 +01:00
static int bus_job_find ( sd_bus * bus , const char * path , const char * interface , void * userdata , void * * found , sd_bus_error * error ) {
2013-11-19 21:12:59 +01:00
Manager * m = userdata ;
Job * j ;
int r ;
2010-02-01 03:33:24 +01:00
2013-11-19 21:12:59 +01:00
assert ( bus ) ;
assert ( path ) ;
assert ( interface ) ;
assert ( found ) ;
2010-02-01 03:33:24 +01:00
assert ( m ) ;
2013-11-19 21:12:59 +01:00
r = manager_get_job_from_dbus_path ( m , path , & j ) ;
if ( r < 0 )
return 0 ;
2010-02-01 03:33:24 +01:00
2013-11-19 21:12:59 +01:00
* found = j ;
return 1 ;
}
2010-02-01 03:33:24 +01:00
2013-11-22 01:14:57 +01:00
static int find_unit ( Manager * m , sd_bus * bus , const char * path , Unit * * unit , sd_bus_error * error ) {
2017-02-12 19:22:18 +01:00
Unit * u = NULL ; /* just to appease gcc, initialization is not really necessary */
2013-11-19 21:12:59 +01:00
int r ;
2010-02-01 03:33:24 +01:00
2013-11-19 21:12:59 +01:00
assert ( m ) ;
assert ( bus ) ;
assert ( path ) ;
2010-02-01 03:33:24 +01:00
2013-11-19 21:12:59 +01:00
if ( streq_ptr ( path , " /org/freedesktop/systemd1/unit/self " ) ) {
tree-wide: expose "p"-suffix unref calls in public APIs to make gcc cleanup easy
GLIB has recently started to officially support the gcc cleanup
attribute in its public API, hence let's do the same for our APIs.
With this patch we'll define an xyz_unrefp() call for each public
xyz_unref() call, to make it easy to use inside a
__attribute__((cleanup())) expression. Then, all code is ported over to
make use of this.
The new calls are also documented in the man pages, with examples how to
use them (well, I only added docs where the _unref() call itself already
had docs, and the examples, only cover sd_bus_unrefp() and
sd_event_unrefp()).
This also renames sd_lldp_free() to sd_lldp_unref(), since that's how we
tend to call our destructors these days.
Note that this defines no public macro that wraps gcc's attribute and
makes it easier to use. While I think it's our duty in the library to
make our stuff easy to use, I figure it's not our duty to make gcc's own
features easy to use on its own. Most likely, client code which wants to
make use of this should define its own:
#define _cleanup_(function) __attribute__((cleanup(function)))
Or similar, to make the gcc feature easier to use.
Making this logic public has the benefit that we can remove three header
files whose only purpose was to define these functions internally.
See #2008.
2015-11-27 19:13:45 +01:00
_cleanup_ ( sd_bus_creds_unrefp ) sd_bus_creds * creds = NULL ;
2013-11-19 21:12:59 +01:00
sd_bus_message * message ;
pid_t pid ;
2010-02-01 03:33:24 +01:00
2014-05-15 01:15:30 +02:00
message = sd_bus_get_current_message ( bus ) ;
2013-11-19 21:12:59 +01:00
if ( ! message )
2013-11-22 01:14:57 +01:00
return 0 ;
2010-02-01 03:33:24 +01:00
2013-11-28 17:50:02 +01:00
r = sd_bus_query_sender_creds ( message , SD_BUS_CREDS_PID , & creds ) ;
2013-11-19 21:12:59 +01:00
if ( r < 0 )
2013-11-28 17:50:02 +01:00
return r ;
r = sd_bus_creds_get_pid ( creds , & pid ) ;
if ( r < 0 )
return r ;
2010-02-01 03:33:24 +01:00
2013-11-19 21:12:59 +01:00
u = manager_get_unit_by_pid ( m , pid ) ;
2017-02-12 19:22:18 +01:00
if ( ! u )
return 0 ;
2013-11-19 21:12:59 +01:00
} else {
2013-11-22 01:14:57 +01:00
r = manager_load_unit_from_dbus_path ( m , path , error , & u ) ;
2013-11-19 21:12:59 +01:00
if ( r < 0 )
2013-11-22 01:14:57 +01:00
return 0 ;
2017-02-12 19:22:18 +01:00
assert ( u ) ;
2013-11-19 21:12:59 +01:00
}
2010-02-01 03:33:24 +01:00
2013-11-22 01:14:57 +01:00
* unit = u ;
return 1 ;
2010-02-01 03:33:24 +01:00
}
2013-11-22 01:14:57 +01:00
static int bus_unit_find ( sd_bus * bus , const char * path , const char * interface , void * userdata , void * * found , sd_bus_error * error ) {
2013-11-19 21:12:59 +01:00
Manager * m = userdata ;
2010-02-01 03:33:24 +01:00
2013-11-19 21:12:59 +01:00
assert ( bus ) ;
assert ( path ) ;
assert ( interface ) ;
assert ( found ) ;
2010-02-01 03:33:24 +01:00
assert ( m ) ;
2013-11-22 01:14:57 +01:00
return find_unit ( m , bus , path , ( Unit * * ) found , error ) ;
2010-02-01 03:33:24 +01:00
}
2013-11-22 01:14:57 +01:00
static int bus_unit_interface_find ( sd_bus * bus , const char * path , const char * interface , void * userdata , void * * found , sd_bus_error * error ) {
2013-11-19 21:12:59 +01:00
Manager * m = userdata ;
Unit * u ;
2013-11-22 01:14:57 +01:00
int r ;
2010-02-01 03:33:24 +01:00
2013-11-19 21:12:59 +01:00
assert ( bus ) ;
assert ( path ) ;
assert ( interface ) ;
assert ( found ) ;
2010-02-01 03:33:24 +01:00
assert ( m ) ;
2013-11-22 01:14:57 +01:00
r = find_unit ( m , bus , path , & u , error ) ;
if ( r < = 0 )
return r ;
2011-05-23 21:36:52 +02:00
2015-08-27 22:30:43 +02:00
if ( ! streq_ptr ( interface , unit_dbus_interface_from_type ( u - > type ) ) )
2013-11-19 21:12:59 +01:00
return 0 ;
2010-02-01 03:33:24 +01:00
2013-11-19 21:12:59 +01:00
* found = u ;
return 1 ;
2010-02-01 03:33:24 +01:00
}
2013-11-22 01:14:57 +01:00
static int bus_unit_cgroup_find ( sd_bus * bus , const char * path , const char * interface , void * userdata , void * * found , sd_bus_error * error ) {
2013-11-19 21:12:59 +01:00
Manager * m = userdata ;
Unit * u ;
2013-11-22 01:14:57 +01:00
int r ;
2010-02-05 00:38:41 +01:00
2013-11-19 21:12:59 +01:00
assert ( bus ) ;
assert ( path ) ;
assert ( interface ) ;
assert ( found ) ;
2010-02-05 00:38:41 +01:00
assert ( m ) ;
2013-11-22 01:14:57 +01:00
r = find_unit ( m , bus , path , & u , error ) ;
if ( r < = 0 )
return r ;
2010-04-15 23:16:16 +02:00
2015-08-27 22:30:43 +02:00
if ( ! streq_ptr ( interface , unit_dbus_interface_from_type ( u - > type ) ) )
2013-11-19 21:12:59 +01:00
return 0 ;
2010-04-15 23:16:16 +02:00
2015-08-28 17:14:59 +02:00
if ( ! UNIT_HAS_CGROUP_CONTEXT ( u ) )
2013-11-19 21:12:59 +01:00
return 0 ;
2010-06-02 04:24:16 +02:00
2013-11-19 21:12:59 +01:00
* found = u ;
return 1 ;
}
2010-06-02 04:24:16 +02:00
2013-11-22 01:14:57 +01:00
static int bus_cgroup_context_find ( sd_bus * bus , const char * path , const char * interface , void * userdata , void * * found , sd_bus_error * error ) {
2013-11-19 21:12:59 +01:00
Manager * m = userdata ;
CGroupContext * c ;
Unit * u ;
2013-11-22 01:14:57 +01:00
int r ;
2010-06-07 04:15:37 +02:00
2013-11-19 21:12:59 +01:00
assert ( bus ) ;
assert ( path ) ;
assert ( interface ) ;
assert ( found ) ;
assert ( m ) ;
2010-06-02 04:24:16 +02:00
2013-11-22 01:14:57 +01:00
r = find_unit ( m , bus , path , & u , error ) ;
if ( r < = 0 )
return r ;
2010-06-02 04:24:16 +02:00
2015-08-27 22:30:43 +02:00
if ( ! streq_ptr ( interface , unit_dbus_interface_from_type ( u - > type ) ) )
2013-11-19 21:12:59 +01:00
return 0 ;
2010-06-02 04:24:16 +02:00
2013-11-19 21:12:59 +01:00
c = unit_get_cgroup_context ( u ) ;
if ( ! c )
return 0 ;
2010-02-05 00:38:41 +01:00
2013-11-19 21:12:59 +01:00
* found = c ;
return 1 ;
}
2010-06-02 04:24:16 +02:00
2013-11-22 01:14:57 +01:00
static int bus_exec_context_find ( sd_bus * bus , const char * path , const char * interface , void * userdata , void * * found , sd_bus_error * error ) {
2013-11-19 21:12:59 +01:00
Manager * m = userdata ;
ExecContext * c ;
Unit * u ;
2013-11-22 01:14:57 +01:00
int r ;
2010-06-02 04:24:16 +02:00
2013-11-19 21:12:59 +01:00
assert ( bus ) ;
assert ( path ) ;
assert ( interface ) ;
assert ( found ) ;
assert ( m ) ;
2010-06-02 04:24:16 +02:00
2013-11-22 01:14:57 +01:00
r = find_unit ( m , bus , path , & u , error ) ;
if ( r < = 0 )
return r ;
2010-06-02 04:24:16 +02:00
2015-08-27 22:30:43 +02:00
if ( ! streq_ptr ( interface , unit_dbus_interface_from_type ( u - > type ) ) )
2013-11-19 21:12:59 +01:00
return 0 ;
2010-06-02 04:24:16 +02:00
2013-11-19 21:12:59 +01:00
c = unit_get_exec_context ( u ) ;
if ( ! c )
return 0 ;
2010-06-02 04:24:16 +02:00
2013-11-19 21:12:59 +01:00
* found = c ;
return 1 ;
2010-02-05 00:38:41 +01:00
}
2013-11-22 01:14:57 +01:00
static int bus_kill_context_find ( sd_bus * bus , const char * path , const char * interface , void * userdata , void * * found , sd_bus_error * error ) {
2013-11-19 21:12:59 +01:00
Manager * m = userdata ;
KillContext * c ;
Unit * u ;
2013-11-22 01:14:57 +01:00
int r ;
2010-03-31 16:29:55 +02:00
2013-11-19 21:12:59 +01:00
assert ( bus ) ;
assert ( path ) ;
assert ( interface ) ;
assert ( found ) ;
2010-03-31 16:29:55 +02:00
assert ( m ) ;
2013-11-22 01:14:57 +01:00
r = find_unit ( m , bus , path , & u , error ) ;
if ( r < = 0 )
return r ;
2010-03-31 16:29:55 +02:00
2015-08-27 22:30:43 +02:00
if ( ! streq_ptr ( interface , unit_dbus_interface_from_type ( u - > type ) ) )
2013-11-19 21:12:59 +01:00
return 0 ;
2010-03-31 16:29:55 +02:00
2013-11-19 21:12:59 +01:00
c = unit_get_kill_context ( u ) ;
if ( ! c )
return 0 ;
2010-09-03 01:45:14 +02:00
2013-11-19 21:12:59 +01:00
* found = c ;
return 1 ;
}
2010-03-31 16:29:55 +02:00
2013-11-22 01:14:57 +01:00
static int bus_job_enumerate ( sd_bus * bus , const char * path , void * userdata , char * * * nodes , sd_bus_error * error ) {
2017-01-25 04:21:16 +01:00
_cleanup_strv_free_ char * * l = NULL ;
2013-11-19 21:12:59 +01:00
Manager * m = userdata ;
unsigned k = 0 ;
Iterator i ;
Job * j ;
2010-03-31 16:29:55 +02:00
2013-11-19 21:12:59 +01:00
l = new0 ( char * , hashmap_size ( m - > jobs ) + 1 ) ;
if ( ! l )
return - ENOMEM ;
2010-03-31 16:29:55 +02:00
2013-11-19 21:12:59 +01:00
HASHMAP_FOREACH ( j , m - > jobs , i ) {
l [ k ] = job_dbus_path ( j ) ;
if ( ! l [ k ] )
return - ENOMEM ;
2010-06-19 03:04:04 +02:00
2013-11-19 21:12:59 +01:00
k + + ;
}
2010-06-19 03:04:04 +02:00
2013-11-19 21:12:59 +01:00
assert ( hashmap_size ( m - > jobs ) = = k ) ;
2010-08-06 03:21:50 +02:00
2018-03-22 16:53:26 +01:00
* nodes = TAKE_PTR ( l ) ;
2010-06-19 03:04:04 +02:00
2013-11-19 21:12:59 +01:00
return k ;
}
2010-09-03 01:45:14 +02:00
2013-11-22 01:14:57 +01:00
static int bus_unit_enumerate ( sd_bus * bus , const char * path , void * userdata , char * * * nodes , sd_bus_error * error ) {
2017-01-25 04:21:16 +01:00
_cleanup_strv_free_ char * * l = NULL ;
2013-11-19 21:12:59 +01:00
Manager * m = userdata ;
unsigned k = 0 ;
Iterator i ;
Unit * u ;
2010-08-06 03:21:50 +02:00
2013-11-19 21:12:59 +01:00
l = new0 ( char * , hashmap_size ( m - > units ) + 1 ) ;
if ( ! l )
return - ENOMEM ;
2010-09-03 01:45:14 +02:00
2013-11-19 21:12:59 +01:00
HASHMAP_FOREACH ( u , m - > units , i ) {
l [ k ] = unit_dbus_path ( u ) ;
if ( ! l [ k ] )
return - ENOMEM ;
2010-09-03 01:45:14 +02:00
2013-11-19 21:12:59 +01:00
k + + ;
2010-08-06 03:21:50 +02:00
}
2018-03-22 16:53:26 +01:00
* nodes = TAKE_PTR ( l ) ;
2010-06-19 03:04:04 +02:00
2013-11-19 21:12:59 +01:00
return k ;
2010-06-19 03:04:04 +02:00
}
2013-11-19 21:12:59 +01:00
static int bus_setup_api_vtables ( Manager * m , sd_bus * bus ) {
UnitType t ;
int r ;
2010-06-19 03:04:04 +02:00
2010-02-01 03:33:24 +01:00
assert ( m ) ;
2013-11-19 21:12:59 +01:00
assert ( bus ) ;
2010-02-01 03:33:24 +01:00
2017-10-03 10:41:51 +02:00
# if HAVE_SELINUX
2014-10-24 14:15:25 +02:00
r = sd_bus_add_filter ( bus , NULL , mac_selinux_filter , m ) ;
2014-11-28 18:23:20 +01:00
if ( r < 0 )
return log_error_errno ( r , " Failed to add SELinux access filter: %m " ) ;
2013-12-12 15:58:31 +01:00
# endif
2013-11-21 23:36:51 +01:00
2014-05-15 01:15:30 +02:00
r = sd_bus_add_object_vtable ( bus , NULL , " /org/freedesktop/systemd1 " , " org.freedesktop.systemd1.Manager " , bus_manager_vtable , m ) ;
2014-11-28 18:23:20 +01:00
if ( r < 0 )
return log_error_errno ( r , " Failed to register Manager vtable: %m " ) ;
2010-04-21 03:27:44 +02:00
2014-05-15 01:15:30 +02:00
r = sd_bus_add_fallback_vtable ( bus , NULL , " /org/freedesktop/systemd1/job " , " org.freedesktop.systemd1.Job " , bus_job_vtable , bus_job_find , m ) ;
2014-11-28 18:23:20 +01:00
if ( r < 0 )
return log_error_errno ( r , " Failed to register Job vtable: %m " ) ;
2010-02-05 00:38:41 +01:00
2014-05-15 01:15:30 +02:00
r = sd_bus_add_node_enumerator ( bus , NULL , " /org/freedesktop/systemd1/job " , bus_job_enumerate , m ) ;
2014-11-28 18:23:20 +01:00
if ( r < 0 )
return log_error_errno ( r , " Failed to add job enumerator: %m " ) ;
2010-04-04 22:48:47 +02:00
2014-05-15 01:15:30 +02:00
r = sd_bus_add_fallback_vtable ( bus , NULL , " /org/freedesktop/systemd1/unit " , " org.freedesktop.systemd1.Unit " , bus_unit_vtable , bus_unit_find , m ) ;
2014-11-28 18:23:20 +01:00
if ( r < 0 )
return log_error_errno ( r , " Failed to register Unit vtable: %m " ) ;
2010-04-04 22:48:47 +02:00
2014-05-15 01:15:30 +02:00
r = sd_bus_add_node_enumerator ( bus , NULL , " /org/freedesktop/systemd1/unit " , bus_unit_enumerate , m ) ;
2014-11-28 18:23:20 +01:00
if ( r < 0 )
return log_error_errno ( r , " Failed to add job enumerator: %m " ) ;
2010-04-04 22:48:47 +02:00
2013-11-19 21:12:59 +01:00
for ( t = 0 ; t < _UNIT_TYPE_MAX ; t + + ) {
2015-08-27 22:30:43 +02:00
const char * interface ;
assert_se ( interface = unit_dbus_interface_from_type ( t ) ) ;
r = sd_bus_add_fallback_vtable ( bus , NULL , " /org/freedesktop/systemd1/unit " , interface , unit_vtable [ t ] - > bus_vtable , bus_unit_interface_find , m ) ;
2014-11-28 18:23:20 +01:00
if ( r < 0 )
2015-08-27 22:30:43 +02:00
return log_error_errno ( r , " Failed to register type specific vtable for %s: %m " , interface ) ;
2010-04-04 22:48:47 +02:00
2013-11-19 21:12:59 +01:00
if ( unit_vtable [ t ] - > cgroup_context_offset > 0 ) {
2015-08-27 22:30:43 +02:00
r = sd_bus_add_fallback_vtable ( bus , NULL , " /org/freedesktop/systemd1/unit " , interface , bus_unit_cgroup_vtable , bus_unit_cgroup_find , m ) ;
2014-11-28 18:23:20 +01:00
if ( r < 0 )
2015-08-27 22:30:43 +02:00
return log_error_errno ( r , " Failed to register control group unit vtable for %s: %m " , interface ) ;
2010-04-04 22:48:47 +02:00
2015-08-27 22:30:43 +02:00
r = sd_bus_add_fallback_vtable ( bus , NULL , " /org/freedesktop/systemd1/unit " , interface , bus_cgroup_vtable , bus_cgroup_context_find , m ) ;
2014-11-28 18:23:20 +01:00
if ( r < 0 )
2015-08-27 22:30:43 +02:00
return log_error_errno ( r , " Failed to register control group vtable for %s: %m " , interface ) ;
2010-04-04 22:48:47 +02:00
}
2013-11-19 21:12:59 +01:00
if ( unit_vtable [ t ] - > exec_context_offset > 0 ) {
2015-08-27 22:30:43 +02:00
r = sd_bus_add_fallback_vtable ( bus , NULL , " /org/freedesktop/systemd1/unit " , interface , bus_exec_vtable , bus_exec_context_find , m ) ;
2014-11-28 18:23:20 +01:00
if ( r < 0 )
2015-08-27 22:30:43 +02:00
return log_error_errno ( r , " Failed to register execute vtable for %s: %m " , interface ) ;
2013-11-19 21:12:59 +01:00
}
2010-04-04 22:48:47 +02:00
2013-11-19 21:12:59 +01:00
if ( unit_vtable [ t ] - > kill_context_offset > 0 ) {
2015-08-27 22:30:43 +02:00
r = sd_bus_add_fallback_vtable ( bus , NULL , " /org/freedesktop/systemd1/unit " , interface , bus_kill_vtable , bus_kill_context_find , m ) ;
2014-11-28 18:23:20 +01:00
if ( r < 0 )
2015-08-27 22:30:43 +02:00
return log_error_errno ( r , " Failed to register kill vtable for %s: %m " , interface ) ;
2013-11-19 21:12:59 +01:00
}
2010-04-04 22:48:47 +02:00
}
2013-11-19 21:12:59 +01:00
return 0 ;
2010-04-04 22:48:47 +02:00
}
2013-11-19 21:12:59 +01:00
static int bus_setup_disconnected_match ( Manager * m , sd_bus * bus ) {
int r ;
2010-04-04 22:48:47 +02:00
2013-11-19 21:12:59 +01:00
assert ( m ) ;
assert ( bus ) ;
2010-04-04 22:48:47 +02:00
2017-12-19 12:29:04 +01:00
r = sd_bus_match_signal_async (
2013-11-19 21:12:59 +01:00
bus ,
2014-05-15 01:15:30 +02:00
NULL ,
2017-12-19 12:29:04 +01:00
" org.freedesktop.DBus.Local " ,
" /org/freedesktop/DBus/Local " ,
" org.freedesktop.DBus.Local " ,
" Disconnected " ,
signal_disconnected , NULL , m ) ;
2014-11-28 18:23:20 +01:00
if ( r < 0 )
2017-12-19 12:29:04 +01:00
return log_error_errno ( r , " Failed to request match for Disconnected message: %m " ) ;
2010-04-15 23:16:16 +02:00
2013-11-19 21:12:59 +01:00
return 0 ;
2010-02-01 03:33:24 +01:00
}
2013-11-19 21:12:59 +01:00
static int bus_on_connection ( sd_event_source * s , int fd , uint32_t revents , void * userdata ) {
tree-wide: expose "p"-suffix unref calls in public APIs to make gcc cleanup easy
GLIB has recently started to officially support the gcc cleanup
attribute in its public API, hence let's do the same for our APIs.
With this patch we'll define an xyz_unrefp() call for each public
xyz_unref() call, to make it easy to use inside a
__attribute__((cleanup())) expression. Then, all code is ported over to
make use of this.
The new calls are also documented in the man pages, with examples how to
use them (well, I only added docs where the _unref() call itself already
had docs, and the examples, only cover sd_bus_unrefp() and
sd_event_unrefp()).
This also renames sd_lldp_free() to sd_lldp_unref(), since that's how we
tend to call our destructors these days.
Note that this defines no public macro that wraps gcc's attribute and
makes it easier to use. While I think it's our duty in the library to
make our stuff easy to use, I figure it's not our duty to make gcc's own
features easy to use on its own. Most likely, client code which wants to
make use of this should define its own:
#define _cleanup_(function) __attribute__((cleanup(function)))
Or similar, to make the gcc feature easier to use.
Making this logic public has the benefit that we can remove three header
files whose only purpose was to define these functions internally.
See #2008.
2015-11-27 19:13:45 +01:00
_cleanup_ ( sd_bus_unrefp ) sd_bus * bus = NULL ;
2013-11-19 21:12:59 +01:00
_cleanup_close_ int nfd = - 1 ;
2010-06-04 22:03:22 +02:00
Manager * m = userdata ;
2013-11-19 21:12:59 +01:00
sd_id128_t id ;
int r ;
2010-06-04 22:03:22 +02:00
2013-11-19 21:12:59 +01:00
assert ( s ) ;
2010-06-04 22:03:22 +02:00
assert ( m ) ;
2013-11-19 21:12:59 +01:00
nfd = accept4 ( fd , NULL , NULL , SOCK_NONBLOCK | SOCK_CLOEXEC ) ;
if ( nfd < 0 ) {
2014-11-28 19:29:59 +01:00
log_warning_errno ( errno , " Failed to accept private connection, ignoring: %m " ) ;
2013-11-19 21:12:59 +01:00
return 0 ;
}
2010-06-04 22:03:22 +02:00
2013-11-19 21:12:59 +01:00
if ( set_size ( m - > private_buses ) > = CONNECTIONS_MAX ) {
log_warning ( " Too many concurrent connections, refusing " ) ;
return 0 ;
}
2010-06-04 22:03:22 +02:00
2014-08-13 01:00:18 +02:00
r = set_ensure_allocated ( & m - > private_buses , NULL ) ;
2013-11-19 21:12:59 +01:00
if ( r < 0 ) {
log_oom ( ) ;
return 0 ;
}
2010-06-04 22:03:22 +02:00
2013-11-19 21:12:59 +01:00
r = sd_bus_new ( & bus ) ;
if ( r < 0 ) {
2014-11-28 13:19:16 +01:00
log_warning_errno ( r , " Failed to allocate new private connection bus: %m " ) ;
2013-11-19 21:12:59 +01:00
return 0 ;
}
2010-06-04 22:03:22 +02:00
2018-02-07 22:30:17 +01:00
( void ) sd_bus_set_description ( bus , " private-bus-connection " ) ;
2013-11-19 21:12:59 +01:00
r = sd_bus_set_fd ( bus , nfd , nfd ) ;
if ( r < 0 ) {
2014-11-28 13:19:16 +01:00
log_warning_errno ( r , " Failed to set fd on new connection bus: %m " ) ;
2013-11-19 21:12:59 +01:00
return 0 ;
}
2010-06-04 22:03:22 +02:00
2013-11-19 21:12:59 +01:00
nfd = - 1 ;
2010-06-04 22:03:22 +02:00
2013-11-19 21:12:59 +01:00
r = bus_check_peercred ( bus ) ;
if ( r < 0 ) {
2014-11-28 13:19:16 +01:00
log_warning_errno ( r , " Incoming private connection from unprivileged client, refusing: %m " ) ;
2013-11-19 21:12:59 +01:00
return 0 ;
}
2010-06-04 22:03:22 +02:00
2013-11-19 21:12:59 +01:00
assert_se ( sd_id128_randomize ( & id ) > = 0 ) ;
2010-06-04 22:03:22 +02:00
2013-11-19 21:12:59 +01:00
r = sd_bus_set_server ( bus , 1 , id ) ;
if ( r < 0 ) {
2014-11-28 13:19:16 +01:00
log_warning_errno ( r , " Failed to enable server support for new connection bus: %m " ) ;
2013-11-19 21:12:59 +01:00
return 0 ;
}
2010-06-04 22:03:22 +02:00
2015-04-23 00:37:47 +02:00
r = sd_bus_negotiate_creds ( bus , 1 ,
SD_BUS_CREDS_PID | SD_BUS_CREDS_UID |
SD_BUS_CREDS_EUID | SD_BUS_CREDS_EFFECTIVE_CAPS |
SD_BUS_CREDS_SELINUX_CONTEXT ) ;
if ( r < 0 ) {
log_warning_errno ( r , " Failed to enable credentials for new connection: %m " ) ;
return 0 ;
}
2017-12-20 19:43:05 +01:00
r = sd_bus_set_sender ( bus , " org.freedesktop.systemd1 " ) ;
if ( r < 0 ) {
log_warning_errno ( r , " Failed to set direct connection sender: %m " ) ;
return 0 ;
}
2013-11-19 21:12:59 +01:00
r = sd_bus_start ( bus ) ;
if ( r < 0 ) {
2014-11-28 13:19:16 +01:00
log_warning_errno ( r , " Failed to start new connection bus: %m " ) ;
2013-11-19 21:12:59 +01:00
return 0 ;
2010-06-04 22:03:22 +02:00
}
2013-11-19 21:12:59 +01:00
r = sd_bus_attach_event ( bus , m - > event , SD_EVENT_PRIORITY_NORMAL ) ;
if ( r < 0 ) {
2014-11-28 13:19:16 +01:00
log_warning_errno ( r , " Failed to attach new connection bus to event loop: %m " ) ;
2013-11-19 21:12:59 +01:00
return 0 ;
2010-06-04 22:03:22 +02:00
}
2013-11-19 21:12:59 +01:00
r = bus_setup_disconnected_match ( m , bus ) ;
if ( r < 0 )
return 0 ;
2010-06-04 22:03:22 +02:00
2013-11-19 21:12:59 +01:00
r = bus_setup_api_vtables ( m , bus ) ;
if ( r < 0 ) {
2014-11-28 13:19:16 +01:00
log_warning_errno ( r , " Failed to set up API vtables on new connection bus: %m " ) ;
2013-11-19 21:12:59 +01:00
return 0 ;
}
2010-06-04 22:03:22 +02:00
2013-11-19 21:12:59 +01:00
r = set_put ( m - > private_buses , bus ) ;
if ( r < 0 ) {
2015-04-10 23:39:13 +02:00
log_warning_errno ( r , " Failed to add new connection bus to set: %m " ) ;
2013-11-19 21:12:59 +01:00
return 0 ;
2010-06-04 22:03:22 +02:00
}
2013-11-19 21:12:59 +01:00
bus = NULL ;
2010-06-04 22:03:22 +02:00
2013-11-19 21:12:59 +01:00
log_debug ( " Accepted new private connection. " ) ;
2010-06-04 22:03:22 +02:00
2010-03-31 16:29:55 +02:00
return 0 ;
}
2018-02-07 22:36:51 +01:00
static int manager_dispatch_sync_bus_names ( sd_event_source * es , void * userdata ) {
2013-12-03 18:58:18 +01:00
_cleanup_strv_free_ char * * names = NULL ;
2018-02-07 22:36:51 +01:00
Manager * m = userdata ;
core: fix bus name synchronization after daemon-reload
During daemon-reload, PID1 temporarly loses its DBus connection, so there's
a small window in which all signals sent by dbus-daemon are lost.
This is a problem, since we rely on the NameOwnerChanged signals in order to
consider a service with Type=dbus fully started or terminated, respectively.
In order to fix this, a rewrite of bus_list_names() is necessary. We used
to walk the current list of names on the bus, and blindly triggered the
bus_name_owner_change() callback on each service, providing the actual name
as current owner. This implementation has a number of problems:
* We cannot detect if the the name was moved from one owner to the other
while we were reloading
* We don't notify services which missed the name loss signal
* Providing the actual name as current owner is a hack, as the comment also
admits.
To fix this, this patch carries the following changes:
* Track the name of the current bus name owner, and (de-)serialize it
during reload. This way, we can detect changes.
* In bus_list_names(), walk the list of bus names we're interested in
first, and then see if the name is active on the bus. If it is,
check it it's still the same as it used to be, and synthesize
NameOwnerChanged signals for the name add and/or loss.
This should fully synchronize the current name list with the internal
state of all services.
2015-12-18 17:28:15 +01:00
const char * name ;
Iterator i ;
Unit * u ;
2013-11-19 21:12:59 +01:00
int r ;
2010-06-19 03:04:04 +02:00
2018-02-07 22:36:51 +01:00
assert ( es ) ;
2010-06-19 03:04:04 +02:00
assert ( m ) ;
2018-02-07 22:36:51 +01:00
assert ( m - > sync_bus_names_event_source = = es ) ;
/* First things first, destroy the defer event so that we aren't triggered again */
m - > sync_bus_names_event_source = sd_event_source_unref ( m - > sync_bus_names_event_source ) ;
/* Let's see if there's anything to do still? */
if ( ! m - > api_bus )
return 0 ;
if ( hashmap_isempty ( m - > watch_bus ) )
return 0 ;
2010-06-19 03:04:04 +02:00
2018-02-07 22:36:51 +01:00
/* OK, let's sync up the names. Let's see which names are currently on the bus. */
r = sd_bus_list_names ( m - > api_bus , & names , NULL ) ;
2014-11-28 18:23:20 +01:00
if ( r < 0 )
return log_error_errno ( r , " Failed to get initial list of names: %m " ) ;
2010-06-19 03:04:04 +02:00
core: fix bus name synchronization after daemon-reload
During daemon-reload, PID1 temporarly loses its DBus connection, so there's
a small window in which all signals sent by dbus-daemon are lost.
This is a problem, since we rely on the NameOwnerChanged signals in order to
consider a service with Type=dbus fully started or terminated, respectively.
In order to fix this, a rewrite of bus_list_names() is necessary. We used
to walk the current list of names on the bus, and blindly triggered the
bus_name_owner_change() callback on each service, providing the actual name
as current owner. This implementation has a number of problems:
* We cannot detect if the the name was moved from one owner to the other
while we were reloading
* We don't notify services which missed the name loss signal
* Providing the actual name as current owner is a hack, as the comment also
admits.
To fix this, this patch carries the following changes:
* Track the name of the current bus name owner, and (de-)serialize it
during reload. This way, we can detect changes.
* In bus_list_names(), walk the list of bus names we're interested in
first, and then see if the name is active on the bus. If it is,
check it it's still the same as it used to be, and synthesize
NameOwnerChanged signals for the name add and/or loss.
This should fully synchronize the current name list with the internal
state of all services.
2015-12-18 17:28:15 +01:00
/* We have to synchronize the current bus names with the
* list of active services . To do this , walk the list of
* all units with bus names . */
HASHMAP_FOREACH_KEY ( u , name , m - > watch_bus , i ) {
Service * s = SERVICE ( u ) ;
assert ( s ) ;
2015-08-05 17:47:45 +02:00
core: fix bus name synchronization after daemon-reload
During daemon-reload, PID1 temporarly loses its DBus connection, so there's
a small window in which all signals sent by dbus-daemon are lost.
This is a problem, since we rely on the NameOwnerChanged signals in order to
consider a service with Type=dbus fully started or terminated, respectively.
In order to fix this, a rewrite of bus_list_names() is necessary. We used
to walk the current list of names on the bus, and blindly triggered the
bus_name_owner_change() callback on each service, providing the actual name
as current owner. This implementation has a number of problems:
* We cannot detect if the the name was moved from one owner to the other
while we were reloading
* We don't notify services which missed the name loss signal
* Providing the actual name as current owner is a hack, as the comment also
admits.
To fix this, this patch carries the following changes:
* Track the name of the current bus name owner, and (de-)serialize it
during reload. This way, we can detect changes.
* In bus_list_names(), walk the list of bus names we're interested in
first, and then see if the name is active on the bus. If it is,
check it it's still the same as it used to be, and synthesize
NameOwnerChanged signals for the name add and/or loss.
This should fully synchronize the current name list with the internal
state of all services.
2015-12-18 17:28:15 +01:00
if ( ! streq_ptr ( s - > bus_name , name ) ) {
log_unit_warning ( u , " Bus name has changed from %s → %s, ignoring. " , s - > bus_name , name ) ;
continue ;
}
/* Check if a service's bus name is in the list of currently
* active names */
if ( strv_contains ( names , name ) ) {
_cleanup_ ( sd_bus_creds_unrefp ) sd_bus_creds * creds = NULL ;
const char * unique ;
/* If it is, determine its current owner */
2018-02-07 22:36:51 +01:00
r = sd_bus_get_name_creds ( m - > api_bus , name , SD_BUS_CREDS_UNIQUE_NAME , & creds ) ;
core: fix bus name synchronization after daemon-reload
During daemon-reload, PID1 temporarly loses its DBus connection, so there's
a small window in which all signals sent by dbus-daemon are lost.
This is a problem, since we rely on the NameOwnerChanged signals in order to
consider a service with Type=dbus fully started or terminated, respectively.
In order to fix this, a rewrite of bus_list_names() is necessary. We used
to walk the current list of names on the bus, and blindly triggered the
bus_name_owner_change() callback on each service, providing the actual name
as current owner. This implementation has a number of problems:
* We cannot detect if the the name was moved from one owner to the other
while we were reloading
* We don't notify services which missed the name loss signal
* Providing the actual name as current owner is a hack, as the comment also
admits.
To fix this, this patch carries the following changes:
* Track the name of the current bus name owner, and (de-)serialize it
during reload. This way, we can detect changes.
* In bus_list_names(), walk the list of bus names we're interested in
first, and then see if the name is active on the bus. If it is,
check it it's still the same as it used to be, and synthesize
NameOwnerChanged signals for the name add and/or loss.
This should fully synchronize the current name list with the internal
state of all services.
2015-12-18 17:28:15 +01:00
if ( r < 0 ) {
2017-04-10 13:12:25 +02:00
log_full_errno ( r = = - ENXIO ? LOG_DEBUG : LOG_ERR , r , " Failed to get bus name owner %s: %m " , name ) ;
core: fix bus name synchronization after daemon-reload
During daemon-reload, PID1 temporarly loses its DBus connection, so there's
a small window in which all signals sent by dbus-daemon are lost.
This is a problem, since we rely on the NameOwnerChanged signals in order to
consider a service with Type=dbus fully started or terminated, respectively.
In order to fix this, a rewrite of bus_list_names() is necessary. We used
to walk the current list of names on the bus, and blindly triggered the
bus_name_owner_change() callback on each service, providing the actual name
as current owner. This implementation has a number of problems:
* We cannot detect if the the name was moved from one owner to the other
while we were reloading
* We don't notify services which missed the name loss signal
* Providing the actual name as current owner is a hack, as the comment also
admits.
To fix this, this patch carries the following changes:
* Track the name of the current bus name owner, and (de-)serialize it
during reload. This way, we can detect changes.
* In bus_list_names(), walk the list of bus names we're interested in
first, and then see if the name is active on the bus. If it is,
check it it's still the same as it used to be, and synthesize
NameOwnerChanged signals for the name add and/or loss.
This should fully synchronize the current name list with the internal
state of all services.
2015-12-18 17:28:15 +01:00
continue ;
}
r = sd_bus_creds_get_unique_name ( creds , & unique ) ;
if ( r < 0 ) {
2017-04-10 13:12:25 +02:00
log_full_errno ( r = = - ENXIO ? LOG_DEBUG : LOG_ERR , r , " Failed to get unique name for %s: %m " , name ) ;
core: fix bus name synchronization after daemon-reload
During daemon-reload, PID1 temporarly loses its DBus connection, so there's
a small window in which all signals sent by dbus-daemon are lost.
This is a problem, since we rely on the NameOwnerChanged signals in order to
consider a service with Type=dbus fully started or terminated, respectively.
In order to fix this, a rewrite of bus_list_names() is necessary. We used
to walk the current list of names on the bus, and blindly triggered the
bus_name_owner_change() callback on each service, providing the actual name
as current owner. This implementation has a number of problems:
* We cannot detect if the the name was moved from one owner to the other
while we were reloading
* We don't notify services which missed the name loss signal
* Providing the actual name as current owner is a hack, as the comment also
admits.
To fix this, this patch carries the following changes:
* Track the name of the current bus name owner, and (de-)serialize it
during reload. This way, we can detect changes.
* In bus_list_names(), walk the list of bus names we're interested in
first, and then see if the name is active on the bus. If it is,
check it it's still the same as it used to be, and synthesize
NameOwnerChanged signals for the name add and/or loss.
This should fully synchronize the current name list with the internal
state of all services.
2015-12-18 17:28:15 +01:00
continue ;
}
/* Now, let's compare that to the previous bus owner, and
* if it ' s still the same , all is fine , so just don ' t
* bother the service . Otherwise , the name has apparently
* changed , so synthesize a name owner changed signal . */
if ( ! streq_ptr ( unique , s - > bus_name_owner ) )
UNIT_VTABLE ( u ) - > bus_name_owner_change ( u , name , s - > bus_name_owner , unique ) ;
} else {
/* So, the name we're watching is not on the bus.
* This either means it simply hasn ' t appeared yet ,
* or it was lost during the daemon reload .
* Check if the service has a stored name owner ,
* and synthesize a name loss signal in this case . */
if ( s - > bus_name_owner )
UNIT_VTABLE ( u ) - > bus_name_owner_change ( u , name , s - > bus_name_owner , NULL ) ;
}
2015-08-05 17:47:45 +02:00
}
2010-06-19 03:04:04 +02:00
2013-11-19 21:12:59 +01:00
return 0 ;
2010-06-19 03:04:04 +02:00
}
2018-02-07 22:36:51 +01:00
int manager_enqueue_sync_bus_names ( Manager * m ) {
int r ;
assert ( m ) ;
/* Enqueues a request to synchronize the bus names in a later event loop iteration. The callers generally don't
* want us to invoke - > bus_name_owner_change ( ) unit calls from their stack frames as this might result in event
* dispatching on its own creating loops , hence we simply create a defer event for the event loop and exit . */
if ( m - > sync_bus_names_event_source )
return 0 ;
r = sd_event_add_defer ( m - > event , & m - > sync_bus_names_event_source , manager_dispatch_sync_bus_names , m ) ;
if ( r < 0 )
return log_error_errno ( r , " Failed to create bus name synchronization event: %m " ) ;
r = sd_event_source_set_priority ( m - > sync_bus_names_event_source , SD_EVENT_PRIORITY_IDLE ) ;
if ( r < 0 )
return log_error_errno ( r , " Failed to set event priority: %m " ) ;
r = sd_event_source_set_enabled ( m - > sync_bus_names_event_source , SD_EVENT_ONESHOT ) ;
if ( r < 0 )
return log_error_errno ( r , " Failed to set even to oneshot: %m " ) ;
( void ) sd_event_source_set_description ( m - > sync_bus_names_event_source , " manager-sync-bus-names " ) ;
return 0 ;
}
2013-11-19 21:12:59 +01:00
static int bus_setup_api ( Manager * m , sd_bus * bus ) {
2015-08-05 17:47:45 +02:00
Iterator i ;
char * name ;
Unit * u ;
2013-11-19 21:12:59 +01:00
int r ;
2010-04-06 16:32:07 +02:00
2013-11-19 21:12:59 +01:00
assert ( m ) ;
assert ( bus ) ;
2010-02-05 00:38:41 +01:00
2014-11-26 18:57:37 +01:00
/* Let's make sure we have enough credential bits so that we can make security and selinux decisions */
r = sd_bus_negotiate_creds ( bus , 1 ,
SD_BUS_CREDS_PID | SD_BUS_CREDS_UID |
SD_BUS_CREDS_EUID | SD_BUS_CREDS_EFFECTIVE_CAPS |
SD_BUS_CREDS_SELINUX_CONTEXT ) ;
if ( r < 0 )
2014-11-28 13:19:16 +01:00
log_warning_errno ( r , " Failed to enable credential passing, ignoring: %m " ) ;
2014-11-26 18:57:37 +01:00
2013-11-19 21:12:59 +01:00
r = bus_setup_api_vtables ( m , bus ) ;
if ( r < 0 )
return r ;
2011-12-18 14:58:10 +01:00
2015-08-05 17:47:45 +02:00
HASHMAP_FOREACH_KEY ( u , name , m - > watch_bus , i ) {
2015-10-17 16:25:10 +02:00
r = unit_install_bus_match ( u , bus , name ) ;
2015-08-05 17:47:45 +02:00
if ( r < 0 )
2015-10-15 17:39:14 +02:00
log_error_errno ( r , " Failed to subscribe to NameOwnerChanged signal for '%s': %m " , name ) ;
2015-08-05 17:47:45 +02:00
}
2013-11-19 21:12:59 +01:00
2017-12-19 12:29:04 +01:00
r = sd_bus_match_signal_async (
2013-11-19 21:12:59 +01:00
bus ,
2014-05-15 01:15:30 +02:00
NULL ,
2017-12-19 12:29:04 +01:00
" org.freedesktop.DBus " ,
" /org/freedesktop/DBus " ,
" org.freedesktop.systemd1.Activator " ,
" ActivationRequest " ,
signal_activation_request , NULL , m ) ;
2013-11-19 21:12:59 +01:00
if ( r < 0 )
2014-11-28 13:19:16 +01:00
log_warning_errno ( r , " Failed to subscribe to activation signal: %m " ) ;
2011-12-18 14:58:10 +01:00
2017-12-18 22:10:11 +01:00
/* Allow replacing of our name, to ease implementation of reexecution, where we keep the old connection open
* until after the new connection is set up and the name installed to allow clients to synchronously wait for
* reexecution to finish */
r = sd_bus_request_name_async ( bus , NULL , " org.freedesktop.systemd1 " , SD_BUS_NAME_REPLACE_EXISTING | SD_BUS_NAME_ALLOW_REPLACEMENT , NULL , NULL ) ;
2014-11-28 18:23:20 +01:00
if ( r < 0 )
2017-12-18 22:10:11 +01:00
return log_error_errno ( r , " Failed to request name: %m " ) ;
2010-09-03 01:45:14 +02:00
2013-11-19 21:12:59 +01:00
log_debug ( " Successfully connected to API bus. " ) ;
2018-02-07 22:36:51 +01:00
2010-04-06 16:32:07 +02:00
return 0 ;
}
core: rework how we connect to the bus
This removes the current bus_init() call, as it had multiple problems:
it munged handling of the three bus connections we care about (private,
"api" and system) into one, even though the conditions when which was
ready are very different. It also added redundant logging, as the
individual calls it called all logged on their own anyway.
The three calls bus_init_api(), bus_init_private() and bus_init_system()
are now made public. A new call manager_dbus_is_running() is added that
works much like manager_journal_is_running() and is a lot more careful
when checking whether dbus is around. Optionally it checks the unit's
deserialized_state rather than state, in order to accomodate for cases
where we cant to connect to the bus before deserializing the
"subscribed" list, before coldplugging the units.
manager_recheck_dbus() is added, that works a lot like
manager_recheck_journal() and is invoked in unit_notify(), i.e. when
units change state.
All in all this should make handling a bit more alike to journal
handling, and it also fixes one major bug: when running in user mode
we'll now connect to the system bus early on, without conditionalizing
this in anyway.
2018-02-07 14:52:22 +01:00
int bus_init_api ( Manager * m ) {
tree-wide: expose "p"-suffix unref calls in public APIs to make gcc cleanup easy
GLIB has recently started to officially support the gcc cleanup
attribute in its public API, hence let's do the same for our APIs.
With this patch we'll define an xyz_unrefp() call for each public
xyz_unref() call, to make it easy to use inside a
__attribute__((cleanup())) expression. Then, all code is ported over to
make use of this.
The new calls are also documented in the man pages, with examples how to
use them (well, I only added docs where the _unref() call itself already
had docs, and the examples, only cover sd_bus_unrefp() and
sd_event_unrefp()).
This also renames sd_lldp_free() to sd_lldp_unref(), since that's how we
tend to call our destructors these days.
Note that this defines no public macro that wraps gcc's attribute and
makes it easier to use. While I think it's our duty in the library to
make our stuff easy to use, I figure it's not our duty to make gcc's own
features easy to use on its own. Most likely, client code which wants to
make use of this should define its own:
#define _cleanup_(function) __attribute__((cleanup(function)))
Or similar, to make the gcc feature easier to use.
Making this logic public has the benefit that we can remove three header
files whose only purpose was to define these functions internally.
See #2008.
2015-11-27 19:13:45 +01:00
_cleanup_ ( sd_bus_unrefp ) sd_bus * bus = NULL ;
2010-04-06 16:32:07 +02:00
int r ;
2013-11-19 21:12:59 +01:00
if ( m - > api_bus )
return 0 ;
2011-12-18 14:58:10 +01:00
2013-11-19 21:12:59 +01:00
/* The API and system bus is the same if we are running in system mode */
2016-02-24 21:24:23 +01:00
if ( MANAGER_IS_SYSTEM ( m ) & & m - > system_bus )
2013-11-19 21:12:59 +01:00
bus = sd_bus_ref ( m - > system_bus ) ;
else {
2016-02-24 21:24:23 +01:00
if ( MANAGER_IS_SYSTEM ( m ) )
2013-11-19 21:12:59 +01:00
r = sd_bus_open_system ( & bus ) ;
else
r = sd_bus_open_user ( & bus ) ;
2018-01-10 17:22:12 +01:00
if ( r < 0 )
return log_error_errno ( r , " Failed to connect to API bus: %m " ) ;
2011-12-18 14:58:10 +01:00
2013-11-19 21:12:59 +01:00
r = sd_bus_attach_event ( bus , m - > event , SD_EVENT_PRIORITY_NORMAL ) ;
2018-01-10 17:22:12 +01:00
if ( r < 0 )
return log_error_errno ( r , " Failed to attach API bus to event loop: %m " ) ;
2011-12-18 14:58:10 +01:00
2013-11-19 21:12:59 +01:00
r = bus_setup_disconnected_match ( m , bus ) ;
if ( r < 0 )
2018-01-10 17:22:12 +01:00
return r ;
2011-12-18 14:58:10 +01:00
}
2013-11-19 21:12:59 +01:00
r = bus_setup_api ( m , bus ) ;
2018-01-10 17:22:12 +01:00
if ( r < 0 )
return log_error_errno ( r , " Failed to set up API bus: %m " ) ;
2011-12-18 14:58:10 +01:00
2013-11-19 21:12:59 +01:00
m - > api_bus = bus ;
bus = NULL ;
2011-12-18 14:58:10 +01:00
2018-02-07 22:36:51 +01:00
r = manager_enqueue_sync_bus_names ( m ) ;
if ( r < 0 )
return r ;
2011-12-18 14:58:10 +01:00
return 0 ;
}
2013-11-19 21:12:59 +01:00
static int bus_setup_system ( Manager * m , sd_bus * bus ) {
int r ;
2011-12-18 14:58:10 +01:00
2013-11-19 21:12:59 +01:00
assert ( m ) ;
assert ( bus ) ;
2011-12-18 14:58:10 +01:00
2016-05-04 20:43:23 +02:00
/* if we are a user instance we get the Released message via the system bus */
if ( MANAGER_IS_USER ( m ) ) {
2017-12-19 12:29:04 +01:00
r = sd_bus_match_signal_async (
2015-03-11 16:35:21 +01:00
bus ,
NULL ,
2017-12-19 12:29:04 +01:00
NULL ,
" /org/freedesktop/systemd1/agent " ,
" org.freedesktop.systemd1.Agent " ,
" Released " ,
signal_agent_released , NULL , m ) ;
2015-03-11 16:35:21 +01:00
if ( r < 0 )
2017-12-19 12:29:04 +01:00
log_warning_errno ( r , " Failed to request Released match on system bus: %m " ) ;
2015-03-11 16:35:21 +01:00
}
2013-11-19 21:12:59 +01:00
log_debug ( " Successfully connected to system bus. " ) ;
return 0 ;
2011-12-18 14:58:10 +01:00
}
core: rework how we connect to the bus
This removes the current bus_init() call, as it had multiple problems:
it munged handling of the three bus connections we care about (private,
"api" and system) into one, even though the conditions when which was
ready are very different. It also added redundant logging, as the
individual calls it called all logged on their own anyway.
The three calls bus_init_api(), bus_init_private() and bus_init_system()
are now made public. A new call manager_dbus_is_running() is added that
works much like manager_journal_is_running() and is a lot more careful
when checking whether dbus is around. Optionally it checks the unit's
deserialized_state rather than state, in order to accomodate for cases
where we cant to connect to the bus before deserializing the
"subscribed" list, before coldplugging the units.
manager_recheck_dbus() is added, that works a lot like
manager_recheck_journal() and is invoked in unit_notify(), i.e. when
units change state.
All in all this should make handling a bit more alike to journal
handling, and it also fixes one major bug: when running in user mode
we'll now connect to the system bus early on, without conditionalizing
this in anyway.
2018-02-07 14:52:22 +01:00
int bus_init_system ( Manager * m ) {
tree-wide: expose "p"-suffix unref calls in public APIs to make gcc cleanup easy
GLIB has recently started to officially support the gcc cleanup
attribute in its public API, hence let's do the same for our APIs.
With this patch we'll define an xyz_unrefp() call for each public
xyz_unref() call, to make it easy to use inside a
__attribute__((cleanup())) expression. Then, all code is ported over to
make use of this.
The new calls are also documented in the man pages, with examples how to
use them (well, I only added docs where the _unref() call itself already
had docs, and the examples, only cover sd_bus_unrefp() and
sd_event_unrefp()).
This also renames sd_lldp_free() to sd_lldp_unref(), since that's how we
tend to call our destructors these days.
Note that this defines no public macro that wraps gcc's attribute and
makes it easier to use. While I think it's our duty in the library to
make our stuff easy to use, I figure it's not our duty to make gcc's own
features easy to use on its own. Most likely, client code which wants to
make use of this should define its own:
#define _cleanup_(function) __attribute__((cleanup(function)))
Or similar, to make the gcc feature easier to use.
Making this logic public has the benefit that we can remove three header
files whose only purpose was to define these functions internally.
See #2008.
2015-11-27 19:13:45 +01:00
_cleanup_ ( sd_bus_unrefp ) sd_bus * bus = NULL ;
2011-12-18 14:58:10 +01:00
int r ;
if ( m - > system_bus )
return 0 ;
2013-11-19 21:12:59 +01:00
/* The API and system bus is the same if we are running in system mode */
2018-02-07 22:47:26 +01:00
if ( MANAGER_IS_SYSTEM ( m ) & & m - > api_bus )
bus = sd_bus_ref ( m - > api_bus ) ;
else {
r = sd_bus_open_system ( & bus ) ;
if ( r < 0 )
return log_error_errno ( r , " Failed to connect to system bus: %m " ) ;
2011-12-18 14:58:10 +01:00
2018-02-07 22:47:26 +01:00
r = sd_bus_attach_event ( bus , m - > event , SD_EVENT_PRIORITY_NORMAL ) ;
if ( r < 0 )
return log_error_errno ( r , " Failed to attach system bus to event loop: %m " ) ;
2011-12-18 14:58:10 +01:00
2018-02-07 22:47:26 +01:00
r = bus_setup_disconnected_match ( m , bus ) ;
if ( r < 0 )
return r ;
}
2011-12-18 14:58:10 +01:00
2013-11-19 21:12:59 +01:00
r = bus_setup_system ( m , bus ) ;
2018-01-10 17:22:12 +01:00
if ( r < 0 )
return log_error_errno ( r , " Failed to set up system bus: %m " ) ;
2011-12-18 14:58:10 +01:00
2013-11-19 21:12:59 +01:00
m - > system_bus = bus ;
bus = NULL ;
2011-12-18 14:58:10 +01:00
return 0 ;
2010-06-19 03:04:04 +02:00
}
core: rework how we connect to the bus
This removes the current bus_init() call, as it had multiple problems:
it munged handling of the three bus connections we care about (private,
"api" and system) into one, even though the conditions when which was
ready are very different. It also added redundant logging, as the
individual calls it called all logged on their own anyway.
The three calls bus_init_api(), bus_init_private() and bus_init_system()
are now made public. A new call manager_dbus_is_running() is added that
works much like manager_journal_is_running() and is a lot more careful
when checking whether dbus is around. Optionally it checks the unit's
deserialized_state rather than state, in order to accomodate for cases
where we cant to connect to the bus before deserializing the
"subscribed" list, before coldplugging the units.
manager_recheck_dbus() is added, that works a lot like
manager_recheck_journal() and is invoked in unit_notify(), i.e. when
units change state.
All in all this should make handling a bit more alike to journal
handling, and it also fixes one major bug: when running in user mode
we'll now connect to the system bus early on, without conditionalizing
this in anyway.
2018-02-07 14:52:22 +01:00
int bus_init_private ( Manager * m ) {
2013-11-19 21:12:59 +01:00
_cleanup_close_ int fd = - 1 ;
union sockaddr_union sa = {
. un . sun_family = AF_UNIX
2010-06-19 03:04:04 +02:00
} ;
2013-11-19 21:12:59 +01:00
sd_event_source * s ;
socklen_t salen ;
int r ;
2010-06-19 03:04:04 +02:00
assert ( m ) ;
2013-11-19 21:12:59 +01:00
if ( m - > private_listen_fd > = 0 )
2010-06-19 03:04:04 +02:00
return 0 ;
2016-02-24 21:24:23 +01:00
if ( MANAGER_IS_SYSTEM ( m ) ) {
2011-07-01 22:34:37 +02:00
/* We want the private bus only when running as init */
2017-07-20 16:19:18 +02:00
if ( getpid_cached ( ) ! = 1 )
2011-07-01 22:34:37 +02:00
return 0 ;
2013-11-19 21:12:59 +01:00
strcpy ( sa . un . sun_path , " /run/systemd/private " ) ;
2016-05-05 22:24:36 +02:00
salen = SOCKADDR_UN_LEN ( sa . un ) ;
2011-07-01 22:34:37 +02:00
} else {
2013-11-19 21:12:59 +01:00
size_t left = sizeof ( sa . un . sun_path ) ;
char * p = sa . un . sun_path ;
2011-07-01 22:34:37 +02:00
const char * e ;
2012-09-17 00:21:25 +02:00
e = secure_getenv ( " XDG_RUNTIME_DIR " ) ;
2013-11-19 21:12:59 +01:00
if ( ! e ) {
log_error ( " Failed to determine XDG_RUNTIME_DIR " ) ;
return - EHOSTDOWN ;
2011-07-01 22:34:37 +02:00
}
2013-11-19 21:12:59 +01:00
left = strpcpy ( & p , left , e ) ;
left = strpcpy ( & p , left , " /systemd/private " ) ;
2013-02-07 22:14:56 +01:00
2013-11-19 21:12:59 +01:00
salen = sizeof ( sa . un ) - left ;
2011-07-01 22:34:37 +02:00
}
2010-06-19 03:04:04 +02:00
2014-11-07 16:32:06 +01:00
( void ) mkdir_parents_label ( sa . un . sun_path , 0755 ) ;
( void ) unlink ( sa . un . sun_path ) ;
2013-11-19 21:12:59 +01:00
fd = socket ( AF_UNIX , SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK , 0 ) ;
2014-11-28 19:57:32 +01:00
if ( fd < 0 )
return log_error_errno ( errno , " Failed to allocate private socket: %m " ) ;
2010-06-19 03:04:04 +02:00
2013-11-19 21:12:59 +01:00
r = bind ( fd , & sa . sa , salen ) ;
2014-11-28 19:57:32 +01:00
if ( r < 0 )
return log_error_errno ( errno , " Failed to bind private socket: %m " ) ;
2010-06-19 03:04:04 +02:00
2013-11-19 21:12:59 +01:00
r = listen ( fd , SOMAXCONN ) ;
2014-11-28 19:57:32 +01:00
if ( r < 0 )
return log_error_errno ( errno , " Failed to make private socket listening: %m " ) ;
2010-06-19 03:04:04 +02:00
2017-12-27 18:22:31 +01:00
/* Generate an inotify event in case somebody waits for this socket to appear using inotify() */
( void ) touch ( sa . un . sun_path ) ;
2014-02-19 23:54:58 +01:00
r = sd_event_add_io ( m - > event , & s , fd , EPOLLIN , bus_on_connection , m ) ;
2014-11-28 18:23:20 +01:00
if ( r < 0 )
return log_error_errno ( r , " Failed to allocate event source: %m " ) ;
2010-06-19 03:04:04 +02:00
2015-04-29 16:05:32 +02:00
( void ) sd_event_source_set_description ( s , " bus-connection " ) ;
2013-11-19 21:12:59 +01:00
m - > private_listen_fd = fd ;
m - > private_listen_event_source = s ;
fd = - 1 ;
2010-06-19 03:04:04 +02:00
2013-11-19 21:12:59 +01:00
log_debug ( " Successfully created private D-Bus server. " ) ;
2010-06-19 03:04:04 +02:00
2013-11-19 21:12:59 +01:00
return 0 ;
2010-06-19 03:04:04 +02:00
}
2013-11-19 21:12:59 +01:00
static void destroy_bus ( Manager * m , sd_bus * * bus ) {
2010-07-05 00:58:07 +02:00
Iterator i ;
2017-02-10 03:54:48 +01:00
Unit * u ;
2013-11-19 21:12:59 +01:00
Job * j ;
2010-07-05 00:58:07 +02:00
2013-11-19 21:12:59 +01:00
assert ( m ) ;
assert ( bus ) ;
2010-06-19 03:04:04 +02:00
2013-11-19 21:12:59 +01:00
if ( ! * bus )
2011-12-18 14:58:10 +01:00
return ;
2010-04-06 16:32:07 +02:00
2017-02-10 03:54:48 +01:00
/* Make sure all bus slots watching names are released. */
HASHMAP_FOREACH ( u , m - > watch_bus , i ) {
if ( ! u - > match_bus_slot )
continue ;
if ( sd_bus_slot_get_bus ( u - > match_bus_slot ) ! = * bus )
continue ;
u - > match_bus_slot = sd_bus_slot_unref ( u - > match_bus_slot ) ;
}
2013-11-19 21:12:59 +01:00
/* Get rid of tracked clients on this bus */
2014-03-03 01:33:45 +01:00
if ( m - > subscribed & & sd_bus_track_get_bus ( m - > subscribed ) = = * bus )
m - > subscribed = sd_bus_track_unref ( m - > subscribed ) ;
2013-11-19 21:12:59 +01:00
HASHMAP_FOREACH ( j , m - > jobs , i )
2016-11-15 19:29:50 +01:00
if ( j - > bus_track & & sd_bus_track_get_bus ( j - > bus_track ) = = * bus )
j - > bus_track = sd_bus_track_unref ( j - > bus_track ) ;
2010-02-05 00:38:41 +01:00
2018-02-07 22:40:41 +01:00
HASHMAP_FOREACH ( u , m - > units , i )
if ( u - > bus_track & & sd_bus_track_get_bus ( u - > bus_track ) = = * bus )
u - > bus_track = sd_bus_track_unref ( u - > bus_track ) ;
2013-11-19 21:12:59 +01:00
/* Get rid of queued message on this bus */
2015-04-29 19:02:08 +02:00
if ( m - > queued_message & & sd_bus_message_get_bus ( m - > queued_message ) = = * bus )
m - > queued_message = sd_bus_message_unref ( m - > queued_message ) ;
2010-04-06 16:32:07 +02:00
2013-11-19 21:12:59 +01:00
/* Possibly flush unwritten data, but only if we are
* unprivileged , since we don ' t want to sync here */
2016-02-24 21:24:23 +01:00
if ( ! MANAGER_IS_SYSTEM ( m ) )
2013-11-19 21:12:59 +01:00
sd_bus_flush ( * bus ) ;
2010-06-19 03:04:04 +02:00
2013-11-19 21:12:59 +01:00
/* And destroy the object */
sd_bus_close ( * bus ) ;
* bus = sd_bus_unref ( * bus ) ;
2010-06-19 03:04:04 +02:00
}
2018-02-07 15:00:32 +01:00
void bus_done_api ( Manager * m ) {
2010-04-15 23:16:16 +02:00
assert ( m ) ;
2013-11-19 21:12:59 +01:00
if ( m - > api_bus )
destroy_bus ( m , & m - > api_bus ) ;
2018-02-07 15:00:32 +01:00
}
void bus_done_system ( Manager * m ) {
assert ( m ) ;
2013-11-19 21:12:59 +01:00
if ( m - > system_bus )
destroy_bus ( m , & m - > system_bus ) ;
2018-02-07 15:00:32 +01:00
}
void bus_done_private ( Manager * m ) {
sd_bus * b ;
assert ( m ) ;
2013-11-19 21:12:59 +01:00
while ( ( b = set_steal_first ( m - > private_buses ) ) )
destroy_bus ( m , & b ) ;
2010-04-15 23:16:16 +02:00
2015-09-09 23:12:07 +02:00
m - > private_buses = set_free ( m - > private_buses ) ;
2014-03-03 01:33:45 +01:00
2018-02-07 15:00:32 +01:00
m - > private_listen_event_source = sd_event_source_unref ( m - > private_listen_event_source ) ;
m - > private_listen_fd = safe_close ( m - > private_listen_fd ) ;
}
void bus_done ( Manager * m ) {
assert ( m ) ;
2010-04-15 23:16:16 +02:00
2018-02-07 15:00:32 +01:00
bus_done_api ( m ) ;
bus_done_system ( m ) ;
bus_done_private ( m ) ;
2010-04-15 23:16:16 +02:00
2018-02-07 15:00:32 +01:00
assert ( ! m - > subscribed ) ;
2014-08-06 11:45:36 +02:00
2018-02-07 15:00:32 +01:00
m - > deserialized_subscribed = strv_free ( m - > deserialized_subscribed ) ;
2014-08-06 11:45:36 +02:00
bus_verify_polkit_async_registry_free ( m - > polkit_registry ) ;
2010-07-05 00:58:07 +02:00
}
2011-04-28 22:07:01 +02:00
int bus_fdset_add_all ( Manager * m , FDSet * fds ) {
Iterator i ;
2013-11-19 21:12:59 +01:00
sd_bus * b ;
int fd ;
2011-04-28 22:07:01 +02:00
assert ( m ) ;
assert ( fds ) ;
/* When we are about to reexecute we add all D-Bus fds to the
* set to pass over to the newly executed systemd . They won ' t
2013-11-19 21:12:59 +01:00
* be used there however , except thatt they are closed at the
2011-04-28 22:07:01 +02:00
* very end of deserialization , those making it possible for
2011-04-28 23:51:24 +02:00
* clients to synchronously wait for systemd to reexec by
2011-04-28 22:07:01 +02:00
* simply waiting for disconnection */
2013-11-19 21:12:59 +01:00
if ( m - > api_bus ) {
fd = sd_bus_get_fd ( m - > api_bus ) ;
if ( fd > = 0 ) {
2011-04-28 22:07:01 +02:00
fd = fdset_put_dup ( fds , fd ) ;
if ( fd < 0 )
return fd ;
}
}
2013-11-19 21:12:59 +01:00
SET_FOREACH ( b , m - > private_buses , i ) {
fd = sd_bus_get_fd ( b ) ;
if ( fd > = 0 ) {
2011-04-28 22:07:01 +02:00
fd = fdset_put_dup ( fds , fd ) ;
if ( fd < 0 )
return fd ;
}
}
2013-11-19 21:12:59 +01:00
/* We don't offer any APIs on the system bus (well, unless it
* is the same as the API bus ) hence we don ' t bother with it
* here */
2013-07-10 19:24:03 +02:00
2013-11-19 21:12:59 +01:00
return 0 ;
2013-07-10 19:24:03 +02:00
}
2014-03-03 01:33:45 +01:00
int bus_foreach_bus (
Manager * m ,
sd_bus_track * subscribed2 ,
int ( * send_message ) ( sd_bus * bus , void * userdata ) ,
void * userdata ) {
Iterator i ;
sd_bus * b ;
int r , ret = 0 ;
2015-05-11 13:49:29 +02:00
/* Send to all direct buses, unconditionally */
2014-03-03 01:33:45 +01:00
SET_FOREACH ( b , m - > private_buses , i ) {
2018-02-13 18:27:47 +01:00
/* Don't bother with enqueing these messages to clients that haven't started yet */
if ( sd_bus_is_ready ( b ) < = 0 )
continue ;
2014-03-03 01:33:45 +01:00
r = send_message ( b , userdata ) ;
if ( r < 0 )
ret = r ;
}
/* Send to API bus, but only if somebody is subscribed */
2018-02-07 22:44:18 +01:00
if ( m - > api_bus & &
( sd_bus_track_count ( m - > subscribed ) > 0 | |
sd_bus_track_count ( subscribed2 ) > 0 ) ) {
2014-03-03 01:33:45 +01:00
r = send_message ( m - > api_bus , userdata ) ;
if ( r < 0 )
ret = r ;
}
return ret ;
}
2016-08-15 18:12:01 +02:00
void bus_track_serialize ( sd_bus_track * t , FILE * f , const char * prefix ) {
2014-03-03 01:33:45 +01:00
const char * n ;
2013-07-10 19:24:03 +02:00
assert ( f ) ;
2016-08-15 18:12:01 +02:00
assert ( prefix ) ;
2013-07-10 19:24:03 +02:00
2016-08-15 18:12:01 +02:00
for ( n = sd_bus_track_first ( t ) ; n ; n = sd_bus_track_next ( t ) ) {
int c , j ;
2014-12-02 00:15:13 +01:00
2016-08-15 18:12:01 +02:00
c = sd_bus_track_count_name ( t , n ) ;
2014-03-03 01:33:45 +01:00
2016-08-15 18:12:01 +02:00
for ( j = 0 ; j < c ; j + + ) {
fputs ( prefix , f ) ;
fputc ( ' = ' , f ) ;
fputs ( n , f ) ;
fputc ( ' \n ' , f ) ;
}
}
2014-03-03 01:33:45 +01:00
}
2016-08-15 18:12:01 +02:00
int bus_track_coldplug ( Manager * m , sd_bus_track * * t , bool recursive , char * * l ) {
2014-03-03 01:33:45 +01:00
int r = 0 ;
assert ( m ) ;
assert ( t ) ;
2016-08-15 18:12:01 +02:00
if ( strv_isempty ( l ) )
return 0 ;
2014-03-03 01:33:45 +01:00
2016-08-15 18:12:01 +02:00
if ( ! m - > api_bus )
return 0 ;
2014-03-03 01:33:45 +01:00
2016-08-15 18:12:01 +02:00
if ( ! * t ) {
r = sd_bus_track_new ( m - > api_bus , t , NULL , NULL ) ;
if ( r < 0 )
return r ;
2014-03-03 01:33:45 +01:00
}
2016-08-15 18:12:01 +02:00
r = sd_bus_track_set_recursive ( * t , recursive ) ;
if ( r < 0 )
return r ;
2016-11-15 19:18:36 +01:00
return bus_track_add_name_many ( * t , l ) ;
2013-07-10 19:24:03 +02:00
}
2014-08-06 11:45:36 +02:00
2015-02-18 17:40:57 +01:00
int bus_verify_manage_units_async ( Manager * m , sd_bus_message * call , sd_bus_error * error ) {
2015-09-05 16:07:16 +02:00
return bus_verify_polkit_async ( call , CAP_SYS_ADMIN , " org.freedesktop.systemd1.manage-units " , NULL , false , UID_INVALID , & m - > polkit_registry , error ) ;
2014-08-06 11:45:36 +02:00
}
int bus_verify_manage_unit_files_async ( Manager * m , sd_bus_message * call , sd_bus_error * error ) {
2015-09-05 16:07:16 +02:00
return bus_verify_polkit_async ( call , CAP_SYS_ADMIN , " org.freedesktop.systemd1.manage-unit-files " , NULL , false , UID_INVALID , & m - > polkit_registry , error ) ;
2014-08-06 11:45:36 +02:00
}
int bus_verify_reload_daemon_async ( Manager * m , sd_bus_message * call , sd_bus_error * error ) {
2015-09-05 16:07:16 +02:00
return bus_verify_polkit_async ( call , CAP_SYS_ADMIN , " org.freedesktop.systemd1.reload-daemon " , NULL , false , UID_INVALID , & m - > polkit_registry , error ) ;
2014-08-06 11:45:36 +02:00
}
2015-02-18 17:40:57 +01:00
int bus_verify_set_environment_async ( Manager * m , sd_bus_message * call , sd_bus_error * error ) {
2015-09-05 16:07:16 +02:00
return bus_verify_polkit_async ( call , CAP_SYS_ADMIN , " org.freedesktop.systemd1.set-environment " , NULL , false , UID_INVALID , & m - > polkit_registry , error ) ;
2015-02-18 17:40:57 +01:00
}
2018-02-13 18:30:34 +01:00
uint64_t manager_bus_n_queued_write ( Manager * m ) {
uint64_t c = 0 ;
Iterator i ;
sd_bus * b ;
int r ;
/* Returns the total number of messages queued for writing on all our direct and API busses. */
SET_FOREACH ( b , m - > private_buses , i ) {
uint64_t k ;
r = sd_bus_get_n_queued_write ( b , & k ) ;
if ( r < 0 )
log_debug_errno ( r , " Failed to query queued messages for private bus: %m " ) ;
else
c + = k ;
}
if ( m - > api_bus ) {
uint64_t k ;
r = sd_bus_get_n_queued_write ( m - > api_bus , & k ) ;
if ( r < 0 )
log_debug_errno ( r , " Failed to query queued messages for API bus: %m " ) ;
else
c + = k ;
}
return c ;
}