patch-src_copyin_c 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. $OpenBSD: patch-src_copyin_c,v 1.4 2015/09/17 20:16:49 naddy Exp $
  2. CVE-2015-1197: cpio directory traversal
  3. --- src/copyin.c.orig Sat Sep 12 12:57:30 2015
  4. +++ src/copyin.c Wed Sep 16 23:21:15 2015
  5. @@ -695,6 +695,51 @@ copyin_link (struct cpio_file_stat *file_hdr, int in_f
  6. free (link_name);
  7. }
  8. +
  9. +static int
  10. +path_contains_symlink(char *path)
  11. +{
  12. + struct stat st;
  13. + char *slash;
  14. + char *nextslash;
  15. +
  16. + /* we got NULL pointer or empty string */
  17. + if (!path || !*path) {
  18. + return false;
  19. + }
  20. +
  21. + slash = path;
  22. +
  23. + while ((nextslash = strchr(slash + 1, '/')) != NULL) {
  24. + slash = nextslash;
  25. + *slash = '\0';
  26. +
  27. + if (lstat(path, &st) != 0) {
  28. + if (errno == ELOOP) {
  29. + /* ELOOP - too many symlinks */
  30. + *slash = '/';
  31. + return true;
  32. + } else if (errno == ENOMEM) {
  33. + /* No memory for lstat - terminate */
  34. + xalloc_die();
  35. + } else {
  36. + /* cannot lstat path - give up */
  37. + *slash = '/';
  38. + return false;
  39. + }
  40. + }
  41. +
  42. + if (S_ISLNK(st.st_mode)) {
  43. + *slash = '/';
  44. + return true;
  45. + }
  46. +
  47. + *slash = '/';
  48. + }
  49. +
  50. + return false;
  51. +}
  52. +
  53. static void
  54. copyin_file (struct cpio_file_stat *file_hdr, int in_file_des)
  55. {
  56. @@ -1467,6 +1512,23 @@ process_copy_in ()
  57. else
  58. {
  59. /* Copy the input file into the directory structure. */
  60. +
  61. + /* Can we write files over symlinks? */
  62. + if (!extract_over_symlinks)
  63. + {
  64. + if (path_contains_symlink(file_hdr.c_name))
  65. + {
  66. + /* skip the file */
  67. + /*
  68. + fprintf(stderr, "Can't write over symlinks. Skipping %s\n", file_hdr.c_name);
  69. + tape_toss_input (in_file_des, file_hdr.c_filesize);
  70. + tape_skip_padding (in_file_des, file_hdr.c_filesize);
  71. + continue;
  72. + */
  73. + /* terminate */
  74. + error (PAXEXIT_FAILURE, 0, _("Can't write over symlinks: %s\n"), file_hdr.c_name);
  75. + }
  76. + }
  77. /* Do we need to rename the file? */
  78. if (rename_flag || rename_batch_file)