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 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);
... ...