From nobody Thu May 12 20:37:58 2022 X-Original-To: dev-commits-src-branches@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 595E51AC8E19; Thu, 12 May 2022 20:37:58 +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 4Kzk9y221Wz4hJH; Thu, 12 May 2022 20:37:58 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1652387878; 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=Dqz5/7laui9zsbT4LptsobB29+wAZxApga6X7CdK1QM=; b=f8imEQ2d4SAWAknxWf6od28Td1mf27yCtV/Ejvd2743ZLWjHF7X3bHwRsaZQsXJFCW2mJu mr8Fe7YQ8WfIeDry65mxF8L4hbHckDofDSk3iBYc7RHVVxQ0wBTjtn8si4nm02/sF78y8/ wu72o7+pJ+92NrZB8CiVTL1QsEYiyM07+v8vQphYZ2egcNaqJeiJCJf4NrVcxSXueM1/Pn 7HW96VwjXXpy4L0R2p4IU/aWzztGGztsOEMxDkUr3caSsQ58jzE1MdMEoaHkIkGPdQ/8Wp fb4TtZBray3FT3L50lGtLQqqDTF/cwFsx8AOYhzTyx/j1efV7DcmIKVNhBcZig== 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 1B5DD150FD; Thu, 12 May 2022 20:37:58 +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 24CKbw9i030472; Thu, 12 May 2022 20:37:58 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 24CKbw24030471; Thu, 12 May 2022 20:37:58 GMT (envelope-from git) Date: Thu, 12 May 2022 20:37:58 GMT Message-Id: <202205122037.24CKbw24030471@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: ef0e12d5656a - stable/13 - fusefs: validate servers' error values List-Id: Commits to the stable branches of the FreeBSD src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-branches List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-branches@freebsd.org X-BeenThere: dev-commits-src-branches@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/13 X-Git-Reftype: branch X-Git-Commit: ef0e12d5656ad471dcc93a15c63a6af0d1d62bd9 Auto-Submitted: auto-generated ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1652387878; 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=Dqz5/7laui9zsbT4LptsobB29+wAZxApga6X7CdK1QM=; b=OOvwsa0zEKjpU2Uk7U1ovwx5enS8WH42YxsWQ6fqbvKzeOVeLpakAa7YBop/hZh6gv90cN +RrTdfNMzXA/C83OzNbEEsk2YSTtnW4eEHsY60R7QWM+vn8U7nunBHPBeSw/j2sZUww3gq t2owxmObPU5nrqxj1mJ3R/yeyUajjRwi1stB+BQocDN40Pjc7fAF66MDn9QRLsdXqHh1Ga UogWorQPk2sQqfSHrBjgsyv1dLXbOhIVxkkpIWQ1W3INPJ94/ea17e6sQvzVE2s01O3Qxp b8A3aw06VV5Bqr7Wax8oU5O/FPY+9EdYkLmqieAf40ycANH2QDVU7Jb4TZYBzA== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1652387878; a=rsa-sha256; cv=none; b=w2oMdgOpEAV/ap1tqRVIhK060n5t9y0wQGSKy+Bfu6bM9pXCGnPmQAGbDa5QZ2TXYHeKeq uPHaHGt+lruD4C29S5gccrdXCfoXw5GcCemG5GkC0l06xy50bUAwZPpJMLEHF7McFsCQAW 370mCuTqZFFnVtZ7v5cdWnGRcCBun2CpVR0FKzhj7H5uQB5AC0bk2rPPgeV0dwm3V71tPH 4CH68nOZoHtlYNcS7c9tLEbu8ciLvaDwXqjb5JPEMgIQLO3XjadGsUrbasDar9A0TlQCNM 6eVByEwtMSwF+v5Ro1q+BAPw28xdhPUNdCDksmqJRSbR23AGs8577Cyg6wlWXA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none X-ThisMailContainsUnwantedMimeParts: N The branch stable/13 has been updated by asomers: URL: https://cgit.FreeBSD.org/src/commit/?id=ef0e12d5656ad471dcc93a15c63a6af0d1d62bd9 commit ef0e12d5656ad471dcc93a15c63a6af0d1d62bd9 Author: Alan Somers AuthorDate: 2022-04-15 19:04:24 +0000 Commit: Alan Somers CommitDate: 2022-05-12 20:37:24 +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 157c3802ec7e..7d1afb88edb7 100644 --- a/sys/fs/fuse/fuse_device.c +++ b/sys/fs/fuse/fuse_device.c @@ -518,8 +518,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 231f46b18aba..ddfb5527ef13 100644 --- a/tests/sys/fs/fusefs/mockfs.cc +++ b/tests/sys/fs/fusefs/mockfs.cc @@ -418,6 +418,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 = MIN(max_write, max_max_write); @@ -779,6 +780,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) @@ -1011,7 +1013,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 e35f2efb8dae..d471491ea455 100644 --- a/tests/sys/fs/fusefs/mockfs.hh +++ b/tests/sys/fs/fusefs/mockfs.hh @@ -340,6 +340,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 508c3af2828f..65738f4b19a4 100644 --- a/tests/sys/fs/fusefs/utils.cc +++ b/tests/sys/fs/fusefs/utils.cc @@ -217,7 +217,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;