| .. | .. |
|---|
| 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 | */ |
|---|
| .. | .. |
|---|
| 40 | 37 | for (ax25_dev = ax25_dev_list; ax25_dev != NULL; ax25_dev = ax25_dev->next) |
|---|
| 41 | 38 | if (ax25cmp(addr, (ax25_address *)ax25_dev->dev->dev_addr) == 0) { |
|---|
| 42 | 39 | res = ax25_dev; |
|---|
| 40 | + ax25_dev_hold(ax25_dev); |
|---|
| 43 | 41 | } |
|---|
| 44 | 42 | spin_unlock_bh(&ax25_dev_lock); |
|---|
| 45 | 43 | |
|---|
| .. | .. |
|---|
| 59 | 57 | return; |
|---|
| 60 | 58 | } |
|---|
| 61 | 59 | |
|---|
| 60 | + refcount_set(&ax25_dev->refcount, 1); |
|---|
| 62 | 61 | dev->ax25_ptr = ax25_dev; |
|---|
| 63 | 62 | ax25_dev->dev = dev; |
|---|
| 64 | 63 | dev_hold(dev); |
|---|
| .. | .. |
|---|
| 87 | 86 | ax25_dev->next = ax25_dev_list; |
|---|
| 88 | 87 | ax25_dev_list = ax25_dev; |
|---|
| 89 | 88 | spin_unlock_bh(&ax25_dev_lock); |
|---|
| 89 | + ax25_dev_hold(ax25_dev); |
|---|
| 90 | 90 | |
|---|
| 91 | 91 | ax25_register_dev_sysctl(ax25_dev); |
|---|
| 92 | 92 | } |
|---|
| .. | .. |
|---|
| 116 | 116 | if ((s = ax25_dev_list) == ax25_dev) { |
|---|
| 117 | 117 | ax25_dev_list = s->next; |
|---|
| 118 | 118 | spin_unlock_bh(&ax25_dev_lock); |
|---|
| 119 | + ax25_dev_put(ax25_dev); |
|---|
| 119 | 120 | dev->ax25_ptr = NULL; |
|---|
| 120 | 121 | dev_put(dev); |
|---|
| 121 | | - kfree(ax25_dev); |
|---|
| 122 | + ax25_dev_put(ax25_dev); |
|---|
| 122 | 123 | return; |
|---|
| 123 | 124 | } |
|---|
| 124 | 125 | |
|---|
| .. | .. |
|---|
| 126 | 127 | if (s->next == ax25_dev) { |
|---|
| 127 | 128 | s->next = ax25_dev->next; |
|---|
| 128 | 129 | spin_unlock_bh(&ax25_dev_lock); |
|---|
| 130 | + ax25_dev_put(ax25_dev); |
|---|
| 129 | 131 | dev->ax25_ptr = NULL; |
|---|
| 130 | 132 | dev_put(dev); |
|---|
| 131 | | - kfree(ax25_dev); |
|---|
| 133 | + ax25_dev_put(ax25_dev); |
|---|
| 132 | 134 | return; |
|---|
| 133 | 135 | } |
|---|
| 134 | 136 | |
|---|
| .. | .. |
|---|
| 136 | 138 | } |
|---|
| 137 | 139 | spin_unlock_bh(&ax25_dev_lock); |
|---|
| 138 | 140 | dev->ax25_ptr = NULL; |
|---|
| 141 | + ax25_dev_put(ax25_dev); |
|---|
| 139 | 142 | } |
|---|
| 140 | 143 | |
|---|
| 141 | 144 | int ax25_fwd_ioctl(unsigned int cmd, struct ax25_fwd_struct *fwd) |
|---|
| .. | .. |
|---|
| 147 | 150 | |
|---|
| 148 | 151 | switch (cmd) { |
|---|
| 149 | 152 | case SIOCAX25ADDFWD: |
|---|
| 150 | | - if ((fwd_dev = ax25_addr_ax25dev(&fwd->port_to)) == NULL) |
|---|
| 153 | + fwd_dev = ax25_addr_ax25dev(&fwd->port_to); |
|---|
| 154 | + if (!fwd_dev) { |
|---|
| 155 | + ax25_dev_put(ax25_dev); |
|---|
| 151 | 156 | return -EINVAL; |
|---|
| 152 | | - if (ax25_dev->forward != NULL) |
|---|
| 157 | + } |
|---|
| 158 | + if (ax25_dev->forward) { |
|---|
| 159 | + ax25_dev_put(fwd_dev); |
|---|
| 160 | + ax25_dev_put(ax25_dev); |
|---|
| 153 | 161 | return -EINVAL; |
|---|
| 162 | + } |
|---|
| 154 | 163 | ax25_dev->forward = fwd_dev->dev; |
|---|
| 164 | + ax25_dev_put(fwd_dev); |
|---|
| 165 | + ax25_dev_put(ax25_dev); |
|---|
| 155 | 166 | break; |
|---|
| 156 | 167 | |
|---|
| 157 | 168 | case SIOCAX25DELFWD: |
|---|
| 158 | | - if (ax25_dev->forward == NULL) |
|---|
| 169 | + if (!ax25_dev->forward) { |
|---|
| 170 | + ax25_dev_put(ax25_dev); |
|---|
| 159 | 171 | return -EINVAL; |
|---|
| 172 | + } |
|---|
| 160 | 173 | ax25_dev->forward = NULL; |
|---|
| 174 | + ax25_dev_put(ax25_dev); |
|---|
| 161 | 175 | break; |
|---|
| 162 | 176 | |
|---|
| 163 | 177 | default: |
|---|
| 178 | + ax25_dev_put(ax25_dev); |
|---|
| 164 | 179 | return -EINVAL; |
|---|
| 165 | 180 | } |
|---|
| 166 | 181 | |
|---|