File: README.md

package info (click to toggle)
purelibc 1.0.8-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 192 kB
  • sloc: ansic: 2,271; makefile: 3
file content (206 lines) | stat: -rw-r--r-- 5,788 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
# purelibc
A glibc overlay library for process self-virtualization

This is PURE\_LIBC: an overlay library for glibc that allows system call capturing.

(C) 2006,2008 Renzo Davoli University of Bologna (ITALY)
(C) 2006 Andrea Gasparini University of Bologna (ITALY)
 
This is LIBRE software: this work has been released under the LGPLv2,1+
license (see the file COPYING and the header note in the source files).

Pure\_libc converts glibc from a libc+system interfacing library into a 
libc-only library.
A process can trace the system call generated by itself by purelibc.
Pure\_libc is not complete yet. Stdio has been implemented onto the
fopencookie call. 
Due to current limitations of fopencookie, freopen may not work
properly when reopening files different from std{in,out,err}.

This function:
```C
fun _pure_start(sfun pure_syscall,int flags);
```
starts the syscall tracing.
All the system call of the programs are converted into calls of the
`pure_syscall` function.
`pure_socketcall` is meaningful only for architectures where 
all the berkeley socket calls get sent to the kernel using one shared
system call (`__NR_socketcall`)
if `pure_socketcall` is not NULL, purelibc calls it for each 
Berkeley socket call.
If `pure_socketcall` is NULL and  `__NR_socketcall` is defined purelibc calls 
```C
	pure_syscall(__NR_socketcall,socketcall_id,argv)
```
(purelibc mimics the same call received by the kernel).

### FLAGS
* `PUREFLAG_STDIN, PUREFLAG_STDOUT, PUREFLAG_STDERR`: 
The standard streams gets opened by libc before purelibc starts.
Without these flags stdio calls on standard streams will not be 
traced. (e.g. getchar, printf).
These flags force _pure_start to reopen the stdio standard streams to trace
the calls on them.
`PUREFLAG_STDALL` is a shortcut for 
`(PUREFLAG_STDIN|PUREFLAG_STDOUT|PUREFLAG_STDERR)`

### RETURN VALUE
_pure_start returns a pointer to the original libc syscall function.
this function must be stored in a global variable and must be used to 
bypass purelibc and send a system call to the kernel.

WARNING: libc '`syscall(2)`' call itself gets diverted to the `pure_syscall`
function, too.

## Installation

purelibc uses the cmake, so the standard procedure to compile and install the library is:
```sh
$ mkdir build
$ cd build
$ cmake ..
$ make
$ sudo make install
```

## Uninstallation

From the build directory run:
```sh
$ sudo make uninstall
```

## Examples
The following test program prints the number of each system call before actually calling it (it is a 'cat' like stdin to stdout copy, when EOF is sent it prints "hello world"):
```C
#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <stdlib.h>
#include <purelibc.h>

static sfun _native_syscall;

static char buf[128];
static long int mysc(long int sysno, ...){
	va_list ap;
	long int a1,a2,a3,a4,a5,a6;
	va_start (ap, sysno);
	snprintf(buf,128,"SC=%d\n",sysno);
	_native_syscall(__NR_write,2,buf,strlen(buf));
	a1=va_arg(ap,long int);
	a2=va_arg(ap,long int);
	a3=va_arg(ap,long int);
	a4=va_arg(ap,long int);
	a5=va_arg(ap,long int);
	a6=va_arg(ap,long int);
	va_end(ap);
	return _native_syscall(sysno,a1,a2,a3,a4,a5,a6);
}

int main() {
	int c;
	_native_syscall=_pure_start(mysc,PUREFLAG_STDALL);
	while ((c=getchar()) != EOF)
		putchar(c);
	printf("hello world\n");
	return 0;
}
```

To run this example just compile it and link it together with the library
in this way:
```
$ gcc -o puretest puretest.c -lpurelibc
```
if you installed purelibc library in /usr/local/lib you need to add this 
directory to the linker search path,

with CSH:
```
$ setenv LD_LIBRARY_PATH /usr/local/lib
```
or with BASH:
```
$ export LD_LIBRARY_PATH="/usr/local/lib"
```
Unfortunately if you load purelibc as a dynamic library by dlopen
it does not work.

The following example solves the problem.
More specifically:

* It is possible to use purelibc to track the calling process and all
the dynamic libraries loaded at run time.
* The code does not depend on purelibc. If you run it un a host without
purelibc, it will not be able to track its system calls but it works.

```C
#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <purelibc.h>

static sfun _native_syscall;

static char buf[128];
static long int mysc(long int sysno, ...){
	va_list ap;
	long int a1,a2,a3,a4,a5,a6;
	va_start (ap, sysno);
	snprintf(buf,128,"SC=%d\n",sysno);
	_native_syscall(__NR_write,2,buf,strlen(buf));
	a1=va_arg(ap,long int);
	a2=va_arg(ap,long int);
	a3=va_arg(ap,long int);
	a4=va_arg(ap,long int);
	a5=va_arg(ap,long int);
	a6=va_arg(ap,long int);
	va_end(ap);
	return _native_syscall(sysno,a1,a2,a3,a4,a5,a6);
}

int main(int argc,char *argv[]) {
	int c;
	sfun (*_pure_start_p)();
	void *handle;
	/* does pure_libc exist ? */
	if ((_pure_start_p=dlsym(RTLD_DEFAULT,"_pure_start")) == NULL &&
			(handle=dlopen("libpurelibc.so",RTLD_LAZY))!=NULL) {
		char *path;
		dlclose(handle);
		/* get the executable from /proc */
		asprintf(&path,"/proc/%d/exe",getpid());
		/* preload the pure_libc library */
		setenv("LD_PRELOAD","libpurelibc.so",1);
		printf("pure_libc dynamically loaded, exec again\n");
		/* reload the executable */
		execv(path,argv);
		/* useless cleanup */
		free(path);
	}
	if ((_pure_start_p=dlsym(RTLD_DEFAULT,"_pure_start")) != NULL) {
		printf("pure_libc library found: syscall tracing allowed\n");
		_native_syscall=_pure_start_p(mysc,NULL,PUREFLAG_STDALL);
	}
	while ((c=getchar()) != EOF)
		putchar(c);
	printf("hello world\n");
	return 0;
}
```

To run this example just compile it and link it with the dl library
in this way:
```
$ gcc -o puretest2 puretest2.c -ldl
```