Using linux with kernel 4.4.21, I was required to implement a system call which has a custom struct’s pointer among its parameters. These are the files to to edit:
JavaScript
x
// in linux-4.4.21/arch/x86/entry/syscalls/syscall_64.tbl :
546 x32 procmem sys_procmem
// in linux-4.4.21/include/linux/syscalls.h :
struct proc_segs;
asmlinkage longsys_procmem (int pid, struct proc_segs *info);
I put sys_procmem.c (implementation) in linux-4.4.21/kernel/sys_procmem.c (sys_procmem.o added in that dir’s Makefile):
JavaScript
#include <linux/linkage.h>
#include <linux/sched.h>
#include <linux/kernel.h>
struct proc_segs
{
unsigned long stID;
};
asmlinkage long sys_procmem (int pid, struct proc_segs *info)
{
printk("sys_procmem called n"); // this is fine in dmesg
info->stID = 1234567; // KILLED
return 0;
}
Test:
JavaScript
#include <sys/syscall.h>
#include <unistd.h>
#include <stdio.h>
struct proc_segs
{
unsigned long stID;
};
int main() {
unsigned long info[10];
long sysval = syscall(546, 1, info);
printf("My stID : %lun", info[0]);
} // I have no idea why this works (or not on me), but it was included in the excercise's manual
//or:
int main() {
struct proc_segs info;
syscall(546, getpid(), &info);
printf("My stID : %lun", info.stID);
}
Both were killed miserably.
dmesg:
JavaScript
[ 3298.944925] sys_procmem called
[ 3298.944997] BUG: unable to handle kernel paging request at 00007ffe570aa8e0
[ 3298.945005] IP: [<ffffffff8109d540>] sys_procmem+0x140/0x280
[ 3298.945017] PGD 7a919067 PUD 790a6067 PMD 7a82f067 PTE 800000004c530867
[ 3298.945027] Oops: 0003 [#2] SMP
[ 3298.945047] Modules linked in: bnep rfcomm bluetooth btrfs xor qxl raid6_pq snd_hda_codec_generic ttm snd_hda_intel snd_hda_codec kvm_intel drm_kms_helper snd_hda_core kvm drm snd_hwdep snd_pcm snd_seq_midi snd_seq_midi_event snd_rawmidi snd_seq snd_seq_device irqbypass snd_timer crct10dif_pclmul snd crc32_pclmul aesni_intel aes_x86_64 fb_sys_fops lrw syscopyarea glue_helper soundcore sysfillrect ablk_helper sysimgblt joydev lpc_ich cryptd input_leds serio_raw mac_hid parport_pc ppdev lp parport hid_generic usbhid hid e1000e psmouse ahci libahci virtio_blk
[ 3298.945122] CPU: 5 PID: 2752 Comm: test-procmem Tainted: G D 4.4.21.1810887 #13
[ 3298.945126] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS ?-20191223_100556-anatol 04/01/2014
[ 3298.945130] task: ffff88002c1e96c0 ti: ffff880079f68000 task.ti: ffff880079f68000
[ 3298.945134] RIP: 0010:[<ffffffff8109d540>] [<ffffffff8109d540>] sys_procmem+0x140/0x280
[ 3298.945142] RSP: 0018:ffff880079f6bf38 EFLAGS: 00010282
[ 3298.945145] RAX: 0000000000000024 RBX: ffff88013bb98000 RCX: 0000000000000006
[ 3298.945148] RDX: 0000000000000000 RSI: 0000000000000246 RDI: ffff88013fd4db30
[ 3298.945151] RBP: ffff880079f6bf48 R08: 000000000000000a R09: 0000000000000000
[ 3298.945154] R10: 0000000000000000 R11: 0000000000000304 R12: 00007ffe570aa8e0
[ 3298.945157] R13: 00007ffe570aaa10 R14: 0000000000000000 R15: 0000000000000000
[ 3298.945161] FS: 00007fe88da41740(0000) GS:ffff88013fd40000(0000) knlGS:0000000000000000
[ 3298.945165] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 3298.945168] CR2: 00007ffe570aa8e0 CR3: 000000007acb0000 CR4: 00000000003406e0
[ 3298.945177] Stack:
[ 3298.945180] 0000000000000000 0000000000400490 00007ffe570aa930 ffffffff817e7676
[ 3298.945187] 0000000000000000 0000000000000000 00007ffe570aaa10 0000000000000000
[ 3298.945196] 0000000000000000 00007fe88d82d6c8 0000000000000202 00007fe88d82ee80
[ 3298.945205] Call Trace:
[ 3298.945229] [<ffffffff817e7676>] entry_SYSCALL_64_fastpath+0x16/0x75
[ 3298.945234] Code: 00 48 8b b0 08 01 00 00 31 c0 e8 69 b6 0d 00 48 8b 83 48 07 00 00 48 c7 c7 e4 51 aa 81 48 8b b0 18 01 00 00 31 c0 e8 4d b6 0d 00 <49> c7 04 24 c7 a1 1b 00 48 c7 c7 01 52 aa 81 31 c0 e8 37 b6 0d
[ 3298.945315] RIP [<ffffffff8109d540>] sys_procmem+0x140/0x280
[ 3298.945322] RSP <ffff880079f6bf38>
[ 3298.945325] CR2: 00007ffe570aa8e0
[ 3298.945330] ---[ end trace 0b79468970c7e49f ]---
This was done inside a 64-bit Ubuntu 14.04 virtual machine. My friends had no problems when they use VirtualBox or VMWare Player, mine was KVM/QEMU (although the instructor advised us to use the former two explicitly, kernel compilation was indeed faster with KVM). Does a different hypervisor have anything to do with this?
Advertisement
Answer
Thanks to the comments. I have added copy_from_user
and copy_to_user
.
Now it works.
JavaScript
#include <linux/uaccess.h>
// struct definition
asmlinkage long sys_procmem (int pid, struct proc_segs *info)
{
printk("sys_procmem called n");
struct proc_segs temp_info;
copy_from_user(&temp_info, info, sizeof(struct proc_segs));
info->stID = 1234567;
copy_to_user(info, &temp_info, sizeof(struct proc_segs));
return 0;
}