From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on inbox.vuxu.org X-Spam-Level: X-Spam-Status: No, score=-0.8 required=5.0 tests=DKIM_ADSP_CUSTOM_MED, DKIM_INVALID,DKIM_SIGNED,FREEMAIL_FROM,MAILING_LIST_MULTI, RCVD_IN_MSPIKE_H2 autolearn=ham autolearn_force=no version=3.4.4 Received: (qmail 16828 invoked from network); 30 Mar 2023 09:24:25 -0000 Received: from second.openwall.net (193.110.157.125) by inbox.vuxu.org with ESMTPUTF8; 30 Mar 2023 09:24:25 -0000 Received: (qmail 16362 invoked by uid 550); 30 Mar 2023 09:24:21 -0000 Mailing-List: contact musl-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-ID: Reply-To: musl@lists.openwall.com Received: (qmail 16308 invoked from network); 30 Mar 2023 09:24:19 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1680168247; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=hWt3x5cTj39+9/Yb9dnO0mdhJBtCr6FX2u3HetFXEUM=; b=LwiP3tOw7GDC2KctOKqBlH2rtQy2xqT1rWpYNhyEJj+TI4p+8JO2kIrlWbq5/h5xR8 upRS1Lc2DtrKtsMMs/t7LbCqGUJLhjRO4QStsELJnnMlacNZTcKSicgGha416DTcJDla LFqxdsVQcrj0+/h3J8l+AjAGfM1iyMrlARI2up86HNgbfRbkviCJldud3Qo2wOZO9cAr dbM8RKmJdw23wWf2zrwIVEa+oM5gwF46KmQPE8NNKMG26smMSKaBpfIumGetL/G+7feq +/KZS5GNotzMccNDHTW8Ul8ihF3BNVkHkzI6aI3I/FdN2f9P/TREscheToCxOoOSJ1v+ UmzQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1680168247; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=hWt3x5cTj39+9/Yb9dnO0mdhJBtCr6FX2u3HetFXEUM=; b=4ciLOuHjbChcffJaEZNemFBcwGi9RQOkpqLbESqrpe69tRkWSe2Lmb3tqo9U2TV8rK bUWx/5NfeQmQ03SoQD8T+wHnGOYmBQHucDePz5oQmykUk+oyKJdbI0qzBvMXQPFZnEwO F8ZWNUpdio9l1sb+ZZFkdCW/XmmnHEg2cjnz4XdDywEIz8FjIB3qstiM7vzhqMXpTMlp /bg0B2CiPNO0TCio+XYKh05/wRvWW6exc/UwRX7NCl12Zvp/TvMfK/IEe+jy1Gb2Fh4B zUlUlbmK0x3dCxU8xqGAmThDidtvMbin3G1gKC+D6PNym+pfkWsfQTxp8+1q7raCqxED 798w== X-Gm-Message-State: AAQBX9fkkzIjd0anpVMklJ2v6Eti2merFEkfwG4XMKFFQjkzqWApf+VN oRh37XKsw2CldXm9/rA/OU8751PUXpZfcA== X-Google-Smtp-Source: AKy350ajTrpEgDoPtBOXG41QQcJYHNuJPEWiYlsX66/cq7nOSr1RavSO/n6Xvke0crYpuaq4hAnfrw== X-Received: by 2002:a05:6a20:440c:b0:df:fd8d:a432 with SMTP id ce12-20020a056a20440c00b000dffd8da432mr2202590pzb.5.1680168246732; Thu, 30 Mar 2023 02:24:06 -0700 (PDT) From: Matthias Goergens To: musl@lists.openwall.com Cc: Matthias Goergens Date: Thu, 30 Mar 2023 17:23:52 +0800 Message-Id: <20230330092352.1186349-1-matthias.goergens@gmail.com> X-Mailer: git-send-email 2.40.0 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Subject: [musl] [PATCH] mntent: deal with escaped whitespace in mtab and fstab >From glibc's documentation: > Since fields in the mtab and fstab files are separated by whitespace, > octal escapes are used to represent the characters space (\040), > tab (\011), newline (\012), and backslash (\\) in those files when they > occur in one of the four strings in a mntent structure. The > routines addmntent() and getmntent() will convert from string > representation to escaped representation and back. When converting > from escaped representation, the sequence \134 is also converted to a > backslash. This fixes the issue reported in https://www.openwall.com/lists/musl/2021/12/14/1 -- This is a new version that incorporates suggestions by Szabolcs Nagy and rofl0r The previous version had a helper function named `decode1` that decoded a single escape. I implemented Szabolcs Nagy's extremely clever manual inlining. However, I'm not completely sure that it's not too clever for me. (It took me a while to understand why it works.) --- src/misc/mntent.c | 85 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 78 insertions(+), 7 deletions(-) diff --git a/src/misc/mntent.c b/src/misc/mntent.c index d404fbe3..1c129579 100644 --- a/src/misc/mntent.c +++ b/src/misc/mntent.c @@ -1,8 +1,10 @@ +#include #include #include #include #include #include +#include "stdio_impl.h" static char *internal_buf; static size_t internal_bufsize; @@ -20,6 +22,46 @@ int endmntent(FILE *f) return 1; } +static char* decode(char* buf) { + assert(buf != NULL); + char* src = buf; + char* dest = buf; + while (1) { + char* next_src = __strchrnul(src, '\\'); + int offset = next_src - src; + memmove(dest, src, offset); + src = next_src; + dest += offset; + + if(*src == '\0') { + *dest = *src; + return buf; + } + assert (*src == '\\'); + src++; + + const char *replacements = + "\040" "040" "\0" // space + "\011" "011" "\0" // tab + "\012" "012" "\0" // newline + "\134" "134" "\0" // backslash + "\\" "\\" "\0" + // Fallback for unrecognized escape sequence, + // copy literally: + "\\" ""; + while(1) { + char c = *replacements++; + size_t n = strlen(replacements); + if (strncmp(src, replacements, n) == 0) { + *dest++ = c; + src += n; + break; + } + replacements += n+1; + } + } +} + struct mntent *getmntent_r(FILE *f, struct mntent *mnt, char *linebuf, int buflen) { int n[8], use_internal = (linebuf == SENTINEL); @@ -55,10 +97,10 @@ struct mntent *getmntent_r(FILE *f, struct mntent *mnt, char *linebuf, int bufle linebuf[n[5]] = 0; linebuf[n[7]] = 0; - mnt->mnt_fsname = linebuf+n[0]; - mnt->mnt_dir = linebuf+n[2]; - mnt->mnt_type = linebuf+n[4]; - mnt->mnt_opts = linebuf+n[6]; + mnt->mnt_fsname = decode(linebuf+n[0]); + mnt->mnt_dir = decode(linebuf+n[2]); + mnt->mnt_type = decode(linebuf+n[4]); + mnt->mnt_opts = decode(linebuf+n[6]); return mnt; } @@ -69,12 +111,41 @@ struct mntent *getmntent(FILE *f) return getmntent_r(f, &mnt, SENTINEL, 0); } +static int escape_and_write_string(FILE *f, const char* str) +{ + char c; + int error_occured = 0; + while(str && !error_occured && (c = *str++) != 0) { + if(c == '\040') // space + error_occured = fputs("\\040", f) < 0; + else if (c == '\011') // tab + error_occured = fputs("\\011", f) < 0; + else if (c == '\012') // newline + error_occured = fputs("\\012", f) < 0; + else if (c == '\\') + error_occured = fputs("\\\\", f) < 0; + else + error_occured = putc_unlocked(c, f) < 0; + } + return error_occured; +} + int addmntent(FILE *f, const struct mntent *mnt) { if (fseek(f, 0, SEEK_END)) return 1; - return fprintf(f, "%s\t%s\t%s\t%s\t%d\t%d\n", - mnt->mnt_fsname, mnt->mnt_dir, mnt->mnt_type, mnt->mnt_opts, - mnt->mnt_freq, mnt->mnt_passno) < 0; + FLOCK(f); + int error_occured = + escape_and_write_string(f, mnt->mnt_fsname) + || (0 > putc_unlocked('\t', f)) + || escape_and_write_string(f, mnt->mnt_dir) + || (0 > putc_unlocked('\t', f)) + || escape_and_write_string(f, mnt->mnt_type) + || (0 > putc_unlocked('\t', f)) + || escape_and_write_string(f, mnt->mnt_opts) + || (0 > fprintf(f, "\t%d\t%d\n", + mnt->mnt_freq, mnt->mnt_passno)); + FUNLOCK(f); + return error_occured; } char *hasmntopt(const struct mntent *mnt, const char *opt) -- 2.40.0