summaryrefslogtreecommitdiff
path: root/tests/try-syscall.c
blob: 221fe324bf2e4f219df9b66cecdb0cf32f6e66da (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
/* vi:set et sw=2 sts=2 cin cino=t0,f0,(0,{s,>2s,n-s,^-s,e-s:
 * 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.
 *
 * This helper is used for regression tests in both bubblewrap and flatpak.
 * Please keep both copies in sync.
 */

#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 == _ABIO32
#   define MISSING_SYSCALL_BASE 4000
# elif _MIPS_SIM == _ABI64
#   define MISSING_SYSCALL_BASE 5000
# elif _MIPS_SIM == _ABIN32
#   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)

#ifndef PR_GET_CHILD_SUBREAPER
#define PR_GET_CHILD_SUBREAPER 37
#endif

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;
}