gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/test/syscalls/linux/fuse.cc (about) 1 // Copyright 2023 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include <fcntl.h> 16 #include <linux/capability.h> 17 #include <stdio.h> 18 #include <sys/mount.h> 19 #include <sys/stat.h> 20 #include <unistd.h> 21 22 #include <cerrno> 23 #include <cstdint> 24 #include <cstdlib> 25 #include <string> 26 #include <vector> 27 28 #include "gmock/gmock.h" 29 #include "gtest/gtest.h" 30 #include "absl/strings/str_format.h" 31 #include "absl/strings/string_view.h" 32 #include "test/util/file_descriptor.h" 33 #include "test/util/fs_util.h" 34 #include "test/util/linux_capability_util.h" 35 #include "test/util/posix_error.h" 36 #include "test/util/temp_path.h" 37 #include "test/util/test_util.h" 38 39 namespace gvisor { 40 namespace testing { 41 42 namespace { 43 44 TEST(FuseTest, RejectBadInit) { 45 SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN))); 46 const FileDescriptor fd = 47 ASSERT_NO_ERRNO_AND_VALUE(Open("/dev/fuse", O_RDWR, 0)); 48 49 auto mount_point = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir()); 50 auto mount_opts = 51 absl::StrFormat("fd=%d,user_id=0,group_id=0,rootmode=40000", fd.get()); 52 53 EXPECT_THAT(mount("fuse", mount_point.path().c_str(), "fuse", 54 MS_NODEV | MS_NOSUID, mount_opts.c_str()), 55 SyscallSucceeds()); 56 mount_point.release(); 57 58 struct response { 59 uint32_t len; 60 int32_t err; 61 uint64_t uid; 62 } resp; 63 // min value for length is 24 + sizeof(response) 64 resp.len = 24 + sizeof(resp) - 1; 65 resp.err = 0; 66 resp.uid = 2; 67 68 ASSERT_THAT(write(fd.get(), reinterpret_cast<char*>(&resp), sizeof(resp)), 69 SyscallFailsWithErrno(EINVAL)); 70 } 71 72 TEST(FuseTest, LookupUpdatesInode) { 73 SKIP_IF(absl::NullSafeStringView(getenv("GVISOR_FUSE_TEST")) != "TRUE"); 74 const std::string kFileData = "May thy knife chip and shatter.\n"; 75 TempPath path = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith( 76 GetAbsoluteTestTmpdir(), kFileData, TempPath::kDefaultFileMode)); 77 78 FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(Open(path.path(), O_RDONLY)); 79 std::vector<char> buf(kFileData.size()); 80 ASSERT_THAT(ReadFd(fd.get(), buf.data(), kFileData.size()), 81 SyscallSucceedsWithValue(kFileData.size())); 82 83 ASSERT_THAT(unlink(JoinPath("/fuse", Basename(path.path())).c_str()), 84 SyscallSucceeds()); 85 86 EXPECT_THAT(access(path.path().c_str(), O_RDONLY), 87 SyscallFailsWithErrno(ENOENT)); 88 } 89 90 } // namespace 91 } // namespace testing 92 } // namespace gvisor