All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 1/6] 9pfs: fix qemu_mknodat(S_IFREG) on macOS
  2022-04-27 18:58 [PATCH v4 0/6] 9pfs: macOS host fixes Christian Schoenebeck
@ 2022-04-27 18:54 ` Christian Schoenebeck
  2022-04-27 20:16   ` Greg Kurz
  2022-04-27 18:54 ` [PATCH v4 2/6] 9pfs: fix qemu_mknodat(S_IFSOCK) " Christian Schoenebeck
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 12+ messages in thread
From: Christian Schoenebeck @ 2022-04-27 18:54 UTC (permalink / raw)
  To: qemu-devel
  Cc: Will Cohen, Greg Kurz, Michael Roitzsch, Keno Fischer,
	Akihiko Odaki, qemu-stable

mknod() on macOS does not support creating regular files, so
divert to openat_file() if S_IFREG is passed with mode argument.

Furthermore, 'man 2 mknodat' on Linux says: "Zero file type is
equivalent to type S_IFREG".

Link: https://lore.kernel.org/qemu-devel/17933734.zYzKuhC07K@silver/
Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
Reviewed-by: Will Cohen <wwcohen@gmail.com>
Reviewed-by: Greg Kurz <groug@kaod.org>
---
 hw/9pfs/9p-util-darwin.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/hw/9pfs/9p-util-darwin.c b/hw/9pfs/9p-util-darwin.c
index bec0253474..e24d09763a 100644
--- a/hw/9pfs/9p-util-darwin.c
+++ b/hw/9pfs/9p-util-darwin.c
@@ -77,6 +77,15 @@ int fsetxattrat_nofollow(int dirfd, const char *filename, const char *name,
 int qemu_mknodat(int dirfd, const char *filename, mode_t mode, dev_t dev)
 {
     int preserved_errno, err;
+
+    if (S_ISREG(mode) || !(mode & S_IFMT)) {
+        int fd = openat_file(dirfd, filename, O_CREAT, mode);
+        if (fd == -1) {
+            return fd;
+        }
+        close(fd);
+        return 0;
+    }
     if (!pthread_fchdir_np) {
         error_report_once("pthread_fchdir_np() not available on this version of macOS");
         return -ENOTSUP;
-- 
2.32.0 (Apple Git-132)



^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v4 2/6] 9pfs: fix qemu_mknodat(S_IFSOCK) on macOS
  2022-04-27 18:58 [PATCH v4 0/6] 9pfs: macOS host fixes Christian Schoenebeck
  2022-04-27 18:54 ` [PATCH v4 1/6] 9pfs: fix qemu_mknodat(S_IFREG) on macOS Christian Schoenebeck
@ 2022-04-27 18:54 ` Christian Schoenebeck
  2022-04-27 20:36   ` Greg Kurz
  2022-04-27 18:54 ` [PATCH v4 3/6] 9pfs: fix wrong encoding of rdev field in Rgetattr " Christian Schoenebeck
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 12+ messages in thread
From: Christian Schoenebeck @ 2022-04-27 18:54 UTC (permalink / raw)
  To: qemu-devel
  Cc: Will Cohen, Greg Kurz, Michael Roitzsch, Keno Fischer,
	Akihiko Odaki, qemu-stable

mknod() on macOS does not support creating sockets, so divert to
call sequence socket(), bind() and fchmodat() respectively if S_IFSOCK
was passed with mode argument.

Link: https://lore.kernel.org/qemu-devel/17933734.zYzKuhC07K@silver/
Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
---
 hw/9pfs/9p-util-darwin.c | 45 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 44 insertions(+), 1 deletion(-)

diff --git a/hw/9pfs/9p-util-darwin.c b/hw/9pfs/9p-util-darwin.c
index e24d09763a..7d00db47a9 100644
--- a/hw/9pfs/9p-util-darwin.c
+++ b/hw/9pfs/9p-util-darwin.c
@@ -74,6 +74,45 @@ int fsetxattrat_nofollow(int dirfd, const char *filename, const char *name,
  */
 #if defined CONFIG_PTHREAD_FCHDIR_NP
 
+static int create_socket_file_at_cwd(const char *filename, mode_t mode) {
+    int fd, err;
+    struct sockaddr_un addr = {
+        .sun_family = AF_UNIX
+    };
+
+    /*
+     * sun_path is only 104 bytes, explicit filename length check required
+     */
+    if (sizeof(addr.sun_path) - 1 < strlen(filename) + 2) {
+        errno = ENAMETOOLONG;
+        return -1;
+    }
+    fd = socket(PF_UNIX, SOCK_DGRAM, 0);
+    if (fd == -1) {
+        return fd;
+    }
+    snprintf(addr.sun_path, sizeof(addr.sun_path), "./%s", filename);
+    err = bind(fd, (struct sockaddr *) &addr, sizeof(addr));
+    if (err == -1) {
+        goto out;
+    }
+    /*
+     * FIXME: Should rather be using descriptor-based fchmod() on the
+     * socket file descriptor above (preferably before bind() call),
+     * instead of path-based fchmodat(), to prevent concurrent transient
+     * state issues between creating the named FIFO file at bind() and
+     * delayed adjustment of permissions at fchmodat(). However currently
+     * macOS (12.x) does not support such operations on socket file
+     * descriptors yet.
+     *
+     * Filed report with Apple: FB9997731
+     */
+    err = fchmodat(AT_FDCWD, filename, mode, AT_SYMLINK_NOFOLLOW_ANY);
+out:
+    close_preserve_errno(fd);
+    return err;
+}
+
 int qemu_mknodat(int dirfd, const char *filename, mode_t mode, dev_t dev)
 {
     int preserved_errno, err;
@@ -93,7 +132,11 @@ int qemu_mknodat(int dirfd, const char *filename, mode_t mode, dev_t dev)
     if (pthread_fchdir_np(dirfd) < 0) {
         return -1;
     }
-    err = mknod(filename, mode, dev);
+    if (S_ISSOCK(mode)) {
+        err = create_socket_file_at_cwd(filename, mode);
+    } else {
+        err = mknod(filename, mode, dev);
+    }
     preserved_errno = errno;
     /* Stop using the thread-local cwd */
     pthread_fchdir_np(-1);
-- 
2.32.0 (Apple Git-132)



^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v4 3/6] 9pfs: fix wrong encoding of rdev field in Rgetattr on macOS
  2022-04-27 18:58 [PATCH v4 0/6] 9pfs: macOS host fixes Christian Schoenebeck
  2022-04-27 18:54 ` [PATCH v4 1/6] 9pfs: fix qemu_mknodat(S_IFREG) on macOS Christian Schoenebeck
  2022-04-27 18:54 ` [PATCH v4 2/6] 9pfs: fix qemu_mknodat(S_IFSOCK) " Christian Schoenebeck
@ 2022-04-27 18:54 ` Christian Schoenebeck
  2022-04-27 18:54 ` [PATCH v4 4/6] 9pfs: fix wrong errno being sent to Linux client on macOS host Christian Schoenebeck
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 12+ messages in thread
From: Christian Schoenebeck @ 2022-04-27 18:54 UTC (permalink / raw)
  To: qemu-devel
  Cc: Will Cohen, Greg Kurz, Michael Roitzsch, Keno Fischer,
	Akihiko Odaki, qemu-stable

The 'rdev' field in 9p reponse 'Rgetattr' is of type dev_t,
which is actually a system dependant type and therefore both the
size and encoding of dev_t differ between macOS and Linux.

So far we have sent 'rdev' to guest in host's dev_t format as-is,
which caused devices to appear with wrong device numbers on
guests running on macOS hosts, eventually leading to various
misbehaviours on guest in conjunction with device files.

This patch fixes this issue by converting the device number from
host's dev_t format to Linux dev_t format. As 9p request
'Tgettattr' is exclusive to protocol version 9p2000.L, it should
be fair to assume that 'rdev' field is assumed to be in Linux dev_t
format by client as well.

Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
Link: https://lore.kernel.org/qemu-devel/20220421093056.5ab1e7ed@bahia/
Reviewed-by: Greg Kurz <groug@kaod.org>
---
 hw/9pfs/9p-util.h | 39 +++++++++++++++++++++++++++++++++++++++
 hw/9pfs/9p.c      |  2 +-
 2 files changed, 40 insertions(+), 1 deletion(-)

diff --git a/hw/9pfs/9p-util.h b/hw/9pfs/9p-util.h
index 97e681e167..2cc9a5dbfb 100644
--- a/hw/9pfs/9p-util.h
+++ b/hw/9pfs/9p-util.h
@@ -19,6 +19,45 @@
 #define O_PATH_9P_UTIL 0
 #endif
 
+#if !defined(CONFIG_LINUX)
+
+/*
+ * Generates a Linux device number (a.k.a. dev_t) for given device major
+ * and minor numbers.
+ *
+ * To be more precise: it generates a device number in glibc's format
+ * (MMMM_Mmmm_mmmM_MMmm, 64 bits) actually, which is compatible with
+ * Linux's format (mmmM_MMmm, 32 bits), as described in <bits/sysmacros.h>.
+ */
+static inline uint64_t makedev_dotl(uint32_t dev_major, uint32_t dev_minor)
+{
+    uint64_t dev;
+
+    // from glibc sysmacros.h:
+    dev  = (((uint64_t) (dev_major & 0x00000fffu)) <<  8);
+    dev |= (((uint64_t) (dev_major & 0xfffff000u)) << 32);
+    dev |= (((uint64_t) (dev_minor & 0x000000ffu)) <<  0);
+    dev |= (((uint64_t) (dev_minor & 0xffffff00u)) << 12);
+    return dev;
+}
+
+#endif
+
+/*
+ * Converts given device number from host's device number format to Linux
+ * device number format. As both the size of type dev_t and encoding of
+ * dev_t is system dependant, we have to convert them for Linux guests if
+ * host is not running Linux.
+ */
+static inline uint64_t host_dev_to_dotl_dev(dev_t dev)
+{
+#ifdef CONFIG_LINUX
+    return dev;
+#else
+    return makedev_dotl(major(dev), minor(dev));
+#endif
+}
+
 #ifdef CONFIG_DARWIN
 #define qemu_fgetxattr(...) fgetxattr(__VA_ARGS__, 0, 0)
 #define qemu_lgetxattr(...) getxattr(__VA_ARGS__, 0, XATTR_NOFOLLOW)
diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
index 225f31fc31..4a296a0b94 100644
--- a/hw/9pfs/9p.c
+++ b/hw/9pfs/9p.c
@@ -1327,7 +1327,7 @@ static int stat_to_v9stat_dotl(V9fsPDU *pdu, const struct stat *stbuf,
     v9lstat->st_nlink = stbuf->st_nlink;
     v9lstat->st_uid = stbuf->st_uid;
     v9lstat->st_gid = stbuf->st_gid;
-    v9lstat->st_rdev = stbuf->st_rdev;
+    v9lstat->st_rdev = host_dev_to_dotl_dev(stbuf->st_rdev);
     v9lstat->st_size = stbuf->st_size;
     v9lstat->st_blksize = stat_to_iounit(pdu, stbuf);
     v9lstat->st_blocks = stbuf->st_blocks;
-- 
2.32.0 (Apple Git-132)



^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v4 4/6] 9pfs: fix wrong errno being sent to Linux client on macOS host
  2022-04-27 18:58 [PATCH v4 0/6] 9pfs: macOS host fixes Christian Schoenebeck
                   ` (2 preceding siblings ...)
  2022-04-27 18:54 ` [PATCH v4 3/6] 9pfs: fix wrong encoding of rdev field in Rgetattr " Christian Schoenebeck
@ 2022-04-27 18:54 ` Christian Schoenebeck
  2022-04-27 18:54 ` [PATCH v4 5/6] 9pfs: fix removing non-existent POSIX ACL xattr " Christian Schoenebeck
  2022-04-27 18:56 ` [PATCH v4 6/6] 9pfs: fix qemu_mknodat() to always return -1 on error " Christian Schoenebeck
  5 siblings, 0 replies; 12+ messages in thread
From: Christian Schoenebeck @ 2022-04-27 18:54 UTC (permalink / raw)
  To: qemu-devel
  Cc: Will Cohen, Greg Kurz, Michael Roitzsch, Keno Fischer,
	Akihiko Odaki, qemu-stable

Linux and macOS only share some errno definitions with equal macro
name and value. In fact most mappings for errno are completely
different on the two systems.

This patch converts some important errno values from macOS host to
corresponding Linux errno values before eventually sending such error
codes along with 'Rlerror' replies (if 9p2000.L is used that is). Not
having translated errnos before violated the 9p2000.L protocol spec,
which says:

  "
  size[4] Rlerror tag[2] ecode[4]

  ... ecode is a numerical Linux errno.
  "

  https://github.com/chaos/diod/wiki/protocol#lerror----return-error-code

This patch fixes a bunch of misbehaviours when running a Linux client
on macOS host. For instance this patch fixes:

  mount -t 9p -o posixacl ...

on Linux guest if security_mode=mapped was used for 9p server, which
refused to mount successfully, because macOS returned ENOATTR==93
when client tried to retrieve POSIX ACL xattrs, because errno 93
is defined as EPROTONOSUPPORT==93 on Linux, so Linux client believed
that xattrs were not supported by filesystem on host in general.

Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
Link: https://lore.kernel.org/qemu-devel/20220421124835.3e664669@bahia/
Reviewed-by: Greg Kurz <groug@kaod.org>
---
 hw/9pfs/9p-util.h | 30 ++++++++++++++++++++++++++++++
 hw/9pfs/9p.c      |  2 ++
 2 files changed, 32 insertions(+)

diff --git a/hw/9pfs/9p-util.h b/hw/9pfs/9p-util.h
index 2cc9a5dbfb..c3526144c9 100644
--- a/hw/9pfs/9p-util.h
+++ b/hw/9pfs/9p-util.h
@@ -58,6 +58,36 @@ static inline uint64_t host_dev_to_dotl_dev(dev_t dev)
 #endif
 }
 
+/* Translates errno from host -> Linux if needed */
+static inline int errno_to_dotl(int err) {
+#if defined(CONFIG_LINUX)
+    /* nothing to translate (Linux -> Linux) */
+#elif defined(CONFIG_DARWIN)
+    /*
+     * translation mandatory for macOS hosts
+     *
+     * FIXME: Only most important errnos translated here yet, this should be
+     * extended to as many errnos being translated as possible in future.
+     */
+    if (err == ENAMETOOLONG) {
+        err = 36; /* ==ENAMETOOLONG on Linux */
+    } else if (err == ENOTEMPTY) {
+        err = 39; /* ==ENOTEMPTY on Linux */
+    } else if (err == ELOOP) {
+        err = 40; /* ==ELOOP on Linux */
+    } else if (err == ENOATTR) {
+        err = 61; /* ==ENODATA on Linux */
+    } else if (err == ENOTSUP) {
+        err = 95; /* ==EOPNOTSUPP on Linux */
+    } else if (err == EOPNOTSUPP) {
+        err = 95; /* ==EOPNOTSUPP on Linux */
+    }
+#else
+#error Missing errno translation to Linux for this host system
+#endif
+    return err;
+}
+
 #ifdef CONFIG_DARWIN
 #define qemu_fgetxattr(...) fgetxattr(__VA_ARGS__, 0, 0)
 #define qemu_lgetxattr(...) getxattr(__VA_ARGS__, 0, XATTR_NOFOLLOW)
diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
index 4a296a0b94..0cd0c14c2a 100644
--- a/hw/9pfs/9p.c
+++ b/hw/9pfs/9p.c
@@ -1054,6 +1054,8 @@ static void coroutine_fn pdu_complete(V9fsPDU *pdu, ssize_t len)
             }
             len += ret;
             id = P9_RERROR;
+        } else {
+            err = errno_to_dotl(err);
         }
 
         ret = pdu_marshal(pdu, len, "d", err);
-- 
2.32.0 (Apple Git-132)



^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v4 5/6] 9pfs: fix removing non-existent POSIX ACL xattr on macOS host
  2022-04-27 18:58 [PATCH v4 0/6] 9pfs: macOS host fixes Christian Schoenebeck
                   ` (3 preceding siblings ...)
  2022-04-27 18:54 ` [PATCH v4 4/6] 9pfs: fix wrong errno being sent to Linux client on macOS host Christian Schoenebeck
@ 2022-04-27 18:54 ` Christian Schoenebeck
  2022-04-27 18:56 ` [PATCH v4 6/6] 9pfs: fix qemu_mknodat() to always return -1 on error " Christian Schoenebeck
  5 siblings, 0 replies; 12+ messages in thread
From: Christian Schoenebeck @ 2022-04-27 18:54 UTC (permalink / raw)
  To: qemu-devel
  Cc: Will Cohen, Greg Kurz, Michael Roitzsch, Keno Fischer,
	Akihiko Odaki, qemu-stable

When mapped POSIX ACL is used, we are ignoring errors when trying
to remove a POSIX ACL xattr that does not exist. On Linux hosts we
would get ENODATA in such cases, on macOS hosts however we get
ENOATTR instead.

As we can be sure that ENOATTR is defined as being identical on Linux
hosts (at least by qemu/xattr.h), it is safe to fix this issue by
simply comparing against ENOATTR instead of ENODATA.

This patch fixes e.g. a command on Linux guest like:

  cp --preserve=mode old new

Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
Link: https://lore.kernel.org/qemu-devel/2866993.yOYK24bMf6@silver/
Reviewed-by: Greg Kurz <groug@kaod.org>
---
 hw/9pfs/9p-posix-acl.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/hw/9pfs/9p-posix-acl.c b/hw/9pfs/9p-posix-acl.c
index eadae270dd..4b2cb3c66c 100644
--- a/hw/9pfs/9p-posix-acl.c
+++ b/hw/9pfs/9p-posix-acl.c
@@ -65,7 +65,11 @@ static int mp_pacl_removexattr(FsContext *ctx,
     int ret;
 
     ret = local_removexattr_nofollow(ctx, path, MAP_ACL_ACCESS);
-    if (ret == -1 && errno == ENODATA) {
+    /*
+     * macOS returns ENOATTR (!=ENODATA on macOS), whereas Linux returns
+     * ENODATA (==ENOATTR on Linux), so checking for ENOATTR is fine
+     */
+    if (ret == -1 && errno == ENOATTR) {
         /*
          * We don't get ENODATA error when trying to remove a
          * posix acl that is not present. So don't throw the error
@@ -115,7 +119,11 @@ static int mp_dacl_removexattr(FsContext *ctx,
     int ret;
 
     ret = local_removexattr_nofollow(ctx, path, MAP_ACL_DEFAULT);
-    if (ret == -1 && errno == ENODATA) {
+    /*
+     * macOS returns ENOATTR (!=ENODATA on macOS), whereas Linux returns
+     * ENODATA (==ENOATTR on Linux), so checking for ENOATTR is fine
+     */
+    if (ret == -1 && errno == ENOATTR) {
         /*
          * We don't get ENODATA error when trying to remove a
          * posix acl that is not present. So don't throw the error
-- 
2.32.0 (Apple Git-132)



^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v4 6/6] 9pfs: fix qemu_mknodat() to always return -1 on error on macOS host
  2022-04-27 18:58 [PATCH v4 0/6] 9pfs: macOS host fixes Christian Schoenebeck
                   ` (4 preceding siblings ...)
  2022-04-27 18:54 ` [PATCH v4 5/6] 9pfs: fix removing non-existent POSIX ACL xattr " Christian Schoenebeck
@ 2022-04-27 18:56 ` Christian Schoenebeck
  5 siblings, 0 replies; 12+ messages in thread
From: Christian Schoenebeck @ 2022-04-27 18:56 UTC (permalink / raw)
  To: qemu-devel
  Cc: Will Cohen, Greg Kurz, Michael Roitzsch, Keno Fischer,
	Akihiko Odaki, qemu-stable

qemu_mknodat() is expected to behave according to its POSIX API, and
therefore should always return exactly -1 on any error, and errno
should be set for the actual error code.

Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
Reviewed-by: Greg Kurz <groug@kaod.org>
---
 hw/9pfs/9p-util-darwin.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/hw/9pfs/9p-util-darwin.c b/hw/9pfs/9p-util-darwin.c
index 7d00db47a9..649a3ec61c 100644
--- a/hw/9pfs/9p-util-darwin.c
+++ b/hw/9pfs/9p-util-darwin.c
@@ -127,7 +127,8 @@ int qemu_mknodat(int dirfd, const char *filename, mode_t mode, dev_t dev)
     }
     if (!pthread_fchdir_np) {
         error_report_once("pthread_fchdir_np() not available on this version of macOS");
-        return -ENOTSUP;
+        errno = ENOTSUP;
+        return -1;
     }
     if (pthread_fchdir_np(dirfd) < 0) {
         return -1;
-- 
2.32.0 (Apple Git-132)



^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v4 0/6] 9pfs: macOS host fixes
@ 2022-04-27 18:58 Christian Schoenebeck
  2022-04-27 18:54 ` [PATCH v4 1/6] 9pfs: fix qemu_mknodat(S_IFREG) on macOS Christian Schoenebeck
                   ` (5 more replies)
  0 siblings, 6 replies; 12+ messages in thread
From: Christian Schoenebeck @ 2022-04-27 18:58 UTC (permalink / raw)
  To: qemu-devel
  Cc: Will Cohen, Greg Kurz, Michael Roitzsch, Keno Fischer,
	Akihiko Odaki, qemu-stable

A bunch of fixes for recently (in QEMU 7.0) added 9p support on macOS hosts.

Note: there are still issues to address with case-insensitive file systems
on macOS hosts. I sent a separate RFC on that icase issue:
https://lore.kernel.org/qemu-devel/1757498.AyhHxzoH2B@silver/

v3 -> v4:

  * Use fchmodat(AT_SYMLINK_NOFOLLOW_ANY) instead of chmod().
    [patch 2]

Christian Schoenebeck (6):
  9pfs: fix qemu_mknodat(S_IFREG) on macOS
  9pfs: fix qemu_mknodat(S_IFSOCK) on macOS
  9pfs: fix wrong encoding of rdev field in Rgetattr on macOS
  9pfs: fix wrong errno being sent to Linux client on macOS host
  9pfs: fix removing non-existent POSIX ACL xattr on macOS host
  9pfs: fix qemu_mknodat() to always return -1 on error on macOS host

 hw/9pfs/9p-posix-acl.c   | 12 +++++--
 hw/9pfs/9p-util-darwin.c | 57 +++++++++++++++++++++++++++++++--
 hw/9pfs/9p-util.h        | 69 ++++++++++++++++++++++++++++++++++++++++
 hw/9pfs/9p.c             |  4 ++-
 4 files changed, 137 insertions(+), 5 deletions(-)

-- 
2.32.0 (Apple Git-132)



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v4 1/6] 9pfs: fix qemu_mknodat(S_IFREG) on macOS
  2022-04-27 18:54 ` [PATCH v4 1/6] 9pfs: fix qemu_mknodat(S_IFREG) on macOS Christian Schoenebeck
@ 2022-04-27 20:16   ` Greg Kurz
  2022-04-28 11:42     ` Christian Schoenebeck
  0 siblings, 1 reply; 12+ messages in thread
From: Greg Kurz @ 2022-04-27 20:16 UTC (permalink / raw)
  To: Christian Schoenebeck
  Cc: qemu-devel, qemu-stable, Keno Fischer, Michael Roitzsch,
	Will Cohen, Akihiko Odaki

On Wed, 27 Apr 2022 20:54:04 +0200
Christian Schoenebeck <qemu_oss@crudebyte.com> wrote:

> mknod() on macOS does not support creating regular files, so
> divert to openat_file() if S_IFREG is passed with mode argument.
> 
> Furthermore, 'man 2 mknodat' on Linux says: "Zero file type is
> equivalent to type S_IFREG".
> 

Thinking again I have mixed feelings about this... qemu_mknodat()
should certainly match POSIX semantics, even non-portable, as
described in [1] but I'm not sure it should mimic linux-specific
behaviors.

[1] https://pubs.opengroup.org/onlinepubs/9699919799/functions/mknod.html

> Link: https://lore.kernel.org/qemu-devel/17933734.zYzKuhC07K@silver/
> Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
> Reviewed-by: Will Cohen <wwcohen@gmail.com>
> Reviewed-by: Greg Kurz <groug@kaod.org>
> ---
>  hw/9pfs/9p-util-darwin.c | 9 +++++++++
>  1 file changed, 9 insertions(+)
> 
> diff --git a/hw/9pfs/9p-util-darwin.c b/hw/9pfs/9p-util-darwin.c
> index bec0253474..e24d09763a 100644
> --- a/hw/9pfs/9p-util-darwin.c
> +++ b/hw/9pfs/9p-util-darwin.c
> @@ -77,6 +77,15 @@ int fsetxattrat_nofollow(int dirfd, const char *filename, const char *name,
>  int qemu_mknodat(int dirfd, const char *filename, mode_t mode, dev_t dev)
>  {
>      int preserved_errno, err;
> +
> +    if (S_ISREG(mode) || !(mode & S_IFMT)) {

... so maybe I'd just check S_ISREG() here. Not a request, just food
for thought : sticking to POSIX semantics might help to make the code
more portable across all the new host supports that are showing up
these days.

> +        int fd = openat_file(dirfd, filename, O_CREAT, mode);
> +        if (fd == -1) {
> +            return fd;
> +        }
> +        close(fd);
> +        return 0;
> +    }
>      if (!pthread_fchdir_np) {
>          error_report_once("pthread_fchdir_np() not available on this version of macOS");
>          return -ENOTSUP;



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v4 2/6] 9pfs: fix qemu_mknodat(S_IFSOCK) on macOS
  2022-04-27 18:54 ` [PATCH v4 2/6] 9pfs: fix qemu_mknodat(S_IFSOCK) " Christian Schoenebeck
@ 2022-04-27 20:36   ` Greg Kurz
  2022-04-28 11:22     ` Christian Schoenebeck
  0 siblings, 1 reply; 12+ messages in thread
From: Greg Kurz @ 2022-04-27 20:36 UTC (permalink / raw)
  To: Christian Schoenebeck
  Cc: qemu-devel, qemu-stable, Keno Fischer, Michael Roitzsch,
	Will Cohen, Akihiko Odaki

On Wed, 27 Apr 2022 20:54:17 +0200
Christian Schoenebeck <qemu_oss@crudebyte.com> wrote:

> mknod() on macOS does not support creating sockets, so divert to
> call sequence socket(), bind() and fchmodat() respectively if S_IFSOCK
> was passed with mode argument.
> 
> Link: https://lore.kernel.org/qemu-devel/17933734.zYzKuhC07K@silver/
> Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
> ---
>  hw/9pfs/9p-util-darwin.c | 45 +++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 44 insertions(+), 1 deletion(-)
> 
> diff --git a/hw/9pfs/9p-util-darwin.c b/hw/9pfs/9p-util-darwin.c
> index e24d09763a..7d00db47a9 100644
> --- a/hw/9pfs/9p-util-darwin.c
> +++ b/hw/9pfs/9p-util-darwin.c
> @@ -74,6 +74,45 @@ int fsetxattrat_nofollow(int dirfd, const char *filename, const char *name,
>   */
>  #if defined CONFIG_PTHREAD_FCHDIR_NP
>  
> +static int create_socket_file_at_cwd(const char *filename, mode_t mode) {
> +    int fd, err;
> +    struct sockaddr_un addr = {
> +        .sun_family = AF_UNIX
> +    };
> +
> +    /*
> +     * sun_path is only 104 bytes, explicit filename length check required
> +     */
> +    if (sizeof(addr.sun_path) - 1 < strlen(filename) + 2) {

True but I was a bit puzzled by the math until I realized the '+ 2' was
for the prepended "./" ;-)

> +        errno = ENAMETOOLONG;
> +        return -1;
> +    }
> +    fd = socket(PF_UNIX, SOCK_DGRAM, 0);
> +    if (fd == -1) {
> +        return fd;
> +    }
> +    snprintf(addr.sun_path, sizeof(addr.sun_path), "./%s", filename);

What about the more generic approach of checking snprintf()'s return
value ? If it is >= sizeof(addr.sun_path) then truncation occured.

> +    err = bind(fd, (struct sockaddr *) &addr, sizeof(addr));
> +    if (err == -1) {
> +        goto out;
> +    }
> +    /*
> +     * FIXME: Should rather be using descriptor-based fchmod() on the
> +     * socket file descriptor above (preferably before bind() call),
> +     * instead of path-based fchmodat(), to prevent concurrent transient
> +     * state issues between creating the named FIFO file at bind() and
> +     * delayed adjustment of permissions at fchmodat(). However currently
> +     * macOS (12.x) does not support such operations on socket file
> +     * descriptors yet.
> +     *
> +     * Filed report with Apple: FB9997731
> +     */
> +    err = fchmodat(AT_FDCWD, filename, mode, AT_SYMLINK_NOFOLLOW_ANY);
> +out:
> +    close_preserve_errno(fd);

You could close(fd) earlier now, but you might want to keep the code
as is in case FB9997731 gets proper attention.

Anyway, this should do the job so:

Reviewed-by: Greg Kurz <groug@kaod.org>

> +    return err;
> +}
> +
>  int qemu_mknodat(int dirfd, const char *filename, mode_t mode, dev_t dev)
>  {
>      int preserved_errno, err;
> @@ -93,7 +132,11 @@ int qemu_mknodat(int dirfd, const char *filename, mode_t mode, dev_t dev)
>      if (pthread_fchdir_np(dirfd) < 0) {
>          return -1;
>      }
> -    err = mknod(filename, mode, dev);
> +    if (S_ISSOCK(mode)) {
> +        err = create_socket_file_at_cwd(filename, mode);
> +    } else {
> +        err = mknod(filename, mode, dev);
> +    }
>      preserved_errno = errno;
>      /* Stop using the thread-local cwd */
>      pthread_fchdir_np(-1);



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v4 2/6] 9pfs: fix qemu_mknodat(S_IFSOCK) on macOS
  2022-04-27 20:36   ` Greg Kurz
@ 2022-04-28 11:22     ` Christian Schoenebeck
  2022-04-29  1:51       ` Akihiko Odaki
  0 siblings, 1 reply; 12+ messages in thread
From: Christian Schoenebeck @ 2022-04-28 11:22 UTC (permalink / raw)
  To: Greg Kurz
  Cc: qemu-devel, qemu-stable, Keno Fischer, Michael Roitzsch,
	Will Cohen, Akihiko Odaki

On Mittwoch, 27. April 2022 22:36:25 CEST Greg Kurz wrote:
> On Wed, 27 Apr 2022 20:54:17 +0200
> 
> Christian Schoenebeck <qemu_oss@crudebyte.com> wrote:
> > mknod() on macOS does not support creating sockets, so divert to
> > call sequence socket(), bind() and fchmodat() respectively if S_IFSOCK
> > was passed with mode argument.
> > 
> > Link: https://lore.kernel.org/qemu-devel/17933734.zYzKuhC07K@silver/
> > Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
> > ---
> > 
> >  hw/9pfs/9p-util-darwin.c | 45 +++++++++++++++++++++++++++++++++++++++-
> >  1 file changed, 44 insertions(+), 1 deletion(-)
> > 
> > diff --git a/hw/9pfs/9p-util-darwin.c b/hw/9pfs/9p-util-darwin.c
> > index e24d09763a..7d00db47a9 100644
> > --- a/hw/9pfs/9p-util-darwin.c
> > +++ b/hw/9pfs/9p-util-darwin.c
> > @@ -74,6 +74,45 @@ int fsetxattrat_nofollow(int dirfd, const char
> > *filename, const char *name,> 
> >   */
> >  
> >  #if defined CONFIG_PTHREAD_FCHDIR_NP
> > 
> > +static int create_socket_file_at_cwd(const char *filename, mode_t mode) {
> > +    int fd, err;
> > +    struct sockaddr_un addr = {
> > +        .sun_family = AF_UNIX
> > +    };
> > +
> > +    /*
> > +     * sun_path is only 104 bytes, explicit filename length check
> > required
> > +     */
> > +    if (sizeof(addr.sun_path) - 1 < strlen(filename) + 2) {
> 
> True but I was a bit puzzled by the math until I realized the '+ 2' was
> for the prepended "./" ;-)

Correct ...

> > +        errno = ENAMETOOLONG;
> > +        return -1;
> > +    }
> > +    fd = socket(PF_UNIX, SOCK_DGRAM, 0);
> > +    if (fd == -1) {
> > +        return fd;
> > +    }
> > +    snprintf(addr.sun_path, sizeof(addr.sun_path), "./%s", filename);
> 
> What about the more generic approach of checking snprintf()'s return
> value ? If it is >= sizeof(addr.sun_path) then truncation occured.

... well, I can send a v5 if you prefer that solution, or you can send a follow-up
patch later on. As you wish.

> > +    err = bind(fd, (struct sockaddr *) &addr, sizeof(addr));
> > +    if (err == -1) {
> > +        goto out;
> > +    }
> > +    /*
> > +     * FIXME: Should rather be using descriptor-based fchmod() on the
> > +     * socket file descriptor above (preferably before bind() call),
> > +     * instead of path-based fchmodat(), to prevent concurrent transient
> > +     * state issues between creating the named FIFO file at bind() and
> > +     * delayed adjustment of permissions at fchmodat(). However currently
> > +     * macOS (12.x) does not support such operations on socket file
> > +     * descriptors yet.
> > +     *
> > +     * Filed report with Apple: FB9997731
> > +     */
> > +    err = fchmodat(AT_FDCWD, filename, mode, AT_SYMLINK_NOFOLLOW_ANY);
> > +out:
> > +    close_preserve_errno(fd);
> 
> You could close(fd) earlier now, but you might want to keep the code
> as is in case FB9997731 gets proper attention.
> 
> Anyway, this should do the job so:

Sounds like Akihiko's previous suggestion. I would keep it that way:
https://lore.kernel.org/qemu-devel/eafd4bbf-dbff-323a-179f-8f29905701e1@gmail.com/

> Reviewed-by: Greg Kurz <groug@kaod.org>

Thanks!

Best regards,
Christian Schoenebeck

> > +    return err;
> > +}
> > +
> > 
> >  int qemu_mknodat(int dirfd, const char *filename, mode_t mode, dev_t dev)
> >  {
> >  
> >      int preserved_errno, err;
> > 
> > @@ -93,7 +132,11 @@ int qemu_mknodat(int dirfd, const char *filename,
> > mode_t mode, dev_t dev)> 
> >      if (pthread_fchdir_np(dirfd) < 0) {
> >      
> >          return -1;
> >      
> >      }
> > 
> > -    err = mknod(filename, mode, dev);
> > +    if (S_ISSOCK(mode)) {
> > +        err = create_socket_file_at_cwd(filename, mode);
> > +    } else {
> > +        err = mknod(filename, mode, dev);
> > +    }
> > 
> >      preserved_errno = errno;
> >      /* Stop using the thread-local cwd */
> >      pthread_fchdir_np(-1);




^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v4 1/6] 9pfs: fix qemu_mknodat(S_IFREG) on macOS
  2022-04-27 20:16   ` Greg Kurz
@ 2022-04-28 11:42     ` Christian Schoenebeck
  0 siblings, 0 replies; 12+ messages in thread
From: Christian Schoenebeck @ 2022-04-28 11:42 UTC (permalink / raw)
  To: Greg Kurz
  Cc: qemu-devel, qemu-stable, Keno Fischer, Michael Roitzsch,
	Will Cohen, Akihiko Odaki

On Mittwoch, 27. April 2022 22:16:12 CEST Greg Kurz wrote:
> On Wed, 27 Apr 2022 20:54:04 +0200
> 
> Christian Schoenebeck <qemu_oss@crudebyte.com> wrote:
> > mknod() on macOS does not support creating regular files, so
> > divert to openat_file() if S_IFREG is passed with mode argument.
> > 
> > Furthermore, 'man 2 mknodat' on Linux says: "Zero file type is
> > equivalent to type S_IFREG".
> 
> Thinking again I have mixed feelings about this... qemu_mknodat()
> should certainly match POSIX semantics, even non-portable, as
> described in [1] but I'm not sure it should mimic linux-specific
> behaviors.
> 
> [1] https://pubs.opengroup.org/onlinepubs/9699919799/functions/mknod.html
> 
> > Link: https://lore.kernel.org/qemu-devel/17933734.zYzKuhC07K@silver/
> > Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
> > Reviewed-by: Will Cohen <wwcohen@gmail.com>
> > Reviewed-by: Greg Kurz <groug@kaod.org>
> > ---
> > 
> >  hw/9pfs/9p-util-darwin.c | 9 +++++++++
> >  1 file changed, 9 insertions(+)
> > 
> > diff --git a/hw/9pfs/9p-util-darwin.c b/hw/9pfs/9p-util-darwin.c
> > index bec0253474..e24d09763a 100644
> > --- a/hw/9pfs/9p-util-darwin.c
> > +++ b/hw/9pfs/9p-util-darwin.c
> > @@ -77,6 +77,15 @@ int fsetxattrat_nofollow(int dirfd, const char
> > *filename, const char *name,> 
> >  int qemu_mknodat(int dirfd, const char *filename, mode_t mode, dev_t dev)
> >  {
> >  
> >      int preserved_errno, err;
> > 
> > +
> > +    if (S_ISREG(mode) || !(mode & S_IFMT)) {
> 
> ... so maybe I'd just check S_ISREG() here. Not a request, just food
> for thought : sticking to POSIX semantics might help to make the code
> more portable across all the new host supports that are showing up
> these days.

Well, handling !(mode & S_IFMT) (i.e. "zero file type") is needed "somewhere" 
for 9p2000.L to behave as expected on macOS hosts. So you might argue this 
could rather be handled in 9p.c instead and there only if protocol is exactly 
9p2000.L.

OTOH I currently don't see an issue here providing that default behaviour.

Best regards,
Christian Schoenebeck

> > +        int fd = openat_file(dirfd, filename, O_CREAT, mode);
> > +        if (fd == -1) {
> > +            return fd;
> > +        }
> > +        close(fd);
> > +        return 0;
> > +    }
> > 
> >      if (!pthread_fchdir_np) {
> >      
> >          error_report_once("pthread_fchdir_np() not available on this
> >          version of macOS"); return -ENOTSUP;




^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v4 2/6] 9pfs: fix qemu_mknodat(S_IFSOCK) on macOS
  2022-04-28 11:22     ` Christian Schoenebeck
@ 2022-04-29  1:51       ` Akihiko Odaki
  0 siblings, 0 replies; 12+ messages in thread
From: Akihiko Odaki @ 2022-04-29  1:51 UTC (permalink / raw)
  To: Christian Schoenebeck, Greg Kurz
  Cc: Keno Fischer, Michael Roitzsch, Will Cohen, qemu-devel, qemu-stable

On 2022/04/28 20:22, Christian Schoenebeck wrote:
> On Mittwoch, 27. April 2022 22:36:25 CEST Greg Kurz wrote:
>> On Wed, 27 Apr 2022 20:54:17 +0200
>>
>> Christian Schoenebeck <qemu_oss@crudebyte.com> wrote:
>>> mknod() on macOS does not support creating sockets, so divert to
>>> call sequence socket(), bind() and fchmodat() respectively if S_IFSOCK
>>> was passed with mode argument.
>>>
>>> Link: https://lore.kernel.org/qemu-devel/17933734.zYzKuhC07K@silver/
>>> Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
>>> ---
>>>
>>>   hw/9pfs/9p-util-darwin.c | 45 +++++++++++++++++++++++++++++++++++++++-
>>>   1 file changed, 44 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/hw/9pfs/9p-util-darwin.c b/hw/9pfs/9p-util-darwin.c
>>> index e24d09763a..7d00db47a9 100644
>>> --- a/hw/9pfs/9p-util-darwin.c
>>> +++ b/hw/9pfs/9p-util-darwin.c
>>> @@ -74,6 +74,45 @@ int fsetxattrat_nofollow(int dirfd, const char
>>> *filename, const char *name,>
>>>    */
>>>   
>>>   #if defined CONFIG_PTHREAD_FCHDIR_NP
>>>
>>> +static int create_socket_file_at_cwd(const char *filename, mode_t mode) {
>>> +    int fd, err;
>>> +    struct sockaddr_un addr = {
>>> +        .sun_family = AF_UNIX
>>> +    };
>>> +
>>> +    /*
>>> +     * sun_path is only 104 bytes, explicit filename length check
>>> required
>>> +     */
>>> +    if (sizeof(addr.sun_path) - 1 < strlen(filename) + 2) {
>>
>> True but I was a bit puzzled by the math until I realized the '+ 2' was
>> for the prepended "./" ;-)
> 
> Correct ...
> 
>>> +        errno = ENAMETOOLONG;
>>> +        return -1;
>>> +    }
>>> +    fd = socket(PF_UNIX, SOCK_DGRAM, 0);
>>> +    if (fd == -1) {
>>> +        return fd;
>>> +    }
>>> +    snprintf(addr.sun_path, sizeof(addr.sun_path), "./%s", filename);
>>
>> What about the more generic approach of checking snprintf()'s return
>> value ? If it is >= sizeof(addr.sun_path) then truncation occured.
> 
> ... well, I can send a v5 if you prefer that solution, or you can send a follow-up
> patch later on. As you wish.

I also prefer that solution and would like to see v5. The checking code 
has a redundant knowledge about how the output length becomes, and it is 
dangerous if it becomes out of sync with the snprintf() call. Using the 
value returned by snprintf() would eliminate such a potential 
programming error in the future.

> 
>>> +    err = bind(fd, (struct sockaddr *) &addr, sizeof(addr));
>>> +    if (err == -1) {
>>> +        goto out;
>>> +    }
>>> +    /*
>>> +     * FIXME: Should rather be using descriptor-based fchmod() on the
>>> +     * socket file descriptor above (preferably before bind() call),
>>> +     * instead of path-based fchmodat(), to prevent concurrent transient
>>> +     * state issues between creating the named FIFO file at bind() and
>>> +     * delayed adjustment of permissions at fchmodat(). However currently
>>> +     * macOS (12.x) does not support such operations on socket file
>>> +     * descriptors yet.
>>> +     *
>>> +     * Filed report with Apple: FB9997731
>>> +     */
>>> +    err = fchmodat(AT_FDCWD, filename, mode, AT_SYMLINK_NOFOLLOW_ANY);
>>> +out:
>>> +    close_preserve_errno(fd);
>>
>> You could close(fd) earlier now, but you might want to keep the code
>> as is in case FB9997731 gets proper attention.
>>
>> Anyway, this should do the job so:
> 
> Sounds like Akihiko's previous suggestion. I would keep it that way:
> https://lore.kernel.org/qemu-devel/eafd4bbf-dbff-323a-179f-8f29905701e1@gmail.com/
I don't think it would need an extra code change when FB9997731 is 
resolved even if you close the socket immediately after bind(). However, 
I'm not pursuing such a change since doing so would have the same 
trade-off my previous suggestion as Christian noted.

Regards,
Akihiko Odaki

> 
>> Reviewed-by: Greg Kurz <groug@kaod.org>
> 
> Thanks!
> 
> Best regards,
> Christian Schoenebeck
> 
>>> +    return err;
>>> +}
>>> +
>>>
>>>   int qemu_mknodat(int dirfd, const char *filename, mode_t mode, dev_t dev)
>>>   {
>>>   
>>>       int preserved_errno, err;
>>>
>>> @@ -93,7 +132,11 @@ int qemu_mknodat(int dirfd, const char *filename,
>>> mode_t mode, dev_t dev)>
>>>       if (pthread_fchdir_np(dirfd) < 0) {
>>>       
>>>           return -1;
>>>       
>>>       }
>>>
>>> -    err = mknod(filename, mode, dev);
>>> +    if (S_ISSOCK(mode)) {
>>> +        err = create_socket_file_at_cwd(filename, mode);
>>> +    } else {
>>> +        err = mknod(filename, mode, dev);
>>> +    }
>>>
>>>       preserved_errno = errno;
>>>       /* Stop using the thread-local cwd */
>>>       pthread_fchdir_np(-1);
> 
> 



^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2022-04-29  1:53 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-27 18:58 [PATCH v4 0/6] 9pfs: macOS host fixes Christian Schoenebeck
2022-04-27 18:54 ` [PATCH v4 1/6] 9pfs: fix qemu_mknodat(S_IFREG) on macOS Christian Schoenebeck
2022-04-27 20:16   ` Greg Kurz
2022-04-28 11:42     ` Christian Schoenebeck
2022-04-27 18:54 ` [PATCH v4 2/6] 9pfs: fix qemu_mknodat(S_IFSOCK) " Christian Schoenebeck
2022-04-27 20:36   ` Greg Kurz
2022-04-28 11:22     ` Christian Schoenebeck
2022-04-29  1:51       ` Akihiko Odaki
2022-04-27 18:54 ` [PATCH v4 3/6] 9pfs: fix wrong encoding of rdev field in Rgetattr " Christian Schoenebeck
2022-04-27 18:54 ` [PATCH v4 4/6] 9pfs: fix wrong errno being sent to Linux client on macOS host Christian Schoenebeck
2022-04-27 18:54 ` [PATCH v4 5/6] 9pfs: fix removing non-existent POSIX ACL xattr " Christian Schoenebeck
2022-04-27 18:56 ` [PATCH v4 6/6] 9pfs: fix qemu_mknodat() to always return -1 on error " Christian Schoenebeck

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.