• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) International Business Machines  Corp., 2001
4  *  07/2001 Ported by Wayne Boyer
5  *  04/2002 Fixes by wjhuie
6  */
7 /*
8  * DESCRIPTION
9  *	Testcase to check the errnos set by the ioctl(2) system call.
10  *
11  * ALGORITHM
12  *	1. EBADF: Pass an invalid fd to ioctl(fd, ..) and expect EBADF.
13  *	2. EFAULT: Pass an invalid address of arg in ioctl(fd, .., arg)
14  *	3. EINVAL: Pass invalid cmd in ioctl(fd, cmd, arg)
15  *	4. ENOTTY: Pass an non-streams fd in ioctl(fd, cmd, arg)
16  *	5. EFAULT: Pass a NULL address for termio
17  *
18  */
19 
20 #include <errno.h>
21 #include <fcntl.h>
22 #include <stdio.h>
23 #include <termio.h>
24 #include <termios.h>
25 #include "tst_test.h"
26 
27 #define	INVAL_IOCTL	9999999
28 
29 static int fd, fd_file;
30 static int bfd = -1;
31 
32 static struct termio termio;
33 
34 static struct tcase {
35 	int *fd;
36 	int request;
37 	struct termio *s_tio;
38 	int error;
39 } tcases[] = {
40 	/* file descriptor is invalid */
41 	{&bfd, TCGETA, &termio, EBADF},
42 	/* termio address is invalid */
43 	{&fd, TCGETA, (struct termio *)-1, EFAULT},
44 	/* command is invalid */
45 	/* This errno value was changed from EINVAL to ENOTTY
46 	 * by kernel commit 07d106d0 and bbb63c51
47 	 */
48 	{&fd, INVAL_IOCTL, &termio, ENOTTY},
49 	/* file descriptor is for a regular file */
50 	{&fd_file, TCGETA, &termio, ENOTTY},
51 	/* termio is NULL */
52 	{&fd, TCGETA, NULL, EFAULT}
53 };
54 
55 static char *device;
56 
verify_ioctl(unsigned int i)57 static void verify_ioctl(unsigned int i)
58 {
59 	TEST(ioctl(*(tcases[i].fd), tcases[i].request, tcases[i].s_tio));
60 
61 	if (TST_RET != -1) {
62 		tst_res(TFAIL, "call succeeded unexpectedly");
63 		return;
64 	}
65 
66 	if (TST_ERR != tcases[i].error) {
67 		tst_res(TFAIL | TTERRNO,
68 			"failed unexpectedly; expected %s",
69 		        tst_strerrno(tcases[i].error));
70 		return;
71 	}
72 
73 	tst_res(TPASS | TTERRNO, "failed as expected");
74 }
75 
setup(void)76 static void setup(void)
77 {
78 	unsigned int i;
79 
80 	if (!device)
81 		tst_brk(TBROK, "You must specify a tty device with -D option");
82 
83 	fd = SAFE_OPEN(device, O_RDWR, 0777);
84 
85 	if (tst_kvercmp(3, 7, 0) < 0) {
86 		for (i = 0; i < ARRAY_SIZE(tcases); i++) {
87 			if (tcases[i].request == INVAL_IOCTL)
88 				tcases[i].error = EINVAL;
89 		}
90 	}
91 
92 	fd_file = SAFE_OPEN("x", O_CREAT, 0777);
93 }
94 
cleanup(void)95 static void cleanup(void)
96 {
97 	if (fd > 0)
98 		SAFE_CLOSE(fd);
99 
100 	if (fd_file > 0)
101 		SAFE_CLOSE(fd_file);
102 }
103 
104 static struct tst_test test = {
105 	.needs_root = 1,
106 	.needs_tmpdir = 1,
107 	.setup = setup,
108 	.cleanup = cleanup,
109 	.test = verify_ioctl,
110 	.tcnt = ARRAY_SIZE(tcases),
111 	.options = (struct tst_option[]) {
112 		{"D:", &device, "-D <tty device> : for example, /dev/tty[0-9]"},
113 		{}
114 	}
115 };
116