Skip to content

Commit 9dff608

Browse files
Kangiestevegrubb
authored andcommitted
attrs: preserve array counts on replacement
subject_add() and object_add() always incremented cnt after writing a slot. Replacing an existing subject or object attribute therefore made cnt larger than the number of occupied slots, which trips the DEBUG sanity checker as array corruption. Teach both add paths to treat cnt as an occupied-slot count. They now compute the destination slot once, free the previous slot payload when replacing it, and increment cnt only when filling an empty slot. Add an event_test regression that replaces EXE and PATH attributes and verifies cnt stays at one and the new attributes are cached. Verification: ./configure --with-debug --disable-shared --without-rpm --without-deb; make -j32; make -C src/tests -j32 check TESTS=event_test; make -j32 check. Signed-off-by: Matt Jolly <kangie@gentoo.org>
1 parent ecb38c7 commit 9dff608

3 files changed

Lines changed: 79 additions & 4 deletions

File tree

src/library/object.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ object_attr_t *object_access(const o_array *a, object_type_t t)
7878
int object_add(o_array *a, const object_attr_t *obj)
7979
{
8080
object_attr_t *newnode;
81+
object_attr_t **slot;
8182

8283
if (a == NULL || a->obj == NULL)
8384
return 1;
@@ -95,8 +96,14 @@ int object_add(o_array *a, const object_attr_t *obj)
9596
} else
9697
return 1;
9798

98-
a->obj[obj->type - OBJ_START] = newnode;
99-
a->cnt++;
99+
slot = &a->obj[obj->type - OBJ_START];
100+
if (*slot) {
101+
free((*slot)->o);
102+
free(*slot);
103+
} else
104+
a->cnt++;
105+
106+
*slot = newnode;
100107

101108
return 0;
102109
}

src/library/subject.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ subject_attr_t *subject_access(const s_array *a, subject_type_t t)
8585
int subject_add(s_array *a, const subject_attr_t *subj)
8686
{
8787
subject_attr_t* newnode;
88+
subject_attr_t **slot;
8889
subject_type_t t;
8990

9091
if (a == NULL || a->subj == NULL)
@@ -118,8 +119,19 @@ int subject_add(s_array *a, const subject_attr_t *subj)
118119
} else
119120
return 1;
120121

121-
a->subj[t - SUBJ_START] = newnode;
122-
a->cnt++;
122+
slot = &a->subj[t - SUBJ_START];
123+
if (*slot) {
124+
subject_attr_t *old = *slot;
125+
126+
if (old->type == GID || old->type == UID)
127+
attr_set_destroy(old->set);
128+
else if (old->type >= COMM)
129+
free(old->str);
130+
free(old);
131+
} else
132+
a->cnt++;
133+
134+
*slot = newnode;
123135
sanity_check_array(a, "subject_add 2");
124136

125137
return 0;

src/tests/event_test.c

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -671,6 +671,58 @@ static int init_caches(unsigned int subj_size, unsigned int obj_size)
671671
return init_event_system(&cfg);
672672
}
673673

674+
/*
675+
* test_attribute_replacement_preserves_count - verify subject/object array
676+
* replacement keeps cnt as an occupied-slot count.
677+
* Returns 0 on success, test error code otherwise.
678+
*/
679+
static int test_attribute_replacement_preserves_count(void)
680+
{
681+
s_array subjects;
682+
o_array objects;
683+
subject_attr_t old_exe = { .type = EXE, .str = strdup("/old-exe") };
684+
subject_attr_t new_exe = { .type = EXE, .str = strdup("/new-exe") };
685+
object_attr_t old_path = { .type = PATH, .o = strdup("/old-path") };
686+
object_attr_t new_path = { .type = PATH, .o = strdup("/new-path") };
687+
subject_attr_t *cached_subject;
688+
object_attr_t *cached_object;
689+
690+
CHECK(old_exe.str && new_exe.str && old_path.o && new_path.o, 130,
691+
"[ERROR:130] failed to allocate replacement attributes");
692+
CHECK(subject_create(&subjects) == 0, 131,
693+
"[ERROR:131] failed to allocate subject array");
694+
CHECK(object_create(&objects) == 0, 132,
695+
"[ERROR:132] failed to allocate object array");
696+
697+
CHECK(subject_add(&subjects, &old_exe) == 0, 133,
698+
"[ERROR:133] failed to add original subject attribute");
699+
CHECK(subject_add(&subjects, &new_exe) == 0, 134,
700+
"[ERROR:134] failed to replace subject attribute");
701+
CHECK(subjects.cnt == 1, 135,
702+
"[ERROR:135] subject replacement changed slot count");
703+
cached_subject = subject_access(&subjects, EXE);
704+
CHECK(cached_subject != NULL, 136,
705+
"[ERROR:136] replacement subject attribute missing");
706+
CHECK(strcmp(cached_subject->str, "/new-exe") == 0, 137,
707+
"[ERROR:137] replacement subject attribute not cached");
708+
709+
CHECK(object_add(&objects, &old_path) == 0, 138,
710+
"[ERROR:138] failed to add original object attribute");
711+
CHECK(object_add(&objects, &new_path) == 0, 139,
712+
"[ERROR:139] failed to replace object attribute");
713+
CHECK(objects.cnt == 1, 140,
714+
"[ERROR:140] object replacement changed slot count");
715+
cached_object = object_access(&objects, PATH);
716+
CHECK(cached_object != NULL, 141,
717+
"[ERROR:141] replacement object attribute missing");
718+
CHECK(strcmp(cached_object->o, "/new-path") == 0, 142,
719+
"[ERROR:142] replacement object attribute not cached");
720+
721+
subject_clear(&subjects);
722+
object_clear(&objects);
723+
return 0;
724+
}
725+
674726
/*
675727
* test_attr_lookup_metrics - verify request, miss, dependency, and reset data.
676728
* Returns 0 on success, test error code otherwise.
@@ -1122,6 +1174,10 @@ int main(void)
11221174
if (rc)
11231175
return rc;
11241176

1177+
rc = test_attribute_replacement_preserves_count();
1178+
if (rc)
1179+
return rc;
1180+
11251181
rc = test_attr_lookup_metrics();
11261182
if (rc)
11271183
return rc;

0 commit comments

Comments
 (0)