Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
enum frobork_kode {
FK_RETURN,
FK_EXECVE,
FK_DUP2,
FK_CLOSE,
FK_FCHDIR,
FK_SETUID,
FK_SETGID,
FK_SIGNAL,
FK_SETSID,
FK_SETPGID,
FK_TCSETPGRP
};
/*
* frobork.c
*/
#define XX (*kode++)
#define T(type) ((type)XX)
#define X T(int)
#define TRY2(x,y) if((x)==(y)) { goto on_error; } ; break;
#define TRY(x) TRY2(x,-1)
#define OBJLEN(x) (x),sizeof(x)
#define GETX {x=X;}
#if 0 /* support for any of the types we use being larger than an int */
#define MAXUINTP1 (1ULL+(unsigned long long)((unsigned int)-1))
#define SIZUI (sizeof(unsigned int))
#define SIZULL (sizeof(unsigned int))
unsigned long long read_and_increment_pointer (unsigned int**p, unsigned int size) {
unsigned long long r;
unsigned int *q = *p;
unsigned int i = 0;
unsigned long long factor = 1;
if (size <= SIZUI) {
r = *q;
q++;
} else if (size > SIZULL) {
write(2,OBJLEN("frobork: bad int size\n"));
exit(43);
} else {
r = 0;
while (i<size) {
r += *q*f;
f *= MAXUINTP1;
q++;
i+=SIZUI;
}
}
*p = q;
return r;
}
#define T(type) ((type)read_and_increment_pointer((unsigned int**)&kode,sizeof(type)))
#endif
int frobork (int* kode)
{
pid_t pid, p1,p2;
int x;
sighandler_t sh;
char *a,**b,**c;
pid = fork();
if (pid) {
return pid;
}
while (1) {
switch (X) {
case FK_RETURN:
return(0);
case FK_EXECVE:
a=T(char *);b=T(char **);c=T(char **);
TRY(execve(a,b,c));
break;
case FK_DUP2:
GETX; TRY(dup2(x,X));
break;
case FK_CLOSE:
TRY(close(X));
break;
case FK_FCHDIR:
TRY(fchdir(X));
break;
case FK_SETUID:
TRY(setuid(T(uid_it)));
break;
case FK_SETGID:
TRY(setgid(T(gid_it)));
break;
case FK_SIGNAL:
GETX;
switch(X) {
case 0: sh = SIG_...;
case 1: sh = SIG_...;
case 2: sh = SIG_...;
}
TRY2(signal(x,y,SIG_ERR);
break;
case FK_SETSID:
TRY(setsid());
break;
case FK_SETPGID:
p1=T(pid_t);p2=T(pid_t);
TRY(setpgid(p1,p2));
break;
case FK_TCSETPGRP:
GETX;TRY(tcsetpgrp(x,T(pid_t)));
break;
default:
write(2,OBJLEN("frobork: bad code\n"));
exit(42);
}
}
return 0;
on_error:
perror("frobork");
exit(44);
}
#ifdef TEST_FROBORK
int main (int argc, char** argv) {
int kode[] = {
FK_DUP2, 0, 4,
FK_CLOSE, 4,
FK_SETSID,
FK_RETURN
};
argc++;argv++;
printf("pid=%d frobork returned %d\n",getpid(),frobork(kode));
return 0;
}
#endif