Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *  Ioctl handler
0004  *  Linux ethernet bridge
0005  *
0006  *  Authors:
0007  *  Lennert Buytenhek       <buytenh@gnu.org>
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 /* called with RTNL */
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  * Format up to a page worth of forwarding table entries
0051  * userbuf -- where to copy result
0052  * maxnum  -- maximum number of entries desired
0053  *            (limited to a page for sanity)
0054  * offset  -- number of records to skip
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     /* Clamp size to PAGE_SIZE, test maxnum to avoid overflow */
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 /* called with RTNL */
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  * Legacy ioctl's through SIOCDEVPRIVATE
0141  * This interface is deprecated because it was too difficult
0142  * to do the translation for 32/64bit ioctl compatibility.
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 }