Compare commits

...

80 Commits
0.5.1 ... 0.8.2

Author SHA1 Message Date
Guillem Jover
2fb148a290 Release libbsd 0.8.2 2016-01-27 15:25:23 +01:00
Hanno Boeck
c8f0723d2b Fix heap buffer overflow in fgetwln()
In the function fgetwln() there's a 4 byte heap overflow.

There is a while loop that has this check to see whether there's still
enough space in the buffer:

		if (!fb->len || wused > fb->len) {

If this is true more memory gets allocated. However this test won't be
true if wused == fb->len, but at that point wused already points out
of the buffer. Some lines later there's a write to the buffer:

		fb->wbuf[wused++] = wc;

This bug was found with the help of address sanitizer.

Warned-by: ASAN
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=93881
Signed-off-by: Guillem Jover <guillem@hadrons.org>
2016-01-27 15:24:50 +01:00
Hanno Boeck
008316aa29 test: Add missing <sys/stat.h> include
The test in test/strmode.c can fail to compile depending on the
optimization flags used.

The constants that are used in this file (S_IFREG etc.) come from the
<sys/stat.h> include file. It seems gcc ignores this error if one
compiles with "-O2" (default), but if one uses no optimization it fails.

Add the missing include and it works all the time.

Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=93880
Signed-off-by: Guillem Jover <guillem@hadrons.org>
2016-01-27 15:24:39 +01:00
Guillem Jover
e4ab2c62cd test: Fix success return code for arc4random unit test 2016-01-11 02:35:34 +01:00
Lukas Fleischer
bf5573f86c test: Fix race condition in headers-*.sh
When running tests in parallel (e.g. using `make -j4 check`), the header
tests currently fail due to headers-overlay.sh and headers-system.sh
both generating headers-gen.c simultaneously, resulting in garbled
output. Fix this by using separate C files for the tests.

Signed-off-by: Lukas Fleischer <lfleischer@lfos.de>
Signed-off-by: Guillem Jover <guillem@hadrons.org>
2016-01-10 17:36:34 +01:00
Guillem Jover
229f85794f Release libbsd 0.8.1 2015-12-14 03:39:48 +01:00
Guillem Jover
7a75687541 Add support for GNU/Hurd to getentropy()
Reuse the getentropy code for Linux on the Hurd, which has fallbacks
for when the better interfaces are not present. And remove all the code
that is not supported currently on the Hurd. Ideally the Hurd should
get an equivalent interfaces that does not suffer from the same
problems as /dev/urandom.
2015-12-14 03:38:23 +01:00
Guillem Jover
f84004baf2 test: Add new unit tests for individual headers usage 2015-12-14 03:34:40 +01:00
Guillem Jover
cdf998a056 Turn <bsd/bsd.h> inert when using LIBBSD_OVERLAY
Also print a warning stating this fact.
2015-12-14 00:58:59 +01:00
Guillem Jover
2c77ad593c Add missing include to <md5.h>
The header was not self-contained, it was missing definitions for some
types included in <sys/types.h>.
2015-12-14 00:58:59 +01:00
Guillem Jover
48ac79b188 Use the non-overlayed libbsd headers when we need our own definitions 2015-12-14 00:58:51 +01:00
Guillem Jover
290a1ce8f2 Switch COPYING to Debian copyright machine readable format 1.0 2015-12-07 03:36:33 +01:00
Guillem Jover
6bcb1312f4 Relicense my contribution to BSD-2-clause
This avoids having two licenses on the same file.
2015-12-07 03:24:47 +01:00
Guillem Jover
da137a0921 Add missing copyright and license headers 2015-12-07 01:56:25 +01:00
Guillem Jover
d2f59a23d5 Fix getentropy implementation to use the correct system hooks
Include getentropy_<SYSTEM>.c instead of arc4random_<SYSTEM>.c.
2015-12-02 04:03:16 +01:00
Guillem Jover
01b77f0dcf Add support for GNU/kFreeBSD for closefrom() and getentropy() 2015-12-02 03:32:13 +01:00
Guillem Jover
75729394af Unify most arc4random Unix hooks into a single file
The Unix hook should work for most Unix-like systems, move glibc
specific code there and a FreeBSd specific comment, and remove the rest.
Also change the code to always fallback to use the generic Unix code.

This should cover GNU/Hurd and GNU/kFreeBSD among others.
2015-12-02 03:08:17 +01:00
Guillem Jover
8493c7f27d Use local SHA512 header
Actually use the local private SHA512 header instead of relying on the
OpenSSL one for no good reason. Add definition for expected macro
SHA512_DIGEST_LENGTH.
2015-12-01 03:40:57 +01:00
Guillem Jover
2b030da016 Release libbsd 0.8.0 2015-11-30 23:48:50 +01:00
Guillem Jover
330e211142 Update license and copyright information 2015-11-30 23:48:50 +01:00
Guillem Jover
874a0e51d3 Update arc4random module from OpenBSD and LibreSSL
Rework arc4random_stir() and arc4random_addrandom() code over the new
internal API, and documentation in the man page. Adapt the code to the
local build system.

Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=85827
2015-11-30 23:48:50 +01:00
Guillem Jover
9a9a8b2dba Add private getentropy module from OpenBSD and LibreSSL
Adapt the code to the local build system.
2015-11-30 23:48:50 +01:00
Guillem Jover
5f9265f816 Add private SHA512 module from FreeBSD 2015-11-30 23:48:50 +01:00
Marek Vasut
1f77cdb40a Add NIOS2 support to nlist()
Add support for the NIOS2 soft-core CPU provided by Altera.

Signed-off-by: Marek Vasut <marex@denx.de>
Signed-off-by: Guillem Jover <guillem@hadrons.org>
Cc: Ley Foon Tan <lftan@altera.com>
Cc: Thomas Chou <thomas@wytron.com.tw>
Cc: Walter Goossens <waltergoossens@home.nl>
2015-11-30 23:48:50 +01:00
Guillem Jover
f3b115540c man: Rename funopen.3 to funopen.3bsd to avoid clash with funtools
The funtools project ships a man page with the same, name. And although
it mith probably make more sense to rename the man page there, as BSD
systems will certainly not do so, this is the easiest and fastest way
to avoid a file conflict.
2015-11-30 23:48:50 +01:00
Guillem Jover
877732ef4d test: Check asprintf() return code 2015-11-30 23:48:50 +01:00
Guillem Jover
02bccb0a01 test: Add unit test for strmode() 2015-11-30 23:02:23 +01:00
Guillem Jover
58bef83f41 test: Add unit test for arc4random() 2015-11-30 23:02:23 +01:00
Guillem Jover
6e074a2bdc build: Make git log invocation immune to local configuration 2015-11-30 23:02:23 +01:00
Guillem Jover
0871daf7b0 build: Move hash/helper.c into new libbsd_la_included_sources
Use this variable in EXTRA_DIST and libbsd_la_DEPENDENCIES.
2015-11-30 04:12:02 +01:00
Guillem Jover
02c33d5022 build: Move proctitle_LDFLAGS inside BUILD_LIBBSD_CTOR conditional 2015-11-30 04:10:23 +01:00
Guillem Jover
45443583df Add explicit_bzero() function from OpenBSD 2015-09-24 05:47:58 +02:00
Guillem Jover
8641d8aed7 Make closefrom_procfs() fail when reallocarray() fails 2015-09-24 05:28:58 +02:00
Guillem Jover
0982dcd98b Lock the file streams in fgetln() and fparseln()
The fparseln() function had the NetBSD uppercase macros stubbed out,
so replace them with the actual stdio ones. The fgetln() function was
missing any locking at all.
2015-09-23 07:59:34 +02:00
Guillem Jover
ee26e59e72 Mark functions handling format strings with __printflike 2015-09-23 07:59:34 +02:00
Guillem Jover
151bc71d64 Add compile and link-time deprecation warnings for fgetln()
Although the current implementation in libbsd is probably one of the
safest ones around, it still poses some problems when used with many
file streams. This function has now a replacement, that is both more
standard and portable. Ask users to switch to getline(3) instead.
2015-09-23 07:59:34 +02:00
Guillem Jover
41ff37bbcc build: Add support for linker warnings 2015-09-23 07:59:34 +02:00
Guillem Jover
53d989a223 Switch fparseln() implementation from fgetln() to getline() 2015-09-23 07:59:34 +02:00
Guillem Jover
f50b197ea5 test: Add fparseln() unit test 2015-09-23 07:59:34 +02:00
Guillem Jover
54f153414a test: Refactor stream testing functions into a new module 2015-09-23 07:59:34 +02:00
Brent Cook
9688ab26b9 Avoid left shift overflow in reallocarray
Some 64-bit platforms (e.g. Windows 64) have a 32-bit long. So, shifting
1UL 32-bits to the left causes an overflow. This replaces the constant
1UL with (size_t)1 so that we get the correct constant size for the
platform.

Import from OpenBSD.

Signed-off-by: Guillem Jover <guillem@hadrons.org>
2015-09-23 07:59:34 +02:00
Guillem Jover
025b44800e Make mergesort setup() static 2015-09-23 07:59:34 +02:00
Guillem Jover
a6a101effa Use ANSI C prototypes 2015-09-23 07:59:34 +02:00
Guillem Jover
32388fe59f Use reallocarray() instead of malloc() or realloc() 2015-09-23 07:59:34 +02:00
Guillem Jover
30e328cbf1 Do not close file descriptors while scanning the /proc filesystem
Closing file descriptors changes the content of the fd directories in
the /proc filesystem, which means readdir() might get very confused.

Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=85663
2015-09-23 07:59:34 +02:00
Guillem Jover
4cc43915f2 Move procfs based implementation into a new closefrom_procfs() function 2015-09-23 07:59:34 +02:00
Guillem Jover
34df142665 Refactor file descriptor closure into a new closefrom_close() 2015-09-23 07:59:34 +02:00
Guillem Jover
3881c4fc68 Update closefrom() function
Import from sudo. Adapt the build system to detect the required features.
2015-09-23 07:59:34 +02:00
Guillem Jover
3a3d87d730 test: Add closefrom() unit test 2015-09-23 07:59:34 +02:00
Guillem Jover
d62f7d8fac test: Add test case for fpurge(NULL) 2015-09-23 07:59:34 +02:00
Guillem Jover
cfb4d462a9 test: Move and activate fpurge() test case from module to a dedicated file 2015-09-23 07:59:34 +02:00
Guillem Jover
205827a2dd build: Centralize testsuite LDADD setting in a single variable 2015-09-23 07:59:34 +02:00
Guillem Jover
c7e01e9884 Sync queue(3) from FreeBSD
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=85147
2015-09-23 07:59:34 +02:00
Guillem Jover
3267114483 Add __offsetof, __rangeof and __containerof to sys/cdefs.h
Import and adapt from FreeBSD.
2015-09-23 07:59:27 +02:00
Guillem Jover
0e4e3ab269 Add __DECONST, __DEVOLATILE and __DEQUALIFY macros to sys/cdefs.h
Import from FreeBSD.
2015-09-23 07:59:24 +02:00
Guillem Jover
a6fe103c1b Add new man page for reallocarray(3)
Import man page from OpenBSD.

Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=85622
2015-09-23 07:14:24 +02:00
Guillem Jover
02b55488c5 Use stdint integer types instead of BSD legacy ones 2015-09-23 07:14:21 +02:00
Callum Davies
6378351169 Fix arc4random() and arc4random_stir() prototypes
These two functions accept no arguments.  The prototypes should reflect
this.  This change lets the compiler warn about certain (admittedly
silly) mistakes.

Signed-off-by: Guillem Jover <guillem@hadrons.org>
2014-08-12 12:18:13 +02:00
Guillem Jover
e390651b64 Release libbsd 0.7.0 2014-07-29 03:19:15 +02:00
Guillem Jover
e8d3d04177 build: Remove hard requirement for GNU .init_array section support
In case the support is not available, just stop building the
libbsd-ctor.a library, which is a nice to have thing, but should not
have been a hard requirement from the start. This should allow to
build libbsd on non-glibc based systems using another libc.
2014-07-20 02:09:20 +02:00
Benjamin Baier
faa005cb32 Add reallocarray() function from OpenBSD
Signed-off-by: Guillem Jover <guillem@hadrons.org>
2014-07-17 05:13:05 +02:00
Guillem Jover
36aca8c06e Add stringlist module from NetBSD 2014-07-17 05:11:00 +02:00
Guillem Jover
e8f9300355 Add getbsize() function
Import code from DragonFlyBSD and man page from FreeBSD.
2014-07-15 10:57:42 +02:00
Christian Svensson
a88bb8380d Add OpenRISC support to nlist()
Signed-off-by: Guillem Jover <guillem@hadrons.org>
2014-03-06 22:11:27 +01:00
Guillem Jover
8d16c3df67 Add timeconv module from FreeBSD
Inline license information from FreeBSD root dir COPYRIGHT file.
2013-10-21 05:48:30 +02:00
Guillem Jover
f41fdcf186 Add funopen() function
This is a wrapper over the glibc fopencookie() function.

We diverge from the FreeBSD, OpenBSD and DragonFlyBSD declarations,
because seekfn() there wrongly uses fpos_t, assuming it's an integral
type, and any code using that on a system where fpos_t is a struct
(such as GNU-based systems or NetBSD) will fail to build. In which case,
as the code has to be modified anyway, we might just as well use the
correct declaration.
2013-10-21 05:35:44 +02:00
Guillem Jover
86cbff385a Handle glibc partial header inclusions
The glibc headers use selective inclusions through the __need_NAME
mechanism to avoid circular dependencies.

The problem is that if we are being overlaid, and have been requested
a partial inclusion, when we pass control to the system header, then
we might miss definitions needed by our own header, resulting in build
failures.

Workaround that by catching current partial requests, and skip the
current inclusion.
2013-10-21 05:35:17 +02:00
Guillem Jover
ee04e8de14 build: Set subdir-objects automake option
Bump automake minimal version to 1.9.
2013-10-21 05:33:08 +02:00
Guillem Jover
61b2dbb8f5 Fix dehumanize_number() to correctly detect overflows
Do not allow numbers greated than INT64_MAX and smaller than INT64_MIN.
Clarify the positive sign value by prefixing it with an explicit +.

Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=66909
2013-10-21 05:29:37 +02:00
Guillem Jover
119417462e Release libbsd 0.6.0 2013-07-14 13:34:07 +02:00
Guillem Jover
948bcf1db8 Warn when setproctitle() gets called before initialization
Try to give a helpful message in case the program is not initializing
the setproctitle() machinery.
2013-07-14 13:34:07 +02:00
Guillem Jover
c5b9590287 Move setproctitle() automatic initialization to its own library
The automatic initialization cannot be part of the main shared library,
because there is no thread-safe way to change the environ global
variable. This is not a problem if the initializaion happens just at
program load time, but becomes one if the shared library is directly or
indirectly dlopen()ed during the execution of the program, which could
have either kept references to the old environ or could change it in
some other thread. This has been observed for example on systems using
Samba NSS modules.

To avoid any other possible fallout, the constructor is split into a
new static library that needs to be linked explicitly into programs
using setproctitle(). As an additional safety measure the pkg-config
linker flags will mark the program as not allowing to be dlopen()ed
so that we avoid the problem described above.

Reported-by: Jan Alexander Steffens (heftig) <jan.steffens@gmail.com>
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=66679
2013-07-14 13:32:11 +02:00
Guillem Jover
3077d2fffc build: Move version ABI from Makefile to configure.ac
It's easier to find there, and the value can be reused in case we have
to provide another shared library.
2013-07-14 10:27:25 +02:00
Guillem Jover
1bf0a55579 Release libbsd 0.5.2 2013-06-08 18:26:04 +02:00
Guillem Jover
ad613d9d09 Create a shallow copy of environ before replacing it in setproctitle()
Because clearenv() or setenv() might free the environ array of pointers,
we should make sure to copy it so that we can access it later on when
doing the deep copy via setenv().

Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=65470
2013-06-08 18:26:04 +02:00
Guillem Jover
e084ce3fa7 Specify setproctitle_stub() signature manually if typeof is missing
Do not stop exporting the function in the version node even if typeof
is not available, as that would break ABI.
2013-06-08 18:09:36 +02:00
Guillem Jover
50e4c55afd Try to check if setproctitle() constructor got passed arguments 2013-06-08 18:09:36 +02:00
Guillem Jover
6faea4d2a0 Force setproctitle() into .init_array section
The GNU .init_array support is an extension over the standard System V
ABI .init_array support, which passes the main() arguments to the init
function.

This support comes in three parts. First the dynamic linker (from glibc)
needs to support it. Then function pointers need to be placed in the
section, for example by using __attribute__((constructor)), that the
compiler (gcc or clang for example) might place in section .ctors and
the linker (from binutils) will move to .init_array on the output
object, or by placing them directly into .init_array by the compiler
when compiling. If this does not happen and the function pointers end
up in .ctors, then they will not get passed the main() arguments, which
we do really need in this case.

But this relies on recent binutils or gcc having native .init_array
support, and not having it disabled through --disable-initfini-array.

To guarantee we get the correct behaviour, let's just place the function
pointer in the .init_array section directly, so we only require a recent
enough glibc.

Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=65029
2013-06-08 18:09:29 +02:00
Guillem Jover
367e036537 test: Try setting and getting an environment variable after setproctitle() 2013-06-08 18:08:58 +02:00
Guillem Jover
dc8b09783f build: Ignore automake 1.13+ test suite generated files 2013-05-30 04:09:25 +02:00
91 changed files with 7545 additions and 1136 deletions

3
.gitignore vendored
View File

@@ -5,6 +5,9 @@ ChangeLog
*.o *.o
*.so* *.so*
*.a *.a
*.log
*.trs
.dirstamp
.deps/ .deps/
.libs/ .libs/
Makefile Makefile

1031
COPYING

File diff suppressed because it is too large Load Diff

View File

@@ -12,5 +12,5 @@ EXTRA_DIST = \
dist-hook: dist-hook:
echo $(VERSION) >$(distdir)/.dist-version echo $(VERSION) >$(distdir)/.dist-version
if [ -d .git ]; then \ if [ -d .git ]; then \
git log --stat -C >$(distdir)/ChangeLog; \ XDG_CONFIG_HOME= HOME= git log --stat -C >$(distdir)/ChangeLog; \
fi fi

View File

@@ -6,11 +6,18 @@ AC_CONFIG_SRCDIR([src/fgetln.c])
AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_MACRO_DIR([m4])
AM_INIT_AUTOMAKE([1.8 foreign nostdinc no-dist-gzip dist-xz]) AM_INIT_AUTOMAKE([1.9 foreign nostdinc subdir-objects no-dist-gzip dist-xz])
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])], m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])],
[AC_SUBST([AM_DEFAULT_VERBOSITY], [1])]) [AC_SUBST([AM_DEFAULT_VERBOSITY], [1])])
LIBBSD_ABI_MAJOR=0
LIBBSD_ABI_MINOR=8
LIBBSD_ABI_PATCH=2
LIBBSD_ABI="$LIBBSD_ABI_MAJOR:$LIBBSD_ABI_MINOR:$LIBBSD_ABI_PATCH"
AC_SUBST([LIBBSD_ABI])
# Check and store if we got user supplied variables # Check and store if we got user supplied variables
user_CFLAGS=${CFLAGS-unset} user_CFLAGS=${CFLAGS-unset}
@@ -31,9 +38,14 @@ if test "$user_CFLAGS" = unset && test "$GCC" = yes; then
fi fi
# Checks for libraries. # Checks for libraries.
AC_CHECK_LIB([testu01], [unif01_CreateExternGenBits],
[TESTU01_LIBS="-ltestu01"])
AC_SUBST([TESTU01_LIBS])
AM_CONDITIONAL([HAVE_LIBTESTU01],
[test "x$ac_cv_lib_testu01_unif01_CreateExternGenBits" = "xyes"])
# Checks for header files. # Checks for header files.
AC_CHECK_HEADERS([sys/ndir.h sys/dir.h dir.h dirent.h]) AC_CHECK_HEADERS([sys/ndir.h sys/dir.h ndir.h dirent.h])
# Checks for typedefs, structures, and compiler characteristics. # Checks for typedefs, structures, and compiler characteristics.
AC_TYPE_UID_T AC_TYPE_UID_T
@@ -53,6 +65,50 @@ AC_CHECK_DECL([F_CLOSEM],
[#include <limits.h> [#include <limits.h>
#include <fcntl.h>]) #include <fcntl.h>])
AC_CACHE_CHECK(
[for GNU .init_array section support],
[libbsd_cv_gnu_init_array_support],
[AC_RUN_IFELSE(
[AC_LANG_SOURCE(
[[
static int rc = 1;
static void init(int argc) { if (argc == 1) rc = 0; }
void (*init_func)(int argc) __attribute__((section(".init_array"))) = init;
int main() { return rc; }
]]
)],
[libbsd_cv_gnu_init_array_support=yes],
[libbsd_cv_gnu_init_array_support=no],
[AC_PREPROC_IFELSE(
[AC_LANG_SOURCE(
[[
/* Look for a known libc that supports .init_array with the GNU extension
* to pass main() arguments to the init functions. */
#include <stdlib.h>
#if defined __GLIBC_PREREQ
# if __GLIBC_PREREQ(2, 4)
/* glibc supports GNU .init_array since 2.4. */
# else
# error glibc does not support GNU .init_array
# endif
#else
/*
* Basic SysV ABI .init_array support, init functions do not get arguments:
* - Bionic since its inception.
* - uClibc since 0.9.29.
*/
# error unknown whether libc supports GNU .init_array
#endif
]]
)],
[libbsd_cv_gnu_init_array_support=yes],
[libbsd_cv_gnu_init_array_support=no])
]
)]
)
AM_CONDITIONAL([BUILD_LIBBSD_CTOR],
[test "$libbsd_cv_gnu_init_array_support" = yes])
# Checks for library functions. # Checks for library functions.
AC_MSG_CHECKING([for program_invocation_short_name]) AC_MSG_CHECKING([for program_invocation_short_name])
AC_LINK_IFELSE( AC_LINK_IFELSE(
@@ -72,7 +128,10 @@ AC_LINK_IFELSE(
AC_MSG_RESULT([yes])], AC_MSG_RESULT([yes])],
[AC_MSG_RESULT([no])]) [AC_MSG_RESULT([no])])
AC_CHECK_FUNCS([clearenv dirfd __fpurge getexecname getline sysconf]) AC_CHECK_FUNCS([clearenv dirfd fopencookie __fpurge \
getauxval getentropy getexecname getline \
pstat_getproc sysconf])
AM_CONDITIONAL(HAVE_GETENTROPY, [test "x$ac_cv_func_getentropy" = "xtrue"])
AC_CONFIG_FILES([ AC_CONFIG_FILES([
Makefile Makefile
@@ -80,6 +139,7 @@ AC_CONFIG_FILES([
man/Makefile man/Makefile
src/Makefile src/Makefile
src/libbsd.pc src/libbsd.pc
src/libbsd-ctor.pc
src/libbsd-overlay.pc src/libbsd-overlay.pc
test/Makefile test/Makefile
]) ])

View File

@@ -19,6 +19,8 @@ nobase_include_HEADERS = \
bsd/stdio.h \ bsd/stdio.h \
bsd/stdlib.h \ bsd/stdlib.h \
bsd/string.h \ bsd/string.h \
bsd/stringlist.h \
bsd/timeconv.h \
bsd/unistd.h \ bsd/unistd.h \
bsd/vis.h \ bsd/vis.h \
bsd/wchar.h \ bsd/wchar.h \

View File

@@ -27,10 +27,12 @@
#ifndef LIBBSD_H #ifndef LIBBSD_H
#define LIBBSD_H #define LIBBSD_H
#ifdef LIBBSD_OVERLAY
#warning "This header is meant to be used w/o the libbsd overlay."
#else
/* /*
* Include all bsd compat headers. * Include all bsd compat headers.
*/ */
#include <bsd/sys/cdefs.h> #include <bsd/sys/cdefs.h>
#include <bsd/sys/queue.h> #include <bsd/sys/queue.h>
#include <bsd/sys/tree.h> #include <bsd/sys/tree.h>
@@ -40,5 +42,6 @@
#include <bsd/err.h> #include <bsd/err.h>
#include <bsd/getopt.h> #include <bsd/getopt.h>
#include <bsd/md5.h> #include <bsd/md5.h>
#endif
#endif #endif

View File

@@ -34,15 +34,23 @@
#ifndef LIBBSD_ERR_H #ifndef LIBBSD_ERR_H
#define LIBBSD_ERR_H #define LIBBSD_ERR_H
#ifdef LIBBSD_OVERLAY
#include <sys/cdefs.h> #include <sys/cdefs.h>
#else
#include <bsd/sys/cdefs.h>
#endif
#include <stdarg.h> #include <stdarg.h>
__BEGIN_DECLS __BEGIN_DECLS
extern void warnc (int code, const char *format, ...); void warnc(int code, const char *format, ...)
extern void vwarnc (int code, const char *format, va_list ap); __printflike(2, 3);
extern void errc (int status, int code, const char *format, ...); void vwarnc(int code, const char *format, va_list ap)
extern void verrc (int status, int code, const char *format, va_list ap); __printflike(2, 0);
void errc(int status, int code, const char *format, ...)
__printflike(3, 4);
void verrc(int status, int code, const char *format, va_list ap)
__printflike(3, 0);
__END_DECLS __END_DECLS
#endif #endif

View File

@@ -15,26 +15,29 @@
#ifndef _MD5_H_ #ifndef _MD5_H_
#define _MD5_H_ #define _MD5_H_
#include <stdint.h>
#define MD5_BLOCK_LENGTH 64 #define MD5_BLOCK_LENGTH 64
#define MD5_DIGEST_LENGTH 16 #define MD5_DIGEST_LENGTH 16
#define MD5_DIGEST_STRING_LENGTH (MD5_DIGEST_LENGTH * 2 + 1) #define MD5_DIGEST_STRING_LENGTH (MD5_DIGEST_LENGTH * 2 + 1)
typedef struct MD5Context { typedef struct MD5Context {
u_int32_t state[4]; /* state */ uint32_t state[4]; /* state */
u_int64_t count; /* number of bits, mod 2^64 */ uint64_t count; /* number of bits, mod 2^64 */
u_int8_t buffer[MD5_BLOCK_LENGTH]; /* input buffer */ uint8_t buffer[MD5_BLOCK_LENGTH]; /* input buffer */
} MD5_CTX; } MD5_CTX;
#include <sys/cdefs.h> #include <sys/cdefs.h>
#include <sys/types.h>
__BEGIN_DECLS __BEGIN_DECLS
void MD5Init(MD5_CTX *); void MD5Init(MD5_CTX *);
void MD5Update(MD5_CTX *, const u_int8_t *, size_t) void MD5Update(MD5_CTX *, const uint8_t *, size_t)
__attribute__((__bounded__(__string__,2,3))); __attribute__((__bounded__(__string__,2,3)));
void MD5Pad(MD5_CTX *); void MD5Pad(MD5_CTX *);
void MD5Final(u_int8_t [MD5_DIGEST_LENGTH], MD5_CTX *) void MD5Final(uint8_t [MD5_DIGEST_LENGTH], MD5_CTX *)
__attribute__((__bounded__(__minbytes__,1,MD5_DIGEST_LENGTH))); __attribute__((__bounded__(__minbytes__,1,MD5_DIGEST_LENGTH)));
void MD5Transform(u_int32_t [4], const u_int8_t [MD5_BLOCK_LENGTH]) void MD5Transform(uint32_t [4], const uint8_t [MD5_BLOCK_LENGTH])
__attribute__((__bounded__(__minbytes__,1,4))) __attribute__((__bounded__(__minbytes__,1,4)))
__attribute__((__bounded__(__minbytes__,2,MD5_BLOCK_LENGTH))); __attribute__((__bounded__(__minbytes__,2,MD5_BLOCK_LENGTH)));
char *MD5End(MD5_CTX *, char *) char *MD5End(MD5_CTX *, char *)
@@ -43,7 +46,7 @@ char *MD5File(const char *, char *)
__attribute__((__bounded__(__minbytes__,2,MD5_DIGEST_STRING_LENGTH))); __attribute__((__bounded__(__minbytes__,2,MD5_DIGEST_STRING_LENGTH)));
char *MD5FileChunk(const char *, char *, off_t, off_t) char *MD5FileChunk(const char *, char *, off_t, off_t)
__attribute__((__bounded__(__minbytes__,2,MD5_DIGEST_STRING_LENGTH))); __attribute__((__bounded__(__minbytes__,2,MD5_DIGEST_STRING_LENGTH)));
char *MD5Data(const u_int8_t *, size_t, char *) char *MD5Data(const uint8_t *, size_t, char *)
__attribute__((__bounded__(__string__,1,2))) __attribute__((__bounded__(__string__,1,2)))
__attribute__((__bounded__(__minbytes__,3,MD5_DIGEST_STRING_LENGTH))); __attribute__((__bounded__(__minbytes__,3,MD5_DIGEST_STRING_LENGTH)));
__END_DECLS __END_DECLS

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright © 2004, 2005, 2009, 2011 Guillem Jover <guillem@hadrons.org> * Copyright © 2004-2005, 2009, 2011-2013 Guillem Jover <guillem@hadrons.org>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@@ -24,12 +24,17 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#if defined(__need_FILE) || defined(__need___FILE)
#define LIBBSD_STDIO_H_SKIP
#endif
#ifdef LIBBSD_OVERLAY #ifdef LIBBSD_OVERLAY
#include_next <stdio.h> #include_next <stdio.h>
#else #else
#include <stdio.h> #include <stdio.h>
#endif #endif
#ifndef LIBBSD_STDIO_H_SKIP
#ifndef LIBBSD_STDIO_H #ifndef LIBBSD_STDIO_H
#define LIBBSD_STDIO_H #define LIBBSD_STDIO_H
@@ -39,9 +44,33 @@
__BEGIN_DECLS __BEGIN_DECLS
const char *fmtcheck(const char *, const char *); const char *fmtcheck(const char *, const char *);
char *fgetln(FILE *fp, size_t *lenp); /* XXX: The function requires cooperation from the system libc to store the
* line buffer in the FILE struct itself. */
char *fgetln(FILE *fp, size_t *lenp)
__attribute__((deprecated("This functions cannot be safely ported, "
"use getline(3) instead, as it is supported "
"by GNU and POSIX.1-2008.")));
/*
* Note: We diverge from the FreeBSD, OpenBSD and DragonFlyBSD declarations,
* because seekfn() there wrongly uses fpos_t, assuming it's an integral
* type, and any code using that on a system where fpos_t is a struct
* (such as GNU-based systems or NetBSD) will fail to build. In which case,
* as the code has to be modified anyway, we might just as well use the
* correct declaration here.
*/
FILE *funopen(const void *cookie,
int (*readfn)(void *cookie, char *buf, int size),
int (*writefn)(void *cookie, const char *buf, int size),
off_t (*seekfn)(void *cookie, off_t offset, int whence),
int (*closefn)(void *cookie));
#define fropen(cookie, fn) funopen(cookie, fn, NULL, NULL, NULL)
#define fwopen(cookie, fn) funopen(cookie, NULL, fn, NULL, NULL)
int fpurge(FILE *fp); int fpurge(FILE *fp);
__END_DECLS __END_DECLS
#endif #endif
#endif
#undef LIBBSD_STDIO_H_SKIP

View File

@@ -47,11 +47,11 @@
#include <stdint.h> #include <stdint.h>
__BEGIN_DECLS __BEGIN_DECLS
u_int32_t arc4random(); uint32_t arc4random(void);
void arc4random_stir(); void arc4random_stir(void);
void arc4random_addrandom(u_char *dat, int datlen); void arc4random_addrandom(u_char *dat, int datlen);
void arc4random_buf(void *_buf, size_t n); void arc4random_buf(void *_buf, size_t n);
u_int32_t arc4random_uniform(u_int32_t upper_bound); uint32_t arc4random_uniform(uint32_t upper_bound);
int dehumanize_number(const char *str, int64_t *size); int dehumanize_number(const char *str, int64_t *size);
@@ -67,9 +67,12 @@ int sradixsort(const unsigned char **base, int nmemb,
const unsigned char *table, unsigned endbyte); const unsigned char *table, unsigned endbyte);
void *reallocf(void *ptr, size_t size); void *reallocf(void *ptr, size_t size);
void *reallocarray(void *ptr, size_t nmemb, size_t size);
long long strtonum(const char *nptr, long long minval, long long maxval, long long strtonum(const char *nptr, long long minval, long long maxval,
const char **errstr); const char **errstr);
char *getbsize(int *headerlenp, long *blocksizep);
__END_DECLS __END_DECLS
#endif #endif

View File

@@ -41,6 +41,8 @@ size_t strlcpy(char *dst, const char *src, size_t siz);
size_t strlcat(char *dst, const char *src, size_t siz); size_t strlcat(char *dst, const char *src, size_t siz);
char *strnstr(const char *str, const char *find, size_t str_len); char *strnstr(const char *str, const char *find, size_t str_len);
void strmode(mode_t mode, char *str); void strmode(mode_t mode, char *str);
void explicit_bzero(void *buf, size_t len);
__END_DECLS __END_DECLS
#endif #endif

54
include/bsd/stringlist.h Normal file
View File

@@ -0,0 +1,54 @@
/* $NetBSD: stringlist.h,v 1.6 2006/07/27 15:37:19 christos Exp $ */
/*-
* Copyright (c) 1994 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Christos Zoulas.
*
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``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 FOUNDATION OR CONTRIBUTORS
* 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 _STRINGLIST_H
#define _STRINGLIST_H
#include <sys/cdefs.h>
#include <sys/types.h>
/*
* Simple string list
*/
typedef struct _stringlist {
char **sl_str;
size_t sl_max;
size_t sl_cur;
} StringList;
__BEGIN_DECLS
StringList *sl_init(void);
int sl_add(StringList *, char *);
void sl_free(StringList *, int);
char *sl_find(StringList *, const char *);
int sl_delete(StringList *, const char *, int);
__END_DECLS
#endif /* _STRINGLIST_H */

View File

@@ -114,6 +114,47 @@
# define __bounded__(x, y, z) # define __bounded__(x, y, z)
#endif #endif
/*
* We define this here since <stddef.h>, <sys/queue.h>, and <sys/types.h>
* require it.
*/
#ifndef __offsetof
# if LIBBSD_GCC_VERSION >= 0x0401
# define __offsetof(type, field) __builtin_offsetof(type, field)
# else
# ifndef __cplusplus
# define __offsetof(type, field) \
((__size_t)(__uintptr_t)((const volatile void *)&((type *)0)->field))
# else
# define __offsetof(type, field) \
(__offsetof__ (reinterpret_cast <__size_t> \
(&reinterpret_cast <const volatile char &> \
(static_cast<type *> (0)->field))))
# endif
# endif
#endif
#define __rangeof(type, start, end) \
(__offsetof(type, end) - __offsetof(type, start))
/*
* Given the pointer x to the member m of the struct s, return
* a pointer to the containing structure. When using GCC, we first
* assign pointer x to a local variable, to check that its type is
* compatible with member m.
*/
#ifndef __containerof
# if LIBBSD_GCC_VERSION >= 0x0301
# define __containerof(x, s, m) ({ \
const volatile __typeof(((s *)0)->m) *__x = (x); \
__DEQUALIFY(s *, (const volatile char *)__x - __offsetof(s, m)); \
})
# else
# define __containerof(x, s, m) \
__DEQUALIFY(s *, (const volatile char *)(x) - __offsetof(s, m))
# endif
#endif
#ifndef __RCSID #ifndef __RCSID
# define __RCSID(x) # define __RCSID(x)
#endif #endif
@@ -138,4 +179,16 @@
# define __COPYRIGHT(x) # define __COPYRIGHT(x)
#endif #endif
#ifndef __DECONST
#define __DECONST(type, var) ((type)(__uintptr_t)(const void *)(var))
#endif
#ifndef __DEVOLATILE
#define __DEVOLATILE(type, var) ((type)(__uintptr_t)(volatile void *)(var))
#endif
#ifndef __DEQUALIFY
#define __DEQUALIFY(type, var) ((type)(__uintptr_t)(const volatile void *)(var))
#endif
#endif #endif

View File

@@ -1,6 +1,9 @@
/* /*
* Copyright © 2011 Guillem Jover <guillem@hadrons.org> * Copyright © 2011 Guillem Jover <guillem@hadrons.org>
* *
* Copyright © 2002 Thomas Moestl <tmm@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
* are met: * are met:
@@ -9,19 +12,18 @@
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * 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 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/ */
#ifdef LIBBSD_OVERLAY #ifdef LIBBSD_OVERLAY
@@ -49,32 +51,6 @@
#define _PDP_ENDIAN __PDP_ENDIAN #define _PDP_ENDIAN __PDP_ENDIAN
#endif #endif
/*
* Copyright © 2002 Thomas Moestl <tmm@FreeBSD.org>
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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 <stdint.h> #include <stdint.h>
/* Alignment-agnostic encode/decode bytestream to/from little/big endian. */ /* Alignment-agnostic encode/decode bytestream to/from little/big endian. */

View File

@@ -65,7 +65,7 @@
* so that an arbitrary element can be removed without a need to * so that an arbitrary element can be removed without a need to
* traverse the list. New elements can be added to the list before * traverse the list. New elements can be added to the list before
* or after an existing element or at the head of the list. A list * or after an existing element or at the head of the list. A list
* may only be traversed in the forward direction. * may be traversed in either direction.
* *
* A tail queue is headed by a pair of pointers, one to the head of the * A tail queue is headed by a pair of pointers, one to the head of the
* list and the other to the tail of the list. The elements are doubly * list and the other to the tail of the list. The elements are doubly
@@ -85,12 +85,16 @@
* _EMPTY + + + + * _EMPTY + + + +
* _FIRST + + + + * _FIRST + + + +
* _NEXT + + + + * _NEXT + + + +
* _PREV - - - + * _PREV - + - +
* _LAST - - + + * _LAST - - + +
* _FOREACH + + + + * _FOREACH + + + +
* _FOREACH_FROM + + + +
* _FOREACH_SAFE + + + + * _FOREACH_SAFE + + + +
* _FOREACH_FROM_SAFE + + + +
* _FOREACH_REVERSE - - - + * _FOREACH_REVERSE - - - +
* _FOREACH_REVERSE_FROM - - - +
* _FOREACH_REVERSE_SAFE - - - + * _FOREACH_REVERSE_SAFE - - - +
* _FOREACH_REVERSE_FROM_SAFE - - - +
* _INSERT_HEAD + + + + * _INSERT_HEAD + + + +
* _INSERT_BEFORE - + - + * _INSERT_BEFORE - + - +
* _INSERT_AFTER + + + + * _INSERT_AFTER + + + +
@@ -99,19 +103,22 @@
* _REMOVE_AFTER + - + - * _REMOVE_AFTER + - + -
* _REMOVE_HEAD + - + - * _REMOVE_HEAD + - + -
* _REMOVE + + + + * _REMOVE + + + +
* _SWAP + + + +
* *
*/ */
#ifdef QUEUE_MACRO_DEBUG #ifdef QUEUE_MACRO_DEBUG
/* Store the last 2 places the queue element or head was altered */ /* Store the last 2 places the queue element or head was altered */
struct qm_trace { struct qm_trace {
char * lastfile; unsigned long lastline;
int lastline; unsigned long prevline;
char * prevfile; const char *lastfile;
int prevline; const char *prevfile;
}; };
#define TRACEBUF struct qm_trace trace; #define TRACEBUF struct qm_trace trace;
#define TRACEBUF_INITIALIZER { __FILE__, __LINE__, NULL, 0 } ,
#define TRASHIT(x) do {(x) = (void *)-1;} while (0) #define TRASHIT(x) do {(x) = (void *)-1;} while (0)
#define QMD_SAVELINK(name, link) void **name = (void *)&(link)
#define QMD_TRACE_HEAD(head) do { \ #define QMD_TRACE_HEAD(head) do { \
(head)->trace.prevline = (head)->trace.lastline; \ (head)->trace.prevline = (head)->trace.lastline; \
@@ -130,7 +137,9 @@ struct qm_trace {
#else #else
#define QMD_TRACE_ELEM(elem) #define QMD_TRACE_ELEM(elem)
#define QMD_TRACE_HEAD(head) #define QMD_TRACE_HEAD(head)
#define QMD_SAVELINK(name, link)
#define TRACEBUF #define TRACEBUF
#define TRACEBUF_INITIALIZER
#define TRASHIT(x) #define TRASHIT(x)
#endif /* QUEUE_MACRO_DEBUG */ #endif /* QUEUE_MACRO_DEBUG */
@@ -162,11 +171,21 @@ struct { \
(var); \ (var); \
(var) = SLIST_NEXT((var), field)) (var) = SLIST_NEXT((var), field))
#define SLIST_FOREACH_FROM(var, head, field) \
for ((var) = ((var) ? (var) : SLIST_FIRST((head))); \
(var); \
(var) = SLIST_NEXT((var), field))
#define SLIST_FOREACH_SAFE(var, head, field, tvar) \ #define SLIST_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = SLIST_FIRST((head)); \ for ((var) = SLIST_FIRST((head)); \
(var) && ((tvar) = SLIST_NEXT((var), field), 1); \ (var) && ((tvar) = SLIST_NEXT((var), field), 1); \
(var) = (tvar)) (var) = (tvar))
#define SLIST_FOREACH_FROM_SAFE(var, head, field, tvar) \
for ((var) = ((var) ? (var) : SLIST_FIRST((head))); \
(var) && ((tvar) = SLIST_NEXT((var), field), 1); \
(var) = (tvar))
#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \ #define SLIST_FOREACH_PREVPTR(var, varp, head, field) \
for ((varp) = &SLIST_FIRST((head)); \ for ((varp) = &SLIST_FIRST((head)); \
((var) = *(varp)) != NULL; \ ((var) = *(varp)) != NULL; \
@@ -189,6 +208,7 @@ struct { \
#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) #define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
#define SLIST_REMOVE(head, elm, type, field) do { \ #define SLIST_REMOVE(head, elm, type, field) do { \
QMD_SAVELINK(oldnext, (elm)->field.sle_next); \
if (SLIST_FIRST((head)) == (elm)) { \ if (SLIST_FIRST((head)) == (elm)) { \
SLIST_REMOVE_HEAD((head), field); \ SLIST_REMOVE_HEAD((head), field); \
} \ } \
@@ -198,7 +218,7 @@ struct { \
curelm = SLIST_NEXT(curelm, field); \ curelm = SLIST_NEXT(curelm, field); \
SLIST_REMOVE_AFTER(curelm, field); \ SLIST_REMOVE_AFTER(curelm, field); \
} \ } \
TRASHIT((elm)->field.sle_next); \ TRASHIT(*oldnext); \
} while (0) } while (0)
#define SLIST_REMOVE_AFTER(elm, field) do { \ #define SLIST_REMOVE_AFTER(elm, field) do { \
@@ -210,6 +230,12 @@ struct { \
SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \ SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \
} while (0) } while (0)
#define SLIST_SWAP(head1, head2, type) do { \
struct type *swap_first = SLIST_FIRST(head1); \
SLIST_FIRST(head1) = SLIST_FIRST(head2); \
SLIST_FIRST(head2) = swap_first; \
} while (0)
/* /*
* Singly-linked Tail queue declarations. * Singly-linked Tail queue declarations.
*/ */
@@ -247,12 +273,21 @@ struct { \
(var); \ (var); \
(var) = STAILQ_NEXT((var), field)) (var) = STAILQ_NEXT((var), field))
#define STAILQ_FOREACH_FROM(var, head, field) \
for ((var) = ((var) ? (var) : STAILQ_FIRST((head))); \
(var); \
(var) = STAILQ_NEXT((var), field))
#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \ #define STAILQ_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = STAILQ_FIRST((head)); \ for ((var) = STAILQ_FIRST((head)); \
(var) && ((tvar) = STAILQ_NEXT((var), field), 1); \ (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \
(var) = (tvar)) (var) = (tvar))
#define STAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \
for ((var) = ((var) ? (var) : STAILQ_FIRST((head))); \
(var) && ((tvar) = STAILQ_NEXT((var), field), 1); \
(var) = (tvar))
#define STAILQ_INIT(head) do { \ #define STAILQ_INIT(head) do { \
STAILQ_FIRST((head)) = NULL; \ STAILQ_FIRST((head)) = NULL; \
(head)->stqh_last = &STAILQ_FIRST((head)); \ (head)->stqh_last = &STAILQ_FIRST((head)); \
@@ -277,14 +312,13 @@ struct { \
} while (0) } while (0)
#define STAILQ_LAST(head, type, field) \ #define STAILQ_LAST(head, type, field) \
(STAILQ_EMPTY((head)) ? \ (STAILQ_EMPTY((head)) ? NULL : \
NULL : \ __containerof((head)->stqh_last, struct type, field.stqe_next))
((struct type *)(void *) \
((char *)((head)->stqh_last) - __offsetof(struct type, field))))
#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) #define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
#define STAILQ_REMOVE(head, elm, type, field) do { \ #define STAILQ_REMOVE(head, elm, type, field) do { \
QMD_SAVELINK(oldnext, (elm)->field.stqe_next); \
if (STAILQ_FIRST((head)) == (elm)) { \ if (STAILQ_FIRST((head)) == (elm)) { \
STAILQ_REMOVE_HEAD((head), field); \ STAILQ_REMOVE_HEAD((head), field); \
} \ } \
@@ -294,13 +328,7 @@ struct { \
curelm = STAILQ_NEXT(curelm, field); \ curelm = STAILQ_NEXT(curelm, field); \
STAILQ_REMOVE_AFTER(head, curelm, field); \ STAILQ_REMOVE_AFTER(head, curelm, field); \
} \ } \
TRASHIT((elm)->field.stqe_next); \ TRASHIT(*oldnext); \
} while (0)
#define STAILQ_REMOVE_HEAD(head, field) do { \
if ((STAILQ_FIRST((head)) = \
STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \
(head)->stqh_last = &STAILQ_FIRST((head)); \
} while (0) } while (0)
#define STAILQ_REMOVE_AFTER(head, elm, field) do { \ #define STAILQ_REMOVE_AFTER(head, elm, field) do { \
@@ -309,6 +337,12 @@ struct { \
(head)->stqh_last = &STAILQ_NEXT((elm), field); \ (head)->stqh_last = &STAILQ_NEXT((elm), field); \
} while (0) } while (0)
#define STAILQ_REMOVE_HEAD(head, field) do { \
if ((STAILQ_FIRST((head)) = \
STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \
(head)->stqh_last = &STAILQ_FIRST((head)); \
} while (0)
#define STAILQ_SWAP(head1, head2, type) do { \ #define STAILQ_SWAP(head1, head2, type) do { \
struct type *swap_first = STAILQ_FIRST(head1); \ struct type *swap_first = STAILQ_FIRST(head1); \
struct type **swap_last = (head1)->stqh_last; \ struct type **swap_last = (head1)->stqh_last; \
@@ -378,11 +412,21 @@ struct { \
(var); \ (var); \
(var) = LIST_NEXT((var), field)) (var) = LIST_NEXT((var), field))
#define LIST_FOREACH_FROM(var, head, field) \
for ((var) = ((var) ? (var) : LIST_FIRST((head))); \
(var); \
(var) = LIST_NEXT((var), field))
#define LIST_FOREACH_SAFE(var, head, field, tvar) \ #define LIST_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = LIST_FIRST((head)); \ for ((var) = LIST_FIRST((head)); \
(var) && ((tvar) = LIST_NEXT((var), field), 1); \ (var) && ((tvar) = LIST_NEXT((var), field), 1); \
(var) = (tvar)) (var) = (tvar))
#define LIST_FOREACH_FROM_SAFE(var, head, field, tvar) \
for ((var) = ((var) ? (var) : LIST_FIRST((head))); \
(var) && ((tvar) = LIST_NEXT((var), field), 1); \
(var) = (tvar))
#define LIST_INIT(head) do { \ #define LIST_INIT(head) do { \
LIST_FIRST((head)) = NULL; \ LIST_FIRST((head)) = NULL; \
} while (0) } while (0)
@@ -414,15 +458,21 @@ struct { \
#define LIST_NEXT(elm, field) ((elm)->field.le_next) #define LIST_NEXT(elm, field) ((elm)->field.le_next)
#define LIST_PREV(elm, head, type, field) \
((elm)->field.le_prev == &LIST_FIRST((head)) ? NULL : \
__containerof((elm)->field.le_prev, struct type, field.le_next))
#define LIST_REMOVE(elm, field) do { \ #define LIST_REMOVE(elm, field) do { \
QMD_SAVELINK(oldnext, (elm)->field.le_next); \
QMD_SAVELINK(oldprev, (elm)->field.le_prev); \
QMD_LIST_CHECK_NEXT(elm, field); \ QMD_LIST_CHECK_NEXT(elm, field); \
QMD_LIST_CHECK_PREV(elm, field); \ QMD_LIST_CHECK_PREV(elm, field); \
if (LIST_NEXT((elm), field) != NULL) \ if (LIST_NEXT((elm), field) != NULL) \
LIST_NEXT((elm), field)->field.le_prev = \ LIST_NEXT((elm), field)->field.le_prev = \
(elm)->field.le_prev; \ (elm)->field.le_prev; \
*(elm)->field.le_prev = LIST_NEXT((elm), field); \ *(elm)->field.le_prev = LIST_NEXT((elm), field); \
TRASHIT((elm)->field.le_next); \ TRASHIT(*oldnext); \
TRASHIT((elm)->field.le_prev); \ TRASHIT(*oldprev); \
} while (0) } while (0)
#define LIST_SWAP(head1, head2, type, field) do { \ #define LIST_SWAP(head1, head2, type, field) do { \
@@ -446,7 +496,7 @@ struct name { \
} }
#define TAILQ_HEAD_INITIALIZER(head) \ #define TAILQ_HEAD_INITIALIZER(head) \
{ NULL, &(head).tqh_first } { NULL, &(head).tqh_first, TRACEBUF_INITIALIZER }
#define TAILQ_ENTRY(type) \ #define TAILQ_ENTRY(type) \
struct { \ struct { \
@@ -509,21 +559,41 @@ struct { \
(var); \ (var); \
(var) = TAILQ_NEXT((var), field)) (var) = TAILQ_NEXT((var), field))
#define TAILQ_FOREACH_FROM(var, head, field) \
for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \
(var); \
(var) = TAILQ_NEXT((var), field))
#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ #define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = TAILQ_FIRST((head)); \ for ((var) = TAILQ_FIRST((head)); \
(var) && ((tvar) = TAILQ_NEXT((var), field), 1); \ (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
(var) = (tvar)) (var) = (tvar))
#define TAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \
for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \
(var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
(var) = (tvar))
#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ #define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
for ((var) = TAILQ_LAST((head), headname); \ for ((var) = TAILQ_LAST((head), headname); \
(var); \ (var); \
(var) = TAILQ_PREV((var), headname, field)) (var) = TAILQ_PREV((var), headname, field))
#define TAILQ_FOREACH_REVERSE_FROM(var, head, headname, field) \
for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \
(var); \
(var) = TAILQ_PREV((var), headname, field))
#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ #define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \
for ((var) = TAILQ_LAST((head), headname); \ for ((var) = TAILQ_LAST((head), headname); \
(var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \ (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \
(var) = (tvar)) (var) = (tvar))
#define TAILQ_FOREACH_REVERSE_FROM_SAFE(var, head, headname, field, tvar) \
for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \
(var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \
(var) = (tvar))
#define TAILQ_INIT(head) do { \ #define TAILQ_INIT(head) do { \
TAILQ_FIRST((head)) = NULL; \ TAILQ_FIRST((head)) = NULL; \
(head)->tqh_last = &TAILQ_FIRST((head)); \ (head)->tqh_last = &TAILQ_FIRST((head)); \
@@ -587,6 +657,8 @@ struct { \
(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
#define TAILQ_REMOVE(head, elm, field) do { \ #define TAILQ_REMOVE(head, elm, field) do { \
QMD_SAVELINK(oldnext, (elm)->field.tqe_next); \
QMD_SAVELINK(oldprev, (elm)->field.tqe_prev); \
QMD_TAILQ_CHECK_NEXT(elm, field); \ QMD_TAILQ_CHECK_NEXT(elm, field); \
QMD_TAILQ_CHECK_PREV(elm, field); \ QMD_TAILQ_CHECK_PREV(elm, field); \
if ((TAILQ_NEXT((elm), field)) != NULL) \ if ((TAILQ_NEXT((elm), field)) != NULL) \
@@ -597,8 +669,8 @@ struct { \
QMD_TRACE_HEAD(head); \ QMD_TRACE_HEAD(head); \
} \ } \
*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \ *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \
TRASHIT((elm)->field.tqe_next); \ TRASHIT(*oldnext); \
TRASHIT((elm)->field.tqe_prev); \ TRASHIT(*oldprev); \
QMD_TRACE_ELEM(&(elm)->field); \ QMD_TRACE_ELEM(&(elm)->field); \
} while (0) } while (0)

57
include/bsd/timeconv.h Normal file
View File

@@ -0,0 +1,57 @@
/*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
* (c) UNIX System Laboratories, Inc.
* All or some portions of this file are derived from material licensed
* to the University of California by American Telephone and Telegraph
* Co. or Unix System Laboratories, Inc. and are reproduced herein with
* the permission of UNIX System Laboratories, Inc.
*
* 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. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
*
* @(#)time.h 8.3 (Berkeley) 1/21/94
*/
/*
* $FreeBSD$
*/
#ifndef _TIMECONV_H_
#define _TIMECONV_H_
#include <sys/cdefs.h>
#include <stdint.h>
#include <time.h>
time_t _time32_to_time(int32_t t32);
int32_t _time_to_time32(time_t t);
time_t _time64_to_time(int64_t t64);
int64_t _time_to_time64(time_t t);
long _time_to_long(time_t t);
time_t _long_to_time(long tlong);
int _time_to_int(time_t t);
time_t _int_to_time(int tint);
#endif /* _TIMECONV_H_ */

View File

@@ -34,7 +34,11 @@
#ifndef LIBBSD_UNISTD_H #ifndef LIBBSD_UNISTD_H
#define LIBBSD_UNISTD_H #define LIBBSD_UNISTD_H
#ifdef LIBBSD_OVERLAY
#include <sys/cdefs.h> #include <sys/cdefs.h>
#else
#include <bsd/sys/cdefs.h>
#endif
#include <sys/stat.h> #include <sys/stat.h>
#ifndef S_ISTXT #ifndef S_ISTXT
@@ -56,7 +60,12 @@ void *setmode(const char *mode_str);
void closefrom(int lowfd); void closefrom(int lowfd);
void setproctitle(const char *fmt, ...); /* Compatibility with sendmail implementations. */
#define initsetproctitle(c, a, e) setproctitle_init((c), (a), (e))
void setproctitle_init(int argc, char *argv[], char *envp[]);
void setproctitle(const char *fmt, ...)
__printflike(1, 2);
int getpeereid(int s, uid_t *euid, gid_t *egid); int getpeereid(int s, uid_t *euid, gid_t *egid);
__END_DECLS __END_DECLS

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright © 2012 Guillem Jover <guillem@hadrons.org> * Copyright © 2012-2013 Guillem Jover <guillem@hadrons.org>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@@ -24,12 +24,18 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#if defined(__need_wchar_t) || defined(__need_wint_t) || \
defined(__need_mbstate_t)
#define LIBBSD_WCHAR_H_SKIP
#endif
#ifdef LIBBSD_OVERLAY #ifdef LIBBSD_OVERLAY
#include_next <wchar.h> #include_next <wchar.h>
#else #else
#include <wchar.h> #include <wchar.h>
#endif #endif
#ifndef LIBBSD_WCHAR_H_SKIP
#ifndef LIBBSD_WCHAR_H #ifndef LIBBSD_WCHAR_H
#define LIBBSD_WCHAR_H #define LIBBSD_WCHAR_H
@@ -45,3 +51,5 @@ size_t wcslcpy(wchar_t *dst, const wchar_t *src, size_t size);
__END_DECLS __END_DECLS
#endif #endif
#endif
#undef LIBBSD_WCHAR_H_SKIP

View File

@@ -23,11 +23,14 @@ dist_man_MANS = \
closefrom.3 \ closefrom.3 \
dehumanize_number.3 \ dehumanize_number.3 \
expand_number.3 \ expand_number.3 \
explicit_bzero.3 \
fgetln.3 \ fgetln.3 \
fgetwln.3 \ fgetwln.3 \
flopen.3 \ flopen.3 \
fmtcheck.3 \ fmtcheck.3 \
fparseln.3 \ fparseln.3 \
funopen.3bsd \
getbsize.3 \
getmode.3 \ getmode.3 \
getpeereid.3 \ getpeereid.3 \
getprogname.3 \ getprogname.3 \
@@ -40,11 +43,13 @@ dist_man_MANS = \
queue.3bsd \ queue.3bsd \
radixsort.3 \ radixsort.3 \
readpassphrase.3 \ readpassphrase.3 \
reallocarray.3 \
reallocf.3 \ reallocf.3 \
setmode.3 \ setmode.3 \
setproctitle.3 \ setproctitle.3 \
setprogname.3 \ setprogname.3 \
sradixsort.3 \ sradixsort.3 \
stringlist.3 \
strlcat.3 \ strlcat.3 \
strlcpy.3 \ strlcpy.3 \
strnstr.3 \ strnstr.3 \

View File

@@ -1,4 +1,5 @@
.\" $OpenBSD: arc4random.3,v 1.2 1997/04/27 22:40:25 angelos Exp $ .\" $OpenBSD: arc4random.3,v 1.34 2014/07/19 16:11:16 naddy Exp $
.\"
.\" Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> .\" Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
.\" All rights reserved. .\" All rights reserved.
.\" .\"
@@ -28,9 +29,8 @@
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\" .\"
.\" Manual page, using -mandoc macros .\" Manual page, using -mandoc macros
.\" $FreeBSD$
.\" .\"
.Dd April 15, 1997 .Dd $Mdocdate: July 19 2014 $
.Dt ARC4RANDOM 3 .Dt ARC4RANDOM 3
.Os .Os
.Sh NAME .Sh NAME
@@ -45,56 +45,70 @@
.Lb libbsd .Lb libbsd
.Sh SYNOPSIS .Sh SYNOPSIS
.In bsd/stdlib.h .In bsd/stdlib.h
.Ft u_int32_t .Ft uint32_t
.Fn arc4random "void" .Fn arc4random "void"
.Ft void .Ft void
.Fn arc4random_buf "void *buf" "size_t nbytes" .Fn arc4random_buf "void *buf" "size_t nbytes"
.Ft u_int32_t .Ft uint32_t
.Fn arc4random_uniform "u_int32_t upper_bound" .Fn arc4random_uniform "uint32_t upper_bound"
.Ft void .Ft void
.Fn arc4random_stir "void" .Fn arc4random_stir "void"
.Ft void .Ft void
.Fn arc4random_addrandom "unsigned char *dat" "int datlen" .Fn arc4random_addrandom "unsigned char *dat" "int datlen"
.Sh DESCRIPTION .Sh DESCRIPTION
The This family of functions provides higher quality data than those
.Fn arc4random described in
function uses the key stream generator employed by the .Xr rand 3 ,
arc4 cipher, which uses 8*8 8 bit S-Boxes. .Xr random 3 ,
The S-Boxes
can be in about
.if t 2\u\s71700\s10\d
.if n (2**1700)
states.
The
.Fn arc4random
function returns pseudo-random numbers in the range of 0 to
.if t 2\u\s731\s10\d\(mi1,
.if n (2**32)\(mi1,
and therefore has twice the range of
.Xr rand 3
and and
.Xr random 3 . .Xr rand48 3 .
.Pp .Pp
Use of these functions is encouraged for almost all random number
consumption because the other interfaces are deficient in either
quality, portability, standardization, or availability.
These functions can be called in almost all coding environments,
including
.Xr pthreads 3
and
.Xr chroot 2 .
.Pp
High quality 32-bit pseudo-random numbers are generated very quickly.
On each call, a cryptographic pseudo-random number generator is used
to generate a new result.
One data pool is used for all consumers in a process, so that consumption
under program flow can act as additional stirring.
The subsystem is re-seeded from the kernel random number subsystem using
.Xr getentropy 2
on a regular basis, and also upon
.Xr fork 2 .
.Pp
The
.Fn arc4random
function returns a single 32-bit value.
.Pp
The
.Fn arc4random_buf .Fn arc4random_buf
function fills the region function fills the region
.Fa buf .Fa buf
of length of length
.Fa nbytes .Fa nbytes
with ARC4-derived random data. with random data.
.Pp .Pp
.Fn arc4random_uniform .Fn arc4random_uniform
will return a uniformly distributed random number less than will return a single 32-bit value, uniformly distributed but less than
.Fa upper_bound . .Fa upper_bound .
.Fn arc4random_uniform This is recommended over constructions like
is recommended over constructions like
.Dq Li arc4random() % upper_bound .Dq Li arc4random() % upper_bound
as it avoids "modulo bias" when the upper bound is not a power of two. as it avoids "modulo bias" when the upper bound is not a power of two.
In the worst case, this function may consume multiple iterations
to ensure uniformity; see the source code to understand the problem
and solution.
.Pp .Pp
The The
.Fn arc4random_stir .Fn arc4random_stir
function reads data from function reads data from
.Pa /dev/urandom .Xr getentropy 2
and uses it to permute the S-Boxes via and uses it to re-seed the subsystem via
.Fn arc4random_addrandom . .Fn arc4random_addrandom .
.Pp .Pp
There is no need to call There is no need to call
@@ -103,26 +117,22 @@ before using
.Fn arc4random .Fn arc4random
functions family, since functions family, since
they automatically initialize themselves. they automatically initialize themselves.
.Sh EXAMPLES .Sh RETURN VALUES
The following produces a drop-in replacement for the traditional These functions are always successful, and no return value is
.Fn rand reserved to indicate an error.
and
.Fn random
functions using
.Fn arc4random :
.Pp
.Dl "#define foo4random() (arc4random() % ((unsigned)RAND_MAX + 1))"
.Sh SEE ALSO .Sh SEE ALSO
.Xr rand 3 , .Xr rand 3 ,
.Xr random 3 , .Xr rand48 3 ,
.Xr srandomdev 3 .Xr random 3
.Sh HISTORY .Sh HISTORY
.Pa RC4 These functions first appeared in
has been designed by RSA Data Security, Inc. .Ox 2.1 .
It was posted anonymously .Pp
to the USENET and was confirmed to be equivalent by several sources who The original version of this random number generator used the
had access to the original cipher. RC4 (also known as ARC4) algorithm.
Since In
.Pa RC4 .Ox 5.5
used to be a trade secret, the cipher is now referred to as it was replaced with the ChaCha20 cipher, and it may be replaced
.Pa ARC4 . again in the future as cryptographic techniques advance.
A good mnemonic is
.Dq A Replacement Call for Random .

72
man/explicit_bzero.3 Normal file
View File

@@ -0,0 +1,72 @@
.\" Copyright (c) 1990, 1991 The Regents of the University of California.
.\" All rights reserved.
.\"
.\" This code is derived from software contributed to Berkeley by
.\" Chris Torek.
.\" 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. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
.\"
.\" $OpenBSD: bzero.3,v 1.10 2014/01/22 21:06:45 tedu Exp $
.\"
.Dd $Mdocdate: January 22 2014 $
.Dt BZERO 3
.Os
.Sh NAME
.Nm explicit_bzero
.Nd write zeroes to a byte string
.Sh LIBRARY
.ds str-Lb-libbsd Utility functions from BSD systems (libbsd, \-lbsd)
.Lb libbsd
.Sh SYNOPSIS
.In bsd/string.h
.Ft void
.Fn explicit_bzero "void *buf" "size_t len"
.Sh DESCRIPTION
The
.Fn explicit_bzero
function writes
.Fa len
zero bytes to the string
.Fa buf .
If
.Fa len
is zero,
.Fn explicit_bzero
does nothing.
.Pp
The
.Fn explicit_bzero
variant behaves the same as the
.Fn bzero
function, but will not be removed by a compiler's dead store optimization
pass, making it useful for clearing sensitive memory such as a password.
.Sh SEE ALSO
.Xr bzero 3 ,
.Xr memset 3 ,
.Xr swab 3
.Sh HISTORY
The
.Fn explicit_bzero
function first appeared in
.Ox 5.5 .

View File

@@ -126,9 +126,9 @@ is returned.
The The
.Fn fparseln .Fn fparseln
function uses internally function uses internally
.Xr fgetln 3 , .Xr getline 3 ,
so all error conditions that apply to so all error conditions that apply to
.Xr fgetln 3 , .Xr getline 3 ,
apply to apply to
.Fn fparseln . .Fn fparseln .
In addition In addition
@@ -141,7 +141,7 @@ and return
.Dv NULL .Dv NULL
if it runs out of memory. if it runs out of memory.
.Sh SEE ALSO .Sh SEE ALSO
.Xr fgetln 3 .Xr getline 3
.Sh HISTORY .Sh HISTORY
The The
.Fn fparseln .Fn fparseln

191
man/funopen.3bsd Normal file
View File

@@ -0,0 +1,191 @@
.\" Copyright (c) 1990, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
.\" This code is derived from software contributed to Berkeley by
.\" Chris Torek.
.\" 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.
.\" 4. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
.\"
.\" @(#)funopen.3 8.1 (Berkeley) 6/9/93
.\" $FreeBSD$
.\"
.Dd March 19, 2004
.Dt FUNOPEN 3
.Os
.Sh NAME
.Nm funopen ,
.Nm fropen ,
.Nm fwopen
.Nd open a stream
.Sh LIBRARY
.ds str-Lb-libbsd Utility functions from BSD systems (libbsd, \-lbsd)
.Lb libbsd
.Sh SYNOPSIS
.In bsd/stdio.h
.Ft FILE *
.Fn funopen "const void *cookie" "int (*readfn)(void *, char *, int)" "int (*writefn)(void *, const char *, int)" "off_t (*seekfn)(void *, off_t, int)" "int (*closefn)(void *)"
.Ft FILE *
.Fn fropen "void *cookie" "int (*readfn)(void *, char *, int)"
.Ft FILE *
.Fn fwopen "void *cookie" "int (*writefn)(void *, const char *, int)"
.Sh DESCRIPTION
The
.Fn funopen
function
associates a stream with up to four
.Dq Tn I/O No functions .
Either
.Fa readfn
or
.Fa writefn
must be specified;
the others can be given as an appropriately-typed
.Dv NULL
pointer.
These
.Tn I/O
functions will be used to read, write, seek and
close the new stream.
.Pp
In general, omitting a function means that any attempt to perform the
associated operation on the resulting stream will fail.
If the close function is omitted, closing the stream will flush
any buffered output and then succeed.
.Pp
The calling conventions of
.Fa readfn ,
.Fa writefn ,
.Fa seekfn
and
.Fa closefn
must match those, respectively, of
.Xr read 2 ,
.Xr write 2 ,
.Xr lseek 2 ,
and
.Xr close 2
with the single exception that they are passed the
.Fa cookie
argument specified to
.Fn funopen
in place of the traditional file descriptor argument.
.Pp
Read and write
.Tn I/O
functions are allowed to change the underlying buffer
on fully buffered or line buffered streams by calling
.Xr setvbuf 3 .
They are also not required to completely fill or empty the buffer.
They are not, however, allowed to change streams from unbuffered to buffered
or to change the state of the line buffering flag.
They must also be prepared to have read or write calls occur on buffers other
than the one most recently specified.
.Pp
All user
.Tn I/O
functions can report an error by returning \-1.
Additionally, all of the functions should set the external variable
.Va errno
appropriately if an error occurs.
.Pp
An error on
.Fn closefn
does not keep the stream open.
.Pp
As a convenience, the include file
.In stdio.h
defines the macros
.Fn fropen
and
.Fn fwopen
as calls to
.Fn funopen
with only a read or write function specified.
.Sh RETURN VALUES
Upon successful completion,
.Fn funopen
returns a
.Dv FILE
pointer.
Otherwise,
.Dv NULL
is returned and the global variable
.Va errno
is set to indicate the error.
.Sh ERRORS
.Bl -tag -width Er
.It Bq Er EINVAL
The
.Fn funopen
function
was called without either a read or write function.
The
.Fn funopen
function
may also fail and set
.Va errno
for any of the errors
specified for the routine
.Xr malloc 3 .
.El
.Sh SEE ALSO
.Xr fcntl 2 ,
.Xr open 2 ,
.Xr fclose 3 ,
.Xr fopen 3 ,
.Xr fseek 3 ,
.Xr setbuf 3
.Sh HISTORY
The
.Fn funopen
functions first appeared in
.Bx 4.4 .
.Sh BUGS
The
.Fn funopen
function
may not be portable to systems other than
.Bx .
.Pp
On
.Fx ,
.Ox
and
.Dx
the
.Fn funopen
interface erroneously assumes that
.Vt fpos_t
is an integral type, and uses it in the
.Fa seekfn
hook; but because code using a
.Fa seekfn
hook will fail to build on systems where
.Vt fpos_t
is a struct, and it will need to be slightly fixed anyway, the
implementation provided by libbsd (in the same way as
.Nx )
uses the correct
.Vt off_t
types.

95
man/getbsize.3 Normal file
View File

@@ -0,0 +1,95 @@
.\" Copyright (c) 1993
.\" The Regents of the University of California. 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. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
.\"
.\" @(#)getbsize.3 8.1 (Berkeley) 6/4/93
.\" $FreeBSD$
.\"
.Dd November 16, 2012
.Dt GETBSIZE 3
.Os
.Sh NAME
.Nm getbsize
.Nd get preferred block size
.Sh LIBRARY
.ds str-Lb-libbsd Utility functions from BSD systems (libbsd, \-lbsd)
.Lb libbsd
.Sh SYNOPSIS
.In bsd/stdlib.h
.Ft char *
.Fn getbsize "int *headerlenp" "long *blocksizep"
.Sh DESCRIPTION
The
.Fn getbsize
function returns a preferred block size for reporting by system utilities
.Xr df 1 ,
.Xr du 1 ,
.Xr ls 1
and
.Xr systat 1 ,
based on the value of the
.Ev BLOCKSIZE
environment variable.
.Ev BLOCKSIZE
may be specified directly in bytes, or in multiples of a kilobyte by
specifying a number followed by ``K'' or ``k'', in multiples of a
megabyte by specifying a number followed by ``M'' or ``m'' or in
multiples of a gigabyte by specifying a number followed by ``G'' or
``g''.
Multiples must be integers.
.Pp
Valid values of
.Ev BLOCKSIZE
are 512 bytes to 1 gigabyte.
Sizes less than 512 bytes are rounded up to 512 bytes, and sizes
greater than 1 GB are rounded down to 1 GB.
In each case
.Fn getbsize
produces a warning message.
.Pp
The
.Fn getbsize
function returns a pointer to a null-terminated string describing
the block size, something like
.Dq 1K-blocks .
The memory referenced by
.Fa headerlenp
is filled in with the length of the string (not including the
terminating null).
The memory referenced by
.Fa blocksizep
is filled in with block size, in bytes.
.Sh SEE ALSO
.Xr df 1 ,
.Xr du 1 ,
.Xr ls 1 ,
.Xr systat 1 ,
.Xr environ 7
.Sh HISTORY
The
.Fn getbsize
function first appeared in
.Bx 4.4 .

View File

@@ -32,13 +32,13 @@
.Ft void .Ft void
.Fn MDXInit "MDX_CTX *context" .Fn MDXInit "MDX_CTX *context"
.Ft void .Ft void
.Fn MDXUpdate "MDX_CTX *context" "const u_int8_t *data" "size_t len" .Fn MDXUpdate "MDX_CTX *context" "const uint8_t *data" "size_t len"
.Ft void .Ft void
.Fn MDXPad "MDX_CTX *context" .Fn MDXPad "MDX_CTX *context"
.Ft void .Ft void
.Fn MDXFinal "u_int8_t digest[MDX_DIGEST_LENGTH]" "MDX_CTX *context" .Fn MDXFinal "uint8_t digest[MDX_DIGEST_LENGTH]" "MDX_CTX *context"
.Ft void .Ft void
.Fn MDXTransform "u_int32_t state[4]" "u_int8_t block[MDX_BLOCK_LENGTH]" .Fn MDXTransform "uint32_t state[4]" "uint8_t block[MDX_BLOCK_LENGTH]"
.Ft "char *" .Ft "char *"
.Fn MDXEnd "MDX_CTX *context" "char *buf" .Fn MDXEnd "MDX_CTX *context" "char *buf"
.Ft "char *" .Ft "char *"
@@ -46,7 +46,7 @@
.Ft "char *" .Ft "char *"
.Fn MDXFileChunk "const char *filename" "char *buf" "off_t offset" "off_t length" .Fn MDXFileChunk "const char *filename" "char *buf" "off_t offset" "off_t length"
.Ft "char *" .Ft "char *"
.Fn MDXData "const u_int8_t *data" "size_t len" "char *buf" .Fn MDXData "const uint8_t *data" "size_t len" "char *buf"
.Sh DESCRIPTION .Sh DESCRIPTION
The MDX functions calculate a 128-bit cryptographic checksum (digest) The MDX functions calculate a 128-bit cryptographic checksum (digest)
for any number of input bytes. for any number of input bytes.

View File

@@ -9,7 +9,7 @@
.\" 2. Redistributions in binary form must reproduce the above copyright .\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the .\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution. .\" documentation and/or other materials provided with the distribution.
.\" 4. Neither the name of the University nor the names of its contributors .\" 3. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software .\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission. .\" without specific prior written permission.
.\" .\"
@@ -28,15 +28,17 @@
.\" @(#)queue.3 8.2 (Berkeley) 1/24/94 .\" @(#)queue.3 8.2 (Berkeley) 1/24/94
.\" $FreeBSD$ .\" $FreeBSD$
.\" .\"
.Dd May 13, 2011 .Dd June 17, 2013
.Dt QUEUE 3bsd .Dt QUEUE 3
.Os .Os
.Sh NAME .Sh NAME
.Nm SLIST_EMPTY , .Nm SLIST_EMPTY ,
.Nm SLIST_ENTRY , .Nm SLIST_ENTRY ,
.Nm SLIST_FIRST , .Nm SLIST_FIRST ,
.Nm SLIST_FOREACH , .Nm SLIST_FOREACH ,
.Nm SLIST_FOREACH_FROM ,
.Nm SLIST_FOREACH_SAFE , .Nm SLIST_FOREACH_SAFE ,
.Nm SLIST_FOREACH_FROM_SAFE ,
.Nm SLIST_HEAD , .Nm SLIST_HEAD ,
.Nm SLIST_HEAD_INITIALIZER , .Nm SLIST_HEAD_INITIALIZER ,
.Nm SLIST_INIT , .Nm SLIST_INIT ,
@@ -52,7 +54,9 @@
.Nm STAILQ_ENTRY , .Nm STAILQ_ENTRY ,
.Nm STAILQ_FIRST , .Nm STAILQ_FIRST ,
.Nm STAILQ_FOREACH , .Nm STAILQ_FOREACH ,
.Nm STAILQ_FOREACH_FROM ,
.Nm STAILQ_FOREACH_SAFE , .Nm STAILQ_FOREACH_SAFE ,
.Nm STAILQ_FOREACH_FROM_SAFE ,
.Nm STAILQ_HEAD , .Nm STAILQ_HEAD ,
.Nm STAILQ_HEAD_INITIALIZER , .Nm STAILQ_HEAD_INITIALIZER ,
.Nm STAILQ_INIT , .Nm STAILQ_INIT ,
@@ -69,7 +73,9 @@
.Nm LIST_ENTRY , .Nm LIST_ENTRY ,
.Nm LIST_FIRST , .Nm LIST_FIRST ,
.Nm LIST_FOREACH , .Nm LIST_FOREACH ,
.Nm LIST_FOREACH_FROM ,
.Nm LIST_FOREACH_SAFE , .Nm LIST_FOREACH_SAFE ,
.Nm LIST_FOREACH_FROM_SAFE ,
.Nm LIST_HEAD , .Nm LIST_HEAD ,
.Nm LIST_HEAD_INITIALIZER , .Nm LIST_HEAD_INITIALIZER ,
.Nm LIST_INIT , .Nm LIST_INIT ,
@@ -77,6 +83,7 @@
.Nm LIST_INSERT_BEFORE , .Nm LIST_INSERT_BEFORE ,
.Nm LIST_INSERT_HEAD , .Nm LIST_INSERT_HEAD ,
.Nm LIST_NEXT , .Nm LIST_NEXT ,
.Nm LIST_PREV ,
.Nm LIST_REMOVE , .Nm LIST_REMOVE ,
.Nm LIST_SWAP , .Nm LIST_SWAP ,
.Nm TAILQ_CONCAT , .Nm TAILQ_CONCAT ,
@@ -84,9 +91,13 @@
.Nm TAILQ_ENTRY , .Nm TAILQ_ENTRY ,
.Nm TAILQ_FIRST , .Nm TAILQ_FIRST ,
.Nm TAILQ_FOREACH , .Nm TAILQ_FOREACH ,
.Nm TAILQ_FOREACH_FROM ,
.Nm TAILQ_FOREACH_SAFE , .Nm TAILQ_FOREACH_SAFE ,
.Nm TAILQ_FOREACH_FROM_SAFE ,
.Nm TAILQ_FOREACH_REVERSE , .Nm TAILQ_FOREACH_REVERSE ,
.Nm TAILQ_FOREACH_REVERSE_FROM ,
.Nm TAILQ_FOREACH_REVERSE_SAFE , .Nm TAILQ_FOREACH_REVERSE_SAFE ,
.Nm TAILQ_FOREACH_REVERSE_FROM_SAFE ,
.Nm TAILQ_HEAD , .Nm TAILQ_HEAD ,
.Nm TAILQ_HEAD_INITIALIZER , .Nm TAILQ_HEAD_INITIALIZER ,
.Nm TAILQ_INIT , .Nm TAILQ_INIT ,
@@ -108,7 +119,9 @@ lists and tail queues
.Fn SLIST_ENTRY "TYPE" .Fn SLIST_ENTRY "TYPE"
.Fn SLIST_FIRST "SLIST_HEAD *head" .Fn SLIST_FIRST "SLIST_HEAD *head"
.Fn SLIST_FOREACH "TYPE *var" "SLIST_HEAD *head" "SLIST_ENTRY NAME" .Fn SLIST_FOREACH "TYPE *var" "SLIST_HEAD *head" "SLIST_ENTRY NAME"
.Fn SLIST_FOREACH_FROM "TYPE *var" "SLIST_HEAD *head" "SLIST_ENTRY NAME"
.Fn SLIST_FOREACH_SAFE "TYPE *var" "SLIST_HEAD *head" "SLIST_ENTRY NAME" "TYPE *temp_var" .Fn SLIST_FOREACH_SAFE "TYPE *var" "SLIST_HEAD *head" "SLIST_ENTRY NAME" "TYPE *temp_var"
.Fn SLIST_FOREACH_FROM_SAFE "TYPE *var" "SLIST_HEAD *head" "SLIST_ENTRY NAME" "TYPE *temp_var"
.Fn SLIST_HEAD "HEADNAME" "TYPE" .Fn SLIST_HEAD "HEADNAME" "TYPE"
.Fn SLIST_HEAD_INITIALIZER "SLIST_HEAD head" .Fn SLIST_HEAD_INITIALIZER "SLIST_HEAD head"
.Fn SLIST_INIT "SLIST_HEAD *head" .Fn SLIST_INIT "SLIST_HEAD *head"
@@ -125,7 +138,9 @@ lists and tail queues
.Fn STAILQ_ENTRY "TYPE" .Fn STAILQ_ENTRY "TYPE"
.Fn STAILQ_FIRST "STAILQ_HEAD *head" .Fn STAILQ_FIRST "STAILQ_HEAD *head"
.Fn STAILQ_FOREACH "TYPE *var" "STAILQ_HEAD *head" "STAILQ_ENTRY NAME" .Fn STAILQ_FOREACH "TYPE *var" "STAILQ_HEAD *head" "STAILQ_ENTRY NAME"
.Fn STAILQ_FOREACH_FROM "TYPE *var" "STAILQ_HEAD *head" "STAILQ_ENTRY NAME"
.Fn STAILQ_FOREACH_SAFE "TYPE *var" "STAILQ_HEAD *head" "STAILQ_ENTRY NAME" "TYPE *temp_var" .Fn STAILQ_FOREACH_SAFE "TYPE *var" "STAILQ_HEAD *head" "STAILQ_ENTRY NAME" "TYPE *temp_var"
.Fn STAILQ_FOREACH_FROM_SAFE "TYPE *var" "STAILQ_HEAD *head" "STAILQ_ENTRY NAME" "TYPE *temp_var"
.Fn STAILQ_HEAD "HEADNAME" "TYPE" .Fn STAILQ_HEAD "HEADNAME" "TYPE"
.Fn STAILQ_HEAD_INITIALIZER "STAILQ_HEAD head" .Fn STAILQ_HEAD_INITIALIZER "STAILQ_HEAD head"
.Fn STAILQ_INIT "STAILQ_HEAD *head" .Fn STAILQ_INIT "STAILQ_HEAD *head"
@@ -143,7 +158,9 @@ lists and tail queues
.Fn LIST_ENTRY "TYPE" .Fn LIST_ENTRY "TYPE"
.Fn LIST_FIRST "LIST_HEAD *head" .Fn LIST_FIRST "LIST_HEAD *head"
.Fn LIST_FOREACH "TYPE *var" "LIST_HEAD *head" "LIST_ENTRY NAME" .Fn LIST_FOREACH "TYPE *var" "LIST_HEAD *head" "LIST_ENTRY NAME"
.Fn LIST_FOREACH_FROM "TYPE *var" "LIST_HEAD *head" "LIST_ENTRY NAME"
.Fn LIST_FOREACH_SAFE "TYPE *var" "LIST_HEAD *head" "LIST_ENTRY NAME" "TYPE *temp_var" .Fn LIST_FOREACH_SAFE "TYPE *var" "LIST_HEAD *head" "LIST_ENTRY NAME" "TYPE *temp_var"
.Fn LIST_FOREACH_FROM_SAFE "TYPE *var" "LIST_HEAD *head" "LIST_ENTRY NAME" "TYPE *temp_var"
.Fn LIST_HEAD "HEADNAME" "TYPE" .Fn LIST_HEAD "HEADNAME" "TYPE"
.Fn LIST_HEAD_INITIALIZER "LIST_HEAD head" .Fn LIST_HEAD_INITIALIZER "LIST_HEAD head"
.Fn LIST_INIT "LIST_HEAD *head" .Fn LIST_INIT "LIST_HEAD *head"
@@ -151,6 +168,7 @@ lists and tail queues
.Fn LIST_INSERT_BEFORE "TYPE *listelm" "TYPE *elm" "LIST_ENTRY NAME" .Fn LIST_INSERT_BEFORE "TYPE *listelm" "TYPE *elm" "LIST_ENTRY NAME"
.Fn LIST_INSERT_HEAD "LIST_HEAD *head" "TYPE *elm" "LIST_ENTRY NAME" .Fn LIST_INSERT_HEAD "LIST_HEAD *head" "TYPE *elm" "LIST_ENTRY NAME"
.Fn LIST_NEXT "TYPE *elm" "LIST_ENTRY NAME" .Fn LIST_NEXT "TYPE *elm" "LIST_ENTRY NAME"
.Fn LIST_PREV "TYPE *elm" "LIST_HEAD *head" "TYPE" "LIST_ENTRY NAME"
.Fn LIST_REMOVE "TYPE *elm" "LIST_ENTRY NAME" .Fn LIST_REMOVE "TYPE *elm" "LIST_ENTRY NAME"
.Fn LIST_SWAP "LIST_HEAD *head1" "LIST_HEAD *head2" "TYPE" "LIST_ENTRY NAME" .Fn LIST_SWAP "LIST_HEAD *head1" "LIST_HEAD *head2" "TYPE" "LIST_ENTRY NAME"
.\" .\"
@@ -159,9 +177,13 @@ lists and tail queues
.Fn TAILQ_ENTRY "TYPE" .Fn TAILQ_ENTRY "TYPE"
.Fn TAILQ_FIRST "TAILQ_HEAD *head" .Fn TAILQ_FIRST "TAILQ_HEAD *head"
.Fn TAILQ_FOREACH "TYPE *var" "TAILQ_HEAD *head" "TAILQ_ENTRY NAME" .Fn TAILQ_FOREACH "TYPE *var" "TAILQ_HEAD *head" "TAILQ_ENTRY NAME"
.Fn TAILQ_FOREACH_FROM "TYPE *var" "TAILQ_HEAD *head" "TAILQ_ENTRY NAME"
.Fn TAILQ_FOREACH_SAFE "TYPE *var" "TAILQ_HEAD *head" "TAILQ_ENTRY NAME" "TYPE *temp_var" .Fn TAILQ_FOREACH_SAFE "TYPE *var" "TAILQ_HEAD *head" "TAILQ_ENTRY NAME" "TYPE *temp_var"
.Fn TAILQ_FOREACH_FROM_SAFE "TYPE *var" "TAILQ_HEAD *head" "TAILQ_ENTRY NAME" "TYPE *temp_var"
.Fn TAILQ_FOREACH_REVERSE "TYPE *var" "TAILQ_HEAD *head" "HEADNAME" "TAILQ_ENTRY NAME" .Fn TAILQ_FOREACH_REVERSE "TYPE *var" "TAILQ_HEAD *head" "HEADNAME" "TAILQ_ENTRY NAME"
.Fn TAILQ_FOREACH_REVERSE_FROM "TYPE *var" "TAILQ_HEAD *head" "HEADNAME" "TAILQ_ENTRY NAME"
.Fn TAILQ_FOREACH_REVERSE_SAFE "TYPE *var" "TAILQ_HEAD *head" "HEADNAME" "TAILQ_ENTRY NAME" "TYPE *temp_var" .Fn TAILQ_FOREACH_REVERSE_SAFE "TYPE *var" "TAILQ_HEAD *head" "HEADNAME" "TAILQ_ENTRY NAME" "TYPE *temp_var"
.Fn TAILQ_FOREACH_REVERSE_FROM_SAFE "TYPE *var" "TAILQ_HEAD *head" "HEADNAME" "TAILQ_ENTRY NAME" "TYPE *temp_var"
.Fn TAILQ_HEAD "HEADNAME" "TYPE" .Fn TAILQ_HEAD "HEADNAME" "TYPE"
.Fn TAILQ_HEAD_INITIALIZER "TAILQ_HEAD head" .Fn TAILQ_HEAD_INITIALIZER "TAILQ_HEAD head"
.Fn TAILQ_INIT "TAILQ_HEAD *head" .Fn TAILQ_INIT "TAILQ_HEAD *head"
@@ -244,8 +266,18 @@ Code size and execution time of operations (except for removal) is about
twice that of the singly-linked data-structures. twice that of the singly-linked data-structures.
.El .El
.Pp .Pp
Linked lists are the simplest of the doubly linked data structures and support Linked lists are the simplest of the doubly linked data structures.
only the above functionality over singly-linked lists. They add the following functionality over the above:
.Bl -enum -compact -offset indent
.It
They may be traversed backwards.
.El
However:
.Bl -enum -compact -offset indent
.It
To traverse backwards, an entry to begin the traversal and the list in
which it is contained must be specified.
.El
.Pp .Pp
Tail queues add the following functionality: Tail queues add the following functionality:
.Bl -enum -compact -offset indent .Bl -enum -compact -offset indent
@@ -349,6 +381,19 @@ turn to
.Fa var . .Fa var .
.Pp .Pp
The macro The macro
.Nm SLIST_FOREACH_FROM
behaves identically to
.Nm SLIST_FOREACH
when
.Fa var
is NULL, else it treats
.Fa var
as a previously found SLIST element and begins the loop at
.Fa var
instead of the first element in the SLIST referenced by
.Fa head .
.Pp
The macro
.Nm SLIST_FOREACH_SAFE .Nm SLIST_FOREACH_SAFE
traverses the list referenced by traverses the list referenced by
.Fa head .Fa head
@@ -363,6 +408,19 @@ as well as free it from within the loop safely without interfering with the
traversal. traversal.
.Pp .Pp
The macro The macro
.Nm SLIST_FOREACH_FROM_SAFE
behaves identically to
.Nm SLIST_FOREACH_SAFE
when
.Fa var
is NULL, else it treats
.Fa var
as a previously found SLIST element and begins the loop at
.Fa var
instead of the first element in the SLIST referenced by
.Fa head .
.Pp
The macro
.Nm SLIST_INIT .Nm SLIST_INIT
initializes the list referenced by initializes the list referenced by
.Fa head . .Fa head .
@@ -388,7 +446,8 @@ The macro
.Nm SLIST_REMOVE_AFTER .Nm SLIST_REMOVE_AFTER
removes the element after removes the element after
.Fa elm .Fa elm
from the list. Unlike from the list.
Unlike
.Fa SLIST_REMOVE , .Fa SLIST_REMOVE ,
this macro does not traverse the entire list. this macro does not traverse the entire list.
.Pp .Pp
@@ -528,6 +587,19 @@ in turn to
.Fa var . .Fa var .
.Pp .Pp
The macro The macro
.Nm STAILQ_FOREACH_FROM
behaves identically to
.Nm STAILQ_FOREACH
when
.Fa var
is NULL, else it treats
.Fa var
as a previously found STAILQ element and begins the loop at
.Fa var
instead of the first element in the STAILQ referenced by
.Fa head .
.Pp
The macro
.Nm STAILQ_FOREACH_SAFE .Nm STAILQ_FOREACH_SAFE
traverses the tail queue referenced by traverses the tail queue referenced by
.Fa head .Fa head
@@ -542,6 +614,19 @@ as well as free it from within the loop safely without interfering with the
traversal. traversal.
.Pp .Pp
The macro The macro
.Nm STAILQ_FOREACH_FROM_SAFE
behaves identically to
.Nm STAILQ_FOREACH_SAFE
when
.Fa var
is NULL, else it treats
.Fa var
as a previously found STAILQ element and begins the loop at
.Fa var
instead of the first element in the STAILQ referenced by
.Fa head .
.Pp
The macro
.Nm STAILQ_INIT .Nm STAILQ_INIT
initializes the tail queue referenced by initializes the tail queue referenced by
.Fa head . .Fa head .
@@ -579,7 +664,8 @@ The macro
.Nm STAILQ_REMOVE_AFTER .Nm STAILQ_REMOVE_AFTER
removes the element after removes the element after
.Fa elm .Fa elm
from the tail queue. Unlike from the tail queue.
Unlike
.Fa STAILQ_REMOVE , .Fa STAILQ_REMOVE ,
this macro does not traverse the entire tail queue. this macro does not traverse the entire tail queue.
.Pp .Pp
@@ -717,6 +803,19 @@ in the forward direction, assigning each element in turn to
.Fa var . .Fa var .
.Pp .Pp
The macro The macro
.Nm LIST_FOREACH_FROM
behaves identically to
.Nm LIST_FOREACH
when
.Fa var
is NULL, else it treats
.Fa var
as a previously found LIST element and begins the loop at
.Fa var
instead of the first element in the LIST referenced by
.Fa head .
.Pp
The macro
.Nm LIST_FOREACH_SAFE .Nm LIST_FOREACH_SAFE
traverses the list referenced by traverses the list referenced by
.Fa head .Fa head
@@ -730,6 +829,19 @@ as well as free it from within the loop safely without interfering with the
traversal. traversal.
.Pp .Pp
The macro The macro
.Nm LIST_FOREACH_FROM_SAFE
behaves identically to
.Nm LIST_FOREACH_SAFE
when
.Fa var
is NULL, else it treats
.Fa var
as a previously found LIST element and begins the loop at
.Fa var
instead of the first element in the LIST referenced by
.Fa head .
.Pp
The macro
.Nm LIST_INIT .Nm LIST_INIT
initializes the list referenced by initializes the list referenced by
.Fa head . .Fa head .
@@ -759,6 +871,14 @@ The macro
returns the next element in the list, or NULL if this is the last. returns the next element in the list, or NULL if this is the last.
.Pp .Pp
The macro The macro
.Nm LIST_PREV
returns the previous element in the list, or NULL if this is the first.
List
.Fa head
must contain element
.Fa elm .
.Pp
The macro
.Nm LIST_REMOVE .Nm LIST_REMOVE
removes the element removes the element
.Fa elm .Fa elm
@@ -894,12 +1014,38 @@ is set to
if the loop completes normally, or if there were no elements. if the loop completes normally, or if there were no elements.
.Pp .Pp
The macro The macro
.Nm TAILQ_FOREACH_FROM
behaves identically to
.Nm TAILQ_FOREACH
when
.Fa var
is NULL, else it treats
.Fa var
as a previously found TAILQ element and begins the loop at
.Fa var
instead of the first element in the TAILQ referenced by
.Fa head .
.Pp
The macro
.Nm TAILQ_FOREACH_REVERSE .Nm TAILQ_FOREACH_REVERSE
traverses the tail queue referenced by traverses the tail queue referenced by
.Fa head .Fa head
in the reverse direction, assigning each element in turn to in the reverse direction, assigning each element in turn to
.Fa var . .Fa var .
.Pp .Pp
The macro
.Nm TAILQ_FOREACH_REVERSE_FROM
behaves identically to
.Nm TAILQ_FOREACH_REVERSE
when
.Fa var
is NULL, else it treats
.Fa var
as a previously found TAILQ element and begins the reverse loop at
.Fa var
instead of the last element in the TAILQ referenced by
.Fa head .
.Pp
The macros The macros
.Nm TAILQ_FOREACH_SAFE .Nm TAILQ_FOREACH_SAFE
and and
@@ -919,6 +1065,32 @@ as well as free it from within the loop safely without interfering with the
traversal. traversal.
.Pp .Pp
The macro The macro
.Nm TAILQ_FOREACH_FROM_SAFE
behaves identically to
.Nm TAILQ_FOREACH_SAFE
when
.Fa var
is NULL, else it treats
.Fa var
as a previously found TAILQ element and begins the loop at
.Fa var
instead of the first element in the TAILQ referenced by
.Fa head .
.Pp
The macro
.Nm TAILQ_FOREACH_REVERSE_FROM_SAFE
behaves identically to
.Nm TAILQ_FOREACH_REVERSE_SAFE
when
.Fa var
is NULL, else it treats
.Fa var
as a previously found TAILQ element and begins the reverse loop at
.Fa var
instead of the last element in the TAILQ referenced by
.Fa head .
.Pp
The macro
.Nm TAILQ_INIT .Nm TAILQ_INIT
initializes the tail queue referenced by initializes the tail queue referenced by
.Fa head . .Fa head .

102
man/reallocarray.3 Normal file
View File

@@ -0,0 +1,102 @@
.\"
.\" Copyright (c) 1980, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
.\" This code is derived from software contributed to Berkeley by
.\" the American National Standards Committee X3, on Information
.\" Processing Systems.
.\"
.\" 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. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
.\"
.\" $OpenBSD: malloc.3,v 1.78 2014/05/01 18:41:59 jmc Exp $
.\"
.Dd $Mdocdate: May 1 2014 $
.Dt MALLOC 3
.Os
.Sh NAME
.Nm reallocarray
.Nd memory allocation and deallocation
.Sh LIBRARY
.ds str-Lb-libbsd Utility functions from BSD systems (libbsd, \-lbsd)
.Lb libbsd
.Sh SYNOPSIS
.In bsd/stdlib.h
.Ft void *
.Fn reallocarray "void *ptr" "size_t nmemb" "size_t size"
.Sh DESCRIPTION
.Pp
When using
.Fn malloc
be careful to avoid the following idiom:
.Bd -literal -offset indent
if ((p = malloc(num * size)) == NULL)
err(1, "malloc");
.Ed
.Pp
The multiplication may lead to an integer overflow, which can
be avoided using the extension
.Fn reallocarray ,
as follows:
.Bd -literal -offset indent
if ((p = reallocarray(NULL, num, size)) == NULL)
err(1, "malloc");
.Ed
.Pp
Alternatively
.Fn calloc
is a more portable solution which comes with the cost of clearing memory.
.Pp
If
.Fn malloc
must be used, be sure to test for overflow:
.Bd -literal -offset indent
if (size && num > SIZE_MAX / size) {
errno = ENOMEM;
err(1, "overflow");
}
.Ed
.Pp
The use of
.Fn reallocarray
or
.Fn calloc
is strongly encouraged when allocating multiple sized objects
in order to avoid possible integer overflows.
.Sh RETURN VALUES
The
.Fn reallocarray
function returns a pointer to the allocated space if successful; otherwise,
a null pointer is returned and
.Va errno
is set to
.Er ENOMEM .
.Sh SEE ALSO
.Xr malloc 3 ,
.Xr calloc 3 ,
.Xr alloca 3
.Sh HISTORY
.Fn reallocarray
appeared in
.Ox 5.6 .

View File

@@ -33,6 +33,8 @@
.In sys/types.h .In sys/types.h
.In bsd/unistd.h .In bsd/unistd.h
.Ft void .Ft void
.Fn setproctitle_init "int argc" "char *argv[]" "char *envp[]"
.Ft void
.Fn setproctitle "const char *fmt" "..." .Fn setproctitle "const char *fmt" "..."
.Sh DESCRIPTION .Sh DESCRIPTION
The The
@@ -41,6 +43,15 @@ library routine sets the process title that appears on the
.Xr ps 1 .Xr ps 1
command. command.
.Pp .Pp
The
.Fn setproctitle_init
library routine only needs to be called (before any call to
.Fn setproctitle
and with
.Fn main
arguments), if the automatic constructor support has not
been linked in through the libbsd-ctor pkg-config file.
.Pp
The title is set from the executable's name, followed by the The title is set from the executable's name, followed by the
result of a result of a
.Xr printf 3 .Xr printf 3
@@ -101,6 +112,11 @@ first appeared in
.Fx 2.2 . .Fx 2.2 .
Other operating systems have Other operating systems have
similar functions. similar functions.
.Pp
The
.Fn setproctitle_init
function is a libbsd extension not present on the BSDs, avoid using it
in portable code.
.Sh AUTHORS .Sh AUTHORS
.An -nosplit .An -nosplit
.An Peter Wemm Aq peter@FreeBSD.org .An Peter Wemm Aq peter@FreeBSD.org

147
man/stringlist.3 Normal file
View File

@@ -0,0 +1,147 @@
.\" $NetBSD: stringlist.3,v 1.15 2010/05/06 09:46:49 jruoho Exp $
.\"
.\" Copyright (c) 1997, 1999 The NetBSD Foundation, Inc.
.\" All rights reserved.
.\"
.\" This file was contributed to The NetBSD Foundation by Luke Mewburn.
.\"
.\" 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.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
.\" ``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 FOUNDATION OR CONTRIBUTORS
.\" 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.
.\"
.Dd May 6, 2010
.Dt STRINGLIST 3
.Os
.Sh NAME
.Nm stringlist ,
.Nm sl_init ,
.Nm sl_add ,
.Nm sl_free ,
.Nm sl_find ,
.Nm sl_delete
.Nd stringlist manipulation functions
.Sh LIBRARY
.ds str-Lb-libbsd Utility functions from BSD systems (libbsd, \-lbsd)
.Lb libbsd
.Sh SYNOPSIS
.In bsd/stringlist.h
.Ft StringList *
.Fn sl_init "void"
.Ft int
.Fn sl_add "StringList *sl" "char *item"
.Ft void
.Fn sl_free "StringList *sl" "int freeall"
.Ft char *
.Fn sl_find "StringList *sl" "const char *item"
.Ft int
.Fn sl_delete "StringList *sl" "const char *item" "int freeit"
.Sh DESCRIPTION
The
.Nm
functions manipulate stringlists, which are lists of
strings that extend automatically if necessary.
.Pp
The
.Ar StringList
structure has the following definition:
.Bd -literal -offset indent
typedef struct _stringlist {
char **sl_str;
size_t sl_max;
size_t sl_cur;
} StringList;
.Ed
.Pp
where:
.Bl -tag -width "sl_str" -offset indent
.It Ar sl_str
is a pointer to the base of the array containing the list,
.It Ar sl_max
is the size of
.Ar sl_str ,
and
.It Ar sl_cur
is the offset in
.Ar sl_str
of the current element.
.El
.Pp
The following stringlist manipulation functions are available:
.Bl -tag -width "sl_delete()" -offset 2n
.It Fn sl_init
Create a stringlist.
Returns a pointer to a
.Ar StringList ,
or
.Dv NULL
in case of failure.
.It Fn sl_free
Releases memory occupied by
.Ar sl
and the
.Ar sl-\*[Gt]sl_str
array.
If
.Ar freeall
is non-zero, then each of the items within
.Ar sl-\*[Gt]sl_str
is released as well.
.It Fn sl_add
Add
.Ar item
to
.Ar sl-\*[Gt]sl_str
at
.Ar sl-\*[Gt]sl_cur ,
extending the size of
.Ar sl-\*[Gt]sl_str .
Returns zero upon success, \-1 upon failure.
.It Fn sl_find
Find
.Ar item
in
.Ar sl ,
returning
.Dv NULL
if it's not found.
.It Fn sl_delete
Remove
.Ar item
from the list.
If
.Ar freeit
is non-zero, the string is freed.
Returns
.Dv 0
if the name is found
and
.Dv \-1
if the name is not found.
.El
.Sh SEE ALSO
.Xr free 3 ,
.Xr malloc 3
.Sh HISTORY
The
.Nm
functions appeared in
.Fx 2.2.6
and
.Nx 1.3 .

View File

@@ -7,11 +7,23 @@ AM_CPPFLAGS = \
-DLIBBSD_OVERLAY -DLIBBSD_DISABLE_DEPRECATED \ -DLIBBSD_OVERLAY -DLIBBSD_DISABLE_DEPRECATED \
-D__REENTRANT -D__REENTRANT
libbsd_la_included_sources = \
hash/helper.c \
getentropy_aix.c \
getentropy_bsd.c \
getentropy_hpux.c \
getentropy_hurd.c \
getentropy_linux.c \
getentropy_osx.c \
getentropy_solaris.c \
$(nil)
EXTRA_DIST = \ EXTRA_DIST = \
libbsd.map \ libbsd.map \
libbsd.pc.in \ libbsd.pc.in \
libbsd-ctor.pc.in \
libbsd-overlay.pc.in \ libbsd-overlay.pc.in \
hash/helper.c \ $(libbsd_la_included_sources) \
$(nil) $(nil)
CLEANFILES = \ CLEANFILES = \
@@ -25,56 +37,88 @@ pkgconfig_DATA = \
$(nil) $(nil)
lib_LTLIBRARIES = libbsd.la lib_LTLIBRARIES = libbsd.la
lib_LIBRARIES =
if BUILD_LIBBSD_CTOR
pkgconfig_DATA += libbsd-ctor.pc
lib_LIBRARIES += libbsd-ctor.a
endif
hash/md5hl.c: $(srcdir)/hash/helper.c hash/md5hl.c: $(srcdir)/hash/helper.c
$(AM_V_at) $(MKDIR_P) hash $(AM_V_at) $(MKDIR_P) hash
$(AM_V_GEN) sed -e 's:hashinc:md5.h:g' -e 's:HASH:MD5:g' $< > $@ $(AM_V_GEN) sed -e 's:hashinc:md5.h:g' -e 's:HASH:MD5:g' $< > $@
libbsd_la_DEPENDENCIES = \ libbsd_la_DEPENDENCIES = \
$(libbsd_la_included_sources) \
libbsd.map libbsd.map
libbsd_la_LDFLAGS = \ libbsd_la_LDFLAGS = \
-Wl,--version-script=$(srcdir)/libbsd.map \ -Wl,--version-script=$(srcdir)/libbsd.map \
-version-number 0:5:1 -version-number $(LIBBSD_ABI)
libbsd_la_SOURCES = \ libbsd_la_SOURCES = \
arc4random.c \ arc4random.c \
arc4random.h \
arc4random_unix.h \
arc4random_openbsd.h \
arc4random_uniform.c \
bsd_getopt.c \ bsd_getopt.c \
chacha_private.h \
closefrom.c \ closefrom.c \
dehumanize_number.c \ dehumanize_number.c \
err.c \ err.c \
expand_number.c \ expand_number.c \
explicit_bzero.c \
fgetln.c \ fgetln.c \
fgetwln.c \ fgetwln.c \
flopen.c \ flopen.c \
fmtcheck.c \ fmtcheck.c \
fparseln.c \ fparseln.c \
fpurge.c \ fpurge.c \
funopen.c \
getbsize.c \
getpeereid.c \ getpeereid.c \
hash/md5.c \ hash/md5.c \
hash/md5hl.c \ hash/md5hl.c \
hash/sha512.h \
hash/sha512c.c \
heapsort.c \ heapsort.c \
humanize_number.c \ humanize_number.c \
inet_net_pton.c \ inet_net_pton.c \
local-elf.h \ local-elf.h \
local-link.h \
merge.c \ merge.c \
nlist.c \ nlist.c \
pidfile.c \ pidfile.c \
progname.c \ progname.c \
radixsort.c \ radixsort.c \
readpassphrase.c \ readpassphrase.c \
reallocarray.c \
reallocf.c \ reallocf.c \
setmode.c \ setmode.c \
setproctitle.c \ setproctitle.c \
strlcat.c \ strlcat.c \
strlcpy.c \ strlcpy.c \
stringlist.c \
strmode.c \ strmode.c \
strnstr.c \ strnstr.c \
strtonum.c \ strtonum.c \
timeconv.c \
unvis.c \ unvis.c \
vis.c \ vis.c \
wcslcat.c \ wcslcat.c \
wcslcpy.c \ wcslcpy.c \
$(nil) $(nil)
if !HAVE_GETENTROPY
libbsd_la_SOURCES += \
getentropy.c \
$(nil)
endif
libbsd_ctor_a_SOURCES = \
setproctitle_ctor.c \
$(nil)
runtimelibdir = $(libdir) runtimelibdir = $(libdir)
install-exec-hook: install-exec-hook:

View File

@@ -1,6 +1,11 @@
/* $OpenBSD: arc4random.c,v 1.53 2015/09/10 18:53:50 bcook Exp $ */
/* /*
* Copyright (c) 1996, David Mazieres <dm@uun.org> * Copyright (c) 1996, David Mazieres <dm@uun.org>
* Copyright (c) 2008, Damien Miller <djm@openbsd.org> * Copyright (c) 2008, Damien Miller <djm@openbsd.org>
* Copyright (c) 2013, Markus Friedl <markus@openbsd.org>
* Copyright (c) 2014, Theo de Raadt <deraadt@openbsd.org>
* Copyright (c) 2015, Guillem Jover <guillem@hadrons.org>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@@ -16,281 +21,192 @@
*/ */
/* /*
* Arc4 random number generator for OpenBSD. * ChaCha based random number generator for OpenBSD.
*
* This code is derived from section 17.1 of Applied Cryptography,
* second edition, which describes a stream cipher allegedly
* compatible with RSA Labs "RC4" cipher (the actual description of
* which is a trade secret). The same algorithm is used as a stream
* cipher called "arcfour" in Tatu Ylonen's ssh package.
*
* Here the stream cipher has been modified always to include the time
* when initializing the state. That makes it impossible to
* regenerate the same random sequence twice, so this can't be used
* for encryption, but will generate good random numbers.
*
* RC4 is a registered trademark of RSA Laboratories.
*/ */
#include <sys/cdefs.h> #include <fcntl.h>
__FBSDID("$FreeBSD$"); #include <limits.h>
#include <signal.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/time.h> #include <sys/time.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <pthread.h>
struct arc4_stream { #define KEYSTREAM_ONLY
u_int8_t i; #include "chacha_private.h"
u_int8_t j;
u_int8_t s[256];
};
#define RANDOMDEV "/dev/urandom" #define minimum(a, b) ((a) < (b) ? (a) : (b))
#define KEYSIZE 128
#ifdef __REENTRANT #if defined(__GNUC__) || defined(_MSC_VER)
static pthread_mutex_t arc4random_mtx = PTHREAD_MUTEX_INITIALIZER; #define inline __inline
#define THREAD_LOCK() pthread_mutex_lock(&arc4random_mtx) #else /* __GNUC__ || _MSC_VER */
#define THREAD_UNLOCK() pthread_mutex_unlock(&arc4random_mtx) #define inline
#else #endif /* !__GNUC__ && !_MSC_VER */
#define THREAD_LOCK()
#define THREAD_UNLOCK() #define KEYSZ 32
#define IVSZ 8
#define BLOCKSZ 64
#define RSBUFSZ (16*BLOCKSZ)
/* Marked MAP_INHERIT_ZERO, so zero'd out in fork children. */
static struct _rs {
size_t rs_have; /* valid bytes at end of rs_buf */
size_t rs_count; /* bytes till reseed */
} *rs;
/* Maybe be preserved in fork children, if _rs_allocate() decides. */
static struct _rsx {
chacha_ctx rs_chacha; /* chacha context for random keystream */
u_char rs_buf[RSBUFSZ]; /* keystream blocks */
} *rsx;
static inline int _rs_allocate(struct _rs **, struct _rsx **);
static inline void _rs_forkdetect(void);
#include "arc4random.h"
static inline void
_rs_init(u_char *buf, size_t n)
{
if (n < KEYSZ + IVSZ)
return;
if (rs == NULL) {
if (_rs_allocate(&rs, &rsx) == -1)
abort();
}
chacha_keysetup(&rsx->rs_chacha, buf, KEYSZ * 8, 0);
chacha_ivsetup(&rsx->rs_chacha, buf + KEYSZ);
}
static inline void
_rs_rekey(u_char *dat, size_t datlen)
{
#ifndef KEYSTREAM_ONLY
memset(rsx->rs_buf, 0, sizeof(rsx->rs_buf));
#endif #endif
/* fill rs_buf with the keystream */
chacha_encrypt_bytes(&rsx->rs_chacha, rsx->rs_buf,
rsx->rs_buf, sizeof(rsx->rs_buf));
/* mix in optional user provided data */
if (dat) {
size_t i, m;
static struct arc4_stream rs; m = minimum(datlen, KEYSZ + IVSZ);
static int rs_initialized; for (i = 0; i < m; i++)
static int rs_stired; rsx->rs_buf[i] ^= dat[i];
static int arc4_count;
static inline u_int8_t arc4_getbyte(void);
static void arc4_stir(void);
static inline void
arc4_init(void)
{
int n;
for (n = 0; n < 256; n++)
rs.s[n] = n;
rs.i = 0;
rs.j = 0;
}
static inline void
arc4_addrandom(u_char *dat, int datlen)
{
int n;
u_int8_t si;
rs.i--;
for (n = 0; n < 256; n++) {
rs.i = (rs.i + 1);
si = rs.s[rs.i];
rs.j = (rs.j + si + dat[n % datlen]);
rs.s[rs.i] = rs.s[rs.j];
rs.s[rs.j] = si;
} }
rs.j = rs.i; /* immediately reinit for backtracking resistance */
_rs_init(rsx->rs_buf, KEYSZ + IVSZ);
memset(rsx->rs_buf, 0, KEYSZ + IVSZ);
rs->rs_have = sizeof(rsx->rs_buf) - KEYSZ - IVSZ;
} }
static void static void
arc4_stir(void) _rs_stir(void)
{ {
int done, fd, n; u_char rnd[KEYSZ + IVSZ];
struct {
struct timeval tv;
pid_t pid;
u_int8_t rnd[KEYSIZE];
} rdat;
fd = open(RANDOMDEV, O_RDONLY, 0); if (getentropy(rnd, sizeof rnd) == -1)
done = 0; _getentropy_fail();
if (fd >= 0) {
if (read(fd, &rdat, KEYSIZE) == KEYSIZE)
done = 1;
(void)close(fd);
}
if (!done) {
(void)gettimeofday(&rdat.tv, NULL);
rdat.pid = getpid();
/* We'll just take whatever was on the stack too... */
}
arc4_addrandom((u_char *)&rdat, KEYSIZE); if (!rs)
_rs_init(rnd, sizeof(rnd));
else
_rs_rekey(rnd, sizeof(rnd));
explicit_bzero(rnd, sizeof(rnd)); /* discard source seed */
/* /* invalidate rs_buf */
* Throw away the first N bytes of output, as suggested in the rs->rs_have = 0;
* paper "Weaknesses in the Key Scheduling Algorithm of RC4" memset(rsx->rs_buf, 0, sizeof(rsx->rs_buf));
* by Fluher, Mantin, and Shamir. N=1024 is based on
* suggestions in the paper "(Not So) Random Shuffles of RC4" rs->rs_count = 1600000;
* by Ilya Mironov.
*/
for (n = 0; n < 1024; n++)
(void) arc4_getbyte();
arc4_count = 1600000;
} }
static inline u_int8_t static inline void
arc4_getbyte(void) _rs_stir_if_needed(size_t len)
{ {
u_int8_t si, sj; _rs_forkdetect();
if (!rs || rs->rs_count <= len)
rs.i = (rs.i + 1); _rs_stir();
si = rs.s[rs.i]; if (rs->rs_count <= len)
rs.j = (rs.j + si); rs->rs_count = 0;
sj = rs.s[rs.j]; else
rs.s[rs.i] = sj; rs->rs_count -= len;
rs.s[rs.j] = si;
return (rs.s[(si + sj) & 0xff]);
} }
static inline u_int32_t static inline void
arc4_getword(void) _rs_random_buf(void *_buf, size_t n)
{ {
u_int32_t val; u_char *buf = (u_char *)_buf;
u_char *keystream;
size_t m;
val = arc4_getbyte() << 24; _rs_stir_if_needed(n);
val |= arc4_getbyte() << 16; while (n > 0) {
val |= arc4_getbyte() << 8; if (rs->rs_have > 0) {
val |= arc4_getbyte(); m = minimum(n, rs->rs_have);
keystream = rsx->rs_buf + sizeof(rsx->rs_buf)
return (val); - rs->rs_have;
} memcpy(buf, keystream, m);
memset(keystream, 0, m);
static void buf += m;
arc4_check_init(void) n -= m;
{ rs->rs_have -= m;
if (!rs_initialized) { }
arc4_init(); if (rs->rs_have == 0)
rs_initialized = 1; _rs_rekey(NULL, 0);
} }
} }
static inline void static inline void
arc4_check_stir(void) _rs_random_u32(uint32_t *val)
{ {
if (!rs_stired || arc4_count <= 0) { u_char *keystream;
arc4_stir();
rs_stired = 1; _rs_stir_if_needed(sizeof(*val));
} if (rs->rs_have < sizeof(*val))
_rs_rekey(NULL, 0);
keystream = rsx->rs_buf + sizeof(rsx->rs_buf) - rs->rs_have;
memcpy(val, keystream, sizeof(*val));
memset(keystream, 0, sizeof(*val));
rs->rs_have -= sizeof(*val);
} }
void void
arc4random_stir(void) arc4random_stir(void)
{ {
THREAD_LOCK(); _ARC4_LOCK();
arc4_check_init(); _rs_stir();
arc4_stir(); _ARC4_UNLOCK();
rs_stired = 1;
THREAD_UNLOCK();
} }
void void
arc4random_addrandom(u_char *dat, int datlen) arc4random_addrandom(u_char *dat, int datlen)
{ {
THREAD_LOCK(); _ARC4_LOCK();
arc4_check_init(); _rs_stir_if_needed(datlen);
arc4_check_stir(); _rs_rekey(dat, datlen);
arc4_addrandom(dat, datlen); _ARC4_UNLOCK();
THREAD_UNLOCK();
} }
u_int32_t uint32_t
arc4random(void) arc4random(void)
{ {
u_int32_t rnd; uint32_t val;
THREAD_LOCK(); _ARC4_LOCK();
arc4_check_init(); _rs_random_u32(&val);
arc4_check_stir(); _ARC4_UNLOCK();
rnd = arc4_getword(); return val;
arc4_count -= 4;
THREAD_UNLOCK();
return (rnd);
} }
void void
arc4random_buf(void *_buf, size_t n) arc4random_buf(void *buf, size_t n)
{ {
u_char *buf = (u_char *)_buf; _ARC4_LOCK();
_rs_random_buf(buf, n);
THREAD_LOCK(); _ARC4_UNLOCK();
arc4_check_init();
while (n--) {
arc4_check_stir();
buf[n] = arc4_getbyte();
arc4_count--;
}
THREAD_UNLOCK();
} }
/*
* Calculate a uniformly distributed random number less than upper_bound
* avoiding "modulo bias".
*
* Uniformity is achieved by generating new random numbers until the one
* returned is outside the range [0, 2**32 % upper_bound). This
* guarantees the selected random number will be inside
* [2**32 % upper_bound, 2**32) which maps back to [0, upper_bound)
* after reduction modulo upper_bound.
*/
u_int32_t
arc4random_uniform(u_int32_t upper_bound)
{
u_int32_t r, min;
if (upper_bound < 2)
return (0);
#if (ULONG_MAX > 0xffffffffUL)
min = 0x100000000UL % upper_bound;
#else
/* Calculate (2**32 % upper_bound) avoiding 64-bit math */
if (upper_bound > 0x80000000)
min = 1 + ~upper_bound; /* 2**32 - upper_bound */
else {
/* (2**32 - (x * 2)) % x == 2**32 % x when x <= 2**31 */
min = ((0xffffffff - (upper_bound * 2)) + 1) % upper_bound;
}
#endif
/*
* This could theoretically loop forever but each retry has
* p > 0.5 (worst case, usually far better) of selecting a
* number inside the range we need, so it should rarely need
* to re-roll.
*/
for (;;) {
r = arc4random();
if (r >= min)
break;
}
return (r % upper_bound);
}
#if 0
/*-------- Test code for i386 --------*/
#include <stdio.h>
#include <machine/pctr.h>
int
main(int argc, char **argv)
{
const int iter = 1000000;
int i;
pctrval v;
v = rdtsc();
for (i = 0; i < iter; i++)
arc4random();
v = rdtsc() - v;
v /= iter;
printf("%qd cycles\n", v);
}
#endif

41
src/arc4random.h Normal file
View File

@@ -0,0 +1,41 @@
/*
* Copyright © 2015 Guillem Jover <guillem@hadrons.org>
*
* 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 ``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 LIBBSD_ARC4RANDOM_H
#define LIBBSD_ARC4RANDOM_H
#include <sys/param.h>
int
getentropy(void *buf, size_t len);
#if defined(__OpenBSD__)
#include "arc4random_openbsd.h"
#else
#include "arc4random_unix.h"
#endif
#endif

61
src/arc4random_openbsd.h Normal file
View File

@@ -0,0 +1,61 @@
/* $OpenBSD: arc4random.h,v 1.3 2014/07/20 20:51:13 bcook Exp $ */
/*
* Copyright (c) 1996, David Mazieres <dm@uun.org>
* Copyright (c) 2008, Damien Miller <djm@openbsd.org>
* Copyright (c) 2013, Markus Friedl <markus@openbsd.org>
* Copyright (c) 2014, Theo de Raadt <deraadt@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* Stub functions for portability.
*/
#include <sys/mman.h>
#include <signal.h>
#include "thread_private.h"
static inline void
_getentropy_fail(void)
{
raise(SIGKILL);
}
static inline int
_rs_allocate(struct _rs **rsp, struct _rsx **rsxp)
{
struct {
struct _rs rs;
struct _rsx rsx;
} *p;
if ((p = mmap(NULL, sizeof(*p), PROT_READ|PROT_WRITE,
MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED)
return (-1);
if (minherit(p, sizeof(*p), MAP_INHERIT_ZERO) == -1) {
munmap(p, sizeof(*p));
return (-1);
}
*rsp = &p->rs;
*rsxp = &p->rsx;
return (0);
}
static inline void
_rs_forkdetect(void)
{
}

57
src/arc4random_uniform.c Normal file
View File

@@ -0,0 +1,57 @@
/* $OpenBSD: arc4random_uniform.c,v 1.1 2014/07/12 13:24:54 deraadt Exp $ */
/*
* Copyright (c) 2008, Damien Miller <djm@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#include <stdlib.h>
/*
* Calculate a uniformly distributed random number less than upper_bound
* avoiding "modulo bias".
*
* Uniformity is achieved by generating new random numbers until the one
* returned is outside the range [0, 2**32 % upper_bound). This
* guarantees the selected random number will be inside
* [2**32 % upper_bound, 2**32) which maps back to [0, upper_bound)
* after reduction modulo upper_bound.
*/
uint32_t
arc4random_uniform(uint32_t upper_bound)
{
uint32_t r, min;
if (upper_bound < 2)
return 0;
/* 2**32 % x == (2**32 - x) % x */
min = -upper_bound % upper_bound;
/*
* This could theoretically loop forever but each retry has
* p > 0.5 (worst case, usually far better) of selecting a
* number inside the range we need, so it should rarely need
* to re-roll.
*/
for (;;) {
r = arc4random();
if (r >= min)
break;
}
return r % upper_bound;
}
//DEF_WEAK(arc4random_uniform);

92
src/arc4random_unix.h Normal file
View File

@@ -0,0 +1,92 @@
/* $OpenBSD: arc4random_linux.h,v 1.8 2014/08/13 06:04:10 deraadt Exp $ */
/*
* Copyright (c) 1996, David Mazieres <dm@uun.org>
* Copyright (c) 2008, Damien Miller <djm@openbsd.org>
* Copyright (c) 2013, Markus Friedl <markus@openbsd.org>
* Copyright (c) 2014, Theo de Raadt <deraadt@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* Stub functions for portability.
*/
#include <sys/mman.h>
#include <pthread.h>
#include <signal.h>
static pthread_mutex_t arc4random_mtx = PTHREAD_MUTEX_INITIALIZER;
#define _ARC4_LOCK() pthread_mutex_lock(&arc4random_mtx)
#define _ARC4_UNLOCK() pthread_mutex_unlock(&arc4random_mtx)
#ifdef __GLIBC__
extern void *__dso_handle;
extern int __register_atfork(void (*)(void), void(*)(void), void (*)(void), void *);
#define _ARC4_ATFORK(f) __register_atfork(NULL, NULL, (f), __dso_handle)
#else
/*
* Unfortunately, pthread_atfork() is broken on FreeBSD (at least 9 and 10) if
* a program does not link to -lthr. Callbacks registered with pthread_atfork()
* appear to fail silently. So, it is not always possible to detect a PID
* wraparound.
*/
#define _ARC4_ATFORK(f) pthread_atfork(NULL, NULL, (f))
#endif
static inline void
_getentropy_fail(void)
{
raise(SIGKILL);
}
static volatile sig_atomic_t _rs_forked;
static inline void
_rs_forkhandler(void)
{
_rs_forked = 1;
}
static inline void
_rs_forkdetect(void)
{
static pid_t _rs_pid = 0;
pid_t pid = getpid();
if (_rs_pid == 0 || _rs_pid != pid || _rs_forked) {
_rs_pid = pid;
_rs_forked = 0;
if (rs)
memset(rs, 0, sizeof(*rs));
}
}
static inline int
_rs_allocate(struct _rs **rsp, struct _rsx **rsxp)
{
if ((*rsp = mmap(NULL, sizeof(**rsp), PROT_READ|PROT_WRITE,
MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED)
return (-1);
if ((*rsxp = mmap(NULL, sizeof(**rsxp), PROT_READ|PROT_WRITE,
MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) {
munmap(*rsp, sizeof(**rsp));
return (-1);
}
_ARC4_ATFORK(_rs_forkhandler);
return (0);
}

222
src/chacha_private.h Normal file
View File

@@ -0,0 +1,222 @@
/*
chacha-merged.c version 20080118
D. J. Bernstein
Public domain.
*/
/* $OpenBSD$ */
typedef unsigned char u8;
typedef unsigned int u32;
typedef struct
{
u32 input[16]; /* could be compressed */
} chacha_ctx;
#define U8C(v) (v##U)
#define U32C(v) (v##U)
#define U8V(v) ((u8)(v) & U8C(0xFF))
#define U32V(v) ((u32)(v) & U32C(0xFFFFFFFF))
#define ROTL32(v, n) \
(U32V((v) << (n)) | ((v) >> (32 - (n))))
#define U8TO32_LITTLE(p) \
(((u32)((p)[0]) ) | \
((u32)((p)[1]) << 8) | \
((u32)((p)[2]) << 16) | \
((u32)((p)[3]) << 24))
#define U32TO8_LITTLE(p, v) \
do { \
(p)[0] = U8V((v) ); \
(p)[1] = U8V((v) >> 8); \
(p)[2] = U8V((v) >> 16); \
(p)[3] = U8V((v) >> 24); \
} while (0)
#define ROTATE(v,c) (ROTL32(v,c))
#define XOR(v,w) ((v) ^ (w))
#define PLUS(v,w) (U32V((v) + (w)))
#define PLUSONE(v) (PLUS((v),1))
#define QUARTERROUND(a,b,c,d) \
a = PLUS(a,b); d = ROTATE(XOR(d,a),16); \
c = PLUS(c,d); b = ROTATE(XOR(b,c),12); \
a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \
c = PLUS(c,d); b = ROTATE(XOR(b,c), 7);
static const char sigma[16] = "expand 32-byte k";
static const char tau[16] = "expand 16-byte k";
static void
chacha_keysetup(chacha_ctx *x,const u8 *k,u32 kbits,u32 ivbits)
{
const char *constants;
x->input[4] = U8TO32_LITTLE(k + 0);
x->input[5] = U8TO32_LITTLE(k + 4);
x->input[6] = U8TO32_LITTLE(k + 8);
x->input[7] = U8TO32_LITTLE(k + 12);
if (kbits == 256) { /* recommended */
k += 16;
constants = sigma;
} else { /* kbits == 128 */
constants = tau;
}
x->input[8] = U8TO32_LITTLE(k + 0);
x->input[9] = U8TO32_LITTLE(k + 4);
x->input[10] = U8TO32_LITTLE(k + 8);
x->input[11] = U8TO32_LITTLE(k + 12);
x->input[0] = U8TO32_LITTLE(constants + 0);
x->input[1] = U8TO32_LITTLE(constants + 4);
x->input[2] = U8TO32_LITTLE(constants + 8);
x->input[3] = U8TO32_LITTLE(constants + 12);
}
static void
chacha_ivsetup(chacha_ctx *x,const u8 *iv)
{
x->input[12] = 0;
x->input[13] = 0;
x->input[14] = U8TO32_LITTLE(iv + 0);
x->input[15] = U8TO32_LITTLE(iv + 4);
}
static void
chacha_encrypt_bytes(chacha_ctx *x,const u8 *m,u8 *c,u32 bytes)
{
u32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
u32 j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15;
u8 *ctarget = NULL;
u8 tmp[64];
u_int i;
if (!bytes) return;
j0 = x->input[0];
j1 = x->input[1];
j2 = x->input[2];
j3 = x->input[3];
j4 = x->input[4];
j5 = x->input[5];
j6 = x->input[6];
j7 = x->input[7];
j8 = x->input[8];
j9 = x->input[9];
j10 = x->input[10];
j11 = x->input[11];
j12 = x->input[12];
j13 = x->input[13];
j14 = x->input[14];
j15 = x->input[15];
for (;;) {
if (bytes < 64) {
for (i = 0;i < bytes;++i) tmp[i] = m[i];
m = tmp;
ctarget = c;
c = tmp;
}
x0 = j0;
x1 = j1;
x2 = j2;
x3 = j3;
x4 = j4;
x5 = j5;
x6 = j6;
x7 = j7;
x8 = j8;
x9 = j9;
x10 = j10;
x11 = j11;
x12 = j12;
x13 = j13;
x14 = j14;
x15 = j15;
for (i = 20;i > 0;i -= 2) {
QUARTERROUND( x0, x4, x8,x12)
QUARTERROUND( x1, x5, x9,x13)
QUARTERROUND( x2, x6,x10,x14)
QUARTERROUND( x3, x7,x11,x15)
QUARTERROUND( x0, x5,x10,x15)
QUARTERROUND( x1, x6,x11,x12)
QUARTERROUND( x2, x7, x8,x13)
QUARTERROUND( x3, x4, x9,x14)
}
x0 = PLUS(x0,j0);
x1 = PLUS(x1,j1);
x2 = PLUS(x2,j2);
x3 = PLUS(x3,j3);
x4 = PLUS(x4,j4);
x5 = PLUS(x5,j5);
x6 = PLUS(x6,j6);
x7 = PLUS(x7,j7);
x8 = PLUS(x8,j8);
x9 = PLUS(x9,j9);
x10 = PLUS(x10,j10);
x11 = PLUS(x11,j11);
x12 = PLUS(x12,j12);
x13 = PLUS(x13,j13);
x14 = PLUS(x14,j14);
x15 = PLUS(x15,j15);
#ifndef KEYSTREAM_ONLY
x0 = XOR(x0,U8TO32_LITTLE(m + 0));
x1 = XOR(x1,U8TO32_LITTLE(m + 4));
x2 = XOR(x2,U8TO32_LITTLE(m + 8));
x3 = XOR(x3,U8TO32_LITTLE(m + 12));
x4 = XOR(x4,U8TO32_LITTLE(m + 16));
x5 = XOR(x5,U8TO32_LITTLE(m + 20));
x6 = XOR(x6,U8TO32_LITTLE(m + 24));
x7 = XOR(x7,U8TO32_LITTLE(m + 28));
x8 = XOR(x8,U8TO32_LITTLE(m + 32));
x9 = XOR(x9,U8TO32_LITTLE(m + 36));
x10 = XOR(x10,U8TO32_LITTLE(m + 40));
x11 = XOR(x11,U8TO32_LITTLE(m + 44));
x12 = XOR(x12,U8TO32_LITTLE(m + 48));
x13 = XOR(x13,U8TO32_LITTLE(m + 52));
x14 = XOR(x14,U8TO32_LITTLE(m + 56));
x15 = XOR(x15,U8TO32_LITTLE(m + 60));
#endif
j12 = PLUSONE(j12);
if (!j12) {
j13 = PLUSONE(j13);
/* stopping at 2^70 bytes per nonce is user's responsibility */
}
U32TO8_LITTLE(c + 0,x0);
U32TO8_LITTLE(c + 4,x1);
U32TO8_LITTLE(c + 8,x2);
U32TO8_LITTLE(c + 12,x3);
U32TO8_LITTLE(c + 16,x4);
U32TO8_LITTLE(c + 20,x5);
U32TO8_LITTLE(c + 24,x6);
U32TO8_LITTLE(c + 28,x7);
U32TO8_LITTLE(c + 32,x8);
U32TO8_LITTLE(c + 36,x9);
U32TO8_LITTLE(c + 40,x10);
U32TO8_LITTLE(c + 44,x11);
U32TO8_LITTLE(c + 48,x12);
U32TO8_LITTLE(c + 52,x13);
U32TO8_LITTLE(c + 56,x14);
U32TO8_LITTLE(c + 60,x15);
if (bytes <= 64) {
if (bytes < 64) {
for (i = 0;i < bytes;++i) ctarget[i] = c[i];
}
x->input[12] = j12;
x->input[13] = j13;
return;
}
bytes -= 64;
c += 64;
#ifndef KEYSTREAM_ONLY
m += 64;
#endif
}
}

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2004-2005, 2007, 2010 * Copyright (c) 2004-2005, 2007, 2010, 2012-2014
* Todd C. Miller <Todd.Miller@courtesan.com> * Todd C. Miller <Todd.Miller@courtesan.com>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
@@ -18,7 +18,6 @@
#include <config.h> #include <config.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/param.h>
#include <unistd.h> #include <unistd.h>
#include <stdio.h> #include <stdio.h>
#ifdef STDC_HEADERS #ifdef STDC_HEADERS
@@ -30,20 +29,26 @@
# endif # endif
#endif /* STDC_HEADERS */ #endif /* STDC_HEADERS */
#include <fcntl.h> #include <fcntl.h>
#ifdef HAVE_DIRENT_H #include <limits.h>
# include <dirent.h> #ifdef HAVE_PSTAT_GETPROC
# define NAMLEN(dirent) strlen((dirent)->d_name) # include <sys/param.h>
# include <sys/pstat.h>
#else #else
# define dirent direct # ifdef HAVE_DIRENT_H
# define NAMLEN(dirent) (dirent)->d_namlen # include <dirent.h>
# ifdef HAVE_SYS_NDIR_H # define NAMLEN(dirent) strlen((dirent)->d_name)
# include <sys/ndir.h> # else
# endif # define dirent direct
# ifdef HAVE_SYS_DIR_H # define NAMLEN(dirent) (dirent)->d_namlen
# include <sys/dir.h> # ifdef HAVE_SYS_NDIR_H
# endif # include <sys/ndir.h>
# ifdef HAVE_NDIR_H # endif
# include <ndir.h> # ifdef HAVE_SYS_DIR_H
# include <sys/dir.h>
# endif
# ifdef HAVE_NDIR_H
# include <ndir.h>
# endif
# endif # endif
#endif #endif
@@ -51,15 +56,24 @@
# define OPEN_MAX 256 # define OPEN_MAX 256
#endif #endif
#ifndef HAVE_FCNTL_CLOSEM #if defined(HAVE_FCNTL_CLOSEM) && !defined(HAVE_DIRFD)
# ifndef HAVE_DIRFD # define closefrom closefrom_fallback
# define closefrom_fallback closefrom
# endif
#endif #endif
static inline void
closefrom_close(int fd)
{
#ifdef __APPLE__
/* Avoid potential libdispatch crash when we close its fds. */
(void)fcntl(fd, F_SETFD, FD_CLOEXEC);
#else
(void)close(fd);
#endif
}
/* /*
* Close all file descriptors greater than or equal to lowfd. * Close all file descriptors greater than or equal to lowfd.
* This is the expensive (ballback) method. * This is the expensive (fallback) method.
*/ */
void void
closefrom_fallback(int lowfd) closefrom_fallback(int lowfd)
@@ -80,43 +94,99 @@ closefrom_fallback(int lowfd)
maxfd = OPEN_MAX; maxfd = OPEN_MAX;
for (fd = lowfd; fd < maxfd; fd++) for (fd = lowfd; fd < maxfd; fd++)
(void)close((int)fd); closefrom_close(fd);
} }
/* /*
* Close all file descriptors greater than or equal to lowfd. * Close all file descriptors greater than or equal to lowfd.
* We try the fast way first, falling back on the slow method. * We try the fast way first, falling back on the slow method.
*/ */
#ifdef HAVE_FCNTL_CLOSEM #if defined(HAVE_FCNTL_CLOSEM)
void void
closefrom(int lowfd) closefrom(int lowfd)
{ {
if (fcntl(lowfd, F_CLOSEM, 0) == -1) if (fcntl(lowfd, F_CLOSEM, 0) == -1)
closefrom_fallback(lowfd); closefrom_fallback(lowfd);
} }
#else #elif defined(HAVE_PSTAT_GETPROC)
# ifdef HAVE_DIRFD
void void
closefrom(int lowfd) closefrom(int lowfd)
{ {
struct dirent *dent; struct pst_status pstat;
DIR *dirp; int fd;
char *endp;
long fd;
/* Use /proc/self/fd directory if it exists. */ if (pstat_getproc(&pstat, sizeof(pstat), 0, getpid()) != -1) {
dirp = opendir("/proc/self/fd"); for (fd = lowfd; fd <= pstat.pst_highestfd; fd++)
if (dirp != NULL) { (void)close(fd);
while ((dent = readdir(dirp)) != NULL) { } else {
fd = strtol(dent->d_name, &endp, 10);
if (dent->d_name != endp && *endp == '\0' &&
fd >= 0 && fd < INT_MAX && fd >= lowfd &&
fd != dirfd(dirp))
(void)close((int)fd);
}
(void)closedir(dirp);
} else
closefrom_fallback(lowfd); closefrom_fallback(lowfd);
}
}
#elif defined(HAVE_DIRFD)
static int
closefrom_procfs(int lowfd)
{
const char *path;
DIR *dirp;
struct dirent *dent;
int *fd_array = NULL;
int fd_array_used = 0;
int fd_array_size = 0;
int ret = 0;
int i;
/* Use /proc/self/fd (or /dev/fd on FreeBSD) if it exists. */
# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__)
path = "/dev/fd";
# else
path = "/proc/self/fd";
# endif
dirp = opendir(path);
if (dirp == NULL)
return -1;
while ((dent = readdir(dirp)) != NULL) {
const char *errstr;
int fd;
fd = strtonum(dent->d_name, lowfd, INT_MAX, &errstr);
if (errstr != NULL || fd == dirfd(dirp))
continue;
if (fd_array_used >= fd_array_size) {
int *ptr;
if (fd_array_size > 0)
fd_array_size *= 2;
else
fd_array_size = 32;
ptr = reallocarray(fd_array, fd_array_size, sizeof(int));
if (ptr == NULL) {
ret = -1;
break;
}
fd_array = ptr;
}
fd_array[fd_array_used++] = fd;
}
for (i = 0; i < fd_array_used; i++)
closefrom_close(fd_array[i]);
free(fd_array);
(void)closedir(dirp);
return ret;
}
void
closefrom(int lowfd)
{
if (closefrom_procfs(lowfd) == 0)
return;
closefrom_fallback(lowfd);
} }
#endif /* HAVE_DIRFD */
#endif /* HAVE_FCNTL_CLOSEM */ #endif /* HAVE_FCNTL_CLOSEM */

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright © 2012 Guillem Jover <guillem@hadrons.org> * Copyright © 2012-2013 Guillem Jover <guillem@hadrons.org>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@@ -35,8 +35,8 @@
int int
dehumanize_number(const char *buf, int64_t *num) dehumanize_number(const char *buf, int64_t *num)
{ {
uint64_t rval; uint64_t rval, rmax;
int sign = 1; int sign = +1;
int rc; int rc;
/* The current expand_number() implementation uses bit shifts, so /* The current expand_number() implementation uses bit shifts, so
@@ -52,7 +52,13 @@ dehumanize_number(const char *buf, int64_t *num)
rc = expand_number(buf, &rval); rc = expand_number(buf, &rval);
if (rc < 0) if (rc < 0)
return rc; return rc;
if (rval == UINT64_MAX && sign == -1) {
/* The sign has been stripped, so rval has the absolute value.
* Error out, regardless of the sign, if rval is greater than
* abs(INT64_MIN) (== INT64_MAX + 1), or if the sign is positive
* and the value has overflown by one (INT64_MAX + 1). */
rmax = INT64_MAX + 1ULL;
if (rval > rmax || (rval == rmax && sign == +1)) {
errno = ERANGE; errno = ERANGE;
return -1; return -1;
} }

19
src/explicit_bzero.c Normal file
View File

@@ -0,0 +1,19 @@
/* $OpenBSD: explicit_bzero.c,v 1.3 2014/06/21 02:34:26 matthew Exp $ */
/*
* Public domain.
* Written by Matthew Dempsky.
*/
#include <string.h>
__attribute__((weak)) void
__explicit_bzero_hook(void *buf, size_t len)
{
}
void
explicit_bzero(void *buf, size_t len)
{
memset(buf, 0, len);
__explicit_bzero_hook(buf, len);
}

View File

@@ -30,6 +30,8 @@
#include <sys/types.h> #include <sys/types.h>
#include <string.h> #include <string.h>
#include "local-link.h"
#ifdef HAVE_GETLINE #ifdef HAVE_GETLINE
struct filebuf { struct filebuf {
FILE *fp; FILE *fp;
@@ -48,6 +50,8 @@ fgetln(FILE *stream, size_t *len)
struct filebuf *fb; struct filebuf *fb;
ssize_t nread; ssize_t nread;
flockfile(stream);
/* Try to diminish the possibility of several fgetln() calls being /* Try to diminish the possibility of several fgetln() calls being
* used on different streams, by using a pool of buffers per file. */ * used on different streams, by using a pool of buffers per file. */
fb = &fb_pool[fb_pool_cur]; fb = &fb_pool[fb_pool_cur];
@@ -59,6 +63,9 @@ fgetln(FILE *stream, size_t *len)
fb->fp = stream; fb->fp = stream;
nread = getline(&fb->buf, &fb->len, stream); nread = getline(&fb->buf, &fb->len, stream);
funlockfile(stream);
/* Note: the getdelim/getline API ensures nread != 0. */ /* Note: the getdelim/getline API ensures nread != 0. */
if (nread == -1) { if (nread == -1) {
*len = 0; *len = 0;
@@ -68,6 +75,9 @@ fgetln(FILE *stream, size_t *len)
return fb->buf; return fb->buf;
} }
} }
libbsd_link_warning(fgetln,
"This functions cannot be safely ported, use getline(3) "
"instead, as it is supported by GNU and POSIX.1-2008.")
#else #else
#error "Function fgetln() needs to be ported." #error "Function fgetln() needs to be ported."
#endif #endif

View File

@@ -60,7 +60,7 @@ fgetwln(FILE *stream, size_t *lenp)
fb->fp = stream; fb->fp = stream;
while ((wc = fgetwc(stream)) != WEOF) { while ((wc = fgetwc(stream)) != WEOF) {
if (!fb->len || wused > fb->len) { if (!fb->len || wused >= fb->len) {
wchar_t *wp; wchar_t *wp;
if (fb->len) if (fb->len)
@@ -68,7 +68,7 @@ fgetwln(FILE *stream, size_t *lenp)
else else
fb->len = FILEWBUF_INIT_LEN; fb->len = FILEWBUF_INIT_LEN;
wp = realloc(fb->wbuf, fb->len * sizeof(wchar_t)); wp = reallocarray(fb->wbuf, fb->len, sizeof(wchar_t));
if (wp == NULL) { if (wp == NULL) {
wused = 0; wused = 0;
break; break;

View File

@@ -35,8 +35,6 @@ __RCSID("$NetBSD: fparseln.c,v 1.10 2009/10/21 01:07:45 snj Exp $");
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#define FLOCKFILE(fp)
#define FUNLOCKFILE(fp)
#define _DIAGASSERT(t) #define _DIAGASSERT(t)
static int isescaped(const char *, const char *, int); static int isescaped(const char *, const char *, int);
@@ -77,7 +75,8 @@ fparseln(FILE *fp, size_t *size, size_t *lineno, const char str[3], int flags)
{ {
static const char dstr[3] = { '\\', '\\', '#' }; static const char dstr[3] = { '\\', '\\', '#' };
size_t s, len; ssize_t s;
size_t len, ptrlen;
char *buf; char *buf;
char *ptr, *cp; char *ptr, *cp;
int cnt; int cnt;
@@ -87,6 +86,8 @@ fparseln(FILE *fp, size_t *size, size_t *lineno, const char str[3], int flags)
len = 0; len = 0;
buf = NULL; buf = NULL;
ptrlen = 0;
ptr = NULL;
cnt = 1; cnt = 1;
if (str == NULL) if (str == NULL)
@@ -97,11 +98,11 @@ fparseln(FILE *fp, size_t *size, size_t *lineno, const char str[3], int flags)
com = str[2]; com = str[2];
/* /*
* XXX: it would be cool to be able to specify the newline character, * XXX: it would be cool to be able to specify the newline character,
* but unfortunately, fgetln does not let us * getdelim(3) does let us, but supporting it would diverge from BSDs.
*/ */
nl = '\n'; nl = '\n';
FLOCKFILE(fp); flockfile(fp);
while (cnt) { while (cnt) {
cnt = 0; cnt = 0;
@@ -109,7 +110,8 @@ fparseln(FILE *fp, size_t *size, size_t *lineno, const char str[3], int flags)
if (lineno) if (lineno)
(*lineno)++; (*lineno)++;
if ((ptr = fgetln(fp, &s)) == NULL) s = getline(&ptr, &ptrlen, fp);
if (s < 0)
break; break;
if (s && com) { /* Check and eliminate comments */ if (s && com) { /* Check and eliminate comments */
@@ -147,8 +149,9 @@ fparseln(FILE *fp, size_t *size, size_t *lineno, const char str[3], int flags)
} }
if ((cp = realloc(buf, len + s + 1)) == NULL) { if ((cp = realloc(buf, len + s + 1)) == NULL) {
FUNLOCKFILE(fp); funlockfile(fp);
free(buf); free(buf);
free(ptr);
return NULL; return NULL;
} }
buf = cp; buf = cp;
@@ -158,7 +161,8 @@ fparseln(FILE *fp, size_t *size, size_t *lineno, const char str[3], int flags)
buf[len] = '\0'; buf[len] = '\0';
} }
FUNLOCKFILE(fp); funlockfile(fp);
free(ptr);
if ((flags & FPARSELN_UNESCALL) != 0 && esc && buf != NULL && if ((flags & FPARSELN_UNESCALL) != 0 && esc && buf != NULL &&
strchr(buf, esc) != NULL) { strchr(buf, esc) != NULL) {
@@ -195,36 +199,3 @@ fparseln(FILE *fp, size_t *size, size_t *lineno, const char str[3], int flags)
*size = len; *size = len;
return buf; return buf;
} }
#ifdef TEST
int main(int, char **);
int
main(int argc, char **argv)
{
char *ptr;
size_t size, line;
line = 0;
while ((ptr = fparseln(stdin, &size, &line, NULL,
FPARSELN_UNESCALL)) != NULL)
printf("line %d (%d) |%s|\n", line, size, ptr);
return 0;
}
/*
# This is a test
line 1
line 2 \
line 3 # Comment
line 4 \# Not comment \\\\
# And a comment \
line 5 \\\
line 6
*/
#endif /* TEST */

View File

@@ -44,23 +44,3 @@ fpurge(FILE *fp)
#else #else
#error "Function fpurge() needs to be ported." #error "Function fpurge() needs to be ported."
#endif #endif
#ifdef TEST
int
main()
{
static FILE fp_bad;
FILE *fp;
if (fpurge(&fp_bad) == 0)
return 1;
fp = fopen("/dev/zero", "r");
if (fpurge(fp) < 0)
return 1;
fclose(fp);
return 0;
}
#endif

142
src/funopen.c Normal file
View File

@@ -0,0 +1,142 @@
/*
* Copyright © 2011, 2013 Guillem Jover
*
* 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 ``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 <sys/cdefs.h>
#include <sys/types.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#ifdef HAVE_FOPENCOOKIE
struct funopen_cookie {
void *orig_cookie;
int (*readfn)(void *cookie, char *buf, int size);
int (*writefn)(void *cookie, const char *buf, int size);
off_t (*seekfn)(void *cookie, off_t offset, int whence);
int (*closefn)(void *cookie);
};
static ssize_t
funopen_read(void *cookie, char *buf, size_t size)
{
struct funopen_cookie *cookiewrap = cookie;
if (cookiewrap->readfn == NULL) {
errno = EBADF;
return -1;
}
return cookiewrap->readfn(cookiewrap->orig_cookie, buf, size);
}
static ssize_t
funopen_write(void *cookie, const char *buf, size_t size)
{
struct funopen_cookie *cookiewrap = cookie;
if (cookiewrap->writefn == NULL)
return EOF;
return cookiewrap->writefn(cookiewrap->orig_cookie, buf, size);
}
static int
funopen_seek(void *cookie, off64_t *offset, int whence)
{
struct funopen_cookie *cookiewrap = cookie;
off_t soff = *offset;
if (cookiewrap->seekfn == NULL) {
errno = ESPIPE;
return -1;
}
soff = cookiewrap->seekfn(cookiewrap->orig_cookie, soff, whence);
*offset = soff;
return *offset;
}
static int
funopen_close(void *cookie)
{
struct funopen_cookie *cookiewrap = cookie;
int rc;
if (cookiewrap->closefn == NULL)
return 0;
rc = cookiewrap->closefn(cookiewrap->orig_cookie);
free(cookiewrap);
return rc;
}
FILE *
funopen(const void *cookie,
int (*readfn)(void *cookie, char *buf, int size),
int (*writefn)(void *cookie, const char *buf, int size),
off_t (*seekfn)(void *cookie, off_t offset, int whence),
int (*closefn)(void *cookie))
{
struct funopen_cookie *cookiewrap;
cookie_io_functions_t funcswrap = {
.read = funopen_read,
.write = funopen_write,
.seek = funopen_seek,
.close = funopen_close,
};
const char *mode;
if (readfn) {
if (writefn == NULL)
mode = "r";
else
mode = "r+";
} else if (writefn) {
mode = "w";
} else {
errno = EINVAL;
return NULL;
}
cookiewrap = malloc(sizeof(*cookiewrap));
if (cookiewrap == NULL)
return NULL;
cookiewrap->orig_cookie = (void *)cookie;
cookiewrap->readfn = readfn;
cookiewrap->writefn = writefn;
cookiewrap->seekfn = seekfn;
cookiewrap->closefn = closefn;
return fopencookie(cookiewrap, mode, funcswrap);
}
#else
#error "Function funopen() needs to be ported."
#endif

102
src/getbsize.c Normal file
View File

@@ -0,0 +1,102 @@
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. 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. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
*
* @(#)getbsize.c 8.1 (Berkeley) 6/4/93
* $FreeBSD: src/lib/libc/gen/getbsize.c,v 1.9 2008/08/04 06:53:13 cperciva Exp $
* $DragonFly: src/lib/libc/gen/getbsize.c,v 1.4 2005/11/13 00:07:42 swildner Exp $
*/
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *
getbsize(int *headerlenp, long *blocksizep)
{
static char header[20];
long n, max, mul, blocksize;
char *ep, *p;
const char *form;
#define KB (1024L)
#define MB (1024L * 1024L)
#define GB (1024L * 1024L * 1024L)
#define MAXB GB /* No tera, peta, nor exa. */
form = "";
if ((p = getenv("BLOCKSIZE")) != NULL && *p != '\0') {
if ((n = strtol(p, &ep, 10)) < 0)
goto underflow;
if (n == 0)
n = 1;
if (*ep && ep[1])
goto fmterr;
switch (*ep) {
case 'G': case 'g':
form = "G";
max = MAXB / GB;
mul = GB;
break;
case 'K': case 'k':
form = "K";
max = MAXB / KB;
mul = KB;
break;
case 'M': case 'm':
form = "M";
max = MAXB / MB;
mul = MB;
break;
case '\0':
max = MAXB;
mul = 1;
break;
default:
fmterr: warnx("%s: unknown blocksize", p);
n = 512;
max = MAXB;
mul = 1;
break;
}
if (n > max) {
warnx("maximum blocksize is %ldG", MAXB / GB);
n = max;
}
if ((blocksize = n * mul) < 512) {
underflow: warnx("minimum blocksize is 512");
form = "";
blocksize = n = 512;
}
} else
blocksize = n = 512;
snprintf(header, sizeof(header), "%ld%s-blocks", n, form);
*headerlenp = strlen(header);
*blocksizep = blocksize;
return (header);
}

45
src/getentropy.c Normal file
View File

@@ -0,0 +1,45 @@
/*
* Copyright © 2015 Guillem Jover <guillem@hadrons.org>
*
* 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 ``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.
*/
#if defined(__linux__)
#include "getentropy_linux.c"
#elif defined(__GNU__)
#include "getentropy_hurd.c"
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
#include "getentropy_bsd.c"
#elif defined(__NetBSD__)
#include "getentropy_bsd.c"
#elif defined(__sun)
#include "getentropy_solaris.c"
#elif defined(__APPLE__)
#include "getentropy_osx.c"
#elif defined(_AIX)
#include "getentropy_aix.c"
#elif defined(__hpux)
#include "getentropy_hpux.c"
#else
#error "No getentropy hooks defined for this platform."
#endif

425
src/getentropy_aix.c Normal file
View File

@@ -0,0 +1,425 @@
/* $OpenBSD: getentropy_aix.c,v 1.3 2015/08/25 17:26:43 deraadt Exp $ */
/*
* Copyright (c) 2015 Michael Felt <aixtools@gmail.com>
* Copyright (c) 2014 Theo de Raadt <deraadt@openbsd.org>
* Copyright (c) 2014 Bob Beck <beck@obtuse.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Emulation of getentropy(2) as documented at:
* http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man2/getentropy.2
*/
/*
* -lperfstat is needed for the psuedo entropy data
*/
#include <sys/mman.h>
#include <sys/procfs.h>
#include <sys/protosw.h>
#include <sys/resource.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
#include <sys/timers.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <termios.h>
#include "hash/sha512.h"
#include <libperfstat.h>
#define REPEAT 5
#define min(a, b) (((a) < (b)) ? (a) : (b))
#define HX(a, b) \
do { \
if ((a)) \
HD(errno); \
else \
HD(b); \
} while (0)
#define HR(x, l) (SHA512_Update(&ctx, (char *)(x), (l)))
#define HD(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (x)))
#define HF(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (void*)))
int getentropy(void *buf, size_t len);
static int gotdata(char *buf, size_t len);
static int getentropy_urandom(void *buf, size_t len, const char *path,
int devfscheck);
static int getentropy_fallback(void *buf, size_t len);
int
getentropy(void *buf, size_t len)
{
int ret = -1;
if (len > 256) {
errno = EIO;
return (-1);
}
/*
* Try to get entropy with /dev/urandom
*/
ret = getentropy_urandom(buf, len, "/dev/urandom", 0);
if (ret != -1)
return (ret);
/*
* Entropy collection via /dev/urandom has failed.
*
* No other API exists for collecting entropy, and we have
* no failsafe way to get it on AIX that is not sensitive
* to resource exhaustion.
*
* We have very few options:
* - Even syslog_r is unsafe to call at this low level, so
* there is no way to alert the user or program.
* - Cannot call abort() because some systems have unsafe
* corefiles.
* - Could raise(SIGKILL) resulting in silent program termination.
* - Return EIO, to hint that arc4random's stir function
* should raise(SIGKILL)
* - Do the best under the circumstances....
*
* This code path exists to bring light to the issue that AIX
* does not provide a failsafe API for entropy collection.
*
* We hope this demonstrates that AIX should consider
* providing a new failsafe API which works in a chroot or
* when file descriptors are exhausted.
*/
#undef FAIL_INSTEAD_OF_TRYING_FALLBACK
#ifdef FAIL_INSTEAD_OF_TRYING_FALLBACK
raise(SIGKILL);
#endif
ret = getentropy_fallback(buf, len);
if (ret != -1)
return (ret);
errno = EIO;
return (ret);
}
/*
* Basic sanity checking; wish we could do better.
*/
static int
gotdata(char *buf, size_t len)
{
char any_set = 0;
size_t i;
for (i = 0; i < len; ++i)
any_set |= buf[i];
if (any_set == 0)
return (-1);
return (0);
}
static int
getentropy_urandom(void *buf, size_t len, const char *path, int devfscheck)
{
struct stat st;
size_t i;
int fd, flags;
int save_errno = errno;
start:
flags = O_RDONLY;
#ifdef O_NOFOLLOW
flags |= O_NOFOLLOW;
#endif
#ifdef O_CLOEXEC
flags |= O_CLOEXEC;
#endif
fd = open(path, flags, 0);
if (fd == -1) {
if (errno == EINTR)
goto start;
goto nodevrandom;
}
#ifndef O_CLOEXEC
fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
#endif
/* Lightly verify that the device node looks sane */
if (fstat(fd, &st) == -1 || !S_ISCHR(st.st_mode)) {
close(fd);
goto nodevrandom;
}
for (i = 0; i < len; ) {
size_t wanted = len - i;
ssize_t ret = read(fd, (char *)buf + i, wanted);
if (ret == -1) {
if (errno == EAGAIN || errno == EINTR)
continue;
close(fd);
goto nodevrandom;
}
i += ret;
}
close(fd);
if (gotdata(buf, len) == 0) {
errno = save_errno;
return (0); /* satisfied */
}
nodevrandom:
errno = EIO;
return (-1);
}
static const int cl[] = {
CLOCK_REALTIME,
#ifdef CLOCK_MONOTONIC
CLOCK_MONOTONIC,
#endif
#ifdef CLOCK_MONOTONIC_RAW
CLOCK_MONOTONIC_RAW,
#endif
#ifdef CLOCK_TAI
CLOCK_TAI,
#endif
#ifdef CLOCK_VIRTUAL
CLOCK_VIRTUAL,
#endif
#ifdef CLOCK_UPTIME
CLOCK_UPTIME,
#endif
#ifdef CLOCK_PROCESS_CPUTIME_ID
CLOCK_PROCESS_CPUTIME_ID,
#endif
#ifdef CLOCK_THREAD_CPUTIME_ID
CLOCK_THREAD_CPUTIME_ID,
#endif
};
static int
getentropy_fallback(void *buf, size_t len)
{
uint8_t results[SHA512_DIGEST_LENGTH];
int save_errno = errno, e, pgs = sysconf(_SC_PAGESIZE), faster = 0, repeat;
static int cnt;
struct timespec ts;
struct timeval tv;
perfstat_cpu_total_t cpustats;
#ifdef _AIX61
perfstat_cpu_total_wpar_t cpustats_wpar;
#endif
perfstat_partition_total_t lparstats;
perfstat_disk_total_t diskinfo;
perfstat_netinterface_total_t netinfo;
struct rusage ru;
sigset_t sigset;
struct stat st;
SHA512_CTX ctx;
static pid_t lastpid;
pid_t pid;
size_t i, ii, m;
char *p;
pid = getpid();
if (lastpid == pid) {
faster = 1;
repeat = 2;
} else {
faster = 0;
lastpid = pid;
repeat = REPEAT;
}
for (i = 0; i < len; ) {
int j;
SHA512_Init(&ctx);
for (j = 0; j < repeat; j++) {
HX((e = gettimeofday(&tv, NULL)) == -1, tv);
if (e != -1) {
cnt += (int)tv.tv_sec;
cnt += (int)tv.tv_usec;
}
HX(perfstat_cpu_total(NULL, &cpustats,
sizeof(cpustats), 1) == -1, cpustats);
#ifdef _AIX61
HX(perfstat_cpu_total_wpar(NULL, &cpustats_wpar,
sizeof(cpustats_wpar), 1) == -1, cpustats_wpar);
#endif
HX(perfstat_partition_total(NULL, &lparstats,
sizeof(lparstats), 1) == -1, lparstats);
HX(perfstat_disk_total(NULL, &diskinfo,
sizeof(diskinfo), 1) == -1, diskinfo);
HX(perfstat_netinterface_total(NULL, &netinfo,
sizeof(netinfo), 1) == -1, netinfo);
for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]); ii++)
HX(clock_gettime(cl[ii], &ts) == -1, ts);
HX((pid = getpid()) == -1, pid);
HX((pid = getsid(pid)) == -1, pid);
HX((pid = getppid()) == -1, pid);
HX((pid = getpgid(0)) == -1, pid);
HX((e = getpriority(0, 0)) == -1, e);
if (!faster) {
ts.tv_sec = 0;
ts.tv_nsec = 1;
(void) nanosleep(&ts, NULL);
}
HX(sigpending(&sigset) == -1, sigset);
HX(sigprocmask(SIG_BLOCK, NULL, &sigset) == -1,
sigset);
HF(getentropy); /* an addr in this library */
HF(printf); /* an addr in libc */
p = (char *)&p;
HD(p); /* an addr on stack */
p = (char *)&errno;
HD(p); /* the addr of errno */
if (i == 0) {
struct sockaddr_storage ss;
struct statvfs stvfs;
struct termios tios;
socklen_t ssl;
off_t off;
/*
* Prime-sized mappings encourage fragmentation;
* thus exposing some address entropy.
*/
struct mm {
size_t npg;
void *p;
} mm[] = {
{ 17, MAP_FAILED }, { 3, MAP_FAILED },
{ 11, MAP_FAILED }, { 2, MAP_FAILED },
{ 5, MAP_FAILED }, { 3, MAP_FAILED },
{ 7, MAP_FAILED }, { 1, MAP_FAILED },
{ 57, MAP_FAILED }, { 3, MAP_FAILED },
{ 131, MAP_FAILED }, { 1, MAP_FAILED },
};
for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
HX(mm[m].p = mmap(NULL,
mm[m].npg * pgs,
PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANON, -1,
(off_t)0), mm[m].p);
if (mm[m].p != MAP_FAILED) {
size_t mo;
/* Touch some memory... */
p = mm[m].p;
mo = cnt %
(mm[m].npg * pgs - 1);
p[mo] = 1;
cnt += (int)((long)(mm[m].p)
/ pgs);
}
/* Check cnts and times... */
for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]);
ii++) {
HX((e = clock_gettime(cl[ii],
&ts)) == -1, ts);
if (e != -1)
cnt += (int)ts.tv_nsec;
}
HX((e = getrusage(RUSAGE_SELF,
&ru)) == -1, ru);
if (e != -1) {
cnt += (int)ru.ru_utime.tv_sec;
cnt += (int)ru.ru_utime.tv_usec;
}
}
for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
if (mm[m].p != MAP_FAILED)
munmap(mm[m].p, mm[m].npg * pgs);
mm[m].p = MAP_FAILED;
}
HX(stat(".", &st) == -1, st);
HX(statvfs(".", &stvfs) == -1, stvfs);
HX(stat("/", &st) == -1, st);
HX(statvfs("/", &stvfs) == -1, stvfs);
HX((e = fstat(0, &st)) == -1, st);
if (e == -1) {
if (S_ISREG(st.st_mode) ||
S_ISFIFO(st.st_mode) ||
S_ISSOCK(st.st_mode)) {
HX(fstatvfs(0, &stvfs) == -1,
stvfs);
HX((off = lseek(0, (off_t)0,
SEEK_CUR)) < 0, off);
}
if (S_ISCHR(st.st_mode)) {
HX(tcgetattr(0, &tios) == -1,
tios);
} else if (S_ISSOCK(st.st_mode)) {
memset(&ss, 0, sizeof ss);
ssl = sizeof(ss);
HX(getpeername(0,
(void *)&ss, &ssl) == -1,
ss);
}
}
HX((e = getrusage(RUSAGE_CHILDREN,
&ru)) == -1, ru);
if (e != -1) {
cnt += (int)ru.ru_utime.tv_sec;
cnt += (int)ru.ru_utime.tv_usec;
}
} else {
/* Subsequent hashes absorb previous result */
HD(results);
}
HX((e = gettimeofday(&tv, NULL)) == -1, tv);
if (e != -1) {
cnt += (int)tv.tv_sec;
cnt += (int)tv.tv_usec;
}
HD(cnt);
}
SHA512_Final(results, &ctx);
memcpy((char *)buf + i, results, min(sizeof(results), len - i));
i += min(sizeof(results), len - i);
}
explicit_bzero(&ctx, sizeof ctx);
explicit_bzero(results, sizeof results);
if (gotdata(buf, len) == 0) {
errno = save_errno;
return (0); /* satisfied */
}
errno = EIO;
return (-1);
}

62
src/getentropy_bsd.c Normal file
View File

@@ -0,0 +1,62 @@
/* $OpenBSD: getentropy_freebsd.c,v 1.1 2014/11/03 06:23:30 bcook Exp $ */
/*
* Copyright (c) 2014 Pawel Jakub Dawidek <pjd@FreeBSD.org>
* Copyright (c) 2014 Brent Cook <bcook@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Emulation of getentropy(2) as documented at:
* http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man2/getentropy.2
*/
#include <sys/types.h>
#include <sys/sysctl.h>
#include <errno.h>
#include <stddef.h>
/*
* Derived from lib/libc/gen/arc4random.c from FreeBSD.
*/
static size_t
getentropy_sysctl(u_char *buf, size_t size)
{
int mib[2];
size_t len, done;
mib[0] = CTL_KERN;
mib[1] = KERN_ARND;
done = 0;
do {
len = size;
if (sysctl(mib, 2, buf, &len, NULL, 0) == -1)
return (done);
done += len;
buf += len;
size -= len;
} while (size > 0);
return (done);
}
int
getentropy(void *buf, size_t len)
{
if (len <= 256 && getentropy_sysctl(buf, len) == len)
return (0);
errno = EIO;
return (-1);
}

420
src/getentropy_hpux.c Normal file
View File

@@ -0,0 +1,420 @@
/* $OpenBSD: getentropy_hpux.c,v 1.3 2015/08/25 17:26:43 deraadt Exp $ */
/*
* Copyright (c) 2014 Theo de Raadt <deraadt@openbsd.org>
* Copyright (c) 2014 Bob Beck <beck@obtuse.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Emulation of getentropy(2) as documented at:
* http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man2/getentropy.2
*/
#include <sys/types.h>
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/resource.h>
#include <sys/syscall.h>
#include <sys/statvfs.h>
#include <sys/socket.h>
#include <sys/mount.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <termios.h>
#include <fcntl.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <time.h>
#include "hash/sha512.h"
#include <sys/vfs.h>
#include <sys/pstat.h>
#define REPEAT 5
#define min(a, b) (((a) < (b)) ? (a) : (b))
#define HX(a, b) \
do { \
if ((a)) \
HD(errno); \
else \
HD(b); \
} while (0)
#define HR(x, l) (SHA512_Update(&ctx, (char *)(x), (l)))
#define HD(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (x)))
#define HF(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (void*)))
int getentropy(void *buf, size_t len);
static int gotdata(char *buf, size_t len);
static int getentropy_urandom(void *buf, size_t len, const char *path,
int devfscheck);
static int getentropy_fallback(void *buf, size_t len);
int
getentropy(void *buf, size_t len)
{
int ret = -1;
if (len > 256) {
errno = EIO;
return (-1);
}
/*
* Try to get entropy with /dev/urandom
*/
ret = getentropy_urandom(buf, len, "/dev/urandom", 0);
if (ret != -1)
return (ret);
/*
* Entropy collection via /dev/urandom has failed.
*
* No other API exists for collecting entropy, and we have
* no failsafe way to get it on hpux that is not sensitive
* to resource exhaustion.
*
* We have very few options:
* - Even syslog_r is unsafe to call at this low level, so
* there is no way to alert the user or program.
* - Cannot call abort() because some systems have unsafe
* corefiles.
* - Could raise(SIGKILL) resulting in silent program termination.
* - Return EIO, to hint that arc4random's stir function
* should raise(SIGKILL)
* - Do the best under the circumstances....
*
* This code path exists to bring light to the issue that hpux
* does not provide a failsafe API for entropy collection.
*
* We hope this demonstrates that hpux should consider
* providing a new failsafe API which works in a chroot or
* when file descriptors are exhausted.
*/
#undef FAIL_INSTEAD_OF_TRYING_FALLBACK
#ifdef FAIL_INSTEAD_OF_TRYING_FALLBACK
raise(SIGKILL);
#endif
ret = getentropy_fallback(buf, len);
if (ret != -1)
return (ret);
errno = EIO;
return (ret);
}
/*
* Basic sanity checking; wish we could do better.
*/
static int
gotdata(char *buf, size_t len)
{
char any_set = 0;
size_t i;
for (i = 0; i < len; ++i)
any_set |= buf[i];
if (any_set == 0)
return (-1);
return (0);
}
static int
getentropy_urandom(void *buf, size_t len, const char *path, int devfscheck)
{
struct stat st;
size_t i;
int fd, flags;
int save_errno = errno;
start:
flags = O_RDONLY;
#ifdef O_NOFOLLOW
flags |= O_NOFOLLOW;
#endif
#ifdef O_CLOEXEC
flags |= O_CLOEXEC;
#endif
fd = open(path, flags, 0);
if (fd == -1) {
if (errno == EINTR)
goto start;
goto nodevrandom;
}
#ifndef O_CLOEXEC
fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
#endif
/* Lightly verify that the device node looks sane */
if (fstat(fd, &st) == -1 || !S_ISCHR(st.st_mode)) {
close(fd);
goto nodevrandom;
}
for (i = 0; i < len; ) {
size_t wanted = len - i;
ssize_t ret = read(fd, (char *)buf + i, wanted);
if (ret == -1) {
if (errno == EAGAIN || errno == EINTR)
continue;
close(fd);
goto nodevrandom;
}
i += ret;
}
close(fd);
if (gotdata(buf, len) == 0) {
errno = save_errno;
return (0); /* satisfied */
}
nodevrandom:
errno = EIO;
return (-1);
}
static const int cl[] = {
CLOCK_REALTIME,
#ifdef CLOCK_MONOTONIC
CLOCK_MONOTONIC,
#endif
#ifdef CLOCK_MONOTONIC_RAW
CLOCK_MONOTONIC_RAW,
#endif
#ifdef CLOCK_TAI
CLOCK_TAI,
#endif
#ifdef CLOCK_VIRTUAL
CLOCK_VIRTUAL,
#endif
#ifdef CLOCK_UPTIME
CLOCK_UPTIME,
#endif
#ifdef CLOCK_PROCESS_CPUTIME_ID
CLOCK_PROCESS_CPUTIME_ID,
#endif
#ifdef CLOCK_THREAD_CPUTIME_ID
CLOCK_THREAD_CPUTIME_ID,
#endif
};
static int
getentropy_fallback(void *buf, size_t len)
{
uint8_t results[SHA512_DIGEST_LENGTH];
int save_errno = errno, e, pgs = sysconf(_SC_PAGESIZE), faster = 0, repeat;
static int cnt;
struct timespec ts;
struct timeval tv;
struct pst_vminfo pvi;
struct pst_vm_status pvs;
struct pst_dynamic pdy;
struct rusage ru;
sigset_t sigset;
struct stat st;
SHA512_CTX ctx;
static pid_t lastpid;
pid_t pid;
size_t i, ii, m;
char *p;
pid = getpid();
if (lastpid == pid) {
faster = 1;
repeat = 2;
} else {
faster = 0;
lastpid = pid;
repeat = REPEAT;
}
for (i = 0; i < len; ) {
int j;
SHA512_Init(&ctx);
for (j = 0; j < repeat; j++) {
HX((e = gettimeofday(&tv, NULL)) == -1, tv);
if (e != -1) {
cnt += (int)tv.tv_sec;
cnt += (int)tv.tv_usec;
}
HX(pstat_getvminfo(&pvi, sizeof(pvi), 1, 0) != 1, pvi);
HX(pstat_getprocvm(&pvs, sizeof(pvs), 0, 0) != 1, pvs);
for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]); ii++)
HX(clock_gettime(cl[ii], &ts) == -1, ts);
HX((pid = getpid()) == -1, pid);
HX((pid = getsid(pid)) == -1, pid);
HX((pid = getppid()) == -1, pid);
HX((pid = getpgid(0)) == -1, pid);
HX((e = getpriority(0, 0)) == -1, e);
if(pstat_getdynamic(&pdy, sizeof(pdy), 1, 0) != 1) {
HD(errno);
} else {
HD(pdy.psd_avg_1_min);
HD(pdy.psd_avg_5_min);
HD(pdy.psd_avg_15_min);
}
if (!faster) {
ts.tv_sec = 0;
ts.tv_nsec = 1;
(void) nanosleep(&ts, NULL);
}
HX(sigpending(&sigset) == -1, sigset);
HX(sigprocmask(SIG_BLOCK, NULL, &sigset) == -1,
sigset);
HF(getentropy); /* an addr in this library */
HF(printf); /* an addr in libc */
p = (char *)&p;
HD(p); /* an addr on stack */
p = (char *)&errno;
HD(p); /* the addr of errno */
if (i == 0) {
struct sockaddr_storage ss;
struct statvfs stvfs;
struct termios tios;
socklen_t ssl;
off_t off;
/*
* Prime-sized mappings encourage fragmentation;
* thus exposing some address entropy.
*/
struct mm {
size_t npg;
void *p;
} mm[] = {
{ 17, MAP_FAILED }, { 3, MAP_FAILED },
{ 11, MAP_FAILED }, { 2, MAP_FAILED },
{ 5, MAP_FAILED }, { 3, MAP_FAILED },
{ 7, MAP_FAILED }, { 1, MAP_FAILED },
{ 57, MAP_FAILED }, { 3, MAP_FAILED },
{ 131, MAP_FAILED }, { 1, MAP_FAILED },
};
for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
HX(mm[m].p = mmap(NULL,
mm[m].npg * pgs,
PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANON, -1,
(off_t)0), mm[m].p);
if (mm[m].p != MAP_FAILED) {
size_t mo;
/* Touch some memory... */
p = mm[m].p;
mo = cnt %
(mm[m].npg * pgs - 1);
p[mo] = 1;
cnt += (int)((long)(mm[m].p)
/ pgs);
}
/* Check cnts and times... */
for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]);
ii++) {
HX((e = clock_gettime(cl[ii],
&ts)) == -1, ts);
if (e != -1)
cnt += (int)ts.tv_nsec;
}
HX((e = getrusage(RUSAGE_SELF,
&ru)) == -1, ru);
if (e != -1) {
cnt += (int)ru.ru_utime.tv_sec;
cnt += (int)ru.ru_utime.tv_usec;
}
}
for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
if (mm[m].p != MAP_FAILED)
munmap(mm[m].p, mm[m].npg * pgs);
mm[m].p = MAP_FAILED;
}
HX(stat(".", &st) == -1, st);
HX(statvfs(".", &stvfs) == -1, stvfs);
HX(stat("/", &st) == -1, st);
HX(statvfs("/", &stvfs) == -1, stvfs);
HX((e = fstat(0, &st)) == -1, st);
if (e == -1) {
if (S_ISREG(st.st_mode) ||
S_ISFIFO(st.st_mode) ||
S_ISSOCK(st.st_mode)) {
HX(fstatvfs(0, &stvfs) == -1,
stvfs);
HX((off = lseek(0, (off_t)0,
SEEK_CUR)) < 0, off);
}
if (S_ISCHR(st.st_mode)) {
HX(tcgetattr(0, &tios) == -1,
tios);
} else if (S_ISSOCK(st.st_mode)) {
memset(&ss, 0, sizeof ss);
ssl = sizeof(ss);
HX(getpeername(0,
(void *)&ss, &ssl) == -1,
ss);
}
}
HX((e = getrusage(RUSAGE_CHILDREN,
&ru)) == -1, ru);
if (e != -1) {
cnt += (int)ru.ru_utime.tv_sec;
cnt += (int)ru.ru_utime.tv_usec;
}
} else {
/* Subsequent hashes absorb previous result */
HD(results);
}
HX((e = gettimeofday(&tv, NULL)) == -1, tv);
if (e != -1) {
cnt += (int)tv.tv_sec;
cnt += (int)tv.tv_usec;
}
HD(cnt);
}
SHA512_Final(results, &ctx);
memcpy((char *)buf + i, results, min(sizeof(results), len - i));
i += min(sizeof(results), len - i);
}
explicit_bzero(&ctx, sizeof ctx);
explicit_bzero(results, sizeof results);
if (gotdata(buf, len) == 0) {
errno = save_errno;
return (0); /* satisfied */
}
errno = EIO;
return (-1);
}

446
src/getentropy_hurd.c Normal file
View File

@@ -0,0 +1,446 @@
/* $OpenBSD: getentropy_linux.c,v 1.40 2015/08/25 17:26:43 deraadt Exp $ */
/*
* Copyright (c) 2014 Theo de Raadt <deraadt@openbsd.org>
* Copyright (c) 2014 Bob Beck <beck@obtuse.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Emulation of getentropy(2) as documented at:
* http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man2/getentropy.2
*/
#define _POSIX_C_SOURCE 199309L
#define _GNU_SOURCE 1
#include <sys/types.h>
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/resource.h>
#include <sys/syscall.h>
#include <sys/statvfs.h>
#include <sys/socket.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <link.h>
#include <termios.h>
#include <fcntl.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <time.h>
#include "hash/sha512.h"
#ifdef HAVE_GETAUXVAL
#include <sys/auxv.h>
#endif
#include <sys/vfs.h>
#define REPEAT 5
#define min(a, b) (((a) < (b)) ? (a) : (b))
#define HX(a, b) \
do { \
if ((a)) \
HD(errno); \
else \
HD(b); \
} while (0)
#define HR(x, l) (SHA512_Update(&ctx, (char *)(x), (l)))
#define HD(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (x)))
#define HF(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (void*)))
int getentropy(void *buf, size_t len);
static int gotdata(char *buf, size_t len);
static int getentropy_urandom(void *buf, size_t len);
static int getentropy_fallback(void *buf, size_t len);
static int getentropy_phdr(struct dl_phdr_info *info, size_t size, void *data);
int
getentropy(void *buf, size_t len)
{
int ret = -1;
if (len > 256) {
errno = EIO;
return (-1);
}
/*
* Try to get entropy with /dev/urandom
*
* This can fail if the process is inside a chroot or if file
* descriptors are exhausted.
*/
ret = getentropy_urandom(buf, len);
if (ret != -1)
return (ret);
/*
* Entropy collection via /dev/urandom has failed.
*
* No other API exists for collecting entropy. See the large
* comment block above.
*
* We have very few options:
* - Even syslog_r is unsafe to call at this low level, so
* there is no way to alert the user or program.
* - Cannot call abort() because some systems have unsafe
* corefiles.
* - Could raise(SIGKILL) resulting in silent program termination.
* - Return EIO, to hint that arc4random's stir function
* should raise(SIGKILL)
* - Do the best under the circumstances....
*
* This code path exists to bring light to the issue that Hurd
* does not provide a failsafe API for entropy collection.
*
* We hope this demonstrates that Hurd should either get a
* sysctl ABI, or consider providing a new failsafe API which
* works in a chroot or when file descriptors are exhausted.
*/
#undef FAIL_INSTEAD_OF_TRYING_FALLBACK
#ifdef FAIL_INSTEAD_OF_TRYING_FALLBACK
raise(SIGKILL);
#endif
ret = getentropy_fallback(buf, len);
if (ret != -1)
return (ret);
errno = EIO;
return (ret);
}
/*
* Basic sanity checking; wish we could do better.
*/
static int
gotdata(char *buf, size_t len)
{
char any_set = 0;
size_t i;
for (i = 0; i < len; ++i)
any_set |= buf[i];
if (any_set == 0)
return (-1);
return (0);
}
static int
getentropy_urandom(void *buf, size_t len)
{
struct stat st;
size_t i;
int fd, flags;
int save_errno = errno;
start:
flags = O_RDONLY;
#ifdef O_NOFOLLOW
flags |= O_NOFOLLOW;
#endif
#ifdef O_CLOEXEC
flags |= O_CLOEXEC;
#endif
fd = open("/dev/urandom", flags, 0);
if (fd == -1) {
if (errno == EINTR)
goto start;
goto nodevrandom;
}
#ifndef O_CLOEXEC
fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
#endif
/* Lightly verify that the device node looks sane */
if (fstat(fd, &st) == -1 || !S_ISCHR(st.st_mode)) {
close(fd);
goto nodevrandom;
}
for (i = 0; i < len; ) {
size_t wanted = len - i;
ssize_t ret = read(fd, (char *)buf + i, wanted);
if (ret == -1) {
if (errno == EAGAIN || errno == EINTR)
continue;
close(fd);
goto nodevrandom;
}
i += ret;
}
close(fd);
if (gotdata(buf, len) == 0) {
errno = save_errno;
return (0); /* satisfied */
}
nodevrandom:
errno = EIO;
return (-1);
}
static const int cl[] = {
CLOCK_REALTIME,
#ifdef CLOCK_MONOTONIC
CLOCK_MONOTONIC,
#endif
#ifdef CLOCK_MONOTONIC_RAW
CLOCK_MONOTONIC_RAW,
#endif
#ifdef CLOCK_TAI
CLOCK_TAI,
#endif
#ifdef CLOCK_VIRTUAL
CLOCK_VIRTUAL,
#endif
#ifdef CLOCK_UPTIME
CLOCK_UPTIME,
#endif
#ifdef CLOCK_PROCESS_CPUTIME_ID
CLOCK_PROCESS_CPUTIME_ID,
#endif
#ifdef CLOCK_THREAD_CPUTIME_ID
CLOCK_THREAD_CPUTIME_ID,
#endif
};
static int
getentropy_phdr(struct dl_phdr_info *info, size_t size, void *data)
{
SHA512_CTX *ctx = data;
SHA512_Update(ctx, &info->dlpi_addr, sizeof (info->dlpi_addr));
return (0);
}
static int
getentropy_fallback(void *buf, size_t len)
{
uint8_t results[SHA512_DIGEST_LENGTH];
int save_errno = errno, e, pgs = getpagesize(), faster = 0, repeat;
static int cnt;
struct timespec ts;
struct timeval tv;
struct rusage ru;
sigset_t sigset;
struct stat st;
SHA512_CTX ctx;
static pid_t lastpid;
pid_t pid;
size_t i, ii, m;
char *p;
pid = getpid();
if (lastpid == pid) {
faster = 1;
repeat = 2;
} else {
faster = 0;
lastpid = pid;
repeat = REPEAT;
}
for (i = 0; i < len; ) {
int j;
SHA512_Init(&ctx);
for (j = 0; j < repeat; j++) {
HX((e = gettimeofday(&tv, NULL)) == -1, tv);
if (e != -1) {
cnt += (int)tv.tv_sec;
cnt += (int)tv.tv_usec;
}
dl_iterate_phdr(getentropy_phdr, &ctx);
for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]); ii++)
HX(clock_gettime(cl[ii], &ts) == -1, ts);
HX((pid = getpid()) == -1, pid);
HX((pid = getsid(pid)) == -1, pid);
HX((pid = getppid()) == -1, pid);
HX((pid = getpgid(0)) == -1, pid);
HX((e = getpriority(0, 0)) == -1, e);
if (!faster) {
ts.tv_sec = 0;
ts.tv_nsec = 1;
(void) nanosleep(&ts, NULL);
}
HX(sigpending(&sigset) == -1, sigset);
HX(sigprocmask(SIG_BLOCK, NULL, &sigset) == -1,
sigset);
HF(getentropy); /* an addr in this library */
HF(printf); /* an addr in libc */
p = (char *)&p;
HD(p); /* an addr on stack */
p = (char *)&errno;
HD(p); /* the addr of errno */
if (i == 0) {
struct sockaddr_storage ss;
struct statvfs stvfs;
struct termios tios;
struct statfs stfs;
socklen_t ssl;
off_t off;
/*
* Prime-sized mappings encourage fragmentation;
* thus exposing some address entropy.
*/
struct mm {
size_t npg;
void *p;
} mm[] = {
{ 17, MAP_FAILED }, { 3, MAP_FAILED },
{ 11, MAP_FAILED }, { 2, MAP_FAILED },
{ 5, MAP_FAILED }, { 3, MAP_FAILED },
{ 7, MAP_FAILED }, { 1, MAP_FAILED },
{ 57, MAP_FAILED }, { 3, MAP_FAILED },
{ 131, MAP_FAILED }, { 1, MAP_FAILED },
};
for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
HX(mm[m].p = mmap(NULL,
mm[m].npg * pgs,
PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANON, -1,
(off_t)0), mm[m].p);
if (mm[m].p != MAP_FAILED) {
size_t mo;
/* Touch some memory... */
p = mm[m].p;
mo = cnt %
(mm[m].npg * pgs - 1);
p[mo] = 1;
cnt += (int)((long)(mm[m].p)
/ pgs);
}
/* Check cnts and times... */
for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]);
ii++) {
HX((e = clock_gettime(cl[ii],
&ts)) == -1, ts);
if (e != -1)
cnt += (int)ts.tv_nsec;
}
HX((e = getrusage(RUSAGE_SELF,
&ru)) == -1, ru);
if (e != -1) {
cnt += (int)ru.ru_utime.tv_sec;
cnt += (int)ru.ru_utime.tv_usec;
}
}
for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
if (mm[m].p != MAP_FAILED)
munmap(mm[m].p, mm[m].npg * pgs);
mm[m].p = MAP_FAILED;
}
HX(stat(".", &st) == -1, st);
HX(statvfs(".", &stvfs) == -1, stvfs);
HX(statfs(".", &stfs) == -1, stfs);
HX(stat("/", &st) == -1, st);
HX(statvfs("/", &stvfs) == -1, stvfs);
HX(statfs("/", &stfs) == -1, stfs);
HX((e = fstat(0, &st)) == -1, st);
if (e == -1) {
if (S_ISREG(st.st_mode) ||
S_ISFIFO(st.st_mode) ||
S_ISSOCK(st.st_mode)) {
HX(fstatvfs(0, &stvfs) == -1,
stvfs);
HX(fstatfs(0, &stfs) == -1,
stfs);
HX((off = lseek(0, (off_t)0,
SEEK_CUR)) < 0, off);
}
if (S_ISCHR(st.st_mode)) {
HX(tcgetattr(0, &tios) == -1,
tios);
} else if (S_ISSOCK(st.st_mode)) {
memset(&ss, 0, sizeof ss);
ssl = sizeof(ss);
HX(getpeername(0,
(void *)&ss, &ssl) == -1,
ss);
}
}
HX((e = getrusage(RUSAGE_CHILDREN,
&ru)) == -1, ru);
if (e != -1) {
cnt += (int)ru.ru_utime.tv_sec;
cnt += (int)ru.ru_utime.tv_usec;
}
} else {
/* Subsequent hashes absorb previous result */
HD(results);
}
HX((e = gettimeofday(&tv, NULL)) == -1, tv);
if (e != -1) {
cnt += (int)tv.tv_sec;
cnt += (int)tv.tv_usec;
}
HD(cnt);
}
#ifdef HAVE_GETAUXVAL
#ifdef AT_RANDOM
/* Not as random as you think but we take what we are given */
p = (char *) getauxval(AT_RANDOM);
if (p)
HR(p, 16);
#endif
#ifdef AT_SYSINFO_EHDR
p = (char *) getauxval(AT_SYSINFO_EHDR);
if (p)
HR(p, pgs);
#endif
#ifdef AT_BASE
p = (char *) getauxval(AT_BASE);
if (p)
HD(p);
#endif
#endif
SHA512_Final(results, &ctx);
memcpy((char *)buf + i, results, min(sizeof(results), len - i));
i += min(sizeof(results), len - i);
}
explicit_bzero(&ctx, sizeof ctx);
explicit_bzero(results, sizeof results);
if (gotdata(buf, len) == 0) {
errno = save_errno;
return (0); /* satisfied */
}
errno = EIO;
return (-1);
}

548
src/getentropy_linux.c Normal file
View File

@@ -0,0 +1,548 @@
/* $OpenBSD: getentropy_linux.c,v 1.40 2015/08/25 17:26:43 deraadt Exp $ */
/*
* Copyright (c) 2014 Theo de Raadt <deraadt@openbsd.org>
* Copyright (c) 2014 Bob Beck <beck@obtuse.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Emulation of getentropy(2) as documented at:
* http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man2/getentropy.2
*/
#define _POSIX_C_SOURCE 199309L
#define _GNU_SOURCE 1
#include <sys/types.h>
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/resource.h>
#include <sys/syscall.h>
#ifdef SYS__sysctl
#include <linux/sysctl.h>
#endif
#include <sys/statvfs.h>
#include <sys/socket.h>
#include <sys/mount.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <link.h>
#include <termios.h>
#include <fcntl.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <time.h>
#include "hash/sha512.h"
#include <linux/types.h>
#include <linux/random.h>
#ifdef HAVE_GETAUXVAL
#include <sys/auxv.h>
#endif
#include <sys/vfs.h>
#define REPEAT 5
#define min(a, b) (((a) < (b)) ? (a) : (b))
#define HX(a, b) \
do { \
if ((a)) \
HD(errno); \
else \
HD(b); \
} while (0)
#define HR(x, l) (SHA512_Update(&ctx, (char *)(x), (l)))
#define HD(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (x)))
#define HF(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (void*)))
int getentropy(void *buf, size_t len);
static int gotdata(char *buf, size_t len);
#ifdef SYS_getrandom
static int getentropy_getrandom(void *buf, size_t len);
#endif
static int getentropy_urandom(void *buf, size_t len);
#ifdef SYS__sysctl
static int getentropy_sysctl(void *buf, size_t len);
#endif
static int getentropy_fallback(void *buf, size_t len);
static int getentropy_phdr(struct dl_phdr_info *info, size_t size, void *data);
int
getentropy(void *buf, size_t len)
{
int ret = -1;
if (len > 256) {
errno = EIO;
return (-1);
}
#ifdef SYS_getrandom
/*
* Try descriptor-less getrandom()
*/
ret = getentropy_getrandom(buf, len);
if (ret != -1)
return (ret);
if (errno != ENOSYS)
return (-1);
#endif
/*
* Try to get entropy with /dev/urandom
*
* This can fail if the process is inside a chroot or if file
* descriptors are exhausted.
*/
ret = getentropy_urandom(buf, len);
if (ret != -1)
return (ret);
#ifdef SYS__sysctl
/*
* Try to use sysctl CTL_KERN, KERN_RANDOM, RANDOM_UUID.
* sysctl is a failsafe API, so it guarantees a result. This
* should work inside a chroot, or when file descriptors are
* exhuasted.
*
* However this can fail if the Linux kernel removes support
* for sysctl. Starting in 2007, there have been efforts to
* deprecate the sysctl API/ABI, and push callers towards use
* of the chroot-unavailable fd-using /proc mechanism --
* essentially the same problems as /dev/urandom.
*
* Numerous setbacks have been encountered in their deprecation
* schedule, so as of June 2014 the kernel ABI still exists on
* most Linux architectures. The sysctl() stub in libc is missing
* on some systems. There are also reports that some kernels
* spew messages to the console.
*/
ret = getentropy_sysctl(buf, len);
if (ret != -1)
return (ret);
#endif /* SYS__sysctl */
/*
* Entropy collection via /dev/urandom and sysctl have failed.
*
* No other API exists for collecting entropy. See the large
* comment block above.
*
* We have very few options:
* - Even syslog_r is unsafe to call at this low level, so
* there is no way to alert the user or program.
* - Cannot call abort() because some systems have unsafe
* corefiles.
* - Could raise(SIGKILL) resulting in silent program termination.
* - Return EIO, to hint that arc4random's stir function
* should raise(SIGKILL)
* - Do the best under the circumstances....
*
* This code path exists to bring light to the issue that Linux
* does not provide a failsafe API for entropy collection.
*
* We hope this demonstrates that Linux should either retain their
* sysctl ABI, or consider providing a new failsafe API which
* works in a chroot or when file descriptors are exhausted.
*/
#undef FAIL_INSTEAD_OF_TRYING_FALLBACK
#ifdef FAIL_INSTEAD_OF_TRYING_FALLBACK
raise(SIGKILL);
#endif
ret = getentropy_fallback(buf, len);
if (ret != -1)
return (ret);
errno = EIO;
return (ret);
}
/*
* Basic sanity checking; wish we could do better.
*/
static int
gotdata(char *buf, size_t len)
{
char any_set = 0;
size_t i;
for (i = 0; i < len; ++i)
any_set |= buf[i];
if (any_set == 0)
return (-1);
return (0);
}
#ifdef SYS_getrandom
static int
getentropy_getrandom(void *buf, size_t len)
{
int pre_errno = errno;
int ret;
if (len > 256)
return (-1);
do {
ret = syscall(SYS_getrandom, buf, len, 0);
} while (ret == -1 && errno == EINTR);
if (ret != (int)len)
return (-1);
errno = pre_errno;
return (0);
}
#endif
static int
getentropy_urandom(void *buf, size_t len)
{
struct stat st;
size_t i;
int fd, cnt, flags;
int save_errno = errno;
start:
flags = O_RDONLY;
#ifdef O_NOFOLLOW
flags |= O_NOFOLLOW;
#endif
#ifdef O_CLOEXEC
flags |= O_CLOEXEC;
#endif
fd = open("/dev/urandom", flags, 0);
if (fd == -1) {
if (errno == EINTR)
goto start;
goto nodevrandom;
}
#ifndef O_CLOEXEC
fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
#endif
/* Lightly verify that the device node looks sane */
if (fstat(fd, &st) == -1 || !S_ISCHR(st.st_mode)) {
close(fd);
goto nodevrandom;
}
if (ioctl(fd, RNDGETENTCNT, &cnt) == -1) {
close(fd);
goto nodevrandom;
}
for (i = 0; i < len; ) {
size_t wanted = len - i;
ssize_t ret = read(fd, (char *)buf + i, wanted);
if (ret == -1) {
if (errno == EAGAIN || errno == EINTR)
continue;
close(fd);
goto nodevrandom;
}
i += ret;
}
close(fd);
if (gotdata(buf, len) == 0) {
errno = save_errno;
return (0); /* satisfied */
}
nodevrandom:
errno = EIO;
return (-1);
}
#ifdef SYS__sysctl
static int
getentropy_sysctl(void *buf, size_t len)
{
static int mib[] = { CTL_KERN, KERN_RANDOM, RANDOM_UUID };
size_t i;
int save_errno = errno;
for (i = 0; i < len; ) {
size_t chunk = min(len - i, 16);
/* SYS__sysctl because some systems already removed sysctl() */
struct __sysctl_args args = {
.name = mib,
.nlen = 3,
.oldval = (char *)buf + i,
.oldlenp = &chunk,
};
if (syscall(SYS__sysctl, &args) != 0)
goto sysctlfailed;
i += chunk;
}
if (gotdata(buf, len) == 0) {
errno = save_errno;
return (0); /* satisfied */
}
sysctlfailed:
errno = EIO;
return (-1);
}
#endif /* SYS__sysctl */
static const int cl[] = {
CLOCK_REALTIME,
#ifdef CLOCK_MONOTONIC
CLOCK_MONOTONIC,
#endif
#ifdef CLOCK_MONOTONIC_RAW
CLOCK_MONOTONIC_RAW,
#endif
#ifdef CLOCK_TAI
CLOCK_TAI,
#endif
#ifdef CLOCK_VIRTUAL
CLOCK_VIRTUAL,
#endif
#ifdef CLOCK_UPTIME
CLOCK_UPTIME,
#endif
#ifdef CLOCK_PROCESS_CPUTIME_ID
CLOCK_PROCESS_CPUTIME_ID,
#endif
#ifdef CLOCK_THREAD_CPUTIME_ID
CLOCK_THREAD_CPUTIME_ID,
#endif
};
static int
getentropy_phdr(struct dl_phdr_info *info, size_t size, void *data)
{
SHA512_CTX *ctx = data;
SHA512_Update(ctx, &info->dlpi_addr, sizeof (info->dlpi_addr));
return (0);
}
static int
getentropy_fallback(void *buf, size_t len)
{
uint8_t results[SHA512_DIGEST_LENGTH];
int save_errno = errno, e, pgs = getpagesize(), faster = 0, repeat;
static int cnt;
struct timespec ts;
struct timeval tv;
struct rusage ru;
sigset_t sigset;
struct stat st;
SHA512_CTX ctx;
static pid_t lastpid;
pid_t pid;
size_t i, ii, m;
char *p;
pid = getpid();
if (lastpid == pid) {
faster = 1;
repeat = 2;
} else {
faster = 0;
lastpid = pid;
repeat = REPEAT;
}
for (i = 0; i < len; ) {
int j;
SHA512_Init(&ctx);
for (j = 0; j < repeat; j++) {
HX((e = gettimeofday(&tv, NULL)) == -1, tv);
if (e != -1) {
cnt += (int)tv.tv_sec;
cnt += (int)tv.tv_usec;
}
dl_iterate_phdr(getentropy_phdr, &ctx);
for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]); ii++)
HX(clock_gettime(cl[ii], &ts) == -1, ts);
HX((pid = getpid()) == -1, pid);
HX((pid = getsid(pid)) == -1, pid);
HX((pid = getppid()) == -1, pid);
HX((pid = getpgid(0)) == -1, pid);
HX((e = getpriority(0, 0)) == -1, e);
if (!faster) {
ts.tv_sec = 0;
ts.tv_nsec = 1;
(void) nanosleep(&ts, NULL);
}
HX(sigpending(&sigset) == -1, sigset);
HX(sigprocmask(SIG_BLOCK, NULL, &sigset) == -1,
sigset);
HF(getentropy); /* an addr in this library */
HF(printf); /* an addr in libc */
p = (char *)&p;
HD(p); /* an addr on stack */
p = (char *)&errno;
HD(p); /* the addr of errno */
if (i == 0) {
struct sockaddr_storage ss;
struct statvfs stvfs;
struct termios tios;
struct statfs stfs;
socklen_t ssl;
off_t off;
/*
* Prime-sized mappings encourage fragmentation;
* thus exposing some address entropy.
*/
struct mm {
size_t npg;
void *p;
} mm[] = {
{ 17, MAP_FAILED }, { 3, MAP_FAILED },
{ 11, MAP_FAILED }, { 2, MAP_FAILED },
{ 5, MAP_FAILED }, { 3, MAP_FAILED },
{ 7, MAP_FAILED }, { 1, MAP_FAILED },
{ 57, MAP_FAILED }, { 3, MAP_FAILED },
{ 131, MAP_FAILED }, { 1, MAP_FAILED },
};
for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
HX(mm[m].p = mmap(NULL,
mm[m].npg * pgs,
PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANON, -1,
(off_t)0), mm[m].p);
if (mm[m].p != MAP_FAILED) {
size_t mo;
/* Touch some memory... */
p = mm[m].p;
mo = cnt %
(mm[m].npg * pgs - 1);
p[mo] = 1;
cnt += (int)((long)(mm[m].p)
/ pgs);
}
/* Check cnts and times... */
for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]);
ii++) {
HX((e = clock_gettime(cl[ii],
&ts)) == -1, ts);
if (e != -1)
cnt += (int)ts.tv_nsec;
}
HX((e = getrusage(RUSAGE_SELF,
&ru)) == -1, ru);
if (e != -1) {
cnt += (int)ru.ru_utime.tv_sec;
cnt += (int)ru.ru_utime.tv_usec;
}
}
for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
if (mm[m].p != MAP_FAILED)
munmap(mm[m].p, mm[m].npg * pgs);
mm[m].p = MAP_FAILED;
}
HX(stat(".", &st) == -1, st);
HX(statvfs(".", &stvfs) == -1, stvfs);
HX(statfs(".", &stfs) == -1, stfs);
HX(stat("/", &st) == -1, st);
HX(statvfs("/", &stvfs) == -1, stvfs);
HX(statfs("/", &stfs) == -1, stfs);
HX((e = fstat(0, &st)) == -1, st);
if (e == -1) {
if (S_ISREG(st.st_mode) ||
S_ISFIFO(st.st_mode) ||
S_ISSOCK(st.st_mode)) {
HX(fstatvfs(0, &stvfs) == -1,
stvfs);
HX(fstatfs(0, &stfs) == -1,
stfs);
HX((off = lseek(0, (off_t)0,
SEEK_CUR)) < 0, off);
}
if (S_ISCHR(st.st_mode)) {
HX(tcgetattr(0, &tios) == -1,
tios);
} else if (S_ISSOCK(st.st_mode)) {
memset(&ss, 0, sizeof ss);
ssl = sizeof(ss);
HX(getpeername(0,
(void *)&ss, &ssl) == -1,
ss);
}
}
HX((e = getrusage(RUSAGE_CHILDREN,
&ru)) == -1, ru);
if (e != -1) {
cnt += (int)ru.ru_utime.tv_sec;
cnt += (int)ru.ru_utime.tv_usec;
}
} else {
/* Subsequent hashes absorb previous result */
HD(results);
}
HX((e = gettimeofday(&tv, NULL)) == -1, tv);
if (e != -1) {
cnt += (int)tv.tv_sec;
cnt += (int)tv.tv_usec;
}
HD(cnt);
}
#ifdef HAVE_GETAUXVAL
#ifdef AT_RANDOM
/* Not as random as you think but we take what we are given */
p = (char *) getauxval(AT_RANDOM);
if (p)
HR(p, 16);
#endif
#ifdef AT_SYSINFO_EHDR
p = (char *) getauxval(AT_SYSINFO_EHDR);
if (p)
HR(p, pgs);
#endif
#ifdef AT_BASE
p = (char *) getauxval(AT_BASE);
if (p)
HD(p);
#endif
#endif
SHA512_Final(results, &ctx);
memcpy((char *)buf + i, results, min(sizeof(results), len - i));
i += min(sizeof(results), len - i);
}
explicit_bzero(&ctx, sizeof ctx);
explicit_bzero(results, sizeof results);
if (gotdata(buf, len) == 0) {
errno = save_errno;
return (0); /* satisfied */
}
errno = EIO;
return (-1);
}

429
src/getentropy_osx.c Normal file
View File

@@ -0,0 +1,429 @@
/* $OpenBSD: getentropy_osx.c,v 1.8 2014/07/21 20:19:47 guenther Exp $ */
/*
* Copyright (c) 2014 Theo de Raadt <deraadt@openbsd.org>
* Copyright (c) 2014 Bob Beck <beck@obtuse.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Emulation of getentropy(2) as documented at:
* http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man2/getentropy.2
*/
#include <sys/types.h>
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/resource.h>
#include <sys/syscall.h>
#include <sys/sysctl.h>
#include <sys/statvfs.h>
#include <sys/socket.h>
#include <sys/mount.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <termios.h>
#include <fcntl.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <time.h>
#include <mach/mach_time.h>
#include <mach/mach_host.h>
#include <mach/host_info.h>
#include <sys/socketvar.h>
#include <sys/vmmeter.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <netinet/ip_var.h>
#include <netinet/tcp_var.h>
#include <netinet/udp_var.h>
#include <CommonCrypto/CommonDigest.h>
#define SHA512_Update(a, b, c) (CC_SHA512_Update((a), (b), (c)))
#define SHA512_Init(xxx) (CC_SHA512_Init((xxx)))
#define SHA512_Final(xxx, yyy) (CC_SHA512_Final((xxx), (yyy)))
#define SHA512_CTX CC_SHA512_CTX
#define SHA512_DIGEST_LENGTH CC_SHA512_DIGEST_LENGTH
#define REPEAT 5
#define min(a, b) (((a) < (b)) ? (a) : (b))
#define HX(a, b) \
do { \
if ((a)) \
HD(errno); \
else \
HD(b); \
} while (0)
#define HR(x, l) (SHA512_Update(&ctx, (char *)(x), (l)))
#define HD(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (x)))
#define HF(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (void*)))
int getentropy(void *buf, size_t len);
static int gotdata(char *buf, size_t len);
static int getentropy_urandom(void *buf, size_t len);
static int getentropy_fallback(void *buf, size_t len);
int
getentropy(void *buf, size_t len)
{
int ret = -1;
if (len > 256) {
errno = EIO;
return (-1);
}
/*
* Try to get entropy with /dev/urandom
*
* This can fail if the process is inside a chroot or if file
* descriptors are exhausted.
*/
ret = getentropy_urandom(buf, len);
if (ret != -1)
return (ret);
/*
* Entropy collection via /dev/urandom and sysctl have failed.
*
* No other API exists for collecting entropy, and we have
* no failsafe way to get it on OSX that is not sensitive
* to resource exhaustion.
*
* We have very few options:
* - Even syslog_r is unsafe to call at this low level, so
* there is no way to alert the user or program.
* - Cannot call abort() because some systems have unsafe
* corefiles.
* - Could raise(SIGKILL) resulting in silent program termination.
* - Return EIO, to hint that arc4random's stir function
* should raise(SIGKILL)
* - Do the best under the circumstances....
*
* This code path exists to bring light to the issue that OSX
* does not provide a failsafe API for entropy collection.
*
* We hope this demonstrates that OSX should consider
* providing a new failsafe API which works in a chroot or
* when file descriptors are exhausted.
*/
#undef FAIL_INSTEAD_OF_TRYING_FALLBACK
#ifdef FAIL_INSTEAD_OF_TRYING_FALLBACK
raise(SIGKILL);
#endif
ret = getentropy_fallback(buf, len);
if (ret != -1)
return (ret);
errno = EIO;
return (ret);
}
/*
* Basic sanity checking; wish we could do better.
*/
static int
gotdata(char *buf, size_t len)
{
char any_set = 0;
size_t i;
for (i = 0; i < len; ++i)
any_set |= buf[i];
if (any_set == 0)
return (-1);
return (0);
}
static int
getentropy_urandom(void *buf, size_t len)
{
struct stat st;
size_t i;
int fd, flags;
int save_errno = errno;
start:
flags = O_RDONLY;
#ifdef O_NOFOLLOW
flags |= O_NOFOLLOW;
#endif
#ifdef O_CLOEXEC
flags |= O_CLOEXEC;
#endif
fd = open("/dev/urandom", flags, 0);
if (fd == -1) {
if (errno == EINTR)
goto start;
goto nodevrandom;
}
#ifndef O_CLOEXEC
fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
#endif
/* Lightly verify that the device node looks sane */
if (fstat(fd, &st) == -1 || !S_ISCHR(st.st_mode)) {
close(fd);
goto nodevrandom;
}
for (i = 0; i < len; ) {
size_t wanted = len - i;
ssize_t ret = read(fd, (char *)buf + i, wanted);
if (ret == -1) {
if (errno == EAGAIN || errno == EINTR)
continue;
close(fd);
goto nodevrandom;
}
i += ret;
}
close(fd);
if (gotdata(buf, len) == 0) {
errno = save_errno;
return (0); /* satisfied */
}
nodevrandom:
errno = EIO;
return (-1);
}
static int tcpmib[] = { CTL_NET, AF_INET, IPPROTO_TCP, TCPCTL_STATS };
static int udpmib[] = { CTL_NET, AF_INET, IPPROTO_UDP, UDPCTL_STATS };
static int ipmib[] = { CTL_NET, AF_INET, IPPROTO_IP, IPCTL_STATS };
static int kmib[] = { CTL_KERN, KERN_USRSTACK };
static int hwmib[] = { CTL_HW, HW_USERMEM };
static int
getentropy_fallback(void *buf, size_t len)
{
uint8_t results[SHA512_DIGEST_LENGTH];
int save_errno = errno, e, pgs = getpagesize(), faster = 0, repeat;
static int cnt;
struct timespec ts;
struct timeval tv;
struct rusage ru;
sigset_t sigset;
struct stat st;
SHA512_CTX ctx;
static pid_t lastpid;
pid_t pid;
size_t i, ii, m;
char *p;
struct tcpstat tcpstat;
struct udpstat udpstat;
struct ipstat ipstat;
uint64_t mach_time;
unsigned int idata;
void *addr;
pid = getpid();
if (lastpid == pid) {
faster = 1;
repeat = 2;
} else {
faster = 0;
lastpid = pid;
repeat = REPEAT;
}
for (i = 0; i < len; ) {
int j;
SHA512_Init(&ctx);
for (j = 0; j < repeat; j++) {
HX((e = gettimeofday(&tv, NULL)) == -1, tv);
if (e != -1) {
cnt += (int)tv.tv_sec;
cnt += (int)tv.tv_usec;
}
mach_time = mach_absolute_time();
HD(mach_time);
ii = sizeof(addr);
HX(sysctl(kmib, sizeof(kmib) / sizeof(kmib[0]),
&addr, &ii, NULL, 0) == -1, addr);
ii = sizeof(idata);
HX(sysctl(hwmib, sizeof(hwmib) / sizeof(hwmib[0]),
&idata, &ii, NULL, 0) == -1, idata);
ii = sizeof(tcpstat);
HX(sysctl(tcpmib, sizeof(tcpmib) / sizeof(tcpmib[0]),
&tcpstat, &ii, NULL, 0) == -1, tcpstat);
ii = sizeof(udpstat);
HX(sysctl(udpmib, sizeof(udpmib) / sizeof(udpmib[0]),
&udpstat, &ii, NULL, 0) == -1, udpstat);
ii = sizeof(ipstat);
HX(sysctl(ipmib, sizeof(ipmib) / sizeof(ipmib[0]),
&ipstat, &ii, NULL, 0) == -1, ipstat);
HX((pid = getpid()) == -1, pid);
HX((pid = getsid(pid)) == -1, pid);
HX((pid = getppid()) == -1, pid);
HX((pid = getpgid(0)) == -1, pid);
HX((e = getpriority(0, 0)) == -1, e);
if (!faster) {
ts.tv_sec = 0;
ts.tv_nsec = 1;
(void) nanosleep(&ts, NULL);
}
HX(sigpending(&sigset) == -1, sigset);
HX(sigprocmask(SIG_BLOCK, NULL, &sigset) == -1,
sigset);
HF(getentropy); /* an addr in this library */
HF(printf); /* an addr in libc */
p = (char *)&p;
HD(p); /* an addr on stack */
p = (char *)&errno;
HD(p); /* the addr of errno */
if (i == 0) {
struct sockaddr_storage ss;
struct statvfs stvfs;
struct termios tios;
struct statfs stfs;
socklen_t ssl;
off_t off;
/*
* Prime-sized mappings encourage fragmentation;
* thus exposing some address entropy.
*/
struct mm {
size_t npg;
void *p;
} mm[] = {
{ 17, MAP_FAILED }, { 3, MAP_FAILED },
{ 11, MAP_FAILED }, { 2, MAP_FAILED },
{ 5, MAP_FAILED }, { 3, MAP_FAILED },
{ 7, MAP_FAILED }, { 1, MAP_FAILED },
{ 57, MAP_FAILED }, { 3, MAP_FAILED },
{ 131, MAP_FAILED }, { 1, MAP_FAILED },
};
for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
HX(mm[m].p = mmap(NULL,
mm[m].npg * pgs,
PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANON, -1,
(off_t)0), mm[m].p);
if (mm[m].p != MAP_FAILED) {
size_t mo;
/* Touch some memory... */
p = mm[m].p;
mo = cnt %
(mm[m].npg * pgs - 1);
p[mo] = 1;
cnt += (int)((long)(mm[m].p)
/ pgs);
}
/* Check cnts and times... */
mach_time = mach_absolute_time();
HD(mach_time);
cnt += (int)mach_time;
HX((e = getrusage(RUSAGE_SELF,
&ru)) == -1, ru);
if (e != -1) {
cnt += (int)ru.ru_utime.tv_sec;
cnt += (int)ru.ru_utime.tv_usec;
}
}
for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
if (mm[m].p != MAP_FAILED)
munmap(mm[m].p, mm[m].npg * pgs);
mm[m].p = MAP_FAILED;
}
HX(stat(".", &st) == -1, st);
HX(statvfs(".", &stvfs) == -1, stvfs);
HX(statfs(".", &stfs) == -1, stfs);
HX(stat("/", &st) == -1, st);
HX(statvfs("/", &stvfs) == -1, stvfs);
HX(statfs("/", &stfs) == -1, stfs);
HX((e = fstat(0, &st)) == -1, st);
if (e == -1) {
if (S_ISREG(st.st_mode) ||
S_ISFIFO(st.st_mode) ||
S_ISSOCK(st.st_mode)) {
HX(fstatvfs(0, &stvfs) == -1,
stvfs);
HX(fstatfs(0, &stfs) == -1,
stfs);
HX((off = lseek(0, (off_t)0,
SEEK_CUR)) < 0, off);
}
if (S_ISCHR(st.st_mode)) {
HX(tcgetattr(0, &tios) == -1,
tios);
} else if (S_ISSOCK(st.st_mode)) {
memset(&ss, 0, sizeof ss);
ssl = sizeof(ss);
HX(getpeername(0,
(void *)&ss, &ssl) == -1,
ss);
}
}
HX((e = getrusage(RUSAGE_CHILDREN,
&ru)) == -1, ru);
if (e != -1) {
cnt += (int)ru.ru_utime.tv_sec;
cnt += (int)ru.ru_utime.tv_usec;
}
} else {
/* Subsequent hashes absorb previous result */
HD(results);
}
HX((e = gettimeofday(&tv, NULL)) == -1, tv);
if (e != -1) {
cnt += (int)tv.tv_sec;
cnt += (int)tv.tv_usec;
}
HD(cnt);
}
SHA512_Final(results, &ctx);
memcpy((char *)buf + i, results, min(sizeof(results), len - i));
i += min(sizeof(results), len - i);
}
explicit_bzero(&ctx, sizeof ctx);
explicit_bzero(results, sizeof results);
if (gotdata(buf, len) == 0) {
errno = save_errno;
return (0); /* satisfied */
}
errno = EIO;
return (-1);
}

445
src/getentropy_solaris.c Normal file
View File

@@ -0,0 +1,445 @@
/* $OpenBSD: getentropy_solaris.c,v 1.10 2015/08/25 17:26:43 deraadt Exp $ */
/*
* Copyright (c) 2014 Theo de Raadt <deraadt@openbsd.org>
* Copyright (c) 2014 Bob Beck <beck@obtuse.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Emulation of getentropy(2) as documented at:
* http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man2/getentropy.2
*/
#include <sys/types.h>
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/resource.h>
#include <sys/syscall.h>
#include <sys/statvfs.h>
#include <sys/socket.h>
#include <sys/mount.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <link.h>
#include <termios.h>
#include <fcntl.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <time.h>
#include <sys/sha2.h>
#define SHA512_Init SHA512Init
#define SHA512_Update SHA512Update
#define SHA512_Final SHA512Final
#include <sys/vfs.h>
#include <sys/statfs.h>
#include <sys/loadavg.h>
#define REPEAT 5
#define min(a, b) (((a) < (b)) ? (a) : (b))
#define HX(a, b) \
do { \
if ((a)) \
HD(errno); \
else \
HD(b); \
} while (0)
#define HR(x, l) (SHA512_Update(&ctx, (char *)(x), (l)))
#define HD(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (x)))
#define HF(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (void*)))
int getentropy(void *buf, size_t len);
static int gotdata(char *buf, size_t len);
static int getentropy_urandom(void *buf, size_t len, const char *path,
int devfscheck);
static int getentropy_fallback(void *buf, size_t len);
static int getentropy_phdr(struct dl_phdr_info *info, size_t size, void *data);
int
getentropy(void *buf, size_t len)
{
int ret = -1;
if (len > 256) {
errno = EIO;
return (-1);
}
/*
* Try to get entropy with /dev/urandom
*
* Solaris provides /dev/urandom as a symbolic link to
* /devices/pseudo/random@0:urandom which is provided by
* a devfs filesystem. Best practice is to use O_NOFOLLOW,
* so we must try the unpublished name directly.
*
* This can fail if the process is inside a chroot which lacks
* the devfs mount, or if file descriptors are exhausted.
*/
ret = getentropy_urandom(buf, len,
"/devices/pseudo/random@0:urandom", 1);
if (ret != -1)
return (ret);
/*
* Unfortunately, chroot spaces on Solaris are sometimes setup
* with direct device node of the well-known /dev/urandom name
* (perhaps to avoid dragging all of devfs into the space).
*
* This can fail if the process is inside a chroot or if file
* descriptors are exhausted.
*/
ret = getentropy_urandom(buf, len, "/dev/urandom", 0);
if (ret != -1)
return (ret);
/*
* Entropy collection via /dev/urandom has failed.
*
* No other API exists for collecting entropy, and we have
* no failsafe way to get it on Solaris that is not sensitive
* to resource exhaustion.
*
* We have very few options:
* - Even syslog_r is unsafe to call at this low level, so
* there is no way to alert the user or program.
* - Cannot call abort() because some systems have unsafe
* corefiles.
* - Could raise(SIGKILL) resulting in silent program termination.
* - Return EIO, to hint that arc4random's stir function
* should raise(SIGKILL)
* - Do the best under the circumstances....
*
* This code path exists to bring light to the issue that Solaris
* does not provide a failsafe API for entropy collection.
*
* We hope this demonstrates that Solaris should consider
* providing a new failsafe API which works in a chroot or
* when file descriptors are exhausted.
*/
#undef FAIL_INSTEAD_OF_TRYING_FALLBACK
#ifdef FAIL_INSTEAD_OF_TRYING_FALLBACK
raise(SIGKILL);
#endif
ret = getentropy_fallback(buf, len);
if (ret != -1)
return (ret);
errno = EIO;
return (ret);
}
/*
* Basic sanity checking; wish we could do better.
*/
static int
gotdata(char *buf, size_t len)
{
char any_set = 0;
size_t i;
for (i = 0; i < len; ++i)
any_set |= buf[i];
if (any_set == 0)
return (-1);
return (0);
}
static int
getentropy_urandom(void *buf, size_t len, const char *path, int devfscheck)
{
struct stat st;
size_t i;
int fd, flags;
int save_errno = errno;
start:
flags = O_RDONLY;
#ifdef O_NOFOLLOW
flags |= O_NOFOLLOW;
#endif
#ifdef O_CLOEXEC
flags |= O_CLOEXEC;
#endif
fd = open(path, flags, 0);
if (fd == -1) {
if (errno == EINTR)
goto start;
goto nodevrandom;
}
#ifndef O_CLOEXEC
fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
#endif
/* Lightly verify that the device node looks sane */
if (fstat(fd, &st) == -1 || !S_ISCHR(st.st_mode) ||
(devfscheck && (strcmp(st.st_fstype, "devfs") != 0))) {
close(fd);
goto nodevrandom;
}
for (i = 0; i < len; ) {
size_t wanted = len - i;
ssize_t ret = read(fd, (char *)buf + i, wanted);
if (ret == -1) {
if (errno == EAGAIN || errno == EINTR)
continue;
close(fd);
goto nodevrandom;
}
i += ret;
}
close(fd);
if (gotdata(buf, len) == 0) {
errno = save_errno;
return (0); /* satisfied */
}
nodevrandom:
errno = EIO;
return (-1);
}
static const int cl[] = {
CLOCK_REALTIME,
#ifdef CLOCK_MONOTONIC
CLOCK_MONOTONIC,
#endif
#ifdef CLOCK_MONOTONIC_RAW
CLOCK_MONOTONIC_RAW,
#endif
#ifdef CLOCK_TAI
CLOCK_TAI,
#endif
#ifdef CLOCK_VIRTUAL
CLOCK_VIRTUAL,
#endif
#ifdef CLOCK_UPTIME
CLOCK_UPTIME,
#endif
#ifdef CLOCK_PROCESS_CPUTIME_ID
CLOCK_PROCESS_CPUTIME_ID,
#endif
#ifdef CLOCK_THREAD_CPUTIME_ID
CLOCK_THREAD_CPUTIME_ID,
#endif
};
static int
getentropy_phdr(struct dl_phdr_info *info, size_t size, void *data)
{
SHA512_CTX *ctx = data;
SHA512_Update(ctx, &info->dlpi_addr, sizeof (info->dlpi_addr));
return (0);
}
static int
getentropy_fallback(void *buf, size_t len)
{
uint8_t results[SHA512_DIGEST_LENGTH];
int save_errno = errno, e, pgs = getpagesize(), faster = 0, repeat;
static int cnt;
struct timespec ts;
struct timeval tv;
double loadavg[3];
struct rusage ru;
sigset_t sigset;
struct stat st;
SHA512_CTX ctx;
static pid_t lastpid;
pid_t pid;
size_t i, ii, m;
char *p;
pid = getpid();
if (lastpid == pid) {
faster = 1;
repeat = 2;
} else {
faster = 0;
lastpid = pid;
repeat = REPEAT;
}
for (i = 0; i < len; ) {
int j;
SHA512_Init(&ctx);
for (j = 0; j < repeat; j++) {
HX((e = gettimeofday(&tv, NULL)) == -1, tv);
if (e != -1) {
cnt += (int)tv.tv_sec;
cnt += (int)tv.tv_usec;
}
dl_iterate_phdr(getentropy_phdr, &ctx);
for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]); ii++)
HX(clock_gettime(cl[ii], &ts) == -1, ts);
HX((pid = getpid()) == -1, pid);
HX((pid = getsid(pid)) == -1, pid);
HX((pid = getppid()) == -1, pid);
HX((pid = getpgid(0)) == -1, pid);
HX((e = getpriority(0, 0)) == -1, e);
HX((getloadavg(loadavg, 3) == -1), loadavg);
if (!faster) {
ts.tv_sec = 0;
ts.tv_nsec = 1;
(void) nanosleep(&ts, NULL);
}
HX(sigpending(&sigset) == -1, sigset);
HX(sigprocmask(SIG_BLOCK, NULL, &sigset) == -1,
sigset);
HF(getentropy); /* an addr in this library */
HF(printf); /* an addr in libc */
p = (char *)&p;
HD(p); /* an addr on stack */
p = (char *)&errno;
HD(p); /* the addr of errno */
if (i == 0) {
struct sockaddr_storage ss;
struct statvfs stvfs;
struct termios tios;
socklen_t ssl;
off_t off;
/*
* Prime-sized mappings encourage fragmentation;
* thus exposing some address entropy.
*/
struct mm {
size_t npg;
void *p;
} mm[] = {
{ 17, MAP_FAILED }, { 3, MAP_FAILED },
{ 11, MAP_FAILED }, { 2, MAP_FAILED },
{ 5, MAP_FAILED }, { 3, MAP_FAILED },
{ 7, MAP_FAILED }, { 1, MAP_FAILED },
{ 57, MAP_FAILED }, { 3, MAP_FAILED },
{ 131, MAP_FAILED }, { 1, MAP_FAILED },
};
for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
HX(mm[m].p = mmap(NULL,
mm[m].npg * pgs,
PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANON, -1,
(off_t)0), mm[m].p);
if (mm[m].p != MAP_FAILED) {
size_t mo;
/* Touch some memory... */
p = mm[m].p;
mo = cnt %
(mm[m].npg * pgs - 1);
p[mo] = 1;
cnt += (int)((long)(mm[m].p)
/ pgs);
}
/* Check cnts and times... */
for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]);
ii++) {
HX((e = clock_gettime(cl[ii],
&ts)) == -1, ts);
if (e != -1)
cnt += (int)ts.tv_nsec;
}
HX((e = getrusage(RUSAGE_SELF,
&ru)) == -1, ru);
if (e != -1) {
cnt += (int)ru.ru_utime.tv_sec;
cnt += (int)ru.ru_utime.tv_usec;
}
}
for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
if (mm[m].p != MAP_FAILED)
munmap(mm[m].p, mm[m].npg * pgs);
mm[m].p = MAP_FAILED;
}
HX(stat(".", &st) == -1, st);
HX(statvfs(".", &stvfs) == -1, stvfs);
HX(stat("/", &st) == -1, st);
HX(statvfs("/", &stvfs) == -1, stvfs);
HX((e = fstat(0, &st)) == -1, st);
if (e == -1) {
if (S_ISREG(st.st_mode) ||
S_ISFIFO(st.st_mode) ||
S_ISSOCK(st.st_mode)) {
HX(fstatvfs(0, &stvfs) == -1,
stvfs);
HX((off = lseek(0, (off_t)0,
SEEK_CUR)) < 0, off);
}
if (S_ISCHR(st.st_mode)) {
HX(tcgetattr(0, &tios) == -1,
tios);
} else if (S_ISSOCK(st.st_mode)) {
memset(&ss, 0, sizeof ss);
ssl = sizeof(ss);
HX(getpeername(0,
(void *)&ss, &ssl) == -1,
ss);
}
}
HX((e = getrusage(RUSAGE_CHILDREN,
&ru)) == -1, ru);
if (e != -1) {
cnt += (int)ru.ru_utime.tv_sec;
cnt += (int)ru.ru_utime.tv_usec;
}
} else {
/* Subsequent hashes absorb previous result */
HD(results);
}
HX((e = gettimeofday(&tv, NULL)) == -1, tv);
if (e != -1) {
cnt += (int)tv.tv_sec;
cnt += (int)tv.tv_usec;
}
HD(cnt);
}
SHA512_Final(results, &ctx);
memcpy((char *)buf + i, results, min(sizeof(results), len - i));
i += min(sizeof(results), len - i);
}
explicit_bzero(&ctx, sizeof ctx);
explicit_bzero(results, sizeof results);
if (gotdata(buf, len) == 0) {
errno = save_errno;
return (0); /* satisfied */
}
errno = EIO;
return (-1);
}

View File

@@ -27,7 +27,7 @@ char *
HASHEnd(HASH_CTX *ctx, char *buf) HASHEnd(HASH_CTX *ctx, char *buf)
{ {
int i; int i;
u_int8_t digest[HASH_DIGEST_LENGTH]; uint8_t digest[HASH_DIGEST_LENGTH];
#ifdef HASH_DIGEST_UPPERCASE #ifdef HASH_DIGEST_UPPERCASE
static const char hex[] = "0123456789ABCDEF"; static const char hex[] = "0123456789ABCDEF";
#else #else

View File

@@ -37,7 +37,7 @@
(cp)[1] = (value) >> 8; \ (cp)[1] = (value) >> 8; \
(cp)[0] = (value); } while (0) (cp)[0] = (value); } while (0)
static u_int8_t PADDING[MD5_BLOCK_LENGTH] = { static uint8_t PADDING[MD5_BLOCK_LENGTH] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
@@ -71,7 +71,7 @@ MD5Update(MD5_CTX *ctx, const unsigned char *input, size_t len)
need = MD5_BLOCK_LENGTH - have; need = MD5_BLOCK_LENGTH - have;
/* Update bitcount */ /* Update bitcount */
ctx->count += (u_int64_t)len << 3; ctx->count += (uint64_t)len << 3;
if (len >= need) { if (len >= need) {
if (have != 0) { if (have != 0) {
@@ -102,7 +102,7 @@ MD5Update(MD5_CTX *ctx, const unsigned char *input, size_t len)
void void
MD5Pad(MD5_CTX *ctx) MD5Pad(MD5_CTX *ctx)
{ {
u_int8_t count[8]; uint8_t count[8];
size_t padlen; size_t padlen;
/* Convert count to 8 bytes in little endian order. */ /* Convert count to 8 bytes in little endian order. */
@@ -152,19 +152,19 @@ MD5Final(unsigned char digest[MD5_DIGEST_LENGTH], MD5_CTX *ctx)
* the data and converts bytes into longwords for this routine. * the data and converts bytes into longwords for this routine.
*/ */
void void
MD5Transform(u_int32_t state[4], const u_int8_t block[MD5_BLOCK_LENGTH]) MD5Transform(uint32_t state[4], const uint8_t block[MD5_BLOCK_LENGTH])
{ {
u_int32_t a, b, c, d, in[MD5_BLOCK_LENGTH / 4]; uint32_t a, b, c, d, in[MD5_BLOCK_LENGTH / 4];
#if BYTE_ORDER == LITTLE_ENDIAN #if BYTE_ORDER == LITTLE_ENDIAN
memcpy(in, block, sizeof(in)); memcpy(in, block, sizeof(in));
#else #else
for (a = 0; a < MD5_BLOCK_LENGTH / 4; a++) { for (a = 0; a < MD5_BLOCK_LENGTH / 4; a++) {
in[a] = (u_int32_t)( in[a] = (uint32_t)(
(u_int32_t)(block[a * 4 + 0]) | (uint32_t)(block[a * 4 + 0]) |
(u_int32_t)(block[a * 4 + 1]) << 8 | (uint32_t)(block[a * 4 + 1]) << 8 |
(u_int32_t)(block[a * 4 + 2]) << 16 | (uint32_t)(block[a * 4 + 2]) << 16 |
(u_int32_t)(block[a * 4 + 3]) << 24); (uint32_t)(block[a * 4 + 3]) << 24);
} }
#endif #endif

53
src/hash/sha512.h Normal file
View File

@@ -0,0 +1,53 @@
/*-
* Copyright 2005 Colin Percival
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
*
* $FreeBSD$
*/
#ifndef _SHA512_H_
#define _SHA512_H_
#include <sys/types.h>
#define SHA512_DIGEST_LENGTH 64
typedef struct SHA512Context {
uint64_t state[8];
uint64_t count[2];
unsigned char buf[128];
} SHA512_CTX;
__BEGIN_DECLS
void SHA512_Init(SHA512_CTX *);
void SHA512_Update(SHA512_CTX *, const void *, size_t);
void SHA512_Final(unsigned char [64], SHA512_CTX *);
char *SHA512_End(SHA512_CTX *, char *);
char *SHA512_File(const char *, char *);
char *SHA512_FileChunk(const char *, char *, off_t, off_t);
char *SHA512_Data(const void *, unsigned int, char *);
__END_DECLS
#endif /* !_SHA512_H_ */

320
src/hash/sha512c.c Normal file
View File

@@ -0,0 +1,320 @@
/*-
* Copyright 2005 Colin Percival
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/endian.h>
#include <sys/types.h>
#include <string.h>
#include "sha512.h"
#if BYTE_ORDER == BIG_ENDIAN
/* Copy a vector of big-endian uint64_t into a vector of bytes */
#define be64enc_vect(dst, src, len) \
memcpy((void *)dst, (const void *)src, (size_t)len)
/* Copy a vector of bytes into a vector of big-endian uint64_t */
#define be64dec_vect(dst, src, len) \
memcpy((void *)dst, (const void *)src, (size_t)len)
#else /* BYTE_ORDER != BIG_ENDIAN */
/*
* Encode a length len/4 vector of (uint64_t) into a length len vector of
* (unsigned char) in big-endian form. Assumes len is a multiple of 8.
*/
static void
be64enc_vect(unsigned char *dst, const uint64_t *src, size_t len)
{
size_t i;
for (i = 0; i < len / 8; i++)
be64enc(dst + i * 8, src[i]);
}
/*
* Decode a big-endian length len vector of (unsigned char) into a length
* len/4 vector of (uint64_t). Assumes len is a multiple of 8.
*/
static void
be64dec_vect(uint64_t *dst, const unsigned char *src, size_t len)
{
size_t i;
for (i = 0; i < len / 8; i++)
dst[i] = be64dec(src + i * 8);
}
#endif /* BYTE_ORDER != BIG_ENDIAN */
/* Elementary functions used by SHA512 */
#define Ch(x, y, z) ((x & (y ^ z)) ^ z)
#define Maj(x, y, z) ((x & (y | z)) | (y & z))
#define SHR(x, n) (x >> n)
#define ROTR(x, n) ((x >> n) | (x << (64 - n)))
#define S0(x) (ROTR(x, 28) ^ ROTR(x, 34) ^ ROTR(x, 39))
#define S1(x) (ROTR(x, 14) ^ ROTR(x, 18) ^ ROTR(x, 41))
#define s0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7))
#define s1(x) (ROTR(x, 19) ^ ROTR(x, 61) ^ SHR(x, 6))
/* SHA512 round function */
#define RND(a, b, c, d, e, f, g, h, k) \
t0 = h + S1(e) + Ch(e, f, g) + k; \
t1 = S0(a) + Maj(a, b, c); \
d += t0; \
h = t0 + t1;
/* Adjusted round function for rotating state */
#define RNDr(S, W, i, k) \
RND(S[(80 - i) % 8], S[(81 - i) % 8], \
S[(82 - i) % 8], S[(83 - i) % 8], \
S[(84 - i) % 8], S[(85 - i) % 8], \
S[(86 - i) % 8], S[(87 - i) % 8], \
W[i] + k)
/*
* SHA512 block compression function. The 512-bit state is transformed via
* the 512-bit input block to produce a new state.
*/
static void
SHA512_Transform(uint64_t * state, const unsigned char block[128])
{
uint64_t W[80];
uint64_t S[8];
uint64_t t0, t1;
int i;
/* 1. Prepare message schedule W. */
be64dec_vect(W, block, 128);
for (i = 16; i < 80; i++)
W[i] = s1(W[i - 2]) + W[i - 7] + s0(W[i - 15]) + W[i - 16];
/* 2. Initialize working variables. */
memcpy(S, state, 64);
/* 3. Mix. */
RNDr(S, W, 0, 0x428a2f98d728ae22ULL);
RNDr(S, W, 1, 0x7137449123ef65cdULL);
RNDr(S, W, 2, 0xb5c0fbcfec4d3b2fULL);
RNDr(S, W, 3, 0xe9b5dba58189dbbcULL);
RNDr(S, W, 4, 0x3956c25bf348b538ULL);
RNDr(S, W, 5, 0x59f111f1b605d019ULL);
RNDr(S, W, 6, 0x923f82a4af194f9bULL);
RNDr(S, W, 7, 0xab1c5ed5da6d8118ULL);
RNDr(S, W, 8, 0xd807aa98a3030242ULL);
RNDr(S, W, 9, 0x12835b0145706fbeULL);
RNDr(S, W, 10, 0x243185be4ee4b28cULL);
RNDr(S, W, 11, 0x550c7dc3d5ffb4e2ULL);
RNDr(S, W, 12, 0x72be5d74f27b896fULL);
RNDr(S, W, 13, 0x80deb1fe3b1696b1ULL);
RNDr(S, W, 14, 0x9bdc06a725c71235ULL);
RNDr(S, W, 15, 0xc19bf174cf692694ULL);
RNDr(S, W, 16, 0xe49b69c19ef14ad2ULL);
RNDr(S, W, 17, 0xefbe4786384f25e3ULL);
RNDr(S, W, 18, 0x0fc19dc68b8cd5b5ULL);
RNDr(S, W, 19, 0x240ca1cc77ac9c65ULL);
RNDr(S, W, 20, 0x2de92c6f592b0275ULL);
RNDr(S, W, 21, 0x4a7484aa6ea6e483ULL);
RNDr(S, W, 22, 0x5cb0a9dcbd41fbd4ULL);
RNDr(S, W, 23, 0x76f988da831153b5ULL);
RNDr(S, W, 24, 0x983e5152ee66dfabULL);
RNDr(S, W, 25, 0xa831c66d2db43210ULL);
RNDr(S, W, 26, 0xb00327c898fb213fULL);
RNDr(S, W, 27, 0xbf597fc7beef0ee4ULL);
RNDr(S, W, 28, 0xc6e00bf33da88fc2ULL);
RNDr(S, W, 29, 0xd5a79147930aa725ULL);
RNDr(S, W, 30, 0x06ca6351e003826fULL);
RNDr(S, W, 31, 0x142929670a0e6e70ULL);
RNDr(S, W, 32, 0x27b70a8546d22ffcULL);
RNDr(S, W, 33, 0x2e1b21385c26c926ULL);
RNDr(S, W, 34, 0x4d2c6dfc5ac42aedULL);
RNDr(S, W, 35, 0x53380d139d95b3dfULL);
RNDr(S, W, 36, 0x650a73548baf63deULL);
RNDr(S, W, 37, 0x766a0abb3c77b2a8ULL);
RNDr(S, W, 38, 0x81c2c92e47edaee6ULL);
RNDr(S, W, 39, 0x92722c851482353bULL);
RNDr(S, W, 40, 0xa2bfe8a14cf10364ULL);
RNDr(S, W, 41, 0xa81a664bbc423001ULL);
RNDr(S, W, 42, 0xc24b8b70d0f89791ULL);
RNDr(S, W, 43, 0xc76c51a30654be30ULL);
RNDr(S, W, 44, 0xd192e819d6ef5218ULL);
RNDr(S, W, 45, 0xd69906245565a910ULL);
RNDr(S, W, 46, 0xf40e35855771202aULL);
RNDr(S, W, 47, 0x106aa07032bbd1b8ULL);
RNDr(S, W, 48, 0x19a4c116b8d2d0c8ULL);
RNDr(S, W, 49, 0x1e376c085141ab53ULL);
RNDr(S, W, 50, 0x2748774cdf8eeb99ULL);
RNDr(S, W, 51, 0x34b0bcb5e19b48a8ULL);
RNDr(S, W, 52, 0x391c0cb3c5c95a63ULL);
RNDr(S, W, 53, 0x4ed8aa4ae3418acbULL);
RNDr(S, W, 54, 0x5b9cca4f7763e373ULL);
RNDr(S, W, 55, 0x682e6ff3d6b2b8a3ULL);
RNDr(S, W, 56, 0x748f82ee5defb2fcULL);
RNDr(S, W, 57, 0x78a5636f43172f60ULL);
RNDr(S, W, 58, 0x84c87814a1f0ab72ULL);
RNDr(S, W, 59, 0x8cc702081a6439ecULL);
RNDr(S, W, 60, 0x90befffa23631e28ULL);
RNDr(S, W, 61, 0xa4506cebde82bde9ULL);
RNDr(S, W, 62, 0xbef9a3f7b2c67915ULL);
RNDr(S, W, 63, 0xc67178f2e372532bULL);
RNDr(S, W, 64, 0xca273eceea26619cULL);
RNDr(S, W, 65, 0xd186b8c721c0c207ULL);
RNDr(S, W, 66, 0xeada7dd6cde0eb1eULL);
RNDr(S, W, 67, 0xf57d4f7fee6ed178ULL);
RNDr(S, W, 68, 0x06f067aa72176fbaULL);
RNDr(S, W, 69, 0x0a637dc5a2c898a6ULL);
RNDr(S, W, 70, 0x113f9804bef90daeULL);
RNDr(S, W, 71, 0x1b710b35131c471bULL);
RNDr(S, W, 72, 0x28db77f523047d84ULL);
RNDr(S, W, 73, 0x32caab7b40c72493ULL);
RNDr(S, W, 74, 0x3c9ebe0a15c9bebcULL);
RNDr(S, W, 75, 0x431d67c49c100d4cULL);
RNDr(S, W, 76, 0x4cc5d4becb3e42b6ULL);
RNDr(S, W, 77, 0x597f299cfc657e2aULL);
RNDr(S, W, 78, 0x5fcb6fab3ad6faecULL);
RNDr(S, W, 79, 0x6c44198c4a475817ULL);
/* 4. Mix local working variables into global state */
for (i = 0; i < 8; i++)
state[i] += S[i];
}
static unsigned char PAD[128] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/* Add padding and terminating bit-count. */
static void
SHA512_Pad(SHA512_CTX * ctx)
{
unsigned char len[16];
uint64_t r, plen;
/*
* Convert length to a vector of bytes -- we do this now rather
* than later because the length will change after we pad.
*/
be64enc_vect(len, ctx->count, 16);
/* Add 1--128 bytes so that the resulting length is 112 mod 128 */
r = (ctx->count[1] >> 3) & 0x7f;
plen = (r < 112) ? (112 - r) : (240 - r);
SHA512_Update(ctx, PAD, (size_t)plen);
/* Add the terminating bit-count */
SHA512_Update(ctx, len, 16);
}
/* SHA-512 initialization. Begins a SHA-512 operation. */
void
SHA512_Init(SHA512_CTX * ctx)
{
/* Zero bits processed so far */
ctx->count[0] = ctx->count[1] = 0;
/* Magic initialization constants */
ctx->state[0] = 0x6a09e667f3bcc908ULL;
ctx->state[1] = 0xbb67ae8584caa73bULL;
ctx->state[2] = 0x3c6ef372fe94f82bULL;
ctx->state[3] = 0xa54ff53a5f1d36f1ULL;
ctx->state[4] = 0x510e527fade682d1ULL;
ctx->state[5] = 0x9b05688c2b3e6c1fULL;
ctx->state[6] = 0x1f83d9abfb41bd6bULL;
ctx->state[7] = 0x5be0cd19137e2179ULL;
}
/* Add bytes into the hash */
void
SHA512_Update(SHA512_CTX * ctx, const void *in, size_t len)
{
uint64_t bitlen[2];
uint64_t r;
const unsigned char *src = in;
/* Number of bytes left in the buffer from previous updates */
r = (ctx->count[1] >> 3) & 0x7f;
/* Convert the length into a number of bits */
bitlen[1] = ((uint64_t)len) << 3;
bitlen[0] = ((uint64_t)len) >> 61;
/* Update number of bits */
if ((ctx->count[1] += bitlen[1]) < bitlen[1])
ctx->count[0]++;
ctx->count[0] += bitlen[0];
/* Handle the case where we don't need to perform any transforms */
if (len < 128 - r) {
memcpy(&ctx->buf[r], src, len);
return;
}
/* Finish the current block */
memcpy(&ctx->buf[r], src, 128 - r);
SHA512_Transform(ctx->state, ctx->buf);
src += 128 - r;
len -= 128 - r;
/* Perform complete blocks */
while (len >= 128) {
SHA512_Transform(ctx->state, src);
src += 128;
len -= 128;
}
/* Copy left over data into buffer */
memcpy(ctx->buf, src, len);
}
/*
* SHA-512 finalization. Pads the input data, exports the hash value,
* and clears the context state.
*/
void
SHA512_Final(unsigned char digest[64], SHA512_CTX * ctx)
{
/* Add padding */
SHA512_Pad(ctx);
/* Write the hash */
be64enc_vect(digest, ctx->state, 64);
/* Clear the context state */
memset((void *)ctx, 0, sizeof(*ctx));
}

View File

@@ -130,10 +130,8 @@
* only advantage over quicksort is that it requires little additional memory. * only advantage over quicksort is that it requires little additional memory.
*/ */
int int
heapsort(vbase, nmemb, size, compar) heapsort(void *vbase, size_t nmemb, size_t size,
void *vbase; int (*compar)(const void *, const void *))
size_t nmemb, size;
int (*compar)(const void *, const void *);
{ {
size_t cnt, i, j, l; size_t cnt, i, j, l;
char tmp, *tmp1, *tmp2; char tmp, *tmp1, *tmp2;

View File

@@ -55,11 +55,7 @@ static int inet_net_pton_ipv4(const char *src, u_char *dst, size_t size);
* Paul Vixie (ISC), June 1996 * Paul Vixie (ISC), June 1996
*/ */
int int
inet_net_pton(af, src, dst, size) inet_net_pton(int af, const char *src, void *dst, size_t size)
int af;
const char *src;
void *dst;
size_t size;
{ {
switch (af) { switch (af) {
case AF_INET: case AF_INET:
@@ -87,10 +83,7 @@ inet_net_pton(af, src, dst, size)
* Paul Vixie (ISC), June 1996 * Paul Vixie (ISC), June 1996
*/ */
static int static int
inet_net_pton_ipv4(src, dst, size) inet_net_pton_ipv4(const char *src, u_char *dst, size_t size)
const char *src;
u_char *dst;
size_t size;
{ {
static const char static const char
xdigits[] = "0123456789abcdef", xdigits[] = "0123456789abcdef",

12
src/libbsd-ctor.pc.in Normal file
View File

@@ -0,0 +1,12 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: libbsd-ctor
Description: Automatic constructor functions for libbsd
Version: @VERSION@
URL: http://libbsd.freedesktop.org/
Cflags: -I${includedir}
Libs: -L${libdir} -Wl,-z,nodlopen -Wl,-u,libbsd_init_func -lbsd-ctor
Requires: libbsd

View File

@@ -105,3 +105,34 @@ LIBBSD_0.5 {
wcslcat; wcslcat;
wcslcpy; wcslcpy;
} LIBBSD_0.4; } LIBBSD_0.4;
LIBBSD_0.6 {
/* Exported to cope with the constructor+dlopen+threads mess. */
setproctitle_init;
} LIBBSD_0.5;
LIBBSD_0.7 {
getbsize;
funopen;
reallocarray;
sl_init;
sl_add;
sl_free;
sl_find;
_time32_to_time;
_time_to_time32;
_time64_to_time;
_time_to_time64;
_time_to_long;
_long_to_time;
_time_to_int;
_int_to_time;
} LIBBSD_0.6;
LIBBSD_0.8 {
explicit_bzero;
} LIBBSD_0.7;

View File

@@ -134,6 +134,12 @@
#define ELF_TARG_DATA ELFDATA2LSB #define ELF_TARG_DATA ELFDATA2LSB
#endif #endif
#elif defined(__nios2__)
#define ELF_TARG_MACH EM_ALTERA_NIOS2
#define ELF_TARG_CLASS ELFCLASS32
#define ELF_TARG_DATA ELFDATA2LSB
#elif defined(__powerpc__) #elif defined(__powerpc__)
#define ELF_TARG_MACH EM_PPC #define ELF_TARG_MACH EM_PPC
@@ -179,6 +185,12 @@
#endif #endif
#define ELF_TARG_DATA ELFDATA2MSB #define ELF_TARG_DATA ELFDATA2MSB
#elif defined(__or1k__)
#define ELF_TARG_MACH EM_OPENRISC
#define ELF_TARG_CLASS ELFCLASS32
#define ELF_TARG_DATA ELFDATA2MSB
#else #else
#error Unknown ELF machine type #error Unknown ELF machine type

33
src/local-link.h Normal file
View File

@@ -0,0 +1,33 @@
/*
* Copyright © 2015 Guillem Jover <guillem@hadrons.org>
*
* 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 ``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 LIBBSD_LOCAL_LINK_H
#define LIBBSD_LOCAL_LINK_H
#define libbsd_link_warning(symbol, msg) \
static const char libbsd_emit_link_warning_##symbol[] \
__attribute__((used,section(".gnu.warning." #symbol))) = msg;
#endif

View File

@@ -95,11 +95,8 @@ static void insertionsort(u_char *, size_t, size_t,
* Arguments are as for qsort. * Arguments are as for qsort.
*/ */
int int
mergesort(base, nmemb, size, cmp) mergesort(void *base, size_t nmemb, size_t size,
void *base; int (*cmp)(const void *, const void *))
size_t nmemb;
size_t size;
int (*cmp)(const void *, const void *);
{ {
size_t i; size_t i;
int sense; int sense;
@@ -258,11 +255,9 @@ COPY: b = t;
* when THRESHOLD/2 pairs compare with same sense. (Only used when NATURAL * when THRESHOLD/2 pairs compare with same sense. (Only used when NATURAL
* is defined. Otherwise simple pairwise merging is used.) * is defined. Otherwise simple pairwise merging is used.)
*/ */
void static void
setup(list1, list2, n, size, cmp) setup(u_char *list1, u_char *list2, size_t n, size_t size,
size_t n, size; int (*cmp)(const void *, const void *))
int (*cmp)(const void *, const void *);
u_char *list1, *list2;
{ {
int i, length, size2, tmp, sense; int i, length, size2, tmp, sense;
u_char *f1, *f2, *s, *l2, *last, *p2; u_char *f1, *f2, *s, *l2, *last, *p2;
@@ -333,10 +328,8 @@ setup(list1, list2, n, size, cmp)
* last 4 elements. * last 4 elements.
*/ */
static void static void
insertionsort(a, n, size, cmp) insertionsort(u_char *a, size_t n, size_t size,
u_char *a; int (*cmp)(const void *, const void *))
size_t n, size;
int (*cmp)(const void *, const void *);
{ {
u_char *ai, *s, *t, *u, tmp; u_char *ai, *s, *t, *u, tmp;
int i; int i;

View File

@@ -70,9 +70,7 @@ static int __elf_fdnlist(int, struct nlist *);
int __fdnlist(int, struct nlist *); int __fdnlist(int, struct nlist *);
int int
nlist(name, list) nlist(const char *name, struct nlist *list)
const char *name;
struct nlist *list;
{ {
int fd, n; int fd, n;
@@ -96,9 +94,7 @@ static struct nlist_handlers {
}; };
int int
__fdnlist(fd, list) __fdnlist(int fd, struct nlist *list)
int fd;
struct nlist *list;
{ {
size_t i; size_t i;
int n = -1; int n = -1;
@@ -115,9 +111,7 @@ __fdnlist(fd, list)
#ifdef _NLIST_DO_AOUT #ifdef _NLIST_DO_AOUT
static int static int
__aout_fdnlist(fd, list) __aout_fdnlist(int fd, struct nlist *list)
int fd;
struct nlist *list;
{ {
struct nlist *p, *symtab; struct nlist *p, *symtab;
caddr_t strtab, a_out_mmap; caddr_t strtab, a_out_mmap;
@@ -220,8 +214,7 @@ static void elf_sym_to_nlist(struct nlist *, Elf_Sym *, Elf_Shdr *, int);
* as such its use should be restricted. * as such its use should be restricted.
*/ */
static int static int
__elf_is_okay__(ehdr) __elf_is_okay__(Elf_Ehdr *ehdr)
Elf_Ehdr *ehdr;
{ {
int retval = 0; int retval = 0;
/* /*
@@ -244,9 +237,7 @@ __elf_is_okay__(ehdr)
} }
static int static int
__elf_fdnlist(fd, list) __elf_fdnlist(int fd, struct nlist *list)
int fd;
struct nlist *list;
{ {
struct nlist *p; struct nlist *p;
Elf_Off symoff = 0, symstroff = 0; Elf_Off symoff = 0, symstroff = 0;
@@ -386,11 +377,7 @@ __elf_fdnlist(fd, list)
* n_value and n_type members. * n_value and n_type members.
*/ */
static void static void
elf_sym_to_nlist(nl, s, shdr, shnum) elf_sym_to_nlist(struct nlist *nl, Elf_Sym *s, Elf_Shdr *shdr, int shnum)
struct nlist *nl;
Elf_Sym *s;
Elf_Shdr *shdr;
int shnum;
{ {
nl->n_value = s->st_value; nl->n_value = s->st_value;

View File

@@ -118,7 +118,8 @@ sradixsort(const u_char **a, int n, const u_char *tab, u_int endch)
if (n < THRESHOLD) if (n < THRESHOLD)
simplesort(a, n, 0, tr, endch); simplesort(a, n, 0, tr, endch);
else { else {
if ((ta = malloc(n * sizeof(a))) == NULL) ta = reallocarray(NULL, n, sizeof(a));
if (ta == NULL)
return (-1); return (-1);
r_sort_b(a, ta, n, 0, tr, endch); r_sort_b(a, ta, n, 0, tr, endch);
free(ta); free(ta);

38
src/reallocarray.c Normal file
View File

@@ -0,0 +1,38 @@
/* $OpenBSD: reallocarray.c,v 1.2 2014/12/08 03:45:00 bcook Exp $ */
/*
* Copyright (c) 2008 Otto Moerbeek <otto@drijf.net>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#include <errno.h>
#include <stdint.h>
#include <stdlib.h>
/*
* This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
* if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
*/
#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
void *
reallocarray(void *optr, size_t nmemb, size_t size)
{
if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
nmemb > 0 && SIZE_MAX / nmemb < size) {
errno = ENOMEM;
return NULL;
}
return realloc(optr, size * nmemb);
}

View File

@@ -154,7 +154,7 @@ common: if (set->cmd2 & CMD2_CLR) {
if (set >= endset) { \ if (set >= endset) { \
BITCMD *newset; \ BITCMD *newset; \
setlen += SET_LEN_INCR; \ setlen += SET_LEN_INCR; \
newset = realloc(saveset, sizeof(BITCMD) * setlen); \ newset = reallocarray(saveset, setlen, sizeof(BITCMD)); \
if (newset == NULL) \ if (newset == NULL) \
goto out; \ goto out; \
set = newset + (set - saveset); \ set = newset + (set - saveset); \
@@ -197,7 +197,8 @@ setmode(const char *p)
setlen = SET_LEN + 2; setlen = SET_LEN + 2;
if ((set = malloc((u_int)(sizeof(BITCMD) * setlen))) == NULL) set = reallocarray(NULL, setlen, sizeof(BITCMD));
if (set == NULL)
return (NULL); return (NULL);
saveset = set; saveset = set;
endset = set + (setlen - 2); endset = set + (setlen - 2);

View File

@@ -1,6 +1,6 @@
/* /*
* Copyright © 2010 William Ahern * Copyright © 2010 William Ahern
* Copyright © 2012 Guillem Jover <guillem@hadrons.org> * Copyright © 2012-2013 Guillem Jover <guillem@hadrons.org>
* *
* Permission is hereby granted, free of charge, to any person obtaining a * Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the * copy of this software and associated documentation files (the
@@ -28,6 +28,7 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <err.h>
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <string.h>
@@ -41,6 +42,7 @@ static struct {
/* Pointer to original nul character within base. */ /* Pointer to original nul character within base. */
char *nul; char *nul;
bool warned;
bool reset; bool reset;
int error; int error;
} SPT; } SPT;
@@ -76,36 +78,60 @@ spt_clearenv(void)
} }
static int static int
spt_copyenv(char *oldenv[]) spt_copyenv(int envc, char *envp[])
{ {
char **envcopy;
char *eq; char *eq;
int envsize;
int i, error; int i, error;
if (environ != oldenv) if (environ != envp)
return 0; return 0;
/* Make a copy of the old environ array of pointers, in case
* clearenv() or setenv() is implemented to free the internal
* environ array, because we will need to access the old environ
* contents to make the new copy. */
envsize = (envc + 1) * sizeof(char *);
envcopy = malloc(envsize);
if (envcopy == NULL)
return errno;
memcpy(envcopy, envp, envsize);
error = spt_clearenv(); error = spt_clearenv();
if (error) { if (error) {
environ = oldenv; environ = envp;
free(envcopy);
return error; return error;
} }
for (i = 0; oldenv[i]; i++) { for (i = 0; envcopy[i]; i++) {
eq = strchr(oldenv[i], '='); eq = strchr(envcopy[i], '=');
if (eq == NULL) if (eq == NULL)
continue; continue;
*eq = '\0'; *eq = '\0';
if (setenv(oldenv[i], eq + 1, 1) < 0) if (setenv(envcopy[i], eq + 1, 1) < 0)
error = errno; error = errno;
*eq = '='; *eq = '=';
if (error) { if (error) {
environ = oldenv; #ifdef HAVE_CLEARENV
/* Because the old environ might not be available
* anymore we will make do with the shallow copy. */
environ = envcopy;
#else
environ = envp;
free(envcopy);
#endif
return error; return error;
} }
} }
/* Dispose of the shallow copy, now that we've finished transfering
* the old environment. */
free(envcopy);
return 0; return 0;
} }
@@ -129,11 +155,15 @@ spt_copyargs(int argc, char *argv[])
return 0; return 0;
} }
static void __attribute__((constructor)) void
spt_init(int argc, char *argv[], char *envp[]) setproctitle_init(int argc, char *argv[], char *envp[])
{ {
char *base, *end, *nul, *tmp; char *base, *end, *nul, *tmp;
int i, error; int i, envc, error;
/* Try to make sure we got called with main() arguments. */
if (argc < 0)
return;
base = argv[0]; base = argv[0];
if (base == NULL) if (base == NULL)
@@ -155,6 +185,7 @@ spt_init(int argc, char *argv[], char *envp[])
end = envp[i] + strlen(envp[i]) + 1; end = envp[i] + strlen(envp[i]) + 1;
} }
envc = i;
SPT.arg0 = strdup(argv[0]); SPT.arg0 = strdup(argv[0]);
if (SPT.arg0 == NULL) { if (SPT.arg0 == NULL) {
@@ -169,7 +200,7 @@ spt_init(int argc, char *argv[], char *envp[])
} }
setprogname(tmp); setprogname(tmp);
error = spt_copyenv(envp); error = spt_copyenv(envc, envp);
if (error) { if (error) {
SPT.error = error; SPT.error = error;
return; return;
@@ -199,8 +230,14 @@ setproctitle_impl(const char *fmt, ...)
char *nul; char *nul;
int len; int len;
if (SPT.base == NULL) if (SPT.base == NULL) {
if (!SPT.warned) {
warnx("setproctitle not initialized, please either call "
"setproctitle_init() or link against libbsd-ctor.");
SPT.warned = true;
}
return; return;
}
if (fmt) { if (fmt) {
if (fmt[0] == '-') { if (fmt[0] == '-') {
@@ -245,11 +282,14 @@ setproctitle_impl(const char *fmt, ...)
} }
__asm__(".symver setproctitle_impl,setproctitle@@LIBBSD_0.5"); __asm__(".symver setproctitle_impl,setproctitle@@LIBBSD_0.5");
#ifdef HAVE_TYPEOF
/* The original function introduced in 0.2 was a stub, it only got implemented /* The original function introduced in 0.2 was a stub, it only got implemented
* in 0.5, make the implementation available in the old version as an alias * in 0.5, make the implementation available in the old version as an alias
* for code linking against that version, and change the default to use the * for code linking against that version, and change the default to use the
* new version, so that new code depends on the implemented version. */ * new version, so that new code depends on the implemented version. */
#ifdef HAVE_TYPEOF
extern typeof(setproctitle_impl) setproctitle_stub __attribute__((alias("setproctitle_impl"))); extern typeof(setproctitle_impl) setproctitle_stub __attribute__((alias("setproctitle_impl")));
__asm__(".symver setproctitle_stub,setproctitle@LIBBSD_0.2"); #else
void setproctitle_stub(const char *fmt, ...)
__attribute__((alias("setproctitle_impl")));
#endif #endif
__asm__(".symver setproctitle_stub,setproctitle@LIBBSD_0.2");

52
src/setproctitle_ctor.c Normal file
View File

@@ -0,0 +1,52 @@
/*
* Copyright © 2013 Guillem Jover <guillem@hadrons.org>
*
* 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 ``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 <unistd.h>
/*
* The automatic initialization cannot be part of the main shared library,
* because there is no thread-safe way to change the environ global
* variable. This is not a problem if the initializaion happens just at
* program load time, but becomes one if the shared library is directly or
* indirectly dlopen()ed during the execution of the program, which could
* have either kept references to the old environ or could change it in
* some other thread. This has been observed for example on systems using
* Samba NSS modules.
*
* To avoid any other possible fallout, the constructor is split into a
* new static library that needs to be linked explicitly into programs
* using setproctitle(). As an additional safety measure the pkg-config
* linker flags will mark the program as not allowing to be dlopen()ed
* so that we make sure to avoid the problem described above.
*/
/*
* Force setproctitle_init() function into the .init_array section instead of
* expecting either the compiler to place constructors there or the linker to
* move them from .ctors to .init_array.
*/
void (*libbsd_init_func)(int argc, char *argv[], char *envp[])
__attribute__((section(".init_array"))) = setproctitle_init;

155
src/stringlist.c Normal file
View File

@@ -0,0 +1,155 @@
/* $NetBSD: stringlist.c,v 1.12 2007/05/09 17:10:29 christos Exp $ */
/*-
* Copyright (c) 1994, 1999 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Christos Zoulas.
*
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``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 FOUNDATION OR CONTRIBUTORS
* 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 <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
__RCSID("$NetBSD: stringlist.c,v 1.12 2007/05/09 17:10:29 christos Exp $");
#endif /* LIBC_SCCS and not lint */
#include <assert.h>
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stringlist.h>
#define _DIAGASSERT(t)
#ifdef __weak_alias
__weak_alias(sl_add,_sl_add)
__weak_alias(sl_find,_sl_find)
__weak_alias(sl_free,_sl_free)
__weak_alias(sl_init,_sl_init)
__weak_alias(sl_delete,_sl_delete)
#endif
#define _SL_CHUNKSIZE 20
/*
* sl_init(): Initialize a string list
*/
StringList *
sl_init(void)
{
StringList *sl;
sl = malloc(sizeof(StringList));
if (sl == NULL)
return NULL;
sl->sl_cur = 0;
sl->sl_max = _SL_CHUNKSIZE;
sl->sl_str = reallocarray(NULL, sl->sl_max, sizeof(char *));
if (sl->sl_str == NULL) {
free(sl);
sl = NULL;
}
return sl;
}
/*
* sl_add(): Add an item to the string list
*/
int
sl_add(StringList *sl, char *name)
{
_DIAGASSERT(sl != NULL);
if (sl->sl_cur == sl->sl_max - 1) {
char **new;
new = reallocarray(sl->sl_str,
(sl->sl_max + _SL_CHUNKSIZE), sizeof(char *));
if (new == NULL)
return -1;
sl->sl_max += _SL_CHUNKSIZE;
sl->sl_str = new;
}
sl->sl_str[sl->sl_cur++] = name;
return 0;
}
/*
* sl_free(): Free a stringlist
*/
void
sl_free(StringList *sl, int all)
{
size_t i;
if (sl == NULL)
return;
if (sl->sl_str) {
if (all)
for (i = 0; i < sl->sl_cur; i++)
free(sl->sl_str[i]);
free(sl->sl_str);
}
free(sl);
}
/*
* sl_find(): Find a name in the string list
*/
char *
sl_find(StringList *sl, const char *name)
{
size_t i;
_DIAGASSERT(sl != NULL);
for (i = 0; i < sl->sl_cur; i++)
if (strcmp(sl->sl_str[i], name) == 0)
return sl->sl_str[i];
return NULL;
}
int
sl_delete(StringList *sl, const char *name, int all)
{
size_t i, j;
for (i = 0; i < sl->sl_cur; i++)
if (strcmp(sl->sl_str[i], name) == 0) {
if (all)
free(sl->sl_str[i]);
for (j = i + 1; j < sl->sl_cur; j++)
sl->sl_str[j - 1] = sl->sl_str[j];
sl->sl_str[--sl->sl_cur] = NULL;
return 0;
}
return -1;
}

View File

@@ -37,9 +37,7 @@ static char sccsid[] = "@(#)strmode.c 8.3 (Berkeley) 8/15/94";
#include <string.h> #include <string.h>
void void
strmode(mode, p) strmode(mode_t mode, char *p)
mode_t mode;
char *p;
{ {
/* print type */ /* print type */
switch (mode & S_IFMT) { switch (mode & S_IFMT) {

119
src/timeconv.c Normal file
View File

@@ -0,0 +1,119 @@
/*-
* Copyright (c) 2001 FreeBSD Inc.
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
*
* These routines are for converting time_t to fixed-bit representations
* for use in protocols or storage. When converting time to a larger
* representation of time_t these routines are expected to assume temporal
* locality and use the 50-year rule to properly set the msb bits. XXX
*
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <timeconv.h>
/*
* Convert a 32 bit representation of time_t into time_t. XXX needs to
* implement the 50-year rule to handle post-2038 conversions.
*/
time_t
_time32_to_time(int32_t t32)
{
return((time_t)t32);
}
/*
* Convert time_t to a 32 bit representation. If time_t is 64 bits we can
* simply chop it down. The resulting 32 bit representation can be
* converted back to a temporally local 64 bit time_t using time32_to_time.
*/
int32_t
_time_to_time32(time_t t)
{
return((int32_t)t);
}
/*
* Convert a 64 bit representation of time_t into time_t. If time_t is
* represented as 32 bits we can simply chop it and not support times
* past 2038.
*/
time_t
_time64_to_time(int64_t t64)
{
return((time_t)t64);
}
/*
* Convert time_t to a 64 bit representation. If time_t is represented
* as 32 bits we simply sign-extend and do not support times past 2038.
*/
int64_t
_time_to_time64(time_t t)
{
return((int64_t)t);
}
/*
* Convert to/from 'long'. Depending on the sizeof(long) this may or
* may not require using the 50-year rule.
*/
long
_time_to_long(time_t t)
{
if (sizeof(long) == sizeof(int64_t))
return(_time_to_time64(t));
return((long)t);
}
time_t
_long_to_time(long tlong)
{
if (sizeof(long) == sizeof(int32_t))
return(_time32_to_time(tlong));
return((time_t)tlong);
}
/*
* Convert to/from 'int'. Depending on the sizeof(int) this may or
* may not require using the 50-year rule.
*/
int
_time_to_int(time_t t)
{
if (sizeof(int) == sizeof(int64_t))
return(_time_to_time64(t));
return((int)t);
}
time_t
_int_to_time(int tint)
{
if (sizeof(int) == sizeof(int32_t))
return(_time32_to_time(tint));
return((time_t)tint);
}

10
test/.gitignore vendored
View File

@@ -1,6 +1,14 @@
arc4random
bzero
closefrom
endian endian
fgetln fgetln
headers funopen
fparseln
fpurge
headers-gen.c
humanize humanize
overlay overlay
proctitle-init
proctitle proctitle
strmode

View File

@@ -1,23 +1,69 @@
## Process this file with automake to produce Makefile.in ## Process this file with automake to produce Makefile.in
AM_CPPFLAGS = \ HEADERS_CPPFLAGS = \
-I$(top_builddir) \ -I$(top_builddir) \
-isystem $(top_srcdir)/include/bsd/ \
-include $(top_builddir)/config.h \ -include $(top_builddir)/config.h \
-DLIBBSD_OVERLAY -DLIBBSD_DISABLE_DEPRECATED \ -DLIBBSD_DISABLE_DEPRECATED \
-D__REENTRANT -D__REENTRANT
AM_CPPFLAGS = \
-isystem $(top_srcdir)/include/bsd/ \
$(HEADERS_CPPFLAGS) \
-DLIBBSD_OVERLAY
AM_TESTS_ENVIRONMENT = \
export CC="$(CC)"; \
export CPPFLAGS="$(HEADERS_CPPFLAGS)"; \
export top_srcdir="$(top_srcdir)"; \
$(nil)
LDADD = $(top_builddir)/src/libbsd.la
EXTRA_DIST = \
headers-overlay.sh \
headers-system.sh \
$(nil)
check_SCRIPTS = \
headers-overlay.sh \
headers-system.sh \
$(nil)
check_PROGRAMS = \ check_PROGRAMS = \
headers \
overlay \ overlay \
bzero \
closefrom \
endian \ endian \
humanize \ humanize \
fgetln \ fgetln \
proctitle \ funopen \
fparseln \
fpurge \
proctitle-init \
strmode \
$(nil) $(nil)
humanize_LDFLAGS = $(top_builddir)/src/libbsd.la if HAVE_LIBTESTU01
fgetln_LDFLAGS = $(top_builddir)/src/libbsd.la arc4random_LDADD = $(LDADD) $(TESTU01_LIBS)
proctitle_LDFLAGS = $(top_builddir)/src/libbsd.la
TESTS = $(check_PROGRAMS) check_PROGRAMS += arc4random
endif
if BUILD_LIBBSD_CTOR
proctitle_LDFLAGS = \
-Wl,-u,libbsd_init_func \
$(top_builddir)/src/libbsd-ctor.a \
$(top_builddir)/src/libbsd.la \
$(nil)
check_PROGRAMS += proctitle
endif
fgetln_SOURCES = test-stream.c test-stream.h fgetln.c
fgetln_CFLAGS = -Wno-deprecated-declarations
fparseln_SOURCES = test-stream.c test-stream.h fparseln.c
proctitle_init_SOURCES = proctitle.c
proctitle_init_CPPFLAGS = $(AM_CPPFLAGS) -DTEST_USE_SETPROCTITLE_INIT=1
TESTS = $(check_SCRIPTS) $(check_PROGRAMS)

107
test/arc4random.c Normal file
View File

@@ -0,0 +1,107 @@
/*
* Copyright © 2015 Guillem Jover <guillem@hadrons.org>
*
* 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 ``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 <assert.h>
#include <stdlib.h>
#include <testu01/gdef.h>
#include <testu01/unif01.h>
#include <testu01/swrite.h>
#include <testu01/bbattery.h>
#define TEST_OK 0
#define TEST_SKIP 77
#define TEST_DIE 99
#define test_print(msg, ...) \
printf("TEST: " msg "\n", __VA_ARGS__)
#define test_res(idx, name, pval, action) \
test_print("[%4d] (%s) pVal[%d] = %f -> %s", \
idx, name[idx], i, pval[idx], action)
static int test_failed = 0;
static void
test_battery_result(void)
{
char **testNames = bbattery_TestNames;
double *pVal = bbattery_pVal;
double pSuspect = 0.001;
test_print("bbattery_NTests = %d", bbattery_NTests);
for (int i = 0; i < bbattery_NTests; i++) {
/* That test was not done: pVal = -1. */
if (pVal[i] < 0.0) {
test_res(i, testNames, pVal, "SKIP");
continue;
}
/* That test passed or failed. */
if ((pVal[i] >= pSuspect) &&
(pVal[i] <= 1.0 - pSuspect)) {
test_res(i, testNames, pVal, "PASS");
} else {
test_res(i, testNames, pVal, "FAIL");
test_failed++;
}
}
}
int
main(int argc, char **argv)
{
unif01_Gen *gen;
int rc;
gen = unif01_CreateExternGenBits("arc4random", arc4random);
/* XXX: The following battery does not set pVal, so we cannot check
* the results. */
bbattery_FIPS_140_2(gen);
/* XXX: The following battery fails one test. */
bbattery_pseudoDIEHARD(gen);
test_battery_result();
bbattery_Rabbit(gen, 33554432);
test_battery_result();
bbattery_SmallCrush(gen);
test_battery_result();
unif01_DeleteExternGenBits(gen);
if (test_failed) {
test_print("failed tests = %d", test_failed);
/* XXX: We should probably FAIL the test, but we currently
* have one test always failing. */
rc = TEST_SKIP;
} else {
rc = TEST_OK;
}
return rc;
}

47
test/bzero.c Normal file
View File

@@ -0,0 +1,47 @@
/*
* Copyright © 2015 Guillem Jover <guillem@hadrons.org>
*
* 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 ``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 <assert.h>
#include <string.h>
int
main()
{
unsigned char array[40];
size_t i;
memset(array, 0x3e, sizeof(array));
explicit_bzero(array, 0);
for (i = 0; i < sizeof(array); i++)
assert(array[i] == 0x3e);
explicit_bzero(array, sizeof(array));
for (i = 0; i < sizeof(array); i++)
assert(array[i] == 0);
return 0;
}

53
test/closefrom.c Normal file
View File

@@ -0,0 +1,53 @@
/*
* Copyright © 2015 Guillem Jover <guillem@hadrons.org>
*
* 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 ``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 <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
int
main()
{
int i;
int fd;
fd = open("/dev/null", O_RDONLY);
for (i = 4; i < 1024; i *= 2)
assert(dup2(fd, i) == i);
if (fd < 4)
close(fd);
closefrom(4);
for (i = 4; i < 1024; i++)
assert(fcntl(i, F_GETFL) == -1 && errno == EBADF);
assert(fcntl(fd, F_GETFL) == -1 && errno == EBADF);
return 0;
}

View File

@@ -24,15 +24,15 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <sys/wait.h>
#include <assert.h> #include <assert.h>
#include <unistd.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <locale.h> #include <locale.h>
#include <wchar.h> #include <wchar.h>
#include "test-stream.h"
#define skip(msg) \ #define skip(msg) \
do { \ do { \
printf("skip: %s\n", (msg)); \ printf("skip: %s\n", (msg)); \
@@ -67,58 +67,6 @@ struct file {
int got_len; int got_len;
}; };
static FILE *
pipe_feed(const char *fmt, const void **buf, int buf_nmemb)
{
FILE *fp;
int rc;
int pipefd[2];
pid_t pid;
rc = pipe(pipefd);
assert(rc >= 0);
pid = fork();
assert(pid >= 0);
if (pid == 0) {
int line;
/* Child writes data to pipe. */
rc = close(pipefd[0]);
assert(rc >= 0);
fp = fdopen(pipefd[1], "w");
assert(fp);
for (line = 0; line < buf_nmemb; line++) {
rc = fprintf(fp, fmt, buf[line]);
assert(rc >= 0);
}
rc = fclose(fp);
assert(rc >= 0);
_exit(0);
} else {
/* Parent gets a FILE and reads from it. */
rc = close(pipefd[1]);
assert(rc >= 0);
fp = fdopen(pipefd[0], "r");
assert(fp);
return fp;
}
}
static void
pipe_close(FILE *fp)
{
fclose(fp);
wait(NULL);
}
static void static void
test_fgetln_single(void) test_fgetln_single(void)
{ {
@@ -149,7 +97,7 @@ test_fgetln_multi(void)
str = strdup("A\n"); str = strdup("A\n");
str[0] += i; str[0] += i;
files[i].lines = malloc(sizeof(char *) * LINE_COUNT); files[i].lines = reallocarray(NULL, LINE_COUNT, sizeof(char *));
files[i].lines[0] = str; files[i].lines[0] = str;
files[i].lines[1] = str; files[i].lines[1] = str;
files[i].fp = pipe_feed("%s", files[i].lines, LINE_COUNT); files[i].fp = pipe_feed("%s", files[i].lines, LINE_COUNT);
@@ -211,7 +159,7 @@ test_fgetwln_multi(void)
wstr = wcsdup(L"A\n"); wstr = wcsdup(L"A\n");
wstr[0] += i; wstr[0] += i;
files[i].lines = malloc(sizeof(char *) * LINE_COUNT); files[i].lines = reallocarray(NULL, LINE_COUNT, sizeof(char *));
files[i].lines[0] = wstr; files[i].lines[0] = wstr;
files[i].lines[1] = wstr; files[i].lines[1] = wstr;
files[i].fp = pipe_feed("%ls", files[i].lines, LINE_COUNT); files[i].fp = pipe_feed("%ls", files[i].lines, LINE_COUNT);

92
test/fparseln.c Normal file
View File

@@ -0,0 +1,92 @@
/*
* Copyright © 2015 Guillem Jover <guillem@hadrons.org>
*
* 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 ``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 <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "test-stream.h"
#define TEST_LINES 9
static const char *data_test[] = {
"# This is a test\n",
"line 1\n",
"line 2 \\\n",
"line 3 # Comment\n",
"line 4 \\# Not comment \\\\\\\\\n",
"\n",
"# And a comment \\\n",
"line 5 \\\\\\\n",
"line 6 w/ escape sequences \\b, \\t, \\\\t",
};
#define EXPECT_LINES 5
static size_t lineno_expect[] = { 2, 4, 5, 6, 9 };
static const char *data_parse[] = {
"line 1",
"line 2 line 3 ",
"line 4 \\# Not comment \\\\\\\\",
"",
"line 5 \\\\line 6 w/ escape sequences \\b, \\t, \\\\t",
};
static const char *data_escape[] = {
"line 1",
"line 2 line 3 ",
"line 4 # Not comment \\\\",
"",
"line 5 \\line 6 w/ escape sequences b, t, \\t",
};
static void
test_fparseln(const char **data_expect, int flags)
{
FILE *fp;
size_t i, len, lineno = 0;
fp = pipe_feed("%s", (const void **)data_test, TEST_LINES);
for (i = 0; i < EXPECT_LINES; i++) {
char *str = fparseln(fp, &len, &lineno, NULL, flags);
assert(str);
assert(lineno == lineno_expect[i]);
assert(strcmp(str, data_expect[i]) == 0);
free(str);
}
assert(fparseln(fp, &len, NULL, NULL, 0) == NULL);
pipe_close(fp);
}
int
main(int argc, char **argv)
{
test_fparseln(data_parse, 0);
test_fparseln(data_escape, FPARSELN_UNESCALL);
return 0;
}

48
test/fpurge.c Normal file
View File

@@ -0,0 +1,48 @@
/*
* Copyright © 2011 Guillem Jover <guillem@hadrons.org>
*
* 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 ``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 <stdio.h>
int
main()
{
static FILE fp_bad;
FILE *fp;
if (fpurge(NULL) == 0)
return 1;
if (fpurge(&fp_bad) == 0)
return 1;
fp = fopen("/dev/zero", "r");
if (fpurge(fp) < 0)
return 1;
fclose(fp);
return 0;
}

178
test/funopen.c Normal file
View File

@@ -0,0 +1,178 @@
/*
* Copyright © 2013 Guillem Jover <guillem@hadrons.org>
*
* 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 ``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 <assert.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#define ARRAY_SIZE 100
#define TEST_SIZE 50
struct test_cookie {
char array[ARRAY_SIZE];
int index;
};
int
test_readfn(void *cookie, char *buf, int size)
{
struct test_cookie *tc = cookie;
int left_size = sizeof(tc->array) - tc->index;
if (left_size < 0)
size = 0;
else if (left_size < size)
size = left_size;
if (size > 0) {
memcpy(buf, tc->array + tc->index, size);
tc->index += size;
}
return size;
}
int
test_writefn(void *cookie, const char *buf, int size)
{
struct test_cookie *tc = cookie;
int left_size = sizeof(tc->array) - tc->index;
if (left_size < 0)
size = 0;
else if (left_size < size)
size = left_size;
if (size > 0) {
memcpy(tc->array + tc->index, buf, size);
tc->index += size;
}
return size;
}
off_t
test_seekfn(void *cookie, off_t offset, int whence)
{
struct test_cookie *tc = cookie;
switch (whence) {
case SEEK_SET:
tc->index = offset;
break;
case SEEK_CUR:
tc->index += offset;
break;
case SEEK_END:
tc->index = sizeof(tc->array) + offset;
break;
}
return tc->index;
}
int
test_closefn(void *cookie)
{
struct test_cookie *tc = cookie;
memset(tc->array, 0x7f, sizeof(tc->array));
return 0;
}
int
main(int argc, char **argv)
{
struct test_cookie tc;
char data[ARRAY_SIZE];
FILE *fp;
size_t i;
/* Test invalid hooks. */
fp = funopen(&tc, NULL, NULL, NULL, NULL);
assert(fp == NULL);
assert(errno == EINVAL);
/* Test read-only file. */
tc.index = 0;
for (i = 0; i < sizeof(tc.array); i++)
tc.array[i] = i;
fp = fropen(&tc, test_readfn);
assert(fp);
assert(fread(data, 1, TEST_SIZE, fp) == TEST_SIZE);
assert(memcmp(tc.array, data, TEST_SIZE) == 0);
assert(fwrite(data, 1, TEST_SIZE, fp) == 0);
assert(fclose(fp) == 0);
/* Test write-only file. */
memset(&tc, 0, sizeof(tc));
fp = fwopen(&tc, test_writefn);
assert(fp);
setvbuf(fp, NULL, _IONBF, 0);
assert(fwrite(data, 1, TEST_SIZE, fp) == TEST_SIZE);
assert(memcmp(tc.array, data, TEST_SIZE) == 0);
assert(fread(data, 1, TEST_SIZE, fp) == 0);
assert(fclose(fp) == 0);
/* Test seekable file. */
memset(&tc, 0, sizeof(tc));
fp = funopen(&tc, test_readfn, test_writefn, test_seekfn, NULL);
assert(fp);
setvbuf(fp, NULL, _IONBF, 0);
assert(fwrite(data, 1, TEST_SIZE, fp) == TEST_SIZE);
assert(fseek(fp, 0L, SEEK_SET) == 0);
assert(fwrite(data, 1, ARRAY_SIZE, fp) == ARRAY_SIZE);
assert(memcmp(tc.array, data, ARRAY_SIZE) == 0);
assert(fread(data, 1, TEST_SIZE, fp) == 0);
assert(fclose(fp) == 0);
/* Test close hook. */
memset(&tc, 0, sizeof(tc));
fp = funopen(&tc, test_readfn, test_writefn, NULL, test_closefn);
assert(fclose(fp) == 0);
for (i = 0; i < sizeof(tc.array); i++)
assert(tc.array[i] == 0x7f);
return 0;
}

25
test/headers-overlay.sh Executable file
View File

@@ -0,0 +1,25 @@
#!/bin/sh
set -e
run()
{
echo "$@"
"$@"
}
incdir="${top_srcdir}/include/bsd"
CPPFLAGS="$CPPFLAGS -DLIBBSD_OVERLAY"
for inc in $(cd $incdir; find -name '*.h' | sort | cut -c3-); do
cat >headers-overlay-gen.c <<SOURCE
#include <$inc>
int main() { return 0; }
SOURCE
echo "testing header $inc"
run $CC -isystem "$incdir" $CPPFLAGS headers-overlay-gen.c -o /dev/null
echo
rm -f headers-overlay-gen*
done

24
test/headers-system.sh Executable file
View File

@@ -0,0 +1,24 @@
#!/bin/sh
set -e
run()
{
echo "$@"
"$@"
}
incdir="${top_srcdir}/include"
for inc in $(cd $incdir; find -name '*.h' | sort | cut -c3-); do
cat >headers-system-gen.c <<SOURCE
#include <$inc>
int main() { return 0; }
SOURCE
echo "testing header $inc"
run $CC -isystem "$incdir" $CPPFLAGS headers-system-gen.c -o /dev/null
echo
rm -f headers-system-gen.*
done

View File

@@ -1,25 +0,0 @@
/* Check that all libbsd overlayed headers preprocess. */
#include <sys/cdefs.h>
#include <sys/endian.h>
#include <sys/bitstring.h>
#include <sys/queue.h>
#include <sys/tree.h>
#include <sys/poll.h>
#include <err.h>
#include <getopt.h>
#include <libutil.h>
#include <md5.h>
#include <nlist.h>
#include <readpassphrase.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <vis.h>
int
main()
{
return 0;
}

View File

@@ -25,6 +25,7 @@
*/ */
#include <assert.h> #include <assert.h>
#include <errno.h>
#include <stdlib.h> #include <stdlib.h>
int int
@@ -60,5 +61,17 @@ main(int argc, char **argv)
assert(dehumanize_number("-3G", &val) == 0); assert(dehumanize_number("-3G", &val) == 0);
assert(val == -3221225472LL); assert(val == -3221225472LL);
assert(dehumanize_number("9223372036854775807", &val) == 0);
assert(val == INT64_MAX);
assert(dehumanize_number("9223372036854775808", &val) == -1);
assert(errno == ERANGE);
assert(dehumanize_number("-9223372036854775808", &val) == 0);
assert(val == INT64_MIN);
assert(dehumanize_number("-9223372036854775809", &val) == -1);
assert(errno == ERANGE);
return 0; return 0;
} }

View File

@@ -1,3 +1,29 @@
/*
* Copyright © 2012 Guillem Jover <guillem@hadrons.org>
*
* 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 ``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 system headers that are “known” to pull bits selectively from /* Include system headers that are “known” to pull bits selectively from
* other headers through magic macros, to check that the overlay is working * other headers through magic macros, to check that the overlay is working
* properly. */ * properly. */

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright © 2012 Guillem Jover <guillem@hadrons.org> * Copyright © 2012-2013 Guillem Jover <guillem@hadrons.org>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@@ -31,18 +31,30 @@
#include <string.h> #include <string.h>
int int
main(int argc, char **argv) main(int argc, char **argv, char **envp)
{ {
const char newtitle_base[] = "test arg1 arg2"; const char newtitle_base[] = "test arg1 arg2";
char *newtitle_full; char *newtitle_full;
char *envvar;
int rc;
#ifdef TEST_USE_SETPROCTITLE_INIT
setproctitle_init(argc, argv, envp);
#endif
setproctitle("-test %s arg2", "arg1"); setproctitle("-test %s arg2", "arg1");
assert(strcmp(argv[0], newtitle_base) == 0); assert(strcmp(argv[0], newtitle_base) == 0);
asprintf(&newtitle_full, "%s: %s", getprogname(), newtitle_base); rc = asprintf(&newtitle_full, "%s: %s", getprogname(), newtitle_base);
assert(rc > 0);
setproctitle("test %s arg2", "arg1"); setproctitle("test %s arg2", "arg1");
assert(strcmp(argv[0], newtitle_full) == 0); assert(strcmp(argv[0], newtitle_full) == 0);
free(newtitle_full); free(newtitle_full);
assert(setenv("LIBBSD_TEST", "test value", 1) == 0);
envvar = getenv("LIBBSD_TEST");
assert(envvar != NULL);
assert(strcmp(envvar, "test value") == 0);
return 0; return 0;
} }

70
test/strmode.c Normal file
View File

@@ -0,0 +1,70 @@
/*
* Copyright © 2015 Guillem Jover <guillem@hadrons.org>
*
* 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 ``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 <sys/stat.h>
#include <assert.h>
#include <string.h>
int
main(int argc, char **argv)
{
char mode_str[12];
strmode(0, mode_str);
assert(strcmp(mode_str, "?--------- ") == 0);
strmode(0777, mode_str);
assert(strcmp(mode_str, "?rwxrwxrwx ") == 0);
strmode(0777 | S_IFREG, mode_str);
assert(strcmp(mode_str, "-rwxrwxrwx ") == 0);
strmode(0777 | S_IFREG | S_ISUID | S_ISGID | S_ISVTX, mode_str);
assert(strcmp(mode_str, "-rwsrwsrwt ") == 0);
strmode(0666 | S_IFREG | S_ISUID | S_ISGID | S_ISVTX, mode_str);
assert(strcmp(mode_str, "-rwSrwSrwT ") == 0);
strmode(0777 | S_IFLNK, mode_str);
assert(strcmp(mode_str, "lrwxrwxrwx ") == 0);
strmode(0777 | S_IFCHR, mode_str);
assert(strcmp(mode_str, "crwxrwxrwx ") == 0);
strmode(0777 | S_IFBLK, mode_str);
assert(strcmp(mode_str, "brwxrwxrwx ") == 0);
strmode(0777 | S_IFDIR, mode_str);
assert(strcmp(mode_str, "drwxrwxrwx ") == 0);
strmode(0777 | S_IFIFO, mode_str);
assert(strcmp(mode_str, "prwxrwxrwx ") == 0);
strmode(0777 | S_IFSOCK, mode_str);
assert(strcmp(mode_str, "srwxrwxrwx ") == 0);
return 0;
}

84
test/test-stream.c Normal file
View File

@@ -0,0 +1,84 @@
/*
* Copyright © 2013 Guillem Jover <guillem@hadrons.org>
*
* 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 ``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 <sys/wait.h>
#include <assert.h>
#include <unistd.h>
#include <stdio.h>
#include "test-stream.h"
FILE *
pipe_feed(const char *fmt, const void **buf, int buf_nmemb)
{
FILE *fp;
int rc;
int pipefd[2];
pid_t pid;
rc = pipe(pipefd);
assert(rc >= 0);
pid = fork();
assert(pid >= 0);
if (pid == 0) {
int line;
/* Child writes data to pipe. */
rc = close(pipefd[0]);
assert(rc >= 0);
fp = fdopen(pipefd[1], "w");
assert(fp);
for (line = 0; line < buf_nmemb; line++) {
rc = fprintf(fp, fmt, buf[line]);
assert(rc >= 0);
}
rc = fclose(fp);
assert(rc >= 0);
_exit(0);
} else {
/* Parent gets a FILE and reads from it. */
rc = close(pipefd[1]);
assert(rc >= 0);
fp = fdopen(pipefd[0], "r");
assert(fp);
return fp;
}
}
void
pipe_close(FILE *fp)
{
fclose(fp);
wait(NULL);
}

37
test/test-stream.h Normal file
View File

@@ -0,0 +1,37 @@
/*
* Copyright © 2013 Guillem Jover <guillem@hadrons.org>
*
* 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 ``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 LIBBSD_TEST_STREAM
#define LIBBSD_TEST_STREAM
#include <stdio.h>
FILE *
pipe_feed(const char *fmt, const void **buf, int buf_nmemb);
void
pipe_close(FILE *fp);
#endif