From: "Daniel P. Berrangé" <berrange@redhat.com>
To: Li Zhijian <lizhijian@cn.fujitsu.com>
Cc: kwolf@redhat.com, qemu-devel@nongnu.org, qemu-block@nongnu.org,
mreitz@redhat.com
Subject: Re: [PATCH v2] block: Improve backing file validation
Date: Tue, 11 May 2021 09:35:44 +0100 [thread overview]
Message-ID: <YJpB4IVbg8vHBiOZ@redhat.com> (raw)
In-Reply-To: <20210511055518.31876-1-lizhijian@cn.fujitsu.com>
On Tue, May 11, 2021 at 01:55:18PM +0800, Li Zhijian wrote:
> Image below user cases:
> case 1:
> ```
> $ qemu-img create -f raw source.raw 1G
> $ qemu-img create -f qcow2 -F raw -b source.raw ./source.raw
> qemu-img info source.raw
> image: source.raw
> file format: qcow2
> virtual size: 193K (197120 bytes)
> disk size: 196K
> cluster_size: 65536
> backing file: source.raw <<<<<<
> backing file format: raw
> Format specific information:
> compat: 1.1
> lazy refcounts: false
> refcount bits: 16
> corrupt: false
> ```
>
> case 2:
> ```
> $ qemu-img create -f raw source.raw 1G
> $ ln -sf source.raw destination.qcow2
> $ qemu-img create -f qcow2 -F raw -b source.raw ./destination.qcow2
> qemu-img info source.raw
> image: source.raw
> file format: qcow2 <<<<<<
> virtual size: 2.0G (2147483648 bytes)
> disk size: 196K
> cluster_size: 65536
> backing file: source.raw
> backing file format: raw
> Format specific information:
> compat: 1.1
> lazy refcounts: false
> refcount bits: 16
> corrupt: false
> ```
> Generally, we don't expect to corrupte the source.raw anyway, while
> actually it does.
>
> Here we check their inode number instead of file name.
>
> Suggested-by: Daniel P. Berrangé <berrange@redhat.com>
> Signed-off-by: Li Zhijian <lizhijian@cn.fujitsu.com>
>
> ---
> v2: utilize stat() instead of realpath() (Daniel)
>
> Signed-off-by: Li Zhijian <lizhijian@cn.fujitsu.com>
> ---
> block.c | 39 ++++++++++++++++++++++++++++++++-------
> 1 file changed, 32 insertions(+), 7 deletions(-)
>
> diff --git a/block.c b/block.c
> index 9ad725d205..db4ae57959 100644
> --- a/block.c
> +++ b/block.c
> @@ -6431,6 +6431,37 @@ bool bdrv_op_blocker_is_empty(BlockDriverState *bs)
> return true;
> }
>
> +static bool validate_backing_file(const char *filename,
> + const char *backing_file, Error **errp)
> +{
> + struct stat filename_stat, backing_stat;
> +
> + if (backing_file[0] == '\0') {
> + error_setg(errp, "Expected backing file name, got empty string");
> + goto out;
> + }
> +
> + /* check whether filename and backing_file are refering to the same file */
> + if (stat(backing_file, &backing_stat) == -1) {
> + error_setg(errp, "Cannot stat backing file %s", backing_file);
> + goto out;
> + }
> + if (stat(filename, &filename_stat) == -1) {
> + /* Simply consider filename doesn't exist, no need to further check */
> + return true;
> + }
> + if ((filename_stat.st_dev == backing_stat.st_dev) &&
> + (filename_stat.st_ino == backing_stat.st_ino)) {
> + error_setg(errp, "Error: Trying to create an image with the "
> + "same filename as the backing file");
> + goto out;
> + }
> +
> + return true;
> +out:
> + return false;
> +}
> +
> void bdrv_img_create(const char *filename, const char *fmt,
> const char *base_filename, const char *base_fmt,
> char *options, uint64_t img_size, int flags, bool quiet,
> @@ -6507,13 +6538,7 @@ void bdrv_img_create(const char *filename, const char *fmt,
>
> backing_file = qemu_opt_get(opts, BLOCK_OPT_BACKING_FILE);
> if (backing_file) {
> - if (!strcmp(filename, backing_file)) {
> - error_setg(errp, "Error: Trying to create an image with the "
> - "same filename as the backing file");
> - goto out;
> - }
> - if (backing_file[0] == '\0') {
> - error_setg(errp, "Expected backing file name, got empty string");
> + if (!validate_backing_file(filename, backing_file, errp)) {
> goto out;
> }
> }
Thinking about this again, this seems to be quite high in the generic block
layer code. As such I don't think we can assume that the backing file here
is actually a plain file on disk. IIUC the backing file could still be any
of the block drivers. Only once we get down into the protocol specific
drivers can be validate the type of backend.
I'm not sure what the right way to deal with that is, so perhaps Kevin or
Max can make a suggestion.
Regards,
Daniel
--
|: https://berrange.com -o- https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o- https://fstop138.berrange.com :|
|: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|
next prev parent reply other threads:[~2021-05-11 9:03 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-05-11 5:55 [PATCH v2] block: Improve backing file validation Li Zhijian
2021-05-11 8:35 ` Daniel P. Berrangé [this message]
2021-05-12 15:10 ` Kevin Wolf
2021-05-17 7:28 ` lizhijian
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=YJpB4IVbg8vHBiOZ@redhat.com \
--to=berrange@redhat.com \
--cc=kwolf@redhat.com \
--cc=lizhijian@cn.fujitsu.com \
--cc=mreitz@redhat.com \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).