unsafe_symlink_target.c 1.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748
  1. /* vi: set sw=4 ts=4: */
  2. /*
  3. * Licensed under GPLv2 or later, see file LICENSE in this source tree.
  4. */
  5. #include "libbb.h"
  6. #include "bb_archive.h"
  7. int FAST_FUNC unsafe_symlink_target(const char *target)
  8. {
  9. const char *dot;
  10. if (target[0] == '/') {
  11. const char *var;
  12. unsafe:
  13. var = getenv("EXTRACT_UNSAFE_SYMLINKS");
  14. if (var) {
  15. if (LONE_CHAR(var, '1'))
  16. return 0; /* pretend it's safe */
  17. return 1; /* "UNSAFE!" */
  18. }
  19. bb_error_msg("skipping unsafe symlink to '%s' in archive,"
  20. " set %s=1 to extract",
  21. target,
  22. "EXTRACT_UNSAFE_SYMLINKS"
  23. );
  24. /* Prevent further messages */
  25. setenv("EXTRACT_UNSAFE_SYMLINKS", "0", 0);
  26. return 1; /* "UNSAFE!" */
  27. }
  28. dot = target;
  29. for (;;) {
  30. dot = strchr(dot, '.');
  31. if (!dot)
  32. return 0; /* safe target */
  33. /* Is it a path component starting with ".."? */
  34. if ((dot[1] == '.')
  35. && (dot == target || dot[-1] == '/')
  36. /* Is it exactly ".."? */
  37. && (dot[2] == '/' || dot[2] == '\0')
  38. ) {
  39. goto unsafe;
  40. }
  41. /* NB: it can even be trailing ".", should only add 1 */
  42. dot += 1;
  43. }
  44. }