1/*
2 * Copyright(c) 2016 Fujitsu Ltd.
3 * Author: Xiao Yang <yangx.jy@cn.fujitsu.com>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it would be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 *
13 * You should have received a copy of the GNU General Public License
14 * alone with this program.
15 */
16
17/*
18 * Test Name: sendto02
19 *
20 * Description:
21 * When sctp protocol is selected in socket(2) and buffer is invalid,
22 * sendto(2) should fail and set errno to EFAULT, but it sets errno
23 * to ENOMEM.
24 *
25 * This is a regression test and has been fixed by kernel commit:
26 * 6e51fe7572590d8d86e93b547fab6693d305fd0d (sctp: fix -ENOMEM result
27 * with invalid user space pointer in sendto() syscall)
28 */
29
30#include <errno.h>
31#include <string.h>
32#include <unistd.h>
33#include <sys/types.h>
34#include <sys/socket.h>
35#include <netinet/in.h>
36
37#include "tst_test.h"
38
39#ifndef IPPROTO_SCTP
40# define IPPROTO_SCTP	132
41#endif
42
43static int sockfd;
44static struct sockaddr_in sa;
45
46static void setup(void)
47{
48	sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP);
49	if (sockfd == -1) {
50		if (errno == EPROTONOSUPPORT)
51			tst_brk(TCONF, "sctp protocol was not supported");
52		else
53			tst_brk(TBROK | TERRNO, "socket() failed with sctp");
54	}
55
56	memset(&sa, 0, sizeof(sa));
57	sa.sin_family = AF_INET;
58	sa.sin_addr.s_addr = inet_addr("127.0.0.1");
59	sa.sin_port = htons(11111);
60}
61
62static void cleanup(void)
63{
64	if (sockfd > 0)
65		SAFE_CLOSE(sockfd);
66}
67
68static void verify_sendto(void)
69{
70	TEST(sendto(sockfd, NULL, 1, 0, (struct sockaddr *) &sa, sizeof(sa)));
71	if (TEST_RETURN != -1) {
72		tst_res(TFAIL, "sendto(fd, NULL, ...) succeeded unexpectedly");
73		return;
74	}
75
76	if (TEST_ERRNO == EFAULT) {
77		tst_res(TPASS | TTERRNO,
78			"sendto(fd, NULL, ...) failed expectedly");
79		return;
80	}
81
82	tst_res(TFAIL | TTERRNO,
83		"sendto(fd, NULL, ...) failed unexpectedly, expected EFAULT");
84}
85
86static struct tst_test test = {
87	.tid = "sendto02",
88	.setup = setup,
89	.cleanup = cleanup,
90	.test_all = verify_sendto,
91};
92