Модуль, реализующий поддержку протокола управления логическим каналом Logical Link Layer, IEEE 802.2 (net/llc)
Ниже представлены результаты анализа поверхности атаки для модуля LLC с точки зрения зависимости от сетевого трафика.
LLC (Logical Link Control, уровень управления логической связью) – верхний подуровень канального уровня модели OSI. Протокол LLC связывает протоколы сетевого уровня с протоколами уровня MAC.
В соответствии со стандартом IEEE 802.2 уровень управления логическим каналом предоставляет верхним уровням три типа процедур:
- LLC1 – процедура без установления соединения и без подтверждения;
- LLC2 – процедура с установлением соединения и подтверждением;
- LLC3 – процедура без установления соединения, но с подтверждением.
По своему назначению кадры уровня LLC, называемые в стандарте блоками данных (Protocol Data Unit, PDU), подразделяются на три типа – информационные, управляющие и ненумерованные.
- Информационные кадры предназначены для передачи информации в процедурах с установлением логического соединения и должны обязательно содержать поле информации. В процессе передачи информационных блоков осуществляется их нумерация в режиме скользящего окна.
- Управляющие кадры предназначены для передачи команд и ответов в процедурах с установлением логического соединения, в том числе запросов на повторную передачу искаженных информационных блоков.
- Ненумерованные кадры предназначены для передачи ненумерованных команд и ответов, выполняющих в процедурах без установления логического соединения передачу информации, идентификацию и тестирование LLC-уровня, а в процедурах с установлением логического соединения – установление и разъединение логического соединения, а также информирование об ошибках.
В режиме LLC1 используется только один тип кадра – ненумерованный.
В режиме LLC2 используются все три типа кадров. В этом режиме кадры делятся на команды и ответы на эти команды.
Стоит отметить, что кадры LLC могут переносить как пользовательские данные, так и команды самого протокола LLC (например, установить или разорвать соединение для соединений типа LLC2).
Минимальная функциональность протокола содержится в трех файлах:
llc_core.c– минимальная функциональность для управления точками доступа SAP (Service Access Point),llc_input.c– обработка входящего трафика,llc_output.c– обработка исходящего трафика.
Для использования протокола LLC с установлением соединения (LLC2) и поддержки сокетов типа PF_LLC требуется подключить дополнительный подмодуль. Соответствующая функциональность находится в следующих файлах:
af_llc.c– пользовательский интерфейс сокетов LLC,llc_if.c– интерфейс LLC для протоколов верхнего уровня,llc_conn.c– интерфейс драйвера для компонента соединений,llc_sap.c– интерфейс драйвера для компонента SAP,llc_station.c– компонент LLC station,llc_pdu.c– управление значениями полей кадра PDU.
Описание конечного автомата (state machine) для компонента соединений содержится в файлах:
llc_c_ac.c– действия (actions) при переходах между состояниями,llc_c_ev.c– события (events),llc_c_st.c– переходы конечного автомата (state machine transitions).
Описание конечного автомата (state machine) компонента SAP:
llc_s_ac.c– действия (actions) при переходах между состояниями,llc_s_ev.c– события (events),llc_s_st.c– переходы конечного автомата (state machine transitions).
Дополнительные подмодули:
llc_proc.c– интерфейс специальной файловой системы proc,sysctl_net_llc.c– интерфейс sysctl для сетевой подсистемы LLC.
Ниже на диаграмме косые четырехугольники – это статические (static) функции, которые вызываются или через функциональный указатель или внутри модуля.
Красным цветом выделены интерфейсные функции, которые могут являться поверхностью атаки.
Оранжевым цветом выделены интерфейсные функции, которые могут являться поверхностью атаки при вызовах из недоверенного пользовательского пространства.
Розовым цветом выделены интерфейсные функции, требующие более глубокого анализа с точки зрения поверхности атаки.
Темно-серые прямоугольники – это интерфейсные функции, которые не оперируют сетевыми данными и не является поверхностью атаки.
Зеленые ромбы на диаграммах - это один или несколько элементов некоторой структуры, которые являются указателями на функции. Если из ромба выходит стрелка, значит элементу соответствующей структуры присвоено имя функции, на которую указывает стрелка. Если стрелка входит в ромб из функции, значит в этой функции имеется вызов функции по соответствующему указателю. Зеленые прямоугольники – это структуры, переопределяющие структуру обозначенную зеленым ромбом.

Сводная таблица результатов анализа
| Имя подмодуля и/или функции | Назначение | Поверхность атаки |
|---|---|---|
| llc_core.c: llc_sap_find, llc_sap_open, llc_sap_close | Минимальная функциональность для управления точками доступа SAP | Нет |
| llc_input.c | Обработка входящего трафика | |
| llc_add_pack, llc_remove_pack | Нет | |
| llc_set_station_handler | Устанавливает указатель на обработчик входящих пакетов. | Нет |
| llc_rcv | Первичная обработка входящего трафика. Точка входа для протоколов нижнего уровня. | Да |
| llc_output.c | обработка исходящего трафика | |
| llc_mac_hdr_init | Инициализация заголовка MAC | Да |
| llc_build_and_send_ui_pkt | Интерфейсная функция отправки данных без установления соединения (connection-less) для протоколов верхнего уровня. | Да |
| af_llc.c | Пользовательский интерфейс сокетов LLC | |
| llc_ui_create, llc_ui_release, llc_ui_bind, llc_ui_shutdown, llc_ui_connect, llc_ui_listen, llc_ui_accept, llc_ui_sendmsg, llc_ui_getname, llc_ui_ioctl, llc_ui_setsockopt, llc_ui_getsockopt | Стандартные методы интерфейса сокетов | Да |
| llc_ui_recvmsg | Получение пришедших данных | Да |
| llc_if.c: llc_build_and_send_pkt, llc_establish_connection, llc_send_disc | Интерфейс LLC для протоколов верхнего уровня. Все функции вызываются через интерфейс LLC сокета. | Да |
| llc_conn.c | Интерфейс драйвера для компонента соединений | |
| llc_sk_alloc, llc_sk_stop_all_timers, llc_sk_free, llc_sk_reset, llc_conn_remove_acked_pdus, llc_lookup_established, llc_data_accept_state, llc_build_offset_table, llc_sap_add_socket, llc_sap_remove_socket | Нет | |
| llc_conn_send_pdu, llc_conn_resend_i_pdu_as_cmd, llc_conn_resend_i_pdu_as_rsp | Отправка кадров | Да |
| llc_conn_rtn_pdu, llc_conn_state_process, llc_conn_handler, llc_backlog_rcv | Обработка входящих кадров | Да |
| llc_sap.c | Интерфейс драйвера для компонента SAP | |
| llc_alloc_frame | Выделение памяти | Нет |
| llc_save_primitive | Да | |
| llc_sap_rtn_pdu | Информирование протокола верхнего уровня о типе пришедших данных. | Да |
| llc_sap_handler | Обработчик входящих данных компонентом SAP. | Да |
| llc_build_and_send_test_pkt, llc_build_and_send_xid_pkt | Интерфейсные функции для протоколов верхнего уровня для отправки разных типов PDU. | Да |
| llc_station.c: llc_station_rcv | Компонент LLC station. Передача полученного PDU для обработки в конечный автомат станции (station state machine). | Да |
| llc_proc.c | Интерфейс специальной файловой системы proc | Да |
| sysctl_net_llc.c | Интерфейс sysctl для сетевой подсистемы LLC | Да |
| llc_pdu.c | Управление значениями полей кадра PDU | Да, требуется дополнительный анализ |
| llc_c_ac.c | Действия (actions) при переходах между состояниями конечного автомата (КА) компонента соединений (КС) | Требуется дополнительный анализ |
| llc_c_ev.c | События (events) КА КС | Требуется дополнительный анализ |
| llc_c_st.c | Переходы (transitions) КА КС | Нет |
| llc_s_ac.c | Действия (actions) при переходах между состояниями конечного автомата (КА) компонента SAP | Требуется дополнительный анализ |
| llc_s_ev.c | События (events) КА SAP | Требуется дополнительный анализ |
| llc_s_st.c | Переходы (transitions) КА SAP | Нет |
Распределение функций, являющихся поверхностью атаки, по направлению трафика
| Имя функции | Направление трафика |
|---|---|
| llc_input.c | |
| llc_rcv | Входящий |
| llc_output.c | |
| llc_mac_hdr_init, llc_build_and_send_ui_pkt | Исходящий |
| af_llc.c | |
| llc_ui_create, llc_ui_release, llc_ui_bind, llc_ui_shutdown, llc_ui_connect, llc_ui_listen, llc_ui_accept, llc_ui_getname, llc_ui_ioctl, llc_ui_setsockopt, llc_ui_getsockopt | Из пользовательского пространства |
| llc_ui_sendmsg | Исходящий |
| llc_ui_recvmsg | Входящий |
| llc_if.c | |
| llc_build_and_send_pkt, llc_establish_connection, llc_send_disc | Исходящий |
| llc_conn.c | |
| llc_conn_send_pdu, llc_conn_resend_i_pdu_as_cmd, llc_conn_resend_i_pdu_as_rsp | Исходящий |
| llc_conn_rtn_pdu, llc_conn_handler, llc_backlog_rcv | Входящий |
| llc_conn_state_process | В обоих направлениях |
| llc_sap.c | |
| llc_sap_rtn_pdu, llc_sap_handler | Входящий |
| llc_save_primitive | В обоих направлениях |
| llc_build_and_send_test_pkt, llc_build_and_send_xid_pkt | Исходящий |
| llc_station.c | |
| llc_station_rcv | Входящий |
| llc_proc.c | Из пользовательского пространства |
| sysctl_net_llc.c | Из пользовательского пространства |
| llc_pdu.c | Требуется дополнительный анализ |
| llc_c_ac.c | Требуется дополнительный анализ |
| llc_c_ev.c | Требуется дополнительный анализ |
| llc_s_ac.c | Требуется дополнительный анализ |
| llc_s_ev.c | Требуется дополнительный анализ |
Ниже перечислены все файлы и функции, доступные для вызова вне модуля.
llc_core.c
Минимальная функциональность для управления точками доступа SAP (Service Access Point) и инициализации всего модуля LLC.
struct llc_sap *llc_sap_find(unsigned char sap_value)
struct llc_sap *llc_sap_open(unsigned char lsap,
int (*func)(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt,
struct net_device *orig_dev))
void llc_sap_close(struct llc_sap *sap)
static struct packet_type llc_packet_type __read_mostly = {
.type = cpu_to_be16(ETH_P_802_2),
.func = llc_rcv,
};
static struct packet_type llc_tr_packet_type __read_mostly = {
.type = cpu_to_be16(ETH_P_TR_802_2),
.func = llc_rcv,
};
С сетевыми данными функции модуля не работают. Две структуры используют указатель на функцию llc_rcv (llc_input.c).
llc_input.c
Обработка входящего трафика.
void llc_add_pack(int type, void (*handler)(struct llc_sap *sap, struct sk_buff *skb))
void llc_remove_pack(int type)
void llc_set_station_handler(void (*handler)(struct sk_buff *skb))
int llc_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt, struct net_device *orig_dev)
С сетевыми данные обрабатываются только в функции llc_rcv, которая является первичным обработчиком входящих пакетов и точкой входа для протоколов нижнего уровня.
Функция llc_set_station_handler устанавливает указатель на обработчик входящих пакетов llc_station_rcv (llc_station.c), который затем вызывается через llc_rcv.
llc_output.c
Обработка исходящего трафика.
int llc_mac_hdr_init(struct sk_buff *skb, const unsigned char *sa, const unsigned char *da)
int llc_build_and_send_ui_pkt(struct llc_sap *sap, struct sk_buff *skb, unsigned char *dmac,
unsigned char dsap)
llc_mac_hdr_init – инициализация заголовка MAC.
llc_build_and_send_ui_pkt – интерфейсная функция отправки данных для протоколов верхнего уровня при использовании соединений LLC1 (connection-less).
Обе функции являются поверхностью атаки при вызовах из пользовательского пространства.
af_llc.c
Пользовательский интерфейс сокетов LLC.
static int llc_ui_create(struct net *net, struct socket *sock, int protocol, int kern)
static int llc_ui_release(struct socket *sock)
static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen)
static int llc_ui_shutdown(struct socket *sock, int how)
static int llc_ui_connect(struct socket *sock, struct sockaddr *uaddr, int addrlen, int flags)
static int llc_ui_listen(struct socket *sock, int backlog)
static int llc_ui_accept(struct socket *sock, struct socket *newsock, int flags, bool kern)
static int llc_ui_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, int flags)
static int llc_ui_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
static int llc_ui_getname(struct socket *sock, struct sockaddr *uaddr, int peer)
static int llc_ui_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
static int llc_ui_setsockopt(struct socket *sock, int level, int optname, sockptr_t optval,
unsigned int optlen)
static int llc_ui_getsockopt(struct socket *sock, int level, int optname, char __user *optval,
int __user *optlen)
static const struct net_proto_family llc_ui_family_ops = {
.create = llc_ui_create,
};
static const struct proto_ops llc_ui_ops = {
.release = llc_ui_release,
.bind = llc_ui_bind,
.connect = llc_ui_connect,
.accept = llc_ui_accept,
.getname = llc_ui_getname,
.ioctl = llc_ui_ioctl,
.listen = llc_ui_listen,
.shutdown = llc_ui_shutdown,
.setsockopt = llc_ui_setsockopt,
.getsockopt = llc_ui_getsockopt,
.sendmsg = llc_ui_sendmsg,
.recvmsg = llc_ui_recvmsg,
};
Данный модуль целиком является поверхностью атаки при вызовах из пользовательского пространства. С входящим трафиком работает только функция recvmsg.
llc_if.c
Интерфейс LLC для протоколов верхнего уровня.
int llc_build_and_send_pkt(struct sock *sk, struct sk_buff *skb)
int llc_establish_connection(struct sock *sk, u8 *lmac, u8 *dmac, u8 dsap)
int llc_send_disc(struct sock *sk)
Все функции являются поверхностью атаки при вызовах из пользовательского пространства, вызываются через указанный выше интерфейс сокета af_llc.
llc_conn.c
Интерфейс драйвера для компонента соединений.
int llc_conn_state_process(struct sock *sk, struct sk_buff *skb)
void llc_conn_send_pdu(struct sock *sk, struct sk_buff *skb)
void llc_conn_rtn_pdu(struct sock *sk, struct sk_buff *skb)
void llc_conn_resend_i_pdu_as_cmd(struct sock *sk, u8 nr, u8 first_p_bit)
void llc_conn_resend_i_pdu_as_rsp(struct sock *sk, u8 nr, u8 first_f_bit)
int llc_conn_remove_acked_pdus(struct sock *sk, u8 nr, u16 *how_many_unacked)
struct sock *llc_lookup_established(struct llc_sap *sap, struct llc_addr *daddr, struct llc_addr *laddr)
u8 llc_data_accept_state(u8 state)
void __init llc_build_offset_table(void)
void llc_sap_add_socket(struct llc_sap *sap, struct sock *sk)
void llc_sap_remove_socket(struct llc_sap *sap, struct sock *sk)
void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb)
static int llc_backlog_rcv(struct sock *sk, struct sk_buff *skb)
static void llc_sk_init(struct sock *sk)
{
sk->sk_backlog_rcv = llc_backlog_rcv;
}
struct sock *llc_sk_alloc(struct net *net, int family, gfp_t priority, struct proto *prot, int kern)
void llc_sk_stop_all_timers(struct sock *sk, bool sync)
void llc_sk_free(struct sock *sk)
void llc_sk_reset(struct sock *sk)
С входящим трафиком работают функции llc_conn_rtn_pdu, llc_conn_handler, llc_backlog_rcv.
С иcходящим трафиком работают функции llc_conn_send_pdu, llc_conn_resend_i_pdu_as_cmd, llc_conn_resend_i_pdu_as_rsp.
Функция llc_conn_state_process используется в обоих направлениях, она используется для отправки события (event) в компонент, отвечающий за соединения (connection state machine).
Также устанавливаются обработчики по таймеру: llc_conn_ack_tmr_cb, llc_conn_pf_cycle_tmr_cb, llc_conn_rej_tmr_cb, llc_conn_busy_tmr_cb (из файла llc_c_ac.c), которые влияют на состояние автомата соединений (connection state machine).
static void llc_sk_init(struct sock *sk)
{
…
timer_setup(&llc->ack_timer.timer, llc_conn_ack_tmr_cb, 0);
llc->ack_timer.expire = sysctl_llc2_ack_timeout;
timer_setup(&llc->pf_cycle_timer.timer, llc_conn_pf_cycle_tmr_cb, 0);
llc->pf_cycle_timer.expire = sysctl_llc2_p_timeout;
timer_setup(&llc->rej_sent_timer.timer, llc_conn_rej_tmr_cb, 0);
llc->rej_sent_timer.expire = sysctl_llc2_rej_timeout;
timer_setup(&llc->busy_state_timer.timer, llc_conn_busy_tmr_cb, 0);
llc->busy_state_timer.expire = sysctl_llc2_busy_timeout;
…
}
llc_sap.c
Интерфейс драйвера для компонента SAP.
struct sk_buff *llc_alloc_frame(struct sock *sk, struct net_device *dev, u8 type, u32 data_size)
void llc_save_primitive(struct sock *sk, struct sk_buff *skb, u8 prim)
void llc_sap_rtn_pdu(struct llc_sap *sap, struct sk_buff *skb)
void llc_build_and_send_test_pkt(struct llc_sap *sap, struct sk_buff *skb, u8 *dmac, u8 dsap)
void llc_build_and_send_xid_pkt(struct llc_sap *sap, struct sk_buff *skb, u8 *dmac, u8 dsap)
void llc_sap_handler(struct llc_sap *sap, struct sk_buff *skb)
llc_sap_handler – обработчик входящих данных на уровне компонента SAP, вызывается через llc_rcv (llc_input.c).
С входящим трафиком работают функции llc_save_primitive, llc_sap_rtn_pdu, llc_sap_handler.
С иcходящим трафиком работают функции llc_build_and_send_test_pkt, llc_build_and_send_xid_pkt.
llc_station.c
Компонент LLC station.
static void llc_station_rcv(struct sk_buff *skb)
void __init llc_station_init(void)
{
llc_set_station_handler(llc_station_rcv);
}
С входящим трафиком работает функция llc_station_rcv, которая передает полученный кадр PDU для обработки в конечный автомат станции (station state machine).
llc_proc.c
Реализует интерфейс специальной файловой системы proc.
С входящим трафиком не работает, является поверхностью атаки при вызовах из пользовательского пространства.
sysctl_net_llc.c
Реализует интерфейс sysctl для сетевой подсистемы LLC. С входящим трафиком не работает, является поверхностью атаки при вызовах из пользовательского пространства.
Ниже представлены подмодули, описывающие конечные автоматы (state machine) для компонента соединений и компонента SAP. Данные подмодули рассмотрены очень поверхностно. Для анализа возможной поверхности атаки требуется детальное изучение спецификации протокола.
llc_pdu.c
Модуль управления значениями полей кадра PDU.
void llc_pdu_set_cmd_rsp(struct sk_buff *skb, u8 pdu_type)
void llc_pdu_set_pf_bit(struct sk_buff *skb, u8 bit_value)
void llc_pdu_decode_pf_bit(struct sk_buff *skb, u8 *pf_bit)
void llc_pdu_init_as_disc_cmd(struct sk_buff *skb, u8 p_bit)
void llc_pdu_init_as_i_cmd(struct sk_buff *skb, u8 p_bit, u8 ns, u8 nr)
void llc_pdu_init_as_rej_cmd(struct sk_buff *skb, u8 p_bit, u8 nr)
void llc_pdu_init_as_rnr_cmd(struct sk_buff *skb, u8 p_bit, u8 nr)
void llc_pdu_init_as_rr_cmd(struct sk_buff *skb, u8 p_bit, u8 nr)
void llc_pdu_init_as_sabme_cmd(struct sk_buff *skb, u8 p_bit)
void llc_pdu_init_as_dm_rsp(struct sk_buff *skb, u8 f_bit)
void llc_pdu_init_as_frmr_rsp(struct sk_buff *skb, struct llc_pdu_sn *prev_pdu,
u8 f_bit, u8 vs, u8 vr, u8 vzyxw)
void llc_pdu_init_as_rr_rsp(struct sk_buff *skb, u8 f_bit, u8 nr)
void llc_pdu_init_as_rej_rsp(struct sk_buff *skb, u8 f_bit, u8 nr)
void llc_pdu_init_as_rnr_rsp(struct sk_buff *skb, u8 f_bit, u8 nr)
void llc_pdu_init_as_ua_rsp(struct sk_buff *skb, u8 f_bit)
Все функции работают с кадрами протокола, устанавливая для разных типов сообщений соответствующие биты управляющего поля.
Описание конечного автомата (state machine) SAP
llc_s_ac.c
Модуль действий (actions) при переходах между состояниями.
int llc_sap_action_unitdata_ind(struct llc_sap *sap, struct sk_buff *skb)
int llc_sap_action_send_ui(struct llc_sap *sap, struct sk_buff *skb)
int llc_sap_action_send_xid_c(struct llc_sap *sap, struct sk_buff *skb)
int llc_sap_action_send_xid_r(struct llc_sap *sap, struct sk_buff *skb)
int llc_sap_action_send_test_c(struct llc_sap *sap, struct sk_buff *skb)
int llc_sap_action_send_test_r(struct llc_sap *sap, struct sk_buff *skb)
int llc_sap_action_report_status(struct llc_sap *sap, struct sk_buff *skb)
int llc_sap_action_xid_ind(struct llc_sap *sap, struct sk_buff *skb)
int llc_sap_action_test_ind(struct llc_sap *sap, struct sk_buff *skb)
Все функции работают с сетевыми данными (напомним, что под сетевыми данными понимаются не только данные верхнего протокола, но и управляющие команды протокола LLC).
llc_s_ev.c
Модуль событий (events).
int llc_sap_ev_activation_req(struct llc_sap *sap, struct sk_buff *skb)
int llc_sap_ev_rx_ui(struct llc_sap *sap, struct sk_buff *skb)
int llc_sap_ev_unitdata_req(struct llc_sap *sap, struct sk_buff *skb)
int llc_sap_ev_xid_req(struct llc_sap *sap, struct sk_buff *skb)
int llc_sap_ev_rx_xid_c(struct llc_sap *sap, struct sk_buff *skb)
int llc_sap_ev_rx_xid_r(struct llc_sap *sap, struct sk_buff *skb)
int llc_sap_ev_test_req(struct llc_sap *sap, struct sk_buff *skb)
int llc_sap_ev_rx_test_c(struct llc_sap *sap, struct sk_buff *skb)
int llc_sap_ev_rx_test_r(struct llc_sap *sap, struct sk_buff *skb)
int llc_sap_ev_deactivation_req(struct llc_sap *sap, struct sk_buff *skb)
Все функции работают с сетевыми данными.
llc_s_st.c
Модуль переходов конечного автомата (state machine transitions). Обработка данных отсутствует, только устанавливается соответствие между событиями и необходимыми действиями.
Описание конечного автомата (state machine) для соединений
llc_c_ac.c– действия (actions) при переходах между состояниями. Все функции работают с сетевыми данными.llc_c_ev.c– события (events). Все функции работают с сетевыми данными.llc_c_st.c– переходы конечного автомата (state machine transitions). Обработка данных отсутствует, только устанавливается соответствие между событиями и необходимыми действиями.
Заключение
Проведенный анализ модуля LLC (net/LLC) показал, что 8 функций этого модуля представляют поверхность атаки для входящего сетевого трафика, 11 – используются для исходящего трафика, 2 – могут использоваться в обоих направлениях. Кроме этого, три подмодуля af_llc.c (11 функций), llc_proc.c, sysctl_net_llc являются поверхностью атаки при использовании из пользовательского пространства (данные функции оперируют не сетевыми данными, а настройками сетевых соединений). Также 5 подмодулей (llc_pdu.c, llc_c_ac.c, llc_c_ev.c, llc_s_ac.c, llc_s_ev.c), отвечающих за работу конечных автоматов протокола, требуют детального изучения спецификации протокола и дополнительного анализа.