Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: ioctl: Use kernel memory on protocol ioctl callbacks

Most of the ioctls to net protocols operates directly on userspace
argument (arg). Usually doing get_user()/put_user() directly in the
ioctl callback. This is not flexible, because it is hard to reuse these
functions without passing userspace buffers.

Change the "struct proto" ioctls to avoid touching userspace memory and
operate on kernel buffers, i.e., all protocol's ioctl callbacks is
adapted to operate on a kernel memory other than on userspace (so, no
more {put,get}_user() and friends being called in the ioctl callback).

This changes the "struct proto" ioctl format in the following way:

int (*ioctl)(struct sock *sk, int cmd,
- unsigned long arg);
+ int *karg);

(Important to say that this patch does not touch the "struct proto_ops"
protocols)

So, the "karg" argument, which is passed to the ioctl callback, is a
pointer allocated to kernel space memory (inside a function wrapper).
This buffer (karg) may contain input argument (copied from userspace in
a prep function) and it might return a value/buffer, which is copied
back to userspace if necessary. There is not one-size-fits-all format
(that is I am using 'may' above), but basically, there are three type of
ioctls:

1) Do not read from userspace, returns a result to userspace
2) Read an input parameter from userspace, and does not return anything
to userspace
3) Read an input from userspace, and return a buffer to userspace.

The default case (1) (where no input parameter is given, and an "int" is
returned to userspace) encompasses more than 90% of the cases, but there
are two other exceptions. Here is a list of exceptions:

* Protocol RAW:
* cmd = SIOCGETVIFCNT:
* input and output = struct sioc_vif_req
* cmd = SIOCGETSGCNT
* input and output = struct sioc_sg_req
* Explanation: for the SIOCGETVIFCNT case, userspace passes the input
argument, which is struct sioc_vif_req. Then the callback populates
the struct, which is copied back to userspace.

* Protocol RAW6:
* cmd = SIOCGETMIFCNT_IN6
* input and output = struct sioc_mif_req6
* cmd = SIOCGETSGCNT_IN6
* input and output = struct sioc_sg_req6

* Protocol PHONET:
* cmd == SIOCPNADDRESOURCE | SIOCPNDELRESOURCE
* input int (4 bytes)
* Nothing is copied back to userspace.

For the exception cases, functions sock_sk_ioctl_inout() will
copy the userspace input, and copy it back to kernel space.

The wrapper that prepare the buffer and put the buffer back to user is
sk_ioctl(), so, instead of calling sk->sk_prot->ioctl(), the callee now
calls sk_ioctl(), which will handle all cases.

Signed-off-by: Breno Leitao <leitao@debian.org>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Reviewed-by: David Ahern <dsahern@kernel.org>
Reviewed-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Link: https://lore.kernel.org/r/20230609152800.830401-1-leitao@debian.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Breno Leitao and committed by
Jakub Kicinski
e1d001fa 173780ff

+267 -129
+6
include/linux/icmpv6.h
··· 111 111 return false; 112 112 } 113 113 114 + static inline int sk_is_icmpv6(struct sock *sk) 115 + { 116 + return sk->sk_family == AF_INET6 && 117 + inet_sk(sk)->inet_num == IPPROTO_ICMPV6; 118 + } 119 + 114 120 #endif
+20 -2
include/linux/mroute.h
··· 16 16 return opt >= MRT_BASE && opt <= MRT_MAX; 17 17 } 18 18 19 + static inline int sk_is_ipmr(struct sock *sk) 20 + { 21 + return sk->sk_family == AF_INET && 22 + inet_sk(sk)->inet_num == IPPROTO_IGMP; 23 + } 24 + 19 25 int ip_mroute_setsockopt(struct sock *, int, sockptr_t, unsigned int); 20 26 int ip_mroute_getsockopt(struct sock *, int, sockptr_t, sockptr_t); 21 - int ipmr_ioctl(struct sock *sk, int cmd, void __user *arg); 27 + int ipmr_ioctl(struct sock *sk, int cmd, void *arg); 22 28 int ipmr_compat_ioctl(struct sock *sk, unsigned int cmd, void __user *arg); 23 29 int ip_mr_init(void); 24 30 bool ipmr_rule_default(const struct fib_rule *rule); 31 + int ipmr_sk_ioctl(struct sock *sk, unsigned int cmd, void __user *arg); 25 32 #else 26 33 static inline int ip_mroute_setsockopt(struct sock *sock, int optname, 27 34 sockptr_t optval, unsigned int optlen) ··· 42 35 return -ENOPROTOOPT; 43 36 } 44 37 45 - static inline int ipmr_ioctl(struct sock *sk, int cmd, void __user *arg) 38 + static inline int ipmr_ioctl(struct sock *sk, int cmd, void *arg) 46 39 { 47 40 return -ENOIOCTLCMD; 48 41 } ··· 57 50 return 0; 58 51 } 59 52 53 + static inline int sk_is_ipmr(struct sock *sk) 54 + { 55 + return 0; 56 + } 57 + 60 58 static inline bool ipmr_rule_default(const struct fib_rule *rule) 61 59 { 62 60 return true; 61 + } 62 + 63 + static inline int ipmr_sk_ioctl(struct sock *sk, unsigned int cmd, 64 + void __user *arg) 65 + { 66 + return 1; 63 67 } 64 68 #endif 65 69
+29 -2
include/linux/mroute6.h
··· 29 29 extern int ip6_mroute_setsockopt(struct sock *, int, sockptr_t, unsigned int); 30 30 extern int ip6_mroute_getsockopt(struct sock *, int, sockptr_t, sockptr_t); 31 31 extern int ip6_mr_input(struct sk_buff *skb); 32 - extern int ip6mr_ioctl(struct sock *sk, int cmd, void __user *arg); 33 32 extern int ip6mr_compat_ioctl(struct sock *sk, unsigned int cmd, void __user *arg); 34 33 extern int ip6_mr_init(void); 35 34 extern void ip6_mr_cleanup(void); 35 + int ip6mr_ioctl(struct sock *sk, int cmd, void *arg); 36 36 #else 37 37 static inline int ip6_mroute_setsockopt(struct sock *sock, int optname, 38 38 sockptr_t optval, unsigned int optlen) ··· 48 48 } 49 49 50 50 static inline 51 - int ip6mr_ioctl(struct sock *sk, int cmd, void __user *arg) 51 + int ip6mr_ioctl(struct sock *sk, int cmd, void *arg) 52 52 { 53 53 return -ENOIOCTLCMD; 54 54 } ··· 100 100 #ifdef CONFIG_IPV6_MROUTE 101 101 bool mroute6_is_socket(struct net *net, struct sk_buff *skb); 102 102 extern int ip6mr_sk_done(struct sock *sk); 103 + static inline int ip6mr_sk_ioctl(struct sock *sk, unsigned int cmd, 104 + void __user *arg) 105 + { 106 + switch (cmd) { 107 + /* These userspace buffers will be consumed by ip6mr_ioctl() */ 108 + case SIOCGETMIFCNT_IN6: { 109 + struct sioc_mif_req6 buffer; 110 + 111 + return sock_ioctl_inout(sk, cmd, arg, &buffer, 112 + sizeof(buffer)); 113 + } 114 + case SIOCGETSGCNT_IN6: { 115 + struct sioc_mif_req6 buffer; 116 + 117 + return sock_ioctl_inout(sk, cmd, arg, &buffer, 118 + sizeof(buffer)); 119 + } 120 + } 121 + 122 + return 1; 123 + } 103 124 #else 104 125 static inline bool mroute6_is_socket(struct net *net, struct sk_buff *skb) 105 126 { ··· 129 108 static inline int ip6mr_sk_done(struct sock *sk) 130 109 { 131 110 return 0; 111 + } 112 + 113 + static inline int ip6mr_sk_ioctl(struct sock *sk, unsigned int cmd, 114 + void __user *arg) 115 + { 116 + return 1; 132 117 } 133 118 #endif 134 119 #endif
+21
include/net/phonet/phonet.h
··· 109 109 int isi_register(void); 110 110 void isi_unregister(void); 111 111 112 + static inline bool sk_is_phonet(struct sock *sk) 113 + { 114 + return sk->sk_family == PF_PHONET; 115 + } 116 + 117 + static inline int phonet_sk_ioctl(struct sock *sk, unsigned int cmd, 118 + void __user *arg) 119 + { 120 + int karg; 121 + 122 + switch (cmd) { 123 + case SIOCPNADDRESOURCE: 124 + case SIOCPNDELRESOURCE: 125 + if (get_user(karg, (int __user *)arg)) 126 + return -EFAULT; 127 + 128 + return sk->sk_prot->ioctl(sk, cmd, &karg); 129 + } 130 + /* A positive return value means that the ioctl was not processed */ 131 + return 1; 132 + } 112 133 #endif
+4 -1
include/net/sock.h
··· 1258 1258 bool kern); 1259 1259 1260 1260 int (*ioctl)(struct sock *sk, int cmd, 1261 - unsigned long arg); 1261 + int *karg); 1262 1262 int (*init)(struct sock *sk); 1263 1263 void (*destroy)(struct sock *sk); 1264 1264 void (*shutdown)(struct sock *sk, int how); ··· 2974 2974 int sock_copy_user_timeval(struct __kernel_sock_timeval *tv, 2975 2975 sockptr_t optval, int optlen, bool old_timeval); 2976 2976 2977 + int sock_ioctl_inout(struct sock *sk, unsigned int cmd, 2978 + void __user *arg, void *karg, size_t size); 2979 + int sk_ioctl(struct sock *sk, unsigned int cmd, void __user *arg); 2977 2980 static inline bool sk_is_readable(struct sock *sk) 2978 2981 { 2979 2982 if (sk->sk_prot->sock_is_readable)
+1 -1
include/net/tcp.h
··· 340 340 void tcp_wfree(struct sk_buff *skb); 341 341 void tcp_write_timer_handler(struct sock *sk); 342 342 void tcp_delack_timer_handler(struct sock *sk); 343 - int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg); 343 + int tcp_ioctl(struct sock *sk, int cmd, int *karg); 344 344 int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb); 345 345 void tcp_rcv_established(struct sock *sk, struct sk_buff *skb); 346 346 void tcp_rcv_space_adjust(struct sock *sk);
+1 -1
include/net/udp.h
··· 285 285 int udp_cmsg_send(struct sock *sk, struct msghdr *msg, u16 *gso_size); 286 286 void udp4_hwcsum(struct sk_buff *skb, __be32 src, __be32 dst); 287 287 int udp_rcv(struct sk_buff *skb); 288 - int udp_ioctl(struct sock *sk, int cmd, unsigned long arg); 288 + int udp_ioctl(struct sock *sk, int cmd, int *karg); 289 289 int udp_init_sock(struct sock *sk); 290 290 int udp_pre_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len); 291 291 int __udp_disconnect(struct sock *sk, int flags);
+64
net/core/sock.c
··· 114 114 #include <linux/memcontrol.h> 115 115 #include <linux/prefetch.h> 116 116 #include <linux/compat.h> 117 + #include <linux/mroute.h> 118 + #include <linux/mroute6.h> 119 + #include <linux/icmpv6.h> 117 120 118 121 #include <linux/uaccess.h> 119 122 ··· 141 138 142 139 #include <net/tcp.h> 143 140 #include <net/busy_poll.h> 141 + #include <net/phonet/phonet.h> 144 142 145 143 #include <linux/ethtool.h> 146 144 ··· 4154 4150 return sk->sk_prot->bind_add(sk, addr, addr_len); 4155 4151 } 4156 4152 EXPORT_SYMBOL(sock_bind_add); 4153 + 4154 + /* Copy 'size' bytes from userspace and return `size` back to userspace */ 4155 + int sock_ioctl_inout(struct sock *sk, unsigned int cmd, 4156 + void __user *arg, void *karg, size_t size) 4157 + { 4158 + int ret; 4159 + 4160 + if (copy_from_user(karg, arg, size)) 4161 + return -EFAULT; 4162 + 4163 + ret = READ_ONCE(sk->sk_prot)->ioctl(sk, cmd, karg); 4164 + if (ret) 4165 + return ret; 4166 + 4167 + if (copy_to_user(arg, karg, size)) 4168 + return -EFAULT; 4169 + 4170 + return 0; 4171 + } 4172 + EXPORT_SYMBOL(sock_ioctl_inout); 4173 + 4174 + /* This is the most common ioctl prep function, where the result (4 bytes) is 4175 + * copied back to userspace if the ioctl() returns successfully. No input is 4176 + * copied from userspace as input argument. 4177 + */ 4178 + static int sock_ioctl_out(struct sock *sk, unsigned int cmd, void __user *arg) 4179 + { 4180 + int ret, karg = 0; 4181 + 4182 + ret = READ_ONCE(sk->sk_prot)->ioctl(sk, cmd, &karg); 4183 + if (ret) 4184 + return ret; 4185 + 4186 + return put_user(karg, (int __user *)arg); 4187 + } 4188 + 4189 + /* A wrapper around sock ioctls, which copies the data from userspace 4190 + * (depending on the protocol/ioctl), and copies back the result to userspace. 4191 + * The main motivation for this function is to pass kernel memory to the 4192 + * protocol ioctl callbacks, instead of userspace memory. 4193 + */ 4194 + int sk_ioctl(struct sock *sk, unsigned int cmd, void __user *arg) 4195 + { 4196 + int rc = 1; 4197 + 4198 + if (sk_is_ipmr(sk)) 4199 + rc = ipmr_sk_ioctl(sk, cmd, arg); 4200 + else if (sk_is_icmpv6(sk)) 4201 + rc = ip6mr_sk_ioctl(sk, cmd, arg); 4202 + else if (sk_is_phonet(sk)) 4203 + rc = phonet_sk_ioctl(sk, cmd, arg); 4204 + 4205 + /* If ioctl was processed, returns its value */ 4206 + if (rc <= 0) 4207 + return rc; 4208 + 4209 + /* Otherwise call the default handler */ 4210 + return sock_ioctl_out(sk, cmd, arg); 4211 + } 4212 + EXPORT_SYMBOL(sk_ioctl);
+1 -1
net/dccp/dccp.h
··· 292 292 char __user *optval, int __user *optlen); 293 293 int dccp_setsockopt(struct sock *sk, int level, int optname, 294 294 sockptr_t optval, unsigned int optlen); 295 - int dccp_ioctl(struct sock *sk, int cmd, unsigned long arg); 295 + int dccp_ioctl(struct sock *sk, int cmd, int *karg); 296 296 int dccp_sendmsg(struct sock *sk, struct msghdr *msg, size_t size); 297 297 int dccp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int flags, 298 298 int *addr_len);
+6 -6
net/dccp/proto.c
··· 362 362 363 363 EXPORT_SYMBOL_GPL(dccp_poll); 364 364 365 - int dccp_ioctl(struct sock *sk, int cmd, unsigned long arg) 365 + int dccp_ioctl(struct sock *sk, int cmd, int *karg) 366 366 { 367 367 int rc = -ENOTCONN; 368 368 ··· 373 373 374 374 switch (cmd) { 375 375 case SIOCOUTQ: { 376 - int amount = sk_wmem_alloc_get(sk); 376 + *karg = sk_wmem_alloc_get(sk); 377 377 /* Using sk_wmem_alloc here because sk_wmem_queued is not used by DCCP and 378 378 * always 0, comparably to UDP. 379 379 */ 380 380 381 - rc = put_user(amount, (int __user *)arg); 381 + rc = 0; 382 382 } 383 383 break; 384 384 case SIOCINQ: { 385 385 struct sk_buff *skb; 386 - unsigned long amount = 0; 386 + *karg = 0; 387 387 388 388 skb = skb_peek(&sk->sk_receive_queue); 389 389 if (skb != NULL) { ··· 391 391 * We will only return the amount of this packet since 392 392 * that is all that will be read. 393 393 */ 394 - amount = skb->len; 394 + *karg = skb->len; 395 395 } 396 - rc = put_user(amount, (int __user *)arg); 396 + rc = 0; 397 397 } 398 398 break; 399 399 default:
+7 -8
net/ieee802154/socket.c
··· 162 162 default: 163 163 if (!sk->sk_prot->ioctl) 164 164 return -ENOIOCTLCMD; 165 - return sk->sk_prot->ioctl(sk, cmd, arg); 165 + return sk_ioctl(sk, cmd, (void __user *)arg); 166 166 } 167 167 } 168 168 ··· 531 531 return err; 532 532 } 533 533 534 - static int dgram_ioctl(struct sock *sk, int cmd, unsigned long arg) 534 + static int dgram_ioctl(struct sock *sk, int cmd, int *karg) 535 535 { 536 536 switch (cmd) { 537 537 case SIOCOUTQ: 538 538 { 539 - int amount = sk_wmem_alloc_get(sk); 539 + *karg = sk_wmem_alloc_get(sk); 540 540 541 - return put_user(amount, (int __user *)arg); 541 + return 0; 542 542 } 543 543 544 544 case SIOCINQ: 545 545 { 546 546 struct sk_buff *skb; 547 - unsigned long amount; 548 547 549 - amount = 0; 548 + *karg = 0; 550 549 spin_lock_bh(&sk->sk_receive_queue.lock); 551 550 skb = skb_peek(&sk->sk_receive_queue); 552 551 if (skb) { ··· 553 554 * of this packet since that is all 554 555 * that will be read. 555 556 */ 556 - amount = skb->len - ieee802154_hdr_length(skb); 557 + *karg = skb->len - ieee802154_hdr_length(skb); 557 558 } 558 559 spin_unlock_bh(&sk->sk_receive_queue.lock); 559 - return put_user(amount, (int __user *)arg); 560 + return 0; 560 561 } 561 562 } 562 563
+1 -1
net/ipv4/af_inet.c
··· 998 998 break; 999 999 default: 1000 1000 if (sk->sk_prot->ioctl) 1001 - err = sk->sk_prot->ioctl(sk, cmd, arg); 1001 + err = sk_ioctl(sk, cmd, (void __user *)arg); 1002 1002 else 1003 1003 err = -ENOIOCTLCMD; 1004 1004 break;
+39 -24
net/ipv4/ipmr.c
··· 1547 1547 return ret; 1548 1548 } 1549 1549 1550 + /* Execute if this ioctl is a special mroute ioctl */ 1551 + int ipmr_sk_ioctl(struct sock *sk, unsigned int cmd, void __user *arg) 1552 + { 1553 + switch (cmd) { 1554 + /* These userspace buffers will be consumed by ipmr_ioctl() */ 1555 + case SIOCGETVIFCNT: { 1556 + struct sioc_vif_req buffer; 1557 + 1558 + return sock_ioctl_inout(sk, cmd, arg, &buffer, 1559 + sizeof(buffer)); 1560 + } 1561 + case SIOCGETSGCNT: { 1562 + struct sioc_sg_req buffer; 1563 + 1564 + return sock_ioctl_inout(sk, cmd, arg, &buffer, 1565 + sizeof(buffer)); 1566 + } 1567 + } 1568 + /* return code > 0 means that the ioctl was not executed */ 1569 + return 1; 1570 + } 1571 + 1550 1572 /* Getsock opt support for the multicast routing system. */ 1551 1573 int ip_mroute_getsockopt(struct sock *sk, int optname, sockptr_t optval, 1552 1574 sockptr_t optlen) ··· 1615 1593 } 1616 1594 1617 1595 /* The IP multicast ioctl support routines. */ 1618 - int ipmr_ioctl(struct sock *sk, int cmd, void __user *arg) 1596 + int ipmr_ioctl(struct sock *sk, int cmd, void *arg) 1619 1597 { 1620 - struct sioc_sg_req sr; 1621 - struct sioc_vif_req vr; 1622 1598 struct vif_device *vif; 1623 1599 struct mfc_cache *c; 1624 1600 struct net *net = sock_net(sk); 1601 + struct sioc_vif_req *vr; 1602 + struct sioc_sg_req *sr; 1625 1603 struct mr_table *mrt; 1626 1604 1627 1605 mrt = ipmr_get_table(net, raw_sk(sk)->ipmr_table ? : RT_TABLE_DEFAULT); ··· 1630 1608 1631 1609 switch (cmd) { 1632 1610 case SIOCGETVIFCNT: 1633 - if (copy_from_user(&vr, arg, sizeof(vr))) 1634 - return -EFAULT; 1635 - if (vr.vifi >= mrt->maxvif) 1611 + vr = (struct sioc_vif_req *)arg; 1612 + if (vr->vifi >= mrt->maxvif) 1636 1613 return -EINVAL; 1637 - vr.vifi = array_index_nospec(vr.vifi, mrt->maxvif); 1614 + vr->vifi = array_index_nospec(vr->vifi, mrt->maxvif); 1638 1615 rcu_read_lock(); 1639 - vif = &mrt->vif_table[vr.vifi]; 1640 - if (VIF_EXISTS(mrt, vr.vifi)) { 1641 - vr.icount = READ_ONCE(vif->pkt_in); 1642 - vr.ocount = READ_ONCE(vif->pkt_out); 1643 - vr.ibytes = READ_ONCE(vif->bytes_in); 1644 - vr.obytes = READ_ONCE(vif->bytes_out); 1616 + vif = &mrt->vif_table[vr->vifi]; 1617 + if (VIF_EXISTS(mrt, vr->vifi)) { 1618 + vr->icount = READ_ONCE(vif->pkt_in); 1619 + vr->ocount = READ_ONCE(vif->pkt_out); 1620 + vr->ibytes = READ_ONCE(vif->bytes_in); 1621 + vr->obytes = READ_ONCE(vif->bytes_out); 1645 1622 rcu_read_unlock(); 1646 1623 1647 - if (copy_to_user(arg, &vr, sizeof(vr))) 1648 - return -EFAULT; 1649 1624 return 0; 1650 1625 } 1651 1626 rcu_read_unlock(); 1652 1627 return -EADDRNOTAVAIL; 1653 1628 case SIOCGETSGCNT: 1654 - if (copy_from_user(&sr, arg, sizeof(sr))) 1655 - return -EFAULT; 1629 + sr = (struct sioc_sg_req *)arg; 1656 1630 1657 1631 rcu_read_lock(); 1658 - c = ipmr_cache_find(mrt, sr.src.s_addr, sr.grp.s_addr); 1632 + c = ipmr_cache_find(mrt, sr->src.s_addr, sr->grp.s_addr); 1659 1633 if (c) { 1660 - sr.pktcnt = c->_c.mfc_un.res.pkt; 1661 - sr.bytecnt = c->_c.mfc_un.res.bytes; 1662 - sr.wrong_if = c->_c.mfc_un.res.wrong_if; 1634 + sr->pktcnt = c->_c.mfc_un.res.pkt; 1635 + sr->bytecnt = c->_c.mfc_un.res.bytes; 1636 + sr->wrong_if = c->_c.mfc_un.res.wrong_if; 1663 1637 rcu_read_unlock(); 1664 - 1665 - if (copy_to_user(arg, &sr, sizeof(sr))) 1666 - return -EFAULT; 1667 1638 return 0; 1668 1639 } 1669 1640 rcu_read_unlock();
+8 -8
net/ipv4/raw.c
··· 856 856 return do_raw_getsockopt(sk, level, optname, optval, optlen); 857 857 } 858 858 859 - static int raw_ioctl(struct sock *sk, int cmd, unsigned long arg) 859 + static int raw_ioctl(struct sock *sk, int cmd, int *karg) 860 860 { 861 861 switch (cmd) { 862 862 case SIOCOUTQ: { 863 - int amount = sk_wmem_alloc_get(sk); 864 - 865 - return put_user(amount, (int __user *)arg); 863 + *karg = sk_wmem_alloc_get(sk); 864 + return 0; 866 865 } 867 866 case SIOCINQ: { 868 867 struct sk_buff *skb; 869 - int amount = 0; 870 868 871 869 spin_lock_bh(&sk->sk_receive_queue.lock); 872 870 skb = skb_peek(&sk->sk_receive_queue); 873 871 if (skb) 874 - amount = skb->len; 872 + *karg = skb->len; 873 + else 874 + *karg = 0; 875 875 spin_unlock_bh(&sk->sk_receive_queue.lock); 876 - return put_user(amount, (int __user *)arg); 876 + return 0; 877 877 } 878 878 879 879 default: 880 880 #ifdef CONFIG_IP_MROUTE 881 - return ipmr_ioctl(sk, cmd, (void __user *)arg); 881 + return ipmr_ioctl(sk, cmd, karg); 882 882 #else 883 883 return -ENOIOCTLCMD; 884 884 #endif
+3 -2
net/ipv4/tcp.c
··· 599 599 } 600 600 EXPORT_SYMBOL(tcp_poll); 601 601 602 - int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg) 602 + int tcp_ioctl(struct sock *sk, int cmd, int *karg) 603 603 { 604 604 struct tcp_sock *tp = tcp_sk(sk); 605 605 int answ; ··· 641 641 return -ENOIOCTLCMD; 642 642 } 643 643 644 - return put_user(answ, (int __user *)arg); 644 + *karg = answ; 645 + return 0; 645 646 } 646 647 EXPORT_SYMBOL(tcp_ioctl); 647 648
+5 -7
net/ipv4/udp.c
··· 1692 1692 * IOCTL requests applicable to the UDP protocol 1693 1693 */ 1694 1694 1695 - int udp_ioctl(struct sock *sk, int cmd, unsigned long arg) 1695 + int udp_ioctl(struct sock *sk, int cmd, int *karg) 1696 1696 { 1697 1697 switch (cmd) { 1698 1698 case SIOCOUTQ: 1699 1699 { 1700 - int amount = sk_wmem_alloc_get(sk); 1701 - 1702 - return put_user(amount, (int __user *)arg); 1700 + *karg = sk_wmem_alloc_get(sk); 1701 + return 0; 1703 1702 } 1704 1703 1705 1704 case SIOCINQ: 1706 1705 { 1707 - int amount = max_t(int, 0, first_packet_length(sk)); 1708 - 1709 - return put_user(amount, (int __user *)arg); 1706 + *karg = max_t(int, 0, first_packet_length(sk)); 1707 + return 0; 1710 1708 } 1711 1709 1712 1710 default:
+1 -1
net/ipv6/af_inet6.c
··· 579 579 prot = READ_ONCE(sk->sk_prot); 580 580 if (!prot->ioctl) 581 581 return -ENOIOCTLCMD; 582 - return prot->ioctl(sk, cmd, arg); 582 + return sk_ioctl(sk, cmd, (void __user *)arg); 583 583 } 584 584 /*NOTREACHED*/ 585 585 return 0;
+18 -26
net/ipv6/ip6mr.c
··· 1879 1879 /* 1880 1880 * The IP multicast ioctl support routines. 1881 1881 */ 1882 - 1883 - int ip6mr_ioctl(struct sock *sk, int cmd, void __user *arg) 1882 + int ip6mr_ioctl(struct sock *sk, int cmd, void *arg) 1884 1883 { 1885 - struct sioc_sg_req6 sr; 1886 - struct sioc_mif_req6 vr; 1884 + struct sioc_sg_req6 *sr; 1885 + struct sioc_mif_req6 *vr; 1887 1886 struct vif_device *vif; 1888 1887 struct mfc6_cache *c; 1889 1888 struct net *net = sock_net(sk); ··· 1894 1895 1895 1896 switch (cmd) { 1896 1897 case SIOCGETMIFCNT_IN6: 1897 - if (copy_from_user(&vr, arg, sizeof(vr))) 1898 - return -EFAULT; 1899 - if (vr.mifi >= mrt->maxvif) 1898 + vr = (struct sioc_mif_req6 *)arg; 1899 + if (vr->mifi >= mrt->maxvif) 1900 1900 return -EINVAL; 1901 - vr.mifi = array_index_nospec(vr.mifi, mrt->maxvif); 1901 + vr->mifi = array_index_nospec(vr->mifi, mrt->maxvif); 1902 1902 rcu_read_lock(); 1903 - vif = &mrt->vif_table[vr.mifi]; 1904 - if (VIF_EXISTS(mrt, vr.mifi)) { 1905 - vr.icount = READ_ONCE(vif->pkt_in); 1906 - vr.ocount = READ_ONCE(vif->pkt_out); 1907 - vr.ibytes = READ_ONCE(vif->bytes_in); 1908 - vr.obytes = READ_ONCE(vif->bytes_out); 1903 + vif = &mrt->vif_table[vr->mifi]; 1904 + if (VIF_EXISTS(mrt, vr->mifi)) { 1905 + vr->icount = READ_ONCE(vif->pkt_in); 1906 + vr->ocount = READ_ONCE(vif->pkt_out); 1907 + vr->ibytes = READ_ONCE(vif->bytes_in); 1908 + vr->obytes = READ_ONCE(vif->bytes_out); 1909 1909 rcu_read_unlock(); 1910 - 1911 - if (copy_to_user(arg, &vr, sizeof(vr))) 1912 - return -EFAULT; 1913 1910 return 0; 1914 1911 } 1915 1912 rcu_read_unlock(); 1916 1913 return -EADDRNOTAVAIL; 1917 1914 case SIOCGETSGCNT_IN6: 1918 - if (copy_from_user(&sr, arg, sizeof(sr))) 1919 - return -EFAULT; 1915 + sr = (struct sioc_sg_req6 *)arg; 1920 1916 1921 1917 rcu_read_lock(); 1922 - c = ip6mr_cache_find(mrt, &sr.src.sin6_addr, &sr.grp.sin6_addr); 1918 + c = ip6mr_cache_find(mrt, &sr->src.sin6_addr, 1919 + &sr->grp.sin6_addr); 1923 1920 if (c) { 1924 - sr.pktcnt = c->_c.mfc_un.res.pkt; 1925 - sr.bytecnt = c->_c.mfc_un.res.bytes; 1926 - sr.wrong_if = c->_c.mfc_un.res.wrong_if; 1921 + sr->pktcnt = c->_c.mfc_un.res.pkt; 1922 + sr->bytecnt = c->_c.mfc_un.res.bytes; 1923 + sr->wrong_if = c->_c.mfc_un.res.wrong_if; 1927 1924 rcu_read_unlock(); 1928 - 1929 - if (copy_to_user(arg, &sr, sizeof(sr))) 1930 - return -EFAULT; 1931 1925 return 0; 1932 1926 } 1933 1927 rcu_read_unlock();
+8 -8
net/ipv6/raw.c
··· 1118 1118 return do_rawv6_getsockopt(sk, level, optname, optval, optlen); 1119 1119 } 1120 1120 1121 - static int rawv6_ioctl(struct sock *sk, int cmd, unsigned long arg) 1121 + static int rawv6_ioctl(struct sock *sk, int cmd, int *karg) 1122 1122 { 1123 1123 switch (cmd) { 1124 1124 case SIOCOUTQ: { 1125 - int amount = sk_wmem_alloc_get(sk); 1126 - 1127 - return put_user(amount, (int __user *)arg); 1125 + *karg = sk_wmem_alloc_get(sk); 1126 + return 0; 1128 1127 } 1129 1128 case SIOCINQ: { 1130 1129 struct sk_buff *skb; 1131 - int amount = 0; 1132 1130 1133 1131 spin_lock_bh(&sk->sk_receive_queue.lock); 1134 1132 skb = skb_peek(&sk->sk_receive_queue); 1135 1133 if (skb) 1136 - amount = skb->len; 1134 + *karg = skb->len; 1135 + else 1136 + *karg = 0; 1137 1137 spin_unlock_bh(&sk->sk_receive_queue.lock); 1138 - return put_user(amount, (int __user *)arg); 1138 + return 0; 1139 1139 } 1140 1140 1141 1141 default: 1142 1142 #ifdef CONFIG_IPV6_MROUTE 1143 - return ip6mr_ioctl(sk, cmd, (void __user *)arg); 1143 + return ip6mr_ioctl(sk, cmd, karg); 1144 1144 #else 1145 1145 return -ENOIOCTLCMD; 1146 1146 #endif
+1 -1
net/l2tp/l2tp_core.h
··· 272 272 void l2tp_nl_unregister_ops(enum l2tp_pwtype pw_type); 273 273 274 274 /* IOCTL helper for IP encap modules. */ 275 - int l2tp_ioctl(struct sock *sk, int cmd, unsigned long arg); 275 + int l2tp_ioctl(struct sock *sk, int cmd, int *karg); 276 276 277 277 /* Extract the tunnel structure from a socket's sk_user_data pointer, 278 278 * validating the tunnel magic feather.
+4 -5
net/l2tp/l2tp_ip.c
··· 562 562 return err ? err : copied; 563 563 } 564 564 565 - int l2tp_ioctl(struct sock *sk, int cmd, unsigned long arg) 565 + int l2tp_ioctl(struct sock *sk, int cmd, int *karg) 566 566 { 567 567 struct sk_buff *skb; 568 - int amount; 569 568 570 569 switch (cmd) { 571 570 case SIOCOUTQ: 572 - amount = sk_wmem_alloc_get(sk); 571 + *karg = sk_wmem_alloc_get(sk); 573 572 break; 574 573 case SIOCINQ: 575 574 spin_lock_bh(&sk->sk_receive_queue.lock); 576 575 skb = skb_peek(&sk->sk_receive_queue); 577 - amount = skb ? skb->len : 0; 576 + *karg = skb ? skb->len : 0; 578 577 spin_unlock_bh(&sk->sk_receive_queue.lock); 579 578 break; 580 579 ··· 581 582 return -ENOIOCTLCMD; 582 583 } 583 584 584 - return put_user(amount, (int __user *)arg); 585 + return 0; 585 586 } 586 587 EXPORT_SYMBOL_GPL(l2tp_ioctl); 587 588
+5 -6
net/mptcp/protocol.c
··· 3570 3570 return (int)delta; 3571 3571 } 3572 3572 3573 - static int mptcp_ioctl(struct sock *sk, int cmd, unsigned long arg) 3573 + static int mptcp_ioctl(struct sock *sk, int cmd, int *karg) 3574 3574 { 3575 3575 struct mptcp_sock *msk = mptcp_sk(sk); 3576 3576 bool slow; 3577 - int answ; 3578 3577 3579 3578 switch (cmd) { 3580 3579 case SIOCINQ: ··· 3582 3583 3583 3584 lock_sock(sk); 3584 3585 __mptcp_move_skbs(msk); 3585 - answ = mptcp_inq_hint(sk); 3586 + *karg = mptcp_inq_hint(sk); 3586 3587 release_sock(sk); 3587 3588 break; 3588 3589 case SIOCOUTQ: 3589 3590 slow = lock_sock_fast(sk); 3590 - answ = mptcp_ioctl_outq(msk, READ_ONCE(msk->snd_una)); 3591 + *karg = mptcp_ioctl_outq(msk, READ_ONCE(msk->snd_una)); 3591 3592 unlock_sock_fast(sk, slow); 3592 3593 break; 3593 3594 case SIOCOUTQNSD: 3594 3595 slow = lock_sock_fast(sk); 3595 - answ = mptcp_ioctl_outq(msk, msk->snd_nxt); 3596 + *karg = mptcp_ioctl_outq(msk, msk->snd_nxt); 3596 3597 unlock_sock_fast(sk, slow); 3597 3598 break; 3598 3599 default: 3599 3600 return -ENOIOCTLCMD; 3600 3601 } 3601 3602 3602 - return put_user(answ, (int __user *)arg); 3603 + return 0; 3603 3604 } 3604 3605 3605 3606 static void mptcp_subflow_early_fallback(struct mptcp_sock *msk,
+4 -7
net/phonet/datagram.c
··· 28 28 sk_common_release(sk); 29 29 } 30 30 31 - static int pn_ioctl(struct sock *sk, int cmd, unsigned long arg) 31 + static int pn_ioctl(struct sock *sk, int cmd, int *karg) 32 32 { 33 33 struct sk_buff *skb; 34 - int answ; 35 34 36 35 switch (cmd) { 37 36 case SIOCINQ: 38 37 lock_sock(sk); 39 38 skb = skb_peek(&sk->sk_receive_queue); 40 - answ = skb ? skb->len : 0; 39 + *karg = skb ? skb->len : 0; 41 40 release_sock(sk); 42 - return put_user(answ, (int __user *)arg); 41 + return 0; 43 42 44 43 case SIOCPNADDRESOURCE: 45 44 case SIOCPNDELRESOURCE: { 46 - u32 res; 47 - if (get_user(res, (u32 __user *)arg)) 48 - return -EFAULT; 45 + u32 res = *karg; 49 46 if (res >= 256) 50 47 return -EINVAL; 51 48 if (cmd == SIOCPNADDRESOURCE)
+5 -6
net/phonet/pep.c
··· 917 917 return 0; 918 918 } 919 919 920 - static int pep_ioctl(struct sock *sk, int cmd, unsigned long arg) 920 + static int pep_ioctl(struct sock *sk, int cmd, int *karg) 921 921 { 922 922 struct pep_sock *pn = pep_sk(sk); 923 - int answ; 924 923 int ret = -ENOIOCTLCMD; 925 924 926 925 switch (cmd) { ··· 932 933 lock_sock(sk); 933 934 if (sock_flag(sk, SOCK_URGINLINE) && 934 935 !skb_queue_empty(&pn->ctrlreq_queue)) 935 - answ = skb_peek(&pn->ctrlreq_queue)->len; 936 + *karg = skb_peek(&pn->ctrlreq_queue)->len; 936 937 else if (!skb_queue_empty(&sk->sk_receive_queue)) 937 - answ = skb_peek(&sk->sk_receive_queue)->len; 938 + *karg = skb_peek(&sk->sk_receive_queue)->len; 938 939 else 939 - answ = 0; 940 + *karg = 0; 940 941 release_sock(sk); 941 - ret = put_user(answ, (int __user *)arg); 942 + ret = 0; 942 943 break; 943 944 944 945 case SIOCPNENABLEPIPE:
+1 -1
net/phonet/socket.c
··· 387 387 return put_user(handle, (__u16 __user *)arg); 388 388 } 389 389 390 - return sk->sk_prot->ioctl(sk, cmd, arg); 390 + return sk_ioctl(sk, cmd, (void __user *)arg); 391 391 } 392 392 393 393 static int pn_socket_listen(struct socket *sock, int backlog)
+4 -4
net/sctp/socket.c
··· 4895 4895 } 4896 4896 4897 4897 /* The SCTP ioctl handler. */ 4898 - static int sctp_ioctl(struct sock *sk, int cmd, unsigned long arg) 4898 + static int sctp_ioctl(struct sock *sk, int cmd, int *karg) 4899 4899 { 4900 4900 int rc = -ENOTCONN; 4901 4901 ··· 4911 4911 switch (cmd) { 4912 4912 case SIOCINQ: { 4913 4913 struct sk_buff *skb; 4914 - unsigned int amount = 0; 4914 + *karg = 0; 4915 4915 4916 4916 skb = skb_peek(&sk->sk_receive_queue); 4917 4917 if (skb != NULL) { ··· 4919 4919 * We will only return the amount of this packet since 4920 4920 * that is all that will be read. 4921 4921 */ 4922 - amount = skb->len; 4922 + *karg = skb->len; 4923 4923 } 4924 - rc = put_user(amount, (int __user *)arg); 4924 + rc = 0; 4925 4925 break; 4926 4926 } 4927 4927 default: