| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright (C) 2011 Intel Corporation. All rights reserved. |
|---|
| 3 | | - * |
|---|
| 4 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 5 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 6 | | - * the Free Software Foundation; either version 2 of the License, or |
|---|
| 7 | | - * (at your option) any later version. |
|---|
| 8 | | - * |
|---|
| 9 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 10 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 11 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 12 | | - * GNU General Public License for more details. |
|---|
| 13 | | - * |
|---|
| 14 | | - * You should have received a copy of the GNU General Public License |
|---|
| 15 | | - * along with this program; if not, see <http://www.gnu.org/licenses/>. |
|---|
| 16 | 4 | */ |
|---|
| 17 | 5 | |
|---|
| 18 | 6 | #define pr_fmt(fmt) "llcp: %s: " fmt, __func__ |
|---|
| .. | .. |
|---|
| 111 | 99 | } |
|---|
| 112 | 100 | |
|---|
| 113 | 101 | llcp_sock->dev = dev; |
|---|
| 114 | | - llcp_sock->local = nfc_llcp_local_get(local); |
|---|
| 102 | + llcp_sock->local = local; |
|---|
| 115 | 103 | llcp_sock->nfc_protocol = llcp_addr.nfc_protocol; |
|---|
| 116 | 104 | llcp_sock->service_name_len = min_t(unsigned int, |
|---|
| 117 | 105 | llcp_addr.service_name_len, |
|---|
| .. | .. |
|---|
| 193 | 181 | } |
|---|
| 194 | 182 | |
|---|
| 195 | 183 | llcp_sock->dev = dev; |
|---|
| 196 | | - llcp_sock->local = nfc_llcp_local_get(local); |
|---|
| 184 | + llcp_sock->local = local; |
|---|
| 197 | 185 | llcp_sock->nfc_protocol = llcp_addr.nfc_protocol; |
|---|
| 198 | 186 | |
|---|
| 199 | 187 | nfc_llcp_sock_link(&local->raw_sockets, sk); |
|---|
| .. | .. |
|---|
| 236 | 224 | } |
|---|
| 237 | 225 | |
|---|
| 238 | 226 | static int nfc_llcp_setsockopt(struct socket *sock, int level, int optname, |
|---|
| 239 | | - char __user *optval, unsigned int optlen) |
|---|
| 227 | + sockptr_t optval, unsigned int optlen) |
|---|
| 240 | 228 | { |
|---|
| 241 | 229 | struct sock *sk = sock->sk; |
|---|
| 242 | 230 | struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk); |
|---|
| .. | .. |
|---|
| 259 | 247 | break; |
|---|
| 260 | 248 | } |
|---|
| 261 | 249 | |
|---|
| 262 | | - if (get_user(opt, (u32 __user *) optval)) { |
|---|
| 250 | + if (copy_from_sockptr(&opt, optval, sizeof(u32))) { |
|---|
| 263 | 251 | err = -EFAULT; |
|---|
| 264 | 252 | break; |
|---|
| 265 | 253 | } |
|---|
| .. | .. |
|---|
| 281 | 269 | break; |
|---|
| 282 | 270 | } |
|---|
| 283 | 271 | |
|---|
| 284 | | - if (get_user(opt, (u32 __user *) optval)) { |
|---|
| 272 | + if (copy_from_sockptr(&opt, optval, sizeof(u32))) { |
|---|
| 285 | 273 | err = -EFAULT; |
|---|
| 286 | 274 | break; |
|---|
| 287 | 275 | } |
|---|
| .. | .. |
|---|
| 710 | 698 | if (dev->dep_link_up == false) { |
|---|
| 711 | 699 | ret = -ENOLINK; |
|---|
| 712 | 700 | device_unlock(&dev->dev); |
|---|
| 713 | | - goto put_dev; |
|---|
| 701 | + goto sock_llcp_put_local; |
|---|
| 714 | 702 | } |
|---|
| 715 | 703 | device_unlock(&dev->dev); |
|---|
| 716 | 704 | |
|---|
| 717 | 705 | if (local->rf_mode == NFC_RF_INITIATOR && |
|---|
| 718 | 706 | addr->target_idx != local->target_idx) { |
|---|
| 719 | 707 | ret = -ENOLINK; |
|---|
| 720 | | - goto put_dev; |
|---|
| 708 | + goto sock_llcp_put_local; |
|---|
| 721 | 709 | } |
|---|
| 722 | 710 | |
|---|
| 723 | 711 | llcp_sock->dev = dev; |
|---|
| 724 | | - llcp_sock->local = nfc_llcp_local_get(local); |
|---|
| 712 | + llcp_sock->local = local; |
|---|
| 725 | 713 | llcp_sock->ssap = nfc_llcp_get_local_ssap(local); |
|---|
| 726 | 714 | if (llcp_sock->ssap == LLCP_SAP_MAX) { |
|---|
| 727 | | - nfc_llcp_local_put(llcp_sock->local); |
|---|
| 728 | | - llcp_sock->local = NULL; |
|---|
| 729 | 715 | ret = -ENOMEM; |
|---|
| 730 | | - goto put_dev; |
|---|
| 716 | + goto sock_llcp_nullify; |
|---|
| 731 | 717 | } |
|---|
| 732 | 718 | |
|---|
| 733 | 719 | llcp_sock->reserved_ssap = llcp_sock->ssap; |
|---|
| .. | .. |
|---|
| 743 | 729 | llcp_sock->service_name = kmemdup(addr->service_name, |
|---|
| 744 | 730 | llcp_sock->service_name_len, |
|---|
| 745 | 731 | GFP_KERNEL); |
|---|
| 732 | + if (!llcp_sock->service_name) { |
|---|
| 733 | + ret = -ENOMEM; |
|---|
| 734 | + goto sock_llcp_release; |
|---|
| 735 | + } |
|---|
| 746 | 736 | |
|---|
| 747 | 737 | nfc_llcp_sock_link(&local->connecting_sockets, sk); |
|---|
| 748 | 738 | |
|---|
| .. | .. |
|---|
| 762 | 752 | return ret; |
|---|
| 763 | 753 | |
|---|
| 764 | 754 | sock_unlink: |
|---|
| 765 | | - nfc_llcp_put_ssap(local, llcp_sock->ssap); |
|---|
| 766 | | - nfc_llcp_local_put(llcp_sock->local); |
|---|
| 767 | | - llcp_sock->local = NULL; |
|---|
| 768 | | - |
|---|
| 769 | 755 | nfc_llcp_sock_unlink(&local->connecting_sockets, sk); |
|---|
| 770 | 756 | kfree(llcp_sock->service_name); |
|---|
| 771 | 757 | llcp_sock->service_name = NULL; |
|---|
| 758 | + |
|---|
| 759 | +sock_llcp_release: |
|---|
| 760 | + nfc_llcp_put_ssap(local, llcp_sock->ssap); |
|---|
| 761 | + |
|---|
| 762 | +sock_llcp_nullify: |
|---|
| 763 | + llcp_sock->local = NULL; |
|---|
| 764 | + llcp_sock->dev = NULL; |
|---|
| 765 | + |
|---|
| 766 | +sock_llcp_put_local: |
|---|
| 767 | + nfc_llcp_local_put(local); |
|---|
| 772 | 768 | |
|---|
| 773 | 769 | put_dev: |
|---|
| 774 | 770 | nfc_put_device(dev); |
|---|
| .. | .. |
|---|
| 949 | 945 | .ioctl = sock_no_ioctl, |
|---|
| 950 | 946 | .listen = sock_no_listen, |
|---|
| 951 | 947 | .shutdown = sock_no_shutdown, |
|---|
| 952 | | - .setsockopt = sock_no_setsockopt, |
|---|
| 953 | | - .getsockopt = sock_no_getsockopt, |
|---|
| 954 | 948 | .sendmsg = sock_no_sendmsg, |
|---|
| 955 | 949 | .recvmsg = llcp_sock_recvmsg, |
|---|
| 956 | 950 | .mmap = sock_no_mmap, |
|---|