@@ -1090,67 +1090,45 @@ static int __parse_bitfield_probe_arg(const char *bf,
10901090 return (BYTES_TO_BITS (t -> size ) < (bw + bo )) ? - EINVAL : 0 ;
10911091}
10921092
1093- /* String length checking wrapper */
1094- static int traceprobe_parse_probe_arg_body (const char * argv , ssize_t * size ,
1095- struct probe_arg * parg ,
1096- struct traceprobe_parse_context * ctx )
1093+ /* Split type part from @arg and return it. */
1094+ static char * parse_probe_arg_type (char * arg , struct probe_arg * parg ,
1095+ struct traceprobe_parse_context * ctx )
10971096{
1098- struct fetch_insn * code , * scode , * tmp = NULL ;
1099- char * t , * t2 , * t3 ;
1100- int ret , len ;
1101- char * arg ;
1097+ char * t = NULL , * t2 , * t3 ;
1098+ int offs ;
11021099
1103- arg = kstrdup (argv , GFP_KERNEL );
1104- if (!arg )
1105- return - ENOMEM ;
1106-
1107- ret = - EINVAL ;
1108- len = strlen (arg );
1109- if (len > MAX_ARGSTR_LEN ) {
1110- trace_probe_log_err (ctx -> offset , ARG_TOO_LONG );
1111- goto out ;
1112- } else if (len == 0 ) {
1113- trace_probe_log_err (ctx -> offset , NO_ARG_BODY );
1114- goto out ;
1115- }
1116-
1117- ret = - ENOMEM ;
1118- parg -> comm = kstrdup (arg , GFP_KERNEL );
1119- if (!parg -> comm )
1120- goto out ;
1121-
1122- ret = - EINVAL ;
11231100 t = strchr (arg , ':' );
11241101 if (t ) {
1125- * t = '\0' ;
1126- t2 = strchr (++ t , '[' );
1102+ * t ++ = '\0' ;
1103+ t2 = strchr (t , '[' );
11271104 if (t2 ) {
11281105 * t2 ++ = '\0' ;
11291106 t3 = strchr (t2 , ']' );
11301107 if (!t3 ) {
1131- int offs = t2 + strlen (t2 ) - arg ;
1108+ offs = t2 + strlen (t2 ) - arg ;
11321109
11331110 trace_probe_log_err (ctx -> offset + offs ,
11341111 ARRAY_NO_CLOSE );
1135- goto out ;
1112+ return ERR_PTR ( - EINVAL ) ;
11361113 } else if (t3 [1 ] != '\0' ) {
11371114 trace_probe_log_err (ctx -> offset + t3 + 1 - arg ,
11381115 BAD_ARRAY_SUFFIX );
1139- goto out ;
1116+ return ERR_PTR ( - EINVAL ) ;
11401117 }
11411118 * t3 = '\0' ;
11421119 if (kstrtouint (t2 , 0 , & parg -> count ) || !parg -> count ) {
11431120 trace_probe_log_err (ctx -> offset + t2 - arg ,
11441121 BAD_ARRAY_NUM );
1145- goto out ;
1122+ return ERR_PTR ( - EINVAL ) ;
11461123 }
11471124 if (parg -> count > MAX_ARRAY_LEN ) {
11481125 trace_probe_log_err (ctx -> offset + t2 - arg ,
11491126 ARRAY_TOO_BIG );
1150- goto out ;
1127+ return ERR_PTR ( - EINVAL ) ;
11511128 }
11521129 }
11531130 }
1131+ offs = t ? t - arg : 0 ;
11541132
11551133 /*
11561134 * Since $comm and immediate string can not be dereferenced,
@@ -1161,74 +1139,52 @@ static int traceprobe_parse_probe_arg_body(const char *argv, ssize_t *size,
11611139 strncmp (arg , "\\\"" , 2 ) == 0 )) {
11621140 /* The type of $comm must be "string", and not an array type. */
11631141 if (parg -> count || (t && strcmp (t , "string" ))) {
1164- trace_probe_log_err (ctx -> offset + (t ? (t - arg ) : 0 ),
1165- NEED_STRING_TYPE );
1166- goto out ;
1142+ trace_probe_log_err (ctx -> offset + offs , NEED_STRING_TYPE );
1143+ return ERR_PTR (- EINVAL );
11671144 }
11681145 parg -> type = find_fetch_type ("string" , ctx -> flags );
11691146 } else
11701147 parg -> type = find_fetch_type (t , ctx -> flags );
1148+
11711149 if (!parg -> type ) {
1172- trace_probe_log_err (ctx -> offset + ( t ? ( t - arg ) : 0 ) , BAD_TYPE );
1173- goto out ;
1150+ trace_probe_log_err (ctx -> offset + offs , BAD_TYPE );
1151+ return ERR_PTR ( - EINVAL ) ;
11741152 }
11751153
1176- code = tmp = kcalloc (FETCH_INSN_MAX , sizeof (* code ), GFP_KERNEL );
1177- if (!code )
1178- goto out ;
1179- code [FETCH_INSN_MAX - 1 ].op = FETCH_OP_END ;
1180-
1181- ctx -> last_type = NULL ;
1182- ret = parse_probe_arg (arg , parg -> type , & code , & code [FETCH_INSN_MAX - 1 ],
1183- ctx );
1184- if (ret )
1185- goto fail ;
1186-
1187- /* Update storing type if BTF is available */
1188- if (IS_ENABLED (CONFIG_PROBE_EVENTS_BTF_ARGS ) &&
1189- ctx -> last_type ) {
1190- if (!t ) {
1191- parg -> type = find_fetch_type_from_btf_type (ctx );
1192- } else if (strstr (t , "string" )) {
1193- ret = check_prepare_btf_string_fetch (t , & code , ctx );
1194- if (ret )
1195- goto fail ;
1196- }
1197- }
1198- parg -> offset = * size ;
1199- * size += parg -> type -> size * (parg -> count ?: 1 );
1154+ return t ;
1155+ }
12001156
1201- if (parg -> count ) {
1202- len = strlen (parg -> type -> fmttype ) + 6 ;
1203- parg -> fmt = kmalloc (len , GFP_KERNEL );
1204- if (!parg -> fmt ) {
1205- ret = - ENOMEM ;
1206- goto out ;
1207- }
1208- snprintf (parg -> fmt , len , "%s[%d]" , parg -> type -> fmttype ,
1209- parg -> count );
1210- }
1157+ /* After parsing, adjust the fetch_insn according to the probe_arg */
1158+ static int finalize_fetch_insn (struct fetch_insn * code ,
1159+ struct probe_arg * parg ,
1160+ char * type ,
1161+ int type_offset ,
1162+ struct traceprobe_parse_context * ctx )
1163+ {
1164+ struct fetch_insn * scode ;
1165+ int ret ;
12111166
1212- ret = - EINVAL ;
12131167 /* Store operation */
12141168 if (parg -> type -> is_string ) {
1169+ /* Check bad combination of the type and the last fetch_insn. */
12151170 if (!strcmp (parg -> type -> name , "symstr" )) {
12161171 if (code -> op != FETCH_OP_REG && code -> op != FETCH_OP_STACK &&
12171172 code -> op != FETCH_OP_RETVAL && code -> op != FETCH_OP_ARG &&
12181173 code -> op != FETCH_OP_DEREF && code -> op != FETCH_OP_TP_ARG ) {
1219- trace_probe_log_err (ctx -> offset + ( t ? ( t - arg ) : 0 ) ,
1174+ trace_probe_log_err (ctx -> offset + type_offset ,
12201175 BAD_SYMSTRING );
1221- goto fail ;
1176+ return - EINVAL ;
12221177 }
12231178 } else {
12241179 if (code -> op != FETCH_OP_DEREF && code -> op != FETCH_OP_UDEREF &&
12251180 code -> op != FETCH_OP_IMM && code -> op != FETCH_OP_COMM &&
12261181 code -> op != FETCH_OP_DATA && code -> op != FETCH_OP_TP_ARG ) {
1227- trace_probe_log_err (ctx -> offset + ( t ? ( t - arg ) : 0 ) ,
1182+ trace_probe_log_err (ctx -> offset + type_offset ,
12281183 BAD_STRING );
1229- goto fail ;
1184+ return - EINVAL ;
12301185 }
12311186 }
1187+
12321188 if (!strcmp (parg -> type -> name , "symstr" ) ||
12331189 (code -> op == FETCH_OP_IMM || code -> op == FETCH_OP_COMM ||
12341190 code -> op == FETCH_OP_DATA ) || code -> op == FETCH_OP_TP_ARG ||
@@ -1244,9 +1200,10 @@ static int traceprobe_parse_probe_arg_body(const char *argv, ssize_t *size,
12441200 code ++ ;
12451201 if (code -> op != FETCH_OP_NOP ) {
12461202 trace_probe_log_err (ctx -> offset , TOO_MANY_OPS );
1247- goto fail ;
1203+ return - EINVAL ;
12481204 }
12491205 }
1206+
12501207 /* If op == DEREF, replace it with STRING */
12511208 if (!strcmp (parg -> type -> name , "ustring" ) ||
12521209 code -> op == FETCH_OP_UDEREF )
@@ -1267,47 +1224,134 @@ static int traceprobe_parse_probe_arg_body(const char *argv, ssize_t *size,
12671224 code ++ ;
12681225 if (code -> op != FETCH_OP_NOP ) {
12691226 trace_probe_log_err (ctx -> offset , TOO_MANY_OPS );
1270- goto fail ;
1227+ return - E2BIG ;
12711228 }
12721229 code -> op = FETCH_OP_ST_RAW ;
12731230 code -> size = parg -> type -> size ;
12741231 }
1232+
1233+ /* Save storing fetch_insn. */
12751234 scode = code ;
1235+
12761236 /* Modify operation */
1277- if (t != NULL ) {
1278- ret = __parse_bitfield_probe_arg (t , parg -> type , & code );
1237+ if (type != NULL ) {
1238+ /* Bitfield needs a special fetch_insn. */
1239+ ret = __parse_bitfield_probe_arg (type , parg -> type , & code );
12791240 if (ret ) {
1280- trace_probe_log_err (ctx -> offset + t - arg , BAD_BITFIELD );
1281- goto fail ;
1241+ trace_probe_log_err (ctx -> offset + type_offset , BAD_BITFIELD );
1242+ return ret ;
12821243 }
12831244 } else if (IS_ENABLED (CONFIG_PROBE_EVENTS_BTF_ARGS ) &&
12841245 ctx -> last_type ) {
1246+ /* If user not specified the type, try parsing BTF bitfield. */
12851247 ret = parse_btf_bitfield (& code , ctx );
12861248 if (ret )
1287- goto fail ;
1249+ return ret ;
12881250 }
1289- ret = - EINVAL ;
1251+
12901252 /* Loop(Array) operation */
12911253 if (parg -> count ) {
12921254 if (scode -> op != FETCH_OP_ST_MEM &&
12931255 scode -> op != FETCH_OP_ST_STRING &&
12941256 scode -> op != FETCH_OP_ST_USTRING ) {
1295- trace_probe_log_err (ctx -> offset + (t ? (t - arg ) : 0 ),
1296- BAD_STRING );
1297- goto fail ;
1257+ trace_probe_log_err (ctx -> offset + type_offset , BAD_STRING );
1258+ return - EINVAL ;
12981259 }
12991260 code ++ ;
13001261 if (code -> op != FETCH_OP_NOP ) {
13011262 trace_probe_log_err (ctx -> offset , TOO_MANY_OPS );
1302- goto fail ;
1263+ return - E2BIG ;
13031264 }
13041265 code -> op = FETCH_OP_LP_ARRAY ;
13051266 code -> param = parg -> count ;
13061267 }
1268+
1269+ /* Finalize the fetch_insn array. */
13071270 code ++ ;
13081271 code -> op = FETCH_OP_END ;
13091272
1310- ret = 0 ;
1273+ return 0 ;
1274+ }
1275+
1276+ /* String length checking wrapper */
1277+ static int traceprobe_parse_probe_arg_body (const char * argv , ssize_t * size ,
1278+ struct probe_arg * parg ,
1279+ struct traceprobe_parse_context * ctx )
1280+ {
1281+ struct fetch_insn * code , * tmp = NULL ;
1282+ char * type , * arg ;
1283+ int ret , len ;
1284+
1285+ len = strlen (argv );
1286+ if (len > MAX_ARGSTR_LEN ) {
1287+ trace_probe_log_err (ctx -> offset , ARG_TOO_LONG );
1288+ return - E2BIG ;
1289+ } else if (len == 0 ) {
1290+ trace_probe_log_err (ctx -> offset , NO_ARG_BODY );
1291+ return - EINVAL ;
1292+ }
1293+
1294+ arg = kstrdup (argv , GFP_KERNEL );
1295+ if (!arg )
1296+ return - ENOMEM ;
1297+
1298+ parg -> comm = kstrdup (arg , GFP_KERNEL );
1299+ if (!parg -> comm ) {
1300+ ret = - ENOMEM ;
1301+ goto out ;
1302+ }
1303+
1304+ type = parse_probe_arg_type (arg , parg , ctx );
1305+ if (IS_ERR (type )) {
1306+ ret = PTR_ERR (type );
1307+ goto out ;
1308+ }
1309+
1310+ code = tmp = kcalloc (FETCH_INSN_MAX , sizeof (* code ), GFP_KERNEL );
1311+ if (!code ) {
1312+ ret = - ENOMEM ;
1313+ goto out ;
1314+ }
1315+ code [FETCH_INSN_MAX - 1 ].op = FETCH_OP_END ;
1316+
1317+ ctx -> last_type = NULL ;
1318+ ret = parse_probe_arg (arg , parg -> type , & code , & code [FETCH_INSN_MAX - 1 ],
1319+ ctx );
1320+ if (ret < 0 )
1321+ goto fail ;
1322+
1323+ /* Update storing type if BTF is available */
1324+ if (IS_ENABLED (CONFIG_PROBE_EVENTS_BTF_ARGS ) &&
1325+ ctx -> last_type ) {
1326+ if (!type ) {
1327+ parg -> type = find_fetch_type_from_btf_type (ctx );
1328+ } else if (strstr (type , "string" )) {
1329+ ret = check_prepare_btf_string_fetch (type , & code , ctx );
1330+ if (ret )
1331+ goto fail ;
1332+ }
1333+ }
1334+ parg -> offset = * size ;
1335+ * size += parg -> type -> size * (parg -> count ?: 1 );
1336+
1337+ if (parg -> count ) {
1338+ len = strlen (parg -> type -> fmttype ) + 6 ;
1339+ parg -> fmt = kmalloc (len , GFP_KERNEL );
1340+ if (!parg -> fmt ) {
1341+ ret = - ENOMEM ;
1342+ goto out ;
1343+ }
1344+ snprintf (parg -> fmt , len , "%s[%d]" , parg -> type -> fmttype ,
1345+ parg -> count );
1346+ }
1347+
1348+ ret = finalize_fetch_insn (code , parg , type , type ? type - arg : 0 , ctx );
1349+ if (ret < 0 )
1350+ goto fail ;
1351+
1352+ for (; code < tmp + FETCH_INSN_MAX ; code ++ )
1353+ if (code -> op == FETCH_OP_END )
1354+ break ;
13111355 /* Shrink down the code buffer */
13121356 parg -> code = kcalloc (code - tmp + 1 , sizeof (* code ), GFP_KERNEL );
13131357 if (!parg -> code )
@@ -1316,7 +1360,7 @@ static int traceprobe_parse_probe_arg_body(const char *argv, ssize_t *size,
13161360 memcpy (parg -> code , tmp , sizeof (* code ) * (code - tmp + 1 ));
13171361
13181362fail :
1319- if (ret ) {
1363+ if (ret < 0 ) {
13201364 for (code = tmp ; code < tmp + FETCH_INSN_MAX ; code ++ )
13211365 if (code -> op == FETCH_NOP_SYMBOL ||
13221366 code -> op == FETCH_OP_DATA )
0 commit comments