diff mbox series

[meta-oe,scarthgap] netplan: Fix CVE-2022-4968

Message ID 20250319031411.3194592-1-jinfeng.wang.cn@windriver.com
State New
Headers show
Series [meta-oe,scarthgap] netplan: Fix CVE-2022-4968 | expand

Commit Message

Wang, Jinfeng (CN) March 19, 2025, 3:14 a.m. UTC
From: Jinfeng Wang <jinfeng.wang.cn@windriver.com>

Reference:
https://nvd.nist.gov/vuln/detail/CVE-2022-4968

Upstream-patch:
https://github.com/canonical/netplan/commit/4c39b75b5c6ae7d976bda6da68da60d9a7f085ee

Signed-off-by: Jinfeng Wang <jinfeng.wang.cn@windriver.com>
---
 .../netplan/netplan/CVE-2022-4968.patch       | 452 ++++++++++++++++++
 .../netplan/netplan_1.0.bb                    |   1 +
 2 files changed, 453 insertions(+)
 create mode 100644 meta-oe/dynamic-layers/meta-python/recipes-connectivity/netplan/netplan/CVE-2022-4968.patch
diff mbox series

Patch

diff --git a/meta-oe/dynamic-layers/meta-python/recipes-connectivity/netplan/netplan/CVE-2022-4968.patch b/meta-oe/dynamic-layers/meta-python/recipes-connectivity/netplan/netplan/CVE-2022-4968.patch
new file mode 100644
index 0000000000..a7a3c28f3f
--- /dev/null
+++ b/meta-oe/dynamic-layers/meta-python/recipes-connectivity/netplan/netplan/CVE-2022-4968.patch
@@ -0,0 +1,452 @@ 
+From 9d9a67b00b18708ce190b806686065a6c7b73527 Mon Sep 17 00:00:00 2001
+From: Danilo Egea Gondolfo <danilogondolfo@gmail.com>
+Date: Wed, 22 May 2024 15:44:16 +0100
+Subject: [PATCH] libnetplan: use more restrictive file permissions
+
+A new util.c:_netplan_g_string_free_to_file_with_permissions() was added
+and accepts the owner, group and file mode as arguments. When these
+properties can't be set, when the generator is called by a non-root user
+for example, it will not hard-fail. This function is called by unit
+tests where we can't set the owner to a privileged account for example.
+
+When generating backend files, use more restrictive permissions:
+
+networkd related files will be owned by root:systemd-network and have
+mode 0640.
+
+service unit files will be owned by root:root and have mode 0640.
+udevd files will be owned by root:root with mode 0640.
+
+wpa_supplicant and Network Manager files will continue with the existing
+permissions.
+
+Autopkgtests will check if the permissions are set as expected when
+calling the generator.
+
+CVE: CVE-2022-4968
+
+Upstream-Status: Backport [https://github.com/canonical/netplan/commit/4c39b75b5c6ae7d976bda6da68da60d9a7f085ee]
+
+Signed-off-by: Jinfeng Wang <jinfeng.wang.cn@windriver.com>
+---
+ src/networkd.c                | 36 +++------------
+ src/networkd.h                |  2 +
+ src/nm.c                      |  4 +-
+ src/openvswitch.c             |  2 +-
+ src/sriov.c                   |  4 +-
+ src/util-internal.h           |  3 ++
+ src/util.c                    | 46 +++++++++++++++++++
+ tests/generator/test_auth.py  |  2 +-
+ tests/generator/test_wifis.py |  2 +-
+ tests/integration/base.py     | 85 +++++++++++++++++++++++++++++++++++
+ 10 files changed, 150 insertions(+), 36 deletions(-)
+
+diff --git a/src/networkd.c b/src/networkd.c
+index 25121c4..a051c6f 100644
+--- a/src/networkd.c
++++ b/src/networkd.c
+@@ -221,7 +221,6 @@ STATIC void
+ write_link_file(const NetplanNetDefinition* def, const char* rootdir, const char* path)
+ {
+     GString* s = NULL;
+-    mode_t orig_umask;
+ 
+     /* Don't write .link files for virtual devices; they use .netdev instead.
+      * Don't write .link files for MODEM devices, as they aren't supported by networkd.
+@@ -293,9 +292,7 @@ write_link_file(const NetplanNetDefinition* def, const char* rootdir, const char
+         g_string_append_printf(s, "LargeReceiveOffload=%s\n",
+         (def->large_receive_offload ? "true" : "false"));
+ 
+-    orig_umask = umask(022);
+-    _netplan_g_string_free_to_file(s, rootdir, path, ".link");
+-    umask(orig_umask);
++    _netplan_g_string_free_to_file_with_permissions(s, rootdir, path, ".link", "root", "root", 0640);
+ }
+ 
+ STATIC gboolean
+@@ -313,7 +310,7 @@ write_regdom(const NetplanNetDefinition* def, const char* rootdir, GError** erro
+     g_string_append(s, "\n[Service]\nType=oneshot\n");
+     g_string_append_printf(s, "ExecStart="SBINDIR"/iw reg set %s\n", def->regulatory_domain);
+ 
+-    _netplan_g_string_free_to_file(s, rootdir, path, NULL);
++    _netplan_g_string_free_to_file_with_permissions(s, rootdir, path, NULL, "root", "root", 0640);
+     _netplan_safe_mkdir_p_dir(link);
+     if (symlink(path, link) < 0 && errno != EEXIST) {
+         // LCOV_EXCL_START
+@@ -493,7 +490,6 @@ STATIC void
+ write_netdev_file(const NetplanNetDefinition* def, const char* rootdir, const char* path)
+ {
+     GString* s = NULL;
+-    mode_t orig_umask;
+ 
+     g_assert(def->type >= NETPLAN_DEF_TYPE_VIRTUAL);
+ 
+@@ -589,11 +585,7 @@ write_netdev_file(const NetplanNetDefinition* def, const char* rootdir, const ch
+         default: g_assert_not_reached(); // LCOV_EXCL_LINE
+     }
+ 
+-    /* these do not contain secrets and need to be readable by
+-     * systemd-networkd - LP: #1736965 */
+-    orig_umask = umask(022);
+-    _netplan_g_string_free_to_file(s, rootdir, path, ".netdev");
+-    umask(orig_umask);
++    _netplan_g_string_free_to_file_with_permissions(s, rootdir, path, ".netdev", "root", NETWORKD_GROUP, 0640);
+ }
+ 
+ STATIC void
+@@ -737,7 +729,6 @@ _netplan_netdef_write_network_file(
+     g_autoptr(GString) network = NULL;
+     g_autoptr(GString) link = NULL;
+     GString* s = NULL;
+-    mode_t orig_umask;
+     gboolean is_optional = def->optional;
+ 
+     SET_OPT_OUT_PTR(has_been_written, FALSE);
+@@ -993,11 +984,7 @@ _netplan_netdef_write_network_file(
+         if (network->len > 0)
+             g_string_append_printf(s, "\n[Network]\n%s", network->str);
+ 
+-        /* these do not contain secrets and need to be readable by
+-         * systemd-networkd - LP: #1736965 */
+-        orig_umask = umask(022);
+-        _netplan_g_string_free_to_file(s, rootdir, path, ".network");
+-        umask(orig_umask);
++        _netplan_g_string_free_to_file_with_permissions(s, rootdir, path, ".network", "root", NETWORKD_GROUP, 0640);
+     }
+ 
+     SET_OPT_OUT_PTR(has_been_written, TRUE);
+@@ -1009,7 +996,6 @@ write_rules_file(const NetplanNetDefinition* def, const char* rootdir)
+ {
+     GString* s = NULL;
+     g_autofree char* path = g_strjoin(NULL, "run/udev/rules.d/99-netplan-", def->id, ".rules", NULL);
+-    mode_t orig_umask;
+ 
+     /* do we need to write a .rules file?
+      * It's only required for reliably setting the name of a physical device
+@@ -1043,9 +1029,7 @@ write_rules_file(const NetplanNetDefinition* def, const char* rootdir)
+ 
+     g_string_append_printf(s, "NAME=\"%s\"\n", def->set_name);
+ 
+-    orig_umask = umask(022);
+-    _netplan_g_string_free_to_file(s, rootdir, path, NULL);
+-    umask(orig_umask);
++    _netplan_g_string_free_to_file_with_permissions(s, rootdir, path, NULL, "root", "root", 0640);
+ }
+ 
+ STATIC gboolean
+@@ -1194,7 +1178,6 @@ STATIC void
+ write_wpa_unit(const NetplanNetDefinition* def, const char* rootdir)
+ {
+     g_autofree gchar *stdouth = NULL;
+-    mode_t orig_umask;
+ 
+     stdouth = systemd_escape(def->id);
+ 
+@@ -1213,9 +1196,7 @@ write_wpa_unit(const NetplanNetDefinition* def, const char* rootdir)
+     } else {
+         g_string_append(s, " -Dnl80211,wext\n");
+     }
+-    orig_umask = umask(022);
+-    _netplan_g_string_free_to_file(s, rootdir, path, NULL);
+-    umask(orig_umask);
++    _netplan_g_string_free_to_file_with_permissions(s, rootdir, path, NULL, "root", "root", 0640);
+ }
+ 
+ STATIC gboolean
+@@ -1224,7 +1205,6 @@ write_wpa_conf(const NetplanNetDefinition* def, const char* rootdir, GError** er
+     GHashTableIter iter;
+     GString* s = g_string_new("ctrl_interface=/run/wpa_supplicant\n\n");
+     g_autofree char* path = g_strjoin(NULL, "run/netplan/wpa-", def->id, ".conf", NULL);
+-    mode_t orig_umask;
+ 
+     g_debug("%s: Creating wpa_supplicant configuration file %s", def->id, path);
+     if (def->type == NETPLAN_DEF_TYPE_WIFI) {
+@@ -1313,9 +1293,7 @@ write_wpa_conf(const NetplanNetDefinition* def, const char* rootdir, GError** er
+     }
+ 
+     /* use tight permissions as this contains secrets */
+-    orig_umask = umask(077);
+-    _netplan_g_string_free_to_file(s, rootdir, path, NULL);
+-    umask(orig_umask);
++    _netplan_g_string_free_to_file_with_permissions(s, rootdir, path, NULL, "root", "root", 0600);
+     return TRUE;
+ }
+ 
+diff --git a/src/networkd.h b/src/networkd.h
+index 2bd0848..36c34b3 100644
+--- a/src/networkd.h
++++ b/src/networkd.h
+@@ -20,6 +20,8 @@
+ #include "netplan.h"
+ #include <glib.h>
+ 
++#define NETWORKD_GROUP "systemd-network"
++
+ NETPLAN_INTERNAL gboolean
+ _netplan_netdef_write_networkd(
+         const NetplanState* np_state,
+diff --git a/src/nm.c b/src/nm.c
+index 2b850af..8f1bf05 100644
+--- a/src/nm.c
++++ b/src/nm.c
+@@ -1150,13 +1150,13 @@ netplan_state_finish_nm_write(
+ 
+     /* write generated NetworkManager drop-in config */
+     if (nm_conf->len > 0)
+-        _netplan_g_string_free_to_file(nm_conf, rootdir, "run/NetworkManager/conf.d/netplan.conf", NULL);
++        _netplan_g_string_free_to_file_with_permissions(nm_conf, rootdir, "run/NetworkManager/conf.d/netplan.conf", NULL, "root", "root", 0640);
+     else
+         g_string_free(nm_conf, TRUE);
+ 
+     /* write generated udev rules */
+     if (udev_rules->len > 0)
+-        _netplan_g_string_free_to_file(udev_rules, rootdir, "run/udev/rules.d/90-netplan.rules", NULL);
++        _netplan_g_string_free_to_file_with_permissions(udev_rules, rootdir, "run/udev/rules.d/90-netplan.rules", NULL, "root", "root", 0640);
+     else
+         g_string_free(udev_rules, TRUE);
+ 
+diff --git a/src/openvswitch.c b/src/openvswitch.c
+index 6eb0688..2ab77e7 100644
+--- a/src/openvswitch.c
++++ b/src/openvswitch.c
+@@ -66,7 +66,7 @@ write_ovs_systemd_unit(const char* id, const GString* cmds, const char* rootdir,
+         g_string_append(s, "StartLimitBurst=0\n");
+     g_string_append(s, cmds->str);
+ 
+-    _netplan_g_string_free_to_file(s, rootdir, path, NULL);
++    _netplan_g_string_free_to_file_with_permissions(s, rootdir, path, NULL, "root", "root", 0640);
+ 
+     _netplan_safe_mkdir_p_dir(link);
+     if (symlink(path, link) < 0 && errno != EEXIST) {
+diff --git a/src/sriov.c b/src/sriov.c
+index 1534c94..213f124 100644
+--- a/src/sriov.c
++++ b/src/sriov.c
+@@ -54,7 +54,7 @@ write_sriov_rebind_systemd_unit(GHashTable* pfs, const char* rootdir, GError** e
+     g_string_truncate(interfaces, interfaces->len-1); /* cut trailing whitespace */
+     g_string_append_printf(s, "ExecStart=" SBINDIR "/netplan rebind --debug %s\n", interfaces->str);
+ 
+-    _netplan_g_string_free_to_file(s, rootdir, path, NULL);
++    _netplan_g_string_free_to_file_with_permissions(s, rootdir, path, NULL, "root", "root", 0640);
+     g_string_free(interfaces, TRUE);
+ 
+     _netplan_safe_mkdir_p_dir(link);
+@@ -90,7 +90,7 @@ write_sriov_apply_systemd_unit(GHashTable* pfs, const char* rootdir, GError** er
+     g_string_append(s, "\n[Service]\nType=oneshot\n");
+     g_string_append_printf(s, "ExecStart=" SBINDIR "/netplan apply --sriov-only\n");
+ 
+-    _netplan_g_string_free_to_file(s, rootdir, path, NULL);
++    _netplan_g_string_free_to_file_with_permissions(s, rootdir, path, NULL, "root", "root", 0640);
+ 
+     _netplan_safe_mkdir_p_dir(link);
+     if (symlink(path, link) < 0 && errno != EEXIST) {
+diff --git a/src/util-internal.h b/src/util-internal.h
+index 86bd1b7..7454e77 100644
+--- a/src/util-internal.h
++++ b/src/util-internal.h
+@@ -40,6 +40,9 @@ _netplan_safe_mkdir_p_dir(const char* file_path);
+ NETPLAN_INTERNAL void
+ _netplan_g_string_free_to_file(GString* s, const char* rootdir, const char* path, const char* suffix);
+ 
++void
++_netplan_g_string_free_to_file_with_permissions(GString* s, const char* rootdir, const char* path, const char* suffix, const char* owner, const char* group, mode_t mode);
++
+ NETPLAN_INTERNAL void
+ _netplan_unlink_glob(const char* rootdir, const char* _glob);
+ 
+diff --git a/src/util.c b/src/util.c
+index 36eb896..c2f9494 100644
+--- a/src/util.c
++++ b/src/util.c
+@@ -23,6 +23,9 @@
+ #include <regex.h>
+ #include <string.h>
+ #include <sys/mman.h>
++#include <sys/types.h>
++#include <pwd.h>
++#include <grp.h>
+ 
+ #include <glib.h>
+ #include <glib/gprintf.h>
+@@ -87,6 +90,49 @@ void _netplan_g_string_free_to_file(GString* s, const char* rootdir, const char*
+     }
+ }
+ 
++void _netplan_g_string_free_to_file_with_permissions(GString* s, const char* rootdir, const char* path, const char* suffix, const char* owner, const char* group, mode_t mode)
++{
++    g_autofree char* full_path = NULL;
++    g_autofree char* path_suffix = NULL;
++    g_autofree char* contents = g_string_free(s, FALSE);
++    GError* error = NULL;
++    struct passwd* pw = NULL;
++    struct group* gr = NULL;
++    int ret = 0;
++
++    path_suffix = g_strjoin(NULL, path, suffix, NULL);
++    full_path = g_build_path(G_DIR_SEPARATOR_S, rootdir ?: G_DIR_SEPARATOR_S, path_suffix, NULL);
++    _netplan_safe_mkdir_p_dir(full_path);
++    if (!g_file_set_contents_full(full_path, contents, -1, G_FILE_SET_CONTENTS_CONSISTENT | G_FILE_SET_CONTENTS_ONLY_EXISTING, mode, &error)) {
++        /* the mkdir() just succeeded, there is no sensible
++         * method to test this without root privileges, bind mounts, and
++         * simulating ENOSPC */
++        // LCOV_EXCL_START
++        g_fprintf(stderr, "ERROR: cannot create file %s: %s\n", path, error->message);
++        exit(1);
++        // LCOV_EXCL_STOP
++    }
++
++    /* Here we take the owner and group names and look up for their IDs in the passwd and group files.
++     * It's OK to fail to set the owners and mode as this code will be called from unit tests.
++     * The autopkgtests will check if the owner/group and mode are correctly set.
++     */
++    pw = getpwnam(owner);
++    if (!pw) {
++        g_debug("Failed to determine the UID of user %s: %s", owner, strerror(errno)); // LCOV_EXCL_LINE
++    }
++    gr = getgrnam(group);
++    if (!gr) {
++        g_debug("Failed to determine the GID of group %s: %s", group, strerror(errno)); // LCOV_EXCL_LINE
++    }
++    if (pw && gr) {
++        ret = chown(full_path, pw->pw_uid, gr->gr_gid);
++        if (ret != 0) {
++            g_debug("Failed to set owner and group for file %s: %s", full_path, strerror(errno));
++        }
++    }
++}
++
+ /**
+  * Remove all files matching given glob.
+  */
+diff --git a/tests/generator/test_auth.py b/tests/generator/test_auth.py
+index de23adb..d3d886c 100644
+--- a/tests/generator/test_auth.py
++++ b/tests/generator/test_auth.py
+@@ -226,7 +226,7 @@ network={
+ 
+         with open(os.path.join(self.workdir.name, 'run/systemd/system/netplan-wpa-eth0.service')) as f:
+             self.assertEqual(f.read(), SD_WPA % {'iface': 'eth0', 'drivers': 'wired'})
+-            self.assertEqual(stat.S_IMODE(os.fstat(f.fileno()).st_mode), 0o644)
++            self.assertEqual(stat.S_IMODE(os.fstat(f.fileno()).st_mode), 0o640)
+         self.assertTrue(os.path.islink(os.path.join(
+             self.workdir.name, 'run/systemd/system/systemd-networkd.service.wants/netplan-wpa-eth0.service')))
+ 
+diff --git a/tests/generator/test_wifis.py b/tests/generator/test_wifis.py
+index b875172..610782a 100644
+--- a/tests/generator/test_wifis.py
++++ b/tests/generator/test_wifis.py
+@@ -140,7 +140,7 @@ network={
+             self.workdir.name, 'run/systemd/system/netplan-wpa-wl0.service')))
+         with open(os.path.join(self.workdir.name, 'run/systemd/system/netplan-wpa-wl0.service')) as f:
+             self.assertEqual(f.read(), SD_WPA % {'iface': 'wl0', 'drivers': 'nl80211,wext'})
+-            self.assertEqual(stat.S_IMODE(os.fstat(f.fileno()).st_mode), 0o644)
++            self.assertEqual(stat.S_IMODE(os.fstat(f.fileno()).st_mode), 0o640)
+         self.assertTrue(os.path.islink(os.path.join(
+             self.workdir.name, 'run/systemd/system/systemd-networkd.service.wants/netplan-wpa-wl0.service')))
+ 
+diff --git a/tests/integration/base.py b/tests/integration/base.py
+index e9c366c..74f0682 100644
+--- a/tests/integration/base.py
++++ b/tests/integration/base.py
+@@ -32,6 +32,8 @@ import shutil
+ import gi
+ import glob
+ import json
++import pwd
++import grp
+ 
+ # make sure we point to libnetplan properly.
+ os.environ.update({'LD_LIBRARY_PATH': '.:{}'.format(os.environ.get('LD_LIBRARY_PATH'))})
+@@ -367,6 +369,89 @@ class IntegrationTestsBase(unittest.TestCase):
+             if state:
+                 self.wait_output(['ip', 'addr', 'show', iface], state, 30)
+ 
++        # Assert file permissions
++        self.assert_file_permissions()
++
++    def assert_file_permissions(self):
++        """ Check if the generated files have the expected permissions """
++
++        nd_expected_mode = 0o100640
++        nd_expected_owner = 'root'
++        nd_expected_group = 'systemd-network'
++
++        sd_expected_mode = 0o100640
++        sd_expected_owner = 'root'
++        sd_expected_group = 'root'
++
++        udev_expected_mode = 0o100640
++        udev_expected_owner = 'root'
++        udev_expected_group = 'root'
++
++        nm_expected_mode = 0o100600
++        nm_expected_owner = 'root'
++        nm_expected_group = 'root'
++
++        wpa_expected_mode = 0o100600
++        wpa_expected_owner = 'root'
++        wpa_expected_group = 'root'
++
++        # Check systemd-networkd files
++        base_path = '/run/systemd/network'
++        files = glob.glob(f'{base_path}/*.network') + glob.glob(f'{base_path}/*.netdev')
++        for file in files:
++            res = os.stat(file)
++            user = pwd.getpwuid(res.st_uid)
++            group = grp.getgrgid(res.st_gid)
++            self.assertEqual(res.st_mode, nd_expected_mode, f'file {file}')
++            self.assertEqual(user.pw_name, nd_expected_owner, f'file {file}')
++            self.assertEqual(group.gr_name, nd_expected_group, f'file {file}')
++
++        # Check Network Manager files
++        base_path = '/run/NetworkManager/system-connections'
++        files = glob.glob(f'{base_path}/*.nmconnection')
++        for file in files:
++            res = os.stat(file)
++            user = pwd.getpwuid(res.st_uid)
++            group = grp.getgrgid(res.st_gid)
++            self.assertEqual(res.st_mode, nm_expected_mode, f'file {file}')
++            self.assertEqual(user.pw_name, nm_expected_owner, f'file {file}')
++            self.assertEqual(group.gr_name, nm_expected_group, f'file {file}')
++
++        # Check wpa_supplicant configuration files
++        base_path = '/run/netplan'
++        files = glob.glob(f'{base_path}/wpa-*.conf')
++        for file in files:
++            res = os.stat(file)
++            user = pwd.getpwuid(res.st_uid)
++            group = grp.getgrgid(res.st_gid)
++            self.assertEqual(res.st_mode, wpa_expected_mode, f'file {file}')
++            self.assertEqual(user.pw_name, wpa_expected_owner, f'file {file}')
++            self.assertEqual(group.gr_name, wpa_expected_group, f'file {file}')
++
++        # Check systemd service unit files
++        base_path = '/run/systemd/system/'
++        files = glob.glob(f'{base_path}/netplan-*.service')
++        files += glob.glob(f'{base_path}/systemd-networkd-wait-online.service.d/*.conf')
++        for file in files:
++            res = os.stat(file)
++            user = pwd.getpwuid(res.st_uid)
++            group = grp.getgrgid(res.st_gid)
++            self.assertEqual(res.st_mode, sd_expected_mode, f'file {file}')
++            self.assertEqual(user.pw_name, sd_expected_owner, f'file {file}')
++            self.assertEqual(group.gr_name, sd_expected_group, f'file {file}')
++
++        # Check systemd-udevd files
++        udev_path = '/run/udev/rules.d'
++        link_path = '/run/systemd/network'
++        files = glob.glob(f'{udev_path}/*-netplan*.rules') + glob.glob(f'{link_path}/*.link')
++        for file in files:
++            res = os.stat(file)
++            user = pwd.getpwuid(res.st_uid)
++            group = grp.getgrgid(res.st_gid)
++            self.assertEqual(res.st_mode, udev_expected_mode, f'file {file}')
++            self.assertEqual(user.pw_name, udev_expected_owner, f'file {file}')
++            self.assertEqual(group.gr_name, udev_expected_group, f'file {file}')
++
+     def state(self, iface, state):
+         '''Tell generate_and_settle() to wait for a specific state'''
+         return iface + '/' + state
+-- 
+2.44.1
+
diff --git a/meta-oe/dynamic-layers/meta-python/recipes-connectivity/netplan/netplan_1.0.bb b/meta-oe/dynamic-layers/meta-python/recipes-connectivity/netplan/netplan_1.0.bb
index cf8d6d19e7..752acc23c3 100644
--- a/meta-oe/dynamic-layers/meta-python/recipes-connectivity/netplan/netplan_1.0.bb
+++ b/meta-oe/dynamic-layers/meta-python/recipes-connectivity/netplan/netplan_1.0.bb
@@ -17,6 +17,7 @@  REQUIRED_DISTRO_FEATURES = "systemd"
 SRC_URI = "git://github.com/CanonicalLtd/netplan.git;branch=main;protocol=https \
            file://0001-meson.build-drop-unnecessary-build-dependencies.patch \
            file://0002-meson.build-do-not-use-Werror.patch \
+           file://CVE-2022-4968.patch \
           "
 
 SRC_URI:append:libc-musl = " file://0001-don-t-fail-if-GLOB_BRACE-is-not-defined.patch"