@@ -1090,67 +1090,45 @@ static int __parse_bitfield_probe_arg(const char *bf,
1090
1090
return (BYTES_TO_BITS (t -> size ) < (bw + bo )) ? - EINVAL : 0 ;
1091
1091
}
1092
1092
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 )
1097
1096
{
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 ;
1102
1099
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 ;
1123
1100
t = strchr (arg , ':' );
1124
1101
if (t ) {
1125
- * t = '\0' ;
1126
- t2 = strchr (++ t , '[' );
1102
+ * t ++ = '\0' ;
1103
+ t2 = strchr (t , '[' );
1127
1104
if (t2 ) {
1128
1105
* t2 ++ = '\0' ;
1129
1106
t3 = strchr (t2 , ']' );
1130
1107
if (!t3 ) {
1131
- int offs = t2 + strlen (t2 ) - arg ;
1108
+ offs = t2 + strlen (t2 ) - arg ;
1132
1109
1133
1110
trace_probe_log_err (ctx -> offset + offs ,
1134
1111
ARRAY_NO_CLOSE );
1135
- goto out ;
1112
+ return ERR_PTR ( - EINVAL ) ;
1136
1113
} else if (t3 [1 ] != '\0' ) {
1137
1114
trace_probe_log_err (ctx -> offset + t3 + 1 - arg ,
1138
1115
BAD_ARRAY_SUFFIX );
1139
- goto out ;
1116
+ return ERR_PTR ( - EINVAL ) ;
1140
1117
}
1141
1118
* t3 = '\0' ;
1142
1119
if (kstrtouint (t2 , 0 , & parg -> count ) || !parg -> count ) {
1143
1120
trace_probe_log_err (ctx -> offset + t2 - arg ,
1144
1121
BAD_ARRAY_NUM );
1145
- goto out ;
1122
+ return ERR_PTR ( - EINVAL ) ;
1146
1123
}
1147
1124
if (parg -> count > MAX_ARRAY_LEN ) {
1148
1125
trace_probe_log_err (ctx -> offset + t2 - arg ,
1149
1126
ARRAY_TOO_BIG );
1150
- goto out ;
1127
+ return ERR_PTR ( - EINVAL ) ;
1151
1128
}
1152
1129
}
1153
1130
}
1131
+ offs = t ? t - arg : 0 ;
1154
1132
1155
1133
/*
1156
1134
* 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,
1161
1139
strncmp (arg , "\\\"" , 2 ) == 0 )) {
1162
1140
/* The type of $comm must be "string", and not an array type. */
1163
1141
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 );
1167
1144
}
1168
1145
parg -> type = find_fetch_type ("string" , ctx -> flags );
1169
1146
} else
1170
1147
parg -> type = find_fetch_type (t , ctx -> flags );
1148
+
1171
1149
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 ) ;
1174
1152
}
1175
1153
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
+ }
1200
1156
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 ;
1211
1166
1212
- ret = - EINVAL ;
1213
1167
/* Store operation */
1214
1168
if (parg -> type -> is_string ) {
1169
+ /* Check bad combination of the type and the last fetch_insn. */
1215
1170
if (!strcmp (parg -> type -> name , "symstr" )) {
1216
1171
if (code -> op != FETCH_OP_REG && code -> op != FETCH_OP_STACK &&
1217
1172
code -> op != FETCH_OP_RETVAL && code -> op != FETCH_OP_ARG &&
1218
1173
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 ,
1220
1175
BAD_SYMSTRING );
1221
- goto fail ;
1176
+ return - EINVAL ;
1222
1177
}
1223
1178
} else {
1224
1179
if (code -> op != FETCH_OP_DEREF && code -> op != FETCH_OP_UDEREF &&
1225
1180
code -> op != FETCH_OP_IMM && code -> op != FETCH_OP_COMM &&
1226
1181
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 ,
1228
1183
BAD_STRING );
1229
- goto fail ;
1184
+ return - EINVAL ;
1230
1185
}
1231
1186
}
1187
+
1232
1188
if (!strcmp (parg -> type -> name , "symstr" ) ||
1233
1189
(code -> op == FETCH_OP_IMM || code -> op == FETCH_OP_COMM ||
1234
1190
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,
1244
1200
code ++ ;
1245
1201
if (code -> op != FETCH_OP_NOP ) {
1246
1202
trace_probe_log_err (ctx -> offset , TOO_MANY_OPS );
1247
- goto fail ;
1203
+ return - EINVAL ;
1248
1204
}
1249
1205
}
1206
+
1250
1207
/* If op == DEREF, replace it with STRING */
1251
1208
if (!strcmp (parg -> type -> name , "ustring" ) ||
1252
1209
code -> op == FETCH_OP_UDEREF )
@@ -1267,47 +1224,134 @@ static int traceprobe_parse_probe_arg_body(const char *argv, ssize_t *size,
1267
1224
code ++ ;
1268
1225
if (code -> op != FETCH_OP_NOP ) {
1269
1226
trace_probe_log_err (ctx -> offset , TOO_MANY_OPS );
1270
- goto fail ;
1227
+ return - E2BIG ;
1271
1228
}
1272
1229
code -> op = FETCH_OP_ST_RAW ;
1273
1230
code -> size = parg -> type -> size ;
1274
1231
}
1232
+
1233
+ /* Save storing fetch_insn. */
1275
1234
scode = code ;
1235
+
1276
1236
/* 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 );
1279
1240
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 ;
1282
1243
}
1283
1244
} else if (IS_ENABLED (CONFIG_PROBE_EVENTS_BTF_ARGS ) &&
1284
1245
ctx -> last_type ) {
1246
+ /* If user not specified the type, try parsing BTF bitfield. */
1285
1247
ret = parse_btf_bitfield (& code , ctx );
1286
1248
if (ret )
1287
- goto fail ;
1249
+ return ret ;
1288
1250
}
1289
- ret = - EINVAL ;
1251
+
1290
1252
/* Loop(Array) operation */
1291
1253
if (parg -> count ) {
1292
1254
if (scode -> op != FETCH_OP_ST_MEM &&
1293
1255
scode -> op != FETCH_OP_ST_STRING &&
1294
1256
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 ;
1298
1259
}
1299
1260
code ++ ;
1300
1261
if (code -> op != FETCH_OP_NOP ) {
1301
1262
trace_probe_log_err (ctx -> offset , TOO_MANY_OPS );
1302
- goto fail ;
1263
+ return - E2BIG ;
1303
1264
}
1304
1265
code -> op = FETCH_OP_LP_ARRAY ;
1305
1266
code -> param = parg -> count ;
1306
1267
}
1268
+
1269
+ /* Finalize the fetch_insn array. */
1307
1270
code ++ ;
1308
1271
code -> op = FETCH_OP_END ;
1309
1272
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 ;
1311
1355
/* Shrink down the code buffer */
1312
1356
parg -> code = kcalloc (code - tmp + 1 , sizeof (* code ), GFP_KERNEL );
1313
1357
if (!parg -> code )
@@ -1316,7 +1360,7 @@ static int traceprobe_parse_probe_arg_body(const char *argv, ssize_t *size,
1316
1360
memcpy (parg -> code , tmp , sizeof (* code ) * (code - tmp + 1 ));
1317
1361
1318
1362
fail :
1319
- if (ret ) {
1363
+ if (ret < 0 ) {
1320
1364
for (code = tmp ; code < tmp + FETCH_INSN_MAX ; code ++ )
1321
1365
if (code -> op == FETCH_NOP_SYMBOL ||
1322
1366
code -> op == FETCH_OP_DATA )
0 commit comments