diff options
Diffstat (limited to 'elf')
-rw-r--r-- | elf/dl-tunable-types.h | 4 | ||||
-rw-r--r-- | elf/dl-tunables.c | 128 | ||||
-rw-r--r-- | elf/dl-tunables.h | 37 |
3 files changed, 61 insertions, 108 deletions
diff --git a/elf/dl-tunable-types.h b/elf/dl-tunable-types.h index 3fcc080..626ca33 100644 --- a/elf/dl-tunable-types.h +++ b/elf/dl-tunable-types.h @@ -38,8 +38,8 @@ typedef enum typedef struct { tunable_type_code_t type_code; - int64_t min; - int64_t max; + tunable_num_t min; + tunable_num_t max; } tunable_type_t; /* Security level for tunables. This decides what to do with individual diff --git a/elf/dl-tunables.c b/elf/dl-tunables.c index b1a50b8..a2be9cd 100644 --- a/elf/dl-tunables.c +++ b/elf/dl-tunables.c @@ -93,87 +93,45 @@ get_next_env (char **envp, char **name, size_t *namelen, char **val, return NULL; } -#define TUNABLE_SET_VAL_IF_VALID_RANGE(__cur, __val, __type) \ -({ \ - __type min = (__cur)->type.min; \ - __type max = (__cur)->type.max; \ - \ - if ((__type) (__val) >= min && (__type) (__val) <= max) \ - { \ - (__cur)->val.numval = (__val); \ - (__cur)->initialized = true; \ - } \ -}) - -#define TUNABLE_SET_BOUNDS_IF_VALID(__cur, __minp, __maxp, __type) \ -({ \ - if (__minp != NULL) \ - { \ - /* MIN is specified. */ \ - __type min = *((__type *) __minp); \ - if (__maxp != NULL) \ - { \ - /* Both MIN and MAX are specified. */ \ - __type max = *((__type *) __maxp); \ - if (max >= min \ - && max <= (__cur)->type.max \ - && min >= (__cur)->type.min) \ - { \ - (__cur)->type.min = min; \ - (__cur)->type.max = max; \ - } \ - } \ - else if (min > (__cur)->type.min && min <= (__cur)->type.max) \ - { \ - /* Only MIN is specified. */ \ - (__cur)->type.min = min; \ - } \ - } \ - else if (__maxp != NULL) \ - { \ - /* Only MAX is specified. */ \ - __type max = *((__type *) __maxp); \ - if (max < (__cur)->type.max && max >= (__cur)->type.min) \ - (__cur)->type.max = max; \ - } \ -}) - static void -do_tunable_update_val (tunable_t *cur, const void *valp, - const void *minp, const void *maxp) +do_tunable_update_val (tunable_t *cur, const tunable_val_t *valp, + const tunable_num_t *minp, + const tunable_num_t *maxp) { - uint64_t val; + tunable_num_t val, min, max; - if (cur->type.type_code != TUNABLE_TYPE_STRING) - val = *((int64_t *) valp); + if (cur->type.type_code == TUNABLE_TYPE_STRING) + { + cur->val.strval = valp->strval; + cur->initialized = true; + return; + } - switch (cur->type.type_code) + val = valp->numval; + min = minp != NULL ? *minp : cur->type.min; + max = maxp != NULL ? *maxp : cur->type.max; + + /* We allow only increasingly restrictive bounds. */ + if (min < cur->type.min) + min = cur->type.min; + + if (max > cur->type.max) + max = cur->type.max; + + /* Skip both bounds if they're inconsistent. */ + if (min > max) { - case TUNABLE_TYPE_INT_32: - { - TUNABLE_SET_BOUNDS_IF_VALID (cur, minp, maxp, int64_t); - TUNABLE_SET_VAL_IF_VALID_RANGE (cur, val, int64_t); - break; - } - case TUNABLE_TYPE_UINT_64: - { - TUNABLE_SET_BOUNDS_IF_VALID (cur, minp, maxp, uint64_t); - TUNABLE_SET_VAL_IF_VALID_RANGE (cur, val, uint64_t); - break; - } - case TUNABLE_TYPE_SIZE_T: - { - TUNABLE_SET_BOUNDS_IF_VALID (cur, minp, maxp, uint64_t); - TUNABLE_SET_VAL_IF_VALID_RANGE (cur, val, uint64_t); - break; - } - case TUNABLE_TYPE_STRING: - { - cur->val.strval = valp; - break; - } - default: - __builtin_unreachable (); + min = cur->type.min; + max = cur->type.max; + } + + /* Write everything out if the value and the bounds are valid. */ + if (min <= val && val <= max) + { + cur->val.numval = val; + cur->type.min = min; + cur->type.max = max; + cur->initialized = true; } } @@ -182,24 +140,18 @@ do_tunable_update_val (tunable_t *cur, const void *valp, static void tunable_initialize (tunable_t *cur, const char *strval) { - uint64_t val; - const void *valp; + tunable_val_t val; if (cur->type.type_code != TUNABLE_TYPE_STRING) - { - val = _dl_strtoul (strval, NULL); - valp = &val; - } + val.numval = (tunable_num_t) _dl_strtoul (strval, NULL); else - { - cur->initialized = true; - valp = strval; - } - do_tunable_update_val (cur, valp, NULL, NULL); + val.strval = strval; + do_tunable_update_val (cur, &val, NULL, NULL); } void -__tunable_set_val (tunable_id_t id, void *valp, void *minp, void *maxp) +__tunable_set_val (tunable_id_t id, tunable_val_t *valp, tunable_num_t *minp, + tunable_num_t *maxp) { tunable_t *cur = &tunable_list[id]; diff --git a/elf/dl-tunables.h b/elf/dl-tunables.h index 971376b..ba7ae6b 100644 --- a/elf/dl-tunables.h +++ b/elf/dl-tunables.h @@ -33,9 +33,11 @@ __tunables_init (char **unused __attribute__ ((unused))) # include <stddef.h> # include <stdint.h> +typedef intmax_t tunable_num_t; + typedef union { - int64_t numval; + tunable_num_t numval; const char *strval; } tunable_val_t; @@ -52,7 +54,8 @@ typedef void (*tunable_callback_t) (tunable_val_t *); extern void __tunables_init (char **); extern void __tunables_print (void); extern void __tunable_get_val (tunable_id_t, void *, tunable_callback_t); -extern void __tunable_set_val (tunable_id_t, void *, void *, void *); +extern void __tunable_set_val (tunable_id_t, tunable_val_t *, tunable_num_t *, + tunable_num_t *); rtld_hidden_proto (__tunables_init) rtld_hidden_proto (__tunables_print) rtld_hidden_proto (__tunable_get_val) @@ -64,20 +67,18 @@ rtld_hidden_proto (__tunable_set_val) #if defined TOP_NAMESPACE && defined TUNABLE_NAMESPACE # define TUNABLE_GET(__id, __type, __cb) \ TUNABLE_GET_FULL (TOP_NAMESPACE, TUNABLE_NAMESPACE, __id, __type, __cb) -# define TUNABLE_SET(__id, __type, __val) \ - TUNABLE_SET_FULL (TOP_NAMESPACE, TUNABLE_NAMESPACE, __id, __type, __val) -# define TUNABLE_SET_WITH_BOUNDS(__id, __type, __val, __min, __max) \ +# define TUNABLE_SET(__id, __val) \ + TUNABLE_SET_FULL (TOP_NAMESPACE, TUNABLE_NAMESPACE, __id, __val) +# define TUNABLE_SET_WITH_BOUNDS(__id, __val, __min, __max) \ TUNABLE_SET_WITH_BOUNDS_FULL (TOP_NAMESPACE, TUNABLE_NAMESPACE, __id, \ - __type, __val, __min, __max) + __val, __min, __max) #else # define TUNABLE_GET(__top, __ns, __id, __type, __cb) \ TUNABLE_GET_FULL (__top, __ns, __id, __type, __cb) -# define TUNABLE_SET(__top, __ns, __id, __type, __val) \ - TUNABLE_SET_FULL (__top, __ns, __id, __type, __val) -# define TUNABLE_SET_WITH_BOUNDS(__top, __ns, __id, __type, __val, \ - __min, __max) \ - TUNABLE_SET_WITH_BOUNDS_FULL (__top, __ns, __id, __type, __val, \ - __min, __max) +# define TUNABLE_SET(__top, __ns, __id, __val) \ + TUNABLE_SET_FULL (__top, __ns, __id, __val) +# define TUNABLE_SET_WITH_BOUNDS(__top, __ns, __id, __val, __min, __max) \ + TUNABLE_SET_WITH_BOUNDS_FULL (__top, __ns, __id, __val, __min, __max) #endif /* Get and return a tunable value. If the tunable was set externally and __CB @@ -91,19 +92,19 @@ rtld_hidden_proto (__tunable_set_val) }) /* Set a tunable value. */ -# define TUNABLE_SET_FULL(__top, __ns, __id, __type, __val) \ +# define TUNABLE_SET_FULL(__top, __ns, __id, __val) \ ({ \ __tunable_set_val (TUNABLE_ENUM_NAME (__top, __ns, __id), \ - & (__type) {__val}, NULL, NULL); \ + & (tunable_val_t) {.numval = __val}, NULL, NULL); \ }) /* Set a tunable value together with min/max values. */ -# define TUNABLE_SET_WITH_BOUNDS_FULL(__top, __ns, __id, __type, __val, \ - __min, __max) \ +# define TUNABLE_SET_WITH_BOUNDS_FULL(__top, __ns, __id,__val, __min, __max) \ ({ \ __tunable_set_val (TUNABLE_ENUM_NAME (__top, __ns, __id), \ - & (__type) {__val}, & (__type) {__min}, \ - & (__type) {__max}); \ + & (tunable_val_t) {.numval = __val}, \ + & (tunable_num_t) {__min}, \ + & (tunable_num_t) {__max}); \ }) /* Namespace sanity for callback functions. Use this macro to keep the |