uml: add Kernel 6.1 support via testing
Add the latest default Kernel for testing. There is no uml_watchdog userspace daemon available, hence CONFIG_UML_WATCHDOG is disabled. Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
This commit is contained in:
		| @@ -14,6 +14,7 @@ BOARDNAME:=User Mode Linux | |||||||
| FEATURES:=audio ext4 rootfs-part squashfs | FEATURES:=audio ext4 rootfs-part squashfs | ||||||
|  |  | ||||||
| KERNEL_PATCHVER:=5.15 | KERNEL_PATCHVER:=5.15 | ||||||
|  | KERNEL_TESTING_PATCHVER:=6.1 | ||||||
|  |  | ||||||
| include $(INCLUDE_DIR)/target.mk | include $(INCLUDE_DIR)/target.mk | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										150
									
								
								target/linux/uml/config-6.1
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										150
									
								
								target/linux/uml/config-6.1
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,150 @@ | |||||||
|  | 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_COMPACT_UNEVICTABLE_DEFAULT=1 | ||||||
|  | # 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_CRC32=y | ||||||
|  | CONFIG_CRYPTO_CRC32C=y | ||||||
|  | CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y | ||||||
|  | CONFIG_CRYPTO_LIB_POLY1305_RSIZE=11 | ||||||
|  | CONFIG_CRYPTO_LIB_SHA1=y | ||||||
|  | CONFIG_CRYPTO_LIB_UTILS=y | ||||||
|  | CONFIG_CRYPTO_RNG2=y | ||||||
|  | CONFIG_CRYPTO_SHA1=y | ||||||
|  | CONFIG_DCACHE_WORD_ACCESS=y | ||||||
|  | CONFIG_DECOMPRESS_BZIP2=y | ||||||
|  | CONFIG_DECOMPRESS_GZIP=y | ||||||
|  | CONFIG_DNOTIFY=y | ||||||
|  | # CONFIG_EARLY_PRINTK is not set | ||||||
|  | CONFIG_EXCLUSIVE_SYSTEM_RAM=y | ||||||
|  | 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_FW_LOADER_SYSFS=y | ||||||
|  | CONFIG_GCC11_NO_ARRAY_BOUNDS=y | ||||||
|  | CONFIG_GENERIC_CLOCKEVENTS=y | ||||||
|  | # CONFIG_GENERIC_CPU is not set | ||||||
|  | CONFIG_GENERIC_CPU_DEVICES=y | ||||||
|  | CONFIG_GENERIC_IRQ_SHOW=y | ||||||
|  | CONFIG_GPIO_CDEV=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_PREEMPT_NONE_BUILD=y | ||||||
|  | # CONFIG_PROCESSOR_SELECT is not set | ||||||
|  | CONFIG_PROC_PAGE_MONITOR=y | ||||||
|  | CONFIG_PTP_1588_CLOCK_OPTIONAL=y | ||||||
|  | CONFIG_PTY_CHAN=y | ||||||
|  | CONFIG_RANDSTRUCT_NONE=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_DAEMON_DEFAULT_SOCK="/tmp/uml.ctl" | ||||||
|  | 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 is not set | ||||||
|  | CONFIG_UML_X86=y | ||||||
|  | # CONFIG_USER_NS is not set | ||||||
|  | CONFIG_VIRTIO=y | ||||||
|  | CONFIG_VIRTIO_ANCHOR=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_XTERM_CHAN_DEFAULT_EMULATOR="xterm" | ||||||
|  | CONFIG_ZLIB_INFLATE=y | ||||||
							
								
								
									
										213
									
								
								target/linux/uml/patches-6.1/101-mconsole-exec.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										213
									
								
								target/linux/uml/patches-6.1/101-mconsole-exec.patch
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||||
|  | @@ -23,6 +23,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 | ||||||
|  | @@ -29,6 +29,7 @@ | ||||||
|  |  #include <linux/uaccess.h> | ||||||
|  |  #include <linux/initrd.h> | ||||||
|  |  #include <linux/freezer.h> | ||||||
|  | +#include <linux/pipe_fs_i.h> | ||||||
|  |   | ||||||
|  |  #include <trace/events/module.h> | ||||||
|  |   | ||||||
|  | @@ -74,6 +75,28 @@ static int call_usermodehelper_exec_asyn | ||||||
|  |  	flush_signal_handlers(current, 1); | ||||||
|  |  	spin_unlock_irq(¤t->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 | ||||||
|  | @@ -333,6 +356,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 | ||||||
							
								
								
									
										151
									
								
								target/linux/uml/patches-6.1/102-pseudo-random-mac.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										151
									
								
								target/linux/uml/patches-6.1/102-pseudo-random-mac.patch
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,151 @@ | |||||||
|  | =============================================================================== | ||||||
|  |  | ||||||
|  | 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 | ||||||
|  | @@ -153,6 +153,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,55 @@ 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 = NULL; | ||||||
|  | +	struct crypto_ahash *tfm = NULL; | ||||||
|  | +	struct scatterlist sg; | ||||||
|  | +	char *vmif = NULL; | ||||||
|  | +	int ret = -ENOMEM; | ||||||
|  | + | ||||||
|  | +	vmif = kmalloc(1024, GFP_KERNEL); | ||||||
|  | +	if (!vmif) | ||||||
|  | +		goto out; | ||||||
|  | + | ||||||
|  | +	strcpy (vmif, umid); | ||||||
|  | +	strcat (vmif, ifname); | ||||||
|  | + | ||||||
|  | +	tfm = crypto_alloc_ahash("sha1", 0, CRYPTO_ALG_ASYNC); | ||||||
|  | +	if (IS_ERR(tfm)) | ||||||
|  | +		goto out; | ||||||
|  | + | ||||||
|  | +	desc = ahash_request_alloc(tfm, GFP_KERNEL); | ||||||
|  | +	if (!desc) | ||||||
|  | +		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); | ||||||
|  | +	ahash_request_free(desc); | ||||||
|  | +	kfree(vmif); | ||||||
|  | + | ||||||
|  | +	return ret; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +#endif | ||||||
|  | + | ||||||
|  |  void uml_net_setup_etheraddr(struct net_device *dev, char *str) | ||||||
|  |  { | ||||||
|  |  	u8 addr[ETH_ALEN]; | ||||||
|  | +	u8 hash[SHA1_DIGEST_SIZE]; | ||||||
|  |  	char *end; | ||||||
|  |  	int i; | ||||||
|  |   | ||||||
|  | @@ -320,9 +374,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); | ||||||
|  | +		eth_random_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 | ||||||
|  | @@ -357,12 +357,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]; | ||||||
		Reference in New Issue
	
	Block a user
	 Christian Lamparter
					Christian Lamparter