From nobody Sat Aug 20 00:54:37 2022 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4M8gBP2X8vz4YgQT; Sat, 20 Aug 2022 00:54:37 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4M8gBP23KJz45CQ; Sat, 20 Aug 2022 00:54:37 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1660956877; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=Y6xhxAEvP7ffiBU6hA7+P845XrhsGstdjlh5JzBu+F0=; b=AiCfcV/tckD8VF51PVDvxKuHzXgoMYIsYid02sicNpDC5R2tjnLtpun4mNxayANY/SLiyb djaVLKH0QXQ7oFT65kTWaQyIV8AVjamIfIQGSj4DIUp9aEzxleNlcfiLyiV0zPSI98vw4Z kk0X0OnhpP+2gCd8ezLq9eH5hlU9fOVtsEfAjzxAJ3EO/cXnddlTPpvjwZ3D4ubp7k4v/m YJZ2mS4CoPyUs/zTl2zwLfr1q8qk4YJAzK0FtFx7vuioSd483Oi/37wAppxfUbV/SjDhvh 6qH/nUuMG5//xcK4R9jLcKYYac9j7S18WOt1fKBBI8wBFQPrcTNAQglcpKyZpg== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4M8gBP15nfz1CMH; Sat, 20 Aug 2022 00:54:37 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 27K0sbt5080686; Sat, 20 Aug 2022 00:54:37 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 27K0sbm7080685; Sat, 20 Aug 2022 00:54:37 GMT (envelope-from git) Date: Sat, 20 Aug 2022 00:54:37 GMT Message-Id: <202208200054.27K0sbm7080685@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Alan Somers Subject: git: 73e02a370e52 - stable/12 - fusefs: validate servers' error values List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-all@freebsd.org X-BeenThere: dev-commits-src-all@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: asomers X-Git-Repository: src X-Git-Refname: refs/heads/stable/12 X-Git-Reftype: branch X-Git-Commit: 73e02a370e524eb1e5719d9c37098e29c0d9be78 Auto-Submitted: auto-generated ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1660956877; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=Y6xhxAEvP7ffiBU6hA7+P845XrhsGstdjlh5JzBu+F0=; b=OOoMqEx3Rpim5z4BL2KM6s2Ud2MxA16ruPCyE5iN1vLE/uFXXrSIIBZMMZnMjNa+d2QMcO jw6Rpu6il6bimqmbaJp7rLEBN93MxL0b3FyKoXfKgavp5H0eJhRVvbDMjase4CkAj8qkEI w/Yma+AX1CdjTLczLWpAc9UBURmCNoCLpju6JB3SIq8j+08dyIGZS6H5f601aPyP0194gx +S8F600QnZ8dejyYIWN8KsMhwu7qqsK5Pxqd82bb41zVwXt03Usi+6SqWfmXCUwyZHvEJq E7tSP144tqBm8/vKLdZ1vmJWzb6qZgKa6e0uCZXAlCpqB8+jgHzJnAdcdRk1Ag== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1660956877; a=rsa-sha256; cv=none; b=V1pHpmFbw5EfqYzj5dpwBsNsnbFtUya5DgTU5fj7IHfsPtcOjghAI7E3O+T+c6OFPcELcL hcyFFXZSEE4sWn9ARrkL48ms/oNkLafYm9rZ8ib8fRCR+bvQwyPZNFJ9ulnXv7Z+tYhWNz kbWA3OhLEMZnCoV079GpccQKZfWHLd4ouTloAXPkTzT1LeJRYI69mVrz1kDxUmPtw7dGzs 2Y11UhZ9MMfBOzKuQCVLfZVUJ0W2R89yBE3zlF4DV8f16B5aYmh4ZU0NIUQk4j+gbEPbsI jTMi/wAg5dC9VJD9wTnYkVk7bjC5QyUwEpmfNWOby8xLPCfRz3WnD3JGszSK8g== ARC-Authentication-Results: i=1; mx1.freebsd.org; none X-ThisMailContainsUnwantedMimeParts: N The branch stable/12 has been updated by asomers: URL: https://cgit.FreeBSD.org/src/commit/?id=73e02a370e524eb1e5719d9c37098e29c0d9be78 commit 73e02a370e524eb1e5719d9c37098e29c0d9be78 Author: Alan Somers AuthorDate: 2022-04-15 19:04:24 +0000 Commit: Alan Somers CommitDate: 2022-08-20 00:49:23 +0000 fusefs: validate servers' error values Formerly fusefs would pass up the stack any error value returned by the fuse server. However, some values aren't valid for userland, but have special meanings within the kernel. One of these, EJUSTRETURN, could cause a kernel page fault if the server returned it in response to FUSE_LOOKUP. Fix by validating all errors returned by the server. Also, fix a data lifetime bug in the FUSE_DESTROY test. PR: 263220 Reported by: Robert Morris Sponsored by: Axcient Reviewed by: emaste Differential Revision: https://reviews.freebsd.org/D34931 (cherry picked from commit 155ac516c60f20573d15c54bafabfd0e52d21fa6) --- sys/fs/fuse/fuse_device.c | 14 ++++++++++++-- tests/sys/fs/fusefs/lookup.cc | 21 +++++++++++++++++++++ tests/sys/fs/fusefs/mockfs.cc | 9 ++++++++- tests/sys/fs/fusefs/mockfs.hh | 3 +++ tests/sys/fs/fusefs/utils.cc | 2 +- 5 files changed, 45 insertions(+), 4 deletions(-) diff --git a/sys/fs/fuse/fuse_device.c b/sys/fs/fuse/fuse_device.c index c634f903e519..3368041edebc 100644 --- a/sys/fs/fuse/fuse_device.c +++ b/sys/fs/fuse/fuse_device.c @@ -505,8 +505,18 @@ fuse_device_write(struct cdev *dev, struct uio *uio, int ioflag) "pass ticket to a callback"); /* Sanitize the linuxism of negative errnos */ ohead.error *= -1; - memcpy(&tick->tk_aw_ohead, &ohead, sizeof(ohead)); - err = tick->tk_aw_handler(tick, uio); + if (ohead.error < 0 || ohead.error > ELAST) { + /* Illegal error code */ + ohead.error = EIO; + memcpy(&tick->tk_aw_ohead, &ohead, + sizeof(ohead)); + tick->tk_aw_handler(tick, uio); + err = EINVAL; + } else { + memcpy(&tick->tk_aw_ohead, &ohead, + sizeof(ohead)); + err = tick->tk_aw_handler(tick, uio); + } } else { /* pretender doesn't wanna do anything with answer */ SDT_PROBE2(fusefs, , device, trace, 1, diff --git a/tests/sys/fs/fusefs/lookup.cc b/tests/sys/fs/fusefs/lookup.cc index 32e2a08eb949..0ec02913f66a 100644 --- a/tests/sys/fs/fusefs/lookup.cc +++ b/tests/sys/fs/fusefs/lookup.cc @@ -276,6 +276,27 @@ TEST_F(Lookup, dotdot_no_parent_nid) EXPECT_EQ(ESTALE, errno); } +/* + * A daemon that returns an illegal error value should be handled gracefully. + * Regression test for https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=263220 + */ +TEST_F(Lookup, ejustreturn) +{ + const char FULLPATH[] = "mountpoint/does_not_exist"; + const char RELPATH[] = "does_not_exist"; + + EXPECT_LOOKUP(FUSE_ROOT_ID, RELPATH) + .WillOnce(Invoke(ReturnImmediate([=](auto in __unused, auto& out) { + out.header.len = sizeof(out.header); + out.header.error = 2; + m_mock->m_expected_write_errno = EINVAL; + }))); + + EXPECT_NE(0, access(FULLPATH, F_OK)); + + EXPECT_EQ(EIO, errno); +} + TEST_F(Lookup, enoent) { const char FULLPATH[] = "mountpoint/does_not_exist"; diff --git a/tests/sys/fs/fusefs/mockfs.cc b/tests/sys/fs/fusefs/mockfs.cc index 4266d6be214c..ab1b98729e59 100644 --- a/tests/sys/fs/fusefs/mockfs.cc +++ b/tests/sys/fs/fusefs/mockfs.cc @@ -363,6 +363,7 @@ MockFS::MockFS(int max_readahead, bool allow_other, bool default_permissions, const bool trueval = true; m_daemon_id = NULL; + m_expected_write_errno = 0; m_kernel_minor_version = kernel_minor_version; m_maxreadahead = max_readahead; m_maxwrite = max_write; @@ -708,6 +709,7 @@ void MockFS::loop() { bzero(in.get(), sizeof(*in)); read_request(*in, buflen); + m_expected_write_errno = 0; if (m_quit) break; if (verbosity > 0) @@ -940,7 +942,12 @@ void MockFS::write_response(const mockfs_buf_out &out) { FAIL() << "not yet implemented"; } r = write(m_fuse_fd, &out, out.header.len); - ASSERT_TRUE(r > 0 || errno == EAGAIN) << strerror(errno); + if (m_expected_write_errno) { + ASSERT_EQ(-1, r); + ASSERT_EQ(m_expected_write_errno, errno) << strerror(errno); + } else { + ASSERT_TRUE(r > 0 || errno == EAGAIN) << strerror(errno); + } } void* MockFS::service(void *pthr_data) { diff --git a/tests/sys/fs/fusefs/mockfs.hh b/tests/sys/fs/fusefs/mockfs.hh index 391606704371..16ccb81ab891 100644 --- a/tests/sys/fs/fusefs/mockfs.hh +++ b/tests/sys/fs/fusefs/mockfs.hh @@ -319,6 +319,9 @@ class MockFS { /* pid of child process, for two-process test cases */ pid_t m_child_pid; + /* the expected errno of the next write to /dev/fuse */ + int m_expected_write_errno; + /* Maximum size of a FUSE_WRITE write */ uint32_t m_maxwrite; diff --git a/tests/sys/fs/fusefs/utils.cc b/tests/sys/fs/fusefs/utils.cc index d5ac580dc8ae..3674471226a5 100644 --- a/tests/sys/fs/fusefs/utils.cc +++ b/tests/sys/fs/fusefs/utils.cc @@ -218,7 +218,7 @@ FuseTest::expect_destroy(int error) return (in.header.opcode == FUSE_DESTROY); }, Eq(true)), _) - ).WillOnce(Invoke( ReturnImmediate([&](auto in, auto& out) { + ).WillOnce(Invoke(ReturnImmediate([=](auto in, auto& out) { m_mock->m_quit = true; out.header.len = sizeof(out.header); out.header.unique = in.header.unique;