diff options
author | Andreas Gruenbacher <agruen@linbit.com> | 2012-09-17 15:25:25 +0200 |
---|---|---|
committer | Andreas Gruenbacher <agruen@linbit.com> | 2012-09-17 15:48:06 +0200 |
commit | 20c9d7d5abc41d5a2c6cfed9fe69654ae9a3a4f6 (patch) | |
tree | fd19325e0d8165438c67b2cdd3ffb56768e7ffa2 | |
parent | 2b2fb1f36c4d0662dc2340c57a8a9b084ea861c8 (diff) | |
download | patch-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.c | 27 | ||||
-rw-r--r-- | tests/bad-filenames | 11 |
2 files changed, 38 insertions, 0 deletions
@@ -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 |