qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Peter Xu <peterx@redhat.com>
To: Ben Chaney <bchaney@akamai.com>
Cc: berrange@redhat.com, farosas@suse.de, armbru@redhat.com,
	mark.kanda@oracle.com, qemu-devel@nongnu.org, johunt@akamai.com,
	mtottenh@akamai.com, nhudson@akamai.com
Subject: Re: [PATCH] migration: cpr socket permissions fix
Date: Fri, 21 Nov 2025 11:07:48 -0500	[thread overview]
Message-ID: <aSCOVNMJ-NK_9PuH@x1.local> (raw)
In-Reply-To: <20251120185733.141912-1-bchaney@akamai.com>

On Thu, Nov 20, 2025 at 01:57:33PM -0500, Ben Chaney wrote:
> Fix an issue where cpr transfer fails when running with the
> -run-with user=$USERID with a permission denied error. This issue
> occurs because the destination host creates the transfer sockets before
> it drops permissions while the source host tries to connect after
> dropping permissions. Fix this by changing the ownership of the cpr
> socket to the lower level so it is accessible to both parties.
> 
> Resolves: https://lore.kernel.org/all/3D32B62F-29E2-4470-86A5-9A2B3B29E371@akamai.com/
> Signed-off-by: Ben Chaney <bchaney@akamai.com>
> ---
>  include/system/os-posix.h |  1 +
>  include/system/os-wasm.h  |  1 +
>  include/system/os-win32.h |  1 +
>  os-posix.c                | 12 ++++++++++++
>  stubs/meson.build         |  1 +
>  stubs/os-file.c           |  6 ++++++
>  util/qemu-sockets.c       |  6 ++++++
>  7 files changed, 28 insertions(+)
>  create mode 100644 stubs/os-file.c
> 
> diff --git a/include/system/os-posix.h b/include/system/os-posix.h
> index ce5b3bccf8..e4b69fc316 100644
> --- a/include/system/os-posix.h
> +++ b/include/system/os-posix.h
> @@ -54,6 +54,7 @@ void os_set_chroot(const char *path);
>  void os_setup_limits(void);
>  void os_setup_post(void);
>  int os_mlock(bool on_fault);
> +void os_set_socket_permissions(const char *path);
>  
>  /**
>   * qemu_alloc_stack:
> diff --git a/include/system/os-wasm.h b/include/system/os-wasm.h
> index 3abb3aaa03..eeac092183 100644
> --- a/include/system/os-wasm.h
> +++ b/include/system/os-wasm.h
> @@ -57,6 +57,7 @@ static inline int os_set_daemonize(bool d)
>  };
>  bool is_daemonized(void);
>  static inline void os_daemonize(void) {}
> +static inline void os_set_socket_permissions(const char *dummy) {};
>  
>  /**
>   * qemu_alloc_stack:
> diff --git a/include/system/os-win32.h b/include/system/os-win32.h
> index 22d72babdf..79e42ec297 100644
> --- a/include/system/os-win32.h
> +++ b/include/system/os-win32.h
> @@ -103,6 +103,7 @@ static inline void os_setup_post(void) {}
>  static inline void os_set_proc_name(const char *dummy) {}
>  void os_set_line_buffering(void);
>  void os_setup_early_signal_handling(void);
> +static inline void os_set_socket_permissions(const char *dummy) {};
>  
>  int getpagesize(void);
>  
> diff --git a/os-posix.c b/os-posix.c
> index 52925c23d3..bbd17ff2b9 100644
> --- a/os-posix.c
> +++ b/os-posix.c
> @@ -94,6 +94,18 @@ static struct passwd *user_pwd;    /*   NULL   non-NULL   NULL   */
>  static uid_t user_uid = (uid_t)-1; /*   -1      -1        >=0    */
>  static gid_t user_gid = (gid_t)-1; /*   -1      -1        >=0    */
>  
> +void os_set_socket_permissions(const char *path)
> +{
> +    uid_t uid = user_pwd ? user_pwd->pw_uid : user_uid;
> +    gid_t gid = user_pwd ? user_pwd->pw_gid : user_gid;
> +
> +    if (chown(path, uid, gid) < 0) {
> +        error_report("Failed to chown socket %s: %s", path, strerror(errno));
> +        exit(1);
> +    }
> +}
> +
> +
>  /*
>   * Prepare to change user ID. user_id can be one of 3 forms:
>   *   - a username, in which case user ID will be changed to its uid,
> diff --git a/stubs/meson.build b/stubs/meson.build
> index 0b2778c568..4a4342344b 100644
> --- a/stubs/meson.build
> +++ b/stubs/meson.build
> @@ -24,6 +24,7 @@ if have_block
>    stub_ss.add(files('ram-block.c'))
>    stub_ss.add(files('runstate-check.c'))
>    stub_ss.add(files('uuid.c'))
> +  stub_ss.add(files('os-file.c'))
>  endif
>  
>  if have_block or have_ga
> diff --git a/stubs/os-file.c b/stubs/os-file.c
> new file mode 100644
> index 0000000000..c32cbc7efa
> --- /dev/null
> +++ b/stubs/os-file.c
> @@ -0,0 +1,6 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +#include "qemu/osdep.h"
> +
> +void os_set_socket_permissions(const char *dummy)
> +{
> +}
> diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c
> index 4773755fd5..77b2d9287b 100644
> --- a/util/qemu-sockets.c
> +++ b/util/qemu-sockets.c
> @@ -1026,6 +1026,12 @@ static int unix_listen_saddr(UnixSocketAddress *saddr,
>          error_setg_errno(errp, errno, "Failed to bind socket to %s", path);
>          goto err;
>      }
> +    /*
> +     * Change the permissions on the socket to match the permission of the
> +     * counterparty process
> +     */
> +    os_set_socket_permissions(un.sun_path);

QEMU's -run-with described user= as:

  user=username or user=uid:gid can be used to drop root privileges before
  starting guest execution. QEMU will use the setuid and setgid system
  calls to switch to the specified identity...

So it explicitly mentioned "before starting guest execution", hence at
least from that doc it's hard to say if unix socket should be created with
the privilege or after dropped..  Here I believe cpr socket should be the
case for latter, however when it's a generic change to unix listening
ports, I wonder if there's other unwanted side effects.

Considering unix socket itself doesn't really have a UID attached to it,
it's only the unix path that needs a chmod(), meanwhile the mgmt of course
knows both the right UID (as specified in -run-with) and the path, would it
make sense if the mgmt chmod() after it starts dest QEMU?  That'll reduce
the scope of impact to minimum.

Thanks,

> +
>      if (listen(sock, num) < 0) {
>          error_setg_errno(errp, errno, "Failed to listen on socket");
>          goto err;
> -- 
> 2.34.1
> 

-- 
Peter Xu



  reply	other threads:[~2025-11-22  1:56 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-11-20 18:57 [PATCH] migration: cpr socket permissions fix Ben Chaney
2025-11-21 16:07 ` Peter Xu [this message]
2025-11-21 16:54   ` Daniel P. Berrangé

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=aSCOVNMJ-NK_9PuH@x1.local \
    --to=peterx@redhat.com \
    --cc=armbru@redhat.com \
    --cc=bchaney@akamai.com \
    --cc=berrange@redhat.com \
    --cc=farosas@suse.de \
    --cc=johunt@akamai.com \
    --cc=mark.kanda@oracle.com \
    --cc=mtottenh@akamai.com \
    --cc=nhudson@akamai.com \
    --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).