提交 4b31da34 编写于 作者: L Laine Stump

network: don't require private addresses if dnsmasq uses SO_BINDTODEVICE

This is yet another refinement to the fix for CVE-2012-3411:

   https://bugzilla.redhat.com/show_bug.cgi?id=833033

It turns out that it would be very intrusive to correctly backport the
entire --bind-dynamic option to older dnsmasq versions
(e.g. dnsmasq-2.48 that is used on RHEL6.x and CentOS 6.x), but very
simple to patch those versions to just use SO_BINDTODEVICE on all
their listening sockets (SO_BINDTODEVICE also has the desired effect
of permitting only traffic that was received on the interface(s) where
dnsmasq was set to listen.)

This patch modifies the dnsmasq capabilities detection to detect the
string:

    --bind-interfaces with SO_BINDTODEVICE

in the output of "dnsmasq --version", and in that case realize that
using the old --bind-interfaces option is just as safe as
--bind-dynamic (and therefore *not* forbid creation of networks that
use public IP address ranges).

If -bind-dynamic is available, it is still preferred over
--bind-interfaces.

Note that this patch does no harm in upstream, or in any distro's
downstream if it happens to end up there, but builds for distros that
have a new enough dnsmasq to support --bind-dynamic do *NOT* need to
specifically backport this patch; it's only required for distro
releases that have dnsmasq too old to have --bind-dynamic (and those
distros will need to add the SO_BINDTODEVICE patch to dnsmasq,
*including the extra string in the --version output*, as well.
上级 cdfe739c
...@@ -726,15 +726,17 @@ networkDnsmasqConfContents(virNetworkObjPtr network, ...@@ -726,15 +726,17 @@ networkDnsmasqConfContents(virNetworkObjPtr network,
* dnsmasq doesn't have bind-dynamic, only allow listening on * dnsmasq doesn't have bind-dynamic, only allow listening on
* private/local IP addresses (see RFC1918/RFC3484/RFC4193) * private/local IP addresses (see RFC1918/RFC3484/RFC4193)
*/ */
if (!virSocketAddrIsPrivate(&tmpipdef->address)) { if (!dnsmasqCapsGet(caps, DNSMASQ_CAPS_BINDTODEVICE) &&
!virSocketAddrIsPrivate(&tmpipdef->address)) {
unsigned long version = dnsmasqCapsGetVersion(caps); unsigned long version = dnsmasqCapsGetVersion(caps);
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("Publicly routable address %s is prohibited. " _("Publicly routable address %s is prohibited. "
"The version of dnsmasq on this host (%d.%d) " "The version of dnsmasq on this host (%d.%d) "
"doesn't support the bind-dynamic option, " "doesn't support the bind-dynamic option or "
"which is required for safe operation on a " "use SO_BINDTODEVICE on listening sockets, "
"publicly routable subnet " "one of which is required for safe operation "
"on a publicly routable subnet "
"(see CVE-2012-3411). You must either " "(see CVE-2012-3411). You must either "
"upgrade dnsmasq, or use a private/local " "upgrade dnsmasq, or use a private/local "
"subnet range for this network " "subnet range for this network "
......
...@@ -664,10 +664,20 @@ dnsmasqCapsSetFromBuffer(dnsmasqCapsPtr caps, const char *buf) ...@@ -664,10 +664,20 @@ dnsmasqCapsSetFromBuffer(dnsmasqCapsPtr caps, const char *buf)
if (strstr(buf, "--bind-dynamic")) if (strstr(buf, "--bind-dynamic"))
dnsmasqCapsSet(caps, DNSMASQ_CAPS_BIND_DYNAMIC); dnsmasqCapsSet(caps, DNSMASQ_CAPS_BIND_DYNAMIC);
VIR_INFO("dnsmasq version is %d.%d, --bind-dynamic is %s", /* if this string is a part of the --version output, dnsmasq
(int)caps->version / 1000000, (int)(caps->version % 1000000) / 1000, * has been patched to use SO_BINDTODEVICE when listening,
dnsmasqCapsGet(caps, DNSMASQ_CAPS_BIND_DYNAMIC) * so that it will only accept requests that arrived on the
? "present" : "NOT present"); * listening interface(s)
*/
if (strstr(buf, "--bind-interfaces with SO_BINDTODEVICE"))
dnsmasqCapsSet(caps, DNSMASQ_CAPS_BINDTODEVICE);
VIR_INFO("dnsmasq version is %d.%d, --bind-dynamic is %spresent, "
"SO_BINDTODEVICE is %sin use",
(int)caps->version / 1000000,
(int)(caps->version % 1000000) / 1000,
dnsmasqCapsGet(caps, DNSMASQ_CAPS_BIND_DYNAMIC) ? "" : "NOT ",
dnsmasqCapsGet(caps, DNSMASQ_CAPS_BIND_DYNAMIC) ? "" : "NOT ");
return 0; return 0;
fail: fail:
......
...@@ -68,6 +68,7 @@ typedef struct ...@@ -68,6 +68,7 @@ typedef struct
typedef enum { typedef enum {
DNSMASQ_CAPS_BIND_DYNAMIC = 0, /* support for --bind-dynamic */ DNSMASQ_CAPS_BIND_DYNAMIC = 0, /* support for --bind-dynamic */
DNSMASQ_CAPS_BINDTODEVICE = 1, /* uses SO_BINDTODEVICE for --bind-interfaces */
DNSMASQ_CAPS_LAST, /* this must always be the last item */ DNSMASQ_CAPS_LAST, /* this must always be the last item */
} dnsmasqCapsFlags; } dnsmasqCapsFlags;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册