summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2015-04-08 15:54:30 +0200
committerThomas Haller <thaller@redhat.com>2015-04-29 14:14:20 +0200
commitbdaaf9849b0cacf131b71fa2ae168f5db796874f (patch)
tree0345a0bf8d58ecf7066051adc6f67d7ce882cb65
parent02c6a9334335d3ef32c6cc8fafc6cea235c80ffc (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
-rw-r--r--src/devices/nm-device.c10
-rw-r--r--src/nm-iface-helper.c10
-rw-r--r--src/platform/nm-platform.c32
-rw-r--r--src/platform/nm-platform.h2
4 files changed, 38 insertions, 16 deletions
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index 1de4e4730b..fb892be3db 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -4303,14 +4303,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_PLATFORM_GET, nm_device_get_ip_iface (self), rdisc->hop_limit);
if (changed & NM_RDISC_CONFIG_MTU)
priv->ip6_mtu = rdisc->mtu;
diff --git a/src/nm-iface-helper.c b/src/nm-iface-helper.c
index 94a6f0550b..979c2ba665 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_PLATFORM_GET, 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 (NM_PLATFORM_GET, 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 1a7b9bc182..518b69dd02 100644
--- a/src/platform/nm-platform.c
+++ b/src/platform/nm-platform.c
@@ -271,6 +271,38 @@ nm_platform_sysctl_set (NMPlatform *self, const char *path, const char *value)
return klass->sysctl_set (self, path, value);
}
+gboolean
+nm_platform_sysctl_set_ip6_hop_limit_safe (NMPlatform *self, 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 (self, 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 (self, path, svalue);
+ }
+
+ return TRUE;
+}
+
/**
* nm_platform_sysctl_get:
* @self: platform instance
diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h
index 5cd5ae8e0c..67a9639cda 100644
--- a/src/platform/nm-platform.h
+++ b/src/platform/nm-platform.h
@@ -508,6 +508,8 @@ char *nm_platform_sysctl_get (NMPlatform *self, const char *path);
gint32 nm_platform_sysctl_get_int32 (NMPlatform *self, const char *path, gint32 fallback);
gint64 nm_platform_sysctl_get_int_checked (NMPlatform *self, const char *path, guint base, gint64 min, gint64 max, gint64 fallback);
+gboolean nm_platform_sysctl_set_ip6_hop_limit_safe (NMPlatform *self, const char *iface, int value);
+
gboolean nm_platform_link_get (NMPlatform *self, int ifindex, NMPlatformLink *link);
GArray *nm_platform_link_get_all (NMPlatform *self);
gboolean nm_platform_dummy_add (NMPlatform *self, const char *name);