Prevent an skb with the bridge_restricted attribute set from being forwarded to devices marked with the IFF_BRIDGE_RESTRICTED flag. Signed-off-by: Antonio Quartulli <antonio@xxxxxxxxxxxxx> --- net/bridge/br_forward.c | 18 +++++++++++++++++- net/bridge/br_input.c | 6 ++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c index 092b20e..52b9031 100644 --- a/net/bridge/br_forward.c +++ b/net/bridge/br_forward.c @@ -26,13 +26,29 @@ static int deliver_clone(const struct net_bridge_port *prev, void (*__packet_hook)(const struct net_bridge_port *p, struct sk_buff *skb)); +/** + * should_restrict - check if incoming and outgoing ports are restricted + * @skb: the incoming packet + * @dev: the outgoing port + * + * Return true if the skb is coming from a restricted port and out_dev is + * restricted too. False otherwise + */ +static inline int should_restrict(const struct sk_buff *skb, + const struct net_device *out_dev) +{ + return skb->bridge_restricted && + (out_dev->flags & IFF_BRIDGE_RESTRICTED); +} + /* Don't forward packets to originating port or forwarding diasabled */ static inline int should_deliver(const struct net_bridge_port *p, const struct sk_buff *skb) { return (((p->flags & BR_HAIRPIN_MODE) || skb->dev != p->dev) && br_allowed_egress(p->br, nbp_get_vlan_info(p), skb) && - p->state == BR_STATE_FORWARDING); + p->state == BR_STATE_FORWARDING && + !should_restrict(skb, p->dev)); } static inline unsigned int packet_length(const struct sk_buff *skb) diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index 828e2bc..73b4d4d 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c @@ -169,6 +169,12 @@ rx_handler_result_t br_handle_frame(struct sk_buff **pskb) p = br_port_get_rcu(skb->dev); + /* if this skb has been generated by a restricted port, mark it as well + * so that a "remote bridge" does not forward it to another restricted + * device + */ + skb->bridge_restricted = !!(skb->dev->flags & IFF_BRIDGE_RESTRICTED); + if (unlikely(is_link_local_ether_addr(dest))) { /* * See IEEE 802.1D Table 7-10 Reserved addresses -- 1.8.1.5