Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how could I intercept linux sys calls?

Tags:

Besides the LD_PRELOAD trick , and Linux Kernel Modules that replace a certain syscall with one provided by you , is there any possibility to intercept a syscall ( open for example ) , so that it first goes through your function , before it reaches the actual open ?

like image 467
Vhaerun Avatar asked Sep 16 '08 06:09

Vhaerun


People also ask

How does Linux handle system call?

The Linux kernel sets aside a specific software interrupt number that can be used by user space programs to enter the kernel and execute a system call. The Linux kernel registers an interrupt handler named ia32_syscall for the interrupt number: 128 (0x80).

What is intercept OS?

Processes run in two modes: user and kernel. Most of the time processes run under the user mode when they have access to limited resources. When a process needs to perform a service offered by the kernel, it invokes a system call. System calls serve as gates into the kernel.

Are Linux commands system calls?

The Linux System calls under this are fork() , exit() , exec(). A new process is created by the fork() system call. A new process may be created with fork() without a new program being run-the new sub-process simply continues to execute exactly the same program that the first (parent) process was running.


1 Answers

Why can't you / don't want to use the LD_PRELOAD trick?

Example code here:

/*
 * File: soft_atimes.c
 * Author: D.J. Capelis
 *
 * Compile:
 * gcc -fPIC -c -o soft_atimes.o soft_atimes.c
 * gcc -shared -o soft_atimes.so soft_atimes.o -ldl
 *
 * Use:
 * LD_PRELOAD="./soft_atimes.so" command
 *
 * Copyright 2007 Regents of the University of California
 */

#define _GNU_SOURCE
#include <dlfcn.h>
#define _FCNTL_H
#include <sys/types.h>
#include <bits/fcntl.h>
#include <stddef.h>

extern int errorno;

int __thread (*_open)(const char * pathname, int flags, ...) = NULL;
int __thread (*_open64)(const char * pathname, int flags, ...) = NULL;

int open(const char * pathname, int flags, mode_t mode)
{
    if (NULL == _open) {
        _open = (int (*)(const char * pathname, int flags, ...)) dlsym(RTLD_NEXT, "open");
    }
    if(flags & O_CREAT)
        return _open(pathname, flags | O_NOATIME, mode);
    else
        return _open(pathname, flags | O_NOATIME, 0);
}

int open64(const char * pathname, int flags, mode_t mode)
{
    if (NULL == _open64) {
        _open64 = (int (*)(const char * pathname, int flags, ...)) dlsym(RTLD_NEXT, "open64");
    }
    if(flags & O_CREAT)
        return _open64(pathname, flags | O_NOATIME, mode);
    else
        return _open64(pathname, flags | O_NOATIME, 0);
}

From what I understand... it is pretty much the LD_PRELOAD trick or a kernel module. There's not a whole lot of middle ground unless you want to run it under an emulator which can trap out to your function or do code re-writing on the actual binary to trap out to your function.

Assuming you can't modify the program and can't (or don't want to) modify the kernel, the LD_PRELOAD approach is the best one, assuming your application is fairly standard and isn't actually one that's maliciously trying to get past your interception. (In which case you will need one of the other techniques.)

like image 148
DJ Capelis Avatar answered Oct 15 '22 06:10

DJ Capelis