syscall-intercept 0.1.0

Userspace syscall intercepting library.
Documentation
.\" Automatically generated by Pandoc 1.17.2
.\"
.TH "libsyscall_intercept" "3" "syscall_intercept API version 0.1.0" "" "" ""
.hy
.\" Copyright 2016-2017, Intel Corporation
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\"
.\"     * Redistributions of source code must retain the above copyright
.\"       notice, this list of conditions and the following disclaimer.
.\"
.\"     * Redistributions in binary form must reproduce the above copyright
.\"       notice, this list of conditions and the following disclaimer in
.\"       the documentation and/or other materials provided with the
.\"       distribution.
.\"
.\"     * Neither the name of the copyright holder nor the names of its
.\"       contributors may be used to endorse or promote products derived
.\"       from this software without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
.\" OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.SH NAME
.PP
\f[B]libsyscall_intercept\f[] \-\- User space syscall intercepting
library
.SH SYNOPSIS
.IP
.nf
\f[C]
#include\ <libsyscall_intercept_hook_point.h>
\f[]
.fi
.IP
.nf
\f[C]
cc\ \-lsyscall_intercept\ \-fpic\ \-shared\ source.c\ \-o\ preloadlib.so

LD_PRELOAD=preloadlib.so\ ./application
\f[]
.fi
.SH DESCRIPTION
.PP
The system call intercepting library provides a low\-level interface for
hooking Linux system calls in user space.
This is achieved by hotpatching the machine code of the standard C
library in the memory of a process.
The user of this library can provide the functionality of almost any
syscall in user space, using the very simple API specified in the
libsyscall_intercept_hook_point.h header file:
.IP
.nf
\f[C]
int\ (*intercept_hook_point)(long\ syscall_number,
\ \ \ \ \ \ \ \ \ \ \ \ long\ arg0,\ long\ arg1,
\ \ \ \ \ \ \ \ \ \ \ \ long\ arg2,\ long\ arg3,
\ \ \ \ \ \ \ \ \ \ \ \ long\ arg4,\ long\ arg5,
\ \ \ \ \ \ \ \ \ \ \ \ long\ *result);
\f[]
.fi
.PP
The user of the library shall assign to the variable called
intercept_hook_point a pointer to the address of a callback function.
A non\-zero return value returned by the callback function is used to
signal to the intercepting library that the specific system call was
ignored by the user and the original syscall should be executed.
A zero return value signals that the user takes over the system call.
In this case, the result of the system call (the value stored in the RAX
register after the system call) can be set via the *result pointer.
In order to use the library, the intercepting code is expected to be
loaded using the LD_PRELOAD feature provided by the system loader.
.PP
All syscalls issued by libc are intercepted.
Syscalls made by code outside libc are not intercepted.
In order to be able to issue syscalls that are not intercepted, a
convenience function is provided by the library:
.IP
.nf
\f[C]
long\ syscall_no_intercept(long\ syscall_number,\ ...);
\f[]
.fi
.PP
In addition to hooking syscalls before they would be called, the API has
one special hook point that is executed after thread creation, right
after a clone syscall creating a thread returns in a child thread:
.IP
.nf
\f[C]
void\ (*intercept_hook_point_clone_child)(void);
\f[]
.fi
.PP
Using \f[C]intercept_hook_point_clone_child\f[], one can be notified of
thread creations.
.PP
To make it easy to detect syscall return values indicating errors, one
can use the syscall_error_code function:
.IP
.nf
\f[C]
int\ syscall_error_code(long\ result);
\f[]
.fi
.PP
When passed a return value from syscall_no_intercept, this function can
translate it to an error code equivalent to a libc error code:
.IP
.nf
\f[C]
int\ fd\ =\ (int)syscall_no_intercept(SYS_open,\ "file",\ O_RDWR);
if\ (syscall_error_code(fd)\ !=\ 0)
\ \ \ \ fprintf(stderr,\ strerror(syscall_error_code(fd)));
\f[]
.fi
.SH ENVIRONMENT VARIABLES
.PP
Three environment variables control the operation of the library:
.PP
\f[I]INTERCEPT_LOG\f[] \-\- when set, the library logs each syscall
intercepted to a file.
If it ends with "\-" the path of the file is formed by appending a
process id to the value provided in the environment variable.
E.g.: initializing the library in a process with pid 123 when the
INTERCEPT_LOG is set to "intercept.log\-" will result in a log file
named intercept.log\-123.
.PP
*INTERCEPT_LOG_TRUNC \-\- when set to 0, the log file from INTERCEPT_LOG
is not truncated.
.PP
\f[I]INTERCEPT_HOOK_CMDLINE_FILTER\f[] \-\- when set, the library checks
the contents of the /proc/self/cmdline file.
Hotpatching, and syscall intercepting is only done, if the last
component of the first zero terminated string in /proc/self/cmdline
matches the string provided in the environment variable.
This can also be queried by the user of the library:
.IP
.nf
\f[C]
int\ syscall_hook_in_process_allowed(void);
\f[]
.fi
.SH EXAMPLE
.IP
.nf
\f[C]
#include\ <libsyscall_intercept_hook_point.h>
#include\ <syscall.h>
#include\ <errno.h>

static\ int
hook(long\ syscall_number,
\ \ \ \ \ \ \ \ \ \ \ \ long\ arg0,\ long\ arg1,
\ \ \ \ \ \ \ \ \ \ \ \ long\ arg2,\ long\ arg3,
\ \ \ \ \ \ \ \ \ \ \ \ long\ arg4,\ long\ arg5,
\ \ \ \ \ \ \ \ \ \ \ \ long\ *result)
{
\ \ \ \ if\ (syscall_number\ ==\ SYS_getdents)\ {
\ \ \ \ \ \ \ \ /*
\ \ \ \ \ \ \ \ \ *\ Prevent\ the\ application\ from
\ \ \ \ \ \ \ \ \ *\ using\ the\ getdents\ syscall.\ From
\ \ \ \ \ \ \ \ \ *\ the\ point\ of\ view\ of\ the\ calling
\ \ \ \ \ \ \ \ \ *\ process,\ it\ is\ as\ if\ the\ kernel
\ \ \ \ \ \ \ \ \ *\ would\ return\ the\ ENOTSUP\ error
\ \ \ \ \ \ \ \ \ *\ code\ from\ the\ syscall.
\ \ \ \ \ \ \ \ \ */
\ \ \ \ \ \ \ \ *result\ =\ \-ENOTSUP;
\ \ \ \ \ \ \ \ return\ 0;
\ \ \ \ }\ else\ {
\ \ \ \ \ \ \ \ /*
\ \ \ \ \ \ \ \ \ *\ Ignore\ any\ other\ syscalls
\ \ \ \ \ \ \ \ \ *\ i.e.:\ pass\ them\ on\ to\ the\ kernel
\ \ \ \ \ \ \ \ \ *\ as\ would\ normally\ happen.
\ \ \ \ \ \ \ \ \ */
\ \ \ \ \ \ \ \ return\ 1;
\ \ \ \ }
}

static\ __attribute__((constructor))\ void
init(void)
{
\ \ \ \ //\ Set\ up\ the\ callback\ function
\ \ \ \ intercept_hook_point\ =\ hook;
}
\f[]
.fi
.IP
.nf
\f[C]
$\ cc\ example.c\ \-lsyscall_intercept\ \-fpic\ \-shared\ \-o\ example.so
$\ LD_LIBRARY_PATH=.\ LD_PRELOAD=example.so\ ls
ls:\ reading\ directory\ \[aq].\[aq]:\ Operation\ not\ supported
\f[]
.fi
.SH SEE ALSO
.PP
\f[B]syscall\f[](2)