mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2026-05-03 06:47:04 -04:00
security: add total sample cache size limit in PulseAudio protocol
There was no limit on the total size of the sample cache. A client could upload many samples to exhaust server memory. Add a configurable pulse.max-sample-cache property (default 64MB) to cap the total size of all cached samples. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
37990b5e90
commit
52afec565b
5 changed files with 18 additions and 0 deletions
|
|
@ -120,6 +120,7 @@ pulse.properties = {
|
||||||
#pulse.min.quantum = 256/48000 # 5.3ms
|
#pulse.min.quantum = 256/48000 # 5.3ms
|
||||||
#pulse.idle.timeout = 0 # don't pause after underruns
|
#pulse.idle.timeout = 0 # don't pause after underruns
|
||||||
#pulse.max-streams = 64 # max streams per client
|
#pulse.max-streams = 64 # max streams per client
|
||||||
|
#pulse.max-sample-cache = 67108864 # max total sample cache size (64MB)
|
||||||
#pulse.default.format = F32
|
#pulse.default.format = F32
|
||||||
#pulse.default.position = [ FL FR ]
|
#pulse.default.position = [ FL FR ]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -77,6 +77,7 @@
|
||||||
* #pulse.default.position = [ FL FR ]
|
* #pulse.default.position = [ FL FR ]
|
||||||
* #pulse.idle.timeout = 0
|
* #pulse.idle.timeout = 0
|
||||||
* #pulse.max-streams = 64
|
* #pulse.max-streams = 64
|
||||||
|
* #pulse.max-sample-cache = 67108864
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* pulse.properties.rules = [
|
* pulse.properties.rules = [
|
||||||
|
|
@ -254,6 +255,13 @@
|
||||||
*
|
*
|
||||||
* The maximum number of streams a single client can create. Default is 64.
|
* The maximum number of streams a single client can create. Default is 64.
|
||||||
*
|
*
|
||||||
|
*\code{.unparsed}
|
||||||
|
* pulse.max-sample-cache = 67108864
|
||||||
|
*\endcode
|
||||||
|
*
|
||||||
|
* The maximum total size in bytes of all sample cache entries. Default is
|
||||||
|
* 67108864 (64MB).
|
||||||
|
*
|
||||||
* ## Command execution
|
* ## Command execution
|
||||||
*
|
*
|
||||||
* As part of the server startup sequence, a set of commands can be executed.
|
* As part of the server startup sequence, a set of commands can be executed.
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@
|
||||||
#define MAX_NAME 1024u
|
#define MAX_NAME 1024u
|
||||||
|
|
||||||
#define SCACHE_ENTRY_SIZE_MAX (1024*1024*16)
|
#define SCACHE_ENTRY_SIZE_MAX (1024*1024*16)
|
||||||
|
#define MAX_SAMPLE_CACHE (1024u*1024*64) /* 64MB */
|
||||||
|
|
||||||
#define MAX_CLIENTS 64u
|
#define MAX_CLIENTS 64u
|
||||||
#define MAX_STREAMS 64u
|
#define MAX_STREAMS 64u
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ struct defs {
|
||||||
uint32_t quantum_limit;
|
uint32_t quantum_limit;
|
||||||
uint32_t idle_timeout;
|
uint32_t idle_timeout;
|
||||||
uint32_t max_streams;
|
uint32_t max_streams;
|
||||||
|
uint32_t max_sample_cache;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct stats {
|
struct stats {
|
||||||
|
|
|
||||||
|
|
@ -2413,6 +2413,12 @@ static int do_finish_upload_stream(struct client *client, uint32_t command, uint
|
||||||
channel, name);
|
channel, name);
|
||||||
|
|
||||||
struct sample *old = find_sample(impl, SPA_ID_INVALID, name);
|
struct sample *old = find_sample(impl, SPA_ID_INVALID, name);
|
||||||
|
uint32_t new_length = stream->attr.maxlength;
|
||||||
|
uint32_t old_length = old != NULL ? old->length : 0;
|
||||||
|
if (impl->stat.sample_cache + new_length - old_length > impl->defs.max_sample_cache) {
|
||||||
|
res = -ENOSPC;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
if (old == NULL || old->ref > 1) {
|
if (old == NULL || old->ref > 1) {
|
||||||
sample = calloc(1, sizeof(*sample));
|
sample = calloc(1, sizeof(*sample));
|
||||||
if (sample == NULL)
|
if (sample == NULL)
|
||||||
|
|
@ -5606,6 +5612,7 @@ static void load_defaults(struct defs *def, struct pw_properties *props)
|
||||||
parse_position(props, "pulse.default.position", DEFAULT_POSITION, &def->channel_map);
|
parse_position(props, "pulse.default.position", DEFAULT_POSITION, &def->channel_map);
|
||||||
parse_uint32(props, "pulse.idle.timeout", DEFAULT_IDLE_TIMEOUT, &def->idle_timeout);
|
parse_uint32(props, "pulse.idle.timeout", DEFAULT_IDLE_TIMEOUT, &def->idle_timeout);
|
||||||
parse_uint32(props, "pulse.max-streams", SPA_STRINGIFY(MAX_STREAMS), &def->max_streams);
|
parse_uint32(props, "pulse.max-streams", SPA_STRINGIFY(MAX_STREAMS), &def->max_streams);
|
||||||
|
parse_uint32(props, "pulse.max-sample-cache", SPA_STRINGIFY(MAX_SAMPLE_CACHE), &def->max_sample_cache);
|
||||||
def->sample_spec.channels = def->channel_map.channels;
|
def->sample_spec.channels = def->channel_map.channels;
|
||||||
def->quantum_limit = 8192;
|
def->quantum_limit = 8192;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue