.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * IEEE802154.4 socket interface |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright 2007, 2008 Siemens AG |
---|
5 | | - * |
---|
6 | | - * This program is free software; you can redistribute it and/or modify |
---|
7 | | - * it under the terms of the GNU General Public License version 2 |
---|
8 | | - * as published by the Free Software Foundation. |
---|
9 | | - * |
---|
10 | | - * This program is distributed in the hope that it will be useful, |
---|
11 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
12 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
13 | | - * GNU General Public License for more details. |
---|
14 | 6 | * |
---|
15 | 7 | * Written by: |
---|
16 | 8 | * Sergey Lapin <slapin@ossfans.org> |
---|
.. | .. |
---|
164 | 156 | struct sock *sk = sock->sk; |
---|
165 | 157 | |
---|
166 | 158 | switch (cmd) { |
---|
167 | | - case SIOCGSTAMP: |
---|
168 | | - return sock_get_timestamp(sk, (struct timeval __user *)arg); |
---|
169 | | - case SIOCGSTAMPNS: |
---|
170 | | - return sock_get_timestampns(sk, (struct timespec __user *)arg); |
---|
171 | 159 | case SIOCGIFADDR: |
---|
172 | 160 | case SIOCSIFADDR: |
---|
173 | 161 | return ieee802154_dev_ioctl(sk, (struct ifreq __user *)arg, |
---|
.. | .. |
---|
213 | 201 | int err = 0; |
---|
214 | 202 | struct net_device *dev = NULL; |
---|
215 | 203 | |
---|
216 | | - if (len < sizeof(*uaddr)) |
---|
217 | | - return -EINVAL; |
---|
| 204 | + err = ieee802154_sockaddr_check_size(uaddr, len); |
---|
| 205 | + if (err < 0) |
---|
| 206 | + return err; |
---|
218 | 207 | |
---|
219 | 208 | uaddr = (struct sockaddr_ieee802154 *)_uaddr; |
---|
220 | 209 | if (uaddr->family != AF_IEEE802154) |
---|
.. | .. |
---|
282 | 271 | if (size > mtu) { |
---|
283 | 272 | pr_debug("size = %zu, mtu = %u\n", size, mtu); |
---|
284 | 273 | err = -EMSGSIZE; |
---|
| 274 | + goto out_dev; |
---|
| 275 | + } |
---|
| 276 | + if (!size) { |
---|
| 277 | + err = 0; |
---|
285 | 278 | goto out_dev; |
---|
286 | 279 | } |
---|
287 | 280 | |
---|
.. | .. |
---|
394 | 387 | } |
---|
395 | 388 | |
---|
396 | 389 | static int raw_setsockopt(struct sock *sk, int level, int optname, |
---|
397 | | - char __user *optval, unsigned int optlen) |
---|
| 390 | + sockptr_t optval, unsigned int optlen) |
---|
398 | 391 | { |
---|
399 | 392 | return -EOPNOTSUPP; |
---|
400 | 393 | } |
---|
.. | .. |
---|
426 | 419 | .getname = sock_no_getname, |
---|
427 | 420 | .poll = datagram_poll, |
---|
428 | 421 | .ioctl = ieee802154_sock_ioctl, |
---|
| 422 | + .gettstamp = sock_gettstamp, |
---|
429 | 423 | .listen = sock_no_listen, |
---|
430 | 424 | .shutdown = sock_no_shutdown, |
---|
431 | 425 | .setsockopt = sock_common_setsockopt, |
---|
.. | .. |
---|
434 | 428 | .recvmsg = sock_common_recvmsg, |
---|
435 | 429 | .mmap = sock_no_mmap, |
---|
436 | 430 | .sendpage = sock_no_sendpage, |
---|
437 | | -#ifdef CONFIG_COMPAT |
---|
438 | | - .compat_setsockopt = compat_sock_common_setsockopt, |
---|
439 | | - .compat_getsockopt = compat_sock_common_getsockopt, |
---|
440 | | -#endif |
---|
441 | 431 | }; |
---|
442 | 432 | |
---|
443 | 433 | /* DGRAM Sockets (802.15.4 dataframes) */ |
---|
.. | .. |
---|
509 | 499 | |
---|
510 | 500 | ro->bound = 0; |
---|
511 | 501 | |
---|
512 | | - if (len < sizeof(*addr)) |
---|
| 502 | + err = ieee802154_sockaddr_check_size(addr, len); |
---|
| 503 | + if (err < 0) |
---|
513 | 504 | goto out; |
---|
514 | 505 | |
---|
515 | | - if (addr->family != AF_IEEE802154) |
---|
| 506 | + if (addr->family != AF_IEEE802154) { |
---|
| 507 | + err = -EINVAL; |
---|
516 | 508 | goto out; |
---|
| 509 | + } |
---|
517 | 510 | |
---|
518 | 511 | ieee802154_addr_from_sa(&haddr, &addr->addr); |
---|
519 | 512 | dev = ieee802154_get_dev(sock_net(sk), &haddr); |
---|
.. | .. |
---|
580 | 573 | struct dgram_sock *ro = dgram_sk(sk); |
---|
581 | 574 | int err = 0; |
---|
582 | 575 | |
---|
583 | | - if (len < sizeof(*addr)) |
---|
584 | | - return -EINVAL; |
---|
| 576 | + err = ieee802154_sockaddr_check_size(addr, len); |
---|
| 577 | + if (err < 0) |
---|
| 578 | + return err; |
---|
585 | 579 | |
---|
586 | 580 | if (addr->family != AF_IEEE802154) |
---|
587 | 581 | return -EINVAL; |
---|
.. | .. |
---|
620 | 614 | struct ieee802154_mac_cb *cb; |
---|
621 | 615 | struct dgram_sock *ro = dgram_sk(sk); |
---|
622 | 616 | struct ieee802154_addr dst_addr; |
---|
| 617 | + DECLARE_SOCKADDR(struct sockaddr_ieee802154*, daddr, msg->msg_name); |
---|
623 | 618 | int hlen, tlen; |
---|
624 | 619 | int err; |
---|
625 | 620 | |
---|
.. | .. |
---|
628 | 623 | return -EOPNOTSUPP; |
---|
629 | 624 | } |
---|
630 | 625 | |
---|
631 | | - if (!ro->connected && !msg->msg_name) |
---|
632 | | - return -EDESTADDRREQ; |
---|
633 | | - else if (ro->connected && msg->msg_name) |
---|
634 | | - return -EISCONN; |
---|
| 626 | + if (msg->msg_name) { |
---|
| 627 | + if (ro->connected) |
---|
| 628 | + return -EISCONN; |
---|
| 629 | + if (msg->msg_namelen < IEEE802154_MIN_NAMELEN) |
---|
| 630 | + return -EINVAL; |
---|
| 631 | + err = ieee802154_sockaddr_check_size(daddr, msg->msg_namelen); |
---|
| 632 | + if (err < 0) |
---|
| 633 | + return err; |
---|
| 634 | + ieee802154_addr_from_sa(&dst_addr, &daddr->addr); |
---|
| 635 | + } else { |
---|
| 636 | + if (!ro->connected) |
---|
| 637 | + return -EDESTADDRREQ; |
---|
| 638 | + dst_addr = ro->dst_addr; |
---|
| 639 | + } |
---|
635 | 640 | |
---|
636 | 641 | if (!ro->bound) |
---|
637 | 642 | dev = dev_getfirstbyhwtype(sock_net(sk), ARPHRD_IEEE802154); |
---|
.. | .. |
---|
667 | 672 | cb = mac_cb_init(skb); |
---|
668 | 673 | cb->type = IEEE802154_FC_TYPE_DATA; |
---|
669 | 674 | cb->ackreq = ro->want_ack; |
---|
670 | | - |
---|
671 | | - if (msg->msg_name) { |
---|
672 | | - DECLARE_SOCKADDR(struct sockaddr_ieee802154*, |
---|
673 | | - daddr, msg->msg_name); |
---|
674 | | - |
---|
675 | | - ieee802154_addr_from_sa(&dst_addr, &daddr->addr); |
---|
676 | | - } else { |
---|
677 | | - dst_addr = ro->dst_addr; |
---|
678 | | - } |
---|
679 | | - |
---|
680 | 675 | cb->secen = ro->secen; |
---|
681 | 676 | cb->secen_override = ro->secen_override; |
---|
682 | 677 | cb->seclevel = ro->seclevel; |
---|
.. | .. |
---|
887 | 882 | } |
---|
888 | 883 | |
---|
889 | 884 | static int dgram_setsockopt(struct sock *sk, int level, int optname, |
---|
890 | | - char __user *optval, unsigned int optlen) |
---|
| 885 | + sockptr_t optval, unsigned int optlen) |
---|
891 | 886 | { |
---|
892 | 887 | struct dgram_sock *ro = dgram_sk(sk); |
---|
893 | 888 | struct net *net = sock_net(sk); |
---|
.. | .. |
---|
897 | 892 | if (optlen < sizeof(int)) |
---|
898 | 893 | return -EINVAL; |
---|
899 | 894 | |
---|
900 | | - if (get_user(val, (int __user *)optval)) |
---|
| 895 | + if (copy_from_sockptr(&val, optval, sizeof(int))) |
---|
901 | 896 | return -EFAULT; |
---|
902 | 897 | |
---|
903 | 898 | lock_sock(sk); |
---|
.. | .. |
---|
988 | 983 | .getname = sock_no_getname, |
---|
989 | 984 | .poll = datagram_poll, |
---|
990 | 985 | .ioctl = ieee802154_sock_ioctl, |
---|
| 986 | + .gettstamp = sock_gettstamp, |
---|
991 | 987 | .listen = sock_no_listen, |
---|
992 | 988 | .shutdown = sock_no_shutdown, |
---|
993 | 989 | .setsockopt = sock_common_setsockopt, |
---|
.. | .. |
---|
996 | 992 | .recvmsg = sock_common_recvmsg, |
---|
997 | 993 | .mmap = sock_no_mmap, |
---|
998 | 994 | .sendpage = sock_no_sendpage, |
---|
999 | | -#ifdef CONFIG_COMPAT |
---|
1000 | | - .compat_setsockopt = compat_sock_common_setsockopt, |
---|
1001 | | - .compat_getsockopt = compat_sock_common_getsockopt, |
---|
1002 | | -#endif |
---|
1003 | 995 | }; |
---|
1004 | 996 | |
---|
1005 | 997 | static void ieee802154_sock_destruct(struct sock *sk) |
---|
.. | .. |
---|
1110 | 1102 | |
---|
1111 | 1103 | static int __init af_ieee802154_init(void) |
---|
1112 | 1104 | { |
---|
1113 | | - int rc = -EINVAL; |
---|
| 1105 | + int rc; |
---|
1114 | 1106 | |
---|
1115 | 1107 | rc = proto_register(&ieee802154_raw_prot, 1); |
---|
1116 | 1108 | if (rc) |
---|