浏览代码

uml: add Kernel 5.15 support via testing

Add the latest default Kernel for testing.

Signed-off-by: Christian Lamparter <[email protected]>
Christian Lamparter 3 年之前
父节点
当前提交
e2f0821b5a

+ 1 - 0
target/linux/uml/Makefile

@@ -14,6 +14,7 @@ BOARDNAME:=User Mode Linux
 FEATURES:=audio ext4 rootfs-part squashfs
 FEATURES:=audio ext4 rootfs-part squashfs
 
 
 KERNEL_PATCHVER:=5.10
 KERNEL_PATCHVER:=5.10
+KERNEL_TESTING_PATCHVER:=5.15
 
 
 include $(INCLUDE_DIR)/target.mk
 include $(INCLUDE_DIR)/target.mk
 
 

+ 1 - 1
target/linux/uml/README.md

@@ -28,7 +28,7 @@ console prompt. If you would like it in xterms, substitute `con=xterm` and
 `con0=xterm`. **No networking is configured** but it's a starting point. The
 `con0=xterm`. **No networking is configured** but it's a starting point. The
 resulting file system has just enough free space to start kicking the tires and
 resulting file system has just enough free space to start kicking the tires and
 playing in the world of 'embedded routers' along with all the resource
 playing in the world of 'embedded routers' along with all the resource
-restrictions that come with that world.  
+restrictions that come with that world.
 
 
 To configure networking and more refer to the *user mode linux* documentation
 To configure networking and more refer to the *user mode linux* documentation
 online. A quick start goes along this line. Install the `uml-utilities`
 online. A quick start goes along this line. Install the `uml-utilities`

+ 141 - 0
target/linux/uml/config-5.15

@@ -0,0 +1,141 @@
+CONFIG_3_LEVEL_PGTABLES=y
+CONFIG_64BIT=y
+CONFIG_ARCH_DMA_ADDR_T_64BIT=y
+CONFIG_ARCH_EPHEMERAL_INODES=y
+CONFIG_ARCH_NO_PREEMPT=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_BLK_DEV_COW_COMMON=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_UBD=y
+CONFIG_BLK_DEV_UBD_SYNC=y
+CONFIG_BLK_MQ_VIRTIO=y
+CONFIG_CDROM=y
+# CONFIG_COMMON_CLK is not set
+# CONFIG_COMPAT_32BIT_TIME is not set
+CONFIG_CON_CHAN="xterm"
+CONFIG_CON_ZERO_CHAN="fd:0,fd:1"
+CONFIG_CPU_SUP_AMD=y
+CONFIG_CPU_SUP_CENTAUR=y
+CONFIG_CPU_SUP_HYGON=y
+CONFIG_CPU_SUP_INTEL=y
+CONFIG_CPU_SUP_ZHAOXIN=y
+CONFIG_CRC16=y
+CONFIG_CRYPTO_BLAKE2S=y
+CONFIG_CRYPTO_CRC32=y
+CONFIG_CRYPTO_CRC32C=y
+CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y
+CONFIG_CRYPTO_LIB_POLY1305_RSIZE=11
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_SHA1=y
+# CONFIG_CRYPTO_TWOFISH_X86_64 is not set
+CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_DECOMPRESS_BZIP2=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DNOTIFY=y
+# CONFIG_EARLY_PRINTK is not set
+CONFIG_EXT4_FS=y
+CONFIG_F2FS_FS=y
+CONFIG_FAILOVER=y
+CONFIG_FS_IOMAP=y
+CONFIG_FS_MBCACHE=y
+CONFIG_FW_LOADER_PAGED_BUF=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+# CONFIG_GENERIC_CPU is not set
+CONFIG_GENERIC_CPU_DEVICES=y
+CONFIG_GENERIC_FIND_FIRST_BIT=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_HOSTFS=y
+CONFIG_HVC_DRIVER=y
+CONFIG_HW_RANDOM=y
+CONFIG_HZ_PERIODIC=y
+CONFIG_IA32_FEAT_CTL=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_INIT_ENV_ARG_LIMIT=128
+CONFIG_IRQ_WORK=y
+CONFIG_ISO9660_FS=y
+CONFIG_JBD2=y
+# CONFIG_JFFS2_FS is not set
+CONFIG_KALLSYMS=y
+CONFIG_KERNEL_STACK_ORDER=2
+CONFIG_LOCK_DEBUGGING_SUPPORT=y
+# CONFIG_MATOM is not set
+CONFIG_MAY_HAVE_RUNTIME_DEPS=y
+CONFIG_MCONSOLE=y
+# CONFIG_MCORE2 is not set
+CONFIG_MEMFD_CREATE=y
+CONFIG_MIGRATION=y
+CONFIG_MK8=y
+# CONFIG_MMAPPER is not set
+CONFIG_MODULES_USE_ELF_RELA=y
+# CONFIG_MPSC is not set
+CONFIG_NAMESPACES=y
+CONFIG_NEED_PER_CPU_KM=y
+CONFIG_NET_FAILOVER=y
+# CONFIG_NET_NS is not set
+CONFIG_NLS=y
+CONFIG_NO_DMA=y
+CONFIG_NO_IOMEM=y
+CONFIG_NO_IOPORT_MAP=y
+CONFIG_NR_CPUS=1
+CONFIG_NULL_CHAN=y
+# CONFIG_OF is not set
+CONFIG_PGTABLE_LEVELS=3
+CONFIG_PHYS_ADDR_T_64BIT=y
+CONFIG_PORT_CHAN=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
+# CONFIG_PROCESSOR_SELECT is not set
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_PTP_1588_CLOCK_OPTIONAL=y
+CONFIG_PTY_CHAN=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_GZIP=y
+CONFIG_RELAY=y
+CONFIG_SG_POOL=y
+CONFIG_SOFT_WATCHDOG=m
+CONFIG_SRCU=y
+CONFIG_SSL=y
+CONFIG_SSL_CHAN="pty"
+CONFIG_STACKTRACE=y
+CONFIG_STDERR_CONSOLE=y
+CONFIG_TICK_CPU_ACCOUNTING=y
+CONFIG_TINY_SRCU=y
+CONFIG_TTY_CHAN=y
+CONFIG_UML=y
+CONFIG_UML_NET=y
+CONFIG_UML_NET_DAEMON=y
+CONFIG_UML_NET_DETERMINISTIC_MAC=y
+CONFIG_UML_NET_ETHERTAP=y
+CONFIG_UML_NET_MCAST=y
+# CONFIG_UML_NET_PCAP is not set
+CONFIG_UML_NET_SLIP=y
+CONFIG_UML_NET_SLIRP=y
+CONFIG_UML_NET_TUNTAP=y
+# CONFIG_UML_NET_VDE is not set
+CONFIG_UML_NET_VECTOR=y
+# CONFIG_UML_PCI_OVER_VIRTIO is not set
+CONFIG_UML_RANDOM=y
+# CONFIG_UML_SOUND is not set
+CONFIG_UML_TIME_TRAVEL_SUPPORT=y
+CONFIG_UML_WATCHDOG=y
+CONFIG_UML_X86=y
+# CONFIG_USER_NS is not set
+CONFIG_VIRTIO=y
+CONFIG_VIRTIO_BLK=y
+CONFIG_VIRTIO_CONSOLE=y
+CONFIG_VIRTIO_NET=y
+CONFIG_VIRTIO_UML=y
+CONFIG_VMAP_STACK=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_WATCHDOG_CORE=y
+CONFIG_X86_64=y
+CONFIG_X86_CMOV=y
+CONFIG_X86_CMPXCHG64=y
+CONFIG_X86_INTEL_USERCOPY=y
+CONFIG_X86_INTERNODE_CACHE_SHIFT=6
+CONFIG_X86_L1_CACHE_SHIFT=6
+CONFIG_X86_MINIMUM_CPU_FAMILY=64
+CONFIG_X86_TSC=y
+CONFIG_X86_USE_PPRO_CHECKSUM=y
+CONFIG_XTERM_CHAN=y
+CONFIG_ZLIB_INFLATE=y

+ 54 - 0
target/linux/uml/patches-5.15/001-um-fix-default-console-kernel-parameter.patch

@@ -0,0 +1,54 @@
+From 53b5c5f559cc95fc676cb4cc9e5a8d9f0cb8f58c Mon Sep 17 00:00:00 2001
+Message-Id: <53b5c5f559cc95fc676cb4cc9e5a8d9f0cb8f58c.1659815468.git.chunkeey@gmail.com>
+From: Christian Lamparter <[email protected]>
+Date: Sat, 6 Aug 2022 21:22:01 +0200
+Subject: [PATCH v1 1/2] um: fix default console kernel parameter
+To: [email protected]
+Cc: Richard Weinberger <[email protected]>,
+    Anton Ivanov <[email protected]>,
+    Johannes Berg <[email protected]>
+
+OpenWrt's UML with 5.15 was producing odd errors/warnings during preinit
+part of the early userspace portion:
+
+|[    0.000000] Kernel command line: ubd0=root.img root=98:0 console=tty
+|[...]
+|[    0.440000] random: jshn: uninitialized urandom read (4 bytes read)
+|[    0.460000] random: jshn: uninitialized urandom read (4 bytes read)
+|/etc/preinit: line 47: can't create /dev/tty: No such device or address
+|/etc/preinit: line 48: can't create /dev/tty: No such device or address
+|/etc/preinit: line 58: can't open /dev/tty: No such device or address
+|[...] repeated many times
+
+That "/dev/tty" came from the command line (which is automatically
+added if no console= parameter was specified for the uml binary).
+
+The TLDP project tells the following about the /dev/tty:
+<https://tldp.org/HOWTO/Text-Terminal-HOWTO-7.html#ss7.3>
+| /dev/tty stands for the controlling terminal (if any) for the current
+| process.[...]
+| /dev/tty is something like a link to the actually terminal device[..]
+
+The "(if any)" is important here, since it's possible for processes to
+not have a controlling terminal.
+
+I think this was a simple typo and the author wanted tty0 there.
+
+CC: Thomas Meyer <[email protected]>
+Fixes: d7ffac33631b ("um: stdio_console: Make preferred console")
+Signed-off-by: Christian Lamparter <[email protected]>
+---
+ arch/um/kernel/um_arch.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/um/kernel/um_arch.c
++++ b/arch/um/kernel/um_arch.c
+@@ -31,7 +31,7 @@
+ #include <os.h>
+ 
+ #define DEFAULT_COMMAND_LINE_ROOT "root=98:0"
+-#define DEFAULT_COMMAND_LINE_CONSOLE "console=tty"
++#define DEFAULT_COMMAND_LINE_CONSOLE "console=tty0"
+ 
+ /* Changed in add_arg and setup_arch, which run before SMP is started */
+ static char __initdata command_line[COMMAND_LINE_SIZE] = { 0 };

+ 213 - 0
target/linux/uml/patches-5.15/101-mconsole-exec.patch

@@ -0,0 +1,213 @@
+#
+# Minimalist mconsole exec patch 
+#
+# 3.10 version (with bit more synchronous behavior) by fingon at iki dot fi
+# Adaptation to kernel 3.3.8 made by David Fernández (david at dit.upm.es) for 
+# Starting point: mconsole-exec-2.6.30.patch for kernel 2.6.30
+# Author of original patch: Paolo Giarrusso, aka Blaisorblade 
+#                           (http://www.user-mode-linux.org/~blaisorblade)
+#
+# Known misfeatures:
+#
+# - If output is too long, blocks (and breaks horribly) 
+# (this misfeature from 3.10 patches, when minimalizing the patch;
+#  workaround: redirect to a shared filesystem if long output is expected)
+#
+# - Nothing useful is done with stdin
+#
+--- a/arch/um/drivers/mconsole.h
++++ b/arch/um/drivers/mconsole.h
+@@ -85,6 +85,7 @@ extern void mconsole_cad(struct mc_reque
+ extern void mconsole_stop(struct mc_request *req);
+ extern void mconsole_go(struct mc_request *req);
+ extern void mconsole_log(struct mc_request *req);
++extern void mconsole_exec(struct mc_request *req);
+ extern void mconsole_proc(struct mc_request *req);
+ extern void mconsole_stack(struct mc_request *req);
+ 
+--- a/arch/um/drivers/mconsole_kern.c
++++ b/arch/um/drivers/mconsole_kern.c
+@@ -4,6 +4,7 @@
+  * Copyright (C) 2001 - 2008 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+  */
+ 
++#include <linux/kmod.h>
+ #include <linux/console.h>
+ #include <linux/ctype.h>
+ #include <linux/string.h>
+@@ -27,6 +28,7 @@
+ #include <linux/mount.h>
+ #include <linux/file.h>
+ #include <linux/uaccess.h>
++#include <linux/completion.h>
+ #include <asm/switch_to.h>
+ 
+ #include <init.h>
+@@ -124,6 +126,59 @@ void mconsole_log(struct mc_request *req
+ 	mconsole_reply(req, "", 0, 0);
+ }
+ 
++void mconsole_exec(struct mc_request *req)
++{
++  struct subprocess_info *sub_info;
++  int res, len;
++  struct file *out;
++  char buf[MCONSOLE_MAX_DATA];
++
++  char *envp[] = {
++    "HOME=/", "TERM=linux",
++    "PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin",
++    NULL
++  };
++  char *argv[] = {
++    "/bin/sh", "-c",
++    req->request.data + strlen("exec "),
++    NULL
++  };
++
++  sub_info = call_usermodehelper_setup("/bin/sh", argv, envp, GFP_ATOMIC, NULL, NULL, NULL);
++  if (sub_info == NULL) {
++    mconsole_reply(req, "call_usermodehelper_setup failed", 1, 0);
++    return;
++  }
++  res = call_usermodehelper_stdoutpipe(sub_info, &out);
++  if (res < 0) {
++    kfree(sub_info);
++    mconsole_reply(req, "call_usermodehelper_stdoutpipe failed", 1, 0);
++    return;
++  }
++
++  res = call_usermodehelper_exec(sub_info, UMH_WAIT_PROC);
++  if (res < 0) {
++    kfree(sub_info);
++    mconsole_reply(req, "call_usermodehelper_exec failed", 1, 0);
++    return;
++  }
++
++  for (;;) {
++    len = out->f_op->read(out, buf, sizeof(buf), &out->f_pos);
++    if (len < 0) {
++      mconsole_reply(req, "reading output failed", 1, 0);
++      break;
++    }
++    if (len == 0)
++      break;
++    mconsole_reply_len(req, buf, len, 0, 1);
++  }
++  fput(out);
++
++  mconsole_reply_len(req, NULL, 0, 0, 0);
++}
++
++
+ void mconsole_proc(struct mc_request *req)
+ {
+ 	struct vfsmount *mnt = proc_mnt;
+@@ -190,6 +245,7 @@ void mconsole_proc(struct mc_request *re
+     stop - pause the UML; it will do nothing until it receives a 'go' \n\
+     go - continue the UML after a 'stop' \n\
+     log <string> - make UML enter <string> into the kernel log\n\
++    exec <string> - pass <string> to /bin/sh -c synchronously\n\
+     proc <file> - returns the contents of the UML's /proc/<file>\n\
+     stack <pid> - returns the stack of the specified pid\n\
+ "
+--- a/arch/um/drivers/mconsole_user.c
++++ b/arch/um/drivers/mconsole_user.c
+@@ -30,6 +30,7 @@ static struct mconsole_command commands[
+ 	{ "stop", mconsole_stop, MCONSOLE_PROC },
+ 	{ "go", mconsole_go, MCONSOLE_INTR },
+ 	{ "log", mconsole_log, MCONSOLE_INTR },
++	{ "exec", mconsole_exec, MCONSOLE_PROC },
+ 	{ "proc", mconsole_proc, MCONSOLE_PROC },
+ 	{ "stack", mconsole_stack, MCONSOLE_INTR },
+ };
+--- a/arch/um/os-Linux/file.c
++++ b/arch/um/os-Linux/file.c
+@@ -560,6 +560,8 @@ int os_create_unix_socket(const char *fi
+ 
+ 	addr.sun_family = AF_UNIX;
+ 
++	if (len > sizeof(addr.sun_path))
++		len = sizeof(addr.sun_path);
+ 	snprintf(addr.sun_path, len, "%s", file);
+ 
+ 	err = bind(sock, (struct sockaddr *) &addr, sizeof(addr));
+--- a/include/linux/kmod.h
++++ b/include/linux/kmod.h
+@@ -32,4 +32,6 @@ static inline int request_module_nowait(
+ #define try_then_request_module(x, mod...) (x)
+ #endif
+ 
++int call_usermodehelper_stdoutpipe(struct subprocess_info *sub_info, struct file **filp);
++
+ #endif /* __LINUX_KMOD_H__ */
+--- a/include/linux/umh.h
++++ b/include/linux/umh.h
+@@ -22,6 +22,7 @@ struct subprocess_info {
+ 	const char *path;
+ 	char **argv;
+ 	char **envp;
++	struct file *stdout;
+ 	int wait;
+ 	int retval;
+ 	int (*init)(struct subprocess_info *info, struct cred *new);
+--- a/kernel/umh.c
++++ b/kernel/umh.c
+@@ -28,6 +28,7 @@
+ #include <linux/async.h>
+ #include <linux/uaccess.h>
+ #include <linux/initrd.h>
++#include <linux/pipe_fs_i.h>
+ 
+ #include <trace/events/module.h>
+ 
+@@ -73,6 +74,28 @@ static int call_usermodehelper_exec_asyn
+ 	flush_signal_handlers(current, 1);
+ 	spin_unlock_irq(&current->sighand->siglock);
+ 
++	/* Install output when needed */
++	if (sub_info->stdout) {
++		struct files_struct *f = current->files;
++		struct fdtable *fdt;
++
++		sys_close(1);
++		sys_close(2);
++		get_file(sub_info->stdout);
++		fd_install(1, sub_info->stdout);
++		fd_install(2, sub_info->stdout);
++		spin_lock(&f->file_lock);
++		fdt = files_fdtable(f);
++		__set_bit(1, fdt->open_fds);
++		__clear_bit(1, fdt->close_on_exec);
++		__set_bit(2, fdt->open_fds);
++		__clear_bit(2, fdt->close_on_exec);
++		spin_unlock(&f->file_lock);
++
++		/* disallow core files */
++		current->signal->rlim[RLIMIT_CORE] = (struct rlimit){0, 0};
++	}
++
+ 	/*
+ 	 * Initial kernel threads share ther FS with init, in order to
+ 	 * get the init root directory. But we've now created a new
+@@ -332,6 +355,20 @@ static void helper_unlock(void)
+ 		wake_up(&running_helpers_waitq);
+ }
+ 
++int call_usermodehelper_stdoutpipe(struct subprocess_info *sub_info,
++					struct file **filp)
++{
++	struct file *f[2];
++
++	if (create_pipe_files(f, 0) < 0)
++		 return PTR_ERR(f);
++
++	sub_info->stdout = f[1];
++	*filp = f[0];
++	return 0;
++}
++EXPORT_SYMBOL(call_usermodehelper_stdoutpipe);
++
+ /**
+  * call_usermodehelper_setup - prepare to call a usermode helper
+  * @path: path to usermode executable

+ 147 - 0
target/linux/uml/patches-5.15/102-pseudo-random-mac.patch

@@ -0,0 +1,147 @@
+===============================================================================
+
+This patch makes MAC addresses of network interfaces predictable. In
+particular, it adds a small routine that computes MAC addresses of based on
+a SHA1 hash of the virtual machine name and interface ID.
+
+TECHNICAL INFORMATION:
+
+Applies to vanilla kernel 3.9.4.
+
+===============================================================================
+--- a/arch/um/drivers/Kconfig
++++ b/arch/um/drivers/Kconfig
+@@ -146,6 +146,20 @@ config UML_NET
+ 	  enable at least one of the following transport options to actually
+ 	  make use of UML networking.
+ 
++config UML_NET_DETERMINISTIC_MAC
++	bool "Use deterministic MAC addresses for network interfaces"
++	default y
++	depends on UML_NET
++	select CRYPTO_SHA1
++	help
++        Virtual network devices inside a User-Mode Linux instance must be
++        assigned a MAC (Ethernet) address. If none is specified on the UML
++        command line, one must be automatically computed. If this option is
++        enabled, a randomly generated address is used. Otherwise, if this
++        option is disabled, the address is generated from a SHA1 hash of
++        the umid of the UML instance and the interface name. The latter choice
++        is useful to make MAC addresses predictable.
++
+ config UML_NET_ETHERTAP
+ 	bool "Ethertap transport (obsolete)"
+ 	depends on UML_NET
+--- a/arch/um/drivers/net_kern.c
++++ b/arch/um/drivers/net_kern.c
+@@ -25,6 +25,14 @@
+ #include <net_kern.h>
+ #include <net_user.h>
+ 
++#include <crypto/sha1.h>
++#include <crypto/hash.h>
++#include <linux/string.h>
++#include <linux/crypto.h>
++#include <linux/err.h>
++#include <linux/scatterlist.h>
++#include "os.h"
++
+ #define DRIVER_NAME "uml-netdev"
+ 
+ static DEFINE_SPINLOCK(opened_lock);
+@@ -274,9 +282,51 @@ static const struct ethtool_ops uml_net_
+ 	.get_ts_info	= ethtool_op_get_ts_info,
+ };
+ 
++#ifdef CONFIG_UML_NET_DETERMINISTIC_MAC
++
++/* Compute a SHA1 hash of the UML instance's id and
++ *  * an interface name. */
++static int compute_hash(const char *umid, const char *ifname, char *hash)
++{
++	struct ahash_request *desc;
++	struct crypto_ahash *tfm;
++	struct scatterlist sg;
++	char vmif[1024];
++	int ret;
++
++	strcpy (vmif, umid);
++	strcat (vmif, ifname);
++
++	tfm = crypto_alloc_ahash("sha1", 0, CRYPTO_ALG_ASYNC);
++	if (IS_ERR(tfm))
++		return -ENOMEM;
++
++	desc = ahash_request_alloc(tfm, GFP_KERNEL);
++	if (!desc) {
++		ret = -ENOMEM;
++		goto out;
++	}
++
++	crypto_ahash_clear_flags(tfm, ~0);
++
++	sg_init_table(&sg, 1);
++	sg_set_buf(&sg, vmif, strlen(vmif));
++
++	ahash_request_set_crypt(desc, &sg, hash, strlen(vmif));
++
++	ret = crypto_ahash_digest(desc);
++out:
++	crypto_free_ahash(tfm);
++
++	return ret;
++}
++
++#endif
++
+ void uml_net_setup_etheraddr(struct net_device *dev, char *str)
+ {
+ 	unsigned char *addr = dev->dev_addr;
++	u8 hash[SHA1_DIGEST_SIZE];
+ 	char *end;
+ 	int i;
+ 
+@@ -319,9 +369,26 @@ void uml_net_setup_etheraddr(struct net_
+ 	return;
+ 
+ random:
++#ifndef CONFIG_UML_NET_DETERMINISTIC_MAC
+ 	printk(KERN_INFO
+ 	       "Choosing a random ethernet address for device %s\n", dev->name);
+ 	eth_hw_addr_random(dev);
++#else
++	printk(KERN_INFO
++	       "Computing a digest to use as ethernet address for device %s\n", dev->name);
++	if (compute_hash(get_umid(), dev->name, hash) < 0) {
++		printk(KERN_WARNING
++		       "Could not compute digest to use as ethernet address for device %s. "
++		       "Using random address instead.\n", dev->name);
++		random_ether_addr(addr);
++	}
++	else {
++		for (i=0; i < 6; i++)
++			addr[i] = (hash[i] + hash[i+6]) % 0x100;
++	}
++	addr [0] &= 0xfe; /* clear multicast bit */
++	addr [0] |= 0x02; /* set local assignment bit (IEEE802) */
++#endif
+ }
+ 
+ static DEFINE_SPINLOCK(devices_lock);
+--- a/kernel/umh.c
++++ b/kernel/umh.c
+@@ -356,12 +356,12 @@ static void helper_unlock(void)
+ }
+ 
+ int call_usermodehelper_stdoutpipe(struct subprocess_info *sub_info,
+-					struct file **filp)
++				   struct file **filp)
+ {
+ 	struct file *f[2];
+ 
+ 	if (create_pipe_files(f, 0) < 0)
+-		 return PTR_ERR(f);
++		return PTR_ERR(f);
+ 
+ 	sub_info->stdout = f[1];
+ 	*filp = f[0];

+ 40 - 0
target/linux/uml/patches-5.15/104-um-increase-default-virtual-physical-memory-to-64.patch

@@ -0,0 +1,40 @@
+From d7936f11aded13f03871c0d6502d611d6a1e2dc5 Mon Sep 17 00:00:00 2001
+Message-Id: <d7936f11aded13f03871c0d6502d611d6a1e2dc5.1659815468.git.chunkeey@gmail.com>
+In-Reply-To: <53b5c5f559cc95fc676cb4cc9e5a8d9f0cb8f58c.1659815468.git.chunkeey@gmail.com>
+References: <53b5c5f559cc95fc676cb4cc9e5a8d9f0cb8f58c.1659815468.git.chunkeey@gmail.com>
+From: Christian Lamparter <[email protected]>
+Date: Sat, 6 Aug 2022 19:27:20 +0200
+Subject: [PATCH v1 2/2] um: increase default virtual physical memory to 64 MiB
+To: [email protected]
+Cc: Richard Weinberger <[email protected]>,
+    Anton Ivanov <[email protected]>,
+    Johannes Berg <[email protected]>
+
+The current 32 MiB of RAM causes OOMs to appear shortly after
+booting in a minimal OpenWrt 22.03 configuration with a
+5.10.134 kernel.
+
+Of course, passing a "mem=64M" (from the --help text) parameter
+works too, but it produces the following (info) message:
+
+| [    0.000000] Unknown kernel command line parameters "mem=64M", will be passed to user space.
+
+That's why, I think it would be nicer, if this is working out
+of the box again :).
+
+Signed-off-by: Christian Lamparter <[email protected]>
+---
+ arch/um/kernel/um_arch.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/um/kernel/um_arch.c
++++ b/arch/um/kernel/um_arch.c
+@@ -130,7 +130,7 @@ static int have_root __initdata;
+ static int have_console __initdata;
+ 
+ /* Set in uml_mem_setup and modified in linux_main */
+-long long physmem_size = 32 * 1024 * 1024;
++long long physmem_size = 64 * 1024 * 1024;
+ EXPORT_SYMBOL(physmem_size);
+ 
+ static const char *usage_string =