diff options
Diffstat (limited to 'meta/recipes-core')
21 files changed, 1828 insertions, 75 deletions
diff --git a/meta/recipes-core/busybox/busybox/0001-decompress_gunzip-Fix-DoS-if-gzip-is-corrupt.patch b/meta/recipes-core/busybox/busybox/0001-decompress_gunzip-Fix-DoS-if-gzip-is-corrupt.patch new file mode 100644 index 0000000000..67c9f189cc --- /dev/null +++ b/meta/recipes-core/busybox/busybox/0001-decompress_gunzip-Fix-DoS-if-gzip-is-corrupt.patch @@ -0,0 +1,58 @@ +From fe791386ebc270219ca00406c9fdadc5130b64ee Mon Sep 17 00:00:00 2001 +From: Samuel Sapalski <samuel.sapalski@nokia.com> +Date: Wed, 3 Mar 2021 16:31:22 +0100 +Subject: [PATCH] decompress_gunzip: Fix DoS if gzip is corrupt + +On certain corrupt gzip files, huft_build will set the error bit on +the result pointer. If afterwards abort_unzip is called huft_free +might run into a segmentation fault or an invalid pointer to +free(p). + +In order to mitigate this, we check in huft_free if the error bit +is set and clear it before the linked list is freed. + +Signed-off-by: Samuel Sapalski <samuel.sapalski@nokia.com> +Signed-off-by: Peter Kaestle <peter.kaestle@nokia.com> +Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com> + +Upstream-Status: Backport +CVE: CVE-2021-28831 +Signed-off-by: Chen Qi <Qi.Chen@windriver.com> +--- + archival/libarchive/decompress_gunzip.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/archival/libarchive/decompress_gunzip.c b/archival/libarchive/decompress_gunzip.c +index eb3b64930..e93cd5005 100644 +--- a/archival/libarchive/decompress_gunzip.c ++++ b/archival/libarchive/decompress_gunzip.c +@@ -220,10 +220,20 @@ static const uint8_t border[] ALIGN1 = { + * each table. + * t: table to free + */ ++#define BAD_HUFT(p) ((uintptr_t)(p) & 1) ++#define ERR_RET ((huft_t*)(uintptr_t)1) + static void huft_free(huft_t *p) + { + huft_t *q; + ++ /* ++ * If 'p' has the error bit set we have to clear it, otherwise we might run ++ * into a segmentation fault or an invalid pointer to free(p) ++ */ ++ if (BAD_HUFT(p)) { ++ p = (huft_t*)((uintptr_t)(p) ^ (uintptr_t)(ERR_RET)); ++ } ++ + /* Go through linked list, freeing from the malloced (t[-1]) address. */ + while (p) { + q = (--p)->v.t; +@@ -289,8 +299,6 @@ static unsigned fill_bitbuffer(STATE_PARAM unsigned bitbuffer, unsigned *current + * or a valid pointer to a Huffman table, ORed with 0x1 if incompete table + * is given: "fixed inflate" decoder feeds us such data. + */ +-#define BAD_HUFT(p) ((uintptr_t)(p) & 1) +-#define ERR_RET ((huft_t*)(uintptr_t)1) + static huft_t* huft_build(const unsigned *b, const unsigned n, + const unsigned s, const struct cp_ext *cp_ext, + unsigned *m) diff --git a/meta/recipes-core/busybox/busybox_1.32.0.bb b/meta/recipes-core/busybox/busybox_1.32.0.bb index 8e23b0d4a2..b91f7cf711 100644 --- a/meta/recipes-core/busybox/busybox_1.32.0.bb +++ b/meta/recipes-core/busybox/busybox_1.32.0.bb @@ -46,7 +46,8 @@ SRC_URI = "https://busybox.net/downloads/busybox-${PV}.tar.bz2;name=tarball \ file://0001-hwclock-make-glibc-2.31-compatible.patch \ file://rev.cfg \ file://pgrep.cfg \ -" + file://0001-decompress_gunzip-Fix-DoS-if-gzip-is-corrupt.patch \ + " SRC_URI_append_libc-musl = " file://musl.cfg " SRC_URI[tarball.md5sum] = "9576986f1a960da471d03b72a62f13c7" diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219.patch new file mode 100644 index 0000000000..a4ec01134a --- /dev/null +++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2021-27219.patch @@ -0,0 +1,1444 @@ +commit b70039028b4a39ea071f6ed368a58ad5b5b90ba3 +Author: Anatol Belski <anbelski@microsoft.com> +Date: Sun Mar 14 17:51:53 2021 +0000 + + backport: 2.64.5_CVE-2021-27219 + +CVE: CVE-2021-27219 +Upstream-Status: Backport +[https://gitlab.gnome.org/GNOME/glib/-/merge_requests/1926] + +Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com> + +diff --git a/docs/reference/glib/meson.build b/docs/reference/glib/meson.build +index 62d95f78d..7eebb04ac 100644 +--- a/docs/reference/glib/meson.build ++++ b/docs/reference/glib/meson.build +@@ -22,6 +22,7 @@ if get_option('gtk_doc') + 'gprintfint.h', + 'gmirroringtable.h', + 'gscripttable.h', ++ 'gstrfuncsprivate.h', + 'glib-mirroring-tab', + 'gnulib', + 'pcre', +diff --git a/gio/gdatainputstream.c b/gio/gdatainputstream.c +index 2e7750cb5..2cdcbda19 100644 +--- a/gio/gdatainputstream.c ++++ b/gio/gdatainputstream.c +@@ -27,6 +27,7 @@ + #include "gioenumtypes.h" + #include "gioerror.h" + #include "glibintl.h" ++#include "gstrfuncsprivate.h" + + #include <string.h> + +@@ -856,7 +857,7 @@ static gssize + scan_for_chars (GDataInputStream *stream, + gsize *checked_out, + const char *stop_chars, +- gssize stop_chars_len) ++ gsize stop_chars_len) + { + GBufferedInputStream *bstream; + const char *buffer; +@@ -952,7 +953,7 @@ typedef struct + gsize checked; + + gchar *stop_chars; +- gssize stop_chars_len; ++ gsize stop_chars_len; + gsize length; + } GDataInputStreamReadData; + +@@ -1078,12 +1079,17 @@ g_data_input_stream_read_async (GDataInputStream *stream, + { + GDataInputStreamReadData *data; + GTask *task; ++ gsize stop_chars_len_unsigned; + + data = g_slice_new0 (GDataInputStreamReadData); +- if (stop_chars_len == -1) +- stop_chars_len = strlen (stop_chars); +- data->stop_chars = g_memdup (stop_chars, stop_chars_len); +- data->stop_chars_len = stop_chars_len; ++ ++ if (stop_chars_len < 0) ++ stop_chars_len_unsigned = strlen (stop_chars); ++ else ++ stop_chars_len_unsigned = (gsize) stop_chars_len; ++ ++ data->stop_chars = g_memdup2 (stop_chars, stop_chars_len_unsigned); ++ data->stop_chars_len = stop_chars_len_unsigned; + data->last_saw_cr = FALSE; + + task = g_task_new (stream, cancellable, callback, user_data); +@@ -1338,17 +1344,20 @@ g_data_input_stream_read_upto (GDataInputStream *stream, + gssize found_pos; + gssize res; + char *data_until; ++ gsize stop_chars_len_unsigned; + + g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), NULL); + + if (stop_chars_len < 0) +- stop_chars_len = strlen (stop_chars); ++ stop_chars_len_unsigned = strlen (stop_chars); ++ else ++ stop_chars_len_unsigned = (gsize) stop_chars_len; + + bstream = G_BUFFERED_INPUT_STREAM (stream); + + checked = 0; + +- while ((found_pos = scan_for_chars (stream, &checked, stop_chars, stop_chars_len)) == -1) ++ while ((found_pos = scan_for_chars (stream, &checked, stop_chars, stop_chars_len_unsigned)) == -1) + { + if (g_buffered_input_stream_get_available (bstream) == + g_buffered_input_stream_get_buffer_size (bstream)) +diff --git a/gio/gdbusconnection.c b/gio/gdbusconnection.c +index 1a4dae3bd..9de661bde 100644 +--- a/gio/gdbusconnection.c ++++ b/gio/gdbusconnection.c +@@ -110,6 +110,7 @@ + #include "gasyncinitable.h" + #include "giostream.h" + #include "gasyncresult.h" ++#include "gstrfuncsprivate.h" + #include "gtask.h" + #include "gmarshal-internal.h" + +@@ -4007,7 +4008,7 @@ _g_dbus_interface_vtable_copy (const GDBusInterfaceVTable *vtable) + /* Don't waste memory by copying padding - remember to update this + * when changing struct _GDBusInterfaceVTable in gdbusconnection.h + */ +- return g_memdup ((gconstpointer) vtable, 3 * sizeof (gpointer)); ++ return g_memdup2 ((gconstpointer) vtable, 3 * sizeof (gpointer)); + } + + static void +@@ -4024,7 +4025,7 @@ _g_dbus_subtree_vtable_copy (const GDBusSubtreeVTable *vtable) + /* Don't waste memory by copying padding - remember to update this + * when changing struct _GDBusSubtreeVTable in gdbusconnection.h + */ +- return g_memdup ((gconstpointer) vtable, 3 * sizeof (gpointer)); ++ return g_memdup2 ((gconstpointer) vtable, 3 * sizeof (gpointer)); + } + + static void +diff --git a/gio/gdbusinterfaceskeleton.c b/gio/gdbusinterfaceskeleton.c +index 4a06516c1..4a4b719a5 100644 +--- a/gio/gdbusinterfaceskeleton.c ++++ b/gio/gdbusinterfaceskeleton.c +@@ -28,6 +28,7 @@ + #include "gdbusmethodinvocation.h" + #include "gdbusconnection.h" + #include "gmarshal-internal.h" ++#include "gstrfuncsprivate.h" + #include "gtask.h" + #include "gioerror.h" + +@@ -701,7 +702,7 @@ add_connection_locked (GDBusInterfaceSkeleton *interface_, + * properly before building the hooked_vtable, so we create it + * once at the last minute. + */ +- interface_->priv->hooked_vtable = g_memdup (g_dbus_interface_skeleton_get_vtable (interface_), sizeof (GDBusInterfaceVTable)); ++ interface_->priv->hooked_vtable = g_memdup2 (g_dbus_interface_skeleton_get_vtable (interface_), sizeof (GDBusInterfaceVTable)); + interface_->priv->hooked_vtable->method_call = skeleton_intercept_handle_method_call; + } + +diff --git a/gio/gfile.c b/gio/gfile.c +index a2ded14ea..25930435f 100644 +--- a/gio/gfile.c ++++ b/gio/gfile.c +@@ -60,6 +60,7 @@ + #include "gasyncresult.h" + #include "gioerror.h" + #include "glibintl.h" ++#include "gstrfuncsprivate.h" + + + /** +@@ -7854,7 +7855,7 @@ measure_disk_usage_progress (gboolean reporting, + g_main_context_invoke_full (g_task_get_context (task), + g_task_get_priority (task), + measure_disk_usage_invoke_progress, +- g_memdup (&progress, sizeof progress), ++ g_memdup2 (&progress, sizeof progress), + g_free); + } + +@@ -7872,7 +7873,7 @@ measure_disk_usage_thread (GTask *task, + data->progress_callback ? measure_disk_usage_progress : NULL, task, + &result.disk_usage, &result.num_dirs, &result.num_files, + &error)) +- g_task_return_pointer (task, g_memdup (&result, sizeof result), g_free); ++ g_task_return_pointer (task, g_memdup2 (&result, sizeof result), g_free); + else + g_task_return_error (task, error); + } +@@ -7896,7 +7897,7 @@ g_file_real_measure_disk_usage_async (GFile *file, + + task = g_task_new (file, cancellable, callback, user_data); + g_task_set_source_tag (task, g_file_real_measure_disk_usage_async); +- g_task_set_task_data (task, g_memdup (&data, sizeof data), g_free); ++ g_task_set_task_data (task, g_memdup2 (&data, sizeof data), g_free); + g_task_set_priority (task, io_priority); + + g_task_run_in_thread (task, measure_disk_usage_thread); +diff --git a/gio/giowin32-private.c b/gio/giowin32-private.c +index 7120ae0ea..47e840805 100644 +--- a/gio/giowin32-private.c ++++ b/gio/giowin32-private.c +@@ -16,11 +16,12 @@ + * along with this library; if not, see <http://www.gnu.org/licenses/>. + */ + ++#include "gstrfuncsprivate.h" + +-static gssize ++static gsize + g_utf16_len (const gunichar2 *str) + { +- gssize result; ++ gsize result; + + for (result = 0; str[0] != 0; str++, result++) + ; +@@ -31,17 +32,20 @@ g_utf16_len (const gunichar2 *str) + static gunichar2 * + g_wcsdup (const gunichar2 *str, gssize str_len) + { +- gssize str_size; ++ gsize str_len_unsigned; ++ gsize str_size; + + g_return_val_if_fail (str != NULL, NULL); + +- if (str_len == -1) +- str_len = g_utf16_len (str); ++ if (str_len < 0) ++ str_len_unsigned = g_utf16_len (str); ++ else ++ str_len_unsigned = (gsize) str_len; + +- g_assert (str_len <= G_MAXSIZE / sizeof (gunichar2) - 1); +- str_size = (str_len + 1) * sizeof (gunichar2); ++ g_assert (str_len_unsigned <= G_MAXSIZE / sizeof (gunichar2) - 1); ++ str_size = (str_len_unsigned + 1) * sizeof (gunichar2); + +- return g_memdup (str, str_size); ++ return g_memdup2 (str, str_size); + } + + static const gunichar2 * +diff --git a/gio/gkeyfilesettingsbackend.c b/gio/gkeyfilesettingsbackend.c +index cd5765afd..de216e615 100644 +--- a/gio/gkeyfilesettingsbackend.c ++++ b/gio/gkeyfilesettingsbackend.c +@@ -33,6 +33,7 @@ + #include "gfilemonitor.h" + #include "gsimplepermission.h" + #include "gsettingsbackendinternal.h" ++#include "gstrfuncsprivate.h" + #include "giomodule-priv.h" + #include "gportalsupport.h" + +@@ -145,8 +146,8 @@ convert_path (GKeyfileSettingsBackend *kfsb, + gchar **group, + gchar **basename) + { +- gint key_len = strlen (key); +- gint i; ++ gsize key_len = strlen (key); ++ const gchar *last_slash; + + if (key_len < kfsb->prefix_len || + memcmp (key, kfsb->prefix, kfsb->prefix_len) != 0) +@@ -155,38 +156,48 @@ convert_path (GKeyfileSettingsBackend *kfsb, + key_len -= kfsb->prefix_len; + key += kfsb->prefix_len; + +- for (i = key_len; i >= 0; i--) +- if (key[i] == '/') +- break; ++ last_slash = strrchr (key, '/'); ++ ++ /* Disallow empty group names or key names */ ++ if (key_len == 0 || ++ (last_slash != NULL && ++ (*(last_slash + 1) == '\0' || ++ last_slash == key))) ++ return FALSE; + + if (kfsb->root_group) + { + /* if a root_group was specified, make sure the user hasn't given + * a path that ghosts that group name + */ +- if (i == kfsb->root_group_len && memcmp (key, kfsb->root_group, i) == 0) ++ if (last_slash != NULL && (last_slash - key) == kfsb->root_group_len && memcmp (key, kfsb->root_group, last_slash - key) == 0) + return FALSE; + } + else + { + /* if no root_group was given, ensure that the user gave a path */ +- if (i == -1) ++ if (last_slash == NULL) + return FALSE; + } + + if (group) + { +- if (i >= 0) ++ if (last_slash != NULL) + { +- *group = g_memdup (key, i + 1); +- (*group)[i] = '\0'; ++ *group = g_memdup2 (key, (last_slash - key) + 1); ++ (*group)[(last_slash - key)] = '\0'; + } + else + *group = g_strdup (kfsb->root_group); + } + + if (basename) +- *basename = g_memdup (key + i + 1, key_len - i); ++ { ++ if (last_slash != NULL) ++ *basename = g_memdup2 (last_slash + 1, key_len - (last_slash - key)); ++ else ++ *basename = g_strdup (key); ++ } + + return TRUE; + } +diff --git a/gio/gsettingsschema.c b/gio/gsettingsschema.c +index 0b94f76f6..eb5a3b846 100644 +--- a/gio/gsettingsschema.c ++++ b/gio/gsettingsschema.c +@@ -20,6 +20,7 @@ + + #include "gsettingsschema-internal.h" + #include "gsettings.h" ++#include "gstrfuncsprivate.h" + + #include "gvdb/gvdb-reader.h" + #include "strinfo.c" +@@ -1067,9 +1068,9 @@ g_settings_schema_list_children (GSettingsSchema *schema) + + if (g_str_has_suffix (key, "/")) + { +- gint length = strlen (key); ++ gsize length = strlen (key); + +- strv[j] = g_memdup (key, length); ++ strv[j] = g_memdup2 (key, length); + strv[j][length - 1] = '\0'; + j++; + } +diff --git a/gio/gsocket.c b/gio/gsocket.c +index 2a15bdd22..554af026b 100644 +--- a/gio/gsocket.c ++++ b/gio/gsocket.c +@@ -75,6 +75,7 @@ + #include "gcredentialsprivate.h" + #include "glibintl.h" + #include "gioprivate.h" ++#include "gstrfuncsprivate.h" + + #ifdef G_OS_WIN32 + /* For Windows XP runtime compatibility, but use the system's if_nametoindex() if available */ +@@ -174,7 +175,7 @@ static gboolean g_socket_datagram_based_condition_wait (GDatagramBased + GError **error); + + static GSocketAddress * +-cache_recv_address (GSocket *socket, struct sockaddr *native, int native_len); ++cache_recv_address (GSocket *socket, struct sockaddr *native, size_t native_len); + + static gssize + g_socket_receive_message_with_timeout (GSocket *socket, +@@ -260,7 +261,7 @@ struct _GSocketPrivate + struct { + GSocketAddress *addr; + struct sockaddr *native; +- gint native_len; ++ gsize native_len; + guint64 last_used; + } recv_addr_cache[RECV_ADDR_CACHE_SIZE]; + }; +@@ -5259,14 +5260,14 @@ g_socket_send_messages_with_timeout (GSocket *socket, + } + + static GSocketAddress * +-cache_recv_address (GSocket *socket, struct sockaddr *native, int native_len) ++cache_recv_address (GSocket *socket, struct sockaddr *native, size_t native_len) + { + GSocketAddress *saddr; + gint i; + guint64 oldest_time = G_MAXUINT64; + gint oldest_index = 0; + +- if (native_len <= 0) ++ if (native_len == 0) + return NULL; + + saddr = NULL; +@@ -5274,7 +5275,7 @@ cache_recv_address (GSocket *socket, struct sockaddr *native, int native_len) + { + GSocketAddress *tmp = socket->priv->recv_addr_cache[i].addr; + gpointer tmp_native = socket->priv->recv_addr_cache[i].native; +- gint tmp_native_len = socket->priv->recv_addr_cache[i].native_len; ++ gsize tmp_native_len = socket->priv->recv_addr_cache[i].native_len; + + if (!tmp) + continue; +@@ -5304,7 +5305,7 @@ cache_recv_address (GSocket *socket, struct sockaddr *native, int native_len) + g_free (socket->priv->recv_addr_cache[oldest_index].native); + } + +- socket->priv->recv_addr_cache[oldest_index].native = g_memdup (native, native_len); ++ socket->priv->recv_addr_cache[oldest_index].native = g_memdup2 (native, native_len); + socket->priv->recv_addr_cache[oldest_index].native_len = native_len; + socket->priv->recv_addr_cache[oldest_index].addr = g_object_ref (saddr); + socket->priv->recv_addr_cache[oldest_index].last_used = g_get_monotonic_time (); +@@ -5452,6 +5453,9 @@ g_socket_receive_message_with_timeout (GSocket *socket, + /* do it */ + while (1) + { ++ /* addrlen has to be of type int because that’s how WSARecvFrom() is defined */ ++ G_STATIC_ASSERT (sizeof addr <= G_MAXINT); ++ + addrlen = sizeof addr; + if (address) + result = WSARecvFrom (socket->priv->fd, +diff --git a/gio/gtlspassword.c b/gio/gtlspassword.c +index 1e437a7b6..bd86a6dfe 100644 +--- a/gio/gtlspassword.c ++++ b/gio/gtlspassword.c +@@ -23,6 +23,7 @@ + #include "glibintl.h" + + #include "gioenumtypes.h" ++#include "gstrfuncsprivate.h" + #include "gtlspassword.h" + + #include <string.h> +@@ -287,9 +288,14 @@ g_tls_password_set_value (GTlsPassword *password, + g_return_if_fail (G_IS_TLS_PASSWORD (password)); + + if (length < 0) +- length = strlen ((gchar *)value); ++ { ++ /* FIXME: g_tls_password_set_value_full() doesn’t support unsigned gsize */ ++ gsize length_unsigned = strlen ((gchar *) value); ++ g_return_if_fail (length_unsigned <= G_MAXSSIZE); ++ length = (gssize) length_unsigned; ++ } + +- g_tls_password_set_value_full (password, g_memdup (value, length), length, g_free); ++ g_tls_password_set_value_full (password, g_memdup2 (value, (gsize) length), length, g_free); + } + + /** +diff --git a/gio/gwin32registrykey.c b/gio/gwin32registrykey.c +index aa7819294..efb9ae713 100644 +--- a/gio/gwin32registrykey.c ++++ b/gio/gwin32registrykey.c +@@ -28,6 +28,8 @@ + #include <ntstatus.h> + #include <winternl.h> + ++#include "gstrfuncsprivate.h" ++ + #ifndef _WDMDDK_ + typedef enum _KEY_INFORMATION_CLASS { + KeyBasicInformation, +@@ -125,16 +127,34 @@ typedef enum + G_WIN32_REGISTRY_UPDATED_PATH = 1, + } GWin32RegistryKeyUpdateFlag; + ++static gsize ++g_utf16_len (const gunichar2 *str) ++{ ++ gsize result; ++ ++ for (result = 0; str[0] != 0; str++, result++) ++ ; ++ ++ return result; ++} ++ + static gunichar2 * +-g_wcsdup (const gunichar2 *str, +- gssize str_size) ++g_wcsdup (const gunichar2 *str, gssize str_len) + { +- if (str_size == -1) +- { +- str_size = wcslen (str) + 1; +- str_size *= sizeof (gunichar2); +- } +- return g_memdup (str, str_size); ++ gsize str_len_unsigned; ++ gsize str_size; ++ ++ g_return_val_if_fail (str != NULL, NULL); ++ ++ if (str_len < 0) ++ str_len_unsigned = g_utf16_len (str); ++ else ++ str_len_unsigned = (gsize) str_len; ++ ++ g_assert (str_len_unsigned <= G_MAXSIZE / sizeof (gunichar2) - 1); ++ str_size = (str_len_unsigned + 1) * sizeof (gunichar2); ++ ++ return g_memdup2 (str, str_size); + } + + /** +@@ -247,7 +267,7 @@ g_win32_registry_value_iter_copy (const GWin32RegistryValueIter *iter) + new_iter->value_name_size = iter->value_name_size; + + if (iter->value_data != NULL) +- new_iter->value_data = g_memdup (iter->value_data, iter->value_data_size); ++ new_iter->value_data = g_memdup2 (iter->value_data, iter->value_data_size); + + new_iter->value_data_size = iter->value_data_size; + +@@ -268,8 +288,8 @@ g_win32_registry_value_iter_copy (const GWin32RegistryValueIter *iter) + new_iter->value_data_expanded_charsize = iter->value_data_expanded_charsize; + + if (iter->value_data_expanded_u8 != NULL) +- new_iter->value_data_expanded_u8 = g_memdup (iter->value_data_expanded_u8, +- iter->value_data_expanded_charsize); ++ new_iter->value_data_expanded_u8 = g_memdup2 (iter->value_data_expanded_u8, ++ iter->value_data_expanded_charsize); + + new_iter->value_data_expanded_u8_size = iter->value_data_expanded_charsize; + +diff --git a/gio/tests/async-close-output-stream.c b/gio/tests/async-close-output-stream.c +index 5f6620275..d3f97a119 100644 +--- a/gio/tests/async-close-output-stream.c ++++ b/gio/tests/async-close-output-stream.c +@@ -24,6 +24,8 @@ + #include <stdlib.h> + #include <string.h> + ++#include "gstrfuncsprivate.h" ++ + #define DATA_TO_WRITE "Hello world\n" + + typedef struct +@@ -147,9 +149,9 @@ prepare_data (SetupData *data, + + data->expected_size = g_memory_output_stream_get_data_size (G_MEMORY_OUTPUT_STREAM (data->data_stream)); + +- g_assert_cmpint (data->expected_size, >, 0); ++ g_assert_cmpuint (data->expected_size, >, 0); + +- data->expected_output = g_memdup (written, (guint)data->expected_size); ++ data->expected_output = g_memdup2 (written, data->expected_size); + + /* then recreate the streams and prepare them for the asynchronous close */ + destroy_streams (data); +diff --git a/gio/tests/gdbus-export.c b/gio/tests/gdbus-export.c +index fda654c44..10dd6d82f 100644 +--- a/gio/tests/gdbus-export.c ++++ b/gio/tests/gdbus-export.c +@@ -23,6 +23,7 @@ + #include <string.h> + + #include "gdbus-tests.h" ++#include "gstrfuncsprivate.h" + + /* all tests rely on a shared mainloop */ + static GMainLoop *loop = NULL; +@@ -671,7 +672,7 @@ subtree_introspect (GDBusConnection *connection, + g_assert_not_reached (); + } + +- return g_memdup (interfaces, 2 * sizeof (void *)); ++ return g_memdup2 (interfaces, 2 * sizeof (void *)); + } + + static const GDBusInterfaceVTable * +@@ -727,7 +728,7 @@ dynamic_subtree_introspect (GDBusConnection *connection, + { + const GDBusInterfaceInfo *interfaces[2] = { &dyna_interface_info, NULL }; + +- return g_memdup (interfaces, 2 * sizeof (void *)); ++ return g_memdup2 (interfaces, 2 * sizeof (void *)); + } + + static const GDBusInterfaceVTable * +diff --git a/gio/tests/gsettings.c b/gio/tests/gsettings.c +index baadca8f5..afe594a23 100644 +--- a/gio/tests/gsettings.c ++++ b/gio/tests/gsettings.c +@@ -1,3 +1,4 @@ ++#include <errno.h> + #include <stdlib.h> + #include <locale.h> + #include <libintl.h> +@@ -1740,6 +1741,14 @@ key_changed_cb (GSettings *settings, const gchar *key, gpointer data) + (*b) = TRUE; + } + ++typedef struct ++{ ++ const gchar *path; ++ const gchar *root_group; ++ const gchar *keyfile_group; ++ const gchar *root_path; ++} KeyfileTestData; ++ + /* + * Test that using a keyfile works + */ +@@ -1834,7 +1843,11 @@ test_keyfile (Fixture *fixture, + g_free (str); + + g_settings_set (settings, "farewell", "s", "cheerio"); +- ++ ++ /* Check that empty keys/groups are not allowed. */ ++ g_assert_false (g_settings_is_writable (settings, "")); ++ g_assert_false (g_settings_is_writable (settings, "/")); ++ + /* When executing as root, changing the mode of the keyfile will have + * no effect on the writability of the settings. + */ +@@ -1866,6 +1879,149 @@ test_keyfile (Fixture *fixture, + g_free (keyfile_path); + } + ++/* ++ * Test that using a keyfile works with a schema with no path set. ++ */ ++static void ++test_keyfile_no_path (Fixture *fixture, ++ gconstpointer user_data) ++{ ++ const KeyfileTestData *test_data = user_data; ++ GSettingsBackend *kf_backend; ++ GSettings *settings; ++ GKeyFile *keyfile; ++ gboolean writable; ++ gchar *key = NULL; ++ GError *error = NULL; ++ gchar *keyfile_path = NULL, *store_path = NULL; ++ ++ keyfile_path = g_build_filename (fixture->tmp_dir, "keyfile", NULL); ++ store_path = g_build_filename (keyfile_path, "gsettings.store", NULL); ++ kf_backend = g_keyfile_settings_backend_new (store_path, test_data->root_path, test_data->root_group); ++ settings = g_settings_new_with_backend_and_path ("org.gtk.test.no-path", kf_backend, test_data->path); ++ g_object_unref (kf_backend); ++ ++ g_settings_reset (settings, "test-boolean"); ++ g_assert_true (g_settings_get_boolean (settings, "test-boolean")); ++ ++ writable = g_settings_is_writable (settings, "test-boolean"); ++ g_assert_true (writable); ++ g_settings_set (settings, "test-boolean", "b", FALSE); ++ ++ g_assert_false (g_settings_get_boolean (settings, "test-boolean")); ++ ++ g_settings_delay (settings); ++ g_settings_set (settings, "test-boolean", "b", TRUE); ++ g_settings_apply (settings); ++ ++ keyfile = g_key_file_new (); ++ g_assert_true (g_key_file_load_from_file (keyfile, store_path, 0, NULL)); ++ ++ g_assert_true (g_key_file_get_boolean (keyfile, test_data->keyfile_group, "test-boolean", NULL)); ++ ++ g_key_file_free (keyfile); ++ ++ g_settings_reset (settings, "test-boolean"); ++ g_settings_apply (settings); ++ keyfile = g_key_file_new (); ++ g_assert_true (g_key_file_load_from_file (keyfile, store_path, 0, NULL)); ++ ++ g_assert_false (g_key_file_get_string (keyfile, test_data->keyfile_group, "test-boolean", &error)); ++ g_assert_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND); ++ g_clear_error (&error); ++ ++ /* Check that empty keys/groups are not allowed. */ ++ g_assert_false (g_settings_is_writable (settings, "")); ++ g_assert_false (g_settings_is_writable (settings, "/")); ++ ++ /* Keys which ghost the root group name are not allowed. This can only be ++ * tested when the path is `/` as otherwise it acts as a prefix and prevents ++ * any ghosting. */ ++ if (g_str_equal (test_data->path, "/")) ++ { ++ key = g_strdup_printf ("%s/%s", test_data->root_group, ""); ++ g_assert_false (g_settings_is_writable (settings, key)); ++ g_free (key); ++ ++ key = g_strdup_printf ("%s/%s", test_data->root_group, "/"); ++ g_assert_false (g_settings_is_writable (settings, key)); ++ g_free (key); ++ ++ key = g_strdup_printf ("%s/%s", test_data->root_group, "test-boolean"); ++ g_assert_false (g_settings_is_writable (settings, key)); ++ g_free (key); ++ } ++ ++ g_key_file_free (keyfile); ++ g_object_unref (settings); ++ ++ /* Clean up the temporary directory. */ ++ g_assert_cmpint (g_chmod (keyfile_path, 0777) == 0 ? 0 : errno, ==, 0); ++ g_assert_cmpint (g_remove (store_path) == 0 ? 0 : errno, ==, 0); ++ g_assert_cmpint (g_rmdir (keyfile_path) == 0 ? 0 : errno, ==, 0); ++ g_free (store_path); ++ g_free (keyfile_path); ++} ++ ++/* ++ * Test that a keyfile rejects writes to keys outside its root path. ++ */ ++static void ++test_keyfile_outside_root_path (Fixture *fixture, ++ gconstpointer user_data) ++{ ++ GSettingsBackend *kf_backend; ++ GSettings *settings; ++ gchar *keyfile_path = NULL, *store_path = NULL; ++ ++ keyfile_path = g_build_filename (fixture->tmp_dir, "keyfile", NULL); ++ store_path = g_build_filename (keyfile_path, "gsettings.store", NULL); ++ kf_backend = g_keyfile_settings_backend_new (store_path, "/tests/basic-types/", "root"); ++ settings = g_settings_new_with_backend_and_path ("org.gtk.test.no-path", kf_backend, "/tests/"); ++ g_object_unref (kf_backend); ++ ++ g_assert_false (g_settings_is_writable (settings, "test-boolean")); ++ ++ g_object_unref (settings); ++ ++ /* Clean up the temporary directory. The keyfile probably doesn’t exist, so ++ * don’t error on failure. */ ++ g_remove (store_path); ++ g_assert_cmpint (g_rmdir (keyfile_path) == 0 ? 0 : errno, ==, 0); ++ g_free (store_path); ++ g_free (keyfile_path); ++} ++ ++/* ++ * Test that a keyfile rejects writes to keys in the root if no root group is set. ++ */ ++static void ++test_keyfile_no_root_group (Fixture *fixture, ++ gconstpointer user_data) ++{ ++ GSettingsBackend *kf_backend; ++ GSettings *settings; ++ gchar *keyfile_path = NULL, *store_path = NULL; ++ ++ keyfile_path = g_build_filename (fixture->tmp_dir, "keyfile", NULL); ++ store_path = g_build_filename (keyfile_path, "gsettings.store", NULL); ++ kf_backend = g_keyfile_settings_backend_new (store_path, "/", NULL); ++ settings = g_settings_new_with_backend_and_path ("org.gtk.test.no-path", kf_backend, "/"); ++ g_object_unref (kf_backend); ++ ++ g_assert_false (g_settings_is_writable (settings, "test-boolean")); ++ g_assert_true (g_settings_is_writable (settings, "child/test-boolean")); ++ ++ g_object_unref (settings); ++ ++ /* Clean up the temporary directory. The keyfile probably doesn’t exist, so ++ * don’t error on failure. */ ++ g_remove (store_path); ++ g_assert_cmpint (g_rmdir (keyfile_path) == 0 ? 0 : errno, ==, 0); ++ g_free (store_path); ++ g_free (keyfile_path); ++} ++ + /* Test that getting child schemas works + */ + static void +@@ -2844,6 +3000,14 @@ main (int argc, char *argv[]) + gchar *override_text; + gchar *enums; + gint result; ++ const KeyfileTestData keyfile_test_data_explicit_path = { "/tests/", "root", "tests", "/" }; ++ const KeyfileTestData keyfile_test_data_empty_path = { "/", "root", "root", "/" }; ++ const KeyfileTestData keyfile_test_data_long_path = { ++ "/tests/path/is/very/long/and/this/makes/some/comparisons/take/a/different/branch/", ++ "root", ++ "tests/path/is/very/long/and/this/makes/some/comparisons/take/a/different/branch", ++ "/" ++ }; + + /* Meson build sets this */ + #ifdef TEST_LOCALE_PATH +@@ -2967,6 +3131,11 @@ main (int argc, char *argv[]) + } + + g_test_add ("/gsettings/keyfile", Fixture, NULL, setup, test_keyfile, teardown); ++ g_test_add ("/gsettings/keyfile/explicit-path", Fixture, &keyfile_test_data_explicit_path, setup, test_keyfile_no_path, teardown); ++ g_test_add ("/gsettings/keyfile/empty-path", Fixture, &keyfile_test_data_empty_path, setup, test_keyfile_no_path, teardown); ++ g_test_add ("/gsettings/keyfile/long-path", Fixture, &keyfile_test_data_long_path, setup, test_keyfile_no_path, teardown); ++ g_test_add ("/gsettings/keyfile/outside-root-path", Fixture, NULL, setup, test_keyfile_outside_root_path, teardown); ++ g_test_add ("/gsettings/keyfile/no-root-group", Fixture, NULL, setup, test_keyfile_no_root_group, teardown); + g_test_add_func ("/gsettings/child-schema", test_child_schema); + g_test_add_func ("/gsettings/strinfo", test_strinfo); + g_test_add_func ("/gsettings/enums", test_enums); +diff --git a/gio/tests/tls-interaction.c b/gio/tests/tls-interaction.c +index 4f0737d7e..5661e8e0d 100644 +--- a/gio/tests/tls-interaction.c ++++ b/gio/tests/tls-interaction.c +@@ -174,6 +174,38 @@ test_interaction_ask_password_finish_failure (GTlsInteraction *interaction, + } + + ++/* Return a copy of @str that is allocated in a silly way, to exercise ++ * custom free-functions. The returned pointer points to a copy of @str ++ * in a buffer of the form "BEFORE \0 str \0 AFTER". */ ++static guchar * ++special_dup (const char *str) ++{ ++ GString *buf = g_string_new ("BEFORE"); ++ guchar *ret; ++ ++ g_string_append_c (buf, '\0'); ++ g_string_append (buf, str); ++ g_string_append_c (buf, '\0'); ++ g_string_append (buf, "AFTER"); ++ ret = (guchar *) g_string_free (buf, FALSE); ++ return ret + strlen ("BEFORE") + 1; ++} ++ ++ ++/* Free a copy of @str that was made with special_dup(), after asserting ++ * that it has not been corrupted. */ ++static void ++special_free (gpointer p) ++{ ++ gchar *s = p; ++ gchar *buf = s - strlen ("BEFORE") - 1; ++ ++ g_assert_cmpstr (buf, ==, "BEFORE"); ++ g_assert_cmpstr (s + strlen (s) + 1, ==, "AFTER"); ++ g_free (buf); ++} ++ ++ + static GTlsInteractionResult + test_interaction_ask_password_sync_success (GTlsInteraction *interaction, + GTlsPassword *password, +@@ -181,6 +213,8 @@ test_interaction_ask_password_sync_success (GTlsInteraction *interaction, + GError **error) + { + TestInteraction *self; ++ const guchar *value; ++ gsize len; + + g_assert (TEST_IS_INTERACTION (interaction)); + self = TEST_INTERACTION (interaction); +@@ -192,6 +226,27 @@ test_interaction_ask_password_sync_success (GTlsInteraction *interaction, + g_assert (error != NULL); + g_assert (*error == NULL); + ++ /* Exercise different ways to set the value */ ++ g_tls_password_set_value (password, (const guchar *) "foo", 4); ++ len = 0; ++ value = g_tls_password_get_value (password, &len); ++ g_assert_cmpmem (value, len, "foo", 4); ++ ++ g_tls_password_set_value (password, (const guchar *) "bar", -1); ++ len = 0; ++ value = g_tls_password_get_value (password, &len); ++ g_assert_cmpmem (value, len, "bar", 3); ++ ++ g_tls_password_set_value_full (password, special_dup ("baa"), 4, special_free); ++ len = 0; ++ value = g_tls_password_get_value (password, &len); ++ g_assert_cmpmem (value, len, "baa", 4); ++ ++ g_tls_password_set_value_full (password, special_dup ("baz"), -1, special_free); ++ len = 0; ++ value = g_tls_password_get_value (password, &len); ++ g_assert_cmpmem (value, len, "baz", 3); ++ + /* Don't do this in real life. Include a null terminator for testing */ + g_tls_password_set_value (password, (const guchar *)"the password", 13); + return G_TLS_INTERACTION_HANDLED; +diff --git a/gio/win32/gwinhttpfile.c b/gio/win32/gwinhttpfile.c +index cf5eed31d..246ec0578 100644 +--- a/gio/win32/gwinhttpfile.c ++++ b/gio/win32/gwinhttpfile.c +@@ -29,6 +29,7 @@ + #include "gio/gfile.h" + #include "gio/gfileattribute.h" + #include "gio/gfileinfo.h" ++#include "gstrfuncsprivate.h" + #include "gwinhttpfile.h" + #include "gwinhttpfileinputstream.h" + #include "gwinhttpfileoutputstream.h" +@@ -393,10 +394,10 @@ g_winhttp_file_resolve_relative_path (GFile *file, + child = g_object_new (G_TYPE_WINHTTP_FILE, NULL); + child->vfs = winhttp_file->vfs; + child->url = winhttp_file->url; +- child->url.lpszScheme = g_memdup (winhttp_file->url.lpszScheme, (winhttp_file->url.dwSchemeLength+1)*2); +- child->url.lpszHostName = g_memdup (winhttp_file->url.lpszHostName, (winhttp_file->url.dwHostNameLength+1)*2); +- child->url.lpszUserName = g_memdup (winhttp_file->url.lpszUserName, (winhttp_file->url.dwUserNameLength+1)*2); +- child->url.lpszPassword = g_memdup (winhttp_file->url.lpszPassword, (winhttp_file->url.dwPasswordLength+1)*2); ++ child->url.lpszScheme = g_memdup2 (winhttp_file->url.lpszScheme, ((gsize) winhttp_file->url.dwSchemeLength + 1) * 2); ++ child->url.lpszHostName = g_memdup2 (winhttp_file->url.lpszHostName, ((gsize) winhttp_file->url.dwHostNameLength + 1) * 2); ++ child->url.lpszUserName = g_memdup2 (winhttp_file->url.lpszUserName, ((gsize) winhttp_file->url.dwUserNameLength + 1) * 2); ++ child->url.lpszPassword = g_memdup2 (winhttp_file->url.lpszPassword, ((gsize) winhttp_file->url.dwPasswordLength + 1) * 2); + child->url.lpszUrlPath = wnew_path; + child->url.dwUrlPathLength = wcslen (wnew_path); + child->url.lpszExtraInfo = NULL; +diff --git a/glib/gbytes.c b/glib/gbytes.c +index ec6923188..6f17d104c 100644 +--- a/glib/gbytes.c ++++ b/glib/gbytes.c +@@ -34,6 +34,8 @@ + + #include <string.h> + ++#include "gstrfuncsprivate.h" ++ + /** + * GBytes: + * +@@ -95,7 +97,7 @@ g_bytes_new (gconstpointer data, + { + g_return_val_if_fail (data != NULL || size == 0, NULL); + +- return g_bytes_new_take (g_memdup (data, size), size); ++ return g_bytes_new_take (g_memdup2 (data, size), size); + } + + /** +@@ -499,7 +501,7 @@ g_bytes_unref_to_data (GBytes *bytes, + * Copy: Non g_malloc (or compatible) allocator, or static memory, + * so we have to copy, and then unref. + */ +- result = g_memdup (bytes->data, bytes->size); ++ result = g_memdup2 (bytes->data, bytes->size); + *size = bytes->size; + g_bytes_unref (bytes); + } +diff --git a/glib/gdir.c b/glib/gdir.c +index 6b85e99c8..6747a8c6f 100644 +--- a/glib/gdir.c ++++ b/glib/gdir.c +@@ -37,6 +37,7 @@ + #include "gconvert.h" + #include "gfileutils.h" + #include "gstrfuncs.h" ++#include "gstrfuncsprivate.h" + #include "gtestutils.h" + #include "glibintl.h" + +@@ -112,7 +113,7 @@ g_dir_open_with_errno (const gchar *path, + return NULL; + #endif + +- return g_memdup (&dir, sizeof dir); ++ return g_memdup2 (&dir, sizeof dir); + } + + /** +diff --git a/glib/ghash.c b/glib/ghash.c +index 0f1562a06..c1e15c957 100644 +--- a/glib/ghash.c ++++ b/glib/ghash.c +@@ -34,6 +34,7 @@ + #include "gmacros.h" + #include "glib-private.h" + #include "gstrfuncs.h" ++#include "gstrfuncsprivate.h" + #include "gatomic.h" + #include "gtestutils.h" + #include "gslice.h" +@@ -962,7 +963,7 @@ g_hash_table_ensure_keyval_fits (GHashTable *hash_table, gpointer key, gpointer + if (hash_table->have_big_keys) + { + if (key != value) +- hash_table->values = g_memdup (hash_table->keys, sizeof (gpointer) * hash_table->size); ++ hash_table->values = g_memdup2 (hash_table->keys, sizeof (gpointer) * hash_table->size); + /* Keys and values are both big now, so no need for further checks */ + return; + } +@@ -970,7 +971,7 @@ g_hash_table_ensure_keyval_fits (GHashTable *hash_table, gpointer key, gpointer + { + if (key != value) + { +- hash_table->values = g_memdup (hash_table->keys, sizeof (guint) * hash_table->size); ++ hash_table->values = g_memdup2 (hash_table->keys, sizeof (guint) * hash_table->size); + is_a_set = FALSE; + } + } +@@ -998,7 +999,7 @@ g_hash_table_ensure_keyval_fits (GHashTable *hash_table, gpointer key, gpointer + + /* Just split if necessary */ + if (is_a_set && key != value) +- hash_table->values = g_memdup (hash_table->keys, sizeof (gpointer) * hash_table->size); ++ hash_table->values = g_memdup2 (hash_table->keys, sizeof (gpointer) * hash_table->size); + + #endif + } +diff --git a/glib/giochannel.c b/glib/giochannel.c +index d16399846..b41381d38 100644 +--- a/glib/giochannel.c ++++ b/glib/giochannel.c +@@ -37,6 +37,7 @@ + #include "giochannel.h" + + #include "gstrfuncs.h" ++#include "gstrfuncsprivate.h" + #include "gtestutils.h" + #include "glibintl.h" + +@@ -886,17 +887,26 @@ g_io_channel_set_line_term (GIOChannel *channel, + const gchar *line_term, + gint length) + { ++ guint length_unsigned; ++ + g_return_if_fail (channel != NULL); + g_return_if_fail (line_term == NULL || length != 0); /* Disallow "" */ + + if (line_term == NULL) +- length = 0; +- else if (length < 0) +- length = strlen (line_term); ++ length_unsigned = 0; ++ else if (length >= 0) ++ length_unsigned = (guint) length; ++ else ++ { ++ /* FIXME: We’re constrained by line_term_len being a guint here */ ++ gsize length_size = strlen (line_term); ++ g_return_if_fail (length_size <= G_MAXUINT); ++ length_unsigned = (guint) length_size; ++ } + + g_free (channel->line_term); +- channel->line_term = line_term ? g_memdup (line_term, length) : NULL; +- channel->line_term_len = length; ++ channel->line_term = line_term ? g_memdup2 (line_term, length_unsigned) : NULL; ++ channel->line_term_len = length_unsigned; + } + + /** +@@ -1673,10 +1683,10 @@ g_io_channel_read_line (GIOChannel *channel, + + /* Copy the read bytes (including any embedded nuls) and nul-terminate. + * `USE_BUF (channel)->str` is guaranteed to be nul-terminated as it’s a +- * #GString, so it’s safe to call g_memdup() with +1 length to allocate ++ * #GString, so it’s safe to call g_memdup2() with +1 length to allocate + * a nul-terminator. */ + g_assert (USE_BUF (channel)); +- line = g_memdup (USE_BUF (channel)->str, got_length + 1); ++ line = g_memdup2 (USE_BUF (channel)->str, got_length + 1); + line[got_length] = '\0'; + *str_return = g_steal_pointer (&line); + g_string_erase (USE_BUF (channel), 0, got_length); +diff --git a/glib/gslice.c b/glib/gslice.c +index 4c758c3be..bcdbb8853 100644 +--- a/glib/gslice.c ++++ b/glib/gslice.c +@@ -41,6 +41,7 @@ + #include "gmain.h" + #include "gmem.h" /* gslice.h */ + #include "gstrfuncs.h" ++#include "gstrfuncsprivate.h" + #include "gutils.h" + #include "gtrashstack.h" + #include "gtestutils.h" +@@ -350,7 +351,7 @@ g_slice_get_config_state (GSliceConfig ckey, + array[i++] = allocator->contention_counters[address]; + array[i++] = allocator_get_magazine_threshold (allocator, address); + *n_values = i; +- return g_memdup (array, sizeof (array[0]) * *n_values); ++ return g_memdup2 (array, sizeof (array[0]) * *n_values); + default: + return NULL; + } +diff --git a/glib/gstrfuncsprivate.h b/glib/gstrfuncsprivate.h +new file mode 100644 +index 000000000..85c88328a +--- /dev/null ++++ b/glib/gstrfuncsprivate.h +@@ -0,0 +1,55 @@ ++/* GLIB - Library of useful routines for C programming ++ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, see <http://www.gnu.org/licenses/>. ++ */ ++ ++#include <glib.h> ++#include <string.h> ++ ++/* ++ * g_memdup2: ++ * @mem: (nullable): the memory to copy. ++ * @byte_size: the number of bytes to copy. ++ * ++ * Allocates @byte_size bytes of memory, and copies @byte_size bytes into it ++ * from @mem. If @mem is %NULL it returns %NULL. ++ * ++ * This replaces g_memdup(), which was prone to integer overflows when ++ * converting the argument from a #gsize to a #guint. ++ * ++ * This static inline version is a backport of the new public API from ++ * GLib 2.68, kept internal to GLib for backport to older stable releases. ++ * See https://gitlab.gnome.org/GNOME/glib/-/issues/2319. ++ * ++ * Returns: (nullable): a pointer to the newly-allocated copy of the memory, ++ * or %NULL if @mem is %NULL. ++ * Since: 2.68 ++ */ ++static inline gpointer ++g_memdup2 (gconstpointer mem, ++ gsize byte_size) ++{ ++ gpointer new_mem; ++ ++ if (mem && byte_size != 0) ++ { ++ new_mem = g_malloc (byte_size); ++ memcpy (new_mem, mem, byte_size); ++ } ++ else ++ new_mem = NULL; ++ ++ return new_mem; ++} +diff --git a/glib/gtestutils.c b/glib/gtestutils.c +index 18b117285..26d46ad75 100644 +--- a/glib/gtestutils.c ++++ b/glib/gtestutils.c +@@ -49,6 +49,7 @@ + #include "gpattern.h" + #include "grand.h" + #include "gstrfuncs.h" ++#include "gstrfuncsprivate.h" + #include "gtimer.h" + #include "gslice.h" + #include "gspawn.h" +@@ -3803,7 +3804,7 @@ g_test_log_extract (GTestLogBuffer *tbuffer) + if (p <= tbuffer->data->str + mlength) + { + g_string_erase (tbuffer->data, 0, mlength); +- tbuffer->msgs = g_slist_prepend (tbuffer->msgs, g_memdup (&msg, sizeof (msg))); ++ tbuffer->msgs = g_slist_prepend (tbuffer->msgs, g_memdup2 (&msg, sizeof (msg))); + return TRUE; + } + +diff --git a/glib/gvariant.c b/glib/gvariant.c +index 77d7e746b..ef4257f6d 100644 +--- a/glib/gvariant.c ++++ b/glib/gvariant.c +@@ -33,6 +33,7 @@ + + #include <string.h> + ++#include "gstrfuncsprivate.h" + + /** + * SECTION:gvariant +@@ -725,7 +726,7 @@ g_variant_new_variant (GVariant *value) + g_variant_ref_sink (value); + + return g_variant_new_from_children (G_VARIANT_TYPE_VARIANT, +- g_memdup (&value, sizeof value), ++ g_memdup2 (&value, sizeof value), + 1, g_variant_is_trusted (value)); + } + +@@ -1229,7 +1230,7 @@ g_variant_new_fixed_array (const GVariantType *element_type, + return NULL; + } + +- data = g_memdup (elements, n_elements * element_size); ++ data = g_memdup2 (elements, n_elements * element_size); + value = g_variant_new_from_data (array_type, data, + n_elements * element_size, + FALSE, g_free, data); +@@ -1908,7 +1909,7 @@ g_variant_dup_bytestring (GVariant *value, + if (length) + *length = size; + +- return g_memdup (original, size + 1); ++ return g_memdup2 (original, size + 1); + } + + /** +diff --git a/glib/gvarianttype.c b/glib/gvarianttype.c +index c46f1a2c6..585e29ab2 100644 +--- a/glib/gvarianttype.c ++++ b/glib/gvarianttype.c +@@ -28,6 +28,7 @@ + + #include <string.h> + ++#include "gstrfuncsprivate.h" + + /** + * SECTION:gvarianttype +@@ -1181,7 +1182,7 @@ g_variant_type_new_tuple (const GVariantType * const *items, + g_assert (offset < sizeof buffer); + buffer[offset++] = ')'; + +- return (GVariantType *) g_memdup (buffer, offset); ++ return (GVariantType *) g_memdup2 (buffer, offset); + } + + /** +diff --git a/glib/meson.build b/glib/meson.build +index 456e0c2a1..2e5cd77bb 100644 +--- a/glib/meson.build ++++ b/glib/meson.build +@@ -268,6 +268,7 @@ glib_sources = files( + 'gslist.c', + 'gstdio.c', + 'gstrfuncs.c', ++ 'gstrfuncsprivate.h', + 'gstring.c', + 'gstringchunk.c', + 'gtestutils.c', +diff --git a/glib/tests/array-test.c b/glib/tests/array-test.c +index 1da514a3e..88f22de80 100644 +--- a/glib/tests/array-test.c ++++ b/glib/tests/array-test.c +@@ -29,6 +29,8 @@ + #include <string.h> + #include "glib.h" + ++#include "gstrfuncsprivate.h" ++ + /* Test data to be passed to any function which calls g_array_new(), providing + * the parameters for that call. Most #GArray tests should be repeated for all + * possible values of #ArrayTestData. */ +@@ -1917,7 +1919,7 @@ byte_array_new_take (void) + GByteArray *gbarray; + guint8 *data; + +- data = g_memdup ("woooweeewow", 11); ++ data = g_memdup2 ("woooweeewow", 11); + gbarray = g_byte_array_new_take (data, 11); + g_assert (gbarray->data == data); + g_assert_cmpuint (gbarray->len, ==, 11); +diff --git a/glib/tests/io-channel.c b/glib/tests/io-channel.c +index ff53fcef7..4a1b10876 100644 +--- a/glib/tests/io-channel.c ++++ b/glib/tests/io-channel.c +@@ -49,8 +49,10 @@ test_read_line_embedded_nuls (void) + channel = g_io_channel_new_file (filename, "r", &local_error); + g_assert_no_error (local_error); + +- /* Only break on newline characters, not nuls. */ +- g_io_channel_set_line_term (channel, "\n", 1); ++ /* Only break on newline characters, not nuls. ++ * Use length -1 here to exercise glib#2323; the case where length > 0 ++ * is covered in glib/tests/protocol.c. */ ++ g_io_channel_set_line_term (channel, "\n", -1); + g_io_channel_set_encoding (channel, NULL, &local_error); + g_assert_no_error (local_error); + +diff --git a/glib/tests/option-context.c b/glib/tests/option-context.c +index 149d22353..88d2b80d1 100644 +--- a/glib/tests/option-context.c ++++ b/glib/tests/option-context.c +@@ -27,6 +27,8 @@ + #include <string.h> + #include <locale.h> + ++#include "gstrfuncsprivate.h" ++ + static GOptionEntry main_entries[] = { + { "main-switch", 0, 0, + G_OPTION_ARG_NONE, NULL, +@@ -256,7 +258,7 @@ join_stringv (int argc, char **argv) + static char ** + copy_stringv (char **argv, int argc) + { +- return g_memdup (argv, sizeof (char *) * (argc + 1)); ++ return g_memdup2 (argv, sizeof (char *) * (argc + 1)); + } + + static void +@@ -2323,7 +2325,7 @@ test_group_parse (void) + g_option_context_add_group (context, group); + + argv = split_string ("program --test arg1 -f arg2 --group-test arg3 --frob arg4 -z arg5", &argc); +- orig_argv = g_memdup (argv, (argc + 1) * sizeof (char *)); ++ orig_argv = g_memdup2 (argv, (argc + 1) * sizeof (char *)); + + retval = g_option_context_parse (context, &argc, &argv, &error); + +diff --git a/glib/tests/strfuncs.c b/glib/tests/strfuncs.c +index e1f9619c7..d968afff9 100644 +--- a/glib/tests/strfuncs.c ++++ b/glib/tests/strfuncs.c +@@ -32,6 +32,8 @@ + #include <string.h> + #include "glib.h" + ++#include "gstrfuncsprivate.h" ++ + #if defined (_MSC_VER) && (_MSC_VER <= 1800) + #define isnan(x) _isnan(x) + +@@ -219,6 +221,26 @@ test_memdup (void) + g_free (str_dup); + } + ++/* Testing g_memdup2() function with various positive and negative cases */ ++static void ++test_memdup2 (void) ++{ ++ gchar *str_dup = NULL; ++ const gchar *str = "The quick brown fox jumps over the lazy dog"; ++ ++ /* Testing negative cases */ ++ g_assert_null (g_memdup2 (NULL, 1024)); ++ g_assert_null (g_memdup2 (str, 0)); ++ g_assert_null (g_memdup2 (NULL, 0)); ++ ++ /* Testing normal usage cases */ ++ str_dup = g_memdup2 (str, strlen (str) + 1); ++ g_assert_nonnull (str_dup); ++ g_assert_cmpstr (str, ==, str_dup); ++ ++ g_free (str_dup); ++} ++ + /* Testing g_strpcpy() function with various positive and negative cases */ + static void + test_stpcpy (void) +@@ -2523,6 +2545,7 @@ main (int argc, + g_test_add_func ("/strfuncs/has-prefix", test_has_prefix); + g_test_add_func ("/strfuncs/has-suffix", test_has_suffix); + g_test_add_func ("/strfuncs/memdup", test_memdup); ++ g_test_add_func ("/strfuncs/memdup2", test_memdup2); + g_test_add_func ("/strfuncs/stpcpy", test_stpcpy); + g_test_add_func ("/strfuncs/str_match_string", test_str_match_string); + g_test_add_func ("/strfuncs/str_tokenize_and_fold", test_str_tokenize_and_fold); +diff --git a/gobject/gsignal.c b/gobject/gsignal.c +index 45effa92d..effbfec62 100644 +--- a/gobject/gsignal.c ++++ b/gobject/gsignal.c +@@ -28,6 +28,7 @@ + #include <signal.h> + + #include "gsignal.h" ++#include "gstrfuncsprivate.h" + #include "gtype-private.h" + #include "gbsearcharray.h" + #include "gvaluecollector.h" +@@ -1809,7 +1810,7 @@ g_signal_newv (const gchar *signal_name, + node->single_va_closure_is_valid = FALSE; + node->flags = signal_flags & G_SIGNAL_FLAGS_MASK; + node->n_params = n_params; +- node->param_types = g_memdup (param_types, sizeof (GType) * n_params); ++ node->param_types = g_memdup2 (param_types, sizeof (GType) * n_params); + node->return_type = return_type; + node->class_closure_bsa = NULL; + if (accumulator) +diff --git a/gobject/gtype.c b/gobject/gtype.c +index b5ef2d11e..8d152dccc 100644 +--- a/gobject/gtype.c ++++ b/gobject/gtype.c +@@ -33,6 +33,7 @@ + + #include "glib-private.h" + #include "gconstructor.h" ++#include "gstrfuncsprivate.h" + + #ifdef G_OS_WIN32 + #include <windows.h> +@@ -1470,7 +1471,7 @@ type_add_interface_Wm (TypeNode *node, + iholder->next = iface_node_get_holders_L (iface); + iface_node_set_holders_W (iface, iholder); + iholder->instance_type = NODE_TYPE (node); +- iholder->info = info ? g_memdup (info, sizeof (*info)) : NULL; ++ iholder->info = info ? g_memdup2 (info, sizeof (*info)) : NULL; + iholder->plugin = plugin; + + /* create an iface entry for this type */ +@@ -1731,7 +1732,7 @@ type_iface_retrieve_holder_info_Wm (TypeNode *iface, + INVALID_RECURSION ("g_type_plugin_*", iholder->plugin, NODE_NAME (iface)); + + check_interface_info_I (iface, instance_type, &tmp_info); +- iholder->info = g_memdup (&tmp_info, sizeof (tmp_info)); ++ iholder->info = g_memdup2 (&tmp_info, sizeof (tmp_info)); + } + + return iholder; /* we don't modify write lock upon returning NULL */ +@@ -2016,10 +2017,10 @@ type_iface_vtable_base_init_Wm (TypeNode *iface, + IFaceEntry *pentry = type_lookup_iface_entry_L (pnode, iface); + + if (pentry) +- vtable = g_memdup (pentry->vtable, iface->data->iface.vtable_size); ++ vtable = g_memdup2 (pentry->vtable, iface->data->iface.vtable_size); + } + if (!vtable) +- vtable = g_memdup (iface->data->iface.dflt_vtable, iface->data->iface.vtable_size); ++ vtable = g_memdup2 (iface->data->iface.dflt_vtable, iface->data->iface.vtable_size); + entry->vtable = vtable; + vtable->g_type = NODE_TYPE (iface); + vtable->g_instance_type = NODE_TYPE (node); +diff --git a/gobject/gtypemodule.c b/gobject/gtypemodule.c +index 4ecaf8c88..20911fafd 100644 +--- a/gobject/gtypemodule.c ++++ b/gobject/gtypemodule.c +@@ -19,6 +19,7 @@ + + #include <stdlib.h> + ++#include "gstrfuncsprivate.h" + #include "gtypeplugin.h" + #include "gtypemodule.h" + +@@ -436,7 +437,7 @@ g_type_module_register_type (GTypeModule *module, + module_type_info->loaded = TRUE; + module_type_info->info = *type_info; + if (type_info->value_table) +- module_type_info->info.value_table = g_memdup (type_info->value_table, ++ module_type_info->info.value_table = g_memdup2 (type_info->value_table, + sizeof (GTypeValueTable)); + + return module_type_info->type; +diff --git a/gobject/tests/param.c b/gobject/tests/param.c +index 93c3f4b94..0a77e51b7 100644 +--- a/gobject/tests/param.c ++++ b/gobject/tests/param.c +@@ -2,6 +2,8 @@ + #include <glib-object.h> + #include <stdlib.h> + ++#include "gstrfuncsprivate.h" ++ + static void + test_param_value (void) + { +@@ -874,7 +876,7 @@ main (int argc, char *argv[]) + test_path = g_strdup_printf ("/param/implement/subprocess/%d-%d-%d-%d", + data.change_this_flag, data.change_this_type, + data.use_this_flag, data.use_this_type); +- test_data = g_memdup (&data, sizeof (TestParamImplementData)); ++ test_data = g_memdup2 (&data, sizeof (TestParamImplementData)); + g_test_add_data_func_full (test_path, test_data, test_param_implement_child, g_free); + g_free (test_path); + } diff --git a/meta/recipes-core/glib-2.0/glib-2.0_2.64.5.bb b/meta/recipes-core/glib-2.0/glib-2.0_2.64.5.bb index b9462bc945..ed7b649dc6 100644 --- a/meta/recipes-core/glib-2.0/glib-2.0_2.64.5.bb +++ b/meta/recipes-core/glib-2.0/glib-2.0_2.64.5.bb @@ -18,6 +18,7 @@ SRC_URI = "${GNOME_MIRROR}/glib/${SHRT_VER}/glib-${PV}.tar.xz \ file://0001-gio-tests-resources.c-comment-out-a-build-host-only-.patch \ file://tzdata-update.patch \ file://CVE-2020-35457.patch \ + file://CVE-2021-27219.patch \ " SRC_URI_append_class-native = " file://relocate-modules.patch" diff --git a/meta/recipes-core/glib-2.0/glib.inc b/meta/recipes-core/glib-2.0/glib.inc index e48b5cb67b..71777bc459 100644 --- a/meta/recipes-core/glib-2.0/glib.inc +++ b/meta/recipes-core/glib-2.0/glib.inc @@ -34,10 +34,6 @@ DEPENDS_append_class-target = "${@' gtk-doc' if d.getVar('GTKDOC_ENABLED') == 'T GTKDOC_MESON_OPTION = "gtk_doc" -# This avoids the need to depend on target python3, which in case of mingw is not even possible. -# meson's python configuration pokes into python3 configuration, so this provides the native config to it. -unset _PYTHON_SYSCONFIGDATA_NAME - S = "${WORKDIR}/glib-${PV}" PACKAGECONFIG ??= "system-pcre libmount \ diff --git a/meta/recipes-core/glibc/glibc-version.inc b/meta/recipes-core/glibc/glibc-version.inc index 1566056297..84d199bb1d 100644 --- a/meta/recipes-core/glibc/glibc-version.inc +++ b/meta/recipes-core/glibc/glibc-version.inc @@ -1,6 +1,6 @@ SRCBRANCH ?= "release/2.32/master" PV = "2.32" -SRCREV_glibc ?= "3de512be7ea6053255afed6154db9ee31d4e557a" +SRCREV_glibc ?= "44b395932961a29825da4ad025124a6760858d9c" SRCREV_localedef ?= "bd644c9e6f3e20c5504da1488448173c69c56c28" GLIBC_GIT_URI ?= "git://sourceware.org/git/glibc.git" diff --git a/meta/recipes-core/glibc/glibc_2.32.bb b/meta/recipes-core/glibc/glibc_2.32.bb index b850c28c78..03aea52508 100644 --- a/meta/recipes-core/glibc/glibc_2.32.bb +++ b/meta/recipes-core/glibc/glibc_2.32.bb @@ -1,7 +1,8 @@ require glibc.inc require glibc-version.inc -CVE_CHECK_WHITELIST += "CVE-2020-10029" +# whitelist CVE's with fixes in latest release/2.32/master branch +CVE_CHECK_WHITELIST += "CVE-2019-25013 CVE-2020-10029 CVE-2020-27618 CVE-2021-27645 CVE-2021-3326" DEPENDS += "gperf-native bison-native make-native" diff --git a/meta/recipes-core/images/build-appliance-image_15.0.0.bb b/meta/recipes-core/images/build-appliance-image_15.0.0.bb index 7f87c065db..9e944a2534 100644 --- a/meta/recipes-core/images/build-appliance-image_15.0.0.bb +++ b/meta/recipes-core/images/build-appliance-image_15.0.0.bb @@ -22,9 +22,9 @@ APPEND += "rootfstype=ext4 quiet" DEPENDS = "zip-native python3-pip-native" IMAGE_FSTYPES = "wic.vmdk" -inherit core-image module-base setuptools3 +inherit core-image setuptools3 -SRCREV ?= "76dac9d657f3b2864dec3bfcd2ee392fafdcdfe6" +SRCREV ?= "79c4792da2b400431c09d9a2f53efd4443812281" SRC_URI = "git://git.yoctoproject.org/poky;branch=gatesgarth \ file://Yocto_Build_Appliance.vmx \ file://Yocto_Build_Appliance.vmxf \ @@ -61,12 +61,6 @@ fakeroot do_populate_poky_src () { # Place the README_VirtualBox_Toaster file in builders home folder. cp ${WORKDIR}/README_VirtualBox_Toaster.txt ${IMAGE_ROOTFS}/home/builder/ - # Create a symlink, needed for out-of-tree kernel modules build - if [ ! -e ${IMAGE_ROOTFS}/lib/modules/${KERNEL_VERSION}/build ]; then - rm -f ${IMAGE_ROOTFS}/lib/modules/${KERNEL_VERSION}/build - lnr ${IMAGE_ROOTFS}${KERNEL_SRC_PATH} ${IMAGE_ROOTFS}/lib/modules/${KERNEL_VERSION}/build - fi - echo "INHERIT += \"rm_work\"" >> ${IMAGE_ROOTFS}/home/builder/poky/build/conf/auto.conf echo "export LC_ALL=en_US.utf8" >> ${IMAGE_ROOTFS}/home/builder/.bashrc diff --git a/meta/recipes-core/initrdscripts/files/init-install-efi.sh b/meta/recipes-core/initrdscripts/files/init-install-efi.sh index b6855b5aac..f667518b89 100644 --- a/meta/recipes-core/initrdscripts/files/init-install-efi.sh +++ b/meta/recipes-core/initrdscripts/files/init-install-efi.sh @@ -279,6 +279,11 @@ fi umount /tgt_root +# copy any extra files needed for ESP +if [ -d /run/media/$1/esp ]; then + cp -r /run/media/$1/esp/* /boot +fi + # Copy kernel artifacts. To add more artifacts just add to types # For now just support kernel types already being used by something in OE-core for types in bzImage zImage vmlinux vmlinuz fitImage; do diff --git a/meta/recipes-core/meta/buildtools-extended-tarball.bb b/meta/recipes-core/meta/buildtools-extended-tarball.bb index 0816486754..83e3fddccc 100644 --- a/meta/recipes-core/meta/buildtools-extended-tarball.bb +++ b/meta/recipes-core/meta/buildtools-extended-tarball.bb @@ -28,11 +28,21 @@ TOOLCHAIN_HOST_TASK += "\ nativesdk-libtool \ nativesdk-pkgconfig \ nativesdk-glibc-utils \ + nativesdk-glibc-gconv-ibm850 \ + nativesdk-glibc-gconv-iso8859-1 \ + nativesdk-glibc-gconv-utf-16 \ + nativesdk-glibc-gconv-cp1250 \ + nativesdk-glibc-gconv-cp1251 \ + nativesdk-glibc-gconv-cp1252 \ + nativesdk-glibc-gconv-euc-jp \ + nativesdk-glibc-gconv-libjis \ nativesdk-libxcrypt-dev \ nativesdk-parted \ nativesdk-dosfstools \ nativesdk-gptfdisk \ " +# gconv-cp1250, cp1251 and euc-jp needed for iconv to work in vim builds +# also copied list from uninative TOOLCHAIN_OUTPUTNAME = "${SDK_ARCH}-buildtools-extended-nativesdk-standalone-${DISTRO_VERSION}" diff --git a/meta/recipes-core/meta/cve-update-db-native.bb b/meta/recipes-core/meta/cve-update-db-native.bb index cf62e1e32c..b073936298 100644 --- a/meta/recipes-core/meta/cve-update-db-native.bb +++ b/meta/recipes-core/meta/cve-update-db-native.bb @@ -138,14 +138,24 @@ def parse_node_and_insert(c, node, cveId): for cpe in node.get('cpe_match', ()): if not cpe['vulnerable']: return - cpe23 = cpe['cpe23Uri'].split(':') + cpe23 = cpe.get('cpe23Uri') + if not cpe23: + return + cpe23 = cpe23.split(':') + if len(cpe23) < 6: + return vendor = cpe23[3] product = cpe23[4] version = cpe23[5] + if cpe23[6] == '*' or cpe23[6] == '-': + version_suffix = "" + else: + version_suffix = "_" + cpe23[6] + if version != '*' and version != '-': # Version is defined, this is a '=' match - yield [cveId, vendor, product, version, '=', '', ''] + yield [cveId, vendor, product, version + version_suffix, '=', '', ''] elif version == '-': # no version information is available yield [cveId, vendor, product, version, '', '', ''] diff --git a/meta/recipes-core/ncurses/ncurses.inc b/meta/recipes-core/ncurses/ncurses.inc index fe4e8a5d6e..ef59bc3b0a 100644 --- a/meta/recipes-core/ncurses/ncurses.inc +++ b/meta/recipes-core/ncurses/ncurses.inc @@ -324,3 +324,8 @@ FILES_${PN}-terminfo-base = "\ RSUGGESTS_${PN}-libtinfo = "${PN}-terminfo" RRECOMMENDS_${PN}-libtinfo = "${PN}-terminfo-base" + +# Putting terminfo into the sysroot adds around 2800 files to +# each recipe specific sysroot. We can live without this, particularly +# as many recipes may have native and target copies. +SYSROOT_DIRS_remove = "${datadir}" diff --git a/meta/recipes-core/ovmf/ovmf-shell-image.bb b/meta/recipes-core/ovmf/ovmf-shell-image.bb index 0d2b8bf52f..fd4fb5b732 100644 --- a/meta/recipes-core/ovmf/ovmf-shell-image.bb +++ b/meta/recipes-core/ovmf/ovmf-shell-image.bb @@ -1,4 +1,5 @@ DESCRIPTION = "boot image with UEFI shell and tools" +COMPATIBLE_HOST_class-target='(i.86|x86_64).*' # For this image recipe, only the wic format with a # single vfat partition makes sense. Because we have no diff --git a/meta/recipes-core/systemd/systemd-boot_246.2.bb b/meta/recipes-core/systemd/systemd-boot_246.9.bb index f92c639810..f92c639810 100644 --- a/meta/recipes-core/systemd/systemd-boot_246.2.bb +++ b/meta/recipes-core/systemd/systemd-boot_246.9.bb diff --git a/meta/recipes-core/systemd/systemd-conf/wired.network b/meta/recipes-core/systemd/systemd-conf/wired.network index dcf3534596..06d00ea1ba 100644 --- a/meta/recipes-core/systemd/systemd-conf/wired.network +++ b/meta/recipes-core/systemd/systemd-conf/wired.network @@ -1,6 +1,7 @@ [Match] Name=en* eth* KernelCommandLine=!nfsroot +KernelCommandLine=!ip [Network] DHCP=yes diff --git a/meta/recipes-core/systemd/systemd-conf_246.1.bb b/meta/recipes-core/systemd/systemd-conf_246.9.bb index d9ec023bfd..9b797a91f4 100644 --- a/meta/recipes-core/systemd/systemd-conf_246.1.bb +++ b/meta/recipes-core/systemd/systemd-conf_246.9.bb @@ -23,9 +23,6 @@ do_install() { # Based on change from YP bug 8141, OE commit 5196d7bacaef1076c361adaa2867be31759c1b52 do_install_append_qemuall() { install -D -m0644 ${WORKDIR}/system.conf-qemuall ${D}${systemd_unitdir}/system.conf.d/01-${PN}.conf - - # Do not install wired.network for qemu bsps - rm -rf ${D}${systemd_unitdir}/network } PACKAGE_ARCH = "${MACHINE_ARCH}" diff --git a/meta/recipes-core/systemd/systemd.inc b/meta/recipes-core/systemd/systemd.inc index 1733565fc0..b0f8a72bbe 100644 --- a/meta/recipes-core/systemd/systemd.inc +++ b/meta/recipes-core/systemd/systemd.inc @@ -14,7 +14,7 @@ LICENSE = "GPLv2 & LGPLv2.1" LIC_FILES_CHKSUM = "file://LICENSE.GPL2;md5=751419260aa954499f7abaabaa882bbe \ file://LICENSE.LGPL2.1;md5=4fbd65380cdd255951079008b364516c" -SRCREV = "2ee1c57c4ff4fd3349cf03c2e89fbd18ca0b3a4a" +SRCREV = "90f7f6c5777e9e2a4990f299474f730459054bf4" SRCBRANCH = "v246-stable" SRC_URI = "git://github.com/systemd/systemd-stable.git;protocol=git;branch=${SRCBRANCH}" diff --git a/meta/recipes-core/systemd/systemd/0001-binfmt-Don-t-install-dependency-links-at-install-tim.patch b/meta/recipes-core/systemd/systemd/0001-binfmt-Don-t-install-dependency-links-at-install-tim.patch index 2676c144f2..643b9547b7 100644 --- a/meta/recipes-core/systemd/systemd/0001-binfmt-Don-t-install-dependency-links-at-install-tim.patch +++ b/meta/recipes-core/systemd/systemd/0001-binfmt-Don-t-install-dependency-links-at-install-tim.patch @@ -1,4 +1,4 @@ -From 564830719be2017c4953589d50f21a9e856a4ecc Mon Sep 17 00:00:00 2001 +From ad5b89a366785d8a19ba970f5b0c97b4de848fa3 Mon Sep 17 00:00:00 2001 From: Chen Qi <Qi.Chen@windriver.com> Date: Thu, 21 Feb 2019 16:23:24 +0800 Subject: [PATCH] binfmt: Don't install dependency links at install time for @@ -18,17 +18,16 @@ Signed-off-by: Khem Raj <raj.khem@gmail.com> Signed-off-by: Chen Qi <Qi.Chen@windriver.com> [rebased for systemd 243] Signed-off-by: Scott Murray <scott.murray@konsulko.com> - --- units/meson.build | 6 ++---- units/proc-sys-fs-binfmt_misc.automount | 3 +++ units/systemd-binfmt.service.in | 4 ++++ 3 files changed, 9 insertions(+), 4 deletions(-) -Index: systemd-stable/units/meson.build -=================================================================== ---- systemd-stable.orig/units/meson.build -+++ systemd-stable/units/meson.build +diff --git a/units/meson.build b/units/meson.build +index 031237c..0d43bdb 100644 +--- a/units/meson.build ++++ b/units/meson.build @@ -54,8 +54,7 @@ units = [ ['poweroff.target', '', (with_runlevels ? 'runlevel0.target' : '')], @@ -38,8 +37,8 @@ Index: systemd-stable/units/meson.build + ['proc-sys-fs-binfmt_misc.automount', 'ENABLE_BINFMT'], ['proc-sys-fs-binfmt_misc.mount', 'ENABLE_BINFMT'], ['reboot.target', '', - (with_runlevels ? 'runlevel6.target ctrl-alt-del.target' : 'ctrl-alt-del.target')], -@@ -162,8 +161,7 @@ in_units = [ + 'ctrl-alt-del.target' + (with_runlevels ? ' runlevel6.target' : '')], +@@ -164,8 +163,7 @@ in_units = [ ['rc-local.service', 'HAVE_SYSV_COMPAT'], ['rescue.service', ''], ['systemd-backlight@.service', 'ENABLE_BACKLIGHT'], @@ -49,10 +48,10 @@ Index: systemd-stable/units/meson.build ['systemd-bless-boot.service', 'ENABLE_EFI HAVE_BLKID'], ['systemd-boot-check-no-failures.service', ''], ['systemd-coredump@.service', 'ENABLE_COREDUMP'], -Index: systemd-stable/units/proc-sys-fs-binfmt_misc.automount -=================================================================== ---- systemd-stable.orig/units/proc-sys-fs-binfmt_misc.automount -+++ systemd-stable/units/proc-sys-fs-binfmt_misc.automount +diff --git a/units/proc-sys-fs-binfmt_misc.automount b/units/proc-sys-fs-binfmt_misc.automount +index 30a6bc9..4231f3b 100644 +--- a/units/proc-sys-fs-binfmt_misc.automount ++++ b/units/proc-sys-fs-binfmt_misc.automount @@ -18,3 +18,6 @@ ConditionPathIsReadWrite=/proc/sys/ [Automount] @@ -60,11 +59,11 @@ Index: systemd-stable/units/proc-sys-fs-binfmt_misc.automount + +[Install] +WantedBy=sysinit.target -Index: systemd-stable/units/systemd-binfmt.service.in -=================================================================== ---- systemd-stable.orig/units/systemd-binfmt.service.in -+++ systemd-stable/units/systemd-binfmt.service.in -@@ -14,6 +14,7 @@ Documentation=https://www.kernel.org/doc +diff --git a/units/systemd-binfmt.service.in b/units/systemd-binfmt.service.in +index e54e95e..372a598 100644 +--- a/units/systemd-binfmt.service.in ++++ b/units/systemd-binfmt.service.in +@@ -14,6 +14,7 @@ Documentation=https://www.kernel.org/doc/html/latest/admin-guide/binfmt-misc.htm Documentation=https://www.freedesktop.org/wiki/Software/systemd/APIFileSystems DefaultDependencies=no Conflicts=shutdown.target @@ -79,3 +78,6 @@ Index: systemd-stable/units/systemd-binfmt.service.in + +[Install] +WantedBy=sysinit.target +-- +2.7.4 + diff --git a/meta/recipes-core/systemd/systemd/0001-logind-Restore-chvt-as-non-root-user-without-polkit.patch b/meta/recipes-core/systemd/systemd/0001-logind-Restore-chvt-as-non-root-user-without-polkit.patch new file mode 100644 index 0000000000..89ef39bc3e --- /dev/null +++ b/meta/recipes-core/systemd/systemd/0001-logind-Restore-chvt-as-non-root-user-without-polkit.patch @@ -0,0 +1,227 @@ +From 150d9cade6d475570395cb418b824524dead9577 Mon Sep 17 00:00:00 2001 +From: Joshua Watt <JPEWhacker@gmail.com> +Date: Fri, 30 Oct 2020 08:15:43 -0500 +Subject: [PATCH] logind: Restore chvt as non-root user without polkit + +4acf0cfd2f ("logind: check PolicyKit before allowing VT switch") broke +the ability to write user sessions that run graphical sessions (e.g. +weston/X11). This was partially amended in 19bb87fbfa ("login: allow +non-console sessions to change vt") by changing the default PolicyKit +policy so that non-root users are again allowed to switch the VT. This +makes the policy when PolKit is not enabled (as on many embedded +systems) match the default PolKit policy and allows launching graphical +sessions as a non-root user. + +Closes #17473 +--- + src/login/logind-dbus.c | 11 ++------- + src/login/logind-polkit.c | 26 +++++++++++++++++++++ + src/login/logind-polkit.h | 10 ++++++++ + src/login/logind-seat-dbus.c | 41 ++++----------------------------- + src/login/logind-session-dbus.c | 11 ++------- + src/login/meson.build | 1 + + 6 files changed, 46 insertions(+), 54 deletions(-) + create mode 100644 src/login/logind-polkit.c + create mode 100644 src/login/logind-polkit.h + +diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c +index 0f83ed99bc..a3765d88ba 100644 +--- a/src/login/logind-dbus.c ++++ b/src/login/logind-dbus.c +@@ -30,6 +30,7 @@ + #include "format-util.h" + #include "fs-util.h" + #include "logind-dbus.h" ++#include "logind-polkit.h" + #include "logind-seat-dbus.h" + #include "logind-session-dbus.h" + #include "logind-user-dbus.h" +@@ -1047,15 +1048,7 @@ static int method_activate_session_on_seat(sd_bus_message *message, void *userda + return sd_bus_error_setf(error, BUS_ERROR_SESSION_NOT_ON_SEAT, + "Session %s not on seat %s", session_name, seat_name); + +- r = bus_verify_polkit_async( +- message, +- CAP_SYS_ADMIN, +- "org.freedesktop.login1.chvt", +- NULL, +- false, +- UID_INVALID, +- &m->polkit_registry, +- error); ++ r = check_polkit_chvt(message, m, error); + if (r < 0) + return r; + if (r == 0) +diff --git a/src/login/logind-polkit.c b/src/login/logind-polkit.c +new file mode 100644 +index 0000000000..9072570cc6 +--- /dev/null ++++ b/src/login/logind-polkit.c +@@ -0,0 +1,26 @@ ++/* SPDX-License-Identifier: LGPL-2.1+ */ ++ ++#include "bus-polkit.h" ++#include "logind-polkit.h" ++#include "missing_capability.h" ++#include "user-util.h" ++ ++int check_polkit_chvt(sd_bus_message *message, Manager *manager, sd_bus_error *error) { ++#if ENABLE_POLKIT ++ return bus_verify_polkit_async( ++ message, ++ CAP_SYS_ADMIN, ++ "org.freedesktop.login1.chvt", ++ NULL, ++ false, ++ UID_INVALID, ++ &manager->polkit_registry, ++ error); ++#else ++ /* Allow chvt when polkit is not present. This allows a service to start a graphical session as a ++ * non-root user when polkit is not compiled in, matching the default polkit policy */ ++ return 1; ++#endif ++} ++ ++ +diff --git a/src/login/logind-polkit.h b/src/login/logind-polkit.h +new file mode 100644 +index 0000000000..476c077a8a +--- /dev/null ++++ b/src/login/logind-polkit.h +@@ -0,0 +1,10 @@ ++/* SPDX-License-Identifier: LGPL-2.1+ */ ++#pragma once ++ ++#include "sd-bus.h" ++ ++#include "bus-object.h" ++#include "logind.h" ++ ++int check_polkit_chvt(sd_bus_message *message, Manager *manager, sd_bus_error *error); ++ +diff --git a/src/login/logind-seat-dbus.c b/src/login/logind-seat-dbus.c +index a945132284..f22e9e2734 100644 +--- a/src/login/logind-seat-dbus.c ++++ b/src/login/logind-seat-dbus.c +@@ -9,6 +9,7 @@ + #include "bus-polkit.h" + #include "bus-util.h" + #include "logind-dbus.h" ++#include "logind-polkit.h" + #include "logind-seat-dbus.h" + #include "logind-seat.h" + #include "logind-session-dbus.h" +@@ -179,15 +180,7 @@ static int method_activate_session(sd_bus_message *message, void *userdata, sd_b + if (session->seat != s) + return sd_bus_error_setf(error, BUS_ERROR_SESSION_NOT_ON_SEAT, "Session %s not on seat %s", name, s->id); + +- r = bus_verify_polkit_async( +- message, +- CAP_SYS_ADMIN, +- "org.freedesktop.login1.chvt", +- NULL, +- false, +- UID_INVALID, +- &s->manager->polkit_registry, +- error); ++ r = check_polkit_chvt(message, s->manager, error); + if (r < 0) + return r; + if (r == 0) +@@ -215,15 +208,7 @@ static int method_switch_to(sd_bus_message *message, void *userdata, sd_bus_erro + if (to <= 0) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid virtual terminal"); + +- r = bus_verify_polkit_async( +- message, +- CAP_SYS_ADMIN, +- "org.freedesktop.login1.chvt", +- NULL, +- false, +- UID_INVALID, +- &s->manager->polkit_registry, +- error); ++ r = check_polkit_chvt(message, s->manager, error); + if (r < 0) + return r; + if (r == 0) +@@ -243,15 +228,7 @@ static int method_switch_to_next(sd_bus_message *message, void *userdata, sd_bus + assert(message); + assert(s); + +- r = bus_verify_polkit_async( +- message, +- CAP_SYS_ADMIN, +- "org.freedesktop.login1.chvt", +- NULL, +- false, +- UID_INVALID, +- &s->manager->polkit_registry, +- error); ++ r = check_polkit_chvt(message, s->manager, error); + if (r < 0) + return r; + if (r == 0) +@@ -271,15 +248,7 @@ static int method_switch_to_previous(sd_bus_message *message, void *userdata, sd + assert(message); + assert(s); + +- r = bus_verify_polkit_async( +- message, +- CAP_SYS_ADMIN, +- "org.freedesktop.login1.chvt", +- NULL, +- false, +- UID_INVALID, +- &s->manager->polkit_registry, +- error); ++ r = check_polkit_chvt(message, s->manager, error); + if (r < 0) + return r; + if (r == 0) +diff --git a/src/login/logind-session-dbus.c b/src/login/logind-session-dbus.c +index ccc5ac8df2..57c8a4e900 100644 +--- a/src/login/logind-session-dbus.c ++++ b/src/login/logind-session-dbus.c +@@ -11,6 +11,7 @@ + #include "fd-util.h" + #include "logind-brightness.h" + #include "logind-dbus.h" ++#include "logind-polkit.h" + #include "logind-seat-dbus.h" + #include "logind-session-dbus.h" + #include "logind-session-device.h" +@@ -192,15 +193,7 @@ int bus_session_method_activate(sd_bus_message *message, void *userdata, sd_bus_ + assert(message); + assert(s); + +- r = bus_verify_polkit_async( +- message, +- CAP_SYS_ADMIN, +- "org.freedesktop.login1.chvt", +- NULL, +- false, +- UID_INVALID, +- &s->manager->polkit_registry, +- error); ++ r = check_polkit_chvt(message, s->manager, error); + if (r < 0) + return r; + if (r == 0) +diff --git a/src/login/meson.build b/src/login/meson.build +index 0a7d3d5440..7e46be2add 100644 +--- a/src/login/meson.build ++++ b/src/login/meson.build +@@ -26,6 +26,7 @@ liblogind_core_sources = files(''' + logind-device.h + logind-inhibit.c + logind-inhibit.h ++ logind-polkit.c + logind-seat-dbus.c + logind-seat-dbus.h + logind-seat.c +-- +2.28.0 + diff --git a/meta/recipes-core/systemd/systemd/0002-don-t-use-glibc-specific-qsort_r.patch b/meta/recipes-core/systemd/systemd/0002-don-t-use-glibc-specific-qsort_r.patch index 30fe9a14df..3be5095f07 100644 --- a/meta/recipes-core/systemd/systemd/0002-don-t-use-glibc-specific-qsort_r.patch +++ b/meta/recipes-core/systemd/systemd/0002-don-t-use-glibc-specific-qsort_r.patch @@ -1,4 +1,4 @@ -From 3eb12a6ba0bce149717eaabeb1505d379b3d705a Mon Sep 17 00:00:00 2001 +From 263e4100a849f28f62fcfcc1456e9e6de8ee836b Mon Sep 17 00:00:00 2001 From: Chen Qi <Qi.Chen@windriver.com> Date: Mon, 25 Feb 2019 13:41:41 +0800 Subject: [PATCH] don't use glibc-specific qsort_r @@ -12,16 +12,16 @@ Signed-off-by: Chen Qi <Qi.Chen@windriver.com> Signed-off-by: Andrej Valek <andrej.valek@siemens.com> --- - src/basic/sort-util.h | 14 ------------ - src/libsystemd/sd-hwdb/hwdb-util.c | 19 +++++++++++----- - src/shared/format-table.c | 36 ++++++++++++++++++++---------- + src/basic/sort-util.h | 14 -------------- + src/libsystemd/sd-hwdb/hwdb-util.c | 19 ++++++++++++++----- + src/shared/format-table.c | 36 ++++++++++++++++++++++++------------ 3 files changed, 38 insertions(+), 31 deletions(-) -Index: systemd-stable/src/basic/sort-util.h -=================================================================== ---- systemd-stable.orig/src/basic/sort-util.h -+++ systemd-stable/src/basic/sort-util.h -@@ -54,17 +54,3 @@ static inline void _qsort_safe(void *bas +diff --git a/src/basic/sort-util.h b/src/basic/sort-util.h +index a8dc3bb..9541061 100644 +--- a/src/basic/sort-util.h ++++ b/src/basic/sort-util.h +@@ -54,17 +54,3 @@ static inline void _qsort_safe(void *base, size_t nmemb, size_t size, __compar_f int (*_func_)(const typeof(p[0])*, const typeof(p[0])*) = func; \ _qsort_safe((p), (n), sizeof((p)[0]), (__compar_fn_t) _func_); \ }) @@ -39,11 +39,11 @@ Index: systemd-stable/src/basic/sort-util.h - int (*_func_)(const typeof(p[0])*, const typeof(p[0])*, typeof(userdata)) = func; \ - qsort_r_safe((p), (n), sizeof((p)[0]), (__compar_d_fn_t) _func_, userdata); \ - }) -Index: systemd-stable/src/libsystemd/sd-hwdb/hwdb-util.c -=================================================================== ---- systemd-stable.orig/src/libsystemd/sd-hwdb/hwdb-util.c -+++ systemd-stable/src/libsystemd/sd-hwdb/hwdb-util.c -@@ -128,9 +128,13 @@ static void trie_free(struct trie *trie) +diff --git a/src/libsystemd/sd-hwdb/hwdb-util.c b/src/libsystemd/sd-hwdb/hwdb-util.c +index 5c75216..3986fc8 100644 +--- a/src/libsystemd/sd-hwdb/hwdb-util.c ++++ b/src/libsystemd/sd-hwdb/hwdb-util.c +@@ -128,9 +128,13 @@ static void trie_free(struct trie *trie) { DEFINE_TRIVIAL_CLEANUP_FUNC(struct trie*, trie_free); @@ -60,7 +60,7 @@ Index: systemd-stable/src/libsystemd/sd-hwdb/hwdb-util.c } static int trie_node_add_value(struct trie *trie, struct trie_node *node, -@@ -158,7 +162,10 @@ static int trie_node_add_value(struct tr +@@ -158,7 +162,10 @@ static int trie_node_add_value(struct trie *trie, struct trie_node *node, .value_off = v, }; @@ -72,7 +72,7 @@ Index: systemd-stable/src/libsystemd/sd-hwdb/hwdb-util.c if (val) { /* At this point we have 2 identical properties on the same match-string. * Since we process files in order, we just replace the previous value. */ -@@ -184,7 +191,9 @@ static int trie_node_add_value(struct tr +@@ -184,7 +191,9 @@ static int trie_node_add_value(struct trie *trie, struct trie_node *node, .line_number = line_number, }; node->values_count++; @@ -83,11 +83,11 @@ Index: systemd-stable/src/libsystemd/sd-hwdb/hwdb-util.c return 0; } -Index: systemd-stable/src/shared/format-table.c -=================================================================== ---- systemd-stable.orig/src/shared/format-table.c -+++ systemd-stable/src/shared/format-table.c -@@ -1246,31 +1246,33 @@ static int cell_data_compare(TableData * +diff --git a/src/shared/format-table.c b/src/shared/format-table.c +index 612402c..04638b2 100644 +--- a/src/shared/format-table.c ++++ b/src/shared/format-table.c +@@ -1243,30 +1243,32 @@ static int cell_data_compare(TableData *a, size_t index_a, TableData *b, size_t return CMP(index_a, index_b); } @@ -95,7 +95,6 @@ Index: systemd-stable/src/shared/format-table.c +static Table *user_table; +static int table_data_compare(const void *x, const void *y) { + const size_t *a = x, *b=y; - size_t i; int r; - assert(t); @@ -115,8 +114,8 @@ Index: systemd-stable/src/shared/format-table.c return 1; /* Order other lines by the sorting map */ -- for (i = 0; i < t->n_sort_map; i++) { -+ for (i = 0; i < user_table->n_sort_map; i++) { +- for (size_t i = 0; i < t->n_sort_map; i++) { ++ for (size_t i = 0; i < user_table->n_sort_map; i++) { TableData *d, *dd; - d = t->data[*a + t->sort_map[i]]; @@ -131,8 +130,8 @@ Index: systemd-stable/src/shared/format-table.c } /* Order identical lines by the order there were originally added in */ -@@ -1798,7 +1800,12 @@ int table_print(Table *t, FILE *f) { - for (i = 0; i < n_rows; i++) +@@ -1844,7 +1846,12 @@ int table_print(Table *t, FILE *f) { + for (size_t i = 0; i < n_rows; i++) sorted[i] = i * t->n_columns; - typesafe_qsort_r(sorted, n_rows, table_data_compare, t); @@ -145,8 +144,8 @@ Index: systemd-stable/src/shared/format-table.c } if (t->display_map) -@@ -2375,7 +2382,12 @@ int table_to_json(Table *t, JsonVariant - for (i = 0; i < n_rows; i++) +@@ -2440,7 +2447,12 @@ int table_to_json(Table *t, JsonVariant **ret) { + for (size_t i = 0; i < n_rows; i++) sorted[i] = i * t->n_columns; - typesafe_qsort_r(sorted, n_rows, table_data_compare, t); diff --git a/meta/recipes-core/systemd/systemd_246.6.bb b/meta/recipes-core/systemd/systemd_246.9.bb index 9215adf8dc..6524b8216a 100644 --- a/meta/recipes-core/systemd/systemd_246.6.bb +++ b/meta/recipes-core/systemd/systemd_246.9.bb @@ -21,6 +21,7 @@ SRC_URI += "file://touchscreen.rules \ file://0001-binfmt-Don-t-install-dependency-links-at-install-tim.patch \ file://0003-implment-systemd-sysv-install-for-OE.patch \ file://0001-systemd.pc.in-use-ROOTPREFIX-without-suffixed-slash.patch \ + file://0001-logind-Restore-chvt-as-non-root-user-without-polkit.patch \ " # patches needed by musl @@ -134,7 +135,7 @@ PACKAGECONFIG[hibernate] = "-Dhibernate=true,-Dhibernate=false" PACKAGECONFIG[hostnamed] = "-Dhostnamed=true,-Dhostnamed=false" PACKAGECONFIG[idn] = "-Didn=true,-Didn=false" PACKAGECONFIG[ima] = "-Dima=true,-Dima=false" -# importd requires curl/xz/zlib/bzip2/gcrypt +# importd requires journal-upload/xz/zlib/bzip2/gcrypt PACKAGECONFIG[importd] = "-Dimportd=true,-Dimportd=false" # Update NAT firewall rules PACKAGECONFIG[iptc] = "-Dlibiptc=true,-Dlibiptc=false,iptables" @@ -357,15 +358,15 @@ USERADD_PACKAGES = "${PN} ${PN}-extra-utils \ ${@bb.utils.contains('PACKAGECONFIG', 'journal-upload', '${PN}-journal-upload', '', d)} \ " GROUPADD_PARAM_${PN} = "-r systemd-journal" -USERADD_PARAM_${PN} += "${@bb.utils.contains('PACKAGECONFIG', 'coredump', '--system -d / -M --shell /bin/nologin systemd-coredump;', '', d)}" -USERADD_PARAM_${PN} += "${@bb.utils.contains('PACKAGECONFIG', 'networkd', '--system -d / -M --shell /bin/nologin systemd-network;', '', d)}" +USERADD_PARAM_${PN} += "${@bb.utils.contains('PACKAGECONFIG', 'coredump', '--system -d / -M --shell /sbin/nologin systemd-coredump;', '', d)}" +USERADD_PARAM_${PN} += "${@bb.utils.contains('PACKAGECONFIG', 'networkd', '--system -d / -M --shell /sbin/nologin systemd-network;', '', d)}" USERADD_PARAM_${PN} += "${@bb.utils.contains('PACKAGECONFIG', 'polkit', '--system --no-create-home --user-group --home-dir ${sysconfdir}/polkit-1 polkitd;', '', d)}" -USERADD_PARAM_${PN} += "${@bb.utils.contains('PACKAGECONFIG', 'resolved', '--system -d / -M --shell /bin/nologin systemd-resolve;', '', d)}" -USERADD_PARAM_${PN} += "${@bb.utils.contains('PACKAGECONFIG', 'timesyncd', '--system -d / -M --shell /bin/nologin systemd-timesync;', '', d)}" -USERADD_PARAM_${PN}-extra-utils = "--system -d / -M --shell /bin/nologin systemd-bus-proxy" -USERADD_PARAM_${PN}-journal-gateway = "--system -d / -M --shell /bin/nologin systemd-journal-gateway" -USERADD_PARAM_${PN}-journal-remote = "--system -d / -M --shell /bin/nologin systemd-journal-remote" -USERADD_PARAM_${PN}-journal-upload = "--system -d / -M --shell /bin/nologin systemd-journal-upload" +USERADD_PARAM_${PN} += "${@bb.utils.contains('PACKAGECONFIG', 'resolved', '--system -d / -M --shell /sbin/nologin systemd-resolve;', '', d)}" +USERADD_PARAM_${PN} += "${@bb.utils.contains('PACKAGECONFIG', 'timesyncd', '--system -d / -M --shell /sbin/nologin systemd-timesync;', '', d)}" +USERADD_PARAM_${PN}-extra-utils = "--system -d / -M --shell /sbin/nologin systemd-bus-proxy" +USERADD_PARAM_${PN}-journal-gateway = "--system -d / -M --shell /sbin/nologin systemd-journal-gateway" +USERADD_PARAM_${PN}-journal-remote = "--system -d / -M --shell /sbin/nologin systemd-journal-remote" +USERADD_PARAM_${PN}-journal-upload = "--system -d / -M --shell /sbin/nologin systemd-journal-upload" FILES_${PN}-analyze = "${bindir}/systemd-analyze" |