exists. Reported by Qualys, assisted by Claude Mythos
Preview. File: pipe.c.
-20260720:
+20260720
Bug (defect introduced: Postfix 1,1, date: 20010524): the
postsuper command over-read a very short queue filename.
service. Files: nbdb_safe.c, nbdb_safe.h, nbdb_safe_test.c,
nbdb_process_test.c.
+20260721
+
+ Hardening: in the non-BerkeleyDB migration service, delay
+ the decision between running postmap or postalias until
+ after the database file/directory owner/permission checks.
+ The benefit from making the decision early (better error
+ messages) was not worth the risk. Qualys, assisted by Claude
+ Mythos Preview. Files: nbdb_process.c, nbdb_process_test.c.
+
+ Back-port htable fixes to binhash tables: 1) segfault in
+ the binhash first/next iterator when a table contains one
+ element; 2) technical debt: allow an element to be deleted
+ after the binhash table's first/next iterator has started,
+ but before it has visited the element; 3) don't free null
+ data pointers. File: util/binhash.c.
+
+ Code health: missing <arpa/inet> includes. Files:
+ testing/mock_servent.c, util/find_inet_service.c.
+
TODO
Reorganize PTEST_LIB, PMOCK_LIB, TESTLIB, TESTLIBS, etc.
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
-#define MAIL_RELEASE_DATE "20260720"
+#define MAIL_RELEASE_DATE "20260721"
#define MAIL_VERSION_NUMBER "3.12"
#ifdef SNAPSHOT
return (NBDB_STAT_ERROR);
}
- /*
- * Should we run postmap or postalias? Open the source file with the same
- * (uid, gid) as the postmap or postalias commands would, so that we can
- * detect permission errors quickly.
- *
- * Note: we do this before the file allowlist/owner/permission safety
- * checks, so that we can log the concrete postmap or postalias command
- * if a safety check fails.
- */
- if ((index_cmd = nbdb_get_index_cmd_as(source_path, leg_idx_st.st_uid,
- leg_idx_st.st_gid, why)) == 0)
- return (NBDB_STAT_ERROR);
-
/*
* Allow indexing as the legacy indexed file owner if it is considered
* "safe".
if (!nbdb_safe_to_index_as_legacy_index_owner(source_path, &source_st,
STR(leg_idx_path), &leg_idx_st,
parent_dir, &parent_dir_st, why)) {
- status = NBDB_STAT_ERROR;
+ return (NBDB_STAT_ERROR);
+ }
+
+ /*
+ * Should we run postmap or postalias? Open the source file with the same
+ * (uid, gid) as the postmap or postalias commands would, so that we can
+ * detect permission errors quickly. 202607 Qualys+Mythos: move this
+ * after the safety checks.
+ */
+ if ((index_cmd = nbdb_get_index_cmd_as(source_path, leg_idx_st.st_uid,
+ leg_idx_st.st_gid, why)) == 0) {
+ return (NBDB_STAT_ERROR);
}
/*
.in_new_type = "hash",
.in_source_path = "/path/to/file",
.want_status = NBDB_STAT_ERROR,
- .want_why = "could not execute command 'postmap cdb:/path/to/file': table /path/to/file has an unexpected pathname",
+ .want_why = "table /path/to/file has an unexpected pathname",
},
},
* System library.
*/
#include <sys_defs.h>
+#include <arpa/inet.h>
#include <wrap_netdb.h>
#include <string.h>
/* depending on the value of the "how" argument. Specify
/* BINHASH_SEQ_FIRST to start a new sequence, BINHASH_SEQ_NEXT
/* to continue, and BINHASH_SEQ_STOP to terminate a sequence
-/* early. The caller must not delete an element before it is
-/* visited.
+/* early.
/* RESTRICTIONS
/* A callback function should not modify the hash table that is
/* specified to its caller.
void binhash_delete(BINHASH *table, const void *key, ssize_t key_len, void (*free_fn) (void *))
{
if (table != 0) {
- BINHASH_INFO *ht;
+ BINHASH_INFO *ht, **sp;
BINHASH_INFO **h = table->data + binhash_hash(key, key_len, table->size);
for (ht = *h; ht; ht = ht->next) {
*h = ht->next;
table->used--;
myfree(ht->key);
- if (free_fn)
+ if (free_fn && ht->value)
(*free_fn) (ht->value);
myfree((void *) ht);
+ /* In case the first/next iterator has not yet visited it */
+ for (sp = table->seq_element; sp && *sp; sp++) {
+ if (*sp == ht) {
+ while ((*sp = sp[1]) != 0)
+ sp += 1;
+ break;
+ }
+ }
return;
}
}
for (ht = *h++; ht; ht = next) {
next = ht->next;
myfree(ht->key);
- if (free_fn)
+ if (free_fn && ht->value)
(*free_fn) (ht->value);
myfree((void *) ht);
}
myfree((void *) table->seq_bucket);
table->seq_bucket = binhash_list(table);
table->seq_element = table->seq_bucket;
- return (*(table->seq_element)++);
+ /* FALLTHROUGH */
case BINHASH_SEQ_NEXT: /* next element */
if (table->seq_element && *table->seq_element)
return (*(table->seq_element)++);
msg_panic("%ld entries not deleted", (long) hash->used);
myfree((void *) ht_info);
binhash_free(hash, (void (*) (void *)) 0);
+
+ /* Iterate one-element table. */
+ hash = binhash_create(10);
+ binhash_enter(hash, "one", 4, "one");
+ if( binhash_sequence(hash,BINHASH_SEQ_FIRST) == 0)
+ msg_panic("one-element iterator BINHASH_SEQ_FIRST");
+ if (binhash_sequence(hash,BINHASH_SEQ_NEXT) != 0)
+ msg_panic("one-element iterator BINHASH_SEQ_NEXT");
+ binhash_free(hash, (void (*) (void *)) 0);
+
+ /* TODO: Delete element before it is visited by iterator. */
+
vstring_free(buf);
return (0);
}
/* System libraries. */
#include <sys_defs.h>
+#include <arpa/inet.h>
#include <wrap_netdb.h>
#include <stdlib.h>
#include <string.h>