Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'for-linus-4.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/uml

Pull UML updates from Richard Weinberger:

- remove hppfs ("HonePot ProcFS")

- initial support for musl libc

- uaccess cleanup

- random cleanups and bug fixes all over the place

* 'for-linus-4.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/uml: (21 commits)
um: Don't pollute kernel namespace with uapi
um: Include sys/types.h for makedev(), major(), minor()
um: Do not use stdin and stdout identifiers for struct members
um: Do not use __ptr_t type for stack_t's .ss pointer
um: Fix mconsole dependency
um: Handle tracehook_report_syscall_entry() result
um: Remove copy&paste code from init.h
um: Stop abusing __KERNEL__
um: Catch unprotected user memory access
um: Fix warning in setup_signal_stack_si()
um: Rework uaccess code
um: Add uaccess.h to ldt.c
um: Add uaccess.h to syscalls_64.c
um: Add asm/elf.h to vma.c
um: Cleanup mem_32/64.c headers
um: Remove hppfs
um: Move syscall() declaration into os.h
um: kernel: ksyms: Export symbol syscall() for fixing modpost issue
um/os-Linux: Use char[] for syscall_stub declarations
um: Use char[] for linker script address declarations
...

+154 -1063
+1 -15
arch/um/Kconfig.um
··· 44 44 If you'd like to be able to work with files stored on the host, 45 45 say Y or M here; otherwise say N. 46 46 47 - config HPPFS 48 - tristate "HoneyPot ProcFS" 49 - depends on PROC_FS 50 - help 51 - hppfs (HoneyPot ProcFS) is a filesystem which allows UML /proc 52 - entries to be overridden, removed, or fabricated from the host. 53 - Its purpose is to allow a UML to appear to be a physical machine 54 - by removing or changing anything in /proc which gives away the 55 - identity of a UML. 56 - 57 - See <http://user-mode-linux.sf.net/old/hppfs.html> for more information. 58 - 59 - You only need this if you are setting up a UML honeypot. Otherwise, 60 - it is safe to say 'N' here. 61 - 62 47 config MCONSOLE 63 48 bool "Management console" 49 + depends on PROC_FS 64 50 default y 65 51 help 66 52 The user mode linux management console is a low-level interface to
+4 -3
arch/um/Makefile
··· 68 68 69 69 KBUILD_AFLAGS += $(ARCH_INCLUDE) 70 70 71 - USER_CFLAGS = $(patsubst $(KERNEL_DEFINES),,$(patsubst -D__KERNEL__,,\ 72 - $(patsubst -I%,,$(KBUILD_CFLAGS)))) $(ARCH_INCLUDE) $(MODE_INCLUDE) \ 73 - $(filter -I%,$(CFLAGS)) -D_FILE_OFFSET_BITS=64 -idirafter include 71 + USER_CFLAGS = $(patsubst $(KERNEL_DEFINES),,$(patsubst -I%,,$(KBUILD_CFLAGS))) \ 72 + $(ARCH_INCLUDE) $(MODE_INCLUDE) $(filter -I%,$(CFLAGS)) \ 73 + -D_FILE_OFFSET_BITS=64 -idirafter include \ 74 + -D__KERNEL__ -D__UM_HOST__ 74 75 75 76 #This will adjust *FLAGS accordingly to the platform. 76 77 include $(ARCH_DIR)/Makefile-os-$(OS)
+9 -9
arch/um/drivers/harddog_user.c
··· 9 9 #include <os.h> 10 10 11 11 struct dog_data { 12 - int stdin; 13 - int stdout; 12 + int stdin_fd; 13 + int stdout_fd; 14 14 int close_me[2]; 15 15 }; 16 16 ··· 18 18 { 19 19 struct dog_data *data = d; 20 20 21 - dup2(data->stdin, 0); 22 - dup2(data->stdout, 1); 23 - dup2(data->stdout, 2); 24 - close(data->stdin); 25 - close(data->stdout); 21 + dup2(data->stdin_fd, 0); 22 + dup2(data->stdout_fd, 1); 23 + dup2(data->stdout_fd, 2); 24 + close(data->stdin_fd); 25 + close(data->stdout_fd); 26 26 close(data->close_me[0]); 27 27 close(data->close_me[1]); 28 28 } ··· 49 49 goto out_close_in; 50 50 } 51 51 52 - data.stdin = out_fds[0]; 53 - data.stdout = in_fds[1]; 52 + data.stdin_fd = out_fds[0]; 53 + data.stdout_fd = in_fds[1]; 54 54 data.close_me[0] = out_fds[1]; 55 55 data.close_me[1] = in_fds[0]; 56 56
+1 -1
arch/um/drivers/mconsole.h
··· 7 7 #ifndef __MCONSOLE_H__ 8 8 #define __MCONSOLE_H__ 9 9 10 - #ifndef __KERNEL__ 10 + #ifdef __UM_HOST__ 11 11 #include <stdint.h> 12 12 #define u32 uint32_t 13 13 #endif
+3 -3
arch/um/drivers/net_user.c
··· 166 166 167 167 struct change_pre_exec_data { 168 168 int close_me; 169 - int stdout; 169 + int stdout_fd; 170 170 }; 171 171 172 172 static void change_pre_exec(void *arg) ··· 174 174 struct change_pre_exec_data *data = arg; 175 175 176 176 close(data->close_me); 177 - dup2(data->stdout, 1); 177 + dup2(data->stdout_fd, 1); 178 178 } 179 179 180 180 static int change_tramp(char **argv, char *output, int output_len) ··· 189 189 return err; 190 190 } 191 191 pe_data.close_me = fds[0]; 192 - pe_data.stdout = fds[1]; 192 + pe_data.stdout_fd = fds[1]; 193 193 pid = run_helper(change_pre_exec, &pe_data, argv); 194 194 195 195 if (pid > 0) /* Avoid hang as we won't get data in failure case. */
+7 -7
arch/um/drivers/slip_user.c
··· 55 55 } 56 56 57 57 struct slip_pre_exec_data { 58 - int stdin; 59 - int stdout; 58 + int stdin_fd; 59 + int stdout_fd; 60 60 int close_me; 61 61 }; 62 62 ··· 64 64 { 65 65 struct slip_pre_exec_data *data = arg; 66 66 67 - if (data->stdin >= 0) 68 - dup2(data->stdin, 0); 69 - dup2(data->stdout, 1); 67 + if (data->stdin_fd >= 0) 68 + dup2(data->stdin_fd, 0); 69 + dup2(data->stdout_fd, 1); 70 70 if (data->close_me >= 0) 71 71 close(data->close_me); 72 72 } ··· 85 85 } 86 86 87 87 err = 0; 88 - pe_data.stdin = fd; 89 - pe_data.stdout = fds[1]; 88 + pe_data.stdin_fd = fd; 89 + pe_data.stdout_fd = fds[1]; 90 90 pe_data.close_me = fds[0]; 91 91 err = run_helper(slip_pre_exec, &pe_data, argv); 92 92 if (err < 0)
+8 -8
arch/um/drivers/slirp_user.c
··· 20 20 } 21 21 22 22 struct slirp_pre_exec_data { 23 - int stdin; 24 - int stdout; 23 + int stdin_fd; 24 + int stdout_fd; 25 25 }; 26 26 27 27 static void slirp_pre_exec(void *arg) 28 28 { 29 29 struct slirp_pre_exec_data *data = arg; 30 30 31 - if (data->stdin != -1) 32 - dup2(data->stdin, 0); 33 - if (data->stdout != -1) 34 - dup2(data->stdout, 1); 31 + if (data->stdin_fd != -1) 32 + dup2(data->stdin_fd, 0); 33 + if (data->stdout_fd != -1) 34 + dup2(data->stdout_fd, 1); 35 35 } 36 36 37 37 static int slirp_tramp(char **argv, int fd) ··· 39 39 struct slirp_pre_exec_data pe_data; 40 40 int pid; 41 41 42 - pe_data.stdin = fd; 43 - pe_data.stdout = fd; 42 + pe_data.stdin_fd = fd; 43 + pe_data.stdout_fd = fd; 44 44 pid = run_helper(slirp_pre_exec, &pe_data, argv); 45 45 46 46 return pid;
-1
arch/um/include/asm/Kbuild
··· 21 21 generic-y += pci.h 22 22 generic-y += percpu.h 23 23 generic-y += preempt.h 24 - generic-y += sections.h 25 24 generic-y += switch_to.h 26 25 generic-y += topology.h 27 26 generic-y += trace_clock.h
+1 -2
arch/um/include/asm/ptrace-generic.h
··· 8 8 9 9 #ifndef __ASSEMBLY__ 10 10 11 - #include <asm/ptrace-abi.h> 12 11 #include <sysdep/ptrace.h> 13 12 14 13 struct pt_regs { ··· 36 37 37 38 extern int arch_copy_tls(struct task_struct *new); 38 39 extern void clear_flushed_tls(struct task_struct *task); 39 - extern void syscall_trace_enter(struct pt_regs *regs); 40 + extern int syscall_trace_enter(struct pt_regs *regs); 40 41 extern void syscall_trace_leave(struct pt_regs *regs); 41 42 42 43 #endif
+9
arch/um/include/asm/sections.h
··· 1 + #ifndef __UM_SECTIONS_H 2 + #define __UM_SECTIONS_H 3 + 4 + #include <asm-generic/sections.h> 5 + 6 + extern char __binary_start[]; 7 + extern char __syscall_stub_start[], __syscall_stub_end[]; 8 + 9 + #endif
+1 -1
arch/um/include/asm/thread_info.h
··· 10 10 11 11 #include <asm/types.h> 12 12 #include <asm/page.h> 13 - #include <asm/uaccess.h> 13 + #include <asm/segment.h> 14 14 15 15 struct thread_info { 16 16 struct task_struct *task; /* main task structure */
+24 -150
arch/um/include/asm/uaccess.h
··· 1 1 /* 2 2 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) 3 + * Copyright (C) 2015 Richard Weinberger (richard@nod.at) 3 4 * Licensed under the GPL 4 5 */ 5 6 6 7 #ifndef __UM_UACCESS_H 7 8 #define __UM_UACCESS_H 8 9 9 - /* thread_info has a mm_segment_t in it, so put the definition up here */ 10 - typedef struct { 11 - unsigned long seg; 12 - } mm_segment_t; 13 - 14 - #include <linux/thread_info.h> 15 - #include <linux/errno.h> 16 - #include <asm/processor.h> 10 + #include <asm/thread_info.h> 17 11 #include <asm/elf.h> 18 - 19 - #define VERIFY_READ 0 20 - #define VERIFY_WRITE 1 21 - 22 - /* 23 - * The fs value determines whether argument validity checking should be 24 - * performed or not. If get_fs() == USER_DS, checking is performed, with 25 - * get_fs() == KERNEL_DS, checking is bypassed. 26 - * 27 - * For historical reasons, these macros are grossly misnamed. 28 - */ 29 - 30 - #define MAKE_MM_SEG(s) ((mm_segment_t) { (s) }) 31 - 32 - #define KERNEL_DS MAKE_MM_SEG(0xFFFFFFFF) 33 - #define USER_DS MAKE_MM_SEG(TASK_SIZE) 34 - 35 - #define get_ds() (KERNEL_DS) 36 - #define get_fs() (current_thread_info()->addr_limit) 37 - #define set_fs(x) (current_thread_info()->addr_limit = (x)) 38 - 39 - #define segment_eq(a, b) ((a).seg == (b).seg) 40 12 41 13 #define __under_task_size(addr, size) \ 42 14 (((unsigned long) (addr) < TASK_SIZE) && \ 43 15 (((unsigned long) (addr) + (size)) < TASK_SIZE)) 44 16 45 - #define __access_ok_vsyscall(type, addr, size) \ 46 - ((type == VERIFY_READ) && \ 47 - ((unsigned long) (addr) >= FIXADDR_USER_START) && \ 17 + #define __access_ok_vsyscall(addr, size) \ 18 + (((unsigned long) (addr) >= FIXADDR_USER_START) && \ 48 19 ((unsigned long) (addr) + (size) <= FIXADDR_USER_END) && \ 49 20 ((unsigned long) (addr) + (size) >= (unsigned long)(addr))) 50 21 51 22 #define __addr_range_nowrap(addr, size) \ 52 23 ((unsigned long) (addr) <= ((unsigned long) (addr) + (size))) 53 24 54 - #define access_ok(type, addr, size) \ 55 - (__addr_range_nowrap(addr, size) && \ 56 - (__under_task_size(addr, size) || \ 57 - __access_ok_vsyscall(type, addr, size) || \ 58 - segment_eq(get_fs(), KERNEL_DS))) 25 + extern long __copy_from_user(void *to, const void __user *from, unsigned long n); 26 + extern long __copy_to_user(void __user *to, const void *from, unsigned long n); 27 + extern long __strncpy_from_user(char *dst, const char __user *src, long count); 28 + extern long __strnlen_user(const void __user *str, long len); 29 + extern unsigned long __clear_user(void __user *mem, unsigned long len); 30 + static inline int __access_ok(unsigned long addr, unsigned long size); 59 31 60 - extern int copy_from_user(void *to, const void __user *from, int n); 61 - extern int copy_to_user(void __user *to, const void *from, int n); 62 - 63 - /* 64 - * strncpy_from_user: - Copy a NUL terminated string from userspace. 65 - * @dst: Destination address, in kernel space. This buffer must be at 66 - * least @count bytes long. 67 - * @src: Source address, in user space. 68 - * @count: Maximum number of bytes to copy, including the trailing NUL. 69 - * 70 - * Copies a NUL-terminated string from userspace to kernel space. 71 - * 72 - * On success, returns the length of the string (not including the trailing 73 - * NUL). 74 - * 75 - * If access to userspace fails, returns -EFAULT (some data may have been 76 - * copied). 77 - * 78 - * If @count is smaller than the length of the string, copies @count bytes 79 - * and returns @count. 80 - */ 81 - 82 - extern int strncpy_from_user(char *dst, const char __user *src, int count); 83 - 84 - /* 85 - * __clear_user: - Zero a block of memory in user space, with less checking. 86 - * @to: Destination address, in user space. 87 - * @n: Number of bytes to zero. 88 - * 89 - * Zero a block of memory in user space. Caller must check 90 - * the specified block with access_ok() before calling this function. 91 - * 92 - * Returns number of bytes that could not be cleared. 93 - * On success, this will be zero. 94 - */ 95 - extern int __clear_user(void __user *mem, int len); 96 - 97 - /* 98 - * clear_user: - Zero a block of memory in user space. 99 - * @to: Destination address, in user space. 100 - * @n: Number of bytes to zero. 101 - * 102 - * Zero a block of memory in user space. 103 - * 104 - * Returns number of bytes that could not be cleared. 105 - * On success, this will be zero. 106 - */ 107 - extern int clear_user(void __user *mem, int len); 108 - 109 - /* 110 - * strlen_user: - Get the size of a string in user space. 111 - * @str: The string to measure. 112 - * @n: The maximum valid length 113 - * 114 - * Get the size of a NUL-terminated string in user space. 115 - * 116 - * Returns the size of the string INCLUDING the terminating NUL. 117 - * On exception, returns 0. 118 - * If the string is too long, returns a value greater than @n. 119 - */ 120 - extern int strnlen_user(const void __user *str, int len); 121 - 122 - #define __copy_from_user(to, from, n) copy_from_user(to, from, n) 123 - 124 - #define __copy_to_user(to, from, n) copy_to_user(to, from, n) 125 - 32 + /* Teach asm-generic/uaccess.h that we have C functions for these. */ 33 + #define __access_ok __access_ok 34 + #define __clear_user __clear_user 35 + #define __copy_to_user __copy_to_user 36 + #define __copy_from_user __copy_from_user 37 + #define __strnlen_user __strnlen_user 38 + #define __strncpy_from_user __strncpy_from_user 126 39 #define __copy_to_user_inatomic __copy_to_user 127 40 #define __copy_from_user_inatomic __copy_from_user 128 41 129 - #define __get_user(x, ptr) \ 130 - ({ \ 131 - const __typeof__(*(ptr)) __user *__private_ptr = (ptr); \ 132 - __typeof__(x) __private_val; \ 133 - int __private_ret = -EFAULT; \ 134 - (x) = (__typeof__(*(__private_ptr)))0; \ 135 - if (__copy_from_user((__force void *)&__private_val, (__private_ptr),\ 136 - sizeof(*(__private_ptr))) == 0) { \ 137 - (x) = (__typeof__(*(__private_ptr))) __private_val; \ 138 - __private_ret = 0; \ 139 - } \ 140 - __private_ret; \ 141 - }) 42 + #include <asm-generic/uaccess.h> 142 43 143 - #define get_user(x, ptr) \ 144 - ({ \ 145 - const __typeof__((*(ptr))) __user *private_ptr = (ptr); \ 146 - (access_ok(VERIFY_READ, private_ptr, sizeof(*private_ptr)) ? \ 147 - __get_user(x, private_ptr) : ((x) = (__typeof__(*ptr))0, -EFAULT)); \ 148 - }) 149 - 150 - #define __put_user(x, ptr) \ 151 - ({ \ 152 - __typeof__(*(ptr)) __user *__private_ptr = ptr; \ 153 - __typeof__(*(__private_ptr)) __private_val; \ 154 - int __private_ret = -EFAULT; \ 155 - __private_val = (__typeof__(*(__private_ptr))) (x); \ 156 - if (__copy_to_user((__private_ptr), &__private_val, \ 157 - sizeof(*(__private_ptr))) == 0) { \ 158 - __private_ret = 0; \ 159 - } \ 160 - __private_ret; \ 161 - }) 162 - 163 - #define put_user(x, ptr) \ 164 - ({ \ 165 - __typeof__(*(ptr)) __user *private_ptr = (ptr); \ 166 - (access_ok(VERIFY_WRITE, private_ptr, sizeof(*private_ptr)) ? \ 167 - __put_user(x, private_ptr) : -EFAULT); \ 168 - }) 169 - 170 - #define strlen_user(str) strnlen_user(str, ~0U >> 1) 171 - 172 - struct exception_table_entry 44 + static inline int __access_ok(unsigned long addr, unsigned long size) 173 45 { 174 - unsigned long insn; 175 - unsigned long fixup; 176 - }; 46 + return __addr_range_nowrap(addr, size) && 47 + (__under_task_size(addr, size) || 48 + __access_ok_vsyscall(addr, size) || 49 + segment_eq(get_fs(), KERNEL_DS)); 50 + } 177 51 178 52 #endif
+2 -22
arch/um/include/shared/init.h
··· 40 40 typedef int (*initcall_t)(void); 41 41 typedef void (*exitcall_t)(void); 42 42 43 - #ifndef __KERNEL__ 44 - #ifndef __section 45 - # define __section(S) __attribute__ ((__section__(#S))) 46 - #endif 47 - 48 - #if __GNUC__ == 3 49 - 50 - #if __GNUC_MINOR__ >= 3 51 - # define __used __attribute__((__used__)) 52 - #else 53 - # define __used __attribute__((__unused__)) 54 - #endif 55 - 56 - #else 57 - #if __GNUC__ == 4 58 - # define __used __attribute__((__used__)) 59 - #endif 60 - #endif 61 - 62 - #else 63 43 #include <linux/compiler.h> 64 - #endif 44 + 65 45 /* These are for everybody (although not all archs will actually 66 46 discard it in modules) */ 67 47 #define __init __section(.init.text) ··· 111 131 #define __uml_postsetup_call __used __section(.uml.postsetup.init) 112 132 #define __uml_exit_call __used __section(.uml.exitcall.exit) 113 133 114 - #ifndef __KERNEL__ 134 + #ifdef __UM_HOST__ 115 135 116 136 #define __define_initcall(level,fn) \ 117 137 static initcall_t __initcall_##fn __used \
+2
arch/um/include/shared/os.h
··· 301 301 /* sys-$ARCH/task_size.c */ 302 302 extern unsigned long os_get_top_address(void); 303 303 304 + long syscall(long number, ...); 305 + 304 306 #endif
+1 -1
arch/um/include/shared/user.h
··· 17 17 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) 18 18 19 19 /* This is to get size_t */ 20 - #ifdef __KERNEL__ 20 + #ifndef __UM_HOST__ 21 21 #include <linux/types.h> 22 22 #else 23 23 #include <stddef.h>
+2
arch/um/kernel/ksyms.c
··· 42 42 EXPORT_SYMBOL(add_sigio_fd); 43 43 EXPORT_SYMBOL(ignore_sigio_fd); 44 44 EXPORT_SYMBOL(sigio_broken); 45 + 46 + EXPORT_SYMBOL(syscall);
+3 -4
arch/um/kernel/physmem.c
··· 8 8 #include <linux/mm.h> 9 9 #include <linux/pfn.h> 10 10 #include <asm/page.h> 11 + #include <asm/sections.h> 11 12 #include <as-layout.h> 12 13 #include <init.h> 13 14 #include <kern.h> ··· 55 54 "err = %d\n", virt, fd, offset, len, r, w, x, err); 56 55 } 57 56 } 58 - 59 - extern int __syscall_stub_start; 60 57 61 58 /** 62 59 * setup_physmem() - Setup physical memory for UML ··· 109 110 * Special kludge - This page will be mapped in to userspace processes 110 111 * from physmem_fd, so it needs to be written out there. 111 112 */ 112 - os_seek_file(physmem_fd, __pa(&__syscall_stub_start)); 113 - os_write_file(physmem_fd, &__syscall_stub_start, PAGE_SIZE); 113 + os_seek_file(physmem_fd, __pa(__syscall_stub_start)); 114 + os_write_file(physmem_fd, __syscall_stub_start, PAGE_SIZE); 114 115 os_fsync_file(physmem_fd); 115 116 116 117 bootmap_size = init_bootmem(pfn, pfn + delta);
+4 -3
arch/um/kernel/ptrace.c
··· 8 8 #include <linux/sched.h> 9 9 #include <linux/tracehook.h> 10 10 #include <asm/uaccess.h> 11 + #include <asm/ptrace-abi.h> 11 12 12 13 void user_enable_single_step(struct task_struct *child) 13 14 { ··· 132 131 * XXX Check PT_DTRACE vs TIF_SINGLESTEP for singlestepping check and 133 132 * PT_PTRACED vs TIF_SYSCALL_TRACE for syscall tracing check 134 133 */ 135 - void syscall_trace_enter(struct pt_regs *regs) 134 + int syscall_trace_enter(struct pt_regs *regs) 136 135 { 137 136 audit_syscall_entry(UPT_SYSCALL_NR(&regs->regs), 138 137 UPT_SYSCALL_ARG1(&regs->regs), ··· 141 140 UPT_SYSCALL_ARG4(&regs->regs)); 142 141 143 142 if (!test_thread_flag(TIF_SYSCALL_TRACE)) 144 - return; 143 + return 0; 145 144 146 - tracehook_report_syscall_entry(regs); 145 + return tracehook_report_syscall_entry(regs); 147 146 } 148 147 149 148 void syscall_trace_leave(struct pt_regs *regs)
+3 -4
arch/um/kernel/skas/mmu.c
··· 8 8 #include <linux/slab.h> 9 9 #include <asm/pgalloc.h> 10 10 #include <asm/pgtable.h> 11 + #include <asm/sections.h> 11 12 #include <as-layout.h> 12 13 #include <os.h> 13 14 #include <skas.h> 14 - 15 - extern int __syscall_stub_start; 16 15 17 16 static int init_stub_pte(struct mm_struct *mm, unsigned long proc, 18 17 unsigned long kernel) ··· 92 93 int err, ret; 93 94 94 95 ret = init_stub_pte(mm, STUB_CODE, 95 - (unsigned long) &__syscall_stub_start); 96 + (unsigned long) __syscall_stub_start); 96 97 if (ret) 97 98 goto out; 98 99 ··· 100 101 if (ret) 101 102 goto out; 102 103 103 - mm->context.stub_pages[0] = virt_to_page(&__syscall_stub_start); 104 + mm->context.stub_pages[0] = virt_to_page(__syscall_stub_start); 104 105 mm->context.stub_pages[1] = virt_to_page(mm->context.id.stack); 105 106 106 107 /* dup_mmap already holds mmap_sem */
+5 -1
arch/um/kernel/skas/syscall.c
··· 18 18 long result; 19 19 int syscall; 20 20 21 - syscall_trace_enter(regs); 21 + if (syscall_trace_enter(regs)) { 22 + result = -ENOSYS; 23 + goto out; 24 + } 22 25 23 26 /* 24 27 * This should go in the declaration of syscall, but when I do that, ··· 37 34 result = -ENOSYS; 38 35 else result = EXECUTE_SYSCALL(syscall, regs); 39 36 37 + out: 40 38 PT_REGS_SET_SYSCALL_RETURN(regs, result); 41 39 42 40 syscall_trace_leave(regs);
+17 -30
arch/um/kernel/skas/uaccess.c
··· 87 87 return n; 88 88 } 89 89 90 - static int buffer_op(unsigned long addr, int len, int is_write, 91 - int (*op)(unsigned long, int, void *), void *arg) 90 + static long buffer_op(unsigned long addr, int len, int is_write, 91 + int (*op)(unsigned long, int, void *), void *arg) 92 92 { 93 - int size, remain, n; 93 + long size, remain, n; 94 94 95 95 size = min(PAGE_ALIGN(addr) - addr, (unsigned long) len); 96 96 remain = len; ··· 139 139 return 0; 140 140 } 141 141 142 - int copy_from_user(void *to, const void __user *from, int n) 142 + long __copy_from_user(void *to, const void __user *from, unsigned long n) 143 143 { 144 144 if (segment_eq(get_fs(), KERNEL_DS)) { 145 145 memcpy(to, (__force void*)from, n); 146 146 return 0; 147 147 } 148 148 149 - return access_ok(VERIFY_READ, from, n) ? 150 - buffer_op((unsigned long) from, n, 0, copy_chunk_from_user, &to): 151 - n; 149 + return buffer_op((unsigned long) from, n, 0, copy_chunk_from_user, &to); 152 150 } 153 - EXPORT_SYMBOL(copy_from_user); 151 + EXPORT_SYMBOL(__copy_from_user); 154 152 155 153 static int copy_chunk_to_user(unsigned long to, int len, void *arg) 156 154 { ··· 159 161 return 0; 160 162 } 161 163 162 - int copy_to_user(void __user *to, const void *from, int n) 164 + long __copy_to_user(void __user *to, const void *from, unsigned long n) 163 165 { 164 166 if (segment_eq(get_fs(), KERNEL_DS)) { 165 167 memcpy((__force void *) to, from, n); 166 168 return 0; 167 169 } 168 170 169 - return access_ok(VERIFY_WRITE, to, n) ? 170 - buffer_op((unsigned long) to, n, 1, copy_chunk_to_user, &from) : 171 - n; 171 + return buffer_op((unsigned long) to, n, 1, copy_chunk_to_user, &from); 172 172 } 173 - EXPORT_SYMBOL(copy_to_user); 173 + EXPORT_SYMBOL(__copy_to_user); 174 174 175 175 static int strncpy_chunk_from_user(unsigned long from, int len, void *arg) 176 176 { ··· 184 188 return 0; 185 189 } 186 190 187 - int strncpy_from_user(char *dst, const char __user *src, int count) 191 + long __strncpy_from_user(char *dst, const char __user *src, long count) 188 192 { 189 - int n; 193 + long n; 190 194 char *ptr = dst; 191 195 192 196 if (segment_eq(get_fs(), KERNEL_DS)) { ··· 194 198 return strnlen(dst, count); 195 199 } 196 200 197 - if (!access_ok(VERIFY_READ, src, 1)) 198 - return -EFAULT; 199 - 200 201 n = buffer_op((unsigned long) src, count, 0, strncpy_chunk_from_user, 201 202 &ptr); 202 203 if (n != 0) 203 204 return -EFAULT; 204 205 return strnlen(dst, count); 205 206 } 206 - EXPORT_SYMBOL(strncpy_from_user); 207 + EXPORT_SYMBOL(__strncpy_from_user); 207 208 208 209 static int clear_chunk(unsigned long addr, int len, void *unused) 209 210 { ··· 208 215 return 0; 209 216 } 210 217 211 - int __clear_user(void __user *mem, int len) 212 - { 213 - return buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL); 214 - } 215 - 216 - int clear_user(void __user *mem, int len) 218 + unsigned long __clear_user(void __user *mem, unsigned long len) 217 219 { 218 220 if (segment_eq(get_fs(), KERNEL_DS)) { 219 221 memset((__force void*)mem, 0, len); 220 222 return 0; 221 223 } 222 224 223 - return access_ok(VERIFY_WRITE, mem, len) ? 224 - buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL) : len; 225 + return buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL); 225 226 } 226 - EXPORT_SYMBOL(clear_user); 227 + EXPORT_SYMBOL(__clear_user); 227 228 228 229 static int strnlen_chunk(unsigned long str, int len, void *arg) 229 230 { ··· 231 244 return 0; 232 245 } 233 246 234 - int strnlen_user(const void __user *str, int len) 247 + long __strnlen_user(const void __user *str, long len) 235 248 { 236 249 int count = 0, n; 237 250 ··· 243 256 return count + 1; 244 257 return 0; 245 258 } 246 - EXPORT_SYMBOL(strnlen_user); 259 + EXPORT_SYMBOL(__strnlen_user);
+5
arch/um/kernel/trap.c
··· 220 220 show_regs(container_of(regs, struct pt_regs, regs)); 221 221 panic("Segfault with no mm"); 222 222 } 223 + else if (!is_user && address < TASK_SIZE) { 224 + show_regs(container_of(regs, struct pt_regs, regs)); 225 + panic("Kernel tried to access user memory at addr 0x%lx, ip 0x%lx", 226 + address, ip); 227 + } 223 228 224 229 if (SEGV_IS_FIXABLE(&fi)) 225 230 err = handle_page_fault(address, ip, is_write, is_user,
+1 -3
arch/um/kernel/um_arch.c
··· 248 248 249 249 #define MIN_VMALLOC (32 * 1024 * 1024) 250 250 251 - extern char __binary_start; 252 - 253 251 int __init linux_main(int argc, char **argv) 254 252 { 255 253 unsigned long avail, diff; ··· 292 294 physmem_size += UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end); 293 295 } 294 296 295 - uml_physmem = (unsigned long) &__binary_start & PAGE_MASK; 297 + uml_physmem = (unsigned long) __binary_start & PAGE_MASK; 296 298 297 299 /* Reserve up to 4M after the current brk */ 298 300 uml_reserved = ROUND_4M(brk_start) + (1 << 22);
+3 -3
arch/um/os-Linux/drivers/tuntap_user.c
··· 47 47 } 48 48 49 49 struct tuntap_pre_exec_data { 50 - int stdout; 50 + int stdout_fd; 51 51 int close_me; 52 52 }; 53 53 ··· 55 55 { 56 56 struct tuntap_pre_exec_data *data = arg; 57 57 58 - dup2(data->stdout, 1); 58 + dup2(data->stdout_fd, 1); 59 59 close(data->close_me); 60 60 } 61 61 ··· 74 74 75 75 sprintf(version_buf, "%d", UML_NET_VERSION); 76 76 77 - data.stdout = remote; 77 + data.stdout_fd = remote; 78 78 data.close_me = me; 79 79 80 80 pid = run_helper(tuntap_pre_exec, &data, argv);
+1
arch/um/os-Linux/file.c
··· 13 13 #include <sys/socket.h> 14 14 #include <sys/stat.h> 15 15 #include <sys/un.h> 16 + #include <sys/types.h> 16 17 #include <os.h> 17 18 18 19 static void copy_stat(struct uml_stat *dst, const struct stat64 *src)
+5 -3
arch/um/os-Linux/signal.c
··· 112 112 113 113 void set_sigstack(void *sig_stack, int size) 114 114 { 115 - stack_t stack = ((stack_t) { .ss_flags = 0, 116 - .ss_sp = (__ptr_t) sig_stack, 117 - .ss_size = size - sizeof(void *) }); 115 + stack_t stack = { 116 + .ss_flags = 0, 117 + .ss_sp = sig_stack, 118 + .ss_size = size - sizeof(void *) 119 + }; 118 120 119 121 if (sigaltstack(&stack, NULL) != 0) 120 122 panic("enabling signal stack failed, errno = %d\n", errno);
+3 -3
arch/um/os-Linux/skas/mem.c
··· 18 18 #include <sysdep/ptrace.h> 19 19 #include <sysdep/stub.h> 20 20 21 - extern unsigned long batch_syscall_stub, __syscall_stub_start; 21 + extern char batch_syscall_stub[], __syscall_stub_start[]; 22 22 23 23 extern void wait_stub_done(int pid); 24 24 ··· 38 38 { 39 39 get_safe_registers(syscall_regs, NULL); 40 40 syscall_regs[REGS_IP_INDEX] = STUB_CODE + 41 - ((unsigned long) &batch_syscall_stub - 42 - (unsigned long) &__syscall_stub_start); 41 + ((unsigned long) batch_syscall_stub - 42 + (unsigned long) __syscall_stub_start); 43 43 return 0; 44 44 } 45 45
+4 -4
arch/um/os-Linux/skas/process.c
··· 174 174 handle_syscall(regs); 175 175 } 176 176 177 - extern int __syscall_stub_start; 177 + extern char __syscall_stub_start[]; 178 178 179 179 static int userspace_tramp(void *stack) 180 180 { ··· 197 197 * This has a pte, but it can't be mapped in with the usual 198 198 * tlb_flush mechanism because this is part of that mechanism 199 199 */ 200 - fd = phys_mapping(to_phys(&__syscall_stub_start), &offset); 200 + fd = phys_mapping(to_phys(__syscall_stub_start), &offset); 201 201 addr = mmap64((void *) STUB_CODE, UM_KERN_PAGE_SIZE, 202 202 PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fd, offset); 203 203 if (addr == MAP_FAILED) { ··· 223 223 224 224 unsigned long v = STUB_CODE + 225 225 (unsigned long) stub_segv_handler - 226 - (unsigned long) &__syscall_stub_start; 226 + (unsigned long) __syscall_stub_start; 227 227 228 228 set_sigstack((void *) STUB_DATA, UM_KERN_PAGE_SIZE); 229 229 sigemptyset(&sa.sa_mask); ··· 447 447 /* Set parent's instruction pointer to start of clone-stub */ 448 448 thread_regs[REGS_IP_INDEX] = STUB_CODE + 449 449 (unsigned long) stub_clone_handler - 450 - (unsigned long) &__syscall_stub_start; 450 + (unsigned long) __syscall_stub_start; 451 451 thread_regs[REGS_SP_INDEX] = STUB_DATA + UM_KERN_PAGE_SIZE - 452 452 sizeof(void *); 453 453 #ifdef __SIGNAL_FRAMESIZE
+1
arch/x86/um/asm/checksum.h
··· 3 3 4 4 #include <linux/string.h> 5 5 #include <linux/in6.h> 6 + #include <linux/uaccess.h> 6 7 7 8 /* 8 9 * computes the checksum of a memory block at buff, length len,
-2
arch/x86/um/asm/elf.h
··· 200 200 201 201 typedef struct user_i387_struct elf_fpregset_t; 202 202 203 - #define task_pt_regs(t) (&(t)->thread.regs) 204 - 205 203 struct task_struct; 206 204 207 205 extern int elf_core_copy_fpregs(struct task_struct *t, elf_fpregset_t *fpu);
+2
arch/x86/um/asm/processor.h
··· 28 28 #define cpu_relax() rep_nop() 29 29 #define cpu_relax_lowlatency() cpu_relax() 30 30 31 + #define task_pt_regs(t) (&(t)->thread.regs) 32 + 31 33 #include <asm/processor-generic.h> 32 34 33 35 #endif
+8
arch/x86/um/asm/segment.h
··· 7 7 #define GDT_ENTRY_TLS_MIN host_gdt_entry_tls_min 8 8 #define GDT_ENTRY_TLS_MAX (GDT_ENTRY_TLS_MIN + GDT_ENTRY_TLS_ENTRIES - 1) 9 9 10 + typedef struct { 11 + unsigned long seg; 12 + } mm_segment_t; 13 + 14 + #define MAKE_MM_SEG(s) ((mm_segment_t) { (s) }) 15 + #define KERNEL_DS MAKE_MM_SEG(~0UL) 16 + #define USER_DS MAKE_MM_SEG(TASK_SIZE) 17 + 10 18 #endif
+1
arch/x86/um/ldt.c
··· 6 6 #include <linux/mm.h> 7 7 #include <linux/sched.h> 8 8 #include <linux/slab.h> 9 + #include <linux/uaccess.h> 9 10 #include <asm/unistd.h> 10 11 #include <os.h> 11 12 #include <skas.h>
+1 -2
arch/x86/um/mem_32.c
··· 7 7 */ 8 8 9 9 #include <linux/mm.h> 10 - #include <asm/page.h> 11 - #include <asm/mman.h> 10 + #include <asm/elf.h> 12 11 13 12 static struct vm_area_struct gate_vma; 14 13
+1 -2
arch/x86/um/mem_64.c
··· 1 1 #include <linux/mm.h> 2 - #include <asm/page.h> 3 - #include <asm/mman.h> 2 + #include <asm/elf.h> 4 3 5 4 const char *arch_vma_name(struct vm_area_struct *vma) 6 5 {
+1
arch/x86/um/ptrace_32.c
··· 6 6 #include <linux/mm.h> 7 7 #include <linux/sched.h> 8 8 #include <asm/uaccess.h> 9 + #include <asm/ptrace-abi.h> 9 10 #include <skas.h> 10 11 11 12 extern int arch_switch_tls(struct task_struct *to);
+1
arch/x86/um/ptrace_64.c
··· 11 11 #define __FRAME_OFFSETS 12 12 #include <asm/ptrace.h> 13 13 #include <asm/uaccess.h> 14 + #include <asm/ptrace-abi.h> 14 15 15 16 /* 16 17 * determines which flags the user has access to.
+3 -3
arch/x86/um/shared/sysdep/tls.h
··· 1 1 #ifndef _SYSDEP_TLS_H 2 2 #define _SYSDEP_TLS_H 3 3 4 - # ifndef __KERNEL__ 4 + #ifdef __UM_HOST__ 5 5 6 6 /* Change name to avoid conflicts with the original one from <asm/ldt.h>, which 7 7 * may be named user_desc (but in 2.4 and in header matching its API was named ··· 22 22 #endif 23 23 } user_desc_t; 24 24 25 - # else /* __KERNEL__ */ 25 + #else /* __UM_HOST__ */ 26 26 27 27 typedef struct user_desc user_desc_t; 28 28 29 - # endif /* __KERNEL__ */ 29 + #endif /* __UM_HOST__ */ 30 30 31 31 extern int os_set_thread_area(user_desc_t *info, int pid); 32 32 extern int os_get_thread_area(user_desc_t *info, int pid);
+2 -1
arch/x86/um/signal.c
··· 541 541 */ 542 542 /* x86-64 should always use SA_RESTORER. */ 543 543 if (ksig->ka.sa.sa_flags & SA_RESTORER) 544 - err |= __put_user(ksig->ka.sa.sa_restorer, &frame->pretcode); 544 + err |= __put_user((void *)ksig->ka.sa.sa_restorer, 545 + &frame->pretcode); 545 546 else 546 547 /* could use a vstub here */ 547 548 return err;
+1
arch/x86/um/syscalls_64.c
··· 6 6 */ 7 7 8 8 #include <linux/sched.h> 9 + #include <linux/uaccess.h> 9 10 #include <asm/prctl.h> /* XXX This should get the constants from libc */ 10 11 #include <os.h> 11 12
+1
arch/x86/um/tls_32.c
··· 7 7 #include <linux/sched.h> 8 8 #include <linux/syscalls.h> 9 9 #include <asm/uaccess.h> 10 + #include <asm/ptrace-abi.h> 10 11 #include <os.h> 11 12 #include <skas.h> 12 13 #include <sysdep/tls.h>
+1
arch/x86/um/tls_64.c
··· 1 1 #include <linux/sched.h> 2 + #include <asm/ptrace-abi.h> 2 3 3 4 void clear_flushed_tls(struct task_struct *task) 4 5 {
+1
arch/x86/um/vdso/vma.c
··· 10 10 #include <linux/sched.h> 11 11 #include <linux/mm.h> 12 12 #include <asm/page.h> 13 + #include <asm/elf.h> 13 14 #include <linux/init.h> 14 15 15 16 static unsigned int __read_mostly vdso_enabled = 1;
-1
fs/Makefile
··· 115 115 obj-$(CONFIG_NILFS2_FS) += nilfs2/ 116 116 obj-$(CONFIG_BEFS_FS) += befs/ 117 117 obj-$(CONFIG_HOSTFS) += hostfs/ 118 - obj-$(CONFIG_HPPFS) += hppfs/ 119 118 obj-$(CONFIG_CACHEFILES) += cachefiles/ 120 119 obj-$(CONFIG_DEBUG_FS) += debugfs/ 121 120 obj-$(CONFIG_TRACING) += tracefs/
-6
fs/hppfs/Makefile
··· 1 - # 2 - # Copyright (C) 2002 - 2008 Jeff Dike (jdike@{addtoit,linux.intel}.com) 3 - # Licensed under the GPL 4 - # 5 - 6 - obj-$(CONFIG_HPPFS) += hppfs.o
-765
fs/hppfs/hppfs.c
··· 1 - /* 2 - * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) 3 - * Licensed under the GPL 4 - */ 5 - 6 - #include <linux/ctype.h> 7 - #include <linux/dcache.h> 8 - #include <linux/file.h> 9 - #include <linux/fs.h> 10 - #include <linux/init.h> 11 - #include <linux/kernel.h> 12 - #include <linux/list.h> 13 - #include <linux/module.h> 14 - #include <linux/mount.h> 15 - #include <linux/slab.h> 16 - #include <linux/statfs.h> 17 - #include <linux/types.h> 18 - #include <linux/pid_namespace.h> 19 - #include <linux/namei.h> 20 - #include <asm/uaccess.h> 21 - #include <os.h> 22 - 23 - static struct inode *get_inode(struct super_block *, struct dentry *); 24 - 25 - struct hppfs_data { 26 - struct list_head list; 27 - char contents[PAGE_SIZE - sizeof(struct list_head)]; 28 - }; 29 - 30 - struct hppfs_private { 31 - struct file *proc_file; 32 - int host_fd; 33 - loff_t len; 34 - struct hppfs_data *contents; 35 - }; 36 - 37 - struct hppfs_inode_info { 38 - struct dentry *proc_dentry; 39 - struct inode vfs_inode; 40 - }; 41 - 42 - static inline struct hppfs_inode_info *HPPFS_I(struct inode *inode) 43 - { 44 - return container_of(inode, struct hppfs_inode_info, vfs_inode); 45 - } 46 - 47 - #define HPPFS_SUPER_MAGIC 0xb00000ee 48 - 49 - static const struct super_operations hppfs_sbops; 50 - 51 - static int is_pid(struct dentry *dentry) 52 - { 53 - struct super_block *sb; 54 - int i; 55 - 56 - sb = dentry->d_sb; 57 - if (dentry->d_parent != sb->s_root) 58 - return 0; 59 - 60 - for (i = 0; i < dentry->d_name.len; i++) { 61 - if (!isdigit(dentry->d_name.name[i])) 62 - return 0; 63 - } 64 - return 1; 65 - } 66 - 67 - static char *dentry_name(struct dentry *dentry, int extra) 68 - { 69 - struct dentry *parent; 70 - char *root, *name; 71 - const char *seg_name; 72 - int len, seg_len, root_len; 73 - 74 - len = 0; 75 - parent = dentry; 76 - while (parent->d_parent != parent) { 77 - if (is_pid(parent)) 78 - len += strlen("pid") + 1; 79 - else len += parent->d_name.len + 1; 80 - parent = parent->d_parent; 81 - } 82 - 83 - root = "proc"; 84 - root_len = strlen(root); 85 - len += root_len; 86 - name = kmalloc(len + extra + 1, GFP_KERNEL); 87 - if (name == NULL) 88 - return NULL; 89 - 90 - name[len] = '\0'; 91 - parent = dentry; 92 - while (parent->d_parent != parent) { 93 - if (is_pid(parent)) { 94 - seg_name = "pid"; 95 - seg_len = strlen(seg_name); 96 - } 97 - else { 98 - seg_name = parent->d_name.name; 99 - seg_len = parent->d_name.len; 100 - } 101 - 102 - len -= seg_len + 1; 103 - name[len] = '/'; 104 - memcpy(&name[len + 1], seg_name, seg_len); 105 - parent = parent->d_parent; 106 - } 107 - memcpy(name, root, root_len); 108 - return name; 109 - } 110 - 111 - static int file_removed(struct dentry *dentry, const char *file) 112 - { 113 - char *host_file; 114 - int extra, fd; 115 - 116 - extra = 0; 117 - if (file != NULL) 118 - extra += strlen(file) + 1; 119 - 120 - host_file = dentry_name(dentry, extra + strlen("/remove")); 121 - if (host_file == NULL) { 122 - printk(KERN_ERR "file_removed : allocation failed\n"); 123 - return -ENOMEM; 124 - } 125 - 126 - if (file != NULL) { 127 - strcat(host_file, "/"); 128 - strcat(host_file, file); 129 - } 130 - strcat(host_file, "/remove"); 131 - 132 - fd = os_open_file(host_file, of_read(OPENFLAGS()), 0); 133 - kfree(host_file); 134 - if (fd > 0) { 135 - os_close_file(fd); 136 - return 1; 137 - } 138 - return 0; 139 - } 140 - 141 - static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry, 142 - unsigned int flags) 143 - { 144 - struct dentry *proc_dentry, *parent; 145 - struct qstr *name = &dentry->d_name; 146 - struct inode *inode; 147 - int err, deleted; 148 - 149 - deleted = file_removed(dentry, NULL); 150 - if (deleted < 0) 151 - return ERR_PTR(deleted); 152 - else if (deleted) 153 - return ERR_PTR(-ENOENT); 154 - 155 - parent = HPPFS_I(ino)->proc_dentry; 156 - mutex_lock(&d_inode(parent)->i_mutex); 157 - proc_dentry = lookup_one_len(name->name, parent, name->len); 158 - mutex_unlock(&d_inode(parent)->i_mutex); 159 - 160 - if (IS_ERR(proc_dentry)) 161 - return proc_dentry; 162 - 163 - err = -ENOMEM; 164 - inode = get_inode(ino->i_sb, proc_dentry); 165 - if (!inode) 166 - goto out; 167 - 168 - d_add(dentry, inode); 169 - return NULL; 170 - 171 - out: 172 - return ERR_PTR(err); 173 - } 174 - 175 - static const struct inode_operations hppfs_file_iops = { 176 - }; 177 - 178 - static ssize_t read_proc(struct file *file, char __user *buf, ssize_t count, 179 - loff_t *ppos, int is_user) 180 - { 181 - ssize_t (*read)(struct file *, char __user *, size_t, loff_t *); 182 - ssize_t n; 183 - 184 - read = file_inode(file)->i_fop->read; 185 - 186 - if (!is_user) 187 - set_fs(KERNEL_DS); 188 - 189 - n = (*read)(file, buf, count, &file->f_pos); 190 - 191 - if (!is_user) 192 - set_fs(USER_DS); 193 - 194 - if (ppos) 195 - *ppos = file->f_pos; 196 - return n; 197 - } 198 - 199 - static ssize_t hppfs_read_file(int fd, char __user *buf, ssize_t count) 200 - { 201 - ssize_t n; 202 - int cur, err; 203 - char *new_buf; 204 - 205 - n = -ENOMEM; 206 - new_buf = kmalloc(PAGE_SIZE, GFP_KERNEL); 207 - if (new_buf == NULL) { 208 - printk(KERN_ERR "hppfs_read_file : kmalloc failed\n"); 209 - goto out; 210 - } 211 - n = 0; 212 - while (count > 0) { 213 - cur = min_t(ssize_t, count, PAGE_SIZE); 214 - err = os_read_file(fd, new_buf, cur); 215 - if (err < 0) { 216 - printk(KERN_ERR "hppfs_read : read failed, " 217 - "errno = %d\n", err); 218 - n = err; 219 - goto out_free; 220 - } else if (err == 0) 221 - break; 222 - 223 - if (copy_to_user(buf, new_buf, err)) { 224 - n = -EFAULT; 225 - goto out_free; 226 - } 227 - n += err; 228 - count -= err; 229 - } 230 - out_free: 231 - kfree(new_buf); 232 - out: 233 - return n; 234 - } 235 - 236 - static ssize_t hppfs_read(struct file *file, char __user *buf, size_t count, 237 - loff_t *ppos) 238 - { 239 - struct hppfs_private *hppfs = file->private_data; 240 - struct hppfs_data *data; 241 - loff_t off; 242 - int err; 243 - 244 - if (hppfs->contents != NULL) { 245 - int rem; 246 - 247 - if (*ppos >= hppfs->len) 248 - return 0; 249 - 250 - data = hppfs->contents; 251 - off = *ppos; 252 - while (off >= sizeof(data->contents)) { 253 - data = list_entry(data->list.next, struct hppfs_data, 254 - list); 255 - off -= sizeof(data->contents); 256 - } 257 - 258 - if (off + count > hppfs->len) 259 - count = hppfs->len - off; 260 - rem = copy_to_user(buf, &data->contents[off], count); 261 - *ppos += count - rem; 262 - if (rem > 0) 263 - return -EFAULT; 264 - } else if (hppfs->host_fd != -1) { 265 - err = os_seek_file(hppfs->host_fd, *ppos); 266 - if (err) { 267 - printk(KERN_ERR "hppfs_read : seek failed, " 268 - "errno = %d\n", err); 269 - return err; 270 - } 271 - err = hppfs_read_file(hppfs->host_fd, buf, count); 272 - if (err < 0) { 273 - printk(KERN_ERR "hppfs_read: read failed: %d\n", err); 274 - return err; 275 - } 276 - count = err; 277 - if (count > 0) 278 - *ppos += count; 279 - } 280 - else count = read_proc(hppfs->proc_file, buf, count, ppos, 1); 281 - 282 - return count; 283 - } 284 - 285 - static ssize_t hppfs_write(struct file *file, const char __user *buf, 286 - size_t len, loff_t *ppos) 287 - { 288 - struct hppfs_private *data = file->private_data; 289 - struct file *proc_file = data->proc_file; 290 - ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *); 291 - 292 - write = file_inode(proc_file)->i_fop->write; 293 - return (*write)(proc_file, buf, len, ppos); 294 - } 295 - 296 - static int open_host_sock(char *host_file, int *filter_out) 297 - { 298 - char *end; 299 - int fd; 300 - 301 - end = &host_file[strlen(host_file)]; 302 - strcpy(end, "/rw"); 303 - *filter_out = 1; 304 - fd = os_connect_socket(host_file); 305 - if (fd > 0) 306 - return fd; 307 - 308 - strcpy(end, "/r"); 309 - *filter_out = 0; 310 - fd = os_connect_socket(host_file); 311 - return fd; 312 - } 313 - 314 - static void free_contents(struct hppfs_data *head) 315 - { 316 - struct hppfs_data *data; 317 - struct list_head *ele, *next; 318 - 319 - if (head == NULL) 320 - return; 321 - 322 - list_for_each_safe(ele, next, &head->list) { 323 - data = list_entry(ele, struct hppfs_data, list); 324 - kfree(data); 325 - } 326 - kfree(head); 327 - } 328 - 329 - static struct hppfs_data *hppfs_get_data(int fd, int filter, 330 - struct file *proc_file, 331 - struct file *hppfs_file, 332 - loff_t *size_out) 333 - { 334 - struct hppfs_data *data, *new, *head; 335 - int n, err; 336 - 337 - err = -ENOMEM; 338 - data = kmalloc(sizeof(*data), GFP_KERNEL); 339 - if (data == NULL) { 340 - printk(KERN_ERR "hppfs_get_data : head allocation failed\n"); 341 - goto failed; 342 - } 343 - 344 - INIT_LIST_HEAD(&data->list); 345 - 346 - head = data; 347 - *size_out = 0; 348 - 349 - if (filter) { 350 - while ((n = read_proc(proc_file, data->contents, 351 - sizeof(data->contents), NULL, 0)) > 0) 352 - os_write_file(fd, data->contents, n); 353 - err = os_shutdown_socket(fd, 0, 1); 354 - if (err) { 355 - printk(KERN_ERR "hppfs_get_data : failed to shut down " 356 - "socket\n"); 357 - goto failed_free; 358 - } 359 - } 360 - while (1) { 361 - n = os_read_file(fd, data->contents, sizeof(data->contents)); 362 - if (n < 0) { 363 - err = n; 364 - printk(KERN_ERR "hppfs_get_data : read failed, " 365 - "errno = %d\n", err); 366 - goto failed_free; 367 - } else if (n == 0) 368 - break; 369 - 370 - *size_out += n; 371 - 372 - if (n < sizeof(data->contents)) 373 - break; 374 - 375 - new = kmalloc(sizeof(*data), GFP_KERNEL); 376 - if (new == 0) { 377 - printk(KERN_ERR "hppfs_get_data : data allocation " 378 - "failed\n"); 379 - err = -ENOMEM; 380 - goto failed_free; 381 - } 382 - 383 - INIT_LIST_HEAD(&new->list); 384 - list_add(&new->list, &data->list); 385 - data = new; 386 - } 387 - return head; 388 - 389 - failed_free: 390 - free_contents(head); 391 - failed: 392 - return ERR_PTR(err); 393 - } 394 - 395 - static struct hppfs_private *hppfs_data(void) 396 - { 397 - struct hppfs_private *data; 398 - 399 - data = kmalloc(sizeof(*data), GFP_KERNEL); 400 - if (data == NULL) 401 - return data; 402 - 403 - *data = ((struct hppfs_private ) { .host_fd = -1, 404 - .len = -1, 405 - .contents = NULL } ); 406 - return data; 407 - } 408 - 409 - static int file_mode(int fmode) 410 - { 411 - if (fmode == (FMODE_READ | FMODE_WRITE)) 412 - return O_RDWR; 413 - if (fmode == FMODE_READ) 414 - return O_RDONLY; 415 - if (fmode == FMODE_WRITE) 416 - return O_WRONLY; 417 - return 0; 418 - } 419 - 420 - static int hppfs_open(struct inode *inode, struct file *file) 421 - { 422 - const struct cred *cred = file->f_cred; 423 - struct hppfs_private *data; 424 - struct path path; 425 - char *host_file; 426 - int err, fd, type, filter; 427 - 428 - err = -ENOMEM; 429 - data = hppfs_data(); 430 - if (data == NULL) 431 - goto out; 432 - 433 - host_file = dentry_name(file->f_path.dentry, strlen("/rw")); 434 - if (host_file == NULL) 435 - goto out_free2; 436 - 437 - path.mnt = inode->i_sb->s_fs_info; 438 - path.dentry = HPPFS_I(inode)->proc_dentry; 439 - 440 - data->proc_file = dentry_open(&path, file_mode(file->f_mode), cred); 441 - err = PTR_ERR(data->proc_file); 442 - if (IS_ERR(data->proc_file)) 443 - goto out_free1; 444 - 445 - type = os_file_type(host_file); 446 - if (type == OS_TYPE_FILE) { 447 - fd = os_open_file(host_file, of_read(OPENFLAGS()), 0); 448 - if (fd >= 0) 449 - data->host_fd = fd; 450 - else 451 - printk(KERN_ERR "hppfs_open : failed to open '%s', " 452 - "errno = %d\n", host_file, -fd); 453 - 454 - data->contents = NULL; 455 - } else if (type == OS_TYPE_DIR) { 456 - fd = open_host_sock(host_file, &filter); 457 - if (fd > 0) { 458 - data->contents = hppfs_get_data(fd, filter, 459 - data->proc_file, 460 - file, &data->len); 461 - if (!IS_ERR(data->contents)) 462 - data->host_fd = fd; 463 - } else 464 - printk(KERN_ERR "hppfs_open : failed to open a socket " 465 - "in '%s', errno = %d\n", host_file, -fd); 466 - } 467 - kfree(host_file); 468 - 469 - file->private_data = data; 470 - return 0; 471 - 472 - out_free1: 473 - kfree(host_file); 474 - out_free2: 475 - free_contents(data->contents); 476 - kfree(data); 477 - out: 478 - return err; 479 - } 480 - 481 - static int hppfs_dir_open(struct inode *inode, struct file *file) 482 - { 483 - const struct cred *cred = file->f_cred; 484 - struct hppfs_private *data; 485 - struct path path; 486 - int err; 487 - 488 - err = -ENOMEM; 489 - data = hppfs_data(); 490 - if (data == NULL) 491 - goto out; 492 - 493 - path.mnt = inode->i_sb->s_fs_info; 494 - path.dentry = HPPFS_I(inode)->proc_dentry; 495 - data->proc_file = dentry_open(&path, file_mode(file->f_mode), cred); 496 - err = PTR_ERR(data->proc_file); 497 - if (IS_ERR(data->proc_file)) 498 - goto out_free; 499 - 500 - file->private_data = data; 501 - return 0; 502 - 503 - out_free: 504 - kfree(data); 505 - out: 506 - return err; 507 - } 508 - 509 - static loff_t hppfs_llseek(struct file *file, loff_t off, int where) 510 - { 511 - struct hppfs_private *data = file->private_data; 512 - struct file *proc_file = data->proc_file; 513 - loff_t (*llseek)(struct file *, loff_t, int); 514 - loff_t ret; 515 - 516 - llseek = file_inode(proc_file)->i_fop->llseek; 517 - if (llseek != NULL) { 518 - ret = (*llseek)(proc_file, off, where); 519 - if (ret < 0) 520 - return ret; 521 - } 522 - 523 - return default_llseek(file, off, where); 524 - } 525 - 526 - static int hppfs_release(struct inode *inode, struct file *file) 527 - { 528 - struct hppfs_private *data = file->private_data; 529 - struct file *proc_file = data->proc_file; 530 - if (proc_file) 531 - fput(proc_file); 532 - kfree(data); 533 - return 0; 534 - } 535 - 536 - static const struct file_operations hppfs_file_fops = { 537 - .owner = NULL, 538 - .llseek = hppfs_llseek, 539 - .read = hppfs_read, 540 - .write = hppfs_write, 541 - .open = hppfs_open, 542 - .release = hppfs_release, 543 - }; 544 - 545 - struct hppfs_dirent { 546 - struct dir_context ctx; 547 - struct dir_context *caller; 548 - struct dentry *dentry; 549 - }; 550 - 551 - static int hppfs_filldir(struct dir_context *ctx, const char *name, int size, 552 - loff_t offset, u64 inode, unsigned int type) 553 - { 554 - struct hppfs_dirent *dirent = 555 - container_of(ctx, struct hppfs_dirent, ctx); 556 - 557 - if (file_removed(dirent->dentry, name)) 558 - return 0; 559 - 560 - dirent->caller->pos = dirent->ctx.pos; 561 - return !dir_emit(dirent->caller, name, size, inode, type); 562 - } 563 - 564 - static int hppfs_readdir(struct file *file, struct dir_context *ctx) 565 - { 566 - struct hppfs_private *data = file->private_data; 567 - struct file *proc_file = data->proc_file; 568 - struct hppfs_dirent d = { 569 - .ctx.actor = hppfs_filldir, 570 - .caller = ctx, 571 - .dentry = file->f_path.dentry 572 - }; 573 - int err; 574 - proc_file->f_pos = ctx->pos; 575 - err = iterate_dir(proc_file, &d.ctx); 576 - ctx->pos = d.ctx.pos; 577 - return err; 578 - } 579 - 580 - static const struct file_operations hppfs_dir_fops = { 581 - .owner = NULL, 582 - .iterate = hppfs_readdir, 583 - .open = hppfs_dir_open, 584 - .llseek = default_llseek, 585 - .release = hppfs_release, 586 - }; 587 - 588 - static int hppfs_statfs(struct dentry *dentry, struct kstatfs *sf) 589 - { 590 - sf->f_blocks = 0; 591 - sf->f_bfree = 0; 592 - sf->f_bavail = 0; 593 - sf->f_files = 0; 594 - sf->f_ffree = 0; 595 - sf->f_type = HPPFS_SUPER_MAGIC; 596 - return 0; 597 - } 598 - 599 - static struct inode *hppfs_alloc_inode(struct super_block *sb) 600 - { 601 - struct hppfs_inode_info *hi; 602 - 603 - hi = kmalloc(sizeof(*hi), GFP_KERNEL); 604 - if (!hi) 605 - return NULL; 606 - 607 - hi->proc_dentry = NULL; 608 - inode_init_once(&hi->vfs_inode); 609 - return &hi->vfs_inode; 610 - } 611 - 612 - void hppfs_evict_inode(struct inode *ino) 613 - { 614 - clear_inode(ino); 615 - dput(HPPFS_I(ino)->proc_dentry); 616 - mntput(ino->i_sb->s_fs_info); 617 - } 618 - 619 - static void hppfs_i_callback(struct rcu_head *head) 620 - { 621 - struct inode *inode = container_of(head, struct inode, i_rcu); 622 - kfree(HPPFS_I(inode)); 623 - } 624 - 625 - static void hppfs_destroy_inode(struct inode *inode) 626 - { 627 - call_rcu(&inode->i_rcu, hppfs_i_callback); 628 - } 629 - 630 - static const struct super_operations hppfs_sbops = { 631 - .alloc_inode = hppfs_alloc_inode, 632 - .destroy_inode = hppfs_destroy_inode, 633 - .evict_inode = hppfs_evict_inode, 634 - .statfs = hppfs_statfs, 635 - }; 636 - 637 - static int hppfs_readlink(struct dentry *dentry, char __user *buffer, 638 - int buflen) 639 - { 640 - struct dentry *proc_dentry = HPPFS_I(d_inode(dentry))->proc_dentry; 641 - return d_inode(proc_dentry)->i_op->readlink(proc_dentry, buffer, 642 - buflen); 643 - } 644 - 645 - static const char *hppfs_follow_link(struct dentry *dentry, void **cookie) 646 - { 647 - struct dentry *proc_dentry = HPPFS_I(d_inode(dentry))->proc_dentry; 648 - 649 - return d_inode(proc_dentry)->i_op->follow_link(proc_dentry, cookie); 650 - } 651 - 652 - static void hppfs_put_link(struct inode *inode, void *cookie) 653 - { 654 - struct inode *proc_inode = d_inode(HPPFS_I(inode)->proc_dentry); 655 - 656 - if (proc_inode->i_op->put_link) 657 - proc_inode->i_op->put_link(proc_inode, cookie); 658 - } 659 - 660 - static const struct inode_operations hppfs_dir_iops = { 661 - .lookup = hppfs_lookup, 662 - }; 663 - 664 - static const struct inode_operations hppfs_link_iops = { 665 - .readlink = hppfs_readlink, 666 - .follow_link = hppfs_follow_link, 667 - .put_link = hppfs_put_link, 668 - }; 669 - 670 - static struct inode *get_inode(struct super_block *sb, struct dentry *dentry) 671 - { 672 - struct inode *proc_ino = d_inode(dentry); 673 - struct inode *inode = new_inode(sb); 674 - 675 - if (!inode) { 676 - dput(dentry); 677 - return NULL; 678 - } 679 - 680 - if (d_is_dir(dentry)) { 681 - inode->i_op = &hppfs_dir_iops; 682 - inode->i_fop = &hppfs_dir_fops; 683 - } else if (d_is_symlink(dentry)) { 684 - inode->i_op = &hppfs_link_iops; 685 - inode->i_fop = &hppfs_file_fops; 686 - } else { 687 - inode->i_op = &hppfs_file_iops; 688 - inode->i_fop = &hppfs_file_fops; 689 - } 690 - 691 - HPPFS_I(inode)->proc_dentry = dentry; 692 - 693 - inode->i_uid = proc_ino->i_uid; 694 - inode->i_gid = proc_ino->i_gid; 695 - inode->i_atime = proc_ino->i_atime; 696 - inode->i_mtime = proc_ino->i_mtime; 697 - inode->i_ctime = proc_ino->i_ctime; 698 - inode->i_ino = proc_ino->i_ino; 699 - inode->i_mode = proc_ino->i_mode; 700 - set_nlink(inode, proc_ino->i_nlink); 701 - inode->i_size = proc_ino->i_size; 702 - inode->i_blocks = proc_ino->i_blocks; 703 - 704 - return inode; 705 - } 706 - 707 - static int hppfs_fill_super(struct super_block *sb, void *d, int silent) 708 - { 709 - struct inode *root_inode; 710 - struct vfsmount *proc_mnt; 711 - int err = -ENOENT; 712 - 713 - proc_mnt = mntget(task_active_pid_ns(current)->proc_mnt); 714 - if (IS_ERR(proc_mnt)) 715 - goto out; 716 - 717 - sb->s_blocksize = 1024; 718 - sb->s_blocksize_bits = 10; 719 - sb->s_magic = HPPFS_SUPER_MAGIC; 720 - sb->s_op = &hppfs_sbops; 721 - sb->s_fs_info = proc_mnt; 722 - 723 - err = -ENOMEM; 724 - root_inode = get_inode(sb, dget(proc_mnt->mnt_root)); 725 - sb->s_root = d_make_root(root_inode); 726 - if (!sb->s_root) 727 - goto out_mntput; 728 - 729 - return 0; 730 - 731 - out_mntput: 732 - mntput(proc_mnt); 733 - out: 734 - return(err); 735 - } 736 - 737 - static struct dentry *hppfs_read_super(struct file_system_type *type, 738 - int flags, const char *dev_name, 739 - void *data) 740 - { 741 - return mount_nodev(type, flags, data, hppfs_fill_super); 742 - } 743 - 744 - static struct file_system_type hppfs_type = { 745 - .owner = THIS_MODULE, 746 - .name = "hppfs", 747 - .mount = hppfs_read_super, 748 - .kill_sb = kill_anon_super, 749 - .fs_flags = 0, 750 - }; 751 - MODULE_ALIAS_FS("hppfs"); 752 - 753 - static int __init init_hppfs(void) 754 - { 755 - return register_filesystem(&hppfs_type); 756 - } 757 - 758 - static void __exit exit_hppfs(void) 759 - { 760 - unregister_filesystem(&hppfs_type); 761 - } 762 - 763 - module_init(init_hppfs) 764 - module_exit(exit_hppfs) 765 - MODULE_LICENSE("GPL");