All of lore.kernel.org
 help / color / mirror / Atom feed
* [pseudo][PATCH RFC 0/2] Implement new openat2 flags
@ 2026-11-12 18:47 Mark Hatle
  2026-11-12 18:47 ` [pseudo][PATCH RFC 1/2] ports/linux: Pass an empty openat() path to the kernel Mark Hatle
  2026-11-12 18:47 ` [pseudo][PATCH RFC 2/2] openat2: Look at dirfd for an empty path Mark Hatle
  0 siblings, 2 replies; 3+ messages in thread
From: Mark Hatle @ 2026-11-12 18:47 UTC (permalink / raw)
  To: yocto-patches

See [YOCTO #16327].  As reported the new Linux 7.2 includes both
O_EMPTYPATH and OPENAT2_REGULAR.

OPENAT2_REGULAR requires no changes, as the flag is passed to the
kernel and no local pseudo behavior changes are required.

O_EMPTYPATH requires minor changes, and also pointed out a behavior
inconsistency with the existing implementation where a blank dir
was expanded.

I do not have a Linux 7.2 or newer environment to test this on.  This
was implementated based on description, kernel source inspection and
man pages.

Sent as an RFC as I'm not able to directly run this on a newer kernel
and validate it is working.

Any review / test would be appreciated!

Mark Hatle (2):
  ports/linux: Pass an empty openat() path to the kernel
  openat2: Look at dirfd for an empty path

 makewrappers                       |  13 +++-
 ports/linux/guts/openat.c          |  21 ++++--
 ports/linux/openat2/guts/openat2.c |  24 +++++--
 ports/linux/wrapfuncs.in           |   8 +--
 test/test-openat-emptypath.c       | 105 +++++++++++++++++++++++++++++
 test/test-openat-emptypath.sh      |  12 ++++
 6 files changed, 166 insertions(+), 17 deletions(-)
 create mode 100644 test/test-openat-emptypath.c
 create mode 100755 test/test-openat-emptypath.sh

-- 
2.34.1


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

* [pseudo][PATCH RFC 1/2] ports/linux: Pass an empty openat() path to the kernel
  2026-11-12 18:47 [pseudo][PATCH RFC 0/2] Implement new openat2 flags Mark Hatle
@ 2026-11-12 18:47 ` Mark Hatle
  2026-11-12 18:47 ` [pseudo][PATCH RFC 2/2] openat2: Look at dirfd for an empty path Mark Hatle
  1 sibling, 0 replies; 3+ messages in thread
From: Mark Hatle @ 2026-11-12 18:47 UTC (permalink / raw)
  To: yocto-patches

openat() wrappers resolved an empty path to dirfd's recorded path, so
openat(dirfd, "", ...) opened dirfd's path instead of failing with
ENOENT.

Linux 7.2 adds O_EMPTYPATH, with which an empty path reopens
dirfd itself, e.g. to turn an O_PATH descriptor into a usable one;
resolving it to a path opens the wrong file if dirfd's file was renamed
or removed.

Add a makewrappers option, keep_empty_path, to leave an empty path
unchanged, and use it for the openat() wrappers so the kernel decides
what an empty path means.  The guts look at dirfd with AT_EMPTY_PATH
and record dirfd's path for the new descriptor.

[YOCTO #16327]

Reported-by: Paul Barker <paul@pbarker.dev>
AI-Generated: Uses GitHub Copilot
Signed-off-by: Mark Hatle <mark.hatle@amd.com>
---
 makewrappers                  | 13 ++++--
 ports/linux/guts/openat.c     | 21 +++++++---
 ports/linux/wrapfuncs.in      |  8 ++--
 test/test-openat-emptypath.c  | 79 +++++++++++++++++++++++++++++++++++
 test/test-openat-emptypath.sh | 12 ++++++
 5 files changed, 121 insertions(+), 12 deletions(-)
 create mode 100644 test/test-openat-emptypath.c
 create mode 100755 test/test-openat-emptypath.sh

diff --git a/makewrappers b/makewrappers
index 303ae32..84dc563 100755
--- a/makewrappers
+++ b/makewrappers
@@ -262,6 +262,10 @@ class Function:
         # In those cases, use a suffix ('_int') for the path variable names instead of
         # overwriting them. This means the wrapper needs to handle paths itself.
         self.preserve_paths = False
+        # Leave an empty path unchanged instead of resolving it to dirfd's
+        # path, for functions where only a flag (e.g. O_EMPTYPATH) makes
+        # an empty path name dirfd.
+        self.keep_empty_path = False
     
         function, comments = line.split(';')
         comment = re.search(r'/\* *(.*) *\*/', comments)
@@ -427,9 +431,12 @@ class Function:
             if self.preserve_paths and self.noignore_path:
                 # path_int is only read by the ignore_paths() check
                 continue
-            fix_paths.append(
-                "%s = pseudo_root_path(__func__, __LINE__, %s%s, %s, %s);" %
-                (pathvar, prefix, self.dirfd, path, self.flags))
+            munge = "%s = pseudo_root_path(__func__, __LINE__, %s%s, %s, %s);" % \
+                (pathvar, prefix, self.dirfd, path, self.flags)
+            if self.keep_empty_path:
+                # see above for the asm()
+                munge = "asm(\"\" : \"+r\"(%s));\n\t\tif (!%s || *%s)\n\t\t\t%s" % (path, path, path, munge)
+            fix_paths.append(munge)
         return "\n\t\t".join(fix_paths)
 
     def ignore_paths(self):
diff --git a/ports/linux/guts/openat.c b/ports/linux/guts/openat.c
index 9d32283..e0075fe 100644
--- a/ports/linux/guts/openat.c
+++ b/ports/linux/guts/openat.c
@@ -13,6 +13,17 @@
 	int existed = 1;
 	int save_errno;
 	sigset_t local_saved_sigmask;
+	const char *record_path = path;
+	int stat_flags = (flags & O_NOFOLLOW) ? AT_SYMLINK_NOFOLLOW : 0;
+
+	/* An empty path is left for the kernel, which only accepts it with
+	 * O_EMPTYPATH, to reopen dirfd.  Look at and record dirfd instead.
+	 */
+	if (path && !*path) {
+		stat_flags |= AT_EMPTY_PATH;
+		record_path = pseudo_root_path(__func__, __LINE__, dirfd,
+			dirfd == AT_FDCWD ? "." : "", 0);
+	}
 
 	/* mask out mode bits appropriately */
 	mode = mode & ~pseudo_umask;
@@ -47,7 +58,7 @@
 	/* note "else" in #ifdef O_TMPFILE above */
 	if (flags & O_CREAT) {
 		save_errno = errno;
-		rc = base_fstatat(dirfd, path, &buf, (flags & O_NOFOLLOW) ? AT_SYMLINK_NOFOLLOW : 0);
+		rc = base_fstatat(dirfd, path, &buf, stat_flags);
 		existed = (rc != -1);
 		if (!existed)
 			pseudo_debug(PDBGF_FILE, "openat_creat: %s -> 0%o\n", path, mode);
@@ -60,7 +71,7 @@
 	 */
 	if (!(flags & O_NONBLOCK) && ((flags & (O_WRONLY | O_RDONLY | O_RDWR)) != O_RDWR)) {
 		save_errno = errno;
-		rc = base_fstatat(dirfd, path, &buf, (flags & O_NOFOLLOW) ? AT_SYMLINK_NOFOLLOW : 0);
+		rc = base_fstatat(dirfd, path, &buf, stat_flags);
 		if (rc != -1 && S_ISFIFO(buf.st_mode)) {
 			overly_magic_nonblocking = 1;
 		}
@@ -105,7 +116,7 @@
 			return rc;
 		}
 #endif
-		stat_rc = base_fstatat(dirfd, path, &buf, (flags & O_NOFOLLOW) ? AT_SYMLINK_NOFOLLOW : 0);
+		stat_rc = base_fstatat(dirfd, path, &buf, stat_flags);
 
 		pseudo_debug(PDBGF_FILE, "openat(path %s), flags %o, stat rc %d, stat mode %o\n",
 			path, flags, stat_rc, buf.st_mode);
@@ -122,11 +133,11 @@
 				}
 				pseudo_client_path_unlock(path_lock_fd);
 			}
-				pseudo_client_op(OP_OPEN, PSEUDO_ACCESS(flags), rc, dirfd, path, &buf);
+				pseudo_client_op(OP_OPEN, PSEUDO_ACCESS(flags), rc, dirfd, record_path, &buf);
 		} else {
 			pseudo_debug(PDBGF_FILE, "openat (fd %d, path %d/%s, flags %d) succeeded, but stat failed (%s).\n",
 				rc, dirfd, path, flags, strerror(errno));
-			pseudo_client_op(OP_OPEN, PSEUDO_ACCESS(flags), rc, dirfd, path, 0);
+			pseudo_client_op(OP_OPEN, PSEUDO_ACCESS(flags), rc, dirfd, record_path, 0);
 		}
 		errno = save_errno;
 	}
diff --git a/ports/linux/wrapfuncs.in b/ports/linux/wrapfuncs.in
index 1874b60..dbbf2f7 100644
--- a/ports/linux/wrapfuncs.in
+++ b/ports/linux/wrapfuncs.in
@@ -8,8 +8,8 @@ int __fxstat(int ver, int fd, struct stat *buf);
 int lchmod(const char *path, mode_t mode); /* flags=AT_SYMLINK_NOFOLLOW, path_lock=shared */
 int lchown(const char *path, uid_t owner, gid_t group); /* flags=AT_SYMLINK_NOFOLLOW, path_lock=shared */
 int __fxstatat(int ver, int dirfd, const char *path, struct stat *buf, int flags); /* path_lock=shared */
-int openat(int dirfd, const char *path, int flags, ...{mode_t mode}); /* flags=((flags&O_NOFOLLOW)||((flags&(O_CREAT|O_EXCL))==(O_CREAT|O_EXCL))), noignore_path=1 */
-int __openat_2(int dirfd, const char *path, int flags); /* flags=((flags&O_NOFOLLOW)||((flags&(O_CREAT|O_EXCL))==(O_CREAT|O_EXCL))), noignore_path=1 */
+int openat(int dirfd, const char *path, int flags, ...{mode_t mode}); /* flags=((flags&O_NOFOLLOW)||((flags&(O_CREAT|O_EXCL))==(O_CREAT|O_EXCL))), noignore_path=1, keep_empty_path=1 */
+int __openat_2(int dirfd, const char *path, int flags); /* flags=((flags&O_NOFOLLOW)||((flags&(O_CREAT|O_EXCL))==(O_CREAT|O_EXCL))), noignore_path=1, keep_empty_path=1 */
 int open_tree(int dirfd, const char *path, unsigned int flags); /* preserve_paths=1, noignore_path=1 */
 int open_tree_attr(int dirfd, const char *path, unsigned int flags, struct mount_attr *attr, size_t size); /* preserve_paths=1, noignore_path=1*/
 int name_to_handle_at(int dirfd, const char *name, struct file_handle *handle, int *mount_id, int flags);
@@ -24,8 +24,8 @@ int fcntl64(int fd, int cmd, ...{struct flock *lock});  /* noignore_path=1 */
 char *canonicalize_file_name(const char *filename);
 int eaccess(const char *path, int mode);
 int open64(const char *path, int flags, ...{mode_t mode}); /* flags=((flags&O_NOFOLLOW)||((flags&(O_CREAT|O_EXCL))==(O_CREAT|O_EXCL))), noignore_path=1 */
-int openat64(int dirfd, const char *path, int flags, ...{mode_t mode}); /* flags=((flags&O_NOFOLLOW)||((flags&(O_CREAT|O_EXCL))==(O_CREAT|O_EXCL))), noignore_path=1 */
-int __openat64_2(int dirfd, const char *path, int flags); /* flags=((flags&O_NOFOLLOW)||((flags&(O_CREAT|O_EXCL))==(O_CREAT|O_EXCL))), noignore_path=1 */
+int openat64(int dirfd, const char *path, int flags, ...{mode_t mode}); /* flags=((flags&O_NOFOLLOW)||((flags&(O_CREAT|O_EXCL))==(O_CREAT|O_EXCL))), noignore_path=1, keep_empty_path=1 */
+int __openat64_2(int dirfd, const char *path, int flags); /* flags=((flags&O_NOFOLLOW)||((flags&(O_CREAT|O_EXCL))==(O_CREAT|O_EXCL))), noignore_path=1, keep_empty_path=1 */
 int creat64(const char *path, mode_t mode);
 int stat(const char *path, struct stat *buf); /* real_func=pseudo_stat, path_lock=shared */
 int lstat(const char *path, struct stat *buf); /* real_func=pseudo_lstat, flags=AT_SYMLINK_NOFOLLOW, path_lock=shared */
diff --git a/test/test-openat-emptypath.c b/test/test-openat-emptypath.c
new file mode 100644
index 0000000..076f1fd
--- /dev/null
+++ b/test/test-openat-emptypath.c
@@ -0,0 +1,79 @@
+/*
+ * Test opening an empty path, which only names dirfd with O_EMPTYPATH
+ * (Linux 7.2), the way the kernel does.
+ * SPDX-License-Identifier: LGPL-2.1-only
+ */
+#define _GNU_SOURCE
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#ifndef O_EMPTYPATH
+#define O_EMPTYPATH (1 << 26)
+#endif
+
+static int failed;
+
+#define FAIL(...) do { printf(__VA_ARGS__); failed = 1; } while (0)
+
+/* fd should be dir, with pseudo knowing its path */
+static void
+check_reopened(const char *how, int fd) {
+	struct stat st;
+
+	if (fd == -1) {
+		if (errno == ENOENT || errno == EINVAL)
+			printf("%s: O_EMPTYPATH not supported by the kernel, skipping\n", how);
+		else
+			FAIL("%s: %s\n", how, strerror(errno));
+		return;
+	}
+	if (fstatat(fd, "file", &st, 0) == -1)
+		FAIL("%s: fstatat: %s\n", how, strerror(errno));
+	else if (st.st_uid != 123 || st.st_gid != 456)
+		FAIL("%s: file owned by %d:%d, expected 123:456\n",
+			how, (int) st.st_uid, (int) st.st_gid);
+	close(fd);
+}
+
+int
+main(int argc, char *argv[]) {
+	char path[4096];
+	int dfd, pfd, fd;
+
+	if (argc != 2) {
+		fprintf(stderr, "usage: %s <dir>\n", argv[0]);
+		return 2;
+	}
+	snprintf(path, sizeof(path), "%s/file", argv[1]);
+	if (chown(path, 123, 456) == -1) {
+		perror("chown");
+		return 1;
+	}
+	dfd = open(argv[1], O_RDONLY | O_DIRECTORY);
+	pfd = open(argv[1], O_PATH | O_DIRECTORY);
+	if (dfd == -1 || pfd == -1) {
+		perror("open");
+		return 1;
+	}
+
+	fd = openat(dfd, "", O_RDONLY);
+	if (fd != -1 || errno != ENOENT)
+		FAIL("openat without O_EMPTYPATH: expected ENOENT, got %d (%s)\n",
+			fd, strerror(errno));
+	if (fd != -1)
+		close(fd);
+
+	check_reopened("openat", openat(pfd, "", O_RDONLY | O_DIRECTORY | O_EMPTYPATH));
+	if (fchdir(dfd) == -1) {
+		perror("fchdir");
+		return 1;
+	}
+	check_reopened("openat AT_FDCWD", openat(AT_FDCWD, "", O_RDONLY | O_DIRECTORY | O_EMPTYPATH));
+
+	return failed;
+}
diff --git a/test/test-openat-emptypath.sh b/test/test-openat-emptypath.sh
new file mode 100755
index 0000000..ead5191
--- /dev/null
+++ b/test/test-openat-emptypath.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+#
+# Test opening an empty path, with and without O_EMPTYPATH.
+# SPDX-License-Identifier: LGPL-2.1-only
+
+dir=$(pwd)/openat_emptypath_test
+trap 'rm -rf "$dir"' 0
+rm -rf "$dir"
+mkdir -p "$dir"
+touch "$dir/file"
+
+./test/test-openat-emptypath "$dir"
-- 
2.34.1


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

* [pseudo][PATCH RFC 2/2] openat2: Look at dirfd for an empty path
  2026-11-12 18:47 [pseudo][PATCH RFC 0/2] Implement new openat2 flags Mark Hatle
  2026-11-12 18:47 ` [pseudo][PATCH RFC 1/2] ports/linux: Pass an empty openat() path to the kernel Mark Hatle
@ 2026-11-12 18:47 ` Mark Hatle
  1 sibling, 0 replies; 3+ messages in thread
From: Mark Hatle @ 2026-11-12 18:47 UTC (permalink / raw)
  To: yocto-patches

openat2() passes an empty path to the kernel, which with Linux 7.2's
O_EMPTYPATH reopens dirfd, but pseudo then looked at and recorded
dirfd's recorded path.  With AT_FDCWD that path is empty, so *at() calls
relative to the new descriptor failed, and for a descriptor on a symlink
it described the target instead.

Look at dirfd itself with AT_EMPTY_PATH, as openat() now does, and record
dirfd's path, or the working directory's for AT_FDCWD.

[YOCTO #16327]

Reported-by: Paul Barker <paul@pbarker.dev>
AI-Generated: Uses GitHub Copilot
Signed-off-by: Mark Hatle <mark.hatle@amd.com>
---
 ports/linux/openat2/guts/openat2.c | 24 +++++++++++++++++++-----
 test/test-openat-emptypath.c       | 30 ++++++++++++++++++++++++++++--
 2 files changed, 47 insertions(+), 7 deletions(-)

diff --git a/ports/linux/openat2/guts/openat2.c b/ports/linux/openat2/guts/openat2.c
index bb4a125..30a51ab 100644
--- a/ports/linux/openat2/guts/openat2.c
+++ b/ports/linux/openat2/guts/openat2.c
@@ -15,6 +15,8 @@
 	sigset_t local_saved_sigmask;
 	struct open_how my_how;
 	char *pseudo_path;
+	const char *stat_path, *record_path;
+	int stat_flags;
 
 	/* Validate parameters */
 	if (!how || size < sizeof(struct open_how)) {
@@ -41,6 +43,18 @@
 
 	memcpy(&my_how, how, size);
 
+	stat_path = record_path = pseudo_path;
+	stat_flags = (my_how.flags & O_NOFOLLOW) ? AT_SYMLINK_NOFOLLOW : 0;
+	/* An empty path is passed to the kernel, which only accepts it with
+	 * O_EMPTYPATH, to reopen dirfd.  Look at and record dirfd instead.
+	 */
+	if (path && !*path) {
+		stat_path = "";
+		stat_flags |= AT_EMPTY_PATH;
+		record_path = pseudo_root_path(__func__, __LINE__, dirfd,
+			dirfd == AT_FDCWD ? "." : "", 0);
+	}
+
 	/* mask out mode bits appropriately */
 	my_how.mode = my_how.mode & ~pseudo_umask;
 
@@ -81,7 +95,7 @@
 	/* note "else" in #ifdef O_TMPFILE above */
 	if (my_how.flags & O_CREAT) {
 		save_errno = errno;
-		rc = base_fstatat(dirfd, pseudo_path, &buf, (my_how.flags & O_NOFOLLOW) ? AT_SYMLINK_NOFOLLOW : 0);
+		rc = base_fstatat(dirfd, stat_path, &buf, stat_flags);
 		existed = (rc != -1);
 		if (!existed)
 			pseudo_debug(PDBGF_FILE, "openat2_creat: %s -> 0%lld\n", pseudo_path, my_how.mode);
@@ -94,7 +108,7 @@
 	 */
 	if (!(my_how.flags & O_NONBLOCK) && ((my_how.flags & (O_WRONLY | O_RDONLY | O_RDWR)) != O_RDWR)) {
 		save_errno = errno;
-		rc = base_fstatat(dirfd, pseudo_path, &buf, (my_how.flags & O_NOFOLLOW) ? AT_SYMLINK_NOFOLLOW : 0);
+		rc = base_fstatat(dirfd, stat_path, &buf, stat_flags);
 		if (rc != -1 && S_ISFIFO(buf.st_mode)) {
 			overly_magic_nonblocking = 1;
 		}
@@ -151,7 +165,7 @@
 			return rc;
 		}
 #endif
-		stat_rc = base_fstatat(dirfd, pseudo_path, &buf, (my_how.flags & O_NOFOLLOW) ? AT_SYMLINK_NOFOLLOW : 0);
+		stat_rc = base_fstatat(dirfd, stat_path, &buf, stat_flags);
 
 		pseudo_debug(PDBGF_FILE, "openat2(path %s), flags %lld, stat rc %d, stat mode %o\n",
 			pseudo_path, my_how.flags, stat_rc, buf.st_mode);
@@ -168,11 +182,11 @@
 				}
 				pseudo_client_path_unlock(path_lock_fd);
 			}
-				pseudo_client_op(OP_OPEN, PSEUDO_ACCESS(my_how.flags), rc, dirfd, pseudo_path, &buf);
+				pseudo_client_op(OP_OPEN, PSEUDO_ACCESS(my_how.flags), rc, dirfd, record_path, &buf);
 		} else {
 			pseudo_debug(PDBGF_FILE, "openat2 (fd %d, path %d/%s, flags %lld) succeeded, but stat failed (%s).\n",
 				rc, dirfd, pseudo_path, my_how.flags, strerror(errno));
-			pseudo_client_op(OP_OPEN, PSEUDO_ACCESS(my_how.flags), rc, dirfd, pseudo_path, 0);
+			pseudo_client_op(OP_OPEN, PSEUDO_ACCESS(my_how.flags), rc, dirfd, record_path, 0);
 		}
 		errno = save_errno;
 	}
diff --git a/test/test-openat-emptypath.c b/test/test-openat-emptypath.c
index 076f1fd..7ebec12 100644
--- a/test/test-openat-emptypath.c
+++ b/test/test-openat-emptypath.c
@@ -1,6 +1,6 @@
 /*
- * Test opening an empty path, which only names dirfd with O_EMPTYPATH
- * (Linux 7.2), the way the kernel does.
+ * Test opening an empty path with openat() and openat2(), which only
+ * names dirfd with O_EMPTYPATH (Linux 7.2), the way the kernel does.
  * SPDX-License-Identifier: LGPL-2.1-only
  */
 #define _GNU_SOURCE
@@ -10,8 +10,19 @@
 #include <stdio.h>
 #include <string.h>
 #include <sys/stat.h>
+#include <sys/syscall.h>
 #include <unistd.h>
 
+#if __has_include (<linux/openat2.h>)
+# include <linux/openat2.h>
+#else
+struct open_how {
+	unsigned long long flags;
+	unsigned long long mode;
+	unsigned long long resolve;
+};
+#endif
+
 #ifndef O_EMPTYPATH
 #define O_EMPTYPATH (1 << 26)
 #endif
@@ -20,6 +31,13 @@ static int failed;
 
 #define FAIL(...) do { printf(__VA_ARGS__); failed = 1; } while (0)
 
+static int
+do_openat2(int dirfd, const char *path, unsigned long long flags) {
+	struct open_how how = { .flags = flags };
+
+	return syscall(SYS_openat2, dirfd, path, &how, sizeof(how));
+}
+
 /* fd should be dir, with pseudo knowing its path */
 static void
 check_reopened(const char *how, int fd) {
@@ -67,13 +85,21 @@ main(int argc, char *argv[]) {
 			fd, strerror(errno));
 	if (fd != -1)
 		close(fd);
+	fd = do_openat2(dfd, "", O_RDONLY);
+	if (fd != -1 || errno != ENOENT)
+		FAIL("openat2 without O_EMPTYPATH: expected ENOENT, got %d (%s)\n",
+			fd, strerror(errno));
+	if (fd != -1)
+		close(fd);
 
 	check_reopened("openat", openat(pfd, "", O_RDONLY | O_DIRECTORY | O_EMPTYPATH));
+	check_reopened("openat2", do_openat2(pfd, "", O_RDONLY | O_DIRECTORY | O_EMPTYPATH));
 	if (fchdir(dfd) == -1) {
 		perror("fchdir");
 		return 1;
 	}
 	check_reopened("openat AT_FDCWD", openat(AT_FDCWD, "", O_RDONLY | O_DIRECTORY | O_EMPTYPATH));
+	check_reopened("openat2 AT_FDCWD", do_openat2(AT_FDCWD, "", O_RDONLY | O_DIRECTORY | O_EMPTYPATH));
 
 	return failed;
 }
-- 
2.34.1


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

end of thread, other threads:[~2026-11-12 22:54 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-12 18:47 [pseudo][PATCH RFC 0/2] Implement new openat2 flags Mark Hatle
2026-11-12 18:47 ` [pseudo][PATCH RFC 1/2] ports/linux: Pass an empty openat() path to the kernel Mark Hatle
2026-11-12 18:47 ` [pseudo][PATCH RFC 2/2] openat2: Look at dirfd for an empty path Mark Hatle

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.