pdcp: drop PDCP control PDUs

this patch adds a check to drop all PDCP control PDUs
in order to prevent handling them as data PDUs.

This could happen when the size exceeded the arbitrary length check.

This should fix #1787
This commit is contained in:
Andre Puschmann 2020-09-28 21:57:43 +02:00
parent b3eb9651d6
commit 795db30338
4 changed files with 24 additions and 7 deletions

View File

@ -43,6 +43,13 @@ const uint8_t PDCP_SN_LEN_18 = 18;
typedef enum { PDCP_RB_IS_SRB, PDCP_RB_IS_DRB } pdcp_rb_type_t;
enum pdcp_dc_field_t {
PDCP_DC_FIELD_CONTROL_PDU = 0,
PDCP_DC_FIELD_DATA_PDU,
PDCP_DC_FIELD_N_ITEMS,
};
static const char* pdcp_dc_field_text[PDCP_DC_FIELD_N_ITEMS] = {"Control PDU", "Data PDU"};
// Taken from PDCP-Config (TS 38.331 version 15.2.1)
enum class pdcp_t_reordering_t {
ms0 = 0,

View File

@ -158,6 +158,7 @@ protected:
void cipher_decrypt(uint8_t* ct, uint32_t ct_len, uint32_t count, uint8_t* msg);
// Common packing functions
bool is_control_pdu(const unique_byte_buffer_t& pdu);
uint32_t read_data_header(const unique_byte_buffer_t& pdu);
void discard_data_header(const unique_byte_buffer_t& pdu);
void write_data_header(const srslte::unique_byte_buffer_t& sdu, uint32_t count);

View File

@ -27,8 +27,7 @@
namespace srslte {
pdcp_entity_base::pdcp_entity_base(task_sched_handle task_sched_, srslte::log_ref log_) :
log(log_),
task_sched(task_sched_)
log(log_), task_sched(task_sched_)
{}
pdcp_entity_base::~pdcp_entity_base() {}
@ -218,6 +217,13 @@ void pdcp_entity_base::cipher_decrypt(uint8_t* ct, uint32_t ct_len, uint32_t cou
/****************************************************************************
* Common pack functions
***************************************************************************/
bool pdcp_entity_base::is_control_pdu(const unique_byte_buffer_t& pdu)
{
const uint8_t* payload = pdu->msg;
return ((*(payload) >> 7) & 0x01) == PDCP_DC_FIELD_CONTROL_PDU;
}
uint32_t pdcp_entity_base::read_data_header(const unique_byte_buffer_t& pdu)
{
// Check PDU is long enough to extract header
@ -273,7 +279,7 @@ void pdcp_entity_base::write_data_header(const srslte::unique_byte_buffer_t& sdu
sdu->msg[0] = SN(count); // Data PDU and SN LEN 5 implies SRB, D flag must not be present
break;
case PDCP_SN_LEN_7:
sdu->msg[0] = SN(count);
sdu->msg[0] = SN(count);
if (is_drb()) {
sdu->msg[0] |= 0x80; // On Data PDUs for DRBs we must set the D flag.
}

View File

@ -31,10 +31,7 @@ pdcp_entity_lte::pdcp_entity_lte(srsue::rlc_interface_pdcp* rlc_,
srslte::log_ref log_,
uint32_t lcid_,
pdcp_config_t cfg_) :
pdcp_entity_base(task_sched_, log_),
rlc(rlc_),
rrc(rrc_),
gw(gw_)
pdcp_entity_base(task_sched_, log_), rlc(rlc_), rrc(rrc_), gw(gw_)
{
lcid = lcid_;
cfg = cfg_;
@ -161,6 +158,12 @@ void pdcp_entity_lte::write_sdu(unique_byte_buffer_t sdu)
// RLC interface
void pdcp_entity_lte::write_pdu(unique_byte_buffer_t pdu)
{
// drop control PDUs
if (is_drb() && is_control_pdu(pdu)) {
log->info("Dropping PDCP control PDU\n");
return;
}
// Sanity check
if (pdu->N_bytes <= cfg.hdr_len_bytes) {
log->error("PDCP PDU smaller than required header size.\n");