mirror of
https://frontier.innolan.net/rainlance/c-ares.git
synced 2025-11-23 20:32:47 +00:00
test: Add framework for containerized testing
On Linux we can potentially use user and UTS namespaces to run a test in a pseudo-container with: - arbitrary filesystem (e.g. /etc/resolv.conf, /etc/nsswitch.conf, /etc/hosts) - arbitrary hostname/domainname. Include a first pass at the framework code to allow this, along with a first test case that uses the container.
This commit is contained in:
54
m4/ax_check_user_namespace.m4
Normal file
54
m4/ax_check_user_namespace.m4
Normal file
@ -0,0 +1,54 @@
|
||||
# -*- Autoconf -*-
|
||||
|
||||
# SYNOPSIS
|
||||
#
|
||||
# AX_CHECK_USER_NAMESPACE
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# This macro checks whether the local system supports Linux user namespaces.
|
||||
# If so, it calls AC_DEFINE(HAVE_USER_NAMESPACE).
|
||||
|
||||
AC_DEFUN([AX_CHECK_USER_NAMESPACE],[dnl
|
||||
AC_CACHE_CHECK([whether user namespaces are supported],
|
||||
ax_cv_user_namespace,[
|
||||
AC_LANG_PUSH([C])
|
||||
AC_RUN_IFELSE([AC_LANG_SOURCE([[
|
||||
#define _GNU_SOURCE
|
||||
#include <fcntl.h>
|
||||
#include <sched.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
int userfn(void *d) {
|
||||
usleep(100000); /* synchronize by sleep */
|
||||
return (getuid() != 0);
|
||||
}
|
||||
char userst[1024*1024];
|
||||
int main() {
|
||||
char buffer[1024];
|
||||
int rc, status, fd;
|
||||
pid_t child = clone(userfn, userst + 1024*1024, CLONE_NEWUSER|SIGCHLD, 0);
|
||||
if (child < 0) return 1;
|
||||
|
||||
sprintf(buffer, "/proc/%d/uid_map", child);
|
||||
fd = open(buffer, O_CREAT|O_WRONLY|O_TRUNC, 0755);
|
||||
sprintf(buffer, "0 %d 1\n", getuid());
|
||||
write(fd, buffer, strlen(buffer));
|
||||
close(fd);
|
||||
|
||||
rc = waitpid(child, &status, 0);
|
||||
if (rc <= 0) return 1;
|
||||
if (!WIFEXITED(status)) return 1;
|
||||
return WEXITSTATUS(status);
|
||||
}
|
||||
]])],[ax_cv_user_namespace=yes], [ax_cv_user_namespace=no])
|
||||
AC_LANG_POP([C])
|
||||
])
|
||||
if test "$ax_cv_user_namespace" = yes; then
|
||||
AC_DEFINE([HAVE_USER_NAMESPACE],[1],[Whether user namespaces are available])
|
||||
fi
|
||||
]) # AX_CHECK_USER_NAMESPACE
|
||||
76
m4/ax_check_uts_namespace.m4
Normal file
76
m4/ax_check_uts_namespace.m4
Normal file
@ -0,0 +1,76 @@
|
||||
# -*- Autoconf -*-
|
||||
|
||||
# SYNOPSIS
|
||||
#
|
||||
# AX_CHECK_UTS_NAMESPACE
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# This macro checks whether the local system supports Linux UTS namespaces.
|
||||
# Also requires user namespaces to be available, so that non-root users
|
||||
# can enter the namespace.
|
||||
# If so, it calls AC_DEFINE(HAVE_UTS_NAMESPACE).
|
||||
|
||||
AC_DEFUN([AX_CHECK_UTS_NAMESPACE],[dnl
|
||||
AC_CACHE_CHECK([whether UTS namespaces are supported],
|
||||
ax_cv_uts_namespace,[
|
||||
AC_LANG_PUSH([C])
|
||||
AC_RUN_IFELSE([AC_LANG_SOURCE([[
|
||||
#define _GNU_SOURCE
|
||||
#include <sched.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
int utsfn(void *d) {
|
||||
char buffer[1024];
|
||||
const char *name = "autoconftest";
|
||||
int rc = sethostname(name, strlen(name));
|
||||
if (rc != 0) return 1;
|
||||
gethostname(buffer, 1024);
|
||||
return (strcmp(buffer, name) != 0);
|
||||
}
|
||||
|
||||
char st2[1024*1024];
|
||||
int fn(void *d) {
|
||||
pid_t child;
|
||||
int rc, status;
|
||||
usleep(100000); /* synchronize by sleep */
|
||||
if (getuid() != 0) return 1;
|
||||
child = clone(utsfn, st2 + 1024*1024, CLONE_NEWUTS|SIGCHLD, 0);
|
||||
if (child < 0) return 1;
|
||||
rc = waitpid(child, &status, 0);
|
||||
if (rc <= 0) return 1;
|
||||
if (!WIFEXITED(status)) return 1;
|
||||
return WEXITSTATUS(status);
|
||||
}
|
||||
char st[1024*1024];
|
||||
int main() {
|
||||
char buffer[1024];
|
||||
int rc, status, fd;
|
||||
pid_t child = clone(fn, st + 1024*1024, CLONE_NEWUSER|SIGCHLD, 0);
|
||||
if (child < 0) return 1;
|
||||
|
||||
sprintf(buffer, "/proc/%d/uid_map", child);
|
||||
fd = open(buffer, O_CREAT|O_WRONLY|O_TRUNC, 0755);
|
||||
sprintf(buffer, "0 %d 1\n", getuid());
|
||||
write(fd, buffer, strlen(buffer));
|
||||
close(fd);
|
||||
|
||||
rc = waitpid(child, &status, 0);
|
||||
if (rc <= 0) return 1;
|
||||
if (!WIFEXITED(status)) return 1;
|
||||
return WEXITSTATUS(status);
|
||||
}
|
||||
]])
|
||||
],[ax_cv_uts_namespace=yes], [ax_cv_uts_namespace=no])
|
||||
AC_LANG_POP([C])
|
||||
])
|
||||
if test "$ax_cv_uts_namespace" = yes; then
|
||||
AC_DEFINE([HAVE_UTS_NAMESPACE],[1],[Whether UTS namespaces are available])
|
||||
fi
|
||||
]) # AX_CHECK_UTS_NAMESPACE
|
||||
Reference in New Issue
Block a user