0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/capability.h>
0011 #include <linux/compat.h>
0012 #include <linux/kernel.h>
0013 #include <linux/if_bridge.h>
0014 #include <linux/netdevice.h>
0015 #include <linux/slab.h>
0016 #include <linux/times.h>
0017 #include <net/net_namespace.h>
0018 #include <linux/uaccess.h>
0019 #include "br_private.h"
0020
0021 static int get_bridge_ifindices(struct net *net, int *indices, int num)
0022 {
0023 struct net_device *dev;
0024 int i = 0;
0025
0026 rcu_read_lock();
0027 for_each_netdev_rcu(net, dev) {
0028 if (i >= num)
0029 break;
0030 if (netif_is_bridge_master(dev))
0031 indices[i++] = dev->ifindex;
0032 }
0033 rcu_read_unlock();
0034
0035 return i;
0036 }
0037
0038
0039 static void get_port_ifindices(struct net_bridge *br, int *ifindices, int num)
0040 {
0041 struct net_bridge_port *p;
0042
0043 list_for_each_entry(p, &br->port_list, list) {
0044 if (p->port_no < num)
0045 ifindices[p->port_no] = p->dev->ifindex;
0046 }
0047 }
0048
0049
0050
0051
0052
0053
0054
0055
0056 static int get_fdb_entries(struct net_bridge *br, void __user *userbuf,
0057 unsigned long maxnum, unsigned long offset)
0058 {
0059 int num;
0060 void *buf;
0061 size_t size;
0062
0063
0064 if (maxnum > PAGE_SIZE/sizeof(struct __fdb_entry))
0065 maxnum = PAGE_SIZE/sizeof(struct __fdb_entry);
0066
0067 size = maxnum * sizeof(struct __fdb_entry);
0068
0069 buf = kmalloc(size, GFP_USER);
0070 if (!buf)
0071 return -ENOMEM;
0072
0073 num = br_fdb_fillbuf(br, buf, maxnum, offset);
0074 if (num > 0) {
0075 if (copy_to_user(userbuf, buf,
0076 array_size(num, sizeof(struct __fdb_entry))))
0077 num = -EFAULT;
0078 }
0079 kfree(buf);
0080
0081 return num;
0082 }
0083
0084
0085 static int add_del_if(struct net_bridge *br, int ifindex, int isadd)
0086 {
0087 struct net *net = dev_net(br->dev);
0088 struct net_device *dev;
0089 int ret;
0090
0091 if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
0092 return -EPERM;
0093
0094 dev = __dev_get_by_index(net, ifindex);
0095 if (dev == NULL)
0096 return -EINVAL;
0097
0098 if (isadd)
0099 ret = br_add_if(br, dev, NULL);
0100 else
0101 ret = br_del_if(br, dev);
0102
0103 return ret;
0104 }
0105
0106 #define BR_UARGS_MAX 4
0107 static int br_dev_read_uargs(unsigned long *args, size_t nr_args,
0108 void __user **argp, void __user *data)
0109 {
0110 int ret;
0111
0112 if (nr_args < 2 || nr_args > BR_UARGS_MAX)
0113 return -EINVAL;
0114
0115 if (in_compat_syscall()) {
0116 unsigned int cargs[BR_UARGS_MAX];
0117 int i;
0118
0119 ret = copy_from_user(cargs, data, nr_args * sizeof(*cargs));
0120 if (ret)
0121 goto fault;
0122
0123 for (i = 0; i < nr_args; ++i)
0124 args[i] = cargs[i];
0125
0126 *argp = compat_ptr(args[1]);
0127 } else {
0128 ret = copy_from_user(args, data, nr_args * sizeof(*args));
0129 if (ret)
0130 goto fault;
0131 *argp = (void __user *)args[1];
0132 }
0133
0134 return 0;
0135 fault:
0136 return -EFAULT;
0137 }
0138
0139
0140
0141
0142
0143
0144 int br_dev_siocdevprivate(struct net_device *dev, struct ifreq *rq,
0145 void __user *data, int cmd)
0146 {
0147 struct net_bridge *br = netdev_priv(dev);
0148 struct net_bridge_port *p = NULL;
0149 unsigned long args[4];
0150 void __user *argp;
0151 int ret;
0152
0153 ret = br_dev_read_uargs(args, ARRAY_SIZE(args), &argp, data);
0154 if (ret)
0155 return ret;
0156
0157 switch (args[0]) {
0158 case BRCTL_ADD_IF:
0159 case BRCTL_DEL_IF:
0160 return add_del_if(br, args[1], args[0] == BRCTL_ADD_IF);
0161
0162 case BRCTL_GET_BRIDGE_INFO:
0163 {
0164 struct __bridge_info b;
0165
0166 memset(&b, 0, sizeof(struct __bridge_info));
0167 rcu_read_lock();
0168 memcpy(&b.designated_root, &br->designated_root, 8);
0169 memcpy(&b.bridge_id, &br->bridge_id, 8);
0170 b.root_path_cost = br->root_path_cost;
0171 b.max_age = jiffies_to_clock_t(br->max_age);
0172 b.hello_time = jiffies_to_clock_t(br->hello_time);
0173 b.forward_delay = br->forward_delay;
0174 b.bridge_max_age = br->bridge_max_age;
0175 b.bridge_hello_time = br->bridge_hello_time;
0176 b.bridge_forward_delay = jiffies_to_clock_t(br->bridge_forward_delay);
0177 b.topology_change = br->topology_change;
0178 b.topology_change_detected = br->topology_change_detected;
0179 b.root_port = br->root_port;
0180
0181 b.stp_enabled = (br->stp_enabled != BR_NO_STP);
0182 b.ageing_time = jiffies_to_clock_t(br->ageing_time);
0183 b.hello_timer_value = br_timer_value(&br->hello_timer);
0184 b.tcn_timer_value = br_timer_value(&br->tcn_timer);
0185 b.topology_change_timer_value = br_timer_value(&br->topology_change_timer);
0186 b.gc_timer_value = br_timer_value(&br->gc_work.timer);
0187 rcu_read_unlock();
0188
0189 if (copy_to_user((void __user *)args[1], &b, sizeof(b)))
0190 return -EFAULT;
0191
0192 return 0;
0193 }
0194
0195 case BRCTL_GET_PORT_LIST:
0196 {
0197 int num, *indices;
0198
0199 num = args[2];
0200 if (num < 0)
0201 return -EINVAL;
0202 if (num == 0)
0203 num = 256;
0204 if (num > BR_MAX_PORTS)
0205 num = BR_MAX_PORTS;
0206
0207 indices = kcalloc(num, sizeof(int), GFP_KERNEL);
0208 if (indices == NULL)
0209 return -ENOMEM;
0210
0211 get_port_ifindices(br, indices, num);
0212 if (copy_to_user(argp, indices, array_size(num, sizeof(int))))
0213 num = -EFAULT;
0214 kfree(indices);
0215 return num;
0216 }
0217
0218 case BRCTL_SET_BRIDGE_FORWARD_DELAY:
0219 if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN))
0220 return -EPERM;
0221
0222 ret = br_set_forward_delay(br, args[1]);
0223 break;
0224
0225 case BRCTL_SET_BRIDGE_HELLO_TIME:
0226 if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN))
0227 return -EPERM;
0228
0229 ret = br_set_hello_time(br, args[1]);
0230 break;
0231
0232 case BRCTL_SET_BRIDGE_MAX_AGE:
0233 if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN))
0234 return -EPERM;
0235
0236 ret = br_set_max_age(br, args[1]);
0237 break;
0238
0239 case BRCTL_SET_AGEING_TIME:
0240 if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN))
0241 return -EPERM;
0242
0243 ret = br_set_ageing_time(br, args[1]);
0244 break;
0245
0246 case BRCTL_GET_PORT_INFO:
0247 {
0248 struct __port_info p;
0249 struct net_bridge_port *pt;
0250
0251 rcu_read_lock();
0252 if ((pt = br_get_port(br, args[2])) == NULL) {
0253 rcu_read_unlock();
0254 return -EINVAL;
0255 }
0256
0257 memset(&p, 0, sizeof(struct __port_info));
0258 memcpy(&p.designated_root, &pt->designated_root, 8);
0259 memcpy(&p.designated_bridge, &pt->designated_bridge, 8);
0260 p.port_id = pt->port_id;
0261 p.designated_port = pt->designated_port;
0262 p.path_cost = pt->path_cost;
0263 p.designated_cost = pt->designated_cost;
0264 p.state = pt->state;
0265 p.top_change_ack = pt->topology_change_ack;
0266 p.config_pending = pt->config_pending;
0267 p.message_age_timer_value = br_timer_value(&pt->message_age_timer);
0268 p.forward_delay_timer_value = br_timer_value(&pt->forward_delay_timer);
0269 p.hold_timer_value = br_timer_value(&pt->hold_timer);
0270
0271 rcu_read_unlock();
0272
0273 if (copy_to_user(argp, &p, sizeof(p)))
0274 return -EFAULT;
0275
0276 return 0;
0277 }
0278
0279 case BRCTL_SET_BRIDGE_STP_STATE:
0280 if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN))
0281 return -EPERM;
0282
0283 ret = br_stp_set_enabled(br, args[1], NULL);
0284 break;
0285
0286 case BRCTL_SET_BRIDGE_PRIORITY:
0287 if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN))
0288 return -EPERM;
0289
0290 br_stp_set_bridge_priority(br, args[1]);
0291 ret = 0;
0292 break;
0293
0294 case BRCTL_SET_PORT_PRIORITY:
0295 {
0296 if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN))
0297 return -EPERM;
0298
0299 spin_lock_bh(&br->lock);
0300 if ((p = br_get_port(br, args[1])) == NULL)
0301 ret = -EINVAL;
0302 else
0303 ret = br_stp_set_port_priority(p, args[2]);
0304 spin_unlock_bh(&br->lock);
0305 break;
0306 }
0307
0308 case BRCTL_SET_PATH_COST:
0309 {
0310 if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN))
0311 return -EPERM;
0312
0313 spin_lock_bh(&br->lock);
0314 if ((p = br_get_port(br, args[1])) == NULL)
0315 ret = -EINVAL;
0316 else
0317 ret = br_stp_set_path_cost(p, args[2]);
0318 spin_unlock_bh(&br->lock);
0319 break;
0320 }
0321
0322 case BRCTL_GET_FDB_ENTRIES:
0323 return get_fdb_entries(br, argp, args[2], args[3]);
0324
0325 default:
0326 ret = -EOPNOTSUPP;
0327 }
0328
0329 if (!ret) {
0330 if (p)
0331 br_ifinfo_notify(RTM_NEWLINK, NULL, p);
0332 else
0333 netdev_state_change(br->dev);
0334 }
0335
0336 return ret;
0337 }
0338
0339 static int old_deviceless(struct net *net, void __user *data)
0340 {
0341 unsigned long args[3];
0342 void __user *argp;
0343 int ret;
0344
0345 ret = br_dev_read_uargs(args, ARRAY_SIZE(args), &argp, data);
0346 if (ret)
0347 return ret;
0348
0349 switch (args[0]) {
0350 case BRCTL_GET_VERSION:
0351 return BRCTL_VERSION;
0352
0353 case BRCTL_GET_BRIDGES:
0354 {
0355 int *indices;
0356 int ret = 0;
0357
0358 if (args[2] >= 2048)
0359 return -ENOMEM;
0360 indices = kcalloc(args[2], sizeof(int), GFP_KERNEL);
0361 if (indices == NULL)
0362 return -ENOMEM;
0363
0364 args[2] = get_bridge_ifindices(net, indices, args[2]);
0365
0366 ret = copy_to_user(argp, indices,
0367 array_size(args[2], sizeof(int)))
0368 ? -EFAULT : args[2];
0369
0370 kfree(indices);
0371 return ret;
0372 }
0373
0374 case BRCTL_ADD_BRIDGE:
0375 case BRCTL_DEL_BRIDGE:
0376 {
0377 char buf[IFNAMSIZ];
0378
0379 if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
0380 return -EPERM;
0381
0382 if (copy_from_user(buf, argp, IFNAMSIZ))
0383 return -EFAULT;
0384
0385 buf[IFNAMSIZ-1] = 0;
0386
0387 if (args[0] == BRCTL_ADD_BRIDGE)
0388 return br_add_bridge(net, buf);
0389
0390 return br_del_bridge(net, buf);
0391 }
0392 }
0393
0394 return -EOPNOTSUPP;
0395 }
0396
0397 int br_ioctl_stub(struct net *net, struct net_bridge *br, unsigned int cmd,
0398 struct ifreq *ifr, void __user *uarg)
0399 {
0400 int ret = -EOPNOTSUPP;
0401
0402 rtnl_lock();
0403
0404 switch (cmd) {
0405 case SIOCGIFBR:
0406 case SIOCSIFBR:
0407 ret = old_deviceless(net, uarg);
0408 break;
0409 case SIOCBRADDBR:
0410 case SIOCBRDELBR:
0411 {
0412 char buf[IFNAMSIZ];
0413
0414 if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) {
0415 ret = -EPERM;
0416 break;
0417 }
0418
0419 if (copy_from_user(buf, uarg, IFNAMSIZ)) {
0420 ret = -EFAULT;
0421 break;
0422 }
0423
0424 buf[IFNAMSIZ-1] = 0;
0425 if (cmd == SIOCBRADDBR)
0426 ret = br_add_bridge(net, buf);
0427 else
0428 ret = br_del_bridge(net, buf);
0429 }
0430 break;
0431 case SIOCBRADDIF:
0432 case SIOCBRDELIF:
0433 ret = add_del_if(br, ifr->ifr_ifindex, cmd == SIOCBRADDIF);
0434 break;
0435 }
0436
0437 rtnl_unlock();
0438
0439 return ret;
0440 }