path: root/pseudo_util.c
AgeCommit message (Collapse)AuthorFilesLines
2019-05-15Add SPDX-License-Identifier: LGPL-2.1-only to filesRichard Purdie1-12/+1
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>
2018-04-13Fix one more stray slashSeebs1-1/+1
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>
2018-03-31don't change errno in pseudo_fix_pathSeebs1-2/+12
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>
2018-03-30rework path computationsSeebs1-82/+86
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>
2018-03-30refix path againSeebs1-7/+9
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>
2018-03-30don't add quite so many slashesSeebs1-10/+28
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>
2018-03-06Improve path handling by not dereferencing filesSeebs1-40/+66
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>
2017-04-13Prevent bash from segfaulting when unloading pseudoSeebs1-1/+1
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>
2016-10-31Drop now-redundant if.Seebs1-4/+1
2016-09-28Use correct file descriptorSeebs1-1/+2
So it turns out that pseudo_logfile() was returning 0 or -1, and pseudo_debug_logfile() was expecting it to be the correct file descriptor to use. And it's basically a mystery that any of that ever worked. Signed-off-by: Seebs <seebs@seebs.net>
2016-03-09make bash stop bullying mePeter Seebach1-16/+30
So we had this really strange problem where, sometimes but not always, pseudo would have strange problems on startup, where the pseudo server would end up running under pseudo. And this produced the most fascinating thing, which was: unsetenv("LD_PRELOAD"); assert(getenv("LD_PRELOAD") == NULL); for (int i = 0; environ[i]; ++i) { assert(strncmp(environ[i], "LD_PRELOAD=", 11)); } (pseudocode untested) This would crash on the environ search. Because getenv() was not searching environ. WHAT. So it turns out, *bash overrides getenv, setenv, and so on*. Under those names. Hiding the glibc ones. And this creates horrible problems if you assumed that your code could call those functions and expect them to work. So as a workaround, pseudo now uses dlsym to find getenv, etc., from glibc, and invokes those directly if possible. Also the client now uses unwrapped fork/exec for spawning the server, which cleans up the behavior of that code quite a bit.
2016-03-02Server launch rework continued, probably finishedPeter Seebach1-2/+6
Server process now waits for its forked child when daemonizing, allowing us to yield meaningful exit status. Lock is now taken by the child, since it has a way to tell the parent about the exit status. (We send SIGUSR1 to the server to cause the wait loop to stop when the client is ready to go.) This allows us to switch to fcntl locking, which should in theory allow us to run with the pseudo directory NFS-mounted. Woot! Also mark a couple of overly spammy messages as PDBGF_VERBOSE to reduce the volume of uninteresting dup spam when looking at client behaviors. Client now uses execve to spawn server to work around a very strange behavior of unsetenv. Signed-off-by: Peter Seebach <peter.seebach@windriver.com>
2016-02-24Various logging and cleanupPeter Seebach1-2/+2
Improve event logging a little bit more, increase default event log size, reduce retries (we shouldn't need that many if nothing's wrong), and make the server log timestamps during database cleanup, since I'm suspicious of that as a possible source of delays. Also cause server to emit a useful exit status if it can't get a lock, and client to check server exit status when spawning server.
2016-02-23Add event loggerPeter Seebach1-20/+176
For debugging the client/server startup, add an event logger to allow better recording of events that we may, or may not, want to dump out listings of later.
2016-02-23Improve logfile handlingPeter Seebach1-6/+7
For sound reasons, the server wants to be sure no client is on fd 2. However, the client shouldn't force the pseudo log file to be fd 2; it should leave stderr alone when a log file is specified.
2015-09-01Don't use bare lstat.Peter Seebach1-4/+3
lstat can fail on XFS if the inode number won't fit in a 32-bit value. Use base_lstat. Also, just in case, don't call it if it's not initialized yet (which should never happen). Signed-off-by: Peter Seebach <peter.seebach@windriver.com>
2015-08-21New option: Use extended attributes to store db values.Peter Seebach1-1/+5
This is a moderately experimental feature which stores values in an extended attribute called 'user.pseudo_data' instead of in the database. Still missing: Database<->filesystem synchronization for this. For at least some workloads, this can dramatically improve performance. Signed-off-by: Peter Seebach <peter.seebach@windriver.com>
2015-08-20Drop the allocation in pseudo_fix_path/pseudo_root_path/etc.Peter Seebach1-46/+25
Instead of allocating (and then freeing) these paths all the time, use a rotating selection of buffers of fixed but probably large enough size (the same size that would have been the maximum anyway in general). With the exception of fts_open, there's no likely way to end up needing more than two or three such paths at a time. fts_open dups the paths since it could have a large number and need them for a while. This dramatically reduces (in principle) the amount of allocation and especially reallocation going on. Signed-off-by: Peter Seebach <peter.seebach@windriver.com>
2015-08-20Initial profiling implementation.Peter Seebach1-0/+3
A partially-implemented profiler for client time, which basically just inserts (optional) gettimeofday calls in various places and stashes data in a flat file containing one data block per pid. Signed-off-by: Peter Seebach <peter.seebach@windriver.com>
2015-01-15Clean up the path allocation a bit morePeter Seebach1-1/+8
Having the same logic twice was sorta bugging me. Now the function-like-macro is sorta bugging me, and I'll just let it.
2015-01-14Make --without-passwd-fallback workPeter Seebach1-2/+2
This is derived in significant part from contributions to oe-core by Peter A. Bigot. I reworked the path routine a bit to use an already duplicated string instead of allocating copies of parts of it. The first issue was just that there was a missing antimagic() around some of the path operations. The second is that we wanted to have a way to provide a fallback password file which isn't the host's, but which can be used in the case where the target filesystem hasn't got a password yet, for bootstrapping purposes. (So there's a minimal password file that just has root, basically.) Also, I noticed a design flaw, which is that if you ended up calling pseudo_pwd_lck_open() twice in a row, the second time through, pseudo would first check whether it had a path name for the file (it does), and thus not allocate one, then call the close routine (which frees it and nulls the pointer), then open a new one... and not have a file name, so the next attempt to close it wouldn't unlink the file. This shouldn't ever come up in real code, but it was bugging me. Signed-off-by: Peter Seebach <peter.seebach@windriver.com>
2015-01-05Try to handle trailing slashesPeter Seebach1-1/+6
It turns out that "a/" is equivalent to "a/.", and that in particular it should fail when a is not a directory. Pseudo's been silently stripping them and this breaks things. Attempt to fix that, lightly tested.
2014-06-13Use constant initializer for staticPeter Seebach1-1/+1
strlen(array) isn't a constant expression, even though gcc can sometimes figure it out at compile time.
2014-05-16pseudo_has_unload: add functionPeter Seebach1-0/+27
Various wrappers checked for a non-null pseudo_get_value("PSEUDO_UNLOAD") to determine whether the environment should include the pseudo variables. None of those checks freed the returned value when it was not null. The new check function does. The new check function also sees whether PSEUDO_UNLOAD was defined in the environment that should be used in the wrapped system call. This allows pkg_postinst scripts to strip out the LD_PRELOAD setting, for example before invoking qemu to execute commands in an environment that does not have libpseudo.so. [YOCTO #4843] Signed-off-by: Peter A. Bigot <pab@pabigot.com> Signed-off-by: Peter Seebach <peter.seebach@windriver.com>
2014-04-22xattr support and other path stuff: reduce allocation and copyingPeter Seebach1-0/+37
The xattr first-pass implementation was allocating a buffer to hold the name and value for a set operation, then pseudo_client was allocating *another* buffer to hold the path and those two values. pseudo_client_op develops more nuanced argument handling, and also uses a static buffer for the extended paths it sometimes needs. So for the typical use case, only occasional operations will need to reallocate/expand the buffer, and we'll be down to copying things into that buffer once per operation, instead of having two alloc/free pairs and two copies. And of course, that wasn't two alloc/free pairs, it was one alloc/free pair and one alloc without a free. Whoops. Signed-off-by: Peter Seebach <peter.seebach@windriver.com>
2014-04-21Initial draft xattr supportPeter Seebach1-8/+0
Initial, incomplete, support for extended attributes. Extended attributes are implemented fairly naively, using a second table in the file database using the primary file table's id as a foreign key. The ON DELETE CASCADE behavior requires sqlite 3.6.19 or later with foreign key and trigger support compiled in. To reduce round-trips, the client does not check for existing attributes, but rather, sends three distinct set messages; OP_SET_XATTR, OP_CREATE_XATTR, OP_REPLACE_XATTR. A SET message always succeeds, a CREATE fails if the attribute already exists, and a REPLACE fails if the attribute does not already exist. The /* flags */ feature of makewrappers is used to correct path names appropriately, so all functions are already working with complete paths, and can always use functions that work on links; if they were supposed to dereference, the path fixup code got that. The xattr support is enabled, for now, conditional on whether getfattr --help succeeds. Not yet implemented: Translation for system.posix_acl_access, which is used by "cp -a" (or "cp --preserve-all") on some systems to try to copy modes. Signed-off-by: Peter Seebach <peter.seebach@windriver.com>
2014-01-22Don't automatically fall back to /etc/passwd.Peter Seebach1-39/+39
In some cases, we'd rather pseudo fail than fall back to using /etc/passwd or /etc/group. Make the determination of what to fall back to when neither PSEUDO_PASSWD nor a chroot directory contains passwd/group files controllable by a configure-time flag, controlled by --with-passwd-fallback= or --without-passwd-fallback.
2013-06-25Change debugging to use flags rather than levelsPeter Seebach1-64/+81
This is a moderately intrusive change. The basic overall effect: Debugging messages are now controlled, not by a numeric "level", but by a series of flags, which are expressed as a string of letters. Each flag has a single-letter form used for string specifications, a name, a description, a numeric value (1 through N), and a flag value (which is 1 << the numeric value). (This does mean that no flag has the value 1, so we only have 31 bits available. Tiny violins play.) The other significant change is that the pseudo_debug calls are now implemented with a do/while macro containing a conditional, so that computationally-expensive arguments are never evaluated if the corresponding debug flags weren't set. The assumption is that in the vast majority of cases (specifically, all of them so far) the debug flags for a given call are a compile-time constant, so the nested conditional will never actually show up in code when compiled with optimization; we'll just see the appropriate conditional test. The VERBOSE flag is magical, in that if the VERBOSE flag is used in a message, the debug flags have to have both VERBOSE and at least one other flag for the call to be made. This should dramatically improve performance for a lot of cases without as much need for PSEUDO_NDEBUG, and improve the ability of users to get coherent debugging output that means something and is relevant to a given case. It's also intended to set the stage for future development work involving improving the clarity and legibility of pseudo's diagnostic messages in general. Old things which used numeric values for PSEUDO_DEBUG will sort of continue to work, though they will almost always be less verbose than they used to. There should probably be a pass through adding "| PDBGF_CONSISTENCY" to a lot of the messages that are specific to some other type.
2013-02-26PSEUDO_ALLOW_FSYNC: Allow fsync()pseudo-1.5PSEUDO_1_5Peter Seebach1-0/+1
Some filesystems have buggy semantics where stat(2) will return incorrect sizes for files for a while after some changes, sometimes, unless they've been fsync'd. We still want to disable fsync most of the time, but enabling it for specific programs can be useful. Signed-off-by: Peter Seebach <peter.seebach@windriver.com>
2013-01-30Remove a couple of highly non-obvious GLIBC_2.7 dependencies.Peter Seebach1-11/+3
There were a couple of cases where pseudo built against GLIBC_2.7 or newer was ending up with dependencies on symbols which required GLIBC_2.7. With these gone, it appears that a libpseudo.so can be used on an older host in some cases. None were particularly important or intentional: 1. pseudo_util was conditionally calling open() with only two arguments, which can invoke a new __open2() function in some systems. Don't care, and the docs specifically state that the mode argument is "ignored" when O_CREAT is absent, so it's not necessary to omit it. 2. The calls to sscanf/fscanf in pseudo_client.c were getting translated into a special new iso_c99 sscanf/fscanf, and we don't care because we're not using those features; #define _GNU_SOURCE suppresses the extra-compliant behavior. Signed-off-by: seebs <peter.seebach@windriver.com>
2012-06-28[Yocto #2639] Don't crash with really long chroot directoriesPeter Seebach1-3/+7
The logic for whether to allocate space for the "base" path in pseudo_fix_path recognized that you don't need it when the path you're evaluating starts with a slash. This is great, except: 1. It's not actually true, if rootlen isn't 0. 2. The decision of whether or not to copy over the base path didn't check for this, so it would happen anyway. The net result is, if you had a path in excess of 256 characters as a base (say, a chroot directory), and you tried to evaluate a path starting with a slash (say, /etc/shadow), pseudo would allocate enough space for the path, but not for the base path, and then copy the base path into it anyway. The rounding up to multiples of 256 isn't enough to save us in this case. Solution: 1. Make the logic for the base path copy match the allocation logic. 2. Use (path[0] != '/' || rootlen) as the second part of the test, because if there's a non-zero rootlen, we're in a chroot and MUST preserve at least some of the path. This could maybe be smarter (what if we only allocated space for rootlen in that case?) except that in reality, it's very very often the case that baselen == rootlen, and it's not as though we want MORE complexity.
2012-03-28cleanup and fixesPeter Seebach1-1/+1
Spotted a couple of things during the last batch of fixes; fixing these up so things are more consistent or clearer.
2011-11-02Implement PSEUDO_UNLOAD, replacing existing PSEUDO_RELOADED semantics.Mark Hatle1-1/+1
Change from internal PSEUDO_RELOADED to external PSEUDO_UNLOAD environment variable. Enable external programs to have a safe and reliable way to unload pseudo on the next exec*. PSEUDO_UNLOAD also will disable pseudo if we're in a fork/clone situation in the same way PSEUDO_DISABLED=1 would. Rename the PSEUDO_DISABLED tests, and create a similar set for the new PSEUDO_UNLOAD. Signed-off-by: Mark Hatle <mark.hatle@windriver.com>
2011-03-25Try to force debug fd to 2. The intent is that this will keep mallocPeter Seebach1-0/+13
debugger messages from going to the wrong place. No longer fclose(stderr) after grabbing log file, because stderr is likely still using fd 2.
2011-03-25Merge in ports workPeter Seebach1-65/+190
This is a spiffied-up rebase of a bunch of intermediate changes, presented as a whole because it is, surprisingly, less confusing that way. The basic idea is to separate the guts code into categories ranging from generic stuff that can be the same everywhere and specific variants. The big scary one is the Darwin support, which actually seems to run okay on 64-bit OS X 10.6. (No other variants were tested.) The other example given is support for the old clone() syscall on RHEL 4, which affects some wrlinux use cases. There's a few minor cleanup bits here, such as a function with inconsistent calling conventions, but nothing really exciting.
2011-02-08Expand paths on exec.Peter Seebach1-4/+2
This is fussy, because we have to actually do the path search ourselves as best we can to handle unqualified paths. The result, though, is more meaningful logs. Along the way, fix some bitrot in the comments in pseudo_fix_path and friends.
2010-12-13Further amend the system to enable/disable sudo during fork/exec.Mark Hatle1-20/+24
2010-12-09: * (mhatle) Add doc/program_flow to attempt to explain startup/running * (mhatle) guts/* minor cleanup * (mhatle) Reorganize into a new constructor for libpseudo ONLY pseudo main() now manually calls the util init new / revised init for client, wrappers and utils * (mhatle) Add central "reinit" function * (mhatle) Add manul execv* functions * (mhatle) rename pseudo_populate_wrappers to pseudo_check_wrappers Signed-off-by: Mark Hatle <mark.hatle@windriver.com>
2010-12-07This is a merge of several commits from a tree which turned out toPeter Seebach1-18/+40
be out of sync in a very inconvenient way. Changes include: * Some whitespace fixes, also move the pseudo_variables definition into pseudo_util.c since it's not used anywhere else. * Further improvements in the fork() support: We now recognize both positive and negative forms of PSEUDO_DISABLED, so we can distinguish between "it was removed from the environment by env -i" (restore the old value) and "it was intentionally turned off" (the new value wins). * clone(2) support. This is a little primitive, and programs might still fail horribly due to clone's semantics, but at least it's there and passes easy test cases. Plus a big patch from Mark Hatle: Cleanup fork/clone and PSEUDO_DISABLED guts/fork.c: * cleanup function and make it more robust * be sure to call pseudo_setupenv prior to pseudo_client_reset to match exec behavior pseudo_wrappers.c: * fix mismatched type in execl_to_v call via typecast * Simplify fork call via single call to wrap_fork() * be sure to save pseudo_disabled * be sure to call pseudo_setupenv prior to pseudo_client_reset to match exec behavior tests: * Add a test of whether pseudo can be disabled/enabled on a fork. Signed-off-by: Mark Hatle <mark.hatle@windriver.com>
2010-09-01A couple more int/size_t mismatch fixes.Peter Seebach1-2/+4
2010-08-27We got bitten AGAIN by hard-coded lengths in memcmp, so we've swappedPeter Seebach1-6/+6
that for a macro that does it correctly. Why not just use strcmp, you ask? Because we aren't doing a string compare, we're looking for a prefix.
2010-08-26The logic for updating LD_LIBRARY_PATH had a bug; if you hadseebs1-15/+21
an LD_LIBRARY_PATH that included the pseudo library directory and some other directories, the other directories would get wiped out. Also a couple of whitespace rationalizatoins.
2010-08-20Handle insane boundary condition for regcomp()/regexec()seebs1-4/+28
For reasons that may never be known, the /usr/bin/find on RHEL5 contains its own local copies of regcomp() and regexec(). Thus, when pseudo makes calls to these functions, it gets the local copies in the binary instead of the ones in libc. But wait! That's not all. There's also the fascinating detail that, for reasons unknown, these local copies have an incompatible API, such that: regexec(pattern, list, 1, pmatch, 0); can write to more than one element of pmatch, and since that's a local array of one member, that means that they can crush something on the stack, such that a couple of function calls later you get a segfault in Nothing In Particular. So. We try to grab the real regcomp/regexec from libc, using dlsym, and if we can't, we fall back on whatever the defaults were. Inexplicably, this code actually made pseudo crash less often on at least one target. This is madness within madness, and I really have no idea why on earth /usr/bin/find, on a Linux system, would have its own local copies of regcomp/regexec, let alone why it would have copies that had substantially different semantics.
2010-08-16A few minor fixes:seebs1-7/+14
Fixed a couple of allocation issues, corrected an off-by-one error in environment setup.
2010-08-16Fix ld_preload/ld_library_path mixupMark Hatle1-1/+1
Fix an obvious ld_preload/ld_library_path mixup in pseudo_util.c Signed-off-by: Richard Purdie <richard.purdie@intel.com> Signed-off-by: Mark Hatle <mark.hatle@windriver.com>
2010-08-12Whoops, const really does mean read-only on some targets.seebs1-5/+5
2010-08-11Enable local variable cacheMark Hatle1-212/+347
Add local variable cache via get_value and set_value. The local cache is setup at constructor time (or soon after). Rewrite the pseudo_setupenv and pseudo_dropenv routines, add a new pseudo_setupenvp and pseudo_dropenvp as well to handle the execve cases. We can now successfully use /usr/bin/env -i env and get pseudo values back!
2010-08-11Fix off by 4 error..Mark Hatle1-1/+1
We can potentially under allocate memory due.
2010-08-06Fix an exec program with an empty environmentMark Hatle1-1/+54
If the environment has been cleared (in an execve for instance), we need to seed the environment with the PSEUDO_PREFIX, PSEUDO_BINDIR, PSEUDO_LIBDIR, and PSEUDO_LOCALSTATEDIR values.
2010-08-04Add new environment values to allow easy override of default locationsMark Hatle1-27/+145
Add PSEUDO_BINDIR, PSEUDO_LIBDIR, and PSEUDO_LOCALSTATEDIR to allow for more easy customization of PSEUDO components at run-time. If these are not set they will be automatically generated based on the existing PSEUDO_PREFIX path. PSEUDO_BINDIR = PSEUDO_PREFIX /bin PSEUDO_LIBDIR = PSEUDO_PREFIX /lib PSEUDO_LOCALSTATEDIR = PSEUDO_PREFIX /var/pseudo Signed-off-by: Mark Hatle <mark.hatle@windriver.com>
2010-06-29Whoops, remove a couple of extra debugging messages.Peter Seebach1-12/+1