linux/tools/testing/selftests/x86/syscall_numbering.c
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0 */
   2/*
   3 * syscall_arg_fault.c - tests faults 32-bit fast syscall stack args
   4 * Copyright (c) 2018 Andrew Lutomirski
   5 */
   6
   7#define _GNU_SOURCE
   8
   9#include <stdlib.h>
  10#include <stdio.h>
  11#include <stdbool.h>
  12#include <errno.h>
  13#include <unistd.h>
  14#include <syscall.h>
  15
  16static int nerrs;
  17
  18#define X32_BIT 0x40000000UL
  19
  20static void check_enosys(unsigned long nr, bool *ok)
  21{
  22        /* If this fails, a segfault is reasonably likely. */
  23        fflush(stdout);
  24
  25        long ret = syscall(nr, 0, 0, 0, 0, 0, 0);
  26        if (ret == 0) {
  27                printf("[FAIL]\tsyscall %lu succeeded, but it should have failed\n", nr);
  28                *ok = false;
  29        } else if (errno != ENOSYS) {
  30                printf("[FAIL]\tsyscall %lu had error code %d, but it should have reported ENOSYS\n", nr, errno);
  31                *ok = false;
  32        }
  33}
  34
  35static void test_x32_without_x32_bit(void)
  36{
  37        bool ok = true;
  38
  39        /*
  40         * Syscalls 512-547 are "x32" syscalls.  They are intended to be
  41         * called with the x32 (0x40000000) bit set.  Calling them without
  42         * the x32 bit set is nonsense and should not work.
  43         */
  44        printf("[RUN]\tChecking syscalls 512-547\n");
  45        for (int i = 512; i <= 547; i++)
  46                check_enosys(i, &ok);
  47
  48        /*
  49         * Check that a handful of 64-bit-only syscalls are rejected if the x32
  50         * bit is set.
  51         */
  52        printf("[RUN]\tChecking some 64-bit syscalls in x32 range\n");
  53        check_enosys(16 | X32_BIT, &ok);        /* ioctl */
  54        check_enosys(19 | X32_BIT, &ok);        /* readv */
  55        check_enosys(20 | X32_BIT, &ok);        /* writev */
  56
  57        /*
  58         * Check some syscalls with high bits set.
  59         */
  60        printf("[RUN]\tChecking numbers above 2^32-1\n");
  61        check_enosys((1UL << 32), &ok);
  62        check_enosys(X32_BIT | (1UL << 32), &ok);
  63
  64        if (!ok)
  65                nerrs++;
  66        else
  67                printf("[OK]\tThey all returned -ENOSYS\n");
  68}
  69
  70int main()
  71{
  72        /*
  73         * Anyone diagnosing a failure will want to know whether the kernel
  74         * supports x32.  Tell them.
  75         */
  76        printf("\tChecking for x32...");
  77        fflush(stdout);
  78        if (syscall(39 | X32_BIT, 0, 0, 0, 0, 0, 0) >= 0) {
  79                printf(" supported\n");
  80        } else if (errno == ENOSYS) {
  81                printf(" not supported\n");
  82        } else {
  83                printf(" confused\n");
  84        }
  85
  86        test_x32_without_x32_bit();
  87
  88        return nerrs ? 1 : 0;
  89}
  90