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