Skip to content

Commit

Permalink
tests: Add try-syscall helper
Browse files Browse the repository at this point in the history
This exercises various syscalls. It's heavily based on the one from
<containers/bubblewrap#459>, but with the
addition of a mode to output the numeric values of various expected
errno codes, which are not otherwise available to shell scripts.

Signed-off-by: Simon McVittie <smcv@collabora.com>
  • Loading branch information
smcv committed Oct 21, 2021
1 parent 14b375e commit e45bfde
Show file tree
Hide file tree
Showing 2 changed files with 178 additions and 0 deletions.
5 changes: 5 additions & 0 deletions tests/Makefile.am.inc
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,10 @@ tests_test_authenticator_CFLAGS = $(AM_CFLAGS) $(BASE_CFLAGS) \
tests_test_authenticator_LDADD = $(AM_LDADD) $(BASE_LIBS) libflatpak-common.la libflatpak-common-base.la libglnx.la
tests_test_authenticator_SOURCES = tests/test-authenticator.c

tests_try_syscall_CFLAGS = $(AM_CFLAGS)
tests_try_syscall_LDADD = $(AM_LDADD)
tests_try_syscall_SOURCES = tests/try-syscall.c

tests_list_unused_CFLAGS = $(AM_CFLAGS) $(BASE_CFLAGS) $(OSTREE_CFLAGS) $(SOUP_CFLAGS) $(JSON_CFLAGS) $(APPSTREAM_GLIB_CFLAGS) \
-DFLATPAK_COMPILATION \
-DLOCALEDIR=\"$(localedir)\"
Expand Down Expand Up @@ -317,6 +321,7 @@ test_extra_programs = \
tests/test-authenticator \
tests/test-portal-impl \
tests/test-update-portal \
tests/try-syscall \
$(NULL)

@VALGRIND_CHECK_RULES@
Expand Down
173 changes: 173 additions & 0 deletions tests/try-syscall.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
/*
* Copyright 2021 Simon McVittie
* SPDX-License-Identifier: LGPL-2.0-or-later
*
* Try one or more system calls that might have been blocked by a
* seccomp filter. Return the last value of errno seen.
*
* In general, we pass a bad fd or pointer to each syscall that will
* accept one, so that it will fail with EBADF or EFAULT without side-effects.
*/

#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/prctl.h>
#include <sys/socket.h>
#include <sys/syscall.h>
#include <sys/stat.h>
#include <sys/types.h>

#if defined(_MIPS_SIM)
# if _MIPS_SIM == _MIPS_SIM_ABI32
# define MISSING_SYSCALL_BASE 4000
# elif _MIPS_SIM == _MIPS_SIM_ABI64
# define MISSING_SYSCALL_BASE 5000
# elif _MIPS_SIM == _MIPS_SIM_NABI32
# define MISSING_SYSCALL_BASE 6000
# else
# error "Unknown MIPS ABI"
# endif
#endif

#if defined(__ia64__)
# define MISSING_SYSCALL_BASE 1024
#endif

#if defined(__alpha__)
# define MISSING_SYSCALL_BASE 110
#endif

#if defined(__x86_64__) && defined(__ILP32__)
# define MISSING_SYSCALL_BASE 0x40000000
#endif

/*
* MISSING_SYSCALL_BASE:
*
* Number to add to the syscall numbers of recently-added syscalls
* to get the appropriate syscall for the current ABI.
*/
#ifndef MISSING_SYSCALL_BASE
# define MISSING_SYSCALL_BASE 0
#endif

#ifndef __NR_clone3
# define __NR_clone3 (MISSING_SYSCALL_BASE + 435)
#endif

/*
* The size of clone3's parameter (as of 2021)
*/
#define SIZEOF_STRUCT_CLONE_ARGS ((size_t) 88)

/*
* An invalid pointer that will cause syscalls to fail with EFAULT
*/
#define WRONG_POINTER ((char *) 1)

int
main (int argc, char **argv)
{
int errsv = 0;
int i;

for (i = 1; i < argc; i++)
{
const char *arg = argv[i];

if (strcmp (arg, "print-errno-values") == 0)
{
printf ("EBADF=%d\n", EBADF);
printf ("EFAULT=%d\n", EFAULT);
printf ("ENOENT=%d\n", ENOENT);
printf ("ENOSYS=%d\n", ENOSYS);
printf ("EPERM=%d\n", EPERM);
}
else if (strcmp (arg, "chmod") == 0)
{
/* If not blocked by seccomp, this will fail with EFAULT */
if (chmod (WRONG_POINTER, 0700) != 0)
{
errsv = errno;
perror (arg);
}
}
else if (strcmp (arg, "chroot") == 0)
{
/* If not blocked by seccomp, this will fail with EFAULT */
if (chroot (WRONG_POINTER) != 0)
{
errsv = errno;
perror (arg);
}
}
else if (strcmp (arg, "clone3") == 0)
{
/* If not blocked by seccomp, this will fail with EFAULT */
if (syscall (__NR_clone3, WRONG_POINTER, SIZEOF_STRUCT_CLONE_ARGS) != 0)
{
errsv = errno;
perror (arg);
}
}
else if (strcmp (arg, "ioctl TIOCNOTTY") == 0)
{
/* If not blocked by seccomp, this will fail with EBADF */
if (ioctl (-1, TIOCNOTTY) != 0)
{
errsv = errno;
perror (arg);
}
}
else if (strcmp (arg, "ioctl TIOCSTI") == 0)
{
/* If not blocked by seccomp, this will fail with EBADF */
if (ioctl (-1, TIOCSTI, WRONG_POINTER) != 0)
{
errsv = errno;
perror (arg);
}
}
#ifdef __LP64__
else if (strcmp (arg, "ioctl TIOCSTI CVE-2019-10063") == 0)
{
unsigned long not_TIOCSTI = (0x123UL << 32) | (unsigned long) TIOCSTI;

/* If not blocked by seccomp, this will fail with EBADF */
if (syscall (__NR_ioctl, -1, not_TIOCSTI, WRONG_POINTER) != 0)
{
errsv = errno;
perror (arg);
}
}
#endif
else if (strcmp (arg, "listen") == 0)
{
/* If not blocked by seccomp, this will fail with EBADF */
if (listen (-1, 42) != 0)
{
errsv = errno;
perror (arg);
}
}
else if (strcmp (arg, "prctl") == 0)
{
/* If not blocked by seccomp, this will fail with EFAULT */
if (prctl (PR_GET_CHILD_SUBREAPER, WRONG_POINTER, 0, 0, 0) != 0)
{
errsv = errno;
perror (arg);
}
}
else
{
fprintf (stderr, "Unsupported syscall \"%s\"\n", arg);
errsv = ENOENT;
}
}

return errsv;
}

0 comments on commit e45bfde

Please sign in to comment.