Ticket #4770: kdl.cpp

File kdl.cpp, 4.4 KB (added by rogueeve, 15 years ago)

the source alone for browsing online

Line 
1
2/*
3 kdl.cpp
4 (c)2009 Caitlin Shaw, GPL (as if anyone actually wants this)
5
6
7 * this program causes a "Page fault in kernel space" under Haiku r33411,
8 crashing the system via KDL. it contacts Google in order to get a remote peer
9 which will send data to it, thus it requires internet access to function.
10
11 * the crash occurs because the recv() function apparently both runs from within
12 kernel space and does no checking on the validity of it's buffer, and so passing
13 an invalid pointer as the buffer to recv() will bring down the whole system.
14
15 * have not checked but it seems it might possibly be a problem for priveledge
16 escalation? if the memory is being clobbered with ring 0 authority.
17
18 * this is a distilled version of a bug discovered in one of my real programs.
19
20*/
21
22#include <stdio.h>
23#include <netdb.h>
24#include <memory.h>
25#include <sys/types.h>
26#include <arpa/inet.h>
27#include <netinet/tcp.h>
28#include <unistd.h>
29#include <fcntl.h>
30#include <errno.h>
31
32unsigned int net_dnslookup(const char *host);
33uint connect_tcp(uint ip, ushort port, int timeout_ms);
34bool net_setnonblock(uint sock, bool enable);
35int sendstr(short sock, const char *str);
36char *decimalip(unsigned int ip);
37
38
39int main(int argc, char **argv)
40{
41uint connect_ip;
42uint sock;
43
44 printf("welcome to kdl_computer\n");
45 printf("DNS lookup in progress...\n");
46
47 connect_ip = net_dnslookup("www.google.com");
48
49 printf("connecting to %s:80...\n", decimalip(connect_ip), 80);
50 sock = connect_tcp(connect_ip, 80, 5000);
51 if (!sock)
52 {
53 fprintf(stderr, "failed to connect to host");
54 return 1;
55 }
56
57 printf("connected, sending request...\n");
58
59 sendstr(sock, "GET / HTTP/1.1\r\n");
60 sendstr(sock, "\r\n");
61
62 printf("\n************************************\n");
63 printf("* Prepare to die... *\n");
64 printf("************************************\n");
65
66 char *buffer = (char *)42;
67 int size = recv(sock, buffer, sizeof(buffer), 0);
68
69
70 printf("\nif you're seeing this, your system has unfortunately failed to KDL.\n");
71 printf("sorry buddy, looks like you're out of luck.\n");
72 printf("received size = %d\n", size);
73
74 return 0;
75}
76
77
78/*
79void c------------------------------() {}
80*/
81
82// convert a hostname to an IP address via DNS.
83unsigned int net_dnslookup(const char *host)
84{
85struct hostent *hosten;
86unsigned long ip;
87
88 printf("Resolving '%s' via DNS...\n", host);
89
90 // attempt to resolve the hostname via DNS
91 hosten = gethostbyname(host);
92 if (hosten == NULL)
93 {
94 fprintf(stderr, "dnslookup: failed to resolve host: '%s'.", host);
95 return 0;
96 }
97 else
98 {
99 memcpy((char*)&ip, hosten->h_addr_list[0], 4);
100 return ntohl(ip);
101 }
102}
103
104// attempts to connect to ip:port, and returns the new socket number if successful,
105// else returns 0.
106uint connect_tcp(uint ip, ushort port, int timeout_ms)
107{
108int conn_socket, result;
109bool connected;
110bool use_timeout;
111struct sockaddr_in sain;
112
113 if (!(conn_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)))
114 {
115 fprintf(stderr, "connect_tcp: Failed to create socket.\n");
116 return 1;
117 }
118
119 net_setnonblock(conn_socket, true);
120
121 sain.sin_addr.s_addr = htonl(ip);
122 sain.sin_port = htons(port);
123 sain.sin_family = AF_INET;
124
125 #define TICK_BASE 10
126 connected = false;
127 use_timeout = timeout_ms != 0;
128
129 for(;;)
130 {
131 result = connect(conn_socket, (struct sockaddr *)&sain, sizeof(struct sockaddr_in));
132
133 if (errno == EISCONN || result != -1)
134 {
135 connected = true;
136 break;
137 }
138
139 if (errno == EINTR) break;
140
141 if (use_timeout)
142 {
143 if (timeout_ms >= 0)
144 {
145 usleep(TICK_BASE * 1000);
146 timeout_ms -= TICK_BASE;
147 }
148 else break;
149 }
150 }
151
152 net_setnonblock(conn_socket, false);
153
154 if (connected)
155 {
156 return conn_socket;
157 }
158
159 close(conn_socket);
160 return 0;
161}
162
163
164// set a socket to blocking or non-blocking mode.
165bool net_setnonblock(uint sock, bool enable)
166{
167long fvalue;
168
169 if ((fvalue = fcntl(sock, F_GETFL, NULL)) < 0)
170 {
171 fprintf(stderr, "net_setnonblock: Error fcntl(..., F_GETFL) (%s)", strerror(errno));
172 return 1;
173 }
174
175 if (enable)
176 fvalue |= O_NONBLOCK;
177 else
178 fvalue &= ~O_NONBLOCK;
179
180 if (fcntl(sock, F_SETFL, fvalue) < 0)
181 {
182 fprintf(stderr, "net_setnonblock: Error fcntl(..., F_SETFL) (%s)", strerror(errno));
183 return 1;
184 }
185
186 return 0;
187}
188
189// transmit a string out a socket.
190int sendstr(short sock, const char *str)
191{
192 return send(sock, str, strlen(str), 0);
193}
194
195// convert a ipv4 address into display representation.
196char *decimalip(unsigned int ip)
197{
198static char buffer[800];
199 sprintf(buffer, "%d.%d.%d.%d",
200 (ip>>24)&255, (ip>>16)&255, (ip>>8)&255, ip&255);
201 return buffer;
202}
203
204