]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-3.11.5 v3.11.5
authorWietse Z Venema <wietse@porcupine.org>
Mon, 6 Jul 2026 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <ietf-dane@dukhovni.org>
Tue, 7 Jul 2026 02:40:49 +0000 (12:40 +1000)
17 files changed:
postfix/HISTORY
postfix/src/cleanup/cleanup_extracted.c
postfix/src/cleanup/cleanup_milter.c
postfix/src/global/dict_ldap.c
postfix/src/global/mail_version.h
postfix/src/local/include.c
postfix/src/local/recipient.c
postfix/src/milter/milter8.c
postfix/src/postdrop/postdrop.c
postfix/src/postlogd/postlogd.c
postfix/src/postscreen/postscreen_smtpd.c
postfix/src/showq/showq.c
postfix/src/smtpd/smtpd.c
postfix/src/tls/tlsrpt_wrapper.c
postfix/src/tlsmgr/tlsmgr.c
postfix/src/util/mymalloc.c
postfix/src/util/open_as.c

index e2b3ba79450e58b24edb9553fbc01c2ae007bfd0..8e5ed5f389e1fd0870176566728116cff02be5e0 100644 (file)
@@ -30865,3 +30865,142 @@ Apologies for any names omitted.
        could reject or discard the parameter value, but this has
        never been reported to happen. Found during code maintenance.
        File: smtp_proto.c.
+
+20260618
+
+       Hardening: make sure that optimizers will not delete a
+       memset() call in myfree() that wipes memory. File: mymalloc.c.
+
+       Bug (defect introduced: Postfix 3.1, date: 20151129): a
+       missing return statement in the SHOWQ_CLEANUP_AND_RETURN()
+       macro. A local user could submit a crafted message that
+       triggered a read-after-free and panic() in the unprivileged
+       showq daemon (which scans the mail queue for the 'postqueue
+       -f' and 'mailq' commands). This could happen only before a
+       message had been picked up by the pickup(8) daemon. Problem
+       reported by Qualys, assisted by Claude Mythos Preview. File:
+       showq.c.
+
+20260619
+
+       Bug (defect introduced: Postfix 3.4, date: 20190121): missing
+       null termination in a postlogd process that was started
+       with an EMPTY maillog_file setting, while receiving a message
+       from a postlog command that was started with a NON-EMPTY
+       maillog_file setting. Under these contradicting conditions,
+       an unprivileged attacker could cause postlogd to write null
+       bytes to stack memory as it tokenized text outside the
+       receive buffer, and possibly gain 'postfix' privilege.
+       Problem reported by Qualys, assisted by Claude Mythos
+       Preview. File: postlogd.c.
+
+20260621
+
+       Bug (defect introduced: postfix-3.11.0-RC1, date: 20251222):
+       heap memory over-read in the cleanup daemon as it handled
+       a milter "shutdown" reply. The over-read memory was logged
+       after masking unprintable content. Problem reported by
+       Qualys, assisted by Claude Mythos Preview. File: cleanup_milter.c.
+
+       Bug (defect introduced: Postfix 2.3, date: 20050526): limited
+       (<= 11 byte) heap over-read in the cleanup daemon. This
+       could be triggered by local user with a crafted queue file,
+       but the over-read content was not disclosed and there was
+       no other impact. Problem reported by Qualys, assisted by
+       Claude Mythos Preview. File: cleanup_extracted.c.
+
+       Maintainer future proofing: allow zero-length memory
+       allocation requests. Many people have experience with systems
+       that allow this, therefore it should not trigger a panic
+       in Postfix. File: mymalloc.c.
+
+20260623
+
+       Bug (defect introduced: Postfix 2.3, date: 20060611): double
+       ldap_msgfree(resloop) call during error handling when
+       special_result_attribute is configured. An attacker who
+       controls the LDAP server or can play attacker-in-the-middle
+       could corrupt heap memory. Reported by Qualys, assisted by
+       Claude Mythos Preview. File: dict_ldap.c.
+
+20260624
+
+       Bug (defect introduced: Postfix < alpha, date: 1997): missing
+       recursion guard while processing :include: files that
+       directly include other :include: files in local(8) aliases
+       or .forward files. This could result in exhausting stack
+       space (segfault) or file handles (fatal error). This is not
+       a global DOS; it affected at most two parallel delivery
+       processes for the local recipient who created the condition.
+       Reported by Qualys, assisted by Claude Mythos Preview. File:
+       local/include.c.
+
+       Safety: added a global nesting guard. File: local/recipient.c.
+
+20260625
+
+       Bug (defect introduced: Postfix 2.7, date: 20090617):
+       out-of-memory condition with remote input in the postscreen
+       dummy SMTP engine. This dummy engine is used after PREGREET
+       or DNSBL checks fail, or when "after 220" protocol checks
+       are enabled. Reported by Qualys, assisted by Claude Mythos
+       Preview. File: postscreen_smtpd.c.
+
+       Bug (defect introduced: Postfix 2.0, date: 20030619): file
+       system DOS: with smtpd_proxy_filter enabled, the before-filter
+       SMTP server did not enforce the message size limit for
+       mailbox From_ lines at the beginning of a message. With
+       smtpd_proxy_filter disabled, the file size limit was still
+       enforced by the cleanup daemon. Reported by Qualys, assisted
+       by Claude Mythos Preview. File: smtpd.c.
+
+       Bug (defect introduced: Postfix 2.1, date: 20030619): SMTP
+       server panic() in smtpd_proxy_filter when handling long
+       mailbox From_ lines at the beginning of a message. Reported
+       by Qualys, assisted by Claude Mythos Preview. File: smtpd.c.
+
+       Bug: (defect introduced: Postfix 3.10, date: 20240925):
+       NULL pointer read in the TLSRPT client, caused by missing
+       STR_OR_NULL() wrappers. Reported by Qualys, assisted by
+       Claude Mythos Preview. File: tlsrpt_wrapper.c.
+
+       Bug (defect introduced: Postfix 3.11, date: 20260219): In
+       the non-BerkeleyDB re-indexing server, vstream_fopen_as()
+       ignored the uid and gid arguments and opened a database
+       source file read-only as the 'postfix' user instead of the
+       file owner. Reported by Qualys, assisted by Claude Mythos
+       Preview. File: open_as.c.
+
+20260627
+
+       Future proofing: use the correct device name in DEV_PATH()
+       macro. Reported by Qualys, assisted by Claude Mythos Preview.
+       File: tlsmgr.c.
+
+       Bug (defect introduced: Postfix 2.2. date: 20040829): after
+       a RAND_bytes() call failure, do not rely on stack-based
+       pseudo-randomness for tlsmgr seed generation, and for timing
+       jitter of tlsmgr seed refresh intervals. Reported by Qualys,
+       assisted by Claude Mythos Preview. File: tlsmgr.c.
+
+       Bug (defect introduced: Postfix 2.3, date: 20060711): In
+       the Milter client, null-terminate the SMFIR_REPLYCODE
+       response data to exclude stale data when processing the
+       result as a C string. Reported by Qualys, assisted by Claude
+       Mythos Preview. File: milter8.c.
+
+       Bug (defect introduced: Postfix 2.3, date: 20060711):
+       one-byte heap over-write in the Milter client with
+       soft_bounce=yes while processing a malformed SMFIR_REPLYCODE
+       Milter response. An attacker who controls the Milter or who
+       can play attacker-in-the-middle could corrupt heap memory.
+       Reported by Qualys, assisted by Claude Mythos Preview. File:
+       milter8.c.
+
+20260628
+
+       Bug (defect introduced: Postfix < alpha, date: 19971221):
+       a signal handler in the postdrop command could call unlink()
+       with a pathname that was already wiped and free()d, but not
+       yet reused. Reported by Qualys, assisted by Claude Mythos
+       Preview. File: postdrop.c.
index a0cbc5a64bdb213d0fd74cad024300138bd0c86a..43ea36fd9e2c36229804a0ddbffdf2234d21df47 100644 (file)
@@ -107,6 +107,8 @@ void    cleanup_extracted_process(CLEANUP_STATE *state, int type,
     char   *attr_value;
     const char *error_text;
     int     extra_opts;
+    int     mapped_type = type;
+    const char *mapped_buf = buf;
     int     junk;
 
 #ifdef DELAY_ACTION
@@ -168,9 +170,10 @@ void    cleanup_extracted_process(CLEANUP_STATE *state, int type,
                     state->queue_id, attr_name);
            return;
        }
+       /* 202606 Qualys+Mythos: don't clobber 'type' and 'buf'. */
        if ((junk = rec_attr_map(attr_name)) != 0) {
-           buf = attr_value;
-           type = junk;
+           mapped_buf = attr_value;
+           mapped_type = junk;
        }
     }
 
@@ -240,24 +243,25 @@ void    cleanup_extracted_process(CLEANUP_STATE *state, int type,
        state->dsn_notify = 0;
        return;
     }
-    if (type == REC_TYPE_DSN_ORCPT) {
+    if (mapped_type == REC_TYPE_DSN_ORCPT) {
        if (state->dsn_orcpt) {
            msg_warn("%s: ignoring out-of-order DSN original recipient record <%.200s>",
                     state->queue_id, state->dsn_orcpt);
            myfree(state->dsn_orcpt);
        }
-       state->dsn_orcpt = mystrdup(buf);
+       state->dsn_orcpt = mystrdup(mapped_buf);
        return;
     }
-    if (type == REC_TYPE_DSN_NOTIFY) {
+    if (mapped_type == REC_TYPE_DSN_NOTIFY) {
        if (state->dsn_notify) {
            msg_warn("%s: ignoring out-of-order DSN notify record <%d>",
                     state->queue_id, state->dsn_notify);
            state->dsn_notify = 0;
        }
-       if (!alldig(buf) || (junk = atoi(buf)) == 0 || DSN_NOTIFY_OK(junk) == 0)
+       if (!alldig(mapped_buf) || (junk = atoi(mapped_buf)) == 0
+           || DSN_NOTIFY_OK(junk) == 0)
            msg_warn("%s: ignoring malformed dsn notify record <%.200s>",
-                    state->queue_id, buf);
+                    state->queue_id, mapped_buf);
        else
            state->qmgr_opts |=
                QMGR_READ_FLAG_FROM_DSN(state->dsn_notify = junk);
index 4819c712d03117a4ee3402e7713114714d44830f..9c894d7e6af19c9bf69cfde05bf8fce4496f7ff8 100644 (file)
@@ -2077,15 +2077,9 @@ static const char *cleanup_milter_apply(CLEANUP_STATE *state, const char *event,
        text = "milter triggers DISCARD action";
        break;
     case 'S':
-       if (state->flags & CLEANUP_STAT_CONT)
-           return (0);
-       /* Shutdown' may be the default action for an I/O error. */
-       CLEANUP_MILTER_SET_SMTP_REPLY(state, resp);
-       ret = state->reason;
-       state->errs |= CLEANUP_STAT_WRITE;
-       action = "milter-reject";
-       text = resp + 4;
-       break;
+       /* 202606 Qualys+Mythos found heap over-read at "S" + 4. */
+       resp = "421 4.7.0 Service unavailable"; /* See also smtpd.c. */
+       /* FALLTHROUGH */
 
        /*
         * Override permanent reject with temporary reject. This happens when
index 9236639a1deff9e295e0656fa53d25d37a55018d..1e65a5179a806d37de2213bcd91f096d0d5630f5 100644 (file)
@@ -1183,8 +1183,10 @@ static void dict_ldap_get_values(DICT_LDAP *dict_ldap, LDAPMessage *res,
                        break;
                    }
 
-                   if (resloop != 0)
+                   if (resloop != 0) {
                        ldap_msgfree(resloop);
+                       resloop = 0;
+                   }
 
                    if (dict_ldap->dict.error != 0)
                        break;
index 40279c025dc6b3ff8053ef3b5862031d38493e58..eb602025d419166a887939fd5bbf2b3b0eb0d99f 100644 (file)
@@ -20,8 +20,8 @@
   * Patches change both the patchlevel and the release date. Snapshots have no
   * patchlevel; they change the release date only.
   */
-#define MAIL_RELEASE_DATE      "20260617"
-#define MAIL_VERSION_NUMBER    "3.11.4"
+#define MAIL_RELEASE_DATE      "20260706"
+#define MAIL_VERSION_NUMBER    "3.11.5"
 
 #ifdef SNAPSHOT
 #define MAIL_VERSION_DATE      "-" MAIL_RELEASE_DATE
index a213d3c0888b5d5ca96b3e0b5c8c01163ee9a2ac..da5b6a8d08d0151906233f854ea77f32e47a4d32 100644 (file)
@@ -93,6 +93,15 @@ int     deliver_include(LOCAL_STATE state, USER_ATTR usr_attr, char *path)
     if (msg_verbose)
        MSG_LOG_STATE(myname, state);
 
+    /* 202606 Qualys+Mythos: add missing nesting limit. */
+    if (state.level > 100) {
+       msg_warn(":include: nesting limit exceeded for %s", path);
+       dsb_simple(state.msg_attr.why, "5.4.6",
+                  ":include: nesting limit exceeded");
+       return (bounce_append(BOUNCE_FLAGS(state.request),
+                             BOUNCE_ATTR(state.msg_attr)));
+    }
+
     /*
      * DUPLICATE ELIMINATION
      * 
index e3f4d1ceb93e462f8465180471d4700c2e6ed585..a1900d6d03bfed030b7f522fadf39497f224ee74 100644 (file)
@@ -216,6 +216,20 @@ int     deliver_recipient(LOCAL_STATE state, USER_ATTR usr_attr)
     if (msg_verbose)
        MSG_LOG_STATE(myname, state);
 
+    /*
+     * Global recursion safety check for loops that are not already broken
+     * locally, such as :include: files that directly :include: another
+     * file).
+     */
+    if (state.level > 100) {
+       msg_warn("recipient nesting limit exceeded for %s",
+                state.msg_attr.rcpt.address);
+       dsb_simple(state.msg_attr.why, "5.4.6",
+                  "recipient nesting limit exceeded");
+       return (bounce_append(BOUNCE_FLAGS(state.request),
+                             BOUNCE_ATTR(state.msg_attr)));
+    }
+
     /*
      * Duplicate filter.
      */
index 02e3ca3cd00c7a3fcb9246a1f01025c24923ea9f..1abd04505d28f1661ac301e966b19d03534d5338 100644 (file)
@@ -491,6 +491,7 @@ static const NAME_CODE milter8_versions[] = {
 
 #define STR(x) vstring_str(x)
 #define LEN(x) VSTRING_LEN(x)
+#define END(x) vstring_end(x)
 
 /* milter8_def_reply - set persistent response */
 
@@ -683,6 +684,8 @@ static int vmilter8_read_data(MILTER8 *milter, ssize_t *data_len, va_list ap)
                return (milter8_comm_error(milter));
            }
            *data_len = 0;
+           /* Qualys+Mythos: terminate string data before stale data. */
+           VSTRING_TERMINATE(buf);
            break;
 
            /*
@@ -1309,10 +1312,11 @@ static const char *milter8_event(MILTER8 *milter, int event,
                }
            }
            if (var_soft_bounce) {
-               for (cp = STR(milter->buf); /* void */ ; cp = next) {
+               for (cp = STR(milter->buf); cp < END(milter->buf) ; cp = next) {
                    if (cp[0] == '5') {
                        cp[0] = '4';
-                       if (cp[4] == '5')
+                       /* Qualys+Mythos: add missing guard. */
+                       if (cp + 4 < END(milter->buf) && cp[4] == '5')
                            cp[4] = '4';
                    }
                    if ((next = strstr(cp, "\r\n")) == 0)
index f7771ea79a23732cd2cbdf08a419f27b4111dd26..28c89748c5f7106a3b09f271c6ad23c700d707a7 100644 (file)
@@ -504,8 +504,10 @@ int     main(int argc, char **argv)
                msg_warn("uid=%ld: remove %s: %m", (long) uid, postdrop_path);
            else if (msg_verbose)
                msg_info("remove %s", postdrop_path);
-           myfree(postdrop_path);
+           /* Qualys+Mythos: avoid read-after-free in signal handler. */
+           junk = postdrop_path;
            postdrop_path = 0;
+           myfree(junk);
            exit(0);
        }
        if (rec_type == REC_TYPE_ERROR)
index f844c3d576966b446711d6e41c0e55ff44fec8e7..6e7aee5d9b6050342fae10b10c46e904c552cfa5 100644 (file)
@@ -152,10 +152,10 @@ static void postlogd_fallback(const char *buf)
 static void postlogd_service(int sock, char *unused_service,
                                     char **unused_argv)
 {
-    char    buf[DGRAM_BUF_SIZE];
+    char    buf[DGRAM_BUF_SIZE + 1];
     ssize_t len;
 
-    if ((len = recv(sock, buf, sizeof(buf), 0)) < 0) {
+    if ((len = recv(sock, buf, sizeof(buf) - 1, 0)) < 0) {
        msg_warn("failed to receive message with recv: %m");
        return;
     }
@@ -173,6 +173,9 @@ static void postlogd_service(int sock, char *unused_service,
        char   *bp = buf;
        char   *progname_pid;
 
+       /* 202606 Qualys+Mythos: null-terminate the buffer. */
+       buf[len] = 0;
+
        /*
         * Avoid surprises: strip off the date, time, host, and program[pid]:
         * prefix that were prepended by msg_logger(3). Then, hope that the
index 6b72626a751c93f6068691416769cd46c44d4050..ac181d2481c7924e5af62f52cd40fc513b2116d0 100644 (file)
@@ -839,9 +839,10 @@ static void psc_smtpd_read_event(int event, void *context)
 
            /*
             * Sanity check. We don't want to store infinitely long commands.
+            * 
+            * Qualys+Mythos: make the VSTRING_LEN test unconditional.
             */
-           if (state->read_state == PSC_SMTPD_CMD_ST_ANY
-               && VSTRING_LEN(state->cmd_buffer) >= var_line_limit) {
+           if (VSTRING_LEN(state->cmd_buffer) >= var_line_limit) {
                msg_info("COMMAND LENGTH LIMIT from [%s]:%s after %s",
                         PSC_CLIENT_ADDR_PORT(state), state->where);
                PSC_CLEAR_EVENT_DROP_SESSION_STATE(state, psc_smtpd_time_event,
index 89ac9cf3953f98958be70067dc711c900c5aae59..9021cea18d009550d19f77847e612edc61ad98e0 100644 (file)
@@ -180,8 +180,10 @@ static void showq_report(VSTREAM *client, char *queue, char *id,
 
     /*
      * Let the optimizer worry about eliminating duplicate code.
+     * 
+     * 202606 Qualys+Mythos: add missing return statement.
      */
-#define SHOWQ_CLEANUP_AND_RETURN { \
+#define SHOWQ_CLEANUP_AND_RETURN do { \
        if (sender_seen > 0) \
            attr_print(client, ATTR_FLAG_NONE, ATTR_TYPE_END); \
        vstring_free(buf); \
@@ -193,7 +195,8 @@ static void showq_report(VSTREAM *client, char *queue, char *id,
            dsb_free(dsn_buf); \
        if (dup_filter) \
            htable_free(dup_filter, (void (*) (void *)) 0); \
-    }
+       return; \
+    } while (0)
 
     /*
      * XXX addresses in defer logfiles are in printable quoted form, while
index d2272ee187ec92dbd8162278cff0639086b7318a..ef1bc14777454198e41ada7f97a5c88e23e557de 100644 (file)
@@ -3749,10 +3749,11 @@ static void receive_data_message(SMTPD_STATE *state,
        start = vstring_str(state->buffer);
        len = VSTRING_LEN(state->buffer);
        if (first) {
+           /* Qualys+Mythos: DOS in mbox line reading loop. */
            if (strncmp(start + strspn(start, ">"), "From ", 5) == 0) {
-               out_fprintf(out_stream, curr_rec_type,
-                           "X-Mailbox-Line: %s", start);
-               continue;
+               /* Qualys+Mythos: panic in smtpd_proxy*rec_fprintf(). */
+               out_record(out_stream, REC_TYPE_CONT, "X-Mailbox-Line: ", 16);
+               state->act_size += 16;
            }
            first = 0;
            if (len > 0 && IS_SPACE_TAB(start[0]))
index 3feca68bf21274ef20ff0eb9c98c185e89806ea5..194609f669130c903f6a8437a506c1aca8b785de 100644 (file)
@@ -582,7 +582,8 @@ int     trw_report_failure(TLSRPT_WRAPPER *trw,
     /* Give the local admin a clue. */
     msg_info("TLSRPT: status=failure, domain=%s, receiving_mx=%s[%s],"
             " failure_type=%s%s%s",
-            trw->rpt_policy_domain, trw->rcv_mta_name, trw->rcv_mta_addr,
+            trw->rpt_policy_domain, STR_OR_NULL(trw->rcv_mta_name),
+            STR_OR_NULL(trw->rcv_mta_addr),
             trw_failure_type_to_string(failure_type),
             failure_reason ? ", failure_reason=" : "",
             failure_reason ? failure_reason : "");
index d32e63d4b9d3f42423403457e28213f18b178d17..59fc95eec9179daf7f414cf818ed89a80fc19ff9 100644 (file)
@@ -283,7 +283,7 @@ static TLS_PRNG_SRC *rand_source_file;
   */
 #define DEV_PREF "dev:"
 #define DEV_PREF_LEN (sizeof((DEV_PREF)) - 1)
-#define DEV_PATH(dev) ((dev) + EGD_PREF_LEN)
+#define DEV_PATH(dev) ((dev) + DEV_PREF_LEN)
 
 #define EGD_PREF "egd:"
 #define EGD_PREF_LEN (sizeof((EGD_PREF)) - 1)
@@ -353,7 +353,8 @@ static void tlsmgr_prng_exch_event(int unused_event, void *dummy)
      * Make prediction difficult for outsiders and calculate the time for the
      * next execution randomly.
      */
-    RAND_bytes(&randbyte, 1);
+    if (RAND_bytes(&randbyte, 1) < 0)
+       randbyte = getpid() & 0xff;
     next_period = (var_tls_prng_exch_period * randbyte) / UCHAR_MAX;
     event_request_timer(tlsmgr_prng_exch_event, dummy, next_period);
 }
@@ -758,9 +759,12 @@ static void tlsmgr_service(VSTREAM *client_stream, char *unused_service,
                             len, TLS_MGR_REQ_SEED);
                } else {
                    VSTRING_SPACE(buffer, len);
-                   RAND_bytes((unsigned char *) STR(buffer), len);
-                   vstring_set_payload_size(buffer, len);
-                   status = TLS_MGR_STAT_OK;
+                   if (RAND_bytes((unsigned char *) STR(buffer), len) < 0) {
+                       status = TLS_MGR_STAT_ERR;
+                   } else {
+                       vstring_set_payload_size(buffer, len);
+                       status = TLS_MGR_STAT_OK;
+                   }
                }
            }
            attr_print(client_stream, ATTR_FLAG_NONE,
index 94f7bb3e7aa733e31e0290e67022740ca46222bd..48a0539c78c588a8f9f04e63b5e4302f7e92bc05 100644 (file)
@@ -129,6 +129,12 @@ typedef struct MBLOCK {
 
 #define SPACE_FOR(len) (offsetof(MBLOCK, u.payload[0]) + len)
 
+ /*
+  * The memset-before-free safety net should not be optimized out by future
+  * compilers or linkers.
+  */
+static void *(*volatile safe_memset) (void *, int, size_t) = memset;
+
  /*
   * Optimization for short strings. We share one copy with multiple callers.
   * This differs from normal heap memory in two ways, because the memory is
@@ -140,6 +146,8 @@ typedef struct MBLOCK {
   * - myfree() cannot overwrite the memory with a filler pattern like it can do
   * with heap memory. Therefore, some dangling pointer bugs will be masked.
   */
+#undef NO_SHARED_EMPTY_STRINGS
+
 #ifndef NO_SHARED_EMPTY_STRINGS
 static const char empty_string[] = "";
 
@@ -152,6 +160,15 @@ void   *mymalloc(ssize_t len)
     void   *ptr;
     MBLOCK *real_ptr;
 
+    /*
+     * Maintainer proofing: many people expect that a request for null memory
+     * will not result in a panic().
+     */
+#ifndef NO_SHARED_EMPTY_STRINGS
+    if (len == 0)
+       return ((void *) empty_string);
+#endif
+
     /*
      * Note: for safety reasons the request length is a signed type. This
      * allows us to catch integer overflow problems that weren't already
@@ -213,7 +230,7 @@ void    myfree(void *ptr)
     if (ptr != empty_string) {
 #endif
        CHECK_IN_PTR(ptr, real_ptr, len, "myfree");
-       memset((void *) real_ptr, FILLER, SPACE_FOR(len));
+       safe_memset((void *) real_ptr, FILLER, SPACE_FOR(len));
        free((void *) real_ptr);
 #ifndef NO_SHARED_EMPTY_STRINGS
     }
index 744bb816186537fb9858863862920900c3be43b7..8adecd81960609ed7067232ed84455b87f054597 100644 (file)
@@ -89,7 +89,7 @@ VSTREAM *vstream_fopen_as(const char *path, int flags, mode_t mode,
 {
     int     fd;
 
-    if ((fd = open(path, flags, mode)) < 0)
+    if ((fd = open_as(path, flags, mode, euid, egid)) < 0)
        return (0);
     return (vstream_fdopen(fd, flags));
 }