repl_meta_data: fix linked attribute corruption on databases with unsorted links...
authorStefan Metzmacher <metze@samba.org>
Wed, 17 Jan 2018 07:07:03 +0000 (08:07 +0100)
committerAndreas Schneider <asn@cryptomilk.org>
Mon, 22 Jan 2018 11:26:19 +0000 (12:26 +0100)
commita25c99c9f1fd1814c56c21848c748cd0e038eed7
tree2598d654eaaa081d595cbbc4367a0829f2c981bc
parentc34c2dd55545b99fba46cf374a1653bad96cea9e
repl_meta_data: fix linked attribute corruption on databases with unsorted links on expunge

This is really critical bug, it removes valid linked attributes.

When a DC was provisioned/joined with a Samba version older than 4.7
is upgraded to 4.7 (or later), it can happen that the garbage collection
(dsdb_garbage_collect_tombstones()), triggered periodically by the 'kcc' task
of 'samba' or my 'samba-tool domain tombstones expunge' corrupt the linked attributes.

This is similar to Bug #13095 - Broken linked attribute handling,
but it's not triggered by an originating change.

The bug happens in replmd_modify_la_delete()
were get_parsed_dns_trusted() generates a sorted array of
struct parsed_dn based on the values in old_el->values.

If the database doesn't support the sortedLinks compatibleFeatures
in the @SAMBA_DSDB record, it's very likely that
the array of old_dns is sorted differently than the values
in old_el->values.

The problem is that struct parsed_dn has just a pointer
'struct ldb_val *v' that points to the corresponding
value in old_el->values.

Now if vanish_links is true the damage happens here:

        if (vanish_links) {
                unsigned j = 0;
                for (i = 0; i < old_el->num_values; i++) {
                        if (old_dns[i].v != NULL) {
                                old_el->values[j] = *old_dns[i].v;
                                j++;
                        }
                }
                old_el->num_values = j;
        }

old_el->values[0] = *old_dns[0].v;
can change the value old_dns[1].v is pointing at!
That means that some values can get lost while others
are stored twice, because the LDB_FLAG_INTERNAL_DISABLE_SINGLE_VALUE_CHECK
allows it to be stored.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=13228

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
selftest/knownfail.d/unsorted-links [deleted file]
source4/dsdb/samdb/ldb_modules/repl_meta_data.c