Age | Commit message (Collapse) | Author |
|
When statting a file that we may or may not be opening with O_NOFOLLOW,
we should use lstat (or AT_SYMLINK_NOFOLLOW) to try to get information
about the right file.
Also when we want to check whether a bit is set, we should use & rather
than |. I am an experienced programmer and know the difference between
those.
|
|
Did you know that, similar to AT_SYMLINK_NOFOLLOW, there's
an O_NOFOLLOW available in flags for open/openat?
I didn't.
|
|
This adds SPDX license headers to all source files in pseudo so license
identification models current best practise.
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
|
|
Clean up the "unused parameter" warnings in renameat2.
|
|
This is a heck of a special case: If you call open on a FIFO/pipe,
and you didn't have O_NONBLOCK, and you used O_RDONLY or O_WRONLY,
but not O_RDWR, the open can block forever. Unfortunately, pseudo
assumes syscalls complete. We attempt to drop the lock and restore
our state, then recover it later.
Why? Because the .NET runtime does this for a debug hook.
|
|
So renameat2 now has a glibc wrapper in some recent glibc, which
means that mv can use it, and thus bypass all our clever testing,
and since we can't intercept the actual syscall (gnulib's implementation
apparently doesn't hit the glibc syscall() wrapper?), this results
in files being moved without pseudo knowing about them.
Implementing the semantics properly is Very Hard, but possibly we
can just fail politely for now.
We'll be back to this later.
|
|
We've had really weird sporadic things, but it looks like the
underlying problem is that something's getting symlinked over
(which is clearly impossible), but we're nuking everything with
that inode, rather than just the entry for that path, and this
is causing us to drop ownership info for an existing thing.
|
|
Since msg->pathlen is set to len in the first branch, we can share the
final submit-and-check-for-success part of the two branches.
Signed-off-by: Rasmus Villemoes <rasmus.villemoes@prevas.dk>
Signed-off-by: Seebs <seebs@seebs.net>
|
|
MSG_NOSIGNAL has been in Linux since 2.2, and has been standardized in
POSIX 2008. Using that when available avoids the overhead of the two
syscalls to set and restore the SIGPIPE handler. Moreover, we can
eliminate one write() call by making use of sendmsg() to do
scatter-gather I/O.
Signed-off-by: Rasmus Villemoes <rasmus.villemoes@prevas.dk>
Signed-off-by: Seebs <seebs@seebs.net>
|
|
Turns out you need <stdint.h> for int64_t and friends and
some systems were picking it up implicitly and others weren't.
|
|
bind_int doesn't handle 64-bit ints on most targets, we need
bind_int64, and weren't using it. What a silly bug. Caught
and fixed by <Jack.Fewx@dell.com>.
Signed-off-by: seebs <seebs@seebs.net>
|
|
|
|
So ino_t is uint64_t, sqlite field types are magical and erratic and
if a value doesn't fit inside signed int64, it gets converted to
float64. of course. This means that the top half of the inode range
produces invalid-ish values, because a 64-bit double is typically
53 bits of mantissa, so a value around 2^64 will convert to a float64
value which is going to compare equal to at least 2^10 other integer
values if they were also converted to float64. Which makes weird
problems.
|
|
openat() was passing its flags unaltered to pseudo_root_path(), which
assumes that a flags argument other than 0 means "don't follow symlinks
in last path component". This is completely wrong, and I have no idea
how it survived this long unnoticed.
Now, if a plain flags variable is set and not overruled by a
comment like /* flags=... */, it's masked with AT_SYMLINK_NOFOLLOW,
as there are other values fstatat() and friends can take, and the
openat() flags are just overridden with 0. (The only meaningful case
would be O_NOFOLLOW, but O_NOFOLLOW instructs us to *fail* in the
open if the path is a symlink, so we don't care.)
Signed-off-by: Seebs <seebs@seebs.net>
|
|
After the rest of the restandardization on "path does not have
to be slash-terminated", I missed the case where you get an absolute
symlink, which could result in a path starting with an extra slash.
Signed-off-by: Seebs <seebs@seebs.net>
|
|
Stop producing the path mismatch messages for things with multiple
links. We could probably make this smarter, but for now this is
sufficient to reduce the spam.
pseudo_debug(0, ...) now produces a message, as a special case.
Signed-off-by: Seebs <seebs@seebs.net>
|
|
Too lazy to go back and change it, so Wind River can keep
the copyright on my shiny new completely-unused syscall internals,
but I'm fixing the default copyright message for new wrappers.
Signed-off-by: Seebs <seebs@seebs.net>
|
|
But what if syscall(2) was the *first* function with a wrapper
that you called?
Also reduced amount of argument-copying in syscall(2), on further
study, anything with off_t arguments has less than 6 arguments
by enough to keep the total argument count down.
Signed-off-by: Seebs <seebs@seebs.net>
|
|
Two issues: (1) pseudo_fix_path could call lstat("") which generated
ENOENT, (2) some people, and I'm totally not staring intently
at cross-localedef here, don't know that it is in general *not*
valid to check errno unless an operation has failed, and the mere
fact that something set errno does not mean that the error indicated
actually occurred or has any relevance to you.
Nonetheless, pseudo_fix_path now saves and restores errno,
and cross-localedef can just go ahead and check it as though it
were guaranteed not to sometimes get set even though no error
occurred.
Signed-off-by: Seebs <seebs@seebs.net>
|
|
Merge fixes from Richard Tollerton and associated test
cases and permissions fixes.
Signed-off-by: Seebs <seebs@seebs.net>
|
|
is followed by setxattr(); previously it was the other way around. This
broke pseudo when a copied directory has one of the special
bits (setuid, setgid, sticky) set; the special bit wound up getting
removed.
Root cause is that ACLs never included special bits in the first place,
so we need to merge them back in ourselves.
[YOCTO #12379]
Signed-off-by: Richard Tollerton <rich.tollerton@ni.com>
|
|
Signed-off-by: Seebs <seebs@seebs.net>
|
|
The path logic had gotten gradually more baroque, originally
from the need to handle trailing slashes in paths (because
we need "*/" to be a glob that matches only directories),
then from the need not to handle "regularfile/." and the like.
The revised solution is to move the invariant from "partial
path always ends with slash" to "appending always adds a
slash". Because this implies wanting to know the type of
the current partial path, and we also check the type of the
new path whenever we append an element, we now have a shared
stat buf for those. (With some manual tweaking, such as
an empty path is implicitly root and thus a directory, and
anything in which we want to expand a symlink is a
directory.)
Signed-off-by: Seebs <seebs@seebs.net>
|
|
wasn't gracefully handling the empty-path case, such as the
initial slash at the beginning of a path.
this is just a staging point, i need to reeimplement these
cleanly.
Signed-off-by: Seebs <seebs@seebs.net>
|
|
pseudo_append_elements was unconditionally adding a slash after
each element. this means that if it gets called more than once,
as when processing symlinks, you end up with trailing slashes.
change it to add infix slashes.
This code probably wants a rethink.
Signed-off-by: Seebs <seebs@seebs.net>
|
|
This wrapper should allow us to reject renameat2 attempts by
coreutils, letting us regain functionality on FC27 and related
systems.
This is not safe/portable/etc even by pseudo's standards, and
arguably it should be a separate and optional port.
[Amended commit: Don't include the dodgy renameat2 wrapper
which it turns out we'd never hit anyway.]
Signed-off-by: Seebs <seebs@seebs.net>
|
|
The path handling was stripping /., or moving back up a level for
/.., even when the current thing was a plain file, resulting in the
surprising behavior that "a/." was a valid name for a file called a,
which canonicalized without the extra directory. This breaks some
stuff occasionally. (Related to, but not the same as, the previous
issues with the use of trailing slashes in names to match only
directories.)
This is not yet well-tested.
Signed-off-by: Seebs <seebs@seebs.net>
|
|
When OP_CREAT comes in, if there's an existing entry with the
same inode, we nuke that entry because CREAT implies a new file
got that inode, and if there's an existing entry with the same
path, we don't create a link, because there's already something
there.
So if there's a single entry with the same path and inode, it
gets deleted and not recreated. Oops.
Now distinguishing between a single exact match of both path
and inode, and distinct matches by path and by inode.
This addresses a use case where parallel creations could
in theory cause pseudo to mistakenly drop database entries,
potentially. (I could only trigger it by doing this to files
which had existing entries, and then deleting the files outside
of pseudo, though.)
Signed-off-by: seebs <seebs@seebs.net>
|
|
The mkostemps() family are all bad but people use them so here we
are. Since mkstemp(), mkstemps(), and mkostemp() can all be
implemented by calling mkostemps() with additional zeroes passed
in, do it that way.
Signed-off-by: Seebs <seebs@seebs.net>
|
|
So in the non-listen-fd case, apparently I broke the code to use
the index of the returned event, rather than the corresponding ID
value registered with epoll, as the index into the clients array.
This, of course, was nonsense, and explains why we were seeing a
ton of attempts to modify client 0.
This also reverts the previous, incorrect, attempt to address all
those messages.
Signed-off-by: seebs <seebs@seebs.net>
|
|
It seems like the epoll setup can in some cases end up with a
client #0, which the code would refuse to close, so it just
looped forever. Only reject negative numbers, not zero.
Signed-off-by: seebs <seebs@seebs.net>
|
|
O_TMPFILE is, on at least one system, (__O_TMPFILE | O_DIRECTORY),
so (flags & O_TMPFILE) can be non-zero even when O_TMPFILE was not set.
Signed-off-by: Seebs <seebs@seebs.net>
|
|
Whoops, missed this one. Reported/submitted by
<joshua.g.lock@linux.intel.com>.
Signed-off-by: Seebs <seebs@seebs.net>
|
|
FASTOP is logically fine as long as there's no errors, but
if there could be errors, we lose error detection. Responding
instantly with a trivial ACK for FASTOP messages slightly
reduces performance but improves reliability and seems to work
better.
Signed-off-by: Seebs <seebs@seebs.net>
|
|
|
|
Patch was submitted by <dan.dedrick@gmail.com>, revised to make it
a subport in case someone cares about a Linux system which doesn't
have this function. (Which is probably unlikely, but I am a cautious
sort.)
Signed-off-by: Seebs <seebs@seebs.net>
|
|
Original commit message:
The idea came up here:
https://bugzilla.yoctoproject.org/show_bug.cgi?id=11309
and here:
http://lists.openembedded.org/pipermail/openembedded-core/2017-August/141491.html
Signed-off-by: Alexander Kanavin <alexander.kanavin@linux.intel.com>
I've adapted this to make epoll a configure-time option; you must
use --enable-epoll to get the new behavior. I've also confirmed that
it builds both ways and appears to run, and restored the SIGUSR2
functionality (except for the state check) for the epoll case.
Signed-off-by: Seebs <seebs@seebs.net>
|
|
It turns out that these diagnostics can be spurious now on
some hosts, also that they've probably been wrong forever;
for instance, on some Linux, there's not a real "mknod" function
and probably never was, so reporting this error is pointless.
Signed-off-by: Seebs <seebs@seebs.net>
|
|
This allows the pseudo /etc/group to contain extremely long lines,
e.g. when a group has a lot of members. Without this, chown and
chgrp fail for group names that occur after such long lines.
Signed-off-by: Zoltán Böszörményi <zboszor@pr.hu>
Signed-off-by: Seebs <seebs@seebs.net>
---
ports/darwin/guts/getgrouplist.c | 54 +++++++++++++++++++++++++++-----------
ports/linux/guts/getgrouplist.c | 54 +++++++++++++++++++++++++++-----------
ports/uids_generic/guts/getgrent.c | 26 +++++++++++++++---
ports/uids_generic/guts/getgrgid.c | 26 +++++++++++++++---
ports/uids_generic/guts/getgrnam.c | 25 +++++++++++++++---
5 files changed, 146 insertions(+), 39 deletions(-)
|
|
This is a rework which replaces a previous patch. In this version,
files created with O_TMPFILE don't get recorded in the database
at all, but if we get a link request for /proc/self/fd/N, and the
corresponding file is not in the database, we send a CREAT request
for it instead of a LINK, and that appears to work with a MUCH
reduced chance of database leakage.
Also the O_TMPFILE won't be creating bogus database entries
anymore.
Signed-off-by: Seebs <seebs@seebs.net>
linkat fix
|
|
This patch relates to some debugging of handling of large numbers
of clients, but actually it seems useful to have, so checking
it in.
Signed-off-by: Seebs <seebs@seebs.net>
|
|
bash's extremely fancy internal awareness of how the environment looks
means that, if you directly call the underlying libc "unsetenv" on
a variable, bash can end up trying to access a null pointer. Fixing
this generically is actually rather hard; you can't really avoid
writing to environ on fork() or popen(), even if you change all
execv*() functions to use the execv*e() variants. So for now, instead
of unsetting the variable, set it to an empty string.
Thanks to Saur in IRC for spotting this and helping debug it.
Signed-off-by: Seebs <seebs@seebs.net>
|
|
Based on a submission from Anton Gerasimov <anton@advancedtelematic.com>
On some systems, with some kernel configs, "cp -a" apparently tries to
set an empty ACL list, with a valid header but no contents, which causes
strange and mysterious behavior later if we actually create such an entry.
So filter that out, also sanity-check a couple of other things.
Signed-off-by: Seebs <seebs@seebs.net>
|
|
Currently, the Makefile rebuilds the binary at every invokation of
the command make:
$ make
cc -pipe -std=gnu99 -Wall -W -Wextra -fPIC
-D_LARGEFILE64_SOURCE -D_ATFILE_SOURCE -m64
-DPSEUDO_PREFIX='"/opt"' -DPSEUDO_SUFFIX='""'
-DPSEUDO_BINDIR='"bin"' -DPSEUDO_LIBDIR='"lib64"'
-DPSEUDO_LOCALSTATEDIR='"var/pseudo"' -DPSEUDO_VERSION='"1.8.1"'
-DUSE_MEMORY_DB -DPSEUDO_PASSWD_FALLBACK='""'
-DPSEUDO_XATTR_SUPPORT -O2 -g -o bin/pseudo \ pseudo.o
pseudo_server.o pseudo_client.o pseudo_ipc.o \ pseudo_db.o
pseudo_tables.o pseudo_util.o -lsqlite3 -lpthread -ldl
-lpthread cc -pipe -std=gnu99 -Wall -W -Wextra -fPIC
-D_LARGEFILE64_SOURCE -D_ATFILE_SOURCE -m64
-DPSEUDO_PREFIX='"/opt"' -DPSEUDO_SUFFIX='""'
-DPSEUDO_BINDIR='"bin"' -DPSEUDO_LIBDIR='"lib64"'
-DPSEUDO_LOCALSTATEDIR='"var/pseudo"' -DPSEUDO_VERSION='"1.8.1"'
-DUSE_MEMORY_DB -DPSEUDO_PASSWD_FALLBACK='""'
-DPSEUDO_XATTR_SUPPORT -O2 -g -o bin/pseudodb pseudodb.o \
pseudo_db.o pseudo_tables.o pseudo_util.o pseudo_ipc.o -lsqlite3
-lpthread -ldl -lpthread
The fault comes from the $(BIN) directory prerequesite.
According to the documention of GNU make(*), directory prerequesites
normally go to <order-only-prerequisites>:
targets: normal-prerequisites | order-only-prerequisites
> Consider an example where your targets are to be placed in a separate
> directory, and that directory might not exist before make is run. In
> this situation, you want the directory to be created before any
> targets are placed into it but, because the timestamps on directories
> change whenever a file is added, removed, or renamed, we certainly
> don’t want to rebuild all the targets whenever the directory’s
> timestamp changes. One way to manage this is with order-only
> prerequisites: make the directory an order-only prerequisite on all
> the targets.
>
> OBJDIR := objdir
> OBJS := $(addprefix $(OBJDIR)/,foo.o bar.o baz.o)
>
> $(OBJDIR)/%.o : %.c
> $(COMPILE.c) $(OUTPUT_OPTION) $<
>
> all: $(OBJS)
>
> $(OBJS): | $(OBJDIR)
>
> $(OBJDIR):
> mkdir $(OBJDIR)
>
> Now the rule to create the objdir directory will be run, if needed,
> before any ‘.o’ is built, but no ‘.o’ will be built because the
> objdir directory timestamp changed.
This patch fixes this behavior. No binaries are rebuilt when the command
make is re-run:
$ make
make: Nothing to be done for 'all'.
*: https://www.gnu.org/software/make/manual/html_node/Prerequisite-Types.html
Signed-off-by: Gaël PORTAY <gael.portay@savoirfairelinux.com>
Signed-off-by: Seebs <seebs@seebs.net>
|
|
|
|
When deleting a specific file, delete xattrs only if it's the last file
with that device/inode pair.
Signed-off-by: Seebs <seebs@seebs.net>
|
|
Each manual page should start with a "NAME" section, which lists the
name and a brief description of the page separated by "\-".
Signed-off-by: Igor Gnatenko <i.gnatenko.brain@gmail.com>
Signed-off-by: Seebs <seebs@seebs.net>
|
|
file. Before setting a file's capabilities with cap_set_file() (which uses
setxattr()) it calls cap_set_flag(mycaps, CAP_EFFECTIVE, 1, &capflag,
CAP_SET). cap_set_flag() uses the capset syscall to raise the process'
effective capability. In most cases if the process isn't running as root
this will fail and setcap will exit with an error. Because setxattr is
intercepted by pseudo it's unnecessary for setcap to call capset().
Override capset with a pseudo function that does nothing and always
returns 0.
Signed-off-by: George McCollister <george.mccollister at gmail.com>
Signed-off-by: Seebs <seebs@seebs.net>
|
|
When tclsh forks it can create new threads in the child process, in a
pthread_atfork() handler. Running this under pseudo results in a
deadlock since the pseudo_lock() call in the new thread in the child
process premanently believes that the mutex is already locked by another
thread (which actually only existed in the parent process).
The provided test cases reproduces this. Similar hangs can also been
seen in other cases, such as when attempting to use vim's cscope support
under pseudo.
Fix it by reseting the mutex in a pthread_atfork() child function.
Signed-off-by: Rabin Vincent <rabinv@axis.com>
Signed-off-by: Seebs <seebs@seebs.net>
|
|
test-umask fails if run twice. Make it remove the created temporary
files before the test.
Signed-off-by: Rabin Vincent <rabinv@axis.com>
Signed-off-by: Seebs <seebs@seebs.net>
|