From patchwork Thu May 5 17:44:20 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Christian_G=C3=B6ttsche?= X-Patchwork-Id: 12839841 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C64DDC433FE for ; Thu, 5 May 2022 17:44:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1382892AbiEERsa (ORCPT ); Thu, 5 May 2022 13:48:30 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40954 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1383036AbiEERsY (ORCPT ); Thu, 5 May 2022 13:48:24 -0400 Received: from mail-ed1-x534.google.com (mail-ed1-x534.google.com [IPv6:2a00:1450:4864:20::534]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9C7995DBFE for ; Thu, 5 May 2022 10:44:25 -0700 (PDT) Received: by mail-ed1-x534.google.com with SMTP id k27so6057911edk.4 for ; Thu, 05 May 2022 10:44:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlemail.com; s=20210112; h=from:to:subject:date:message-id:mime-version :content-transfer-encoding; bh=EPBieDaIeSqSyXTnXmssaaoiP34ed6CgKN0A2Uoz0B8=; b=XycFOQilXjBXC1tEoPpHUGZb1b77rClEUZ60r0k9XdKncHBTLZKrxhDHhBLWEy3S5s vBazeHVhTzKAX6J6JflgsxfkMfQT+EPki6MQFikdoUtbhPdM0cdpPzEpexGQWEVBRk6h UCb8ddXzx7/+neoSDhN87nCGilq3LSq6GiN0XnRwfFghvrGlpeh37DCJVm+XfMJc9y7D xSSUHSLzC4j8h4mFUXcWgzwAf+sUtAQGtYf6/a7E5D4KPxCP1xZtT+esn2tRyzQYheS0 qgad+zefSMlmcHsPzyHBR+QmOU3DYpmt1RTRpbuEhvxKsVMLL+8cMPDQg+4KBBY3qyaX cfIA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:subject:date:message-id:mime-version :content-transfer-encoding; bh=EPBieDaIeSqSyXTnXmssaaoiP34ed6CgKN0A2Uoz0B8=; b=mIFwHPw0jifsJlLKhgOBRzi/ww2pDfJXVerS9lhpnknas3jn3euW216Gv5keb5dB3+ 13neTlNvRaRo2bVuaQcYMrUD2sEKXm0rvbjyJxG6/UTEv6kgQjPQ3t3/Js+rn5UvqNoO wx0ABf+mS8rq5hbyfD5K0jMhDdC/Ywxvi7S4DD2MitS+BekfSvEdW0QJCaDSLeFW+0wv wFYW1DbiAH8LoNEAoA8O22KgQvgi2TdVmRhsMs4NmTFItYqDREgxXTomp5l1YfbMPzPO mqBqU6vYHIhOSCi9W9RFvH4xxUILWreFwBXpmOZIiRdOccNsqbxqUljI2j8mKGGTtNyz jn6A== X-Gm-Message-State: AOAM532AKkyh9Zb3OhfwLTxJO5oYGVbrT9GQwtXZBF+jsPmJjMJT5dS4 PdtAziKXxfdV74bgYWPUN5mXKUGV0dw= X-Google-Smtp-Source: ABdhPJxL+P6dYVlQKoSprYFkwGYzWQ5qj5ZQETswFmEovo1nTxVsghqEHrVb6zpJGjMpIUGKhtOHTA== X-Received: by 2002:a05:6402:1850:b0:425:f2e2:2594 with SMTP id v16-20020a056402185000b00425f2e22594mr31483024edy.3.1651772664189; Thu, 05 May 2022 10:44:24 -0700 (PDT) Received: from debianHome.localdomain (dynamic-077-001-152-226.77.1.pool.telefonica.de. [77.1.152.226]) by smtp.gmail.com with ESMTPSA id 13-20020a170906014d00b006f4c4330c49sm1027908ejh.57.2022.05.05.10.44.23 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 05 May 2022 10:44:23 -0700 (PDT) From: =?utf-8?q?Christian_G=C3=B6ttsche?= To: selinux@vger.kernel.org Subject: [RFC PATCH] libselinux: emulate O_PATH support in fgetfilecon/fsetfilecon Date: Thu, 5 May 2022 19:44:20 +0200 Message-Id: <20220505174420.24537-1-cgzones@googlemail.com> X-Mailer: git-send-email 2.36.0 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: selinux@vger.kernel.org Operating on a file descriptor avoids TOCTOU issues and one opened via O_PATH avoids the requirement of having read access to the file. Since Linux does not natively support file descriptors opened via O_PATH in fgetxattr(2) and at least glibc and musl does not emulate O_PATH support in their implementations, fgetfilecon(3) and fsetfilecon(3) also do not currently support file descriptors opened with O_PATH. Inspired by CVE-2013-4392: https://github.com/systemd/systemd/pull/8583 Implementation adapted from: https://android.googlesource.com/platform/bionic/+/2825f10b7f61558c264231a536cf3affc0d84204%5E%21/ Signed-off-by: Christian Göttsche Acked-by: James Carter --- libselinux/man/man3/getfilecon.3 | 4 +++- libselinux/man/man3/setfilecon.3 | 4 +++- libselinux/src/fgetfilecon.c | 28 +++++++++++++++++++++++++--- libselinux/src/fsetfilecon.c | 23 ++++++++++++++++++++++- 4 files changed, 53 insertions(+), 6 deletions(-) diff --git a/libselinux/man/man3/getfilecon.3 b/libselinux/man/man3/getfilecon.3 index 5bb575b5..c3e92ba1 100644 --- a/libselinux/man/man3/getfilecon.3 +++ b/libselinux/man/man3/getfilecon.3 @@ -33,7 +33,9 @@ is identical to .BR getfilecon (), only the open file pointed to by filedes (as returned by .BR open (2)) -is interrogated in place of path. +is interrogated in place of path. Since libselinux 3.4 a file opened via +.I O_PATH +is supported. .BR getfilecon_raw (), .BR lgetfilecon_raw () diff --git a/libselinux/man/man3/setfilecon.3 b/libselinux/man/man3/setfilecon.3 index 0e9a383f..61f9a806 100644 --- a/libselinux/man/man3/setfilecon.3 +++ b/libselinux/man/man3/setfilecon.3 @@ -29,7 +29,9 @@ link itself has it's context set, not the file that it refers to. is identical to setfilecon, only the open file pointed to by filedes (as returned by .BR open (2)) -has it's context set in place of path. +has it's context set in place of path. Since libselinux 3.4 a file opened via +.I O_PATH +is supported. .BR setfilecon_raw (), .BR lsetfilecon_raw (), diff --git a/libselinux/src/fgetfilecon.c b/libselinux/src/fgetfilecon.c index 8c748f8a..baf38ec1 100644 --- a/libselinux/src/fgetfilecon.c +++ b/libselinux/src/fgetfilecon.c @@ -3,10 +3,32 @@ #include #include #include +#include #include #include "selinux_internal.h" #include "policy.h" +static ssize_t fgetxattr_wrapper(int fd, const char *name, void *value, size_t size) { + char buf[40]; + int fd_flag, saved_errno = errno; + ssize_t ret; + + ret = fgetxattr(fd, name, value, size); + if (ret != -1 || errno != EBADF) + return ret; + + /* Emulate O_PATH support */ + fd_flag = fcntl(fd, F_GETFL); + if (fd_flag == -1 || (fd_flag & O_PATH) == 0) { + errno = EBADF; + return -1; + } + + snprintf(buf, sizeof(buf), "/proc/self/fd/%d", fd); + errno = saved_errno; + return getxattr(buf, name, value, size); +} + int fgetfilecon_raw(int fd, char ** context) { char *buf; @@ -19,11 +41,11 @@ int fgetfilecon_raw(int fd, char ** context) return -1; memset(buf, 0, size); - ret = fgetxattr(fd, XATTR_NAME_SELINUX, buf, size - 1); + ret = fgetxattr_wrapper(fd, XATTR_NAME_SELINUX, buf, size - 1); if (ret < 0 && errno == ERANGE) { char *newbuf; - size = fgetxattr(fd, XATTR_NAME_SELINUX, NULL, 0); + size = fgetxattr_wrapper(fd, XATTR_NAME_SELINUX, NULL, 0); if (size < 0) goto out; @@ -34,7 +56,7 @@ int fgetfilecon_raw(int fd, char ** context) buf = newbuf; memset(buf, 0, size); - ret = fgetxattr(fd, XATTR_NAME_SELINUX, buf, size - 1); + ret = fgetxattr_wrapper(fd, XATTR_NAME_SELINUX, buf, size - 1); } out: if (ret == 0) { diff --git a/libselinux/src/fsetfilecon.c b/libselinux/src/fsetfilecon.c index 5cf34e3f..be821c7a 100644 --- a/libselinux/src/fsetfilecon.c +++ b/libselinux/src/fsetfilecon.c @@ -3,13 +3,34 @@ #include #include #include +#include #include #include "selinux_internal.h" #include "policy.h" +static int fsetxattr_wrapper(int fd, const char* name, const void* value, size_t size, int flags) { + char buf[40]; + int rc, fd_flag, saved_errno = errno; + + rc = fsetxattr(fd, name, value, size, flags); + if (rc == 0 || errno != EBADF) + return rc; + + /* Emulate O_PATH support */ + fd_flag = fcntl(fd, F_GETFL); + if (fd_flag == -1 || (fd_flag & O_PATH) == 0) { + errno = EBADF; + return -1; + } + + snprintf(buf, sizeof(buf), "/proc/self/fd/%d", fd); + errno = saved_errno; + return setxattr(buf, name, value, size, flags); +} + int fsetfilecon_raw(int fd, const char * context) { - int rc = fsetxattr(fd, XATTR_NAME_SELINUX, context, strlen(context) + 1, + int rc = fsetxattr_wrapper(fd, XATTR_NAME_SELINUX, context, strlen(context) + 1, 0); if (rc < 0 && errno == ENOTSUP) { char * ccontext = NULL; From patchwork Wed May 11 18:42:23 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Christian_G=C3=B6ttsche?= X-Patchwork-Id: 12846544 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E5495C433EF for ; Wed, 11 May 2022 18:42:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1346446AbiEKSmg (ORCPT ); Wed, 11 May 2022 14:42:36 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37344 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S243972AbiEKSmf (ORCPT ); Wed, 11 May 2022 14:42:35 -0400 Received: from mail-ej1-x62d.google.com (mail-ej1-x62d.google.com [IPv6:2a00:1450:4864:20::62d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 771EE61293 for ; Wed, 11 May 2022 11:42:34 -0700 (PDT) Received: by mail-ej1-x62d.google.com with SMTP id i19so5767434eja.11 for ; Wed, 11 May 2022 11:42:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlemail.com; s=20210112; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=oLv41upLn9lzvRODLU8/ka+NpA5IOCMt58nX/x+6gbQ=; b=b4FY6k8bdA/B00Ht7e9zoTNVJ1sS+VzZZDLoIvlkBSgplaY/lTBWelK8zmu5TuvK1T Ag90+HnzaQpYtYDpOogsE/k0vuihcEI9/H9wSq09WaDzhvyDWEPai2Hle8zsFpidN8r1 CorA7D6UEbYPUWsT408yri+Uy96oryivASi3W54KoK1t+T/oMKzYPtFgTEk8S8FIMxsd e4ylQ7kKLaj1Hsu1lmk5OnU0LxS1ZQbf2IXJFgTZu9a1aVucPtesXjjgn/PwrOyaJlrU bT6mUOlnZdU6o/KhvnBd++2/tXfArCjUep4y3uJ0i6wrywrmUCFda8b18a95K4YH49Kw J7Fw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=oLv41upLn9lzvRODLU8/ka+NpA5IOCMt58nX/x+6gbQ=; b=nX3MTsIeoQ7I04JhN/9126jTjYHg7ONjpkmGMWE3FJGnXv3t6I1A4WEhzkjVXde/7+ bv+kTdJLraHBPZjhIjXC2CYhVjsPrJ/f17xDsN0whFzV6SnDHilri6qfQI0zRrxM1aOz 5f2EaZ+VbgCWYceSvmD+4DDPkTtFKKt1rsc+UwIo5XXJwl6eQYPcl4O8Ul2058WC9SH3 ex0HYmyJHZtUeKC07VT6wzcG86l0W1BirJ1hWKXVIoyuMbMDioAnCIeKV5zPMfl3pVI2 8FKG8i6Wpqj291Sfhb6y/slTkH1QMoZnwzRZ+GeCQLLA812HhQAS1jlVGcUFAY3gb6zg GGzg== X-Gm-Message-State: AOAM5327DSHZzk/5vFrhpcmp7ZZEq0Lcbx4h1FQ+rYSd7rkXCNGyGAHJ VkV2Cjo1JkPEed3Vb9J3Dhy6HuT/WPI= X-Google-Smtp-Source: ABdhPJyTbetJ9qqWIxzYqEPMzd0AgQ2YkNauFmTecQth958yqyx9au7RQdlEQMtrcwJyIqeGgK/T5w== X-Received: by 2002:a17:907:3da4:b0:6f4:ff2b:8299 with SMTP id he36-20020a1709073da400b006f4ff2b8299mr27482300ejc.109.1652294552962; Wed, 11 May 2022 11:42:32 -0700 (PDT) Received: from debianHome.localdomain (dynamic-095-112-140-049.95.112.pool.telefonica.de. [95.112.140.49]) by smtp.gmail.com with ESMTPSA id y25-20020aa7ca19000000b0042617ba639dsm1535788eds.39.2022.05.11.11.42.32 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 11 May 2022 11:42:32 -0700 (PDT) From: =?utf-8?q?Christian_G=C3=B6ttsche?= To: selinux@vger.kernel.org Subject: [RFC PATCH 2/4] libselinux: restorecon: misc tweaks Date: Wed, 11 May 2022 20:42:23 +0200 Message-Id: <20220511184225.218062-1-cgzones@googlemail.com> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220505174420.24537-1-cgzones@googlemail.com> References: <20220505174420.24537-1-cgzones@googlemail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: selinux@vger.kernel.org * mark read-only parameters const * check for overflow when adding exclude directory * use 64 bit integer for file counting * avoid implicit conversions Signed-off-by: Christian Göttsche Acked-by: James Carter --- libselinux/src/selinux_restorecon.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/libselinux/src/selinux_restorecon.c b/libselinux/src/selinux_restorecon.c index e6192912..c158ead8 100644 --- a/libselinux/src/selinux_restorecon.c +++ b/libselinux/src/selinux_restorecon.c @@ -44,7 +44,7 @@ static struct selabel_handle *fc_sehandle = NULL; static bool selabel_no_digest; static char *rootpath = NULL; -static int rootpathlen; +static size_t rootpathlen; /* Information on excluded fs and directories. */ struct edir { @@ -55,7 +55,7 @@ struct edir { }; #define CALLER_EXCLUDED true static bool ignore_mounts; -static int exclude_non_seclabel_mounts(void); +static uint64_t exclude_non_seclabel_mounts(void); static int exclude_count = 0; static struct edir *exclude_lst = NULL; static uint64_t fc_count = 0; /* Number of files processed so far */ @@ -169,6 +169,12 @@ static int add_exclude(const char *directory, bool who) return -1; } + if (exclude_count >= INT_MAX - 1) { + selinux_log(SELINUX_ERROR, "Too many directory excludes: %d.\n", exclude_count); + errno = EOVERFLOW; + return -1; + } + tmp_list = realloc(exclude_lst, sizeof(struct edir) * (exclude_count + 1)); if (!tmp_list) @@ -211,10 +217,10 @@ static int check_excluded(const char *file) return 0; } -static int file_system_count(char *name) +static uint64_t file_system_count(const char *name) { struct statvfs statvfs_buf; - int nfile = 0; + uint64_t nfile = 0; memset(&statvfs_buf, 0, sizeof(statvfs_buf)); if (!statvfs(name, &statvfs_buf)) @@ -230,12 +236,13 @@ static int file_system_count(char *name) * that support security labels have the seclabel option, return * approximate total file count. */ -static int exclude_non_seclabel_mounts(void) +static uint64_t exclude_non_seclabel_mounts(void) { struct utsname uts; FILE *fp; size_t len; - int index = 0, found = 0, nfile = 0; + int index = 0, found = 0; + uint64_t nfile = 0; char *mount_info[4]; char *buf = NULL, *item; @@ -300,7 +307,8 @@ static int add_xattr_entry(const char *directory, bool delete_nonmatch, { char *sha1_buf = NULL; size_t i, digest_len = 0; - int rc, digest_result; + int rc; + enum digest_result digest_result; bool match; struct dir_xattr *new_entry; uint8_t *xattr_digest = NULL; @@ -573,7 +581,7 @@ static void filespec_destroy(void) * Called if SELINUX_RESTORECON_SET_SPECFILE_CTX is not set to check if * the type components differ, updating newtypecon if so. */ -static int compare_types(char *curcon, char *newcon, char **newtypecon) +static int compare_types(const char *curcon, const char *newcon, char **newtypecon) { int types_differ = 0; context_t cona; @@ -1398,7 +1406,7 @@ void selinux_restorecon_set_exclude_list(const char **exclude_list) /* selinux_restorecon_set_alt_rootpath(3) sets an alternate rootpath. */ int selinux_restorecon_set_alt_rootpath(const char *alt_rootpath) { - int len; + size_t len; /* This should be NULL on first use */ if (rootpath) From patchwork Wed May 11 18:42:24 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Christian_G=C3=B6ttsche?= X-Patchwork-Id: 12846545 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 98EBBC433F5 for ; Wed, 11 May 2022 18:42:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243972AbiEKSmh (ORCPT ); Wed, 11 May 2022 14:42:37 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37386 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1346306AbiEKSmg (ORCPT ); Wed, 11 May 2022 14:42:36 -0400 Received: from mail-ej1-x62b.google.com (mail-ej1-x62b.google.com [IPv6:2a00:1450:4864:20::62b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1A82E61610 for ; Wed, 11 May 2022 11:42:35 -0700 (PDT) Received: by mail-ej1-x62b.google.com with SMTP id kq17so5830929ejb.4 for ; Wed, 11 May 2022 11:42:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlemail.com; s=20210112; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=axs+U/EnzeJxnHAR3Qi80oI1rvQT9yMbtS5LcaW3670=; b=AxANPBGUq8IxUiKjE4MgnIIgZWJ6dVKyCD1BxlAP7I/OIIVSkn9/UBiZiopuuXm8jE OUpKkmFxxaL89hL7kAjsAHGOB3da9Xcyzj0sP2vDzKxjN4P8tm8ONNNyFtRrFxm4ytPl +QG2Wg0UiZKDPPf2lzER+Yi61k0NyapEJE31fyDrqcNMB6e0JLIajHO0S4QruTnYOy7o vCn5TmxaNorgTXh2l0e8BhIFf5k7+1HeasOjwRyEb5SvftmvyZXdv5spuQ+XEK4z5g7E bgSrchrYE6xjASEXcFQtkO/rrD0Yvc2yqcXB3o+QZaBzWqHAHrJ0O2fgoEAXwUims+o3 ar4g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=axs+U/EnzeJxnHAR3Qi80oI1rvQT9yMbtS5LcaW3670=; b=10rZHRXoF2ES6cQy6R3m3Gw6qkMgi8EHPZhwgCjxyvYjXjrSJbTWTeLWgHwXQP1Sb3 VWO1ftVfCa9cltxTdcPPZsrTcV3TAlN/2wfIaziAZ5ZtmkqjPv6ziof77NuybVz97ox4 4xuvPvBrC/HBDlbnZ1yvtad0GpHRjyYR8VJjohWMbzufWWg1mG2ziz/fxCF2qZySFXJm rihqKJN4ruQp1EPUWt5EQZmTGIlFuLJu2PPtlgk8he9vaeIwkuD8KuJqER2bs2HW9Jil SG9O52EwV6NRs959KPtCsreZMKKueQ4CmBW8vRL6Az4MwkP7CU180tw+qzoOf/aVfyDa skJg== X-Gm-Message-State: AOAM532838+Sb/E87Nl92wwzFHfxwiRWEYxXOifE/GksHGWgEDdapU/a YUX4QS0UmVrm91Piq1nw1cNMTO9cJZo= X-Google-Smtp-Source: ABdhPJwZSKEoj1CLktsli31KgJlESegDeDZ9z0Wj6LXP3fubLc7rip7OAdsj4D05QMHlAVvvs1EzjA== X-Received: by 2002:a17:907:969f:b0:6f3:dede:f2d2 with SMTP id hd31-20020a170907969f00b006f3dedef2d2mr25223632ejc.511.1652294553635; Wed, 11 May 2022 11:42:33 -0700 (PDT) Received: from debianHome.localdomain (dynamic-095-112-140-049.95.112.pool.telefonica.de. [95.112.140.49]) by smtp.gmail.com with ESMTPSA id y25-20020aa7ca19000000b0042617ba639dsm1535788eds.39.2022.05.11.11.42.33 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 11 May 2022 11:42:33 -0700 (PDT) From: =?utf-8?q?Christian_G=C3=B6ttsche?= To: selinux@vger.kernel.org Subject: [RFC PATCH 3/4] libselinux: restorecon: forward error if not ENOENT Date: Wed, 11 May 2022 20:42:24 +0200 Message-Id: <20220511184225.218062-2-cgzones@googlemail.com> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220511184225.218062-1-cgzones@googlemail.com> References: <20220505174420.24537-1-cgzones@googlemail.com> <20220511184225.218062-1-cgzones@googlemail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: selinux@vger.kernel.org selabel_lookup_raw(3) can fail for other reasons than no corresponding context found, e.g. ENOMEM or EINVAL for invalid key or type. Signed-off-by: Christian Göttsche Acked-by: James Carter --- libselinux/src/selinux_restorecon.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/libselinux/src/selinux_restorecon.c b/libselinux/src/selinux_restorecon.c index c158ead8..42ef30cb 100644 --- a/libselinux/src/selinux_restorecon.c +++ b/libselinux/src/selinux_restorecon.c @@ -651,12 +651,16 @@ static int restorecon_sb(const char *pathname, const struct stat *sb, sb->st_mode); if (rc < 0) { - if (errno == ENOENT && flags->warnonnomatch && first) - selinux_log(SELINUX_INFO, - "Warning no default label for %s\n", - lookup_path); + if (errno == ENOENT) { + if (flags->warnonnomatch && first) + selinux_log(SELINUX_INFO, + "Warning no default label for %s\n", + lookup_path); - return 0; /* no match, but not an error */ + return 0; /* no match, but not an error */ + } + + return -1; } if (flags->progress) { From patchwork Wed May 11 18:42:25 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Christian_G=C3=B6ttsche?= X-Patchwork-Id: 12846546 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id BE813C433F5 for ; Wed, 11 May 2022 18:42:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1346449AbiEKSmi (ORCPT ); Wed, 11 May 2022 14:42:38 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:37500 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1346306AbiEKSmh (ORCPT ); Wed, 11 May 2022 14:42:37 -0400 Received: from mail-ed1-x52c.google.com (mail-ed1-x52c.google.com [IPv6:2a00:1450:4864:20::52c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3FDE062109 for ; Wed, 11 May 2022 11:42:36 -0700 (PDT) Received: by mail-ed1-x52c.google.com with SMTP id y21so3629801edo.2 for ; Wed, 11 May 2022 11:42:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlemail.com; s=20210112; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=OYnGhqBkWK3YCzBC1rPyCC1CVX/TAKhA2r8wx1STzSk=; b=fUe6a4s4CMAq//ZbF72RiD1xa61g7A6cHDIooM5JSEdpA4OWvfxPlfhRuOWcwRnTvm TljycibZ6CMfQ5XMXoWtjSmQcmNz4xL/m5fLbLUep1ZqjXghnnPx1FONoa5p6MPmqLzO 2gsJlsa0+j/uYPQLs4nWZBZmpUJ9CZgGeKvhkpxrryPYtTVG2TVk/YvdAB6CjOHAMQZK QHvkhKdrJCxunoSTkujOsD7YEUIOaMWmADYbYLyhCFUZuE2//r7Fu8627aAkhoUTmzWr k7+f2OzqIt97X0RPReKWjs90MOPFcJvRENbV1KysBVaNOc2TZyBtrnpwq8pBqJoPOGYv Eiiw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=OYnGhqBkWK3YCzBC1rPyCC1CVX/TAKhA2r8wx1STzSk=; b=t0cSlgN/n5r/VlW3JU295uNIpSFucPtxsE6xw0C3Tv59ZI7UR6UctnfVic3ZgNrU/W 8PjBVbvECwOyRQO5pLFzms09J4MrFRuSYLOSnuiiavQrnyFD+NloJfKqHE+gn0jy0p9F VkttaieVnESeYsw3iWb+vxrPf9PAaJiwzFeQsfms6fx2HMyHNcTH1uCXN3Yfo/WudNL6 zGRhW3fxUZW0ILh2Y255lR1sg940x/3L4yRgitfxwFL+hluNS8hgxQV21X+RKnQDDNfh q+41/B32I1k8EhAZ8NXGgg5Ct7Zixv7X1smPH/4hw7FLfj2cF9275zESpfqL5dlJMTrB JftA== X-Gm-Message-State: AOAM531SXeGB7Xj9p5te89Ars1WruAoCmgT5OYuOPwfFXO5O6ScAcbT+ O4G8dIe0yv2l660hI7wR5EEGKz8TEz8= X-Google-Smtp-Source: ABdhPJyaBDv+qvCqEaZLj+pLOw9RFWtzIIhJ3AuV2jY+us3LNNj8XGmLaunY8YcSHSXvSnFVJ2o6fA== X-Received: by 2002:a05:6402:e99:b0:41d:11f2:85e0 with SMTP id h25-20020a0564020e9900b0041d11f285e0mr30222477eda.339.1652294554728; Wed, 11 May 2022 11:42:34 -0700 (PDT) Received: from debianHome.localdomain (dynamic-095-112-140-049.95.112.pool.telefonica.de. [95.112.140.49]) by smtp.gmail.com with ESMTPSA id y25-20020aa7ca19000000b0042617ba639dsm1535788eds.39.2022.05.11.11.42.33 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 11 May 2022 11:42:33 -0700 (PDT) From: =?utf-8?q?Christian_G=C3=B6ttsche?= To: selinux@vger.kernel.org Subject: [RFC PATCH 4/4] libselinux: restorecon: pin file to avoid TOCTOU issues Date: Wed, 11 May 2022 20:42:25 +0200 Message-Id: <20220511184225.218062-3-cgzones@googlemail.com> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220511184225.218062-1-cgzones@googlemail.com> References: <20220505174420.24537-1-cgzones@googlemail.com> <20220511184225.218062-1-cgzones@googlemail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: selinux@vger.kernel.org Pin the file to operate on in restorecon_sb() to prevent symlink attacks in between the label database lookup, the current context query and the final context write. Also don't use the file information from fts_read(3), which might also be out of sync. Due to querying file information twice, one in fts_read(3) needed for the cross device check and one on the pinned file descriptor for the database lookup, there is a slight slowdown: [current] Time (mean ± σ): 14.456 s ± 0.306 s [User: 45.863 s, System: 4.463 s] Range (min … max): 14.275 s … 15.294 s 10 runs [changed] Time (mean ± σ): 15.843 s ± 0.045 s [User: 46.274 s, System: 9.495 s] Range (min … max): 15.787 s … 15.916 s 10 runs Signed-off-by: Christian Göttsche Acked-by: James Carter --- libselinux/src/selinux_restorecon.c | 43 +++++++++++++++++------------ 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/libselinux/src/selinux_restorecon.c b/libselinux/src/selinux_restorecon.c index 42ef30cb..12b85101 100644 --- a/libselinux/src/selinux_restorecon.c +++ b/libselinux/src/selinux_restorecon.c @@ -621,13 +621,13 @@ out: return rc; } -static int restorecon_sb(const char *pathname, const struct stat *sb, - struct rest_flags *flags, bool first) +static int restorecon_sb(const char *pathname, struct rest_flags *flags, bool first) { char *newcon = NULL; char *curcon = NULL; char *newtypecon = NULL; - int rc; + int fd = -1, rc; + struct stat stat_buf; bool updated = false; const char *lookup_path = pathname; float pc; @@ -642,13 +642,21 @@ static int restorecon_sb(const char *pathname, const struct stat *sb, lookup_path += rootpathlen; } + fd = open(pathname, O_PATH | O_NOFOLLOW | O_EXCL); + if (fd < 0) + goto err; + + rc = fstat(fd, &stat_buf); + if (rc < 0) + goto err; + if (rootpath != NULL && lookup_path[0] == '\0') /* this is actually the root dir of the alt root. */ rc = selabel_lookup_raw(fc_sehandle, &newcon, "/", - sb->st_mode); + stat_buf.st_mode); else rc = selabel_lookup_raw(fc_sehandle, &newcon, lookup_path, - sb->st_mode); + stat_buf.st_mode); if (rc < 0) { if (errno == ENOENT) { @@ -657,10 +665,10 @@ static int restorecon_sb(const char *pathname, const struct stat *sb, "Warning no default label for %s\n", lookup_path); - return 0; /* no match, but not an error */ + goto out; /* no match, but not an error */ } - return -1; + goto err; } if (flags->progress) { @@ -680,19 +688,17 @@ static int restorecon_sb(const char *pathname, const struct stat *sb, } if (flags->add_assoc) { - rc = filespec_add(sb->st_ino, newcon, pathname, flags); + rc = filespec_add(stat_buf.st_ino, newcon, pathname, flags); if (rc < 0) { selinux_log(SELINUX_ERROR, "filespec_add error: %s\n", pathname); - freecon(newcon); - return -1; + goto out1; } if (rc > 0) { /* Already an association and it took precedence. */ - freecon(newcon); - return 0; + goto out; } } @@ -700,7 +706,7 @@ static int restorecon_sb(const char *pathname, const struct stat *sb, selinux_log(SELINUX_INFO, "%s matched by %s\n", pathname, newcon); - if (lgetfilecon_raw(pathname, &curcon) < 0) { + if (fgetfilecon_raw(fd, &curcon) < 0) { if (errno != ENODATA) goto err; @@ -733,7 +739,7 @@ static int restorecon_sb(const char *pathname, const struct stat *sb, } if (!flags->nochange) { - if (lsetfilecon(pathname, newcon) < 0) + if (fsetfilecon(fd, newcon) < 0) goto err; updated = true; } @@ -758,6 +764,8 @@ static int restorecon_sb(const char *pathname, const struct stat *sb, out: rc = 0; out1: + if (fd >= 0) + close(fd); freecon(curcon); freecon(newcon); return rc; @@ -855,7 +863,6 @@ static void *selinux_restorecon_thread(void *arg) FTSENT *ftsent; int error; char ent_path[PATH_MAX]; - struct stat ent_st; bool first = false; if (state->parallel) @@ -953,11 +960,11 @@ loop_body: /* fall through */ default: strcpy(ent_path, ftsent->fts_path); - ent_st = *ftsent->fts_statp; + if (state->parallel) pthread_mutex_unlock(&state->mutex); - error = restorecon_sb(ent_path, &ent_st, &state->flags, + error = restorecon_sb(ent_path, &state->flags, first); if (state->parallel) { @@ -1153,7 +1160,7 @@ static int selinux_restorecon_common(const char *pathname_orig, goto cleanup; } - error = restorecon_sb(pathname, &sb, &state.flags, true); + error = restorecon_sb(pathname, &state.flags, true); goto cleanup; }