From patchwork Mon Nov 6 15:05:03 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alejandro Vallejo X-Patchwork-Id: 13447086 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 lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id C6EAEC4332F for ; Mon, 6 Nov 2023 15:05:34 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.628133.979250 (Exim 4.92) (envelope-from ) id 1r01AE-0008BY-DP; Mon, 06 Nov 2023 15:05:18 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 628133.979250; Mon, 06 Nov 2023 15:05:18 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1r01AE-0008BE-9A; Mon, 06 Nov 2023 15:05:18 +0000 Received: by outflank-mailman (input) for mailman id 628133; Mon, 06 Nov 2023 15:05:17 +0000 Received: from se1-gles-flk1-in.inumbo.com ([94.247.172.50] helo=se1-gles-flk1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1r01AD-000892-0u for xen-devel@lists.xenproject.org; Mon, 06 Nov 2023 15:05:17 +0000 Received: from mail-wm1-x32c.google.com (mail-wm1-x32c.google.com [2a00:1450:4864:20::32c]) by se1-gles-flk1.inumbo.com (Halon) with ESMTPS id e39219c9-7cb5-11ee-9b0e-b553b5be7939; Mon, 06 Nov 2023 16:05:14 +0100 (CET) Received: by mail-wm1-x32c.google.com with SMTP id 5b1f17b1804b1-40891d38e3fso32313555e9.1 for ; Mon, 06 Nov 2023 07:05:14 -0800 (PST) Received: from EMEAENGAAD19049.citrite.net ([2.223.46.215]) by smtp.gmail.com with ESMTPSA id q8-20020a05600c46c800b0040776008abdsm12507392wmo.40.2023.11.06.07.05.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 06 Nov 2023 07:05:13 -0800 (PST) X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: e39219c9-7cb5-11ee-9b0e-b553b5be7939 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cloud.com; s=cloud; t=1699283114; x=1699887914; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=DxkVS4hBSJv6X7HlZm/O6maHe61jzX44hOr03J+Zv60=; b=Hp5fJYZqVFhKh1upbu/mARsyNOFDsVIsXDG4i2cllh2xoZyr9D0wuJ4DgqXbZqU+KQ vLvmqOO++8DubvoEQq+Ay7GnyDYefyTDd/7/E0LwTMAmHBwMTK9xOVKhQ36dhUHVG7A0 3pW3eq6qloksvX7Ge3xXRBOwD/t92SXdKvhrw= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699283114; x=1699887914; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=DxkVS4hBSJv6X7HlZm/O6maHe61jzX44hOr03J+Zv60=; b=vqDp8FzflJrY0LzqRMdifTRY9Wo0dqM9lK1gu+sNKPJ/eQR1FXYcKWaFh6xf5EMkbR TiZ1zjuMMT+64XC43DBYBlCpDPKGaqq97upuS834Rm/pTuGsRmqgrqbPXxsnLZzNaaU2 U7xj2O1EGQh4wVKzxH/DW5g5Su5MDCg9SdmxJFz3vdn7UgqIcSGzNP5sb3qpzAEYpa6P BrRX2NtCjkNoiHYl4nxOIckcGX3NE1Oiw8n4wjpUXr3IKehlUDHVZ15Arq9rx6HuAt0q WTduexXb/OjdN0avakyTC6QrD9wWM3MjZcLMhdbDMONhcXr4pLRldFw7Z2QNDD31EY4A 8l0g== X-Gm-Message-State: AOJu0YwqzbrBRDtNk3Wx6niMaAis0XlCVE/JVrDLxaWeCFuz1wZuRA7q whrsgKjCNEmIjNPP297u4W51L59cak9ENoZ4k3I= X-Google-Smtp-Source: AGHT+IHK5/VVMvkWkg0o/sGZuDH2oGFdVWlv421KRFLy61nmtP55QYZaQVd3uX7wVa/c5bsIloEYnA== X-Received: by 2002:a05:600c:470e:b0:408:4f50:9602 with SMTP id v14-20020a05600c470e00b004084f509602mr25649437wmo.12.1699283113467; Mon, 06 Nov 2023 07:05:13 -0800 (PST) From: Alejandro Vallejo To: Xen-devel Cc: Alejandro Vallejo , Wei Liu , Anthony PERARD Subject: [PATCH 1/6] tools/pygrub: Set mount propagation to private recursively Date: Mon, 6 Nov 2023 15:05:03 +0000 Message-Id: <20231106150508.22665-2-alejandro.vallejo@cloud.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231106150508.22665-1-alejandro.vallejo@cloud.com> References: <20231106150508.22665-1-alejandro.vallejo@cloud.com> MIME-Version: 1.0 This is important in order for every mount done inside a mount namespace to go away after the namespace itself goes away. The comment referring to unreliability in Linux 4.19 was just wrong. This patch sets the story straight and makes the depriv pygrub a bit more confined should a layer of the onion be vulnerable. Signed-off-by: Alejandro Vallejo Acked-by: Andrew Cooper --- tools/pygrub/src/pygrub | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/tools/pygrub/src/pygrub b/tools/pygrub/src/pygrub index 541e562327..08540ad288 100755 --- a/tools/pygrub/src/pygrub +++ b/tools/pygrub/src/pygrub @@ -55,6 +55,12 @@ def unshare(flags): if unshare(flags) < 0: raise OSError(ctypes.get_errno(), os.strerror(ctypes.get_errno())) + # It's very typical for systemd to mount / with MS_SHARED. That means + # any events in the new namespace get propagated back to the parent. + # + # Undo it so that every mount done in the NS stay confined within it. + subprocess.check_output(["mount", "--make-rprivate", "/"]) + def bind_mount(src, dst, options): open(dst, "a").close() # touch @@ -113,11 +119,9 @@ def depriv(output_directory, output, device, uid, path_kernel, path_ramdisk): if rc != 0 or os.path.getsize(path) == 0: os.unlink(path) - # Normally, unshare(CLONE_NEWNS) will ensure this is not required. - # However, this syscall doesn't exist in *BSD systems and doesn't - # auto-unmount everything on older Linux kernels (At least as of - # Linux 4.19, but it seems fixed in 5.15). Either way, - # recursively unmount everything if needed. Quietly. + # Unshare(CLONE_NEWNS) ensures this is not required, but that's not + # present on *BSD, so recursively unmount everything if needed. + # Quietly. with open('/dev/null', 'w') as devnull: subprocess.call(["umount", "-f", chroot + device_path], stdout=devnull, stderr=devnull) From patchwork Mon Nov 6 15:05:04 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alejandro Vallejo X-Patchwork-Id: 13447088 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 lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id D40FAC4167B for ; Mon, 6 Nov 2023 15:05:38 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.628138.979305 (Exim 4.92) (envelope-from ) id 1r01AM-0001Lc-AA; Mon, 06 Nov 2023 15:05:26 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 628138.979305; Mon, 06 Nov 2023 15:05:26 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1r01AM-0001LR-79; Mon, 06 Nov 2023 15:05:26 +0000 Received: by outflank-mailman (input) for mailman id 628138; Mon, 06 Nov 2023 15:05:24 +0000 Received: from se1-gles-flk1-in.inumbo.com ([94.247.172.50] helo=se1-gles-flk1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1r01AK-000892-DO for xen-devel@lists.xenproject.org; Mon, 06 Nov 2023 15:05:24 +0000 Received: from mail-wm1-x336.google.com (mail-wm1-x336.google.com [2a00:1450:4864:20::336]) by se1-gles-flk1.inumbo.com (Halon) with ESMTPS id e8176dff-7cb5-11ee-9b0e-b553b5be7939; Mon, 06 Nov 2023 16:05:22 +0100 (CET) Received: by mail-wm1-x336.google.com with SMTP id 5b1f17b1804b1-40907b82ab9so32935115e9.1 for ; Mon, 06 Nov 2023 07:05:22 -0800 (PST) Received: from EMEAENGAAD19049.citrite.net ([2.223.46.215]) by smtp.gmail.com with ESMTPSA id q8-20020a05600c46c800b0040776008abdsm12507392wmo.40.2023.11.06.07.05.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 06 Nov 2023 07:05:14 -0800 (PST) X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: e8176dff-7cb5-11ee-9b0e-b553b5be7939 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cloud.com; s=cloud; t=1699283121; x=1699887921; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=z4/Hgemc7FudDEbRsY77L74znr+mz6WqSRzC5h7qg2g=; b=X49b5EgeCbaWw46qSJ4hKp1gccCM3lf2KUICJ+OWIYgWuMo7AewmzSLq+fGWOfOVza QTFdkfYHMzIW6yghbDVftQVRT75npFQazoAF+wYcIr91sY5ZeUf7qc/kUBU7GWM1yCEG mq6fJbPCWXKg14JW9kA3uH+QD8dLdScMLwJRk= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699283121; x=1699887921; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=z4/Hgemc7FudDEbRsY77L74znr+mz6WqSRzC5h7qg2g=; b=uz/prow8c/cjicBT25pDbwBiCztZTFL5goSx9cjFd6bPsS3hvLW80nmIhf7aJqcO8C tsCxKLcytLyV3VhKwrEKpD/ZUJ+uNMZOSBZWDMjTHmZ6u0J3gyZlJkJGIRZolTmGiEyT ultHvamaxwYOI31MvFQza5XAQZiU1u8fLDm9nSDqCcXqV722ODvzDztlyfersfhovc8t XbApz8xK0uyW22Ifojq3xDNROugBV/y6ralyhx2T/+6U6S25UNyVIR5UrVSNQJU8qz/p 4s96Y27+VVadvGvKfW+igG9M4TNQcxkw+ST1Z1ud5VMDmpVrjoWY5Fm1eHp72c8RlQqG WbHw== X-Gm-Message-State: AOJu0YwEbvGQz7iIU684ZQb58yPd5QIBJOCQEWs5s93iLDozucg+Dzcm HJi3ffn9trTD8my0XZpBgam4d/yuBX9p13n8cAg= X-Google-Smtp-Source: AGHT+IGh7mkaVJD+dEz1MhtP/IPYiw7iBgy6n149cmbUk/mpic12Beg8L/ECH7uBbE6E9DQ1MHmlpw== X-Received: by 2002:a05:600c:19d3:b0:402:f91e:df80 with SMTP id u19-20020a05600c19d300b00402f91edf80mr11789213wmq.3.1699283114304; Mon, 06 Nov 2023 07:05:14 -0800 (PST) From: Alejandro Vallejo To: Xen-devel Cc: Alejandro Vallejo , Wei Liu , Anthony PERARD Subject: [PATCH 2/6] tools/pygrub: Fix bug in LIMIT_FSIZE env variable override Date: Mon, 6 Nov 2023 15:05:04 +0000 Message-Id: <20231106150508.22665-3-alejandro.vallejo@cloud.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231106150508.22665-1-alejandro.vallejo@cloud.com> References: <20231106150508.22665-1-alejandro.vallejo@cloud.com> MIME-Version: 1.0 The env variable must be interpreted as an integer. As it is, the override logic simply causes an exception. Signed-off-by: Alejandro Vallejo --- tools/pygrub/src/pygrub | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/pygrub/src/pygrub b/tools/pygrub/src/pygrub index 08540ad288..327cf51774 100755 --- a/tools/pygrub/src/pygrub +++ b/tools/pygrub/src/pygrub @@ -89,7 +89,7 @@ def downgrade_rlimits(): # write permissions are bound. fsize = LIMIT_FSIZE if "PYGRUB_MAX_FILE_SIZE_MB" in os.environ.keys(): - fsize = os.environ["PYGRUB_MAX_FILE_SIZE_MB"] << 20 + fsize = int(os.environ["PYGRUB_MAX_FILE_SIZE_MB"]) << 20 resource.setrlimit(resource.RLIMIT_FSIZE, (fsize, fsize)) From patchwork Mon Nov 6 15:05:05 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alejandro Vallejo X-Patchwork-Id: 13447089 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 lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id E0955C41535 for ; Mon, 6 Nov 2023 15:05:38 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.628134.979258 (Exim 4.92) (envelope-from ) id 1r01AE-0008Ja-OO; Mon, 06 Nov 2023 15:05:18 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 628134.979258; Mon, 06 Nov 2023 15:05:18 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1r01AE-0008JB-Hx; Mon, 06 Nov 2023 15:05:18 +0000 Received: by outflank-mailman (input) for mailman id 628134; Mon, 06 Nov 2023 15:05:17 +0000 Received: from se1-gles-sth1-in.inumbo.com ([159.253.27.254] helo=se1-gles-sth1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1r01AD-000893-1F for xen-devel@lists.xenproject.org; Mon, 06 Nov 2023 15:05:17 +0000 Received: from mail-wm1-x335.google.com (mail-wm1-x335.google.com [2a00:1450:4864:20::335]) by se1-gles-sth1.inumbo.com (Halon) with ESMTPS id e43a4f46-7cb5-11ee-98da-6d05b1d4d9a1; Mon, 06 Nov 2023 16:05:15 +0100 (CET) Received: by mail-wm1-x335.google.com with SMTP id 5b1f17b1804b1-40850b244beso35235505e9.2 for ; Mon, 06 Nov 2023 07:05:15 -0800 (PST) Received: from EMEAENGAAD19049.citrite.net ([2.223.46.215]) by smtp.gmail.com with ESMTPSA id q8-20020a05600c46c800b0040776008abdsm12507392wmo.40.2023.11.06.07.05.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 06 Nov 2023 07:05:14 -0800 (PST) X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: e43a4f46-7cb5-11ee-98da-6d05b1d4d9a1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cloud.com; s=cloud; t=1699283115; x=1699887915; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=/bWTMrd0hqyfKgRpoolH0LkMWSKATEK93JdgDRPa6nY=; b=KcOLb2EuKe8AfUg1uUOfXEXDUF8n22rFQ+2cQ94EDWlxhFh0+f9wxykLIsLbwV6hxz BNH323jCnxULB+I0BkZqI1lHQu7OFW74cDCsD0jKJ9QuIboORVPYhEWTtmV9KMz0Cqiu woD/pV/4aAcdZHcR6ML3o+sp+INsAPu0D/TYI= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699283115; x=1699887915; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=/bWTMrd0hqyfKgRpoolH0LkMWSKATEK93JdgDRPa6nY=; b=CRmR9WFxyvjofpzIsRVxdjEEaZpky/PvqSMRCoowhMSOPA5tJXbUGGqEOl6GnDm3eD nmcpPazYe+oOAPf3k39DmgpZ4w5cuDSCYQ4gZVA63+AP4dSL0ESeu6o1MZ6/uHQUo70o XPc8nSElA1ttPcpiQwYnD2OEsqqAojhGRi7bRStkM8T5NM8ETw1jHbJhSql7CT2QfwPW JL/fqKM2Se3c4b9UpaOa5cCKCdNfEEp5wP8REg8xj8ZdNzp5sQet8pRWBPwp8KUffnNf hVngp5IU2uLcQIF8Mkvn6llyaN7NLH8xiQqQ/xmgmE5ch6uTj4G7q+UgY1x54cVtH64w TDRw== X-Gm-Message-State: AOJu0YxP6WJkvSD+Yw5At7iBeVy1BEvH+DF+UTZmGAOUsjdToYAEUJ5o JEOKhHBhMzRDk8WcxrhqVLlgiH4mkL6QxMyyZQw= X-Google-Smtp-Source: AGHT+IE65AVWleH4U/Zc+SQDhA16L/LXkoWcrwzeBuSOUVeWDJlO6PAtQaDAVcEGIYTbLkXxOoJSpg== X-Received: by 2002:a05:600c:1988:b0:409:19a0:d26f with SMTP id t8-20020a05600c198800b0040919a0d26fmr24529964wmq.23.1699283114818; Mon, 06 Nov 2023 07:05:14 -0800 (PST) From: Alejandro Vallejo To: Xen-devel Cc: Alejandro Vallejo , Wei Liu , Anthony PERARD Subject: [PATCH 3/6] tools/pygrub: Restrict depriv operation with RLIMIT_AS Date: Mon, 6 Nov 2023 15:05:05 +0000 Message-Id: <20231106150508.22665-4-alejandro.vallejo@cloud.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231106150508.22665-1-alejandro.vallejo@cloud.com> References: <20231106150508.22665-1-alejandro.vallejo@cloud.com> MIME-Version: 1.0 Prevents the depriv pygrub from consuming more than a fixed amount of memory. Signed-off-by: Alejandro Vallejo Acked-by: Andrew Cooper --- tools/pygrub/src/pygrub | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tools/pygrub/src/pygrub b/tools/pygrub/src/pygrub index 327cf51774..b96bdfd849 100755 --- a/tools/pygrub/src/pygrub +++ b/tools/pygrub/src/pygrub @@ -39,6 +39,11 @@ SECTOR_SIZE = 512 # pygrub LIMIT_FSIZE = 128 << 20 +# Unless provided through the env variable PYGRUB_MAX_RAM_USAGE_MB, then +# this is the maximum amount of memory allowed to be used by the depriv +# pygrub. +LIMIT_AS = 2 * LIMIT_FSIZE + CLONE_NEWNS = 0x00020000 # mount namespace CLONE_NEWNET = 0x40000000 # network namespace CLONE_NEWIPC = 0x08000000 # IPC namespace @@ -75,6 +80,11 @@ def downgrade_rlimits(): resource.setrlimit(resource.RLIMIT_CORE, (0, 0)) resource.setrlimit(resource.RLIMIT_MEMLOCK, (0, 0)) + max_ram_usage = LIMIT_AS + if "PYGRUB_MAX_RAM_USAGE_MB" in os.environ.keys(): + max_ram_usage = int(os.environ["PYGRUB_MAX_RAM_USAGE_MB"]) << 20 + resource.setrlimit(resource.RLIMIT_AS, (max_ram_usage, max_ram_usage)) + # py2's resource module doesn't know about resource.RLIMIT_MSGQUEUE # # TODO: Use resource.RLIMIT_MSGQUEUE after python2 is deprecated From patchwork Mon Nov 6 15:05:06 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alejandro Vallejo X-Patchwork-Id: 13447090 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 lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id EFDCDC4167D for ; Mon, 6 Nov 2023 15:05:38 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.628136.979269 (Exim 4.92) (envelope-from ) id 1r01AF-00007x-CI; Mon, 06 Nov 2023 15:05:19 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 628136.979269; Mon, 06 Nov 2023 15:05:19 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1r01AF-00005z-5n; Mon, 06 Nov 2023 15:05:19 +0000 Received: by outflank-mailman (input) for mailman id 628136; Mon, 06 Nov 2023 15:05:18 +0000 Received: from se1-gles-flk1-in.inumbo.com ([94.247.172.50] helo=se1-gles-flk1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1r01AE-000892-14 for xen-devel@lists.xenproject.org; Mon, 06 Nov 2023 15:05:18 +0000 Received: from mail-wm1-x334.google.com (mail-wm1-x334.google.com [2a00:1450:4864:20::334]) by se1-gles-flk1.inumbo.com (Halon) with ESMTPS id e467330d-7cb5-11ee-9b0e-b553b5be7939; Mon, 06 Nov 2023 16:05:16 +0100 (CET) Received: by mail-wm1-x334.google.com with SMTP id 5b1f17b1804b1-4083740f92dso33829815e9.3 for ; Mon, 06 Nov 2023 07:05:16 -0800 (PST) Received: from EMEAENGAAD19049.citrite.net ([2.223.46.215]) by smtp.gmail.com with ESMTPSA id q8-20020a05600c46c800b0040776008abdsm12507392wmo.40.2023.11.06.07.05.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 06 Nov 2023 07:05:15 -0800 (PST) X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: e467330d-7cb5-11ee-9b0e-b553b5be7939 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cloud.com; s=cloud; t=1699283115; x=1699887915; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=kUl/YemLBar/By9ea/qJ8DP9EY4pMDlEHPma04eJp64=; b=aa7gL0Zr/oz7ZM11Nv1NtlDtXfHKFTd5MpV9hOheAkn3oF/nvcNmDTJKK+x+n2dqJy Esh2/jKMjAbD97HUwEn4SlfYwpIyXvBnkoXA55oqyzZ7DXnchD4OzB4xC4d5odj3piYP 6dZ2M8GlUWtWciCCjZfGIvwYU3d19yZ6gvuUE= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699283115; x=1699887915; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=kUl/YemLBar/By9ea/qJ8DP9EY4pMDlEHPma04eJp64=; b=EV++YPxEulF/hc1ZvL3kuwI2/RF+2tY4egjptXdCDjRsrSCz0bxAewEbnPl92Z2hoJ ajNqzGwIrUPfvhCsgAWkp2PPydkJRFYcAF3jwq5uQAnCpWq4HLEmkR7xrjp+y/U3TZbt Ga2a07NCOhvdSpDNBAuY+MkXbS5ro3xtXstTX8+EGfXlwNKx5rZcEsvYwpQk86qRMzH9 fLjSpHA2XjWrhZjAt4m51D516QN3CXYpAxvc5ph+owRa2lpx7pZ66xZg5ja7ibcJepsS bz+HIvGig15UVfQrNRhJF52ycnLgD6mM03crCrPddUr49eOufee9hUBU2rgop5veGif2 hbyw== X-Gm-Message-State: AOJu0YwNu/55egELo6bH6HfUoRxmf+iguSc+cTalR+MwOTPUsltJRn2e ywdImMYQlb+cfEQUXALW24dPdAsoHf3vseZMBiA= X-Google-Smtp-Source: AGHT+IFiYrJniTDE0DlNzldrdMGBp1AMlFw3FlzGj3VRdyqCtM3fEF3dtfiPOzWteyxQ0kvPGlFgyA== X-Received: by 2002:a05:600c:358a:b0:408:59d4:f3d8 with SMTP id p10-20020a05600c358a00b0040859d4f3d8mr24447779wmq.18.1699283115286; Mon, 06 Nov 2023 07:05:15 -0800 (PST) From: Alejandro Vallejo To: Xen-devel Cc: Alejandro Vallejo , Wei Liu , Anthony PERARD Subject: [PATCH 4/6] tools/libfsimage: Add an fdopen() interface to libfsimage Date: Mon, 6 Nov 2023 15:05:06 +0000 Message-Id: <20231106150508.22665-5-alejandro.vallejo@cloud.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231106150508.22665-1-alejandro.vallejo@cloud.com> References: <20231106150508.22665-1-alejandro.vallejo@cloud.com> MIME-Version: 1.0 Currently libfsimage requires taking a path so it can open a file itself. This needs not to be the case and is, as far as I've gathered, a side effect of the ext2fs-lib's optional dependency because it couldn't cope directly with FDs until e2fsprogs-1.43.2. That was 2016, so it's safe to make use of this feature in order to improve the security stance of pygrub. https://github.com/tytso/e2fsprogs/commit/4ccf9e4fe165cfa966c8af0f3d310230aa5c3a1e This patch modifies the internals of libfsimage to: * Expose a new fdopen() function * Mirrors open(), except we pass an fd rather than a path * Refactor open() to use fdopen() internally * Rewire libfsimage so paths are not passed around * Rewire ext2fs-lib shim to use unixfd_io_manager Note that while fdopen() takes an FD, close() will still close it. Clients of libfsimage must ensure they duplicate any file descriptor they want to preserve past the lifetime of the fsi_t* objects that use them. Signed-off-by: Alejandro Vallejo --- tools/libfsimage/common/fsimage.c | 42 +++++++++++++++------ tools/libfsimage/common/fsimage_grub.c | 2 +- tools/libfsimage/common/fsimage_plugin.c | 4 +- tools/libfsimage/common/fsimage_priv.h | 3 +- tools/libfsimage/common/mapfile-GNU | 2 + tools/libfsimage/common/mapfile-SunOS | 2 + tools/libfsimage/common/xenfsimage.h | 3 ++ tools/libfsimage/common/xenfsimage_plugin.h | 2 +- tools/libfsimage/ext2fs-lib/ext2fs-lib.c | 14 ++++++- 9 files changed, 56 insertions(+), 18 deletions(-) diff --git a/tools/libfsimage/common/fsimage.c b/tools/libfsimage/common/fsimage.c index 5cfa56a84d..1fd302e506 100644 --- a/tools/libfsimage/common/fsimage.c +++ b/tools/libfsimage/common/fsimage.c @@ -38,15 +38,32 @@ static pthread_mutex_t fsi_lock = PTHREAD_MUTEX_INITIALIZER; fsi_t *fsi_open_fsimage(const char *path, uint64_t off, const char *options) { - fsi_t *fsi = NULL; + fsi_t *fsi; int fd; int err; if ((fd = open(path, O_RDONLY)) == -1) - goto fail; + return NULL; + + fsi = fsi_fdopen_fsimage(fd, off, options); + + if (fsi) + return fsi; + + err = errno; + (void) close(fd); + errno = err; + + return NULL; +} + +fsi_t *fsi_fdopen_fsimage(int fd, uint64_t off, const char *options) +{ + fsi_t *fsi = NULL; + int err; if ((fsi = malloc(sizeof(*fsi))) == NULL) - goto fail; + return NULL; fsi->f_fd = fd; fsi->f_off = off; @@ -54,20 +71,17 @@ fsi_t *fsi_open_fsimage(const char *path, uint64_t off, const char *options) fsi->f_bootstring = NULL; pthread_mutex_lock(&fsi_lock); - err = find_plugin(fsi, path, options); + err = find_plugin(fsi, options); pthread_mutex_unlock(&fsi_lock); - if (err != 0) - goto fail; - return (fsi); + if (!err) + return fsi; -fail: err = errno; - if (fd != -1) - (void) close(fd); free(fsi); errno = err; - return (NULL); + + return NULL; } void fsi_close_fsimage(fsi_t *fsi) @@ -167,3 +181,9 @@ fsi_fs_bootstring(fsi_t *fsi) { return (fsi->f_bootstring); } + +int +fsi_fd(fsi_t *fsi) +{ + return (fsi->f_fd); +} diff --git a/tools/libfsimage/common/fsimage_grub.c b/tools/libfsimage/common/fsimage_grub.c index 258d48bfbb..04397235f7 100644 --- a/tools/libfsimage/common/fsimage_grub.c +++ b/tools/libfsimage/common/fsimage_grub.c @@ -221,7 +221,7 @@ fsig_substring(const char *s1, const char *s2) } static int -fsig_mount(fsi_t *fsi, const char *path, const char *options) +fsig_mount(fsi_t *fsi, const char *options) { fsig_plugin_ops_t *ops = fsi->f_plugin->fp_data; fsi_file_t *ffi; diff --git a/tools/libfsimage/common/fsimage_plugin.c b/tools/libfsimage/common/fsimage_plugin.c index d0cb9e96a6..6645ce3bfe 100644 --- a/tools/libfsimage/common/fsimage_plugin.c +++ b/tools/libfsimage/common/fsimage_plugin.c @@ -175,7 +175,7 @@ fail: return (ret); } -int find_plugin(fsi_t *fsi, const char *path, const char *options) +int find_plugin(fsi_t *fsi, const char *options) { fsi_plugin_t *fp; int ret = 0; @@ -185,7 +185,7 @@ int find_plugin(fsi_t *fsi, const char *path, const char *options) for (fp = plugins; fp != NULL; fp = fp->fp_next) { fsi->f_plugin = fp; - if (fp->fp_ops->fpo_mount(fsi, path, options) == 0) + if (fp->fp_ops->fpo_mount(fsi, options) == 0) goto out; } diff --git a/tools/libfsimage/common/fsimage_priv.h b/tools/libfsimage/common/fsimage_priv.h index 2274403557..779e433b37 100644 --- a/tools/libfsimage/common/fsimage_priv.h +++ b/tools/libfsimage/common/fsimage_priv.h @@ -29,6 +29,7 @@ extern C { #endif #include +#include #include "xenfsimage.h" #include "xenfsimage_plugin.h" @@ -54,7 +55,7 @@ struct fsi_file { void *ff_data; }; -int find_plugin(fsi_t *, const char *, const char *); +int find_plugin(fsi_t *, const char *); #ifdef __cplusplus }; diff --git a/tools/libfsimage/common/mapfile-GNU b/tools/libfsimage/common/mapfile-GNU index 2d54d527d7..658f313315 100644 --- a/tools/libfsimage/common/mapfile-GNU +++ b/tools/libfsimage/common/mapfile-GNU @@ -3,6 +3,7 @@ VERSION { global: fsi_init; fsi_open_fsimage; + fsi_fdopen_fsimage; fsi_close_fsimage; fsi_file_exists; fsi_open_file; @@ -12,6 +13,7 @@ VERSION { fsi_bootstring_alloc; fsi_bootstring_free; fsi_fs_bootstring; + fsi_fd; fsip_fs_set_data; fsip_file_alloc; diff --git a/tools/libfsimage/common/mapfile-SunOS b/tools/libfsimage/common/mapfile-SunOS index 48deedb425..a03646ff73 100644 --- a/tools/libfsimage/common/mapfile-SunOS +++ b/tools/libfsimage/common/mapfile-SunOS @@ -2,6 +2,7 @@ libfsimage.so.1.0 { global: fsi_init; fsi_open_fsimage; + fsi_fdopen_fsimage; fsi_close_fsimage; fsi_file_exists; fsi_open_file; @@ -11,6 +12,7 @@ libfsimage.so.1.0 { fsi_bootstring_alloc; fsi_bootstring_free; fsi_fs_bootstring; + fsi_fd; fsip_fs_set_data; fsip_file_alloc; diff --git a/tools/libfsimage/common/xenfsimage.h b/tools/libfsimage/common/xenfsimage.h index 341883b2d7..8048cc7470 100644 --- a/tools/libfsimage/common/xenfsimage.h +++ b/tools/libfsimage/common/xenfsimage.h @@ -44,6 +44,7 @@ typedef struct fsi_file fsi_file_t; int fsi_init(void); fsi_t *fsi_open_fsimage(const char *, uint64_t, const char *); +fsi_t *fsi_fdopen_fsimage(int, uint64_t, const char *); void fsi_close_fsimage(fsi_t *); int fsi_file_exists(fsi_t *, const char *); @@ -57,6 +58,8 @@ char *fsi_bootstring_alloc(fsi_t *, size_t); void fsi_bootstring_free(fsi_t *); char *fsi_fs_bootstring(fsi_t *); +int fsi_fd(fsi_t *); + #ifdef __cplusplus }; #endif diff --git a/tools/libfsimage/common/xenfsimage_plugin.h b/tools/libfsimage/common/xenfsimage_plugin.h index 4135769018..996ea5ecbb 100644 --- a/tools/libfsimage/common/xenfsimage_plugin.h +++ b/tools/libfsimage/common/xenfsimage_plugin.h @@ -38,7 +38,7 @@ typedef struct fsi_plugin fsi_plugin_t; typedef struct fsi_plugin_ops { int fpo_version; - int (*fpo_mount)(fsi_t *, const char *, const char *); + int (*fpo_mount)(fsi_t *, const char *); int (*fpo_umount)(fsi_t *); fsi_file_t *(*fpo_open)(fsi_t *, const char *); ssize_t (*fpo_read)(fsi_file_t *, void *, size_t); diff --git a/tools/libfsimage/ext2fs-lib/ext2fs-lib.c b/tools/libfsimage/ext2fs-lib/ext2fs-lib.c index 864a15b349..9f07ea288f 100644 --- a/tools/libfsimage/ext2fs-lib/ext2fs-lib.c +++ b/tools/libfsimage/ext2fs-lib/ext2fs-lib.c @@ -25,15 +25,25 @@ #include INCLUDE_EXTFS_H #include #include +#include static int -ext2lib_mount(fsi_t *fsi, const char *name, const char *options) +ext2lib_mount(fsi_t *fsi, const char *options) { int err; char opts[30] = ""; ext2_filsys *fs; uint64_t offset = fsip_fs_offset(fsi); + /* + * We must choose unixfd_io_manager rather than unix_io_manager in + * order for the library to accept fd strings instead of paths. It + * still means we must pass a string representing an fd rather than + * an int, but at least this way we don't need to pass paths around + */ + char name[32] = {0}; + (void)snprintf(name, sizeof(name) - 1, "%d", fsi_fd(fsi)); + if (offset) snprintf(opts, 29, "offset=%" PRId64, offset); @@ -41,7 +51,7 @@ ext2lib_mount(fsi_t *fsi, const char *name, const char *options) if (fs == NULL) return (-1); - err = ext2fs_open2(name, opts, 0, 0, 0, unix_io_manager, fs); + err = ext2fs_open2(name, opts, 0, 0, 0, unixfd_io_manager, fs); if (err != 0) { free(fs); From patchwork Mon Nov 6 15:05:07 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alejandro Vallejo X-Patchwork-Id: 13447087 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 lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 445B3C4332F for ; Mon, 6 Nov 2023 15:05:37 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.628135.979263 (Exim 4.92) (envelope-from ) id 1r01AF-0008Q7-26; Mon, 06 Nov 2023 15:05:19 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 628135.979263; Mon, 06 Nov 2023 15:05:19 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1r01AE-0008OE-R7; Mon, 06 Nov 2023 15:05:18 +0000 Received: by outflank-mailman (input) for mailman id 628135; Mon, 06 Nov 2023 15:05:17 +0000 Received: from se1-gles-sth1-in.inumbo.com ([159.253.27.254] helo=se1-gles-sth1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1r01AD-000893-As for xen-devel@lists.xenproject.org; Mon, 06 Nov 2023 15:05:17 +0000 Received: from mail-wm1-x334.google.com (mail-wm1-x334.google.com [2a00:1450:4864:20::334]) by se1-gles-sth1.inumbo.com (Halon) with ESMTPS id e4d616d2-7cb5-11ee-98da-6d05b1d4d9a1; Mon, 06 Nov 2023 16:05:16 +0100 (CET) Received: by mail-wm1-x334.google.com with SMTP id 5b1f17b1804b1-4083f613275so34133525e9.2 for ; Mon, 06 Nov 2023 07:05:16 -0800 (PST) Received: from EMEAENGAAD19049.citrite.net ([2.223.46.215]) by smtp.gmail.com with ESMTPSA id q8-20020a05600c46c800b0040776008abdsm12507392wmo.40.2023.11.06.07.05.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 06 Nov 2023 07:05:15 -0800 (PST) X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: e4d616d2-7cb5-11ee-98da-6d05b1d4d9a1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cloud.com; s=cloud; t=1699283115; x=1699887915; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=HRK5wV0p3XK/zB6bzaQicMvY21LdOakLo9+vF3VIjHw=; b=UWV17fW+ctiXRL6URYf0akj+iraMAytVnugFX7wFd7UQUWGXcRFxY+XDhehGBFXy0t QvwS9j0ia/KUoD94zq72Nae3vhme4ZYQgUihBLFUi9utlyD57lPNF5Nnwl1yEGm62z/V bI1o5HL7/IW9z/81dcqJ5pJZftZJDoNvE5zRk= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699283115; x=1699887915; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=HRK5wV0p3XK/zB6bzaQicMvY21LdOakLo9+vF3VIjHw=; b=kX/RqYcmbrPGQn2RUPJeFBTaZcBY9qZaK4LwAd3shAH83vcsnuAWmo9ZdJlR6H1uLx w86pOHdSRAqy8JqspGOwm52iRZzcQUEGH1TQ91MUR74T6bdGTpOWpP4K7y8h2Kyr1uiQ vhQ19K7f5ItDSs1ipPTeE4lmY8w9bLDCQCLS0d3oRBObXPNus3VRZo/415t6ALSTC1Sv l7I3Nd66AjcB1huvaMn9pruuSCeVBh8vRWKUf1fAtnCrvVPZWHqKx5/xBxt/qFv9VYyY f06WUi3L3tMFz1zgfclSxLwbvPd1k+rmHFZFdLlRzkrqmUkhxK2Z2AWLwZ98pkGDQOoY eQ0A== X-Gm-Message-State: AOJu0YzPyfbhtpwX8pFM9XcQyXaTl7XiUYfjQ1wEmCChz7tL0gqt0PcQ cp37behFPjJPgPm14tCldvq1OXWWleRQQbqbreQ= X-Google-Smtp-Source: AGHT+IG18h4uGdSyUknwafJjm6DBdq+5DvkA9UzKtHFfxAq/HwAKalRu7cbbWqCtuHf/w/f+LVM1nw== X-Received: by 2002:a05:600c:4fd1:b0:408:80bb:ae80 with SMTP id o17-20020a05600c4fd100b0040880bbae80mr25137238wmq.7.1699283115679; Mon, 06 Nov 2023 07:05:15 -0800 (PST) From: Alejandro Vallejo To: Xen-devel Cc: Alejandro Vallejo , Wei Liu , Anthony PERARD Subject: [PATCH 5/6] tools/pygrub: Expose libfsimage's fdopen() to python Date: Mon, 6 Nov 2023 15:05:07 +0000 Message-Id: <20231106150508.22665-6-alejandro.vallejo@cloud.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231106150508.22665-1-alejandro.vallejo@cloud.com> References: <20231106150508.22665-1-alejandro.vallejo@cloud.com> MIME-Version: 1.0 Create a wrapper for the new fdopen() function of libfsimage. Signed-off-by: Alejandro Vallejo --- tools/pygrub/src/fsimage/fsimage.c | 33 ++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/tools/pygrub/src/fsimage/fsimage.c b/tools/pygrub/src/fsimage/fsimage.c index 12dfcff6e3..216f265331 100644 --- a/tools/pygrub/src/fsimage/fsimage.c +++ b/tools/pygrub/src/fsimage/fsimage.c @@ -270,6 +270,30 @@ fsimage_open(PyObject *o, PyObject *args, PyObject *kwargs) return (PyObject *)fs; } +static PyObject * +fsimage_fdopen(PyObject *o, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = { "fd", "offset", "options", NULL }; + int fd; + char *options = NULL; + uint64_t offset = 0; + fsimage_fs_t *fs; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|Ls", kwlist, + &fd, &offset, &options)) + return (NULL); + + if ((fs = PyObject_NEW(fsimage_fs_t, &fsimage_fs_type)) == NULL) + return (NULL); + + if ((fs->fs = fsi_fdopen_fsimage(fd, offset, options)) == NULL) { + PyErr_SetFromErrno(PyExc_IOError); + return (NULL); + } + + return (PyObject *)fs; +} + static PyObject * fsimage_getbootstring(PyObject *o, PyObject *args) { @@ -302,6 +326,13 @@ PyDoc_STRVAR(fsimage_open__doc__, "offset - offset of file system within file image.\n" "options - mount options string.\n"); +PyDoc_STRVAR(fsimage_fdopen__doc__, + "fdopen(fd, [offset=off]) - Use the file provided by the given fd as a filesystem image.\n" + "\n" + "fd - File descriptor to use.\n" + "offset - offset of file system within file image.\n" + "options - mount options string.\n"); + PyDoc_STRVAR(fsimage_getbootstring__doc__, "getbootstring(fs) - Return the boot string needed for this file system " "or NULL if none is needed.\n"); @@ -315,6 +346,8 @@ static struct PyMethodDef fsimage_module_methods[] = { METH_VARARGS, fsimage_init__doc__ }, { "open", (PyCFunction)fsimage_open, METH_VARARGS|METH_KEYWORDS, fsimage_open__doc__ }, + { "fdopen", (PyCFunction)fsimage_fdopen, + METH_VARARGS|METH_KEYWORDS, fsimage_fdopen__doc__ }, { "getbootstring", (PyCFunction)fsimage_getbootstring, METH_VARARGS, fsimage_getbootstring__doc__ }, { NULL, NULL, 0, NULL } From patchwork Mon Nov 6 15:05:08 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alejandro Vallejo X-Patchwork-Id: 13447091 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 lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 2E7A9C0018A for ; Mon, 6 Nov 2023 15:05:39 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.628137.979295 (Exim 4.92) (envelope-from ) id 1r01AG-0000wO-VF; Mon, 06 Nov 2023 15:05:20 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 628137.979295; Mon, 06 Nov 2023 15:05:20 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1r01AG-0000vz-PO; Mon, 06 Nov 2023 15:05:20 +0000 Received: by outflank-mailman (input) for mailman id 628137; Mon, 06 Nov 2023 15:05:20 +0000 Received: from se1-gles-flk1-in.inumbo.com ([94.247.172.50] helo=se1-gles-flk1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1r01AF-000892-Sy for xen-devel@lists.xenproject.org; Mon, 06 Nov 2023 15:05:20 +0000 Received: from mail-wm1-x329.google.com (mail-wm1-x329.google.com [2a00:1450:4864:20::329]) by se1-gles-flk1.inumbo.com (Halon) with ESMTPS id e571f82d-7cb5-11ee-9b0e-b553b5be7939; Mon, 06 Nov 2023 16:05:17 +0100 (CET) Received: by mail-wm1-x329.google.com with SMTP id 5b1f17b1804b1-40838915cecso33861875e9.2 for ; Mon, 06 Nov 2023 07:05:17 -0800 (PST) Received: from EMEAENGAAD19049.citrite.net ([2.223.46.215]) by smtp.gmail.com with ESMTPSA id q8-20020a05600c46c800b0040776008abdsm12507392wmo.40.2023.11.06.07.05.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 06 Nov 2023 07:05:15 -0800 (PST) X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: e571f82d-7cb5-11ee-9b0e-b553b5be7939 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cloud.com; s=cloud; t=1699283117; x=1699887917; darn=lists.xenproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=yowsapQA+Hk3t7pzlY0dGZgRSDLtI+G/ZK19XU66m/8=; b=TGgk+CMOf9kZwnz5k96Jk3ZwvCMd4VreUA0K1BwF6pVYBisELmB+e98AMRMYxOHPaf sdq+dHPUs47hrLi0es5d8vyPq3+c0Dy1um8GIrQIhcQdctgpRNnnGehXDAF3lXcN1NR0 UB6D56zOAKvnWoN6YsjNV7ByqzHgPWhWifiC0= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1699283117; x=1699887917; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=yowsapQA+Hk3t7pzlY0dGZgRSDLtI+G/ZK19XU66m/8=; b=wWC9zdpXV2DKO9VAJmDdb/yeZ4hMypckRaRajpOpTaX6KB5sCKy4dSHcOMzrR0WM5M Pdx+I1XyAhk6zufEg/zZYekFaSpVUEpwpiXGRqebtfENLAZpqwNCPGecL8ZOW/+VoX4K /Dl9TLiNLaXDHnaizEJJBAOpU8DbM/ICHOuuPTa9OMaYz3voxk4jbR9nHRusjavrvil9 JtDP7yL74e+cIAu8s+PuM0nCSVFMdWnaQNUCI468Fy9ZXr2sy/bIBhimo3PrIPmCtd6e QfveQU2qZZKYKRjKHeDjm42T5PRB4lWqyKfovmOhsGERbPOvckd1aUEew2Cv9nsOVRMW /lsQ== X-Gm-Message-State: AOJu0Yw3MnIOIKeF/JhiFiSVC4G/MwXCCgCi0SUd9zEh1yatTXkKqfhb lt4tOh3z/uIJu9D1u8PJTRppwn4QvI7oQiZK6jA= X-Google-Smtp-Source: AGHT+IGnVq4XQdzv37lduWCcsMnjRT/Dj0YkahdBsVtH52O+w5UUdeRpX50hKpxt9wyKM61zcglBcw== X-Received: by 2002:a05:600c:4fcb:b0:401:b204:3b97 with SMTP id o11-20020a05600c4fcb00b00401b2043b97mr24125222wmq.4.1699283116697; Mon, 06 Nov 2023 07:05:16 -0800 (PST) From: Alejandro Vallejo To: Xen-devel Cc: Alejandro Vallejo , Wei Liu , Anthony PERARD Subject: [PATCH 6/6] tools/pygrub: Hook libfsimage's fdopen() to pygrub Date: Mon, 6 Nov 2023 15:05:08 +0000 Message-Id: <20231106150508.22665-7-alejandro.vallejo@cloud.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231106150508.22665-1-alejandro.vallejo@cloud.com> References: <20231106150508.22665-1-alejandro.vallejo@cloud.com> MIME-Version: 1.0 This patch increases the security posture by removing the need to grant filesystem access to the depriv pygrub. Using libfsimage's fdopen(), the parent thread in the depriv procedure can simply ensure all the appropriate file descriptors are present before revoking permissions to the filesystem. A convenient usability side-effect is that it's no longer required for the restricted user to have access to the disk, because the depriv thread already has the file descriptor open by its parent. Signed-off-by: Alejandro Vallejo --- docs/man/xl.cfg.5.pod.in | 6 +- tools/pygrub/src/ExtLinuxConf.py | 20 ++++--- tools/pygrub/src/GrubConf.py | 29 ++++++---- tools/pygrub/src/LiloConf.py | 20 ++++--- tools/pygrub/src/pygrub | 95 ++++++++------------------------ 5 files changed, 68 insertions(+), 102 deletions(-) diff --git a/docs/man/xl.cfg.5.pod.in b/docs/man/xl.cfg.5.pod.in index 2e234b450e..e3fd2e37eb 100644 --- a/docs/man/xl.cfg.5.pod.in +++ b/docs/man/xl.cfg.5.pod.in @@ -1704,8 +1704,7 @@ See docs/features/qemu-deprivilege.pandoc for more information on how to setup the unprivileged users. Note that running the bootloader in restricted mode also implies using -non-interactive mode, and the disk image must be readable by the -restricted user. +non-interactive mode. =item B @@ -2768,8 +2767,7 @@ See docs/features/qemu-deprivilege.pandoc for more information on how to setup the unprivileged users. Note that running the bootloader in restricted mode also implies using -non-interactive mode, and the disk image must be readable by the -restricted user. +non-interactive mode. =item B diff --git a/tools/pygrub/src/ExtLinuxConf.py b/tools/pygrub/src/ExtLinuxConf.py index 4e990a9304..f2e9a81013 100644 --- a/tools/pygrub/src/ExtLinuxConf.py +++ b/tools/pygrub/src/ExtLinuxConf.py @@ -123,6 +123,7 @@ class ExtLinuxImage(object): class ExtLinuxConfigFile(object): def __init__(self, fn = None): self.filename = fn + self.file = None self.images = [] self.timeout = -1 self._default = 0 @@ -138,16 +139,21 @@ class ExtLinuxConfigFile(object): def parse(self, buf = None): if buf is None: - if self.filename is None: + if not self.filename and not self.file: raise ValueError("No config file defined to parse!") - f = open(self.filename, 'r') - lines = f.readlines() - f.close() - else: - lines = buf.split("\n") + if self.file: + buf = file.read() + path = self.file.name + else: + f = open(self.filename, 'r') + buf = f.read() + f.close() + lines = buf.split("\n") + + if not path: + path = os.path.dirname(self.filename) - path = os.path.dirname(self.filename) img = [] for l in lines: l = l.strip() diff --git a/tools/pygrub/src/GrubConf.py b/tools/pygrub/src/GrubConf.py index 580c9628ca..96b79b89a7 100644 --- a/tools/pygrub/src/GrubConf.py +++ b/tools/pygrub/src/GrubConf.py @@ -170,6 +170,7 @@ class GrubImage(_GrubImage): class _GrubConfigFile(object): def __init__(self, fn = None): self.filename = fn + self.file = None self.images = [] self.timeout = -1 self._default = 0 @@ -271,14 +272,16 @@ class GrubConfigFile(_GrubConfigFile): def parse(self, buf = None): if buf is None: - if self.filename is None: + if not self.filename and not self.file: raise ValueError("No config file defined to parse!") - f = open(self.filename, 'r') - lines = f.readlines() - f.close() - else: - lines = buf.split("\n") + if self.file: + buf = file.read() + else: + f = open(self.filename, 'r') + buf = f.read() + f.close() + lines = buf.split("\n") img = None title = "" @@ -370,14 +373,16 @@ class Grub2ConfigFile(_GrubConfigFile): def parse(self, buf = None): if buf is None: - if self.filename is None: + if not self.filename and not self.file: raise ValueError("No config file defined to parse!") - f = open(self.filename, 'r') - lines = f.readlines() - f.close() - else: - lines = buf.split("\n") + if self.file: + buf = file.read() + else: + f = open(self.filename, 'r') + buf = f.read() + f.close() + lines = buf.split("\n") in_function = False img = None diff --git a/tools/pygrub/src/LiloConf.py b/tools/pygrub/src/LiloConf.py index e3bfcb5244..73f8fcb214 100644 --- a/tools/pygrub/src/LiloConf.py +++ b/tools/pygrub/src/LiloConf.py @@ -90,6 +90,7 @@ class LiloImage(object): class LiloConfigFile(object): def __init__(self, fn = None): self.filename = fn + self.file = None self.images = [] self.timeout = -1 self._default = 0 @@ -99,16 +100,21 @@ class LiloConfigFile(object): def parse(self, buf = None): if buf is None: - if self.filename is None: + if not self.filename and not self.file: raise ValueError("No config file defined to parse!") - f = open(self.filename, 'r') - lines = f.readlines() - f.close() - else: - lines = buf.split("\n") + if self.file: + buf = file.read() + path = self.file.name + else: + f = open(self.filename, 'r') + buf = f.read() + f.close() + lines = buf.split("\n") + + if not path: + path = os.path.dirname(self.filename) - path = os.path.dirname(self.filename) img = [] for l in lines: l = l.strip() diff --git a/tools/pygrub/src/pygrub b/tools/pygrub/src/pygrub index b96bdfd849..123e9c40ad 100755 --- a/tools/pygrub/src/pygrub +++ b/tools/pygrub/src/pygrub @@ -66,14 +66,6 @@ def unshare(flags): # Undo it so that every mount done in the NS stay confined within it. subprocess.check_output(["mount", "--make-rprivate", "/"]) -def bind_mount(src, dst, options): - open(dst, "a").close() # touch - - rc = subprocess.call(["mount", "--bind", "-o", options, src, dst]) - if rc != 0: - raise RuntimeError("bad_mount: src=%s dst=%s opts=%s" % - (src, dst, options)) - def downgrade_rlimits(): # Wipe the authority to use unrequired resources resource.setrlimit(resource.RLIMIT_NPROC, (0, 0)) @@ -103,7 +95,7 @@ def downgrade_rlimits(): resource.setrlimit(resource.RLIMIT_FSIZE, (fsize, fsize)) -def depriv(output_directory, output, device, uid, path_kernel, path_ramdisk): +def depriv(output_directory, uid, path_kernel, path_ramdisk): # The only point of this call is to force the loading of libfsimage. # That way, we don't need to bind-mount it into the chroot rc = xenfsimage.init() @@ -114,7 +106,7 @@ def depriv(output_directory, output, device, uid, path_kernel, path_ramdisk): # Create a temporary directory for the chroot chroot = tempfile.mkdtemp(prefix=str(uid)+'-', dir=output_directory) + '/' - device_path = '/device' + os.chmod(chroot, 0o700) pid = os.fork() if pid: @@ -129,16 +121,7 @@ def depriv(output_directory, output, device, uid, path_kernel, path_ramdisk): if rc != 0 or os.path.getsize(path) == 0: os.unlink(path) - # Unshare(CLONE_NEWNS) ensures this is not required, but that's not - # present on *BSD, so recursively unmount everything if needed. - # Quietly. - with open('/dev/null', 'w') as devnull: - subprocess.call(["umount", "-f", chroot + device_path], - stdout=devnull, stderr=devnull) - subprocess.call(["umount", "-f", chroot], - stdout=devnull, stderr=devnull) os.rmdir(chroot) - sys.exit(rc) # By unsharing the namespace we're making sure it's all bulk-released @@ -150,20 +133,6 @@ def depriv(output_directory, output, device, uid, path_kernel, path_ramdisk): # Set sensible limits using the setrlimit interface downgrade_rlimits() - # We'll mount tmpfs on the chroot to ensure the deprivileged child - # cannot affect the persistent state. It's RW now in order to - # bind-mount the device, but note it's remounted RO after that. - rc = subprocess.call(["mount", "-t", "tmpfs", "none", chroot]) - if rc != 0: - raise RuntimeError("mount_tmpfs rc=%d dst=\"%s\"" % (rc, chroot)) - - # Bind the untrusted device RO - bind_mount(device, chroot + device_path, "ro,nosuid,noexec") - - rc = subprocess.call(["mount", "-t", "tmpfs", "-o", "remount,ro,nosuid,noexec,nodev", "none", chroot]) - if rc != 0: - raise RuntimeError("remount_tmpfs rc=%d dst=\"%s\"" % (rc, chroot)) - # Drop superpowers! os.chroot(chroot) os.chdir('/') @@ -171,15 +140,7 @@ def depriv(output_directory, output, device, uid, path_kernel, path_ramdisk): os.setgroups([uid]) os.setuid(uid) - return device_path - -def read_size_roundup(fd, size): - if platform.system() != 'FreeBSD': - return size - st = os.fstat(fd) - if (not stat.S_ISCHR(st.st_mode)): - return size - # Round up to sector size if it's a raw character device +def round_up_to_sectorsize(size): return (((size)+((SECTOR_SIZE)-1))&(~((SECTOR_SIZE)-1))) def enable_cursor(ison): @@ -196,9 +157,8 @@ def enable_cursor(ison): DISK_TYPE_RAW, DISK_TYPE_HYBRIDISO, DISK_TYPE_DOS = range(3) def identify_disk_image(file): """Detect DOS partition table or HybridISO format.""" - fd = os.open(file, os.O_RDONLY) - buf = os.read(fd, read_size_roundup(fd, 0x8006)) - os.close(fd) + file.seek(0, 0) + buf = file.read(0x8200) if len(buf) >= 512 and \ struct.unpack("H", buf[0x1fe: 0x200]) == (0xaa55,): @@ -215,10 +175,8 @@ V_ROOT=0x2 def get_solaris_slice(file, offset): """Find the root slice in a Solaris VTOC.""" - fd = os.open(file, os.O_RDONLY) - os.lseek(fd, offset + (DK_LABEL_LOC * SECTOR_SIZE), 0) - buf = os.read(fd, 512) - os.close(fd) + file.seek(offset + (DK_LABEL_LOC * SECTOR_SIZE), 0) + buf = file.read(512) if struct.unpack("" %(sys.argv[0],), file=sys.stderr) - def copy_from_image(fs, file_to_read, file_type, fd_dst, path_dst, not_really): + def copy_from_image(fs, file_to_read, file_type, fd_dst, not_really): if not_really: if fs.file_exists(file_to_read): return "<%s:%s>" % (file_type, file_to_read) @@ -898,14 +853,7 @@ if __name__ == "__main__": os.close(fd_dst) del datafile return - try: - os.write(fd_dst, data) - except Exception as e: - print(e, file=sys.stderr) - if path_dst: - os.unlink(path_dst) - del datafile - sys.exit("Error writing temporary copy of "+file_type) + os.write(fd_dst, data) dataoff += len(data) try: @@ -1020,13 +968,15 @@ if __name__ == "__main__": (fd_ramdisk, path_ramdisk) = tempfile.mkstemp(prefix="boot_ramdisk.", dir=output_directory) + file = open(file, 'rb') + if output is None: fd = sys.stdout.fileno() else: fd = os.open(output, os.O_WRONLY) if uid: - file = depriv(output_directory, output, file, uid, path_kernel, path_ramdisk) + depriv(output_directory, uid, path_kernel, path_ramdisk) # debug if isconfig: @@ -1049,9 +999,10 @@ if __name__ == "__main__": if part_offs is None: part_offs = get_partition_offsets(file) + file.seek(0, 0) for offset in part_offs: try: - fs = xenfsimage.open(file, offset, bootfsoptions) + fs = xenfsimage.fdopen(os.dup(file.fileno()), offset, bootfsoptions) chosencfg = sniff_solaris(fs, incfg) @@ -1083,13 +1034,13 @@ if __name__ == "__main__": raise RuntimeError("Unable to find partition containing kernel") copy_from_image(fs, chosencfg["kernel"], "kernel", - fd_kernel, None if uid else path_kernel, not_really) + fd_kernel, not_really) bootcfg["kernel"] = path_kernel if chosencfg["ramdisk"]: try: copy_from_image(fs, chosencfg["ramdisk"], "ramdisk", - fd_ramdisk, None if uid else path_ramdisk, not_really) + fd_ramdisk, not_really) except: if not uid and not not_really: os.unlink(path_kernel)