mirror of
https://github.com/openvswitch/ovs
synced 2025-08-31 06:15:47 +00:00
ovsdb-idl: Adjust indexes during transactions.
When transactions modified tables with indexes, the indexes were not properly updated to reflect the changes. For deleted rows, in particular, this could cause use-after-free errors. This commit fixes the problem and adds some simple test cases provided by Han Zhou that, without the fix, cause a crash. Reported-by: Han Zhou <zhouhan@gmail.com> Reported-at: https://mail.openvswitch.org/pipermail/ovs-discuss/2018-August/047185.html Signed-off-by: Ben Pfaff <blp@ovn.org>
This commit is contained in:
@@ -3515,9 +3515,18 @@ ovsdb_idl_txn_disassemble(struct ovsdb_idl_txn *txn)
|
||||
txn->db->txn = NULL;
|
||||
|
||||
HMAP_FOR_EACH_SAFE (row, next, txn_node, &txn->txn_rows) {
|
||||
enum { INSERTED, MODIFIED, DELETED } op
|
||||
= (!row->new_datum ? DELETED
|
||||
: !row->old_datum ? INSERTED
|
||||
: MODIFIED);
|
||||
|
||||
if (op != DELETED) {
|
||||
ovsdb_idl_remove_from_indexes(row);
|
||||
}
|
||||
|
||||
ovsdb_idl_destroy_all_map_op_lists(row);
|
||||
ovsdb_idl_destroy_all_set_op_lists(row);
|
||||
if (row->old_datum) {
|
||||
if (op != INSERTED) {
|
||||
if (row->written) {
|
||||
ovsdb_idl_row_unparse(row);
|
||||
ovsdb_idl_row_clear_arcs(row, false);
|
||||
@@ -3536,7 +3545,9 @@ ovsdb_idl_txn_disassemble(struct ovsdb_idl_txn *txn)
|
||||
|
||||
hmap_remove(&txn->txn_rows, &row->txn_node);
|
||||
hmap_node_nullify(&row->txn_node);
|
||||
if (!row->old_datum) {
|
||||
if (op != INSERTED) {
|
||||
ovsdb_idl_add_to_indexes(row);
|
||||
} else {
|
||||
hmap_remove(&row->table->rows, &row->hmap_node);
|
||||
free(row);
|
||||
}
|
||||
@@ -4216,6 +4227,10 @@ ovsdb_idl_txn_write__(const struct ovsdb_idl_row *row_,
|
||||
goto discard_datum;
|
||||
}
|
||||
|
||||
bool index_row = is_index_row(row);
|
||||
if (!index_row) {
|
||||
ovsdb_idl_remove_from_indexes(row);
|
||||
}
|
||||
if (hmap_node_is_null(&row->txn_node)) {
|
||||
hmap_insert(&row->table->db->txn->txn_rows, &row->txn_node,
|
||||
uuid_hash(&row->uuid));
|
||||
@@ -4238,6 +4253,9 @@ ovsdb_idl_txn_write__(const struct ovsdb_idl_row *row_,
|
||||
}
|
||||
(column->unparse)(row);
|
||||
(column->parse)(row, &row->new_datum[column_idx]);
|
||||
if (!index_row) {
|
||||
ovsdb_idl_add_to_indexes(row);
|
||||
}
|
||||
return;
|
||||
|
||||
discard_datum:
|
||||
@@ -4365,6 +4383,8 @@ ovsdb_idl_txn_delete(const struct ovsdb_idl_row *row_)
|
||||
}
|
||||
|
||||
ovs_assert(row->new_datum != NULL);
|
||||
ovs_assert(!is_index_row(row_));
|
||||
ovsdb_idl_remove_from_indexes(row_);
|
||||
if (!row->old_datum) {
|
||||
ovsdb_idl_row_unparse(row);
|
||||
ovsdb_idl_row_clear_new(row);
|
||||
@@ -4412,6 +4432,7 @@ ovsdb_idl_txn_insert(struct ovsdb_idl_txn *txn,
|
||||
row->new_datum = xmalloc(class->n_columns * sizeof *row->new_datum);
|
||||
hmap_insert(&row->table->rows, &row->hmap_node, uuid_hash(&row->uuid));
|
||||
hmap_insert(&txn->txn_rows, &row->txn_node, uuid_hash(&row->uuid));
|
||||
ovsdb_idl_add_to_indexes(row);
|
||||
return row;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user