From ba08c5932e556aa4f5101357127a6224c40e5ebe Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Thu, 20 Mar 2014 10:31:37 +0000 Subject: [PATCH] Fix unitialized data in virSocketAddrMask The virSocketAddrMask method did not initialize all fields in the sockaddr_in6 struct. In paticular the 'sin6_scope_id' field could contain random garbage, which would in turn affect the result of any later virSocketAddrFormat calls. This led to ip6tables rules in the FORWARD chain which matched on random garbage sin6_scope_id. Fortunately these were ACCEPT rules, so the impact was merely that desired traffic was blocked, rather than undesired traffic allowed. Signed-off-by: Daniel P. Berrange --- src/util/virsocketaddr.c | 1 + tests/sockettest.c | 53 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/src/util/virsocketaddr.c b/src/util/virsocketaddr.c index 3f270e26b3..1099eaef80 100644 --- a/src/util/virsocketaddr.c +++ b/src/util/virsocketaddr.c @@ -424,6 +424,7 @@ virSocketAddrMask(const virSocketAddr *addr, const virSocketAddr *netmask, virSocketAddrPtr network) { + memset(network, 0, sizeof(*network)); if (addr->data.stor.ss_family != netmask->data.stor.ss_family) { network->data.stor.ss_family = AF_UNSPEC; return -1; diff --git a/tests/sockettest.c b/tests/sockettest.c index e613546b9a..68b0536225 100644 --- a/tests/sockettest.c +++ b/tests/sockettest.c @@ -153,6 +153,49 @@ static int testNetmaskHelper(const void *opaque) return testNetmask(data->addr1, data->addr2, data->netmask, data->pass); } + + +static int testMaskNetwork(const char *addrstr, + int prefix, + const char *networkstr) +{ + virSocketAddr addr; + virSocketAddr network; + char *gotnet = NULL; + + /* Intentionally fill with garbage */ + memset(&network, 1, sizeof(network)); + + if (virSocketAddrParse(&addr, addrstr, AF_UNSPEC) < 0) + return -1; + + if (virSocketAddrMaskByPrefix(&addr, prefix, &network) < 0) + return -1; + + if (!(gotnet = virSocketAddrFormat(&network))) + return -1; + + if (STRNEQ(networkstr, gotnet)) { + VIR_FREE(gotnet); + fprintf(stderr, "Expected %s, got %s\n", networkstr, gotnet); + return -1; + } + VIR_FREE(gotnet); + return 0; +} + +struct testMaskNetworkData { + const char *addr1; + int prefix; + const char *network; +}; +static int testMaskNetworkHelper(const void *opaque) +{ + const struct testMaskNetworkData *data = opaque; + return testMaskNetwork(data->addr1, data->prefix, data->network); +} + + static int testWildcard(const char *addrstr, bool pass) { @@ -255,6 +298,14 @@ mymain(void) ret = -1; \ } while (0) +#define DO_TEST_MASK_NETWORK(addr1, prefix, network) \ + do { \ + struct testMaskNetworkData data = { addr1, prefix, network }; \ + if (virtTestRun("Test mask network " addr1 " / " #prefix " == " network, \ + testMaskNetworkHelper, &data) < 0) \ + ret = -1; \ + } while (0) + #define DO_TEST_WILDCARD(addr, pass) \ do { \ struct testWildcardData data = { addr, pass}; \ @@ -324,6 +375,8 @@ mymain(void) DO_TEST_NETMASK("2000::1:1", "9000::1:1", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:0", false); + DO_TEST_MASK_NETWORK("2001:db8:ca2:2::1", 64, "2001:db8:ca2:2::"); + DO_TEST_WILDCARD("0.0.0.0", true); DO_TEST_WILDCARD("::", true); DO_TEST_WILDCARD("0", true);