From patchwork Mon Oct 5 12:16:45 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff King X-Patchwork-Id: 11816549 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 95265618 for ; Mon, 5 Oct 2020 12:16:48 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 84A0520774 for ; Mon, 5 Oct 2020 12:16:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726680AbgJEMQr (ORCPT ); Mon, 5 Oct 2020 08:16:47 -0400 Received: from cloud.peff.net ([104.130.231.41]:49598 "EHLO cloud.peff.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726000AbgJEMQr (ORCPT ); Mon, 5 Oct 2020 08:16:47 -0400 Received: (qmail 32267 invoked by uid 109); 5 Oct 2020 12:16:46 -0000 Received: from Unknown (HELO peff.net) (10.0.1.2) by cloud.peff.net (qpsmtpd/0.94) with ESMTP; Mon, 05 Oct 2020 12:16:46 +0000 Authentication-Results: cloud.peff.net; auth=none Received: (qmail 19057 invoked by uid 111); 5 Oct 2020 12:16:45 -0000 Received: from coredump.intra.peff.net (HELO sigill.intra.peff.net) (10.0.0.2) by peff.net (qpsmtpd/0.94) with (TLS_AES_256_GCM_SHA384 encrypted) ESMTPS; Mon, 05 Oct 2020 08:16:45 -0400 Authentication-Results: peff.net; auth=none Date: Mon, 5 Oct 2020 08:16:45 -0400 From: Jeff King To: git@vger.kernel.org Cc: Jonathan Nieder Subject: [PATCH v2 7/8] verify_path(): disallow symlinks in .gitattributes and .gitignore Message-ID: <20201005121645.GG2907394@coredump.intra.peff.net> References: <20201005121609.GA2907272@coredump.intra.peff.net> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20201005121609.GA2907272@coredump.intra.peff.net> Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org In commit 10ecfa7649 (verify_path: disallow symlinks in .gitmodules, 2018-05-04) we made it impossible to load a .gitmodules file that's a symlink into the index. The security reasons for doing so are described there. We also discussed forbidding symlinks of other .git files as part of that fix, but the tradeoff was less compelling: 1. Unlike .gitmodules, the other files don't have content-level fsck checks. So an attacker using symlinks to evade those checks isn't a problem. 2. Unlike .gitmodules, Git will never write .gitignore or .gitattributes itself, making it much less likely to use them to write outside the repo. They could be used for out-of-repo reads, however. 3. The .gitmodules change was part of a critical bug-fix that was not publicly disclosed until it was released. Changing the other files was not needed for the minimal fix. However, it's still a reasonable idea to forbid symlinks for these files: - As noted, they can still be used to read out-of-repo files (which is fairly restricted, but in some circumstances you can probe file content by speculatively creating files and seeing if they get ignored) - They don't currently behave well in all cases. We sometimes read these files from the index, where we _don't_ follow symlinks (we'd just treat the symlink target as the .gitignore or .gitattributes content, which is actively wrong). This patch forbids symlinked versions of these files from entering the index. We already have helpers for obscured forms of the names from e7cb0b4455 (is_ntfs_dotgit: match other .git files, 2018-05-11) and 0fc333ba20 (is_hfs_dotgit: match other .git files, 2018-05-02), which were done as part of the series touching .gitmodules. No tests yet, as we'll add them in a subsequent patch once we have fsck support, too. Signed-off-by: Jeff King --- read-cache.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/read-cache.c b/read-cache.c index ecf6f68994..63aec6c35d 100644 --- a/read-cache.c +++ b/read-cache.c @@ -947,7 +947,9 @@ static int verify_dotfile(const char *rest, unsigned mode) return 0; if (S_ISLNK(mode)) { rest += 3; - if (skip_iprefix(rest, "modules", &rest) && + if ((skip_iprefix(rest, "modules", &rest) || + skip_iprefix(rest, "ignore", &rest) || + skip_iprefix(rest, "attributes", &rest)) && (*rest == '\0' || is_dir_sep(*rest))) return 0; } @@ -980,7 +982,9 @@ int verify_path(const char *path, unsigned mode) if (is_hfs_dotgit(path)) return 0; if (S_ISLNK(mode)) { - if (is_hfs_dotgitmodules(path)) + if (is_hfs_dotgitmodules(path) || + is_hfs_dotgitignore(path) || + is_hfs_dotgitattributes(path)) return 0; } } @@ -992,7 +996,9 @@ int verify_path(const char *path, unsigned mode) if (is_ntfs_dotgit(path)) return 0; if (S_ISLNK(mode)) { - if (is_ntfs_dotgitmodules(path)) + if (is_ntfs_dotgitmodules(path) || + is_ntfs_dotgitignore(path) || + is_ntfs_dotgitattributes(path)) return 0; } }