diff -Naur -X exclude-files ac_cur/arch/um/drivers/net_kern.c ac/arch/um/drivers/net_kern.c --- ac_cur/arch/um/drivers/net_kern.c Sat Nov 3 16:12:55 2001 +++ ac/arch/um/drivers/net_kern.c Sat Nov 3 16:15:32 2001 @@ -31,6 +31,7 @@ #include "mcast.h" #include "mcast_kern.h" #include "mconsole_kern.h" +#include "init.h" LIST_HEAD(opened); @@ -110,8 +111,53 @@ return(1); } -__setup("eth", eth_setup); +#ifdef CONFIG_UML_NET_ETHERTAP +#define UML_NET_ETHERTAP_HELP \ +" eth[0-9]+=ethertap,,,\n" \ +" eth0=ethertap,tap0,,192.168.0.1\n\n" +#else +#define UML_NET_ETHERTAP_HELP +#endif +#ifdef CONFIG_UML_NET_TUNTAP +#define UML_NET_TUNTAP_HELP \ +" eth[0-9]+=tuntap,,,\n" \ +" eth0=tuntap,,fe:fd:0:0:0:1,192.168.0.1\n\n" +#else +#define UML_NET_TUNTAP_HELP +#endif +#ifdef CONFIG_UML_NET_DAEMON +#define UML_NET_DAEMON_HELP \ +" eth[0-9]+=daemon,,,,\n" \ +" eth0=daemon,unix,/tmp/uml.ctl,/tmp/uml.data\n\n" +#else +#define UML_NET_DAEMON_HELP +#endif +#ifdef CONFIG_UML_NET_SLIP +#define UML_NET_SLIP_HELP \ +" eth[0-9]+=slip,\n" \ +" eth0=slip,192.168.0.1\n\n" +#else +#define UML_NET_SLIP_HELP +#endif +#ifdef CONFIG_UML_NET_MCAST +#define UML_NET_MCAST_HELP \ +" eth[0-9]+=mcast,,
,,\n" \ +" eth0=mcast,,224.2.3.4:5555,3\n\n" +#else +#define UML_NET_MCAST_HELP +#endif +__setup("eth", eth_setup); +__uml_help(eth_setup, +"eth[0-9]+=,\n" +" Configure a network device. Formats and examples follow (one \n" +" for each configured transport).\n\n" +UML_NET_ETHERTAP_HELP +UML_NET_TUNTAP_HELP +UML_NET_DAEMON_HELP +UML_NET_SLIP_HELP +UML_NET_MCAST_HELP +); int ndev = 0; static int uml_net_rx(struct net_device *dev) diff -Naur -X exclude-files ac_cur/arch/um/drivers/ssl.c ac/arch/um/drivers/ssl.c --- ac_cur/arch/um/drivers/ssl.c Sat Nov 3 16:12:55 2001 +++ ac/arch/um/drivers/ssl.c Sat Nov 3 16:15:32 2001 @@ -16,6 +16,7 @@ #include "user_util.h" #include "kern_util.h" #include "kern.h" +#include "init.h" static int ssl_version = 1; @@ -283,6 +284,7 @@ } __setup("ssl", ssl_chan_setup); +__channel_help(ssl_chan_setup, "ssl"); static void ssl_exit(void) { diff -Naur -X exclude-files ac_cur/arch/um/drivers/stdio_console.c ac/arch/um/drivers/stdio_console.c --- ac_cur/arch/um/drivers/stdio_console.c Sat Nov 3 16:14:54 2001 +++ ac/arch/um/drivers/stdio_console.c Sat Nov 3 16:15:32 2001 @@ -21,6 +21,7 @@ #include "chan.h" #include "user_util.h" #include "kern_util.h" +#include "init.h" #define MAX_TTYS (8) @@ -64,9 +65,8 @@ if(err < 0){ printk("Failed to open virtual console %d, errno = %d\n", line, err); - return(err); } - return(0); + return(err); } static int open_console(int line, struct tty_struct *tty) @@ -280,6 +280,7 @@ } __setup("con", console_chan_setup); +__channel_help(console_chan_setup, "con"); static void console_exit(void) { diff -Naur -X exclude-files ac_cur/arch/um/drivers/ubd.c ac/arch/um/drivers/ubd.c --- ac_cur/arch/um/drivers/ubd.c Sat Nov 3 16:13:06 2001 +++ ac/arch/um/drivers/ubd.c Sat Nov 3 16:15:32 2001 @@ -25,6 +25,7 @@ #include "kern_util.h" #include "kern.h" #include "mconsole_kern.h" +#include "init.h" extern __u64 file_size(char *file); @@ -201,6 +202,10 @@ } __setup("fake_ide", fake_ide_setup); +__uml_help(fake_ide_setup, +"fake_ide\n" +" Create ide0 entries that map onto ubd devices.\n\n" +); static int ubd_setup_common(char *str, int *index_out) { @@ -268,6 +273,17 @@ } __setup("ubd", ubd_setup); +__uml_help(ubd_setup, +"ubd=\n" +" This is used to associate a device with a file in the underlying\n" +" filesystem. Usually, there is a filesystem in the file, but \n" +" that's not required. Swap devices containing swap files can be\n" +" specified like this. Also, a file which doesn't contain a\n" +" filesystem can have its contents read in the virtual \n" +" machine by running dd on the device. n must be in the range\n" +" 0 to 7. Appending an 'r' to the number will cause that device\n" +" to be mounted read-only. For example ubd1r=./ext_fs\n\n" +); static int fakehd(char *str) { @@ -277,6 +293,10 @@ } __setup("fakehd", fakehd); +__uml_help(fakehd, +"fakehd\n" +" Change the ubd device name to \"hd\".\n\n" +); static void do_ubd_request(request_queue_t * q); diff -Naur -X exclude-files ac_cur/arch/um/include/chan.h ac/arch/um/include/chan.h --- ac_cur/arch/um/include/chan.h Sat Nov 3 16:12:55 2001 +++ ac/arch/um/include/chan.h Sat Nov 3 16:15:32 2001 @@ -5,6 +5,7 @@ #ifndef __TTY_H__ #define __TTY_H__ +#include "init.h" struct chan { enum { XTERM, PTY, SOCKET, FD, TTY, PTS, FILE_CHAN, COPY } type; @@ -41,6 +42,13 @@ struct chan in; struct chan out; }; + +#define __channel_help(fn, prefix) \ +__uml_help(fn, prefix "[0-9]*=\n" \ +" Attach a console or serial line to a host channel. See\n" \ +" http://user-mode-linux.sourceforge.net/input.html for a complete\n" \ +" description of this switch.\n\n" \ +); #define INIT_STATIC (0) #define INIT_ALL (1) diff -Naur -X exclude-files ac_cur/arch/um/include/init.h ac/arch/um/include/init.h --- ac_cur/arch/um/include/init.h Wed Dec 31 19:00:00 1969 +++ ac/arch/um/include/init.h Sat Nov 3 16:15:32 2001 @@ -0,0 +1,94 @@ +#ifndef _LINUX_UML_INIT_H +#define _LINUX_UML_INIT_H + +/* These macros are used to mark some functions or + * initialized data (doesn't apply to uninitialized data) + * as `initialization' functions. The kernel can take this + * as hint that the function is used only during the initialization + * phase and free up used memory resources after + * + * Usage: + * For functions: + * + * You should add __init immediately before the function name, like: + * + * static void __init initme(int x, int y) + * { + * extern int z; z = x * y; + * } + * + * If the function has a prototype somewhere, you can also add + * __init between closing brace of the prototype and semicolon: + * + * extern int initialize_foobar_device(int, int, int) __init; + * + * For initialized data: + * You should insert __initdata between the variable name and equal + * sign followed by value, e.g.: + * + * static int init_variable __initdata = 0; + * static char linux_logo[] __initdata = { 0x32, 0x36, ... }; + * + * Don't forget to initialize data not at file scope, i.e. within a function, + * as gcc otherwise puts the data into the bss section and not into the init + * section. + * + * Also note, that this data cannot be "const". + */ + +#ifndef _LINUX_INIT_H +typedef int (*initcall_t)(void); +typedef void (*exitcall_t)(void); + +#define __init __attribute__ ((__section__ (".text.init"))) +#define __exit __attribute__ ((unused, __section__(".text.exit"))) +#define __initdata __attribute__ ((__section__ (".data.init"))) + +#endif +struct uml_param { + const char *str; + int (*setup_func)(char *, int *); +}; + +extern initcall_t __uml_initcall_start, __uml_initcall_end; +extern initcall_t __uml_postsetup_start, __uml_postsetup_end; +extern const char *__uml_help_start, *__uml_help_end; + +#define __uml_initcall(fn) \ + static initcall_t __uml_initcall_##fn __uml_init_call = fn +#define __uml_exitcall(fn) \ + static exitcall_t __uml_exitcall_##fn __uml_exit_call = fn + +extern struct uml_param __uml_setup_start, __uml_setup_end; + +#define __uml_postsetup(fn) \ + static initcall_t __uml_postsetup_##fn __uml_postsetup_call = fn + +#define __non_empty_string(dummyname,string) \ + struct __uml_non_empty_string_struct_##dummyname \ + { \ + char _string[sizeof(string)-2]; \ + } + +#define __uml_setup(str, fn, help...) \ + __non_empty_string(fn ##_setup, str); \ + __uml_help(fn, help); \ + static char __uml_setup_str_##fn[] __initdata = str; \ + static struct uml_param __uml_setup_##fn __uml_init_setup = { __uml_setup_str_##fn, fn }\ + +#define __uml_help(fn, help...) \ + __non_empty_string(fn ##__help, help); \ + static char __uml_help_str_##fn[] __initdata = help; \ + static const char *__uml_help_##fn __uml_setup_help = __uml_help_str_##fn + +/* + * Mark functions and data as being only used at initialization + * or exit time. + */ +#define __uml_init_setup __attribute__ ((unused,__section__ (".uml.setup.init"))) +#define __uml_setup_help __attribute__ ((unused,__section__ (".uml.help.init"))) +#define __uml_init_call __attribute__ ((unused,__section__ (".uml.initcall.init"))) +#define __uml_postsetup_call __attribute__ ((unused,__section__ (".uml.postsetup.init"))) +#define __uml_exit_call __attribute__ ((unused,__section__ (".uml.exitcall.exit"))) + +#endif /* _LINUX_UML_INIT_H */ diff -Naur -X exclude-files ac_cur/arch/um/include/initrd.h ac/arch/um/include/initrd.h --- ac_cur/arch/um/include/initrd.h Wed Dec 31 19:00:00 1969 +++ ac/arch/um/include/initrd.h Sat Nov 3 16:15:32 2001 @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#ifndef __INITRD_USER_H__ +#define __INITRD_USER_H__ + +extern int load_initrd(char *filename, void *buf, int size); + +#endif + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff -Naur -X exclude-files ac_cur/arch/um/include/mem_user.h ac/arch/um/include/mem_user.h --- ac_cur/arch/um/include/mem_user.h Sat Nov 3 16:12:55 2001 +++ ac/arch/um/include/mem_user.h Sat Nov 3 16:15:32 2001 @@ -37,12 +37,13 @@ extern unsigned long host_task_size; extern unsigned long task_size; +extern int init_mem_user(void); extern int create_mem_file(unsigned long len); extern void setup_range(int fd, char *driver, unsigned long start, unsigned long usable, unsigned long total); extern void map(unsigned long virt, void *p, unsigned long len, int r, int w, int x); -extern void parse_iomem(char *str); +extern int parse_iomem(char *str, int *add); extern void setup_memory(void); extern unsigned long find_iomem(char *driver, unsigned long *len_out); diff -Naur -X exclude-files ac_cur/arch/um/kernel/Makefile ac/arch/um/kernel/Makefile --- ac_cur/arch/um/kernel/Makefile Sat Nov 3 16:14:09 2001 +++ ac/arch/um/kernel/Makefile Sat Nov 3 16:15:32 2001 @@ -6,6 +6,10 @@ sysrq.o sys_call_table.o time.o time_kern.o tlb.o trap_kern.o \ trap_user.o uaccess_user.o um_arch.o umid.o user_util.o +ifeq ($(CONFIG_BLK_DEV_INITRD), y) + OBJS += initrd_kern.o initrd_user.o +endif + export-objs = ksyms.o process_kern.o signal_kern.o user_syms.o UNMAP_CFLAGS := $(patsubst -pg -DPROFILING,,$(USER_CFLAGS)) diff -Naur -X exclude-files ac_cur/arch/um/kernel/initrd_kern.c ac/arch/um/kernel/initrd_kern.c --- ac_cur/arch/um/kernel/initrd_kern.c Wed Dec 31 19:00:00 1969 +++ ac/arch/um/kernel/initrd_kern.c Sat Nov 3 16:15:32 2001 @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#include "linux/init.h" +#include "linux/bootmem.h" + +#include "linux/blk.h" +#include "user_util.h" +#include "initrd.h" +#include "init.h" + +static char *initrd __initdata = NULL; +static int __init read_initrd(void) +{ + void *area; + int size; + + if(initrd == NULL) return 0; + size = file_size(initrd); + if(size < 0) return 0; + area = alloc_bootmem(size); + if(area == NULL) return 0; + if(load_initrd(initrd, area, size) == -1) return 0; + initrd_start = (unsigned long) area; + initrd_end = initrd_start + size; + return 0; +} +static int __init uml_initrd_setup(char *line, int *add) +{ + initrd = line; + return 0; +} +__uml_setup("initrd=", uml_initrd_setup, +"initrd=\n" +" This is used to boot UML from an initrd image. The argument is the\n" +" name of the file containing the image\n" +); +__uml_postsetup(read_initrd); + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff -Naur -X exclude-files ac_cur/arch/um/kernel/initrd_user.c ac/arch/um/kernel/initrd_user.c --- ac_cur/arch/um/kernel/initrd_user.c Wed Dec 31 19:00:00 1969 +++ ac/arch/um/kernel/initrd_user.c Sat Nov 3 16:15:32 2001 @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#include +#include +#include +#include +#include + +#include "user_util.h" +#include "kern_util.h" +#include "user.h" +#include "initrd.h" + +int load_initrd(char *filename, void *buf, int size) +{ + int fd, n; + + if((fd = open(filename, O_RDONLY)) == -1){ + printk("Opening '%s' failed - errno = %d\n", filename, errno); + return(-1); + } + if((n = read(fd, buf, size)) != size){ + printk("Read of %d bytes from '%s' returned %d, errno = %d\n", + size, filename, n, errno); + return(-1); + } + return(0); +} + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff -Naur -X exclude-files ac_cur/arch/um/kernel/mem.c ac/arch/um/kernel/mem.c --- ac_cur/arch/um/kernel/mem.c Sat Nov 3 16:14:40 2001 +++ ac/arch/um/kernel/mem.c Sat Nov 3 16:15:32 2001 @@ -19,6 +19,7 @@ #include "kern_util.h" #include "mem_user.h" #include "kern.h" +#include "init.h" unsigned long high_physmem; @@ -39,6 +40,7 @@ static unsigned long totalram_pages = 0; extern char __init_begin, __init_end; +extern long physmem_size; int kmalloc_ok = 0; @@ -193,6 +195,22 @@ { kmem_top = new; } + +static int __init uml_mem_setup(char *line, int *add) +{ + char *retptr; + physmem_size = memparse(line,&retptr); + return 0; +} +__uml_setup("mem=",uml_mem_setup, +"mem=\n" +" This controls how much \"physical\" memory the kernel allocates\n" +" for the system. The size is specified as a number followed by\n" +" one of 'k', 'K', 'm', 'M', which have the obvious meanings.\n" +" This is not related to the amount of memory in the physical\n" +" machine. It can be more, and the excess, if it's ever used, will\n" +" just be swapped out.\n Example: mem=64M\n\n" +); /* * Overrides for Emacs so that we follow Linus's tabbing style. diff -Naur -X exclude-files ac_cur/arch/um/kernel/mem_user.c ac/arch/um/kernel/mem_user.c --- ac_cur/arch/um/kernel/mem_user.c Sat Nov 3 16:12:55 2001 +++ ac/arch/um/kernel/mem_user.c Sat Nov 3 16:15:32 2001 @@ -41,6 +41,8 @@ #include #include "kern_util.h" #include "user.h" +#include "user_util.h" +#include "init.h" struct mem_region { struct mem_region *next; @@ -55,21 +57,14 @@ struct mem_region *mem_list = &physmem_region; +#define TEMPNAME_TEMPLATE "vm_file-XXXXXX" + int create_mem_file(unsigned long len) { - char tempname[sizeof("/tmp/vm_file-XXXXXX\0")]; int fd; char zero; - strcpy(tempname, "/tmp/vm_file-XXXXXX"); - if((fd = mkstemp(tempname)) < 0){ - perror("open - cannot create /tmp/vm_file-XXXXXX"); - exit(1); - } - if(unlink(tempname) < 0){ - perror("unlink"); - exit(1); - } + fd = make_tempfile(TEMPNAME_TEMPLATE, NULL, 1); if (fchmod(fd, 0777) < 0){ perror("fchmod"); exit(1); @@ -137,7 +132,7 @@ } } -void parse_iomem(char *str) +static int __init parse_iomem(char *str, int *add) { struct stat buf; char *file, *driver; @@ -147,21 +142,26 @@ file = strchr(str,','); if(file == NULL){ printk(__FUNCTION__ " failed to parse iomem\n"); - return; + return 1; } *file = '\0'; file++; fd = open(file, O_RDWR); if(fd < 0){ perror("Couldn't open io file"); - return; + return 1; } if(fstat(fd, &buf) < 0) { perror(__FUNCTION__ "fstat - cannot fstat file"); exit(1); } setup_range(fd, driver, -1, buf.st_size, buf.st_size); + return 0; } +__uml_setup("iomem=",parse_iomem, +"iomem=,\n" +" Configure as a named IO memory region named .\n\n" +); void map(unsigned long virt, void *p, unsigned long len, int r, int w, int x) diff -Naur -X exclude-files ac_cur/arch/um/kernel/process_kern.c ac/arch/um/kernel/process_kern.c --- ac_cur/arch/um/kernel/process_kern.c Sat Nov 3 16:14:40 2001 +++ ac/arch/um/kernel/process_kern.c Sat Nov 3 16:15:32 2001 @@ -29,6 +29,7 @@ #include "kern.h" #include "signal_kern.h" #include "signal_user.h" +#include "init.h" struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { -1, NULL } }; @@ -737,11 +738,26 @@ return(new); } +static int jail = 0; + +static int __init jail_setup(char *line, int *add) +{ + jail = 1; + *add = 1; + return(0); +} + +__uml_setup("jail", jail_setup, +"jail\n" +" Enables the protection of kernel memory from processes\n\n" +); + void unprotect_kernel_mem(void) { unsigned long start_stack, end_stack; - if(current_task == &init_task) return; + if(!jail) return; + if(current == &init_task) return; start_stack = (unsigned long) current + PAGE_SIZE; end_stack = (unsigned long) current + PAGE_SIZE * 4; protect(uml_physmem, start_stack - uml_physmem, 1, 1, 1); @@ -752,7 +768,8 @@ { unsigned long start_stack, end_stack; - if(current_task == &init_task) return; + if(!jail) return; + if(current == &init_task) return; start_stack = (unsigned long) current + PAGE_SIZE; end_stack = (unsigned long) current + PAGE_SIZE * 4; protect(uml_physmem, start_stack - uml_physmem, 1, 0, 1); diff -Naur -X exclude-files ac_cur/arch/um/kernel/trap_kern.c ac/arch/um/kernel/trap_kern.c --- ac_cur/arch/um/kernel/trap_kern.c Sat Nov 3 16:14:09 2001 +++ ac/arch/um/kernel/trap_kern.c Sat Nov 3 16:15:32 2001 @@ -305,6 +305,30 @@ return(pid); } +#ifdef notdef /* Put this back in when it does something useful */ +static int __init uml_gdb_init_setup(char *line, int *add) +{ + gdb_init = line; + return 0; +} + +__uml_setup("gdb=", uml_gdb_init_setup, +"gdb=\n\n" +); +#endif + +static int __init uml_gdb_pid_setup(char *line, int *add) +{ + gdb_pid = simple_strtoul(line, NULL, 0); + return 0; +} + +__uml_setup("gdb-pid=", uml_gdb_pid_setup, +"gdb-pid=\n" +" gdb-pid is used to attach an external debugger to UML. This may be\n" +" an already-running gdb or a debugger-like process like strace.\n\n" +); + #else void debugger_signal(int status, pid_t pid){ } diff -Naur -X exclude-files ac_cur/arch/um/kernel/trap_user.c ac/arch/um/kernel/trap_user.c --- ac_cur/arch/um/kernel/trap_user.c Sat Nov 3 16:14:09 2001 +++ ac/arch/um/kernel/trap_user.c Sat Nov 3 16:15:32 2001 @@ -25,6 +25,7 @@ #include "user.h" #include "process.h" #include "sysdep/sigcontext.h" +#include "init.h" static void signal_segv(int sig) { @@ -283,6 +284,31 @@ return(0); } +static int __init uml_debugtrace_setup(char *line, int *add) +{ + debug_trace = 1; + return 0; +} +__uml_setup("debugtrace=",uml_debugtrace_setup, +"debugtrace\n" +" Causes the tracing thread to pause until it is attached by a\n" +" debugger and continued. This is mostly for debugging crashes\n" +" early during boot, and should be pretty much obsoleted by\n" +" the debug switch.\n\n" +); + +static int __init uml_honeypot_setup(char *line, int *add) +{ + honeypot = 1; + return 0; +} +__uml_setup("honeypot", uml_honeypot_setup, +"honeypot\n" +" This makes UML put process stacks in the same location as they are\n" +" on the host, allowing expoits such as stack smashes to work against\n" +" UML.\n\n" +); + int nsegfaults = 0; void segv_handler(int sig, void *sc, int usermode) @@ -377,6 +403,22 @@ irq_handler(sig, sc); timer_ready = 1; } + +static int __init uml_debug_setup(char *line, int *add) +{ + debug = 1; + if(!strcmp(line, "=go")){ + debug_stop = 0; + *add = 0; + } + return 0; +} +__uml_setup("debug",uml_debug_setup, +"debug\n" +" Starts up the kernel under the control of gdb. See the \n" +" kernel debugging tutorial and the debugging session pages\n" +" at http://user-mode-linux.sourceforge.net/ for more information.\n\n" +); void do_longjmp(void *p) { diff -Naur -X exclude-files ac_cur/arch/um/kernel/um_arch.c ac/arch/um/kernel/um_arch.c --- ac_cur/arch/um/kernel/um_arch.c Sat Nov 3 16:14:40 2001 +++ ac/arch/um/kernel/um_arch.c Sat Nov 3 16:15:32 2001 @@ -12,9 +12,6 @@ #include "linux/bootmem.h" #include "linux/spinlock.h" #include "linux/utsname.h" -#ifdef CONFIG_BLK_DEV_INITRD -#include "linux/blk.h" -#endif #include "asm/page.h" #include "asm/pgtable.h" #include "asm/ptrace.h" @@ -30,6 +27,8 @@ #include "mprot.h" #include "mem_user.h" #include "umid.h" +#include "initrd.h" +#include "init.h" extern __u64 file_size(char *file); @@ -128,6 +127,9 @@ static char *argv1_begin = NULL; static char *argv1_end = NULL; +static int have_root __initdata = 0; +long physmem_size = 32 * 1024 * 1024; + void set_cmdline(char *cmd) { if(honeypot) return; @@ -139,78 +141,89 @@ } static char *usage_string = -"User Mode Linux v%s" -" available at http://user-mode-linux.sourceforge.net/\n\n" -"--help\n Prints this message\n" -"--version\n Gives the version number of the kernel\n" +"User Mode Linux v%s\n" +" available at http://user-mode-linux.sourceforge.net/\n\n"; + +static int __init uml_version_setup(char *line, int *add) +{ + printf("%s\n", system_utsname.release); + exit(0); +} + +__uml_setup("--version", uml_version_setup, +"--version\n" +" Prints the version number of the kernel\n\n" +); + +static int __init uml_root_setup(char *line, int *add) +{ + have_root = 1; + return 0; +} +__uml_setup("root=", uml_root_setup, "root=\n" " This is actually used by the generic kernel in exactly the same\n" " way as in any other kernel. If you configure a number of block\n" " devices and want to boot off something other than ubd0, you \n" " would use something like:\n" " root=/dev/ubd5\n\n" -"mem=\n" -" This controls how much \"physical\" memory the kernel allocates\n" -" for the system. The size is specified as a number followed by\n" -" one of 'k', 'K', 'm', 'M', which have the obvious meanings.\n" -" This is not related to the amount of memory in the physical\n" -" machine. It can be more, and the excess, if it's ever used, will\n" -" just be swapped out.\n Example: mem=64M\n\n" +); + #ifdef CONFIG_SMP +__uml_setup("ncpus=", uml_ncpus_setup, "ncpus=<# of desired CPUs>\n" " This tells an SMP kernel how many virtual processors to start.\n" " Currently, this has no effect because SMP isn't enabled.\n\n" +); #endif -"debugtrace\n" -" Causes the tracing thread to pause until it is attached by a\n" -" debugger and continued. This is mostly for debugging crashes\n" -" early during boot, and should be pretty much obsoleted by\n" -" the debug switch.\n\n" -"debug\n" -" Starts up the kernel under the control of gdb. See the \n" -" kernel debugging tutorial and the debugging session pages\n" -" at http://user-mode-linux.sourceforge.net/ for more information\n\n" -"umn=\n" -" This sets the ip address of the host side of the slip device \n" -" that the umn device configures. This is necessary if you want\n" -" to set up networking, but your local net isn't 192.168.0.x,\n" -" or you want to run multiple virtual machines on a network,\n" -" in which case, you need to assign different ip addresses to the\n" -" different machines.\n\n" -"ubd=\n" -" This is used to associate a device with a file in the underlying\n" -" filesystem. Usually, there is a filesystem in the file, but \n" -" that's not required. Swap devices containing swap files can be\n" -" specified like this. Also, a file which doesn't contain a\n" -" filesystem can have its contents read in the virtual \n" -" machine by running dd on the device. n must be in the range\n" -" 0 to 7. Appending an 'r' to the number will cause that device\n" -" to be mounted read-only. For example ubd1r=./ext_fs\n\n" -"umid=\n" -" This is used to assign a unique identity to this UML machine\n" -" Used for naming the pid file and console socket\n"; -static void Usage(void) +static int __init Usage(char *line, int *add) { + const char **p; + printf(usage_string, system_utsname.release); + p = &__uml_help_start; + while (p < &__uml_help_end) { + printf("%s", *p); + p++; + } exit(0); } -#ifdef CONFIG_BLK_DEV_INITRD -static void read_initrd(char *initrd) +__uml_setup("--help", Usage, +"--help\n" +" Prints this message\n\n" +); + +static int __init uml_checksetup(char *line, int *add) { - void *area; - int size; + struct uml_param *p; - size = file_size(initrd); - if(size < 0) return; - area = alloc_bootmem(size); - if(area == NULL) return; - if(load_initrd(initrd, area, size) == -1) return; - initrd_start = (unsigned long) area; - initrd_end = initrd_start + size; + p = &__uml_setup_start; + while(p < &__uml_setup_end) { + int n; + + n = strlen(p->str); + if(!strncmp(line, p->str, n)){ + if (p->setup_func(line + n, add)) + return 1; + } + p++; + } + return 0; +} + +static void __init uml_postsetup(void) +{ + initcall_t *p; + + p = &__uml_postsetup_start; + while(p < &__uml_postsetup_end){ + (*p)(); + p++; + } + return; } -#endif extern unsigned long _stext, _etext, _sdata, _edata, __bss_start, _end; extern int debug_trace; @@ -218,14 +231,10 @@ int linux_main(int argc, char **argv) { unsigned long start_pfn, end_pfn, bootmap_size; - unsigned long physmem_size, virtmem_size; - unsigned int i, have_root, add; - char *retptr; + unsigned long virtmem_size; + unsigned int i, add; void *sp; void *brk_start; -#ifdef CONFIG_BLK_DEV_INITRD - char *initrd = NULL; -#endif remap_data(ROUND_DOWN(&_stext), ROUND_UP(&_etext)); remap_data(ROUND_DOWN(&_sdata), ROUND_UP(&_edata)); @@ -235,57 +244,10 @@ /* Start physical memory at least 4M after the current brk */ uml_physmem = ROUND_4M(brk_start) + (1 << 22); - /* Create fake command line from argv[]. */ - have_root = 0; - physmem_size = 32 * 1024 * 1024; - virtmem_size = physmem_size; for (i = 1; i < argc; i++){ if((i == 1) && (argv[i][0] == ' ')) continue; add = 1; - if(!strncmp(argv[i], "root=", strlen("root="))) have_root = 1; - else if(!strncmp(argv[i], "mem=", strlen("mem="))) - physmem_size = memparse(argv[i] + strlen("mem="), - &retptr); -#ifdef CONFIG_SMP - else if(!strncmp(argv[i], "ncpus=", strlen("ncpus="))) - ncpus = strtoul(argv[i] + strlen("ncpus="), NULL, 10); -#endif - else if(!strcmp(argv[i], "debugtrace")) debug_trace = 1; - else if(!strncmp(argv[i], "debug", strlen("debug"))){ - debug = 1; - debug_stop = 1; - if(!strcmp(argv[i], "debug=go")){ - debug_stop = 0; - add = 0; - } - } -#ifdef CONFIG_PT_PROXY - else if(!strncmp(argv[i], "gdb=", strlen("gdb="))) - gdb_init = &argv[i][strlen("gdb=")]; - else if(!strncmp(argv[i], "gdb-pid=", strlen("gdb-pid="))) - gdb_pid = simple_strtoul(&argv[i][strlen("gdb-pid=")], - NULL, 0); -#endif - else if(!strncmp(argv[i], "umid=", strlen("umid="))){ - set_umid(&argv[i][strlen("umid=")]); - } - else if(!strncmp(argv[i], "iomem=", strlen("iomem="))){ - parse_iomem(&argv[i][strlen("iomem=")]); - } - else if(!strcmp(argv[i], "honeypot")){ - honeypot = 1; - } - else if(!strcmp(argv[i], "--version")){ - printf("%s\n", system_utsname.release); - exit(0); - } - else if(!strcmp(argv[i], "--help")){ - Usage(); - } -#ifdef CONFIG_BLK_DEV_INITRD - else if(!strncmp(argv[i], "initrd=", strlen("initrd="))) - initrd = &argv[i][strlen("initrd=")]; -#endif + uml_checksetup(argv[i], &add); if(add) add_arg(saved_command_line, argv[i]); } if(have_root == 0) add_arg(saved_command_line, DEFAULT_COMMAND_LINE); @@ -324,9 +286,7 @@ free_bootmem(__pa(uml_physmem) + bootmap_size, high_physmem - uml_physmem - bootmap_size); -#ifdef CONFIG_BLK_DEV_INITRD - if(initrd != NULL) read_initrd(initrd); -#endif + uml_postsetup(); init_task.thread.kernel_stack = (unsigned long) &init_task + 2 * PAGE_SIZE; #ifndef CONFIG_SMP diff -Naur -X exclude-files ac_cur/arch/um/kernel/umid.c ac/arch/um/kernel/umid.c --- ac_cur/arch/um/kernel/umid.c Sat Nov 3 16:12:55 2001 +++ ac/arch/um/kernel/umid.c Sat Nov 3 16:15:32 2001 @@ -9,49 +9,78 @@ #include #include "user.h" #include "umid.h" +#include "init.h" #define UMID_LEN 64 +#define UML_DIR "/tmp/uml/" static char umid[UMID_LEN] = { 0 }; +static char *uml_dir = UML_DIR; static int umid_inited = 0; -int umid_file_name(char *name, char *buf, int len) +static int make_umid(void); + +static int __init set_umid(char *name, int *add) +{ + if(umid_inited){ + printk("Unique machine name can't be set twice\n"); + return(-1); + } + + if(strlen(name) > UMID_LEN - 1) + printk("Unique machine name is being truncated to %s " + "characters\n", UMID_LEN); + strncpy(umid, name, UMID_LEN - 1); + umid[UMID_LEN - 1] = '\0'; + + umid_inited = 1; + return 0; +} + +__uml_setup("umid=", set_umid, +"umid=\n" +" This is used to assign a unique identity to this UML machine\n" +" This is used for naming the pid file and management console socket\n\n" +); + +int __init umid_file_name(char *name, char *buf, int len) { int n; - if(!umid_inited && set_umid(NULL)) return(-1); + if(!umid_inited && make_umid()) return(-1); - n = sizeof("/tmp/uml") + strlen(umid) + sizeof("/") + strlen(name) + 1; + n = strlen(uml_dir) + strlen(umid) + strlen(name) + 1; if(n > len){ printk("umid_file_name : buffer too short\n"); return(-1); } - sprintf(buf, "/tmp/uml/%s/%s", umid, name); + sprintf(buf, "%s%s/%s", uml_dir, umid, name); return(0); } extern int tracing_pid; -static void create_pid_file(void) +static int __init create_pid_file(void) { - char file[sizeof("/tmp/uml/") + UMID_LEN + sizeof("/pid\0")]; + char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")]; char pid[sizeof("nnnnn\0")]; int fd; - if(umid_file_name("pid", file, sizeof(file))) return; + if(umid_file_name("pid", file, sizeof(file))) return 0; if((fd = open(file, O_RDWR | O_CREAT | O_EXCL, 0644)) < 0){ printk("Open of machine pid file \"%s\" failed - " "errno = %d\n", file, errno); - return; + return 0; } sprintf(pid, "%d\n", (tracing_pid == -1) ? getpid() : tracing_pid); if(write(fd, pid, strlen(pid)) != strlen(pid)) printk("Write of pid file failed - errno = %d\n", errno); close(fd); + return 0; } static int actually_do_remove(char *dir) @@ -93,10 +122,10 @@ void remove_umid_dir(void) { - char dir[sizeof("/tmp/uml/") + UMID_LEN + 1]; + char dir[strlen(uml_dir) + UMID_LEN + 1]; if(!umid_inited) return; - sprintf(dir, "/tmp/uml/%s", umid); + sprintf(dir, "%s%s", uml_dir, umid); actually_do_remove(dir); } @@ -105,9 +134,9 @@ return(umid); } -static int not_dead_yet(char *dir) +int not_dead_yet(char *dir) { - char file[sizeof("/tmp/uml/") + UMID_LEN + sizeof("/pid\0")]; + char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")]; char pid[sizeof("nnnnn\0")], *end; int dead, fd, p; @@ -133,37 +162,54 @@ "errno = %d\n", file, errno); dead = 1; } - if((kill(p, 0) < 0) && (errno == ESRCH)) dead = 1; + if(((kill(p, 0) < 0) && (errno == ESRCH)) || + (p == tracing_pid)) + dead = 1; } if(!dead) return(1); return(actually_do_remove(dir)); return(0); } -int set_umid(char *name) +static int __init set_uml_dir(char *name, int *add) { - int fd, err; - char tmp[sizeof("/tmp/uml/") + UMID_LEN + 1]; - - if(umid_inited){ - printk("Unique machine name can't be set twice\n"); - return(-1); + if((strlen(name) > 0) && (name[strlen(name) - 1] != '/')){ + uml_dir = malloc(strlen(name) + 1); + if(uml_dir == NULL){ + printk("Failed to malloc uml_dir - error = %d\n", + errno); + uml_dir = name; + return(0); + } + sprintf(uml_dir, "%s/", name); } + else uml_dir = name; + return 0; +} - if((mkdir("/tmp/uml", 0777) < 0) && (errno != EEXIST)){ - printk("Failed to create /tmp/uml - errno = %s\n", errno); +static int __init make_uml_dir(void) +{ + if((mkdir(uml_dir, 0777) < 0) && (errno != EEXIST)){ + printk("Failed to mkdir %s - errno = %i\n", uml_dir, errno); return(-1); } + return 0; +} + +static int __init make_umid(void) +{ + int fd, err; + char tmp[strlen(uml_dir) + UMID_LEN + 1]; - strcpy(tmp, "/tmp/uml/"); + strcpy(tmp, uml_dir); - if(name == NULL){ + if(*umid == 0){ strcat(tmp, "XXXXXX"); fd = mkstemp(tmp); if(fd < 0){ printk("set_umid - mkstemp failed, errno = %d\n", errno); - return(-1); + return(1); } close(fd); @@ -172,16 +218,10 @@ * for directories. */ unlink(tmp); - name = &tmp[strlen("/tmp/uml/")]; + strcpy(umid, &tmp[strlen(uml_dir)]); } - - if(strlen(name) > UMID_LEN - 1) - printk("Unique machine name is being truncated to %s " - "characters\n", UMID_LEN); - strncpy(umid, name, UMID_LEN - 1); - umid[UMID_LEN - 1] = '\0'; - sprintf(tmp, "/tmp/uml/%s", umid); + sprintf(tmp, "%s%s", uml_dir, umid); if((err = mkdir(tmp, 0777)) < 0){ if(errno == EEXIST){ @@ -197,10 +237,17 @@ return(-1); } - umid_inited = 1; - create_pid_file(); return(0); } + +__uml_setup("uml_dir=", set_uml_dir, +"uml_dir=\n" +" The location to place the pid and umid files.\n\n" +); + +__uml_postsetup(make_uml_dir); +__uml_postsetup(make_umid); +__uml_postsetup(create_pid_file); /* * Overrides for Emacs so that we follow Linus's tabbing style. diff -Naur -X exclude-files ac_cur/arch/um/kernel/user_util.c ac/arch/um/kernel/user_util.c --- ac_cur/arch/um/kernel/user_util.c Sat Nov 3 16:13:06 2001 +++ ac/arch/um/kernel/user_util.c Sat Nov 3 16:15:32 2001 @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -26,6 +27,7 @@ #include "kern_util.h" #include "user.h" #include "mem_user.h" +#include "init.h" #define COMMAND_LINE_SIZE _POSIX_ARG_MAX @@ -152,22 +154,6 @@ return(buf.st_size); } -int load_initrd(char *filename, void *buf, int size) -{ - int fd, n; - - if((fd = open(filename, O_RDONLY)) == -1){ - printk("Opening '%s' failed - errno = %d\n", filename, errno); - return(-1); - } - if((n = read(fd, buf, size)) != size){ - printk("Read of %d bytes from '%s' returned %d, errno = %d\n", - size, filename, n, errno); - return(-1); - } - return(0); -} - void stop(void) { while(1) sleep(1000000); @@ -323,6 +309,62 @@ void close_fd(int fd) { close(fd); +} + +char *tempdir = NULL; + +static void __init find_tempdir(void) +{ + char *dirs[] = { "TMP", "TEMP", "TMPDIR", NULL }; + int i; + char *dir = NULL; + + if(tempdir != NULL) return; /* We've already been called */ + for(i = 0; dirs[i]; i++){ + dir = getenv(dirs[i]); + if(dir != NULL) break; + } + if(dir == NULL) dir = "/tmp"; + else if(*dir == '\0') dir = NULL; + if(dir != NULL) { + tempdir = malloc(strlen(dir) + 2); + if(tempdir == NULL){ + fprintf(stderr, "Failed to malloc tempdir, " + "errno = %d\n", errno); + return; + } + strcpy(tempdir, dir); + strcat(tempdir, "/"); + } +} + +int make_tempfile(const char *template, char **out_tempname, int do_unlink) +{ + char tempname[MAXPATHLEN]; + int fd; + + find_tempdir(); + if (*template != '/') + strcpy(tempname, tempdir); + else + *tempname = 0; + strcat(tempname, template); + if((fd = mkstemp(tempname)) < 0){ + fprintf(stderr, "open - cannot create %s: %s\n", tempname, + strerror(errno)); + return -1; + } + if(do_unlink && (unlink(tempname) < 0)){ + perror("unlink"); + return -1; + } + if(out_tempname){ + if((*out_tempname = strdup(tempname)) == NULL){ + perror("strdup"); + return -1; + } + } + return(fd); } /* diff -Naur -X exclude-files ac_cur/arch/um/link.ld.in ac/arch/um/link.ld.in --- ac_cur/arch/um/link.ld.in Sat Nov 3 16:12:55 2001 +++ ac/arch/um/link.ld.in Sat Nov 3 16:15:32 2001 @@ -11,27 +11,14 @@ _stext = .; __init_begin = .; .text.init : { *(.text.init) } - .data.init : { *(.data.init) } - . = ALIGN(16); - __setup_start = .; - .setup.init : { *(.setup.init) } - __setup_end = .; - __initcall_start = .; - .initcall.init : { *(.initcall.init) } - __initcall_end = .; . = ALIGN(4096); - __init_end = .; - __exitcall_begin = .; - .exitcall : { *(.exitcall.exit) } - __exitcall_end = .; - .text : { *(.text) /* .gnu.warning sections are handled specially by elf32.em. */ *(.gnu.warning) *(.gnu.linkonce.t*) - } =0x9090 + } .kstrtab : { *(.kstrtab) } . = ALIGN(16); /* Exception table */ @@ -47,13 +34,38 @@ .rodata1 : { *(.rodata1) } _etext = .; PROVIDE (etext = .); - /* Adjust the address for the data segment. We want to adjust up to - the same address within the page on the next page up. */ - . = ALIGN(0x1000) + (. & (0x1000 - 1)); + + . = ALIGN(4096); + PROVIDE (_sdata = .); + __uml_setup_start = .; + .uml.setup.init : { *(.uml.setup.init) } + __uml_setup_end = .; + __uml_help_start = .; + .uml.help.init : { *(.uml.help.init) } + __uml_help_end = .; + __uml_postsetup_start = .; + .uml.postsetup.init : { *(.uml.postsetup.init) } + __uml_postsetup_end = .; + __setup_start = .; + .setup.init : { *(.setup.init) } + __setup_end = .; + __initcall_start = .; + .initcall.init : { *(.initcall.init) } + __initcall_end = .; + __uml_initcall_start = .; + .uml.initcall.init : { *(.uml.initcall.init) } + __uml_initcall_end = .; + __init_end = .; + __exitcall_begin = .; + .exitcall : { *(.exitcall.exit) } + __exitcall_end = .; + __uml_exitcall_begin = .; + .uml.exitcall : { *(.uml.exitcall.exit) } + __uml_exitcall_end = .; + + .data.init : { *(.data.init) } .data : { - _sdata = .; - PROVIDE (sdata = .); . = ALIGN(16384); /* init_task */ *(.data.init_task) *(.data) diff -Naur -X exclude-files ac_cur/arch/um/main.c ac/arch/um/main.c --- ac_cur/arch/um/main.c Sat Nov 3 16:14:09 2001 +++ ac/arch/um/main.c Sat Nov 3 16:15:32 2001 @@ -17,6 +17,7 @@ #include "kern_util.h" #include "mem_user.h" #include "user.h" +#include "init.h" unsigned long stacksizelim; @@ -56,6 +57,16 @@ task_size = host_task_size - 0x20000000; } +static __init void do_uml_initcalls(void) +{ + initcall_t *call; + + call = &__uml_initcall_start; + while (call < &__uml_initcall_end){; + (*call)(); + call++; + } +} int main(int argc, char **argv, char **envp) { struct termios tt; @@ -106,6 +117,7 @@ } new_argv[argc] = NULL; + do_uml_initcalls(); ret = linux_main(argc, argv); /* Reboot */ diff -Naur -X exclude-files ac_cur/arch/um/ptproxy/proxy.c ac/arch/um/ptproxy/proxy.c --- ac_cur/arch/um/ptproxy/proxy.c Sat Nov 3 16:12:55 2001 +++ ac/arch/um/ptproxy/proxy.c Sat Nov 3 16:15:32 2001 @@ -213,8 +213,7 @@ if(err) return(err); slave = CHAN_OUT_FD(gdb_chan); if((child = fork()) == 0){ - char tempname[sizeof("/tmp/gdb_init-XXXXXX")]; - char arg[sizeof("--command=/tmp/gdb_init-XXXXXX")]; + char *tempname = NULL; int fd; if(setsid() < 0) perror("setsid"); @@ -236,13 +235,11 @@ exit(1); #endif } - strcpy(tempname, "/tmp/gdb_init-XXXXXX"); - if((fd = mkstemp(tempname)) < 0){ - printk("start_debugger : mkstmp failed, errno = %d\n", + if((fd = make_tempfile("/tmp/gdb_init-XXXXXX", &tempname, 0)) < 0){ + printk("start_debugger : make_tempfile failed, errno = %d\n", errno); exit(1); } - sprintf(arg, "--command=%s", tempname); write(fd, "att 1\n", strlen("att 1\n")); write(fd, "b panic\n", strlen("b panic\n")); write(fd, "b stop\n", strlen("b stop\n")); @@ -260,7 +257,7 @@ "errno = %d\n", errno); exit(1); } - execlp("gdb", "gdb", arg, prog, NULL); + execlp("gdb", "gdb", "--command", tempname, prog, NULL); printk("start_debugger : exec of gdb failed, errno = %d\n", errno); }