diff options
-rw-r--r-- | .gitignore | 3 | ||||
-rw-r--r-- | Makefile.in | 22 | ||||
-rw-r--r-- | ports/linux/xattr/portdefs.h | 5 | ||||
-rw-r--r-- | pseudo.c | 3 | ||||
-rw-r--r-- | pseudo_util.c | 34 | ||||
-rw-r--r-- | test/test-chroot-symlink.c | 28 | ||||
-rwxr-xr-x | test/test-chroot-symlink.sh | 19 | ||||
-rwxr-xr-x | test/test-relative-from-root.sh | 14 | ||||
-rwxr-xr-x | test/test-umask.sh | 1 |
9 files changed, 106 insertions, 23 deletions
@@ -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 @@ -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 |