1
0
mirror of https://github.com/systemd/systemd.git synced 2024-12-25 01:34:28 +03:00

varlink: make 'userdata' pointer inheritance from varlink server to connection optional

@keszybz's right on
https://github.com/systemd/systemd/pull/18248#issuecomment-760798473:
swapping out the userdata pointer of a live varlink connection is iffy.

Let's fix this by making the userdata inheritance from VarlinkServer
object to the Varlink connection object optional: we want it for most
cases, but not all, i.e. all those cases where the calls implemented as
varlink methods are stateless and can be answered synchronously. For the
other cases (i.e. where we want per-connection objects that wrap the
asynchronous operation as it goes on) let's not do such inheritance but
initialize the userdata pointer only once we have it. THis means the
original manager object must be manually retrieved from the
VarlinkServer object, which in turn needs to be requested from the
Varlink connection object.

The userdata inheritance is now controlled by the
VARLINK_INHERIT_USERDATA flag passed at VarlinkServer construction.

Alternative-to: #18248
This commit is contained in:
Lennart Poettering 2021-01-20 19:15:55 +01:00 committed by Yu Watanabe
parent 4723205968
commit 9807fdc1da
7 changed files with 18 additions and 11 deletions

View File

@ -432,7 +432,7 @@ int manager_varlink_init(Manager *m) {
if (!MANAGER_IS_SYSTEM(m))
return 0;
r = varlink_server_new(&s, VARLINK_SERVER_ACCOUNT_UID);
r = varlink_server_new(&s, VARLINK_SERVER_ACCOUNT_UID|VARLINK_SERVER_INHERIT_USERDATA);
if (r < 0)
return log_error_errno(r, "Failed to allocate varlink server object: %m");

View File

@ -956,7 +956,7 @@ static int manager_bind_varlink(Manager *m) {
assert(m);
assert(!m->varlink_server);
r = varlink_server_new(&m->varlink_server, VARLINK_SERVER_ACCOUNT_UID);
r = varlink_server_new(&m->varlink_server, VARLINK_SERVER_ACCOUNT_UID|VARLINK_SERVER_INHERIT_USERDATA);
if (r < 0)
return log_error_errno(r, "Failed to allocate varlink server object: %m");

View File

@ -2033,7 +2033,7 @@ static int server_open_varlink(Server *s, const char *socket, int fd) {
assert(s);
r = varlink_server_new(&s->varlink_server, VARLINK_SERVER_ROOT_ONLY);
r = varlink_server_new(&s->varlink_server, VARLINK_SERVER_ROOT_ONLY|VARLINK_SERVER_INHERIT_USERDATA);
if (r < 0)
return r;

View File

@ -388,7 +388,7 @@ int manager_varlink_init(Manager *m) {
if (m->varlink_server)
return 0;
r = varlink_server_new(&s, VARLINK_SERVER_ACCOUNT_UID);
r = varlink_server_new(&s, VARLINK_SERVER_ACCOUNT_UID|VARLINK_SERVER_INHERIT_USERDATA);
if (r < 0)
return log_error_errno(r, "Failed to allocate varlink server object: %m");

View File

@ -269,11 +269,13 @@ static int vl_method_resolve_hostname(Varlink *link, JsonVariant *parameters, Va
_cleanup_(lookup_parameters_destroy) LookupParameters p = {
.family = AF_UNSPEC,
};
Manager *m = userdata;
DnsQuery *q;
Manager *m;
int r;
assert(link);
m = varlink_server_get_userdata(varlink_get_server(link));
assert(m);
if (FLAGS_SET(flags, VARLINK_METHOD_ONEWAY))
@ -447,11 +449,13 @@ static int vl_method_resolve_address(Varlink *link, JsonVariant *parameters, Var
_cleanup_(lookup_parameters_destroy) LookupParameters p = {
.family = AF_UNSPEC,
};
Manager *m = userdata;
DnsQuery *q;
Manager *m;
int r;
assert(link);
m = varlink_server_get_userdata(varlink_get_server(link));
assert(m);
if (FLAGS_SET(flags, VARLINK_METHOD_ONEWAY))

View File

@ -2137,7 +2137,9 @@ int varlink_server_add_connection(VarlinkServer *server, int fd, Varlink **ret)
return r;
v->fd = fd;
v->userdata = server->userdata;
if (server->flags & VARLINK_SERVER_INHERIT_USERDATA)
v->userdata = server->userdata;
if (ucred_acquired) {
v->ucred = ucred;
v->ucred_acquired = true;

View File

@ -41,11 +41,12 @@ typedef enum VarlinkMethodFlags {
} VarlinkMethodFlags;
typedef enum VarlinkServerFlags {
VARLINK_SERVER_ROOT_ONLY = 1 << 0, /* Only accessible by root */
VARLINK_SERVER_MYSELF_ONLY = 1 << 1, /* Only accessible by our own UID */
VARLINK_SERVER_ACCOUNT_UID = 1 << 2, /* Do per user accounting */
VARLINK_SERVER_ROOT_ONLY = 1 << 0, /* Only accessible by root */
VARLINK_SERVER_MYSELF_ONLY = 1 << 1, /* Only accessible by our own UID */
VARLINK_SERVER_ACCOUNT_UID = 1 << 2, /* Do per user accounting */
VARLINK_SERVER_INHERIT_USERDATA = 1 << 3, /* Initialize Varlink connection userdata from VarlinkServer userdata */
_VARLINK_SERVER_FLAGS_ALL = (1 << 3) - 1,
_VARLINK_SERVER_FLAGS_ALL = (1 << 4) - 1,
} VarlinkServerFlags;
typedef int (*VarlinkMethod)(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata);