Commit 9367964ae21d2a41517c76c87dd26c79abcfe937
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 | 27 | |
28 | 28 | struct tftp_session { |
29 | 29 | int in_use; |
30 | - char filename[TFTP_FILENAME_MAX]; | |
30 | + char *filename; | |
31 | 31 | |
32 | 32 | struct in_addr client_ip; |
33 | 33 | u_int16_t client_port; |
... | ... | @@ -47,6 +47,7 @@ static void tftp_session_update(struct tftp_session *spt) |
47 | 47 | |
48 | 48 | static void tftp_session_terminate(struct tftp_session *spt) |
49 | 49 | { |
50 | + qemu_free(spt->filename); | |
50 | 51 | spt->in_use = 0; |
51 | 52 | } |
52 | 53 | |
... | ... | @@ -62,8 +63,10 @@ static int tftp_session_allocate(struct tftp_t *tp) |
62 | 63 | goto found; |
63 | 64 | |
64 | 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 | 68 | goto found; |
69 | + } | |
67 | 70 | } |
68 | 71 | |
69 | 72 | return -1; |
... | ... | @@ -103,15 +106,8 @@ static int tftp_read_data(struct tftp_session *spt, u_int16_t block_nr, |
103 | 106 | { |
104 | 107 | int fd; |
105 | 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 | 112 | if (fd < 0) { |
117 | 113 | return -1; |
... | ... | @@ -274,6 +270,7 @@ static void tftp_handle_rrq(struct tftp_t *tp, int pktlen) |
274 | 270 | { |
275 | 271 | struct tftp_session *spt; |
276 | 272 | int s, k; |
273 | + size_t prefix_len; | |
277 | 274 | char *req_fname; |
278 | 275 | |
279 | 276 | s = tftp_session_allocate(tp); |
... | ... | @@ -294,8 +291,13 @@ static void tftp_handle_rrq(struct tftp_t *tp, int pktlen) |
294 | 291 | k = 0; |
295 | 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 | 299 | /* get name */ |
298 | - req_fname = spt->filename; | |
300 | + req_fname = spt->filename + prefix_len; | |
299 | 301 | |
300 | 302 | while (1) { |
301 | 303 | if (k >= TFTP_FILENAME_MAX || k >= pktlen) { |
... | ... | @@ -322,10 +324,8 @@ static void tftp_handle_rrq(struct tftp_t *tp, int pktlen) |
322 | 324 | k += 6; /* skipping octet */ |
323 | 325 | |
324 | 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 | 329 | tftp_send_error(spt, 2, "Access violation", tp); |
330 | 330 | return; |
331 | 331 | } |
... | ... | @@ -360,13 +360,7 @@ static void tftp_handle_rrq(struct tftp_t *tp, int pktlen) |
360 | 360 | struct stat stat_p; |
361 | 361 | |
362 | 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 | 364 | tsize = stat_p.st_size; |
371 | 365 | else { |
372 | 366 | tftp_send_error(spt, 1, "File not found", tp); | ... | ... |