1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) International Business Machines Corp., 2001
4 * Copyright (c) 2020 Petr Vorel <[email protected]>
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
32 static int amaster, aslave;
33 static int fd, fd_file;
34 static int bfd = -1;
35
36 static struct termio termio;
37 static struct termios termios;
38
39 static 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
verify_ioctl(unsigned int i)60 static 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
setup(void)66 static 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
cleanup(void)75 static 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
85 static 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