~ubuntu-branches/ubuntu/vivid/cctools/vivid

« back to all changes in this revision

Viewing changes to parrot/src/pfs_dispatch.cc

  • Committer: Bazaar Package Importer
  • Author(s): Michael Hanke
  • Date: 2011-05-07 09:05:00 UTC
  • Revision ID: james.westby@ubuntu.com-20110507090500-lqpmdtwndor6e7os
Tags: upstream-3.3.2
ImportĀ upstreamĀ versionĀ 3.3.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
Copyright (C) 2003-2004 Douglas Thain and the University of Wisconsin
 
3
Copyright (C) 2005- The University of Notre Dame
 
4
This software is distributed under the GNU General Public License.
 
5
See the file COPYING for details.
 
6
*/
 
7
 
 
8
#include "pfs_sysdeps.h"
 
9
#include "pfs_channel.h"
 
10
#include "pfs_channel_cache.h"
 
11
#include "pfs_process.h"
 
12
#include "pfs_sys.h"
 
13
#include "pfs_poll.h"
 
14
#include "pfs_service.h"
 
15
#include "pfs_dispatch.h"
 
16
 
 
17
extern "C" {
 
18
#include "tracer.h"
 
19
#include "stringtools.h"
 
20
#include "full_io.h"
 
21
#include "xmalloc.h"
 
22
#include "int_sizes.h"
 
23
#include "macros.h"
 
24
#include "debug.h"
 
25
}
 
26
 
 
27
#include <stdlib.h>
 
28
#include <stdio.h>
 
29
#include <errno.h>
 
30
#include <string.h>
 
31
#include <unistd.h>
 
32
#include <signal.h>
 
33
#include <time.h>
 
34
#include <fcntl.h>
 
35
#include <limits.h>
 
36
#include <sys/mman.h>
 
37
#include <sys/stat.h>
 
38
#include <sys/statfs.h>
 
39
#include <sys/file.h>
 
40
#include <termios.h>
 
41
#include <sys/time.h>
 
42
#include <ctype.h>
 
43
#include <sys/utsname.h>
 
44
#include <sys/un.h>
 
45
#include <net/if.h>
 
46
#include <linux/sockios.h>
 
47
 
 
48
#include <sys/types.h>
 
49
#include <unistd.h>
 
50
#include <sys/wait.h>
 
51
 
 
52
extern struct pfs_process *pfs_current;
 
53
extern char *pfs_temp_dir;
 
54
extern char *pfs_false_uname;
 
55
extern uid_t pfs_uid;
 
56
extern gid_t pfs_gid;
 
57
 
 
58
extern pid_t trace_this_pid;
 
59
 
 
60
extern INT64_T pfs_syscall_count;
 
61
extern INT64_T pfs_read_count;
 
62
extern INT64_T pfs_write_count;
 
63
 
 
64
extern int pfs_trap_after_fork;
 
65
 
 
66
extern char *pfs_ldso_path;
 
67
extern int *pfs_syscall_totals32;
 
68
 
 
69
extern void handle_specific_process( pid_t pid );
 
70
 
 
71
/*
 
72
Divert this incoming system call to a read or write on the I/O channel
 
73
*/
 
74
 
 
75
static void divert_to_channel( struct pfs_process *p, int syscall, const void *uaddr, int length, pfs_size_t channel_offset )
 
76
{
 
77
        INT64_T args[5];
 
78
        args[0] = pfs_channel_fd();
 
79
        args[1] = (UPTRINT_T)uaddr;
 
80
        args[2] = length;
 
81
        args[3] = channel_offset&0xffffffff;
 
82
        args[4] = (((UINT64_T)channel_offset) >> 32);
 
83
        tracer_args_set(p->tracer,syscall,args,5);
 
84
        p->syscall_args_changed = 1;
 
85
        p->diverted_length = length;
 
86
}
 
87
 
 
88
/*
 
89
Divert this incoming system call to something harmless with the given result.
 
90
*/
 
91
 
 
92
static void divert_to_dummy( struct pfs_process *p, int result )
 
93
{
 
94
        p->syscall_dummy = 1;
 
95
        p->syscall_result = result;
 
96
        tracer_args_set(p->tracer,SYSCALL32_getpid,0,0);
 
97
}
 
98
 
 
99
static int errno_in_progress( int e )
 
100
{
 
101
        return (e==EAGAIN || e==EALREADY || e==EINPROGRESS);
 
102
}
 
103
 
 
104
/*
 
105
The large majority of calls, given below in decode_syscall
 
106
have a simple transformation using tracer_copy_{in,out}.
 
107
Read, write, and similar syscalls need better performance
 
108
and thus have more specialized implementations shown here.
 
109
*/
 
110
 
 
111
/*
 
112
SYSCALL32_read and friends are implemented by loading the data
 
113
into the channel, and then redirecting the system call
 
114
to read from the channel fd.
 
115
*/
 
116
 
 
117
#define POINTER( i ) ((void*)(PTRINT_T)(i))
 
118
 
 
119
static void decode_read( struct pfs_process *p, int entering, int syscall, INT64_T *args )
 
120
{
 
121
        int fd = args[0];
 
122
        void *uaddr = POINTER(args[1]);
 
123
        pfs_size_t length = args[2];
 
124
        pfs_off_t offset = args[3];
 
125
        char *local_addr;
 
126
        
 
127
        if(entering) {
 
128
                if(!pfs_channel_alloc(length,&p->io_channel_offset)) {
 
129
                        divert_to_dummy(p,-ENOMEM);
 
130
                        return;
 
131
                }
 
132
                local_addr = pfs_channel_base() + p->io_channel_offset;
 
133
 
 
134
                if(syscall==SYSCALL32_read) {
 
135
                        p->syscall_result = pfs_read(fd,local_addr,length);
 
136
                } else if(syscall==SYSCALL32_pread) {
 
137
                        p->syscall_result = pfs_pread(fd,local_addr,length,offset);
 
138
                } else if(syscall==SYS_RECV) {
 
139
                        p->syscall_result = pfs_recv(fd,local_addr,length,args[3]);
 
140
                } else if(syscall==SYS_RECVFROM) {
 
141
                        p->syscall_result = pfs_recvfrom(fd,local_addr,length,args[3],(struct sockaddr*)POINTER(args[4]),(int*)POINTER(args[5]));
 
142
                }
 
143
 
 
144
                p->diverted_length = 0;
 
145
 
 
146
                if(p->syscall_result==0) {
 
147
                        divert_to_dummy(p,0);
 
148
                } else if(p->syscall_result>0) {
 
149
                        divert_to_channel(p,SYSCALL32_pread,uaddr,p->syscall_result,p->io_channel_offset);
 
150
                        pfs_read_count += p->syscall_result;
 
151
                } else if( errno==EAGAIN ) {
 
152
                        if(p->interrupted) {
 
153
                                p->interrupted = 0;
 
154
                                divert_to_dummy(p,-EINTR);
 
155
                        } else if(pfs_is_nonblocking(fd)) {
 
156
                                divert_to_dummy(p,-EAGAIN);
 
157
                        } else {
 
158
                                pfs_channel_free(p->io_channel_offset);
 
159
                                p->state = PFS_PROCESS_STATE_WAITREAD;
 
160
                                int rfd = pfs_get_real_fd(fd);
 
161
                                if(rfd>=0) pfs_poll_wakeon(rfd,PFS_POLL_READ);
 
162
                        }
 
163
                } else {
 
164
                        divert_to_dummy(p,-errno);
 
165
                }
 
166
        } else {
 
167
                /*
 
168
                This is an ugly situation.
 
169
                If we arrive here with EINTR, it means that we have copied
 
170
                all of the data into the channel, taken any side effects
 
171
                of accessing the remote storage device, but the system call
 
172
                happened not to read it because of an incoming signal.
 
173
                We have no way of re-trying the channel read, so we do
 
174
                the ugly slow copy out instead.
 
175
                */
 
176
 
 
177
                if( (p->syscall_result==-EINTR) && (p->diverted_length>0) ) {
 
178
                        tracer_copy_out(p->tracer,pfs_channel_base()+p->io_channel_offset,uaddr,p->diverted_length);
 
179
                        p->syscall_result = p->diverted_length;
 
180
                        tracer_result_set(p->tracer,p->syscall_result);
 
181
                }
 
182
 
 
183
                pfs_channel_free(p->io_channel_offset);
 
184
        }
 
185
}
 
186
 
 
187
/*
 
188
decode_write is much the same as read.  We allocate space
 
189
in the channel, and then redirect the caller to write
 
190
to it.  When the syscall completes, we write the data
 
191
to its destination and then set the result.
 
192
*/
 
193
 
 
194
static void decode_write( struct pfs_process *p, int entering, int syscall, INT64_T *args )
 
195
{
 
196
        if(entering) {
 
197
                void *uaddr = POINTER(args[1]);
 
198
                INT64_T length = args[2];
 
199
                if(!pfs_channel_alloc(length,&p->io_channel_offset)) {
 
200
                        divert_to_dummy(p,-ENOMEM);
 
201
                        return;
 
202
                }
 
203
                divert_to_channel(p,SYSCALL32_pwrite,uaddr,length,p->io_channel_offset);
 
204
        } else {
 
205
                INT64_T actual_result;
 
206
                tracer_result_get(p->tracer,&actual_result);
 
207
 
 
208
                if(actual_result!=args[2]) {
 
209
                        debug(D_NOTICE,"channel write returned %lld instead of %lld",actual_result,args[2]);
 
210
                }
 
211
 
 
212
                if(actual_result>0) {
 
213
                        int fd = args[0];
 
214
                        pfs_off_t offset = args[3];
 
215
                        char *local_addr = pfs_channel_base() + p->io_channel_offset;
 
216
 
 
217
                        if(syscall==SYSCALL32_write) {
 
218
                                p->syscall_result = pfs_write(fd,local_addr,actual_result);
 
219
                        } else if(syscall==SYSCALL32_pwrite) {
 
220
                                p->syscall_result = pfs_pwrite(fd,local_addr,actual_result,offset);
 
221
                        } else if(syscall==SYS_SEND) {
 
222
                                p->syscall_result = pfs_send(fd,local_addr,actual_result,args[3]);
 
223
                        } else if(syscall==SYS_SENDTO) {
 
224
                                p->syscall_result = pfs_sendto(fd,local_addr,actual_result,args[3],(struct sockaddr *)POINTER(args[4]),args[5]);
 
225
                        }
 
226
 
 
227
                        if(p->syscall_result>=0) {
 
228
                                if(p->syscall_result!=actual_result) {
 
229
                                        debug(D_SYSCALL,"write returned %lld instead of %lld",p->syscall_result,actual_result);
 
230
                                }
 
231
                                tracer_result_set(p->tracer,p->syscall_result);
 
232
                                pfs_channel_free(p->io_channel_offset);
 
233
                                p->state = PFS_PROCESS_STATE_KERNEL;
 
234
                                entering = 0;
 
235
                                pfs_write_count += p->syscall_result;
 
236
                        } else {
 
237
                                if(errno==EAGAIN && !pfs_is_nonblocking(fd)) {
 
238
                                        p->state = PFS_PROCESS_STATE_WAITWRITE;
 
239
                                        int rfd = pfs_get_real_fd(fd);
 
240
                                        if(rfd>=0) pfs_poll_wakeon(rfd,PFS_POLL_WRITE);
 
241
                                } else {
 
242
                                        p->syscall_result = -errno;
 
243
                                        tracer_result_set(p->tracer,p->syscall_result);
 
244
                                        pfs_channel_free(p->io_channel_offset);
 
245
                                        if(p->syscall_result==-EPIPE) {
 
246
                                                // make sure that we are not in a wait state,
 
247
                                                // otherwise pfs_process_raise will re-dispatch.
 
248
                                                p->state = PFS_PROCESS_STATE_KERNEL;
 
249
                                                pfs_process_raise(p->pid,SIGPIPE,1);
 
250
                                        }
 
251
                                }
 
252
                        }
 
253
                } else {
 
254
                        pfs_channel_free(p->io_channel_offset);
 
255
                }
 
256
        }
 
257
}
 
258
 
 
259
static struct pfs_kernel_iovec * iovec_alloc_in( struct pfs_process *p, struct pfs_kernel_iovec *uv, int count )
 
260
{
 
261
        struct pfs_kernel_iovec *v;
 
262
        int size = sizeof(struct pfs_kernel_iovec)*count;
 
263
 
 
264
        v = (struct pfs_kernel_iovec *) malloc(size);
 
265
        if(v) {
 
266
                tracer_copy_in(p->tracer,v,uv,size);
 
267
                return v;
 
268
        } else {
 
269
                return 0;
 
270
        }
 
271
}
 
272
 
 
273
static int iovec_size( struct pfs_process *p, struct pfs_kernel_iovec *v, int count )
 
274
{
 
275
        int i, total=0;
 
276
        for(i=0;i<count;i++) {
 
277
                total += v[i].iov_len;
 
278
        }
 
279
        return total;   
 
280
}
 
281
 
 
282
static int iovec_copy_in( struct pfs_process *p, char *buf, struct pfs_kernel_iovec *v, int count )
 
283
{
 
284
        int i, pos=0;
 
285
        for(i=0;i<count;i++) {
 
286
                tracer_copy_in(p->tracer,&buf[pos],(void*)(UPTRINT_T)v[i].iov_base,v[i].iov_len);
 
287
                pos += v[i].iov_len;
 
288
        }
 
289
        return pos;
 
290
}
 
291
 
 
292
static int iovec_copy_out( struct pfs_process *p, char *buf, struct pfs_kernel_iovec *v, int count )
 
293
{
 
294
        int i, pos=0;
 
295
        for(i=0;i<count;i++) {
 
296
                tracer_copy_out(p->tracer,&buf[pos],(void*)(UPTRINT_T)v[i].iov_base,v[i].iov_len);
 
297
                pos += v[i].iov_len;
 
298
        }
 
299
        return pos;
 
300
}
 
301
 
 
302
/*
 
303
Both readv and writev have a careful but inefficient implementation.
 
304
For each uio block, we examine the data structures, do a manual
 
305
read and write in our local buffer, and then copy the data over.
 
306
I assume that these are not heavily used system calls, although
 
307
they do seem to appear sporadically in X11, the dynamic linker,
 
308
and sporadically in networking utilities.
 
309
*/
 
310
 
 
311
static void decode_readv( struct pfs_process *p, int entering, int syscall, INT64_T *args )
 
312
{
 
313
        if(entering) {
 
314
                int fd = args[0];
 
315
                struct pfs_kernel_iovec *uv = (struct pfs_kernel_iovec *) POINTER(args[1]);
 
316
                int count = args[2];
 
317
 
 
318
                struct pfs_kernel_iovec *v;
 
319
                int size;
 
320
                char *buffer;
 
321
                int result;
 
322
                
 
323
                if(!uv || count<=0) {
 
324
                        divert_to_dummy(p,-EINVAL);
 
325
                        return;
 
326
                }
 
327
 
 
328
                v = iovec_alloc_in(p,uv,count);
 
329
                if(v) {
 
330
                        size = iovec_size(p,v,count);
 
331
                        buffer = (char*) malloc(size);
 
332
                        if(buffer) {
 
333
                                result = pfs_read(fd,buffer,size);
 
334
                                if(result>=0) {
 
335
                                        iovec_copy_out(p,buffer,v,count);
 
336
                                        divert_to_dummy(p,result);
 
337
                                } else {
 
338
                                        if(errno==EAGAIN && !pfs_is_nonblocking(fd)) {
 
339
                                                p->state = PFS_PROCESS_STATE_WAITREAD;
 
340
                                                int rfd = pfs_get_real_fd(fd);
 
341
                                                if(rfd>=0) pfs_poll_wakeon(rfd,PFS_POLL_READ);
 
342
                                        } else {
 
343
                                                divert_to_dummy(p,-errno);
 
344
                                        }
 
345
                                }
 
346
                                free(buffer);
 
347
                        } else {
 
348
                                divert_to_dummy(p,-ENOMEM);
 
349
                        }
 
350
                        free(v);                
 
351
                } else {
 
352
                        divert_to_dummy(p,-ENOMEM);
 
353
                }
 
354
        }
 
355
}
 
356
 
 
357
static void decode_writev( struct pfs_process *p, int entering, int syscall, INT64_T *args )
 
358
{
 
359
        if(entering) {
 
360
                int fd = args[0];
 
361
                struct pfs_kernel_iovec *uv = (struct pfs_kernel_iovec *)POINTER(args[1]);
 
362
                int count = args[2];
 
363
 
 
364
                struct pfs_kernel_iovec *v;
 
365
                int size;
 
366
                char *buffer;
 
367
                int result;
 
368
 
 
369
                if(!uv || count<=0) {
 
370
                        divert_to_dummy(p,-EINVAL);
 
371
                        return;
 
372
                }
 
373
 
 
374
                v = iovec_alloc_in(p,uv,count);
 
375
                if(v) {
 
376
                        size = iovec_size(p,v,count);
 
377
                        buffer = (char *) malloc(size);
 
378
                        if(buffer) {
 
379
                                iovec_copy_in(p,buffer,v,count);
 
380
                                result = pfs_write(fd,buffer,size);
 
381
                                if(result>=0) {
 
382
                                        divert_to_dummy(p,result);
 
383
                                } else if(result<0) {
 
384
                                        if(errno==EAGAIN && !pfs_is_nonblocking(fd)) {
 
385
                                                /*
 
386
                                                WAITREAD is correct here, because WAITWRITE
 
387
                                                would cause us to be called again with entering=0
 
388
                                                */
 
389
                                                p->state = PFS_PROCESS_STATE_WAITREAD;
 
390
                                                int rfd = pfs_get_real_fd(fd);
 
391
                                                if(rfd>=0) pfs_poll_wakeon(rfd,PFS_POLL_WRITE);
 
392
                                        } else {
 
393
                                                divert_to_dummy(p,-errno);
 
394
                                        }
 
395
                                }
 
396
                                free(buffer);
 
397
                        } else {
 
398
                                divert_to_dummy(p,-ENOMEM);
 
399
                        }
 
400
                        free(v);                
 
401
                } else {
 
402
                        divert_to_dummy(p,-ENOMEM);
 
403
                }
 
404
        }
 
405
}
 
406
 
 
407
static void decode_stat( struct pfs_process *p, int entering, int syscall, INT64_T *args, int sixty_four )
 
408
{
 
409
        int fd = args[0];
 
410
        void *uaddr = (void*) POINTER(args[1]);
 
411
        char *local_addr;
 
412
        struct pfs_stat lbuf;
 
413
        struct pfs_kernel_stat kbuf;
 
414
        struct pfs_kernel_stat64 kbuf64;
 
415
        char path[PFS_PATH_MAX];
 
416
        int bufsize;
 
417
 
 
418
        if(entering) {
 
419
                p->io_channel_offset = 0;
 
420
 
 
421
                if(syscall==SYSCALL32_stat) {
 
422
                        tracer_copy_in_string(p->tracer,path,POINTER(args[0]),sizeof(path));
 
423
                        p->syscall_result = pfs_stat(path,&lbuf);
 
424
                } else if(syscall==SYSCALL32_lstat) {
 
425
                        tracer_copy_in_string(p->tracer,path,POINTER(args[0]),sizeof(path));
 
426
                        p->syscall_result = pfs_lstat(path,&lbuf);
 
427
                } else if(syscall==SYSCALL32_fstat) {
 
428
                        p->syscall_result = pfs_fstat(fd,&lbuf);
 
429
                }
 
430
 
 
431
                if(p->syscall_result>=0) {
 
432
                        if(!pfs_channel_alloc(sizeof(kbuf64),&p->io_channel_offset)) {
 
433
                                divert_to_dummy(p,-ENOMEM);
 
434
                        } else {
 
435
                                local_addr = pfs_channel_base() + p->io_channel_offset;
 
436
 
 
437
                                if(sixty_four) {
 
438
                                        COPY_STAT(lbuf,kbuf64);
 
439
                                        /* Special case: Linux needs stat64.st_ino in two places. */
 
440
                                        kbuf64.st_ino_extra = kbuf64.st_ino;
 
441
                                        memcpy(local_addr,&kbuf64,sizeof(kbuf64));
 
442
                                        bufsize = sizeof(kbuf64);
 
443
                                } else {
 
444
                                        COPY_STAT(lbuf,kbuf);
 
445
                                        memcpy(local_addr,&kbuf,sizeof(kbuf));
 
446
                                        bufsize = sizeof(kbuf);
 
447
                                }
 
448
                                divert_to_channel(p,SYSCALL32_pread,uaddr,bufsize,p->io_channel_offset);
 
449
                        }
 
450
                } else {
 
451
                        divert_to_dummy(p,-errno);
 
452
                }
 
453
        } else {
 
454
                if(p->syscall_result>=0) {
 
455
                        pfs_channel_free(p->io_channel_offset);
 
456
                        divert_to_dummy(p,0);
 
457
                }
 
458
        }
 
459
}
 
460
 
 
461
static void decode_statfs( struct pfs_process *p, int entering, int syscall, INT64_T *args, int sixty_four )
 
462
{
 
463
        struct pfs_statfs lbuf;
 
464
        struct pfs_kernel_statfs kbuf;
 
465
        struct pfs_kernel_statfs64 kbuf64;
 
466
        char path[PFS_PATH_MAX];
 
467
 
 
468
        if(entering) {
 
469
                p->io_channel_offset = 0;
 
470
 
 
471
                if(syscall==SYSCALL32_statfs) {
 
472
                        tracer_copy_in_string(p->tracer,path,POINTER(args[0]),sizeof(path));
 
473
                        p->syscall_result = pfs_statfs(path,&lbuf);
 
474
                } else if(syscall==SYSCALL32_fstatfs) {
 
475
                        p->syscall_result = pfs_fstatfs(args[0],&lbuf);
 
476
                }
 
477
 
 
478
                if(p->syscall_result>=0) {
 
479
                        if(sixty_four) {
 
480
                                COPY_STATFS(lbuf,kbuf64);
 
481
                                tracer_copy_out(p->tracer,&kbuf64,POINTER(args[2]),sizeof(kbuf64));
 
482
                        } else {
 
483
                                if(lbuf.f_blocks > 0xffffffff) lbuf.f_blocks = 0xffffffff;
 
484
                                if(lbuf.f_bavail > 0xffffffff) lbuf.f_bavail = 0xffffffff;
 
485
                                if(lbuf.f_bfree > 0xffffffff)  lbuf.f_bfree = 0xffffffff;
 
486
                                COPY_STATFS(lbuf,kbuf);
 
487
                                tracer_copy_out(p->tracer,&kbuf,POINTER(args[1]),sizeof(kbuf));
 
488
                        }
 
489
                        divert_to_dummy(p,p->syscall_result);
 
490
                } else {
 
491
                        divert_to_dummy(p,-errno);
 
492
                }
 
493
        }
 
494
}
 
495
 
 
496
/*
 
497
On Linux, all of the socket related system calls are
 
498
multiplexed through one system call.
 
499
*/
 
500
 
 
501
void decode_socketcall( struct pfs_process *p, int entering, int syscall, INT64_T *a )
 
502
{
 
503
        int length;
 
504
        int savelength;
 
505
        int fds[2];
 
506
        void *x = NULL;
 
507
        int r;
 
508
        int t4 = 0;
 
509
        int t5 = 0;
 
510
 
 
511
        struct sockaddr_un *paddr;
 
512
        struct sockaddr_un addr;
 
513
 
 
514
        if(entering) {
 
515
                switch(syscall) {
 
516
                case SYS_SOCKET:
 
517
                        r = pfs_socket(a[0],a[1],a[2]);
 
518
                        if(r<0) r=-errno;
 
519
                        divert_to_dummy(p,r);
 
520
                        break;
 
521
                case SYS_BIND:
 
522
                        x = xxmalloc(a[2]+2);
 
523
                        tracer_copy_in(p->tracer,x,POINTER(a[1]),a[2]);
 
524
                        paddr = (struct sockaddr_un *)x;
 
525
                        if(paddr->sun_family==AF_UNIX) {
 
526
                                pfs_name pname;
 
527
                                ((char*)x)[a[2]] = 0;
 
528
                                if(pfs_resolve_name(paddr->sun_path,&pname)) {
 
529
                                        addr.sun_family = AF_UNIX;
 
530
                                        strcpy(addr.sun_path,pname.path);
 
531
                                        r = pfs_bind(a[0],(struct sockaddr *)&addr,sizeof(addr));
 
532
                                } else {
 
533
                                        r = -1;
 
534
                                }
 
535
                        } else {
 
536
                                r = pfs_bind(a[0],(struct sockaddr *)x,a[2]);
 
537
                        }
 
538
                        if(r<0) r=-errno;
 
539
                        free(x);
 
540
                        divert_to_dummy(p,r);
 
541
                        break;
 
542
                case SYS_CONNECT:
 
543
                        x = xxmalloc(a[2]+2);
 
544
                        tracer_copy_in(p->tracer,x,POINTER(a[1]),a[2]);
 
545
                        paddr = (struct sockaddr_un *)x;
 
546
                        if(paddr->sun_family==AF_UNIX) {
 
547
                                pfs_name pname;
 
548
                                ((char*)x)[a[2]] = 0;
 
549
                                if(pfs_resolve_name(paddr->sun_path,&pname)) {
 
550
                                        addr.sun_family = AF_UNIX;
 
551
                                        strcpy(addr.sun_path,pname.path);
 
552
                                        r = pfs_connect(a[0],(struct sockaddr *)&addr,sizeof(addr));
 
553
                                } else {
 
554
                                        r = -1;
 
555
                                }
 
556
                        } else {
 
557
                                r = pfs_connect(a[0],(struct sockaddr*)x,a[2]);
 
558
                        }
 
559
                        if(r>=0) {
 
560
                                divert_to_dummy(p,r);
 
561
                        } else if(errno_in_progress(errno)) {
 
562
                                if(p->interrupted) {
 
563
                                        p->interrupted = 0;
 
564
                                        divert_to_dummy(p,-EINTR);
 
565
                                } else if(pfs_is_nonblocking(a[0])) {
 
566
                                        divert_to_dummy(p,-EINPROGRESS);
 
567
                                } else {
 
568
                                        p->state = PFS_PROCESS_STATE_WAITREAD;
 
569
                                        int rfd = pfs_get_real_fd(a[0]);
 
570
                                        if(rfd>=0) pfs_poll_wakeon(rfd,PFS_POLL_READ|PFS_POLL_WRITE|PFS_POLL_EXCEPT);
 
571
                                }
 
572
                        } else {
 
573
                                divert_to_dummy(p,-errno);
 
574
                        }
 
575
                        free(x);
 
576
                        break;
 
577
                case SYS_LISTEN:
 
578
                        r = pfs_listen(a[0],a[1]);
 
579
                        if(r<0) r=-errno;
 
580
                        divert_to_dummy(p,r);
 
581
                        break;
 
582
                case SYS_ACCEPT:
 
583
                        if(a[1]) {
 
584
                                tracer_copy_in(p->tracer,&length,POINTER(a[2]),sizeof(length));
 
585
                                x = xxmalloc(length);
 
586
                                r = pfs_accept(a[0],(struct sockaddr*)x,&length);
 
587
                        } else {
 
588
                                x = 0;
 
589
                                r = pfs_accept(a[0],0,0);
 
590
                        }
 
591
                        if(r>=0) {
 
592
                                if(x) {
 
593
                                        tracer_copy_out(p->tracer,x,POINTER(a[1]),length);
 
594
                                        tracer_copy_out(p->tracer,&length,POINTER(a[2]),sizeof(length));
 
595
                                }
 
596
                                divert_to_dummy(p,r);
 
597
                        } else if(errno_in_progress(errno)) {
 
598
                                if(p->interrupted) {
 
599
                                        p->interrupted = 0;
 
600
                                        divert_to_dummy(p,-EINTR);
 
601
                                } else if(pfs_is_nonblocking(a[0])) {
 
602
                                        divert_to_dummy(p,-EAGAIN);
 
603
                                } else {
 
604
                                        p->state = PFS_PROCESS_STATE_WAITREAD;
 
605
                                        int rfd = pfs_get_real_fd(a[0]);
 
606
                                        if(rfd>=0) pfs_poll_wakeon(rfd,PFS_POLL_READ);
 
607
                                }
 
608
                        } else {
 
609
                                divert_to_dummy(p,-errno);
 
610
                        }
 
611
                        if(x) free(x);
 
612
                        break;
 
613
                case SYS_GETSOCKNAME:
 
614
                        tracer_copy_in(p->tracer,&length,POINTER(a[2]),sizeof(length));
 
615
                        x = xxmalloc(length);
 
616
                        savelength = length;
 
617
                        r = pfs_getsockname(a[0],(struct sockaddr *)x,&length);
 
618
                        if(r<0) {
 
619
                                r=-errno;
 
620
                        } else {
 
621
                                tracer_copy_out(p->tracer,x,POINTER(a[1]),MIN(length,savelength));
 
622
                                tracer_copy_out(p->tracer,&length,POINTER(a[2]),sizeof(length));
 
623
                        }
 
624
                        free(x);
 
625
                        divert_to_dummy(p,r);
 
626
                        break;
 
627
                case SYS_GETPEERNAME:
 
628
                        tracer_copy_in(p->tracer,&length,POINTER(a[2]),sizeof(length));
 
629
                        x = xxmalloc(length);
 
630
                        r = pfs_getpeername(a[0],(struct sockaddr *)x,&length);
 
631
                        if(r<0) {
 
632
                                r=-errno;
 
633
                        } else {
 
634
                                tracer_copy_out(p->tracer,x,POINTER(a[1]),length);
 
635
                                tracer_copy_out(p->tracer,&length,POINTER(a[2]),sizeof(length));
 
636
                        }
 
637
                        free(x);
 
638
                        divert_to_dummy(p,r);
 
639
                        break;
 
640
                case SYS_SOCKETPAIR:
 
641
                        r = pfs_socketpair(a[0],a[1],a[2],fds);
 
642
                        if(r<0) {
 
643
                                r=-errno;
 
644
                        } else {
 
645
                                tracer_copy_out(p->tracer,fds,(void*)POINTER(a[3]),sizeof(fds));
 
646
                        }
 
647
                        divert_to_dummy(p,r);
 
648
                        break;
 
649
                case SYS_SEND:
 
650
                        decode_write(p,entering,syscall,a);
 
651
                        break;
 
652
                case SYS_SENDTO:
 
653
                        if(a[4]) {
 
654
                                x = xxmalloc(a[5]);
 
655
                                tracer_copy_in(p->tracer,x,POINTER(a[4]),a[5]);
 
656
                                t4 = a[4];
 
657
                                a[4] = (PTRINT_T)x;
 
658
                        }
 
659
                        decode_write(p,entering,syscall,a);
 
660
                        if(a[4]) {
 
661
                                a[4] = t4;
 
662
                                free(x);
 
663
                        }
 
664
                        break;
 
665
                case SYS_RECV:
 
666
                        decode_read(p,entering,syscall,a);
 
667
                        break;
 
668
                case SYS_RECVFROM:
 
669
                        if(a[4]) {
 
670
                                tracer_copy_in(p->tracer,&length,POINTER(a[5]),sizeof(length));
 
671
                                x = xxmalloc(length);
 
672
                                t4 = a[4];
 
673
                                t5 = a[5];
 
674
                                a[4] = (PTRINT_T) x;
 
675
                                a[5] = (PTRINT_T) &length;
 
676
                        }
 
677
                        decode_read(p,entering,syscall,a);
 
678
                        if(a[4]) {
 
679
                                a[4] = t4;
 
680
                                a[5] = t5;
 
681
                                if(p->syscall_result>=0) {
 
682
                                        tracer_copy_out(p->tracer,x,POINTER(a[4]),length);
 
683
                                        tracer_copy_out(p->tracer,&length,POINTER(a[5]),sizeof(length));
 
684
                                }
 
685
                                free(x);
 
686
                        }
 
687
                        break;
 
688
                case SYS_SHUTDOWN:
 
689
                        r = pfs_shutdown(a[0],a[1]);
 
690
                        if(r<0) r=-errno;
 
691
                        divert_to_dummy(p,r);
 
692
                        break;
 
693
                case SYS_SETSOCKOPT:
 
694
                        x = xxmalloc(a[4]);
 
695
                        tracer_copy_in(p->tracer,x,(void*)POINTER(a[3]),a[4]);
 
696
                        r = pfs_setsockopt(a[0],a[1],a[2],x,a[4]);
 
697
                        if(r<0) r=-errno;
 
698
                        free(x);
 
699
                        divert_to_dummy(p,r);
 
700
                        break;
 
701
                case SYS_GETSOCKOPT:
 
702
                        tracer_copy_in(p->tracer,&length,POINTER(a[4]),sizeof(length));
 
703
                        x = xxmalloc(length);
 
704
                        r = pfs_getsockopt(a[0],a[1],a[2],x,&length);
 
705
                        if(r<0) {
 
706
                                r=-errno;
 
707
                        } else {
 
708
                                tracer_copy_out(p->tracer,x,(void*)POINTER(a[3]),length);
 
709
                                tracer_copy_out(p->tracer,&length,POINTER(a[4]),sizeof(length));
 
710
                        }               
 
711
                        free(x);
 
712
                        divert_to_dummy(p,r);
 
713
                        break;
 
714
 
 
715
                        /*
 
716
                        In principle, sendmsg and recvmsg are quite simple,
 
717
                        but they require much copying in and out of pointers
 
718
                        to support the complex msghdr structure.
 
719
                        */
 
720
 
 
721
                case SYS_SENDMSG:
 
722
                case SYS_RECVMSG:
 
723
                        {
 
724
                        struct pfs_kernel_msghdr umsg;
 
725
                        struct pfs_kernel_iovec *uvec = NULL;
 
726
                        struct msghdr msg;
 
727
                        struct iovec vec;
 
728
 
 
729
                        /* Copy in the msghdr structure */
 
730
                        tracer_copy_in(p->tracer,&umsg,POINTER(a[1]),sizeof(umsg));
 
731
 
 
732
                        /* Build a copy of all of the various sub-pointers */
 
733
 
 
734
                        if(umsg.msg_name && umsg.msg_namelen>0) {
 
735
                                msg.msg_name = xxmalloc(umsg.msg_namelen);
 
736
                                msg.msg_namelen = umsg.msg_namelen;
 
737
                                tracer_copy_in(p->tracer,msg.msg_name,POINTER(umsg.msg_name),umsg.msg_namelen);
 
738
                        } else {
 
739
                                msg.msg_name = 0;
 
740
                                msg.msg_namelen = 0;
 
741
                        }
 
742
        
 
743
                        if(umsg.msg_iov) {
 
744
                                uvec = iovec_alloc_in(p,(struct pfs_kernel_iovec *)POINTER(umsg.msg_iov),umsg.msg_iovlen);
 
745
                                msg.msg_iov = &vec;
 
746
                                msg.msg_iovlen = 1;
 
747
                                vec.iov_len = iovec_size(p,uvec,umsg.msg_iovlen);
 
748
                                vec.iov_base = xxmalloc(vec.iov_len);
 
749
                        } else {
 
750
                                msg.msg_iov = 0;
 
751
                                msg.msg_iovlen = 0;
 
752
                        }
 
753
 
 
754
                        if(umsg.msg_control && umsg.msg_controllen>0) {
 
755
                                msg.msg_control = xxmalloc(umsg.msg_controllen);
 
756
                                msg.msg_controllen = umsg.msg_controllen;
 
757
                                tracer_copy_in(p->tracer,msg.msg_control,POINTER(umsg.msg_control),umsg.msg_controllen);
 
758
                        } else {
 
759
                                msg.msg_control = 0;
 
760
                                msg.msg_controllen = 0;
 
761
                        }
 
762
                        msg.msg_flags = umsg.msg_flags;
 
763
 
 
764
                        /* Do a sendmsg or recvmsg on the data, and copy out if needed */
 
765
 
 
766
                        if(syscall==SYS_SENDMSG) {
 
767
                                iovec_copy_in(p,(char*)vec.iov_base,uvec,umsg.msg_iovlen);
 
768
                                p->syscall_result = pfs_sendmsg(a[0],&msg,a[2]);
 
769
                        } else {
 
770
                                p->syscall_result = pfs_recvmsg(a[0],&msg,a[2]);
 
771
                                if(p->syscall_result>0) {
 
772
                                        iovec_copy_out(p,(char*)vec.iov_base,uvec,umsg.msg_iovlen);
 
773
                                        if(msg.msg_name && msg.msg_namelen>0) {
 
774
                                                tracer_copy_out(p->tracer,msg.msg_name,POINTER(umsg.msg_name),msg.msg_namelen);
 
775
                                        }
 
776
                                        if(msg.msg_control && msg.msg_controllen>0) {
 
777
                                                tracer_copy_out(p->tracer,msg.msg_control,POINTER(umsg.msg_control),msg.msg_controllen);
 
778
                                        }
 
779
                                        umsg.msg_namelen = msg.msg_namelen;
 
780
                                        umsg.msg_controllen = msg.msg_controllen;
 
781
                                        umsg.msg_flags = msg.msg_flags;
 
782
                                        tracer_copy_out(p->tracer,&umsg,POINTER(a[1]),sizeof(umsg));
 
783
                                }
 
784
 
 
785
                        }
 
786
 
 
787
                        /* Delete the msghdr structure */
 
788
 
 
789
                        if(msg.msg_control) free(msg.msg_control);
 
790
                        if(msg.msg_iov)     free(msg.msg_iov->iov_base);
 
791
                        if(uvec)            free(uvec);
 
792
                        if(msg.msg_name)    free(msg.msg_name);
 
793
 
 
794
                        if(p->syscall_result>=0) {
 
795
                                divert_to_dummy(p,p->syscall_result);
 
796
                        } else {
 
797
                                divert_to_dummy(p,-errno);
 
798
                        }
 
799
                        }
 
800
                        break;
 
801
                default:
 
802
                        r = -EINVAL;
 
803
                        divert_to_dummy(p,r);
 
804
                        break;
 
805
                }
 
806
        } else {
 
807
                /* Only these few have any action when exiting */
 
808
 
 
809
                switch(syscall) {
 
810
                        case SYS_SEND:
 
811
                                decode_write(p,entering,syscall,a);
 
812
                                break;
 
813
                        case SYS_SENDTO:
 
814
                                if(a[4]) {
 
815
                                        x = xxmalloc(a[5]);
 
816
                                        tracer_copy_in(p->tracer,x,POINTER(a[4]),a[5]);
 
817
                                        t4 = a[4];
 
818
                                        a[4] = (PTRINT_T)x;
 
819
                                }
 
820
                                decode_write(p,entering,syscall,a);
 
821
                                if(a[4]) {
 
822
                                        a[4] = t4;
 
823
                                        free(x);
 
824
                                }
 
825
                                break;
 
826
                        case SYS_RECV:
 
827
                        case SYS_RECVFROM:
 
828
                                decode_read(p,entering,syscall,a);
 
829
                                break;
 
830
                }
 
831
        }
 
832
}
 
833
                                                                 
 
834
/*
 
835
This function is an inexpensive test to see if a given
 
836
filename is executable.  It is not all-inclusive, nor should
 
837
it be considered a reliable security device.  This function is
 
838
over-optimistic in some cases, but if it falsely reports
 
839
true, the later real execve() may still fail.
 
840
*/
 
841
 
 
842
static int is_executable( const char *path )
 
843
{
 
844
        struct pfs_stat buf;
 
845
 
 
846
        if(pfs_stat(path,&buf)!=0) return 0;
 
847
 
 
848
        if(buf.st_mode&S_ISUID || buf.st_mode&S_ISGID) {
 
849
                debug(D_NOTICE,"cannot execute the program %s because it is setuid.",path);
 
850
                errno = EACCES;
 
851
                return 0;
 
852
        }
 
853
 
 
854
        if(buf.st_mode&S_IXUSR || buf.st_mode&S_IXGRP || buf.st_mode&S_IXOTH) {
 
855
                return 1;
 
856
        } else {
 
857
                errno = ENOEXEC;
 
858
                return 0;
 
859
        }
 
860
}
 
861
 
 
862
#define GET_PTR32(addr) ((PTRINT_T)(addr)&0xffffffff)
 
863
 
 
864
static void redirect_ldso( struct pfs_process *p, const char *ldso, INT64_T *args, char * const start_of_available_scratch )
 
865
{
 
866
        pid_t child_pid;
 
867
        int child_status;
 
868
        char real_physical_name[PFS_PATH_MAX];
 
869
        char ldso_physical_name[PFS_PATH_MAX];
 
870
        typedef unsigned int argv32;
 
871
        argv32 argv[PFS_ARG_MAX];
 
872
        char *ext_argv;
 
873
        char *ext_real_logical_name;
 
874
        char *ext_ldso_physical_name;
 
875
        char *ext_real_physical_name;
 
876
        INT64_T i, argc;
 
877
 
 
878
        strcpy(real_physical_name, p->new_physical_name);
 
879
        debug(D_PROCESS,"redirect_ldso: called on %s (%s)", p->new_logical_name, real_physical_name);
 
880
 
 
881
        if(pfs_get_local_name(ldso,ldso_physical_name,0,0)!=0) {
 
882
                debug(D_PROCESS,"redirect_ldso: cannot get physical name of %s",ldso);
 
883
 
 
884
                return;
 
885
        }
 
886
 
 
887
        /* Unwise to check ldso recursively */
 
888
        if (strcmp(real_physical_name, ldso_physical_name) == 0) return;
 
889
 
 
890
        /* Test whether loading with ldso would work by */
 
891
        /* running ldso --verify on the executable (may be static) */
 
892
 
 
893
        child_pid = fork();
 
894
        if (child_pid < 0) {
 
895
                debug(D_PROCESS,"redirect_ldso: cannot fork");
 
896
                return;
 
897
        }
 
898
        if (child_pid == 0) {
 
899
                int fd = open("/dev/null", O_WRONLY);
 
900
                if (fd >= 0) {
 
901
                        close(1);
 
902
                        close(2);
 
903
                        dup(fd);
 
904
                        dup(fd);
 
905
                }
 
906
                execlp(ldso_physical_name, ldso_physical_name, "--verify", real_physical_name, NULL);
 
907
                return;
 
908
        }
 
909
        waitpid(child_pid, &child_status, 0);
 
910
 
 
911
        if (!WIFEXITED(child_status)) {
 
912
                debug(D_PROCESS,"redirect_ldso: %s --verify %s didn't exit normally. status == %d", ldso_physical_name, real_physical_name, child_status);
 
913
                return;
 
914
        }
 
915
        if (WEXITSTATUS(child_status) != 0) {
 
916
                debug(D_PROCESS,"redirect_ldso: %s --verify %s exited with status %d", ldso_physical_name, real_physical_name, WEXITSTATUS(child_status));
 
917
                return;
 
918
        }
 
919
        
 
920
        /* Start with the physical name of ldso  */
 
921
        ext_ldso_physical_name = start_of_available_scratch;
 
922
                        
 
923
        /* strcpy(p->new_logical_name,ldso); */
 
924
        strcpy(p->new_physical_name,ldso_physical_name);
 
925
 
 
926
        /* then the "real" physical name */
 
927
        ext_real_physical_name = ext_ldso_physical_name + strlen(ldso_physical_name) + 1;
 
928
 
 
929
        /* and the "real" logical name */
 
930
        ext_real_logical_name = ext_real_physical_name + strlen(real_physical_name) + 1;
 
931
 
 
932
        /* the new argv goes in the scratch area next */
 
933
        ext_argv = ext_real_logical_name + strlen(p->new_logical_name) + 1;
 
934
 
 
935
        /* load in the arguments given by the program and count them up */
 
936
        tracer_copy_in(p->tracer,argv,POINTER(args[1]),sizeof(argv));
 
937
 
 
938
        for(argc=0;argv[argc] && argc<PFS_ARG_MAX;argc++) {}
 
939
 
 
940
        /* The original scratch area should have already been saved */
 
941
 
 
942
        /* write out the new exe, logical and physical names */
 
943
        tracer_copy_out(p->tracer,p->new_logical_name,ext_real_logical_name,strlen(p->new_logical_name)+1);
 
944
        tracer_copy_out(p->tracer,ldso_physical_name,ext_ldso_physical_name,strlen(ldso_physical_name)+1);
 
945
        tracer_copy_out(p->tracer,real_physical_name,ext_real_physical_name,strlen(real_physical_name)+1);
 
946
        /* rebuild the argv copy it out */
 
947
        for(i=argc;i>0;i--) argv[i] = argv[i-1];
 
948
        argc+=1;
 
949
        argv[0] = GET_PTR32(ext_real_logical_name);
 
950
        argv[1] = GET_PTR32(ext_real_physical_name);
 
951
        argv[argc] = 0;
 
952
        debug(D_PROCESS,"redirect_ldso: argc == %d", argc);
 
953
        for(i=0;i<=argc;i++) {
 
954
                tracer_copy_out(p->tracer,&argv[i],ext_argv+sizeof(argv32)*i,sizeof(argv32));
 
955
        }
 
956
 
 
957
        /* change the registers to reflect argv */
 
958
        args[0] = (PTRINT_T) ext_ldso_physical_name;
 
959
        args[1] = (PTRINT_T) ext_argv;
 
960
        tracer_args_set(p->tracer,p->syscall,args,3);
 
961
 
 
962
        debug(D_PROCESS,"redirect_ldso: will execute %s %s",ldso,real_physical_name);
 
963
}
 
964
 
 
965
/*
 
966
Several things to note about exec.
 
967
 
 
968
An entry to execve looks like a normal syscall.
 
969
An exit from execve indicates a successfull execve in progress.
 
970
Finally, a *third* event with args[0]==0 indicates an execve
 
971
that has completed with the new image active.
 
972
 
 
973
Now, we cannot execute the path named by the execve directly.
 
974
It must be resolved through PFS, because our idea of the 
 
975
current dir (or even the meaning of the name) may be quite
 
976
different.  We resolve the file name into a local path,
 
977
perhaps by pulling it into the cache.
 
978
 
 
979
In the simple (second) case, we copy the new local name
 
980
into the address space of the process and exec that instead.
 
981
If the exec fails, we must restore the changed bytes afterwards.
 
982
 
 
983
In the complex (first) case, the program contains a pound-bang
 
984
indicating an interpreter.  We instead resolve the interpreter
 
985
as the executable and fiddle around with the job's argv to
 
986
indicate that.  Then, we do much the same as the first case.
 
987
*/
 
988
 
 
989
void decode_execve( struct pfs_process *p, int entering, int syscall, INT64_T *args )
 
990
{
 
991
        char *scratch_addr  = (char*)pfs_process_scratch_address(p);
 
992
        int   scratch_size  = PFS_SCRATCH_SIZE;
 
993
        char *scratch_avail = scratch_addr;
 
994
 
 
995
        if(args[0]==0) {
 
996
                debug(D_PROCESS,"execve: %s executing ",p->name);
 
997
                p->state = PFS_PROCESS_STATE_USER;
 
998
        } else if(entering) {
 
999
                char path[PFS_PATH_MAX];
 
1000
                char firstline[PFS_PATH_MAX];
 
1001
 
 
1002
                tracer_copy_in_string(p->tracer,path,POINTER(args[0]),sizeof(path));
 
1003
 
 
1004
                p->new_logical_name[0] = 0;
 
1005
                p->new_physical_name[0] = 0;
 
1006
 
 
1007
                if(!is_executable(path)) {
 
1008
                        divert_to_dummy(p,-errno);
 
1009
                        return;
 
1010
                }
 
1011
 
 
1012
                firstline[0] = 0;
 
1013
                strcpy(p->new_logical_name,path);
 
1014
                if(pfs_get_local_name(path,p->new_physical_name,firstline,sizeof(firstline))<0) {
 
1015
                        divert_to_dummy(p,-errno);
 
1016
                        return;
 
1017
                }
 
1018
 
 
1019
                /* remove any newlines or spaces at the end */
 
1020
 
 
1021
                char *c = firstline;
 
1022
                while(*c) c++;
 
1023
                c--;
 
1024
                while( *c=='\n' || *c==' ' ) {
 
1025
                        *c = 0;
 
1026
                        c--;
 
1027
                }
 
1028
 
 
1029
                if(!strncmp(firstline,"#!",2)) {
 
1030
                        typedef unsigned int argv32;
 
1031
                        argv32 argv[PFS_ARG_MAX];
 
1032
                        char *ext_argv;
 
1033
                        char *interp, *ext_interp;
 
1034
                        char *interparg, *ext_interparg;
 
1035
                        char *scriptarg, *ext_scriptarg;
 
1036
                        char *ext_physical_name;
 
1037
                        int i, argc, shiftargs;
 
1038
 
 
1039
                        debug(D_PROCESS,"execve: %s is an interpreted executable",p->new_logical_name);
 
1040
 
 
1041
                        /* interp points to the interpreter */
 
1042
                        /* store it in the scratch area */
 
1043
 
 
1044
                        interp = &firstline[2];
 
1045
                        while(isspace(*interp)) interp++;
 
1046
                        ext_interp = scratch_addr;
 
1047
                        
 
1048
                        /* interparg points to the internal argument */
 
1049
                        /* scriptarg points to the script itself */
 
1050
                        interparg = strchr(interp,' ');
 
1051
                        if(interparg) {
 
1052
                                *interparg = 0;
 
1053
                                interparg++;    
 
1054
                                while(isspace(*interparg)) interparg++;
 
1055
                                ext_interparg = ext_interp + strlen(interp) + 1;
 
1056
                                scriptarg = path;
 
1057
                                ext_scriptarg = ext_interparg + strlen(interparg) + 1;
 
1058
                                debug(D_PROCESS,"execve: instead do %s %s %s",interp,interparg,scriptarg);
 
1059
                                shiftargs = 2;
 
1060
                        } else {
 
1061
                                interparg = 0;
 
1062
                                ext_interparg = ext_interp + strlen(interp) + 1; /* BUG ? Why shouldn't it skip interp ?*/
 
1063
                                scriptarg = path;
 
1064
                                ext_scriptarg = ext_interparg;
 
1065
                                shiftargs = 1;
 
1066
                                debug(D_PROCESS,"execve: instead do %s %s",interp,scriptarg);
 
1067
                        }
 
1068
 
 
1069
 
 
1070
                        /* make sure the new interp is loaded */
 
1071
                        strcpy(p->new_logical_name,interp);
 
1072
                        if(pfs_get_local_name(interp,p->new_physical_name,0,0)!=0) {
 
1073
                                divert_to_dummy(p,-errno);
 
1074
                                return;
 
1075
                        }
 
1076
 
 
1077
                        /* the physical name of the interp is next */
 
1078
                        ext_physical_name = ext_scriptarg + strlen(scriptarg) + 1;
 
1079
                        /* make sure redirect_ldso doesn't clobber arguments */
 
1080
                        scratch_avail = ext_physical_name;
 
1081
 
 
1082
                        /* the new argv goes in the scratch area next */
 
1083
                        ext_argv = ext_physical_name + strlen(p->new_physical_name) + 1;
 
1084
 
 
1085
                        /* load in the arguments given by the program and count them up */
 
1086
                        tracer_copy_in(p->tracer,argv,POINTER(args[1]),sizeof(argv));
 
1087
                        for(argc=0;argv[argc] && argc<PFS_ARG_MAX;argc++) {}
 
1088
 
 
1089
                        /* save the scratch area */
 
1090
                        tracer_copy_in(p->tracer,p->scratch_data,scratch_addr,scratch_size);
 
1091
 
 
1092
                        /* write out the new interp, arg, and physical name */
 
1093
                        tracer_copy_out(p->tracer,interp,ext_interp,strlen(interp)+1);
 
1094
                        if(interparg) tracer_copy_out(p->tracer,interparg,ext_interparg,strlen(interparg)+1);
 
1095
                        tracer_copy_out(p->tracer,scriptarg,ext_scriptarg,strlen(scriptarg)+1);
 
1096
                        tracer_copy_out(p->tracer,p->new_physical_name,ext_physical_name,strlen(p->new_physical_name)+1);
 
1097
                        /* rebuild the argv copy it out */
 
1098
                        for(i=argc-1+shiftargs;i>0;i--) argv[i] = argv[i-shiftargs];
 
1099
                        argc+=shiftargs;
 
1100
                        argv[0] = GET_PTR32(ext_interp);
 
1101
                        if(interparg) {
 
1102
                                argv[1] = GET_PTR32(ext_interparg);
 
1103
                                argv[2] = GET_PTR32(ext_scriptarg);
 
1104
                        } else {
 
1105
                                argv[1] = GET_PTR32(ext_scriptarg);
 
1106
                        }
 
1107
                        argv[argc] = 0;
 
1108
                        for(i=0;i<=argc;i++) {
 
1109
                                tracer_copy_out(p->tracer,&argv[i],ext_argv+sizeof(argv32)*i,sizeof(argv32));
 
1110
                        }
 
1111
 
 
1112
                        /* change the registers to reflect argv */
 
1113
                        args[0] = (PTRINT_T) ext_physical_name;
 
1114
                        args[1] = (PTRINT_T) ext_argv;
 
1115
                        tracer_args_set(p->tracer,p->syscall,args,3); /* BUG? Why 3 ? */
 
1116
                } else {
 
1117
                        debug(D_PROCESS,"execve: %s is an ordinary executable",p->new_logical_name);
 
1118
 
 
1119
                        /* save all of the data we are going to clobber */
 
1120
                        tracer_copy_in(p->tracer,p->scratch_data,scratch_addr,scratch_size);
 
1121
 
 
1122
                        /* store the new local path */
 
1123
                        tracer_copy_out(p->tracer,p->new_physical_name,scratch_addr,strlen(p->new_physical_name)+1);
 
1124
 
 
1125
                        /* set the new program name to the logical name */
 
1126
                        args[0] = (PTRINT_T) scratch_addr;
 
1127
                        tracer_args_set(p->tracer,p->syscall,args,3); /* BUG? Why 3 ? */
 
1128
                }
 
1129
                if (pfs_ldso_path) {
 
1130
                        redirect_ldso(p, pfs_ldso_path, args, scratch_avail);
 
1131
                }
 
1132
                debug(D_PROCESS,"execve: %s attempting",p->new_logical_name);
 
1133
 
 
1134
                /* FIXME: It would be nice if we could test whether the D_PROCESS */
 
1135
                /* debug flag is set. */
 
1136
                if (1) {
 
1137
                        typedef unsigned int argv32;
 
1138
                        argv32 argv[PFS_ARG_MAX];
 
1139
                        char debug_argv[256];
 
1140
                        int argc;
 
1141
                        tracer_copy_in(p->tracer,argv,POINTER(args[1]),sizeof(argv));
 
1142
                        for(argc=0;argv[argc] && argc<PFS_ARG_MAX;argc++) {
 
1143
                                debug_argv[sizeof(debug_argv)-1] = 0;
 
1144
                                tracer_copy_in(p->tracer,debug_argv,POINTER(argv[argc]),sizeof(debug_argv)-1);
 
1145
                                debug(D_PROCESS,"execve: argv[%d] == \"%s\"", argc, debug_argv);
 
1146
                        }
 
1147
                }
 
1148
        } else {
 
1149
                INT64_T actual_result;
 
1150
                tracer_result_get(p->tracer,&actual_result);
 
1151
                if(actual_result==0) {
 
1152
                        debug(D_PROCESS,"execve: %s working",p->new_logical_name);
 
1153
                        strcpy(p->name,p->new_logical_name);
 
1154
                        /* after a successful exec, signal handlers are reset */
 
1155
                        memset(p->signal_interruptible,0,sizeof(p->signal_interruptible));
 
1156
                        /* and certain files in the file table are closed */
 
1157
                        p->table->close_on_exec();
 
1158
                        /* and our knowledge of the address space is gone. */
 
1159
                        p->heap_address = 0;
 
1160
                        p->break_address = 0;
 
1161
                        debug(D_PSTREE,"%d exec %s",p->pid,p->new_logical_name);
 
1162
                } else if(p->new_logical_name[0]) {
 
1163
                        debug(D_PROCESS,"execve: %s failed",p->new_logical_name);
 
1164
                        debug(D_PROCESS,"execve: restoring scratch area");
 
1165
                        tracer_copy_out(p->tracer,p->scratch_data,(void*)scratch_addr,scratch_size);
 
1166
                }
 
1167
        }
 
1168
}
 
1169
 
 
1170
 
 
1171
/*
 
1172
Memory mapped files are loaded into the channel,
 
1173
the whole file regardless of what portion is actually
 
1174
mapped.  The channel cache keeps a reference count.
 
1175
 
 
1176
Note some unusual behavior in the implementation of mmap:
 
1177
 
 
1178
The "old" mmap system call simply stores the arguments
 
1179
to mmap in memory, and passes a pointer to the arguments
 
1180
in args[0].  The offset is measured in bytes, as you
 
1181
might expect.
 
1182
 
 
1183
The "new" mmap2 system call puts all of the arguments
 
1184
in registers, **AND** measures the offset in NUMBER OF PAGES,
 
1185
not in bytes! 
 
1186
 
 
1187
To unify the two cases, we copy the arguments into the
 
1188
nargs array and adjust the offset as needed.
 
1189
*/
 
1190
 
 
1191
void decode_mmap( struct pfs_process *p, int syscall, int entering, INT64_T *args )
 
1192
{
 
1193
        if(entering) {
 
1194
                UINT32_T addr, orig_length, prot, fd, flags;
 
1195
                UINT32_T nargs[TRACER_ARGS_MAX];
 
1196
                pfs_size_t length, channel_offset, source_offset;
 
1197
 
 
1198
                if(p->syscall==SYSCALL32_mmap) {
 
1199
                        tracer_copy_in(p->tracer,nargs,POINTER(args[0]),sizeof(nargs));
 
1200
                } else {
 
1201
                        for(int i=0;i<TRACER_ARGS_MAX;i++) {
 
1202
                                nargs[i] = args[i];
 
1203
                        }
 
1204
                }
 
1205
 
 
1206
                addr = nargs[0];
 
1207
                orig_length = nargs[1];
 
1208
                prot = nargs[2];
 
1209
                flags = nargs[3];
 
1210
                fd = nargs[4];
 
1211
 
 
1212
                if(p->syscall==SYSCALL32_mmap) {
 
1213
                        source_offset = nargs[5];
 
1214
                } else {
 
1215
                        source_offset = nargs[5]*getpagesize();
 
1216
                }
 
1217
 
 
1218
                // Note that on many versions of Linux, nargs[5]
 
1219
                // is corrupted in mmap2 on a 64-bit machine.
 
1220
                // See comments in tracer.c and
 
1221
                // http://lkml.org/lkml/2007/1/31/317
 
1222
 
 
1223
                #ifdef CCTOOLS_CPU_X86_64
 
1224
                if(p->syscall==SYSCALL32_mmap2 && (source_offset & 0x80000000 )) {
 
1225
                        debug(D_SYSCALL,"detected kernel bug in ptrace: offset has suspicious value of 0x%llx",source_offset);
 
1226
                        tracer_has_args5_bug(p->tracer);
 
1227
                        tracer_args_get(p->tracer,&p->syscall,p->syscall_args);
 
1228
                        source_offset = args[5]*getpagesize();
 
1229
                        debug(D_SYSCALL,"detected kernel bug in ptrace: new offset is 0x%llx",source_offset);
 
1230
                }
 
1231
                #endif
 
1232
 
 
1233
                debug(D_SYSCALL,"mmap addr=0x%x len=0x%x prot=0x%x flags=0x%x fd=%d offset=0x%llx",addr,orig_length,prot,flags,fd,source_offset);
 
1234
 
 
1235
                if(flags&MAP_ANONYMOUS) {
 
1236
                        /* great, just do it. */
 
1237
                        debug(D_SYSCALL,"mmap skipped b/c anonymous");
 
1238
                } else {
 
1239
                        char file_name[PFS_PATH_MAX];
 
1240
 
 
1241
                        if(pfs_get_full_name(fd,file_name)!=0) {
 
1242
                                debug(D_SYSCALL,"mmap failed name: %s",strerror(errno));
 
1243
                                divert_to_dummy(p,-errno);
 
1244
                                return;
 
1245
                        }
 
1246
 
 
1247
                        if(pfs_channel_cache_alloc(file_name,fd,&length,&channel_offset)) {
 
1248
                                nargs[3] = flags & ~MAP_DENYWRITE;
 
1249
                                nargs[4] = pfs_channel_fd();
 
1250
                                nargs[5] = channel_offset+source_offset;
 
1251
 
 
1252
                                debug(D_SYSCALL,"channel_offset=0x%llx source_offset=0x%llx total=0x%x",channel_offset,source_offset,nargs[5]);
 
1253
 
 
1254
                                if(p->syscall==SYSCALL32_mmap) {
 
1255
                                        tracer_copy_out(p->tracer,nargs,POINTER(args[0]),sizeof(nargs));
 
1256
                                } else {
 
1257
                                        nargs[5] = nargs[5] / getpagesize();
 
1258
                                        for(int i=0;i<TRACER_ARGS_MAX;i++) {
 
1259
                                                args[i] = nargs[i];
 
1260
                                        }
 
1261
                                        tracer_args_set(p->tracer,p->syscall,args,6);
 
1262
                                        p->syscall_args_changed = 1;
 
1263
                                }       
 
1264
                                debug(D_SYSCALL,"mmap changed: fd=%d addr=0x%x",nargs[4],nargs[5]);
 
1265
                        } else {
 
1266
                                debug(D_SYSCALL,"mmap failed cache: %s",strerror(errno));
 
1267
                                divert_to_dummy(p,-errno);
 
1268
                                return;
 
1269
                        }
 
1270
                }
 
1271
        }
 
1272
}
 
1273
 
 
1274
int decode_ioctl_siocgifconf( struct pfs_process *p, int fd, int cmd, void *uaddr )
 
1275
{
 
1276
        struct pfs_kernel_ifconf uifc;
 
1277
        struct ifconf ifc;
 
1278
        char *buffer;
 
1279
        int length;
 
1280
        int result;
 
1281
 
 
1282
        tracer_copy_in(p->tracer,&uifc,uaddr,sizeof(uifc));
 
1283
        buffer = (char*) malloc(uifc.ifc_len);
 
1284
        length = tracer_copy_in(p->tracer,buffer,(void*)(PTRINT_T)uifc.ifc_buffer,uifc.ifc_len);
 
1285
 
 
1286
        ifc.ifc_buf = buffer;
 
1287
        ifc.ifc_len = length;
 
1288
 
 
1289
        result = pfs_ioctl(fd,cmd,&ifc);
 
1290
 
 
1291
        if(result>=0) {
 
1292
                uifc.ifc_len = ifc.ifc_len;
 
1293
                tracer_copy_out(p->tracer,&uifc,uaddr,sizeof(uifc));
 
1294
                tracer_copy_out(p->tracer,buffer,(void*)(PTRINT_T)uifc.ifc_buffer,uifc.ifc_len);
 
1295
        }
 
1296
 
 
1297
        free(buffer);
 
1298
        
 
1299
        return result;
 
1300
}
 
1301
 
 
1302
void decode_syscall( struct pfs_process *p, int entering )
 
1303
{
 
1304
        INT64_T *args;
 
1305
 
 
1306
        char path[PFS_PATH_MAX];
 
1307
        char path2[PFS_PATH_MAX];
 
1308
 
 
1309
        if(entering) {
 
1310
                p->state = PFS_PROCESS_STATE_KERNEL;
 
1311
                p->syscall_dummy = 0;
 
1312
                tracer_args_get(p->tracer,&p->syscall,p->syscall_args);
 
1313
                debug(D_SYSCALL,"%s",tracer_syscall_name(p->tracer,p->syscall));
 
1314
                p->syscall_original = p->syscall;
 
1315
                pfs_syscall_count++;
 
1316
 
 
1317
                if(pfs_syscall_totals32) {
 
1318
                        int s = p->syscall;
 
1319
                        if(s>=0 && s<SYSCALL32_MAX) {
 
1320
                                pfs_syscall_totals32[p->syscall]++;
 
1321
                        }
 
1322
                }
 
1323
        }
 
1324
 
 
1325
        args = p->syscall_args;
 
1326
 
 
1327
        switch(p->syscall) {
 
1328
                case SYSCALL32_oldolduname:
 
1329
                        p->syscall = SYSCALL32_execve;
 
1330
 
 
1331
                case SYSCALL32_execve:
 
1332
                        decode_execve(p,entering,p->syscall,args);
 
1333
                        break;
 
1334
 
 
1335
                /*
 
1336
                Some variants of fork do not propagate ptrace, so we
 
1337
                must convert them into clone with appropriate flags.
 
1338
                Once a fork is started, we must trace only that pid
 
1339
                so that we can determine the child pid before seeing
 
1340
                any events from the child. On return, we must fill
 
1341
                in the child process with its parent's ppid.
 
1342
                */
 
1343
 
 
1344
                case SYSCALL32_fork:
 
1345
                case SYSCALL32_clone:
 
1346
                        if(entering) {
 
1347
                                INT64_T newargs[4];
 
1348
                                int newargs_count;
 
1349
                                if(p->syscall==SYSCALL32_fork) {
 
1350
                                        newargs[0] = CLONE_PTRACE|CLONE_PARENT|SIGCHLD;
 
1351
                                        newargs[1] = 0;
 
1352
                                        newargs_count = 2;
 
1353
                                        p->syscall_args_changed = 1;
 
1354
                                        debug(D_SYSCALL,"converting fork into clone(%x)",newargs[0]);
 
1355
                                } else {
 
1356
                                        newargs[0] = (args[0]&~0xff)|CLONE_PTRACE|CLONE_PARENT|SIGCHLD;
 
1357
                                        newargs_count = 1;
 
1358
                                        debug(D_SYSCALL,"adjusting clone(%llx,%llx,%llx,%llx) -> clone(%llx)",args[0],args[1],args[2],args[3],newargs[0]);
 
1359
                                }
 
1360
                                tracer_args_set(p->tracer,SYSCALL32_clone,newargs,newargs_count);
 
1361
                                trace_this_pid = p->pid;
 
1362
                        } else {
 
1363
                                INT64_T childpid;
 
1364
                                struct pfs_process *child;
 
1365
                                tracer_result_get(p->tracer,&childpid);
 
1366
                                if(childpid>0) {
 
1367
                                        int child_signal,clone_files;
 
1368
                                        if(p->syscall_original==SYSCALL32_fork) {
 
1369
                                                child_signal = SIGCHLD;
 
1370
                                                clone_files = 0;
 
1371
                                        } else {
 
1372
                                                child_signal = args[0]&0xff;
 
1373
                                                clone_files = args[0]&CLONE_FILES;
 
1374
                                        }
 
1375
                                        pid_t notify_parent;
 
1376
                                        if(args[0]&(CLONE_PARENT|CLONE_THREAD)) {
 
1377
                                                notify_parent = p->ppid;
 
1378
                                        } else {
 
1379
                                                notify_parent = p->pid;
 
1380
                                        }
 
1381
                                        child = pfs_process_create(childpid,p->pid,notify_parent,clone_files,child_signal);
 
1382
                                        child->syscall_result = 0;
 
1383
                                        if(args[0]&CLONE_THREAD) child->tgid = p->tgid;
 
1384
                                        if(p->syscall_original==SYSCALL32_fork) {
 
1385
                                                memcpy(child->syscall_args,p->syscall_args,sizeof(p->syscall_args));
 
1386
                                                child->syscall_args_changed = 1;
 
1387
                                        }
 
1388
                                        if(pfs_trap_after_fork) {
 
1389
                                                child->state = PFS_PROCESS_STATE_KERNEL;
 
1390
                                        } else {
 
1391
                                                child->state = PFS_PROCESS_STATE_USER;
 
1392
                                        }
 
1393
                                        debug(D_PROCESS,"%d created pid %d",(int)p->pid,(int)childpid);
 
1394
                                        /* now trace any process at all */
 
1395
                                        trace_this_pid = -1;
 
1396
                                }
 
1397
 
 
1398
                        }
 
1399
                        break;
 
1400
 
 
1401
                /*
 
1402
                Note that we do not support vfork.  The behavior of vfork
 
1403
                varies greatly from kernel to kernel, and is in fact impossible
 
1404
                to support through ptrace without a kernel patch in some cases.
 
1405
                However, glibc is smart and converts vfork into fork if the
 
1406
                kernel response that it does not exist.  So, failed vforks
 
1407
                eventually end up in the previous case.  Also note parrot_helper.so,
 
1408
                which also aims to solve this problem.
 
1409
                */
 
1410
 
 
1411
                case SYSCALL32_vfork:
 
1412
                        if(entering) {
 
1413
                                debug(D_NOTICE,"sorry, I cannot run this program (%s) without parrot_helper.so.",p->name);
 
1414
                                divert_to_dummy(p,-ENOSYS);
 
1415
                        }
 
1416
                        break;
 
1417
 
 
1418
                /*
 
1419
                On ptraces that do not preserve the process structure,
 
1420
                we must trap and manage variants of wait() to permit
 
1421
                the propagation of child completion.
 
1422
                */
 
1423
                case SYSCALL32_waitpid:
 
1424
                        if(entering) {
 
1425
                                pfs_process_waitpid(p,args[0],(int*)POINTER(args[1]),args[2],0);
 
1426
                                divert_to_dummy(p,p->syscall_result);
 
1427
                        }
 
1428
                        break;
 
1429
 
 
1430
                case SYSCALL32_wait4:
 
1431
                        if(entering) {
 
1432
                                pfs_process_waitpid(p,args[0],(int*)POINTER(args[1]),args[2],(struct rusage*)POINTER(args[3]));
 
1433
                                divert_to_dummy(p,p->syscall_result);
 
1434
                        }
 
1435
                        break;
 
1436
 
 
1437
                /*
 
1438
                We don't do anything special with exit.  Just let it
 
1439
                run to completion, and then process the exit event
 
1440
                in the main loop.
 
1441
                */
 
1442
 
 
1443
                case SYSCALL32_exit:
 
1444
                case SYSCALL32_exit_group:
 
1445
                        break;
 
1446
 
 
1447
                /*
 
1448
                Here begin all of the I/O operations, given in the
 
1449
                same order as in pfs_table.  Notice that most operations
 
1450
                use the simple but slow tracer_copy_{in,out} routines.
 
1451
                When performance is important (write,mmap), we resort
 
1452
                to redirection I/O to the side channel.
 
1453
                */
 
1454
 
 
1455
                /* File descriptor creation */
 
1456
 
 
1457
                case SYSCALL32_open:
 
1458
                case SYSCALL32_creat:
 
1459
                        if(entering) {
 
1460
                                tracer_copy_in_string(p->tracer,path,POINTER(args[0]),sizeof(path));
 
1461
                                if(p->syscall==SYSCALL32_creat) {
 
1462
                                        p->syscall_result = pfs_open(path,O_CREAT|O_WRONLY|O_TRUNC,args[1]);
 
1463
                                } else {
 
1464
                                        p->syscall_result = pfs_open(path,args[1],args[2]);
 
1465
                                }
 
1466
                                if(p->syscall_result<0) p->syscall_result = -errno;
 
1467
                                divert_to_dummy(p,p->syscall_result);
 
1468
                        }
 
1469
                        break;
 
1470
 
 
1471
                case SYSCALL32_pipe:
 
1472
                        if(entering) {
 
1473
                                int fds[2];
 
1474
                                p->syscall_result = pfs_pipe(fds);
 
1475
                                if(p->syscall_result<0) {
 
1476
                                        p->syscall_result = -errno;
 
1477
                                } else {
 
1478
                                        tracer_copy_out(p->tracer,(void*)fds,POINTER(args[0]),sizeof(fds));
 
1479
                                }
 
1480
                                divert_to_dummy(p,p->syscall_result);
 
1481
                        }
 
1482
                        break;
 
1483
 
 
1484
                /* operations on open files */
 
1485
 
 
1486
                case SYSCALL32_close:
 
1487
                        if(entering) {
 
1488
                                p->syscall_result = pfs_close(args[0]);
 
1489
                                if(p->syscall_result<0) p->syscall_result = -errno;
 
1490
                                divert_to_dummy(p,p->syscall_result);
 
1491
                        }
 
1492
                        break;
 
1493
 
 
1494
                case SYSCALL32_read:
 
1495
                case SYSCALL32_pread:
 
1496
                        decode_read(p,entering,p->syscall,args);
 
1497
                        break;
 
1498
 
 
1499
                case SYSCALL32_write:
 
1500
                case SYSCALL32_pwrite:
 
1501
                        decode_write(p,entering,p->syscall,args);
 
1502
                        break;
 
1503
 
 
1504
                case SYSCALL32_readv:
 
1505
                        decode_readv(p,entering,p->syscall,args);
 
1506
                        break;
 
1507
 
 
1508
                case SYSCALL32_writev:
 
1509
                        decode_writev(p,entering,p->syscall,args);
 
1510
                        break;
 
1511
 
 
1512
                case SYSCALL32_socketcall: {
 
1513
                        INT32_T subargs[6];
 
1514
                        INT64_T subargs64[6];
 
1515
                        int i;
 
1516
                        tracer_copy_in(p->tracer,subargs,POINTER(args[1]),sizeof(subargs));
 
1517
                        for(i=0;i<6;i++) subargs64[i] = subargs[i];
 
1518
                        decode_socketcall(p,entering,args[0],subargs64);
 
1519
                        break;
 
1520
                }
 
1521
 
 
1522
                /*
 
1523
                Now we have a series of standard file operations that
 
1524
                only use the integer arguments, and are (mostly) easily
 
1525
                passed back and forth.
 
1526
                */
 
1527
 
 
1528
                case SYSCALL32_lseek:
 
1529
                        if(entering) {
 
1530
                                p->syscall_result = pfs_lseek(args[0],args[1],args[2]);
 
1531
                                if(p->syscall_result<0) p->syscall_result = -errno;
 
1532
                                divert_to_dummy(p,p->syscall_result);
 
1533
                        }
 
1534
                        break;
 
1535
 
 
1536
                case SYSCALL32__llseek:
 
1537
                        if(entering) {
 
1538
                                UINT64_T high = args[1];
 
1539
                                UINT64_T low = args[2];
 
1540
                                UINT64_T offset = (high<<32) | low;
 
1541
                                INT64_T result = pfs_lseek(args[0],offset,args[4]);
 
1542
                                if(result<0) {
 
1543
                                        p->syscall_result = -errno;
 
1544
                                } else {
 
1545
                                        tracer_copy_out(p->tracer,&result,POINTER(args[3]),sizeof(result));
 
1546
                                        p->syscall_result = 0;
 
1547
                                }
 
1548
                                divert_to_dummy(p,p->syscall_result);
 
1549
                        }
 
1550
                        break;
 
1551
 
 
1552
                case SYSCALL32_ftruncate:
 
1553
                        if(entering) {
 
1554
                                p->syscall_result = pfs_ftruncate(args[0],args[1]);
 
1555
                                if(p->syscall_result<0) p->syscall_result = -errno;
 
1556
                                divert_to_dummy(p,p->syscall_result);
 
1557
                        }
 
1558
                break;
 
1559
 
 
1560
                case SYSCALL32_ftruncate64:
 
1561
                        if(entering) {
 
1562
                                INT64_T offset = args[1]+(((INT64_T)args[2])<<32);
 
1563
                                p->syscall_result = pfs_ftruncate(args[0],offset);
 
1564
                                if(p->syscall_result<0) p->syscall_result = -errno;
 
1565
                                divert_to_dummy(p,p->syscall_result);
 
1566
                        }
 
1567
                        break;
 
1568
 
 
1569
                case SYSCALL32_fstat:
 
1570
                        decode_stat(p,entering,SYSCALL32_fstat,args,0);
 
1571
                        break;
 
1572
                case SYSCALL32_fstat64:
 
1573
                        decode_stat(p,entering,SYSCALL32_fstat,args,1);
 
1574
                        break;
 
1575
                case SYSCALL32_fstatfs:
 
1576
                        decode_statfs(p,entering,SYSCALL32_fstatfs,args,0);
 
1577
                        break;
 
1578
                case SYSCALL32_fstatfs64:
 
1579
                        decode_statfs(p,entering,SYSCALL32_fstatfs,args,1);
 
1580
                        break;
 
1581
 
 
1582
                case SYSCALL32_flock:
 
1583
                        if(entering) {
 
1584
                                p->syscall_result = pfs_flock(args[0],args[1]);
 
1585
                                if(p->syscall_result<0) p->syscall_result = -errno;
 
1586
                                divert_to_dummy(p,p->syscall_result);
 
1587
                        }
 
1588
                        break;
 
1589
                                
 
1590
                case SYSCALL32_fsync:
 
1591
                case SYSCALL32_fdatasync:
 
1592
                        if(entering) {
 
1593
                                p->syscall_result = pfs_fsync(args[0]);
 
1594
                                if(p->syscall_result<0) p->syscall_result = -errno;
 
1595
                                divert_to_dummy(p,p->syscall_result);
 
1596
                        }
 
1597
                        break;
 
1598
 
 
1599
                case SYSCALL32_fchdir:
 
1600
                        if(entering) {
 
1601
                                p->syscall_result = pfs_fchdir(args[0]);
 
1602
                                if(p->syscall_result<0) p->syscall_result = -errno;
 
1603
                                divert_to_dummy(p,p->syscall_result);
 
1604
                        }
 
1605
                        break;
 
1606
 
 
1607
                case SYSCALL32_fchmod:
 
1608
                        if(entering) {
 
1609
                                p->syscall_result = pfs_fchmod(args[0],args[1]);
 
1610
                                if(p->syscall_result<0) p->syscall_result = -errno;
 
1611
                                divert_to_dummy(p,p->syscall_result);
 
1612
                        }
 
1613
                        break;
 
1614
 
 
1615
                case SYSCALL32_fchown:
 
1616
                case SYSCALL32_fchown32:
 
1617
                        if(entering) {
 
1618
                                p->syscall_result = pfs_fchown(args[0],args[1],args[2]);
 
1619
                                if(p->syscall_result<0) p->syscall_result = -errno;
 
1620
                                divert_to_dummy(p,p->syscall_result);
 
1621
                        }
 
1622
                        break;
 
1623
 
 
1624
                /*
 
1625
                ioctl presents both bad news and good news.
 
1626
                The bad news is that all ioctl operations are driver
 
1627
                specific.  I have no intention of coding up all the
 
1628
                possible ioctls here, nor could I. However, it is a fair
 
1629
                assumption that the third argument, when a valid pointer,
 
1630
                is a continuous and small chunk of memory.  So, we copy
 
1631
                in one page that it points to (if any), and use that as
 
1632
                a temporary buffer.  We copy back to the application only
 
1633
                those words in the buffer that change.  If none change,
 
1634
                then the argument was likely interpreted as an integer
 
1635
                rather than a pointer.  A nice coincidence is that 
 
1636
                copy in is generally efficient, while copy out, though
 
1637
                slow, is minimized.
 
1638
                */
 
1639
 
 
1640
                case SYSCALL32_ioctl:
 
1641
                        if(entering) {
 
1642
                                int fd = args[0];
 
1643
                                int cmd = args[1];
 
1644
                                void *uaddr = POINTER(args[2]);
 
1645
                                char buffer[65536];
 
1646
                                char tbuffer[65536];
 
1647
                                int length = 0;
 
1648
 
 
1649
 
 
1650
                                if(cmd==SIOCGIFCONF) {
 
1651
                                        p->syscall_result = decode_ioctl_siocgifconf(p,fd,cmd,uaddr);
 
1652
                                        divert_to_dummy(p,p->syscall_result);
 
1653
                                        break;
 
1654
                                }
 
1655
 
 
1656
                                if(uaddr) {
 
1657
                                        length = tracer_copy_in(p->tracer,buffer,uaddr,sizeof(buffer));
 
1658
                                        if(length>0) {
 
1659
                                                memcpy(tbuffer,buffer,length);
 
1660
                                                p->syscall_result = pfs_ioctl(fd,cmd,buffer);
 
1661
                                        } else {
 
1662
                                                uaddr = 0;
 
1663
                                                p->syscall_result = pfs_ioctl(fd,cmd,uaddr);
 
1664
                                        }
 
1665
                                } else {
 
1666
                                        p->syscall_result = pfs_ioctl(fd,cmd,uaddr);
 
1667
                                }
 
1668
 
 
1669
                                if(p->syscall_result<0) {
 
1670
                                        p->syscall_result = -errno;
 
1671
                                } else {
 
1672
                                        if(uaddr) {
 
1673
                                                int i, changed=0;
 
1674
                                                for(i=0;i<length;i++) {
 
1675
                                                        if(tbuffer[i]!=buffer[i]) {
 
1676
                                                                changed = i+1;
 
1677
                                                        }
 
1678
                                                }
 
1679
                                                changed = _ROUND_UP(changed,sizeof(int));
 
1680
                                                tracer_copy_out(p->tracer,buffer,uaddr,changed);
 
1681
                                        }
 
1682
                                }
 
1683
                                divert_to_dummy(p,p->syscall_result);
 
1684
                        }
 
1685
                        break;
 
1686
 
 
1687
                /*
 
1688
                Unlike ioctl, fcntl operations are rather generic
 
1689
                and operate on the file table itself.  These things
 
1690
                we can parse, understand, and pass along to the 
 
1691
                file table in most cases.
 
1692
 
 
1693
                We permit the user to set the O_ASYNC flag and thus
 
1694
                receive activity notification via SIGIO.  However,
 
1695
                we don't yet support extended signal information.
 
1696
                */
 
1697
 
 
1698
                case SYSCALL32_fcntl:
 
1699
                case SYSCALL32_fcntl64:
 
1700
                        if(entering) {
 
1701
                                int fd = args[0];
 
1702
                                int cmd = args[1];
 
1703
                                void *uaddr = POINTER(args[2]);
 
1704
                                struct pfs_kernel_flock kfl;
 
1705
                                struct pfs_kernel_flock64 kfl64;
 
1706
                                struct flock fl;
 
1707
                                struct flock64 fl64;
 
1708
                                PTRINT_T pid;
 
1709
 
 
1710
                                switch(cmd) {
 
1711
                                        case F_DUPFD:
 
1712
                                        case F_GETFD:
 
1713
                                        case F_SETFD:
 
1714
                                        case F_GETFL:
 
1715
                                        case F_SETFL:
 
1716
                                                p->syscall_result = pfs_fcntl(fd,cmd,uaddr);
 
1717
                                                if(p->syscall_result<0) p->syscall_result=-errno;
 
1718
                                                divert_to_dummy(p,p->syscall_result);
 
1719
 
 
1720
                                                if(cmd==F_SETFL) {
 
1721
                                                        int flags = (int)args[2];
 
1722
                                                        if(flags&O_ASYNC) {
 
1723
                                                                debug(D_PROCESS,"pid %d requests O_ASYNC on fd %d",(int)pfs_current->pid,(int)fd);
 
1724
                                                                p->flags |= PFS_PROCESS_FLAGS_ASYNC;
 
1725
                                                        }
 
1726
                                                }
 
1727
                                                break;
 
1728
 
 
1729
                                        case PFS_GETLK:
 
1730
                                        case PFS_SETLK:
 
1731
                                        case PFS_SETLKW:
 
1732
                                                tracer_copy_in(p->tracer,&kfl,uaddr,sizeof(kfl));
 
1733
                                                COPY_FLOCK(kfl,fl);
 
1734
                                                p->syscall_result = pfs_fcntl(fd,cmd,&kfl);
 
1735
                                                if(p->syscall_result<0) {
 
1736
                                                        p->syscall_result=-errno;
 
1737
                                                } else {
 
1738
                                                        COPY_FLOCK(fl,kfl);
 
1739
                                                        tracer_copy_out(p->tracer,&kfl,uaddr,sizeof(kfl));
 
1740
                                                }
 
1741
                                                divert_to_dummy(p,p->syscall_result);
 
1742
                                                break;
 
1743
 
 
1744
                                        case PFS_GETLK64:
 
1745
                                        case PFS_SETLK64:
 
1746
                                        case PFS_SETLKW64:
 
1747
                                                tracer_copy_in(p->tracer,&kfl64,uaddr,sizeof(kfl64));
 
1748
                                                COPY_FLOCK(kfl64,fl64);
 
1749
                                                p->syscall_result = pfs_fcntl(fd,cmd,&fl64);
 
1750
                                                if(p->syscall_result<0) {
 
1751
                                                        p->syscall_result=-errno;
 
1752
                                                } else {
 
1753
                                                        COPY_FLOCK(fl64,kfl64);
 
1754
                                                        tracer_copy_out(p->tracer,&kfl64,uaddr,sizeof(kfl64));
 
1755
                                                }
 
1756
                                                divert_to_dummy(p,p->syscall_result);
 
1757
                                                break;
 
1758
 
 
1759
                                        /* Pretend that the caller is the signal recipient */
 
1760
                                        case F_GETOWN:
 
1761
                                                divert_to_dummy(p,p->pid);
 
1762
                                                break;
 
1763
 
 
1764
                                        /* But we always get the signal. */
 
1765
                                        case F_SETOWN:
 
1766
                                                debug(D_PROCESS,"pid %d requests F_SETOWN on fd %d",(int)pfs_current->pid,(int)fd);
 
1767
                                                p->flags |= PFS_PROCESS_FLAGS_ASYNC;
 
1768
                                                pid = getpid();
 
1769
                                                pfs_fcntl(fd,F_SETOWN,(void*)pid);
 
1770
                                                divert_to_dummy(p,0);
 
1771
                                                break;
 
1772
 
 
1773
                                        default:
 
1774
                                                divert_to_dummy(p,-ENOSYS);
 
1775
                                                break;
 
1776
                                }
 
1777
                        }
 
1778
                        break;
 
1779
 
 
1780
 
 
1781
                case SYSCALL32_mmap:
 
1782
                case SYSCALL32_mmap2:
 
1783
                        decode_mmap(p,p->syscall,entering,args);
 
1784
                        break;
 
1785
 
 
1786
                /*
 
1787
                XXX Incomplete but acceptable for now.
 
1788
                We permit the application to munmap whatever it likes.
 
1789
                This might be an anonymous map that we don't track,
 
1790
                or it could be file.  In the latter case, we would like
 
1791
                to decrement the reference count.  At the moment, we
 
1792
                can't tell the difference, nor can we reverse map the
 
1793
                application's space into our own address space.
 
1794
                Once loaded, mmaped objects just stay in until the
 
1795
                parent pfs process dies.
 
1796
                */
 
1797
 
 
1798
                case SYSCALL32_munmap:
 
1799
                        break;
 
1800
 
 
1801
                /*
 
1802
                For select, we must copy in all the data structures
 
1803
                that are pointed to, select, and then copy out.
 
1804
                Notice that on Linux, newselect has the ordinary
 
1805
                interface, while SYSCALL32_select keeps all of the arguments
 
1806
                in a single structure.
 
1807
                */
 
1808
 
 
1809
                case SYSCALL32__newselect:
 
1810
                case SYSCALL32_select:
 
1811
                        if(entering) {
 
1812
                                int maxfd = args[0];
 
1813
                                fd_set rset, wset, eset;
 
1814
                                struct pfs_kernel_timeval ktv;
 
1815
                                struct timeval tv;
 
1816
                                fd_set *prset, *pwset, *peset;
 
1817
                                struct timeval *ptv;
 
1818
                                int nlongs,nbytes;
 
1819
 
 
1820
                                nlongs = (maxfd+31)/32;
 
1821
                                nbytes = nlongs*4;
 
1822
 
 
1823
                                FD_ZERO(&rset);
 
1824
                                FD_ZERO(&wset);
 
1825
                                FD_ZERO(&eset);
 
1826
 
 
1827
                                if(args[1]) {
 
1828
                                        tracer_copy_in(p->tracer,&rset,POINTER(args[1]),nbytes);
 
1829
                                        prset = &rset;
 
1830
                                } else {
 
1831
                                        prset = 0;
 
1832
                                }
 
1833
 
 
1834
                                if(args[2]) {
 
1835
                                        tracer_copy_in(p->tracer,&wset,POINTER(args[2]),nbytes);
 
1836
                                        pwset = &wset;
 
1837
                                } else {
 
1838
                                        pwset = 0;
 
1839
                                }
 
1840
 
 
1841
                                if(args[3]) {
 
1842
                                        tracer_copy_in(p->tracer,&eset,POINTER(args[3]),nbytes);
 
1843
                                        peset = &eset;
 
1844
                                } else {
 
1845
                                        peset = 0;
 
1846
                                }
 
1847
 
 
1848
                                if(args[4]) {
 
1849
                                        tracer_copy_in(p->tracer,&ktv,POINTER(args[4]),sizeof(tv));
 
1850
                                        COPY_TIMEVAL(ktv,tv);
 
1851
                                        ptv = &tv;
 
1852
                                } else {
 
1853
                                        ptv = 0;
 
1854
                                }
 
1855
 
 
1856
                                p->syscall_result = pfs_select(maxfd,prset,pwset,peset,ptv);
 
1857
 
 
1858
                                if(p->syscall_result>=0) {
 
1859
                                        divert_to_dummy(p,p->syscall_result);
 
1860
                                        if(prset) tracer_copy_out(p->tracer,prset,POINTER(args[1]),nbytes);
 
1861
                                        if(pwset) tracer_copy_out(p->tracer,pwset,POINTER(args[2]),nbytes);
 
1862
                                        if(peset) tracer_copy_out(p->tracer,peset,POINTER(args[3]),nbytes);
 
1863
                                        if(ptv) {
 
1864
                                                COPY_TIMEVAL(tv,ktv);
 
1865
                                                tracer_copy_out(p->tracer,&ktv,POINTER(args[4]),sizeof(ktv));
 
1866
                                        }
 
1867
                                } else if(errno==EAGAIN) {
 
1868
                                        if(p->interrupted) {
 
1869
                                                p->interrupted = 0;
 
1870
                                                divert_to_dummy(p,-EINTR);
 
1871
                                        } else {
 
1872
                                                p->state = PFS_PROCESS_STATE_WAITREAD;
 
1873
                                        }
 
1874
                                } else {
 
1875
                                        divert_to_dummy(p,-errno);
 
1876
                                }
 
1877
                        }
 
1878
                        break;
 
1879
 
 
1880
                case SYSCALL32_poll:
 
1881
                        if(entering) {
 
1882
                                struct pollfd *ufds;
 
1883
                                if(args[1]>1024) {
 
1884
                                        divert_to_dummy(p,-EINVAL);
 
1885
                                } else {
 
1886
                                        int length = sizeof(*ufds)*args[1];
 
1887
                                        ufds = (struct pollfd *) malloc(length);
 
1888
                                        if(ufds) {
 
1889
                                                tracer_copy_in(p->tracer,ufds,POINTER(args[0]),length);
 
1890
                                                p->syscall_result = pfs_poll(ufds,args[1],args[2]);
 
1891
                                                if(p->syscall_result>=0) {
 
1892
                                                        divert_to_dummy(p,p->syscall_result);
 
1893
                                                        tracer_copy_out(p->tracer,ufds,POINTER(args[0]),length);
 
1894
                                                } else if(errno==EAGAIN) {
 
1895
                                                        if(p->interrupted) {
 
1896
                                                                p->interrupted = 0;
 
1897
                                                                divert_to_dummy(p,-EINTR);
 
1898
                                                        } else {
 
1899
                                                                p->state = PFS_PROCESS_STATE_WAITREAD;
 
1900
                                                        }
 
1901
                                                } else {
 
1902
                                                        divert_to_dummy(p,-errno);
 
1903
                                                }
 
1904
                                        free(ufds);
 
1905
                                        } else {
 
1906
                                                divert_to_dummy(p,-ENOMEM);
 
1907
                                        }
 
1908
                                }
 
1909
                        }
 
1910
                break;
 
1911
 
 
1912
                /*
 
1913
                Next, we have operations that do not modify any files
 
1914
                in particular, but change the state of the file table
 
1915
                within the process in question.
 
1916
                */
 
1917
 
 
1918
                case SYSCALL32_chdir:
 
1919
                        if(entering) {
 
1920
                                tracer_copy_in_string(p->tracer,path,POINTER(args[0]),sizeof(path));
 
1921
                                p->syscall_result = pfs_chdir(path);
 
1922
                                if(p->syscall_result<0) p->syscall_result = -errno;
 
1923
                                divert_to_dummy(p,p->syscall_result);
 
1924
                        }
 
1925
                        break;
 
1926
 
 
1927
                case SYSCALL32_getcwd:
 
1928
                        if(entering) {
 
1929
                                if(pfs_getcwd(path,sizeof(path))) {
 
1930
                                        p->syscall_result = strlen(path)+1;
 
1931
                                        if(p->syscall_result>args[1]) {
 
1932
                                                p->syscall_result = -ERANGE;
 
1933
                                        } else {
 
1934
                                                tracer_copy_out(p->tracer,path,POINTER(args[0]),p->syscall_result);
 
1935
                                        }
 
1936
                                } else {
 
1937
                                        p->syscall_result = -errno;
 
1938
                                }
 
1939
                                divert_to_dummy(p,p->syscall_result);
 
1940
                        }
 
1941
                        break;
 
1942
 
 
1943
                case SYSCALL32_dup:
 
1944
                        if(entering) {
 
1945
                                p->syscall_result = pfs_dup(args[0]);
 
1946
                                if(p->syscall_result<0) p->syscall_result = -errno;
 
1947
                                divert_to_dummy(p,p->syscall_result);
 
1948
                        }
 
1949
                        break;
 
1950
 
 
1951
                case SYSCALL32_dup2:
 
1952
                        if(entering) {
 
1953
                                p->syscall_result = pfs_dup2(args[0],args[1]);
 
1954
                                if(p->syscall_result<0) p->syscall_result = -errno;
 
1955
                                divert_to_dummy(p,p->syscall_result);
 
1956
                        }
 
1957
                        break;
 
1958
 
 
1959
                /*
 
1960
                Next we have all of the system calls that work on
 
1961
                a file name, rather than an open file.  In most cases,
 
1962
                we use the (fast) tracer_copy_in to fetch the file
 
1963
                name, and then invoke the pfs_  XXX We should have
 
1964
                some sort of bounds checking on the path name.
 
1965
                */
 
1966
 
 
1967
                case SYSCALL32_stat:
 
1968
                        decode_stat(p,entering,SYSCALL32_stat,args,0);
 
1969
                        break;
 
1970
                case SYSCALL32_stat64:
 
1971
                        decode_stat(p,entering,SYSCALL32_stat,args,1);
 
1972
                        break;
 
1973
                case SYSCALL32_lstat:
 
1974
                        decode_stat(p,entering,SYSCALL32_lstat,args,0);
 
1975
                        break;
 
1976
                case SYSCALL32_lstat64:
 
1977
                        decode_stat(p,entering,SYSCALL32_lstat,args,1);
 
1978
                        break;
 
1979
                case SYSCALL32_statfs:
 
1980
                        decode_statfs(p,entering,SYSCALL32_statfs,args,0);
 
1981
                        break;
 
1982
                case SYSCALL32_statfs64:
 
1983
                        decode_statfs(p,entering,SYSCALL32_statfs,args,1);
 
1984
                        break;
 
1985
 
 
1986
                case SYSCALL32_access:
 
1987
                        if(entering) {
 
1988
                                tracer_copy_in_string(p->tracer,path,POINTER(args[0]),sizeof(path));
 
1989
                                p->syscall_result = pfs_access(path,args[1]);
 
1990
                                if(p->syscall_result<0) p->syscall_result = -errno;
 
1991
                                divert_to_dummy(p,p->syscall_result);
 
1992
                        }
 
1993
                        break;
 
1994
 
 
1995
                case SYSCALL32_chmod:
 
1996
                        if(entering) {
 
1997
                                tracer_copy_in_string(p->tracer,path,POINTER(args[0]),sizeof(path));
 
1998
                                p->syscall_result = pfs_chmod(path,args[1]);
 
1999
                                if(p->syscall_result<0) p->syscall_result = -errno;
 
2000
                                divert_to_dummy(p,p->syscall_result);
 
2001
                        }
 
2002
                        break;
 
2003
 
 
2004
                case SYSCALL32_chown:
 
2005
                case SYSCALL32_chown32:
 
2006
                        if(entering) {
 
2007
                                tracer_copy_in_string(p->tracer,path,POINTER(args[0]),sizeof(path));
 
2008
                                p->syscall_result = pfs_chown(path,args[1],args[2]);
 
2009
                                if(p->syscall_result<0) p->syscall_result = -errno;
 
2010
                                divert_to_dummy(p,p->syscall_result);
 
2011
                        }
 
2012
                        break;
 
2013
 
 
2014
                case SYSCALL32_lchown:
 
2015
                case SYSCALL32_lchown32:
 
2016
                        if(entering) {
 
2017
                                tracer_copy_in_string(p->tracer,path,POINTER(args[0]),sizeof(path));
 
2018
                                p->syscall_result = pfs_lchown(path,args[1],args[2]);
 
2019
                                if(p->syscall_result<0) p->syscall_result = -errno;
 
2020
                                divert_to_dummy(p,p->syscall_result);
 
2021
                        }
 
2022
                        break;
 
2023
 
 
2024
                case SYSCALL32_truncate:
 
2025
                        if(entering) {
 
2026
                                tracer_copy_in_string(p->tracer,path,POINTER(args[0]),sizeof(path));
 
2027
                                p->syscall_result = pfs_truncate(path,args[1]);
 
2028
                                if(p->syscall_result<0) p->syscall_result = -errno;
 
2029
                                divert_to_dummy(p,p->syscall_result);
 
2030
                        }
 
2031
                        break;
 
2032
 
 
2033
                case SYSCALL32_truncate64:
 
2034
                        if(entering) {
 
2035
                                INT64_T offset = args[1]+(((INT64_T)args[2])<<32);
 
2036
                                tracer_copy_in_string(p->tracer,path,POINTER(args[0]),sizeof(path));
 
2037
                                p->syscall_result = pfs_truncate(path,offset);
 
2038
                                if(p->syscall_result<0) p->syscall_result = -errno;
 
2039
                                divert_to_dummy(p,p->syscall_result);
 
2040
                        }
 
2041
                        break;
 
2042
 
 
2043
                case SYSCALL32_unlink:
 
2044
                        if(entering) {
 
2045
                                tracer_copy_in_string(p->tracer,path,POINTER(args[0]),sizeof(path));
 
2046
                                p->syscall_result = pfs_unlink(path);
 
2047
                                if(p->syscall_result<0) p->syscall_result = -errno;
 
2048
                                divert_to_dummy(p,p->syscall_result);
 
2049
                        }
 
2050
                        break;
 
2051
 
 
2052
                case SYSCALL32_rename:
 
2053
                        if(entering) {
 
2054
                                tracer_copy_in_string(p->tracer,path,POINTER(args[0]),sizeof(path));
 
2055
                                tracer_copy_in_string(p->tracer,path2,POINTER(args[1]),sizeof(path2));
 
2056
                                p->syscall_result = pfs_rename(path,path2);
 
2057
                                if(p->syscall_result<0) p->syscall_result = -errno;
 
2058
                                divert_to_dummy(p,p->syscall_result);
 
2059
                        }
 
2060
                        break;
 
2061
 
 
2062
                case SYSCALL32_link:
 
2063
                        if(entering) {
 
2064
                                tracer_copy_in_string(p->tracer,path,POINTER(args[0]),sizeof(path));
 
2065
                                tracer_copy_in_string(p->tracer,path2,POINTER(args[1]),sizeof(path2));
 
2066
                                p->syscall_result = pfs_link(path,path2);
 
2067
                                if(p->syscall_result<0) p->syscall_result = -errno;
 
2068
                                divert_to_dummy(p,p->syscall_result);
 
2069
                        }
 
2070
                        break;
 
2071
 
 
2072
                case SYSCALL32_symlink:
 
2073
                        if(entering) {
 
2074
                                tracer_copy_in_string(p->tracer,path,POINTER(args[0]),sizeof(path));
 
2075
                                tracer_copy_in_string(p->tracer,path2,POINTER(args[1]),sizeof(path2));
 
2076
                                p->syscall_result = pfs_symlink(path,path2);
 
2077
                                if(p->syscall_result<0) p->syscall_result = -errno;
 
2078
                                divert_to_dummy(p,p->syscall_result);
 
2079
                        }
 
2080
                        break;
 
2081
 
 
2082
                case SYSCALL32_readlink:
 
2083
                        if(entering) {
 
2084
                                tracer_copy_in_string(p->tracer,path,POINTER(args[0]),sizeof(path));
 
2085
                                p->syscall_result = pfs_readlink(path,path2,sizeof(path2));
 
2086
                                if(p->syscall_result<0) {
 
2087
                                        p->syscall_result = -errno;
 
2088
                                } else {
 
2089
                                        tracer_copy_out(p->tracer,path2,POINTER(args[1]),p->syscall_result);
 
2090
                                }
 
2091
                                divert_to_dummy(p,p->syscall_result);
 
2092
                        }
 
2093
                        break;
 
2094
 
 
2095
                case SYSCALL32_mknod:
 
2096
                        if(entering) {
 
2097
                                tracer_copy_in_string(p->tracer,path,POINTER(args[0]),sizeof(path));
 
2098
                                p->syscall_result = pfs_mknod(path,args[1],args[2]);
 
2099
                                if(p->syscall_result<0) p->syscall_result = -errno;
 
2100
                                divert_to_dummy(p,p->syscall_result);
 
2101
                        }
 
2102
                        break;
 
2103
 
 
2104
                case SYSCALL32_mkdir:
 
2105
                        if(entering) {
 
2106
                                tracer_copy_in_string(p->tracer,path,POINTER(args[0]),sizeof(path));
 
2107
                                p->syscall_result = pfs_mkdir(path,args[1]);
 
2108
                                if(p->syscall_result<0) p->syscall_result = -errno;
 
2109
                                divert_to_dummy(p,p->syscall_result);
 
2110
                        }
 
2111
                        break;
 
2112
 
 
2113
                case SYSCALL32_rmdir:
 
2114
                        if(entering) {
 
2115
                                tracer_copy_in_string(p->tracer,path,POINTER(args[0]),sizeof(path));
 
2116
                                p->syscall_result = pfs_rmdir(path);
 
2117
                                if(p->syscall_result<0) p->syscall_result = -errno;
 
2118
                                divert_to_dummy(p,p->syscall_result);
 
2119
                        }
 
2120
                        break;
 
2121
 
 
2122
                /*
 
2123
                Although pfs_table supports the high-level operations
 
2124
                opendir/readdir/closedir, all we can get a hold of at
 
2125
                this level is getdents, which works on an open file
 
2126
                descriptor.  We copy dirents out one by one using fdreaddir,
 
2127
                and transform them into the type expected by the kernel.
 
2128
                If we overrun the available buffer, immediately seek
 
2129
                the fd back to where it was before.
 
2130
                */
 
2131
 
 
2132
                case SYSCALL32_getdents:
 
2133
                        if(entering) {
 
2134
                                int fd = args[0];
 
2135
                                char *uaddr = (char*) POINTER(args[1]);
 
2136
                                int length = args[2];
 
2137
                                int result = 0;
 
2138
 
 
2139
                                struct dirent *d;
 
2140
                                struct pfs_kernel_dirent buf;
 
2141
 
 
2142
                                errno = 0;
 
2143
                                while((d=pfs_fdreaddir(fd))) {
 
2144
                                        COPY_DIRENT(*d,buf);
 
2145
                                        if(DIRENT_SIZE(buf)>(unsigned)length) {
 
2146
                                                pfs_lseek(fd,d->d_off,SEEK_SET);
 
2147
                                                errno = EINVAL;
 
2148
                                                break;
 
2149
                                        }
 
2150
                                        tracer_copy_out(p->tracer,&buf,(void*)uaddr,buf.d_reclen);
 
2151
                                        uaddr  += buf.d_reclen;
 
2152
                                        length -= buf.d_reclen;
 
2153
                                        result += buf.d_reclen;
 
2154
                                }
 
2155
 
 
2156
                                if(result==0 && errno!=0) {
 
2157
                                        p->syscall_result = -errno;
 
2158
                                } else {
 
2159
                                        p->syscall_result = result;
 
2160
                                }
 
2161
                                divert_to_dummy(p,p->syscall_result);
 
2162
                        }
 
2163
                        break;
 
2164
 
 
2165
 
 
2166
                case SYSCALL32_getdents64:
 
2167
                        if(entering) {
 
2168
                                int fd = args[0];
 
2169
                                char *uaddr = (char*) POINTER(args[1]);
 
2170
                                int length = args[2];
 
2171
                                int result = 0;
 
2172
 
 
2173
                                struct dirent *d;
 
2174
                                struct pfs_kernel_dirent64 buf;
 
2175
 
 
2176
                                errno = 0;
 
2177
                                while((d=pfs_fdreaddir(fd))) {
 
2178
                                        COPY_DIRENT(*d,buf);
 
2179
                                        if(DIRENT_SIZE(buf)>(unsigned)length) {
 
2180
                                                pfs_lseek(fd,d->d_off,SEEK_SET);
 
2181
                                                errno = EINVAL;
 
2182
                                                break;
 
2183
                                        }
 
2184
                                        tracer_copy_out(p->tracer,&buf,(void*)uaddr,buf.d_reclen);
 
2185
                                        uaddr  += buf.d_reclen;
 
2186
                                        length -= buf.d_reclen;
 
2187
                                        result += buf.d_reclen;
 
2188
                                }
 
2189
 
 
2190
                                if(result==0 && errno!=0) {
 
2191
                                        p->syscall_result = -errno;
 
2192
                                } else {
 
2193
                                        p->syscall_result = result;
 
2194
                                }
 
2195
                                divert_to_dummy(p,p->syscall_result);
 
2196
                        }
 
2197
                        break;
 
2198
 
 
2199
                case SYSCALL32_utime:
 
2200
                        if(entering) {
 
2201
                                struct pfs_kernel_utimbuf kut;
 
2202
                                struct utimbuf ut;
 
2203
                                tracer_copy_in_string(p->tracer,path,POINTER(args[0]),sizeof(path));
 
2204
                                if(args[1]) {
 
2205
                                        tracer_copy_in(p->tracer,&kut,POINTER(args[1]),sizeof(kut));
 
2206
                                        COPY_UTIMBUF(kut,ut);
 
2207
                                } else {
 
2208
                                        ut.actime = ut.modtime = time(0);
 
2209
                                }
 
2210
                                p->syscall_result = pfs_utime(path,&ut);
 
2211
                                if(p->syscall_result<0) p->syscall_result = -errno;
 
2212
                                divert_to_dummy(p,p->syscall_result);
 
2213
                        }
 
2214
                        break;
 
2215
 
 
2216
                case SYSCALL32_utimes:
 
2217
                        if(entering) {
 
2218
                                struct pfs_kernel_timeval times[2];
 
2219
                                struct utimbuf ut;
 
2220
                                tracer_copy_in_string(p->tracer,path,POINTER(args[0]),sizeof(path));
 
2221
                                if(args[1]) {
 
2222
                                        tracer_copy_in(p->tracer,times,POINTER(args[1]),sizeof(times));
 
2223
                                        ut.actime = times[0].tv_sec;
 
2224
                                        ut.modtime = times[1].tv_sec;
 
2225
                                } else {
 
2226
                                        ut.actime = ut.modtime = time(0);
 
2227
                                }
 
2228
                                p->syscall_result = pfs_utime(path,&ut);
 
2229
                                if(p->syscall_result<0) p->syscall_result = -errno;
 
2230
                                divert_to_dummy(p,p->syscall_result);
 
2231
                        }
 
2232
                        break;
 
2233
 
 
2234
 
 
2235
                /*
 
2236
                Note that we call pfs_process_raise here so that the process data
 
2237
                structures are made aware of the signal propagation, possibly kicking
 
2238
                someone out of sleep.  However, we do *not* convert this call to
 
2239
                a dummy, so that the sender can deliver itself, thus getting the
 
2240
                correct data into the sa_info structure.
 
2241
                */
 
2242
 
 
2243
                case SYSCALL32_kill:
 
2244
                case SYSCALL32_tkill:
 
2245
                        if(entering) {
 
2246
                                pfs_process_raise(args[0],args[1],0);
 
2247
                        }
 
2248
                        break;
 
2249
 
 
2250
 
 
2251
                case SYSCALL32_tgkill:
 
2252
                        if(entering) {
 
2253
                                pfs_process_raise(args[0],args[2],0);
 
2254
                        }
 
2255
                        break;
 
2256
 
 
2257
                /*
 
2258
                We need to track the umask ourselves and use it in open.
 
2259
                */
 
2260
 
 
2261
                case SYSCALL32_umask:
 
2262
                        if(entering) {
 
2263
                                int old_umask = pfs_current->umask;
 
2264
                                pfs_current->umask = args[0] & 0777;
 
2265
                                divert_to_dummy(p,old_umask);
 
2266
                        }
 
2267
                        break;
 
2268
 
 
2269
                /*
 
2270
                The tracing mechanism re-parents traced children,
 
2271
                so we must fake the parent pid if the child wants
 
2272
                to send its parent a signal.
 
2273
                */
 
2274
 
 
2275
                case SYSCALL32_getppid:
 
2276
                        divert_to_dummy(p,p->ppid);
 
2277
                        break;
 
2278
 
 
2279
                /*
 
2280
                Always return the dummy uids.   
 
2281
                */
 
2282
 
 
2283
                case SYSCALL32_getuid32:
 
2284
                case SYSCALL32_geteuid32:
 
2285
                case SYSCALL32_geteuid:
 
2286
                case SYSCALL32_getuid:
 
2287
                        divert_to_dummy(p,pfs_uid);
 
2288
                        break;
 
2289
 
 
2290
                case SYSCALL32_getgid32:
 
2291
                case SYSCALL32_getegid32:
 
2292
                case SYSCALL32_getegid:
 
2293
                case SYSCALL32_getgid:
 
2294
                        divert_to_dummy(p,pfs_gid);
 
2295
                        break;
 
2296
 
 
2297
                case SYSCALL32_getresuid32:
 
2298
                case SYSCALL32_getresuid:
 
2299
                        tracer_copy_out(p->tracer,&pfs_uid,POINTER(args[0]),sizeof(pfs_uid));
 
2300
                        tracer_copy_out(p->tracer,&pfs_uid,POINTER(args[1]),sizeof(pfs_uid));
 
2301
                        tracer_copy_out(p->tracer,&pfs_uid,POINTER(args[2]),sizeof(pfs_uid));
 
2302
                        divert_to_dummy(p,0);
 
2303
                        break;
 
2304
                
 
2305
 
 
2306
                case SYSCALL32_getresgid32:
 
2307
                case SYSCALL32_getresgid:
 
2308
                        tracer_copy_out(p->tracer,&pfs_gid,POINTER(args[0]),sizeof(pfs_uid));
 
2309
                        tracer_copy_out(p->tracer,&pfs_gid,POINTER(args[1]),sizeof(pfs_uid));
 
2310
                        tracer_copy_out(p->tracer,&pfs_gid,POINTER(args[2]),sizeof(pfs_uid));
 
2311
                        divert_to_dummy(p,0);
 
2312
                        break;
 
2313
 
 
2314
                case SYSCALL32_setsid:
 
2315
                        if(entering) {
 
2316
                                pfs_current->tty[0] = 0;
 
2317
                        }
 
2318
                        break;
 
2319
 
 
2320
                /*
 
2321
                Generally speaking, the kernel implements signal handling,
 
2322
                so we just pass through operations such as sigaction and signal.
 
2323
                However, we must keep track of which signals are allowed to
 
2324
                interrupt I/O operations in progress.  Each process has an
 
2325
                array, signal_interruptible, that records this. The SA_RESTART
 
2326
                flag to sigaction can turn this on or off.  The traditional
 
2327
                BSD signal() always turns it on.
 
2328
                */
 
2329
 
 
2330
                case SYSCALL32_sigaction:
 
2331
                case SYSCALL32_rt_sigaction:
 
2332
                        if(entering) {
 
2333
                                if(args[1]) {
 
2334
                                        int sig = args[0];
 
2335
                                        struct pfs_kernel_sigaction act;
 
2336
                                        tracer_copy_in(p->tracer,&act,POINTER(args[1]),sizeof(act));
 
2337
                                        if(act.pfs_sa_flags&SA_RESTART) {
 
2338
                                                pfs_current->signal_interruptible[sig] = 0;
 
2339
                                        } else {
 
2340
                                                pfs_current->signal_interruptible[sig] = 1;
 
2341
                                        }
 
2342
                                }
 
2343
                        }
 
2344
                        break;
 
2345
 
 
2346
                case SYSCALL32_signal:
 
2347
                        if(entering) {
 
2348
                                int sig = args[0];
 
2349
                                pfs_current->signal_interruptible[sig] = 0;
 
2350
                        }
 
2351
                        break;
 
2352
 
 
2353
                case SYSCALL32_parrot_lsalloc:
 
2354
                        if(entering) {
 
2355
                                char alloc_path[PFS_PATH_MAX];
 
2356
                                pfs_ssize_t avail, inuse;
 
2357
                                tracer_copy_in_string(p->tracer,path,POINTER(args[0]),sizeof(path));
 
2358
                                p->syscall_result = pfs_lsalloc(path,alloc_path,&avail,&inuse);
 
2359
                                if(p->syscall_result>=0) {
 
2360
                                        tracer_copy_out(p->tracer,alloc_path,POINTER(args[1]),strlen(alloc_path));
 
2361
                                        tracer_copy_out(p->tracer,&avail,POINTER(args[2]),sizeof(avail));
 
2362
                                        tracer_copy_out(p->tracer,&inuse,POINTER(args[3]),sizeof(inuse));
 
2363
                                } else {
 
2364
                                        p->syscall_result = -errno;
 
2365
                                }
 
2366
                                divert_to_dummy(p,p->syscall_result);
 
2367
                        }
 
2368
                        break;
 
2369
 
 
2370
                case SYSCALL32_parrot_mkalloc:
 
2371
                        if(entering) {
 
2372
                                pfs_ssize_t size;
 
2373
                                tracer_copy_in_string(p->tracer,path,POINTER(args[0]),sizeof(path));
 
2374
                                tracer_copy_in(p->tracer,&size,POINTER(args[1]),sizeof(size));
 
2375
                                p->syscall_result = pfs_mkalloc(path,size,args[2]);
 
2376
                                if(p->syscall_result<0) p->syscall_result = -errno;
 
2377
                                divert_to_dummy(p,p->syscall_result);
 
2378
                        }
 
2379
                        break;
 
2380
 
 
2381
                case SYSCALL32_parrot_setacl:
 
2382
                        if(entering) {
 
2383
                                char path[PFS_PATH_MAX];
 
2384
                                char subject[PFS_PATH_MAX];
 
2385
                                char rights[PFS_PATH_MAX];
 
2386
                                tracer_copy_in_string(p->tracer,path,POINTER(args[0]),sizeof(path));
 
2387
                                tracer_copy_in_string(p->tracer,subject,POINTER(args[1]),sizeof(subject));
 
2388
                                tracer_copy_in_string(p->tracer,rights,POINTER(args[2]),sizeof(rights));
 
2389
                                p->syscall_result = pfs_setacl(path,subject,rights);
 
2390
                                if(p->syscall_result<0) p->syscall_result = -errno;
 
2391
                                divert_to_dummy(p,p->syscall_result);
 
2392
                        }
 
2393
                        break;
 
2394
 
 
2395
                case SYSCALL32_parrot_getacl:
 
2396
                case SYSCALL32_parrot_whoami:
 
2397
                        if(entering) {
 
2398
                                char path[PFS_PATH_MAX];
 
2399
                                char buffer[4096];
 
2400
                                unsigned size=args[2];
 
2401
 
 
2402
                                tracer_copy_in_string(p->tracer,path,POINTER(args[0]),sizeof(path));
 
2403
                                if(size>sizeof(buffer)) size = sizeof(buffer);
 
2404
 
 
2405
                                if(p->syscall==SYSCALL32_parrot_getacl) {
 
2406
                                        p->syscall_result = pfs_getacl(path,buffer,sizeof(buffer));
 
2407
                                } else {
 
2408
                                        p->syscall_result = pfs_whoami(path,buffer,sizeof(buffer));
 
2409
                                }
 
2410
 
 
2411
                                if(p->syscall_result>=0) {
 
2412
                                        tracer_copy_out(p->tracer,buffer,POINTER(args[1]),p->syscall_result);
 
2413
                                } else {
 
2414
                                        p->syscall_result = -errno;
 
2415
                                }
 
2416
                                divert_to_dummy(p,p->syscall_result);
 
2417
                        }
 
2418
                        break;
 
2419
 
 
2420
                case SYSCALL32_parrot_locate:
 
2421
                        if(entering) {
 
2422
                                char path[PFS_PATH_MAX];
 
2423
                                char buffer[4096];
 
2424
                                unsigned size=args[2];
 
2425
                                
 
2426
                                if (args[0]) {
 
2427
                                        tracer_copy_in_string(p->tracer,path,POINTER(args[0]),sizeof(path));
 
2428
                                        if(size>sizeof(buffer)) size = sizeof(buffer);
 
2429
                                } else {
 
2430
                                        path[0] = 0;
 
2431
                                }
 
2432
 
 
2433
                                p->syscall_result = pfs_locate(path,buffer,sizeof(buffer));
 
2434
 
 
2435
                                if(p->syscall_result>=0) {
 
2436
                                        tracer_copy_out(p->tracer,buffer,POINTER(args[1]),p->syscall_result);
 
2437
                                } else {
 
2438
                                        p->syscall_result = -errno;
 
2439
                                }
 
2440
                                divert_to_dummy(p,p->syscall_result);
 
2441
                        }
 
2442
                        break;
 
2443
 
 
2444
                case SYSCALL32_parrot_timeout:
 
2445
                        if(entering) {
 
2446
                                char buffer[1024];
 
2447
                                if (args[0]) {
 
2448
                                        tracer_copy_in_string(p->tracer,buffer,POINTER(args[0]),sizeof(buffer));
 
2449
                                        p->syscall_result = pfs_timeout(buffer);
 
2450
                                } else {
 
2451
                                        p->syscall_result = pfs_timeout(NULL);
 
2452
                                }
 
2453
 
 
2454
                                if(p->syscall_result<0) {
 
2455
                                        p->syscall_result = -errno;
 
2456
                                }
 
2457
                                divert_to_dummy(p,p->syscall_result);
 
2458
                        }
 
2459
                        break;
 
2460
 
 
2461
                case SYSCALL32_parrot_copyfile:
 
2462
                        if(entering) {
 
2463
                                char source[PFS_PATH_MAX];
 
2464
                                char target[PFS_PATH_MAX];
 
2465
 
 
2466
                                tracer_copy_in_string(p->tracer,source,POINTER(args[0]),sizeof(source));
 
2467
                                tracer_copy_in_string(p->tracer,target,POINTER(args[1]),sizeof(target));
 
2468
 
 
2469
                                p->syscall_result = pfs_copyfile(source,target);
 
2470
 
 
2471
                                if(p->syscall_result<0) p->syscall_result = -errno;
 
2472
                                divert_to_dummy(p,p->syscall_result);
 
2473
                        }
 
2474
                        break;
 
2475
 
 
2476
                case SYSCALL32_parrot_md5:
 
2477
                        if(entering) {
 
2478
                                char digest[16];
 
2479
                                tracer_copy_in_string(p->tracer,path,POINTER(args[0]),sizeof(path));
 
2480
                                p->syscall_result = pfs_md5(path,(unsigned char*)digest);
 
2481
                                if(p->syscall_result>=0) {
 
2482
                                        tracer_copy_out(p->tracer,digest,POINTER(args[1]),sizeof(digest));
 
2483
                                }
 
2484
                                if(p->syscall_result<0) p->syscall_result = -errno;
 
2485
                                divert_to_dummy(p,p->syscall_result);
 
2486
                        }
 
2487
                        break;
 
2488
                                
 
2489
                /*
 
2490
                Changing the userid is not allow, but for completeness,
 
2491
                you can always change to your own uid.
 
2492
                */
 
2493
                case SYSCALL32_setgid:
 
2494
                case SYSCALL32_setregid:
 
2495
                case SYSCALL32_setuid:
 
2496
                case SYSCALL32_setresuid:
 
2497
                case SYSCALL32_setresgid:
 
2498
                case SYSCALL32_setreuid:
 
2499
                case SYSCALL32_setgid32:
 
2500
                case SYSCALL32_setregid32:
 
2501
                case SYSCALL32_setuid32:
 
2502
                case SYSCALL32_setresuid32:
 
2503
                case SYSCALL32_setresgid32:
 
2504
                case SYSCALL32_setreuid32:
 
2505
                case SYSCALL32_setfsuid32:
 
2506
                case SYSCALL32_setfsgid32:
 
2507
                        divert_to_dummy(p,0);
 
2508
                        break;
 
2509
 
 
2510
                /* Whenever the break address is udpated validly, save it. */
 
2511
                /* This is used as one way of computing a scratch space. */
 
2512
 
 
2513
                case SYSCALL32_brk:
 
2514
                        if(entering) {
 
2515
                        } else {
 
2516
                                if(p->syscall_result==0) {
 
2517
                                        if(p->syscall_args[0]!=0) {
 
2518
                                                p->break_address = p->syscall_args[0];
 
2519
                                        }
 
2520
                                }
 
2521
                        }
 
2522
                        break;
 
2523
 
 
2524
                /*
 
2525
                These things are not currently permitted.
 
2526
                */
 
2527
                case SYSCALL32_chroot:
 
2528
                case SYSCALL32_mount:
 
2529
                case SYSCALL32_stime:
 
2530
                case SYSCALL32_sysfs:
 
2531
                case SYSCALL32_umount2:
 
2532
                case SYSCALL32_umount:
 
2533
                case SYSCALL32_uselib:
 
2534
                case SYSCALL32_lookup_dcookie:
 
2535
                case SYSCALL32_sys_epoll_create:
 
2536
                case SYSCALL32_sys_epoll_ctl:
 
2537
                case SYSCALL32_sys_epoll_wait:
 
2538
                case SYSCALL32_remap_file_pages:
 
2539
 
 
2540
                        divert_to_dummy(p,-EPERM);
 
2541
                        break;
 
2542
                /*
 
2543
                These system calls are historical artifacts or
 
2544
                otherwise not necessary to support.
 
2545
                */
 
2546
                case SYSCALL32_acct:
 
2547
                case SYSCALL32_break:
 
2548
                case SYSCALL32_ftime:
 
2549
                case SYSCALL32_gtty:
 
2550
                case SYSCALL32_lock:
 
2551
                case SYSCALL32_mpx:
 
2552
                case SYSCALL32_profil:
 
2553
                case SYSCALL32_stty:
 
2554
                case SYSCALL32_ulimit:
 
2555
                case SYSCALL32_fadvise64:
 
2556
                        divert_to_dummy(p,-ENOSYS);
 
2557
                        break;
 
2558
 
 
2559
                /*
 
2560
                A wide variety of calls have no relation to file
 
2561
                access, so we simply send them along to the
 
2562
                underlying OS.
 
2563
                */
 
2564
 
 
2565
                case SYSCALL32_uname:
 
2566
                case SYSCALL32_olduname:
 
2567
                case SYSCALL32__sysctl:
 
2568
                case SYSCALL32_adjtimex:
 
2569
                case SYSCALL32_afs_syscall:
 
2570
                case SYSCALL32_alarm:
 
2571
                case SYSCALL32_bdflush:
 
2572
                case SYSCALL32_capget:
 
2573
                case SYSCALL32_capset:
 
2574
                case SYSCALL32_clock_settime:
 
2575
                case SYSCALL32_clock_gettime:
 
2576
                case SYSCALL32_clock_getres:
 
2577
                case SYSCALL32_create_module:           
 
2578
                case SYSCALL32_delete_module:           
 
2579
                case SYSCALL32_get_kernel_syms:
 
2580
                case SYSCALL32_getgroups32:
 
2581
                case SYSCALL32_getgroups:
 
2582
                case SYSCALL32_getitimer:
 
2583
                case SYSCALL32_getpgid:
 
2584
                case SYSCALL32_getpgrp:
 
2585
                case SYSCALL32_getpid:
 
2586
                case SYSCALL32_getpriority:
 
2587
                case SYSCALL32_getrlimit:
 
2588
                case SYSCALL32_getrusage:
 
2589
                case SYSCALL32_getsid:
 
2590
                case SYSCALL32_gettid:
 
2591
                case SYSCALL32_gettimeofday:
 
2592
                case SYSCALL32_idle:
 
2593
                case SYSCALL32_init_module:             
 
2594
                case SYSCALL32_ioperm:
 
2595
                case SYSCALL32_iopl:
 
2596
                case SYSCALL32_ipc:
 
2597
                case SYSCALL32_madvise:
 
2598
                case SYSCALL32_mincore:
 
2599
                case SYSCALL32_mlock:
 
2600
                case SYSCALL32_mlockall:
 
2601
                case SYSCALL32_modify_ldt:
 
2602
                case SYSCALL32_mprotect:
 
2603
                case SYSCALL32_mremap:
 
2604
                case SYSCALL32_msync:
 
2605
                case SYSCALL32_munlock:
 
2606
                case SYSCALL32_munlockall:
 
2607
                case SYSCALL32_nanosleep:
 
2608
                case SYSCALL32_nice:
 
2609
                case SYSCALL32_pause:
 
2610
                case SYSCALL32_prctl:
 
2611
                case SYSCALL32_query_module:
 
2612
                case SYSCALL32_quotactl:
 
2613
                case SYSCALL32_reboot:
 
2614
                case SYSCALL32_rt_sigpending:
 
2615
                case SYSCALL32_rt_sigprocmask:
 
2616
                case SYSCALL32_rt_sigqueueinfo:
 
2617
                case SYSCALL32_rt_sigreturn:
 
2618
                case SYSCALL32_rt_sigsuspend:
 
2619
                case SYSCALL32_rt_sigtimedwait:
 
2620
                case SYSCALL32_sched_get_priority_max:
 
2621
                case SYSCALL32_sched_get_priority_min:
 
2622
                case SYSCALL32_sched_getparam:
 
2623
                case SYSCALL32_sched_getscheduler:
 
2624
                case SYSCALL32_sched_rr_get_interval:
 
2625
                case SYSCALL32_sched_setparam:
 
2626
                case SYSCALL32_sched_setscheduler:
 
2627
                case SYSCALL32_sched_yield:
 
2628
                case SYSCALL32_setdomainname:
 
2629
                case SYSCALL32_setgroups32:
 
2630
                case SYSCALL32_setgroups:
 
2631
                case SYSCALL32_sethostname:
 
2632
                case SYSCALL32_setitimer:
 
2633
                case SYSCALL32_setpgid:
 
2634
                case SYSCALL32_setpriority:
 
2635
                case SYSCALL32_setrlimit:
 
2636
                case SYSCALL32_settimeofday:
 
2637
                case SYSCALL32_set_tid_address:
 
2638
                case SYSCALL32_sgetmask:
 
2639
                case SYSCALL32_sigaltstack:
 
2640
                case SYSCALL32_sigpending:
 
2641
                case SYSCALL32_sigprocmask:
 
2642
                case SYSCALL32_sigreturn:
 
2643
                case SYSCALL32_sigsuspend:
 
2644
                case SYSCALL32_ssetmask:
 
2645
                case SYSCALL32_swapoff:
 
2646
                case SYSCALL32_swapon:
 
2647
                case SYSCALL32_sync:
 
2648
                case SYSCALL32_sysinfo:
 
2649
                case SYSCALL32_syslog:
 
2650
                case SYSCALL32_time:
 
2651
                case SYSCALL32_times:
 
2652
                case SYSCALL32_timer_create:
 
2653
                case SYSCALL32_timer_settime:
 
2654
                case SYSCALL32_timer_gettime:
 
2655
                case SYSCALL32_timer_getoverrun:
 
2656
                case SYSCALL32_timer_delete:
 
2657
                case SYSCALL32_ugetrlimit:
 
2658
                case SYSCALL32_ustat:
 
2659
                case SYSCALL32_vhangup:
 
2660
                case SYSCALL32_vm86:
 
2661
                case SYSCALL32_vm86old:
 
2662
                case SYSCALL32_sched_setaffinity:
 
2663
                case SYSCALL32_sched_getaffinity:
 
2664
                case SYSCALL32_set_thread_area:
 
2665
                case SYSCALL32_get_thread_area:
 
2666
                case SYSCALL32_alloc_hugepages:
 
2667
                case SYSCALL32_free_hugepages:
 
2668
                case SYSCALL32_futex:
 
2669
                case SYSCALL32_set_robust_list:
 
2670
                case SYSCALL32_get_robust_list:
 
2671
                        break;
 
2672
 
 
2673
                /*
 
2674
                These system calls get and set extended
 
2675
                attributes on file systems.  Not only are
 
2676
                they non-standard, they are only implemented
 
2677
                by the jfs filesystem on Linux.  Libraries
 
2678
                expect these to return EOPNOTSUPP.
 
2679
                */
 
2680
                
 
2681
                case SYSCALL32_fgetxattr:
 
2682
                case SYSCALL32_flistxattr:
 
2683
                case SYSCALL32_fremovexattr:
 
2684
                case SYSCALL32_fsetxattr:
 
2685
                case SYSCALL32_getxattr:
 
2686
                case SYSCALL32_lgetxattr:
 
2687
                case SYSCALL32_listxattr:
 
2688
                case SYSCALL32_llistxattr:
 
2689
                case SYSCALL32_lremovexattr:
 
2690
                case SYSCALL32_lsetxattr:
 
2691
                case SYSCALL32_removexattr:
 
2692
                case SYSCALL32_setxattr:
 
2693
                        divert_to_dummy(p,-EOPNOTSUPP);
 
2694
                        break;
 
2695
 
 
2696
                /*
 
2697
                These system calls could concievably be supported,
 
2698
                but we haven't had the need or the time to attack
 
2699
                them.
 
2700
                */
 
2701
 
 
2702
                case SYSCALL32_getpmsg:
 
2703
                case SYSCALL32_io_cancel:
 
2704
                case SYSCALL32_io_destroy:
 
2705
                case SYSCALL32_io_getevents:
 
2706
                case SYSCALL32_io_setup:
 
2707
                case SYSCALL32_io_submit:
 
2708
                case SYSCALL32_ptrace:
 
2709
                case SYSCALL32_putpmsg:
 
2710
                case SYSCALL32_readahead:
 
2711
                case SYSCALL32_security:
 
2712
                case SYSCALL32_sendfile64:
 
2713
                case SYSCALL32_sendfile:
 
2714
                        /* fallthrough */
 
2715
 
 
2716
                /*
 
2717
                If anything else escaped our attention, we must know
 
2718
                about it in an obvious way.
 
2719
                */
 
2720
 
 
2721
                default:
 
2722
                        if(entering) {
 
2723
                                debug(D_NOTICE,"warning: system call %d (%s) not supported for program %s",(int)p->syscall,tracer_syscall_name(p->tracer,p->syscall),p->name);
 
2724
                                divert_to_dummy(p,-ENOSYS);
 
2725
                        }
 
2726
                        break;
 
2727
        }
 
2728
 
 
2729
        if(!entering && p->state==PFS_PROCESS_STATE_KERNEL) {
 
2730
 
 
2731
                p->state = PFS_PROCESS_STATE_USER;
 
2732
 
 
2733
                if(p->syscall_args_changed) {
 
2734
                        tracer_args_set(p->tracer,p->syscall,p->syscall_args,TRACER_ARGS_MAX);
 
2735
                        p->syscall_args_changed = 0;
 
2736
                }
 
2737
 
 
2738
                if(p->syscall_dummy) {
 
2739
                        tracer_result_set(p->tracer,p->syscall_result);
 
2740
                        p->syscall_dummy = 0;
 
2741
                        debug(D_SYSCALL,"= %d %s",(int)p->syscall_result,p->syscall_result<0 ? strerror(-p->syscall_result) : "" );
 
2742
                } else {
 
2743
                        debug(D_SYSCALL,"= ");
 
2744
                }
 
2745
        }
 
2746
 
 
2747
}
 
2748
 
 
2749
/*
 
2750
Note that we clear the interrupted flag whenever
 
2751
we start a new system call or leave an old one.
 
2752
We don't want one system call to be interrupted
 
2753
by a signal from a previous system call.
 
2754
*/
 
2755
 
 
2756
void pfs_dispatch32( struct pfs_process *p, INT64_T signum )
 
2757
{
 
2758
        struct pfs_process *oldcurrent = pfs_current;
 
2759
        pfs_current = p;
 
2760
 
 
2761
        switch(p->state) {
 
2762
                case PFS_PROCESS_STATE_KERNEL:
 
2763
                case PFS_PROCESS_STATE_WAITWRITE:
 
2764
                        decode_syscall(p,0);
 
2765
                        break;
 
2766
                case PFS_PROCESS_STATE_USER:
 
2767
                        p->interrupted = 0;
 
2768
                case PFS_PROCESS_STATE_WAITREAD:
 
2769
                        decode_syscall(p,1);
 
2770
                        break;
 
2771
                case PFS_PROCESS_STATE_WAITPID:
 
2772
                case PFS_PROCESS_STATE_DONE:
 
2773
                        p->interrupted = 0;
 
2774
                        break;
 
2775
                default:
 
2776
                        debug(D_PROCESS,"process %d in unexpected state %d",(int)p->pid,(int)p->state);
 
2777
                        break;
 
2778
        }
 
2779
 
 
2780
        switch(p->state) {
 
2781
                case PFS_PROCESS_STATE_KERNEL:
 
2782
                case PFS_PROCESS_STATE_USER:
 
2783
                        tracer_continue(p->tracer,signum);
 
2784
                        break;
 
2785
                case PFS_PROCESS_STATE_WAITPID:
 
2786
                case PFS_PROCESS_STATE_WAITREAD:
 
2787
                case PFS_PROCESS_STATE_WAITWRITE:
 
2788
                case PFS_PROCESS_STATE_DONE:
 
2789
                        break;
 
2790
                default:
 
2791
                        debug(D_PROCESS,"process %d in unexpected state %d",(int)p->pid,(int)p->state);
 
2792
                        break;
 
2793
        }
 
2794
 
 
2795
        pfs_current = oldcurrent;
 
2796
}
 
2797
 
 
2798
void pfs_dispatch( struct pfs_process *p, INT64_T signum )
 
2799
{
 
2800
        if(p->state==PFS_PROCESS_STATE_DONE) return;
 
2801
 
 
2802
        if(tracer_is_64bit(p->tracer)) {
 
2803
                pfs_dispatch64(p,signum);
 
2804
        } else {
 
2805
                pfs_dispatch32(p,signum);
 
2806
        }
 
2807
}
 
2808