chiark / gitweb /
Revert "Handle Unix domain socket connections from outside our namespace"
[elogind.git] / src / core / busname.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2013 Lennart Poettering
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include "special.h"
23 #include "bus-kernel.h"
24 #include "bus-internal.h"
25 #include "bus-util.h"
26 #include "service.h"
27 #include "dbus-busname.h"
28 #include "busname.h"
29
30 static const UnitActiveState state_translation_table[_BUSNAME_STATE_MAX] = {
31         [BUSNAME_DEAD] = UNIT_INACTIVE,
32         [BUSNAME_REGISTERED] = UNIT_ACTIVE,
33         [BUSNAME_LISTENING] = UNIT_ACTIVE,
34         [BUSNAME_RUNNING] = UNIT_ACTIVE,
35         [BUSNAME_FAILED] = UNIT_FAILED
36 };
37
38 static int busname_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
39
40 static void busname_init(Unit *u) {
41         BusName *n = BUSNAME(u);
42
43         assert(u);
44         assert(u->load_state == UNIT_STUB);
45
46         n->starter_fd = -1;
47         n->accept_fd = true;
48         n->activating = true;
49 }
50
51 static void busname_done(Unit *u) {
52         BusName *n = BUSNAME(u);
53
54         assert(u);
55
56         free(n->name);
57         n->name = NULL;
58
59         unit_ref_unset(&n->service);
60
61         n->event_source = sd_event_source_unref(n->event_source);
62         n->starter_fd = safe_close(n->starter_fd);
63 }
64
65 static int busname_add_default_default_dependencies(BusName *n) {
66         int r;
67
68         assert(n);
69
70         r = unit_add_dependency_by_name(UNIT(n), UNIT_BEFORE, SPECIAL_BUSNAMES_TARGET, NULL, true);
71         if (r < 0)
72                 return r;
73
74         if (UNIT(n)->manager->running_as == SYSTEMD_SYSTEM) {
75                 r = unit_add_two_dependencies_by_name(UNIT(n), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET, NULL, true);
76                 if (r < 0)
77                         return r;
78         }
79
80         return unit_add_two_dependencies_by_name(UNIT(n), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true);
81 }
82
83 static int busname_add_extras(BusName *n) {
84         Unit *u = UNIT(n);
85         int r;
86
87         assert(n);
88
89         if (!n->name) {
90                 n->name = unit_name_to_prefix(u->id);
91                 if (!n->name)
92                         return -ENOMEM;
93         }
94
95         if (!u->description) {
96                 r = unit_set_description(u, n->name);
97                 if (r < 0)
98                         return r;
99         }
100
101         if (n->activating) {
102                 if (!UNIT_DEREF(n->service)) {
103                         Unit *x;
104
105                         r = unit_load_related_unit(u, ".service", &x);
106                         if (r < 0)
107                                 return r;
108
109                         unit_ref_set(&n->service, x);
110                 }
111
112                 r = unit_add_two_dependencies(u, UNIT_BEFORE, UNIT_TRIGGERS, UNIT_DEREF(n->service), true);
113                 if (r < 0)
114                         return r;
115         }
116
117         if (u->default_dependencies) {
118                 r = busname_add_default_default_dependencies(n);
119                 if (r < 0)
120                         return r;
121         }
122
123         return 0;
124 }
125
126 static int busname_verify(BusName *n) {
127         char *e;
128
129         assert(n);
130
131         if (UNIT(n)->load_state != UNIT_LOADED)
132                 return 0;
133
134         if (!service_name_is_valid(n->name)) {
135                 log_error_unit(UNIT(n)->id, "%s's Name= setting is not a valid service name Refusing.", UNIT(n)->id);
136                 return -EINVAL;
137         }
138
139         e = strappenda(n->name, ".busname");
140         if (!unit_has_name(UNIT(n), e)) {
141                 log_error_unit(UNIT(n)->id, "%s's Name= setting doesn't match unit name. Refusing.", UNIT(n)->id);
142                 return -EINVAL;
143         }
144
145         return 0;
146 }
147
148 static int busname_load(Unit *u) {
149         BusName *n = BUSNAME(u);
150         int r;
151
152         assert(u);
153         assert(u->load_state == UNIT_STUB);
154
155         r = unit_load_fragment_and_dropin(u);
156         if (r < 0)
157                 return r;
158
159         if (u->load_state == UNIT_LOADED) {
160                 /* This is a new unit? Then let's add in some extras */
161                 r = busname_add_extras(n);
162                 if (r < 0)
163                         return r;
164         }
165
166         return busname_verify(n);
167 }
168
169 static void busname_dump(Unit *u, FILE *f, const char *prefix) {
170         BusName *n = BUSNAME(u);
171
172         assert(n);
173         assert(f);
174
175         fprintf(f,
176                 "%sBus Name State: %s\n"
177                 "%sResult: %s\n"
178                 "%sName: %s\n"
179                 "%sActivating: %s\n"
180                 "%sAccept FD: %s\n",
181                 prefix, busname_state_to_string(n->state),
182                 prefix, busname_result_to_string(n->result),
183                 prefix, n->name,
184                 prefix, yes_no(n->activating),
185                 prefix, yes_no(n->accept_fd));
186 }
187
188 static void busname_unwatch_fd(BusName *n) {
189         int r;
190
191         assert(n);
192
193         if (n->event_source) {
194                 r = sd_event_source_set_enabled(n->event_source, SD_EVENT_OFF);
195                 if (r < 0)
196                         log_debug_unit(UNIT(n)->id, "Failed to disable event source.");
197         }
198 }
199
200 static void busname_close_fd(BusName *n) {
201         assert(n);
202
203         busname_unwatch_fd(n);
204
205         if (n->starter_fd <= 0)
206                 return;
207
208         n->starter_fd = safe_close(n->starter_fd);
209 }
210
211 static int busname_watch_fd(BusName *n) {
212         int r;
213
214         assert(n);
215
216         if (n->starter_fd < 0)
217                 return 0;
218
219         if (n->event_source)
220                 r = sd_event_source_set_enabled(n->event_source, SD_EVENT_ON);
221         else
222                 r = sd_event_add_io(UNIT(n)->manager->event, &n->event_source, n->starter_fd, EPOLLIN, busname_dispatch_io, n);
223         if (r < 0) {
224                 log_warning_unit(UNIT(n)->id, "Failed to watch starter fd: %s", strerror(-r));
225                 busname_unwatch_fd(n);
226                 return r;
227         }
228
229         return 0;
230 }
231
232 static int busname_open_fd(BusName *n) {
233         assert(n);
234
235         if (n->starter_fd >= 0)
236                 return 0;
237
238         n->starter_fd = bus_kernel_create_starter(
239                         UNIT(n)->manager->running_as == SYSTEMD_SYSTEM ? "system" : "user",
240                         n->name, n->activating, n->accept_fd, n->policy);
241
242         if (n->starter_fd < 0) {
243                 log_warning_unit(UNIT(n)->id, "Failed to create starter fd: %s", strerror(-n->starter_fd));
244                 return n->starter_fd;
245         }
246
247         return 0;
248 }
249
250 static void busname_set_state(BusName *n, BusNameState state) {
251         BusNameState old_state;
252         assert(n);
253
254         old_state = n->state;
255         n->state = state;
256
257         if (state != BUSNAME_LISTENING)
258                 busname_unwatch_fd(n);
259
260         if (!IN_SET(state, BUSNAME_LISTENING, BUSNAME_REGISTERED, BUSNAME_RUNNING))
261                 busname_close_fd(n);
262
263         if (state != old_state)
264                 log_debug_unit(UNIT(n)->id, "%s changed %s -> %s",
265                                UNIT(n)->id, busname_state_to_string(old_state), busname_state_to_string(state));
266
267         unit_notify(UNIT(n), state_translation_table[old_state], state_translation_table[state], true);
268 }
269
270 static int busname_coldplug(Unit *u) {
271         BusName *n = BUSNAME(u);
272         int r;
273
274         assert(n);
275         assert(n->state == BUSNAME_DEAD);
276
277         if (n->deserialized_state == n->state)
278                 return 0;
279
280         if (IN_SET(n->deserialized_state, BUSNAME_LISTENING, BUSNAME_REGISTERED, BUSNAME_RUNNING)) {
281                 r = busname_open_fd(n);
282                 if (r < 0)
283                         return r;
284         }
285
286         if (n->deserialized_state == BUSNAME_LISTENING) {
287                 r = busname_watch_fd(n);
288                 if (r < 0)
289                         return r;
290         }
291
292         busname_set_state(n, n->deserialized_state);
293         return 0;
294 }
295
296 static void busname_enter_dead(BusName *n, BusNameResult f) {
297         assert(n);
298
299         if (f != BUSNAME_SUCCESS)
300                 n->result = f;
301
302         busname_set_state(n, n->result != BUSNAME_SUCCESS ? BUSNAME_FAILED : BUSNAME_DEAD);
303 }
304
305 static void busname_enter_listening(BusName *n) {
306         int r;
307
308         assert(n);
309
310         r = busname_open_fd(n);
311         if (r < 0) {
312                 log_warning_unit(UNIT(n)->id, "%s failed to %s: %s", UNIT(n)->id,
313                                  n->activating ? "listen on bus name" : "register policy for name",
314                                  strerror(-r));
315                 goto fail;
316         }
317
318         if (n->activating) {
319                 r = busname_watch_fd(n);
320                 if (r < 0) {
321                         log_warning_unit(UNIT(n)->id, "%s failed to watch names: %s", UNIT(n)->id, strerror(-r));
322                         goto fail;
323                 }
324
325                 busname_set_state(n, BUSNAME_LISTENING);
326         } else
327                 busname_set_state(n, BUSNAME_REGISTERED);
328
329         return;
330
331 fail:
332         busname_enter_dead(n, BUSNAME_FAILURE_RESOURCES);
333 }
334
335 static void busname_enter_running(BusName *n) {
336         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
337         bool pending = false;
338         Unit *other;
339         Iterator i;
340         int r;
341
342         assert(n);
343
344         if (!n->activating)
345                 return;
346
347         /* We don't take conenctions anymore if we are supposed to
348          * shut down anyway */
349
350         if (unit_stop_pending(UNIT(n))) {
351                 log_debug_unit(UNIT(n)->id, "Suppressing activation request on %s since unit stop is scheduled.", UNIT(n)->id);
352
353                 /* Flush all queued activation reqeuest by closing and reopening the connection */
354                 bus_kernel_drop_one(n->starter_fd);
355
356                 busname_enter_listening(n);
357                 return;
358         }
359
360         /* If there's already a start pending don't bother to do
361          * anything */
362         SET_FOREACH(other, UNIT(n)->dependencies[UNIT_TRIGGERS], i)
363                 if (unit_active_or_pending(other)) {
364                         pending = true;
365                         break;
366                 }
367
368         if (!pending) {
369                 r = manager_add_job(UNIT(n)->manager, JOB_START, UNIT_DEREF(n->service), JOB_REPLACE, true, &error, NULL);
370                 if (r < 0)
371                         goto fail;
372         }
373
374         busname_set_state(n, BUSNAME_RUNNING);
375         return;
376
377 fail:
378         log_warning_unit(UNIT(n)->id, "%s failed to queue service startup job: %s", UNIT(n)->id, bus_error_message(&error, r));
379         busname_enter_dead(n, BUSNAME_FAILURE_RESOURCES);
380 }
381
382 static int busname_start(Unit *u) {
383         BusName *n = BUSNAME(u);
384
385         assert(n);
386
387         if (n->activating && UNIT_ISSET(n->service)) {
388                 Service *service;
389
390                 service = SERVICE(UNIT_DEREF(n->service));
391
392                 if (UNIT(service)->load_state != UNIT_LOADED) {
393                         log_error_unit(u->id, "Bus service %s not loaded, refusing.", UNIT(service)->id);
394                         return -ENOENT;
395                 }
396         }
397
398         assert(IN_SET(n->state, BUSNAME_DEAD, BUSNAME_FAILED));
399
400         n->result = BUSNAME_SUCCESS;
401         busname_enter_listening(n);
402
403         return 0;
404 }
405
406 static int busname_stop(Unit *u) {
407         BusName *n = BUSNAME(u);
408
409         assert(n);
410         assert(IN_SET(n->state, BUSNAME_REGISTERED, BUSNAME_LISTENING, BUSNAME_RUNNING));
411
412         busname_enter_dead(n, BUSNAME_SUCCESS);
413         return 0;
414 }
415
416 static int busname_serialize(Unit *u, FILE *f, FDSet *fds) {
417         BusName *n = BUSNAME(u);
418
419         assert(n);
420         assert(f);
421         assert(fds);
422
423         unit_serialize_item(u, f, "state", busname_state_to_string(n->state));
424         unit_serialize_item(u, f, "result", busname_result_to_string(n->result));
425
426         if (n->starter_fd >= 0) {
427                 int copy;
428
429                 copy = fdset_put_dup(fds, n->starter_fd);
430                 if (copy < 0)
431                         return copy;
432
433                 unit_serialize_item_format(u, f, "starter-fd", "%i", copy);
434         }
435
436         return 0;
437 }
438
439 static int busname_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
440         BusName *n = BUSNAME(u);
441
442         assert(n);
443         assert(key);
444         assert(value);
445
446         if (streq(key, "state")) {
447                 BusNameState state;
448
449                 state = busname_state_from_string(value);
450                 if (state < 0)
451                         log_debug_unit(u->id, "Failed to parse state value %s", value);
452                 else
453                         n->deserialized_state = state;
454
455         } else if (streq(key, "result")) {
456                 BusNameResult f;
457
458                 f = busname_result_from_string(value);
459                 if (f < 0)
460                         log_debug_unit(u->id, "Failed to parse result value %s", value);
461                 else if (f != BUSNAME_SUCCESS)
462                         n->result = f;
463
464         } else if (streq(key, "starter-fd")) {
465                 int fd;
466
467                 if (safe_atoi(value, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
468                         log_debug_unit(u->id, "Failed to parse starter fd value %s", value);
469                 else {
470                         safe_close(n->starter_fd);
471                         n->starter_fd = fdset_remove(fds, fd);
472                 }
473         } else
474                 log_debug_unit(u->id, "Unknown serialization key '%s'", key);
475
476         return 0;
477 }
478
479 _pure_ static UnitActiveState busname_active_state(Unit *u) {
480         assert(u);
481
482         return state_translation_table[BUSNAME(u)->state];
483 }
484
485 _pure_ static const char *busname_sub_state_to_string(Unit *u) {
486         assert(u);
487
488         return busname_state_to_string(BUSNAME(u)->state);
489 }
490
491 static int busname_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
492         BusName *n = userdata;
493
494         assert(n);
495         assert(fd >= 0);
496
497         if (n->state != BUSNAME_LISTENING)
498                 return 0;
499
500         log_debug_unit(UNIT(n)->id, "Activation request on %s", UNIT(n)->id);
501
502         if (revents != EPOLLIN) {
503                 log_error_unit(UNIT(n)->id, "%s: Got unexpected poll event (0x%x) on starter fd.",
504                                UNIT(n)->id, revents);
505                 goto fail;
506         }
507
508         busname_enter_running(n);
509         return 0;
510 fail:
511
512         busname_enter_dead(n, BUSNAME_FAILURE_RESOURCES);
513         return 0;
514 }
515
516 static void busname_reset_failed(Unit *u) {
517         BusName *n = BUSNAME(u);
518
519         assert(n);
520
521         if (n->state == BUSNAME_FAILED)
522                 busname_set_state(n, BUSNAME_DEAD);
523
524         n->result = BUSNAME_SUCCESS;
525 }
526
527 static void busname_trigger_notify(Unit *u, Unit *other) {
528         BusName *n = BUSNAME(u);
529         Service *s;
530
531         assert(n);
532         assert(other);
533
534         if (!IN_SET(n->state, BUSNAME_RUNNING, BUSNAME_LISTENING))
535                 return;
536
537         if (other->load_state != UNIT_LOADED || other->type != UNIT_SERVICE)
538                 return;
539
540         s = SERVICE(other);
541
542         if (s->state == SERVICE_FAILED && s->result == SERVICE_FAILURE_START_LIMIT)
543                 busname_enter_dead(n, BUSNAME_FAILURE_SERVICE_FAILED_PERMANENT);
544         else if (IN_SET(s->state,
545                         SERVICE_DEAD, SERVICE_FAILED,
546                         SERVICE_STOP, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL,
547                         SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL,
548                         SERVICE_AUTO_RESTART))
549                 busname_enter_listening(n);
550 }
551
552 static const char* const busname_state_table[_BUSNAME_STATE_MAX] = {
553         [BUSNAME_DEAD] = "dead",
554         [BUSNAME_REGISTERED] = "registered",
555         [BUSNAME_LISTENING] = "listening",
556         [BUSNAME_RUNNING] = "running",
557         [BUSNAME_FAILED] = "failed"
558 };
559
560 DEFINE_STRING_TABLE_LOOKUP(busname_state, BusNameState);
561
562 static const char* const busname_result_table[_BUSNAME_RESULT_MAX] = {
563         [BUSNAME_SUCCESS] = "success",
564         [BUSNAME_FAILURE_RESOURCES] = "resources",
565         [BUSNAME_FAILURE_SERVICE_FAILED_PERMANENT] = "service-failed-permanent",
566 };
567
568 DEFINE_STRING_TABLE_LOOKUP(busname_result, BusNameResult);
569
570 static const char* const busname_policy_access_table[_BUSNAME_POLICY_ACCESS_MAX] = {
571         [BUSNAME_POLICY_ACCESS_SEE] = "see",
572         [BUSNAME_POLICY_ACCESS_TALK] = "talk",
573         [BUSNAME_POLICY_ACCESS_OWN] = "own",
574 };
575
576 DEFINE_STRING_TABLE_LOOKUP(busname_policy_access, BusNamePolicyAccess);
577
578 const UnitVTable busname_vtable = {
579         .object_size = sizeof(BusName),
580
581         .sections =
582                 "Unit\0"
583                 "BusName\0"
584                 "Install\0",
585         .private_section = "BusName",
586
587         .init = busname_init,
588         .done = busname_done,
589         .load = busname_load,
590
591         .coldplug = busname_coldplug,
592
593         .dump = busname_dump,
594
595         .start = busname_start,
596         .stop = busname_stop,
597
598         .serialize = busname_serialize,
599         .deserialize_item = busname_deserialize_item,
600
601         .active_state = busname_active_state,
602         .sub_state_to_string = busname_sub_state_to_string,
603
604         .trigger_notify = busname_trigger_notify,
605
606         .reset_failed = busname_reset_failed,
607
608         .bus_interface = "org.freedesktop.systemd1.BusName",
609         .bus_vtable = bus_busname_vtable,
610
611         .status_message_formats = {
612                 .finished_start_job = {
613                         [JOB_DONE]       = "Listening on %s.",
614                         [JOB_FAILED]     = "Failed to listen on %s.",
615                         [JOB_DEPENDENCY] = "Dependency failed for %s.",
616                         [JOB_TIMEOUT]    = "Timed out starting %s.",
617                 },
618                 .finished_stop_job = {
619                         [JOB_DONE]       = "Closed %s.",
620                         [JOB_FAILED]     = "Failed stopping %s.",
621                         [JOB_TIMEOUT]    = "Timed out stopping %s.",
622                 },
623         },
624 };