1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Copyright (c) International Business Machines Corp., 2001 4 * Copyright (c) 2020 Petr Vorel <petr.vorel@gmail.com> 5 * Copyright (c) Linux Test Project, 2002-2023 6 * 07/2001 Ported by Wayne Boyer 7 * 04/2002 Fixes by wjhuie 8 */ 9 10/*\ 11 * [Description] 12 * 13 * Testcase to check the errnos set by the ioctl(2) system call. 14 * 15 * - EBADF: Pass an invalid fd to ioctl(fd, ...) and expect EBADF 16 * - EFAULT: Pass an invalid address of arg in ioctl(fd, ..., arg) 17 * - EINVAL: Pass invalid cmd in ioctl(fd, cmd, arg) 18 * - ENOTTY: Pass an non-streams fd in ioctl(fd, cmd, arg) 19 * - EFAULT: Pass a NULL address for termio 20 */ 21 22#include <errno.h> 23#include <fcntl.h> 24#include <stdio.h> 25#include <termios.h> 26#include <pty.h> 27#include "tst_test.h" 28#include "lapi/ioctl.h" 29 30#define INVAL_IOCTL 9999999 31 32static int amaster, aslave; 33static int fd, fd_file; 34static int bfd = -1; 35 36static struct termio termio; 37static struct termios termios; 38 39static struct tcase { 40 const char *desc; 41 int *fd; 42 int request; 43 void *s_tio; 44 int error; 45} tcases[] = { 46 {"File descriptor is invalid (termio)", &bfd, TCGETA, &termio, EBADF}, 47 {"File descriptor is invalid (termios)", &bfd, TCGETS, &termios, EBADF}, 48 {"Termio address is invalid", &fd, TCGETA, (struct termio *)-1, EFAULT}, 49 {"Termios address is invalid", &fd, TCGETS, (struct termios *)-1, EFAULT}, 50 /* This errno value was changed from EINVAL to ENOTTY 51 * by kernel commit 07d106d0 and bbb63c51 52 */ 53 {"Command is invalid", &fd, INVAL_IOCTL, &termio, ENOTTY}, 54 {"File descriptor is for a regular file (termio)", &fd_file, TCGETA, &termio, ENOTTY}, 55 {"File descriptor is for a regular file (termios)", &fd_file, TCGETS, &termios, ENOTTY}, 56 {"Termio is NULL", &fd, TCGETA, NULL, EFAULT}, 57 {"Termios is NULL", &fd, TCGETS, NULL, EFAULT} 58}; 59 60static void verify_ioctl(unsigned int i) 61{ 62 TST_EXP_FAIL(ioctl(*(tcases[i].fd), tcases[i].request, tcases[i].s_tio), 63 tcases[i].error, "%s", tcases[i].desc); 64} 65 66static void setup(void) 67{ 68 if (openpty(&amaster, &aslave, NULL, NULL, NULL) < 0) 69 tst_brk(TBROK | TERRNO, "unable to open pty"); 70 71 fd = amaster; 72 fd_file = SAFE_OPEN("x", O_CREAT, 0777); 73} 74 75static void cleanup(void) 76{ 77 if (amaster > 0) 78 SAFE_CLOSE(amaster); 79 if (aslave > 0) 80 SAFE_CLOSE(aslave); 81 if (fd_file > 0) 82 SAFE_CLOSE(fd_file); 83} 84 85static struct tst_test test = { 86 .needs_tmpdir = 1, 87 .setup = setup, 88 .cleanup = cleanup, 89 .test = verify_ioctl, 90 .tcnt = ARRAY_SIZE(tcases) 91}; 92