| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 3 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 4 | | - * the Free Software Foundation; either version 2 of the License, or |
|---|
| 5 | | - * (at your option) any later version. |
|---|
| 6 | 3 | * |
|---|
| 7 | 4 | * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk) |
|---|
| 8 | 5 | * Copyright (C) Alan Cox GW4PTS (alan@lxorguk.ukuu.org.uk) |
|---|
| .. | .. |
|---|
| 194 | 191 | rose_disconnect(s, ENETUNREACH, ROSE_OUT_OF_ORDER, 0); |
|---|
| 195 | 192 | if (rose->neighbour) |
|---|
| 196 | 193 | rose->neighbour->use--; |
|---|
| 194 | + dev_put(rose->device); |
|---|
| 197 | 195 | rose->device = NULL; |
|---|
| 198 | 196 | } |
|---|
| 199 | 197 | } |
|---|
| .. | .. |
|---|
| 368 | 366 | */ |
|---|
| 369 | 367 | |
|---|
| 370 | 368 | static int rose_setsockopt(struct socket *sock, int level, int optname, |
|---|
| 371 | | - char __user *optval, unsigned int optlen) |
|---|
| 369 | + sockptr_t optval, unsigned int optlen) |
|---|
| 372 | 370 | { |
|---|
| 373 | 371 | struct sock *sk = sock->sk; |
|---|
| 374 | 372 | struct rose_sock *rose = rose_sk(sk); |
|---|
| .. | .. |
|---|
| 380 | 378 | if (optlen < sizeof(int)) |
|---|
| 381 | 379 | return -EINVAL; |
|---|
| 382 | 380 | |
|---|
| 383 | | - if (get_user(opt, (int __user *)optval)) |
|---|
| 381 | + if (copy_from_sockptr(&opt, optval, sizeof(int))) |
|---|
| 384 | 382 | return -EFAULT; |
|---|
| 385 | 383 | |
|---|
| 386 | 384 | switch (optname) { |
|---|
| .. | .. |
|---|
| 489 | 487 | { |
|---|
| 490 | 488 | struct sock *sk = sock->sk; |
|---|
| 491 | 489 | |
|---|
| 490 | + lock_sock(sk); |
|---|
| 491 | + if (sock->state != SS_UNCONNECTED) { |
|---|
| 492 | + release_sock(sk); |
|---|
| 493 | + return -EINVAL; |
|---|
| 494 | + } |
|---|
| 495 | + |
|---|
| 492 | 496 | if (sk->sk_state != TCP_LISTEN) { |
|---|
| 493 | 497 | struct rose_sock *rose = rose_sk(sk); |
|---|
| 494 | 498 | |
|---|
| .. | .. |
|---|
| 498 | 502 | memset(rose->dest_digis, 0, AX25_ADDR_LEN * ROSE_MAX_DIGIS); |
|---|
| 499 | 503 | sk->sk_max_ack_backlog = backlog; |
|---|
| 500 | 504 | sk->sk_state = TCP_LISTEN; |
|---|
| 505 | + release_sock(sk); |
|---|
| 501 | 506 | return 0; |
|---|
| 502 | 507 | } |
|---|
| 508 | + release_sock(sk); |
|---|
| 503 | 509 | |
|---|
| 504 | 510 | return -EOPNOTSUPP; |
|---|
| 505 | 511 | } |
|---|
| .. | .. |
|---|
| 594 | 600 | rose->idle = orose->idle; |
|---|
| 595 | 601 | rose->defer = orose->defer; |
|---|
| 596 | 602 | rose->device = orose->device; |
|---|
| 603 | + if (rose->device) |
|---|
| 604 | + dev_hold(rose->device); |
|---|
| 597 | 605 | rose->qbitincl = orose->qbitincl; |
|---|
| 598 | 606 | |
|---|
| 599 | 607 | return sk; |
|---|
| .. | .. |
|---|
| 647 | 655 | break; |
|---|
| 648 | 656 | } |
|---|
| 649 | 657 | |
|---|
| 658 | + dev_put(rose->device); |
|---|
| 650 | 659 | sock->sk = NULL; |
|---|
| 651 | 660 | release_sock(sk); |
|---|
| 652 | 661 | sock_put(sk); |
|---|
| .. | .. |
|---|
| 689 | 698 | rose->source_call = user->call; |
|---|
| 690 | 699 | ax25_uid_put(user); |
|---|
| 691 | 700 | } else { |
|---|
| 692 | | - if (ax25_uid_policy && !capable(CAP_NET_BIND_SERVICE)) |
|---|
| 701 | + if (ax25_uid_policy && !capable(CAP_NET_BIND_SERVICE)) { |
|---|
| 702 | + dev_put(dev); |
|---|
| 693 | 703 | return -EACCES; |
|---|
| 704 | + } |
|---|
| 694 | 705 | rose->source_call = *source; |
|---|
| 695 | 706 | } |
|---|
| 696 | 707 | |
|---|
| .. | .. |
|---|
| 721 | 732 | struct rose_sock *rose = rose_sk(sk); |
|---|
| 722 | 733 | struct sockaddr_rose *addr = (struct sockaddr_rose *)uaddr; |
|---|
| 723 | 734 | unsigned char cause, diagnostic; |
|---|
| 724 | | - struct net_device *dev; |
|---|
| 725 | 735 | ax25_uid_assoc *user; |
|---|
| 726 | 736 | int n, err = 0; |
|---|
| 727 | 737 | |
|---|
| .. | .. |
|---|
| 778 | 788 | } |
|---|
| 779 | 789 | |
|---|
| 780 | 790 | if (sock_flag(sk, SOCK_ZAPPED)) { /* Must bind first - autobinding in this may or may not work */ |
|---|
| 791 | + struct net_device *dev; |
|---|
| 792 | + |
|---|
| 781 | 793 | sock_reset_flag(sk, SOCK_ZAPPED); |
|---|
| 782 | 794 | |
|---|
| 783 | | - if ((dev = rose_dev_first()) == NULL) { |
|---|
| 795 | + dev = rose_dev_first(); |
|---|
| 796 | + if (!dev) { |
|---|
| 784 | 797 | err = -ENETUNREACH; |
|---|
| 785 | 798 | goto out_release; |
|---|
| 786 | 799 | } |
|---|
| .. | .. |
|---|
| 788 | 801 | user = ax25_findbyuid(current_euid()); |
|---|
| 789 | 802 | if (!user) { |
|---|
| 790 | 803 | err = -EINVAL; |
|---|
| 804 | + dev_put(dev); |
|---|
| 791 | 805 | goto out_release; |
|---|
| 792 | 806 | } |
|---|
| 793 | 807 | |
|---|
| .. | .. |
|---|
| 929 | 943 | /* Now attach up the new socket */ |
|---|
| 930 | 944 | skb->sk = NULL; |
|---|
| 931 | 945 | kfree_skb(skb); |
|---|
| 932 | | - sk->sk_ack_backlog--; |
|---|
| 946 | + sk_acceptq_removed(sk); |
|---|
| 933 | 947 | |
|---|
| 934 | 948 | out_release: |
|---|
| 935 | 949 | release_sock(sk); |
|---|
| .. | .. |
|---|
| 1034 | 1048 | make_rose->va = 0; |
|---|
| 1035 | 1049 | make_rose->vr = 0; |
|---|
| 1036 | 1050 | make_rose->vl = 0; |
|---|
| 1037 | | - sk->sk_ack_backlog++; |
|---|
| 1051 | + sk_acceptq_added(sk); |
|---|
| 1038 | 1052 | |
|---|
| 1039 | 1053 | rose_insert_socket(make); |
|---|
| 1040 | 1054 | |
|---|
| .. | .. |
|---|
| 1299 | 1313 | return put_user(amount, (unsigned int __user *) argp); |
|---|
| 1300 | 1314 | } |
|---|
| 1301 | 1315 | |
|---|
| 1302 | | - case SIOCGSTAMP: |
|---|
| 1303 | | - return sock_get_timestamp(sk, (struct timeval __user *) argp); |
|---|
| 1304 | | - |
|---|
| 1305 | | - case SIOCGSTAMPNS: |
|---|
| 1306 | | - return sock_get_timestampns(sk, (struct timespec __user *) argp); |
|---|
| 1307 | | - |
|---|
| 1308 | 1316 | case SIOCGIFADDR: |
|---|
| 1309 | 1317 | case SIOCSIFADDR: |
|---|
| 1310 | 1318 | case SIOCGIFDSTADDR: |
|---|
| .. | .. |
|---|
| 1472 | 1480 | .getname = rose_getname, |
|---|
| 1473 | 1481 | .poll = datagram_poll, |
|---|
| 1474 | 1482 | .ioctl = rose_ioctl, |
|---|
| 1483 | + .gettstamp = sock_gettstamp, |
|---|
| 1475 | 1484 | .listen = rose_listen, |
|---|
| 1476 | 1485 | .shutdown = sock_no_shutdown, |
|---|
| 1477 | 1486 | .setsockopt = rose_setsockopt, |
|---|
| .. | .. |
|---|
| 1503 | 1512 | int rc; |
|---|
| 1504 | 1513 | |
|---|
| 1505 | 1514 | if (rose_ndevs > 0x7FFFFFFF/sizeof(struct net_device *)) { |
|---|
| 1506 | | - printk(KERN_ERR "ROSE: rose_proto_init - rose_ndevs parameter to large\n"); |
|---|
| 1515 | + printk(KERN_ERR "ROSE: rose_proto_init - rose_ndevs parameter too large\n"); |
|---|
| 1507 | 1516 | rc = -EINVAL; |
|---|
| 1508 | 1517 | goto out; |
|---|
| 1509 | 1518 | } |
|---|