pipewire/src/modules/module-protocol-pulse/client.h

119 lines
2.7 KiB
C
Raw Normal View History

/* PipeWire */
/* SPDX-FileCopyrightText: Copyright © 2020 Wim Taymans */
/* SPDX-License-Identifier: MIT */
#ifndef PULSER_SERVER_CLIENT_H
#define PULSER_SERVER_CLIENT_H
#include <stdbool.h>
#include <stdint.h>
#include <spa/utils/list.h>
#include <spa/utils/hook.h>
#include <pipewire/map.h>
struct impl;
struct server;
struct message;
struct spa_source;
struct pw_properties;
struct pw_core;
struct pw_manager;
struct pw_manager_object;
struct pw_properties;
struct descriptor {
uint32_t length;
uint32_t channel;
uint32_t offset_hi;
uint32_t offset_lo;
uint32_t flags;
};
struct client {
struct spa_list link;
struct impl *impl;
struct server *server;
int ref;
pulse-server: update client::name on UPDATE_CLIENT_PROPLIST command `client::name` points to a string that is owned by `client::props`, so when the property list is updated, it needs to be refreshed as well. Otherwise, various use-after-frees can be triggered, for example: ==1471586==ERROR: AddressSanitizer: heap-use-after-free on address 0x60200007e7d0 at pc 0x7f14390755d0 bp 0x7ffe23edee30 sp 0x7ffe23ede5a8 READ of size 3 at 0x60200007e7d0 thread T0 #0 0x7f14390755cf in printf_common /usr/src/debug/gcc/libsanitizer/sanitizer_common/sanitizer_common_interceptors_format.inc:553 #1 0x7f1439077215 in __interceptor_vsnprintf /usr/src/debug/gcc/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:1665 #2 0x7f1434ead47d in spa_vscnprintf ../spa/include/spa/utils/string.h:239 #3 0x7f1434eae2ae in impl_log_logtv ../spa/plugins/support/logger.c:138 #4 0x7f14385cacc7 in pw_log_logt ../src/pipewire/log.c:135 #5 0x7f1433aef8e9 in do_set_profile ../src/modules/module-protocol-pulse/pulse-server.c:4656 #6 0x7f1433b0af4d in handle_packet ../src/modules/module-protocol-pulse/server.c:109 #7 0x7f1433b0e747 in do_read ../src/modules/module-protocol-pulse/server.c:276 #8 0x7f1433b0eb04 in on_client_data ../src/modules/module-protocol-pulse/server.c:306 #9 0x7f1434ec56a0 in source_io_func ../spa/plugins/support/loop.c:442 #10 0x7f1434ec4a21 in loop_iterate ../spa/plugins/support/loop.c:430 #11 0x7f14385dc23d in pw_main_loop_run ../src/pipewire/main-loop.c:148 #12 0x55b065d73722 in main ../src/daemon/pipewire.c:131 #13 0x7f143742928f (/usr/lib/libc.so.6+0x2928f) #14 0x7f1437429349 in __libc_start_main (/usr/lib/libc.so.6+0x29349) #15 0x55b065d722a4 in _start (./src/daemon/pipewire-pulse+0x42a4) 0x60200007e7d0 is located 0 bytes inside of 16-byte region [0x60200007e7d0,0x60200007e7e0) freed by thread T0 here: #0 0x7f14390be672 in __interceptor_free /usr/src/debug/gcc/libsanitizer/asan/asan_malloc_linux.cpp:52 #1 0x7f14386a775a in do_replace ../src/pipewire/properties.c:414 #2 0x7f14386a785e in pw_properties_set ../src/pipewire/properties.c:441 #3 0x7f14386a658b in pw_properties_update ../src/pipewire/properties.c:309 #4 0x7f1433adb055 in do_update_proplist ../src/modules/module-protocol-pulse/pulse-server.c:3246 #5 0x7f1433b0af4d in handle_packet ../src/modules/module-protocol-pulse/server.c:109 #6 0x7f1433b0e747 in do_read ../src/modules/module-protocol-pulse/server.c:276 #7 0x7f1433b0eb04 in on_client_data ../src/modules/module-protocol-pulse/server.c:306 #8 0x7f1434ec56a0 in source_io_func ../spa/plugins/support/loop.c:442 #9 0x7f1434ec4a21 in loop_iterate ../spa/plugins/support/loop.c:430 #10 0x7f14385dc23d in pw_main_loop_run ../src/pipewire/main-loop.c:148 #11 0x55b065d73722 in main ../src/daemon/pipewire.c:131 #12 0x7f143742928f (/usr/lib/libc.so.6+0x2928f) previously allocated by thread T0 here: #0 0x7f1439072faa in __interceptor_strdup /usr/src/debug/gcc/libsanitizer/asan/asan_interceptors.cpp:439 #1 0x7f14386a6fe2 in do_replace ../src/pipewire/properties.c:394 #2 0x7f14386a785e in pw_properties_set ../src/pipewire/properties.c:441 #3 0x7f1433a6c52d in read_props ../src/modules/module-protocol-pulse/message.c:147 #4 0x7f1433a6f467 in message_get ../src/modules/module-protocol-pulse/message.c:359 #5 0x7f1433ab3191 in do_set_client_name ../src/modules/module-protocol-pulse/pulse-server.c:1030 #6 0x7f1433b0af4d in handle_packet ../src/modules/module-protocol-pulse/server.c:109 #7 0x7f1433b0e747 in do_read ../src/modules/module-protocol-pulse/server.c:276 #8 0x7f1433b0eb04 in on_client_data ../src/modules/module-protocol-pulse/server.c:306 #9 0x7f1434ec56a0 in source_io_func ../spa/plugins/support/loop.c:442 #10 0x7f1434ec4a21 in loop_iterate ../spa/plugins/support/loop.c:430 #11 0x7f14385dc23d in pw_main_loop_run ../src/pipewire/main-loop.c:148 #12 0x55b065d73722 in main ../src/daemon/pipewire.c:131 #13 0x7f143742928f (/usr/lib/libc.so.6+0x2928f)
2022-06-20 17:22:45 +02:00
const char *name; /* owned by `client::props` */
struct spa_source *source;
uint32_t version;
struct pw_properties *props;
uint64_t quirks;
struct pw_core *core;
struct pw_manager *manager;
struct spa_hook manager_listener;
uint32_t subscribed;
struct pw_manager_object *metadata_default;
char *default_sink;
char *default_source;
char *temporary_default_sink; /**< pending value, for MOVE_* commands */
char *temporary_default_source; /**< pending value, for MOVE_* commands */
struct pw_manager_object *metadata_routes;
struct pw_properties *routes;
uint32_t connect_tag;
uint32_t in_index;
uint32_t out_index;
struct descriptor desc;
struct message *message;
struct pw_map streams;
struct spa_list out_messages;
struct spa_list operations;
struct spa_list pending_samples;
unsigned int disconnect:1;
unsigned int new_msg_since_last_flush:1;
unsigned int authenticated:1;
struct pw_manager_object *prev_default_sink;
struct pw_manager_object *prev_default_source;
struct spa_hook_list listener_list;
};
struct client_events {
#define VERSION_CLIENT_EVENTS 1
uint32_t version;
void (*disconnect) (void *data);
void (*routes_changed) (void *data);
};
struct client *client_new(struct server *server);
bool client_detach(struct client *client);
void client_disconnect(struct client *client);
void client_free(struct client *client);
int client_queue_message(struct client *client, struct message *msg);
int client_flush_messages(struct client *client);
int client_queue_subscribe_event(struct client *client, uint32_t mask, uint32_t event, uint32_t id);
void client_update_routes(struct client *client, const char *key, const char *value);
static inline void client_unref(struct client *client)
{
if (--client->ref == 0)
client_free(client);
}
static inline void client_add_listener(struct client *client, struct spa_hook *listener,
const struct client_events *events, void *data)
{
spa_hook_list_append(&client->listener_list, listener, events, data);
}
#endif /* PULSER_SERVER_CLIENT_H */