| 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 |
|