aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoss Burton <ross@burtonini.com>2021-04-08 17:25:09 +0100
committerRichard Purdie <richard.purdie@linuxfoundation.org>2021-04-09 14:28:32 +0100
commitee24ebec9e5a11dd5208c9be2870f35eab3b9e20 (patch)
tree06e1f67f301536c2be024f5321ffb54bd614f0c0
parent60e25a36558f1f07dcce1a044fe976b475bec42b (diff)
downloadpseudo-oe-core.tar.gz
pseudo-oe-core.tar.bz2
pseudo-oe-core.zip
client: strip trailing slashes when opening an ignored pathoe-core
The pseudo client path map stores paths that have been sanitised, but in the ignored-path (PSEUDO_IGNORE_PATHS) codepath for open() calls this sanitising wasn't performed so it is possible for paths that end with a trailing slash to be entered. This then subsequently interacts badly with path manipulation, resulting in the situation where doing: fd = open("/some/path/") parent_fd = openat(fd, "../) results in parent_fd actually pointing at /some/path still. Solve this by ensuring that any trailing slashes are removed from the path when adding to the map in the ignore short-circuit. Also add a test case for this to ensure that it doesn't regress in the future. Signed-off-by: Ross Burton <ross.burton@arm.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r--Makefile.in1
-rw-r--r--pseudo_client.c11
-rw-r--r--test/test-openat.c55
-rwxr-xr-xtest/test-openat.sh7
4 files changed, 73 insertions, 1 deletions
diff --git a/Makefile.in b/Makefile.in
index 6eff522..cf13010 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -76,6 +76,7 @@ all: $(LIBPSEUDO) $(PSEUDO) $(PSEUDODB) $(PSEUDOLOG) $(PSEUDO_PROFILE)
test: all | $(BIN) $(LIB) $(LOCALSTATE)
$(CC) $(CFLAGS) $(CFLAGS_PSEUDO) -o test/test-rename-fstat test/test-rename-fstat.c
+ $(CC) $(CFLAGS) $(CFLAGS_PSEUDO) -o test/test-openat test/test-openat.c
@./run_tests.sh -v
install-lib: $(LIBPSEUDO)
diff --git a/pseudo_client.c b/pseudo_client.c
index f846d54..579db33 100644
--- a/pseudo_client.c
+++ b/pseudo_client.c
@@ -1629,7 +1629,16 @@ pseudo_client_op(pseudo_op_t op, int access, int fd, int dirfd, const char *path
if (op != OP_CHROOT && op != OP_CHDIR && op != OP_CLOSE && op != OP_DUP
&& pseudo_client_ignore_path_chroot(path, 0)) {
if (op == OP_OPEN) {
- pseudo_client_path(fd, path);
+ /* Sanitise the path to have no trailing slash as this is convention in the database */
+ char *stripped_path;
+ pathlen = strlen(path);
+ if (pathlen > 2 && (path[pathlen - 1]) == '/') {
+ stripped_path = strndup(path, pathlen-1);
+ pseudo_client_path(fd, stripped_path);
+ free(stripped_path);
+ } else {
+ pseudo_client_path(fd, path);
+ }
}
/* reenable wrappers */
pseudo_magic();
diff --git a/test/test-openat.c b/test/test-openat.c
new file mode 100644
index 0000000..b710285
--- /dev/null
+++ b/test/test-openat.c
@@ -0,0 +1,55 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <unistd.h>
+#include <string.h>
+
+char *path_of(int fd) {
+ ssize_t len;
+ char proc[PATH_MAX], real[PATH_MAX];
+ snprintf(proc, sizeof(proc), "/proc/self/fd/%d", fd);
+ len = readlink(proc, real, sizeof(real));
+ real[len] = '\0';
+ return strdup(real);
+}
+
+/*
+* Test that recusing up the tree with openat(fd, "../") handles slashes
+* correctly and doesn't end up opening the same directory instead of going up a
+* level.
+*/
+int main () {
+ int fd, dir_fd;
+ struct stat st;
+ ino_t ino;
+ char *path;
+
+ fd = openat(AT_FDCWD, ".", O_DIRECTORY, 0);
+ fstat(fd, &st);
+ ino = st.st_ino;
+
+ while (1) {
+ path = path_of(fd);
+ //puts(path);
+
+ dir_fd = openat(fd, "../", O_DIRECTORY, 0);
+ fstat(dir_fd, &st);
+ if (st.st_ino == ino) {
+ if (strcmp(path, "/") == 0) {
+ //puts("Reached top of tree");
+ return 0;
+ } else {
+ //puts("Recursion failed!");
+ return 1;
+ }
+ }
+
+ free (path);
+ ino = st.st_ino;
+ fd = dir_fd;
+ }
+ return 0;
+}
diff --git a/test/test-openat.sh b/test/test-openat.sh
new file mode 100755
index 0000000..0455586
--- /dev/null
+++ b/test/test-openat.sh
@@ -0,0 +1,7 @@
+#! /bin/sh
+
+# Test with and without paths being ignored. The bug was with paths being ignored.
+
+./test/test-openat
+
+PSEUDO_IGNORE_PATHS=/ ./test/test-openat