diff options
author | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2019-05-21 08:45:19 +0200 |
---|---|---|
committer | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2019-05-29 10:20:42 +0200 |
commit | 0985c7c4e22c8dbbea4398cf3453da45ebf63800 (patch) | |
tree | bbb08300ff3c022617628b8cbff223218b2ebc62 /src/shared/cpu-set-util.h | |
parent | b12ef7141648be40fd8c4b0209a742f2151736d9 (diff) | |
download | systemd-0985c7c4e22c8dbbea4398cf3453da45ebf63800.tar.gz |
Rework cpu affinity parsing
The CPU_SET_S api is pretty bad. In particular, it has a parameter for the size
of the array, but operations which take two (CPU_EQUAL_S) or even three arrays
(CPU_{AND,OR,XOR}_S) still take just one size. This means that all arrays must
be of the same size, or buffer overruns will occur. This is exactly what our
code would do, if it received an array of unexpected size over the network.
("Unexpected" here means anything different from what cpu_set_malloc() detects
as the "right" size.)
Let's rework this, and store the size in bytes of the allocated storage area.
The code will now parse any number up to 8191, independently of what the current
kernel supports. This matches the kernel maximum setting for any architecture,
to make things more portable.
Fixes #12605.
Diffstat (limited to 'src/shared/cpu-set-util.h')
-rw-r--r-- | src/shared/cpu-set-util.h | 47 |
1 files changed, 32 insertions, 15 deletions
diff --git a/src/shared/cpu-set-util.h b/src/shared/cpu-set-util.h index 9574b81582..4c1c81fc59 100644 --- a/src/shared/cpu-set-util.h +++ b/src/shared/cpu-set-util.h @@ -8,23 +8,40 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(cpu_set_t*, CPU_FREE); #define _cleanup_cpu_free_ _cleanup_(CPU_FREEp) -static inline cpu_set_t* cpu_set_mfree(cpu_set_t *p) { - if (p) - CPU_FREE(p); - return NULL; -} - cpu_set_t* cpu_set_malloc(unsigned *ncpus); -char* cpu_set_to_string(const cpu_set_t *set, size_t setsize); -int parse_cpu_set_internal(const char *rvalue, cpu_set_t **cpu_set, bool warn, const char *unit, const char *filename, unsigned line, const char *lvalue); - -static inline int parse_cpu_set_and_warn(const char *rvalue, cpu_set_t **cpu_set, const char *unit, const char *filename, unsigned line, const char *lvalue) { - assert(lvalue); - - return parse_cpu_set_internal(rvalue, cpu_set, true, unit, filename, line, lvalue); +/* This wraps the libc interface with a variable to keep the allocated size. */ +typedef struct CPUSet { + cpu_set_t *set; + size_t allocated; /* in bytes */ +} CPUSet; + +static inline void cpu_set_reset(CPUSet *a) { + assert((a->allocated > 0) == !!a->set); + if (a->set) + CPU_FREE(a->set); + *a = (CPUSet) {}; } -static inline int parse_cpu_set(const char *rvalue, cpu_set_t **cpu_set){ - return parse_cpu_set_internal(rvalue, cpu_set, false, NULL, NULL, 0, NULL); +int cpu_set_add_all(CPUSet *a, const CPUSet *b); + +char* cpu_set_to_string(const CPUSet *a); +int parse_cpu_set_full( + const char *rvalue, + CPUSet *cpu_set, + bool warn, + const char *unit, + const char *filename, unsigned line, + const char *lvalue); +int parse_cpu_set_extend( + const char *rvalue, + CPUSet *old, + bool warn, + const char *unit, + const char *filename, + unsigned line, + const char *lvalue); + +static inline int parse_cpu_set(const char *rvalue, CPUSet *cpu_set){ + return parse_cpu_set_full(rvalue, cpu_set, false, NULL, NULL, 0, NULL); } |