Commit 0c2b1878 authored by Stephen Hemminger's avatar Stephen Hemminger

[BRIDGE]: Allow non-root to inspect the status of a bridge.

parent a4b18f43
...@@ -32,7 +32,7 @@ static int br_dev_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) ...@@ -32,7 +32,7 @@ static int br_dev_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
if (copy_from_user(args, data, 4*sizeof(unsigned long))) if (copy_from_user(args, data, 4*sizeof(unsigned long)))
return -EFAULT; return -EFAULT;
return br_ioctl(dev->priv, args[0], args[1], args[2], args[3]); return br_ioctl_device(dev->priv, args[0], args[1], args[2], args[3]);
} }
static struct net_device_stats *br_dev_get_stats(struct net_device *dev) static struct net_device_stats *br_dev_get_stats(struct net_device *dev)
......
...@@ -38,11 +38,8 @@ static unsigned long timer_residue(const struct timer_list *timer) ...@@ -38,11 +38,8 @@ static unsigned long timer_residue(const struct timer_list *timer)
? (timer->expires - jiffies) : 0); ? (timer->expires - jiffies) : 0);
} }
static int br_ioctl_device(struct net_bridge *br, int br_ioctl_device(struct net_bridge *br, unsigned int cmd,
unsigned int cmd, unsigned long arg0, unsigned long arg1, unsigned long arg2)
unsigned long arg0,
unsigned long arg1,
unsigned long arg2)
{ {
if (br == NULL) if (br == NULL)
return -EINVAL; return -EINVAL;
...@@ -55,6 +52,9 @@ static int br_ioctl_device(struct net_bridge *br, ...@@ -55,6 +52,9 @@ static int br_ioctl_device(struct net_bridge *br,
struct net_device *dev; struct net_device *dev;
int ret; int ret;
if (!capable(CAP_NET_ADMIN))
return -EPERM;
dev = dev_get_by_index(arg0); dev = dev_get_by_index(arg0);
if (dev == NULL) if (dev == NULL)
return -EINVAL; return -EINVAL;
...@@ -121,6 +121,9 @@ static int br_ioctl_device(struct net_bridge *br, ...@@ -121,6 +121,9 @@ static int br_ioctl_device(struct net_bridge *br,
} }
case BRCTL_SET_BRIDGE_FORWARD_DELAY: case BRCTL_SET_BRIDGE_FORWARD_DELAY:
if (!capable(CAP_NET_ADMIN))
return -EPERM;
spin_lock_bh(&br->lock); spin_lock_bh(&br->lock);
br->bridge_forward_delay = user_to_ticks(arg0); br->bridge_forward_delay = user_to_ticks(arg0);
if (br_is_root_bridge(br)) if (br_is_root_bridge(br))
...@@ -129,6 +132,9 @@ static int br_ioctl_device(struct net_bridge *br, ...@@ -129,6 +132,9 @@ static int br_ioctl_device(struct net_bridge *br,
return 0; return 0;
case BRCTL_SET_BRIDGE_HELLO_TIME: case BRCTL_SET_BRIDGE_HELLO_TIME:
if (!capable(CAP_NET_ADMIN))
return -EPERM;
spin_lock_bh(&br->lock); spin_lock_bh(&br->lock);
br->bridge_hello_time = user_to_ticks(arg0); br->bridge_hello_time = user_to_ticks(arg0);
if (br_is_root_bridge(br)) if (br_is_root_bridge(br))
...@@ -137,6 +143,9 @@ static int br_ioctl_device(struct net_bridge *br, ...@@ -137,6 +143,9 @@ static int br_ioctl_device(struct net_bridge *br,
return 0; return 0;
case BRCTL_SET_BRIDGE_MAX_AGE: case BRCTL_SET_BRIDGE_MAX_AGE:
if (!capable(CAP_NET_ADMIN))
return -EPERM;
spin_lock_bh(&br->lock); spin_lock_bh(&br->lock);
br->bridge_max_age = user_to_ticks(arg0); br->bridge_max_age = user_to_ticks(arg0);
if (br_is_root_bridge(br)) if (br_is_root_bridge(br))
...@@ -145,10 +154,10 @@ static int br_ioctl_device(struct net_bridge *br, ...@@ -145,10 +154,10 @@ static int br_ioctl_device(struct net_bridge *br,
return 0; return 0;
case BRCTL_SET_AGEING_TIME: case BRCTL_SET_AGEING_TIME:
br->ageing_time = user_to_ticks(arg0); if (!capable(CAP_NET_ADMIN))
return 0; return -EPERM;
case BRCTL_SET_GC_INTERVAL: /* no longer used */ br->ageing_time = user_to_ticks(arg0);
return 0; return 0;
case BRCTL_GET_PORT_INFO: case BRCTL_GET_PORT_INFO:
...@@ -185,10 +194,16 @@ static int br_ioctl_device(struct net_bridge *br, ...@@ -185,10 +194,16 @@ static int br_ioctl_device(struct net_bridge *br,
} }
case BRCTL_SET_BRIDGE_STP_STATE: case BRCTL_SET_BRIDGE_STP_STATE:
if (!capable(CAP_NET_ADMIN))
return -EPERM;
br->stp_enabled = arg0?1:0; br->stp_enabled = arg0?1:0;
return 0; return 0;
case BRCTL_SET_BRIDGE_PRIORITY: case BRCTL_SET_BRIDGE_PRIORITY:
if (!capable(CAP_NET_ADMIN))
return -EPERM;
spin_lock_bh(&br->lock); spin_lock_bh(&br->lock);
br_stp_set_bridge_priority(br, arg0); br_stp_set_bridge_priority(br, arg0);
spin_unlock_bh(&br->lock); spin_unlock_bh(&br->lock);
...@@ -199,6 +214,9 @@ static int br_ioctl_device(struct net_bridge *br, ...@@ -199,6 +214,9 @@ static int br_ioctl_device(struct net_bridge *br,
struct net_bridge_port *p; struct net_bridge_port *p;
int ret = 0; int ret = 0;
if (!capable(CAP_NET_ADMIN))
return -EPERM;
spin_lock_bh(&br->lock); spin_lock_bh(&br->lock);
if ((p = br_get_port(br, arg0)) == NULL) if ((p = br_get_port(br, arg0)) == NULL)
ret = -EINVAL; ret = -EINVAL;
...@@ -213,6 +231,9 @@ static int br_ioctl_device(struct net_bridge *br, ...@@ -213,6 +231,9 @@ static int br_ioctl_device(struct net_bridge *br,
struct net_bridge_port *p; struct net_bridge_port *p;
int ret = 0; int ret = 0;
if (!capable(CAP_NET_ADMIN))
return -EPERM;
spin_lock_bh(&br->lock); spin_lock_bh(&br->lock);
if ((p = br_get_port(br, arg0)) == NULL) if ((p = br_get_port(br, arg0)) == NULL)
ret = -EINVAL; ret = -EINVAL;
...@@ -265,6 +286,9 @@ static int br_ioctl_deviceless(unsigned int cmd, ...@@ -265,6 +286,9 @@ static int br_ioctl_deviceless(unsigned int cmd,
{ {
char buf[IFNAMSIZ]; char buf[IFNAMSIZ];
if (!capable(CAP_NET_ADMIN))
return -EPERM;
if (copy_from_user(buf, (void *)arg0, IFNAMSIZ)) if (copy_from_user(buf, (void *)arg0, IFNAMSIZ))
return -EFAULT; return -EFAULT;
...@@ -285,25 +309,8 @@ int br_ioctl_deviceless_stub(unsigned long arg) ...@@ -285,25 +309,8 @@ int br_ioctl_deviceless_stub(unsigned long arg)
{ {
unsigned long i[3]; unsigned long i[3];
if (!capable(CAP_NET_ADMIN))
return -EPERM;
if (copy_from_user(i, (void *)arg, 3*sizeof(unsigned long))) if (copy_from_user(i, (void *)arg, 3*sizeof(unsigned long)))
return -EFAULT; return -EFAULT;
return br_ioctl_deviceless(i[0], i[1], i[2]); return br_ioctl_deviceless(i[0], i[1], i[2]);
} }
int br_ioctl(struct net_bridge *br, unsigned int cmd, unsigned long arg0, unsigned long arg1, unsigned long arg2)
{
int err;
if (!capable(CAP_NET_ADMIN))
return -EPERM;
err = br_ioctl_deviceless(cmd, arg0, arg1);
if (err == -EOPNOTSUPP)
err = br_ioctl_device(br, cmd, arg0, arg1, arg2);
return err;
}
...@@ -174,7 +174,7 @@ extern int br_handle_frame_finish(struct sk_buff *skb); ...@@ -174,7 +174,7 @@ extern int br_handle_frame_finish(struct sk_buff *skb);
extern int br_handle_frame(struct sk_buff *skb); extern int br_handle_frame(struct sk_buff *skb);
/* br_ioctl.c */ /* br_ioctl.c */
extern int br_ioctl(struct net_bridge *br, extern int br_ioctl_device(struct net_bridge *br,
unsigned int cmd, unsigned int cmd,
unsigned long arg0, unsigned long arg0,
unsigned long arg1, unsigned long arg1,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment