Age | Commit message (Collapse) | Author |
|
Commit 60e25a36558f1f07dcce1a044fe976b475bec42b started dereferencing
the "path" parameter which for some functions is annotated with the
"nonnull" attribute. While the commit explicitly checks for NULL
pointers before dereferencing it, GCC (at optimization level 1 and
above) removes the check due to the "nonnull" attribute being set for
some parameters in the glibc headers (e.g. statx()).
However, the statx() man page explicitly allows calling with NULL
pointers (in which case the EFAULT is returned) and this behaviour is
used in the wild (e.g. in Rust) to determine whether the statx() system
call is supported.
Disabling the optimization is not possible ([1]) so prevent the compiler
optimization by referencing the parameter in a noop inline assembly
instruction instead.
[1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100404
Signed-off-by: Philip Lorenz <philip@bithub.de>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
|
|
In glibc 2.33 it makes calls like:
fstatat64 (pathfd, "", &st, AT_EMPTY_PATH);
where pathfd may be a symlink. This interacts badly with pseudo_root_path()
since the empty path is replaced with a pathname from the open fd but
AT_SYMLINK_NOFOLLOW is not set, hence the link is resolved and pseudo
throws an abort() due to inode mismatch.
Where the path is empty, an fd is passed and AT_EMPTY_PATH is set,
we can imply that AT_SYMLINK_NOFOLLOW is also effectly set. Adjust
the wrapper functions to ensure this, allowing the functions to behave
correctly in the AT_EMPTY_PATH case.
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
|
|
Pseudo allows wrappers to define special comments in the wrapper lists to
pass extra arguments such as version=GLIBC_2.3 to control which symbol
version to search for. However, these arguments can be architecture-specific.
When parsing the arguments, check for flags that end in the architecture name
(as returned by platform.machine()) and use those values instead.
Signed-off-by: Ross Burton <ross.burton@arm.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
|
|
An except statement was still using Python 2 syntax so caused
SyntaxErrors if the exception was raised.
Signed-off-by: Ross Burton <ross.burton@arm.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
|
|
Currently, pseudo considers any path accessed whist its running to be
a valid entry to track in its database. The way OpenEmbedded uses pseudo,
there are paths we care about accesses to from a pseudo perspective and paths
which we simply don't care about.
This patch adds a PSEUDO_IGNORE_PATHS environment variable which is a comma
separated list of path prefixes to ignore accesses to.
To do this, we add some functions which can check a path argument or a file
descriptor argument and use these in the pseudo wrappers where path or fd
arguments are present. Where paths are being ignored, we skip straight to
the underlying real function.
Psuedo needs to keep track of the open fd mappings to files so we still need
to allow those cases into the pseudo_op function. Specficially this means
OP_CLOSE, OP_OPEN, OP_DUP and OP_CHDIR.
Apart from OP_OPEN which could call the server, the other operations are client
side only so passed through. We 'tag' the functions using these operations so
that the path ignore code isn't triggered. For OP_OPEN we exit early and skip
the server op. We also have a catch all in client_op to ensure any operatings
we didn't manage to skip early still get skipped correctly.
OP_CHROOT is a special case. Where ignored path prefixes are used as a chroot,
for the lifetime of the chroot, the path is effectively dropped from the
PSEUDO_IGNORE_PATHS list. Whilst slightly counter intuaitive, this turned out
to be the most effective way to do things due to commands like useradd and
their use of chroots.
For sqlite3 and appropriate path filtering in OE, this took the database from
45,000 entries to about 180. For dbus this was 88,000 down to 760. Given the
number of client to server trips these numbers of paths involves, the win
is seemingly worthwhile.
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
|
|
Changelog indicates they should be compatible.
Upstream-Status: Pending
Signed-off-by: Alexander Kanavin <alex.kanavin@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
|
|
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>
|
|
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>
|
|
Helped-by: Damien Riegel <damien.riegel@savoirfairelinux.com>
Helped-by: Alexandre Leblanc <alexandre.leblanc@savoirfairelinux.com>
Signed-off-by: Gaël PORTAY <gael.portay@savoirfairelinux.com>
Signed-off-by: Seebs <seebs@seebs.net>
|
|
File "./makewrappers", line 459
print port
^
SyntaxError: Missing parentheses in call to 'print'
Signed-off-by: Gaël PORTAY <gael.portay@savoirfairelinux.com>
Signed-off-by: Seebs <seebs@seebs.net>
---
maketables | 12 ++++++------
makewrappers | 32 ++++++++++++++++----------------
templatefile.py | 8 ++++----
3 files changed, 26 insertions(+), 26 deletions(-)
diff --git a/maketables b/maketables
index b32312e..0726485 100755
--- a/maketables
+++ b/maketables
@@ -73,7 +73,7 @@ class DataType:
for col in columns:
indexed = False
if col.startswith("FLAGS"):
- print "Flags: set for %s" % self.name
+ print("Flags: set for %s" % self.name)
self.flags = True
continue
if col.startswith("INDEXED "):
@@ -248,7 +248,7 @@ def main():
template_file.emit('header')
templates.append(template_file)
except IOError:
- print "Invalid or malformed template %s. Aborting." % path
+ print("Invalid or malformed template %s. Aborting." % path)
exit(1)
for filename in sys.argv[1:]:
@@ -256,15 +256,15 @@ def main():
sys.stdout.write("%s: " % filename)
datatype = DataType(filename)
datatypes.append(datatype)
- print datatype.__repr__()
- print ""
+ print(datatype.__repr__())
+ print("")
- print "Writing datatypes...",
+ print("Writing datatypes...")
for datatype in datatypes:
# populate various tables and files with each datatype
for template_file in templates:
template_file.emit('body', datatype)
- print "done. Cleaning up."
+ print("done. Cleaning up.")
for template_file in templates:
# clean up files
diff --git a/makewrappers b/makewrappers
index 303e2cc..bac856b 100755
--- a/makewrappers
+++ b/makewrappers
@@ -456,7 +456,7 @@ additional ports to include.
self.name = port
self.subports = []
self.preports = []
- print port
+ print(port)
if os.path.exists(self.portfile("pseudo_wrappers.c")):
self.wrappers = self.portfile("pseudo_wrappers.c")
@@ -504,17 +504,17 @@ additional ports to include.
prefuncs = pre.functions()
for name in prefuncs.keys():
if name in mergedfuncs:
- print "Warning: %s from %s overriding %s" % (name, pre.name, mergedfuncs[name].port)
+ print("Warning: %s from %s overriding %s" % (name, pre.name, mergedfuncs[name].port))
mergedfuncs[name] = prefuncs[name]
for name in self.funcs.keys():
if name in mergedfuncs:
- print "Warning: %s from %s overriding %s" % (name, self.name, mergedfuncs[name].port)
+ print("Warning: %s from %s overriding %s" % (name, self.name, mergedfuncs[name].port))
mergedfuncs[name] = self.funcs[name]
for sub in self.subports:
subfuncs = sub.functions()
for name in subfuncs.keys():
if name in mergedfuncs:
- print "Warning: %s from %s overriding %s" % (name, sub.name, mergedfuncs[name].port)
+ print("Warning: %s from %s overriding %s" % (name, sub.name, mergedfuncs[name].port))
mergedfuncs[name] = subfuncs[name]
return mergedfuncs
@@ -576,11 +576,11 @@ def process_wrapfuncs(port):
func.directory = directory
funcs[func.name] = func
sys.stdout.write(".")
- except Exception, e:
- print "Parsing failed:", e
+ except Exception(e):
+ print("Parsing failed:", e)
exit(1)
funclist.close()
- print ""
+ print("")
return funcs
def main(argv):
@@ -599,35 +599,35 @@ def main(argv):
for path in glob.glob('templates/*'):
try:
- print "Considering template: " + path
+ print("Considering template: " + path)
source = TemplateFile(path)
if source.name.endswith('.c') or source.name.endswith('.h'):
source.emit('copyright')
source.emit('header')
sources.append(source)
except IOError:
- print "Invalid or malformed template %s. Aborting." % path
+ print("Invalid or malformed template %s. Aborting." % path)
exit(1)
try:
port = Port('common', sources)
except KeyError:
- print "Unknown uname -s result: '%s'." % uname_s
- print "Known system types are:"
- print "%-20s %-10s %s" % ("uname -s", "port name", "description")
+ print("Unknown uname -s result: '%s'." % uname_s)
+ print("Known system types are:")
+ print("%-20s %-10s %s" % ("uname -s", "port name", "description"))
for key in host_ports:
- print "%-20s %-10s %s" % (key, host_ports[key],
- host_descrs[host_ports[key]])
+ print("%-20s %-10s %s" % (key, host_ports[key],
+ host_descrs[host_ports[key]]))
# the per-function stuff
- print "Writing functions...",
+ print("Writing functions...")
all_funcs = port.functions()
for name in sorted(all_funcs.keys()):
# populate various tables and files with each function
for source in sources:
source.emit('body', all_funcs[name])
- print "done. Cleaning up."
+ print("done. Cleaning up.")
for source in sources:
# clean up files
diff --git a/templatefile.py b/templatefile.py
index 2789b22..abf9a2c 100644
--- a/templatefile.py
+++ b/templatefile.py
@@ -79,13 +79,13 @@ class TemplateFile:
return
path = Template(self.path).safe_substitute(item)
if os.path.exists(path):
- # print "We don't overwrite existing files."
+ # print("We don't overwrite existing files.")
return
self.file = open(path, 'w')
if not self.file:
- print "Couldn't open '%s' (expanded from %s), " \
+ print("Couldn't open '%s' (expanded from %s), " \
"not emitting '%s'." % \
- (path, self.path, template)
+ (path, self.path, template))
return
def emit(self, template, item=None):
@@ -103,7 +103,7 @@ class TemplateFile:
self.file.write(templ.safe_substitute(item))
self.file.write("\n")
else:
- print "Warning: Unknown template '%s'." % template
+ print("Warning: Unknown template '%s'." % template)
if self.file_per_item:
if self.file:
--
2.10.1
|
|
File "./makewrappers", line 327
return """/* This function is not called if pseudo is configured --enable-force-async */
^
TabError: inconsistent use of tabs and spaces in indentation
Signed-off-by: Gaël PORTAY <gael.portay@savoirfairelinux.com>
Signed-off-by: seebs <seebs@seebs.net>
---
makewrappers | 26 +++++++++++++-------------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/makewrappers b/makewrappers
index e9191ed..303e2cc 100755
--- a/makewrappers
+++ b/makewrappers
@@ -324,7 +324,7 @@ class Function:
def maybe_async_skip(self):
if self.async_skip:
- return """/* This function is not called if pseudo is configured --enable-force-async */
+ return """/* This function is not called if pseudo is configured --enable-force-async */
#ifdef PSEUDO_FORCE_ASYNC
if (!pseudo_allow_fsync) {
PROFILE_DONE;
@@ -333,7 +333,7 @@ class Function:
#endif
""" % self.async_skip
else:
- return ""
+ return ""
def comment(self):
"""declare self (in a comment)"""
@@ -393,11 +393,11 @@ class Function:
def rc_format(self):
"""the format string to use for the return value"""
- return typedata.get(self.type, { 'format': '[%s]', 'value': '"' + self.type + '"' })['format']
+ return typedata.get(self.type, { 'format': '[%s]', 'value': '"' + self.type + '"' })['format']
def rc_value(self):
"""the value to pass for the format string for the return value"""
- return typedata.get(self.type, { 'format': '[%s]', 'value': '"' + self.type + '"' })['value']
+ return typedata.get(self.type, { 'format': '[%s]', 'value': '"' + self.type + '"' })['value']
def rc_decl(self):
"""declare rc (if needed)"""
@@ -456,7 +456,7 @@ additional ports to include.
self.name = port
self.subports = []
self.preports = []
- print port
+ print port
if os.path.exists(self.portfile("pseudo_wrappers.c")):
self.wrappers = self.portfile("pseudo_wrappers.c")
@@ -522,11 +522,11 @@ additional ports to include.
return '#define PSEUDO_PORT_%s 1' % string.upper(self.name).replace('/', '_')
def portdeps(self):
- deps = []
- if self.wrappers:
- deps.append(self.wrappers)
- if self.portdef_file:
- deps.append(self.portdef_file)
+ deps = []
+ if self.wrappers:
+ deps.append(self.wrappers)
+ if self.portdef_file:
+ deps.append(self.portdef_file)
if deps:
return 'pseudo_wrappers.o: %s' % ' '.join(deps)
else:
@@ -590,7 +590,7 @@ def main(argv):
for arg in argv:
name, value = arg.split('=')
- os.environ["port_" + name] = value
+ os.environ["port_" + name] = value
# error checking helpfully provided by the exception handler
copyright_file = open('guts/COPYRIGHT')
@@ -599,9 +599,9 @@ def main(argv):
for path in glob.glob('templates/*'):
try:
- print "Considering template: " + path
+ print "Considering template: " + path
source = TemplateFile(path)
- if source.name.endswith('.c') or source.name.endswith('.h'):
+ if source.name.endswith('.c') or source.name.endswith('.h'):
source.emit('copyright')
source.emit('header')
sources.append(source)
--
2.10.1
|
|
I never did this because how could you do it generically, then a
friend who is better at Python gave me an idea for a way to do it,
and now wrapper debugging prints return values, not just errno
values, in most-to-all cases.
Signed-off-by: Peter Seebach <peter.seebach@windriver.com>
|
|
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>
|
|
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>
|
|
We used to rely on filesystem operations to apply the umask when
appropriate, but when we started masking out 022, that stopped working.
Start watching umask.
|
|
Clean-up: Allow specification of environment hints for subports
scripts, such as whether xattr support is available. Also make
configure guess at a bit width if none is specified.
Signed-off-by: Peter Seebach <peter.seebach@windriver.com>
|
|
Ports can provide pseudo_wrappers.c or portdefs.h, and individual
functions have implementations. These dependencies aren't known until
post-configure. Make the Makefile include two sub-Makefiles which can
be updated by makewrappers.
Signed-off-by: Peter Seebach <peter.seebach@windriver.com>
|
|
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>
|
|
Darwin's off_t is a 64-bit type, so there's no off64_t. Also,
there's an uninitialized variable usage in unlinkat which LLVM
catches.
Signed-off-by: Peter Seebach <peter.seebach@windriver.com>
|
|
The openembedded build, at least with RPM or SMART, is heavily affected
by the cost of calling fsync or fdatasync on package databases all the
time. Gosh, wouldn't it be nice if we could suppress that without making
dozens of highly intrusive and risky changes into RPM, various database
packages, and so on?
Yes, yes it would. If only there were a program which could intercept
system calls and change their behavior!
Enter --enable-force-async. There are now wrappers for fsync, fdatasync,
and a few related functions. If --enable-force-async is set, these wrappers
instantly return 0, even if PSEUDO_DISABLED is set. And with any luck,
bitbake will now perform a bit better.
Credit for this insight goes to Richard Purdie. I've reimplemented
this to add the configure option, and make the fsync suppression work
even when PSEUDO_DISABLED is set.
|
|
We never had an implementation for linkat() because no one used it;
now someone uses it. link() is now implemented on top of linkat().
Note the abnormal AT_SYMLINK_FOLLOW (as opposed to _NOFOLLOW) flag.
|
|
|
|
1. Fix *at() where dirfd is obtained through dirfd(DIR *).
The dirfd(DIR *) interface allows you to get the fd for a DIR *,
meaning you can use it with openat(), meaning you can need its
path. This causes a segfault. Also fixed the base_path
code not to segfault in that case, but first fix the
underlying problem.
2. Implement renameat()
After three long years, someone tried to use this. This was impossibly
hard back when pseudo was written, because there was only one dirfd
provided for. Thing is, now, the canonicalization happens in wrapfuncs,
so a small tweak to makewrappers to recognize that oldpath should use
olddirfd if it exists is enough to get us fully canonicalized paths
when needed.
|
|
On some Linux systems, dlsym("realpath", RTLD_NEXT) prefers
for reasons of its own to give a symbol that is also known
as old_realpath, which fails and yields EINVAL when called
with a null pointer as the second argument. This can be
avoided, on some systems, by using dlvsym() to request
the GLIBC_2.3 version of the symbol.
The wrapper logic is enhanced to allow for specifying
versions, although this currently only works for Linux
(Darwin has no dlvsym, apparently?). The test case is
a trivial program which calls realpath(name, NULL) run
with PSEUDO_DISABLED=1.
|
|
|
|
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.
|
|
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>
|
|
in an incoming "maketables".)
|
|
|
|
|
|
|
|
one.
There's a long story here, but to abbreviate it:
The shell script was annoying at best to maintain and starting to
show signs of not really being the right tool for the job. For
various reasons, we have some other Python stuff in our build system,
so we picked Python as the language we were already using for other
stuff. We think this works with anything reasonably recent (around
Python 2.4 through 2.6).
There's a little bit of cleanup, also, of the wrapper templates.
|
|
pseudo_saved_sigmask occurred outside of the check against
antimagic, calls to wrapped functions made by the internals
of a wrapper resulted on overwriting pseudo_saved_sigmask,
so we restored the already-blocked sigmask. This could
result in programs getting their sigmask permanently changed
to block various signals, most crucially SIGCHLD.
We now stash the value immediately before calling a wrapper,
and never stash it if we're not calling a wrapper. Now
the anti-magic stuff happening inside wrappers isn't trashing
the signal mask. YAY!
|
|
in processes started under pseudo.
|
|
We wrap all of the execs so that we can ensure the environment is
properly configured prior to the exec running.
handle ... for the new execl* wrappers
Add a test for the new execl* ... handling.
|
|
Address a couple of compiler warnings, add a couple of signals to the
list of caught signals, etcetera.
|
|
remake(1) can try to close a file from a signal handler. Since
any entrance to a pseudo-emulated function requires the mutex,
this can result in a deadlock. Solution: Suspend SIGCHLD (and
a couple of other signals likely to result in filesystem
operations) for the duration of the lock.
|
|
If multiple clients are active at once, the following could occur:
* Client #1 unlinks file A
* Client #2 creates file B, which reuses A's inode
* Client #2 sends request to server
* Client #1 sends request to server
* Processing client #2's request creates a mismatch warning for
file A/B.
* Processing client #1's request creates a mismatch warning too.
Note that this can happen even if Client #2 sends its request later,
as there's no intrinsic guarantee of the order in which requests
are processed; any SINGLE client is presumably executing operations
in order, but multiple clients aren't.
Fixing this in rmdir, unlink, and rename.
|
|
Migrate the stable part of the wrapper code (not machine-generated)
out of makewrappers, to make it easier to maintain.
|
|
Corporate policy is that each module should have a copyright notice.
|
|
This is a first pass at handling password/group calls, allowing
the use of custom password/group files. In particular, when
chroot()ed to a particular directory, pseudo picks files in
that directory by default, to improve support for the typical
use case where pseudo uses chroot() only to jump into a virtual
target filesystem.
|
|
None of them seem to have been genuine problems, but it's prettier now,
and some were questionable.
|
|
* Improve makewrappers handling of function pointer arguments.
* Regenerate wrappers when makewrappers is touched.
* Move path resolution from pseudo_client_op into wrapper
functions.
* Eliminate dependency on PATH_MAX.
* Related cleanup, such as tracking CWD better, and using
the tracked value for getcwd().
|
|
|