Fix memleak and double free in varlink methods (#43431)
This commit is contained in:
@@ -142,6 +142,10 @@ static int follow_state_setup(sd_varlink *link, sd_journal *_j /* donated! */) {
|
||||
assert(link);
|
||||
assert(j);
|
||||
|
||||
/* The varlink connection already requested the follow mode. Refusing. */
|
||||
if (sd_varlink_get_userdata(link))
|
||||
return -EBUSY;
|
||||
|
||||
sd_varlink_server *server = ASSERT_PTR(sd_varlink_get_server(link));
|
||||
sd_event *event = ASSERT_PTR(sd_varlink_server_get_event(server));
|
||||
|
||||
|
||||
@@ -1873,7 +1873,7 @@ static int manager_schedule_sync(Manager *m, int priority) {
|
||||
}
|
||||
|
||||
if (!m->event || sd_event_get_state(m->event) == SD_EVENT_FINISHED) {
|
||||
/* Shutting down the server? Let's sync immediately. */
|
||||
/* Shutting down the manager? Let's sync immediately. */
|
||||
manager_sync(m, /* wait= */ false);
|
||||
return 0;
|
||||
}
|
||||
@@ -2133,7 +2133,7 @@ int manager_unlink_seqnum_file(Manager *m, const char *fname) {
|
||||
static bool manager_is_idle(Manager *m) {
|
||||
assert(m);
|
||||
|
||||
/* The server for the main namespace is never idle */
|
||||
/* The manager for the main namespace is never idle */
|
||||
if (!m->namespace)
|
||||
return false;
|
||||
|
||||
|
||||
@@ -687,7 +687,7 @@ static int stdout_stream_new(sd_event_source *es, int listen_fd, uint32_t revent
|
||||
|
||||
if (revents != EPOLLIN)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EIO),
|
||||
"Got invalid event from epoll for stdout server fd: %" PRIx32,
|
||||
"Got invalid event from epoll for stdout fd: %" PRIx32,
|
||||
revents);
|
||||
|
||||
fd = accept4(m->stdout_fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
|
||||
@@ -926,11 +926,11 @@ int manager_open_stdout_socket(Manager *m, const char *stdout_socket) {
|
||||
|
||||
r = sd_event_add_io(m->event, &m->stdout_event_source, m->stdout_fd, EPOLLIN, stdout_stream_new, m);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to add stdout server fd to event source: %m");
|
||||
return log_error_errno(r, "Failed to add stdout fd to event source: %m");
|
||||
|
||||
r = sd_event_source_set_priority(m->stdout_event_source, SD_EVENT_PRIORITY_NORMAL+5);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to adjust priority of stdout server event source: %m");
|
||||
return log_error_errno(r, "Failed to adjust priority of stdout event source: %m");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#include "socket-netlink.h"
|
||||
#include "time-util.h"
|
||||
|
||||
StreamSyncReq *stream_sync_req_free(StreamSyncReq *ssr) {
|
||||
StreamSyncReq* stream_sync_req_free(StreamSyncReq *ssr) {
|
||||
if (!ssr)
|
||||
return NULL;
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ typedef struct SyncReq {
|
||||
unsigned boottime_prioq_idx;
|
||||
} SyncReq;
|
||||
|
||||
StreamSyncReq *stream_sync_req_free(StreamSyncReq *ssr);
|
||||
StreamSyncReq* stream_sync_req_free(StreamSyncReq *ssr);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(StreamSyncReq*, stream_sync_req_free);
|
||||
void stream_sync_req_advance_revalidate(StreamSyncReq *ssr, size_t p);
|
||||
|
||||
|
||||
@@ -40,11 +40,17 @@ static int vl_method_synchronize(sd_varlink *link, sd_json_variant *parameters,
|
||||
{}
|
||||
};
|
||||
|
||||
Manager *m = ASSERT_PTR(userdata);
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
|
||||
/* Here, userdata may not be a pointer to the Manager object. Obtain the manager from the server. */
|
||||
Manager *m = ASSERT_PTR(sd_varlink_server_get_userdata(sd_varlink_get_server(link)));
|
||||
|
||||
/* The varlink connection already requested to sync journals. Refusing. */
|
||||
if (sd_varlink_get_userdata(link) != m)
|
||||
return -EBUSY;
|
||||
|
||||
r = sd_varlink_dispatch(link, parameters, dispatch_table, &offline);
|
||||
if (r != 0)
|
||||
return r;
|
||||
@@ -168,10 +174,11 @@ static void vl_disconnect(sd_varlink_server *server, sd_varlink *link, void *use
|
||||
|
||||
void *u = sd_varlink_get_userdata(link);
|
||||
if (u != m) {
|
||||
/* If this is a Varlink connection that does not have the Server object as userdata, then it has a SyncReq object instead. Let's finish it. */
|
||||
/* If this is a Varlink connection that does not have the Manager object as userdata, then
|
||||
* it has a SyncReq object instead. Let's finish it. */
|
||||
|
||||
SyncReq *req = u;
|
||||
sd_varlink_set_userdata(link, m); /* reinstall server object */
|
||||
sd_varlink_set_userdata(link, m); /* reinstall the manager object */
|
||||
sync_req_free(req);
|
||||
}
|
||||
|
||||
|
||||
@@ -236,6 +236,10 @@ static int vl_method_mute(
|
||||
assert(link);
|
||||
assert(FLAGS_SET(flags, SD_VARLINK_METHOD_MORE));
|
||||
|
||||
/* Refuse multiple requests per connection. */
|
||||
if (sd_varlink_get_userdata(link))
|
||||
return -EBUSY;
|
||||
|
||||
_cleanup_free_ Context *nc = new(Context, 1);
|
||||
if (!nc)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -169,6 +169,10 @@ int vl_method_list_candidate_devices(
|
||||
_cleanup_(list_candidate_devices_context_freep) ListCandidateDevicesContext *c = NULL;
|
||||
|
||||
if (p.subscribe) {
|
||||
/* Refuse multiple requests per connection. */
|
||||
if (sd_varlink_get_userdata(link))
|
||||
return -EBUSY;
|
||||
|
||||
/* Start the monitor *before* the initial enumeration so we don't lose events that fire
|
||||
* during the enumeration window. Duplicate add events for the same device are
|
||||
* legitimate and documented; clients upsert by identifier. */
|
||||
|
||||
@@ -726,27 +726,30 @@ static int mdns_next_query_schedule(sd_event_source *s, uint64_t usec, void *use
|
||||
assert(userdata);
|
||||
assert_se(sb = dns_service_browser_ref(userdata));
|
||||
|
||||
/* Enable the answer from the cache for the very first query */
|
||||
if (sb->delay == 0)
|
||||
SET_FLAG(sb->flags, SD_RESOLVED_NO_CACHE, false);
|
||||
/* If the varlink connection has a userdata, then that means the previous query has not been finished. */
|
||||
if (!sd_varlink_get_userdata(sb->link)) {
|
||||
|
||||
/* Set the flag indicating that the query is continuous.
|
||||
* RFC 6762 Section 5.2 outlines timing requirements for continuous queries.
|
||||
*/
|
||||
sb->flags |= SD_RESOLVED_QUERY_CONTINUOUS;
|
||||
/* Enable the answer from the cache for the very first query */
|
||||
if (sb->delay == 0)
|
||||
SET_FLAG(sb->flags, SD_RESOLVED_NO_CACHE, false);
|
||||
|
||||
r = dns_query_new(sb->manager, &q, sb->question_utf8, sb->question_idna, NULL, sb->ifindex, sb->flags);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to create new DNS query: %m");
|
||||
/* Set the flag indicating that the query is continuous.
|
||||
* RFC 6762 Section 5.2 outlines timing requirements for continuous queries. */
|
||||
sb->flags |= SD_RESOLVED_QUERY_CONTINUOUS;
|
||||
|
||||
q->complete = mdns_browse_service_query_complete;
|
||||
q->service_browser_request = dns_service_browser_ref(sb);
|
||||
q->varlink_request = sd_varlink_ref(sb->link);
|
||||
sd_varlink_set_userdata(sb->link, q);
|
||||
r = dns_query_new(sb->manager, &q, sb->question_utf8, sb->question_idna, NULL, sb->ifindex, sb->flags);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to create new DNS query: %m");
|
||||
|
||||
r = dns_query_go(q);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to send DNS query: %m");
|
||||
q->complete = mdns_browse_service_query_complete;
|
||||
q->service_browser_request = dns_service_browser_ref(sb);
|
||||
q->varlink_request = sd_varlink_ref(sb->link);
|
||||
sd_varlink_set_userdata(sb->link, q);
|
||||
|
||||
r = dns_query_go(q);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to send DNS query: %m");
|
||||
}
|
||||
|
||||
/* Calculate the next query delay */
|
||||
sb->delay = mdns_calculate_next_query_delay(sb->delay);
|
||||
@@ -811,6 +814,10 @@ int dns_subscribe_browse_service(
|
||||
assert(m);
|
||||
assert(link);
|
||||
|
||||
/* Refuse multiple requests. */
|
||||
if (hashmap_contains(m->dns_service_browsers, link))
|
||||
return -EBUSY;
|
||||
|
||||
if (ifindex < 0)
|
||||
return sd_varlink_error_invalid_parameter_name(link, "ifindex");
|
||||
|
||||
|
||||
@@ -363,6 +363,9 @@ static int vl_method_resolve_hostname(sd_varlink *link, sd_json_variant *paramet
|
||||
|
||||
assert(link);
|
||||
|
||||
if (sd_varlink_get_userdata(link))
|
||||
return -EBUSY;
|
||||
|
||||
m = sd_varlink_server_get_userdata(sd_varlink_get_server(link));
|
||||
assert(m);
|
||||
|
||||
@@ -490,6 +493,9 @@ static int vl_method_resolve_address(sd_varlink *link, sd_json_variant *paramete
|
||||
|
||||
assert(link);
|
||||
|
||||
if (sd_varlink_get_userdata(link))
|
||||
return -EBUSY;
|
||||
|
||||
m = sd_varlink_server_get_userdata(sd_varlink_get_server(link));
|
||||
assert(m);
|
||||
|
||||
@@ -973,6 +979,9 @@ static int vl_method_resolve_service(sd_varlink* link, sd_json_variant* paramete
|
||||
|
||||
assert(link);
|
||||
|
||||
if (sd_varlink_get_userdata(link))
|
||||
return -EBUSY;
|
||||
|
||||
m = sd_varlink_server_get_userdata(sd_varlink_get_server(link));
|
||||
assert(m);
|
||||
|
||||
@@ -1124,6 +1133,9 @@ static int vl_method_resolve_record(sd_varlink *link, sd_json_variant *parameter
|
||||
|
||||
assert(link);
|
||||
|
||||
if (sd_varlink_get_userdata(link))
|
||||
return -EBUSY;
|
||||
|
||||
m = ASSERT_PTR(sd_varlink_server_get_userdata(sd_varlink_get_server(link)));
|
||||
|
||||
if (FLAGS_SET(flags, SD_VARLINK_METHOD_ONEWAY))
|
||||
|
||||
@@ -1822,6 +1822,10 @@ static int vl_method_list_candidate_devices(
|
||||
|
||||
assert(link);
|
||||
|
||||
/* Refuse multiple requests */
|
||||
if (sd_varlink_get_userdata(link))
|
||||
return -EBUSY;
|
||||
|
||||
sd_varlink_server *varlink_server = sd_varlink_get_server(link);
|
||||
sd_event *event = sd_varlink_server_get_event(varlink_server);
|
||||
Hashmap **polkit_registry = ASSERT_PTR(sd_varlink_server_get_userdata(varlink_server));
|
||||
|
||||
Reference in New Issue
Block a user