diff options
| author | John Brooks <john.brooks@jolla.com> | 2015-03-24 16:54:17 -0400 |
|---|---|---|
| committer | Paul Moore <pmoore@redhat.com> | 2015-04-06 20:16:21 -0400 |
| commit | 33ebc1932a07efd8728975750409741940334489 (patch) | |
| tree | ce88911dbfbfa42b6cfd4c06631a25b74f94d53a | |
| parent | ba39db6e0519aa8362dbda6523ceb69349a18dc3 (diff) | |
selinux: Use a better hash function for avtab
This function, based on murmurhash3, has much better distribution than
the original. Using the current default of 2048 buckets, there are many
fewer collisions:
Before:
101421 entries and 2048/2048 buckets used, longest chain length 374
After:
101421 entries and 2048/2048 buckets used, longest chain length 81
The difference becomes much more significant when buckets are increased.
A naive attempt to expand the current function to larger outputs doesn't
yield any significant improvement; so this function is a prerequisite
for increasing the bucket size.
sds: Adapted from the original patches for libsepol to the kernel.
Signed-off-by: John Brooks <john.brooks@jolla.com>
Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov>
Signed-off-by: Paul Moore <pmoore@redhat.com>
| -rw-r--r-- | security/selinux/ss/avtab.c | 41 | ||||
| -rw-r--r-- | security/selinux/ss/avtab.h | 2 |
2 files changed, 38 insertions, 5 deletions
diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c index 3ea0198fc964..b64f2772b030 100644 --- a/security/selinux/ss/avtab.c +++ b/security/selinux/ss/avtab.c | |||
| @@ -25,10 +25,43 @@ | |||
| 25 | 25 | ||
| 26 | static struct kmem_cache *avtab_node_cachep; | 26 | static struct kmem_cache *avtab_node_cachep; |
| 27 | 27 | ||
| 28 | static inline int avtab_hash(struct avtab_key *keyp, u16 mask) | 28 | /* Based on MurmurHash3, written by Austin Appleby and placed in the |
| 29 | * public domain. | ||
| 30 | */ | ||
| 31 | static inline int avtab_hash(struct avtab_key *keyp, u32 mask) | ||
| 29 | { | 32 | { |
| 30 | return ((keyp->target_class + (keyp->target_type << 2) + | 33 | static const u32 c1 = 0xcc9e2d51; |
| 31 | (keyp->source_type << 9)) & mask); | 34 | static const u32 c2 = 0x1b873593; |
| 35 | static const u32 r1 = 15; | ||
| 36 | static const u32 r2 = 13; | ||
| 37 | static const u32 m = 5; | ||
| 38 | static const u32 n = 0xe6546b64; | ||
| 39 | |||
| 40 | u32 hash = 0; | ||
| 41 | |||
| 42 | #define mix(input) { \ | ||
| 43 | u32 v = input; \ | ||
| 44 | v *= c1; \ | ||
| 45 | v = (v << r1) | (v >> (32 - r1)); \ | ||
| 46 | v *= c2; \ | ||
| 47 | hash ^= v; \ | ||
| 48 | hash = (hash << r2) | (hash >> (32 - r2)); \ | ||
| 49 | hash = hash * m + n; \ | ||
| 50 | } | ||
| 51 | |||
| 52 | mix(keyp->target_class); | ||
| 53 | mix(keyp->target_type); | ||
| 54 | mix(keyp->source_type); | ||
| 55 | |||
| 56 | #undef mix | ||
| 57 | |||
| 58 | hash ^= hash >> 16; | ||
| 59 | hash *= 0x85ebca6b; | ||
| 60 | hash ^= hash >> 13; | ||
| 61 | hash *= 0xc2b2ae35; | ||
| 62 | hash ^= hash >> 16; | ||
| 63 | |||
| 64 | return hash & mask; | ||
| 32 | } | 65 | } |
| 33 | 66 | ||
| 34 | static struct avtab_node* | 67 | static struct avtab_node* |
| @@ -256,7 +289,7 @@ int avtab_init(struct avtab *h) | |||
| 256 | 289 | ||
| 257 | int avtab_alloc(struct avtab *h, u32 nrules) | 290 | int avtab_alloc(struct avtab *h, u32 nrules) |
| 258 | { | 291 | { |
| 259 | u16 mask = 0; | 292 | u32 mask = 0; |
| 260 | u32 shift = 0; | 293 | u32 shift = 0; |
| 261 | u32 work = nrules; | 294 | u32 work = nrules; |
| 262 | u32 nslot = 0; | 295 | u32 nslot = 0; |
diff --git a/security/selinux/ss/avtab.h b/security/selinux/ss/avtab.h index 9318b2b8f6c9..6d794a2eee57 100644 --- a/security/selinux/ss/avtab.h +++ b/security/selinux/ss/avtab.h | |||
| @@ -56,7 +56,7 @@ struct avtab { | |||
| 56 | struct flex_array *htable; | 56 | struct flex_array *htable; |
| 57 | u32 nel; /* number of elements */ | 57 | u32 nel; /* number of elements */ |
| 58 | u32 nslot; /* number of hash slots */ | 58 | u32 nslot; /* number of hash slots */ |
| 59 | u16 mask; /* mask to compute hash func */ | 59 | u32 mask; /* mask to compute hash func */ |
| 60 | 60 | ||
| 61 | }; | 61 | }; |
| 62 | 62 | ||
