@@ -1358,6 +1358,68 @@ static int count_preds(struct filter_parse_state *ps)
1358
1358
return n_preds ;
1359
1359
}
1360
1360
1361
+ /*
1362
+ * The tree is walked at filtering of an event. If the tree is not correctly
1363
+ * built, it may cause an infinite loop. Check here that the tree does
1364
+ * indeed terminate.
1365
+ */
1366
+ static int check_pred_tree (struct event_filter * filter ,
1367
+ struct filter_pred * root )
1368
+ {
1369
+ struct filter_pred * preds ;
1370
+ struct filter_pred * pred ;
1371
+ enum move_type move = MOVE_DOWN ;
1372
+ int count = 0 ;
1373
+ int done = 0 ;
1374
+ int max ;
1375
+
1376
+ /*
1377
+ * The max that we can hit a node is three times.
1378
+ * Once going down, once coming up from left, and
1379
+ * once coming up from right. This is more than enough
1380
+ * since leafs are only hit a single time.
1381
+ */
1382
+ max = 3 * filter -> n_preds ;
1383
+
1384
+ preds = filter -> preds ;
1385
+ if (!preds )
1386
+ return - EINVAL ;
1387
+ pred = root ;
1388
+
1389
+ do {
1390
+ if (WARN_ON (count ++ > max ))
1391
+ return - EINVAL ;
1392
+
1393
+ switch (move ) {
1394
+ case MOVE_DOWN :
1395
+ if (pred -> left != FILTER_PRED_INVALID ) {
1396
+ pred = & preds [pred -> left ];
1397
+ continue ;
1398
+ }
1399
+ /* A leaf at the root is just a leaf in the tree */
1400
+ if (pred == root )
1401
+ break ;
1402
+ pred = get_pred_parent (pred , preds ,
1403
+ pred -> parent , & move );
1404
+ continue ;
1405
+ case MOVE_UP_FROM_LEFT :
1406
+ pred = & preds [pred -> right ];
1407
+ move = MOVE_DOWN ;
1408
+ continue ;
1409
+ case MOVE_UP_FROM_RIGHT :
1410
+ if (pred == root )
1411
+ break ;
1412
+ pred = get_pred_parent (pred , preds ,
1413
+ pred -> parent , & move );
1414
+ continue ;
1415
+ }
1416
+ done = 1 ;
1417
+ } while (!done );
1418
+
1419
+ /* We are fine. */
1420
+ return 0 ;
1421
+ }
1422
+
1361
1423
static int replace_preds (struct ftrace_event_call * call ,
1362
1424
struct event_filter * filter ,
1363
1425
struct filter_parse_state * ps ,
@@ -1366,6 +1428,7 @@ static int replace_preds(struct ftrace_event_call *call,
1366
1428
{
1367
1429
char * operand1 = NULL , * operand2 = NULL ;
1368
1430
struct filter_pred * pred ;
1431
+ struct filter_pred * root ;
1369
1432
struct postfix_elt * elt ;
1370
1433
struct pred_stack stack = { }; /* init to NULL */
1371
1434
int err ;
@@ -1442,14 +1505,21 @@ static int replace_preds(struct ftrace_event_call *call,
1442
1505
if (!pred )
1443
1506
return - EINVAL ;
1444
1507
/* This item is where we start from in matching */
1445
- filter -> root = pred ;
1508
+ root = pred ;
1446
1509
/* Make sure the stack is empty */
1447
1510
pred = __pop_pred_stack (& stack );
1448
1511
if (WARN_ON (pred )) {
1449
1512
err = - EINVAL ;
1450
1513
filter -> root = NULL ;
1451
1514
goto fail ;
1452
1515
}
1516
+ err = check_pred_tree (filter , root );
1517
+ if (err )
1518
+ goto fail ;
1519
+
1520
+ /* We don't set root until we know it works */
1521
+ barrier ();
1522
+ filter -> root = root ;
1453
1523
}
1454
1524
1455
1525
err = 0 ;
0 commit comments