From patchwork Fri Jul 14 16:47:05 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Natanael Copa X-Patchwork-Id: 9841445 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 8C50C60212 for ; Fri, 14 Jul 2017 16:47:30 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7AAF628750 for ; Fri, 14 Jul 2017 16:47:30 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6F57328789; Fri, 14 Jul 2017 16:47:30 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 723B828750 for ; Fri, 14 Jul 2017 16:47:27 +0000 (UTC) Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id EAEF026738E; Fri, 14 Jul 2017 18:47:25 +0200 (CEST) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id 609A726738E; Fri, 14 Jul 2017 18:47:25 +0200 (CEST) Received: from mx1.tetrasec.net (mx1.tetrasec.net [74.117.190.25]) by alsa0.perex.cz (Postfix) with ESMTP id 678C5266C1E; Fri, 14 Jul 2017 18:47:19 +0200 (CEST) Received: from mx1.tetrasec.net (mail.local [127.0.0.1]) by mx1.tetrasec.net (Postfix) with ESMTP id 213009E24B1; Fri, 14 Jul 2017 16:47:18 +0000 (GMT) Received: from ncopa-desktop.copa.dup.pw (15.63.200.37.customer.cdi.no [37.200.63.15]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: n@tanael.org) by mx1.tetrasec.net (Postfix) with ESMTPSA id CF23B9E03B1; Fri, 14 Jul 2017 16:47:16 +0000 (GMT) From: Natanael Copa To: patch@alsa-project.org Date: Fri, 14 Jul 2017 18:47:05 +0200 Message-Id: <20170714164705.3212-1-ncopa@alpinelinux.org> X-Mailer: git-send-email 2.13.2 In-Reply-To: References: Cc: Natanael Copa , alsa-devel@alsa-project.org Subject: [alsa-devel] [PATCH v2 - alsa-lib] snd_user_file: avoid use wordexp X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org X-Virus-Scanned: ClamAV using ClamSMTP As suggested in POSIX[1], wordexp might execute the shell. If the libc implementation does so, it will break the firefox sandbox which does not allow exec. This happened on Alpine Linux with musl libc[2]. Since we cannot guarantee that the system wordexp implementation does not execute shell, we cannot really use it, and need to implement the ~/ expansion ourselves. We provide a configure option --with-wordexp for users that still may need it, but we leave this off by default because wordexp is a large large attack vector and it is better to avoid it. [1]: http://pubs.opengroup.org/onlinepubs/9699919799/functions/wordexp.html#tag_16_684_08 [2]: http://bugs.alpinelinux.org/issues/7454#note-2 Signed-off-by: Natanael Copa --- changes v2: - add configure option to enable old behaviour which uses wordexp. this is off by default. I was not sure if I should use --with-wordexp or --enable-wordexp but went with --with-wordexp similar to --with-softfloat. configure.ac | 19 ++++++++++++++++- src/userfile.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 75 insertions(+), 9 deletions(-) diff --git a/configure.ac b/configure.ac index 26e5d125..fbcfa829 100644 --- a/configure.ac +++ b/configure.ac @@ -303,8 +303,25 @@ fi AC_SUBST(ALSA_DEPLIBS) +dnl Check for use of wordexp... +AC_MSG_CHECKING(for use of wordexp) +AC_ARG_WITH(wordexp, + AS_HELP_STRING([--with-wordexp], + [Use wordexp when expanding configs (default = no)]), + [case "$withval" in + y|yes) wordexp=yes ;; + *) wordexp=no ;; + esac],) +if test "$wordexp" = "yes" ; then + AC_DEFINE(HAVE_WORDEXP, "1", [Enable use of wordexp]) + AC_MSG_RESULT(yes) + AC_CHECK_HEADER([wordexp.h],[], [AC_MSG_ERROR([Couldn't find wordexp.h])]) +else + AC_MSG_RESULT(no) +fi + dnl Check for headers -AC_CHECK_HEADERS([wordexp.h endian.h sys/endian.h sys/shm.h]) +AC_CHECK_HEADERS([endian.h sys/endian.h sys/shm.h]) dnl Check for resmgr support... AC_MSG_CHECKING(for resmgr support) diff --git a/src/userfile.c b/src/userfile.c index 72779da4..f2145470 100644 --- a/src/userfile.c +++ b/src/userfile.c @@ -21,6 +21,7 @@ #include #include #include +#include /** * \brief Get the full file name @@ -32,14 +33,13 @@ * stores the first matchine one. The returned string is strdup'ed. */ -#ifdef HAVE_WORDEXP_H +#ifdef HAVE_WORDEXP #include -#include int snd_user_file(const char *file, char **result) { wordexp_t we; int err; - + assert(file && result); err = wordexp(file, &we, WRDE_NOCMD); switch (err) { @@ -61,13 +61,62 @@ int snd_user_file(const char *file, char **result) return 0; } -#else /* !HAVE_WORDEXP_H */ -/* just copy the string - would be nicer to expand by ourselves, though... */ +#else /* !HAVE_WORDEX */ + +#include +#include +#include +#include +#include + int snd_user_file(const char *file, char **result) { - *result = strdup(file); - if (! *result) + int err; + size_t len; + char *buf = NULL; + + assert(file && result); + *result = NULL; + + /* expand ~/ if needed */ + if (file[0] == '~' && file[1] == '/') { + const char *home = getenv("HOME"); + if (home == NULL) { + struct passwd pwent, *p = NULL; + uid_t id = getuid(); + size_t bufsize = 1024; + + buf = malloc(bufsize); + if (buf == NULL) + goto out; + + while ((err = getpwuid_r(id, &pwent, buf, bufsize, &p)) == ERANGE) { + char *newbuf; + bufsize += 1024; + if (bufsize < 1024) + break; + newbuf = realloc(buf, bufsize); + if (newbuf == NULL) + goto out; + buf = newbuf; + } + home = err ? "" : pwent.pw_dir; + } + len = strlen(home) + strlen(&file[2]) + 2; + *result = malloc(len); + if (*result) + snprintf(*result, len, "%s/%s", home, &file[2]); + } else { + *result = strdup(file); + } + +out: + if (buf) + free(buf); + + if (*result == NULL) return -ENOMEM; return 0; } -#endif /* HAVE_WORDEXP_H */ + +#endif /* HAVE_WORDEXP */