]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: tunnel: handle null address as "any"
authorYu Watanabe <watanabe.yu+github@gmail.com>
Sun, 17 Apr 2022 00:19:26 +0000 (09:19 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Sun, 17 Apr 2022 00:31:30 +0000 (09:31 +0900)
Fixes oss-fuzz#44881 (https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=44881).

Fixes #23098.

src/network/netdev/tunnel.c
test/fuzz/fuzz-netdev-parser/clusterfuzz-testcase-minimized-fuzz-netdev-parser-4697395387039744 [new file with mode: 0644]

index 3ba4484b6b2a992ec3101ff545f3a92c3358842c..747acb1e80961ee9f9b181a290106b4c50f57f70 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/ip.h>
 #include <linux/ip6_tunnel.h>
 
+#include "af-list.h"
 #include "conf-parser.h"
 #include "hexdecoct.h"
 #include "missing_network.h"
@@ -737,6 +738,20 @@ static int netdev_tunnel_verify(NetDev *netdev, const char *filename) {
         return 0;
 }
 
+static int unset_local(Tunnel *t) {
+        assert(t);
+
+        /* Unset the previous assignment. */
+        t->local = IN_ADDR_NULL;
+        t->local_type = _NETDEV_LOCAL_ADDRESS_TYPE_INVALID;
+
+        /* If the remote address is not specified, also clear the address family. */
+        if (!in_addr_is_set(t->family, &t->remote))
+                t->family = AF_UNSPEC;
+
+        return 0;
+}
+
 int config_parse_tunnel_local_address(
                 const char *unit,
                 const char *filename,
@@ -759,16 +774,8 @@ int config_parse_tunnel_local_address(
         assert(rvalue);
         assert(userdata);
 
-        if (isempty(rvalue) || streq(rvalue, "any")) {
-                /* Unset the previous assignment. */
-                t->local = IN_ADDR_NULL;
-                t->local_type = _NETDEV_LOCAL_ADDRESS_TYPE_INVALID;
-
-                /* If the remote address is not specified, also clear the address family. */
-                if (!in_addr_is_set(t->family, &t->remote))
-                        t->family = AF_UNSPEC;
-                return 0;
-        }
+        if (isempty(rvalue) || streq(rvalue, "any"))
+                return unset_local(t);
 
         type = netdev_local_address_type_from_string(rvalue);
         if (IN_SET(type, NETDEV_LOCAL_ADDRESS_IPV4LL, NETDEV_LOCAL_ADDRESS_DHCP4))
@@ -783,6 +790,9 @@ int config_parse_tunnel_local_address(
                                    "Tunnel address \"%s\" invalid, ignoring assignment: %m", rvalue);
                         return 0;
                 }
+
+                if (in_addr_is_null(f, &buffer))
+                        return unset_local(t);
         }
 
         if (t->family != AF_UNSPEC && t->family != f) {
@@ -797,6 +807,20 @@ int config_parse_tunnel_local_address(
         return 0;
 }
 
+static int unset_remote(Tunnel *t) {
+        assert(t);
+
+        /* Unset the previous assignment. */
+        t->remote = IN_ADDR_NULL;
+
+        /* If the local address is not specified, also clear the address family. */
+        if (t->local_type == _NETDEV_LOCAL_ADDRESS_TYPE_INVALID &&
+            !in_addr_is_set(t->family, &t->local))
+                t->family = AF_UNSPEC;
+
+        return 0;
+}
+
 int config_parse_tunnel_remote_address(
                 const char *unit,
                 const char *filename,
@@ -818,16 +842,8 @@ int config_parse_tunnel_remote_address(
         assert(rvalue);
         assert(userdata);
 
-        if (isempty(rvalue) || streq(rvalue, "any")) {
-                /* Unset the previous assignment. */
-                t->remote = IN_ADDR_NULL;
-
-                /* If the local address is not specified, also clear the address family. */
-                if (t->local_type == _NETDEV_LOCAL_ADDRESS_TYPE_INVALID &&
-                    !in_addr_is_set(t->family, &t->local))
-                        t->family = AF_UNSPEC;
-                return 0;
-        }
+        if (isempty(rvalue) || streq(rvalue, "any"))
+                return unset_remote(t);
 
         r = in_addr_from_string_auto(rvalue, &f, &buffer);
         if (r < 0) {
@@ -836,6 +852,9 @@ int config_parse_tunnel_remote_address(
                 return 0;
         }
 
+        if (in_addr_is_null(f, &buffer))
+                return unset_remote(t);
+
         if (t->family != AF_UNSPEC && t->family != f) {
                 log_syntax(unit, LOG_WARNING, filename, line, 0,
                            "Address family does not match the previous assignment, ignoring assignment: %s", rvalue);
diff --git a/test/fuzz/fuzz-netdev-parser/clusterfuzz-testcase-minimized-fuzz-netdev-parser-4697395387039744 b/test/fuzz/fuzz-netdev-parser/clusterfuzz-testcase-minimized-fuzz-netdev-parser-4697395387039744
new file mode 100644 (file)
index 0000000..d2de7fb
Binary files /dev/null and b/test/fuzz/fuzz-netdev-parser/clusterfuzz-testcase-minimized-fuzz-netdev-parser-4697395387039744 differ