Skip to content

Commit e7155d8

Browse files
YHNdnzjbluca
andcommitted
core: reliably check if varlink socket has been deserialized
Follow-up for 6906c02 The mentioned commit uses access() to check if varlink socket already exists in the filesystem, but that isn't sufficient. > Varlink sockets are not serialized until v252, so upgrading from > v251 or older means we will not listen anymore on the varlink sockets. > > See https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1074789 > for more details as this was found when updating from Debian Bullseye to a new version. After this commit, the set up of varlink_server is effectively split into two steps. manager_varlink_init_system(), which is called after deserialization, would no longer skip listening even if Manager.varlink_server is in place, but actually check if we're listening on desired sockets. Then, manager_deserialize() can be switched back to using manager_setup_varlink_server(). Alternative to #33817 Co-authored-by: Luca Boccassi <[email protected]> (cherry picked from commit d4e5c66) (cherry picked from commit b825a8b) (cherry picked from commit 3b3875e)
1 parent 5ff55bc commit e7155d8

File tree

5 files changed

+72
-60
lines changed

5 files changed

+72
-60
lines changed

src/core/core-varlink.c

Lines changed: 28 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "strv.h"
66
#include "user-util.h"
77
#include "varlink.h"
8+
#include "varlink-internal.h"
89

910
typedef struct LookupParameters {
1011
const char *user_name;
@@ -490,46 +491,42 @@ static void vl_disconnect(VarlinkServer *s, Varlink *link, void *userdata) {
490491
}
491492

492493
static int manager_varlink_init_system(Manager *m) {
493-
_cleanup_(varlink_server_unrefp) VarlinkServer *s = NULL;
494494
int r;
495495

496496
assert(m);
497497

498-
if (m->varlink_server)
499-
return 1;
500-
501498
if (!MANAGER_IS_SYSTEM(m))
502499
return 0;
503500

504-
r = manager_setup_varlink_server(m, &s);
501+
r = manager_setup_varlink_server(m);
505502
if (r < 0)
506503
return log_error_errno(r, "Failed to set up varlink server: %m");
504+
bool fresh = r > 0;
507505

508506
if (!MANAGER_IS_TEST_RUN(m)) {
509507
(void) mkdir_p_label("/run/systemd/userdb", 0755);
510508

511509
FOREACH_STRING(address, "/run/systemd/userdb/io.systemd.DynamicUser", VARLINK_ADDR_PATH_MANAGED_OOM_SYSTEM) {
512-
if (MANAGER_IS_RELOADING(m)) {
513-
/* If manager is reloading, we skip listening on existing addresses, since
514-
* the fd should be acquired later through deserialization. */
515-
if (access(address, F_OK) >= 0)
510+
if (!fresh) {
511+
/* We might have got sockets through deserialization. Do not bind to them twice. */
512+
513+
bool found = false;
514+
LIST_FOREACH(sockets, ss, m->varlink_server->sockets)
515+
if (path_equal(ss->address, address)) {
516+
found = true;
517+
break;
518+
}
519+
520+
if (found)
516521
continue;
517-
if (errno != ENOENT)
518-
return log_error_errno(errno,
519-
"Failed to check if varlink socket '%s' exists: %m", address);
520522
}
521523

522-
r = varlink_server_listen_address(s, address, 0666);
524+
r = varlink_server_listen_address(m->varlink_server, address, 0666);
523525
if (r < 0)
524526
return log_error_errno(r, "Failed to bind to varlink socket '%s': %m", address);
525527
}
526528
}
527529

528-
r = varlink_server_attach_event(s, m->event, SD_EVENT_PRIORITY_NORMAL);
529-
if (r < 0)
530-
return log_error_errno(r, "Failed to attach varlink connection to event loop: %m");
531-
532-
m->varlink_server = TAKE_PTR(s);
533530
return 1;
534531
}
535532

@@ -594,12 +591,17 @@ static int manager_varlink_init_user(Manager *m) {
594591
return 1;
595592
}
596593

597-
int manager_setup_varlink_server(Manager *m, VarlinkServer **ret) {
594+
int manager_setup_varlink_server(Manager *m) {
598595
_cleanup_(varlink_server_unrefp) VarlinkServer *s = NULL;
599596
int r;
600597

601598
assert(m);
602-
assert(ret);
599+
600+
if (m->varlink_server)
601+
return 0;
602+
603+
if (!MANAGER_IS_SYSTEM(m))
604+
return -EINVAL;
603605

604606
r = varlink_server_new(&s, VARLINK_SERVER_ACCOUNT_UID|VARLINK_SERVER_INHERIT_USERDATA);
605607
if (r < 0)
@@ -620,8 +622,12 @@ int manager_setup_varlink_server(Manager *m, VarlinkServer **ret) {
620622
if (r < 0)
621623
return log_debug_errno(r, "Failed to register varlink disconnect handler: %m");
622624

623-
*ret = TAKE_PTR(s);
624-
return 0;
625+
r = varlink_server_attach_event(s, m->event, SD_EVENT_PRIORITY_NORMAL);
626+
if (r < 0)
627+
return log_debug_errno(r, "Failed to attach varlink connection to event loop: %m");
628+
629+
m->varlink_server = TAKE_PTR(s);
630+
return 1;
625631
}
626632

627633
int manager_varlink_init(Manager *m) {

src/core/core-varlink.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ void manager_varlink_done(Manager *m);
88

99
/* Creates a new VarlinkServer and binds methods. Does not set up sockets or attach events.
1010
* Used for manager serialize/deserialize. */
11-
int manager_setup_varlink_server(Manager *m, VarlinkServer **ret_s);
11+
int manager_setup_varlink_server(Manager *m);
1212

1313
/* The manager is expected to send an update to systemd-oomd if one of the following occurs:
1414
* - The value of ManagedOOM*= properties change

src/core/manager-serialize.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -534,7 +534,7 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
534534
return -ENOMEM;
535535
} else if ((val = startswith(l, "varlink-server-socket-address="))) {
536536
if (!m->varlink_server && MANAGER_IS_SYSTEM(m)) {
537-
r = manager_varlink_init(m);
537+
r = manager_setup_varlink_server(m);
538538
if (r < 0) {
539539
log_warning_errno(r, "Failed to setup varlink server, ignoring: %m");
540540
continue;

src/shared/varlink-internal.h

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,47 @@
66
#include "fdset.h"
77
#include "varlink.h"
88

9+
typedef struct VarlinkServerSocket VarlinkServerSocket;
10+
11+
struct VarlinkServerSocket {
12+
VarlinkServer *server;
13+
14+
int fd;
15+
char *address;
16+
17+
sd_event_source *event_source;
18+
19+
LIST_FIELDS(VarlinkServerSocket, sockets);
20+
};
21+
22+
struct VarlinkServer {
23+
unsigned n_ref;
24+
VarlinkServerFlags flags;
25+
26+
LIST_HEAD(VarlinkServerSocket, sockets);
27+
28+
Hashmap *methods;
29+
VarlinkConnect connect_callback;
30+
VarlinkDisconnect disconnect_callback;
31+
32+
sd_event *event;
33+
int64_t event_priority;
34+
35+
unsigned n_connections;
36+
Hashmap *by_uid;
37+
38+
void *userdata;
39+
char *description;
40+
41+
unsigned connections_max;
42+
unsigned connections_per_uid_max;
43+
};
44+
45+
typedef struct VarlinkCollectContext {
46+
JsonVariant *parameters;
47+
const char *error_id;
48+
VarlinkReplyFlags flags;
49+
} VarlinkCollectContext ;
50+
951
int varlink_server_serialize(VarlinkServer *s, FILE *f, FDSet *fds);
1052
int varlink_server_deserialize_one(VarlinkServer *s, const char *value, FDSet *fds);

src/shared/varlink.c

Lines changed: 0 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -191,42 +191,6 @@ struct Varlink {
191191
sd_event_source *defer_event_source;
192192
};
193193

194-
typedef struct VarlinkServerSocket VarlinkServerSocket;
195-
196-
struct VarlinkServerSocket {
197-
VarlinkServer *server;
198-
199-
int fd;
200-
char *address;
201-
202-
sd_event_source *event_source;
203-
204-
LIST_FIELDS(VarlinkServerSocket, sockets);
205-
};
206-
207-
struct VarlinkServer {
208-
unsigned n_ref;
209-
VarlinkServerFlags flags;
210-
211-
LIST_HEAD(VarlinkServerSocket, sockets);
212-
213-
Hashmap *methods;
214-
VarlinkConnect connect_callback;
215-
VarlinkDisconnect disconnect_callback;
216-
217-
sd_event *event;
218-
int64_t event_priority;
219-
220-
unsigned n_connections;
221-
Hashmap *by_uid;
222-
223-
void *userdata;
224-
char *description;
225-
226-
unsigned connections_max;
227-
unsigned connections_per_uid_max;
228-
};
229-
230194
static const char* const varlink_state_table[_VARLINK_STATE_MAX] = {
231195
[VARLINK_IDLE_CLIENT] = "idle-client",
232196
[VARLINK_AWAITING_REPLY] = "awaiting-reply",

0 commit comments

Comments
 (0)