1 |
#!/usr/bin/perl |
2 |
|
3 |
# (c)2003 Marc Alexander Lehmann <nbd@plan9.de> |
4 |
# |
5 |
# This file is released under the General Public License, version 2 or later. |
6 |
|
7 |
require v5.8; |
8 |
|
9 |
use strict 'subs'; |
10 |
|
11 |
use Socket; |
12 |
use IO::Socket::INET; |
13 |
|
14 |
$VERSION = 0.1; |
15 |
|
16 |
############################################################################# |
17 |
|
18 |
$DEV = "/dev/nd0"; |
19 |
|
20 |
umask 077; |
21 |
|
22 |
for (0..7) { |
23 |
-e "/dev/nd$_" || qx<sh -x -c "mknod /dev/nd$_ b 43 $_">; |
24 |
} |
25 |
|
26 |
print <<EOF; |
27 |
|
28 |
WARNING: This program contains a locally exploitable race condition. |
29 |
EOF |
30 |
|
31 |
sub NBD_SET_SOCK (){ 0x0000ab00 } |
32 |
sub NBD_SET_BLKSIZE (){ 0x0000ab01 } |
33 |
sub NBD_SET_SIZE (){ 0x0000ab02 } |
34 |
sub NBD_DO_IT (){ 0x0000ab03 } |
35 |
sub NBD_CLEAR_SOCK (){ 0x0000ab04 } |
36 |
sub NBD_CLEAR_QUE (){ 0x0000ab05 } |
37 |
sub NBD_PRINT_DEBUG (){ 0x0000ab06 } |
38 |
sub NBD_SET_SIZE_BLOCKS (){ 0x0000ab07 } |
39 |
sub NBD_DISCONNECT (){ 0x0000ab08 } |
40 |
|
41 |
open ND, "+<", $DEV or die "$DEV: $!"; |
42 |
|
43 |
ioctl ND, NBD_CLEAR_QUE, my $x or die "NBD_CLEAR_QUE: $!"; |
44 |
ioctl ND, NBD_DISCONNECT, my $x; |
45 |
ioctl ND, NBD_CLEAR_SOCK, my $x; |
46 |
|
47 |
############################################################################# |
48 |
|
49 |
$BIN = shift or die "usage: $0 iso9660.bin"; |
50 |
|
51 |
open BIN, "<", $BIN or die "$BIN: $!"; |
52 |
|
53 |
# create a socketpair... ugh |
54 |
my $srv = new IO::Socket::INET LocalHost => "127.0.0.1", Listen => 1 |
55 |
or die "unable to create listen socket: $!"; |
56 |
my $cli = new IO::Socket::INET PeerHost => $srv->sockhost, PeerPort => $srv->sockport |
57 |
or die "unable to connect to listen socket: $!"; |
58 |
$srv = $srv->accept |
59 |
or die "accept: $!"; |
60 |
|
61 |
# TODO: should exchange secure token, but I don't care for races now |
62 |
|
63 |
ioctl ND, NBD_SET_SOCK, 0 + fileno $cli or die "NBD_SET_SOCK: $!"; |
64 |
|
65 |
sub REQ_MAGIC () { 0x25609513 } |
66 |
sub REQ($) { unpack "N N a8 NN N", $_[0] } |
67 |
sub REQ_SIZE (){ 4+4+4 + 8 + 8 } |
68 |
sub REP_MAGIC () { 0x67446698 } |
69 |
sub REP($$$;$) { pack "N N a8 a*", @_ } |
70 |
|
71 |
if (!($srv_pid = fork)) { |
72 |
ioctl ND, NBD_DO_IT, my $x |
73 |
or die "unable do _do_ _it_: $!"; |
74 |
exit; |
75 |
} |
76 |
|
77 |
$SIG{INT} = |
78 |
$SIG{TERM} = |
79 |
$SIG{QUIT} = |
80 |
$SIG{HUP} = sub { exit }; |
81 |
|
82 |
sub END { |
83 |
if ($srv_pid) { |
84 |
print "killing server...\n"; |
85 |
kill 9, $srv_pid; |
86 |
} |
87 |
print "bye.\n"; |
88 |
} |
89 |
|
90 |
#if (fork == 0) { |
91 |
# system "isoinfo", "-l", "-i", $DEV; |
92 |
# _exit(1); |
93 |
#} |
94 |
|
95 |
print <<EOF; |
96 |
|
97 |
Everything seems to be set up now, try sth. like: |
98 |
|
99 |
mount -tiso9660 $DEV /mnt |
100 |
|
101 |
Press ^C to exit... |
102 |
EOF |
103 |
|
104 |
while (REQ_SIZE == sysread $srv, my $req, REQ_SIZE) { |
105 |
my ($magic, $type, $handle, undef, $from, $len) = REQ $req; |
106 |
|
107 |
$magic == REQ_MAGIC |
108 |
or die "protocol error (magic number mismatch)"; |
109 |
|
110 |
my ($from_l, $from_h) = ($from & 2047, $from >> 11); |
111 |
|
112 |
if ($type == 0) { |
113 |
printf "READ %08x \@%08x (block $from_h+$from_l)\n", $len, $from; |
114 |
|
115 |
syswrite $srv, REP REP_MAGIC, 0, $handle; |
116 |
|
117 |
while ($len) { |
118 |
sysseek BIN, ($from_h * 2352) + $from_l + 0x18, 0 |
119 |
or die; |
120 |
|
121 |
$from_l = 2048 - $from_l; |
122 |
$from_l < $len or $from_l = $len; |
123 |
|
124 |
sysread BIN, my $buf, $from_l; |
125 |
|
126 |
$from_l == length $buf or $buf = "\x0" x $from_l; |
127 |
|
128 |
syswrite $srv, $buf; |
129 |
|
130 |
$len -= $from_l; |
131 |
|
132 |
$from_l = 0; |
133 |
$from_h++; |
134 |
} |
135 |
} elsif ($type == 1) { |
136 |
die "write not supported\n"; |
137 |
} elsif ($type == 2) { |
138 |
print "disconnect requested, exiting...\n"; |
139 |
last; |
140 |
} else { |
141 |
die "unsupported operation ($type)\n"; |
142 |
} |
143 |
} |
144 |
|