Dynamic Kernel Patching: Adding Custom System-Calls to Linux, Slides of Computer Applications

A step-by-step guide on how to add custom system-calls to the linux kernel without editing and recompiling it. It covers the concept of system-calls, the 'open source' philosophy, linux modules as an alternative, and the process of changing the jump-table to install your own system-call function. It also includes instructions on finding the sys_call_table and exporting it to other modules.

Typology: Slides

2012/2013

Uploaded on 04/17/2013

pamelaaaa
pamelaaaa 🇮🇳

4.5

(12)

103 documents

1 / 30

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
‘Dynamic’ kernel patching
How you could add your own
system-calls to Linux without
editing and recompiling the kernel
Docsity.com
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12
pf13
pf14
pf15
pf16
pf17
pf18
pf19
pf1a
pf1b
pf1c
pf1d
pf1e

Partial preview of the text

Download Dynamic Kernel Patching: Adding Custom System-Calls to Linux and more Slides Computer Applications in PDF only on Docsity!

‘Dynamic’ kernel patching

How you could add your own system-calls to Linux without editing and recompiling the kernel

System calls

  • System Calls are the basic OS mechanism for providing privileged kernel services to application programs (e.g., fork(), clone(), execve(), read(), write(), signal(), getpid(), waitpid(), gettimeofday(), setitimer(), etc.)
  • Linux implements over 300 system calls
  • To understand how system calls work, we can try creating one of our own design

Alternative to edit/recompile

  • Linux modules offer an alternative method for modifying the OS kernel’s functionality
  • It’s safer -- and vastly more convenient – since error-recovery only needs a reboot, and minimal system knowledge suffices
  • The main hurdle to be overcome concerns the issue of ‘linking’ module code to some non-exported Linux kernel data-structures

Invoking kernel services

application program

user-mode (restricted privileges) (^) (unrestricted privileges)kernel-mode

standard runtime libraries

call ret

Linux kernel

int 0x iret

installable module

call ret

Assembly language (.data)

.section .data

sys_call_table:

.long sys_restart_syscall .long sys_exit .long sys_fork .long sys_read .long sys_write // …etc (from ‘arch/i386/kernel/entry.S’)

The ‘jump-table’ idea

sys_restart_syscall sys_exit sys_fork sys_read sys_write sys_open sys_close

…etc…

sys_call_table 0 .section .text

1 2 3 4 5 6 7

Changing the jump-table

  • To install our own system-call function, we just need to change an entry in the Linux ‘sys_call_table[]’ array, so it points to our own module function, but save the former entry somewhere (so we can restore it if we remove our module from the kernel)
  • But we first need to find ‘sys_call_table[]’ -- and there are two easy ways to do that

Finding the jump-table

  • Older versions of Linux (prior to 2.4.18) used to ‘export’ the ‘sys_call_table[]’ as a global symbol, but current versions keep this table’s address private (for security)
  • But often during kernel-installation there is a ‘System.map’ file that gets put into the ‘/boot’ directory and – assuming it matches your compiled kernel – it holds the kernel address for the ‘sys_call_table[]’ array

The ‘vmlinux’ file

  • Your compiled kernel (uncompressed) is left in the ‘/usr/src/linux’ directory
  • It is an ELF-format (executable) file
  • It contains .text and .data sections
  • You can examine your ‘vmlinux’ kernel with the ‘objdump’ system-utility
  • You can pipe the output through the ‘grep’ utility to locate the ‘sys_call_table’ symbol

Section-Header Table (optional)

Executable versus Linkable

ELF Header

Section 2 Data Section 3 Data … Section n Data

Segment 1 Data Segment 2 Data Segment 3 Data … Segment n Data

Linkable File Executable File

Section-Header Table

Program-Header Table (optional)

Program-Header Table

ELF Header

Section 1 Data

Exporting ‘sys_call_table’

  • Once you know the address of your kernel’s ‘sys_call_table[]’, you can write a module to export that address to other modules, e.g.:

// declare global variable unsigned long *sys_call_table; EXPORT_SYMBOL(sys_call_table); int init_module( void) { sys_call_table = (unsigned long *)0xC0251500; return 0; }

Avoid hard-coded constant

  • You probably don’t want to ‘hard code’ the sys_call_table’s value in your module – if you ever recompile your kernel, or use a differently configured kernel, you’d have to remember to edit your module and then recompile it – or risk a corrupted system!
  • There’s a way to suply the required value as a module-parameter during ‘insmod’

simple_strtoul()

  • There is a kernel function you can use, in your ‘init_module()’ function, that will convert a string of hexadecimal digits into an ‘unsigned long’’: int init_module( void ) { unsigned long myval; myval = simple_strtoul( svctable, NULL, 16 ); sys_call_table = (unsigned long *)myval; return 0; }

Shell scripts

  • It’s inconvenient – and risks typing errors – if you must manually search ‘vmlinux’ and then type in the sys_call_table[]’s address every time you want to install your module
  • Fortunately this sequence of steps can be readily automated – by using a shell-script
  • We have created an example: ‘myscript’