1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Ioctl handler 4 * Linux ethernet bridge 5 * 6 * Authors: 7 * Lennert Buytenhek <buytenh@gnu.org> 8 */ 9 10 #include <linux/capability.h> 11 #include <linux/kernel.h> 12 #include <linux/if_bridge.h> 13 #include <linux/netdevice.h> 14 #include <linux/slab.h> 15 #include <linux/times.h> 16 #include <net/net_namespace.h> 17 #include <linux/uaccess.h> 18 #include "br_private.h" 19 20 static int get_bridge_ifindices(struct net *net, int *indices, int num) 21 { 22 struct net_device *dev; 23 int i = 0; 24 25 rcu_read_lock(); 26 for_each_netdev_rcu(net, dev) { 27 if (i >= num) 28 break; 29 if (netif_is_bridge_master(dev)) 30 indices[i++] = dev->ifindex; 31 } 32 rcu_read_unlock(); 33 34 return i; 35 } 36 37 /* called with RTNL */ 38 static void get_port_ifindices(struct net_bridge *br, int *ifindices, int num) 39 { 40 struct net_bridge_port *p; 41 42 list_for_each_entry(p, &br->port_list, list) { 43 if (p->port_no < num) 44 ifindices[p->port_no] = p->dev->ifindex; 45 } 46 } 47 48 /* 49 * Format up to a page worth of forwarding table entries 50 * userbuf -- where to copy result 51 * maxnum -- maximum number of entries desired 52 * (limited to a page for sanity) 53 * offset -- number of records to skip 54 */ 55 static int get_fdb_entries(struct net_bridge *br, void __user *userbuf, 56 unsigned long maxnum, unsigned long offset) 57 { 58 int num; 59 void *buf; 60 size_t size; 61 62 /* Clamp size to PAGE_SIZE, test maxnum to avoid overflow */ 63 if (maxnum > PAGE_SIZE/sizeof(struct __fdb_entry)) 64 maxnum = PAGE_SIZE/sizeof(struct __fdb_entry); 65 66 size = maxnum * sizeof(struct __fdb_entry); 67 68 buf = kmalloc(size, GFP_USER); 69 if (!buf) 70 return -ENOMEM; 71 72 num = br_fdb_fillbuf(br, buf, maxnum, offset); 73 if (num > 0) { 74 if (copy_to_user(userbuf, buf, 75 array_size(num, sizeof(struct __fdb_entry)))) 76 num = -EFAULT; 77 } 78 kfree(buf); 79 80 return num; 81 } 82 83 /* called with RTNL */ 84 static int add_del_if(struct net_bridge *br, int ifindex, int isadd) 85 { 86 struct net *net = dev_net(br->dev); 87 struct net_device *dev; 88 int ret; 89 90 if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) 91 return -EPERM; 92 93 dev = __dev_get_by_index(net, ifindex); 94 if (dev == NULL) 95 return -EINVAL; 96 97 if (isadd) 98 ret = br_add_if(br, dev, NULL); 99 else 100 ret = br_del_if(br, dev); 101 102 return ret; 103 } 104 105 /* 106 * Legacy ioctl's through SIOCDEVPRIVATE 107 * This interface is deprecated because it was too difficult 108 * to do the translation for 32/64bit ioctl compatibility. 109 */ 110 int br_dev_siocdevprivate(struct net_device *dev, struct ifreq *rq, void __user *data, int cmd) 111 { 112 struct net_bridge *br = netdev_priv(dev); 113 struct net_bridge_port *p = NULL; 114 unsigned long args[4]; 115 void __user *argp; 116 int ret = -EOPNOTSUPP; 117 118 if (in_compat_syscall()) { 119 unsigned int cargs[4]; 120 121 if (copy_from_user(cargs, data, sizeof(cargs))) 122 return -EFAULT; 123 124 args[0] = cargs[0]; 125 args[1] = cargs[1]; 126 args[2] = cargs[2]; 127 args[3] = cargs[3]; 128 129 argp = compat_ptr(args[1]); 130 } else { 131 if (copy_from_user(args, data, sizeof(args))) 132 return -EFAULT; 133 134 argp = (void __user *)args[1]; 135 } 136 137 switch (args[0]) { 138 case BRCTL_ADD_IF: 139 case BRCTL_DEL_IF: 140 return add_del_if(br, args[1], args[0] == BRCTL_ADD_IF); 141 142 case BRCTL_GET_BRIDGE_INFO: 143 { 144 struct __bridge_info b; 145 146 memset(&b, 0, sizeof(struct __bridge_info)); 147 rcu_read_lock(); 148 memcpy(&b.designated_root, &br->designated_root, 8); 149 memcpy(&b.bridge_id, &br->bridge_id, 8); 150 b.root_path_cost = br->root_path_cost; 151 b.max_age = jiffies_to_clock_t(br->max_age); 152 b.hello_time = jiffies_to_clock_t(br->hello_time); 153 b.forward_delay = br->forward_delay; 154 b.bridge_max_age = br->bridge_max_age; 155 b.bridge_hello_time = br->bridge_hello_time; 156 b.bridge_forward_delay = jiffies_to_clock_t(br->bridge_forward_delay); 157 b.topology_change = br->topology_change; 158 b.topology_change_detected = br->topology_change_detected; 159 b.root_port = br->root_port; 160 161 b.stp_enabled = (br->stp_enabled != BR_NO_STP); 162 b.ageing_time = jiffies_to_clock_t(br->ageing_time); 163 b.hello_timer_value = br_timer_value(&br->hello_timer); 164 b.tcn_timer_value = br_timer_value(&br->tcn_timer); 165 b.topology_change_timer_value = br_timer_value(&br->topology_change_timer); 166 b.gc_timer_value = br_timer_value(&br->gc_work.timer); 167 rcu_read_unlock(); 168 169 if (copy_to_user((void __user *)args[1], &b, sizeof(b))) 170 return -EFAULT; 171 172 return 0; 173 } 174 175 case BRCTL_GET_PORT_LIST: 176 { 177 int num, *indices; 178 179 num = args[2]; 180 if (num < 0) 181 return -EINVAL; 182 if (num == 0) 183 num = 256; 184 if (num > BR_MAX_PORTS) 185 num = BR_MAX_PORTS; 186 187 indices = kcalloc(num, sizeof(int), GFP_KERNEL); 188 if (indices == NULL) 189 return -ENOMEM; 190 191 get_port_ifindices(br, indices, num); 192 if (copy_to_user(argp, indices, array_size(num, sizeof(int)))) 193 num = -EFAULT; 194 kfree(indices); 195 return num; 196 } 197 198 case BRCTL_SET_BRIDGE_FORWARD_DELAY: 199 if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN)) 200 return -EPERM; 201 202 ret = br_set_forward_delay(br, args[1]); 203 break; 204 205 case BRCTL_SET_BRIDGE_HELLO_TIME: 206 if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN)) 207 return -EPERM; 208 209 ret = br_set_hello_time(br, args[1]); 210 break; 211 212 case BRCTL_SET_BRIDGE_MAX_AGE: 213 if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN)) 214 return -EPERM; 215 216 ret = br_set_max_age(br, args[1]); 217 break; 218 219 case BRCTL_SET_AGEING_TIME: 220 if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN)) 221 return -EPERM; 222 223 ret = br_set_ageing_time(br, args[1]); 224 break; 225 226 case BRCTL_GET_PORT_INFO: 227 { 228 struct __port_info p; 229 struct net_bridge_port *pt; 230 231 rcu_read_lock(); 232 if ((pt = br_get_port(br, args[2])) == NULL) { 233 rcu_read_unlock(); 234 return -EINVAL; 235 } 236 237 memset(&p, 0, sizeof(struct __port_info)); 238 memcpy(&p.designated_root, &pt->designated_root, 8); 239 memcpy(&p.designated_bridge, &pt->designated_bridge, 8); 240 p.port_id = pt->port_id; 241 p.designated_port = pt->designated_port; 242 p.path_cost = pt->path_cost; 243 p.designated_cost = pt->designated_cost; 244 p.state = pt->state; 245 p.top_change_ack = pt->topology_change_ack; 246 p.config_pending = pt->config_pending; 247 p.message_age_timer_value = br_timer_value(&pt->message_age_timer); 248 p.forward_delay_timer_value = br_timer_value(&pt->forward_delay_timer); 249 p.hold_timer_value = br_timer_value(&pt->hold_timer); 250 251 rcu_read_unlock(); 252 253 if (copy_to_user(argp, &p, sizeof(p))) 254 return -EFAULT; 255 256 return 0; 257 } 258 259 case BRCTL_SET_BRIDGE_STP_STATE: 260 if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN)) 261 return -EPERM; 262 263 ret = br_stp_set_enabled(br, args[1], NULL); 264 break; 265 266 case BRCTL_SET_BRIDGE_PRIORITY: 267 if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN)) 268 return -EPERM; 269 270 br_stp_set_bridge_priority(br, args[1]); 271 ret = 0; 272 break; 273 274 case BRCTL_SET_PORT_PRIORITY: 275 { 276 if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN)) 277 return -EPERM; 278 279 spin_lock_bh(&br->lock); 280 if ((p = br_get_port(br, args[1])) == NULL) 281 ret = -EINVAL; 282 else 283 ret = br_stp_set_port_priority(p, args[2]); 284 spin_unlock_bh(&br->lock); 285 break; 286 } 287 288 case BRCTL_SET_PATH_COST: 289 { 290 if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN)) 291 return -EPERM; 292 293 spin_lock_bh(&br->lock); 294 if ((p = br_get_port(br, args[1])) == NULL) 295 ret = -EINVAL; 296 else 297 ret = br_stp_set_path_cost(p, args[2]); 298 spin_unlock_bh(&br->lock); 299 break; 300 } 301 302 case BRCTL_GET_FDB_ENTRIES: 303 return get_fdb_entries(br, argp, args[2], args[3]); 304 } 305 306 if (!ret) { 307 if (p) 308 br_ifinfo_notify(RTM_NEWLINK, NULL, p); 309 else 310 netdev_state_change(br->dev); 311 } 312 313 return ret; 314 } 315 316 static int old_deviceless(struct net *net, void __user *uarg) 317 { 318 unsigned long args[3]; 319 320 if (copy_from_user(args, uarg, sizeof(args))) 321 return -EFAULT; 322 323 switch (args[0]) { 324 case BRCTL_GET_VERSION: 325 return BRCTL_VERSION; 326 327 case BRCTL_GET_BRIDGES: 328 { 329 int *indices; 330 int ret = 0; 331 332 if (args[2] >= 2048) 333 return -ENOMEM; 334 indices = kcalloc(args[2], sizeof(int), GFP_KERNEL); 335 if (indices == NULL) 336 return -ENOMEM; 337 338 args[2] = get_bridge_ifindices(net, indices, args[2]); 339 340 ret = copy_to_user(uarg, indices, 341 array_size(args[2], sizeof(int))) 342 ? -EFAULT : args[2]; 343 344 kfree(indices); 345 return ret; 346 } 347 348 case BRCTL_ADD_BRIDGE: 349 case BRCTL_DEL_BRIDGE: 350 { 351 char buf[IFNAMSIZ]; 352 353 if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) 354 return -EPERM; 355 356 if (copy_from_user(buf, (void __user *)args[1], IFNAMSIZ)) 357 return -EFAULT; 358 359 buf[IFNAMSIZ-1] = 0; 360 361 if (args[0] == BRCTL_ADD_BRIDGE) 362 return br_add_bridge(net, buf); 363 364 return br_del_bridge(net, buf); 365 } 366 } 367 368 return -EOPNOTSUPP; 369 } 370 371 int br_ioctl_stub(struct net *net, struct net_bridge *br, unsigned int cmd, 372 struct ifreq *ifr, void __user *uarg) 373 { 374 int ret = -EOPNOTSUPP; 375 376 rtnl_lock(); 377 378 switch (cmd) { 379 case SIOCGIFBR: 380 case SIOCSIFBR: 381 ret = old_deviceless(net, uarg); 382 break; 383 case SIOCBRADDBR: 384 case SIOCBRDELBR: 385 { 386 char buf[IFNAMSIZ]; 387 388 if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) { 389 ret = -EPERM; 390 break; 391 } 392 393 if (copy_from_user(buf, uarg, IFNAMSIZ)) { 394 ret = -EFAULT; 395 break; 396 } 397 398 buf[IFNAMSIZ-1] = 0; 399 if (cmd == SIOCBRADDBR) 400 ret = br_add_bridge(net, buf); 401 else 402 ret = br_del_bridge(net, buf); 403 } 404 break; 405 case SIOCBRADDIF: 406 case SIOCBRDELIF: 407 ret = add_del_if(br, ifr->ifr_ifindex, cmd == SIOCBRADDIF); 408 break; 409 } 410 411 rtnl_unlock(); 412 413 return ret; 414 } 415