From 31e882a46229c74649216ddc80fdb2ecbf75ab9e Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Tue, 16 Mar 2021 10:00:44 +0100 Subject: [PATCH 1/1] initrd: fix crash parsing empty rd.znet argument Ignore a rd.znet argument without subchannels. When using net.ifnames (the default), subchannels are used to build the interface name, which is required to match the right connection. With net.ifnames=0 the interface name is build using a prefix and a global counter and therefore in theory it is possible to omit subchannels. However, without subchannels there won't be a udev rule that renames the interface and so it can't work. https://bugzilla.redhat.com/show_bug.cgi?id=1931284 https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/783 (cherry picked from commit 0f8fe3c76b9ecdf52c1690295f7dcc7b7ade16b6) (cherry picked from commit d0d2d97ca51444bc7013943748ede334cc79a33f) --- src/core/initrd/nmi-cmdline-reader.c | 5 +++++ src/core/initrd/tests/test-cmdline-reader.c | 19 +++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/src/core/initrd/nmi-cmdline-reader.c b/src/core/initrd/nmi-cmdline-reader.c index 5f40f63ef269..e3ecc7d969bb 100644 --- a/src/core/initrd/nmi-cmdline-reader.c +++ b/src/core/initrd/nmi-cmdline-reader.c @@ -917,6 +917,11 @@ reader_parse_rd_znet(Reader *reader, char *argument, gboolean net_ifnames) subchannels[0] = get_word(&argument, ','); subchannels[1] = get_word(&argument, ','); + /* Without subchannels we can't univocally match + * a device. */ + if (!subchannels[0] || !subchannels[1]) + return; + if (nm_streq0(nettype, "ctc")) { if (net_ifnames == TRUE) { prefix = "sl"; diff --git a/src/core/initrd/tests/test-cmdline-reader.c b/src/core/initrd/tests/test-cmdline-reader.c index 4b450aae0fa4..ba072e7933dc 100644 --- a/src/core/initrd/tests/test-cmdline-reader.c +++ b/src/core/initrd/tests/test-cmdline-reader.c @@ -1815,6 +1815,24 @@ test_rd_znet_no_ip(void) g_assert_cmpint(g_hash_table_size(connections), ==, 0); } +static void +test_rd_znet_malformed(void) +{ + const char *const *const ARGV0 = NM_MAKE_STRV("rd.znet="); + const char *const *const ARGV1 = NM_MAKE_STRV("rd.znet=,"); + const char *const *const ARGV2 = NM_MAKE_STRV("rd.znet=foobar"); + const char *const *const ARGV3 = NM_MAKE_STRV("rd.znet=qeth,0.0.0800,,,layer2=0,portno=1"); + const char *const *const ARGV[] = {ARGV0, ARGV1, ARGV2, ARGV3}; + guint i; + + for (i = 0; i < G_N_ELEMENTS(ARGV); i++) { + gs_unref_hashtable GHashTable *connections = NULL; + + connections = _parse_cons(ARGV[i]); + g_assert_cmpint(g_hash_table_size(connections), ==, 0); + } +} + static void test_bootif_ip(void) { @@ -2173,6 +2191,7 @@ main(int argc, char **argv) g_test_add_func("/initrd/cmdline/rd_znet", test_rd_znet); g_test_add_func("/initrd/cmdline/rd_znet/legacy", test_rd_znet_legacy); g_test_add_func("/initrd/cmdline/rd_znet/no_ip", test_rd_znet_no_ip); + g_test_add_func("/initrd/cmdline/rd_znet/empty", test_rd_znet_malformed); g_test_add_func("/initrd/cmdline/bootif/ip", test_bootif_ip); g_test_add_func("/initrd/cmdline/bootif/no_ip", test_bootif_no_ip); g_test_add_func("/initrd/cmdline/bootif/hwtype", test_bootif_hwtype); -- 2.30.2