diff options
author | Thomas Haller <thaller@redhat.com> | 2015-04-08 15:54:30 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2015-04-29 14:28:57 +0200 |
commit | 6e8c5b51b16c6a60a533ce753bcc54b7e2e703ca (patch) | |
tree | 28cc7bed45c9845e3d4e43db443c08c29eff8f27 | |
parent | a658561be90e174d99dff3c33eadab935c781f4c (diff) |
platform: don't accept lowering IPv6 hop-limit from RA (CVE-2015-2924)
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=6fd99094de2b83d1d4c8457f2c83483b2828e75a
http://seclists.org/oss-sec/2015/q2/46
https://bugzilla.redhat.com/show_bug.cgi?id=1209902
https://bugzilla.redhat.com/show_bug.cgi?id=1209903
(cherry picked from commit bdaaf9849b0cacf131b71fa2ae168f5db796874f)
Conflicts:
src/nm-iface-helper.c
src/platform/nm-platform.h
-rw-r--r-- | src/devices/nm-device.c | 10 | ||||
-rw-r--r-- | src/nm-iface-helper.c | 10 | ||||
-rw-r--r-- | src/platform/nm-platform.c | 32 | ||||
-rw-r--r-- | src/platform/nm-platform.h | 2 |
4 files changed, 38 insertions, 16 deletions
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index e714aeaa67..47526281d5 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -4168,14 +4168,8 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, NMDevice *self) } } - /* hop_limit == 0 is a special value "unspecified", so do not touch - * in this case */ - if (changed & NM_RDISC_CONFIG_HOP_LIMIT && rdisc->hop_limit > 0) { - char val[16]; - - g_snprintf (val, sizeof (val), "%d", rdisc->hop_limit); - nm_device_ipv6_sysctl_set (self, "hop_limit", val); - } + if (changed & NM_RDISC_CONFIG_HOP_LIMIT) + nm_platform_sysctl_set_ip6_hop_limit_safe (nm_device_get_ip_iface (self), rdisc->hop_limit); if (changed & NM_RDISC_CONFIG_MTU) { char val[16]; diff --git a/src/nm-iface-helper.c b/src/nm-iface-helper.c index 3105c63148..46a615f095 100644 --- a/src/nm-iface-helper.c +++ b/src/nm-iface-helper.c @@ -226,14 +226,8 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, gpointer user_da /* Unsupported until systemd DHCPv6 is ready */ } - /* hop_limit == 0 is a special value "unspecified", so do not touch - * in this case */ - if (changed & NM_RDISC_CONFIG_HOP_LIMIT && rdisc->hop_limit > 0) { - char val[16]; - - g_snprintf (val, sizeof (val), "%d", rdisc->hop_limit); - nm_platform_sysctl_set (nm_utils_ip6_property_path (global_opt.ifname, "hop_limit"), val); - } + if (changed & NM_RDISC_CONFIG_HOP_LIMIT) + nm_platform_sysctl_set_ip6_hop_limit_safe (global_opt.ifname, rdisc->hop_limit); if (changed & NM_RDISC_CONFIG_MTU) { char val[16]; diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index c5d7fb7da6..ba7708d6b4 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -258,6 +258,38 @@ nm_platform_sysctl_set (const char *path, const char *value) return klass->sysctl_set (platform, path, value); } +gboolean +nm_platform_sysctl_set_ip6_hop_limit_safe (const char *iface, int value) +{ + const char *path; + gint64 cur; + + /* the hop-limit provided via RA is uint8. */ + if (value > 0xFF) + return FALSE; + + /* don't allow unreasonable small values */ + if (value < 10) + return FALSE; + + path = nm_utils_ip6_property_path (iface, "hop_limit"); + cur = nm_platform_sysctl_get_int_checked (path, 10, 1, G_MAXINT32, -1); + + /* only allow increasing the hop-limit to avoid DOS by an attacker + * setting a low hop-limit (CVE-2015-2924, rh#1209902) */ + + if (value < cur) + return FALSE; + if (value != cur) { + char svalue[20]; + + sprintf (svalue, "%d", value); + nm_platform_sysctl_set (path, svalue); + } + + return TRUE; +} + /** * nm_platform_sysctl_get: * @path: Absolute path to sysctl diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h index a7937a6b55..a49e0f11ba 100644 --- a/src/platform/nm-platform.h +++ b/src/platform/nm-platform.h @@ -501,6 +501,8 @@ char *nm_platform_sysctl_get (const char *path); gint32 nm_platform_sysctl_get_int32 (const char *path, gint32 fallback); gint64 nm_platform_sysctl_get_int_checked (const char *path, guint base, gint64 min, gint64 max, gint64 fallback); +gboolean nm_platform_sysctl_set_ip6_hop_limit_safe (const char *iface, int value); + gboolean nm_platform_link_get (int ifindex, NMPlatformLink *link); GArray *nm_platform_link_get_all (void); gboolean nm_platform_dummy_add (const char *name); |