From patchwork Fri Mar 10 11:25:52 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Giuseppe Scrivano X-Patchwork-Id: 67366 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:5915:0:0:0:0:0 with SMTP id v21csp814162wrd; Fri, 10 Mar 2023 03:28:10 -0800 (PST) X-Google-Smtp-Source: AK7set9eTgMjeBaOqUDVGEgfjOtE00ngZAqjOjss5JR0Zn7QGkPo8cvieQ8BJExjM1eV/+V5yT4J X-Received: by 2002:a17:902:e5c9:b0:19b:c498:fd01 with SMTP id u9-20020a170902e5c900b0019bc498fd01mr1963520plf.11.1678447689763; Fri, 10 Mar 2023 03:28:09 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1678447689; cv=none; d=google.com; s=arc-20160816; b=SYm6Y1lXAUFVA/K6ViwyI/hbCoHASb2ReoftAMsNBsxQTUxUSw3QAQpSE8W7pijA/u 1ZDBP4uewPVBJK8XJY6ooLPfPiagBo8dQF7BQYRKbc0se7YOuRmC7H6U1rJCGU6sauxZ qk62XHQqbGoKlqnXkBwPhgsfx5esoL05udAEQ/ZhDRvtKMXrGB7ryFvL1osMkW00lWzc dBzEvypGpPNvIWYzbnaJv/Wwp+drBrHT6mThac74Q9W8aHl5447wsfs/Yq6OUiW8tSYO x3DzmkBvumMwhkl88i/UcJ8n8MmZUqVUjqD2+uALXbPaQsT8gaCsRSPS4+u5Ot7Y2F8g AvdA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :message-id:date:subject:cc:to:from:dkim-signature; bh=QuePB9CGeUn2nwUN/prBkWMxpBRB1OgcU+YzFHJpYE4=; b=bCgeZPgeyHTgUYJBxMRqO2n4xVFFbcXLbs6JiyiPc95OnzOv5TqNUeCyCTVUEy+yGg NN+KgtOzmIfh0cLwUkupnXk5BC0NBtMTEX6NL6GIoYag8WUUPd/maXwgnyMH3NjcVF3U c+56jFoQCA4YgrqC05hJJVghg5ldj+QLfHt+3iDQerPzDfS+AJVR91kgG7bkBK/AsOYd uai+WRocERXMd2VirtMmuFfJ1YFxPTCmIx1Srqj8ZO+8Hbs71DVaj+UCXFKFQ8k7We9c GSdq1Ut/f9dF3ZxMvQdc70FAPNXdWCtXpZCwlQq4HV6xLuHNXOqJetqORtD6C7spL3Ju rVuw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=UUuCreZD; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id z10-20020a170902834a00b0019a86f2e34esi1902448pln.381.2023.03.10.03.27.54; Fri, 10 Mar 2023 03:28:09 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=UUuCreZD; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230419AbjCJL1J (ORCPT + 99 others); Fri, 10 Mar 2023 06:27:09 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42052 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230488AbjCJL0z (ORCPT ); Fri, 10 Mar 2023 06:26:55 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EDC5AC9A4A for ; Fri, 10 Mar 2023 03:26:13 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1678447573; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding; bh=QuePB9CGeUn2nwUN/prBkWMxpBRB1OgcU+YzFHJpYE4=; b=UUuCreZDsFLiOF0QhuM4DyjtDiotOWVzJzMzMuEWG/MW9vJcvpjpgLBaSP9MZO18c2TAlN OUZpIeyEOE6rmgEV8E2AgeJQdhHLArZqbwq1fOf/Ex25xbbONhJkHOjgonSYqvNNaDw9a6 ip8uA/lgL2jBewlvczK89D03/XweowA= Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-589-nepR23YANCmHj3P5bxfTEA-1; Fri, 10 Mar 2023 06:26:10 -0500 X-MC-Unique: nepR23YANCmHj3P5bxfTEA-1 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.rdu2.redhat.com [10.11.54.8]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 7C02B1C2C4E2; Fri, 10 Mar 2023 11:26:09 +0000 (UTC) Received: from carbon.redhat.com (unknown [10.39.194.146]) by smtp.corp.redhat.com (Postfix) with ESMTP id 7E64CC15BAD; Fri, 10 Mar 2023 11:26:05 +0000 (UTC) From: Giuseppe Scrivano To: linux-kernel@vger.kernel.org Cc: keescook@chromium.org, bristot@redhat.com, ebiederm@xmission.com, brauner@kernel.org, cyphar@cyphar.com, viro@zeniv.linux.org.uk, walters@verbum.org, avagin@gmail.com, alexl@redhat.com, peterz@infradead.org, bmasney@redhat.com, gscrivan@redhat.com Subject: [PATCH v4 1/3] exec: add PR_HIDE_SELF_EXE prctl Date: Fri, 10 Mar 2023 12:25:52 +0100 Message-Id: <20230310112554.1261731-1-gscrivan@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.8 X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_NONE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1759979965206402370?= X-GMAIL-MSGID: =?utf-8?q?1759979965206402370?= This patch adds a new prctl called PR_HIDE_SELF_EXE which allows processes to hide their own /proc/self/exe file. When this prctl is used, every access to /proc/self/exe for the calling process will fail with EPERM. This is useful for preventing issues like CVE-2019-5736, where an attacker can gain host root access by overwriting the binary in OCI runtimes through file-descriptor mishandling in containers. The current fix for CVE-2019-5736 is to create a read-only copy or a bind-mount of the current executable, and then re-exec the current process. With the new prctl, the read-only copy or bind-mount copy is not needed anymore. Once prctl(PR_HIDE_SELF_EXE) is set, it will blocks PR_SET_DUMPABLE to be set again. It is not done automatically so that PR_SET_DUMPABLE can be set at a later time if needed, e.g. a container runtime might want to do that after the user namespace is joined. It is currently kind of expected that a container uses execve to pass control to a binary in the container chroot, since the /proc/self/exe and /proc/self/map_files refer to files that are not part of the container itself; so if the process can be compromised in any way (e.g. an interpreter running a script in the container without calling execve), it could potentially lead to host compromise. It is necessary to ensure that the current process cannot be set to dumpable anymore, since that would allow another process in the container to get access to its proc files. A container runtime could use the new prctl in the following way: - run prctl(PR_HIDE_SELF_EXE) as soon as possible. - if prctl(PR_HIDE_SELF_EXE) fails then use the more expensive current fallbacks mechanism. - perform all operations that require the process to be dumpable. - prctl(PR_SET_DUMPABLE, 0), as it is already done today. - execve the new binary or run directly the interpreter. Signed-off-by: Giuseppe Scrivano --- v3: https://lkml.org/lkml/2023/1/20/434 Differences from v3: - rebased on top of the latest upstream master. - now prctl(PR_HIDE_SELF_EXE) blocks access only from the same thread group, it won't break CRIU as v3 did. - extend the prctl to also cover files under /proc/self/map_files. - once prctl(PR_HIDE_SELF_EXE) is used, it is not possible to unset SUID_DUMP_DISABLE anymore. This is useful for the case where the container doesn't use execve to pass the control to a binary in the container chroot, and it prevents the process to be set to dumpable again since it would allow a different process in the container to get access to its proc files. - cleaned up the selftest and added more checks. v2: https://lkml.org/lkml/2023/1/19/849 Differences from v2: - fixed the test to check PR_SET_HIDE_SELF_EXE after fork v1: https://lkml.org/lkml/2023/1/4/334 Differences from v1: - amended more information in the commit message wrt map_files not requiring the same protection. - changed the test to verify PR_HIDE_SELF_EXE cannot be unset after a fork. fs/exec.c | 1 + fs/proc/base.c | 9 +++++++++ include/linux/sched.h | 5 +++++ include/uapi/linux/prctl.h | 3 +++ kernel/sys.c | 13 +++++++++++++ tools/include/uapi/linux/prctl.h | 3 +++ 6 files changed, 34 insertions(+) diff --git a/fs/exec.c b/fs/exec.c index 7c44d0c65b1b..d40e019a5ac5 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -1858,6 +1858,7 @@ static int bprm_execve(struct linux_binprm *bprm, /* execve succeeded */ current->fs->in_exec = 0; current->in_execve = 0; + task_clear_hide_self_exe(current); rseq_execve(current); acct_update_integrals(current); task_numa_free(current, false); diff --git a/fs/proc/base.c b/fs/proc/base.c index 5e0e0ccd47aa..14102a133655 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -1719,16 +1719,25 @@ static const struct file_operations proc_pid_set_comm_operations = { .release = single_release, }; +static inline bool is_hide_self_exe_blocked(struct task_struct *task) +{ + return task_hide_self_exe(task) && same_thread_group(current, task); +} + static int proc_exe_link(struct dentry *dentry, struct path *exe_path) { struct task_struct *task; struct file *exe_file; + bool hide_self_exe; task = get_proc_task(d_inode(dentry)); if (!task) return -ENOENT; exe_file = get_task_exe_file(task); + hide_self_exe = is_hide_self_exe_blocked(task); put_task_struct(task); + if (hide_self_exe) + return -EPERM; if (exe_file) { *exe_path = exe_file->f_path; path_get(&exe_file->f_path); diff --git a/include/linux/sched.h b/include/linux/sched.h index 63d242164b1a..fb1faaabe795 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1796,6 +1796,7 @@ static __always_inline bool is_percpu_thread(void) #define PFA_SPEC_IB_DISABLE 5 /* Indirect branch speculation restricted */ #define PFA_SPEC_IB_FORCE_DISABLE 6 /* Indirect branch speculation permanently restricted */ #define PFA_SPEC_SSB_NOEXEC 7 /* Speculative Store Bypass clear on execve() */ +#define PFA_HIDE_SELF_EXE 8 /* Hide /proc/self/exe for the process */ #define TASK_PFA_TEST(name, func) \ static inline bool task_##func(struct task_struct *p) \ @@ -1838,6 +1839,10 @@ TASK_PFA_CLEAR(SPEC_IB_DISABLE, spec_ib_disable) TASK_PFA_TEST(SPEC_IB_FORCE_DISABLE, spec_ib_force_disable) TASK_PFA_SET(SPEC_IB_FORCE_DISABLE, spec_ib_force_disable) +TASK_PFA_TEST(HIDE_SELF_EXE, hide_self_exe) +TASK_PFA_SET(HIDE_SELF_EXE, hide_self_exe) +TASK_PFA_CLEAR(HIDE_SELF_EXE, hide_self_exe) + static inline void current_restore_flags(unsigned long orig_flags, unsigned long flags) { diff --git a/include/uapi/linux/prctl.h b/include/uapi/linux/prctl.h index 1312a137f7fb..715c601b4fed 100644 --- a/include/uapi/linux/prctl.h +++ b/include/uapi/linux/prctl.h @@ -290,4 +290,7 @@ struct prctl_mm_map { #define PR_SET_VMA 0x53564d41 # define PR_SET_VMA_ANON_NAME 0 +#define PR_SET_HIDE_SELF_EXE 67 +#define PR_GET_HIDE_SELF_EXE 68 + #endif /* _LINUX_PRCTL_H */ diff --git a/kernel/sys.c b/kernel/sys.c index 495cd87d9bf4..6e5aae861ae7 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -2408,6 +2408,10 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, error = -EINVAL; break; } + if (task_hide_self_exe(me) && arg2 != SUID_DUMP_DISABLE) { + error = -EPERM; + break; + } set_dumpable(me->mm, arg2); break; @@ -2661,6 +2665,15 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, case PR_SET_VMA: error = prctl_set_vma(arg2, arg3, arg4, arg5); break; + case PR_SET_HIDE_SELF_EXE: + if (arg2 != 1 || arg3 || arg4 || arg5) + return -EINVAL; + task_set_hide_self_exe(current); + break; + case PR_GET_HIDE_SELF_EXE: + if (arg2 || arg3 || arg4 || arg5) + return -EINVAL; + return task_hide_self_exe(current) ? 1 : 0; default: error = -EINVAL; break; diff --git a/tools/include/uapi/linux/prctl.h b/tools/include/uapi/linux/prctl.h index a5e06dcbba13..b4c7a6c248a9 100644 --- a/tools/include/uapi/linux/prctl.h +++ b/tools/include/uapi/linux/prctl.h @@ -284,4 +284,7 @@ struct prctl_mm_map { #define PR_SET_VMA 0x53564d41 # define PR_SET_VMA_ANON_NAME 0 +#define PR_SET_HIDE_SELF_EXE 67 +#define PR_GET_HIDE_SELF_EXE 68 + #endif /* _LINUX_PRCTL_H */ From patchwork Fri Mar 10 11:25:53 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Giuseppe Scrivano X-Patchwork-Id: 67368 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:5915:0:0:0:0:0 with SMTP id v21csp816409wrd; Fri, 10 Mar 2023 03:33:41 -0800 (PST) X-Google-Smtp-Source: AK7set8b034vKaHz7RDmXbCibXX2VqTtGMD1M3BpJJH3KgsnHaffnwN6bf2EF06fpuZ+nFj+aajZ X-Received: by 2002:a17:90b:4c02:b0:23a:ad68:25a9 with SMTP id na2-20020a17090b4c0200b0023aad6825a9mr18421849pjb.43.1678448020788; Fri, 10 Mar 2023 03:33:40 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1678448020; cv=none; d=google.com; s=arc-20160816; b=Twoe+qsnxZTHMT8ZIkO+fLUUFRhb9h5x2RkZCOBzzQP4gCkpXVWVwaj2EuHmZd73z3 FbOo0q20mY7Q/FETbuj9DCpy4muj/+SIFjSD95SyVnUKd9Tj2RPbMrTHcMPBctS5QhPC yr8QKP4an4SJ+ivgOUg3z13ZBkwBmJupUnbvez9CAPkwb5RMVaIvlXfQSJk9arQULINr 1tPZ6/Kn9mRSEJH7xE0JuAqoX8vLfnoLrL7vptdX0BQ5nZcKQfFd6+ET0IS+UOGfCrW7 htgM7Zvs/eFX8/S4BZZiEXxkKTs6tEXq6DdH+plZiQOovSd23LF6a0RHhpovV5UIzetW KMBQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=P/VItM166X+OYnKhtfKsQovz6iE6g5P711OGiudw6Ss=; b=sTc98BQLR1dsKwe9/0lgxyEJafUKWWwscDLIBvVTcHqxMWUYoHVM0X9bNtaCr/xf31 r/gWdrKiSNx3orU9j/9luy0HezA37irNRmwoMFSgkh7QNMOtgqZZ/TqjUGiLe6mG+bAN OThzfb0gkibcXezsfHh7f3CTrf761I2Pultv6VjVV1ByG1ZjDMUlpdR4VLLv5TAQcNx3 F0hTK6qLeyOlGOgMnLPzGfKnmZ3rfVZ2nnjAwe9MnslnjeSrkAQOnXeiXiXy1HUrdtJW P7NTNJJDIjc75g48Wvy5xramMEQ318mB1x4v74TnTsw1B55AFxvvIN72svpo+czsTuPK H9yA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=ZYtzt+gL; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id p4-20020a17090a868400b00234a8e1f2efsi2270022pjn.182.2023.03.10.03.33.28; Fri, 10 Mar 2023 03:33:40 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=ZYtzt+gL; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230283AbjCJL1O (ORCPT + 99 others); Fri, 10 Mar 2023 06:27:14 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42042 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230437AbjCJL0z (ORCPT ); Fri, 10 Mar 2023 06:26:55 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 84E0CC9A5F for ; Fri, 10 Mar 2023 03:26:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1678447575; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=P/VItM166X+OYnKhtfKsQovz6iE6g5P711OGiudw6Ss=; b=ZYtzt+gLnnIYcyAItwYP9dMGEy0R6FIj1UCXF1QTV6ieDQ/75z/ccr7hVKUnowboW+QKJF 3KzH4yANk4847wI1EaaqknrOtAI2GkXW12QdczEqlZ70OPET6tkYNtAdTRI705nJq5gVvZ WSCd+rD9TO6BUtthyC3KAlF5Sgvy4Ew= Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-642-8p-RQurRPlKDuDleB571yA-1; Fri, 10 Mar 2023 06:26:12 -0500 X-MC-Unique: 8p-RQurRPlKDuDleB571yA-1 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.rdu2.redhat.com [10.11.54.8]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 4A5DF382888F; Fri, 10 Mar 2023 11:26:12 +0000 (UTC) Received: from carbon.redhat.com (unknown [10.39.194.146]) by smtp.corp.redhat.com (Postfix) with ESMTP id BB90DC15BA0; Fri, 10 Mar 2023 11:26:09 +0000 (UTC) From: Giuseppe Scrivano To: linux-kernel@vger.kernel.org Cc: keescook@chromium.org, bristot@redhat.com, ebiederm@xmission.com, brauner@kernel.org, cyphar@cyphar.com, viro@zeniv.linux.org.uk, walters@verbum.org, avagin@gmail.com, alexl@redhat.com, peterz@infradead.org, bmasney@redhat.com, gscrivan@redhat.com Subject: [PATCH v4 2/3] exec: PR_HIDE_SELF_EXE hides /proc/self/map_files Date: Fri, 10 Mar 2023 12:25:53 +0100 Message-Id: <20230310112554.1261731-2-gscrivan@redhat.com> In-Reply-To: <20230310112554.1261731-1-gscrivan@redhat.com> References: <20230310112554.1261731-1-gscrivan@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.8 X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_NONE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1759980311912972241?= X-GMAIL-MSGID: =?utf-8?q?1759980311912972241?= extend the new prctl(PR_HIDE_SELF_EXE) to prevent using /proc/self/map_files as well. Signed-off-by: Giuseppe Scrivano --- fs/proc/base.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/fs/proc/base.c b/fs/proc/base.c index 14102a133655..72f1cb44691f 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -2255,9 +2255,21 @@ proc_map_files_get_link(struct dentry *dentry, struct inode *inode, struct delayed_call *done) { + struct task_struct *task; + bool hide_self_exe; + if (!checkpoint_restore_ns_capable(&init_user_ns)) return ERR_PTR(-EPERM); + task = get_proc_task(d_inode(dentry)); + if (!task) + return ERR_PTR(-ENOENT); + hide_self_exe = is_hide_self_exe_blocked(task); + put_task_struct(task); + + if (hide_self_exe) + return ERR_PTR(-EPERM); + return proc_pid_get_link(dentry, inode, done); } From patchwork Fri Mar 10 11:25:54 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Giuseppe Scrivano X-Patchwork-Id: 67367 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:5915:0:0:0:0:0 with SMTP id v21csp814632wrd; Fri, 10 Mar 2023 03:29:19 -0800 (PST) X-Google-Smtp-Source: AK7set8gcOCf4ubsZqWRtPUwdObZMus5y9VWDggDMt737RiWWyz3DvdeUeDbzzcXBfODmE25k1fz X-Received: by 2002:a05:6a20:8f0f:b0:cd:929d:2818 with SMTP id b15-20020a056a208f0f00b000cd929d2818mr29570228pzk.11.1678447759388; Fri, 10 Mar 2023 03:29:19 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1678447759; cv=none; d=google.com; s=arc-20160816; b=dP0wOF19i9FS3WSYCifCXpr155iCWwxIRi8zrrhkn5c+aUK2fon1+5Nb7aQUijY3Hm rBcTBGvjMB2tN7qBHpkIwLKvFbqHFAvtrGo41OMXPPNetU5Z9lrta9C8Hr0b2MLtdEqi d1XzRFn/KgVggVH+c6/TC7YPz5qaAizbgakh+UarGXvzHKR2c9DPSH7WuvUQBj5+rxGc 2Jspm4gmk911KO80sSVezU7Z8gmH1slGGv5OC/9Oc3KTfQLxgn9WeXLG7oKpPUUAGi7L vRbaBoSbk+NjdcUvUDDwxAUBvclhwhHoEb/xp8FfsObVLq0ssJxeTGJl1y2BxoXRhBS6 P+IA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=9qN4d1dr8Q8nRy3REMnilBvKavvms6CXCfUYcSR/eHk=; b=hcxDXFGimywyXV8dPShzElD1OhMkWTA52cIeZEc4BcqXPKLosuFrU/Mp/+iqpNOic3 F2wSYdqIhs4E9IsbmfPmKQnwjHyC4i0QEwlUMA7L+s35Tvf6yisnX+zitflE4a66tz34 Bi4wzJyMvCHV+3r3PGzWK91lEA5wjpKkzs0wfbY4PW02K5nH+W2de9R52tMS4qzQLM4y 1rhCPa1bgMHK/w76GiLV6777STQWNQEqmLn/Lw3DAzwqcSNcqdycqmEQmu4CV8Zy0oVK ErJuJMl5+IuUYtzmwCdvMjVbrKp8zNjnzkJ71auBR3q7Tb3iqOIXEsl1Tfu5TTQ/H5c8 li8g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=guUwl1C1; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id 68-20020a630647000000b004fbcff506besi1852147pgg.48.2023.03.10.03.29.04; Fri, 10 Mar 2023 03:29:19 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=guUwl1C1; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230379AbjCJL1c (ORCPT + 99 others); Fri, 10 Mar 2023 06:27:32 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42128 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230415AbjCJL1G (ORCPT ); Fri, 10 Mar 2023 06:27:06 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DFC67D5892 for ; Fri, 10 Mar 2023 03:26:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1678447579; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=9qN4d1dr8Q8nRy3REMnilBvKavvms6CXCfUYcSR/eHk=; b=guUwl1C1e1XtujfUCJyb3/JUXQ9E6jnAl69D2dSVsfGiPxjhcPJJoLdOxISTYUXHtj8pD4 e93IpAokDTK1BvKKjdT+hTkznHEIwwLp7AeR/eh4riwYNqWFySbkuMFtRSjqO9d3O7+SvA ljMrtCIoi4spdhLuZ4FyE0JjhvHELrg= Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-262-mF0DXHx5PBaRxp0Hhj99WQ-1; Fri, 10 Mar 2023 06:26:15 -0500 X-MC-Unique: mF0DXHx5PBaRxp0Hhj99WQ-1 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.rdu2.redhat.com [10.11.54.8]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 723BB3828887; Fri, 10 Mar 2023 11:26:15 +0000 (UTC) Received: from carbon.redhat.com (unknown [10.39.194.146]) by smtp.corp.redhat.com (Postfix) with ESMTP id 8A9F0C15BAD; Fri, 10 Mar 2023 11:26:12 +0000 (UTC) From: Giuseppe Scrivano To: linux-kernel@vger.kernel.org Cc: keescook@chromium.org, bristot@redhat.com, ebiederm@xmission.com, brauner@kernel.org, cyphar@cyphar.com, viro@zeniv.linux.org.uk, walters@verbum.org, avagin@gmail.com, alexl@redhat.com, peterz@infradead.org, bmasney@redhat.com, gscrivan@redhat.com Subject: [PATCH v4 3/3] selftests: add tests for prctl(SET_HIDE_SELF_EXE) Date: Fri, 10 Mar 2023 12:25:54 +0100 Message-Id: <20230310112554.1261731-3-gscrivan@redhat.com> In-Reply-To: <20230310112554.1261731-1-gscrivan@redhat.com> References: <20230310112554.1261731-1-gscrivan@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.8 X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_NONE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1759980037876891474?= X-GMAIL-MSGID: =?utf-8?q?1759980037876891474?= Signed-off-by: Giuseppe Scrivano --- tools/testing/selftests/prctl/Makefile | 2 +- tools/testing/selftests/prctl/hide-self-exe.c | 193 ++++++++++++++++++ 2 files changed, 194 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/prctl/hide-self-exe.c diff --git a/tools/testing/selftests/prctl/Makefile b/tools/testing/selftests/prctl/Makefile index c7923b205222..024e107b26ec 100644 --- a/tools/testing/selftests/prctl/Makefile +++ b/tools/testing/selftests/prctl/Makefile @@ -5,7 +5,7 @@ ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/x86/ -e s/x86_64/x86/) ifeq ($(ARCH),x86) TEST_PROGS := disable-tsc-ctxt-sw-stress-test disable-tsc-on-off-stress-test \ - disable-tsc-test + disable-tsc-test hide-self-exe all: $(TEST_PROGS) include ../lib.mk diff --git a/tools/testing/selftests/prctl/hide-self-exe.c b/tools/testing/selftests/prctl/hide-self-exe.c new file mode 100644 index 000000000000..d95a7671c1ab --- /dev/null +++ b/tools/testing/selftests/prctl/hide-self-exe.c @@ -0,0 +1,193 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Tests for prctl(PR_GET_HIDE_SELF_EXE, ...) / prctl(PR_SET_HIDE_SELF_EXE, ...) + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef PR_SET_HIDE_SELF_EXE +# define PR_SET_HIDE_SELF_EXE 67 +# define PR_GET_HIDE_SELF_EXE 68 +#endif + +int main(void) +{ + char path[PATH_MAX]; + struct dirent *ent; + int status; + pid_t pid; + DIR *dir; + int ret; + + ret = open("/proc/self/exe", O_RDONLY); + if (ret < 0) { + perror("open /proc/self/exe"); + exit(EXIT_FAILURE); + } + close(ret); + + ret = prctl(PR_SET_DUMPABLE, 0, 0, 0, 0); + if (ret != 0) { + perror("prctl(PR_SET_DUMPABLE, SUID_DUMP_DISABLE)"); + exit(EXIT_FAILURE); + } + + ret = prctl(PR_SET_DUMPABLE, 1, 0, 0, 0); + if (ret != 0) { + perror("prctl(PR_SET_DUMPABLE, SUID_DUMP_USER)"); + exit(EXIT_FAILURE); + } + + ret = prctl(PR_GET_HIDE_SELF_EXE, 0, 0, 0, 0); + if (ret != 0) { + perror("prctl(PR_GET_HIDE_SELF_EXE)"); + exit(EXIT_FAILURE); + } + + ret = prctl(PR_SET_HIDE_SELF_EXE, 1, 0, 0, 0); + if (ret != 0) { + perror("prctl(PR_SET_HIDE_SELF_EXE)"); + exit(EXIT_FAILURE); + } + + ret = prctl(PR_GET_DUMPABLE, 0, 0, 0, 0); + if (ret != 1) { + perror("prctl(PR_GET_DUMPABLE)"); + exit(EXIT_FAILURE); + } + + ret = prctl(PR_SET_DUMPABLE, 0, 0, 0, 0); + if (ret != 0) { + perror("prctl(PR_SET_DUMPABLE, SUID_DUMP_DISABLE)"); + exit(EXIT_FAILURE); + } + + /* It is not permitted anymore. */ + ret = prctl(PR_SET_DUMPABLE, 1, 0, 0, 0); + if (ret == 0) { + perror("prctl(PR_SET_DUMPABLE, SUID_DUMP_USER)"); + exit(EXIT_FAILURE); + } + /* It can only be disabled. */ + ret = prctl(PR_SET_DUMPABLE, 0, 0, 0, 0); + if (ret != 0) { + perror("prctl(PR_SET_DUMPABLE, SUID_DUMP_DISABLE)"); + exit(EXIT_FAILURE); + } + + /* check it doesn't fail a second time. */ + ret = prctl(PR_SET_HIDE_SELF_EXE, 1, 0, 0, 0); + if (ret != 0) { + perror("prctl(PR_SET_HIDE_SELF_EXE)"); + exit(EXIT_FAILURE); + } + + ret = prctl(PR_GET_HIDE_SELF_EXE, 0, 0, 0, 0); + if (ret != 1) { + perror("prctl(PR_GET_HIDE_SELF_EXE)"); + exit(EXIT_FAILURE); + } + + ret = open("/proc/self/exe", O_RDONLY); + if (ret >= 0 || errno != EPERM) { + perror("open /proc/self/exe succeeded"); + exit(EXIT_FAILURE); + } + + ret = execl("/proc/self/exe", "/proc/self/exe", NULL); + if (ret >= 0 || errno != EPERM) { + perror("execl /proc/self/exe succeeded or wrong error"); + exit(EXIT_FAILURE); + } + + pid = fork(); + if (pid < 0) { + perror("fork"); + exit(EXIT_FAILURE); + } + if (pid == 0) { + /* It cannot be unset after a fork(). */ + ret = prctl(PR_SET_HIDE_SELF_EXE, 0, 0, 0, 0); + if (ret == 0) { + perror("prctl(PR_SET_HIDE_SELF_EXE)"); + exit(EXIT_FAILURE); + } + + /* The getter still return the correct value. */ + ret = prctl(PR_GET_HIDE_SELF_EXE, 0, 0, 0, 0); + if (ret != 1) { + perror("prctl(PR_GET_HIDE_SELF_EXE)"); + exit(EXIT_FAILURE); + } + + /* It must be unreachable after fork(). */ + ret = open("/proc/self/exe", O_RDONLY); + if (ret >= 0 || errno != EPERM) { + perror("open /proc/self/exe succeeded or wrong error"); + exit(EXIT_FAILURE); + } + + ret = execl("/proc/self/exe", "/proc/self/exe", NULL); + if (ret >= 0 || errno != EPERM) { + perror("execl /proc/self/exe succeeded wrong error"); + exit(EXIT_FAILURE); + } + + dir = opendir("/proc/self/map_files"); + if (dir == NULL) { + perror("opendir /proc/self/map_files"); + exit(EXIT_FAILURE); + } + + while ((ent = readdir(dir)) != NULL) { + if (ent->d_name[0] == '.') + continue; + + sprintf(path, "/proc/self/map_files/%s", ent->d_name); + ret = open(path, O_RDONLY); + if (ret >= 0 || errno != EPERM) { + perror("open /proc/self/map_files file succeeded or wrong error"); + exit(EXIT_FAILURE); + } + } + closedir(dir); + + /* It can be set again. */ + ret = prctl(PR_SET_HIDE_SELF_EXE, 1, 0, 0, 0); + if (ret != 0) { + perror("prctl(PR_SET_HIDE_SELF_EXE)"); + exit(EXIT_FAILURE); + } + + /* PR_SET_DUMPABLE must not be permitted. */ + ret = prctl(PR_SET_DUMPABLE, 1, 0, 0, 0); + if (ret == 0) { + perror("prctl(PR_SET_DUMPABLE, SUID_DUMP_USER)"); + exit(EXIT_FAILURE); + } + + /* HIDE_SELF_EXE is cleared after execve. */ + ret = system("cat /proc/self/exe > /dev/null"); + exit(ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE); + } + if (waitpid(pid, &status, 0) != pid) { + perror("waitpid"); + exit(EXIT_FAILURE); + } + if (status != 0) { + perror("child failed"); + exit(EXIT_FAILURE); + } + exit(EXIT_SUCCESS); +}