From nobody Fri Apr 15 19:58:22 2022 X-Original-To: dev-commits-src-main@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 855A42DB89E; Fri, 15 Apr 2022 19:58:22 +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 4Kg6Zk3LyKz4lnK; Fri, 15 Apr 2022 19:58:22 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1650052702; 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=54C+hWSPveIyoTIuuFoWt06y3pgfIQQv/tn/0AiKND0=; b=t2ziL/rFbbOgdr8DMhyfrwaXWObJH+Nco2ZbEIg8Fev2E0QeK7fgGTFdK8YndRd7+rrj0p Ega9qsrdPa5LEIfxYveeRuFeBMd5EJUbhC9NDXr52WfeICcBwBPrsjiKBq5fZaXlcF6Rd0 zUf9sKLo0jBRqmP5MBfGN8KmEEJbbQ8kgTc9eMzlup4HHtK9/t8lQG16G+gW9e2Stv6T03 3RHqgNdblY6281eKGAQQm/ULDrYFtuw69zuW6cmNT6SvXXAESuNUAFemUSKs/tIe8nFY0u UWul4u3eVwZsgwtKe3MZisKQpSTAN1PNYu7BffPEPpKbIgaz49UXsxNc61W6uw== 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 4FF251B6DE; Fri, 15 Apr 2022 19:58:22 +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 23FJwM9a010518; Fri, 15 Apr 2022 19:58:22 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 23FJwMkC010517; Fri, 15 Apr 2022 19:58:22 GMT (envelope-from git) Date: Fri, 15 Apr 2022 19:58:22 GMT Message-Id: <202204151958.23FJwMkC010517@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Alan Somers Subject: git: 155ac516c60f - main - fusefs: validate servers' error values List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-main@freebsd.org X-BeenThere: dev-commits-src-main@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/main X-Git-Reftype: branch X-Git-Commit: 155ac516c60f20573d15c54bafabfd0e52d21fa6 Auto-Submitted: auto-generated ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1650052702; 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=54C+hWSPveIyoTIuuFoWt06y3pgfIQQv/tn/0AiKND0=; b=kTJbXspAz4V9UFyDP1KrNxIwKD00HmAPloJdaxdOSogZXz8ZX6JLkHcVO0EqYVh96hjdsh rgJSHelJRRB8hONtzka5FeOerca39OpcS4Z1ag7OMRX4CqDPEKsmepPHlL/eQIAqU/ZlnE PXoMhxi0J5M2rXshOV11LGbvgf8LWn1AeNlQOhOQ33ZbeTXg6ZddkgV74ASmaL5vEx8QqL BsVQL5EUvlg7hK9tq1Pl3eCXVkj/hrNcPLGBHSSZwdDO9Bg+3TolOQREDx4vEmdXyTlT3B +6Lh64B5ocPxENt5z2FXYiugaOco6UxaA48RgXVR0WKV6QYVei8528+ZDx0YPQ== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1650052702; a=rsa-sha256; cv=none; b=schnDAxWW0AKZayjkaivplQL9LihmbxOHDlGncHcRiA6IFiE+L8vrh8R7RSvp3xBQMYQCM VYQYutdnTGein+eKZbLryqGMKHkZ9QxG012VP1CZOK4naefx3psTmmmdB/DAl33mLuKnPH z9XD3SRZYtu7vLVrhtGlvkTwqrODD+qr4Hr0KJ7Hty5Ydg2HjLFbO9Jr2Vr+/Gx0koUm/j 3w/nzT9X4ijrSX1LhMiImkQ20MwhGeEk/rXbzs192K6cCc30svcTwTw7TfR3sb5briM16R Y9e7/khIa97XL0HqEfFNEPlPMjyb63aZ/se8/jPKAi5VgXpqWzqewc0Pnk/krQ== ARC-Authentication-Results: i=1; mx1.freebsd.org; none X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by asomers: URL: https://cgit.FreeBSD.org/src/commit/?id=155ac516c60f20573d15c54bafabfd0e52d21fa6 commit 155ac516c60f20573d15c54bafabfd0e52d21fa6 Author: Alan Somers AuthorDate: 2022-04-15 19:04:24 +0000 Commit: Alan Somers CommitDate: 2022-04-15 19:57:32 +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 MFC after: 3 weeks Sponsored by: Axcient Reviewed by: emaste Differential Revision: https://reviews.freebsd.org/D34931 --- 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;