3333#include "lib/eq.h"
3434#include "fw_tracer.h"
3535#include "fw_tracer_tracepoint.h"
36+ #include <linux/ctype.h>
3637
3738static int mlx5_query_mtrc_caps (struct mlx5_fw_tracer * tracer )
3839{
@@ -358,6 +359,47 @@ static const char *VAL_PARM = "%llx";
358359static const char * REPLACE_64_VAL_PARM = "%x%x" ;
359360static const char * PARAM_CHAR = "%" ;
360361
362+ static bool mlx5_is_valid_spec (const char * str )
363+ {
364+ /* Parse format specifiers to find the actual type.
365+ * Structure: %[flags][width][.precision][length]type
366+ * Skip flags, width, precision & length.
367+ */
368+ while (isdigit (* str ) || * str == '#' || * str == '.' || * str == 'l' )
369+ str ++ ;
370+
371+ /* Check if it's a valid integer/hex specifier or %%:
372+ * Valid formats: %x, %d, %i, %u, etc.
373+ */
374+ if (* str != 'x' && * str != 'X' && * str != 'd' && * str != 'i' &&
375+ * str != 'u' && * str != 'c' && * str != '%' )
376+ return false;
377+
378+ return true;
379+ }
380+
381+ static bool mlx5_tracer_validate_params (const char * str )
382+ {
383+ const char * substr = str ;
384+
385+ if (!str )
386+ return false;
387+
388+ substr = strstr (substr , PARAM_CHAR );
389+ while (substr ) {
390+ if (!mlx5_is_valid_spec (substr + 1 ))
391+ return false;
392+
393+ if (* (substr + 1 ) == '%' )
394+ substr = strstr (substr + 2 , PARAM_CHAR );
395+ else
396+ substr = strstr (substr + 1 , PARAM_CHAR );
397+
398+ }
399+
400+ return true;
401+ }
402+
361403static int mlx5_tracer_message_hash (u32 message_id )
362404{
363405 return jhash_1word (message_id , 0 ) & (MESSAGE_HASH_SIZE - 1 );
@@ -419,6 +461,10 @@ static int mlx5_tracer_get_num_of_params(char *str)
419461 char * substr , * pstr = str ;
420462 int num_of_params = 0 ;
421463
464+ /* Validate that all parameters are valid before processing */
465+ if (!mlx5_tracer_validate_params (str ))
466+ return - EINVAL ;
467+
422468 /* replace %llx with %x%x */
423469 substr = strstr (pstr , VAL_PARM );
424470 while (substr ) {
@@ -427,11 +473,15 @@ static int mlx5_tracer_get_num_of_params(char *str)
427473 substr = strstr (pstr , VAL_PARM );
428474 }
429475
430- /* count all the % characters */
476+ /* count all the % characters, but skip %% (escaped percent) */
431477 substr = strstr (str , PARAM_CHAR );
432478 while (substr ) {
433- num_of_params += 1 ;
434- str = substr + 1 ;
479+ if (* (substr + 1 ) != '%' ) {
480+ num_of_params += 1 ;
481+ str = substr + 1 ;
482+ } else {
483+ str = substr + 2 ;
484+ }
435485 substr = strstr (str , PARAM_CHAR );
436486 }
437487
@@ -570,14 +620,17 @@ void mlx5_tracer_print_trace(struct tracer_string_format *str_frmt,
570620{
571621 char tmp [512 ];
572622
573- snprintf (tmp , sizeof (tmp ), str_frmt -> string ,
574- str_frmt -> params [0 ],
575- str_frmt -> params [1 ],
576- str_frmt -> params [2 ],
577- str_frmt -> params [3 ],
578- str_frmt -> params [4 ],
579- str_frmt -> params [5 ],
580- str_frmt -> params [6 ]);
623+ if (str_frmt -> invalid_string )
624+ snprintf (tmp , sizeof (tmp ), "BAD_FORMAT: %s" , str_frmt -> string );
625+ else
626+ snprintf (tmp , sizeof (tmp ), str_frmt -> string ,
627+ str_frmt -> params [0 ],
628+ str_frmt -> params [1 ],
629+ str_frmt -> params [2 ],
630+ str_frmt -> params [3 ],
631+ str_frmt -> params [4 ],
632+ str_frmt -> params [5 ],
633+ str_frmt -> params [6 ]);
581634
582635 trace_mlx5_fw (dev -> tracer , trace_timestamp , str_frmt -> lost ,
583636 str_frmt -> event_id , tmp );
@@ -609,6 +662,13 @@ static int mlx5_tracer_handle_raw_string(struct mlx5_fw_tracer *tracer,
609662 return 0 ;
610663}
611664
665+ static void mlx5_tracer_handle_bad_format_string (struct mlx5_fw_tracer * tracer ,
666+ struct tracer_string_format * cur_string )
667+ {
668+ cur_string -> invalid_string = true;
669+ list_add_tail (& cur_string -> list , & tracer -> ready_strings_list );
670+ }
671+
612672static int mlx5_tracer_handle_string_trace (struct mlx5_fw_tracer * tracer ,
613673 struct tracer_event * tracer_event )
614674{
@@ -619,12 +679,18 @@ static int mlx5_tracer_handle_string_trace(struct mlx5_fw_tracer *tracer,
619679 if (!cur_string )
620680 return mlx5_tracer_handle_raw_string (tracer , tracer_event );
621681
622- cur_string -> num_of_params = mlx5_tracer_get_num_of_params (cur_string -> string );
623- cur_string -> last_param_num = 0 ;
624682 cur_string -> event_id = tracer_event -> event_id ;
625683 cur_string -> tmsn = tracer_event -> string_event .tmsn ;
626684 cur_string -> timestamp = tracer_event -> string_event .timestamp ;
627685 cur_string -> lost = tracer_event -> lost_event ;
686+ cur_string -> last_param_num = 0 ;
687+ cur_string -> num_of_params = mlx5_tracer_get_num_of_params (cur_string -> string );
688+ if (cur_string -> num_of_params < 0 ) {
689+ pr_debug ("%s Invalid format string parameters\n" ,
690+ __func__ );
691+ mlx5_tracer_handle_bad_format_string (tracer , cur_string );
692+ return 0 ;
693+ }
628694 if (cur_string -> num_of_params == 0 ) /* trace with no params */
629695 list_add_tail (& cur_string -> list , & tracer -> ready_strings_list );
630696 } else {
@@ -634,6 +700,11 @@ static int mlx5_tracer_handle_string_trace(struct mlx5_fw_tracer *tracer,
634700 __func__ , tracer_event -> string_event .tmsn );
635701 return mlx5_tracer_handle_raw_string (tracer , tracer_event );
636702 }
703+ if (cur_string -> num_of_params < 0 ) {
704+ pr_debug ("%s string parameter of invalid string, dumping\n" ,
705+ __func__ );
706+ return 0 ;
707+ }
637708 cur_string -> last_param_num += 1 ;
638709 if (cur_string -> last_param_num > TRACER_MAX_PARAMS ) {
639710 pr_debug ("%s Number of params exceeds the max (%d)\n" ,
0 commit comments