Skip to content

Commit 7903868

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) (cherry picked from commit e7155d8) (cherry picked from commit 69985ea)
1 parent 95dfe92 commit 7903868

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;
@@ -486,46 +487,42 @@ static void vl_disconnect(VarlinkServer *s, Varlink *link, void *userdata) {
486487
}
487488

488489
static int manager_varlink_init_system(Manager *m) {
489-
_cleanup_(varlink_server_unrefp) VarlinkServer *s = NULL;
490490
int r;
491491

492492
assert(m);
493493

494-
if (m->varlink_server)
495-
return 1;
496-
497494
if (!MANAGER_IS_SYSTEM(m))
498495
return 0;
499496

500-
r = manager_setup_varlink_server(m, &s);
497+
r = manager_setup_varlink_server(m);
501498
if (r < 0)
502499
return log_error_errno(r, "Failed to set up varlink server: %m");
500+
bool fresh = r > 0;
503501

504502
if (!MANAGER_IS_TEST_RUN(m)) {
505503
(void) mkdir_p_label("/run/systemd/userdb", 0755);
506504

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

518-
r = varlink_server_listen_address(s, address, 0666);
520+
r = varlink_server_listen_address(m->varlink_server, address, 0666);
519521
if (r < 0)
520522
return log_error_errno(r, "Failed to bind to varlink socket '%s': %m", address);
521523
}
522524
}
523525

524-
r = varlink_server_attach_event(s, m->event, SD_EVENT_PRIORITY_NORMAL);
525-
if (r < 0)
526-
return log_error_errno(r, "Failed to attach varlink connection to event loop: %m");
527-
528-
m->varlink_server = TAKE_PTR(s);
529526
return 1;
530527
}
531528

@@ -590,12 +587,17 @@ static int manager_varlink_init_user(Manager *m) {
590587
return 1;
591588
}
592589

593-
int manager_setup_varlink_server(Manager *m, VarlinkServer **ret) {
590+
int manager_setup_varlink_server(Manager *m) {
594591
_cleanup_(varlink_server_unrefp) VarlinkServer *s = NULL;
595592
int r;
596593

597594
assert(m);
598-
assert(ret);
595+
596+
if (m->varlink_server)
597+
return 0;
598+
599+
if (!MANAGER_IS_SYSTEM(m))
600+
return -EINVAL;
599601

600602
r = varlink_server_new(&s, VARLINK_SERVER_ACCOUNT_UID|VARLINK_SERVER_INHERIT_USERDATA);
601603
if (r < 0)
@@ -616,8 +618,12 @@ int manager_setup_varlink_server(Manager *m, VarlinkServer **ret) {
616618
if (r < 0)
617619
return log_debug_errno(r, "Failed to register varlink disconnect handler: %m");
618620

619-
*ret = TAKE_PTR(s);
620-
return 0;
621+
r = varlink_server_attach_event(s, m->event, SD_EVENT_PRIORITY_NORMAL);
622+
if (r < 0)
623+
return log_debug_errno(r, "Failed to attach varlink connection to event loop: %m");
624+
625+
m->varlink_server = TAKE_PTR(s);
626+
return 1;
621627
}
622628

623629
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
@@ -533,7 +533,7 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
533533
return -ENOMEM;
534534
} else if ((val = startswith(l, "varlink-server-socket-address="))) {
535535
if (!m->varlink_server && MANAGER_IS_SYSTEM(m)) {
536-
r = manager_varlink_init(m);
536+
r = manager_setup_varlink_server(m);
537537
if (r < 0) {
538538
log_warning_errno(r, "Failed to setup varlink server, ignoring: %m");
539539
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
@@ -151,42 +151,6 @@ struct Varlink {
151151
sd_event_source *defer_event_source;
152152
};
153153

154-
typedef struct VarlinkServerSocket VarlinkServerSocket;
155-
156-
struct VarlinkServerSocket {
157-
VarlinkServer *server;
158-
159-
int fd;
160-
char *address;
161-
162-
sd_event_source *event_source;
163-
164-
LIST_FIELDS(VarlinkServerSocket, sockets);
165-
};
166-
167-
struct VarlinkServer {
168-
unsigned n_ref;
169-
VarlinkServerFlags flags;
170-
171-
LIST_HEAD(VarlinkServerSocket, sockets);
172-
173-
Hashmap *methods;
174-
VarlinkConnect connect_callback;
175-
VarlinkDisconnect disconnect_callback;
176-
177-
sd_event *event;
178-
int64_t event_priority;
179-
180-
unsigned n_connections;
181-
Hashmap *by_uid;
182-
183-
void *userdata;
184-
char *description;
185-
186-
unsigned connections_max;
187-
unsigned connections_per_uid_max;
188-
};
189-
190154
static const char* const varlink_state_table[_VARLINK_STATE_MAX] = {
191155
[VARLINK_IDLE_CLIENT] = "idle-client",
192156
[VARLINK_AWAITING_REPLY] = "awaiting-reply",

0 commit comments

Comments
 (0)