summaryrefslogtreecommitdiff
path: root/support
diff options
context:
space:
mode:
authorFlorian Weimer <fweimer@redhat.com>2017-06-02 15:50:36 +0200
committerFlorian Weimer <fweimer@redhat.com>2017-06-02 15:50:36 +0200
commit2714c5f3c95f90977167c1d21326d907fb76b419 (patch)
tree5c3fc58f8177144973b0714aed382f8b32dadd84 /support
parent673cb072a4710bd4bf6029a062d2867cca929c43 (diff)
resolv: Tests for various versions of res_init
Diffstat (limited to 'support')
-rw-r--r--support/Makefile9
-rw-r--r--support/capture_subprocess.h19
-rw-r--r--support/namespace.h12
-rw-r--r--support/support-xstat.c30
-rw-r--r--support/support.h15
-rw-r--r--support/support_can_chroot.c65
-rw-r--r--support/support_capture_subprocess_check.c67
-rw-r--r--support/support_isolate_in_subprocess.c38
-rw-r--r--support/support_shared_allocate.c57
-rw-r--r--support/support_write_file_string.c39
-rw-r--r--support/xchroot.c28
-rw-r--r--support/xmkdir.c28
-rw-r--r--support/xopen.c30
-rw-r--r--support/xunistd.h9
14 files changed, 445 insertions, 1 deletions
diff --git a/support/Makefile b/support/Makefile
index 3ce73a6c76..20b0343ade 100644
--- a/support/Makefile
+++ b/support/Makefile
@@ -35,8 +35,11 @@ libsupport-routines = \
oom_error \
resolv_test \
set_fortify_handler \
+ support-xstat \
support_become_root \
+ support_can_chroot \
support_capture_subprocess \
+ support_capture_subprocess_check \
support_enter_network_namespace \
support_format_address_family \
support_format_addrinfo \
@@ -44,8 +47,11 @@ libsupport-routines = \
support_format_herrno \
support_format_hostent \
support_format_netent \
+ support_isolate_in_subprocess \
support_record_failure \
support_run_diff \
+ support_shared_allocate \
+ support_write_file_string \
support_test_main \
support_test_verify_impl \
temp_file \
@@ -55,6 +61,7 @@ libsupport-routines = \
xasprintf \
xbind \
xcalloc \
+ xchroot \
xclose \
xconnect \
xdup2 \
@@ -65,8 +72,10 @@ libsupport-routines = \
xlisten \
xmalloc \
xmemstream \
+ xmkdir \
xmmap \
xmunmap \
+ xopen \
xpipe \
xpoll \
xpthread_attr_destroy \
diff --git a/support/capture_subprocess.h b/support/capture_subprocess.h
index be5d34fbe2..43caf9bce4 100644
--- a/support/capture_subprocess.h
+++ b/support/capture_subprocess.h
@@ -39,4 +39,23 @@ struct support_capture_subprocess support_capture_subprocess
support_capture_subprocess. */
void support_capture_subprocess_free (struct support_capture_subprocess *);
+enum support_capture_allow
+{
+ /* No output is allowed. */
+ sc_allow_none = 0x01,
+ /* Output to stdout is permitted. */
+ sc_allow_stdout = 0x02,
+ /* Output to standard error is permitted. */
+ sc_allow_stderr = 0x04,
+};
+
+/* Check that the subprocess exited with STATUS and that only the
+ allowed outputs happened. ALLOWED is a combination of
+ support_capture_allow flags. Report errors under the CONTEXT
+ message. */
+void support_capture_subprocess_check (struct support_capture_subprocess *,
+ const char *context, int status,
+ int allowed)
+ __attribute__ ((nonnull (1, 2)));
+
#endif /* SUPPORT_CAPTURE_SUBPROCESS_H */
diff --git a/support/namespace.h b/support/namespace.h
index 6bc82d619b..e1ccaa1ef0 100644
--- a/support/namespace.h
+++ b/support/namespace.h
@@ -35,6 +35,13 @@ __BEGIN_DECLS
single-threaded processes. */
bool support_become_root (void);
+/* Return true if this process can perform a chroot operation. In
+ general, this is only possible if support_become_root has been
+ called. Note that the actual test is performed in a subprocess,
+ after fork, so that the file system root of the original process is
+ not changed. */
+bool support_can_chroot (void);
+
/* Enter a network namespace (and a UTS namespace if possible) and
configure the loopback interface. Return true if a network
namespace could be created. Print diagnostics to standard output.
@@ -48,6 +55,11 @@ bool support_enter_network_namespace (void);
UTS namespace. */
bool support_in_uts_namespace (void);
+/* Invoke CALLBACK (CLOSURE) in a subprocess created using fork.
+ Terminate the calling process if the subprocess exits with a
+ non-zero exit status. */
+void support_isolate_in_subprocess (void (*callback) (void *), void *closure);
+
__END_DECLS
#endif
diff --git a/support/support-xstat.c b/support/support-xstat.c
new file mode 100644
index 0000000000..86a81ec601
--- /dev/null
+++ b/support/support-xstat.c
@@ -0,0 +1,30 @@
+/* stat64 with error checking.
+ Copyright (C) 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* NB: Non-standard file name to avoid sysdeps override for xstat. */
+
+#include <support/check.h>
+#include <support/xunistd.h>
+#include <sys/stat.h>
+
+void
+xstat (const char *path, struct stat64 *result)
+{
+ if (stat64 (path, result) != 0)
+ FAIL_EXIT1 ("stat64 (\"%s\"): %m", path);
+}
diff --git a/support/support.h b/support/support.h
index 7292e2a564..4b5f04c2cc 100644
--- a/support/support.h
+++ b/support/support.h
@@ -44,6 +44,21 @@ void set_fortify_handler (void (*handler) (int sig));
void oom_error (const char *function, size_t size)
__attribute__ ((nonnull (1)));
+/* Return a pointer to a memory region of SIZE bytes. The memory is
+ initialized to zero and will be shared with subprocesses (across
+ fork). The returned pointer must be freed using
+ support_shared_free; it is not compatible with the malloc
+ functions. */
+void *support_shared_allocate (size_t size);
+
+/* Deallocate a pointer returned by support_shared_allocate. */
+void support_shared_free (void *);
+
+/* Write CONTENTS to the file PATH. Create or truncate the file as
+ needed. The file mode is 0666 masked by the umask. Terminate the
+ process on error. */
+void support_write_file_string (const char *path, const char *contents);
+
/* Error-checking wrapper functions which terminate the process on
error. */
diff --git a/support/support_can_chroot.c b/support/support_can_chroot.c
new file mode 100644
index 0000000000..0dfd2deb54
--- /dev/null
+++ b/support/support_can_chroot.c
@@ -0,0 +1,65 @@
+/* Return true if the process can perform a chroot operation.
+ Copyright (C) 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <stdio.h>
+#include <support/check.h>
+#include <support/namespace.h>
+#include <support/support.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <xunistd.h>
+
+static void
+callback (void *closure)
+{
+ int *result = closure;
+ struct stat64 before;
+ xstat ("/dev", &before);
+ if (chroot ("/dev") != 0)
+ {
+ *result = errno;
+ return;
+ }
+ struct stat64 after;
+ xstat ("/", &after);
+ TEST_VERIFY (before.st_dev == after.st_dev);
+ TEST_VERIFY (before.st_ino == after.st_ino);
+ *result = 0;
+}
+
+bool
+support_can_chroot (void)
+{
+ int *result = support_shared_allocate (sizeof (*result));
+ *result = 0;
+ support_isolate_in_subprocess (callback, result);
+ bool ok = *result == 0;
+ if (!ok)
+ {
+ static bool already_warned;
+ if (!already_warned)
+ {
+ already_warned = true;
+ errno = *result;
+ printf ("warning: this process does not support chroot: %m\n");
+ }
+ }
+ support_shared_free (result);
+ return ok;
+}
diff --git a/support/support_capture_subprocess_check.c b/support/support_capture_subprocess_check.c
new file mode 100644
index 0000000000..708c89f331
--- /dev/null
+++ b/support/support_capture_subprocess_check.c
@@ -0,0 +1,67 @@
+/* Verify capture output from a subprocess.
+ Copyright (C) 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <support/capture_subprocess.h>
+#include <support/check.h>
+
+static void
+print_context (const char *context, bool *failed)
+{
+ if (*failed)
+ /* Do not duplicate message. */
+ return;
+ support_record_failure ();
+ printf ("error: subprocess failed: %s\n", context);
+}
+
+void
+support_capture_subprocess_check (struct support_capture_subprocess *proc,
+ const char *context, int status,
+ int allowed)
+{
+ TEST_VERIFY ((allowed & sc_allow_none)
+ || (allowed & sc_allow_stdout)
+ || (allowed & sc_allow_stderr));
+ TEST_VERIFY (!((allowed & sc_allow_none)
+ && ((allowed & sc_allow_stdout)
+ || (allowed & sc_allow_stderr))));
+
+ bool failed = false;
+ if (proc->status != status)
+ {
+ print_context (context, &failed);
+ printf ("error: expected exit status: %d\n", status);
+ printf ("error: actual exit status: %d\n", status);
+ }
+ if (!(allowed & sc_allow_stdout) && proc->out.length != 0)
+ {
+ print_context (context, &failed);
+ printf ("error: unexpected output from subprocess\n");
+ fwrite (proc->out.buffer, proc->out.length, 1, stdout);
+ puts ("\n");
+ }
+ if (!(allowed & sc_allow_stderr) && proc->err.length != 0)
+ {
+ print_context (context, &failed);
+ printf ("error: unexpected error output from subprocess\n");
+ fwrite (proc->err.buffer, proc->err.length, 1, stdout);
+ puts ("\n");
+ }
+}
diff --git a/support/support_isolate_in_subprocess.c b/support/support_isolate_in_subprocess.c
new file mode 100644
index 0000000000..cf48614383
--- /dev/null
+++ b/support/support_isolate_in_subprocess.c
@@ -0,0 +1,38 @@
+/* Run a function in a subprocess.
+ Copyright (C) 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <support/check.h>
+#include <support/xunistd.h>
+
+void
+support_isolate_in_subprocess (void (*callback) (void *), void *closure)
+{
+ pid_t pid = xfork ();
+ if (pid == 0)
+ {
+ /* Child process. */
+ callback (closure);
+ _exit (0);
+ }
+
+ /* Parent process. */
+ int status;
+ xwaitpid (pid, &status, 0);
+ if (status != 0)
+ FAIL_EXIT1 ("child process exited with status %d", status);
+}
diff --git a/support/support_shared_allocate.c b/support/support_shared_allocate.c
new file mode 100644
index 0000000000..61d088e8cf
--- /dev/null
+++ b/support/support_shared_allocate.c
@@ -0,0 +1,57 @@
+/* Allocate a memory region shared across processes.
+ Copyright (C) 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <stddef.h>
+#include <support/support.h>
+#include <support/xunistd.h>
+#include <sys/mman.h>
+
+/* Header for the allocation. It contains the size of the allocation
+ for subsequent unmapping. */
+struct header
+{
+ size_t total_size;
+ char data[] __attribute__ ((aligned (__alignof__ (max_align_t))));
+};
+
+void *
+support_shared_allocate (size_t size)
+{
+ size_t total_size = size + offsetof (struct header, data);
+ if (total_size < size)
+ {
+ errno = ENOMEM;
+ oom_error (__func__, size);
+ return NULL;
+ }
+ else
+ {
+ struct header *result = xmmap (NULL, total_size, PROT_READ | PROT_WRITE,
+ MAP_ANONYMOUS | MAP_SHARED, -1);
+ result->total_size = total_size;
+ return &result->data;
+ }
+}
+
+void
+support_shared_free (void *data)
+{
+ struct header *header = data - offsetof (struct header, data);
+ xmunmap (header, header->total_size);
+}
diff --git a/support/support_write_file_string.c b/support/support_write_file_string.c
new file mode 100644
index 0000000000..48e89597f3
--- /dev/null
+++ b/support/support_write_file_string.c
@@ -0,0 +1,39 @@
+/* Write a string to a file.
+ Copyright (C) 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <fcntl.h>
+#include <string.h>
+#include <support/check.h>
+#include <xunistd.h>
+
+void
+support_write_file_string (const char *path, const char *contents)
+{
+ int fd = xopen (path, O_CREAT | O_TRUNC | O_WRONLY, 0666);
+ const char *end = contents + strlen (contents);
+ for (const char *p = contents; p < end; )
+ {
+ ssize_t ret = write (fd, p, end - p);
+ if (ret < 0)
+ FAIL_EXIT1 ("cannot write to \"%s\": %m", path);
+ if (ret == 0)
+ FAIL_EXIT1 ("zero-length write to \"%s\"", path);
+ p += ret;
+ }
+ xclose (fd);
+}
diff --git a/support/xchroot.c b/support/xchroot.c
new file mode 100644
index 0000000000..abcc299e00
--- /dev/null
+++ b/support/xchroot.c
@@ -0,0 +1,28 @@
+/* chroot with error checking.
+ Copyright (C) 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <support/check.h>
+#include <support/xunistd.h>
+#include <sys/stat.h>
+
+void
+xchroot (const char *path)
+{
+ if (chroot (path) != 0)
+ FAIL_EXIT1 ("chroot (\"%s\"): %m", path);
+}
diff --git a/support/xmkdir.c b/support/xmkdir.c
new file mode 100644
index 0000000000..ea17d49391
--- /dev/null
+++ b/support/xmkdir.c
@@ -0,0 +1,28 @@
+/* mkdir with error checking.
+ Copyright (C) 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <support/check.h>
+#include <support/xunistd.h>
+#include <sys/stat.h>
+
+void
+xmkdir (const char *path, mode_t mode)
+{
+ if (mkdir (path, mode) != 0)
+ FAIL_EXIT1 ("mkdir (\"%s\", 0%o): %m", path, mode);
+}
diff --git a/support/xopen.c b/support/xopen.c
new file mode 100644
index 0000000000..7f033a03a7
--- /dev/null
+++ b/support/xopen.c
@@ -0,0 +1,30 @@
+/* open64 with error checking.
+ Copyright (C) 2017 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <support/check.h>
+#include <support/xunistd.h>
+#include <fcntl.h>
+
+int
+xopen (const char *path, int flags, mode_t mode)
+{
+ int ret = open64 (path, flags, mode);
+ if (ret < 0)
+ FAIL_EXIT1 ("open64 (\"%s\", 0x%x, 0%o): %m", path, flags, mode);
+ return ret;
+}
diff --git a/support/xunistd.h b/support/xunistd.h
index 7c14bda7be..151d743e1f 100644
--- a/support/xunistd.h
+++ b/support/xunistd.h
@@ -22,15 +22,22 @@
#ifndef SUPPORT_XUNISTD_H
#define SUPPORT_XUNISTD_H
-#include <unistd.h>
#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <unistd.h>
__BEGIN_DECLS
+struct stat64;
+
pid_t xfork (void);
pid_t xwaitpid (pid_t, int *status, int flags);
void xpipe (int[2]);
void xdup2 (int, int);
+int xopen (const char *path, int flags, mode_t);
+void xstat (const char *path, struct stat64 *);
+void xmkdir (const char *path, mode_t);
+void xchroot (const char *path);
/* Close the file descriptor. Ignore EINTR errors, but terminate the
process on other errors. */