Commit 9367964ae21d2a41517c76c87dd26c79abcfe937

Authored by Jan Kiszka
Committed by Anthony Liguori
1 parent 20c24bf2

slirp: tftp: Rework filename handling

This changes the filename handling from a static buffer in tftp_session
for the client-provided name + prefix to a dynamically allocated buffer
that keeps the combined path in one place.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Showing 1 changed file with 16 additions and 22 deletions
slirp/tftp.c
@@ -27,7 +27,7 @@ @@ -27,7 +27,7 @@
27 27
28 struct tftp_session { 28 struct tftp_session {
29 int in_use; 29 int in_use;
30 - char filename[TFTP_FILENAME_MAX]; 30 + char *filename;
31 31
32 struct in_addr client_ip; 32 struct in_addr client_ip;
33 u_int16_t client_port; 33 u_int16_t client_port;
@@ -47,6 +47,7 @@ static void tftp_session_update(struct tftp_session *spt) @@ -47,6 +47,7 @@ static void tftp_session_update(struct tftp_session *spt)
47 47
48 static void tftp_session_terminate(struct tftp_session *spt) 48 static void tftp_session_terminate(struct tftp_session *spt)
49 { 49 {
  50 + qemu_free(spt->filename);
50 spt->in_use = 0; 51 spt->in_use = 0;
51 } 52 }
52 53
@@ -62,8 +63,10 @@ static int tftp_session_allocate(struct tftp_t *tp) @@ -62,8 +63,10 @@ static int tftp_session_allocate(struct tftp_t *tp)
62 goto found; 63 goto found;
63 64
64 /* sessions time out after 5 inactive seconds */ 65 /* sessions time out after 5 inactive seconds */
65 - if ((int)(curtime - spt->timestamp) > 5000) 66 + if ((int)(curtime - spt->timestamp) > 5000) {
  67 + qemu_free(spt->filename);
66 goto found; 68 goto found;
  69 + }
67 } 70 }
68 71
69 return -1; 72 return -1;
@@ -103,15 +106,8 @@ static int tftp_read_data(struct tftp_session *spt, u_int16_t block_nr, @@ -103,15 +106,8 @@ static int tftp_read_data(struct tftp_session *spt, u_int16_t block_nr,
103 { 106 {
104 int fd; 107 int fd;
105 int bytes_read = 0; 108 int bytes_read = 0;
106 - char buffer[1024];  
107 - int n;  
108 -  
109 - n = snprintf(buffer, sizeof(buffer), "%s/%s",  
110 - tftp_prefix, spt->filename);  
111 - if (n >= sizeof(buffer))  
112 - return -1;  
113 109
114 - fd = open(buffer, O_RDONLY | O_BINARY); 110 + fd = open(spt->filename, O_RDONLY | O_BINARY);
115 111
116 if (fd < 0) { 112 if (fd < 0) {
117 return -1; 113 return -1;
@@ -274,6 +270,7 @@ static void tftp_handle_rrq(struct tftp_t *tp, int pktlen) @@ -274,6 +270,7 @@ static void tftp_handle_rrq(struct tftp_t *tp, int pktlen)
274 { 270 {
275 struct tftp_session *spt; 271 struct tftp_session *spt;
276 int s, k; 272 int s, k;
  273 + size_t prefix_len;
277 char *req_fname; 274 char *req_fname;
278 275
279 s = tftp_session_allocate(tp); 276 s = tftp_session_allocate(tp);
@@ -294,8 +291,13 @@ static void tftp_handle_rrq(struct tftp_t *tp, int pktlen) @@ -294,8 +291,13 @@ static void tftp_handle_rrq(struct tftp_t *tp, int pktlen)
294 k = 0; 291 k = 0;
295 pktlen -= ((uint8_t *)&tp->x.tp_buf[0] - (uint8_t *)tp); 292 pktlen -= ((uint8_t *)&tp->x.tp_buf[0] - (uint8_t *)tp);
296 293
  294 + /* prepend tftp_prefix */
  295 + prefix_len = strlen(tftp_prefix);
  296 + spt->filename = qemu_malloc(prefix_len + TFTP_FILENAME_MAX + 1);
  297 + memcpy(spt->filename, tftp_prefix, prefix_len);
  298 +
297 /* get name */ 299 /* get name */
298 - req_fname = spt->filename; 300 + req_fname = spt->filename + prefix_len;
299 301
300 while (1) { 302 while (1) {
301 if (k >= TFTP_FILENAME_MAX || k >= pktlen) { 303 if (k >= TFTP_FILENAME_MAX || k >= pktlen) {
@@ -322,10 +324,8 @@ static void tftp_handle_rrq(struct tftp_t *tp, int pktlen) @@ -322,10 +324,8 @@ static void tftp_handle_rrq(struct tftp_t *tp, int pktlen)
322 k += 6; /* skipping octet */ 324 k += 6; /* skipping octet */
323 325
324 /* do sanity checks on the filename */ 326 /* do sanity checks on the filename */
325 -  
326 - if ((spt->filename[0] != '/')  
327 - || (spt->filename[strlen((char *)spt->filename) - 1] == '/')  
328 - || strstr((char *)spt->filename, "/../")) { 327 + if (req_fname[0] != '/' || req_fname[strlen(req_fname) - 1] == '/' ||
  328 + strstr(req_fname, "/../")) {
329 tftp_send_error(spt, 2, "Access violation", tp); 329 tftp_send_error(spt, 2, "Access violation", tp);
330 return; 330 return;
331 } 331 }
@@ -360,13 +360,7 @@ static void tftp_handle_rrq(struct tftp_t *tp, int pktlen) @@ -360,13 +360,7 @@ static void tftp_handle_rrq(struct tftp_t *tp, int pktlen)
360 struct stat stat_p; 360 struct stat stat_p;
361 361
362 if (tsize == 0) { 362 if (tsize == 0) {
363 - char buffer[1024];  
364 - int len;  
365 -  
366 - len = snprintf(buffer, sizeof(buffer), "%s/%s",  
367 - tftp_prefix, spt->filename);  
368 -  
369 - if (stat(buffer, &stat_p) == 0) 363 + if (stat(spt->filename, &stat_p) == 0)
370 tsize = stat_p.st_size; 364 tsize = stat_p.st_size;
371 else { 365 else {
372 tftp_send_error(spt, 1, "File not found", tp); 366 tftp_send_error(spt, 1, "File not found", tp);