From patchwork Mon Aug 7 19:07:32 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Hildenbrand X-Patchwork-Id: 13344754 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.gnu.org (lists.gnu.org [209.51.188.17]) (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 69C24C04A6A for ; Mon, 7 Aug 2023 19:08:42 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qT5a2-0003j8-Jz; Mon, 07 Aug 2023 15:07:50 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qT5Zz-0003i8-JN for qemu-devel@nongnu.org; Mon, 07 Aug 2023 15:07:47 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qT5Zy-0005oG-26 for qemu-devel@nongnu.org; Mon, 07 Aug 2023 15:07:47 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1691435265; 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=ahHtgE5Le4Ql7CB4JIAfDzkB520q7jcsgBSrxoiy7SM=; b=KIheJiKNoYzET/hPlBpbNteSVdRjBJ9AIMkNThXFokNolLLFNPr68LMoDSlUAXcuu0Aqn0 ziiUlcS+hMLAi0I2WNtDJRMH4/3DiQBYw+t6TNZNHEByHS/N1iiZYwBl22Q9AorjcG5U1Y TSb/NariquM6/glVlOpL3xcXmOO9mOQ= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-622-kZM7mED7NPGphC6nxgIQpg-1; Mon, 07 Aug 2023 15:07:41 -0400 X-MC-Unique: kZM7mED7NPGphC6nxgIQpg-1 Received: from smtp.corp.redhat.com (int-mx10.intmail.prod.int.rdu2.redhat.com [10.11.54.10]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id E4C6385CCE5; Mon, 7 Aug 2023 19:07:40 +0000 (UTC) Received: from t14s.redhat.com (unknown [10.39.192.170]) by smtp.corp.redhat.com (Postfix) with ESMTP id 4AD994021B9; Mon, 7 Aug 2023 19:07:39 +0000 (UTC) From: David Hildenbrand To: qemu-devel@nongnu.org Cc: David Hildenbrand , Paolo Bonzini , Peter Xu , Igor Mammedov , Thiner Logoer , =?utf-8?q?Philippe_Mathieu-Daud?= =?utf-8?q?=C3=A9?= Subject: [PATCH v1 1/3] softmmu/physmem: fallback to opening guest RAM file as readonly in a MAP_PRIVATE mapping Date: Mon, 7 Aug 2023 21:07:32 +0200 Message-ID: <20230807190736.572665-2-david@redhat.com> In-Reply-To: <20230807190736.572665-1-david@redhat.com> References: <20230807190736.572665-1-david@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.10 Received-SPF: pass client-ip=170.10.133.124; envelope-from=david@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org From: Thiner Logoer Users may specify * "-mem-path" or * "-object memory-backend-file,share=off,readonly=off" and expect such COW (MAP_PRIVATE) mappings to work, even if the user does not have write permissions to open the file. For now, we would always fail in that case, always requiring file write permissions. Let's detect when that failure happens and fallback to opening the file readonly. Warn the user, since there are other use cases where we want the file to be mapped writable: ftruncate() and fallocate() will fail if the file was not opened with write permissions. Signed-off-by: Thiner Logoer Co-developed-by: David Hildenbrand Signed-off-by: David Hildenbrand Signed-off-by: David Hildenbrand --- softmmu/physmem.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/softmmu/physmem.c b/softmmu/physmem.c index 3df73542e1..d1ae694b20 100644 --- a/softmmu/physmem.c +++ b/softmmu/physmem.c @@ -1289,8 +1289,7 @@ static int64_t get_file_align(int fd) static int file_ram_open(const char *path, const char *region_name, bool readonly, - bool *created, - Error **errp) + bool *created) { char *filename; char *sanitized_name; @@ -1334,10 +1333,7 @@ static int file_ram_open(const char *path, g_free(filename); } if (errno != EEXIST && errno != EINTR) { - error_setg_errno(errp, errno, - "can't open backing store %s for guest RAM", - path); - return -1; + return -errno; } /* * Try again on EINTR and EEXIST. The latter happens when @@ -1946,9 +1942,23 @@ RAMBlock *qemu_ram_alloc_from_file(ram_addr_t size, MemoryRegion *mr, bool created; RAMBlock *block; - fd = file_ram_open(mem_path, memory_region_name(mr), readonly, &created, - errp); + fd = file_ram_open(mem_path, memory_region_name(mr), readonly, &created); + if (fd == -EACCES && !(ram_flags & RAM_SHARED) && !readonly) { + /* + * We can have a writable MAP_PRIVATE mapping of a readonly file. + * However, some operations like ftruncate() or fallocate() might fail + * later, let's warn the user. + */ + fd = file_ram_open(mem_path, memory_region_name(mr), true, &created); + if (fd >= 0) { + warn_report("backing store %s for guest RAM (MAP_PRIVATE) opened" + " readonly because the file is not writable", mem_path); + } + } if (fd < 0) { + error_setg_errno(errp, -fd, + "can't open backing store %s for guest RAM", + mem_path); return NULL; } From patchwork Mon Aug 7 19:07:33 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Hildenbrand X-Patchwork-Id: 13344755 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.gnu.org (lists.gnu.org [209.51.188.17]) (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 60B8DC001DE for ; Mon, 7 Aug 2023 19:08:54 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qT5a1-0003ib-0E; Mon, 07 Aug 2023 15:07:49 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qT5Zy-0003hk-Rl for qemu-devel@nongnu.org; Mon, 07 Aug 2023 15:07:46 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qT5Zx-0005o0-GD for qemu-devel@nongnu.org; Mon, 07 Aug 2023 15:07:46 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1691435264; 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=8/JG4xq1fn1DPP8n2T9g6mLn79wHbUIsLvpRXYT889c=; b=K05oPt84vZBr+c0IOHa/EAUamwoZjZHQpkTBI6JL464i2rsuWiswAbmp9CJ2S6NjEwgZ0I Pqvys6SJFeOv8CkDDI4wkzaTKTz0aRRJGVOMqeqKQpIxG1PBc8btmAkUIylu/o73ySw/Ac augYjAnZWxe3ttT+HxBAIrEV/YyW/fQ= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-653-ENfz1GifPdqnYS8JGhrKtw-1; Mon, 07 Aug 2023 15:07:43 -0400 X-MC-Unique: ENfz1GifPdqnYS8JGhrKtw-1 Received: from smtp.corp.redhat.com (int-mx10.intmail.prod.int.rdu2.redhat.com [10.11.54.10]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 94E6980523D; Mon, 7 Aug 2023 19:07:42 +0000 (UTC) Received: from t14s.redhat.com (unknown [10.39.192.170]) by smtp.corp.redhat.com (Postfix) with ESMTP id 2F891403166; Mon, 7 Aug 2023 19:07:41 +0000 (UTC) From: David Hildenbrand To: qemu-devel@nongnu.org Cc: David Hildenbrand , Paolo Bonzini , Peter Xu , Igor Mammedov , Thiner Logoer , =?utf-8?q?Philippe_Mathieu-Daud?= =?utf-8?q?=C3=A9?= Subject: [PATCH v1 2/3] softmmu/physmem: fail creation of new files in file_ram_open() with readonly=true Date: Mon, 7 Aug 2023 21:07:33 +0200 Message-ID: <20230807190736.572665-3-david@redhat.com> In-Reply-To: <20230807190736.572665-1-david@redhat.com> References: <20230807190736.572665-1-david@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.10 Received-SPF: pass client-ip=170.10.129.124; envelope-from=david@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Currently, if a file does not exist yet, file_ram_open() will create new empty file and open it writable. However, it even does that when readonly=true was specified. So instead of opening the file read-only, we'll open it writable, implying that later fallocate() or ftruncate() could succeed. Specifying O_RDONLY instead would theoretically work, however, ftruncate() will refuse to resize the new empty file and we'll get a warning: ftruncate: Invalid argument mmap() will succeed, but any later access to that memory would fail with SIGBUS. Undesirable. If someone intends to let QEMU open+mmap a file read-only, better create+resize+fill that file ahead of time outside of QEMU context. We'll now fail with: ./qemu-system-x86_64 \ -object memory-backend-file,id=ram0,mem-path=tmp/ls,readonly=true,size=1g qemu-system-x86_64: can't open backing store tmp/ls for guest RAM: No such file or directory It's unlikely that this will harm existing users: especially R/O NVDIMMs better expose some reasonable data that already exists. Everything else would just hide user errors when accidentally specifying a non-existent file. Note that the only memory-backend-file will end up calling memory_region_init_ram_from_file() -> qemu_ram_alloc_from_file() -> file_ram_open(). Signed-off-by: David Hildenbrand --- softmmu/physmem.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/softmmu/physmem.c b/softmmu/physmem.c index d1ae694b20..9580567608 100644 --- a/softmmu/physmem.c +++ b/softmmu/physmem.c @@ -1304,6 +1304,13 @@ static int file_ram_open(const char *path, break; } if (errno == ENOENT) { + if (readonly) { + /* + * O_RDONLY would later make ftruncate() fail, leading to + * SIGBUS after mmap(). + */ + return -ENOENT; + } /* @path names a file that doesn't exist, create it */ fd = open(path, O_RDWR | O_CREAT | O_EXCL, 0644); if (fd >= 0) { From patchwork Mon Aug 7 19:07:34 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Hildenbrand X-Patchwork-Id: 13344753 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.gnu.org (lists.gnu.org [209.51.188.17]) (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 4054FC001B0 for ; Mon, 7 Aug 2023 19:08:42 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qT5a3-0003jD-VE; Mon, 07 Aug 2023 15:07:51 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qT5a1-0003ic-40 for qemu-devel@nongnu.org; Mon, 07 Aug 2023 15:07:49 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qT5Zz-0005ov-GD for qemu-devel@nongnu.org; Mon, 07 Aug 2023 15:07:48 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1691435266; 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=QFpBpOJ7TV3o6XlFKxp6L9ld2Zv7GPx7lsusnUVb2wQ=; b=jNXE3x0CE7Scx/qQqXzPQt6YPCc9QzDc8Wg2njAg+FyuAaQCR8CU0S1fMBkmKKSPpyMPKe PiNmXnqJWSKP73jaY1L56xe+DQgJHureiPgC/DZe55pJGc9MnxKYIuzNqxvYQVGzkXAre4 8xcpBc5gvBwKmnQoghynpEwS5jkVePc= Received: from mimecast-mx02.redhat.com (66.187.233.73 [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-141-oLUVwXVLPo-r3AnMdhB_tw-1; Mon, 07 Aug 2023 15:07:44 -0400 X-MC-Unique: oLUVwXVLPo-r3AnMdhB_tw-1 Received: from smtp.corp.redhat.com (int-mx10.intmail.prod.int.rdu2.redhat.com [10.11.54.10]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 1396E3810D2B; Mon, 7 Aug 2023 19:07:44 +0000 (UTC) Received: from t14s.redhat.com (unknown [10.39.192.170]) by smtp.corp.redhat.com (Postfix) with ESMTP id D3E8E4021B9; Mon, 7 Aug 2023 19:07:42 +0000 (UTC) From: David Hildenbrand To: qemu-devel@nongnu.org Cc: David Hildenbrand , Paolo Bonzini , Peter Xu , Igor Mammedov , Thiner Logoer , =?utf-8?q?Philippe_Mathieu-Daud?= =?utf-8?q?=C3=A9?= Subject: [PATCH v1 3/3] softmmu/physmem: never return directories from file_ram_open() Date: Mon, 7 Aug 2023 21:07:34 +0200 Message-ID: <20230807190736.572665-4-david@redhat.com> In-Reply-To: <20230807190736.572665-1-david@redhat.com> References: <20230807190736.572665-1-david@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.10 Received-SPF: pass client-ip=170.10.129.124; envelope-from=david@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org open() does not fail on directories when opening them readonly (O_RDONLY). Currently, we succeed opening such directories and fail later during mmap(), resulting in a misleading error message. $ ./qemu-system-x86_64 \ -object memory-backend-file,id=ram0,mem-path=tmp,readonly=true,size=1g qemu-system-x86_64: unable to map backing store for guest RAM: No such device To identify directories and handle them accordingly in file_ram_open() also when readonly=true was specified, detect if we just opened a directory using fstat() instead. Then, fail file_ram_open() right away, similarly to how we now fail if the file does not exist and we want to open the file readonly. With this change, we get a nicer error message: qemu-system-x86_64: can't open backing store tmp for guest RAM: Is a directory Note that the only memory-backend-file will end up calling memory_region_init_ram_from_file() -> qemu_ram_alloc_from_file() -> file_ram_open(). Reported-by: Thiner Logoer Signed-off-by: David Hildenbrand --- softmmu/physmem.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/softmmu/physmem.c b/softmmu/physmem.c index 9580567608..91f5f4c2a3 100644 --- a/softmmu/physmem.c +++ b/softmmu/physmem.c @@ -1300,6 +1300,25 @@ static int file_ram_open(const char *path, for (;;) { fd = open(path, readonly ? O_RDONLY : O_RDWR); if (fd >= 0) { + /* + * open(O_RDONLY) won't fail with EISDIR. Check manually if we + * opened a directory and fail similarly to how we fail ENOENT + * in readonly mode. Note that mkstemp() would imply O_RDWR. + */ + if (readonly) { + struct stat file_stat; + + if (fstat(fd, &file_stat)) { + close(fd); + if (errno == EINTR) { + continue; + } + return -errno; + } else if (S_ISDIR(file_stat.st_mode)) { + close(fd); + return -EISDIR; + } + } /* @path names an existing file, use it */ break; }