summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Gruenbacher <agruen@linbit.com>2012-09-17 15:25:25 +0200
committerAndreas Gruenbacher <agruen@linbit.com>2012-09-17 15:48:06 +0200
commit20c9d7d5abc41d5a2c6cfed9fe69654ae9a3a4f6 (patch)
treefd19325e0d8165438c67b2cdd3ffb56768e7ffa2
parent2b2fb1f36c4d0662dc2340c57a8a9b084ea861c8 (diff)
downloadpatch-20c9d7d5abc41d5a2c6cfed9fe69654ae9a3a4f6.tar.gz
Allow to use potentially dangerous filenames from the root directory
* src/pch.c (cwd_is_root): New function to check if we are in the root directory of a filename. (name_is_valid): Allow to use potentially dangerous filenames when the current working directory is the root directory: from there, those names are not any more dangerous than other names. * tests/bad-filenames: New test case.
-rw-r--r--src/pch.c27
-rw-r--r--tests/bad-filenames11
2 files changed, 38 insertions, 0 deletions
diff --git a/src/pch.c b/src/pch.c
index 551099e..8d5f1c4 100644
--- a/src/pch.c
+++ b/src/pch.c
@@ -389,6 +389,29 @@ skip_hex_digits (char const *str)
return s == str ? NULL : s;
}
+/* Check if we are in the root of a particular filesystem namespace ("/" on
+ UNIX or a particular drive's root on DOS-like systems). */
+static bool
+cwd_is_root (char const *name)
+{
+ unsigned int prefix_len = FILE_SYSTEM_PREFIX_LEN (name);
+ char root[prefix_len + 2];
+ struct stat st;
+ dev_t root_dev;
+ ino_t root_ino;
+
+ memcpy (root, name, prefix_len);
+ root[prefix_len] = '/';
+ root[prefix_len + 1] = 0;
+ if (lstat (root, &st))
+ return false;
+ root_dev = st.st_dev;
+ root_ino = st.st_ino;
+ if (lstat (".", &st))
+ return false;
+ return root_dev == st.st_dev && root_ino == st.st_ino;
+}
+
static bool
name_is_valid (char const *name)
{
@@ -420,6 +443,10 @@ name_is_valid (char const *name)
n++;
}
+ /* Allow any filename if we are in the filesystem root. */
+ if (! is_valid && cwd_is_root (name))
+ is_valid = true;
+
if (! is_valid)
{
say ("Ignoring potentially dangerous file name %s\n", quotearg (name));
diff --git a/tests/bad-filenames b/tests/bad-filenames
index 5b4f205..121cfda 100644
--- a/tests/bad-filenames
+++ b/tests/bad-filenames
@@ -42,6 +42,17 @@ No file to patch. Skipping patch.
status: 1
EOF
+for dir in "$TMPDIR" "$TMP" "$TEMP" "/tmp"; do
+ if test -n "$dir"; then
+ filename=$dir/patch-$$-$RANDOM
+ break
+ fi
+done
+
+check 'emit_patch $filename | (cd / && patch -f -p0 --dry-run) || echo status: $?' <<EOF
+patching file $filename
+EOF
+
check 'emit_patch a/../z | patch -f -p0 --dry-run || echo status: $?' <<EOF
Ignoring potentially dangerous file name a/../z
can't find file to patch at input line 3