1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright (C) Bull S.A. 2001
4 * Copyright (c) International Business Machines  Corp., 2001
5 * 07/2001 Ported by Wayne Boyer
6 * 05/2002 Ported by Jacky Malcles
7 */
8
9/*\
10 * [Description]
11 *
12 * Tests readv() failures:
13 *
14 * - EINVAL the sum of the iov_len values overflows an ssize_t value
15 * - EFAULT buffer is outside the accessible address space
16 * - EINVAL the vector count iovcnt is less than zero
17 * - EISDIR the file descriptor is a directory
18 * - EBADF  the file descriptor is not valid
19 */
20
21#include <sys/uio.h>
22#include "tst_test.h"
23
24#define K_1     1024
25#define MODES   0700
26
27#define CHUNK           64
28
29static int badfd = -1;
30static int fd_dir, fd_file;
31static char buf1[K_1];
32const char *TEST_DIR = "test_dir";
33const char *TEST_FILE = "test_file";
34
35static struct iovec invalid_iovec[] = {
36	{buf1, -1},
37	{buf1 + CHUNK, CHUNK},
38	{buf1 + 2*CHUNK, CHUNK},
39};
40
41static struct iovec large_iovec[] = {
42	{buf1, K_1},
43	{buf1 + CHUNK, K_1},
44	{buf1 + CHUNK*2, K_1},
45};
46
47static struct iovec efault_iovec[] = {
48	{NULL, CHUNK},
49	{buf1 + CHUNK, CHUNK},
50	{buf1 + 2*CHUNK, CHUNK},
51};
52
53static struct iovec valid_iovec[] = {
54	{buf1, CHUNK},
55};
56
57static struct tcase {
58	int *fd;
59	void *buf;
60	int count;
61	int exp_error;
62} tcases[] = {
63	{&fd_file, invalid_iovec, 1, EINVAL},
64	{&fd_file, efault_iovec, 3, EFAULT},
65	{&fd_file, large_iovec, -1, EINVAL},
66	{&fd_dir, valid_iovec, 1, EISDIR},
67	{&badfd, valid_iovec, 3, EBADF},
68};
69
70static void verify_readv(unsigned int n)
71{
72	struct tcase *tc = &tcases[n];
73
74	TST_EXP_FAIL2(readv(*tc->fd, tc->buf, tc->count), tc->exp_error,
75		"readv(%d, %p, %d)", *tc->fd, tc->buf, tc->count);
76}
77
78static void setup(void)
79{
80	SAFE_FILE_PRINTF(TEST_FILE, "test");
81
82	fd_file = SAFE_OPEN(TEST_FILE, O_RDONLY);
83
84	efault_iovec[0].iov_base = tst_get_bad_addr(NULL);
85
86	SAFE_MKDIR(TEST_DIR, MODES);
87	fd_dir = SAFE_OPEN(TEST_DIR, O_RDONLY);
88}
89
90static void cleanup(void)
91{
92	if (fd_file > 0)
93		SAFE_CLOSE(fd_file);
94
95	if (fd_dir > 0)
96		SAFE_CLOSE(fd_dir);
97}
98
99static struct tst_test test = {
100	.tcnt = ARRAY_SIZE(tcases),
101	.needs_tmpdir = 1,
102	.setup = setup,
103	.cleanup = cleanup,
104	.test = verify_readv,
105};
106