socket.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <Kernel/FileSystem/OpenFileDescription.h>
  7. #include <Kernel/Net/LocalSocket.h>
  8. #include <Kernel/Process.h>
  9. #include <Kernel/UnixTypes.h>
  10. namespace Kernel {
  11. #define REQUIRE_PROMISE_FOR_SOCKET_DOMAIN(domain) \
  12. do { \
  13. if (domain == AF_INET) \
  14. TRY(require_promise(Pledge::inet)); \
  15. else if (domain == AF_LOCAL) \
  16. TRY(require_promise(Pledge::unix)); \
  17. } while (0)
  18. static void setup_socket_fd(Process::OpenFileDescriptions& fds, int fd, NonnullRefPtr<OpenFileDescription> description, int type)
  19. {
  20. description->set_readable(true);
  21. description->set_writable(true);
  22. unsigned flags = 0;
  23. if (type & SOCK_CLOEXEC)
  24. flags |= FD_CLOEXEC;
  25. if (type & SOCK_NONBLOCK)
  26. description->set_blocking(false);
  27. fds[fd].set(*description, flags);
  28. }
  29. ErrorOr<FlatPtr> Process::sys$socket(int domain, int type, int protocol)
  30. {
  31. VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
  32. REQUIRE_PROMISE_FOR_SOCKET_DOMAIN(domain);
  33. if ((type & SOCK_TYPE_MASK) == SOCK_RAW && !is_superuser())
  34. return EACCES;
  35. return m_fds.with_exclusive([&](auto& fds) -> ErrorOr<FlatPtr> {
  36. auto fd_allocation = TRY(fds.allocate());
  37. auto socket = TRY(Socket::create(domain, type, protocol));
  38. auto description = TRY(OpenFileDescription::try_create(socket));
  39. setup_socket_fd(fds, fd_allocation.fd, move(description), type);
  40. return fd_allocation.fd;
  41. });
  42. }
  43. ErrorOr<FlatPtr> Process::sys$bind(int sockfd, Userspace<sockaddr const*> address, socklen_t address_length)
  44. {
  45. VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
  46. return m_fds.with_exclusive([&](auto& fds) -> ErrorOr<FlatPtr> {
  47. auto description = TRY(fds.open_file_description(sockfd));
  48. if (!description->is_socket())
  49. return ENOTSOCK;
  50. auto& socket = *description->socket();
  51. REQUIRE_PROMISE_FOR_SOCKET_DOMAIN(socket.domain());
  52. TRY(socket.bind(address, address_length));
  53. return 0;
  54. });
  55. }
  56. ErrorOr<FlatPtr> Process::sys$listen(int sockfd, int backlog)
  57. {
  58. VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
  59. if (backlog < 0)
  60. return EINVAL;
  61. auto description = TRY(open_file_description(sockfd));
  62. if (!description->is_socket())
  63. return ENOTSOCK;
  64. auto& socket = *description->socket();
  65. REQUIRE_PROMISE_FOR_SOCKET_DOMAIN(socket.domain());
  66. if (socket.is_connected())
  67. return EINVAL;
  68. TRY(socket.listen(backlog));
  69. return 0;
  70. }
  71. ErrorOr<FlatPtr> Process::sys$accept4(Userspace<Syscall::SC_accept4_params const*> user_params)
  72. {
  73. VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
  74. TRY(require_promise(Pledge::accept));
  75. auto params = TRY(copy_typed_from_user(user_params));
  76. int accepting_socket_fd = params.sockfd;
  77. Userspace<sockaddr*> user_address((FlatPtr)params.addr);
  78. Userspace<socklen_t*> user_address_size((FlatPtr)params.addrlen);
  79. int flags = params.flags;
  80. socklen_t address_size = 0;
  81. if (user_address) {
  82. TRY(copy_from_user(&address_size, static_ptr_cast<socklen_t const*>(user_address_size)));
  83. }
  84. ScopedDescriptionAllocation fd_allocation;
  85. RefPtr<OpenFileDescription> accepting_socket_description;
  86. TRY(m_fds.with_exclusive([&](auto& fds) -> ErrorOr<void> {
  87. fd_allocation = TRY(fds.allocate());
  88. accepting_socket_description = TRY(fds.open_file_description(accepting_socket_fd));
  89. return {};
  90. }));
  91. if (!accepting_socket_description->is_socket())
  92. return ENOTSOCK;
  93. auto& socket = *accepting_socket_description->socket();
  94. if (!socket.can_accept()) {
  95. if (accepting_socket_description->is_blocking()) {
  96. auto unblock_flags = Thread::FileBlocker::BlockFlags::None;
  97. if (Thread::current()->block<Thread::AcceptBlocker>({}, *accepting_socket_description, unblock_flags).was_interrupted())
  98. return EINTR;
  99. } else {
  100. return EAGAIN;
  101. }
  102. }
  103. auto accepted_socket = socket.accept();
  104. VERIFY(accepted_socket);
  105. if (user_address) {
  106. sockaddr_un address_buffer {};
  107. address_size = min(sizeof(sockaddr_un), static_cast<size_t>(address_size));
  108. accepted_socket->get_peer_address((sockaddr*)&address_buffer, &address_size);
  109. TRY(copy_to_user(user_address, &address_buffer, address_size));
  110. TRY(copy_to_user(user_address_size, &address_size));
  111. }
  112. auto accepted_socket_description = TRY(OpenFileDescription::try_create(*accepted_socket));
  113. accepted_socket_description->set_readable(true);
  114. accepted_socket_description->set_writable(true);
  115. if (flags & SOCK_NONBLOCK)
  116. accepted_socket_description->set_blocking(false);
  117. int fd_flags = 0;
  118. if (flags & SOCK_CLOEXEC)
  119. fd_flags |= FD_CLOEXEC;
  120. TRY(m_fds.with_exclusive([&](auto& fds) -> ErrorOr<void> {
  121. fds[fd_allocation.fd].set(move(accepted_socket_description), fd_flags);
  122. return {};
  123. }));
  124. // NOTE: Moving this state to Completed is what causes connect() to unblock on the client side.
  125. accepted_socket->set_setup_state(Socket::SetupState::Completed);
  126. return fd_allocation.fd;
  127. }
  128. ErrorOr<FlatPtr> Process::sys$connect(int sockfd, Userspace<sockaddr const*> user_address, socklen_t user_address_size)
  129. {
  130. VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
  131. auto description = TRY(open_file_description(sockfd));
  132. if (!description->is_socket())
  133. return ENOTSOCK;
  134. auto& socket = *description->socket();
  135. REQUIRE_PROMISE_FOR_SOCKET_DOMAIN(socket.domain());
  136. TRY(socket.connect(*description, user_address, user_address_size, description->is_blocking() ? ShouldBlock::Yes : ShouldBlock::No));
  137. return 0;
  138. }
  139. ErrorOr<FlatPtr> Process::sys$shutdown(int sockfd, int how)
  140. {
  141. VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
  142. TRY(require_promise(Pledge::stdio));
  143. if (how & ~SHUT_RDWR)
  144. return EINVAL;
  145. auto description = TRY(open_file_description(sockfd));
  146. if (!description->is_socket())
  147. return ENOTSOCK;
  148. auto& socket = *description->socket();
  149. REQUIRE_PROMISE_FOR_SOCKET_DOMAIN(socket.domain());
  150. TRY(socket.shutdown(how));
  151. return 0;
  152. }
  153. ErrorOr<FlatPtr> Process::sys$sendmsg(int sockfd, Userspace<const struct msghdr*> user_msg, int flags)
  154. {
  155. VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
  156. TRY(require_promise(Pledge::stdio));
  157. auto msg = TRY(copy_typed_from_user(user_msg));
  158. if (msg.msg_iovlen != 1)
  159. return ENOTSUP; // FIXME: Support this :)
  160. Vector<iovec, 1> iovs;
  161. TRY(iovs.try_resize(msg.msg_iovlen));
  162. TRY(copy_n_from_user(iovs.data(), msg.msg_iov, msg.msg_iovlen));
  163. if (iovs[0].iov_len > NumericLimits<ssize_t>::max())
  164. return EINVAL;
  165. Userspace<sockaddr const*> user_addr((FlatPtr)msg.msg_name);
  166. socklen_t addr_length = msg.msg_namelen;
  167. auto description = TRY(open_file_description(sockfd));
  168. if (!description->is_socket())
  169. return ENOTSOCK;
  170. auto& socket = *description->socket();
  171. if (socket.is_shut_down_for_writing())
  172. return EPIPE;
  173. auto data_buffer = TRY(UserOrKernelBuffer::for_user_buffer((u8*)iovs[0].iov_base, iovs[0].iov_len));
  174. while (true) {
  175. while (!description->can_write()) {
  176. if (!description->is_blocking()) {
  177. return EAGAIN;
  178. }
  179. auto unblock_flags = Thread::FileBlocker::BlockFlags::None;
  180. if (Thread::current()->block<Thread::WriteBlocker>({}, *description, unblock_flags).was_interrupted()) {
  181. return EINTR;
  182. }
  183. // TODO: handle exceptions in unblock_flags
  184. }
  185. auto bytes_sent = TRY(socket.sendto(*description, data_buffer, iovs[0].iov_len, flags, user_addr, addr_length));
  186. if (bytes_sent > 0)
  187. return bytes_sent;
  188. }
  189. }
  190. ErrorOr<FlatPtr> Process::sys$recvmsg(int sockfd, Userspace<struct msghdr*> user_msg, int flags)
  191. {
  192. VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
  193. TRY(require_promise(Pledge::stdio));
  194. struct msghdr msg;
  195. TRY(copy_from_user(&msg, user_msg));
  196. if (msg.msg_iovlen != 1)
  197. return ENOTSUP; // FIXME: Support this :)
  198. Vector<iovec, 1> iovs;
  199. TRY(iovs.try_resize(msg.msg_iovlen));
  200. TRY(copy_n_from_user(iovs.data(), msg.msg_iov, msg.msg_iovlen));
  201. Userspace<sockaddr*> user_addr((FlatPtr)msg.msg_name);
  202. Userspace<socklen_t*> user_addr_length(msg.msg_name ? (FlatPtr)&user_msg.unsafe_userspace_ptr()->msg_namelen : 0);
  203. auto description = TRY(open_file_description(sockfd));
  204. if (!description->is_socket())
  205. return ENOTSOCK;
  206. auto& socket = *description->socket();
  207. if (socket.is_shut_down_for_reading())
  208. return 0;
  209. bool original_blocking = description->is_blocking();
  210. if (flags & MSG_DONTWAIT)
  211. description->set_blocking(false);
  212. auto data_buffer = TRY(UserOrKernelBuffer::for_user_buffer((u8*)iovs[0].iov_base, iovs[0].iov_len));
  213. Time timestamp {};
  214. auto result = socket.recvfrom(*description, data_buffer, iovs[0].iov_len, flags, user_addr, user_addr_length, timestamp);
  215. if (flags & MSG_DONTWAIT)
  216. description->set_blocking(original_blocking);
  217. if (result.is_error())
  218. return result.release_error();
  219. int msg_flags = 0;
  220. if (result.value() > iovs[0].iov_len) {
  221. VERIFY(socket.type() != SOCK_STREAM);
  222. msg_flags |= MSG_TRUNC;
  223. }
  224. if (socket.wants_timestamp()) {
  225. struct {
  226. cmsghdr cmsg;
  227. timeval timestamp;
  228. } cmsg_timestamp;
  229. socklen_t control_length = sizeof(cmsg_timestamp);
  230. if (msg.msg_controllen < control_length) {
  231. msg_flags |= MSG_CTRUNC;
  232. } else {
  233. cmsg_timestamp = { { control_length, SOL_SOCKET, SCM_TIMESTAMP }, timestamp.to_timeval() };
  234. TRY(copy_to_user(msg.msg_control, &cmsg_timestamp, control_length));
  235. }
  236. TRY(copy_to_user(&user_msg.unsafe_userspace_ptr()->msg_controllen, &control_length));
  237. }
  238. TRY(copy_to_user(&user_msg.unsafe_userspace_ptr()->msg_flags, &msg_flags));
  239. return result.value();
  240. }
  241. template<bool sockname, typename Params>
  242. ErrorOr<void> Process::get_sock_or_peer_name(Params const& params)
  243. {
  244. socklen_t addrlen_value;
  245. TRY(copy_from_user(&addrlen_value, params.addrlen, sizeof(socklen_t)));
  246. if (addrlen_value <= 0)
  247. return EINVAL;
  248. auto description = TRY(open_file_description(params.sockfd));
  249. if (!description->is_socket())
  250. return ENOTSOCK;
  251. auto& socket = *description->socket();
  252. REQUIRE_PROMISE_FOR_SOCKET_DOMAIN(socket.domain());
  253. sockaddr_un address_buffer {};
  254. addrlen_value = min(sizeof(sockaddr_un), static_cast<size_t>(addrlen_value));
  255. if constexpr (sockname)
  256. socket.get_local_address((sockaddr*)&address_buffer, &addrlen_value);
  257. else
  258. socket.get_peer_address((sockaddr*)&address_buffer, &addrlen_value);
  259. TRY(copy_to_user(params.addr, &address_buffer, addrlen_value));
  260. return copy_to_user(params.addrlen, &addrlen_value);
  261. }
  262. ErrorOr<FlatPtr> Process::sys$getsockname(Userspace<Syscall::SC_getsockname_params const*> user_params)
  263. {
  264. VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
  265. auto params = TRY(copy_typed_from_user(user_params));
  266. TRY(get_sock_or_peer_name<true>(params));
  267. return 0;
  268. }
  269. ErrorOr<FlatPtr> Process::sys$getpeername(Userspace<Syscall::SC_getpeername_params const*> user_params)
  270. {
  271. VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
  272. auto params = TRY(copy_typed_from_user(user_params));
  273. TRY(get_sock_or_peer_name<false>(params));
  274. return 0;
  275. }
  276. ErrorOr<FlatPtr> Process::sys$getsockopt(Userspace<Syscall::SC_getsockopt_params const*> user_params)
  277. {
  278. VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
  279. auto params = TRY(copy_typed_from_user(user_params));
  280. int sockfd = params.sockfd;
  281. int level = params.level;
  282. int option = params.option;
  283. Userspace<void*> user_value((FlatPtr)params.value);
  284. Userspace<socklen_t*> user_value_size((FlatPtr)params.value_size);
  285. socklen_t value_size;
  286. TRY(copy_from_user(&value_size, params.value_size, sizeof(socklen_t)));
  287. auto description = TRY(open_file_description(sockfd));
  288. if (!description->is_socket())
  289. return ENOTSOCK;
  290. auto& socket = *description->socket();
  291. REQUIRE_PROMISE_FOR_SOCKET_DOMAIN(socket.domain());
  292. TRY(socket.getsockopt(*description, level, option, user_value, user_value_size));
  293. return 0;
  294. }
  295. ErrorOr<FlatPtr> Process::sys$setsockopt(Userspace<Syscall::SC_setsockopt_params const*> user_params)
  296. {
  297. VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
  298. auto params = TRY(copy_typed_from_user(user_params));
  299. Userspace<void const*> user_value((FlatPtr)params.value);
  300. auto description = TRY(open_file_description(params.sockfd));
  301. if (!description->is_socket())
  302. return ENOTSOCK;
  303. auto& socket = *description->socket();
  304. REQUIRE_PROMISE_FOR_SOCKET_DOMAIN(socket.domain());
  305. TRY(socket.setsockopt(params.level, params.option, user_value, params.value_size));
  306. return 0;
  307. }
  308. ErrorOr<FlatPtr> Process::sys$socketpair(Userspace<Syscall::SC_socketpair_params const*> user_params)
  309. {
  310. VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
  311. auto params = TRY(copy_typed_from_user(user_params));
  312. if (params.domain != AF_LOCAL)
  313. return EINVAL;
  314. if (params.protocol != 0 && params.protocol != PF_LOCAL)
  315. return EINVAL;
  316. auto pair = TRY(LocalSocket::try_create_connected_pair(params.type & SOCK_TYPE_MASK));
  317. return m_fds.with_exclusive([&](auto& fds) -> ErrorOr<FlatPtr> {
  318. auto fd_allocation0 = TRY(fds.allocate());
  319. auto fd_allocation1 = TRY(fds.allocate());
  320. int allocated_fds[2];
  321. allocated_fds[0] = fd_allocation0.fd;
  322. allocated_fds[1] = fd_allocation1.fd;
  323. setup_socket_fd(fds, allocated_fds[0], pair.description0, params.type);
  324. setup_socket_fd(fds, allocated_fds[1], pair.description1, params.type);
  325. if (copy_to_user(params.sv, allocated_fds, sizeof(allocated_fds)).is_error()) {
  326. // Avoid leaking both file descriptors on error.
  327. fds[allocated_fds[0]] = {};
  328. fds[allocated_fds[1]] = {};
  329. return EFAULT;
  330. }
  331. return 0;
  332. });
  333. }
  334. }