[libvirt] [PATCH 4/4] Replace hashing algorithm with murmurhash

Eric Blake eblake at redhat.com
Wed Jan 25 19:25:20 UTC 2012


On 01/25/2012 09:38 AM, Daniel P. Berrange wrote:
> From: "Daniel P. Berrange" <berrange at redhat.com>
> 
> Recent discussions have illustrated the potential for DOS attacks
> with the hash table implementations used by most languages and
> libraries.
> 
>    https://lwn.net/Articles/474912/
> 
> libvirt has an internal hash table impl, and uses hash tables for
> a variety of purposes. The hash key generation code is pretty
> simple and thus not strongly collision resistant.
> 
> This patch replaces the current libvirt hash key generator with
> the (public domain) Murmurhash3 code. In addition every hash
> table now gets a random seed value which is used to perturb the
> hashing code. This should make it impossible to mount any
> practical attack against libvirt hashing code.
> 
> * bootstrap.conf: Import bitrotate module
> * src/Makefile.am: Add virhashcode.[ch]
> * src/util/util.c: Make virRandom() return a fixed 32 bit
>   integer value.

This part of the commit message is stale.

> * src/util/hash.c, src/util/hash.h, src/util/cgroup.c: Replace
>   hash code generation with a call to virHashCodeGen()
> * src/util/virhashcode.h, src/util/virhashcode.c: Add a new
>   virHashCodeGen() API using the Murmurhash3 algorithm.
> ---
>  bootstrap.conf         |    1 +
>  src/Makefile.am        |    1 +
>  src/util/cgroup.c      |    6 ++-
>  src/util/virhash.c     |   21 +++------
>  src/util/virhash.h     |    7 ++-
>  src/util/virhashcode.c |  121 ++++++++++++++++++++++++++++++++++++++++++++++++
>  src/util/virhashcode.h |   35 ++++++++++++++
>  7 files changed, 174 insertions(+), 18 deletions(-)
>  create mode 100644 src/util/virhashcode.c
>  create mode 100644 src/util/virhashcode.h
> 

> @@ -1636,9 +1637,10 @@ cleanup:
>  }
>  
>  
> -static uint32_t virCgroupPidCode(const void *name)
> +static uint32_t virCgroupPidCode(const void *name, uint32_t seed)
>  {
> -    return (uint32_t)(int64_t)name;
> +    unsigned long pid = (unsigned long)name;
> +    return virHashCodeGen(&pid, sizeof(pid), seed);

Hmm - now we're losing the double-cast, so you might be reintroducing
compiler warnings about casting a pointer to an incorrectly-sized
integer.  I think you still need to use:

unsigned long pid = (unsigned long)(intptr_t)name;

> + *
> + * The hash code generation is based on the public domain MurmurHash3 from Austin Appleby:
> + * http://code.google.com/p/smhasher/source/browse/trunk/MurmurHash3.cpp
> + *
> + * We use only the 32 bit variant because the 2 produce different result while

s/result/results/

> +/* slower than original but is endian neutral and handles platforms that
> + * do only aligned reads */

s/is endian neutral and/

Your version is endian-dependent, but that's okay (you convinced me that
what matters is that a single libvirtd instance will always generate the
same hash for the same string, regardless of alignment; and that we
aren't transferring the hash over the wire to any other libvirtd
instance running on a different-endian machine).

> +__attribute__((always_inline))
> +static uint32_t getblock(const uint8_t *p, int i)
> +{
> +    uint32_t r;
> +    size_t size = sizeof(uint32_t);

I would have used sizeof(r) here (it's always nicer to use sizeof(var)
rather than sizeof(type), when a var is present, in case var changes
type later in a later patch).

> +
> +    memcpy(&r, &p[i * size], size);

Hopefully the compiler optimizes this decently.

> +
> +    switch (len & 3) {
> +    case 3:
> +        k1 ^= tail[2] << 16;
> +    case 2:
> +        k1 ^= tail[1] << 8;
> +    case 1:

I'd add some /* fallthrough */ comments to shut up Coverity.

Beyond that, it looked like a faithful conversion of the upstream code.

ACK with nits addressed.

-- 
Eric Blake   eblake at redhat.com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 620 bytes
Desc: OpenPGP digital signature
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20120125/f7cc7ae9/attachment-0001.sig>


More information about the libvir-list mailing list