1 #include <asm/ioctls.h> 2 #include <linux/io_uring/net.h> 3 #include <net/sock.h> 4 5 #include "uring_cmd.h" 6 7 static inline int io_uring_cmd_getsockopt(struct socket *sock, 8 struct io_uring_cmd *cmd, 9 unsigned int issue_flags) 10 { 11 const struct io_uring_sqe *sqe = cmd->sqe; 12 bool compat = !!(issue_flags & IO_URING_F_COMPAT); 13 int optlen, optname, level, err; 14 void __user *optval; 15 16 level = READ_ONCE(sqe->level); 17 if (level != SOL_SOCKET) 18 return -EOPNOTSUPP; 19 20 optval = u64_to_user_ptr(READ_ONCE(sqe->optval)); 21 optname = READ_ONCE(sqe->optname); 22 optlen = READ_ONCE(sqe->optlen); 23 24 err = do_sock_getsockopt(sock, compat, level, optname, 25 USER_SOCKPTR(optval), 26 KERNEL_SOCKPTR(&optlen)); 27 if (err) 28 return err; 29 30 /* On success, return optlen */ 31 return optlen; 32 } 33 34 static inline int io_uring_cmd_setsockopt(struct socket *sock, 35 struct io_uring_cmd *cmd, 36 unsigned int issue_flags) 37 { 38 const struct io_uring_sqe *sqe = cmd->sqe; 39 bool compat = !!(issue_flags & IO_URING_F_COMPAT); 40 int optname, optlen, level; 41 void __user *optval; 42 sockptr_t optval_s; 43 44 optval = u64_to_user_ptr(READ_ONCE(sqe->optval)); 45 optname = READ_ONCE(sqe->optname); 46 optlen = READ_ONCE(sqe->optlen); 47 level = READ_ONCE(sqe->level); 48 optval_s = USER_SOCKPTR(optval); 49 50 return do_sock_setsockopt(sock, compat, level, optname, optval_s, 51 optlen); 52 } 53 54 int io_uring_cmd_sock(struct io_uring_cmd *cmd, unsigned int issue_flags) 55 { 56 struct socket *sock = cmd->file->private_data; 57 struct sock *sk = sock->sk; 58 struct proto *prot = READ_ONCE(sk->sk_prot); 59 int ret, arg = 0; 60 61 if (!prot || !prot->ioctl) 62 return -EOPNOTSUPP; 63 64 switch (cmd->cmd_op) { 65 case SOCKET_URING_OP_SIOCINQ: 66 ret = prot->ioctl(sk, SIOCINQ, &arg); 67 if (ret) 68 return ret; 69 return arg; 70 case SOCKET_URING_OP_SIOCOUTQ: 71 ret = prot->ioctl(sk, SIOCOUTQ, &arg); 72 if (ret) 73 return ret; 74 return arg; 75 case SOCKET_URING_OP_GETSOCKOPT: 76 return io_uring_cmd_getsockopt(sock, cmd, issue_flags); 77 case SOCKET_URING_OP_SETSOCKOPT: 78 return io_uring_cmd_setsockopt(sock, cmd, issue_flags); 79 default: 80 return -EOPNOTSUPP; 81 } 82 } 83 EXPORT_SYMBOL_GPL(io_uring_cmd_sock); 84