aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--Makefile.in22
-rw-r--r--ports/linux/xattr/portdefs.h5
-rw-r--r--pseudo.c3
-rw-r--r--pseudo_util.c34
-rw-r--r--test/test-chroot-symlink.c28
-rwxr-xr-xtest/test-chroot-symlink.sh19
-rwxr-xr-xtest/test-relative-from-root.sh14
-rwxr-xr-xtest/test-umask.sh1
9 files changed, 106 insertions, 23 deletions
diff --git a/.gitignore b/.gitignore
index e6e11d9..bc4cbe8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
*.o
+*.pyc
Makefile
libpseudo.so
pseudo_wrapfuncs.*
@@ -14,3 +15,5 @@ pseudo_ports.h
templatefile.pyc
func_deps.mk
port_deps.mk
+test/test-*
+!test/test-*.*
diff --git a/Makefile.in b/Makefile.in
index 4ebe5da..48fdbd2 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -55,6 +55,7 @@ GUTS=$(filter-out "$(GLOB_PATTERN)",$(wildcard $(GLOB_PATTERN)))
SOURCES=$(wildcard *.c)
OBJS=$(subst .c,.o,$(SOURCES))
+TESTS=$(patsubst %.c,%,$(wildcard test/*.c))
SHOBJS=pseudo_tables.o pseudo_util.o
DBOBJS=pseudo_db.o
@@ -74,13 +75,11 @@ TABLES=table_templates/pseudo_tables.c table_templates/pseudo_tables.h
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
- $(CC) $(CFLAGS) $(CFLAGS_PSEUDO) -o test/test-statx test/test-statx.c
- $(CC) $(CFLAGS) $(CFLAGS_PSEUDO) -o test/test-fstat test/test-fstat.c
- $(CC) $(CFLAGS) $(CFLAGS_PSEUDO) -o test/test-fcntl test/test-fcntl.c
- @./run_tests.sh -v
+test: all $(TESTS) | $(BIN) $(LIB)
+ ./run_tests.sh -v
+
+test/%: test/%.c
+ $(CC) $(CFLAGS) $(CFLAGS_PSEUDO) -o $@ $<
install-lib: $(LIBPSEUDO)
mkdir -p $(DESTDIR)$(LIBDIR)
@@ -96,7 +95,7 @@ install-data:
install: all install-lib install-bin install-data
-$(BIN) $(LIB) $(LOCALSTATE):
+$(BIN) $(LIB):
mkdir -p $@
pseudo: $(PSEUDO)
@@ -170,7 +169,8 @@ pseudo_profile: Makefile pseudo_profile.c tables wrappers
$(CC) $(CFLAGS) $(CFLAGS_PSEUDO) -o pseudo_profile pseudo_profile.c
clean:
- rm -f *.o *.so $(PSEUDO) $(PSEUDODB) $(PSEUDOLOG) \
+ rm -f *.o $(LIBPSEUDO) $(PSEUDO) $(PSEUDODB) $(PSEUDOLOG) \
+ $(TESTS) \
pseudo_wrapfuncs.h pseudo_wrapfuncs.c \
pseudo_wrapper_table.c \
pseudo_tables.c pseudo_tables.h \
@@ -181,8 +181,8 @@ clean:
touch port_deps.mk func_deps.mk
distclean: clean
- rm -f Makefile
- rm -rf ./$(BIN) ./$(LIB) ./$(LOCALSTATE)
+ rm -f Makefile port_deps.mk func_deps.mk
+ rm -rf ./$(BIN) ./$(LIB) ./$(LOCALSTATE) ./__pycache__
@echo "WARNING: Makefile has been removed. You must reconfigure to do anything else."
nuke: distclean
diff --git a/ports/linux/xattr/portdefs.h b/ports/linux/xattr/portdefs.h
index 068d39a..beab7d0 100644
--- a/ports/linux/xattr/portdefs.h
+++ b/ports/linux/xattr/portdefs.h
@@ -3,5 +3,8 @@
*
*/
#include <sys/xattr.h>
-#include <attr/attributes.h>
#include <stdint.h>
+
+#ifndef ENOATTR
+#define ENOATTR ENODATA
+#endif
diff --git a/pseudo.c b/pseudo.c
index 528fe1b..4f36786 100644
--- a/pseudo.c
+++ b/pseudo.c
@@ -682,7 +682,8 @@ pseudo_op(pseudo_msg_t *msg, const char *program, const char *tag, char **respon
}
break;
default:
- if (strcmp(msg->path, path_by_ino)) {
+ /* Ignore NAMELESS FILE entries since those could be created by other threads on new files */
+ if (strcmp(msg->path, path_by_ino) && !strcmp(path_by_ino, "NAMELESS FILE")) {
mismatch = 1;
}
break;
diff --git a/pseudo_util.c b/pseudo_util.c
index b6980c2..64636b7 100644
--- a/pseudo_util.c
+++ b/pseudo_util.c
@@ -679,7 +679,7 @@ pseudo_append_element(char *newpath, char *root, size_t allocated, char **pcurre
if (!leave_this && is_dir) {
int is_link = S_ISLNK(buf->st_mode);
if (link_recursion >= PSEUDO_MAX_LINK_RECURSION && is_link) {
- pseudo_diag("link recursion too deep, not expanding path '%s'.\n", newpath);
+ pseudo_debug(PDBGF_PATH, "link recursion too deep, not expanding path '%s'.\n", newpath);
is_link = 0;
}
if (is_link) {
@@ -689,14 +689,15 @@ pseudo_append_element(char *newpath, char *root, size_t allocated, char **pcurre
linklen = readlink(newpath, linkbuf, pseudo_path_max());
if (linklen == -1) {
- pseudo_diag("uh-oh! '%s' seems to be a symlink, but I can't read it. Ignoring.", newpath);
+ pseudo_debug(PDBGF_PATH, "uh-oh! '%s' seems to be a symlink, but I can't read it. Ignoring.\n", newpath);
+ *pcurrent = current;
return 0;
}
/* null-terminate buffer */
linkbuf[linklen] = '\0';
- /* absolute symlink means start over! */
+ /* absolute symlink means go back to root */
if (*linkbuf == '/') {
- current = newpath;
+ current = root;
} else {
/* point back at the end of the previous path... */
current -= (elen + 1);
@@ -791,11 +792,9 @@ static char *pathbufs[PATHBUFS] = { 0 };
static int pathbuf = 0;
/* Canonicalize path. "base", if present, is an already-canonicalized
- * path of baselen characters, presumed not to end in a /. path is
- * the new path to be canonicalized. The tricky part is that path may
- * contain symlinks, which must be resolved.
- * if "path" starts with a /, then it is an absolute path, and
- * we ignore base.
+ * path of baselen characters, presumed not to end in a / unless it is
+ * just "/". path is the new path to be canonicalized. The tricky part
+ * is that path may contain symlinks, which must be resolved.
*/
char *
pseudo_fix_path(const char *base, const char *path, size_t rootlen, size_t baselen, size_t *lenp, int leave_last) {
@@ -809,13 +808,28 @@ pseudo_fix_path(const char *base, const char *path, size_t rootlen, size_t basel
pseudo_diag("can't fix empty path.\n");
return 0;
}
+ if (baselen == 1) {
+ baselen = 0;
+ }
+ if (rootlen == 1) {
+ rootlen = 0;
+ }
newpathlen = pseudo_path_max();
+ pathlen = strlen(path);
+ /* Crazy shell code (e.g. libtool) can pass in a command pipeline as a path which exceeds the max path
+ * length the system can support (6000+ chars). This will fail in libc or the syscall but if we don't
+ * do something here, we'd segfault before it can do that. Leave path unchanged and let libc deal
+ * with it.
+ */
+ if ((pathlen + baselen) >= newpathlen) {
+ return path;
+ }
if (!pathbufs[pathbuf]) {
pathbufs[pathbuf] = malloc(newpathlen);
}
newpath = pathbufs[pathbuf];
pathbuf = (pathbuf + 1) % PATHBUFS;
- pathlen = strlen(path);
+
/* a trailing slash has special meaning, but processing
* trailing slashes is expensive.
*/
diff --git a/test/test-chroot-symlink.c b/test/test-chroot-symlink.c
new file mode 100644
index 0000000..469cb49
--- /dev/null
+++ b/test/test-chroot-symlink.c
@@ -0,0 +1,28 @@
+/*
+ * Test that stat'ing absolute/relative symlinks in a chroot environment works
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+#define _GNU_SOURCE
+
+#include <unistd.h>
+#include <sys/stat.h>
+#include <stdio.h>
+
+int main(int argc, char *argv[]) {
+ struct stat buf;
+
+ if (argc != 2) {
+ perror("args");
+ return 2;
+ }
+ if (chroot(argv[1]) == -1) {
+ perror("chroot");
+ return 1;
+ }
+ if (stat("symlink", &buf) == -1) {
+ perror("stat symlink");
+ return 1;
+ }
+ return 0;
+}
diff --git a/test/test-chroot-symlink.sh b/test/test-chroot-symlink.sh
new file mode 100755
index 0000000..91092c1
--- /dev/null
+++ b/test/test-chroot-symlink.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+#
+# Test that stat'ing absolute/relative symlinks in a chroot environment works
+# SPDX-License-Identifier: LGPL-2.1-only
+#
+
+set -e
+
+touch symlink_target
+trap "rm -f symlink_target symlink" 0
+
+# Absolute symlink
+ln -s /symlink_target symlink
+./test/test-chroot-symlink `pwd`
+rm symlink
+
+# Relative symlink
+ln -s symlink_target symlink
+./test/test-chroot-symlink `pwd`
diff --git a/test/test-relative-from-root.sh b/test/test-relative-from-root.sh
new file mode 100755
index 0000000..e2c230e
--- /dev/null
+++ b/test/test-relative-from-root.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+# pseudo had a bug that made it abort() when looking up a relative path from
+# base "/", such as by openat(dirfd_of_root, "foo/bar") or when cwd is /. It
+# tried to look up base+"/"+path = "//foo/bar", which is wrong.
+
+set -e
+
+touch f1
+relative_pwd=${PWD#/}
+
+cd /
+cat "$relative_pwd/f1"
+
+rm "$relative_pwd/f1"
diff --git a/test/test-umask.sh b/test/test-umask.sh
index e4e366b..e09fdbf 100755
--- a/test/test-umask.sh
+++ b/test/test-umask.sh
@@ -35,3 +35,4 @@ case $(mode b) in
*) exit 1;;
esac
+rm a b