diff options
Diffstat (limited to 'net/bridge/br_sysfs_br.c')
| -rw-r--r-- | net/bridge/br_sysfs_br.c | 22 |
1 files changed, 9 insertions, 13 deletions
diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c index c5c059333eab..5913a3a0047b 100644 --- a/net/bridge/br_sysfs_br.c +++ b/net/bridge/br_sysfs_br.c | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #include <linux/capability.h> | 14 | #include <linux/capability.h> |
| 15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
| 16 | #include <linux/netdevice.h> | 16 | #include <linux/netdevice.h> |
| 17 | #include <linux/etherdevice.h> | ||
| 17 | #include <linux/if_bridge.h> | 18 | #include <linux/if_bridge.h> |
| 18 | #include <linux/rtnetlink.h> | 19 | #include <linux/rtnetlink.h> |
| 19 | #include <linux/spinlock.h> | 20 | #include <linux/spinlock.h> |
| @@ -36,7 +37,7 @@ static ssize_t store_bridge_parm(struct device *d, | |||
| 36 | unsigned long val; | 37 | unsigned long val; |
| 37 | int err; | 38 | int err; |
| 38 | 39 | ||
| 39 | if (!capable(CAP_NET_ADMIN)) | 40 | if (!ns_capable(dev_net(br->dev)->user_ns, CAP_NET_ADMIN)) |
| 40 | return -EPERM; | 41 | return -EPERM; |
| 41 | 42 | ||
| 42 | val = simple_strtoul(buf, &endp, 0); | 43 | val = simple_strtoul(buf, &endp, 0); |
| @@ -132,7 +133,7 @@ static ssize_t store_stp_state(struct device *d, | |||
| 132 | char *endp; | 133 | char *endp; |
| 133 | unsigned long val; | 134 | unsigned long val; |
| 134 | 135 | ||
| 135 | if (!capable(CAP_NET_ADMIN)) | 136 | if (!ns_capable(dev_net(br->dev)->user_ns, CAP_NET_ADMIN)) |
| 136 | return -EPERM; | 137 | return -EPERM; |
| 137 | 138 | ||
| 138 | val = simple_strtoul(buf, &endp, 0); | 139 | val = simple_strtoul(buf, &endp, 0); |
| @@ -165,7 +166,7 @@ static ssize_t store_group_fwd_mask(struct device *d, | |||
| 165 | char *endp; | 166 | char *endp; |
| 166 | unsigned long val; | 167 | unsigned long val; |
| 167 | 168 | ||
| 168 | if (!capable(CAP_NET_ADMIN)) | 169 | if (!ns_capable(dev_net(br->dev)->user_ns, CAP_NET_ADMIN)) |
| 169 | return -EPERM; | 170 | return -EPERM; |
| 170 | 171 | ||
| 171 | val = simple_strtoul(buf, &endp, 0); | 172 | val = simple_strtoul(buf, &endp, 0); |
| @@ -297,23 +298,18 @@ static ssize_t store_group_addr(struct device *d, | |||
| 297 | const char *buf, size_t len) | 298 | const char *buf, size_t len) |
| 298 | { | 299 | { |
| 299 | struct net_bridge *br = to_bridge(d); | 300 | struct net_bridge *br = to_bridge(d); |
| 300 | unsigned int new_addr[6]; | 301 | u8 new_addr[6]; |
| 301 | int i; | 302 | int i; |
| 302 | 303 | ||
| 303 | if (!capable(CAP_NET_ADMIN)) | 304 | if (!ns_capable(dev_net(br->dev)->user_ns, CAP_NET_ADMIN)) |
| 304 | return -EPERM; | 305 | return -EPERM; |
| 305 | 306 | ||
| 306 | if (sscanf(buf, "%x:%x:%x:%x:%x:%x", | 307 | if (sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", |
| 307 | &new_addr[0], &new_addr[1], &new_addr[2], | 308 | &new_addr[0], &new_addr[1], &new_addr[2], |
| 308 | &new_addr[3], &new_addr[4], &new_addr[5]) != 6) | 309 | &new_addr[3], &new_addr[4], &new_addr[5]) != 6) |
| 309 | return -EINVAL; | 310 | return -EINVAL; |
| 310 | 311 | ||
| 311 | /* Must be 01:80:c2:00:00:0X */ | 312 | if (!is_link_local_ether_addr(new_addr)) |
| 312 | for (i = 0; i < 5; i++) | ||
| 313 | if (new_addr[i] != br_group_address[i]) | ||
| 314 | return -EINVAL; | ||
| 315 | |||
| 316 | if (new_addr[5] & ~0xf) | ||
| 317 | return -EINVAL; | 313 | return -EINVAL; |
| 318 | 314 | ||
| 319 | if (new_addr[5] == 1 || /* 802.3x Pause address */ | 315 | if (new_addr[5] == 1 || /* 802.3x Pause address */ |
| @@ -337,7 +333,7 @@ static ssize_t store_flush(struct device *d, | |||
| 337 | { | 333 | { |
| 338 | struct net_bridge *br = to_bridge(d); | 334 | struct net_bridge *br = to_bridge(d); |
| 339 | 335 | ||
| 340 | if (!capable(CAP_NET_ADMIN)) | 336 | if (!ns_capable(dev_net(br->dev)->user_ns, CAP_NET_ADMIN)) |
| 341 | return -EPERM; | 337 | return -EPERM; |
| 342 | 338 | ||
| 343 | br_fdb_flush(br); | 339 | br_fdb_flush(br); |
