Compare commits
10 Commits
v4.25
...
ldv/loopin
Author | SHA1 | Date | |
---|---|---|---|
a3740c54c2 | |||
c528d41d26 | |||
04bda223d9 | |||
f9e5f12b7c | |||
2649c8c8b6 | |||
e2d2dc699f | |||
846e277d0f | |||
e471c53d1d | |||
5f7f0b6c85 | |||
4c9516cc9b |
1
.gitignore
vendored
1
.gitignore
vendored
@ -25,6 +25,7 @@
|
||||
/configure
|
||||
/depcomp
|
||||
/gnu
|
||||
/INSTALL
|
||||
/install-sh
|
||||
/ioctl_iocdef.[ih]
|
||||
/ioctl_redefs[12].h
|
||||
|
@ -5,5 +5,5 @@ that are needed to build strace. Some of these files are generated by tools
|
||||
from the GNU Autoconf and GNU Automake packages.
|
||||
|
||||
Note: rather than running `autoreconf` directly, please invoke `./bootstrap`
|
||||
script and follow the instructions given in [INSTALL](INSTALL) file for further
|
||||
script and follow the instructions given in [INSTALL](README-configure) file for further
|
||||
building and installation.
|
||||
|
@ -185,6 +185,7 @@ strace_SOURCES = \
|
||||
linux/asm_stat.h \
|
||||
linux/x32/asm_stat.h \
|
||||
linux/x86_64/asm_stat.h \
|
||||
list.h \
|
||||
listen.c \
|
||||
lookup_dcookie.c \
|
||||
loop.c \
|
||||
@ -267,6 +268,7 @@ strace_SOURCES = \
|
||||
ptp.c \
|
||||
ptrace.h \
|
||||
quota.c \
|
||||
random_ioctl.c \
|
||||
readahead.c \
|
||||
readlink.c \
|
||||
reboot.c \
|
||||
@ -402,6 +404,7 @@ EXTRA_DIST = \
|
||||
CREDITS \
|
||||
ChangeLog \
|
||||
ChangeLog-CVS \
|
||||
README-configure \
|
||||
README-linux-ptrace \
|
||||
debian/changelog \
|
||||
debian/compat \
|
||||
|
3
NEWS
3
NEWS
@ -1,3 +1,6 @@
|
||||
Noteworthy changes in release ?.?? (????-??-??)
|
||||
===============================================
|
||||
|
||||
Noteworthy changes in release 4.25 (2018-10-30)
|
||||
===============================================
|
||||
|
||||
|
@ -15,10 +15,10 @@ Basic Installation
|
||||
Briefly, the shell command './configure && make && make install' should
|
||||
configure, build, and install this package. The following more-detailed
|
||||
instructions are generic; see the 'README' file for instructions
|
||||
specific to this package. Some packages provide this 'INSTALL' file but
|
||||
do not implement all of the features documented below. The lack of an
|
||||
optional feature in a given package is not necessarily a bug. More
|
||||
recommendations for GNU packages can be found in *note Makefile
|
||||
specific to this package. Some packages provide this 'README-configure'
|
||||
file but do not implement all of the features documented below. The
|
||||
lack of an optional feature in a given package is not necessarily a bug.
|
||||
More recommendations for GNU packages can be found in *note Makefile
|
||||
Conventions: (standards)Makefile Conventions.
|
||||
|
||||
The 'configure' shell script attempts to guess correct values for
|
@ -9,6 +9,8 @@ See the file [NEWS](NEWS) for information on what has changed in recent versions
|
||||
|
||||
Please read the file [INSTALL-git](INSTALL-git.md) for installation instructions.
|
||||
|
||||
Please take a look at [the guide for new contributors](https://strace.io/wiki/NewContributorGuide) if you want to get involved in strace development.
|
||||
|
||||
The user discussion and development of strace take place on [the strace mailing list](https://lists.strace.io/mailman/listinfo/strace-devel) -- everyone is welcome to post bug reports, feature requests, comments and patches to strace-devel@lists.strace.io. The mailing list archives are available at https://lists.strace.io/pipermail/strace-devel/ and other archival sites.
|
||||
|
||||
The GIT repository of strace is available at [GitHub](https://github.com/strace/strace/) and [GitLab](https://gitlab.com/strace/strace/).
|
||||
|
@ -26,7 +26,7 @@ for m in m32 mx32; do
|
||||
done
|
||||
done
|
||||
|
||||
for f in README; do
|
||||
for f in README INSTALL; do
|
||||
cp "dist/$f" .
|
||||
done
|
||||
|
||||
|
6
debian/changelog.in
vendored
6
debian/changelog.in
vendored
@ -4,6 +4,12 @@ strace (@PACKAGE_VERSION@-1) experimental; urgency=low
|
||||
|
||||
-- Strace <@PACKAGE_BUGREPORT@> @DEB_CHANGELOGTIME@
|
||||
|
||||
strace (4.25-1) unstable; urgency=medium
|
||||
|
||||
* New upstream version.
|
||||
|
||||
-- Dmitry V. Levin <ldv@altlinux.org> Tue, 30 Oct 2018 08:09:10 +0000
|
||||
|
||||
strace (4.24-1) unstable; urgency=medium
|
||||
|
||||
* New upstream version.
|
||||
|
11
defs.h
11
defs.h
@ -57,6 +57,7 @@
|
||||
#include "error_prints.h"
|
||||
#include "gcc_compat.h"
|
||||
#include "kernel_types.h"
|
||||
#include "list.h"
|
||||
#include "macros.h"
|
||||
#include "mpers_type.h"
|
||||
#include "string_to_uint.h"
|
||||
@ -236,6 +237,15 @@ struct tcb {
|
||||
|
||||
struct mmap_cache_t *mmap_cache;
|
||||
|
||||
/*
|
||||
* Data that is stored during process wait traversal.
|
||||
* We use indices as the actual data is stored in an array
|
||||
* that is realloc'ed in runtime.
|
||||
*/
|
||||
size_t wait_data_idx;
|
||||
struct list_item wait_list;
|
||||
|
||||
|
||||
#ifdef HAVE_LINUX_KVM_H
|
||||
struct vcpu_info *vcpu_info_list;
|
||||
#endif
|
||||
@ -973,6 +983,7 @@ DECL_IOCTL(kvm);
|
||||
DECL_IOCTL(nbd);
|
||||
DECL_IOCTL(nsfs);
|
||||
DECL_IOCTL(ptp);
|
||||
DECL_IOCTL(random);
|
||||
DECL_IOCTL(scsi);
|
||||
DECL_IOCTL(term);
|
||||
DECL_IOCTL(ubi);
|
||||
|
134
dist/INSTALL
vendored
Normal file
134
dist/INSTALL
vendored
Normal file
@ -0,0 +1,134 @@
|
||||
0. BUILD REQUIREMENTS
|
||||
|
||||
- Sane POSIX shell.
|
||||
- gcc-like compiler that supports C99 and some GNU extensions (namely, empty
|
||||
structures, empty definitions, zero length arrays, ranged designated
|
||||
initialisers).
|
||||
- libc. GNU libc and musl are supported.
|
||||
- Linux UAPI headers.
|
||||
- GNU Make.
|
||||
- GNU coreutils.
|
||||
- For running test suite: gawk, grep, sed, runtime environment for all
|
||||
personalities.
|
||||
- Requirements for optional features are documented in their description.
|
||||
|
||||
1. CONFIGURATION AND OPTIONAL FEATURES
|
||||
|
||||
Configuration is done using GNU Autoconf-generated configure script.
|
||||
Please refer to the README-configure file for generic information regarding
|
||||
configure usage.
|
||||
|
||||
In addition to standard configure options, strace's configure file provides
|
||||
the following options:
|
||||
|
||||
1.1. Additional build and testing hardening
|
||||
|
||||
--enable-gcc-Werror turn on gcc's -Werror option
|
||||
--enable-code-coverage Whether to enable code coverage support
|
||||
--with-gcov=GCOV use given GCOV for coverage (GCOV=gcov).
|
||||
--enable-valgrind Whether to enable Valgrind on the unit tests
|
||||
--disable-valgrind-memcheck
|
||||
Whether to skip memcheck during the Valgrind tests
|
||||
--disable-valgrind-helgrind
|
||||
Whether to skip helgrind during the Valgrind tests
|
||||
--disable-valgrind-drd Whether to skip drd during the Valgrind tests
|
||||
--enable-valgrind-sgcheck
|
||||
Whether to use sgcheck during the Valgrind tests
|
||||
|
||||
1.2. Optional features
|
||||
|
||||
1.2.1. Multiple personalities support
|
||||
|
||||
--enable-mpers=yes|no|check|m32|mx32
|
||||
whether to enable multiple personalities support
|
||||
required for proper decoding of structures used by
|
||||
tracees with personalities that differ from the
|
||||
personality of strace, default is yes.
|
||||
|
||||
Personality is a way system call is performed (in terms of ABI). For example,
|
||||
Linux kernel on multiple 64-bit architectures that evolve from their 32-bit
|
||||
counterparts have support for running 32-bit binaries with 32-bit system call
|
||||
ABI, and that system call ABI constitutes a separate personality in strace's
|
||||
terms. Another example is 32-on-64 bit ABI; while exploiting the same way for
|
||||
performing system calls as native 64-bit system calls, this ABI has different
|
||||
type sizes and, as a result, also constitutes a separate personality; the only
|
||||
such ABI that is currently supported by strace is x32 on x86_64. This is
|
||||
important as different ABIs use different alignments and type sizes, as a
|
||||
result, fields in structures in unions have different offsets on different
|
||||
ABIs. In order to be able to correctly parse all the structures used in various
|
||||
system calls and ioctl commands, strace compiles these structure definitions
|
||||
for these different ABI and then parses DWARF of these compiled definitions in
|
||||
order to generate proper structure definitions that compiled with decoder code.
|
||||
Taking the aforementioned into account, there are the following requirements:
|
||||
|
||||
- gawk (at least version 3)
|
||||
- Ability to compile for m32 personality (on architectures where it is supported)
|
||||
- On x86_64, x32, powerpc64, sparc64, riscv64, tile64: gcc -m32
|
||||
- s390x: gcc -m31
|
||||
- AArch64: a separate compiler for armv7 EABI
|
||||
- See information about configuration in "1.3.2. AArch64: AArch32 support"
|
||||
- Ability to compile for mx32 personality (on architectures where it is supported)
|
||||
- On x86_64: gcc -mx32
|
||||
- For tests: runtime support (linker, libc, and loader)
|
||||
|
||||
1.2.2. Stack unwinding (-k option)
|
||||
|
||||
--with-libunwind use libunwind to implement stack tracing support
|
||||
--with-libiberty use libiberty to demangle symbols in stack trace
|
||||
|
||||
1.3. Architecture-specific features
|
||||
|
||||
1.3.1. ARMv7: OABI support
|
||||
|
||||
--enable-arm-oabi enable OABI support on ARM EABI
|
||||
|
||||
1.3.2. AArch64: AArch32 support
|
||||
|
||||
CC_FOR_M32
|
||||
CPP_FOR_M32
|
||||
CFLAGS_FOR_M32
|
||||
CPPFLAGS_FOR_M32
|
||||
|
||||
1.4. Miscellanea
|
||||
|
||||
1.4.1. Static build configuration
|
||||
|
||||
For static linking, provide LDFLAGS='-static -pthread'.
|
||||
|
||||
1.4.2. Cross-compilation configuration
|
||||
|
||||
2. BUILDING
|
||||
|
||||
make
|
||||
make V=1
|
||||
|
||||
3. TESTING
|
||||
|
||||
make check
|
||||
|
||||
TESTS='list of tests'
|
||||
VALGRIND_FLAGS
|
||||
TIMEOUT_DURATION
|
||||
|
||||
BTRFS_MOUNTPOINT
|
||||
|
||||
4. ADDITIONAL TARGETS
|
||||
|
||||
make code-coverage-capture
|
||||
make code-coverage-capture CODE_COVERAGE_BRANCH_COVERAGE=
|
||||
|
||||
5. INSTALLATION
|
||||
|
||||
make install
|
||||
|
||||
6. PACKAGING
|
||||
|
||||
6.1. Distribution tarball
|
||||
|
||||
./make-dist
|
||||
|
||||
Requires git
|
||||
|
||||
6.2. dpkg package
|
||||
|
||||
6.3. RPM package
|
8
dist/README
vendored
8
dist/README
vendored
@ -10,13 +10,21 @@ of Paul Kranenburg; see the file COPYING for details.
|
||||
See the file CREDITS for a list of authors and other contributors.
|
||||
See the file INSTALL for compilation and installation instructions.
|
||||
See the file NEWS for information on what has changed in recent versions.
|
||||
See the file README-hacking for information related to strace development.
|
||||
|
||||
The project's homepage is at
|
||||
https://strace.io
|
||||
|
||||
The GIT repository of strace is available at
|
||||
https://github.com/strace/strace/ and https://gitlab.com/strace/strace/
|
||||
|
||||
strace has a mailing list:
|
||||
strace-devel@lists.strace.io
|
||||
|
||||
Everyone is welcome to post bug reports, feature requests, comments
|
||||
and patches to the list. The mailing list archives are available at
|
||||
https://lists.strace.io/pipermail/strace-devel/
|
||||
|
||||
System requirements:
|
||||
* Linux kernel >= 2.6.18 is recommended. Older versions might still work
|
||||
but they haven't been thoroughly tested with this release.
|
||||
|
2
ioctl.c
2
ioctl.c
@ -329,6 +329,8 @@ ioctl_decode(struct tcb *tcp)
|
||||
return inotify_ioctl(tcp, code, arg);
|
||||
case 0xab:
|
||||
return nbd_ioctl(tcp, code, arg);
|
||||
case 'R':
|
||||
return random_ioctl(tcp, code, arg);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
137
list.h
Normal file
137
list.h
Normal file
@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Some simple implementation of a list similar to one used in the kernel.
|
||||
*
|
||||
* Copyright (c) 2016-2018 The strace developers.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef STRACE_LIST_H
|
||||
#define STRACE_LIST_H
|
||||
|
||||
#include "macros.h"
|
||||
|
||||
struct list_item {
|
||||
struct list_item *prev;
|
||||
struct list_item *next;
|
||||
};
|
||||
|
||||
#define EMPTY_LIST(l_) struct list_item l_ = { &l_, &l_ }
|
||||
|
||||
static inline void
|
||||
list_init(struct list_item *l)
|
||||
{
|
||||
l->prev = l;
|
||||
l->next = l;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
list_is_empty(struct list_item *l)
|
||||
{
|
||||
return (l->next == l) && (l->prev == l);
|
||||
}
|
||||
|
||||
#define list_elem(var, type, field) containerof((var), type, field)
|
||||
|
||||
#define list_head(head, type, field) \
|
||||
(list_is_empty(head) ? NULL : list_elem((head)->next, type, field))
|
||||
#define list_tail(head, type, field) \
|
||||
(list_is_empty(head) ? NULL : list_elem((head)->prev, type, field))
|
||||
|
||||
#define list_next(val, field) \
|
||||
list_elem((val)->field.next, typeof(*(val)), field)
|
||||
#define list_prev(val, field) \
|
||||
list_elem((val)->field.prev, typeof(*(val)), field)
|
||||
|
||||
static inline void
|
||||
list_insert(struct list_item *head, struct list_item *item)
|
||||
{
|
||||
item->next = head->next;
|
||||
item->prev = head;
|
||||
head->next->prev = item;
|
||||
head->next = item;
|
||||
}
|
||||
|
||||
static inline void
|
||||
list_append(struct list_item *head, struct list_item *item)
|
||||
{
|
||||
item->next = head;
|
||||
item->prev = head->prev;
|
||||
head->prev->next = item;
|
||||
head->prev = item;
|
||||
}
|
||||
|
||||
static inline void
|
||||
list_remove(struct list_item *item)
|
||||
{
|
||||
if (!item->next || !item->prev)
|
||||
return;
|
||||
|
||||
item->prev->next = item->next;
|
||||
item->next->prev = item->prev;
|
||||
item->next = item->prev = NULL;
|
||||
}
|
||||
|
||||
static inline struct list_item *
|
||||
list_remove_tail(struct list_item *head)
|
||||
{
|
||||
struct list_item *t = list_is_empty(head) ? NULL : head->prev;
|
||||
|
||||
if (t)
|
||||
list_remove(t);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
static inline struct list_item *
|
||||
list_remove_head(struct list_item *head)
|
||||
{
|
||||
struct list_item *h = list_is_empty(head) ? NULL : head->next;
|
||||
|
||||
if (h)
|
||||
list_remove(h);
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
static inline void
|
||||
list_replace(struct list_item *old, struct list_item *new)
|
||||
{
|
||||
new->next = old->next;
|
||||
new->prev = old->prev;
|
||||
old->prev->next = new;
|
||||
old->next->prev = new;
|
||||
old->next = old->prev = NULL;
|
||||
}
|
||||
|
||||
#define list_foreach(var_, head_, field_) \
|
||||
for (var_ = list_elem((head_)->next, typeof(*var_), field_); \
|
||||
&(var_->field_) != (head_); var_ = list_next(var_, field_))
|
||||
|
||||
#define list_foreach_safe(var_, head_, field_, _tmp) \
|
||||
for (var_ = list_elem((head_)->next, typeof(*var_), field_), \
|
||||
_tmp = list_elem((var_)->field_.next, typeof(*var_), field_); \
|
||||
&var_->field_ != head_; var_ = _tmp, _tmp = list_next(_tmp, field_))
|
||||
|
||||
#endif /* !STRACE_LIST_H */
|
9
macros.h
9
macros.h
@ -57,6 +57,15 @@
|
||||
(offsetof(type_, member_) + sizeof(((type_ *)0)->member_))
|
||||
#endif
|
||||
|
||||
#ifndef cast_ptr
|
||||
# define cast_ptr(type, var) ((type) (uintptr_t) (const volatile void *) (var))
|
||||
#endif
|
||||
|
||||
#ifndef containerof
|
||||
# define containerof(x, s, m) \
|
||||
cast_ptr(s *, (const volatile char *) (x) - offsetof(s, m))
|
||||
#endif
|
||||
|
||||
static inline bool
|
||||
is_filled(const char *ptr, char fill, size_t size)
|
||||
{
|
||||
|
@ -1,5 +1,5 @@
|
||||
@c This file is imported from GNU Autoconf and edited to produce
|
||||
@c the INSTALL file.
|
||||
@c the README-configure file.
|
||||
|
||||
@ifclear autoconf
|
||||
|
||||
@ -24,8 +24,8 @@ should configure, build, and install this package. The following
|
||||
more-detailed instructions are generic; see the @file{README} file for
|
||||
instructions specific to this package.
|
||||
@ifclear autoconf
|
||||
Some packages provide this @file{INSTALL} file but do not implement all
|
||||
of the features documented below. The lack of an optional feature in a
|
||||
Some packages provide this @file{README-configure} file but do not implement
|
||||
all of the features documented below. The lack of an optional feature in a
|
||||
given package is not necessarily a bug.
|
||||
@end ifclear
|
||||
More recommendations for GNU packages can be found in
|
||||
|
81
random_ioctl.c
Normal file
81
random_ioctl.c
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (c) 2018 The strace developers.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "defs.h"
|
||||
#include "print_fields.h"
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/random.h>
|
||||
|
||||
#define XLAT_MACROS_ONLY
|
||||
# include "xlat/random_ioctl_cmds.h"
|
||||
#undef XLAT_MACROS_ONLY
|
||||
|
||||
/*
|
||||
* RNDGETPOOL was removed in 2.6.9, so non-ancient kernels always
|
||||
* return -EINVAL for that.
|
||||
*/
|
||||
|
||||
int
|
||||
random_ioctl(struct tcb *const tcp, const unsigned int code,
|
||||
const kernel_ulong_t arg)
|
||||
{
|
||||
struct rand_pool_info info;
|
||||
kernel_ulong_t buf;
|
||||
|
||||
switch (code) {
|
||||
case RNDGETENTCNT:
|
||||
if (entering(tcp))
|
||||
return 0;
|
||||
ATTRIBUTE_FALLTHROUGH;
|
||||
case RNDADDTOENTCNT:
|
||||
tprints(", ");
|
||||
printnum_int(tcp, arg, "%d");
|
||||
break;
|
||||
|
||||
case RNDADDENTROPY:
|
||||
tprints(", ");
|
||||
if (!umove_or_printaddr(tcp, arg, &info)) {
|
||||
PRINT_FIELD_D("{", info, entropy_count);
|
||||
PRINT_FIELD_D(", ", info, buf_size);
|
||||
tprints(", buf=");
|
||||
buf = arg + offsetof(struct rand_pool_info, buf);
|
||||
printstrn(tcp, buf, info.buf_size);
|
||||
tprints("}");
|
||||
}
|
||||
break;
|
||||
|
||||
/* ioctls with no parameters */
|
||||
case RNDZAPENTCNT:
|
||||
case RNDCLEARPOOL:
|
||||
case RNDRESEEDCRNG:
|
||||
break;
|
||||
default:
|
||||
return RVAL_DECODED;
|
||||
}
|
||||
return RVAL_IOCTL_DECODED;
|
||||
}
|
335
strace.c
335
strace.c
@ -161,10 +161,17 @@ static struct tcb *current_tcp;
|
||||
struct tcb_wait_data {
|
||||
enum trace_event te; /**< Event passed to dispatch_event() */
|
||||
int status; /**< status, returned by wait4() */
|
||||
unsigned long msg; /**< Value returned by PTRACE_GETEVENTMSG */
|
||||
siginfo_t si; /**< siginfo, returned by PTRACE_GETSIGINFO */
|
||||
};
|
||||
|
||||
static struct tcb **tcbtab;
|
||||
/*
|
||||
* Since the queueing of tracees stops as soon as wait4() returns EAGAIN,
|
||||
* or at least two events for a single tracee, tab_wait_tab size shouldn't
|
||||
* exceed tcbtabsize + 1.
|
||||
*/
|
||||
static struct tcb_wait_data *tcb_wait_tab;
|
||||
static unsigned int nprocs;
|
||||
static size_t tcbtabsize;
|
||||
|
||||
@ -750,6 +757,9 @@ expand_tcbtab(void)
|
||||
for (tcb_ptr = tcbtab + old_tcbtabsize;
|
||||
tcb_ptr < tcbtab + tcbtabsize; tcb_ptr++, newtcbs++)
|
||||
*tcb_ptr = newtcbs;
|
||||
|
||||
tcb_wait_tab = xreallocarray(tcb_wait_tab, sizeof(*tcb_wait_tab),
|
||||
tcbtabsize + 1);
|
||||
}
|
||||
|
||||
static struct tcb *
|
||||
@ -853,6 +863,8 @@ droptcb(struct tcb *tcp)
|
||||
if (printing_tcp == tcp)
|
||||
printing_tcp = NULL;
|
||||
|
||||
list_remove(&tcp->wait_list);
|
||||
|
||||
memset(tcp, 0, sizeof(*tcp));
|
||||
}
|
||||
|
||||
@ -2071,10 +2083,8 @@ maybe_switch_tcbs(struct tcb *tcp, const int pid)
|
||||
{
|
||||
FILE *fp;
|
||||
struct tcb *execve_thread;
|
||||
long old_pid = 0;
|
||||
long old_pid = tcb_wait_tab[tcp->wait_data_idx].msg;
|
||||
|
||||
if (ptrace(PTRACE_GETEVENTMSG, pid, NULL, &old_pid) < 0)
|
||||
return tcp;
|
||||
/* Avoid truncation in pid2tcb() param passing */
|
||||
if (old_pid <= 0 || old_pid == pid)
|
||||
return tcp;
|
||||
@ -2240,17 +2250,27 @@ print_event_exit(struct tcb *tcp)
|
||||
static const struct tcb_wait_data *
|
||||
next_event(void)
|
||||
{
|
||||
static struct tcb_wait_data wait_data;
|
||||
|
||||
int pid;
|
||||
int status;
|
||||
struct tcb *tcp;
|
||||
struct tcb_wait_data *wd = &wait_data;
|
||||
struct rusage ru;
|
||||
|
||||
if (interrupted)
|
||||
return NULL;
|
||||
|
||||
struct tcb *tcp = NULL;
|
||||
struct list_item *elem;
|
||||
|
||||
static EMPTY_LIST(pending_tcps);
|
||||
if (!list_is_empty(&pending_tcps))
|
||||
goto next_event_get_tcp;
|
||||
|
||||
static struct tcb *extra_tcp;
|
||||
static size_t wait_extra_data_idx;
|
||||
if (extra_tcp) {
|
||||
tcp = extra_tcp;
|
||||
extra_tcp = NULL;
|
||||
tcp->wait_data_idx = wait_extra_data_idx;
|
||||
|
||||
debug_msg("dequeued extra event for pid %u", tcp->pid);
|
||||
goto next_event_exit;
|
||||
}
|
||||
|
||||
/*
|
||||
* Used to exit simply when nprocs hits zero, but in this testcase:
|
||||
* int main(void) { _exit(!!fork()); }
|
||||
@ -2292,8 +2312,10 @@ next_event(void)
|
||||
* then the system call will be interrupted and
|
||||
* the expiration will be handled by the signal handler.
|
||||
*/
|
||||
pid = wait4(-1, &status, __WALL, (cflag ? &ru : NULL));
|
||||
const int wait_errno = errno;
|
||||
int status;
|
||||
struct rusage ru;
|
||||
int pid = wait4(-1, &status, __WALL, (cflag ? &ru : NULL));
|
||||
int wait_errno = errno;
|
||||
|
||||
/*
|
||||
* The window of opportunity to handle expirations
|
||||
@ -2309,135 +2331,194 @@ next_event(void)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (pid < 0) {
|
||||
if (wait_errno == EINTR) {
|
||||
wd->te = TE_NEXT;
|
||||
return wd;
|
||||
size_t wait_tab_pos = 0;
|
||||
bool wait_nohang = false;
|
||||
|
||||
for (;;) {
|
||||
struct tcb_wait_data *wd;
|
||||
|
||||
if (pid < 0) {
|
||||
if (wait_errno == EINTR)
|
||||
break;
|
||||
if (wait_nohang)
|
||||
break;
|
||||
if (nprocs == 0 && wait_errno == ECHILD)
|
||||
return NULL;
|
||||
/*
|
||||
* If nprocs > 0, ECHILD is not expected,
|
||||
* treat it as any other error here:
|
||||
*/
|
||||
errno = wait_errno;
|
||||
perror_msg_and_die("wait4(__WALL)");
|
||||
}
|
||||
if (nprocs == 0 && wait_errno == ECHILD)
|
||||
return NULL;
|
||||
/*
|
||||
* If nprocs > 0, ECHILD is not expected,
|
||||
* treat it as any other error here:
|
||||
*/
|
||||
errno = wait_errno;
|
||||
perror_msg_and_die("wait4(__WALL)");
|
||||
}
|
||||
|
||||
wd->status = status;
|
||||
if (!pid)
|
||||
break;
|
||||
|
||||
if (pid == popen_pid) {
|
||||
if (!WIFSTOPPED(status))
|
||||
popen_pid = 0;
|
||||
wd->te = TE_NEXT;
|
||||
return wd;
|
||||
}
|
||||
if (pid == popen_pid) {
|
||||
if (!WIFSTOPPED(status))
|
||||
popen_pid = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (debug_flag)
|
||||
print_debug_info(pid, status);
|
||||
if (debug_flag)
|
||||
print_debug_info(pid, status);
|
||||
|
||||
/* Look up 'pid' in our table. */
|
||||
tcp = pid2tcb(pid);
|
||||
/* Look up 'pid' in our table. */
|
||||
tcp = pid2tcb(pid);
|
||||
|
||||
if (!tcp) {
|
||||
tcp = maybe_allocate_tcb(pid, status);
|
||||
if (!tcp) {
|
||||
wd->te = TE_NEXT;
|
||||
return wd;
|
||||
tcp = maybe_allocate_tcb(pid, status);
|
||||
if (!tcp)
|
||||
break;
|
||||
}
|
||||
|
||||
if (cflag) {
|
||||
struct timespec stime = {
|
||||
.tv_sec = ru.ru_stime.tv_sec,
|
||||
.tv_nsec = ru.ru_stime.tv_usec * 1000
|
||||
};
|
||||
ts_sub(&tcp->dtime, &stime, &tcp->stime);
|
||||
tcp->stime = stime;
|
||||
}
|
||||
|
||||
if (wait_tab_pos > tcbtabsize)
|
||||
error_func_msg_and_die("Wait data storage overflow "
|
||||
"(wait_tab_pos %zu, nprocs %u, "
|
||||
"tcbtabsize %zu)", wait_tab_pos,
|
||||
nprocs, tcbtabsize);
|
||||
|
||||
wd = tcb_wait_tab + wait_tab_pos;
|
||||
memset(wd, 0, sizeof(*wd));
|
||||
|
||||
if (WIFSIGNALED(status)) {
|
||||
wd->te = TE_SIGNALLED;
|
||||
} else if (WIFEXITED(status)) {
|
||||
wd->te = TE_EXITED;
|
||||
} else {
|
||||
/*
|
||||
* As WCONTINUED flag has not been specified to wait4,
|
||||
* it cannot be WIFCONTINUED(status), so the only case
|
||||
* that remains is WIFSTOPPED(status).
|
||||
*/
|
||||
|
||||
const unsigned int sig = WSTOPSIG(status);
|
||||
const unsigned int event = (unsigned int) status >> 16;
|
||||
|
||||
switch (event) {
|
||||
case 0:
|
||||
/*
|
||||
* Is this post-attach SIGSTOP?
|
||||
* Interestingly, the process may stop
|
||||
* with STOPSIG equal to some other signal
|
||||
* than SIGSTOP if we happened to attach
|
||||
* just before the process takes a signal.
|
||||
*/
|
||||
if (sig == SIGSTOP &&
|
||||
(tcp->flags & TCB_IGNORE_ONE_SIGSTOP)) {
|
||||
debug_func_msg("ignored SIGSTOP on "
|
||||
"pid %d", tcp->pid);
|
||||
tcp->flags &= ~TCB_IGNORE_ONE_SIGSTOP;
|
||||
wd->te = TE_RESTART;
|
||||
} else if (sig == syscall_trap_sig) {
|
||||
wd->te = TE_SYSCALL_STOP;
|
||||
} else {
|
||||
/*
|
||||
* True if tracee is stopped by signal
|
||||
* (as opposed to "tracee received
|
||||
* signal").
|
||||
* TODO: shouldn't we check for
|
||||
* errno == EINVAL too?
|
||||
* We can get ESRCH instead, you know...
|
||||
*/
|
||||
bool stopped = ptrace(PTRACE_GETSIGINFO,
|
||||
pid, 0, &wd->si) < 0;
|
||||
|
||||
wd->te = stopped ? TE_GROUP_STOP
|
||||
: TE_SIGNAL_DELIVERY_STOP;
|
||||
}
|
||||
break;
|
||||
case PTRACE_EVENT_STOP:
|
||||
/*
|
||||
* PTRACE_INTERRUPT-stop or group-stop.
|
||||
* PTRACE_INTERRUPT-stop has sig == SIGTRAP here.
|
||||
*/
|
||||
switch (sig) {
|
||||
case SIGSTOP:
|
||||
case SIGTSTP:
|
||||
case SIGTTIN:
|
||||
case SIGTTOU:
|
||||
wd->te = TE_GROUP_STOP;
|
||||
break;
|
||||
default:
|
||||
wd->te = TE_RESTART;
|
||||
}
|
||||
break;
|
||||
case PTRACE_EVENT_EXEC:
|
||||
/*
|
||||
* TODO: shouldn't we check for
|
||||
* errno == EINVAL here, too?
|
||||
* We can get ESRCH instead, you know...
|
||||
*/
|
||||
if (ptrace(PTRACE_GETEVENTMSG, pid, NULL,
|
||||
&wd->msg) < 0)
|
||||
wd->msg = 0;
|
||||
|
||||
wd->te = TE_STOP_BEFORE_EXECVE;
|
||||
break;
|
||||
case PTRACE_EVENT_EXIT:
|
||||
wd->te = TE_STOP_BEFORE_EXIT;
|
||||
break;
|
||||
default:
|
||||
wd->te = TE_RESTART;
|
||||
}
|
||||
}
|
||||
|
||||
if (tcp->wait_list.next) {
|
||||
wait_extra_data_idx = wait_tab_pos;
|
||||
extra_tcp = tcp;
|
||||
debug_func_msg("queued extra pid %d", tcp->pid);
|
||||
} else {
|
||||
tcp->wait_data_idx = wait_tab_pos;
|
||||
list_append(&pending_tcps, &tcp->wait_list);
|
||||
debug_func_msg("queued pid %d", tcp->pid);
|
||||
}
|
||||
|
||||
wd->status = status;
|
||||
wait_tab_pos++;
|
||||
|
||||
if (extra_tcp)
|
||||
break;
|
||||
|
||||
pid = wait4(-1, &status, __WALL | WNOHANG, (cflag ? &ru : NULL));
|
||||
wait_errno = errno;
|
||||
wait_nohang = true;
|
||||
}
|
||||
|
||||
next_event_get_tcp:
|
||||
elem = list_remove_head(&pending_tcps);
|
||||
|
||||
if (!elem) {
|
||||
memset(tcb_wait_tab, 0, sizeof(*tcb_wait_tab));
|
||||
tcb_wait_tab->te = TE_NEXT;
|
||||
|
||||
return tcb_wait_tab;
|
||||
} else {
|
||||
tcp = list_elem(elem, struct tcb, wait_list);
|
||||
debug_func_msg("dequeued pid %d", tcp->pid);
|
||||
}
|
||||
|
||||
next_event_exit:
|
||||
/* Is this the very first time we see this tracee stopped? */
|
||||
if (tcp->flags & TCB_STARTUP)
|
||||
startup_tcb(tcp);
|
||||
|
||||
clear_regs(tcp);
|
||||
|
||||
/* Set current output file */
|
||||
set_current_tcp(tcp);
|
||||
|
||||
if (cflag) {
|
||||
struct timespec stime = {
|
||||
.tv_sec = ru.ru_stime.tv_sec,
|
||||
.tv_nsec = ru.ru_stime.tv_usec * 1000
|
||||
};
|
||||
ts_sub(&tcp->dtime, &stime, &tcp->stime);
|
||||
tcp->stime = stime;
|
||||
}
|
||||
|
||||
if (WIFSIGNALED(status)) {
|
||||
wd->te = TE_SIGNALLED;
|
||||
return wd;
|
||||
}
|
||||
|
||||
if (WIFEXITED(status)) {
|
||||
wd->te = TE_EXITED;
|
||||
return wd;
|
||||
}
|
||||
|
||||
/*
|
||||
* As WCONTINUED flag has not been specified to wait4,
|
||||
* it cannot be WIFCONTINUED(status), so the only case
|
||||
* that remains is WIFSTOPPED(status).
|
||||
*/
|
||||
|
||||
/* Is this the very first time we see this tracee stopped? */
|
||||
if (tcp->flags & TCB_STARTUP)
|
||||
startup_tcb(tcp);
|
||||
|
||||
const unsigned int sig = WSTOPSIG(status);
|
||||
const unsigned int event = (unsigned int) status >> 16;
|
||||
|
||||
switch (event) {
|
||||
case 0:
|
||||
/*
|
||||
* Is this post-attach SIGSTOP?
|
||||
* Interestingly, the process may stop
|
||||
* with STOPSIG equal to some other signal
|
||||
* than SIGSTOP if we happened to attach
|
||||
* just before the process takes a signal.
|
||||
*/
|
||||
if (sig == SIGSTOP && (tcp->flags & TCB_IGNORE_ONE_SIGSTOP)) {
|
||||
debug_func_msg("ignored SIGSTOP on pid %d", tcp->pid);
|
||||
tcp->flags &= ~TCB_IGNORE_ONE_SIGSTOP;
|
||||
wd->te = TE_RESTART;
|
||||
} else if (sig == syscall_trap_sig) {
|
||||
wd->te = TE_SYSCALL_STOP;
|
||||
} else {
|
||||
memset(&wd->si, 0, sizeof(wd->si));
|
||||
/*
|
||||
* True if tracee is stopped by signal
|
||||
* (as opposed to "tracee received signal").
|
||||
* TODO: shouldn't we check for errno == EINVAL too?
|
||||
* We can get ESRCH instead, you know...
|
||||
*/
|
||||
bool stopped = ptrace(PTRACE_GETSIGINFO, pid, 0, &wd->si) < 0;
|
||||
wd->te = stopped ? TE_GROUP_STOP : TE_SIGNAL_DELIVERY_STOP;
|
||||
}
|
||||
break;
|
||||
case PTRACE_EVENT_STOP:
|
||||
/*
|
||||
* PTRACE_INTERRUPT-stop or group-stop.
|
||||
* PTRACE_INTERRUPT-stop has sig == SIGTRAP here.
|
||||
*/
|
||||
switch (sig) {
|
||||
case SIGSTOP:
|
||||
case SIGTSTP:
|
||||
case SIGTTIN:
|
||||
case SIGTTOU:
|
||||
wd->te = TE_GROUP_STOP;
|
||||
break;
|
||||
default:
|
||||
wd->te = TE_RESTART;
|
||||
}
|
||||
break;
|
||||
case PTRACE_EVENT_EXEC:
|
||||
wd->te = TE_STOP_BEFORE_EXECVE;
|
||||
break;
|
||||
case PTRACE_EVENT_EXIT:
|
||||
wd->te = TE_STOP_BEFORE_EXIT;
|
||||
break;
|
||||
default:
|
||||
wd->te = TE_RESTART;
|
||||
}
|
||||
|
||||
return wd;
|
||||
return tcb_wait_tab + tcp->wait_data_idx;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -91,6 +91,9 @@ echo 'END OF TEST SUITE INFORMATION'
|
||||
* @RPM_CHANGELOGTIME@ @PACKAGE_BUGREPORT@ - @PACKAGE_VERSION@-1
|
||||
- @PACKAGE_STRING@ snapshot.
|
||||
|
||||
* Tue Oct 30 2018 Dmitry V. Levin <ldv@altlinux.org> - 4.25-1
|
||||
- v4.24 -> v4.25.
|
||||
|
||||
* Tue Aug 14 2018 Dmitry V. Levin <ldv@altlinux.org> - 4.24-1
|
||||
- v4.23 -> v4.24.
|
||||
|
||||
|
1
test/.gitignore
vendored
1
test/.gitignore
vendored
@ -1,7 +1,6 @@
|
||||
childthread
|
||||
clone
|
||||
leaderkill
|
||||
many_looping_threads
|
||||
mmap_offset_decode
|
||||
mtd
|
||||
seccomp
|
||||
|
@ -3,8 +3,7 @@ CFLAGS += -Wall
|
||||
PROGS = \
|
||||
sig skodic clone leaderkill childthread \
|
||||
sigkill_rain wait_must_be_interruptible threaded_execve \
|
||||
mtd ubi seccomp sfd mmap_offset_decode x32_lseek x32_mmap \
|
||||
many_looping_threads
|
||||
mtd ubi seccomp sfd mmap_offset_decode x32_lseek x32_mmap
|
||||
|
||||
all: $(PROGS)
|
||||
|
||||
@ -12,8 +11,6 @@ leaderkill: LDFLAGS += -pthread
|
||||
|
||||
childthread: LDFLAGS += -pthread
|
||||
|
||||
many_looping_threads: LDFLAGS += -pthread
|
||||
|
||||
clean distclean:
|
||||
rm -f *.o core $(PROGS) *.gdb
|
||||
|
||||
|
@ -1,49 +0,0 @@
|
||||
// This testcase, when run with large number of threads
|
||||
// under stace -f, may never finish because strace does not
|
||||
// ensure any fairness in thread scheduling:
|
||||
// it restarts threads as they stop. If daughter threads crowd out
|
||||
// the "mother" and _they_ get continually restarted by strace,
|
||||
// the end of spawning loop will never be reached.
|
||||
//
|
||||
// Also, it is a testcase which triggers the
|
||||
// "strace: Exit of unknown pid 32457 seen"
|
||||
// message when on testcase exit, strace sees deaths of newly-attached
|
||||
// threads _before_ their first syscall stop.
|
||||
//
|
||||
#include <stdio.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static int thd_no;
|
||||
|
||||
static void *sub_thd(void *c)
|
||||
{
|
||||
dprintf(1, "sub-thread %d created\n", ++thd_no);
|
||||
for (;;)
|
||||
getuid();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
pthread_t *thd;
|
||||
int num_threads = 1;
|
||||
|
||||
if (argv[1])
|
||||
num_threads = atoi(argv[1]);
|
||||
|
||||
thd = malloc(num_threads * sizeof(thd[0]));
|
||||
dprintf(1, "test start, num_threads:%d...\n", num_threads);
|
||||
|
||||
for (i = 0; i < num_threads; i++) {
|
||||
pthread_create(&thd[i], NULL, sub_thd, NULL);
|
||||
dprintf(1, "after pthread_create\n");
|
||||
}
|
||||
|
||||
/* Exit. This kills all threads */
|
||||
return 0;
|
||||
}
|
2
tests/.gitignore
vendored
2
tests/.gitignore
vendored
@ -158,6 +158,7 @@ ioctl_nsfs
|
||||
ioctl_perf
|
||||
ioctl_perf-success
|
||||
ioctl_ptp
|
||||
ioctl_random
|
||||
ioctl_rtc
|
||||
ioctl_rtc-v
|
||||
ioctl_scsi
|
||||
@ -209,6 +210,7 @@ list_sigaction_signum
|
||||
llseek
|
||||
localtime
|
||||
lookup_dcookie
|
||||
looping_threads
|
||||
lseek
|
||||
lstat
|
||||
lstat64
|
||||
|
@ -129,6 +129,7 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \
|
||||
ksysent \
|
||||
list_sigaction_signum \
|
||||
localtime \
|
||||
looping_threads \
|
||||
mmsg-silent \
|
||||
mmsg_name-v \
|
||||
msg_control-v \
|
||||
@ -192,6 +193,7 @@ fstat64_CPPFLAGS = $(AM_CPPFLAGS) -D_FILE_OFFSET_BITS=64
|
||||
fstatat64_CPPFLAGS = $(AM_CPPFLAGS) -D_FILE_OFFSET_BITS=64
|
||||
ftruncate64_CPPFLAGS = $(AM_CPPFLAGS) -D_FILE_OFFSET_BITS=64
|
||||
localtime_LDADD = $(clock_LIBS) $(LDADD)
|
||||
looping_threads_LDADD = -lpthread $(LDADD)
|
||||
lstat64_CPPFLAGS = $(AM_CPPFLAGS) -D_FILE_OFFSET_BITS=64
|
||||
mmap64_CPPFLAGS = $(AM_CPPFLAGS) -D_FILE_OFFSET_BITS=64
|
||||
mmap64_Xabbrev_CPPFLAGS = $(AM_CPPFLAGS) -D_FILE_OFFSET_BITS=64
|
||||
@ -325,6 +327,7 @@ MISC_TESTS = \
|
||||
interactive_block.test \
|
||||
ksysent.test \
|
||||
localtime.test \
|
||||
looping_threads.test \
|
||||
opipe.test \
|
||||
options-syntax.test \
|
||||
pc.test \
|
||||
|
@ -150,6 +150,7 @@ ioctl_nbd +ioctl.test -y
|
||||
ioctl_nsfs +ioctl.test -esignal=none
|
||||
ioctl_perf +ioctl.test
|
||||
ioctl_ptp +ioctl.test
|
||||
ioctl_random +ioctl.test
|
||||
ioctl_rtc +ioctl.test
|
||||
ioctl_rtc-v +ioctl.test -v
|
||||
ioctl_scsi +ioctl.test
|
||||
|
80
tests/ioctl_random.c
Normal file
80
tests/ioctl_random.c
Normal file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Check decoding of RND* commands of ioctl syscall.
|
||||
*
|
||||
* Copyright (c) 2018 The strace developers.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "tests.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/random.h>
|
||||
|
||||
#define XLAT_MACROS_ONLY
|
||||
# include "xlat/random_ioctl_cmds.h"
|
||||
#undef XLAT_MACROS_ONLY
|
||||
|
||||
#define RVAL_EBADF " = -1 EBADF (%m)\n"
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
union {
|
||||
char c[sizeof(struct rand_pool_info) + 8];
|
||||
struct rand_pool_info info;
|
||||
} u;
|
||||
struct rand_pool_info *info = &u.info;
|
||||
int cnt = 6;
|
||||
|
||||
memcpy(info->buf, "12345678", 8);
|
||||
info->buf_size = 8;
|
||||
info->entropy_count = 3;
|
||||
|
||||
ioctl(-1, RNDGETENTCNT, &cnt);
|
||||
printf("ioctl(-1, RNDGETENTCNT, %p)" RVAL_EBADF, &cnt);
|
||||
ioctl(-1, RNDADDTOENTCNT, &cnt);
|
||||
printf("ioctl(-1, RNDADDTOENTCNT, [6])" RVAL_EBADF);
|
||||
|
||||
ioctl(-1, RNDADDENTROPY, NULL);
|
||||
printf("ioctl(-1, RNDADDENTROPY, NULL)" RVAL_EBADF);
|
||||
ioctl(-1, RNDADDENTROPY, info);
|
||||
printf("ioctl(-1, RNDADDENTROPY, {entropy_count=3, buf_size=8, buf=\"12345678\"})" RVAL_EBADF);
|
||||
|
||||
ioctl(-1, RNDZAPENTCNT);
|
||||
printf("ioctl(-1, RNDZAPENTCNT)" RVAL_EBADF);
|
||||
ioctl(-1, RNDCLEARPOOL);
|
||||
printf("ioctl(-1, RNDCLEARPOOL)" RVAL_EBADF);
|
||||
ioctl(-1, RNDRESEEDCRNG);
|
||||
printf("ioctl(-1, RNDRESEEDCRNG)" RVAL_EBADF);
|
||||
|
||||
ioctl(-1, _IO('R', 0xff), NULL);
|
||||
printf("ioctl(-1, _IOC(_IOC_NONE, %#x, 0xff, 0), 0)" RVAL_EBADF, 'R');
|
||||
|
||||
puts("+++ exited with 0 +++");
|
||||
return 0;
|
||||
}
|
110
tests/looping_threads.c
Normal file
110
tests/looping_threads.c
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Check tracing of looping threads.
|
||||
*
|
||||
* Copyright (c) 2009-2018 The strace developers.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "tests.h"
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
static void *
|
||||
thread(void *arg)
|
||||
{
|
||||
for (;;)
|
||||
getuid();
|
||||
return arg;
|
||||
}
|
||||
|
||||
int
|
||||
main(int ac, const char *av[])
|
||||
{
|
||||
assert(ac == 3);
|
||||
|
||||
int timeout = atoi(av[1]);
|
||||
assert(timeout > 0);
|
||||
|
||||
int num_threads = atoi(av[2]);
|
||||
assert(num_threads > 0);
|
||||
|
||||
/* Create a new process group. */
|
||||
if (setpgid(0, 0))
|
||||
perror_msg_and_fail("setpgid");
|
||||
|
||||
/*
|
||||
* When the main process terminates, the process group becomes orphaned.
|
||||
* If any member of the orphaned process group is stopped, then
|
||||
* a SIGHUP signal followed by a SIGCONT signal is sent to each process
|
||||
* in the orphaned process group.
|
||||
* Create a process in a stopped state to activate this behaviour.
|
||||
*/
|
||||
pid_t stopped = fork();
|
||||
if (stopped < 0)
|
||||
perror_msg_and_fail("fork");
|
||||
if (!stopped) {
|
||||
raise(SIGSTOP);
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
const sigset_t set = {};
|
||||
const struct sigaction act = { .sa_handler = SIG_DFL };
|
||||
if (sigaction(SIGALRM, &act, NULL))
|
||||
perror_msg_and_fail("sigaction");
|
||||
if (sigprocmask(SIG_SETMASK, &set, NULL))
|
||||
perror_msg_and_fail("sigprocmask");
|
||||
alarm(timeout);
|
||||
|
||||
/*
|
||||
* Create all threads in a subprocess, this guarantees that
|
||||
* their tracer will not be their parent.
|
||||
*/
|
||||
pid_t pid = fork();
|
||||
if (pid < 0)
|
||||
perror_msg_and_fail("fork");
|
||||
if (!pid) {
|
||||
for (int i = 0; i < num_threads; i++) {
|
||||
pthread_t t;
|
||||
if ((errno = pthread_create(&t, NULL, thread, NULL)))
|
||||
perror_msg_and_fail("pthread_create #%d", i);
|
||||
}
|
||||
|
||||
/* This terminates all threads. */
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
int s;
|
||||
if (waitpid(pid, &s, 0) != pid)
|
||||
perror_msg_and_fail("waitpid");
|
||||
|
||||
assert(WIFEXITED(s));
|
||||
return WEXITSTATUS(s);
|
||||
}
|
37
tests/looping_threads.test
Executable file
37
tests/looping_threads.test
Executable file
@ -0,0 +1,37 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Check tracing of looping threads.
|
||||
#
|
||||
# Copyright (c) 2009-2018 The strace developers.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. The name of the author may not be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
. "${srcdir=.}/init.sh"
|
||||
|
||||
check_prog nproc
|
||||
timeout="$(($TIMEOUT_DURATION/10))"
|
||||
nproc="$((64+$timeout+$(nproc)))"
|
||||
|
||||
run_prog "../$NAME" "$timeout" "$nproc"
|
||||
run_strace -f -qq -enone -esignal=none $args
|
@ -121,6 +121,7 @@ ioctl_mtd
|
||||
ioctl_nbd
|
||||
ioctl_perf
|
||||
ioctl_ptp
|
||||
ioctl_random
|
||||
ioctl_rtc
|
||||
ioctl_scsi
|
||||
ioctl_sg_io_v3
|
||||
|
7
xlat/random_ioctl_cmds.in
Normal file
7
xlat/random_ioctl_cmds.in
Normal file
@ -0,0 +1,7 @@
|
||||
RNDGETENTCNT _IOR( 'R', 0x00, int )
|
||||
RNDADDTOENTCNT _IOW( 'R', 0x01, int )
|
||||
RNDGETPOOL _IOR( 'R', 0x02, int [2] )
|
||||
RNDADDENTROPY _IOW( 'R', 0x03, int [2] )
|
||||
RNDZAPENTCNT _IO( 'R', 0x04 )
|
||||
RNDCLEARPOOL _IO( 'R', 0x06 )
|
||||
RNDRESEEDCRNG _IO( 'R', 0x07 )
|
Reference in New Issue
Block a user