***************************************************************************** * MAKING A NEW SYSTEM CALL MODULE * * * * * * Copyright (c) 2001 Daniel P. Bovet, Marco Cesati, and Cosimo Comella * * Permission is granted to copy, distribute and/or modify this document * * under the terms of the GNU Free Documentation License, Version 1.1, * * published by the Free Software Foundation; with no Invariant Sections, * * with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the * * license is included in the file named LICENSE. * * * * (version 1.1) * ***************************************************************************** We shall use as example the same cacheset() system call that was implemented statically inside the kernel (see patch 2.4.5kh2). ***************************************************************************** STEP 0: set the proper EXTRAVERSION value in Makefile ***************************************************************************** replace: EXTRAVERSION = with: EXTRAVERSION = kh5 ***************************************************************************** STEP 1: modify the linux/arch-i386/config.in file ***************************************************************************** a) add right after: bool ' Verbose BUG() reporting (adds 70K)' CONFIG_DEBUG_BUGVERBOSE the following line: tristate 'Hardware cache disabling' CONFIG_HWCACHE_DISABLE ***************************************************************************** STEP 2: Add a new kernel hacking configuration option ***************************************************************************** a) add right after: Magic System Request Key support CONFIG_MAGIC_SYSRQ If you say Y here, you will have some control over the system even if the system crashes for example during kernel debugging (e.g., you will be able to flush the buffer cache to disk, reboot the system immediately or dump some status information). This is accomplished by pressing various keys while holding SysRq (Alt+PrintScreen). It also works on a serial console (on PC hardware at least), if you send a BREAK and then within 5 seconds a command keypress. The keys are documented in Documentation/sysrq.txt. Don't say Y unless you really know what this hack does. the following lines: Hardware cache disabling support CONFIG_HWCACHE_DISABLE If you say Y here, you will have some control over the CPU hardware cache. More precisely, a new system call denoted as cacheset() may be issued by programs with root privilege to enable or disable the CPU hardware cache. b) run menuconfig and select the CONFIG_HWCACHE_DISABLE option in the kernel hacking menu c) recompile the kernel and check whether the help for the new option is correctly displayed d) read the include/linux/autoconf.h file to see whether CONFIG_HWCACHE_DISABLE is properly defined **************************************************************************** STEP 3: create a new directory linux/new_syscalls which will contain the new object file of the service routine sys_cacheset.o ***************************************************************************** a) mkdir new_syscalls ***************************************************************************** STEP 4: modify the main linux/Makefile ***************************************************************************** a) replace CORE_FILES =kernel/kernel.o mm/mm.o fs/fs.o ipc/ipc.o with: CORE_FILES =kernel/kernel.o mm/mm.o fs/fs.o ipc/ipc.o new_syscalls/new_syscalls.o b) replace SUBDIRS =kernel drivers mm fs net ipc lib line with: SUBDIRS =kernel drivers mm fs net ipc lib new_syscalls ***************************************************************************** STEP 5: Reserve a number for the new system call ***************************************************************************** a) add the following lines in the include/asm-i386/unistd.h file: #if defined(CONFIG_HWCACHE_DISABLE) || defined(CONFIG_HWCACHE_DISABLE_MODULE) #define __NR_cacheset 225 #endif ***************************************************************************** STEP 6: Add new exported symbol in kernel/ksyms.c ***************************************************************************** add right after: EXPORT_SYMBOL(pidhash); the following lines: /* implementing new system call as a module */ #ifdef CONFIG_HWCACHE_DISABLE_MODULE extern int sys_ni_syscall(void); EXPORT_SYMBOL(sys_ni_syscall); #endif ***************************************************************************** STEP 7: Create the Makefile for the linux/new_syscalls file ***************************************************************************** # # Makefile for linux/new_syscalls # # Note: dependencies are done automatically by "make dep", which also removes # any old dependency. DON'T put your own dependencies ere unless it's something # special (ie not a .c file). # # Note2: the CFLAGS definition is now in the main Makefile... # O_TARGET := new_syscalls.o obj-m := obj-y := ifeq ($(CONFIG_HWCACHE_DISABLE),y) obj-y += sys_cacheset.o else ifeq ($(CONFIG_HWCACHE_DISABLE),m) obj-m += sys_cacheset.o endif endif include $(TOPDIR)/Rules.make ***************************************************************************** STEP 8: Add the sys_cacheset service routine in the new_syscalls directory ***************************************************************************** /* */ /* linux/new_syscalls/sys_cacheset.c */ /* */ /* This file contains the service routine of sys_cacheset() */ /* */ #include #include #include #include #include #include #include unsigned long cacheset_clear, cacheset_or; extern long sys_call_table[]; extern int sys_ni_syscall(void); asmlinkage int sys_cacheset(int cd, int nw) { int retcode = 0; #ifdef MODULE MOD_INC_USE_COUNT; #endif if (!capable(CAP_SYS_ADMIN)) { retcode = -EPERM; goto out; } if ((cd == 0) && (nw == 0)) cacheset_or = 0x00000000; else if ((cd == 1) && (nw == 0)) cacheset_or = 0x40000000; else if ((cd == 1) && (nw == 1)) cacheset_or = 0x60000000; else { printk("<1>invalid sys_cacheset parameters\n"); retcode = -1; goto out; } cacheset_clear = 0x9fffffff; /* AND mask used to reset flags cd and nw */ asm("pushl %eax\n\t" "movl %cr0,%eax\n\t" "andl cacheset_clear,%eax\n\t" "orl cacheset_or,%eax\n\t" "movl %eax,%cr0\n\t" "popl %eax"); out: #ifdef MODULE MOD_DEC_USE_COUNT; #endif return retcode; } #ifdef MODULE int init_module(void) { EXPORT_NO_SYMBOLS; printk("cacheset module loaded\n"); (char *)sys_call_table [__NR_cacheset] = sys_cacheset; return 0; } int cleanup_module(void) { (char *)sys_call_table[__NR_cacheset] = sys_ni_syscall; printk("cacheset module unloaded\n"); return 0; } #endif ***************************************************************************** STEP 9: Test the module system call ***************************************************************************** a) run make menuconfig and set to 'm' the CONFIG_HWCACHE_DISABLE kernel hackers option b) run make dep, recompile the kernel and copy the arch/i386/boot/bzImage in /boot/vmlinuz-2.4.12kh5 or on a floppy c) run make modules and make modules_install d) run lilo and reboot the system and select linux-2.4.12kh5 as the system to boot e) login as root and insert the module: insmod /usr/src/linux/new_syscalls/sys_cacheset.o or: modprobe sys_cacheset f) test whether it has been loaded correctly by typing: lsmod sys_cacheset.o If everything is OK, you should get the following answer: Module Size Used by sys_cacheset 840 0 (unused) g) switch to user and run /tmp/Cprogs/Tcacheset 0 0 h) back to superuser, type: rmmod sys_cacheset; lsmod You will get: Module Size Used by i) Switch again to user run /tmp/Cprogs/Tcacheset 0 0: you will get: argc value: 3 cd value: 0 nw value: 0 return value of sys_cacheset(): ffffffff because the cacheset system call no longer exists