[pacman-dev] [PATCH] be_package: validate package file paths
Andrew Gregory
andrew.gregory.8 at gmail.com
Mon Nov 2 18:04:40 UTC 2015
Overly long paths cannot be extracted and paths with
newlines cannot be represented in our database format.
Signed-off-by: Andrew Gregory <andrew.gregory.8 at gmail.com>
---
lib/libalpm/be_package.c | 15 ++++++++++++---
test/pacman/tests/TESTS | 3 +++
test/pacman/tests/filename-basename-too-long.py | 15 +++++++++++++++
test/pacman/tests/filename-path-too-long.py | 20 ++++++++++++++++++++
test/pacman/tests/filename-with-newline.py | 11 +++++++++++
5 files changed, 61 insertions(+), 3 deletions(-)
create mode 100644 test/pacman/tests/filename-basename-too-long.py
create mode 100644 test/pacman/tests/filename-path-too-long.py
create mode 100644 test/pacman/tests/filename-with-newline.py
diff --git a/lib/libalpm/be_package.c b/lib/libalpm/be_package.c
index 53399a3..52db319 100644
--- a/lib/libalpm/be_package.c
+++ b/lib/libalpm/be_package.c
@@ -18,6 +18,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
@@ -390,7 +391,17 @@ static int add_entry_to_files_list(alpm_filelist_t *filelist,
const size_t files_count = filelist->count;
alpm_file_t *current_file;
mode_t type;
- size_t pathlen;
+ size_t pathlen = strlen(path);
+
+ /* +2 to leave space for prepending minimal possible root and appending
+ * trailing slash if a directory */
+ if(pathlen + 2 >= PATH_MAX || strlen(mbasename(path)) >= NAME_MAX) {
+ return -1;
+ }
+ /* our database format cannot represent paths with newlines */
+ if(memchr(path, '\n', pathlen)) {
+ return -1;
+ }
if(!_alpm_greedy_grow((void **)&filelist->files,
files_size, (files_count + 1) * sizeof(alpm_file_t))) {
@@ -399,8 +410,6 @@ static int add_entry_to_files_list(alpm_filelist_t *filelist,
type = archive_entry_filetype(entry);
- pathlen = strlen(path);
-
current_file = filelist->files + files_count;
/* mtree paths don't contain a tailing slash, those we get from
diff --git a/test/pacman/tests/TESTS b/test/pacman/tests/TESTS
index 8ad1b9c..210134f 100644
--- a/test/pacman/tests/TESTS
+++ b/test/pacman/tests/TESTS
@@ -50,6 +50,9 @@ TESTS += test/pacman/tests/fileconflict025.py
TESTS += test/pacman/tests/fileconflict030.py
TESTS += test/pacman/tests/fileconflict031.py
TESTS += test/pacman/tests/fileconflict032.py
+TESTS += test/pacman/tests/filename-basename-too-long.py
+TESTS += test/pacman/tests/filename-path-too-long.py
+TESTS += test/pacman/tests/filename-with-newline.py
TESTS += test/pacman/tests/hook-abortonfail.py
TESTS += test/pacman/tests/hook-file-change-packages.py
TESTS += test/pacman/tests/hook-file-remove-trigger-match.py
diff --git a/test/pacman/tests/filename-basename-too-long.py b/test/pacman/tests/filename-basename-too-long.py
new file mode 100644
index 0000000..93a14a5
--- /dev/null
+++ b/test/pacman/tests/filename-basename-too-long.py
@@ -0,0 +1,15 @@
+import os
+
+self.description = "Install packages with overly long file names"
+
+filename = 'A' * (os.pathconf(self.rootdir(), 'PC_NAME_MAX') + 1)
+
+p = pmpkg("foo")
+p.files = [filename]
+self.addpkg(p)
+
+self.args = "-U %s" % p.filename()
+
+self.addrule("!PACMAN_RETCODE=0")
+self.addrule("!PKG_EXIST=foo")
+self.addrule("!FILE_EXIST=%s" % filename)
diff --git a/test/pacman/tests/filename-path-too-long.py b/test/pacman/tests/filename-path-too-long.py
new file mode 100644
index 0000000..c4278b5
--- /dev/null
+++ b/test/pacman/tests/filename-path-too-long.py
@@ -0,0 +1,20 @@
+import os
+
+self.description = "Install packages with overly long file paths"
+
+# construct a path > PATH_MAX with the fewest possible components to avoid
+# having to build giant filelists and deep recursion in rmtree()
+name_max = os.pathconf(self.rootdir(), 'PC_NAME_MAX') - 1
+path_max = os.pathconf(self.rootdir(), 'PC_PATH_MAX')
+basename = 'A' * name_max + '/'
+filename = basename * ((path_max / name_max) + 1)
+
+p = pmpkg("foo")
+p.files = [filename]
+self.addpkg(p)
+
+self.args = "-U %s" % p.filename()
+
+self.addrule("!PACMAN_RETCODE=0")
+self.addrule("!PKG_EXIST=foo")
+self.addrule("!FILE_EXIST=%s" % filename)
diff --git a/test/pacman/tests/filename-with-newline.py b/test/pacman/tests/filename-with-newline.py
new file mode 100644
index 0000000..df412db
--- /dev/null
+++ b/test/pacman/tests/filename-with-newline.py
@@ -0,0 +1,11 @@
+self.description = "Install a package including a file with a newline in its name"
+
+p = pmpkg("foo")
+p.files = ["foo\nbar"]
+self.addpkg(p)
+
+self.args = "-U %s" % p.filename()
+
+self.addrule("!PACMAN_RETCODE=0")
+self.addrule("!PKG_EXIST=foo")
+self.addrule("!FILE_EXIST=foo\nbar")
--
2.6.2
More information about the pacman-dev
mailing list