summaryrefslogtreecommitdiff
path: root/src/lib/eio
diff options
context:
space:
mode:
authorWonki Kim <wonki_.kim@samsung.com>2019-02-21 05:25:09 +0000
committerCedric BAIL <cedric.bail@free.fr>2019-02-21 11:12:13 -0800
commite7e62c54cd42bff73469db3340c0b6d10a003813 (patch)
tree757b1df909f2ed8ac7e2b506e9769288cdc06c11 /src/lib/eio
parentbb303d6ec593b9f39385d2e2ed5af17e6a1429de (diff)
eio: fix a potentional BOF problem
if length of path arguments are longer than PATH_MAX, there could be a BOF problem potentionally. this patch fixes it. Reviewed-by: Cedric BAIL <cedric.bail@free.fr> Differential Revision: https://phab.enlightenment.org/D7919
Diffstat (limited to 'src/lib/eio')
-rw-r--r--src/lib/eio/eio_dir.c100
1 files changed, 77 insertions, 23 deletions
diff --git a/src/lib/eio/eio_dir.c b/src/lib/eio/eio_dir.c
index 84c7769..af2125a 100644
--- a/src/lib/eio/eio_dir.c
+++ b/src/lib/eio/eio_dir.c
@@ -193,15 +193,15 @@ _eio_dir_init(Ecore_Thread *thread,
193} 193}
194 194
195static void 195static void
196_eio_dir_target(Eio_Dir_Copy *order, char *target, const char *dir, int length_source, int length_dest) 196_eio_dir_target(Eio_Dir_Copy *order, Eina_Strbuf *target, const char *dir, int length_source, int length_dest)
197{ 197{
198 int length; 198 int length;
199 199
200 length = eina_stringshare_strlen(dir); 200 length = eina_stringshare_strlen(dir);
201 201
202 memcpy(target, order->progress.dest, length_dest); 202 eina_strbuf_append_length(target, order->progress.dest, length_dest);
203 target[length_dest] = '/'; 203 eina_strbuf_append(target, "/");
204 memcpy(target + length_dest + 1, dir + length_source, length - length_source + 1); 204 eina_strbuf_append_length(target, dir + length_source, length - length_source + 1);
205} 205}
206 206
207static Eina_Bool 207static Eina_Bool
@@ -211,18 +211,20 @@ _eio_dir_mkdir(Ecore_Thread *thread, Eio_Dir_Copy *order,
211{ 211{
212 const char *dir; 212 const char *dir;
213 Eina_List *l; 213 Eina_List *l;
214 char target[PATH_MAX]; 214 Eina_Strbuf *target = eina_strbuf_new();
215 215
216 /* create all directory */ 216 /* create all directory */
217 EINA_LIST_FOREACH(order->dirs, l, dir) 217 EINA_LIST_FOREACH(order->dirs, l, dir)
218 { 218 {
219 eina_strbuf_reset(target);
219 /* build target dir path */ 220 /* build target dir path */
220 _eio_dir_target(order, target, dir, length_source, length_dest); 221 _eio_dir_target(order, target, dir, length_source, length_dest);
221 222
222 /* create the directory (we will apply the mode later) */ 223 /* create the directory (we will apply the mode later) */
223 if (mkdir(target, 0777) != 0) 224 if (mkdir(eina_strbuf_string_get(target), 0777) != 0)
224 { 225 {
225 eio_file_thread_error(&order->progress.common, thread); 226 eio_file_thread_error(&order->progress.common, thread);
227 eina_strbuf_free(target);
226 return EINA_FALSE; 228 return EINA_FALSE;
227 } 229 }
228 230
@@ -232,9 +234,13 @@ _eio_dir_mkdir(Ecore_Thread *thread, Eio_Dir_Copy *order,
232 234
233 /* check for cancel request */ 235 /* check for cancel request */
234 if (ecore_thread_check(thread)) 236 if (ecore_thread_check(thread))
235 return EINA_FALSE; 237 {
238 eina_strbuf_free(target);
239 return EINA_FALSE;
240 }
236 } 241 }
237 242
243 eina_strbuf_free(target);
238 return EINA_TRUE; 244 return EINA_TRUE;
239} 245}
240 246
@@ -247,32 +253,54 @@ _eio_dir_link(Ecore_Thread *thread, Eio_Dir_Copy *order,
247{ 253{
248 const char *ln; 254 const char *ln;
249 Eina_List *l; 255 Eina_List *l;
250 char oldpath[PATH_MAX]; 256 Eina_Strbuf *oldpath, *buffer;
251 char target[PATH_MAX]; 257 char *target = NULL, *newpath = NULL;
252 char buffer[PATH_MAX]; 258 ssize_t bsz = -1;
253 char *newpath; 259 struct stat st;
260
261 oldpath = eina_strbuf_new();
262 buffer = eina_strbuf_new();
254 263
255 /* Build once the base of the link target */ 264 /* Build once the base of the link target */
256 memcpy(buffer, order->progress.dest, length_dest); 265 eina_strbuf_append_length(buffer, order->progress.dest, length_dest);
257 buffer[length_dest] = '/'; 266 eina_strbuf_append(buffer, "/");
258 267
259 /* recreate all links */ 268 /* recreate all links */
260 EINA_LIST_FOREACH(order->links, l, ln) 269 EINA_LIST_FOREACH(order->links, l, ln)
261 { 270 {
262 ssize_t length; 271 ssize_t length;
263 272
273 eina_strbuf_reset(oldpath);
274
264 /* build oldpath link */ 275 /* build oldpath link */
265 _eio_dir_target(order, oldpath, ln, length_source, length_dest); 276 _eio_dir_target(order, oldpath, ln, length_source, length_dest);
266 277
278 if (lstat(ln, &st) == -1)
279 {
280 goto on_error;
281 }
282 if (st.st_size == 0)
283 {
284 bsz = PATH_MAX;
285 free(target);
286 target = malloc(bsz);
287 }
288 else if(bsz < st.st_size + 1)
289 {
290 bsz = st.st_size +1;
291 free(target);
292 target = malloc(bsz);
293 }
294
267 /* read link target */ 295 /* read link target */
268 length = readlink(ln, target, PATH_MAX); 296 length = readlink(ln, target, bsz);
269 if (length < 0) 297 if (length < 0)
270 goto on_error; 298 goto on_error;
271 299
272 if (strncmp(target, order->progress.source, length_source) == 0) 300 if (strncmp(target, order->progress.source, length_source) == 0)
273 { 301 {
274 /* The link is inside the zone to copy, so rename it */ 302 /* The link is inside the zone to copy, so rename it */
275 memcpy(buffer + length_dest + 1, target + length_source, length - length_source + 1); 303 eina_strbuf_insert_length(buffer, target + length_source,length - length_source + 1, length_dest + 1);
276 newpath = target; 304 newpath = target;
277 } 305 }
278 else 306 else
@@ -282,7 +310,7 @@ _eio_dir_link(Ecore_Thread *thread, Eio_Dir_Copy *order,
282 } 310 }
283 311
284 /* create the link */ 312 /* create the link */
285 if (symlink(newpath, oldpath) != 0) 313 if (symlink(newpath, eina_strbuf_string_get(oldpath)) != 0)
286 goto on_error; 314 goto on_error;
287 315
288 /* inform main thread */ 316 /* inform main thread */
@@ -291,13 +319,21 @@ _eio_dir_link(Ecore_Thread *thread, Eio_Dir_Copy *order,
291 319
292 /* check for cancel request */ 320 /* check for cancel request */
293 if (ecore_thread_check(thread)) 321 if (ecore_thread_check(thread))
294 return EINA_FALSE; 322 goto on_thread_error;
295 } 323 }
296 324
325 eina_strbuf_free(oldpath);
326 eina_strbuf_free(buffer);
327 if(target) free(target);
328
297 return EINA_TRUE; 329 return EINA_TRUE;
298 330
299 on_error: 331 on_error:
300 eio_file_thread_error(&order->progress.common, thread); 332 eio_file_thread_error(&order->progress.common, thread);
333 on_thread_error:
334 eina_strbuf_free(oldpath);
335 eina_strbuf_free(buffer);
336 if(target) free(target);
301 return EINA_FALSE; 337 return EINA_FALSE;
302} 338}
303#endif 339#endif
@@ -309,11 +345,15 @@ _eio_dir_chmod(Ecore_Thread *thread, Eio_Dir_Copy *order,
309 Eina_Bool rmdir_source) 345 Eina_Bool rmdir_source)
310{ 346{
311 const char *dir = NULL; 347 const char *dir = NULL;
312 char target[PATH_MAX]; 348 Eina_Strbuf *target;
313 struct stat buffer; 349 struct stat buffer;
314 350
351 target = eina_strbuf_new();
352
315 while (order->dirs) 353 while (order->dirs)
316 { 354 {
355 eina_strbuf_reset(target);
356
317 /* destroy in reverse order so that we don't prevent change of lower dir */ 357 /* destroy in reverse order so that we don't prevent change of lower dir */
318 dir = eina_list_data_get(eina_list_last(order->dirs)); 358 dir = eina_list_data_get(eina_list_last(order->dirs));
319 order->dirs = eina_list_remove_list(order->dirs, eina_list_last(order->dirs)); 359 order->dirs = eina_list_remove_list(order->dirs, eina_list_last(order->dirs));
@@ -327,7 +367,7 @@ _eio_dir_chmod(Ecore_Thread *thread, Eio_Dir_Copy *order,
327 goto on_error; 367 goto on_error;
328 368
329 /* set the orginal mode to the newly created dir */ 369 /* set the orginal mode to the newly created dir */
330 if (chmod(target, buffer.st_mode) != 0) 370 if (chmod(eina_strbuf_string_get(target), buffer.st_mode) != 0)
331 goto on_error; 371 goto on_error;
332 372
333 /* if required destroy original directory */ 373 /* if required destroy original directory */
@@ -349,12 +389,14 @@ _eio_dir_chmod(Ecore_Thread *thread, Eio_Dir_Copy *order,
349 dir = NULL; 389 dir = NULL;
350 } 390 }
351 391
392 eina_strbuf_free(target);
352 return EINA_TRUE; 393 return EINA_TRUE;
353 394
354 on_error: 395 on_error:
355 eio_file_thread_error(&order->progress.common, thread); 396 eio_file_thread_error(&order->progress.common, thread);
356 on_cancel: 397 on_cancel:
357 if (dir) eina_stringshare_del(dir); 398 if (dir) eina_stringshare_del(dir);
399 eina_strbuf_free(target);
358 return EINA_FALSE; 400 return EINA_FALSE;
359} 401}
360 402
@@ -367,7 +409,7 @@ _eio_dir_copy_heavy(void *data, Ecore_Thread *thread)
367 const char *ln; 409 const char *ln;
368 410
369 Eio_File_Progress file_copy; 411 Eio_File_Progress file_copy;
370 char target[PATH_MAX]; 412 Eina_Strbuf *target;
371 413
372 int length_source = 0; 414 int length_source = 0;
373 int length_dest = 0; 415 int length_dest = 0;
@@ -378,6 +420,8 @@ _eio_dir_copy_heavy(void *data, Ecore_Thread *thread)
378 if (!_eio_dir_recursiv_ls(thread, copy, copy->progress.source)) 420 if (!_eio_dir_recursiv_ls(thread, copy, copy->progress.source))
379 return; 421 return;
380 422
423 target = eina_strbuf_new();
424
381 /* init all structure needed to copy the file */ 425 /* init all structure needed to copy the file */
382 if (!_eio_dir_init(thread, &step, &count, &length_source, &length_dest, copy, &file_copy)) 426 if (!_eio_dir_init(thread, &step, &count, &length_source, &length_dest, copy, &file_copy))
383 goto on_error; 427 goto on_error;
@@ -392,11 +436,13 @@ _eio_dir_copy_heavy(void *data, Ecore_Thread *thread)
392 /* copy all files */ 436 /* copy all files */
393 EINA_LIST_FREE(copy->files, file) 437 EINA_LIST_FREE(copy->files, file)
394 { 438 {
439 eina_strbuf_reset(target);
440
395 /* build target file path */ 441 /* build target file path */
396 _eio_dir_target(copy, target, file, length_source, length_dest); 442 _eio_dir_target(copy, target, file, length_source, length_dest);
397 443
398 file_copy.source = file; 444 file_copy.source = file;
399 file_copy.dest = eina_stringshare_add(target); 445 file_copy.dest = eina_stringshare_add(eina_strbuf_string_get(target));
400 446
401 /* copy the file */ 447 /* copy the file */
402 if (!eio_file_copy_do(thread, &file_copy)) 448 if (!eio_file_copy_do(thread, &file_copy))
@@ -444,6 +490,8 @@ _eio_dir_copy_heavy(void *data, Ecore_Thread *thread)
444 if (!ecore_thread_check(thread)) 490 if (!ecore_thread_check(thread))
445 eio_progress_send(thread, &copy->progress, count, count); 491 eio_progress_send(thread, &copy->progress, count, count);
446 492
493 eina_strbuf_free(target);
494
447 return; 495 return;
448} 496}
449 497
@@ -492,7 +540,7 @@ _eio_dir_move_heavy(void *data, Ecore_Thread *thread)
492 const char *dir = NULL; 540 const char *dir = NULL;
493 541
494 Eio_File_Progress file_move; 542 Eio_File_Progress file_move;
495 char target[PATH_MAX]; 543 Eina_Strbuf *target;
496 544
497 int length_source; 545 int length_source;
498 int length_dest; 546 int length_dest;
@@ -511,6 +559,8 @@ _eio_dir_move_heavy(void *data, Ecore_Thread *thread)
511 if (!_eio_dir_recursiv_ls(thread, move, move->progress.source)) 559 if (!_eio_dir_recursiv_ls(thread, move, move->progress.source))
512 return; 560 return;
513 561
562 target = eina_strbuf_new();
563
514 /* init all structure needed to move the file */ 564 /* init all structure needed to move the file */
515 if (!_eio_dir_init(thread, &step, &count, &length_source, &length_dest, move, &file_move)) 565 if (!_eio_dir_init(thread, &step, &count, &length_source, &length_dest, move, &file_move))
516 goto on_error; 566 goto on_error;
@@ -525,11 +575,13 @@ _eio_dir_move_heavy(void *data, Ecore_Thread *thread)
525 /* move file around */ 575 /* move file around */
526 EINA_LIST_FREE(move->files, file) 576 EINA_LIST_FREE(move->files, file)
527 { 577 {
578 eina_strbuf_reset(target);
579
528 /* build target file path */ 580 /* build target file path */
529 _eio_dir_target(move, target, file, length_source, length_dest); 581 _eio_dir_target(move, target, file, length_source, length_dest);
530 582
531 file_move.source = file; 583 file_move.source = file;
532 file_move.dest = eina_stringshare_add(target); 584 file_move.dest = eina_stringshare_add(eina_strbuf_string_get(target));
533 585
534 /* first try to rename */ 586 /* first try to rename */
535 if (rename(file_move.source, file_move.dest) < 0) 587 if (rename(file_move.source, file_move.dest) < 0)
@@ -594,6 +646,8 @@ _eio_dir_move_heavy(void *data, Ecore_Thread *thread)
594 if (!ecore_thread_check(thread)) 646 if (!ecore_thread_check(thread))
595 eio_progress_send(thread, &move->progress, count, count); 647 eio_progress_send(thread, &move->progress, count, count);
596 648
649 eina_strbuf_free(target);
650
597 return; 651 return;
598} 652}
599 653