xref: /freebsd/tests/sys/fs/fusefs/bad_server.cc (revision b3e7694832e81d7a904a10f525f8797b753bf0d3)
15f51c9c3SAlan Somers /*-
2*4d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
35f51c9c3SAlan Somers  *
45f51c9c3SAlan Somers  * Copyright (c) 2023 Axcient
55f51c9c3SAlan Somers  *
65f51c9c3SAlan Somers  * Redistribution and use in source and binary forms, with or without
75f51c9c3SAlan Somers  * modification, are permitted provided that the following conditions
85f51c9c3SAlan Somers  * are met:
95f51c9c3SAlan Somers  * 1. Redistributions of source code must retain the above copyright
105f51c9c3SAlan Somers  *    notice, this list of conditions and the following disclaimer.
115f51c9c3SAlan Somers  * 2. Redistributions in binary form must reproduce the above copyright
125f51c9c3SAlan Somers  *    notice, this list of conditions and the following disclaimer in the
135f51c9c3SAlan Somers  *    documentation and/or other materials provided with the distribution.
145f51c9c3SAlan Somers  *
155f51c9c3SAlan Somers  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
165f51c9c3SAlan Somers  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
175f51c9c3SAlan Somers  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
185f51c9c3SAlan Somers  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
195f51c9c3SAlan Somers  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
205f51c9c3SAlan Somers  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
215f51c9c3SAlan Somers  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
225f51c9c3SAlan Somers  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
235f51c9c3SAlan Somers  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
245f51c9c3SAlan Somers  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
255f51c9c3SAlan Somers  * SUCH DAMAGE.
265f51c9c3SAlan Somers  */
275f51c9c3SAlan Somers 
285f51c9c3SAlan Somers extern "C" {
295f51c9c3SAlan Somers #include <fcntl.h>
305f51c9c3SAlan Somers #include <unistd.h>
315f51c9c3SAlan Somers }
325f51c9c3SAlan Somers 
335f51c9c3SAlan Somers #include "mockfs.hh"
345f51c9c3SAlan Somers #include "utils.hh"
355f51c9c3SAlan Somers 
365f51c9c3SAlan Somers using namespace testing;
375f51c9c3SAlan Somers 
385f51c9c3SAlan Somers class BadServer: public FuseTest {};
395f51c9c3SAlan Somers 
405f51c9c3SAlan Somers /*
415f51c9c3SAlan Somers  * If the server sends a response for an unknown request, the kernel should
425f51c9c3SAlan Somers  * gracefully return EINVAL.
435f51c9c3SAlan Somers  */
TEST_F(BadServer,UnknownUnique)445f51c9c3SAlan Somers TEST_F(BadServer, UnknownUnique)
455f51c9c3SAlan Somers {
465f51c9c3SAlan Somers 	mockfs_buf_out out;
475f51c9c3SAlan Somers 
485f51c9c3SAlan Somers 	out.header.len = sizeof(out.header);
495f51c9c3SAlan Somers 	out.header.error = 0;
505f51c9c3SAlan Somers 	out.header.unique = 99999;		// Invalid!
515f51c9c3SAlan Somers 	out.expected_errno = EINVAL;
525f51c9c3SAlan Somers 	m_mock->write_response(out);
535f51c9c3SAlan Somers }
545f51c9c3SAlan Somers 
555f51c9c3SAlan Somers /*
565f51c9c3SAlan Somers  * If the server sends less than a header's worth of data, the kernel should
575f51c9c3SAlan Somers  * gracefully return EINVAL.
585f51c9c3SAlan Somers  */
TEST_F(BadServer,ShortWrite)595f51c9c3SAlan Somers TEST_F(BadServer, ShortWrite)
605f51c9c3SAlan Somers {
615f51c9c3SAlan Somers 	mockfs_buf_out out;
625f51c9c3SAlan Somers 
635f51c9c3SAlan Somers 	out.header.len = sizeof(out.header) - 1;
645f51c9c3SAlan Somers 	out.header.error = 0;
655f51c9c3SAlan Somers 	out.header.unique = 0;			// Asynchronous notification
665f51c9c3SAlan Somers 	out.expected_errno = EINVAL;
675f51c9c3SAlan Somers 	m_mock->write_response(out);
685f51c9c3SAlan Somers }
695f51c9c3SAlan Somers 
705f51c9c3SAlan Somers /*
715f51c9c3SAlan Somers  * It is illegal to report an error, and also send back a payload.
725f51c9c3SAlan Somers  */
TEST_F(BadServer,ErrorWithPayload)735f51c9c3SAlan Somers TEST_F(BadServer, ErrorWithPayload)
745f51c9c3SAlan Somers {
755f51c9c3SAlan Somers 	const char FULLPATH[] = "mountpoint/some_file.txt";
765f51c9c3SAlan Somers 	const char RELPATH[] = "some_file.txt";
775f51c9c3SAlan Somers 
785f51c9c3SAlan Somers 	EXPECT_LOOKUP(FUSE_ROOT_ID, RELPATH)
795f51c9c3SAlan Somers 	.WillOnce(Invoke([&](auto in, auto &out) {
805f51c9c3SAlan Somers 		// First send an invalid response
815f51c9c3SAlan Somers 		std::unique_ptr<mockfs_buf_out> out0(new mockfs_buf_out);
825f51c9c3SAlan Somers 		out0->header.unique = in.header.unique;
835f51c9c3SAlan Somers 		out0->header.error = -ENOENT;
845f51c9c3SAlan Somers 		SET_OUT_HEADER_LEN(*out0, entry);	// Invalid!
855f51c9c3SAlan Somers 		out0->expected_errno = EINVAL;
865f51c9c3SAlan Somers 		out.push_back(std::move(out0));
875f51c9c3SAlan Somers 
885f51c9c3SAlan Somers 		// Then, respond to the lookup so we can complete the test
895f51c9c3SAlan Somers 		std::unique_ptr<mockfs_buf_out> out1(new mockfs_buf_out);
905f51c9c3SAlan Somers 		out1->header.unique = in.header.unique;
915f51c9c3SAlan Somers 		out1->header.error = -ENOENT;
925f51c9c3SAlan Somers 		out1->header.len = sizeof(out1->header);
935f51c9c3SAlan Somers 		out.push_back(std::move(out1));
945f51c9c3SAlan Somers 
955f51c9c3SAlan Somers 		// The kernel may disconnect us for bad behavior, so don't try
965f51c9c3SAlan Somers 		// to read any more.
975f51c9c3SAlan Somers 		m_mock->m_quit = true;
985f51c9c3SAlan Somers 	}));
995f51c9c3SAlan Somers 
1005f51c9c3SAlan Somers 	EXPECT_NE(0, access(FULLPATH, F_OK));
1015f51c9c3SAlan Somers 
1025f51c9c3SAlan Somers 	EXPECT_EQ(ENOENT, errno);
1035f51c9c3SAlan Somers }
104