Результаты анализа поверхности атаки для модуля bridge ядра Linux версии 5.10 (net/bridge)

Модуль реализует технологию 802.1d Ethernet Bridging (сетевой мост), позволяющую объединять Ethernet сегменты в единую сеть. Использование дополнительно протокола STP (Spanning tree protocol) для устранения петель в топологии сети, позволяет объединять несколько Ethernet-мостов. Поскольку это сетевой стандарт, мосты Linux корректно взаимодействуют с реализациями мостов сторонних производителей.

Модуль состоит из нескольких подсистем, некоторые из которых для подключения требуют дополнительной настройки ядра.

С точки зрения кода, инициализация дополнительных подсистем (netfilter, netlink, vlan и др.) выполняется через основной интерфейс:

br_init() {                // br.c
   br_fdb_init();          // br_fdb.c
   stp_proto_register();   // /net/802/stp.c
   br_nf_core_init();      // br_nf_core.c
   br_netlink_init();      // br_netlink.c
   br_mdb_init();          // br_mdb.c
   brioctl_set();
}
br_add_bridge() {      // br_if.c
     br_dev_setup()    // br_device.c
}
br_dev_setup()  {                     // br_device.c
        br_netfilter_rtable_init();   // br_nf_core.c
	br_stp_timer_init();          // br_stp_timer.c
	br_multicast_init();          // br_multicast.c
}
br_dev_init() {           // br_device.c
        br_vlan_init();   // br_vlan.c
}

Основная функциональность модуля:

  • br.c – общая функциональность;
  • br_arp_nd_proxy.c – управление сообщениями arp/ipv4 и neighbor discovery/ipv6;
  • br_device.c – интерфейс управления сетевыми устройствами;
  • br_fdb.c – правила пересылки пакетов (forwarding database);
  • br_forward.c – правила пересылки пакетов (forwarding decision);
  • br_if.c – пользовательский интерфейс для управления мостами;
  • br_input.c – управление входящими сообщениями;
  • br_ioctl.c – интерфейс ioctl;
  • br_netlink.c – интерфейс управления мостами через netlink;
  • br_netlink_tunnel.c – интерфейс управления мостами для портов туннелей vlan.

Протокол stp:

  • br_stp.c – поддержка протокола stp (Spanning tree protocol);
  • br_stp_bpdu.c –протокол stp, управление сообщениями BPDU;
  • br_stp_if.c – интерфейс протокола stp;
  • br_stp_timer.c –протокол stp, установка таймеров.

Протокол mrp:

  • br_mrp.c – поддержка протокола mrp (802.1Q Multiple Registration Protocol);
  • br_mrp_netlink.c – интерфейс netlink для протокола mrp;
  • br_mrp_switchdev.c – взаимодействие протокола mrp с драйвером switchdev.

Пересылка сообщений multicast на основе IGMP/MLD:

  • br_mdb.c – правила пересылки пакетов multicast (multicast database);
  • br_multicast.c – пересылка (forwarding) сообщений multicast (IGMP/MLD snooping).

Фильтрация трафика с использованием netfilter:

  • br_nf_core.c – управление фильтрацией трафика (netfilter);
  • br_netfilter_hooks.c – управление фильтрацией трафика (netfilter);
  • br_netfilter_ipv6.c – управление фильтрацией трафика;
  • ./netfilter – модули для фильтрации трафика канального уровня на мосту (настройка netfilter для мостов).

Драйвер switchdev:

  • br_switchdev.c – модель драйвера коммутатора Ethernet.

Файловая система sysfs:

  • br_sysfs_br.c – конфигурация файловой системы sysfs, атрибуты мостов;
  • br_sysfs_if.c – конфигурация файловой системы sysfs, атрибуты портов.

Пересылка пакетов на основе настроек VLAN:

  • br_vlan.c – поддержка vlan;
  • br_vlan_options.c – поддержка vlan;
  • br_vlan_tunnel.c – мост для портов туннелей vlan.

Ниже на диаграмме косые четырехугольники – это статические (static) функции, которые вызываются или через функциональный указатель или внутри модуля.

Красным цветом выделены интерфейсные функции, которые могут являться поверхностью атаки.

Оранжевым цветом выделены интерфейсные функции, которые могут являться поверхностью атаки при вызовах из недоверенного пользовательского пространства.

Розовым цветом выделены интерфейсные функции, требующие более глубокого анализа с точки зрения поверхности атаки.

Темно-серые прямоугольники – это интерфейсные функции, которые не оперируют сетевыми данными и не является поверхностью атаки.

Зеленые ромбы на диаграммах – это один или несколько элементов некоторой структуры, которые являются указателями на функции. Если из ромба выходит стрелка, значит элементу соответствующей структуры присвоено имя функции, на которую указывает стрелка. Если стрелка входит в ромб из функции, значит в этой функции имеется вызов функции по соответствующему указателю. Зеленые прямоугольники: если они относятся к ромбам, то это структуры, переопределяющие структуру обозначенную зеленым ромбом; самостоятельные прямоугольники – это статические функциональные указатели.

Желтые квадраты с цифрой – имеется дубликат функции на диаграмме.

Пунктирная стрелка – это использование функциональных указателей.

Стрелка с ромбом – вызов функции через промежуточные (неуказанные) функции.

bridge

Сводная таблица результатов анализа

Имя подмодуля и/или функцииНазначениеПоверхность атаки
br.cОбщая функциональность модуля
br_device_event, br_switchdev_event, br_boolopt_toggle, br_boolopt_get, br_boolopt_multi_toggle, br_boolopt_multi_get, br_opt_toggleНет
br_arp_nd_proxy.cУправление сообщениями arp/ipv4 и neighbor discovery/ipv6
br_recalculate_neigh_suppress_enabledНет
br_do_proxy_suppress_arp, br_is_nd_neigh_msg, br_do_suppress_ndДа
br_device.cИнтерфейс управления сетевыми устройствами
br_dev_openб br_dev_stopб br_dev_initб br_dev_uninitб br_get_stats64б br_set_mac_addressб br_dev_set_multicast_listб br_change_mtuб br_netpoll_setupб br_netpoll_cleanupб br_netpoll_enableб br_netpoll_disableб br_poll_controllerб br_add_slaveб br_del_slaveб br_fix_featuresб br_getinfoб br_get_link_ksettingsб br_dev_setupНет
br_dev_xmitОтправка пакетовДа
br_dev_change_rx_flagsУправление режимом сбора входящих пакетов (promiscuous mode)Да
br_fdb.cправила пересылки пакетов (forwarding database)
br_fdb_initб br_fdb_finiб br_fdb_hash_initб br_fdb_hash_finiб br_fdb_find_portб br_fdb_find_rcuб br_fdb_find_delete_localб br_fdb_changeaddrб br_fdb_change_mac_addressб br_fdb_cleanupб br_fdb_flushб br_fdb_delete_by_portб br_fdb_test_addrб br_fdb_insertб br_fdb_dumpб br_fdb_getб br_fdb_addб br_fdb_deleteб br_fdb_sync_staticб br_fdb_unsync_staticб br_fdb_external_learn_addб br_fdb_external_learn_delб br_fdb_offloaded_setб br_fdb_clear_offloadНет
br_fdb_fillbufПолучение записи из базы данныхДа
br_fdb_updateИзменение записи в базе данныхДа
br_forward.cПравила пересылки пакетов (forwarding decision)
br_dev_queue_push_xmit, br_forward_finish, br_forward, br_flood, br_multicast_floodДа
br_if.cПользовательский интерфейс для управления мостами
r_dev_delete, br_pot_flag_is_set, br_portcarrier_check, br_addbridge, br_del_brige, br_add_if, br_el_if, brmtu_auto_adjust, br_features_recompute, br_port_flags_change, br_manage_promisc, nbp_backup_change, release_nbp , rport_get_ownershipНет
br_input.cУправление входящими сообщениями
br_handle_frame_finish, br_handle_frameДа
br_get_rx_handler, br_handle_frame_dummyНет
br_input.cУправление входящими сообщениями
br_handle_frame_finish, br_handle_frameДа
br_get_rx_handler, br_handle_frame_dummyНет
br_ioctl.cИнтерфейс ioctl
br_ioctl_deviceless_stub, br_dev_ioctlДа
br_netlink.cИнтерфейс netlink для управления мостами
br_setlink, br_dellink, b_getlink, br_dev_newlink, br_changelink, br_fill_info, br_port_slave_changelink, br_port_fill_slave_info, br_ifinfo_notifyДа
br_validate, br_gt_size, br_fill_linkxtats, br_get_linkxstats_size, br_port_get_slave_size, br_netlink_init, br_netlink_fini, br_process_vlan_info, br_get_link_af_size_filteredНет
br_netlink_tunnel.cИнтерфейс управления мостами для портов туннелей vlanНет
br_stp.cПоддержка протокола stp (Spanning tree protocol)
br_set_state, br_become_roo_bridge, br_transmit_conig, br_transmit_tcn, br_toology_change_detection, br_config_bpdu_generation, br_configuration_udate, br_become_designaed_port, br_port_state_selection, __br_set_topology_change, __set_ageing_time, __br_set_forward_delay, br_received_tcn_bpduНет
br_set_hello_time, br_set_max_age, br_set_ageing_time, br_set_forward_delay, br_get_portУстановка параметровДа
br_received_config_bpduОбработчик входящих сообщенийДа
br_stp_bpdu.cПротокол stp, управление сообщениями BPDU
br_send_config_bpdu, br_send_tcn_bpduОтправка служебных сообщенийНет
br_stp_rcvОбработчик входящих сообщенийДа
br_stp_if.cИнтерфейс протокола stp
br_init_port, br_stp_enable_bridge, br_stp_disable_bridge, br_stp_enable_port, br_stp_disable_port, br_stp_change_bridge_id, br_stp_recalculate_bridge_id, br_show_bridge_idНет
br_stp_set_enabled, br_stp_set_bridge_priority, br_stp_set_port_priority, br_stp_set_path_costУстановка параметровДа
br_stp_timer.cПротокол stp, установка таймеровНет
br_mrp.cПоддержка протокола mrp (802.1Q Multiple Registration Protocol)
br_mrp_test_work_expired, br_mrp_in_test_work_expiredИсходящие служебные сообщения по таймеруНет
br_mrp_add, br_mrp_del, br_mrp_set_port_state, br_mrp_set_port_role, br_mrp_set_ring_state, br_mrp_set_ring_role, br_mrp_set_in_state, br_mrp_set_in_role, br_mrp_start_test, br_mrp_start_in_test, br_mrp_port_del, br_mrp_enabledНет
br_mrp_processОбработка входящих сообщенийДа
br_mrp_netlink.cИнтерфейс netlink для протокола mrp
br_mrp_ring_port_open, br_mrp_in_port_open, br_mrp_parse, br_mrp_fill_infoНет
br_mrp_switchdev.cВзаимодействие протокола mrp с драйвером switchdevНет
br_mdb.cПравила пересылки пакетов multicast (multicast database)
br_mdb_init, br_mdb_uninit, br_mdb_notify, br_rtr_notifyНет
br_mdb_dump, br_mdb_add, br_mdb_delДоступ к записям БД (multicast database)Да
br_multicast.cПересылка (forwarding) сообщений multicast (IGMP/MLD snooping)
br_multicast_init, br_multicast_enabled, br_multicast_router, br_multicast_list_adjacent, br_multicast_has_querier_anywhere, br_multicast_has_querier_adjacent, br_multicast_add_port, br_multicast_del_port, br_multicast_enable_port, br_multicast_disable_port, br_multicast_join_snoopers, br_multicast_leave_snoopers, br_multicast_open, br_multicast_stop, br_multicast_dev_del, br_multicast_host_join, br_multicast_host_leave, br_mdb_ip_get, br_mdb_hash_init, br_mdb_hash_fini, br_multicast_del_pg, br_multicast_init_stats, br_multicast_uninit_stats, br_multicast_get_stats, br_multicast_star_g_handle_mode, br_multicast_sg_add_exclude_ports, br_multicast_new_group, br_multicast_new_port_groupНет
br_multicast_set_port_router, br_multicast_set_router, br_multicast_toggle, br_multicast_set_querier, br_multicast_set_igmp_version, br_multicast_set_mld_versionДа
br_multicast_rcvОбработка входящих пакетовДа
br_mdb_getОбращение к базе данных mdb, с использованием данных пакетаДа
br_multicast_countСбор статистики о трафикеДа
br_nf_core.cУправление фильтрацией трафика (netfilter)
br_netfilter_rtable_init, br_nf_core_init, br_nf_core_finiНет
br_netfilter_hooks.cУправление фильтрацией трафика
nf_bridge_encap_header_len, nf_bridge_update_protocol, br_nf_pre_routing_finish_bridge, setup_pre_routing, br_nf_dev_xmit, br_nf_pre_routing, br_nf_forward_ip, br_nf_forward_arp, br_nf_post_routing, ip_sabotage_in, br_nf_hook_threshПересылка (forwarding) пакетовДа
brnf_sysctl_call_tablesДа
brnf_device_event, brnf_init_net, brnf_exit_netНет
br_netfilter_ipv6.cУправление фильтрацией трафика
br_validate_ipv6, br_nf_pre_routing_ipv6Да
br_switchdev.cМодель драйвера коммутатора Ethernet
nbp_switchdev_mark_set, br_switchdev_fdb_notify, br_switchdev_port_vlan_add, br_switchdev_port_vlan_delНет
nbp_switchdev_frame_mark, nbp_switchdev_allowed_egressДа
br_switchdev_set_port_flagУстановка параметровДа
br_sysfs_br.cКонфигурация файловой системы sysfs, атрибуты мостовДа
br_sysfs_if.cКонфигурация файловой системы sysfs, атрибуты портовДа
br_vlan.cПоддержка vlan
br_vlan_init, br_vlan_add, br_vlan_delete, br_vlan_flush, nbp_vlan_init , nbp_vlan_add, nbp_vlan_delete, nbp_vlan_flush, br_vlan_find, br_vlan_can_enter_range, br_vlan_rtnl_init, br_vlan_rtnl_uninit, br_vlan_enabled, br_vlan_get_proto, br_vlan_get_pvid, br_vlan_get_pvid_rcu, br_vlan_get_info, br_vlan_get_stats, br_vlan_bridge_event, br_vlan_port_event, br_vlan_notifyНет
br_vlan_rtm_dump, br_vlan_rtm_process, br_recalculate_fwd_mask, br_vlan_set_stats, br_vlan_set_stats_per_port, __br_vlan_filter_toggle, br_vlan_filter_toggle, __br_vlan_set_proto, br_vlan_set_proto, __br_vlan_set_default_pvid, br_vlan_set_default_pvid, br_handle_vlan, br_allowed_ingress, br_allowed_egress, br_should_learnДа
br_vlan_options.cПоддержка vlanНет
br_vlan_tunnel.cМост для портов туннелей vlan
br_vlan_tunid_cmp, vlan_tunnel_init, vlan_tunnel_deinit, nbp_vlan_tunnel_info_delete, nbp_vlan_tunnel_info_add, nbp_vlan_tunnel_info_flush, vlan_tunnel_info_delНет
br_handle_ingress_vlan_tunnel, br_handle_egress_vlan_tunnelРабота с пакетами при пересылке через туннельДа

Распределение функций, являющихся поверхностью атаки, по направлению трафика

Имя функцииНаправление трафика
br_arp_nd_proxy.c
br_do_proxy_suppress_arp, br_is_nd_neigh_msg, br_do_suppress_ndИсходящий
br_device.c
br_dev_xmitИсходящий
br_dev_change_rx_flagsИз пользовательского пространства
br_fdb.c
br_fdb_fillbufИз пользовательского пространства
br_fdb_updateВ обе стороны. Из пользовательского пространства
br_forward.c
br_dev_queue_push_xmit, br_forward_finish , br_forward, br_flood, br_multicast_floodВ обе стороны
br_input.c
br_handle_frame_finishВ обе стороны
br_handle_frameВходящий
br_ioctl.c
br_ioctl_deviceless_stub, br_dev_ioctlИз пользовательского пространства
br_netlink.c
br_setlink, br_dellink, br_getlink, br_dev_newlink, br_changelink, br_fill_info, br_port_slave_changelink, br_port_fill_slave_info, br_ifinfo_notifyИз пользовательского пространства
br_stp.c
br_set_hello_time, br_set_max_age, br_set_ageing_time, br_set_forward_delay, br_get_portИз пользовательского пространства
br_received_config_bpduВходящий
br_stp_bpdu.c
br_stp_rcvВходящий
br_stp_if.c
br_stp_set_enabled, br_stp_set_bridge_priority, br_stp_set_port_priority, br_stp_set_path_costИз пользовательского пространства
br_mrp.c
br_mrp_processВходящий
br_mdb.c
br_mdb_dump, br_mdb_add, br_mdb_delИз пользовательского пространства
br_multicast.c
br_multicast_set_port_router, br_multicast_set_router, br_multicast_toggle, br_multicast_set_querier, br_multicast_set_igmp_version, br_multicast_set_mld_versionИз пользовательского пространства
br_multicast_rcv, br_mdb_get, br_multicast_countВ обе стороны
br_netfilter_hooks.c
nf_bridge_encap_header_len, nf_bridge_update_protocol, br_nf_pre_routing_finish_bridge, setup_pre_routing, br_nf_dev_xmit, br_nf_pre_routing, br_nf_forward_ip, br_nf_forward_arp, br_nf_post_routing, ip_sabotage_in, br_nf_hook_threshВ обе стороны
brnf_sysctl_call_tablesИз пользовательского пространства
br_netfilter_ipv6.c
br_validate_ipv6, br_nf_pre_routing_ipv6Исходящий
br_switchdev.c
nbp_switchdev_frame_mark, nbp_switchdev_allowed_egressВходящий
br_switchdev_set_port_flagИз пользовательского пространства
br_sysfs_br.cИз пользовательского пространства
br_sysfs_if.cИз пользовательского пространства
br_vlan.c
br_vlan_rtm_dump, br_vlan_rtm_process, br_recalculate_fwd_mask, br_vlan_set_stats, br_vlan_set_stats_per_port, __br_vlan_filter_toggle, br_vlan_filter_toggle, __br_vlan_set_proto, br_vlan_set_proto, __br_vlan_set_default_pvid, br_vlan_set_default_pvidИз пользовательского пространства
br_handle_vlan, br_allowed_ingress, br_allowed_egressВ обе стороны
br_should_learnВходящий
br_vlan_tunnel.c
br_handle_ingress_vlan_tunnelВходящий
br_handle_egress_vlan_tunnelВ обе стороны

Замечание: структуры, обозначенные зелеными ромбами, не изучались детально на предмет вызовов из других функций. Часто к ним есть доступ из пользовательского пространства, поэтому такие структуры могут рассматриваться как поверхность атаки 3 уровня, но большинство таких операций, как правило, требует права администратора. Каталог net/bridge/netfilter (настройка netfilter для мостов) не изучался.

Далее перечислены все файлы и функции, доступные для вызова вне модуля.

br.c

Общая функциональность.

static int br_device_event(struct notifier_block *unused, unsigned long event, void *ptr)
static struct notifier_block br_device_notifier = {
	.notifier_call = br_device_event
};

static int br_switchdev_event(struct notifier_block *unused, unsigned long event, void *ptr) 
static struct notifier_block br_switchdev_notifier = {
	.notifier_call = br_switchdev_event,
};

/* br_boolopt_toggle - change user-controlled boolean option
int br_boolopt_toggle(struct net_bridge *br, enum br_boolopt_id opt, bool on,
		      struct netlink_ext_ack *extack) 
int br_boolopt_get(const struct net_bridge *br, enum br_boolopt_id opt)
int br_boolopt_multi_toggle(struct net_bridge *br, struct br_boolopt_multi *bm,			
			    struct netlink_ext_ack *extack) 
void br_boolopt_multi_get(const struct net_bridge *br,  struct br_boolopt_multi *bm)
/* private bridge options, controlled by the kernel */
void br_opt_toggle(struct net_bridge *br, enum net_bridge_opts opt, bool on)

static void __net_exit br_net_exit(struct net *net)
static struct pernet_operations br_net_ops = {
	.exit	= br_net_exit,
};
static const struct stp_proto br_stp_proto = {
	.rcv	= br_stp_rcv,
};

#if IS_ENABLED(CONFIG_ATM_LANE)  //  br_private.h
extern int (*br_fdb_test_addr_hook)(struct net_device *dev, unsigned char *addr);
#endif

static int __init br_init(void) {
	err = register_pernet_subsys(&br_net_ops);
	err = register_netdevice_notifier(&br_device_notifier);
	err = register_switchdev_notifier(&br_switchdev_notifier);
	brioctl_set(br_ioctl_deviceless_stub);

#if IS_ENABLED(CONFIG_ATM_LANE)
br_fdb_test_addr_hook = br_fdb_test_addr;
#endif
}
module_init(br_init)

С сетевыми данными не работает.

br_arp_nd_proxy.c

Управление сообщениями arp/ipv4 и neighbor discovery/ipv6.

void br_recalculate_neigh_suppress_enabled(struct net_bridge *br)

#if IS_ENABLED(CONFIG_INET)
void br_do_proxy_suppress_arp(struct sk_buff *skb, struct net_bridge *br, u16 vid,
			      struct net_bridge_port *p) 
              //внутри вызывает br_arp_send
#endif

#if IS_ENABLED(CONFIG_IPV6)
struct nd_msg *br_is_nd_neigh_msg(struct sk_buff *skb, struct nd_msg *msg)
void br_do_suppress_nd(struct sk_buff *skb, struct net_bridge *br, u16 vid,
		       struct net_bridge_port *p, struct nd_msg *msg)
//внутри вызывает br_nd_send
#endif

Функции br_do_proxy_suppress_arp, br_is_nd_neigh_msg, br_do_suppress_nd используются при отправке сообщений arp и neighbor discovery и могут являются поверхностью атаки при вызовах из пользовательского пространства. Однако, данные протоколы обычно недоступны напрямую из пользовательского пространства, поэтому вопрос использования указанных функций для несанкционированных действий требует дополнительного изучения.

br_device.c

Интерфейс управления сетевыми устройствами.

struct nf_br_ops {  
	int (*br_dev_xmit_hook)(struct sk_buff *skb);
};    // br_private.h
const struct nf_br_ops __rcu *nf_br_ops __read_mostly;
EXPORT_SYMBOL_GPL(nf_br_ops);

netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)

#ifdef CONFIG_NET_POLL_CONTROLLER   //  br_private.h
int br_netpoll_enable(struct net_bridge_port *p)
void br_netpoll_disable(struct net_bridge_port *p)
#else
// функции ничего не делают (отсутствует код или возвращают константное значение)
#endif

static void br_getinfo(struct net_device *dev, struct ethtool_drvinfo *info)
static int br_get_link_ksettings(struct net_device *dev, struct ethtool_link_ksettings *cmd)

static const struct ethtool_ops br_ethtool_ops = {
	.get_drvinfo		 = br_getinfo,
	.get_link_ksettings	 = br_get_link_ksettings,
};

static int br_dev_open(struct net_device *dev) 
static int br_dev_stop(struct net_device *dev)
static int br_dev_init(struct net_device *dev)
static void br_dev_uninit(struct net_device *dev)
static void br_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
static int br_set_mac_address(struct net_device *dev, void *p)
static void br_dev_set_multicast_list(struct net_device *dev)
static void br_dev_change_rx_flags(struct net_device *dev, int change)
static int br_change_mtu(struct net_device *dev, int new_mtu)

static int br_netpoll_setup(struct net_device *dev, struct netpoll_info *ni)
static void br_netpoll_cleanup(struct net_device *dev)
static void br_poll_controller(struct net_device *br_dev)

static int br_add_slave(struct net_device *dev, struct net_device *slave_dev,
static int br_del_slave(struct net_device *dev, struct net_device *slave_dev)
static netdev_features_t br_fix_features(struct net_device *dev, netdev_features_t features)


static const struct net_device_ops br_netdev_ops = {
	.ndo_open		 = br_dev_open,
	.ndo_stop		 = br_dev_stop,
	.ndo_init		 = br_dev_init,
	.ndo_uninit		 = br_dev_uninit,
	.ndo_start_xmit		 = br_dev_xmit,
	.ndo_get_stats64	 = br_get_stats64,
	.ndo_set_mac_address	 = br_set_mac_address,
	.ndo_set_rx_mode	 = br_dev_set_multicast_list,
	.ndo_change_rx_flags	 = br_dev_change_rx_flags,
	.ndo_change_mtu	 = br_change_mtu,
	.ndo_do_ioctl		 = br_dev_ioctl,            // br_ioctl.c
#ifdef CONFIG_NET_POLL_CONTROLLER
	.ndo_netpoll_setup	 = br_netpoll_setup,
	.ndo_netpoll_cleanup	 = br_netpoll_cleanup,
	.ndo_poll_controller	 = br_poll_controller,
#endif
	.ndo_add_slave		 = br_add_slave,
	.ndo_del_slave		 = br_del_slave,
	.ndo_fix_features       	 = br_fix_features,
	.ndo_fdb_add		 = br_fdb_add,           // br_fdb.c
	.ndo_fdb_del		 = br_fdb_delete,
	.ndo_fdb_dump		 = br_fdb_dump,
	.ndo_fdb_get		 = br_fdb_get,
	.ndo_bridge_getlink	 = br_getlink,             // br_netlink.c
	.ndo_bridge_setlink	 = br_setlink,
	.ndo_bridge_dellink	 = br_dellink,
};

void br_dev_setup(struct net_device *dev)

С сетевыми данными работает единственная функция br_dev_xmit, которая используется для отправки пакетов и является поверхностью атаки для исходящего трафика. Кроме этого функция br_dev_change_rx_flags управляет режимом сбора пакетов на интерфейсах (promiscuous mode).

Также стоит отметить, что структура struct net_device_ops используется в вызовах dev_ioctl и rtnetlink, что дает возможность вызывать соответствующие функции из пользовательского пространства.

br_fdb.c

Правила пересылки пакетов (forwarding database).

int __init br_fdb_init(void)
void br_fdb_fini(void)
int br_fdb_hash_init(struct net_bridge *br)
void br_fdb_hash_fini(struct net_bridge *br)

struct net_device *br_fdb_find_port(const struct net_device *br_dev, const unsigned char *addr,
				    __u16 vid)
EXPORT_SYMBOL_GPL(br_fdb_find_port);

struct net_bridge_fdb_entry *br_fdb_find_rcu(struct net_bridge *br, const unsigned char *addr,
					     __u16 vid)
void br_fdb_find_delete_local(struct net_bridge *br, const struct net_bridge_port *p,
			      const unsigned char *addr, u16 vid)
void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr)
void br_fdb_change_mac_address(struct net_bridge *br, const u8 *newaddr)
void br_fdb_cleanup(struct work_struct *work)
void br_fdb_flush(struct net_bridge *br)
void br_fdb_delete_by_port(struct net_bridge *br, const struct net_bridge_port *p, u16 vid, int do_all)

#if IS_ENABLED(CONFIG_ATM_LANE)
int br_fdb_test_addr(struct net_device *dev, unsigned char *addr)
#endif /* CONFIG_ATM_LANE */

int br_fdb_fillbuf(struct net_bridge *br, void *buf,
		   unsigned long maxnum, unsigned long skip)
int br_fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
		  const unsigned char *addr, u16 vid)
void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
		   const unsigned char *addr, u16 vid, unsigned long flags)
int br_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb, struct net_device *dev,
		struct net_device *filter_dev, int *idx)
int br_fdb_get(struct sk_buff *skb, struct nlattr *tb[],struct net_device *dev, const unsigned char *addr,
	       u16 vid, u32 portid, u32 seq, struct netlink_ext_ack *extack)
int br_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],struct net_device *dev, const unsigned char *addr,
	       u16 vid, u16 nlh_flags, struct netlink_ext_ack *extack)
int br_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[],struct net_device *dev,
		  const unsigned char *addr, u16 vid)
int br_fdb_sync_static(struct net_bridge *br, struct net_bridge_port *p)
void br_fdb_unsync_static(struct net_bridge *br, struct net_bridge_port *p)
int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
			      const unsigned char *addr, u16 vid, bool swdev_notify)
int br_fdb_external_learn_del(struct net_bridge *br, struct net_bridge_port *p,
			      const unsigned char *addr, u16 vid, bool swdev_notify)
void br_fdb_offloaded_set(struct net_bridge *br, struct net_bridge_port *p,
			  const unsigned char *addr, u16 vid, bool offloaded)

void br_fdb_clear_offload(const struct net_device *dev, u16 vid)
EXPORT_SYMBOL_GPL(br_fdb_clear_offload);

Внешнему функциональному указателю br_fdb_test_addr_hook присваивается значение br_fdb_test_addr (br_init/br.c).

С сетевыми данными работает единственная функция br_fdb_update, которая использует MAC-адрес из пакета (входящего или исходящего) для изменения записи в базе данных (forwarding database). Так же эта функция может использоваться через вызовы ioctl для добавления статических записей в базу данных. Функция br_fdb_fillbuf используется для получения записей из базы данных. Функция br_fdb_update являются поверхностью атаки для обоих направлений трафика. Также обе функции являются поверхностью атаки при вызовах из пользовательского пространства.

br_forward.c

Правила пересылки пакетов (forwarding decision).

int br_dev_queue_push_xmit(struct net *net, struct sock *sk, struct sk_buff *skb)
EXPORT_SYMBOL_GPL(br_dev_queue_push_xmit);
int br_forward_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
EXPORT_SYMBOL_GPL(br_forward_finish);
void br_forward(const struct net_bridge_port *to, struct sk_buff *skb, bool local_rcv, bool local_orig)
EXPORT_SYMBOL_GPL(br_forward);

void br_flood(struct net_bridge *br, struct sk_buff *skb, enum br_pkt_type pkt_type, bool local_rcv,
	      bool local_orig)

#ifdef CONFIG_BRIDGE_IGMP_SNOOPING  //  br_private.h
void br_multicast_flood(struct net_bridge_mdb_entry *mdst, struct sk_buff *skb, bool local_rcv,
			bool local_orig)
#else
// функция ничего не делает (отсутствует код)

С сетевыми данными работают все функции и используются или для отправки локальных пакетов, или для пересылки входящих пакетов. Поэтому все функции являются поверхностью атаки для обоих направлений трафика.

br_if.c

Пользовательский интерфейс для управления мостами.

void br_port_carrier_check(struct net_bridge_port *p, bool *notified);
int br_add_bridge(struct net *net, const char *name);
int br_del_bridge(struct net *net, const char *name);
int br_add_if(struct net_bridge *br, struct net_device *dev, struct netlink_ext_ack *extack);
int br_del_if(struct net_bridge *br, struct net_device *dev);
void br_mtu_auto_adjust(struct net_bridge *br);
netdev_features_t br_features_recompute(struct net_bridge *br, netdev_features_t features);
void br_port_flags_change(struct net_bridge_port *port, unsigned long mask);
void br_manage_promisc(struct net_bridge *br);
int nbp_backup_change(struct net_bridge_port *p, struct net_device *backup_dev);
void br_dev_delete(struct net_device *dev, struct list_head *list);

bool br_port_flag_is_set(const struct net_device *dev, unsigned long flag)
EXPORT_SYMBOL_GPL(br_port_flag_is_set);
static void release_nbp(struct kobject *kobj)
static void brport_get_ownership(struct kobject *kobj, kuid_t *uid, kgid_t *gid)

static struct kobj_type brport_ktype = {
#ifdef CONFIG_SYSFS
	.sysfs_ops = &brport_sysfs_ops,   //  br_sysfs_if.c
#endif
	.release = release_nbp,
	.get_ownership = brport_get_ownership,
};

С сетевыми данными функции не работают. Однако, большинство функций доступно при вызовах из пользовательского пространства через br_ioctl.c и br_sysfs_br.c, что требует дополнительного анализа.

br_input.c

Управление входящими сообщениями.

int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb);
EXPORT_SYMBOL_GPL(br_handle_frame_finish); 

rx_handler_func_t *br_get_rx_handler(const struct net_device *dev);

С сетевыми данными работают обе функции. br_handle_frame_finish используется для заключительной обработки пакета для обоих направлений трафика, br_get_rx_handler возвращает указатель на обработчик входящих пакетов: br_handle_frame_dummy (функция не выполняет никакого кода, только возвращает константное значение) или br_handle_frame. Через функцию br_add_if (br_if.c) при добавлении нового интерфейса происходит регистрация одного из этих обработчиков пакетов.

br_ioctl.c

Интерфейс ioctl.

int br_ioctl_deviceless_stub(struct net *net, unsigned int cmd, void __user *uarg)
int br_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
Интерфейс доступен при вызовах из пользовательского пространства и требует дополнительного анализа.

br_mrp.c

Поддержка протокола mrp (802.1Q Multiple Registration Protocol).

static void br_mrp_test_work_expired(struct work_struct *work)
static void br_mrp_in_test_work_expired(struct work_struct *work)

int br_mrp_add(struct net_bridge *br, struct br_mrp_instance *instance)
int br_mrp_del(struct net_bridge *br, struct br_mrp_instance *instance)
int br_mrp_set_port_state(struct net_bridge_port *p, enum br_mrp_port_state_type state)
int br_mrp_set_port_role(struct net_bridge_port *p, enum br_mrp_port_role_type role)
int br_mrp_set_ring_state(struct net_bridge *br, struct br_mrp_ring_state *state)
int br_mrp_set_ring_role(struct net_bridge *br, struct br_mrp_ring_role *role)
int br_mrp_start_test(struct net_bridge *br, struct br_mrp_start_test *test)
int br_mrp_set_in_state(struct net_bridge *br, struct br_mrp_in_state *state)
int br_mrp_set_in_role(struct net_bridge *br, struct br_mrp_in_role *role)
int br_mrp_start_in_test(struct net_bridge *br, struct br_mrp_start_in_test *in_test)

#if IS_ENABLED(CONFIG_BRIDGE_MRP)  //  br_private.h
int br_mrp_process(struct net_bridge_port *p, struct sk_buff *skb)
bool br_mrp_enabled(struct net_bridge *br)
void br_mrp_port_del(struct net_bridge *br, struct net_bridge_port *p)
#else
// функции ничего не делают (отсутствует код или возвращают константное значение)

С сетевыми данными работает единственная функция br_mrp_process, которая обрабатывает входящий трафик. Функции br_mrp_test_work_expired и br_mrp_in_test_work_expired регулярно вызываются по таймеру и отправляют служебные сообщения, но они не доступы для локального пользователя и внешнего трафика.

br_mrp_netlink.c

Интерфейс netlink для протокола mrp.

int br_mrp_ring_port_open(struct net_device *dev, u8 loc);
int br_mrp_in_port_open(struct net_device *dev, u8 loc);

#if IS_ENABLED(CONFIG_BRIDGE_MRP)  //  br_private.h
int br_mrp_parse(struct net_bridge *br, struct net_bridge_port *p,
		 struct nlattr *attr, int cmd, struct netlink_ext_ack *extack)
int br_mrp_fill_info(struct sk_buff *skb, struct net_bridge *br)
#else
// функции ничего не делают (отсутствует код или возвращают константное значение)

С сетевыми данными функции не работают.

br_mrp_switchdev.c

Взаимодействие протокола mrp с драйвером switchdev.

int br_mrp_switchdev_add(struct net_bridge *br, struct br_mrp *mrp)
int br_mrp_switchdev_del(struct net_bridge *br, struct br_mrp *mrp)
int br_mrp_switchdev_set_ring_role(struct net_bridge *br, struct br_mrp *mrp,
				   enum br_mrp_ring_role_type role)
int br_mrp_switchdev_send_ring_test(struct net_bridge *br, struct br_mrp *mrp, u32 interval,
				    u8 max_miss, u32 period, bool monitor)
int br_mrp_switchdev_set_ring_state(struct net_bridge *br, struct br_mrp *mrp,
				    enum br_mrp_ring_state_type state)
int br_mrp_switchdev_set_in_role(struct net_bridge *br, struct br_mrp *mrp, u16 in_id, u32 ring_id,
				 enum br_mrp_in_role_type role)
int br_mrp_switchdev_set_in_state(struct net_bridge *br, struct br_mrp *mrp,
				  enum br_mrp_in_state_type state)
int br_mrp_switchdev_send_in_test(struct net_bridge *br, struct br_mrp *mrp, u32 interval,
				  u8 max_miss, u32 period)
int br_mrp_port_switchdev_set_state(struct net_bridge_port *p, u32 state)
int br_mrp_port_switchdev_set_role(struct net_bridge_port *p, enum br_mrp_port_role_type role)

С сетевыми данными функции не работают.

br_mdb.c

Правила пересылки пакетов multicast (multicast database).

#ifdef CONFIG_BRIDGE_IGMP_SNOOPING  //  br_private.h
void br_mdb_notify(struct net_device *dev, struct net_bridge_mdb_entry *mp,
		   struct net_bridge_port_group *pg, int type)
void br_rtr_notify(struct net_device *dev, struct net_bridge_port *port, int type)
void br_mdb_init(void)
{
rtnl_register_module(THIS_MODULE, PF_BRIDGE, RTM_GETMDB, NULL, br_mdb_dump, 0);
rtnl_register_module(THIS_MODULE, PF_BRIDGE, RTM_NEWMDB, br_mdb_add, NULL, 0);
rtnl_register_module(THIS_MODULE, PF_BRIDGE, RTM_DELMDB, br_mdb_del, NULL, 0);
}
void br_mdb_uninit(void)
#else
// функции ничего не делают (отсутствует код или возвращают константное значение) или отсутствуют

static int br_mdb_dump(struct sk_buff *skb, struct netlink_callback *cb)
static int br_mdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, struct netlink_ext_ack *extack)
static int br_mdb_del(struct sk_buff *skb, struct nlmsghdr *nlh, struct netlink_ext_ack *extack)

С сетевыми данными функции не работают. Функции br_mdb_dump, br_mdb_add, br_mdb_del доступны из пользовательского пространства через вызовы net/core/rtnetlink.c.

br_multicast.c

Пересылка (forwarding) сообщений multicast (IGMP/MLD snooping).

bool br_multicast_enabled(const struct net_device *dev)
EXPORT_SYMBOL_GPL(br_multicast_enabled);
bool br_multicast_router(const struct net_device *dev)
EXPORT_SYMBOL_GPL(br_multicast_router);
int br_multicast_list_adjacent(struct net_device *dev, struct list_head *br_ip_list)
EXPORT_SYMBOL_GPL(br_multicast_list_adjacent);
bool br_multicast_has_querier_anywhere(struct net_device *dev, int proto)
EXPORT_SYMBOL_GPL(br_multicast_has_querier_anywhere);
bool br_multicast_has_querier_adjacent(struct net_device *dev, int proto)
EXPORT_SYMBOL_GPL(br_multicast_has_querier_adjacent);

#ifdef CONFIG_BRIDGE_IGMP_SNOOPING  //  br_private.h
int br_multicast_rcv(struct net_bridge *br, struct net_bridge_port *port, struct sk_buff *skb, u16 vid);
struct net_bridge_mdb_entry *br_mdb_get(struct net_bridge *br, struct sk_buff *skb, u16 vid);

static void br_multicast_router_expired(struct timer_list *t);
static void br_ip4_multicast_port_query_expired(struct timer_list *t);
static void br_ip6_multicast_port_query_expired(struct timer_list *t);
int br_multicast_add_port(struct net_bridge_port *port);
{
	timer_setup(&port->multicast_router_timer,  br_multicast_router_expired, 0);
	timer_setup(&port->ip4_own_query.timer,     br_ip4_multicast_port_query_expired, 0);
	timer_setup(&port->ip6_own_query.timer,     br_ip6_multicast_port_query_expired, 0);
} 
void br_multicast_del_port(struct net_bridge_port *port);
void br_multicast_enable_port(struct net_bridge_port *port);
void br_multicast_disable_port(struct net_bridge_port *port);

static void br_multicast_local_router_expired(struct timer_list *t);
static void br_ip4_multicast_querier_expired(struct timer_list *t);
static void br_ip6_multicast_querier_expired(struct timer_list *t);
static void br_ip4_multicast_query_expired(struct timer_list *t);
static void br_ip6_multicast_query_expired(struct timer_list *t);
static void br_multicast_gc_work(struct work_struct *work);
void br_multicast_init(struct net_bridge *br)
{
	timer_setup(&br->multicast_router_timer, br_multicast_local_router_expired, 0);
	timer_setup(&br->ip4_other_query.timer, br_ip4_multicast_querier_expired, 0);
	timer_setup(&br->ip4_own_query.timer, br_ip4_multicast_query_expired, 0);
#if IS_ENABLED(CONFIG_IPV6)
	timer_setup(&br->ip6_other_query.timer, br_ip6_multicast_querier_expired, 0);
	timer_setup(&br->ip6_own_query.timer, br_ip6_multicast_query_expired, 0);
#endif
	INIT_WORK(&br->mcast_gc_work, br_multicast_gc_work); 
}
void br_multicast_join_snoopers(struct net_bridge *br);
void br_multicast_leave_snoopers(struct net_bridge *br);
void br_multicast_open(struct net_bridge *br);
void br_multicast_stop(struct net_bridge *br);
void br_multicast_dev_del(struct net_bridge *br);
int br_multicast_set_router(struct net_bridge *br, unsigned long val);
int br_multicast_set_port_router(struct net_bridge_port *p, unsigned long val);
int br_multicast_toggle(struct net_bridge *br, unsigned long val);
int br_multicast_set_querier(struct net_bridge *br, unsigned long val);
int br_multicast_set_igmp_version(struct net_bridge *br, unsigned long val);
#if IS_ENABLED(CONFIG_IPV6)
int br_multicast_set_mld_version(struct net_bridge *br, unsigned long val);
#endif
struct net_bridge_mdb_entry * br_mdb_ip_get(struct net_bridge *br, struct br_ip *dst);

static void br_multicast_group_expired(struct timer_list *t);
struct net_bridge_mdb_entry * br_multicast_new_group(struct net_bridge *br, struct br_ip *group);
{
   timer_setup(&mp->timer, br_multicast_group_expired, 0);
}

static void br_multicast_port_group_expired(struct timer_list *t);
static void br_multicast_port_group_rexmit(struct timer_list *t);
struct net_bridge_port_group * br_multicast_new_port_group(struct net_bridge_port *port,
			    struct br_ip *group, struct net_bridge_port_group __rcu *next, 
			    unsigned char flags, const unsigned char *src, u8 filter_mode, u8 rt_protocol)
{
	timer_setup(&p->timer, br_multicast_port_group_expired, 0);
	timer_setup(&p->rexmit_timer, br_multicast_port_group_rexmit, 0);
}
int br_mdb_hash_init(struct net_bridge *br);
void br_mdb_hash_fini(struct net_bridge *br);
void br_multicast_del_pg(struct net_bridge_mdb_entry *mp, struct net_bridge_port_group *pg,
			 struct net_bridge_port_group __rcu **pp);
void br_multicast_count(struct net_bridge *br, const struct net_bridge_port *p,
			const struct sk_buff *skb, u8 type, u8 dir);
int br_multicast_init_stats(struct net_bridge *br);
void br_multicast_uninit_stats(struct net_bridge *br);
void br_multicast_get_stats(const struct net_bridge *br, const struct net_bridge_port *p,
			    struct br_mcast_stats *dest);
void br_multicast_host_join(struct net_bridge_mdb_entry *mp, bool notify);
void br_multicast_host_leave(struct net_bridge_mdb_entry *mp, bool notify);
void br_multicast_star_g_handle_mode(struct net_bridge_port_group *pg, u8 filter_mode);
void br_multicast_sg_add_exclude_ports(struct net_bridge_mdb_entry *star_mp,
				       struct net_bridge_port_group *sg);
#else
// функции ничего не делают или отсутствуют (отсутствует код или возвращают константное значение)

Функции br_ip4_multicast_port_query_expired, br_ip6_multicast_port_query_expired, br_ip4_multicast_query_expired, br_ip6_multicast_query_expired, br_multicast_port_group_rexmit, вызываемые по таймеру, отправляют служебные сообщения, но они не зависят напрямую от другого сетевого трафика.

Функции br_multicast_set_port_router, br_multicast_set_router, br_multicast_toggle, br_multicast_set_querier, br_multicast_set_igmp_version, br_multicast_set_mld_version доступны из пользовательского пространства через вызовы net/core/rtnetlink.c и br_sysfs_br.c.

Функции br_multicast_rcv, br_mdb_get, br_multicast_count работают с сетевыми данными в обоих направлениях и являются поверхностью атаки.

br_nf_core.c

Управление фильтрацией трафика (netfilter).

static struct dst_ops fake_dst_ops = {
	.family		= AF_INET,
	.update_pmtu	= fake_update_pmtu,  // функция не содержит полезного кода
	.redirect	= fake_redirect,           // функция не содержит полезного кода
	.cow_metrics	= fake_cow_metrics,    // функция не содержит полезного кода
	.neigh_lookup	= fake_neigh_lookup,   // функция не содержит полезного кода
	.mtu		= fake_mtu,
};
static unsigned int fake_mtu(const struct dst_entry *dst)

#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)  //  br_private.h
void br_netfilter_rtable_init(struct net_bridge *br)
int __init br_nf_core_init(void)
void br_nf_core_fini(void)
#else
// функции ничего не делают (отсутствует код или возвращают константное значение)

С сетевыми данными функции не работает.

br_netfilter_hooks.c

Управление фильтрацией трафика (netfilter).

unsigned int nf_bridge_encap_header_len(const struct sk_buff *skb)
void nf_bridge_update_protocol(struct sk_buff *skb)
int br_nf_pre_routing_finish_bridge(struct net *net, struct sock *sk, struct sk_buff *skb)
struct net_device *setup_pre_routing(struct sk_buff *skb, const struct net *net)

static int br_nf_dev_xmit(struct sk_buff *skb)

static const struct nf_br_ops br_ops = {
	.br_dev_xmit_hook =	br_nf_dev_xmit,
};

static unsigned int br_nf_pre_routing(void *priv, struct sk_buff *skb, const struct nf_hook_state *state)
static unsigned int br_nf_forward_ip(void *priv, struct sk_buff *skb, const struct nf_hook_state *state)
static unsigned int br_nf_forward_arp(void *priv, struct sk_buff *skb, const struct nf_hook_state *state)
static unsigned int br_nf_post_routing(void *priv, struct sk_buff *skb, const struct nf_hook_state *state)
static unsigned int ip_sabotage_in(void *priv, struct sk_buff *skb, const struct nf_hook_state *state)

static const struct nf_hook_ops br_nf_ops[] = {
	{
		.hook = br_nf_pre_routing,
		.pf = NFPROTO_BRIDGE,
	},
	{
		.hook = br_nf_forward_ip,
		.pf = NFPROTO_BRIDGE,
	},
	{
		.hook = br_nf_forward_arp,
		.pf = NFPROTO_BRIDGE,
	},
	{
		.hook = br_nf_post_routing,
		.pf = NFPROTO_BRIDGE,
	},
	{
		.hook = ip_sabotage_in,
		.pf = NFPROTO_IPV4,
	},
	{
		.hook = ip_sabotage_in,
		.pf = NFPROTO_IPV6,
	},
};

static int brnf_device_event(struct notifier_block *unused, unsigned long event, void *ptr)

static struct notifier_block brnf_notifier __read_mostly = {
	.notifier_call = brnf_device_event,
};

int br_nf_hook_thresh(unsigned int hook, struct net *net, struct sock *sk, struct sk_buff *skb,
		      struct net_device *indev, struct net_device *outdev,
		      int (*okfn)(struct net *, struct sock *, struct sk_buff *))

#ifdef CONFIG_SYSCTL
static int brnf_sysctl_call_tables(struct ctl_table *ctl, int write, void *buffer, size_t *lenp, loff_t *ppos)

static struct ctl_table brnf_table[] = {
	{
		.procname	= "bridge-nf-call-arptables",
		.proc_handler	= brnf_sysctl_call_tables,
	},
	{
		.procname	= "bridge-nf-call-iptables",
		.proc_handler	= brnf_sysctl_call_tables,
	},
	{
		.procname	= "bridge-nf-call-ip6tables",
		.proc_handler	= brnf_sysctl_call_tables,
	},
	{
		.procname	= "bridge-nf-filter-vlan-tagged",
		.proc_handler	= brnf_sysctl_call_tables,
	},
	{
		.procname	= "bridge-nf-filter-pppoe-tagged",
		.proc_handler	= brnf_sysctl_call_tables,
	},
	{
		.procname	= "bridge-nf-pass-vlan-input-dev",
		.proc_handler	= brnf_sysctl_call_tables,
	},
	{ }
};
#endif

static int __net_init brnf_init_net(struct net *net) 
static void __net_exit brnf_exit_net(struct net *net)

static struct pernet_operations brnf_net_ops __read_mostly = {
#ifdef CONFIG_SYSCTL
	.init = brnf_init_net,
#endif
	.exit = brnf_exit_net,
};

Почти все функции (см. таблицу выше) используются при пересылке (forwarding) пакетов, а значит источником может служить как входящий, так и исходящий трафик. Функции являются поверхностью атаки для обоих направлений трафика.

Функция brnf_sysctl_call_tables используется при вызовах sysctl и доступна из пользовательского пространства.

br_netfilter_ipv6.c

Управление фильтрацией трафика ipv6.

int br_validate_ipv6(struct net *net, struct sk_buff *skb)
unsigned int br_nf_pre_routing_ipv6(void *priv, struct sk_buff *skb, const struct nf_hook_state *state)

Обе функции работают с исходящим трафиком и являются поверхностью атаки.

br_netlink.c

Интерфейс управления мостами через netlink.

int br_netlink_init(void);
void br_netlink_fini(void);
void br_ifinfo_notify(int event, const struct net_bridge *br, const struct net_bridge_port *port);
int br_setlink(struct net_device *dev, struct nlmsghdr *nlmsg, u16 flags, struct netlink_ext_ack *extack);
int br_dellink(struct net_device *dev, struct nlmsghdr *nlmsg, u16 flags);
int br_getlink(struct sk_buff *skb, u32 pid, u32 seq, struct net_device *dev, u32 filter_mask, int nlflags);
int br_process_vlan_info(struct net_bridge *br, struct net_bridge_port *p, int cmd,
			 struct bridge_vlan_info *vinfo_curr, struct bridge_vlan_info **vinfo_last,
			 bool *changed, struct netlink_ext_ack *extack);

static size_t br_get_link_af_size_filtered(const struct net_device *dev, u32 filter_mask)

static struct rtnl_af_ops br_af_ops __read_mostly = {
	.family			= AF_BRIDGE,
	.get_link_af_size	= br_get_link_af_size_filtered,
};

static int br_validate(struct nlattr *tb[], struct nlattr *data[],struct netlink_ext_ack *extack)
static int br_dev_newlink(struct net *src_net, struct net_device *dev, struct nlattr *tb[],
			  struct nlattr *data[], struct netlink_ext_ack *extack)
static int br_changelink(struct net_device *brdev, struct nlattr *tb[],struct nlattr *data[],
			 struct netlink_ext_ack *extack)
static size_t br_get_size(const struct net_device *brdev)
static int br_fill_info(struct sk_buff *skb, const struct net_device *brdev) 
static int br_fill_linkxstats(struct sk_buff *skb, const struct net_device *dev, int *prividx, int attr)
static size_t br_get_linkxstats_size(const struct net_device *dev, int attr)
static int br_port_slave_changelink(struct net_device *brdev, struct net_device *dev, struct nlattr *tb[],
				    struct nlattr *data[],struct netlink_ext_ack *extack)
static size_t br_port_get_slave_size(const struct net_device *brdev, const struct net_device *dev)
static int br_port_fill_slave_info(struct sk_buff *skb, const struct net_device *brdev,
				   const struct net_device *dev)

struct rtnl_link_ops br_link_ops __read_mostly = {
	.setup			= br_dev_setup,     //  br_device.c
	.validate		= br_validate,
	.newlink		= br_dev_newlink,
	.changelink		= br_changelink,
	.dellink			= br_dev_delete,   //  br_if.c
	.get_size		= br_get_size,
	.fill_info		= br_fill_info,
	.fill_linkxstats		= br_fill_linkxstats,
	.get_linkxstats_size	= br_get_linkxstats_size,
	.slave_changelink	= br_port_slave_changelink,
	.get_slave_size		= br_port_get_slave_size,
	.fill_slave_info		= br_port_fill_slave_info,
};

С сетевыми данными функции не работают. Однако, большинство функций доступны через структуры struct rtnl_link_ops и struct net_device_ops, которые используются в вызовах dev_ioctl и rtnetlink, что дает возможность вызывать соответствующие функции из пользовательского пространства. Также функция br_ifinfo_notify используется в вызовах br_ioctl.c и br_sysfs_if.c.

Мы выделяем 9 функций, работающих с настройками мостов и требующих более глубокого анализа: br_setlink, br_dellink, br_getlink, br_dev_newlink, br_changelink, br_fill_info, br_port_slave_changelink, br_port_fill_slave_info, br_ifinfo_notify.

br_netlink_tunnel.c

Интерфейс управления мостами для портов туннелей vlan.

int br_parse_vlan_tunnel_info(struct nlattr *attr, struct vtunnel_info *tinfo);
			      
int br_process_vlan_tunnel_info(const struct net_bridge *br, const struct net_bridge_port *p, int cmd,
		struct vtunnel_info *tinfo_curr, struct vtunnel_info *tinfo_last, bool *changed);
int br_get_vlan_tunnel_info_size(struct net_bridge_vlan_group *vg);
int br_fill_vlan_tunnel_info(struct sk_buff *skb, struct net_bridge_vlan_group *vg);

#ifdef CONFIG_BRIDGE_VLAN_FILTERING  //  br_private_tunnel.h
bool vlan_tunid_inrange(const struct net_bridge_vlan *v_curr, const struct net_bridge_vlan *v_last);
int br_vlan_tunnel_info(const struct net_bridge_port *p, int cmd, u16 vid, u32 tun_id, bool *changed);

С сетевыми данными функции не работают. Функции br_parse_vlan_tunnel_info, br_process_vlan_tunnel_info, br_fill_vlan_tunnel_info, работающие с атрибутами туннелей, вызываются только через функции br_setlink, br_dellink, br_getlink (br_netlink.c).

br_stp.c

Поддержка протокола stp (Spanning tree protocol).

void br_set_state(struct net_bridge_port *p, unsigned int state);
struct net_bridge_port *br_get_port(struct net_bridge *br, u16 port_no);
void br_become_root_bridge(struct net_bridge *br);
void br_transmit_config(struct net_bridge_port *p);
void br_transmit_tcn(struct net_bridge *br);
void br_topology_change_detection(struct net_bridge *br);
void br_config_bpdu_generation(struct net_bridge *);
void br_configuration_update(struct net_bridge *);
void br_become_designated_port(struct net_bridge_port *p);
void br_port_state_selection(struct net_bridge *);
void br_received_config_bpdu(struct net_bridge_port *p, const struct br_config_bpdu *bpdu);
void br_received_tcn_bpdu(struct net_bridge_port *p);
int br_set_hello_time(struct net_bridge *br, unsigned long x);
int br_set_max_age(struct net_bridge *br, unsigned long x);
int __set_ageing_time(struct net_device *dev, unsigned long t);
int br_set_ageing_time(struct net_bridge *br, clock_t ageing_time);
void __br_set_topology_change(struct net_bridge *br, unsigned char val);
void __br_set_forward_delay(struct net_bridge *br, unsigned long t);
int br_set_forward_delay(struct net_bridge *br, unsigned long x);

С входящими сообщениями работают две функции: br_received_tcn_bpdu (с сетевыми данными не работает) и br_received_config_bpdu (работает с сетевыми данными и является поверхностью атаки для входящего трафика). Обе функции вызываются через функцию br_stp_rcv (br_stp_bpdu.c).

Функции br_set_hello_time, br_set_max_age, br_set_ageing_time, br_set_forward_delay (используются для установки значений соответствующих параметров моста), br_get_port доступны при вызовах из пользовательского пространства через br_ioctl.c, br_netlink.c и br_sysfs_br.c.

br_stp_bpdu.c

Протокол stp, управление сообщениями BPDU.

void br_send_config_bpdu(struct net_bridge_port *, struct br_config_bpdu *);
void br_send_tcn_bpdu(struct net_bridge_port *);
void br_stp_rcv(const struct stp_proto *proto, struct sk_buff *skb, struct net_device *dev);

Первые две функции отправляют служебные сообщения протокола, их содержание формируется самим протоколом. С входящими сетевыми данными работает функция @br_stp_rcv@, которая является основным обработчиком входящих сообщений протокола stp, и является поверхностью атаки для входящего трафика.

br_stp_if.c

Интерфейс протокола stp.

void br_init_port(struct net_bridge_port *p);
void br_stp_enable_bridge(struct net_bridge *br);
void br_stp_disable_bridge(struct net_bridge *br);
void br_stp_enable_port(struct net_bridge_port *p);
void br_stp_disable_port(struct net_bridge_port *p);
int br_stp_set_enabled(struct net_bridge *br, unsigned long val, struct netlink_ext_ack *extack);
void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *a);
bool br_stp_recalculate_bridge_id(struct net_bridge *br);
void br_stp_set_bridge_priority(struct net_bridge *br, u16 newprio);
int br_stp_set_port_priority(struct net_bridge_port *p, unsigned long newprio);
int br_stp_set_path_cost(struct net_bridge_port *p, unsigned long path_cost);
ssize_t br_show_bridge_id(char *buf, const struct bridge_id *id);

С сетевыми данными никто не работает. Функции br_stp_set_enabled, br_stp_set_bridge_priority, br_stp_set_port_priority, br_stp_set_path_cost (используются для установки значений соответствующих параметров моста) доступны при вызовах из пользовательского пространства через br_ioctl.c, br_netlink.c и br_sysfs_br.c.

br_stp_timer.c

Протокол stp. Установка таймеров.

void br_stp_timer_init(struct net_bridge *br);
void br_stp_port_timer_init(struct net_bridge_port *p);
unsigned long br_timer_value(const struct timer_list *timer);

С сетевыми данными функции не работают.

br_switchdev.c

Модель драйвера коммутатора Ethernet.

#ifdef CONFIG_NET_SWITCHDEV  //  br_private.h
int nbp_switchdev_mark_set(struct net_bridge_port *p);
void nbp_switchdev_frame_mark(const struct net_bridge_port *p, struct sk_buff *skb);
bool nbp_switchdev_allowed_egress(const struct net_bridge_port *p, const struct sk_buff *skb);
int br_switchdev_set_port_flag(struct net_bridge_port *p, unsigned long flags, unsigned long mask);
void br_switchdev_fdb_notify(const struct net_bridge_fdb_entry *fdb, int type);
int br_switchdev_port_vlan_add(struct net_device *dev, u16 vid, u16 flags,
			       struct netlink_ext_ack *extack);
int br_switchdev_port_vlan_del(struct net_device *dev, u16 vid);
#else
// функции ничего не делают (отсутствует код или возвращают константное значение)

Функции nbp_switchdev_frame_mark и nbp_switchdev_allowed_egress работают с флагом offload_fwd_mark и структурой struct br_input_skb_cb. Предположительно, используются при пересылке входящих пакетов (forwarding) и соответственно являются поверхностью атаки для входящего трафика.

br_switchdev_set_port_flag (установка флагов) доступна при вызовах из пользовательского пространства через br_netlink.c и br_sysfs_if.c.

br_sysfs_br.c

Конфигурация файловой системы sysfs, атрибуты мостов.

static struct attribute *bridge_attrs[] = {
	&dev_attr_forward_delay.attr,
	&dev_attr_hello_time.attr,
	&dev_attr_max_age.attr,
	&dev_attr_ageing_time.attr,
	&dev_attr_stp_state.attr,
	&dev_attr_group_fwd_mask.attr,
	&dev_attr_priority.attr,
	&dev_attr_bridge_id.attr,
	&dev_attr_root_id.attr,
	&dev_attr_root_path_cost.attr,
	&dev_attr_root_port.attr,
	&dev_attr_topology_change.attr,
	&dev_attr_topology_change_detected.attr,
	&dev_attr_hello_timer.attr,
	&dev_attr_tcn_timer.attr,
	&dev_attr_topology_change_timer.attr,
	&dev_attr_gc_timer.attr,
	&dev_attr_group_addr.attr,
	&dev_attr_flush.attr,
	&dev_attr_no_linklocal_learn.attr,
#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
	&dev_attr_multicast_router.attr,
	&dev_attr_multicast_snooping.attr,
	&dev_attr_multicast_querier.attr,
	&dev_attr_multicast_query_use_ifaddr.attr,
	&dev_attr_hash_elasticity.attr,
	&dev_attr_hash_max.attr,
	&dev_attr_multicast_last_member_count.attr,
	&dev_attr_multicast_startup_query_count.attr,
	&dev_attr_multicast_last_member_interval.attr,
	&dev_attr_multicast_membership_interval.attr,
	&dev_attr_multicast_querier_interval.attr,
	&dev_attr_multicast_query_interval.attr,
	&dev_attr_multicast_query_response_interval.attr,
	&dev_attr_multicast_startup_query_interval.attr,
	&dev_attr_multicast_stats_enabled.attr,
	&dev_attr_multicast_igmp_version.attr,
#if IS_ENABLED(CONFIG_IPV6)
	&dev_attr_multicast_mld_version.attr,
#endif
#endif
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
	&dev_attr_nf_call_iptables.attr,
	&dev_attr_nf_call_ip6tables.attr,
	&dev_attr_nf_call_arptables.attr,
#endif
#ifdef CONFIG_BRIDGE_VLAN_FILTERING
	&dev_attr_vlan_filtering.attr,
	&dev_attr_vlan_protocol.attr,
	&dev_attr_default_pvid.attr,
	&dev_attr_vlan_stats_enabled.attr,
	&dev_attr_vlan_stats_per_port.attr,
#endif
	NULL
};

static const struct attribute_group bridge_group = {
	.name = SYSFS_BRIDGE_ATTR,
	.attrs = bridge_attrs,
};

static ssize_t brforward_read(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr,
			      char *buf, loff_t off, size_t count)

static struct bin_attribute bridge_forward = {
	.attr = { .name = SYSFS_BRIDGE_FDB,
		  .mode = 0444, },
	.read = brforward_read,
};

#ifdef CONFIG_SYSFS  //  br_private.h
int br_sysfs_addbr(struct net_device *dev);
void br_sysfs_delbr(struct net_device *dev);
#else
// функции ничего не делают (отсутствует код или возвращают константное значение)

Данный подмодуль доступен из пользовательского пространства.

br_sysfs_if.c

Конфигурация файловой системы sysfs, атрибуты портов.

static const struct brport_attribute *brport_attrs[] = {
	&brport_attr_path_cost,
	&brport_attr_priority,
	&brport_attr_port_id,
	&brport_attr_port_no,
	&brport_attr_designated_root,
	&brport_attr_designated_bridge,
	&brport_attr_designated_port,
	&brport_attr_designated_cost,
	&brport_attr_state,
	&brport_attr_change_ack,
	&brport_attr_config_pending,
	&brport_attr_message_age_timer,
	&brport_attr_forward_delay_timer,
	&brport_attr_hold_timer,
	&brport_attr_flush,
	&brport_attr_hairpin_mode,
	&brport_attr_bpdu_guard,
	&brport_attr_root_block,
	&brport_attr_learning,
	&brport_attr_unicast_flood,
#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
	&brport_attr_multicast_router,
	&brport_attr_multicast_fast_leave,
	&brport_attr_multicast_to_unicast,
#endif
	&brport_attr_proxyarp,
	&brport_attr_proxyarp_wifi,
	&brport_attr_multicast_flood,
	&brport_attr_broadcast_flood,
	&brport_attr_group_fwd_mask,
	&brport_attr_neigh_suppress,
	&brport_attr_isolated,
	&brport_attr_backup_port,
	NULL
};

static ssize_t brport_show(struct kobject *kobj, struct attribute *attr, char *buf)
static ssize_t brport_store(struct kobject *kobj, struct attribute *attr, const char *buf, size_t count)

const struct sysfs_ops brport_sysfs_ops = {
	.show = brport_show,
	.store = brport_store,
};

#ifdef CONFIG_SYSFS  //  br_private.h
int br_sysfs_addif(struct net_bridge_port *p);
int br_sysfs_renameif(struct net_bridge_port *p);
#else
// функции ничего не делают (отсутствует код или возвращают константное значение)

Данный подмодуль доступен из пользовательского пространства.

br_vlan.c

Поддержка vlan.

static inline int br_vlan_cmp(struct rhashtable_compare_arg *arg, const void *ptr)

static const struct rhashtable_params br_vlan_rht_params = {
	.obj_cmpfn = br_vlan_cmp,
};

bool br_vlan_enabled(const struct net_device *dev)
EXPORT_SYMBOL_GPL(br_vlan_enabled);
int br_vlan_get_proto(const struct net_device *dev, u16 *p_proto)
EXPORT_SYMBOL_GPL(br_vlan_get_proto);
int br_vlan_get_pvid(const struct net_device *dev, u16 *p_pvid)
EXPORT_SYMBOL_GPL(br_vlan_get_pvid);
int br_vlan_get_pvid_rcu(const struct net_device *dev, u16 *p_pvid)
EXPORT_SYMBOL_GPL(br_vlan_get_pvid_rcu);
int br_vlan_get_info(const struct net_device *dev, u16 vid, struct bridge_vlan_info *p_vinfo)
EXPORT_SYMBOL_GPL(br_vlan_get_info);

#ifdef CONFIG_BRIDGE_VLAN_FILTERING  //  br_private.h
struct sk_buff *br_handle_vlan(struct net_bridge *br, const struct net_bridge_port *port,
			       struct net_bridge_vlan_group *vg, struct sk_buff *skb);
bool br_allowed_ingress(const struct net_bridge *br, struct net_bridge_vlan_group *vg,
			struct sk_buff *skb, u16 *vid, u8 *state);
bool br_allowed_egress(struct net_bridge_vlan_group *vg, const struct sk_buff *skb);
bool br_should_learn(struct net_bridge_port *p, struct sk_buff *skb, u16 *vid);
int br_vlan_add(struct net_bridge *br, u16 vid, u16 flags, bool *changed,
		struct netlink_ext_ack *extack);
int br_vlan_delete(struct net_bridge *br, u16 vid);
void br_vlan_flush(struct net_bridge *br);
struct net_bridge_vlan *br_vlan_find(struct net_bridge_vlan_group *vg, u16 vid);
void br_recalculate_fwd_mask(struct net_bridge *br);
int __br_vlan_filter_toggle(struct net_bridge *br, unsigned long val);
int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val);
int __br_vlan_set_proto(struct net_bridge *br, __be16 proto);
int br_vlan_set_proto(struct net_bridge *br, unsigned long val);
int br_vlan_set_stats(struct net_bridge *br, unsigned long val);
int br_vlan_set_stats_per_port(struct net_bridge *br, unsigned long val);
int __br_vlan_set_default_pvid(struct net_bridge *br, u16 pvid, struct netlink_ext_ack *extack);
int br_vlan_set_default_pvid(struct net_bridge *br, unsigned long val);
int br_vlan_init(struct net_bridge *br);
int nbp_vlan_init(struct net_bridge_port *port, struct netlink_ext_ack *extack);
int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags, bool *changed,
		 struct netlink_ext_ack *extack);
int nbp_vlan_delete(struct net_bridge_port *port, u16 vid);
void nbp_vlan_flush(struct net_bridge_port *port);
void br_vlan_get_stats(const struct net_bridge_vlan *v, struct br_vlan_stats *stats);
int br_vlan_bridge_event(struct net_device *dev, unsigned long event, void *ptr);
void br_vlan_port_event(struct net_bridge_port *p, unsigned long event);
void br_vlan_notify(const struct net_bridge *br, const struct net_bridge_port *p, u16 vid, u16 vid_range,
		    int cmd);
bool br_vlan_can_enter_range(const struct net_bridge_vlan *v_curr,
			     const struct net_bridge_vlan *range_end);
void br_vlan_rtnl_init(void)
{
	rtnl_register_module(THIS_MODULE, PF_BRIDGE, RTM_GETVLAN, NULL,
			     br_vlan_rtm_dump, 0);
	rtnl_register_module(THIS_MODULE, PF_BRIDGE, RTM_NEWVLAN,
			     br_vlan_rtm_process, NULL, 0);
	rtnl_register_module(THIS_MODULE, PF_BRIDGE, RTM_DELVLAN,
			     br_vlan_rtm_process, NULL, 0);
}
void br_vlan_rtnl_uninit(void);
#else
// функции ничего не делают (отсутствует код или возвращают константное значение) или отсутствуют

static int br_vlan_rtm_dump(struct sk_buff *skb, struct netlink_callback *cb);
static int br_vlan_rtm_process(struct sk_buff *skb, struct nlmsghdr *nlh, struct netlink_ext_ack *extack);

Функции br_handle_vlan, br_allowed_ingress, br_allowed_egress работают с сетевыми данными в обоих направлениях.

Функция br_should_learn работает с входящим трафиком.

11 функций (см. таблицу выше) доступны из пользовательского пространства через вызовы net/core/rtnetlink.c, br_sysfs_br.c.

br_vlan_options.c

Поддержка vlan.

#ifdef CONFIG_BRIDGE_VLAN_FILTERING  //  br_private.h
bool br_vlan_opts_eq_range(const struct net_bridge_vlan *v_curr,
			   const struct net_bridge_vlan *range_end);
bool br_vlan_opts_fill(struct sk_buff *skb, const struct net_bridge_vlan *v);
size_t br_vlan_opts_nl_size(void);
int br_vlan_process_options(const struct net_bridge *br, const struct net_bridge_port *p,
			    struct net_bridge_vlan *range_start, struct net_bridge_vlan *range_end,
			    struct nlattr **tb, struct netlink_ext_ack *extack);

Функции с сетевыми данными не работают.

br_vlan_tunnel.c

Мост для портов туннелей vlan.

static inline int br_vlan_tunid_cmp(struct rhashtable_compare_arg *arg, const void *ptr)
				
static const struct rhashtable_params br_vlan_tunnel_rht_params = {
	.obj_cmpfn = br_vlan_tunid_cmp,
};

#ifdef CONFIG_BRIDGE_VLAN_FILTERING  //  br_private_tunnel.h
int vlan_tunnel_init(struct net_bridge_vlan_group *vg);
void vlan_tunnel_deinit(struct net_bridge_vlan_group *vg);
int nbp_vlan_tunnel_info_delete(const struct net_bridge_port *port, u16 vid);
int nbp_vlan_tunnel_info_add(const struct net_bridge_port *port, u16 vid, u32 tun_id);
void nbp_vlan_tunnel_info_flush(struct net_bridge_port *port);
void vlan_tunnel_info_del(struct net_bridge_vlan_group *vg, struct net_bridge_vlan *vlan);
int br_handle_ingress_vlan_tunnel(struct sk_buff *skb, struct net_bridge_port *p,
				  struct net_bridge_vlan_group *vg);
int br_handle_egress_vlan_tunnel(struct sk_buff *skb, struct net_bridge_vlan *vlan);
#else
// функции ничего не делают (отсутствует код или возвращают константное значение)

Функции br_handle_ingress_vlan_tunnel и br_handle_egress_vlan_tunnel используются при пересылке пакетов через туннель соответственно для входящего и двустороннего трафика, являются поверхностью атаки.

br_private.h

#ifdef CONFIG_BRIDGE_VLAN_FILTERING
int nbp_get_num_vlan_infos(struct net_bridge_port *p, u32 filter_mask);
#else
// функция ничего не делает (возвращает константное значение)

#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
int br_multicast_set_hash_max(struct net_bridge *br, unsigned long val);
#else
// функция отсутствует

Обе функции нигде не используются.

static inline struct net_bridge_port *br_port_get_rcu(const struct net_device *dev);
static inline struct net_bridge_port *br_port_get_rtnl(const struct net_device *dev);
static inline struct net_bridge_port *br_port_get_rtnl_rcu(const struct net_device *dev);

Функции с сетевыми данными не работают.

Заключение

Проведенный анализ модуля Bridge (net/bridge) показал, что 8 функций этого модуля представляют поверхность атаки для входящего сетевого трафика, 6 – используются для исходящего трафика, 25 – могут использоваться в обоих направлениях. Кроме этого, 45 функций и два подмодуля br_sysfs_br.c, br_sysfs_if.c являются поверхностью атаки при вызовах из пользовательского пространства (данные функции оперируют не сетевыми данными, а настройками сетевой подсистемы Linux). Каталог net/bridge/netfilter не изучался.