Line data Source code
1 : /* 2 : Copyright 2018-2024, Barcelona Supercomputing Center (BSC), Spain 3 : Copyright 2015-2024, Johannes Gutenberg Universitaet Mainz, Germany 4 : 5 : This software was partially supported by the 6 : EC H2020 funded project NEXTGenIO (Project ID: 671951, www.nextgenio.eu). 7 : 8 : This software was partially supported by the 9 : ADA-FS project under the SPPEXA project funded by the DFG. 10 : 11 : This file is part of GekkoFS' POSIX interface. 12 : 13 : GekkoFS' POSIX interface is free software: you can redistribute it and/or 14 : modify it under the terms of the GNU Lesser General Public License as 15 : published by the Free Software Foundation, either version 3 of the License, 16 : or (at your option) any later version. 17 : 18 : GekkoFS' POSIX interface is distributed in the hope that it will be useful, 19 : but WITHOUT ANY WARRANTY; without even the implied warranty of 20 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 : GNU Lesser General Public License for more details. 22 : 23 : You should have received a copy of the GNU Lesser General Public License 24 : along with GekkoFS' POSIX interface. If not, see 25 : <https://www.gnu.org/licenses/>. 26 : 27 : SPDX-License-Identifier: LGPL-3.0-or-later 28 : */ 29 : 30 : // This file uses special C formatting for a better overview 31 : // clang-format off 32 : 33 : #ifndef GKFS_SYSCALL_HPP 34 : #define GKFS_SYSCALL_HPP 35 : 36 : #include <client/syscalls/args.hpp> 37 : #include <client/syscalls/rets.hpp> 38 : #include <client/syscalls/errno.hpp> 39 : #include <client/syscalls/detail/syscall_info.h> 40 : 41 : namespace gkfs::syscall { 42 : 43 : static const auto constexpr MAX_ARGS = 6u; 44 : using arg_list = std::array<arg::desc, MAX_ARGS>; 45 : 46 : struct descriptor : private ::syscall_info { 47 : 48 : long 49 494 : number() const { 50 494 : return s_nr; 51 : } 52 : 53 : const char* 54 1172597 : name() const { 55 1172597 : return s_name; 56 : } 57 : 58 : int 59 7869245 : num_args() const { 60 7869245 : return s_nargs; 61 : } 62 : 63 : arg_list 64 : args() const { 65 : 66 : std::array<arg::desc, MAX_ARGS> args; 67 : 68 23439733 : for(auto i = 0u; i < MAX_ARGS; ++i) { 69 20091173 : args[i] = {static_cast<arg::type>(s_args[i].a_type), 70 20091173 : s_args[i].a_name}; 71 : } 72 : 73 3348560 : return args; 74 : } 75 : 76 : ret::desc 77 2339348 : return_type() const { 78 581193 : return ret::desc{static_cast<ret::type>(s_return_type.r_type)}; 79 : } 80 : }; 81 : 82 : static inline descriptor 83 1758199 : lookup_by_number(const long syscall_number) { 84 1758199 : const auto* info = ::get_syscall_info(syscall_number, nullptr); 85 1758168 : return *reinterpret_cast<const descriptor*>(info); 86 : } 87 : 88 : static inline descriptor 89 1172082 : lookup_by_number(const long syscall_number, const long argv[MAX_ARGS]) { 90 1172082 : const auto* info = ::get_syscall_info(syscall_number, argv); 91 1172082 : return *reinterpret_cast<const descriptor*>(info); 92 : } 93 : 94 : static inline descriptor 95 494 : lookup_by_name(const std::string syscall_name) { 96 494 : const auto* info = ::get_syscall_info_by_name(syscall_name.c_str()); 97 494 : return *reinterpret_cast<const descriptor*>(info); 98 : } 99 : 100 : static inline bool 101 1758212 : never_returns(const long syscall_number) { 102 1758212 : const auto desc = lookup_by_number(syscall_number); 103 1758155 : return desc.return_type() == ret::none; 104 : } 105 : 106 : static inline bool 107 : always_returns(const long syscall_number) { 108 : return !never_returns(syscall_number); 109 : } 110 : 111 : static inline bool 112 1172079 : may_not_return(const long syscall_number) { 113 1172079 : return syscall_number == SYS_execve 114 : #ifdef SYS_execveat 115 1172079 : || syscall_number == SYS_execveat 116 : #endif 117 : ; 118 : } 119 : 120 : 121 : // information about a syscall 122 : enum class info : int { 123 : unknown = 0x00000000, // no info (reset) 124 : 125 : // syscall origin 126 : internal = 0x00000001, // syscall originates from GekkoFS' internals 127 : external = 0x00000002, // syscall originates from client application 128 : 129 : // syscall target 130 : kernel = 0x00000010, // syscall forwarded to the kernel 131 : hook = 0x00000020, // syscall handled by GekkoFS 132 : 133 : // syscall state 134 : executed = 0x00000100, // syscall has been executed 135 : not_executed = 0x00000000, // syscall has not been executed 136 : 137 : // masks 138 : origin_mask = 0x00000003, // mask for syscall's origin information 139 : target_mask = 0x7ffffefc, // mask for syscall's target information 140 : execution_mask = 0x00000100 // mask for syscall's execution state 141 : }; 142 : 143 : 144 : inline constexpr info 145 4101642 : operator&(info t1, info t2) { 146 4101642 : return info(static_cast<int>(t1) & static_cast<int>(t2)); 147 : } 148 : 149 : inline constexpr info 150 10773511 : operator|(info t1, info t2) { 151 10773511 : return info(static_cast<int>(t1) | static_cast<int>(t2)); 152 : } 153 : 154 : inline constexpr info 155 : operator^(info t1, info t2) { 156 : return info(static_cast<int>(t1) ^ static_cast<int>(t2)); 157 : } 158 : 159 : inline constexpr info 160 : operator~(info t1) { 161 : return info(~static_cast<int>(t1)); 162 : } 163 : 164 : inline const info& 165 : operator|=(info& t1, info t2) { 166 : return t1 = t1 | t2; 167 : } 168 : 169 : inline const info& 170 : operator&=(info& t1, info t2) { 171 : return t1 = t1 & t2; 172 : } 173 : 174 : inline const info& 175 : operator^=(info& t1, info t2) { 176 : return t1 = t1 ^ t2; 177 : } 178 : 179 : 180 : static const auto constexpr no_info = info::unknown; 181 : static const auto constexpr from_internal_code = info::internal; 182 : static const auto constexpr from_external_code = info::external; 183 : static const auto constexpr to_kernel = info::kernel; 184 : static const auto constexpr to_hook = info::hook; 185 : 186 : static const auto constexpr executed = info::executed; 187 : static const auto constexpr not_executed = info::not_executed; 188 : 189 : static const auto constexpr origin_mask = info::origin_mask; 190 : static const auto constexpr target_mask = info::target_mask; 191 : static const auto constexpr execution_mask = info::execution_mask; 192 : 193 : enum { 194 : hooked = 0x0, 195 : forward_to_kernel = 0x1 196 : }; 197 : 198 : static constexpr auto 199 1172097 : origin(syscall::info info) { 200 1172097 : return info & origin_mask; 201 : } 202 : 203 : static constexpr auto 204 1172097 : target(syscall::info info) { 205 1172097 : return info & target_mask; 206 : } 207 : 208 : static constexpr bool 209 : is_handled_by_kernel(syscall::info info) { 210 : return (info & target_mask) == to_kernel; 211 : } 212 : 213 : static constexpr auto 214 1757448 : execution_is_pending(syscall::info info) { 215 1757448 : return (info & execution_mask) == not_executed; 216 : } 217 : 218 : /* 219 : * error_code - examines a return value from a syscall execution 220 : * and returns an error code if said return value indicates an error. 221 : */ 222 : static inline int 223 586168 : error_code(long result) { 224 586168 : if(result < 0 && result >= -0x1000) 225 4976 : return (int) -result; 226 : 227 : return 0; 228 : } 229 : 230 : } // namespace gkfs::syscall 231 : 232 : #endif // GKFS_SYSCALL_HPP 233 : 234 : // clang-format on