@@ -4027,84 +4027,128 @@ void dlt_daemon_control_set_trace_status_v2(int sock,
40274027
40284028 char * apid = NULL ;
40294029 char * ctid = NULL ;
4030- DltServiceSetLogLevelV2 * req = NULL ;
4030+ char apid_buf [DLT_V2_ID_SIZE ] = {0 };
4031+ char ctid_buf [DLT_V2_ID_SIZE ] = {0 };
40314032 DltDaemonContext * context = NULL ;
4032- int8_t apid_length = 0 ;
4033- int8_t ctid_length = 0 ;
4033+ uint32_t service_id = 0 ;
4034+ uint8_t apidlen = 0 ;
4035+ uint8_t ctidlen = 0 ;
4036+ uint8_t log_level = 0 ;
4037+ int offset = 0 ;
40344038
40354039 if ((daemon == NULL ) || (msg == NULL ) || (msg -> databuffer == NULL ))
40364040 return ;
40374041
4038- //TBD: Review sizeof(DltServiceSetLogLevelV2)) or fixed size
4039- if (dlt_check_rcv_data_size (msg -> datasize , sizeof (DltServiceSetLogLevelV2 )) < 0 )
4042+ if (dlt_check_rcv_data_size (msg -> datasize , DLT_SERVICE_SET_LOG_LEVEL_FIXED_SIZE_V2 ) < 0 )
40404043 return ;
40414044
4042- req = (DltServiceSetLogLevelV2 * )(msg -> databuffer );
4045+ /* Parse wire bytes incrementally instead of casting msg->databuffer to
4046+ * DltServiceSetLogLevelV2 *. The struct contains char *apid / char *ctid
4047+ * pointer fields. Under a direct cast those fields would have been
4048+ * filled with attacker-controlled pointer values from network input,
4049+ * then dereferenced by dlt_set_id_v2 — an arbitrary memory read. The
4050+ * previous code also fell into the same NULL-deref pattern as #863
4051+ * (apid / ctid NULL when used at apid[apid_length - 1] etc.).
4052+ * See #866 for the broader pattern. */
4053+ memcpy (& service_id , msg -> databuffer + offset , sizeof (uint32_t ));
4054+ offset = offset + (int )sizeof (uint32_t );
4055+ memcpy (& apidlen , msg -> databuffer + offset , sizeof (uint8_t ));
4056+ offset = offset + (int )sizeof (uint8_t );
40434057
4044- if (daemon_local -> flags .enforceContextLLAndTS )
4045- req -> log_level = (uint8_t ) getStatus (req -> log_level , daemon_local -> flags .contextTraceStatus );
4058+ /* Bounds check for apid (apidlen bytes) + the upcoming ctidlen byte.
4059+ * The fixed-size precheck at the top only validates the empty case. */
4060+ if ((offset + (int )apidlen + (int )sizeof (uint8_t )) > msg -> datasize )
4061+ return ;
40464062
4047- apid_length = (int8_t ) req -> apidlen ;
4048- dlt_set_id_v2 (apid , req -> apid , req -> apidlen );
4049- ctid_length = (int8_t ) req -> ctidlen ;
4050- dlt_set_id_v2 (ctid , req -> ctid , req -> ctidlen );
4063+ /* Copy the variable-length apid into a local fixed-size buffer through the
4064+ * dlt_set_id_v2() helper rather than aliasing the receive buffer, keeping
4065+ * id initialisation inside the shared API. */
4066+ if (apidlen > 0 ) {
4067+ dlt_set_id_v2 (apid_buf , (const char * )(msg -> databuffer + offset ), apidlen );
4068+ apid = apid_buf ;
4069+ offset = offset + (int )apidlen ;
4070+ }
4071+ memcpy (& ctidlen , msg -> databuffer + offset , sizeof (uint8_t ));
4072+ offset = offset + (int )sizeof (uint8_t );
40514073
4052- //TBD: Review apid[apid_length - 1] == '*'
4053- if ((apid_length != 0 ) && (apid [apid_length - 1 ] == '*' ) && (ctid == NULL )) { /*apid provided having '*' in it and ctid is null*/
4074+ /* Bounds check for ctid (ctidlen bytes) + log_level (1 byte) +
4075+ * the trailing com field (DLT_ID_SIZE bytes). */
4076+ if ((offset + (int )ctidlen + (int )sizeof (uint8_t ) + DLT_ID_SIZE ) > msg -> datasize )
4077+ return ;
4078+
4079+ if (ctidlen > 0 ) {
4080+ dlt_set_id_v2 (ctid_buf , (const char * )(msg -> databuffer + offset ), ctidlen );
4081+ ctid = ctid_buf ;
4082+ offset = offset + (int )ctidlen ;
4083+ }
4084+ memcpy (& log_level , msg -> databuffer + offset , sizeof (uint8_t ));
4085+
4086+ if (daemon_local -> flags .enforceContextLLAndTS )
4087+ log_level = (uint8_t ) getStatus (log_level , daemon_local -> flags .contextTraceStatus );
4088+
4089+ /* Use unsigned widths throughout. Casting uint8_t apidlen / ctidlen
4090+ * to int8_t (as the previous code did) would produce a negative value
4091+ * when the length exceeds 127, underflowing apid[apid_length - 1] etc.
4092+ * Note: downstream helpers below still take int8_t lengths; that
4093+ * narrowing remains a separate latent issue, out of scope here. */
4094+ if ((apidlen != 0 ) && (apid != NULL ) && (apid [apidlen - 1 ] == '*' ) && (ctid == NULL )) {
4095+ /* apid provided having '*' in it and ctid is null */
40544096 dlt_daemon_find_multiple_context_and_send_trace_status_v2 (sock ,
40554097 daemon ,
40564098 daemon_local ,
40574099 1 ,
40584100 apid ,
4059- (int8_t ) (apid_length - 1 ),
4060- (int8_t ) req -> log_level ,
4101+ (int8_t ) (apidlen - 1 ),
4102+ (int8_t ) log_level ,
40614103 verbose );
40624104 }
4063- else if ((ctid_length != 0 ) && (ctid [ctid_length - 1 ] == '*' ) && (apid == NULL )) /*ctid provided is having '*' in it and apid is null*/
4064-
4105+ else if ((ctidlen != 0 ) && (ctid != NULL ) && (ctid [ctidlen - 1 ] == '*' ) && (apid == NULL ))
40654106 {
4107+ /* ctid provided is having '*' in it and apid is null */
40664108 dlt_daemon_find_multiple_context_and_send_trace_status_v2 (sock ,
40674109 daemon ,
40684110 daemon_local ,
40694111 0 ,
40704112 ctid ,
4071- (int8_t ) (ctid_length - 1 ),
4072- (int8_t ) req -> log_level ,
4113+ (int8_t ) (ctidlen - 1 ),
4114+ (int8_t ) log_level ,
40734115 verbose );
40744116 }
4075- else if ((apid_length != 0 ) && (apid [ apid_length - 1 ] != '*' ) && (ctid == NULL )) /*only app id case*/
4117+ else if ((apidlen != 0 ) && (apid != NULL ) && ( apid [ apidlen - 1 ] != '*' ) && (ctid == NULL ))
40764118 {
4119+ /* only app id case */
40774120 dlt_daemon_find_multiple_context_and_send_trace_status_v2 (sock ,
40784121 daemon ,
40794122 daemon_local ,
40804123 1 ,
40814124 apid ,
4082- apid_length ,
4083- (int8_t ) req -> log_level ,
4125+ ( int8_t ) apidlen ,
4126+ (int8_t ) log_level ,
40844127 verbose );
40854128 }
4086- else if ((ctid_length != 0 ) && (ctid [ ctid_length - 1 ] != '*' ) && (apid == NULL )) /*only context id case*/
4129+ else if ((ctidlen != 0 ) && (ctid != NULL ) && ( ctid [ ctidlen - 1 ] != '*' ) && (apid == NULL ))
40874130 {
4131+ /* only context id case */
40884132 dlt_daemon_find_multiple_context_and_send_trace_status_v2 (sock ,
40894133 daemon ,
40904134 daemon_local ,
40914135 0 ,
40924136 ctid ,
4093- ctid_length ,
4094- (int8_t ) req -> log_level ,
4137+ ( int8_t ) ctidlen ,
4138+ (int8_t ) log_level ,
40954139 verbose );
40964140 }
40974141 else {
4098- context = dlt_daemon_context_find_v2 (daemon , ( uint8_t ) apid_length , apid , ( uint8_t ) ctid_length , ctid , daemon -> ecuid2len , daemon -> ecuid2 , verbose );
4142+ context = dlt_daemon_context_find_v2 (daemon , apidlen , apid , ctidlen , ctid , daemon -> ecuid2len , daemon -> ecuid2 , verbose );
40994143
41004144 /* Set trace status */
41014145 if (context != 0 ) {
4102- dlt_daemon_send_trace_status_v2 (sock , daemon , daemon_local , context , (int8_t ) req -> log_level , verbose );
4146+ dlt_daemon_send_trace_status_v2 (sock , daemon , daemon_local , context , (int8_t ) log_level , verbose );
41034147 }
41044148 else {
41054149 dlt_vlog (LOG_ERR ,
41064150 "Could not set trace status: %d. Context [%.4s:%.4s] not found:" ,
4107- req -> log_level ,
4151+ log_level ,
41084152 apid ? apid : "<NULL>" ,
41094153 ctid ? ctid : "<NULL>" );
41104154 dlt_daemon_control_service_response_v2 (sock ,
0 commit comments