diff options
author | Eric Dumazet <eric.dumazet@gmail.com> | 2009-11-05 19:23:01 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-11-08 03:33:43 -0500 |
commit | 6755aebaaf9fc5416acfd4578ab7a1e122ecbc74 (patch) | |
tree | 09f23419b097b15e7c36954cb98bdf28cdfa5af1 | |
parent | cc05368c52fed7d9efa0f56c5270e95bb569713e (diff) |
can: should not use __dev_get_by_index() without locks
bcm_proc_getifname() is called with RTNL and dev_base_lock
not held. It calls __dev_get_by_index() without locks, and
this is illegal (might crash)
Close the race by holding dev_base_lock and copying dev->name
in the protected section.
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: Oliver Hartkopp <oliver@hartkopp.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/can/bcm.c | 19 |
1 files changed, 12 insertions, 7 deletions
diff --git a/net/can/bcm.c b/net/can/bcm.c index 597da4f8f888..e8d58f33fe09 100644 --- a/net/can/bcm.c +++ b/net/can/bcm.c | |||
@@ -132,23 +132,27 @@ static inline struct bcm_sock *bcm_sk(const struct sock *sk) | |||
132 | /* | 132 | /* |
133 | * procfs functions | 133 | * procfs functions |
134 | */ | 134 | */ |
135 | static char *bcm_proc_getifname(int ifindex) | 135 | static char *bcm_proc_getifname(char *result, int ifindex) |
136 | { | 136 | { |
137 | struct net_device *dev; | 137 | struct net_device *dev; |
138 | 138 | ||
139 | if (!ifindex) | 139 | if (!ifindex) |
140 | return "any"; | 140 | return "any"; |
141 | 141 | ||
142 | /* no usage counting */ | 142 | read_lock(&dev_base_lock); |
143 | dev = __dev_get_by_index(&init_net, ifindex); | 143 | dev = __dev_get_by_index(&init_net, ifindex); |
144 | if (dev) | 144 | if (dev) |
145 | return dev->name; | 145 | strcpy(result, dev->name); |
146 | else | ||
147 | strcpy(result, "???"); | ||
148 | read_unlock(&dev_base_lock); | ||
146 | 149 | ||
147 | return "???"; | 150 | return result; |
148 | } | 151 | } |
149 | 152 | ||
150 | static int bcm_proc_show(struct seq_file *m, void *v) | 153 | static int bcm_proc_show(struct seq_file *m, void *v) |
151 | { | 154 | { |
155 | char ifname[IFNAMSIZ]; | ||
152 | struct sock *sk = (struct sock *)m->private; | 156 | struct sock *sk = (struct sock *)m->private; |
153 | struct bcm_sock *bo = bcm_sk(sk); | 157 | struct bcm_sock *bo = bcm_sk(sk); |
154 | struct bcm_op *op; | 158 | struct bcm_op *op; |
@@ -157,7 +161,7 @@ static int bcm_proc_show(struct seq_file *m, void *v) | |||
157 | seq_printf(m, " / sk %p", sk); | 161 | seq_printf(m, " / sk %p", sk); |
158 | seq_printf(m, " / bo %p", bo); | 162 | seq_printf(m, " / bo %p", bo); |
159 | seq_printf(m, " / dropped %lu", bo->dropped_usr_msgs); | 163 | seq_printf(m, " / dropped %lu", bo->dropped_usr_msgs); |
160 | seq_printf(m, " / bound %s", bcm_proc_getifname(bo->ifindex)); | 164 | seq_printf(m, " / bound %s", bcm_proc_getifname(ifname, bo->ifindex)); |
161 | seq_printf(m, " <<<\n"); | 165 | seq_printf(m, " <<<\n"); |
162 | 166 | ||
163 | list_for_each_entry(op, &bo->rx_ops, list) { | 167 | list_for_each_entry(op, &bo->rx_ops, list) { |
@@ -169,7 +173,7 @@ static int bcm_proc_show(struct seq_file *m, void *v) | |||
169 | continue; | 173 | continue; |
170 | 174 | ||
171 | seq_printf(m, "rx_op: %03X %-5s ", | 175 | seq_printf(m, "rx_op: %03X %-5s ", |
172 | op->can_id, bcm_proc_getifname(op->ifindex)); | 176 | op->can_id, bcm_proc_getifname(ifname, op->ifindex)); |
173 | seq_printf(m, "[%d]%c ", op->nframes, | 177 | seq_printf(m, "[%d]%c ", op->nframes, |
174 | (op->flags & RX_CHECK_DLC)?'d':' '); | 178 | (op->flags & RX_CHECK_DLC)?'d':' '); |
175 | if (op->kt_ival1.tv64) | 179 | if (op->kt_ival1.tv64) |
@@ -194,7 +198,8 @@ static int bcm_proc_show(struct seq_file *m, void *v) | |||
194 | list_for_each_entry(op, &bo->tx_ops, list) { | 198 | list_for_each_entry(op, &bo->tx_ops, list) { |
195 | 199 | ||
196 | seq_printf(m, "tx_op: %03X %s [%d] ", | 200 | seq_printf(m, "tx_op: %03X %s [%d] ", |
197 | op->can_id, bcm_proc_getifname(op->ifindex), | 201 | op->can_id, |
202 | bcm_proc_getifname(ifname, op->ifindex), | ||
198 | op->nframes); | 203 | op->nframes); |
199 | 204 | ||
200 | if (op->kt_ival1.tv64) | 205 | if (op->kt_ival1.tv64) |