diff options
Diffstat (limited to 'src/basic')
-rw-r--r-- | src/basic/env-util.c | 2 | ||||
-rw-r--r-- | src/basic/hashmap.c | 35 | ||||
-rw-r--r-- | src/basic/hashmap.h | 11 | ||||
-rw-r--r-- | src/basic/missing.h | 13 | ||||
-rw-r--r-- | src/basic/siphash24.c | 245 | ||||
-rw-r--r-- | src/basic/siphash24.h | 13 | ||||
-rw-r--r-- | src/basic/smack-util.c | 3 | ||||
-rw-r--r-- | src/basic/smack-util.h | 3 | ||||
-rw-r--r-- | src/basic/strv.c | 47 | ||||
-rw-r--r-- | src/basic/strv.h | 2 | ||||
-rw-r--r-- | src/basic/util.c | 34 | ||||
-rw-r--r-- | src/basic/util.h | 2 |
12 files changed, 280 insertions, 130 deletions
diff --git a/src/basic/env-util.c b/src/basic/env-util.c index 4804a67f91..ecb2192c4d 100644 --- a/src/basic/env-util.c +++ b/src/basic/env-util.c @@ -541,7 +541,7 @@ char **replace_env_argv(char **argv, char **env) { STRV_FOREACH(i, argv) { /* If $FOO appears as single word, replace it by the split up variable */ - if ((*i)[0] == '$' && (*i)[1] != '{') { + if ((*i)[0] == '$' && (*i)[1] != '{' && (*i)[1] != '$') { char *e; char **w, **m = NULL; unsigned q; diff --git a/src/basic/hashmap.c b/src/basic/hashmap.c index 7d2a4160c6..20e7e51d9e 100644 --- a/src/basic/hashmap.c +++ b/src/basic/hashmap.c @@ -276,10 +276,8 @@ static const struct hashmap_type_info hashmap_type_info[_HASHMAP_TYPE_MAX] = { }, }; -unsigned long string_hash_func(const void *p, const uint8_t hash_key[HASH_KEY_SIZE]) { - uint64_t u; - siphash24((uint8_t*) &u, p, strlen(p), hash_key); - return (unsigned long) u; +void string_hash_func(const void *p, struct siphash *state) { + siphash24_compress(p, strlen(p) + 1, state); } int string_compare_func(const void *a, const void *b) { @@ -291,10 +289,8 @@ const struct hash_ops string_hash_ops = { .compare = string_compare_func }; -unsigned long trivial_hash_func(const void *p, const uint8_t hash_key[HASH_KEY_SIZE]) { - uint64_t u; - siphash24((uint8_t*) &u, &p, sizeof(p), hash_key); - return (unsigned long) u; +void trivial_hash_func(const void *p, struct siphash *state) { + siphash24_compress(&p, sizeof(p), state); } int trivial_compare_func(const void *a, const void *b) { @@ -306,10 +302,8 @@ const struct hash_ops trivial_hash_ops = { .compare = trivial_compare_func }; -unsigned long uint64_hash_func(const void *p, const uint8_t hash_key[HASH_KEY_SIZE]) { - uint64_t u; - siphash24((uint8_t*) &u, p, sizeof(uint64_t), hash_key); - return (unsigned long) u; +void uint64_hash_func(const void *p, struct siphash *state) { + siphash24_compress(p, sizeof(uint64_t), state); } int uint64_compare_func(const void *_a, const void *_b) { @@ -325,10 +319,8 @@ const struct hash_ops uint64_hash_ops = { }; #if SIZEOF_DEV_T != 8 -unsigned long devt_hash_func(const void *p, const uint8_t hash_key[HASH_KEY_SIZE]) { - uint64_t u; - siphash24((uint8_t*) &u, p, sizeof(dev_t), hash_key); - return (unsigned long) u; +void devt_hash_func(const void *p, struct siphash *state) { + siphash24_compress(p, sizeof(dev_t), state); } int devt_compare_func(const void *_a, const void *_b) { @@ -379,7 +371,16 @@ static uint8_t *hash_key(HashmapBase *h) { } static unsigned base_bucket_hash(HashmapBase *h, const void *p) { - return (unsigned) (h->hash_ops->hash(p, hash_key(h)) % n_buckets(h)); + struct siphash state; + uint64_t hash; + + siphash24_init(&state, hash_key(h)); + + h->hash_ops->hash(p, &state); + + siphash24_finalize((uint8_t*)&hash, &state); + + return (unsigned) (hash % n_buckets(h)); } #define bucket_hash(h, p) base_bucket_hash(HASHMAP_BASE(h), p) diff --git a/src/basic/hashmap.h b/src/basic/hashmap.h index 2af23024de..ed6a092d82 100644 --- a/src/basic/hashmap.h +++ b/src/basic/hashmap.h @@ -25,6 +25,7 @@ #include <stdbool.h> #include "macro.h" +#include "siphash24.h" #include "util.h" /* @@ -67,7 +68,7 @@ typedef struct { #define _IDX_ITERATOR_FIRST (UINT_MAX - 1) #define ITERATOR_FIRST ((Iterator) { .idx = _IDX_ITERATOR_FIRST, .next_key = NULL }) -typedef unsigned long (*hash_func_t)(const void *p, const uint8_t hash_key[HASH_KEY_SIZE]); +typedef void (*hash_func_t)(const void *p, struct siphash *state); typedef int (*compare_func_t)(const void *a, const void *b); struct hash_ops { @@ -75,28 +76,28 @@ struct hash_ops { compare_func_t compare; }; -unsigned long string_hash_func(const void *p, const uint8_t hash_key[HASH_KEY_SIZE]) _pure_; +void string_hash_func(const void *p, struct siphash *state); int string_compare_func(const void *a, const void *b) _pure_; extern const struct hash_ops string_hash_ops; /* This will compare the passed pointers directly, and will not * dereference them. This is hence not useful for strings or * suchlike. */ -unsigned long trivial_hash_func(const void *p, const uint8_t hash_key[HASH_KEY_SIZE]) _pure_; +void trivial_hash_func(const void *p, struct siphash *state); int trivial_compare_func(const void *a, const void *b) _const_; extern const struct hash_ops trivial_hash_ops; /* 32bit values we can always just embedd in the pointer itself, but * in order to support 32bit archs we need store 64bit values * indirectly, since they don't fit in a pointer. */ -unsigned long uint64_hash_func(const void *p, const uint8_t hash_key[HASH_KEY_SIZE]) _pure_; +void uint64_hash_func(const void *p, struct siphash *state); int uint64_compare_func(const void *a, const void *b) _pure_; extern const struct hash_ops uint64_hash_ops; /* On some archs dev_t is 32bit, and on others 64bit. And sometimes * it's 64bit on 32bit archs, and sometimes 32bit on 64bit archs. Yuck! */ #if SIZEOF_DEV_T != 8 -unsigned long devt_hash_func(const void *p, const uint8_t hash_key[HASH_KEY_SIZE]) _pure_; +void devt_hash_func(const void *p, struct siphash *state) _pure_; int devt_compare_func(const void *a, const void *b) _pure_; extern const struct hash_ops devt_hash_ops = { .hash = devt_hash_func, diff --git a/src/basic/missing.h b/src/basic/missing.h index 9811b6b23e..1e3af283bb 100644 --- a/src/basic/missing.h +++ b/src/basic/missing.h @@ -842,6 +842,19 @@ static inline int setns(int fd, int nstype) { #define IFLA_BRIDGE_MAX (__IFLA_BRIDGE_MAX - 1) #endif +#if !HAVE_DECL_IFLA_BR_PRIORITY +#define IFLA_BR_UNSPEC 0 +#define IFLA_BR_FORWARD_DELAY 1 +#define IFLA_BR_HELLO_TIME 2 +#define IFLA_BR_MAX_AGE 3 +#define IFLA_BR_AGEING_TIME 4 +#define IFLA_BR_STP_STATE 5 +#define IFLA_BR_PRIORITY 6 +#define __IFLA_BR_MAX 7 + +#define IFLA_BR_MAX (__IFLA_BR_MAX - 1) +#endif + #if !HAVE_DECL_IFLA_BRPORT_LEARNING_SYNC #define IFLA_BRPORT_UNSPEC 0 #define IFLA_BRPORT_STATE 1 diff --git a/src/basic/siphash24.c b/src/basic/siphash24.c index f68bd283a1..3b61961389 100644 --- a/src/basic/siphash24.c +++ b/src/basic/siphash24.c @@ -13,123 +13,170 @@ this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>. (Minimal changes made by Lennart Poettering, to make clean for inclusion in systemd) + (Refactored by Tom Gundersen to split up in several functions and follow systemd + coding style) */ -#include <stdint.h> -#include <stdio.h> -#include <string.h> + +#include "sparse-endian.h" #include "siphash24.h" +#include "util.h" -typedef uint64_t u64; -typedef uint32_t u32; -typedef uint8_t u8; - -#define ROTL(x,b) (u64)( ((x) << (b)) | ( (x) >> (64 - (b))) ) - -#define U32TO8_LE(p, v) \ - (p)[0] = (u8)((v) ); (p)[1] = (u8)((v) >> 8); \ - (p)[2] = (u8)((v) >> 16); (p)[3] = (u8)((v) >> 24); - -#define U64TO8_LE(p, v) \ - U32TO8_LE((p), (u32)((v) )); \ - U32TO8_LE((p) + 4, (u32)((v) >> 32)); - -#define U8TO64_LE(p) \ - (((u64)((p)[0]) ) | \ - ((u64)((p)[1]) << 8) | \ - ((u64)((p)[2]) << 16) | \ - ((u64)((p)[3]) << 24) | \ - ((u64)((p)[4]) << 32) | \ - ((u64)((p)[5]) << 40) | \ - ((u64)((p)[6]) << 48) | \ - ((u64)((p)[7]) << 56)) - -#define SIPROUND \ - do { \ - v0 += v1; v1=ROTL(v1,13); v1 ^= v0; v0=ROTL(v0,32); \ - v2 += v3; v3=ROTL(v3,16); v3 ^= v2; \ - v0 += v3; v3=ROTL(v3,21); v3 ^= v0; \ - v2 += v1; v1=ROTL(v1,17); v1 ^= v2; v2=ROTL(v2,32); \ - } while(0) +static inline uint64_t rotate_left(uint64_t x, uint8_t b) { + assert(b < 64); + + return (x << b) | (x >> (64 - b)); +} + +static inline void sipround(struct siphash *state) { + assert(state); + + state->v0 += state->v1; + state->v1 = rotate_left(state->v1, 13); + state->v1 ^= state->v0; + state->v0 = rotate_left(state->v0, 32); + state->v2 += state->v3; + state->v3 = rotate_left(state->v3, 16); + state->v3 ^= state->v2; + state->v0 += state->v3; + state->v3 = rotate_left(state->v3, 21); + state->v3 ^= state->v0; + state->v2 += state->v1; + state->v1 = rotate_left(state->v1, 17); + state->v1 ^= state->v2; + state->v2 = rotate_left(state->v2, 32); +} + +void siphash24_init(struct siphash *state, const uint8_t k[16]) { + uint64_t k0, k1; + + assert(state); + assert(k); + + k0 = le64toh(*(le64_t*) k); + k1 = le64toh(*(le64_t*) (k + 8)); + + /* "somepseudorandomlygeneratedbytes" */ + state->v0 = 0x736f6d6570736575ULL ^ k0; + state->v1 = 0x646f72616e646f6dULL ^ k1; + state->v2 = 0x6c7967656e657261ULL ^ k0; + state->v3 = 0x7465646279746573ULL ^ k1; + state->padding = 0; + state->inlen = 0; +} + +void siphash24_compress(const void *_in, size_t inlen, struct siphash *state) { + uint64_t m; + const uint8_t *in = _in; + const uint8_t *end = in + inlen; + unsigned left = state->inlen & 7; + + assert(in); + assert(state); + + /* update total length */ + state->inlen += inlen; + + /* if padding exists, fill it out */ + if (left > 0) { + for ( ; in < end && left < 8; in ++, left ++ ) + state->padding |= ( ( uint64_t )*in ) << (left * 8); + + if (in == end && left < 8) + /* we did not have enough input to fill out the padding completely */ + return; -/* SipHash-2-4 */ -void siphash24(uint8_t out[8], const void *_in, size_t inlen, const uint8_t k[16]) -{ - /* "somepseudorandomlygeneratedbytes" */ - u64 v0 = 0x736f6d6570736575ULL; - u64 v1 = 0x646f72616e646f6dULL; - u64 v2 = 0x6c7967656e657261ULL; - u64 v3 = 0x7465646279746573ULL; - u64 b; - u64 k0 = U8TO64_LE( k ); - u64 k1 = U8TO64_LE( k + 8 ); - u64 m; - const u8 *in = _in; - const u8 *end = in + inlen - ( inlen % sizeof( u64 ) ); - const int left = inlen & 7; - b = ( ( u64 )inlen ) << 56; - v3 ^= k1; - v2 ^= k0; - v1 ^= k1; - v0 ^= k0; - - for ( ; in != end; in += 8 ) - { - m = U8TO64_LE( in ); #ifdef DEBUG - printf( "(%3d) v0 %08x %08x\n", ( int )inlen, ( u32 )( v0 >> 32 ), ( u32 )v0 ); - printf( "(%3d) v1 %08x %08x\n", ( int )inlen, ( u32 )( v1 >> 32 ), ( u32 )v1 ); - printf( "(%3d) v2 %08x %08x\n", ( int )inlen, ( u32 )( v2 >> 32 ), ( u32 )v2 ); - printf( "(%3d) v3 %08x %08x\n", ( int )inlen, ( u32 )( v3 >> 32 ), ( u32 )v3 ); - printf( "(%3d) compress %08x %08x\n", ( int )inlen, ( u32 )( m >> 32 ), ( u32 )m ); + printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0); + printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t) state->v1); + printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t) state->v2); + printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3); + printf("(%3zu) compress padding %08x %08x\n", state->inlen, (uint32_t) (state->padding >> 32), (uint32_t)state->padding); #endif - v3 ^= m; - SIPROUND; - SIPROUND; - v0 ^= m; - } + state->v3 ^= state->padding; + sipround(state); + sipround(state); + state->v0 ^= state->padding; - switch( left ) - { - case 7: b |= ( ( u64 )in[ 6] ) << 48; + state->padding = 0; + } - case 6: b |= ( ( u64 )in[ 5] ) << 40; + end -= ( state->inlen % sizeof (uint64_t) ); - case 5: b |= ( ( u64 )in[ 4] ) << 32; + for ( ; in < end; in += 8 ) { + m = le64toh(*(le64_t*) in); +#ifdef DEBUG + printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0); + printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t) state->v1); + printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t) state->v2); + printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3); + printf("(%3zu) compress %08x %08x\n", state->inlen, (uint32_t) (m >> 32), (uint32_t) m); +#endif + state->v3 ^= m; + sipround(state); + sipround(state); + state->v0 ^= m; + } + + left = state->inlen & 7; + + switch(left) + { + case 7: state->padding |= ((uint64_t) in[6]) << 48; - case 4: b |= ( ( u64 )in[ 3] ) << 24; + case 6: state->padding |= ((uint64_t) in[5]) << 40; - case 3: b |= ( ( u64 )in[ 2] ) << 16; + case 5: state->padding |= ((uint64_t) in[4]) << 32; - case 2: b |= ( ( u64 )in[ 1] ) << 8; + case 4: state->padding |= ((uint64_t) in[3]) << 24; - case 1: b |= ( ( u64 )in[ 0] ); break; + case 3: state->padding |= ((uint64_t) in[2]) << 16; + + case 2: state->padding |= ((uint64_t) in[1]) << 8; + + case 1: state->padding |= ((uint64_t) in[0]); break; + + case 0: break; + } +} - case 0: break; - } +void siphash24_finalize(uint8_t out[8], struct siphash *state) { + uint64_t b; + b = state->padding | (( ( uint64_t )state->inlen ) << 56); #ifdef DEBUG - printf( "(%3d) v0 %08x %08x\n", ( int )inlen, ( u32 )( v0 >> 32 ), ( u32 )v0 ); - printf( "(%3d) v1 %08x %08x\n", ( int )inlen, ( u32 )( v1 >> 32 ), ( u32 )v1 ); - printf( "(%3d) v2 %08x %08x\n", ( int )inlen, ( u32 )( v2 >> 32 ), ( u32 )v2 ); - printf( "(%3d) v3 %08x %08x\n", ( int )inlen, ( u32 )( v3 >> 32 ), ( u32 )v3 ); - printf( "(%3d) padding %08x %08x\n", ( int )inlen, ( u32 )( b >> 32 ), ( u32 )b ); + printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t)state->v0); + printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t)state->v1); + printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t)state->v2); + printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t)state->v3); + printf("(%3zu) padding %08x %08x\n", state->inlen, (uint32_t) (state->padding >> 32), (uint32_t) state->padding); #endif - v3 ^= b; - SIPROUND; - SIPROUND; - v0 ^= b; + state->v3 ^= b; + sipround(state); + sipround(state); + state->v0 ^= b; + #ifdef DEBUG - printf( "(%3d) v0 %08x %08x\n", ( int )inlen, ( u32 )( v0 >> 32 ), ( u32 )v0 ); - printf( "(%3d) v1 %08x %08x\n", ( int )inlen, ( u32 )( v1 >> 32 ), ( u32 )v1 ); - printf( "(%3d) v2 %08x %08x\n", ( int )inlen, ( u32 )( v2 >> 32 ), ( u32 )v2 ); - printf( "(%3d) v3 %08x %08x\n", ( int )inlen, ( u32 )( v3 >> 32 ), ( u32 )v3 ); + printf("(%3zu) v0 %08x %08x\n", state->inlen, (uint32_t) (state->v0 >> 32), (uint32_t) state->v0); + printf("(%3zu) v1 %08x %08x\n", state->inlen, (uint32_t) (state->v1 >> 32), (uint32_t) state->v1); + printf("(%3zu) v2 %08x %08x\n", state->inlen, (uint32_t) (state->v2 >> 32), (uint32_t) state->v2); + printf("(%3zu) v3 %08x %08x\n", state->inlen, (uint32_t) (state->v3 >> 32), (uint32_t) state->v3); #endif - v2 ^= 0xff; - SIPROUND; - SIPROUND; - SIPROUND; - SIPROUND; - b = v0 ^ v1 ^ v2 ^ v3; - U64TO8_LE( out, b ); + state->v2 ^= 0xff; + + sipround(state); + sipround(state); + sipround(state); + sipround(state); + + *(le64_t*)out = htole64(state->v0 ^ state->v1 ^ state->v2 ^ state->v3); +} + +/* SipHash-2-4 */ +void siphash24(uint8_t out[8], const void *_in, size_t inlen, const uint8_t k[16]) { + struct siphash state; + + siphash24_init(&state, k); + siphash24_compress(_in, inlen, &state); + siphash24_finalize(out, &state); } diff --git a/src/basic/siphash24.h b/src/basic/siphash24.h index 62e1168a79..6c5cd98ee8 100644 --- a/src/basic/siphash24.h +++ b/src/basic/siphash24.h @@ -3,4 +3,17 @@ #include <inttypes.h> #include <sys/types.h> +struct siphash { + uint64_t v0; + uint64_t v1; + uint64_t v2; + uint64_t v3; + uint64_t padding; + size_t inlen; +}; + +void siphash24_init(struct siphash *state, const uint8_t k[16]); +void siphash24_compress(const void *in, size_t inlen, struct siphash *state); +void siphash24_finalize(uint8_t out[8], struct siphash *state); + void siphash24(uint8_t out[8], const void *in, size_t inlen, const uint8_t k[16]); diff --git a/src/basic/smack-util.c b/src/basic/smack-util.c index 9e221d6eab..5f570ff02a 100644 --- a/src/basic/smack-util.c +++ b/src/basic/smack-util.c @@ -29,9 +29,6 @@ #include "fileio.h" #include "smack-util.h" -#define SMACK_FLOOR_LABEL "_" -#define SMACK_STAR_LABEL "*" - #ifdef HAVE_SMACK bool mac_smack_use(void) { static int cached_use = -1; diff --git a/src/basic/smack-util.h b/src/basic/smack-util.h index b3aa55eb8a..e756dc8c28 100644 --- a/src/basic/smack-util.h +++ b/src/basic/smack-util.h @@ -27,6 +27,9 @@ #include "macro.h" +#define SMACK_FLOOR_LABEL "_" +#define SMACK_STAR_LABEL "*" + typedef enum SmackAttr { SMACK_ATTR_ACCESS = 0, SMACK_ATTR_EXEC = 1, diff --git a/src/basic/strv.c b/src/basic/strv.c index 9524e80a6f..9fe3b5dfff 100644 --- a/src/basic/strv.c +++ b/src/basic/strv.c @@ -277,8 +277,8 @@ char **strv_split_newlines(const char *s) { } int strv_split_extract(char ***t, const char *s, const char *separators, ExtractFlags flags) { - size_t n = 0, allocated = 0; _cleanup_strv_free_ char **l = NULL; + size_t n = 0, allocated = 0; int r; assert(t); @@ -302,13 +302,16 @@ int strv_split_extract(char ***t, const char *s, const char *separators, Extract l[n] = NULL; } - if (!l) + if (!l) { l = new0(char*, 1); + if (!l) + return -ENOMEM; + } *t = l; l = NULL; - return 0; + return (int) n; } char *strv_join(char **l, const char *separator) { @@ -745,3 +748,41 @@ char **strv_skip(char **l, size_t n) { return l; } + +int strv_extend_n(char ***l, const char *value, size_t n) { + size_t i, j, k; + char **nl; + + assert(l); + + if (!value) + return 0; + if (n == 0) + return 0; + + /* Adds the value value n times to l */ + + k = strv_length(*l); + + nl = realloc(*l, sizeof(char*) * (k + n + 1)); + if (!nl) + return -ENOMEM; + + *l = nl; + + for (i = k; i < k + n; i++) { + nl[i] = strdup(value); + if (!nl[i]) + goto rollback; + } + + nl[i] = NULL; + return 0; + +rollback: + for (j = k; j < i; j++) + free(nl[j]); + + nl[k] = NULL; + return -ENOMEM; +} diff --git a/src/basic/strv.h b/src/basic/strv.h index 4c4b6526de..7c1f80230a 100644 --- a/src/basic/strv.h +++ b/src/basic/strv.h @@ -158,3 +158,5 @@ static inline bool strv_fnmatch_or_empty(char* const* patterns, const char *s, i char ***strv_free_free(char ***l); char **strv_skip(char **l, size_t n); + +int strv_extend_n(char ***l, const char *value, size_t n); diff --git a/src/basic/util.c b/src/basic/util.c index c63ec0ceb0..2855993afe 100644 --- a/src/basic/util.c +++ b/src/basic/util.c @@ -6168,16 +6168,19 @@ int openpt_in_namespace(pid_t pid, int flags) { } ssize_t fgetxattrat_fake(int dirfd, const char *filename, const char *attribute, void *value, size_t size, int flags) { + char fn[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1]; _cleanup_close_ int fd = -1; ssize_t l; /* The kernel doesn't have a fgetxattrat() command, hence let's emulate one */ - fd = openat(dirfd, filename, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOATIME|(flags & AT_SYMLINK_NOFOLLOW ? O_NOFOLLOW : 0)); + fd = openat(dirfd, filename, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_PATH|(flags & AT_SYMLINK_NOFOLLOW ? O_NOFOLLOW : 0)); if (fd < 0) return -errno; - l = fgetxattr(fd, attribute, value, size); + xsprintf(fn, "/proc/self/fd/%i", fd); + + l = getxattr(fn, attribute, value, size); if (l < 0) return -errno; @@ -6842,3 +6845,30 @@ int version(void) { SYSTEMD_FEATURES); return 0; } + +bool fdname_is_valid(const char *s) { + const char *p; + + /* Validates a name for $LISTEN_FDNAMES. We basically allow + * everything ASCII that's not a control character. Also, as + * special exception the ":" character is not allowed, as we + * use that as field separator in $LISTEN_FDNAMES. + * + * Note that the empty string is explicitly allowed + * here. However, we limit the length of the names to 255 + * characters. */ + + if (!s) + return false; + + for (p = s; *p; p++) { + if (*p < ' ') + return false; + if (*p >= 127) + return false; + if (*p == ':') + return false; + } + + return p - s < 256; +} diff --git a/src/basic/util.h b/src/basic/util.h index a4e3672130..034410b8a8 100644 --- a/src/basic/util.h +++ b/src/basic/util.h @@ -941,3 +941,5 @@ int receive_one_fd(int transport_fd, int flags); void nop_signal_handler(int sig); int version(void); + +bool fdname_is_valid(const char *s); |