public inbox for linux-cifs@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH v6 0/4] OPENAT2_REGULAR flag support for openat2
@ 2026-03-28 17:22 Dorjoy Chowdhury
  2026-03-28 17:22 ` [PATCH v6 1/4] openat2: new OPENAT2_REGULAR flag support Dorjoy Chowdhury
                   ` (4 more replies)
  0 siblings, 5 replies; 23+ messages in thread
From: Dorjoy Chowdhury @ 2026-03-28 17:22 UTC (permalink / raw)
  To: linux-fsdevel
  Cc: linux-kernel, linux-api, ceph-devel, gfs2, linux-nfs, linux-cifs,
	v9fs, linux-kselftest, viro, brauner, jack, jlayton, chuck.lever,
	alex.aring, arnd, adilger, mjguzik, smfrench, richard.henderson,
	mattst88, linmag7, tsbogend, James.Bottomley, deller, davem,
	andreas, idryomov, amarkuze, slava, agruenba, trondmy, anna,
	sfrench, pc, ronniesahlberg, sprasad, tom, bharathsm, shuah,
	miklos, hansg

Hi,

I came upon this "Ability to only open regular files" uapi feature suggestion
from https://uapi-group.org/kernel-features/#ability-to-only-open-regular-files
and thought it would be something I could do as a first patch and get to
know the kernel code a bit better.

The following filesystems have been tested by building and booting the kernel
x86 bzImage in a Fedora 43 VM in QEMU. I have tested with OPENAT2_REGULAR that
regular files can be successfully opened and non-regular files (directory, fifo etc)
return -EFTYPE.
- btrfs
- NFS (loopback)
- SMB (loopback)

Changes in v6:
- OPENAT2_REGULAR stripped from file->f_flags in do_dentry_open so that it doesn't leak in fcntl(fd, F_GETFL)
- BUILD_BUG_ON updated to use VALID_OPENAT2_FLAGS instead of VALID_OPEN_FLAGS in build_open_flags and in fcntl_init
- v5 is at: https://lore.kernel.org/linux-fsdevel/20260307140726.70219-1-dorjoychy111@gmail.com/T/

Changes in v5:
- EFTYPE is already used in BSDs mentioned in commit message
- consistently return -EFTYPE in all filesystems
- v4 is at: https://lore.kernel.org/linux-fsdevel/20260221145915.81749-1-dorjoychy111@gmail.com/T/

Changes in v4:
- changed O_REGULAR to OPENAT2_REGULAR
- OPENAT2_REGULAR does not affect O_PATH
- atomic_open codepaths updated to work properly for OPENAT2_REGULAR
- commit message includes the uapi-group URL
- v3 is at: https://lore.kernel.org/linux-fsdevel/20260127180109.66691-1-dorjoychy111@gmail.com/T/

Changes in v3:
- included motivation about O_REGULAR flag in commit message e.g., programs not wanting to be tricked into opening device nodes
- fixed commit message wrongly referencing ENOTREGULAR instead of ENOTREG
- fixed the O_REGULAR flag in arch/parisc/include/uapi/asm/fcntl.h from 060000000 to 0100000000
- added 2 commits converting arch/{mips,sparc}/include/uapi/asm/fcntl.h O_* macros from hex to octal
- v2 is at: https://lore.kernel.org/linux-fsdevel/20260126154156.55723-1-dorjoychy111@gmail.com/T/

Changes in v2:
- rename ENOTREGULAR to ENOTREG
- define ENOTREG in uapi/asm-generic/errno.h (instead of errno-base.h) and in arch/*/include/uapi/asm/errno.h files
- override O_REGULAR in arch/{alpha,sparc,parisc}/include/uapi/asm/fcntl.h due to clash with include/uapi/asm-generic/fcntl.h
- I have kept the kselftest but now that O_REGULAR and ENOTREG can have different value on different architectures I am not sure if it's right
- v1 is at: https://lore.kernel.org/linux-fsdevel/20260125141518.59493-1-dorjoychy111@gmail.com/T/

Thanks.

Regards,
Dorjoy

Dorjoy Chowdhury (4):
  openat2: new OPENAT2_REGULAR flag support
  kselftest/openat2: test for OPENAT2_REGULAR flag
  sparc/fcntl.h: convert O_* flag macros from hex to octal
  mips/fcntl.h: convert O_* flag macros from hex to octal

 arch/alpha/include/uapi/asm/errno.h           |  2 +
 arch/alpha/include/uapi/asm/fcntl.h           |  1 +
 arch/mips/include/uapi/asm/errno.h            |  2 +
 arch/mips/include/uapi/asm/fcntl.h            | 22 +++++------
 arch/parisc/include/uapi/asm/errno.h          |  2 +
 arch/parisc/include/uapi/asm/fcntl.h          |  1 +
 arch/sparc/include/uapi/asm/errno.h           |  2 +
 arch/sparc/include/uapi/asm/fcntl.h           | 35 +++++++++---------
 fs/ceph/file.c                                |  4 ++
 fs/fcntl.c                                    |  4 +-
 fs/gfs2/inode.c                               |  6 +++
 fs/namei.c                                    |  4 ++
 fs/nfs/dir.c                                  |  4 ++
 fs/open.c                                     |  8 ++--
 fs/smb/client/dir.c                           | 14 ++++++-
 include/linux/fcntl.h                         |  2 +
 include/uapi/asm-generic/errno.h              |  2 +
 include/uapi/asm-generic/fcntl.h              |  4 ++
 tools/arch/alpha/include/uapi/asm/errno.h     |  2 +
 tools/arch/mips/include/uapi/asm/errno.h      |  2 +
 tools/arch/parisc/include/uapi/asm/errno.h    |  2 +
 tools/arch/sparc/include/uapi/asm/errno.h     |  2 +
 tools/include/uapi/asm-generic/errno.h        |  2 +
 .../testing/selftests/openat2/openat2_test.c  | 37 ++++++++++++++++++-
 24 files changed, 131 insertions(+), 35 deletions(-)

-- 
2.53.0


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

* [PATCH v6 1/4] openat2: new OPENAT2_REGULAR flag support
  2026-03-28 17:22 [PATCH v6 0/4] OPENAT2_REGULAR flag support for openat2 Dorjoy Chowdhury
@ 2026-03-28 17:22 ` Dorjoy Chowdhury
  2026-03-30 11:49   ` Jeff Layton
                     ` (2 more replies)
  2026-03-28 17:22 ` [PATCH v6 2/4] kselftest/openat2: test for OPENAT2_REGULAR flag Dorjoy Chowdhury
                   ` (3 subsequent siblings)
  4 siblings, 3 replies; 23+ messages in thread
From: Dorjoy Chowdhury @ 2026-03-28 17:22 UTC (permalink / raw)
  To: linux-fsdevel
  Cc: linux-kernel, linux-api, ceph-devel, gfs2, linux-nfs, linux-cifs,
	v9fs, linux-kselftest, viro, brauner, jack, jlayton, chuck.lever,
	alex.aring, arnd, adilger, mjguzik, smfrench, richard.henderson,
	mattst88, linmag7, tsbogend, James.Bottomley, deller, davem,
	andreas, idryomov, amarkuze, slava, agruenba, trondmy, anna,
	sfrench, pc, ronniesahlberg, sprasad, tom, bharathsm, shuah,
	miklos, hansg

This flag indicates the path should be opened if it's a regular file.
This is useful to write secure programs that want to avoid being
tricked into opening device nodes with special semantics while thinking
they operate on regular files. This is a requested feature from the
uapi-group[1].

A corresponding error code EFTYPE has been introduced. For example, if
openat2 is called on path /dev/null with OPENAT2_REGULAR in the flag
param, it will return -EFTYPE. EFTYPE is already used in BSD systems
like FreeBSD, macOS.

When used in combination with O_CREAT, either the regular file is
created, or if the path already exists, it is opened if it's a regular
file. Otherwise, -EFTYPE is returned.

When OPENAT2_REGULAR is combined with O_DIRECTORY, -EINVAL is returned
as it doesn't make sense to open a path that is both a directory and a
regular file.

[1]: https://uapi-group.org/kernel-features/#ability-to-only-open-regular-files

Signed-off-by: Dorjoy Chowdhury <dorjoychy111@gmail.com>
---
 arch/alpha/include/uapi/asm/errno.h        |  2 ++
 arch/alpha/include/uapi/asm/fcntl.h        |  1 +
 arch/mips/include/uapi/asm/errno.h         |  2 ++
 arch/parisc/include/uapi/asm/errno.h       |  2 ++
 arch/parisc/include/uapi/asm/fcntl.h       |  1 +
 arch/sparc/include/uapi/asm/errno.h        |  2 ++
 arch/sparc/include/uapi/asm/fcntl.h        |  1 +
 fs/ceph/file.c                             |  4 ++++
 fs/fcntl.c                                 |  4 ++--
 fs/gfs2/inode.c                            |  6 ++++++
 fs/namei.c                                 |  4 ++++
 fs/nfs/dir.c                               |  4 ++++
 fs/open.c                                  |  8 +++++---
 fs/smb/client/dir.c                        | 14 +++++++++++++-
 include/linux/fcntl.h                      |  2 ++
 include/uapi/asm-generic/errno.h           |  2 ++
 include/uapi/asm-generic/fcntl.h           |  4 ++++
 tools/arch/alpha/include/uapi/asm/errno.h  |  2 ++
 tools/arch/mips/include/uapi/asm/errno.h   |  2 ++
 tools/arch/parisc/include/uapi/asm/errno.h |  2 ++
 tools/arch/sparc/include/uapi/asm/errno.h  |  2 ++
 tools/include/uapi/asm-generic/errno.h     |  2 ++
 22 files changed, 67 insertions(+), 6 deletions(-)

diff --git a/arch/alpha/include/uapi/asm/errno.h b/arch/alpha/include/uapi/asm/errno.h
index 6791f6508632..1a99f38813c7 100644
--- a/arch/alpha/include/uapi/asm/errno.h
+++ b/arch/alpha/include/uapi/asm/errno.h
@@ -127,4 +127,6 @@
 
 #define EHWPOISON	139	/* Memory page has hardware error */
 
+#define EFTYPE		140	/* Wrong file type for the intended operation */
+
 #endif
diff --git a/arch/alpha/include/uapi/asm/fcntl.h b/arch/alpha/include/uapi/asm/fcntl.h
index 50bdc8e8a271..fe488bf7c18e 100644
--- a/arch/alpha/include/uapi/asm/fcntl.h
+++ b/arch/alpha/include/uapi/asm/fcntl.h
@@ -34,6 +34,7 @@
 
 #define O_PATH		040000000
 #define __O_TMPFILE	0100000000
+#define OPENAT2_REGULAR	0200000000
 
 #define F_GETLK		7
 #define F_SETLK		8
diff --git a/arch/mips/include/uapi/asm/errno.h b/arch/mips/include/uapi/asm/errno.h
index c01ed91b1ef4..1835a50b69ce 100644
--- a/arch/mips/include/uapi/asm/errno.h
+++ b/arch/mips/include/uapi/asm/errno.h
@@ -126,6 +126,8 @@
 
 #define EHWPOISON	168	/* Memory page has hardware error */
 
+#define EFTYPE		169	/* Wrong file type for the intended operation */
+
 #define EDQUOT		1133	/* Quota exceeded */
 
 
diff --git a/arch/parisc/include/uapi/asm/errno.h b/arch/parisc/include/uapi/asm/errno.h
index 8cbc07c1903e..93194fbb0a80 100644
--- a/arch/parisc/include/uapi/asm/errno.h
+++ b/arch/parisc/include/uapi/asm/errno.h
@@ -124,4 +124,6 @@
 
 #define EHWPOISON	257	/* Memory page has hardware error */
 
+#define EFTYPE		258	/* Wrong file type for the intended operation */
+
 #endif
diff --git a/arch/parisc/include/uapi/asm/fcntl.h b/arch/parisc/include/uapi/asm/fcntl.h
index 03dee816cb13..d46812f2f0f4 100644
--- a/arch/parisc/include/uapi/asm/fcntl.h
+++ b/arch/parisc/include/uapi/asm/fcntl.h
@@ -19,6 +19,7 @@
 
 #define O_PATH		020000000
 #define __O_TMPFILE	040000000
+#define OPENAT2_REGULAR	0100000000
 
 #define F_GETLK64	8
 #define F_SETLK64	9
diff --git a/arch/sparc/include/uapi/asm/errno.h b/arch/sparc/include/uapi/asm/errno.h
index 4a41e7835fd5..71940ec9130b 100644
--- a/arch/sparc/include/uapi/asm/errno.h
+++ b/arch/sparc/include/uapi/asm/errno.h
@@ -117,4 +117,6 @@
 
 #define EHWPOISON	135	/* Memory page has hardware error */
 
+#define EFTYPE		136	/* Wrong file type for the intended operation */
+
 #endif
diff --git a/arch/sparc/include/uapi/asm/fcntl.h b/arch/sparc/include/uapi/asm/fcntl.h
index 67dae75e5274..bb6e9fa94bc9 100644
--- a/arch/sparc/include/uapi/asm/fcntl.h
+++ b/arch/sparc/include/uapi/asm/fcntl.h
@@ -37,6 +37,7 @@
 
 #define O_PATH		0x1000000
 #define __O_TMPFILE	0x2000000
+#define OPENAT2_REGULAR	0x4000000
 
 #define F_GETOWN	5	/*  for sockets. */
 #define F_SETOWN	6	/*  for sockets. */
diff --git a/fs/ceph/file.c b/fs/ceph/file.c
index 66bbf6d517a9..6d8d4c7765e6 100644
--- a/fs/ceph/file.c
+++ b/fs/ceph/file.c
@@ -977,6 +977,10 @@ int ceph_atomic_open(struct inode *dir, struct dentry *dentry,
 			ceph_init_inode_acls(newino, &as_ctx);
 			file->f_mode |= FMODE_CREATED;
 		}
+		if ((flags & OPENAT2_REGULAR) && !d_is_reg(dentry)) {
+			err = -EFTYPE;
+			goto out_req;
+		}
 		err = finish_open(file, dentry, ceph_open);
 	}
 out_req:
diff --git a/fs/fcntl.c b/fs/fcntl.c
index beab8080badf..240bb511557a 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -1169,9 +1169,9 @@ static int __init fcntl_init(void)
 	 * Exceptions: O_NONBLOCK is a two bit define on parisc; O_NDELAY
 	 * is defined as O_NONBLOCK on some platforms and not on others.
 	 */
-	BUILD_BUG_ON(20 - 1 /* for O_RDONLY being 0 */ !=
+	BUILD_BUG_ON(21 - 1 /* for O_RDONLY being 0 */ !=
 		HWEIGHT32(
-			(VALID_OPEN_FLAGS & ~(O_NONBLOCK | O_NDELAY)) |
+			(VALID_OPENAT2_FLAGS & ~(O_NONBLOCK | O_NDELAY)) |
 			__FMODE_EXEC));
 
 	fasync_cache = kmem_cache_create("fasync_cache",
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index 8344040ecaf7..4604e2e8a9cc 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -738,6 +738,12 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
 	inode = gfs2_dir_search(dir, &dentry->d_name, !S_ISREG(mode) || excl);
 	error = PTR_ERR(inode);
 	if (!IS_ERR(inode)) {
+		if (file && (file->f_flags & OPENAT2_REGULAR) && !S_ISREG(inode->i_mode)) {
+			iput(inode);
+			inode = NULL;
+			error = -EFTYPE;
+			goto fail_gunlock;
+		}
 		if (S_ISDIR(inode->i_mode)) {
 			iput(inode);
 			inode = NULL;
diff --git a/fs/namei.c b/fs/namei.c
index 2113958c3b7a..e557c538c238 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -4679,6 +4679,10 @@ static int do_open(struct nameidata *nd,
 		if (unlikely(error))
 			return error;
 	}
+
+	if ((open_flag & OPENAT2_REGULAR) && !d_is_reg(nd->path.dentry))
+		return -EFTYPE;
+
 	if ((nd->flags & LOOKUP_DIRECTORY) && !d_can_lookup(nd->path.dentry))
 		return -ENOTDIR;
 
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index ddc3789363a5..bfe9470327c8 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -2195,6 +2195,10 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry,
 			break;
 		case -EISDIR:
 		case -ENOTDIR:
+			if (open_flags & OPENAT2_REGULAR) {
+				err = -EFTYPE;
+				break;
+			}
 			goto no_open;
 		case -ELOOP:
 			if (!(open_flags & O_NOFOLLOW))
diff --git a/fs/open.c b/fs/open.c
index 681d405bc61e..a6f445f72181 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -960,7 +960,7 @@ static int do_dentry_open(struct file *f,
 	if (f->f_mapping->a_ops && f->f_mapping->a_ops->direct_IO)
 		f->f_mode |= FMODE_CAN_ODIRECT;
 
-	f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
+	f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC | OPENAT2_REGULAR);
 	f->f_iocb_flags = iocb_flags(f);
 
 	file_ra_state_init(&f->f_ra, f->f_mapping->host->i_mapping);
@@ -1183,7 +1183,7 @@ inline int build_open_flags(const struct open_how *how, struct open_flags *op)
 	int lookup_flags = 0;
 	int acc_mode = ACC_MODE(flags);
 
-	BUILD_BUG_ON_MSG(upper_32_bits(VALID_OPEN_FLAGS),
+	BUILD_BUG_ON_MSG(upper_32_bits(VALID_OPENAT2_FLAGS),
 			 "struct open_flags doesn't yet handle flags > 32 bits");
 
 	/*
@@ -1196,7 +1196,7 @@ inline int build_open_flags(const struct open_how *how, struct open_flags *op)
 	 * values before calling build_open_flags(), but openat2(2) checks all
 	 * of its arguments.
 	 */
-	if (flags & ~VALID_OPEN_FLAGS)
+	if (flags & ~VALID_OPENAT2_FLAGS)
 		return -EINVAL;
 	if (how->resolve & ~VALID_RESOLVE_FLAGS)
 		return -EINVAL;
@@ -1235,6 +1235,8 @@ inline int build_open_flags(const struct open_how *how, struct open_flags *op)
 			return -EINVAL;
 		if (!(acc_mode & MAY_WRITE))
 			return -EINVAL;
+	} else if ((flags & O_DIRECTORY) && (flags & OPENAT2_REGULAR)) {
+		return -EINVAL;
 	}
 	if (flags & O_PATH) {
 		/* O_PATH only permits certain other flags to be set. */
diff --git a/fs/smb/client/dir.c b/fs/smb/client/dir.c
index 953f1fee8cb8..355681ebacf1 100644
--- a/fs/smb/client/dir.c
+++ b/fs/smb/client/dir.c
@@ -222,6 +222,13 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned
 				goto cifs_create_get_file_info;
 			}
 
+			if ((oflags & OPENAT2_REGULAR) && !S_ISREG(newinode->i_mode)) {
+				CIFSSMBClose(xid, tcon, fid->netfid);
+				iput(newinode);
+				rc = -EFTYPE;
+				goto out;
+			}
+
 			if (S_ISDIR(newinode->i_mode)) {
 				CIFSSMBClose(xid, tcon, fid->netfid);
 				iput(newinode);
@@ -436,11 +443,16 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned
 		goto out_err;
 	}
 
-	if (newinode)
+	if (newinode) {
+		if ((oflags & OPENAT2_REGULAR) && !S_ISREG(newinode->i_mode)) {
+			rc = -EFTYPE;
+			goto out_err;
+		}
 		if (S_ISDIR(newinode->i_mode)) {
 			rc = -EISDIR;
 			goto out_err;
 		}
+	}
 
 	d_drop(direntry);
 	d_add(direntry, newinode);
diff --git a/include/linux/fcntl.h b/include/linux/fcntl.h
index a332e79b3207..a80026718217 100644
--- a/include/linux/fcntl.h
+++ b/include/linux/fcntl.h
@@ -12,6 +12,8 @@
 	 FASYNC	| O_DIRECT | O_LARGEFILE | O_DIRECTORY | O_NOFOLLOW | \
 	 O_NOATIME | O_CLOEXEC | O_PATH | __O_TMPFILE)
 
+#define VALID_OPENAT2_FLAGS (VALID_OPEN_FLAGS | OPENAT2_REGULAR)
+
 /* List of all valid flags for the how->resolve argument: */
 #define VALID_RESOLVE_FLAGS \
 	(RESOLVE_NO_XDEV | RESOLVE_NO_MAGICLINKS | RESOLVE_NO_SYMLINKS | \
diff --git a/include/uapi/asm-generic/errno.h b/include/uapi/asm-generic/errno.h
index 92e7ae493ee3..bd78e69e0a43 100644
--- a/include/uapi/asm-generic/errno.h
+++ b/include/uapi/asm-generic/errno.h
@@ -122,4 +122,6 @@
 
 #define EHWPOISON	133	/* Memory page has hardware error */
 
+#define EFTYPE		134	/* Wrong file type for the intended operation */
+
 #endif
diff --git a/include/uapi/asm-generic/fcntl.h b/include/uapi/asm-generic/fcntl.h
index 613475285643..b2c2ddd0edc0 100644
--- a/include/uapi/asm-generic/fcntl.h
+++ b/include/uapi/asm-generic/fcntl.h
@@ -88,6 +88,10 @@
 #define __O_TMPFILE	020000000
 #endif
 
+#ifndef OPENAT2_REGULAR
+#define OPENAT2_REGULAR	040000000
+#endif
+
 /* a horrid kludge trying to make sure that this will fail on old kernels */
 #define O_TMPFILE (__O_TMPFILE | O_DIRECTORY)
 
diff --git a/tools/arch/alpha/include/uapi/asm/errno.h b/tools/arch/alpha/include/uapi/asm/errno.h
index 6791f6508632..1a99f38813c7 100644
--- a/tools/arch/alpha/include/uapi/asm/errno.h
+++ b/tools/arch/alpha/include/uapi/asm/errno.h
@@ -127,4 +127,6 @@
 
 #define EHWPOISON	139	/* Memory page has hardware error */
 
+#define EFTYPE		140	/* Wrong file type for the intended operation */
+
 #endif
diff --git a/tools/arch/mips/include/uapi/asm/errno.h b/tools/arch/mips/include/uapi/asm/errno.h
index c01ed91b1ef4..1835a50b69ce 100644
--- a/tools/arch/mips/include/uapi/asm/errno.h
+++ b/tools/arch/mips/include/uapi/asm/errno.h
@@ -126,6 +126,8 @@
 
 #define EHWPOISON	168	/* Memory page has hardware error */
 
+#define EFTYPE		169	/* Wrong file type for the intended operation */
+
 #define EDQUOT		1133	/* Quota exceeded */
 
 
diff --git a/tools/arch/parisc/include/uapi/asm/errno.h b/tools/arch/parisc/include/uapi/asm/errno.h
index 8cbc07c1903e..93194fbb0a80 100644
--- a/tools/arch/parisc/include/uapi/asm/errno.h
+++ b/tools/arch/parisc/include/uapi/asm/errno.h
@@ -124,4 +124,6 @@
 
 #define EHWPOISON	257	/* Memory page has hardware error */
 
+#define EFTYPE		258	/* Wrong file type for the intended operation */
+
 #endif
diff --git a/tools/arch/sparc/include/uapi/asm/errno.h b/tools/arch/sparc/include/uapi/asm/errno.h
index 4a41e7835fd5..71940ec9130b 100644
--- a/tools/arch/sparc/include/uapi/asm/errno.h
+++ b/tools/arch/sparc/include/uapi/asm/errno.h
@@ -117,4 +117,6 @@
 
 #define EHWPOISON	135	/* Memory page has hardware error */
 
+#define EFTYPE		136	/* Wrong file type for the intended operation */
+
 #endif
diff --git a/tools/include/uapi/asm-generic/errno.h b/tools/include/uapi/asm-generic/errno.h
index 92e7ae493ee3..bd78e69e0a43 100644
--- a/tools/include/uapi/asm-generic/errno.h
+++ b/tools/include/uapi/asm-generic/errno.h
@@ -122,4 +122,6 @@
 
 #define EHWPOISON	133	/* Memory page has hardware error */
 
+#define EFTYPE		134	/* Wrong file type for the intended operation */
+
 #endif
-- 
2.53.0


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

* [PATCH v6 2/4] kselftest/openat2: test for OPENAT2_REGULAR flag
  2026-03-28 17:22 [PATCH v6 0/4] OPENAT2_REGULAR flag support for openat2 Dorjoy Chowdhury
  2026-03-28 17:22 ` [PATCH v6 1/4] openat2: new OPENAT2_REGULAR flag support Dorjoy Chowdhury
@ 2026-03-28 17:22 ` Dorjoy Chowdhury
  2026-03-28 17:22 ` [PATCH v6 3/4] sparc/fcntl.h: convert O_* flag macros from hex to octal Dorjoy Chowdhury
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 23+ messages in thread
From: Dorjoy Chowdhury @ 2026-03-28 17:22 UTC (permalink / raw)
  To: linux-fsdevel
  Cc: linux-kernel, linux-api, ceph-devel, gfs2, linux-nfs, linux-cifs,
	v9fs, linux-kselftest, viro, brauner, jack, jlayton, chuck.lever,
	alex.aring, arnd, adilger, mjguzik, smfrench, richard.henderson,
	mattst88, linmag7, tsbogend, James.Bottomley, deller, davem,
	andreas, idryomov, amarkuze, slava, agruenba, trondmy, anna,
	sfrench, pc, ronniesahlberg, sprasad, tom, bharathsm, shuah,
	miklos, hansg

Just a happy path test.

Signed-off-by: Dorjoy Chowdhury <dorjoychy111@gmail.com>
---
 .../testing/selftests/openat2/openat2_test.c  | 37 ++++++++++++++++++-
 1 file changed, 36 insertions(+), 1 deletion(-)

diff --git a/tools/testing/selftests/openat2/openat2_test.c b/tools/testing/selftests/openat2/openat2_test.c
index 0e161ef9e9e4..e8847f7d416c 100644
--- a/tools/testing/selftests/openat2/openat2_test.c
+++ b/tools/testing/selftests/openat2/openat2_test.c
@@ -320,8 +320,42 @@ void test_openat2_flags(void)
 	}
 }
 
+#ifndef OPENAT2_REGULAR
+#define OPENAT2_REGULAR 040000000
+#endif
+
+#ifndef EFTYPE
+#define EFTYPE 134
+#endif
+
+void test_openat2_regular_flag(void)
+{
+	if (!openat2_supported) {
+		ksft_test_result_skip("Skipping %s as openat2 is not supported\n", __func__);
+		return;
+	}
+
+	struct open_how how = {
+		.flags = OPENAT2_REGULAR | O_RDONLY
+	};
+
+	int fd = sys_openat2(AT_FDCWD, "/dev/null", &how);
+
+	if (fd == -ENOENT) {
+		ksft_test_result_skip("Skipping %s as there is no /dev/null\n", __func__);
+		return;
+	}
+
+	if (fd != -EFTYPE) {
+		ksft_test_result_fail("openat2 should return EFTYPE\n");
+		return;
+	}
+
+	ksft_test_result_pass("%s succeeded\n", __func__);
+}
+
 #define NUM_TESTS (NUM_OPENAT2_STRUCT_VARIATIONS * NUM_OPENAT2_STRUCT_TESTS + \
-		   NUM_OPENAT2_FLAG_TESTS)
+		   NUM_OPENAT2_FLAG_TESTS + 1)
 
 int main(int argc, char **argv)
 {
@@ -330,6 +364,7 @@ int main(int argc, char **argv)
 
 	test_openat2_struct();
 	test_openat2_flags();
+	test_openat2_regular_flag();
 
 	if (ksft_get_fail_cnt() + ksft_get_error_cnt() > 0)
 		ksft_exit_fail();
-- 
2.53.0


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

* [PATCH v6 3/4] sparc/fcntl.h: convert O_* flag macros from hex to octal
  2026-03-28 17:22 [PATCH v6 0/4] OPENAT2_REGULAR flag support for openat2 Dorjoy Chowdhury
  2026-03-28 17:22 ` [PATCH v6 1/4] openat2: new OPENAT2_REGULAR flag support Dorjoy Chowdhury
  2026-03-28 17:22 ` [PATCH v6 2/4] kselftest/openat2: test for OPENAT2_REGULAR flag Dorjoy Chowdhury
@ 2026-03-28 17:22 ` Dorjoy Chowdhury
  2026-03-28 17:22 ` [PATCH v6 4/4] mips/fcntl.h: " Dorjoy Chowdhury
  2026-04-16 13:07 ` [PATCH v6 0/4] OPENAT2_REGULAR flag support for openat2 Christian Brauner
  4 siblings, 0 replies; 23+ messages in thread
From: Dorjoy Chowdhury @ 2026-03-28 17:22 UTC (permalink / raw)
  To: linux-fsdevel
  Cc: linux-kernel, linux-api, ceph-devel, gfs2, linux-nfs, linux-cifs,
	v9fs, linux-kselftest, viro, brauner, jack, jlayton, chuck.lever,
	alex.aring, arnd, adilger, mjguzik, smfrench, richard.henderson,
	mattst88, linmag7, tsbogend, James.Bottomley, deller, davem,
	andreas, idryomov, amarkuze, slava, agruenba, trondmy, anna,
	sfrench, pc, ronniesahlberg, sprasad, tom, bharathsm, shuah,
	miklos, hansg

Following the convention in include/uapi/asm-generic/fcntl.h and other
architecture specific arch/*/include/uapi/asm/fcntl.h files.

Signed-off-by: Dorjoy Chowdhury <dorjoychy111@gmail.com>
---
 arch/sparc/include/uapi/asm/fcntl.h | 36 ++++++++++++++---------------
 1 file changed, 18 insertions(+), 18 deletions(-)

diff --git a/arch/sparc/include/uapi/asm/fcntl.h b/arch/sparc/include/uapi/asm/fcntl.h
index bb6e9fa94bc9..33ce58ec57f6 100644
--- a/arch/sparc/include/uapi/asm/fcntl.h
+++ b/arch/sparc/include/uapi/asm/fcntl.h
@@ -2,23 +2,23 @@
 #ifndef _SPARC_FCNTL_H
 #define _SPARC_FCNTL_H
 
-#define O_APPEND	0x0008
-#define FASYNC		0x0040	/* fcntl, for BSD compatibility */
-#define O_CREAT		0x0200	/* not fcntl */
-#define O_TRUNC		0x0400	/* not fcntl */
-#define O_EXCL		0x0800	/* not fcntl */
-#define O_DSYNC		0x2000	/* used to be O_SYNC, see below */
-#define O_NONBLOCK	0x4000
+#define O_APPEND	0000000010
+#define FASYNC		0000000100	/* fcntl, for BSD compatibility */
+#define O_CREAT		0000001000	/* not fcntl */
+#define O_TRUNC		0000002000	/* not fcntl */
+#define O_EXCL		0000004000	/* not fcntl */
+#define O_DSYNC		0000020000	/* used to be O_SYNC, see below */
+#define O_NONBLOCK	0000040000
 #if defined(__sparc__) && defined(__arch64__)
-#define O_NDELAY	0x0004
+#define O_NDELAY	0000000004
 #else
-#define O_NDELAY	(0x0004 | O_NONBLOCK)
+#define O_NDELAY	(0000000004 | O_NONBLOCK)
 #endif
-#define O_NOCTTY	0x8000	/* not fcntl */
-#define O_LARGEFILE	0x40000
-#define O_DIRECT        0x100000 /* direct disk access hint */
-#define O_NOATIME	0x200000
-#define O_CLOEXEC	0x400000
+#define O_NOCTTY	0000100000	/* not fcntl */
+#define O_LARGEFILE	0001000000
+#define O_DIRECT        0004000000 /* direct disk access hint */
+#define O_NOATIME	0010000000
+#define O_CLOEXEC	0020000000
 /*
  * Before Linux 2.6.33 only O_DSYNC semantics were implemented, but using
  * the O_SYNC flag.  We continue to use the existing numerical value
@@ -32,12 +32,12 @@
  *
  * Note: __O_SYNC must never be used directly.
  */
-#define __O_SYNC	0x800000
+#define __O_SYNC	0040000000
 #define O_SYNC		(__O_SYNC|O_DSYNC)
 
-#define O_PATH		0x1000000
-#define __O_TMPFILE	0x2000000
-#define OPENAT2_REGULAR	0x4000000
+#define O_PATH		0100000000
+#define __O_TMPFILE	0200000000
+#define OPENAT2_REGULAR	0400000000
 
 #define F_GETOWN	5	/*  for sockets. */
 #define F_SETOWN	6	/*  for sockets. */
-- 
2.53.0


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

* [PATCH v6 4/4] mips/fcntl.h: convert O_* flag macros from hex to octal
  2026-03-28 17:22 [PATCH v6 0/4] OPENAT2_REGULAR flag support for openat2 Dorjoy Chowdhury
                   ` (2 preceding siblings ...)
  2026-03-28 17:22 ` [PATCH v6 3/4] sparc/fcntl.h: convert O_* flag macros from hex to octal Dorjoy Chowdhury
@ 2026-03-28 17:22 ` Dorjoy Chowdhury
  2026-04-16 13:07 ` [PATCH v6 0/4] OPENAT2_REGULAR flag support for openat2 Christian Brauner
  4 siblings, 0 replies; 23+ messages in thread
From: Dorjoy Chowdhury @ 2026-03-28 17:22 UTC (permalink / raw)
  To: linux-fsdevel
  Cc: linux-kernel, linux-api, ceph-devel, gfs2, linux-nfs, linux-cifs,
	v9fs, linux-kselftest, viro, brauner, jack, jlayton, chuck.lever,
	alex.aring, arnd, adilger, mjguzik, smfrench, richard.henderson,
	mattst88, linmag7, tsbogend, James.Bottomley, deller, davem,
	andreas, idryomov, amarkuze, slava, agruenba, trondmy, anna,
	sfrench, pc, ronniesahlberg, sprasad, tom, bharathsm, shuah,
	miklos, hansg

Following the convention in include/uapi/asm-generic/fcntl.h and other
architecture specific arch/*/include/uapi/asm/fcntl.h files.

Signed-off-by: Dorjoy Chowdhury <dorjoychy111@gmail.com>
---
 arch/mips/include/uapi/asm/fcntl.h | 22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/arch/mips/include/uapi/asm/fcntl.h b/arch/mips/include/uapi/asm/fcntl.h
index 0369a38e3d4f..6aa3f49df17e 100644
--- a/arch/mips/include/uapi/asm/fcntl.h
+++ b/arch/mips/include/uapi/asm/fcntl.h
@@ -11,15 +11,15 @@
 
 #include <asm/sgidefs.h>
 
-#define O_APPEND	0x0008
-#define O_DSYNC		0x0010	/* used to be O_SYNC, see below */
-#define O_NONBLOCK	0x0080
-#define O_CREAT		0x0100	/* not fcntl */
-#define O_TRUNC		0x0200	/* not fcntl */
-#define O_EXCL		0x0400	/* not fcntl */
-#define O_NOCTTY	0x0800	/* not fcntl */
-#define FASYNC		0x1000	/* fcntl, for BSD compatibility */
-#define O_LARGEFILE	0x2000	/* allow large file opens */
+#define O_APPEND	0000010
+#define O_DSYNC		0000020	/* used to be O_SYNC, see below */
+#define O_NONBLOCK	0000200
+#define O_CREAT		0000400	/* not fcntl */
+#define O_TRUNC		0001000	/* not fcntl */
+#define O_EXCL		0002000	/* not fcntl */
+#define O_NOCTTY	0004000	/* not fcntl */
+#define FASYNC		0010000	/* fcntl, for BSD compatibility */
+#define O_LARGEFILE	0020000	/* allow large file opens */
 /*
  * Before Linux 2.6.33 only O_DSYNC semantics were implemented, but using
  * the O_SYNC flag.  We continue to use the existing numerical value
@@ -33,9 +33,9 @@
  *
  * Note: __O_SYNC must never be used directly.
  */
-#define __O_SYNC	0x4000
+#define __O_SYNC	0040000
 #define O_SYNC		(__O_SYNC|O_DSYNC)
-#define O_DIRECT	0x8000	/* direct disk access hint */
+#define O_DIRECT	0100000	/* direct disk access hint */
 
 #define F_GETLK		14
 #define F_SETLK		6
-- 
2.53.0


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

* Re: [PATCH v6 1/4] openat2: new OPENAT2_REGULAR flag support
  2026-03-28 17:22 ` [PATCH v6 1/4] openat2: new OPENAT2_REGULAR flag support Dorjoy Chowdhury
@ 2026-03-30 11:49   ` Jeff Layton
  2026-03-30 15:07     ` Dorjoy Chowdhury
  2026-04-16 11:41   ` Aleksa Sarai
  2026-04-16 13:52   ` Jori Koolstra
  2 siblings, 1 reply; 23+ messages in thread
From: Jeff Layton @ 2026-03-30 11:49 UTC (permalink / raw)
  To: Dorjoy Chowdhury, linux-fsdevel
  Cc: linux-kernel, linux-api, ceph-devel, gfs2, linux-nfs, linux-cifs,
	v9fs, linux-kselftest, viro, brauner, jack, chuck.lever,
	alex.aring, arnd, adilger, mjguzik, smfrench, richard.henderson,
	mattst88, linmag7, tsbogend, James.Bottomley, deller, davem,
	andreas, idryomov, amarkuze, slava, agruenba, trondmy, anna,
	sfrench, pc, ronniesahlberg, sprasad, tom, bharathsm, shuah,
	miklos, hansg

On Sat, 2026-03-28 at 23:22 +0600, Dorjoy Chowdhury wrote:
> This flag indicates the path should be opened if it's a regular file.
> This is useful to write secure programs that want to avoid being
> tricked into opening device nodes with special semantics while thinking
> they operate on regular files. This is a requested feature from the
> uapi-group[1].
> 
> A corresponding error code EFTYPE has been introduced. For example, if
> openat2 is called on path /dev/null with OPENAT2_REGULAR in the flag
> param, it will return -EFTYPE. EFTYPE is already used in BSD systems
> like FreeBSD, macOS.
> 
> When used in combination with O_CREAT, either the regular file is
> created, or if the path already exists, it is opened if it's a regular
> file. Otherwise, -EFTYPE is returned.
> 
> When OPENAT2_REGULAR is combined with O_DIRECTORY, -EINVAL is returned
> as it doesn't make sense to open a path that is both a directory and a
> regular file.
> 
> [1]: https://uapi-group.org/kernel-features/#ability-to-only-open-regular-files
> 
> Signed-off-by: Dorjoy Chowdhury <dorjoychy111@gmail.com>
> ---
>  arch/alpha/include/uapi/asm/errno.h        |  2 ++
>  arch/alpha/include/uapi/asm/fcntl.h        |  1 +
>  arch/mips/include/uapi/asm/errno.h         |  2 ++
>  arch/parisc/include/uapi/asm/errno.h       |  2 ++
>  arch/parisc/include/uapi/asm/fcntl.h       |  1 +
>  arch/sparc/include/uapi/asm/errno.h        |  2 ++
>  arch/sparc/include/uapi/asm/fcntl.h        |  1 +
>  fs/ceph/file.c                             |  4 ++++
>  fs/fcntl.c                                 |  4 ++--
>  fs/gfs2/inode.c                            |  6 ++++++
>  fs/namei.c                                 |  4 ++++
>  fs/nfs/dir.c                               |  4 ++++
>  fs/open.c                                  |  8 +++++---
>  fs/smb/client/dir.c                        | 14 +++++++++++++-
>  include/linux/fcntl.h                      |  2 ++
>  include/uapi/asm-generic/errno.h           |  2 ++
>  include/uapi/asm-generic/fcntl.h           |  4 ++++
>  tools/arch/alpha/include/uapi/asm/errno.h  |  2 ++
>  tools/arch/mips/include/uapi/asm/errno.h   |  2 ++
>  tools/arch/parisc/include/uapi/asm/errno.h |  2 ++
>  tools/arch/sparc/include/uapi/asm/errno.h  |  2 ++
>  tools/include/uapi/asm-generic/errno.h     |  2 ++
>  22 files changed, 67 insertions(+), 6 deletions(-)
> 
> diff --git a/arch/alpha/include/uapi/asm/errno.h b/arch/alpha/include/uapi/asm/errno.h
> index 6791f6508632..1a99f38813c7 100644
> --- a/arch/alpha/include/uapi/asm/errno.h
> +++ b/arch/alpha/include/uapi/asm/errno.h
> @@ -127,4 +127,6 @@
>  
>  #define EHWPOISON	139	/* Memory page has hardware error */
>  
> +#define EFTYPE		140	/* Wrong file type for the intended operation */
> +
>  #endif
> diff --git a/arch/alpha/include/uapi/asm/fcntl.h b/arch/alpha/include/uapi/asm/fcntl.h
> index 50bdc8e8a271..fe488bf7c18e 100644
> --- a/arch/alpha/include/uapi/asm/fcntl.h
> +++ b/arch/alpha/include/uapi/asm/fcntl.h
> @@ -34,6 +34,7 @@
>  
>  #define O_PATH		040000000
>  #define __O_TMPFILE	0100000000
> +#define OPENAT2_REGULAR	0200000000
>  
>  #define F_GETLK		7
>  #define F_SETLK		8
> diff --git a/arch/mips/include/uapi/asm/errno.h b/arch/mips/include/uapi/asm/errno.h
> index c01ed91b1ef4..1835a50b69ce 100644
> --- a/arch/mips/include/uapi/asm/errno.h
> +++ b/arch/mips/include/uapi/asm/errno.h
> @@ -126,6 +126,8 @@
>  
>  #define EHWPOISON	168	/* Memory page has hardware error */
>  
> +#define EFTYPE		169	/* Wrong file type for the intended operation */
> +
>  #define EDQUOT		1133	/* Quota exceeded */
>  
>  
> diff --git a/arch/parisc/include/uapi/asm/errno.h b/arch/parisc/include/uapi/asm/errno.h
> index 8cbc07c1903e..93194fbb0a80 100644
> --- a/arch/parisc/include/uapi/asm/errno.h
> +++ b/arch/parisc/include/uapi/asm/errno.h
> @@ -124,4 +124,6 @@
>  
>  #define EHWPOISON	257	/* Memory page has hardware error */
>  
> +#define EFTYPE		258	/* Wrong file type for the intended operation */
> +
>  #endif
> diff --git a/arch/parisc/include/uapi/asm/fcntl.h b/arch/parisc/include/uapi/asm/fcntl.h
> index 03dee816cb13..d46812f2f0f4 100644
> --- a/arch/parisc/include/uapi/asm/fcntl.h
> +++ b/arch/parisc/include/uapi/asm/fcntl.h
> @@ -19,6 +19,7 @@
>  
>  #define O_PATH		020000000
>  #define __O_TMPFILE	040000000
> +#define OPENAT2_REGULAR	0100000000
>  
>  #define F_GETLK64	8
>  #define F_SETLK64	9
> diff --git a/arch/sparc/include/uapi/asm/errno.h b/arch/sparc/include/uapi/asm/errno.h
> index 4a41e7835fd5..71940ec9130b 100644
> --- a/arch/sparc/include/uapi/asm/errno.h
> +++ b/arch/sparc/include/uapi/asm/errno.h
> @@ -117,4 +117,6 @@
>  
>  #define EHWPOISON	135	/* Memory page has hardware error */
>  
> +#define EFTYPE		136	/* Wrong file type for the intended operation */
> +
>  #endif
> diff --git a/arch/sparc/include/uapi/asm/fcntl.h b/arch/sparc/include/uapi/asm/fcntl.h
> index 67dae75e5274..bb6e9fa94bc9 100644
> --- a/arch/sparc/include/uapi/asm/fcntl.h
> +++ b/arch/sparc/include/uapi/asm/fcntl.h
> @@ -37,6 +37,7 @@
>  
>  #define O_PATH		0x1000000
>  #define __O_TMPFILE	0x2000000
> +#define OPENAT2_REGULAR	0x4000000
>  
>  #define F_GETOWN	5	/*  for sockets. */
>  #define F_SETOWN	6	/*  for sockets. */
> diff --git a/fs/ceph/file.c b/fs/ceph/file.c
> index 66bbf6d517a9..6d8d4c7765e6 100644
> --- a/fs/ceph/file.c
> +++ b/fs/ceph/file.c
> @@ -977,6 +977,10 @@ int ceph_atomic_open(struct inode *dir, struct dentry *dentry,
>  			ceph_init_inode_acls(newino, &as_ctx);
>  			file->f_mode |= FMODE_CREATED;
>  		}
> +		if ((flags & OPENAT2_REGULAR) && !d_is_reg(dentry)) {
> +			err = -EFTYPE;
> +			goto out_req;
> +		}

^^^
This doesn't look quite right. Here's a larger chunk of the code:

-------------------------8<--------------------------
        if (d_in_lookup(dentry)) {                                                                  
                dn = ceph_finish_lookup(req, dentry, err);                                          
                if (IS_ERR(dn))                                                                     
                        err = PTR_ERR(dn);                                                          
        } else {                                                                                    
                /* we were given a hashed negative dentry */                                        
                dn = NULL;                                                                          
        }                                                                                           
        if (err)                                                                                    
                goto out_req;                                                                       
        if (dn || d_really_is_negative(dentry) || d_is_symlink(dentry)) {                           
                /* make vfs retry on splice, ENOENT, or symlink */                                  
                doutc(cl, "finish_no_open on dn %p\n", dn);                                         
                err = finish_no_open(file, dn);                                                     
        } else {                                                                                    
                if (IS_ENCRYPTED(dir) &&                                                            
                    !fscrypt_has_permitted_context(dir, d_inode(dentry))) {                         
                        pr_warn_client(cl,                                                          
                                "Inconsistent encryption context (parent %llx:%llx child %llx:%llx)\n",
                                ceph_vinop(dir), ceph_vinop(d_inode(dentry)));                      
                        goto out_req;                                                               
                }                                                                                   
                                                                                                    
                doutc(cl, "finish_open on dn %p\n", dn);                                            
                if (req->r_op == CEPH_MDS_OP_CREATE && req->r_reply_info.has_create_ino) {          
                        struct inode *newino = d_inode(dentry);                                     
                                                                                                    
                        cache_file_layout(dir, newino);                                             
                        ceph_init_inode_acls(newino, &as_ctx);                                      
                        file->f_mode |= FMODE_CREATED;                                              
                }                                                                                   
                err = finish_open(file, dentry, ceph_open);                                         
        }                                                                                           
-------------------------8<--------------------------

It looks like this won't handle it correctly if the pathwalk terminates
on a symlink (re: d_is_symlink() case). You should either set up a test
ceph cluster on your own, or reach out to the ceph community and ask
them to test this.

>  		err = finish_open(file, dentry, ceph_open);
>  	}
>  out_req:
> diff --git a/fs/fcntl.c b/fs/fcntl.c
> index beab8080badf..240bb511557a 100644
> --- a/fs/fcntl.c
> +++ b/fs/fcntl.c
> @@ -1169,9 +1169,9 @@ static int __init fcntl_init(void)
>  	 * Exceptions: O_NONBLOCK is a two bit define on parisc; O_NDELAY
>  	 * is defined as O_NONBLOCK on some platforms and not on others.
>  	 */
> -	BUILD_BUG_ON(20 - 1 /* for O_RDONLY being 0 */ !=
> +	BUILD_BUG_ON(21 - 1 /* for O_RDONLY being 0 */ !=
>  		HWEIGHT32(
> -			(VALID_OPEN_FLAGS & ~(O_NONBLOCK | O_NDELAY)) |
> +			(VALID_OPENAT2_FLAGS & ~(O_NONBLOCK | O_NDELAY)) |
>  			__FMODE_EXEC));
>  
>  	fasync_cache = kmem_cache_create("fasync_cache",
> diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
> index 8344040ecaf7..4604e2e8a9cc 100644
> --- a/fs/gfs2/inode.c
> +++ b/fs/gfs2/inode.c
> @@ -738,6 +738,12 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
>  	inode = gfs2_dir_search(dir, &dentry->d_name, !S_ISREG(mode) || excl);
>  	error = PTR_ERR(inode);
>  	if (!IS_ERR(inode)) {
> +		if (file && (file->f_flags & OPENAT2_REGULAR) && !S_ISREG(inode->i_mode)) {

Isn't OPENAT2_REGULAR getting masked off in ->f_flags now?

JFYI: it's quite simple to set up a single-node gfs2 fs to test this.

> +			iput(inode);
> +			inode = NULL;
> +			error = -EFTYPE;
> +			goto fail_gunlock;
> +		}
>  		if (S_ISDIR(inode->i_mode)) {
>  			iput(inode);
>  			inode = NULL;
> diff --git a/fs/namei.c b/fs/namei.c
> index 2113958c3b7a..e557c538c238 100644
> --- a/fs/namei.c
> +++ b/fs/namei.c
> @@ -4679,6 +4679,10 @@ static int do_open(struct nameidata *nd,
>  		if (unlikely(error))
>  			return error;
>  	}
> +
> +	if ((open_flag & OPENAT2_REGULAR) && !d_is_reg(nd->path.dentry))
> +		return -EFTYPE;
> +
>  	if ((nd->flags & LOOKUP_DIRECTORY) && !d_can_lookup(nd->path.dentry))
>  		return -ENOTDIR;
>  
> diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
> index ddc3789363a5..bfe9470327c8 100644
> --- a/fs/nfs/dir.c
> +++ b/fs/nfs/dir.c
> @@ -2195,6 +2195,10 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry,
>  			break;
>  		case -EISDIR:
>  		case -ENOTDIR:
> +			if (open_flags & OPENAT2_REGULAR) {
> +				err = -EFTYPE;
> +				break;
> +			}
>  			goto no_open;
>  		case -ELOOP:
>  			if (!(open_flags & O_NOFOLLOW))
> diff --git a/fs/open.c b/fs/open.c
> index 681d405bc61e..a6f445f72181 100644
> --- a/fs/open.c
> +++ b/fs/open.c
> @@ -960,7 +960,7 @@ static int do_dentry_open(struct file *f,
>  	if (f->f_mapping->a_ops && f->f_mapping->a_ops->direct_IO)
>  		f->f_mode |= FMODE_CAN_ODIRECT;
>  
> -	f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
> +	f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC | OPENAT2_REGULAR);
>  	f->f_iocb_flags = iocb_flags(f);
>  
>  	file_ra_state_init(&f->f_ra, f->f_mapping->host->i_mapping);
> @@ -1183,7 +1183,7 @@ inline int build_open_flags(const struct open_how *how, struct open_flags *op)
>  	int lookup_flags = 0;
>  	int acc_mode = ACC_MODE(flags);
>  
> -	BUILD_BUG_ON_MSG(upper_32_bits(VALID_OPEN_FLAGS),
> +	BUILD_BUG_ON_MSG(upper_32_bits(VALID_OPENAT2_FLAGS),
>  			 "struct open_flags doesn't yet handle flags > 32 bits");
>  
>  	/*
> @@ -1196,7 +1196,7 @@ inline int build_open_flags(const struct open_how *how, struct open_flags *op)
>  	 * values before calling build_open_flags(), but openat2(2) checks all
>  	 * of its arguments.
>  	 */
> -	if (flags & ~VALID_OPEN_FLAGS)
> +	if (flags & ~VALID_OPENAT2_FLAGS)
>  		return -EINVAL;
>  	if (how->resolve & ~VALID_RESOLVE_FLAGS)
>  		return -EINVAL;
> @@ -1235,6 +1235,8 @@ inline int build_open_flags(const struct open_how *how, struct open_flags *op)
>  			return -EINVAL;
>  		if (!(acc_mode & MAY_WRITE))
>  			return -EINVAL;
> +	} else if ((flags & O_DIRECTORY) && (flags & OPENAT2_REGULAR)) {
> +		return -EINVAL;
>  	}
>  	if (flags & O_PATH) {
>  		/* O_PATH only permits certain other flags to be set. */
> diff --git a/fs/smb/client/dir.c b/fs/smb/client/dir.c
> index 953f1fee8cb8..355681ebacf1 100644
> --- a/fs/smb/client/dir.c
> +++ b/fs/smb/client/dir.c
> @@ -222,6 +222,13 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned
>  				goto cifs_create_get_file_info;
>  			}
>  
> +			if ((oflags & OPENAT2_REGULAR) && !S_ISREG(newinode->i_mode)) {
> +				CIFSSMBClose(xid, tcon, fid->netfid);
> +				iput(newinode);
> +				rc = -EFTYPE;
> +				goto out;
> +			}
> +
>  			if (S_ISDIR(newinode->i_mode)) {
>  				CIFSSMBClose(xid, tcon, fid->netfid);
>  				iput(newinode);
> @@ -436,11 +443,16 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned
>  		goto out_err;
>  	}
>  
> -	if (newinode)
> +	if (newinode) {
> +		if ((oflags & OPENAT2_REGULAR) && !S_ISREG(newinode->i_mode)) {
> +			rc = -EFTYPE;
> +			goto out_err;
> +		}
>  		if (S_ISDIR(newinode->i_mode)) {
>  			rc = -EISDIR;
>  			goto out_err;
>  		}
> +	}
>  
>  	d_drop(direntry);
>  	d_add(direntry, newinode);
> diff --git a/include/linux/fcntl.h b/include/linux/fcntl.h
> index a332e79b3207..a80026718217 100644
> --- a/include/linux/fcntl.h
> +++ b/include/linux/fcntl.h
> @@ -12,6 +12,8 @@
>  	 FASYNC	| O_DIRECT | O_LARGEFILE | O_DIRECTORY | O_NOFOLLOW | \
>  	 O_NOATIME | O_CLOEXEC | O_PATH | __O_TMPFILE)
>  
> +#define VALID_OPENAT2_FLAGS (VALID_OPEN_FLAGS | OPENAT2_REGULAR)
> +
>  /* List of all valid flags for the how->resolve argument: */
>  #define VALID_RESOLVE_FLAGS \
>  	(RESOLVE_NO_XDEV | RESOLVE_NO_MAGICLINKS | RESOLVE_NO_SYMLINKS | \
> diff --git a/include/uapi/asm-generic/errno.h b/include/uapi/asm-generic/errno.h
> index 92e7ae493ee3..bd78e69e0a43 100644
> --- a/include/uapi/asm-generic/errno.h
> +++ b/include/uapi/asm-generic/errno.h
> @@ -122,4 +122,6 @@
>  
>  #define EHWPOISON	133	/* Memory page has hardware error */
>  
> +#define EFTYPE		134	/* Wrong file type for the intended operation */
> +
>  #endif
> diff --git a/include/uapi/asm-generic/fcntl.h b/include/uapi/asm-generic/fcntl.h
> index 613475285643..b2c2ddd0edc0 100644
> --- a/include/uapi/asm-generic/fcntl.h
> +++ b/include/uapi/asm-generic/fcntl.h
> @@ -88,6 +88,10 @@
>  #define __O_TMPFILE	020000000
>  #endif
>  
> +#ifndef OPENAT2_REGULAR
> +#define OPENAT2_REGULAR	040000000
> +#endif
> +
>  /* a horrid kludge trying to make sure that this will fail on old kernels */
>  #define O_TMPFILE (__O_TMPFILE | O_DIRECTORY)
>  
> diff --git a/tools/arch/alpha/include/uapi/asm/errno.h b/tools/arch/alpha/include/uapi/asm/errno.h
> index 6791f6508632..1a99f38813c7 100644
> --- a/tools/arch/alpha/include/uapi/asm/errno.h
> +++ b/tools/arch/alpha/include/uapi/asm/errno.h
> @@ -127,4 +127,6 @@
>  
>  #define EHWPOISON	139	/* Memory page has hardware error */
>  
> +#define EFTYPE		140	/* Wrong file type for the intended operation */
> +
>  #endif
> diff --git a/tools/arch/mips/include/uapi/asm/errno.h b/tools/arch/mips/include/uapi/asm/errno.h
> index c01ed91b1ef4..1835a50b69ce 100644
> --- a/tools/arch/mips/include/uapi/asm/errno.h
> +++ b/tools/arch/mips/include/uapi/asm/errno.h
> @@ -126,6 +126,8 @@
>  
>  #define EHWPOISON	168	/* Memory page has hardware error */
>  
> +#define EFTYPE		169	/* Wrong file type for the intended operation */
> +
>  #define EDQUOT		1133	/* Quota exceeded */
>  
>  
> diff --git a/tools/arch/parisc/include/uapi/asm/errno.h b/tools/arch/parisc/include/uapi/asm/errno.h
> index 8cbc07c1903e..93194fbb0a80 100644
> --- a/tools/arch/parisc/include/uapi/asm/errno.h
> +++ b/tools/arch/parisc/include/uapi/asm/errno.h
> @@ -124,4 +124,6 @@
>  
>  #define EHWPOISON	257	/* Memory page has hardware error */
>  
> +#define EFTYPE		258	/* Wrong file type for the intended operation */
> +
>  #endif
> diff --git a/tools/arch/sparc/include/uapi/asm/errno.h b/tools/arch/sparc/include/uapi/asm/errno.h
> index 4a41e7835fd5..71940ec9130b 100644
> --- a/tools/arch/sparc/include/uapi/asm/errno.h
> +++ b/tools/arch/sparc/include/uapi/asm/errno.h
> @@ -117,4 +117,6 @@
>  
>  #define EHWPOISON	135	/* Memory page has hardware error */
>  
> +#define EFTYPE		136	/* Wrong file type for the intended operation */
> +
>  #endif
> diff --git a/tools/include/uapi/asm-generic/errno.h b/tools/include/uapi/asm-generic/errno.h
> index 92e7ae493ee3..bd78e69e0a43 100644
> --- a/tools/include/uapi/asm-generic/errno.h
> +++ b/tools/include/uapi/asm-generic/errno.h
> @@ -122,4 +122,6 @@
>  
>  #define EHWPOISON	133	/* Memory page has hardware error */
>  
> +#define EFTYPE		134	/* Wrong file type for the intended operation */
> +
>  #endif

-- 
Jeff Layton <jlayton@kernel.org>

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

* Re: [PATCH v6 1/4] openat2: new OPENAT2_REGULAR flag support
  2026-03-30 11:49   ` Jeff Layton
@ 2026-03-30 15:07     ` Dorjoy Chowdhury
  2026-04-01 19:02       ` Jeff Layton
  0 siblings, 1 reply; 23+ messages in thread
From: Dorjoy Chowdhury @ 2026-03-30 15:07 UTC (permalink / raw)
  To: Jeff Layton
  Cc: linux-fsdevel, linux-kernel, linux-api, ceph-devel, gfs2,
	linux-nfs, linux-cifs, v9fs, linux-kselftest, viro, brauner, jack,
	chuck.lever, alex.aring, arnd, adilger, mjguzik, smfrench,
	richard.henderson, mattst88, linmag7, tsbogend, James.Bottomley,
	deller, davem, andreas, idryomov, amarkuze, slava, agruenba,
	trondmy, anna, sfrench, pc, ronniesahlberg, sprasad, tom,
	bharathsm, shuah, miklos, hansg

On Mon, Mar 30, 2026 at 5:49 PM Jeff Layton <jlayton@kernel.org> wrote:
>
> On Sat, 2026-03-28 at 23:22 +0600, Dorjoy Chowdhury wrote:
> > This flag indicates the path should be opened if it's a regular file.
> > This is useful to write secure programs that want to avoid being
> > tricked into opening device nodes with special semantics while thinking
> > they operate on regular files. This is a requested feature from the
> > uapi-group[1].
> >
> > A corresponding error code EFTYPE has been introduced. For example, if
> > openat2 is called on path /dev/null with OPENAT2_REGULAR in the flag
> > param, it will return -EFTYPE. EFTYPE is already used in BSD systems
> > like FreeBSD, macOS.
> >
> > When used in combination with O_CREAT, either the regular file is
> > created, or if the path already exists, it is opened if it's a regular
> > file. Otherwise, -EFTYPE is returned.
> >
> > When OPENAT2_REGULAR is combined with O_DIRECTORY, -EINVAL is returned
> > as it doesn't make sense to open a path that is both a directory and a
> > regular file.
> >
> > [1]: https://uapi-group.org/kernel-features/#ability-to-only-open-regular-files
> >
> > Signed-off-by: Dorjoy Chowdhury <dorjoychy111@gmail.com>
> > ---
> >  arch/alpha/include/uapi/asm/errno.h        |  2 ++
> >  arch/alpha/include/uapi/asm/fcntl.h        |  1 +
> >  arch/mips/include/uapi/asm/errno.h         |  2 ++
> >  arch/parisc/include/uapi/asm/errno.h       |  2 ++
> >  arch/parisc/include/uapi/asm/fcntl.h       |  1 +
> >  arch/sparc/include/uapi/asm/errno.h        |  2 ++
> >  arch/sparc/include/uapi/asm/fcntl.h        |  1 +
> >  fs/ceph/file.c                             |  4 ++++
> >  fs/fcntl.c                                 |  4 ++--
> >  fs/gfs2/inode.c                            |  6 ++++++
> >  fs/namei.c                                 |  4 ++++
> >  fs/nfs/dir.c                               |  4 ++++
> >  fs/open.c                                  |  8 +++++---
> >  fs/smb/client/dir.c                        | 14 +++++++++++++-
> >  include/linux/fcntl.h                      |  2 ++
> >  include/uapi/asm-generic/errno.h           |  2 ++
> >  include/uapi/asm-generic/fcntl.h           |  4 ++++
> >  tools/arch/alpha/include/uapi/asm/errno.h  |  2 ++
> >  tools/arch/mips/include/uapi/asm/errno.h   |  2 ++
> >  tools/arch/parisc/include/uapi/asm/errno.h |  2 ++
> >  tools/arch/sparc/include/uapi/asm/errno.h  |  2 ++
> >  tools/include/uapi/asm-generic/errno.h     |  2 ++
> >  22 files changed, 67 insertions(+), 6 deletions(-)
> >
> > diff --git a/arch/alpha/include/uapi/asm/errno.h b/arch/alpha/include/uapi/asm/errno.h
> > index 6791f6508632..1a99f38813c7 100644
> > --- a/arch/alpha/include/uapi/asm/errno.h
> > +++ b/arch/alpha/include/uapi/asm/errno.h
> > @@ -127,4 +127,6 @@
> >
> >  #define EHWPOISON    139     /* Memory page has hardware error */
> >
> > +#define EFTYPE               140     /* Wrong file type for the intended operation */
> > +
> >  #endif
> > diff --git a/arch/alpha/include/uapi/asm/fcntl.h b/arch/alpha/include/uapi/asm/fcntl.h
> > index 50bdc8e8a271..fe488bf7c18e 100644
> > --- a/arch/alpha/include/uapi/asm/fcntl.h
> > +++ b/arch/alpha/include/uapi/asm/fcntl.h
> > @@ -34,6 +34,7 @@
> >
> >  #define O_PATH               040000000
> >  #define __O_TMPFILE  0100000000
> > +#define OPENAT2_REGULAR      0200000000
> >
> >  #define F_GETLK              7
> >  #define F_SETLK              8
> > diff --git a/arch/mips/include/uapi/asm/errno.h b/arch/mips/include/uapi/asm/errno.h
> > index c01ed91b1ef4..1835a50b69ce 100644
> > --- a/arch/mips/include/uapi/asm/errno.h
> > +++ b/arch/mips/include/uapi/asm/errno.h
> > @@ -126,6 +126,8 @@
> >
> >  #define EHWPOISON    168     /* Memory page has hardware error */
> >
> > +#define EFTYPE               169     /* Wrong file type for the intended operation */
> > +
> >  #define EDQUOT               1133    /* Quota exceeded */
> >
> >
> > diff --git a/arch/parisc/include/uapi/asm/errno.h b/arch/parisc/include/uapi/asm/errno.h
> > index 8cbc07c1903e..93194fbb0a80 100644
> > --- a/arch/parisc/include/uapi/asm/errno.h
> > +++ b/arch/parisc/include/uapi/asm/errno.h
> > @@ -124,4 +124,6 @@
> >
> >  #define EHWPOISON    257     /* Memory page has hardware error */
> >
> > +#define EFTYPE               258     /* Wrong file type for the intended operation */
> > +
> >  #endif
> > diff --git a/arch/parisc/include/uapi/asm/fcntl.h b/arch/parisc/include/uapi/asm/fcntl.h
> > index 03dee816cb13..d46812f2f0f4 100644
> > --- a/arch/parisc/include/uapi/asm/fcntl.h
> > +++ b/arch/parisc/include/uapi/asm/fcntl.h
> > @@ -19,6 +19,7 @@
> >
> >  #define O_PATH               020000000
> >  #define __O_TMPFILE  040000000
> > +#define OPENAT2_REGULAR      0100000000
> >
> >  #define F_GETLK64    8
> >  #define F_SETLK64    9
> > diff --git a/arch/sparc/include/uapi/asm/errno.h b/arch/sparc/include/uapi/asm/errno.h
> > index 4a41e7835fd5..71940ec9130b 100644
> > --- a/arch/sparc/include/uapi/asm/errno.h
> > +++ b/arch/sparc/include/uapi/asm/errno.h
> > @@ -117,4 +117,6 @@
> >
> >  #define EHWPOISON    135     /* Memory page has hardware error */
> >
> > +#define EFTYPE               136     /* Wrong file type for the intended operation */
> > +
> >  #endif
> > diff --git a/arch/sparc/include/uapi/asm/fcntl.h b/arch/sparc/include/uapi/asm/fcntl.h
> > index 67dae75e5274..bb6e9fa94bc9 100644
> > --- a/arch/sparc/include/uapi/asm/fcntl.h
> > +++ b/arch/sparc/include/uapi/asm/fcntl.h
> > @@ -37,6 +37,7 @@
> >
> >  #define O_PATH               0x1000000
> >  #define __O_TMPFILE  0x2000000
> > +#define OPENAT2_REGULAR      0x4000000
> >
> >  #define F_GETOWN     5       /*  for sockets. */
> >  #define F_SETOWN     6       /*  for sockets. */
> > diff --git a/fs/ceph/file.c b/fs/ceph/file.c
> > index 66bbf6d517a9..6d8d4c7765e6 100644
> > --- a/fs/ceph/file.c
> > +++ b/fs/ceph/file.c
> > @@ -977,6 +977,10 @@ int ceph_atomic_open(struct inode *dir, struct dentry *dentry,
> >                       ceph_init_inode_acls(newino, &as_ctx);
> >                       file->f_mode |= FMODE_CREATED;
> >               }
> > +             if ((flags & OPENAT2_REGULAR) && !d_is_reg(dentry)) {
> > +                     err = -EFTYPE;
> > +                     goto out_req;
> > +             }
>
> ^^^
> This doesn't look quite right. Here's a larger chunk of the code:
>
> -------------------------8<--------------------------
>         if (d_in_lookup(dentry)) {
>                 dn = ceph_finish_lookup(req, dentry, err);
>                 if (IS_ERR(dn))
>                         err = PTR_ERR(dn);
>         } else {
>                 /* we were given a hashed negative dentry */
>                 dn = NULL;
>         }
>         if (err)
>                 goto out_req;
>         if (dn || d_really_is_negative(dentry) || d_is_symlink(dentry)) {
>                 /* make vfs retry on splice, ENOENT, or symlink */
>                 doutc(cl, "finish_no_open on dn %p\n", dn);
>                 err = finish_no_open(file, dn);
>         } else {
>                 if (IS_ENCRYPTED(dir) &&
>                     !fscrypt_has_permitted_context(dir, d_inode(dentry))) {
>                         pr_warn_client(cl,
>                                 "Inconsistent encryption context (parent %llx:%llx child %llx:%llx)\n",
>                                 ceph_vinop(dir), ceph_vinop(d_inode(dentry)));
>                         goto out_req;
>                 }
>
>                 doutc(cl, "finish_open on dn %p\n", dn);
>                 if (req->r_op == CEPH_MDS_OP_CREATE && req->r_reply_info.has_create_ino) {
>                         struct inode *newino = d_inode(dentry);
>
>                         cache_file_layout(dir, newino);
>                         ceph_init_inode_acls(newino, &as_ctx);
>                         file->f_mode |= FMODE_CREATED;
>                 }
>                 err = finish_open(file, dentry, ceph_open);
>         }
> -------------------------8<--------------------------
>
> It looks like this won't handle it correctly if the pathwalk terminates
> on a symlink (re: d_is_symlink() case). You should either set up a test
> ceph cluster on your own, or reach out to the ceph community and ask
> them to test this.
>

Thanks for reviewing. The d_is_symlink() case seems to be calling
finish_no_open so shouldn't this be okay?

> >               err = finish_open(file, dentry, ceph_open);
> >       }
> >  out_req:
> > diff --git a/fs/fcntl.c b/fs/fcntl.c
> > index beab8080badf..240bb511557a 100644
> > --- a/fs/fcntl.c
> > +++ b/fs/fcntl.c
> > @@ -1169,9 +1169,9 @@ static int __init fcntl_init(void)
> >        * Exceptions: O_NONBLOCK is a two bit define on parisc; O_NDELAY
> >        * is defined as O_NONBLOCK on some platforms and not on others.
> >        */
> > -     BUILD_BUG_ON(20 - 1 /* for O_RDONLY being 0 */ !=
> > +     BUILD_BUG_ON(21 - 1 /* for O_RDONLY being 0 */ !=
> >               HWEIGHT32(
> > -                     (VALID_OPEN_FLAGS & ~(O_NONBLOCK | O_NDELAY)) |
> > +                     (VALID_OPENAT2_FLAGS & ~(O_NONBLOCK | O_NDELAY)) |
> >                       __FMODE_EXEC));
> >
> >       fasync_cache = kmem_cache_create("fasync_cache",
> > diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
> > index 8344040ecaf7..4604e2e8a9cc 100644
> > --- a/fs/gfs2/inode.c
> > +++ b/fs/gfs2/inode.c
> > @@ -738,6 +738,12 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
> >       inode = gfs2_dir_search(dir, &dentry->d_name, !S_ISREG(mode) || excl);
> >       error = PTR_ERR(inode);
> >       if (!IS_ERR(inode)) {
> > +             if (file && (file->f_flags & OPENAT2_REGULAR) && !S_ISREG(inode->i_mode)) {
>
> Isn't OPENAT2_REGULAR getting masked off in ->f_flags now?
>
Yes, I thought the masking off was happening after this codepath got
executed. Maybe it's better anyway to pass another flags param to this
function and forward the flags from the gfs2_atomic_open function and
in other call sites pass 0 ? What do you think?

Regards,
Dorjoy

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

* Re: [PATCH v6 1/4] openat2: new OPENAT2_REGULAR flag support
  2026-03-30 15:07     ` Dorjoy Chowdhury
@ 2026-04-01 19:02       ` Jeff Layton
  2026-04-04 15:17         ` Dorjoy Chowdhury
  0 siblings, 1 reply; 23+ messages in thread
From: Jeff Layton @ 2026-04-01 19:02 UTC (permalink / raw)
  To: Dorjoy Chowdhury
  Cc: linux-fsdevel, linux-kernel, linux-api, ceph-devel, gfs2,
	linux-nfs, linux-cifs, v9fs, linux-kselftest, viro, brauner, jack,
	chuck.lever, alex.aring, arnd, adilger, mjguzik, smfrench,
	richard.henderson, mattst88, linmag7, tsbogend, James.Bottomley,
	deller, davem, andreas, idryomov, amarkuze, slava, agruenba,
	trondmy, anna, sfrench, pc, ronniesahlberg, sprasad, tom,
	bharathsm, shuah, miklos, hansg

On Mon, 2026-03-30 at 21:07 +0600, Dorjoy Chowdhury wrote:
> On Mon, Mar 30, 2026 at 5:49 PM Jeff Layton <jlayton@kernel.org> wrote:
> > 
> > On Sat, 2026-03-28 at 23:22 +0600, Dorjoy Chowdhury wrote:
> > > This flag indicates the path should be opened if it's a regular file.
> > > This is useful to write secure programs that want to avoid being
> > > tricked into opening device nodes with special semantics while thinking
> > > they operate on regular files. This is a requested feature from the
> > > uapi-group[1].
> > > 
> > > A corresponding error code EFTYPE has been introduced. For example, if
> > > openat2 is called on path /dev/null with OPENAT2_REGULAR in the flag
> > > param, it will return -EFTYPE. EFTYPE is already used in BSD systems
> > > like FreeBSD, macOS.
> > > 
> > > When used in combination with O_CREAT, either the regular file is
> > > created, or if the path already exists, it is opened if it's a regular
> > > file. Otherwise, -EFTYPE is returned.
> > > 
> > > When OPENAT2_REGULAR is combined with O_DIRECTORY, -EINVAL is returned
> > > as it doesn't make sense to open a path that is both a directory and a
> > > regular file.
> > > 
> > > [1]: https://uapi-group.org/kernel-features/#ability-to-only-open-regular-files
> > > 
> > > Signed-off-by: Dorjoy Chowdhury <dorjoychy111@gmail.com>
> > > ---
> > >  arch/alpha/include/uapi/asm/errno.h        |  2 ++
> > >  arch/alpha/include/uapi/asm/fcntl.h        |  1 +
> > >  arch/mips/include/uapi/asm/errno.h         |  2 ++
> > >  arch/parisc/include/uapi/asm/errno.h       |  2 ++
> > >  arch/parisc/include/uapi/asm/fcntl.h       |  1 +
> > >  arch/sparc/include/uapi/asm/errno.h        |  2 ++
> > >  arch/sparc/include/uapi/asm/fcntl.h        |  1 +
> > >  fs/ceph/file.c                             |  4 ++++
> > >  fs/fcntl.c                                 |  4 ++--
> > >  fs/gfs2/inode.c                            |  6 ++++++
> > >  fs/namei.c                                 |  4 ++++
> > >  fs/nfs/dir.c                               |  4 ++++
> > >  fs/open.c                                  |  8 +++++---
> > >  fs/smb/client/dir.c                        | 14 +++++++++++++-
> > >  include/linux/fcntl.h                      |  2 ++
> > >  include/uapi/asm-generic/errno.h           |  2 ++
> > >  include/uapi/asm-generic/fcntl.h           |  4 ++++
> > >  tools/arch/alpha/include/uapi/asm/errno.h  |  2 ++
> > >  tools/arch/mips/include/uapi/asm/errno.h   |  2 ++
> > >  tools/arch/parisc/include/uapi/asm/errno.h |  2 ++
> > >  tools/arch/sparc/include/uapi/asm/errno.h  |  2 ++
> > >  tools/include/uapi/asm-generic/errno.h     |  2 ++
> > >  22 files changed, 67 insertions(+), 6 deletions(-)
> > > 
> > > diff --git a/arch/alpha/include/uapi/asm/errno.h b/arch/alpha/include/uapi/asm/errno.h
> > > index 6791f6508632..1a99f38813c7 100644
> > > --- a/arch/alpha/include/uapi/asm/errno.h
> > > +++ b/arch/alpha/include/uapi/asm/errno.h
> > > @@ -127,4 +127,6 @@
> > > 
> > >  #define EHWPOISON    139     /* Memory page has hardware error */
> > > 
> > > +#define EFTYPE               140     /* Wrong file type for the intended operation */
> > > +
> > >  #endif
> > > diff --git a/arch/alpha/include/uapi/asm/fcntl.h b/arch/alpha/include/uapi/asm/fcntl.h
> > > index 50bdc8e8a271..fe488bf7c18e 100644
> > > --- a/arch/alpha/include/uapi/asm/fcntl.h
> > > +++ b/arch/alpha/include/uapi/asm/fcntl.h
> > > @@ -34,6 +34,7 @@
> > > 
> > >  #define O_PATH               040000000
> > >  #define __O_TMPFILE  0100000000
> > > +#define OPENAT2_REGULAR      0200000000
> > > 
> > >  #define F_GETLK              7
> > >  #define F_SETLK              8
> > > diff --git a/arch/mips/include/uapi/asm/errno.h b/arch/mips/include/uapi/asm/errno.h
> > > index c01ed91b1ef4..1835a50b69ce 100644
> > > --- a/arch/mips/include/uapi/asm/errno.h
> > > +++ b/arch/mips/include/uapi/asm/errno.h
> > > @@ -126,6 +126,8 @@
> > > 
> > >  #define EHWPOISON    168     /* Memory page has hardware error */
> > > 
> > > +#define EFTYPE               169     /* Wrong file type for the intended operation */
> > > +
> > >  #define EDQUOT               1133    /* Quota exceeded */
> > > 
> > > 
> > > diff --git a/arch/parisc/include/uapi/asm/errno.h b/arch/parisc/include/uapi/asm/errno.h
> > > index 8cbc07c1903e..93194fbb0a80 100644
> > > --- a/arch/parisc/include/uapi/asm/errno.h
> > > +++ b/arch/parisc/include/uapi/asm/errno.h
> > > @@ -124,4 +124,6 @@
> > > 
> > >  #define EHWPOISON    257     /* Memory page has hardware error */
> > > 
> > > +#define EFTYPE               258     /* Wrong file type for the intended operation */
> > > +
> > >  #endif
> > > diff --git a/arch/parisc/include/uapi/asm/fcntl.h b/arch/parisc/include/uapi/asm/fcntl.h
> > > index 03dee816cb13..d46812f2f0f4 100644
> > > --- a/arch/parisc/include/uapi/asm/fcntl.h
> > > +++ b/arch/parisc/include/uapi/asm/fcntl.h
> > > @@ -19,6 +19,7 @@
> > > 
> > >  #define O_PATH               020000000
> > >  #define __O_TMPFILE  040000000
> > > +#define OPENAT2_REGULAR      0100000000
> > > 
> > >  #define F_GETLK64    8
> > >  #define F_SETLK64    9
> > > diff --git a/arch/sparc/include/uapi/asm/errno.h b/arch/sparc/include/uapi/asm/errno.h
> > > index 4a41e7835fd5..71940ec9130b 100644
> > > --- a/arch/sparc/include/uapi/asm/errno.h
> > > +++ b/arch/sparc/include/uapi/asm/errno.h
> > > @@ -117,4 +117,6 @@
> > > 
> > >  #define EHWPOISON    135     /* Memory page has hardware error */
> > > 
> > > +#define EFTYPE               136     /* Wrong file type for the intended operation */
> > > +
> > >  #endif
> > > diff --git a/arch/sparc/include/uapi/asm/fcntl.h b/arch/sparc/include/uapi/asm/fcntl.h
> > > index 67dae75e5274..bb6e9fa94bc9 100644
> > > --- a/arch/sparc/include/uapi/asm/fcntl.h
> > > +++ b/arch/sparc/include/uapi/asm/fcntl.h
> > > @@ -37,6 +37,7 @@
> > > 
> > >  #define O_PATH               0x1000000
> > >  #define __O_TMPFILE  0x2000000
> > > +#define OPENAT2_REGULAR      0x4000000
> > > 
> > >  #define F_GETOWN     5       /*  for sockets. */
> > >  #define F_SETOWN     6       /*  for sockets. */
> > > diff --git a/fs/ceph/file.c b/fs/ceph/file.c
> > > index 66bbf6d517a9..6d8d4c7765e6 100644
> > > --- a/fs/ceph/file.c
> > > +++ b/fs/ceph/file.c
> > > @@ -977,6 +977,10 @@ int ceph_atomic_open(struct inode *dir, struct dentry *dentry,
> > >                       ceph_init_inode_acls(newino, &as_ctx);
> > >                       file->f_mode |= FMODE_CREATED;
> > >               }
> > > +             if ((flags & OPENAT2_REGULAR) && !d_is_reg(dentry)) {
> > > +                     err = -EFTYPE;
> > > +                     goto out_req;
> > > +             }
> > 
> > ^^^
> > This doesn't look quite right. Here's a larger chunk of the code:
> > 
> > -------------------------8<--------------------------
> >         if (d_in_lookup(dentry)) {
> >                 dn = ceph_finish_lookup(req, dentry, err);
> >                 if (IS_ERR(dn))
> >                         err = PTR_ERR(dn);
> >         } else {
> >                 /* we were given a hashed negative dentry */
> >                 dn = NULL;
> >         }
> >         if (err)
> >                 goto out_req;
> >         if (dn || d_really_is_negative(dentry) || d_is_symlink(dentry)) {
> >                 /* make vfs retry on splice, ENOENT, or symlink */
> >                 doutc(cl, "finish_no_open on dn %p\n", dn);
> >                 err = finish_no_open(file, dn);
> >         } else {
> >                 if (IS_ENCRYPTED(dir) &&
> >                     !fscrypt_has_permitted_context(dir, d_inode(dentry))) {
> >                         pr_warn_client(cl,
> >                                 "Inconsistent encryption context (parent %llx:%llx child %llx:%llx)\n",
> >                                 ceph_vinop(dir), ceph_vinop(d_inode(dentry)));
> >                         goto out_req;
> >                 }
> > 
> >                 doutc(cl, "finish_open on dn %p\n", dn);
> >                 if (req->r_op == CEPH_MDS_OP_CREATE && req->r_reply_info.has_create_ino) {
> >                         struct inode *newino = d_inode(dentry);
> > 
> >                         cache_file_layout(dir, newino);
> >                         ceph_init_inode_acls(newino, &as_ctx);
> >                         file->f_mode |= FMODE_CREATED;
> >                 }
> >                 err = finish_open(file, dentry, ceph_open);
> >         }
> > -------------------------8<--------------------------
> > 
> > It looks like this won't handle it correctly if the pathwalk terminates
> > on a symlink (re: d_is_symlink() case). You should either set up a test
> > ceph cluster on your own, or reach out to the ceph community and ask
> > them to test this.
> > 
> 
> Thanks for reviewing. The d_is_symlink() case seems to be calling
> finish_no_open so shouldn't this be okay?
> 

My mistake -- you're correct. I keep forgetting that finish_no_open()
will handle this case regardless of what else happens.

> > >               err = finish_open(file, dentry, ceph_open);
> > >       }
> > >  out_req:
> > > diff --git a/fs/fcntl.c b/fs/fcntl.c
> > > index beab8080badf..240bb511557a 100644
> > > --- a/fs/fcntl.c
> > > +++ b/fs/fcntl.c
> > > @@ -1169,9 +1169,9 @@ static int __init fcntl_init(void)
> > >        * Exceptions: O_NONBLOCK is a two bit define on parisc; O_NDELAY
> > >        * is defined as O_NONBLOCK on some platforms and not on others.
> > >        */
> > > -     BUILD_BUG_ON(20 - 1 /* for O_RDONLY being 0 */ !=
> > > +     BUILD_BUG_ON(21 - 1 /* for O_RDONLY being 0 */ !=
> > >               HWEIGHT32(
> > > -                     (VALID_OPEN_FLAGS & ~(O_NONBLOCK | O_NDELAY)) |
> > > +                     (VALID_OPENAT2_FLAGS & ~(O_NONBLOCK | O_NDELAY)) |
> > >                       __FMODE_EXEC));
> > > 
> > >       fasync_cache = kmem_cache_create("fasync_cache",
> > > diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
> > > index 8344040ecaf7..4604e2e8a9cc 100644
> > > --- a/fs/gfs2/inode.c
> > > +++ b/fs/gfs2/inode.c
> > > @@ -738,6 +738,12 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
> > >       inode = gfs2_dir_search(dir, &dentry->d_name, !S_ISREG(mode) || excl);
> > >       error = PTR_ERR(inode);
> > >       if (!IS_ERR(inode)) {
> > > +             if (file && (file->f_flags & OPENAT2_REGULAR) && !S_ISREG(inode->i_mode)) {
> > 
> > Isn't OPENAT2_REGULAR getting masked off in ->f_flags now?
> > 
> Yes, I thought the masking off was happening after this codepath got
> executed. Maybe it's better anyway to pass another flags param to this
> function and forward the flags from the gfs2_atomic_open function and
> in other call sites pass 0 ? What do you think?
> 

Also my mistake. That happens in do_dentry_open() which happens in
finish_open(), so you should be OK here.

Reviewed-by: Jeff Layton <jlayton@kernel.org>

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

* Re: [PATCH v6 1/4] openat2: new OPENAT2_REGULAR flag support
  2026-04-01 19:02       ` Jeff Layton
@ 2026-04-04 15:17         ` Dorjoy Chowdhury
  2026-04-05 23:27           ` Jeff Layton
  0 siblings, 1 reply; 23+ messages in thread
From: Dorjoy Chowdhury @ 2026-04-04 15:17 UTC (permalink / raw)
  To: Jeff Layton
  Cc: linux-fsdevel, linux-kernel, linux-api, ceph-devel, gfs2,
	linux-nfs, linux-cifs, v9fs, linux-kselftest, viro, brauner, jack,
	chuck.lever, alex.aring, arnd, adilger, mjguzik, smfrench,
	richard.henderson, mattst88, linmag7, tsbogend, James.Bottomley,
	deller, davem, andreas, idryomov, amarkuze, slava, agruenba,
	trondmy, anna, sfrench, pc, ronniesahlberg, sprasad, tom,
	bharathsm, shuah, miklos, hansg

On Thu, Apr 2, 2026 at 1:02 AM Jeff Layton <jlayton@kernel.org> wrote:
>
> On Mon, 2026-03-30 at 21:07 +0600, Dorjoy Chowdhury wrote:
> > On Mon, Mar 30, 2026 at 5:49 PM Jeff Layton <jlayton@kernel.org> wrote:
> > >
> > > On Sat, 2026-03-28 at 23:22 +0600, Dorjoy Chowdhury wrote:
> > > > This flag indicates the path should be opened if it's a regular file.
> > > > This is useful to write secure programs that want to avoid being
> > > > tricked into opening device nodes with special semantics while thinking
> > > > they operate on regular files. This is a requested feature from the
> > > > uapi-group[1].
> > > >
> > > > A corresponding error code EFTYPE has been introduced. For example, if
> > > > openat2 is called on path /dev/null with OPENAT2_REGULAR in the flag
> > > > param, it will return -EFTYPE. EFTYPE is already used in BSD systems
> > > > like FreeBSD, macOS.
> > > >
> > > > When used in combination with O_CREAT, either the regular file is
> > > > created, or if the path already exists, it is opened if it's a regular
> > > > file. Otherwise, -EFTYPE is returned.
> > > >
> > > > When OPENAT2_REGULAR is combined with O_DIRECTORY, -EINVAL is returned
> > > > as it doesn't make sense to open a path that is both a directory and a
> > > > regular file.
> > > >
> > > > [1]: https://uapi-group.org/kernel-features/#ability-to-only-open-regular-files
> > > >
> > > > Signed-off-by: Dorjoy Chowdhury <dorjoychy111@gmail.com>
> > > > ---
> > > >  arch/alpha/include/uapi/asm/errno.h        |  2 ++
> > > >  arch/alpha/include/uapi/asm/fcntl.h        |  1 +
> > > >  arch/mips/include/uapi/asm/errno.h         |  2 ++
> > > >  arch/parisc/include/uapi/asm/errno.h       |  2 ++
> > > >  arch/parisc/include/uapi/asm/fcntl.h       |  1 +
> > > >  arch/sparc/include/uapi/asm/errno.h        |  2 ++
> > > >  arch/sparc/include/uapi/asm/fcntl.h        |  1 +
> > > >  fs/ceph/file.c                             |  4 ++++
> > > >  fs/fcntl.c                                 |  4 ++--
> > > >  fs/gfs2/inode.c                            |  6 ++++++
> > > >  fs/namei.c                                 |  4 ++++
> > > >  fs/nfs/dir.c                               |  4 ++++
> > > >  fs/open.c                                  |  8 +++++---
> > > >  fs/smb/client/dir.c                        | 14 +++++++++++++-
> > > >  include/linux/fcntl.h                      |  2 ++
> > > >  include/uapi/asm-generic/errno.h           |  2 ++
> > > >  include/uapi/asm-generic/fcntl.h           |  4 ++++
> > > >  tools/arch/alpha/include/uapi/asm/errno.h  |  2 ++
> > > >  tools/arch/mips/include/uapi/asm/errno.h   |  2 ++
> > > >  tools/arch/parisc/include/uapi/asm/errno.h |  2 ++
> > > >  tools/arch/sparc/include/uapi/asm/errno.h  |  2 ++
> > > >  tools/include/uapi/asm-generic/errno.h     |  2 ++
> > > >  22 files changed, 67 insertions(+), 6 deletions(-)
> > > >
> > > > diff --git a/arch/alpha/include/uapi/asm/errno.h b/arch/alpha/include/uapi/asm/errno.h
> > > > index 6791f6508632..1a99f38813c7 100644
> > > > --- a/arch/alpha/include/uapi/asm/errno.h
> > > > +++ b/arch/alpha/include/uapi/asm/errno.h
> > > > @@ -127,4 +127,6 @@
> > > >
> > > >  #define EHWPOISON    139     /* Memory page has hardware error */
> > > >
> > > > +#define EFTYPE               140     /* Wrong file type for the intended operation */
> > > > +
> > > >  #endif
> > > > diff --git a/arch/alpha/include/uapi/asm/fcntl.h b/arch/alpha/include/uapi/asm/fcntl.h
> > > > index 50bdc8e8a271..fe488bf7c18e 100644
> > > > --- a/arch/alpha/include/uapi/asm/fcntl.h
> > > > +++ b/arch/alpha/include/uapi/asm/fcntl.h
> > > > @@ -34,6 +34,7 @@
> > > >
> > > >  #define O_PATH               040000000
> > > >  #define __O_TMPFILE  0100000000
> > > > +#define OPENAT2_REGULAR      0200000000
> > > >
> > > >  #define F_GETLK              7
> > > >  #define F_SETLK              8
> > > > diff --git a/arch/mips/include/uapi/asm/errno.h b/arch/mips/include/uapi/asm/errno.h
> > > > index c01ed91b1ef4..1835a50b69ce 100644
> > > > --- a/arch/mips/include/uapi/asm/errno.h
> > > > +++ b/arch/mips/include/uapi/asm/errno.h
> > > > @@ -126,6 +126,8 @@
> > > >
> > > >  #define EHWPOISON    168     /* Memory page has hardware error */
> > > >
> > > > +#define EFTYPE               169     /* Wrong file type for the intended operation */
> > > > +
> > > >  #define EDQUOT               1133    /* Quota exceeded */
> > > >
> > > >
> > > > diff --git a/arch/parisc/include/uapi/asm/errno.h b/arch/parisc/include/uapi/asm/errno.h
> > > > index 8cbc07c1903e..93194fbb0a80 100644
> > > > --- a/arch/parisc/include/uapi/asm/errno.h
> > > > +++ b/arch/parisc/include/uapi/asm/errno.h
> > > > @@ -124,4 +124,6 @@
> > > >
> > > >  #define EHWPOISON    257     /* Memory page has hardware error */
> > > >
> > > > +#define EFTYPE               258     /* Wrong file type for the intended operation */
> > > > +
> > > >  #endif
> > > > diff --git a/arch/parisc/include/uapi/asm/fcntl.h b/arch/parisc/include/uapi/asm/fcntl.h
> > > > index 03dee816cb13..d46812f2f0f4 100644
> > > > --- a/arch/parisc/include/uapi/asm/fcntl.h
> > > > +++ b/arch/parisc/include/uapi/asm/fcntl.h
> > > > @@ -19,6 +19,7 @@
> > > >
> > > >  #define O_PATH               020000000
> > > >  #define __O_TMPFILE  040000000
> > > > +#define OPENAT2_REGULAR      0100000000
> > > >
> > > >  #define F_GETLK64    8
> > > >  #define F_SETLK64    9
> > > > diff --git a/arch/sparc/include/uapi/asm/errno.h b/arch/sparc/include/uapi/asm/errno.h
> > > > index 4a41e7835fd5..71940ec9130b 100644
> > > > --- a/arch/sparc/include/uapi/asm/errno.h
> > > > +++ b/arch/sparc/include/uapi/asm/errno.h
> > > > @@ -117,4 +117,6 @@
> > > >
> > > >  #define EHWPOISON    135     /* Memory page has hardware error */
> > > >
> > > > +#define EFTYPE               136     /* Wrong file type for the intended operation */
> > > > +
> > > >  #endif
> > > > diff --git a/arch/sparc/include/uapi/asm/fcntl.h b/arch/sparc/include/uapi/asm/fcntl.h
> > > > index 67dae75e5274..bb6e9fa94bc9 100644
> > > > --- a/arch/sparc/include/uapi/asm/fcntl.h
> > > > +++ b/arch/sparc/include/uapi/asm/fcntl.h
> > > > @@ -37,6 +37,7 @@
> > > >
> > > >  #define O_PATH               0x1000000
> > > >  #define __O_TMPFILE  0x2000000
> > > > +#define OPENAT2_REGULAR      0x4000000
> > > >
> > > >  #define F_GETOWN     5       /*  for sockets. */
> > > >  #define F_SETOWN     6       /*  for sockets. */
> > > > diff --git a/fs/ceph/file.c b/fs/ceph/file.c
> > > > index 66bbf6d517a9..6d8d4c7765e6 100644
> > > > --- a/fs/ceph/file.c
> > > > +++ b/fs/ceph/file.c
> > > > @@ -977,6 +977,10 @@ int ceph_atomic_open(struct inode *dir, struct dentry *dentry,
> > > >                       ceph_init_inode_acls(newino, &as_ctx);
> > > >                       file->f_mode |= FMODE_CREATED;
> > > >               }
> > > > +             if ((flags & OPENAT2_REGULAR) && !d_is_reg(dentry)) {
> > > > +                     err = -EFTYPE;
> > > > +                     goto out_req;
> > > > +             }
> > >
> > > ^^^
> > > This doesn't look quite right. Here's a larger chunk of the code:
> > >
> > > -------------------------8<--------------------------
> > >         if (d_in_lookup(dentry)) {
> > >                 dn = ceph_finish_lookup(req, dentry, err);
> > >                 if (IS_ERR(dn))
> > >                         err = PTR_ERR(dn);
> > >         } else {
> > >                 /* we were given a hashed negative dentry */
> > >                 dn = NULL;
> > >         }
> > >         if (err)
> > >                 goto out_req;
> > >         if (dn || d_really_is_negative(dentry) || d_is_symlink(dentry)) {
> > >                 /* make vfs retry on splice, ENOENT, or symlink */
> > >                 doutc(cl, "finish_no_open on dn %p\n", dn);
> > >                 err = finish_no_open(file, dn);
> > >         } else {
> > >                 if (IS_ENCRYPTED(dir) &&
> > >                     !fscrypt_has_permitted_context(dir, d_inode(dentry))) {
> > >                         pr_warn_client(cl,
> > >                                 "Inconsistent encryption context (parent %llx:%llx child %llx:%llx)\n",
> > >                                 ceph_vinop(dir), ceph_vinop(d_inode(dentry)));
> > >                         goto out_req;
> > >                 }
> > >
> > >                 doutc(cl, "finish_open on dn %p\n", dn);
> > >                 if (req->r_op == CEPH_MDS_OP_CREATE && req->r_reply_info.has_create_ino) {
> > >                         struct inode *newino = d_inode(dentry);
> > >
> > >                         cache_file_layout(dir, newino);
> > >                         ceph_init_inode_acls(newino, &as_ctx);
> > >                         file->f_mode |= FMODE_CREATED;
> > >                 }
> > >                 err = finish_open(file, dentry, ceph_open);
> > >         }
> > > -------------------------8<--------------------------
> > >
> > > It looks like this won't handle it correctly if the pathwalk terminates
> > > on a symlink (re: d_is_symlink() case). You should either set up a test
> > > ceph cluster on your own, or reach out to the ceph community and ask
> > > them to test this.
> > >
> >
> > Thanks for reviewing. The d_is_symlink() case seems to be calling
> > finish_no_open so shouldn't this be okay?
> >
>
> My mistake -- you're correct. I keep forgetting that finish_no_open()
> will handle this case regardless of what else happens.
>
> > > >               err = finish_open(file, dentry, ceph_open);
> > > >       }
> > > >  out_req:
> > > > diff --git a/fs/fcntl.c b/fs/fcntl.c
> > > > index beab8080badf..240bb511557a 100644
> > > > --- a/fs/fcntl.c
> > > > +++ b/fs/fcntl.c
> > > > @@ -1169,9 +1169,9 @@ static int __init fcntl_init(void)
> > > >        * Exceptions: O_NONBLOCK is a two bit define on parisc; O_NDELAY
> > > >        * is defined as O_NONBLOCK on some platforms and not on others.
> > > >        */
> > > > -     BUILD_BUG_ON(20 - 1 /* for O_RDONLY being 0 */ !=
> > > > +     BUILD_BUG_ON(21 - 1 /* for O_RDONLY being 0 */ !=
> > > >               HWEIGHT32(
> > > > -                     (VALID_OPEN_FLAGS & ~(O_NONBLOCK | O_NDELAY)) |
> > > > +                     (VALID_OPENAT2_FLAGS & ~(O_NONBLOCK | O_NDELAY)) |
> > > >                       __FMODE_EXEC));
> > > >
> > > >       fasync_cache = kmem_cache_create("fasync_cache",
> > > > diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
> > > > index 8344040ecaf7..4604e2e8a9cc 100644
> > > > --- a/fs/gfs2/inode.c
> > > > +++ b/fs/gfs2/inode.c
> > > > @@ -738,6 +738,12 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
> > > >       inode = gfs2_dir_search(dir, &dentry->d_name, !S_ISREG(mode) || excl);
> > > >       error = PTR_ERR(inode);
> > > >       if (!IS_ERR(inode)) {
> > > > +             if (file && (file->f_flags & OPENAT2_REGULAR) && !S_ISREG(inode->i_mode)) {
> > >
> > > Isn't OPENAT2_REGULAR getting masked off in ->f_flags now?
> > >
> > Yes, I thought the masking off was happening after this codepath got
> > executed. Maybe it's better anyway to pass another flags param to this
> > function and forward the flags from the gfs2_atomic_open function and
> > in other call sites pass 0 ? What do you think?
> >
>
> Also my mistake. That happens in do_dentry_open() which happens in
> finish_open(), so you should be OK here.
>
> Reviewed-by: Jeff Layton <jlayton@kernel.org>

Thanks for patiently reviewing this! I am planning on sending patches
for man-pages and looking into some xfs-tests for this. But I am not
sure if this patch series will get more reviews from others or if it
will be picked up in the vfs branch?

Regards,
Dorjoy

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

* Re: [PATCH v6 1/4] openat2: new OPENAT2_REGULAR flag support
  2026-04-04 15:17         ` Dorjoy Chowdhury
@ 2026-04-05 23:27           ` Jeff Layton
  2026-04-06 15:30             ` Dorjoy Chowdhury
  0 siblings, 1 reply; 23+ messages in thread
From: Jeff Layton @ 2026-04-05 23:27 UTC (permalink / raw)
  To: Dorjoy Chowdhury
  Cc: linux-fsdevel, linux-kernel, linux-api, ceph-devel, gfs2,
	linux-nfs, linux-cifs, v9fs, linux-kselftest, viro, brauner, jack,
	chuck.lever, alex.aring, arnd, adilger, mjguzik, smfrench,
	richard.henderson, mattst88, linmag7, tsbogend, James.Bottomley,
	deller, davem, andreas, idryomov, amarkuze, slava, agruenba,
	trondmy, anna, sfrench, pc, ronniesahlberg, sprasad, tom,
	bharathsm, shuah, miklos, hansg

On Sat, 2026-04-04 at 21:17 +0600, Dorjoy Chowdhury wrote:
> On Thu, Apr 2, 2026 at 1:02 AM Jeff Layton <jlayton@kernel.org> wrote:
> > 
> > On Mon, 2026-03-30 at 21:07 +0600, Dorjoy Chowdhury wrote:
> > > On Mon, Mar 30, 2026 at 5:49 PM Jeff Layton <jlayton@kernel.org> wrote:
> > > > 
> > > > On Sat, 2026-03-28 at 23:22 +0600, Dorjoy Chowdhury wrote:
> > > > > This flag indicates the path should be opened if it's a regular file.
> > > > > This is useful to write secure programs that want to avoid being
> > > > > tricked into opening device nodes with special semantics while thinking
> > > > > they operate on regular files. This is a requested feature from the
> > > > > uapi-group[1].
> > > > > 
> > > > > A corresponding error code EFTYPE has been introduced. For example, if
> > > > > openat2 is called on path /dev/null with OPENAT2_REGULAR in the flag
> > > > > param, it will return -EFTYPE. EFTYPE is already used in BSD systems
> > > > > like FreeBSD, macOS.
> > > > > 
> > > > > When used in combination with O_CREAT, either the regular file is
> > > > > created, or if the path already exists, it is opened if it's a regular
> > > > > file. Otherwise, -EFTYPE is returned.
> > > > > 
> > > > > When OPENAT2_REGULAR is combined with O_DIRECTORY, -EINVAL is returned
> > > > > as it doesn't make sense to open a path that is both a directory and a
> > > > > regular file.
> > > > > 
> > > > > [1]: https://uapi-group.org/kernel-features/#ability-to-only-open-regular-files
> > > > > 
> > > > > Signed-off-by: Dorjoy Chowdhury <dorjoychy111@gmail.com>
> > > > > ---
> > > > >  arch/alpha/include/uapi/asm/errno.h        |  2 ++
> > > > >  arch/alpha/include/uapi/asm/fcntl.h        |  1 +
> > > > >  arch/mips/include/uapi/asm/errno.h         |  2 ++
> > > > >  arch/parisc/include/uapi/asm/errno.h       |  2 ++
> > > > >  arch/parisc/include/uapi/asm/fcntl.h       |  1 +
> > > > >  arch/sparc/include/uapi/asm/errno.h        |  2 ++
> > > > >  arch/sparc/include/uapi/asm/fcntl.h        |  1 +
> > > > >  fs/ceph/file.c                             |  4 ++++
> > > > >  fs/fcntl.c                                 |  4 ++--
> > > > >  fs/gfs2/inode.c                            |  6 ++++++
> > > > >  fs/namei.c                                 |  4 ++++
> > > > >  fs/nfs/dir.c                               |  4 ++++
> > > > >  fs/open.c                                  |  8 +++++---
> > > > >  fs/smb/client/dir.c                        | 14 +++++++++++++-
> > > > >  include/linux/fcntl.h                      |  2 ++
> > > > >  include/uapi/asm-generic/errno.h           |  2 ++
> > > > >  include/uapi/asm-generic/fcntl.h           |  4 ++++
> > > > >  tools/arch/alpha/include/uapi/asm/errno.h  |  2 ++
> > > > >  tools/arch/mips/include/uapi/asm/errno.h   |  2 ++
> > > > >  tools/arch/parisc/include/uapi/asm/errno.h |  2 ++
> > > > >  tools/arch/sparc/include/uapi/asm/errno.h  |  2 ++
> > > > >  tools/include/uapi/asm-generic/errno.h     |  2 ++
> > > > >  22 files changed, 67 insertions(+), 6 deletions(-)
> > > > > 
> > > > > diff --git a/arch/alpha/include/uapi/asm/errno.h b/arch/alpha/include/uapi/asm/errno.h
> > > > > index 6791f6508632..1a99f38813c7 100644
> > > > > --- a/arch/alpha/include/uapi/asm/errno.h
> > > > > +++ b/arch/alpha/include/uapi/asm/errno.h
> > > > > @@ -127,4 +127,6 @@
> > > > > 
> > > > >  #define EHWPOISON    139     /* Memory page has hardware error */
> > > > > 
> > > > > +#define EFTYPE               140     /* Wrong file type for the intended operation */
> > > > > +
> > > > >  #endif
> > > > > diff --git a/arch/alpha/include/uapi/asm/fcntl.h b/arch/alpha/include/uapi/asm/fcntl.h
> > > > > index 50bdc8e8a271..fe488bf7c18e 100644
> > > > > --- a/arch/alpha/include/uapi/asm/fcntl.h
> > > > > +++ b/arch/alpha/include/uapi/asm/fcntl.h
> > > > > @@ -34,6 +34,7 @@
> > > > > 
> > > > >  #define O_PATH               040000000
> > > > >  #define __O_TMPFILE  0100000000
> > > > > +#define OPENAT2_REGULAR      0200000000
> > > > > 
> > > > >  #define F_GETLK              7
> > > > >  #define F_SETLK              8
> > > > > diff --git a/arch/mips/include/uapi/asm/errno.h b/arch/mips/include/uapi/asm/errno.h
> > > > > index c01ed91b1ef4..1835a50b69ce 100644
> > > > > --- a/arch/mips/include/uapi/asm/errno.h
> > > > > +++ b/arch/mips/include/uapi/asm/errno.h
> > > > > @@ -126,6 +126,8 @@
> > > > > 
> > > > >  #define EHWPOISON    168     /* Memory page has hardware error */
> > > > > 
> > > > > +#define EFTYPE               169     /* Wrong file type for the intended operation */
> > > > > +
> > > > >  #define EDQUOT               1133    /* Quota exceeded */
> > > > > 
> > > > > 
> > > > > diff --git a/arch/parisc/include/uapi/asm/errno.h b/arch/parisc/include/uapi/asm/errno.h
> > > > > index 8cbc07c1903e..93194fbb0a80 100644
> > > > > --- a/arch/parisc/include/uapi/asm/errno.h
> > > > > +++ b/arch/parisc/include/uapi/asm/errno.h
> > > > > @@ -124,4 +124,6 @@
> > > > > 
> > > > >  #define EHWPOISON    257     /* Memory page has hardware error */
> > > > > 
> > > > > +#define EFTYPE               258     /* Wrong file type for the intended operation */
> > > > > +
> > > > >  #endif
> > > > > diff --git a/arch/parisc/include/uapi/asm/fcntl.h b/arch/parisc/include/uapi/asm/fcntl.h
> > > > > index 03dee816cb13..d46812f2f0f4 100644
> > > > > --- a/arch/parisc/include/uapi/asm/fcntl.h
> > > > > +++ b/arch/parisc/include/uapi/asm/fcntl.h
> > > > > @@ -19,6 +19,7 @@
> > > > > 
> > > > >  #define O_PATH               020000000
> > > > >  #define __O_TMPFILE  040000000
> > > > > +#define OPENAT2_REGULAR      0100000000
> > > > > 
> > > > >  #define F_GETLK64    8
> > > > >  #define F_SETLK64    9
> > > > > diff --git a/arch/sparc/include/uapi/asm/errno.h b/arch/sparc/include/uapi/asm/errno.h
> > > > > index 4a41e7835fd5..71940ec9130b 100644
> > > > > --- a/arch/sparc/include/uapi/asm/errno.h
> > > > > +++ b/arch/sparc/include/uapi/asm/errno.h
> > > > > @@ -117,4 +117,6 @@
> > > > > 
> > > > >  #define EHWPOISON    135     /* Memory page has hardware error */
> > > > > 
> > > > > +#define EFTYPE               136     /* Wrong file type for the intended operation */
> > > > > +
> > > > >  #endif
> > > > > diff --git a/arch/sparc/include/uapi/asm/fcntl.h b/arch/sparc/include/uapi/asm/fcntl.h
> > > > > index 67dae75e5274..bb6e9fa94bc9 100644
> > > > > --- a/arch/sparc/include/uapi/asm/fcntl.h
> > > > > +++ b/arch/sparc/include/uapi/asm/fcntl.h
> > > > > @@ -37,6 +37,7 @@
> > > > > 
> > > > >  #define O_PATH               0x1000000
> > > > >  #define __O_TMPFILE  0x2000000
> > > > > +#define OPENAT2_REGULAR      0x4000000
> > > > > 
> > > > >  #define F_GETOWN     5       /*  for sockets. */
> > > > >  #define F_SETOWN     6       /*  for sockets. */
> > > > > diff --git a/fs/ceph/file.c b/fs/ceph/file.c
> > > > > index 66bbf6d517a9..6d8d4c7765e6 100644
> > > > > --- a/fs/ceph/file.c
> > > > > +++ b/fs/ceph/file.c
> > > > > @@ -977,6 +977,10 @@ int ceph_atomic_open(struct inode *dir, struct dentry *dentry,
> > > > >                       ceph_init_inode_acls(newino, &as_ctx);
> > > > >                       file->f_mode |= FMODE_CREATED;
> > > > >               }
> > > > > +             if ((flags & OPENAT2_REGULAR) && !d_is_reg(dentry)) {
> > > > > +                     err = -EFTYPE;
> > > > > +                     goto out_req;
> > > > > +             }
> > > > 
> > > > ^^^
> > > > This doesn't look quite right. Here's a larger chunk of the code:
> > > > 
> > > > -------------------------8<--------------------------
> > > >         if (d_in_lookup(dentry)) {
> > > >                 dn = ceph_finish_lookup(req, dentry, err);
> > > >                 if (IS_ERR(dn))
> > > >                         err = PTR_ERR(dn);
> > > >         } else {
> > > >                 /* we were given a hashed negative dentry */
> > > >                 dn = NULL;
> > > >         }
> > > >         if (err)
> > > >                 goto out_req;
> > > >         if (dn || d_really_is_negative(dentry) || d_is_symlink(dentry)) {
> > > >                 /* make vfs retry on splice, ENOENT, or symlink */
> > > >                 doutc(cl, "finish_no_open on dn %p\n", dn);
> > > >                 err = finish_no_open(file, dn);
> > > >         } else {
> > > >                 if (IS_ENCRYPTED(dir) &&
> > > >                     !fscrypt_has_permitted_context(dir, d_inode(dentry))) {
> > > >                         pr_warn_client(cl,
> > > >                                 "Inconsistent encryption context (parent %llx:%llx child %llx:%llx)\n",
> > > >                                 ceph_vinop(dir), ceph_vinop(d_inode(dentry)));
> > > >                         goto out_req;
> > > >                 }
> > > > 
> > > >                 doutc(cl, "finish_open on dn %p\n", dn);
> > > >                 if (req->r_op == CEPH_MDS_OP_CREATE && req->r_reply_info.has_create_ino) {
> > > >                         struct inode *newino = d_inode(dentry);
> > > > 
> > > >                         cache_file_layout(dir, newino);
> > > >                         ceph_init_inode_acls(newino, &as_ctx);
> > > >                         file->f_mode |= FMODE_CREATED;
> > > >                 }
> > > >                 err = finish_open(file, dentry, ceph_open);
> > > >         }
> > > > -------------------------8<--------------------------
> > > > 
> > > > It looks like this won't handle it correctly if the pathwalk terminates
> > > > on a symlink (re: d_is_symlink() case). You should either set up a test
> > > > ceph cluster on your own, or reach out to the ceph community and ask
> > > > them to test this.
> > > > 
> > > 
> > > Thanks for reviewing. The d_is_symlink() case seems to be calling
> > > finish_no_open so shouldn't this be okay?
> > > 
> > 
> > My mistake -- you're correct. I keep forgetting that finish_no_open()
> > will handle this case regardless of what else happens.
> > 
> > > > >               err = finish_open(file, dentry, ceph_open);
> > > > >       }
> > > > >  out_req:
> > > > > diff --git a/fs/fcntl.c b/fs/fcntl.c
> > > > > index beab8080badf..240bb511557a 100644
> > > > > --- a/fs/fcntl.c
> > > > > +++ b/fs/fcntl.c
> > > > > @@ -1169,9 +1169,9 @@ static int __init fcntl_init(void)
> > > > >        * Exceptions: O_NONBLOCK is a two bit define on parisc; O_NDELAY
> > > > >        * is defined as O_NONBLOCK on some platforms and not on others.
> > > > >        */
> > > > > -     BUILD_BUG_ON(20 - 1 /* for O_RDONLY being 0 */ !=
> > > > > +     BUILD_BUG_ON(21 - 1 /* for O_RDONLY being 0 */ !=
> > > > >               HWEIGHT32(
> > > > > -                     (VALID_OPEN_FLAGS & ~(O_NONBLOCK | O_NDELAY)) |
> > > > > +                     (VALID_OPENAT2_FLAGS & ~(O_NONBLOCK | O_NDELAY)) |
> > > > >                       __FMODE_EXEC));
> > > > > 
> > > > >       fasync_cache = kmem_cache_create("fasync_cache",
> > > > > diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
> > > > > index 8344040ecaf7..4604e2e8a9cc 100644
> > > > > --- a/fs/gfs2/inode.c
> > > > > +++ b/fs/gfs2/inode.c
> > > > > @@ -738,6 +738,12 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
> > > > >       inode = gfs2_dir_search(dir, &dentry->d_name, !S_ISREG(mode) || excl);
> > > > >       error = PTR_ERR(inode);
> > > > >       if (!IS_ERR(inode)) {
> > > > > +             if (file && (file->f_flags & OPENAT2_REGULAR) && !S_ISREG(inode->i_mode)) {
> > > > 
> > > > Isn't OPENAT2_REGULAR getting masked off in ->f_flags now?
> > > > 
> > > Yes, I thought the masking off was happening after this codepath got
> > > executed. Maybe it's better anyway to pass another flags param to this
> > > function and forward the flags from the gfs2_atomic_open function and
> > > in other call sites pass 0 ? What do you think?
> > > 
> > 
> > Also my mistake. That happens in do_dentry_open() which happens in
> > finish_open(), so you should be OK here.
> > 
> > Reviewed-by: Jeff Layton <jlayton@kernel.org>
> 
> Thanks for patiently reviewing this! I am planning on sending patches
> for man-pages and looking into some xfs-tests for this. But I am not
> sure if this patch series will get more reviews from others or if it
> will be picked up in the vfs branch?
> 

This is a change to rather core VFS infrastructure so yes, you should
expect some more review. Assuming no major issues are found, then yes,
this should eventually get picked up by the VFS maintainers.

Cheers,
-- 
Jeff Layton <jlayton@kernel.org>

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

* Re: [PATCH v6 1/4] openat2: new OPENAT2_REGULAR flag support
  2026-04-05 23:27           ` Jeff Layton
@ 2026-04-06 15:30             ` Dorjoy Chowdhury
  2026-04-14 17:33               ` Dorjoy Chowdhury
  0 siblings, 1 reply; 23+ messages in thread
From: Dorjoy Chowdhury @ 2026-04-06 15:30 UTC (permalink / raw)
  To: linux-fsdevel, brauner
  Cc: Jeff Layton, linux-kernel, linux-api, ceph-devel, gfs2, linux-nfs,
	linux-cifs, v9fs, linux-kselftest, viro, jack, chuck.lever,
	alex.aring, arnd, adilger, mjguzik, smfrench, richard.henderson,
	mattst88, linmag7, tsbogend, James.Bottomley, deller, davem,
	andreas, idryomov, amarkuze, slava, agruenba, trondmy, anna,
	sfrench, pc, ronniesahlberg, sprasad, tom, bharathsm, shuah,
	miklos, hansg

On Mon, Apr 6, 2026 at 5:27 AM Jeff Layton <jlayton@kernel.org> wrote:
>
> On Sat, 2026-04-04 at 21:17 +0600, Dorjoy Chowdhury wrote:
> > On Thu, Apr 2, 2026 at 1:02 AM Jeff Layton <jlayton@kernel.org> wrote:
> > >
> > > On Mon, 2026-03-30 at 21:07 +0600, Dorjoy Chowdhury wrote:
> > > > On Mon, Mar 30, 2026 at 5:49 PM Jeff Layton <jlayton@kernel.org> wrote:
> > > > >
> > > > > On Sat, 2026-03-28 at 23:22 +0600, Dorjoy Chowdhury wrote:
> > > > > > This flag indicates the path should be opened if it's a regular file.
> > > > > > This is useful to write secure programs that want to avoid being
> > > > > > tricked into opening device nodes with special semantics while thinking
> > > > > > they operate on regular files. This is a requested feature from the
> > > > > > uapi-group[1].
> > > > > >
> > > > > > A corresponding error code EFTYPE has been introduced. For example, if
> > > > > > openat2 is called on path /dev/null with OPENAT2_REGULAR in the flag
> > > > > > param, it will return -EFTYPE. EFTYPE is already used in BSD systems
> > > > > > like FreeBSD, macOS.
> > > > > >
> > > > > > When used in combination with O_CREAT, either the regular file is
> > > > > > created, or if the path already exists, it is opened if it's a regular
> > > > > > file. Otherwise, -EFTYPE is returned.
> > > > > >
> > > > > > When OPENAT2_REGULAR is combined with O_DIRECTORY, -EINVAL is returned
> > > > > > as it doesn't make sense to open a path that is both a directory and a
> > > > > > regular file.
> > > > > >
> > > > > > [1]: https://uapi-group.org/kernel-features/#ability-to-only-open-regular-files
> > > > > >
> > > > > > Signed-off-by: Dorjoy Chowdhury <dorjoychy111@gmail.com>
> > > > > > ---
> > > > > >  arch/alpha/include/uapi/asm/errno.h        |  2 ++
> > > > > >  arch/alpha/include/uapi/asm/fcntl.h        |  1 +
> > > > > >  arch/mips/include/uapi/asm/errno.h         |  2 ++
> > > > > >  arch/parisc/include/uapi/asm/errno.h       |  2 ++
> > > > > >  arch/parisc/include/uapi/asm/fcntl.h       |  1 +
> > > > > >  arch/sparc/include/uapi/asm/errno.h        |  2 ++
> > > > > >  arch/sparc/include/uapi/asm/fcntl.h        |  1 +
> > > > > >  fs/ceph/file.c                             |  4 ++++
> > > > > >  fs/fcntl.c                                 |  4 ++--
> > > > > >  fs/gfs2/inode.c                            |  6 ++++++
> > > > > >  fs/namei.c                                 |  4 ++++
> > > > > >  fs/nfs/dir.c                               |  4 ++++
> > > > > >  fs/open.c                                  |  8 +++++---
> > > > > >  fs/smb/client/dir.c                        | 14 +++++++++++++-
> > > > > >  include/linux/fcntl.h                      |  2 ++
> > > > > >  include/uapi/asm-generic/errno.h           |  2 ++
> > > > > >  include/uapi/asm-generic/fcntl.h           |  4 ++++
> > > > > >  tools/arch/alpha/include/uapi/asm/errno.h  |  2 ++
> > > > > >  tools/arch/mips/include/uapi/asm/errno.h   |  2 ++
> > > > > >  tools/arch/parisc/include/uapi/asm/errno.h |  2 ++
> > > > > >  tools/arch/sparc/include/uapi/asm/errno.h  |  2 ++
> > > > > >  tools/include/uapi/asm-generic/errno.h     |  2 ++
> > > > > >  22 files changed, 67 insertions(+), 6 deletions(-)
> > > > > >
> > > > > > diff --git a/arch/alpha/include/uapi/asm/errno.h b/arch/alpha/include/uapi/asm/errno.h
> > > > > > index 6791f6508632..1a99f38813c7 100644
> > > > > > --- a/arch/alpha/include/uapi/asm/errno.h
> > > > > > +++ b/arch/alpha/include/uapi/asm/errno.h
> > > > > > @@ -127,4 +127,6 @@
> > > > > >
> > > > > >  #define EHWPOISON    139     /* Memory page has hardware error */
> > > > > >
> > > > > > +#define EFTYPE               140     /* Wrong file type for the intended operation */
> > > > > > +
> > > > > >  #endif
> > > > > > diff --git a/arch/alpha/include/uapi/asm/fcntl.h b/arch/alpha/include/uapi/asm/fcntl.h
> > > > > > index 50bdc8e8a271..fe488bf7c18e 100644
> > > > > > --- a/arch/alpha/include/uapi/asm/fcntl.h
> > > > > > +++ b/arch/alpha/include/uapi/asm/fcntl.h
> > > > > > @@ -34,6 +34,7 @@
> > > > > >
> > > > > >  #define O_PATH               040000000
> > > > > >  #define __O_TMPFILE  0100000000
> > > > > > +#define OPENAT2_REGULAR      0200000000
> > > > > >
> > > > > >  #define F_GETLK              7
> > > > > >  #define F_SETLK              8
> > > > > > diff --git a/arch/mips/include/uapi/asm/errno.h b/arch/mips/include/uapi/asm/errno.h
> > > > > > index c01ed91b1ef4..1835a50b69ce 100644
> > > > > > --- a/arch/mips/include/uapi/asm/errno.h
> > > > > > +++ b/arch/mips/include/uapi/asm/errno.h
> > > > > > @@ -126,6 +126,8 @@
> > > > > >
> > > > > >  #define EHWPOISON    168     /* Memory page has hardware error */
> > > > > >
> > > > > > +#define EFTYPE               169     /* Wrong file type for the intended operation */
> > > > > > +
> > > > > >  #define EDQUOT               1133    /* Quota exceeded */
> > > > > >
> > > > > >
> > > > > > diff --git a/arch/parisc/include/uapi/asm/errno.h b/arch/parisc/include/uapi/asm/errno.h
> > > > > > index 8cbc07c1903e..93194fbb0a80 100644
> > > > > > --- a/arch/parisc/include/uapi/asm/errno.h
> > > > > > +++ b/arch/parisc/include/uapi/asm/errno.h
> > > > > > @@ -124,4 +124,6 @@
> > > > > >
> > > > > >  #define EHWPOISON    257     /* Memory page has hardware error */
> > > > > >
> > > > > > +#define EFTYPE               258     /* Wrong file type for the intended operation */
> > > > > > +
> > > > > >  #endif
> > > > > > diff --git a/arch/parisc/include/uapi/asm/fcntl.h b/arch/parisc/include/uapi/asm/fcntl.h
> > > > > > index 03dee816cb13..d46812f2f0f4 100644
> > > > > > --- a/arch/parisc/include/uapi/asm/fcntl.h
> > > > > > +++ b/arch/parisc/include/uapi/asm/fcntl.h
> > > > > > @@ -19,6 +19,7 @@
> > > > > >
> > > > > >  #define O_PATH               020000000
> > > > > >  #define __O_TMPFILE  040000000
> > > > > > +#define OPENAT2_REGULAR      0100000000
> > > > > >
> > > > > >  #define F_GETLK64    8
> > > > > >  #define F_SETLK64    9
> > > > > > diff --git a/arch/sparc/include/uapi/asm/errno.h b/arch/sparc/include/uapi/asm/errno.h
> > > > > > index 4a41e7835fd5..71940ec9130b 100644
> > > > > > --- a/arch/sparc/include/uapi/asm/errno.h
> > > > > > +++ b/arch/sparc/include/uapi/asm/errno.h
> > > > > > @@ -117,4 +117,6 @@
> > > > > >
> > > > > >  #define EHWPOISON    135     /* Memory page has hardware error */
> > > > > >
> > > > > > +#define EFTYPE               136     /* Wrong file type for the intended operation */
> > > > > > +
> > > > > >  #endif
> > > > > > diff --git a/arch/sparc/include/uapi/asm/fcntl.h b/arch/sparc/include/uapi/asm/fcntl.h
> > > > > > index 67dae75e5274..bb6e9fa94bc9 100644
> > > > > > --- a/arch/sparc/include/uapi/asm/fcntl.h
> > > > > > +++ b/arch/sparc/include/uapi/asm/fcntl.h
> > > > > > @@ -37,6 +37,7 @@
> > > > > >
> > > > > >  #define O_PATH               0x1000000
> > > > > >  #define __O_TMPFILE  0x2000000
> > > > > > +#define OPENAT2_REGULAR      0x4000000
> > > > > >
> > > > > >  #define F_GETOWN     5       /*  for sockets. */
> > > > > >  #define F_SETOWN     6       /*  for sockets. */
> > > > > > diff --git a/fs/ceph/file.c b/fs/ceph/file.c
> > > > > > index 66bbf6d517a9..6d8d4c7765e6 100644
> > > > > > --- a/fs/ceph/file.c
> > > > > > +++ b/fs/ceph/file.c
> > > > > > @@ -977,6 +977,10 @@ int ceph_atomic_open(struct inode *dir, struct dentry *dentry,
> > > > > >                       ceph_init_inode_acls(newino, &as_ctx);
> > > > > >                       file->f_mode |= FMODE_CREATED;
> > > > > >               }
> > > > > > +             if ((flags & OPENAT2_REGULAR) && !d_is_reg(dentry)) {
> > > > > > +                     err = -EFTYPE;
> > > > > > +                     goto out_req;
> > > > > > +             }
> > > > >
> > > > > ^^^
> > > > > This doesn't look quite right. Here's a larger chunk of the code:
> > > > >
> > > > > -------------------------8<--------------------------
> > > > >         if (d_in_lookup(dentry)) {
> > > > >                 dn = ceph_finish_lookup(req, dentry, err);
> > > > >                 if (IS_ERR(dn))
> > > > >                         err = PTR_ERR(dn);
> > > > >         } else {
> > > > >                 /* we were given a hashed negative dentry */
> > > > >                 dn = NULL;
> > > > >         }
> > > > >         if (err)
> > > > >                 goto out_req;
> > > > >         if (dn || d_really_is_negative(dentry) || d_is_symlink(dentry)) {
> > > > >                 /* make vfs retry on splice, ENOENT, or symlink */
> > > > >                 doutc(cl, "finish_no_open on dn %p\n", dn);
> > > > >                 err = finish_no_open(file, dn);
> > > > >         } else {
> > > > >                 if (IS_ENCRYPTED(dir) &&
> > > > >                     !fscrypt_has_permitted_context(dir, d_inode(dentry))) {
> > > > >                         pr_warn_client(cl,
> > > > >                                 "Inconsistent encryption context (parent %llx:%llx child %llx:%llx)\n",
> > > > >                                 ceph_vinop(dir), ceph_vinop(d_inode(dentry)));
> > > > >                         goto out_req;
> > > > >                 }
> > > > >
> > > > >                 doutc(cl, "finish_open on dn %p\n", dn);
> > > > >                 if (req->r_op == CEPH_MDS_OP_CREATE && req->r_reply_info.has_create_ino) {
> > > > >                         struct inode *newino = d_inode(dentry);
> > > > >
> > > > >                         cache_file_layout(dir, newino);
> > > > >                         ceph_init_inode_acls(newino, &as_ctx);
> > > > >                         file->f_mode |= FMODE_CREATED;
> > > > >                 }
> > > > >                 err = finish_open(file, dentry, ceph_open);
> > > > >         }
> > > > > -------------------------8<--------------------------
> > > > >
> > > > > It looks like this won't handle it correctly if the pathwalk terminates
> > > > > on a symlink (re: d_is_symlink() case). You should either set up a test
> > > > > ceph cluster on your own, or reach out to the ceph community and ask
> > > > > them to test this.
> > > > >
> > > >
> > > > Thanks for reviewing. The d_is_symlink() case seems to be calling
> > > > finish_no_open so shouldn't this be okay?
> > > >
> > >
> > > My mistake -- you're correct. I keep forgetting that finish_no_open()
> > > will handle this case regardless of what else happens.
> > >
> > > > > >               err = finish_open(file, dentry, ceph_open);
> > > > > >       }
> > > > > >  out_req:
> > > > > > diff --git a/fs/fcntl.c b/fs/fcntl.c
> > > > > > index beab8080badf..240bb511557a 100644
> > > > > > --- a/fs/fcntl.c
> > > > > > +++ b/fs/fcntl.c
> > > > > > @@ -1169,9 +1169,9 @@ static int __init fcntl_init(void)
> > > > > >        * Exceptions: O_NONBLOCK is a two bit define on parisc; O_NDELAY
> > > > > >        * is defined as O_NONBLOCK on some platforms and not on others.
> > > > > >        */
> > > > > > -     BUILD_BUG_ON(20 - 1 /* for O_RDONLY being 0 */ !=
> > > > > > +     BUILD_BUG_ON(21 - 1 /* for O_RDONLY being 0 */ !=
> > > > > >               HWEIGHT32(
> > > > > > -                     (VALID_OPEN_FLAGS & ~(O_NONBLOCK | O_NDELAY)) |
> > > > > > +                     (VALID_OPENAT2_FLAGS & ~(O_NONBLOCK | O_NDELAY)) |
> > > > > >                       __FMODE_EXEC));
> > > > > >
> > > > > >       fasync_cache = kmem_cache_create("fasync_cache",
> > > > > > diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
> > > > > > index 8344040ecaf7..4604e2e8a9cc 100644
> > > > > > --- a/fs/gfs2/inode.c
> > > > > > +++ b/fs/gfs2/inode.c
> > > > > > @@ -738,6 +738,12 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
> > > > > >       inode = gfs2_dir_search(dir, &dentry->d_name, !S_ISREG(mode) || excl);
> > > > > >       error = PTR_ERR(inode);
> > > > > >       if (!IS_ERR(inode)) {
> > > > > > +             if (file && (file->f_flags & OPENAT2_REGULAR) && !S_ISREG(inode->i_mode)) {
> > > > >
> > > > > Isn't OPENAT2_REGULAR getting masked off in ->f_flags now?
> > > > >
> > > > Yes, I thought the masking off was happening after this codepath got
> > > > executed. Maybe it's better anyway to pass another flags param to this
> > > > function and forward the flags from the gfs2_atomic_open function and
> > > > in other call sites pass 0 ? What do you think?
> > > >
> > >
> > > Also my mistake. That happens in do_dentry_open() which happens in
> > > finish_open(), so you should be OK here.
> > >
> > > Reviewed-by: Jeff Layton <jlayton@kernel.org>
> >
> > Thanks for patiently reviewing this! I am planning on sending patches
> > for man-pages and looking into some xfs-tests for this. But I am not
> > sure if this patch series will get more reviews from others or if it
> > will be picked up in the vfs branch?
> >
>
> This is a change to rather core VFS infrastructure so yes, you should
> expect some more review. Assuming no major issues are found, then yes,
> this should eventually get picked up by the VFS maintainers.
>
> Cheers,
> --
> Jeff Layton <jlayton@kernel.org>

Ping....
This patch series got a "Reviewed-by" from Jeff Layton but it probably
requires more reviews from other maintainers/reviewers as well. So
requesting for review on this patch series. Thanks!

Regards,
Dorjoy

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

* Re: [PATCH v6 1/4] openat2: new OPENAT2_REGULAR flag support
  2026-04-06 15:30             ` Dorjoy Chowdhury
@ 2026-04-14 17:33               ` Dorjoy Chowdhury
  0 siblings, 0 replies; 23+ messages in thread
From: Dorjoy Chowdhury @ 2026-04-14 17:33 UTC (permalink / raw)
  To: linux-fsdevel, brauner
  Cc: Jeff Layton, linux-kernel, linux-api, ceph-devel, gfs2, linux-nfs,
	linux-cifs, v9fs, linux-kselftest, viro, jack, chuck.lever,
	alex.aring, arnd, adilger, mjguzik, smfrench, richard.henderson,
	mattst88, linmag7, tsbogend, James.Bottomley, deller, davem,
	andreas, idryomov, amarkuze, slava, agruenba, trondmy, anna,
	sfrench, pc, ronniesahlberg, sprasad, tom, bharathsm, shuah,
	miklos, hansg

On Mon, Apr 6, 2026 at 9:30 PM Dorjoy Chowdhury <dorjoychy111@gmail.com> wrote:
>
> On Mon, Apr 6, 2026 at 5:27 AM Jeff Layton <jlayton@kernel.org> wrote:
> >
> > On Sat, 2026-04-04 at 21:17 +0600, Dorjoy Chowdhury wrote:
> > > On Thu, Apr 2, 2026 at 1:02 AM Jeff Layton <jlayton@kernel.org> wrote:
> > > >
> > > > On Mon, 2026-03-30 at 21:07 +0600, Dorjoy Chowdhury wrote:
> > > > > On Mon, Mar 30, 2026 at 5:49 PM Jeff Layton <jlayton@kernel.org> wrote:
> > > > > >
> > > > > > On Sat, 2026-03-28 at 23:22 +0600, Dorjoy Chowdhury wrote:
> > > > > > > This flag indicates the path should be opened if it's a regular file.
> > > > > > > This is useful to write secure programs that want to avoid being
> > > > > > > tricked into opening device nodes with special semantics while thinking
> > > > > > > they operate on regular files. This is a requested feature from the
> > > > > > > uapi-group[1].
> > > > > > >
> > > > > > > A corresponding error code EFTYPE has been introduced. For example, if
> > > > > > > openat2 is called on path /dev/null with OPENAT2_REGULAR in the flag
> > > > > > > param, it will return -EFTYPE. EFTYPE is already used in BSD systems
> > > > > > > like FreeBSD, macOS.
> > > > > > >
> > > > > > > When used in combination with O_CREAT, either the regular file is
> > > > > > > created, or if the path already exists, it is opened if it's a regular
> > > > > > > file. Otherwise, -EFTYPE is returned.
> > > > > > >
> > > > > > > When OPENAT2_REGULAR is combined with O_DIRECTORY, -EINVAL is returned
> > > > > > > as it doesn't make sense to open a path that is both a directory and a
> > > > > > > regular file.
> > > > > > >
> > > > > > > [1]: https://uapi-group.org/kernel-features/#ability-to-only-open-regular-files
> > > > > > >
> > > > > > > Signed-off-by: Dorjoy Chowdhury <dorjoychy111@gmail.com>
> > > > > > > ---
> > > > > > >  arch/alpha/include/uapi/asm/errno.h        |  2 ++
> > > > > > >  arch/alpha/include/uapi/asm/fcntl.h        |  1 +
> > > > > > >  arch/mips/include/uapi/asm/errno.h         |  2 ++
> > > > > > >  arch/parisc/include/uapi/asm/errno.h       |  2 ++
> > > > > > >  arch/parisc/include/uapi/asm/fcntl.h       |  1 +
> > > > > > >  arch/sparc/include/uapi/asm/errno.h        |  2 ++
> > > > > > >  arch/sparc/include/uapi/asm/fcntl.h        |  1 +
> > > > > > >  fs/ceph/file.c                             |  4 ++++
> > > > > > >  fs/fcntl.c                                 |  4 ++--
> > > > > > >  fs/gfs2/inode.c                            |  6 ++++++
> > > > > > >  fs/namei.c                                 |  4 ++++
> > > > > > >  fs/nfs/dir.c                               |  4 ++++
> > > > > > >  fs/open.c                                  |  8 +++++---
> > > > > > >  fs/smb/client/dir.c                        | 14 +++++++++++++-
> > > > > > >  include/linux/fcntl.h                      |  2 ++
> > > > > > >  include/uapi/asm-generic/errno.h           |  2 ++
> > > > > > >  include/uapi/asm-generic/fcntl.h           |  4 ++++
> > > > > > >  tools/arch/alpha/include/uapi/asm/errno.h  |  2 ++
> > > > > > >  tools/arch/mips/include/uapi/asm/errno.h   |  2 ++
> > > > > > >  tools/arch/parisc/include/uapi/asm/errno.h |  2 ++
> > > > > > >  tools/arch/sparc/include/uapi/asm/errno.h  |  2 ++
> > > > > > >  tools/include/uapi/asm-generic/errno.h     |  2 ++
> > > > > > >  22 files changed, 67 insertions(+), 6 deletions(-)
> > > > > > >
> > > > > > > diff --git a/arch/alpha/include/uapi/asm/errno.h b/arch/alpha/include/uapi/asm/errno.h
> > > > > > > index 6791f6508632..1a99f38813c7 100644
> > > > > > > --- a/arch/alpha/include/uapi/asm/errno.h
> > > > > > > +++ b/arch/alpha/include/uapi/asm/errno.h
> > > > > > > @@ -127,4 +127,6 @@
> > > > > > >
> > > > > > >  #define EHWPOISON    139     /* Memory page has hardware error */
> > > > > > >
> > > > > > > +#define EFTYPE               140     /* Wrong file type for the intended operation */
> > > > > > > +
> > > > > > >  #endif
> > > > > > > diff --git a/arch/alpha/include/uapi/asm/fcntl.h b/arch/alpha/include/uapi/asm/fcntl.h
> > > > > > > index 50bdc8e8a271..fe488bf7c18e 100644
> > > > > > > --- a/arch/alpha/include/uapi/asm/fcntl.h
> > > > > > > +++ b/arch/alpha/include/uapi/asm/fcntl.h
> > > > > > > @@ -34,6 +34,7 @@
> > > > > > >
> > > > > > >  #define O_PATH               040000000
> > > > > > >  #define __O_TMPFILE  0100000000
> > > > > > > +#define OPENAT2_REGULAR      0200000000
> > > > > > >
> > > > > > >  #define F_GETLK              7
> > > > > > >  #define F_SETLK              8
> > > > > > > diff --git a/arch/mips/include/uapi/asm/errno.h b/arch/mips/include/uapi/asm/errno.h
> > > > > > > index c01ed91b1ef4..1835a50b69ce 100644
> > > > > > > --- a/arch/mips/include/uapi/asm/errno.h
> > > > > > > +++ b/arch/mips/include/uapi/asm/errno.h
> > > > > > > @@ -126,6 +126,8 @@
> > > > > > >
> > > > > > >  #define EHWPOISON    168     /* Memory page has hardware error */
> > > > > > >
> > > > > > > +#define EFTYPE               169     /* Wrong file type for the intended operation */
> > > > > > > +
> > > > > > >  #define EDQUOT               1133    /* Quota exceeded */
> > > > > > >
> > > > > > >
> > > > > > > diff --git a/arch/parisc/include/uapi/asm/errno.h b/arch/parisc/include/uapi/asm/errno.h
> > > > > > > index 8cbc07c1903e..93194fbb0a80 100644
> > > > > > > --- a/arch/parisc/include/uapi/asm/errno.h
> > > > > > > +++ b/arch/parisc/include/uapi/asm/errno.h
> > > > > > > @@ -124,4 +124,6 @@
> > > > > > >
> > > > > > >  #define EHWPOISON    257     /* Memory page has hardware error */
> > > > > > >
> > > > > > > +#define EFTYPE               258     /* Wrong file type for the intended operation */
> > > > > > > +
> > > > > > >  #endif
> > > > > > > diff --git a/arch/parisc/include/uapi/asm/fcntl.h b/arch/parisc/include/uapi/asm/fcntl.h
> > > > > > > index 03dee816cb13..d46812f2f0f4 100644
> > > > > > > --- a/arch/parisc/include/uapi/asm/fcntl.h
> > > > > > > +++ b/arch/parisc/include/uapi/asm/fcntl.h
> > > > > > > @@ -19,6 +19,7 @@
> > > > > > >
> > > > > > >  #define O_PATH               020000000
> > > > > > >  #define __O_TMPFILE  040000000
> > > > > > > +#define OPENAT2_REGULAR      0100000000
> > > > > > >
> > > > > > >  #define F_GETLK64    8
> > > > > > >  #define F_SETLK64    9
> > > > > > > diff --git a/arch/sparc/include/uapi/asm/errno.h b/arch/sparc/include/uapi/asm/errno.h
> > > > > > > index 4a41e7835fd5..71940ec9130b 100644
> > > > > > > --- a/arch/sparc/include/uapi/asm/errno.h
> > > > > > > +++ b/arch/sparc/include/uapi/asm/errno.h
> > > > > > > @@ -117,4 +117,6 @@
> > > > > > >
> > > > > > >  #define EHWPOISON    135     /* Memory page has hardware error */
> > > > > > >
> > > > > > > +#define EFTYPE               136     /* Wrong file type for the intended operation */
> > > > > > > +
> > > > > > >  #endif
> > > > > > > diff --git a/arch/sparc/include/uapi/asm/fcntl.h b/arch/sparc/include/uapi/asm/fcntl.h
> > > > > > > index 67dae75e5274..bb6e9fa94bc9 100644
> > > > > > > --- a/arch/sparc/include/uapi/asm/fcntl.h
> > > > > > > +++ b/arch/sparc/include/uapi/asm/fcntl.h
> > > > > > > @@ -37,6 +37,7 @@
> > > > > > >
> > > > > > >  #define O_PATH               0x1000000
> > > > > > >  #define __O_TMPFILE  0x2000000
> > > > > > > +#define OPENAT2_REGULAR      0x4000000
> > > > > > >
> > > > > > >  #define F_GETOWN     5       /*  for sockets. */
> > > > > > >  #define F_SETOWN     6       /*  for sockets. */
> > > > > > > diff --git a/fs/ceph/file.c b/fs/ceph/file.c
> > > > > > > index 66bbf6d517a9..6d8d4c7765e6 100644
> > > > > > > --- a/fs/ceph/file.c
> > > > > > > +++ b/fs/ceph/file.c
> > > > > > > @@ -977,6 +977,10 @@ int ceph_atomic_open(struct inode *dir, struct dentry *dentry,
> > > > > > >                       ceph_init_inode_acls(newino, &as_ctx);
> > > > > > >                       file->f_mode |= FMODE_CREATED;
> > > > > > >               }
> > > > > > > +             if ((flags & OPENAT2_REGULAR) && !d_is_reg(dentry)) {
> > > > > > > +                     err = -EFTYPE;
> > > > > > > +                     goto out_req;
> > > > > > > +             }
> > > > > >
> > > > > > ^^^
> > > > > > This doesn't look quite right. Here's a larger chunk of the code:
> > > > > >
> > > > > > -------------------------8<--------------------------
> > > > > >         if (d_in_lookup(dentry)) {
> > > > > >                 dn = ceph_finish_lookup(req, dentry, err);
> > > > > >                 if (IS_ERR(dn))
> > > > > >                         err = PTR_ERR(dn);
> > > > > >         } else {
> > > > > >                 /* we were given a hashed negative dentry */
> > > > > >                 dn = NULL;
> > > > > >         }
> > > > > >         if (err)
> > > > > >                 goto out_req;
> > > > > >         if (dn || d_really_is_negative(dentry) || d_is_symlink(dentry)) {
> > > > > >                 /* make vfs retry on splice, ENOENT, or symlink */
> > > > > >                 doutc(cl, "finish_no_open on dn %p\n", dn);
> > > > > >                 err = finish_no_open(file, dn);
> > > > > >         } else {
> > > > > >                 if (IS_ENCRYPTED(dir) &&
> > > > > >                     !fscrypt_has_permitted_context(dir, d_inode(dentry))) {
> > > > > >                         pr_warn_client(cl,
> > > > > >                                 "Inconsistent encryption context (parent %llx:%llx child %llx:%llx)\n",
> > > > > >                                 ceph_vinop(dir), ceph_vinop(d_inode(dentry)));
> > > > > >                         goto out_req;
> > > > > >                 }
> > > > > >
> > > > > >                 doutc(cl, "finish_open on dn %p\n", dn);
> > > > > >                 if (req->r_op == CEPH_MDS_OP_CREATE && req->r_reply_info.has_create_ino) {
> > > > > >                         struct inode *newino = d_inode(dentry);
> > > > > >
> > > > > >                         cache_file_layout(dir, newino);
> > > > > >                         ceph_init_inode_acls(newino, &as_ctx);
> > > > > >                         file->f_mode |= FMODE_CREATED;
> > > > > >                 }
> > > > > >                 err = finish_open(file, dentry, ceph_open);
> > > > > >         }
> > > > > > -------------------------8<--------------------------
> > > > > >
> > > > > > It looks like this won't handle it correctly if the pathwalk terminates
> > > > > > on a symlink (re: d_is_symlink() case). You should either set up a test
> > > > > > ceph cluster on your own, or reach out to the ceph community and ask
> > > > > > them to test this.
> > > > > >
> > > > >
> > > > > Thanks for reviewing. The d_is_symlink() case seems to be calling
> > > > > finish_no_open so shouldn't this be okay?
> > > > >
> > > >
> > > > My mistake -- you're correct. I keep forgetting that finish_no_open()
> > > > will handle this case regardless of what else happens.
> > > >
> > > > > > >               err = finish_open(file, dentry, ceph_open);
> > > > > > >       }
> > > > > > >  out_req:
> > > > > > > diff --git a/fs/fcntl.c b/fs/fcntl.c
> > > > > > > index beab8080badf..240bb511557a 100644
> > > > > > > --- a/fs/fcntl.c
> > > > > > > +++ b/fs/fcntl.c
> > > > > > > @@ -1169,9 +1169,9 @@ static int __init fcntl_init(void)
> > > > > > >        * Exceptions: O_NONBLOCK is a two bit define on parisc; O_NDELAY
> > > > > > >        * is defined as O_NONBLOCK on some platforms and not on others.
> > > > > > >        */
> > > > > > > -     BUILD_BUG_ON(20 - 1 /* for O_RDONLY being 0 */ !=
> > > > > > > +     BUILD_BUG_ON(21 - 1 /* for O_RDONLY being 0 */ !=
> > > > > > >               HWEIGHT32(
> > > > > > > -                     (VALID_OPEN_FLAGS & ~(O_NONBLOCK | O_NDELAY)) |
> > > > > > > +                     (VALID_OPENAT2_FLAGS & ~(O_NONBLOCK | O_NDELAY)) |
> > > > > > >                       __FMODE_EXEC));
> > > > > > >
> > > > > > >       fasync_cache = kmem_cache_create("fasync_cache",
> > > > > > > diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
> > > > > > > index 8344040ecaf7..4604e2e8a9cc 100644
> > > > > > > --- a/fs/gfs2/inode.c
> > > > > > > +++ b/fs/gfs2/inode.c
> > > > > > > @@ -738,6 +738,12 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
> > > > > > >       inode = gfs2_dir_search(dir, &dentry->d_name, !S_ISREG(mode) || excl);
> > > > > > >       error = PTR_ERR(inode);
> > > > > > >       if (!IS_ERR(inode)) {
> > > > > > > +             if (file && (file->f_flags & OPENAT2_REGULAR) && !S_ISREG(inode->i_mode)) {
> > > > > >
> > > > > > Isn't OPENAT2_REGULAR getting masked off in ->f_flags now?
> > > > > >
> > > > > Yes, I thought the masking off was happening after this codepath got
> > > > > executed. Maybe it's better anyway to pass another flags param to this
> > > > > function and forward the flags from the gfs2_atomic_open function and
> > > > > in other call sites pass 0 ? What do you think?
> > > > >
> > > >
> > > > Also my mistake. That happens in do_dentry_open() which happens in
> > > > finish_open(), so you should be OK here.
> > > >
> > > > Reviewed-by: Jeff Layton <jlayton@kernel.org>
> > >
> > > Thanks for patiently reviewing this! I am planning on sending patches
> > > for man-pages and looking into some xfs-tests for this. But I am not
> > > sure if this patch series will get more reviews from others or if it
> > > will be picked up in the vfs branch?
> > >
> >
> > This is a change to rather core VFS infrastructure so yes, you should
> > expect some more review. Assuming no major issues are found, then yes,
> > this should eventually get picked up by the VFS maintainers.
> >
> > Cheers,
> > --
> > Jeff Layton <jlayton@kernel.org>
>
> Ping....
> This patch series got a "Reviewed-by" from Jeff Layton but it probably
> requires more reviews from other maintainers/reviewers as well. So
> requesting for review on this patch series. Thanks!
>

Ping...
Requesting for review on this patch series please.

Regards,
Dorjoy

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

* Re: [PATCH v6 1/4] openat2: new OPENAT2_REGULAR flag support
  2026-03-28 17:22 ` [PATCH v6 1/4] openat2: new OPENAT2_REGULAR flag support Dorjoy Chowdhury
  2026-03-30 11:49   ` Jeff Layton
@ 2026-04-16 11:41   ` Aleksa Sarai
  2026-04-16 11:58     ` Dorjoy Chowdhury
  2026-04-16 13:52   ` Jori Koolstra
  2 siblings, 1 reply; 23+ messages in thread
From: Aleksa Sarai @ 2026-04-16 11:41 UTC (permalink / raw)
  To: Dorjoy Chowdhury
  Cc: linux-fsdevel, linux-kernel, linux-api, ceph-devel, gfs2,
	linux-nfs, linux-cifs, v9fs, linux-kselftest, viro, brauner, jack,
	jlayton, chuck.lever, alex.aring, arnd, adilger, mjguzik,
	smfrench, richard.henderson, mattst88, linmag7, tsbogend,
	James.Bottomley, deller, davem, andreas, idryomov, amarkuze,
	slava, agruenba, trondmy, anna, sfrench, pc, ronniesahlberg,
	sprasad, tom, bharathsm, shuah, miklos, hansg

[-- Attachment #1: Type: text/plain, Size: 2250 bytes --]

On 2026-03-28, Dorjoy Chowdhury <dorjoychy111@gmail.com> wrote:
> This flag indicates the path should be opened if it's a regular file.
> This is useful to write secure programs that want to avoid being
> tricked into opening device nodes with special semantics while thinking
> they operate on regular files. This is a requested feature from the
> uapi-group[1].
> 
> A corresponding error code EFTYPE has been introduced. For example, if
> openat2 is called on path /dev/null with OPENAT2_REGULAR in the flag
> param, it will return -EFTYPE. EFTYPE is already used in BSD systems
> like FreeBSD, macOS.
> 
> When used in combination with O_CREAT, either the regular file is
> created, or if the path already exists, it is opened if it's a regular
> file. Otherwise, -EFTYPE is returned.
> 
> When OPENAT2_REGULAR is combined with O_DIRECTORY, -EINVAL is returned
> as it doesn't make sense to open a path that is both a directory and a
> regular file.
> 
> [1]: https://uapi-group.org/kernel-features/#ability-to-only-open-regular-files
> 
> Signed-off-by: Dorjoy Chowdhury <dorjoychy111@gmail.com>
> ---

Aside from the nit below, feel free to take a

Reviewed-by: Aleksa Sarai <aleksa@amutable.com>

> diff --git a/fs/open.c b/fs/open.c
> index 681d405bc61e..a6f445f72181 100644
> --- a/fs/open.c
> +++ b/fs/open.c
> @@ -960,7 +960,7 @@ static int do_dentry_open(struct file *f,
>  	if (f->f_mapping->a_ops && f->f_mapping->a_ops->direct_IO)
>  		f->f_mode |= FMODE_CAN_ODIRECT;
>  
> -	f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
> +	f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC | OPENAT2_REGULAR);

It's not clear to me why you dropped this, I didn't see a review
mentioning it either. (General note: Ideally the cover letter changelog
would mention who suggested a change in brackets after the changelog
line so it's easier to track where a change might've come from.)

I would personally keep it since O_DIRECTORY is not dropped (I do find
it interesting that O_EXCL is dropped too -- you could imagine a
userspace program wanting to know that the file was opened with O_EXCL,
though it provides you very little information).

-- 
Aleksa Sarai
https://www.cyphar.com/

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 265 bytes --]

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

* Re: [PATCH v6 1/4] openat2: new OPENAT2_REGULAR flag support
  2026-04-16 11:41   ` Aleksa Sarai
@ 2026-04-16 11:58     ` Dorjoy Chowdhury
  2026-04-16 13:05       ` Aleksa Sarai
  0 siblings, 1 reply; 23+ messages in thread
From: Dorjoy Chowdhury @ 2026-04-16 11:58 UTC (permalink / raw)
  To: Aleksa Sarai, jlayton
  Cc: linux-fsdevel, linux-kernel, linux-api, ceph-devel, gfs2,
	linux-nfs, linux-cifs, v9fs, linux-kselftest, viro, brauner, jack,
	chuck.lever, alex.aring, arnd, adilger, mjguzik, smfrench,
	richard.henderson, mattst88, linmag7, tsbogend, James.Bottomley,
	deller, davem, andreas, idryomov, amarkuze, slava, agruenba,
	trondmy, anna, sfrench, pc, ronniesahlberg, sprasad, tom,
	bharathsm, shuah, miklos, hansg

On Thu, Apr 16, 2026 at 5:41 PM Aleksa Sarai <cyphar@cyphar.com> wrote:
>
> On 2026-03-28, Dorjoy Chowdhury <dorjoychy111@gmail.com> wrote:
> > This flag indicates the path should be opened if it's a regular file.
> > This is useful to write secure programs that want to avoid being
> > tricked into opening device nodes with special semantics while thinking
> > they operate on regular files. This is a requested feature from the
> > uapi-group[1].
> >
> > A corresponding error code EFTYPE has been introduced. For example, if
> > openat2 is called on path /dev/null with OPENAT2_REGULAR in the flag
> > param, it will return -EFTYPE. EFTYPE is already used in BSD systems
> > like FreeBSD, macOS.
> >
> > When used in combination with O_CREAT, either the regular file is
> > created, or if the path already exists, it is opened if it's a regular
> > file. Otherwise, -EFTYPE is returned.
> >
> > When OPENAT2_REGULAR is combined with O_DIRECTORY, -EINVAL is returned
> > as it doesn't make sense to open a path that is both a directory and a
> > regular file.
> >
> > [1]: https://uapi-group.org/kernel-features/#ability-to-only-open-regular-files
> >
> > Signed-off-by: Dorjoy Chowdhury <dorjoychy111@gmail.com>
> > ---
>
> Aside from the nit below, feel free to take a
>
> Reviewed-by: Aleksa Sarai <aleksa@amutable.com>
>

Thanks for reviewing!

> > diff --git a/fs/open.c b/fs/open.c
> > index 681d405bc61e..a6f445f72181 100644
> > --- a/fs/open.c
> > +++ b/fs/open.c
> > @@ -960,7 +960,7 @@ static int do_dentry_open(struct file *f,
> >       if (f->f_mapping->a_ops && f->f_mapping->a_ops->direct_IO)
> >               f->f_mode |= FMODE_CAN_ODIRECT;
> >
> > -     f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
> > +     f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC | OPENAT2_REGULAR);
>
> It's not clear to me why you dropped this, I didn't see a review
> mentioning it either. (General note: Ideally the cover letter changelog
> would mention who suggested a change in brackets after the changelog
> line so it's easier to track where a change might've come from.)
>

Thanks for the general note. I will keep that in mind.

The review was from Jeff Layton in v5
https://lore.kernel.org/linux-fsdevel/5fcc2a6e6d92dae0601c6b3b8faa8b2f83981afb.camel@kernel.org/
" 1. OPENAT2_REGULAR leaks into f_flags - do_dentry_open() strips
open-time-only flags (O_CREAT|O_EXCL|O_NOCTTY|O_TRUNC)
  but does not strip OPENAT2_REGULAR. When a regular file is
successfully opened via openat2() with this flag, the bit
  persists in file->f_flags and will be returned by fcntl(fd, F_GETFL)."

I think it makes sense to strip off as OPENAT2_REGULAR is an open time
only flag (like O_CREAT and the others already), right?

Regards,
Dorjoy

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

* Re: [PATCH v6 1/4] openat2: new OPENAT2_REGULAR flag support
  2026-04-16 11:58     ` Dorjoy Chowdhury
@ 2026-04-16 13:05       ` Aleksa Sarai
  2026-04-16 13:28         ` Jeff Layton
  0 siblings, 1 reply; 23+ messages in thread
From: Aleksa Sarai @ 2026-04-16 13:05 UTC (permalink / raw)
  To: Dorjoy Chowdhury
  Cc: jlayton, linux-fsdevel, Linus Torvalds, linux-kernel, linux-api,
	ceph-devel, gfs2, linux-nfs, linux-cifs, v9fs, linux-kselftest,
	viro, brauner, jack, chuck.lever, alex.aring, arnd, adilger,
	mjguzik, smfrench, richard.henderson, mattst88, linmag7, tsbogend,
	James.Bottomley, deller, davem, andreas, idryomov, amarkuze,
	slava, agruenba, trondmy, anna, sfrench, pc, ronniesahlberg,
	sprasad, tom, bharathsm, shuah, miklos, hansg

[-- Attachment #1: Type: text/plain, Size: 4282 bytes --]

On 2026-04-16, Dorjoy Chowdhury <dorjoychy111@gmail.com> wrote:
> On Thu, Apr 16, 2026 at 5:41 PM Aleksa Sarai <cyphar@cyphar.com> wrote:
> >
> > On 2026-03-28, Dorjoy Chowdhury <dorjoychy111@gmail.com> wrote:
> > > This flag indicates the path should be opened if it's a regular file.
> > > This is useful to write secure programs that want to avoid being
> > > tricked into opening device nodes with special semantics while thinking
> > > they operate on regular files. This is a requested feature from the
> > > uapi-group[1].
> > >
> > > A corresponding error code EFTYPE has been introduced. For example, if
> > > openat2 is called on path /dev/null with OPENAT2_REGULAR in the flag
> > > param, it will return -EFTYPE. EFTYPE is already used in BSD systems
> > > like FreeBSD, macOS.
> > >
> > > When used in combination with O_CREAT, either the regular file is
> > > created, or if the path already exists, it is opened if it's a regular
> > > file. Otherwise, -EFTYPE is returned.
> > >
> > > When OPENAT2_REGULAR is combined with O_DIRECTORY, -EINVAL is returned
> > > as it doesn't make sense to open a path that is both a directory and a
> > > regular file.
> > >
> > > [1]: https://uapi-group.org/kernel-features/#ability-to-only-open-regular-files
> > >
> > > Signed-off-by: Dorjoy Chowdhury <dorjoychy111@gmail.com>
> > > ---
> >
> > Aside from the nit below, feel free to take a
> >
> > Reviewed-by: Aleksa Sarai <aleksa@amutable.com>
> >
> 
> Thanks for reviewing!
> 
> > > diff --git a/fs/open.c b/fs/open.c
> > > index 681d405bc61e..a6f445f72181 100644
> > > --- a/fs/open.c
> > > +++ b/fs/open.c
> > > @@ -960,7 +960,7 @@ static int do_dentry_open(struct file *f,
> > >       if (f->f_mapping->a_ops && f->f_mapping->a_ops->direct_IO)
> > >               f->f_mode |= FMODE_CAN_ODIRECT;
> > >
> > > -     f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
> > > +     f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC | OPENAT2_REGULAR);
> >
> > It's not clear to me why you dropped this, I didn't see a review
> > mentioning it either. (General note: Ideally the cover letter changelog
> > would mention who suggested a change in brackets after the changelog
> > line so it's easier to track where a change might've come from.)
> >
> 
> Thanks for the general note. I will keep that in mind.
> 
> The review was from Jeff Layton in v5
> https://lore.kernel.org/linux-fsdevel/5fcc2a6e6d92dae0601c6b3b8faa8b2f83981afb.camel@kernel.org/
> " 1. OPENAT2_REGULAR leaks into f_flags - do_dentry_open() strips
> open-time-only flags (O_CREAT|O_EXCL|O_NOCTTY|O_TRUNC)
>   but does not strip OPENAT2_REGULAR. When a regular file is
> successfully opened via openat2() with this flag, the bit
>   persists in file->f_flags and will be returned by fcntl(fd, F_GETFL)."
> 
> I think it makes sense to strip off as OPENAT2_REGULAR is an open time
> only flag (like O_CREAT and the others already), right?

Well, O_DIRECTORY isn't stripped so if we want to mirror that behaviour
then it shouldn't be stripped either IMHO.

O_NOCTTY and O_TRUNC make sense to strip (they are not relevant to the
file after it was opened -- truncation only happens at open time and you
can always set your controlling TTY later).

The story with O_CREAT and O_EXCL is a bit more complicated. They are
stripped but the history there is unclear -- the line was added in Linux
0.98.4(!) with no mention in the release note at the time. (Linus: I
wonder if you remember why this was changed at the time? Sorry for the
trip down memory lane...)

However, the existence of F_CREATED_QUERY kind of shows that these kinds
of checks are stuff that userspace can find handy (though FMODE_CREATED
is more useful than O_CREAT|O_EXCL anyway). O_EXCL is used internally
for stuff so it can be re-exposed, I'm just not sure it's a good
precedent to make a decision based on.

Then again, userspace can check with fstat(2) so it's not the end of the
world, but I don't really see a strong reason to hide information from
userspace. Since the mail was from Claude (and it tends to give silly
nits like that) I'm not sure whether Jeff would agree with my view or
not.

-- 
Aleksa Sarai
https://www.cyphar.com/

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 265 bytes --]

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

* Re: [PATCH v6 0/4] OPENAT2_REGULAR flag support for openat2
  2026-03-28 17:22 [PATCH v6 0/4] OPENAT2_REGULAR flag support for openat2 Dorjoy Chowdhury
                   ` (3 preceding siblings ...)
  2026-03-28 17:22 ` [PATCH v6 4/4] mips/fcntl.h: " Dorjoy Chowdhury
@ 2026-04-16 13:07 ` Christian Brauner
  2026-04-16 15:22   ` Dorjoy Chowdhury
  4 siblings, 1 reply; 23+ messages in thread
From: Christian Brauner @ 2026-04-16 13:07 UTC (permalink / raw)
  To: linux-fsdevel, Dorjoy Chowdhury
  Cc: Christian Brauner, linux-kernel, linux-api, ceph-devel, gfs2,
	linux-nfs, linux-cifs, v9fs, linux-kselftest, viro, jack, jlayton,
	chuck.lever, alex.aring, arnd, adilger, mjguzik, smfrench,
	richard.henderson, mattst88, linmag7, tsbogend, James.Bottomley,
	deller, davem, andreas, idryomov, amarkuze, slava, agruenba,
	trondmy, anna, sfrench, pc, ronniesahlberg, sprasad, tom,
	bharathsm, shuah, miklos, hansg

On Sat, 28 Mar 2026 23:22:21 +0600, Dorjoy Chowdhury wrote:
> I came upon this "Ability to only open regular files" uapi feature suggestion
> from https://uapi-group.org/kernel-features/#ability-to-only-open-regular-files
> and thought it would be something I could do as a first patch and get to
> know the kernel code a bit better.
> 
> The following filesystems have been tested by building and booting the kernel
> x86 bzImage in a Fedora 43 VM in QEMU. I have tested with OPENAT2_REGULAR that
> regular files can be successfully opened and non-regular files (directory, fifo etc)
> return -EFTYPE.
> - btrfs
> - NFS (loopback)
> - SMB (loopback)
> 
> [...]

- I've added an explanation why OPENAT2_REGULAR is only needed for some
  ->atomic_open() implementers but not others. What I don't like is that
  we need all that custom handling in there but it's managable.

- I dropped the topmost style conversions. They really don't belong
  there and if we switch to something better we should use (1 << <nr>).

- I split the EFTYPE errno introduction into a separate patch.

---

Applied to the vfs-7.2.openat.regular branch of the vfs/vfs.git tree.
Patches in the vfs-7.2.openat.regular branch should appear in linux-next soon.

Please report any outstanding bugs that were missed during review in a
new review to the original patch series allowing us to drop it.

It's encouraged to provide Acked-bys and Reviewed-bys even though the
patch has now been applied. If possible patch trailers will be updated.

Note that commit hashes shown below are subject to change due to rebase,
trailer updates or similar. If in doubt, please check the listed branch.

tree:   https://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs.git
branch: master

[1/4] openat2: new OPENAT2_REGULAR flag support
      https://git.kernel.org/vfs/vfs/c/0b649c4d70f7
[2/4] kselftest/openat2: test for OPENAT2_REGULAR flag
      https://git.kernel.org/vfs/vfs/c/d7dc36df8fa7
[3/4] sparc/fcntl.h: convert O_* flag macros from hex to octal
      (dropped)
[4/4] mips/fcntl.h: convert O_* flag macros from hex to octal
      (dropped)

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

* Re: [PATCH v6 1/4] openat2: new OPENAT2_REGULAR flag support
  2026-04-16 13:05       ` Aleksa Sarai
@ 2026-04-16 13:28         ` Jeff Layton
  0 siblings, 0 replies; 23+ messages in thread
From: Jeff Layton @ 2026-04-16 13:28 UTC (permalink / raw)
  To: Aleksa Sarai, Dorjoy Chowdhury
  Cc: linux-fsdevel, Linus Torvalds, linux-kernel, linux-api,
	ceph-devel, gfs2, linux-nfs, linux-cifs, v9fs, linux-kselftest,
	viro, brauner, jack, chuck.lever, alex.aring, arnd, adilger,
	mjguzik, smfrench, richard.henderson, mattst88, linmag7, tsbogend,
	James.Bottomley, deller, davem, andreas, idryomov, amarkuze,
	slava, agruenba, trondmy, anna, sfrench, pc, ronniesahlberg,
	sprasad, tom, bharathsm, shuah, miklos, hansg

On Thu, 2026-04-16 at 23:05 +1000, Aleksa Sarai wrote:
> On 2026-04-16, Dorjoy Chowdhury <dorjoychy111@gmail.com> wrote:
> > On Thu, Apr 16, 2026 at 5:41 PM Aleksa Sarai <cyphar@cyphar.com> wrote:
> > > 
> > > On 2026-03-28, Dorjoy Chowdhury <dorjoychy111@gmail.com> wrote:
> > > > This flag indicates the path should be opened if it's a regular file.
> > > > This is useful to write secure programs that want to avoid being
> > > > tricked into opening device nodes with special semantics while thinking
> > > > they operate on regular files. This is a requested feature from the
> > > > uapi-group[1].
> > > > 
> > > > A corresponding error code EFTYPE has been introduced. For example, if
> > > > openat2 is called on path /dev/null with OPENAT2_REGULAR in the flag
> > > > param, it will return -EFTYPE. EFTYPE is already used in BSD systems
> > > > like FreeBSD, macOS.
> > > > 
> > > > When used in combination with O_CREAT, either the regular file is
> > > > created, or if the path already exists, it is opened if it's a regular
> > > > file. Otherwise, -EFTYPE is returned.
> > > > 
> > > > When OPENAT2_REGULAR is combined with O_DIRECTORY, -EINVAL is returned
> > > > as it doesn't make sense to open a path that is both a directory and a
> > > > regular file.
> > > > 
> > > > [1]: https://uapi-group.org/kernel-features/#ability-to-only-open-regular-files
> > > > 
> > > > Signed-off-by: Dorjoy Chowdhury <dorjoychy111@gmail.com>
> > > > ---
> > > 
> > > Aside from the nit below, feel free to take a
> > > 
> > > Reviewed-by: Aleksa Sarai <aleksa@amutable.com>
> > > 
> > 
> > Thanks for reviewing!
> > 
> > > > diff --git a/fs/open.c b/fs/open.c
> > > > index 681d405bc61e..a6f445f72181 100644
> > > > --- a/fs/open.c
> > > > +++ b/fs/open.c
> > > > @@ -960,7 +960,7 @@ static int do_dentry_open(struct file *f,
> > > >       if (f->f_mapping->a_ops && f->f_mapping->a_ops->direct_IO)
> > > >               f->f_mode |= FMODE_CAN_ODIRECT;
> > > > 
> > > > -     f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
> > > > +     f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC | OPENAT2_REGULAR);
> > > 
> > > It's not clear to me why you dropped this, I didn't see a review
> > > mentioning it either. (General note: Ideally the cover letter changelog
> > > would mention who suggested a change in brackets after the changelog
> > > line so it's easier to track where a change might've come from.)
> > > 
> > 
> > Thanks for the general note. I will keep that in mind.
> > 
> > The review was from Jeff Layton in v5
> > https://lore.kernel.org/linux-fsdevel/5fcc2a6e6d92dae0601c6b3b8faa8b2f83981afb.camel@kernel.org/
> > " 1. OPENAT2_REGULAR leaks into f_flags - do_dentry_open() strips
> > open-time-only flags (O_CREAT|O_EXCL|O_NOCTTY|O_TRUNC)
> >   but does not strip OPENAT2_REGULAR. When a regular file is
> > successfully opened via openat2() with this flag, the bit
> >   persists in file->f_flags and will be returned by fcntl(fd, F_GETFL)."
> > 
> > I think it makes sense to strip off as OPENAT2_REGULAR is an open time
> > only flag (like O_CREAT and the others already), right?
> 
> Well, O_DIRECTORY isn't stripped so if we want to mirror that behaviour
> then it shouldn't be stripped either IMHO.
> 
> O_NOCTTY and O_TRUNC make sense to strip (they are not relevant to the
> file after it was opened -- truncation only happens at open time and you
> can always set your controlling TTY later).
> 
> The story with O_CREAT and O_EXCL is a bit more complicated. They are
> stripped but the history there is unclear -- the line was added in Linux
> 0.98.4(!) with no mention in the release note at the time. (Linus: I
> wonder if you remember why this was changed at the time? Sorry for the
> trip down memory lane...)
> 
> However, the existence of F_CREATED_QUERY kind of shows that these kinds
> of checks are stuff that userspace can find handy (though FMODE_CREATED
> is more useful than O_CREAT|O_EXCL anyway). O_EXCL is used internally
> for stuff so it can be re-exposed, I'm just not sure it's a good
> precedent to make a decision based on.
> 
> Then again, userspace can check with fstat(2) so it's not the end of the
> world, but I don't really see a strong reason to hide information from
> userspace. Since the mail was from Claude (and it tends to give silly
> nits like that) I'm not sure whether Jeff would agree with my view or
> not.

I don't have a strong feeling either way, but it "feels" like O_REGULAR
is not particularly useful to return in F_GETFL.

Once the file is open, then O_REGULAR really doesn't matter anymore. We
_know_ it's a regular file at that point or the open wouldn't have
happened. F_GETFL is more useful for showing flags that actually affect
how the file description works (e.g. O_DIRECT, O_ASYNC, etc.).

-- 
Jeff Layton <jlayton@kernel.org>

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

* Re: [PATCH v6 1/4] openat2: new OPENAT2_REGULAR flag support
  2026-03-28 17:22 ` [PATCH v6 1/4] openat2: new OPENAT2_REGULAR flag support Dorjoy Chowdhury
  2026-03-30 11:49   ` Jeff Layton
  2026-04-16 11:41   ` Aleksa Sarai
@ 2026-04-16 13:52   ` Jori Koolstra
  2026-04-16 14:21     ` Dorjoy Chowdhury
  2 siblings, 1 reply; 23+ messages in thread
From: Jori Koolstra @ 2026-04-16 13:52 UTC (permalink / raw)
  To: Dorjoy Chowdhury
  Cc: linux-fsdevel, linux-kernel, linux-api, ceph-devel, gfs2,
	linux-nfs, linux-cifs, v9fs, linux-kselftest, viro, brauner, jack,
	jlayton, chuck.lever, alex.aring, arnd, adilger, mjguzik,
	smfrench, richard.henderson, mattst88, linmag7, tsbogend,
	James.Bottomley, deller, davem, andreas, idryomov, amarkuze,
	slava, agruenba, trondmy, anna, sfrench, pc, ronniesahlberg,
	sprasad, tom, bharathsm, shuah, miklos, hansg

On Sat, Mar 28, 2026 at 11:22:22PM +0600, Dorjoy Chowdhury wrote:
> diff --git a/arch/alpha/include/uapi/asm/fcntl.h b/arch/alpha/include/uapi/asm/fcntl.h
> index 50bdc8e8a271..fe488bf7c18e 100644
> --- a/arch/alpha/include/uapi/asm/fcntl.h
> +++ b/arch/alpha/include/uapi/asm/fcntl.h
> @@ -34,6 +34,7 @@
>  
>  #define O_PATH		040000000
>  #define __O_TMPFILE	0100000000
> +#define OPENAT2_REGULAR	0200000000
>

I don't quite understand why we are adding OPENAT2_REGULAR inside the
O_* flag range. Wasn't this supposed to be only supported for openat2()?
If so, I don't see the need to waste an O_* flag bit. But maybe I am
missing something.

Thanks,
Jori.

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

* Re: [PATCH v6 1/4] openat2: new OPENAT2_REGULAR flag support
  2026-04-16 13:52   ` Jori Koolstra
@ 2026-04-16 14:21     ` Dorjoy Chowdhury
  2026-04-16 15:03       ` Jori Koolstra
  2026-04-16 15:15       ` Aleksa Sarai
  0 siblings, 2 replies; 23+ messages in thread
From: Dorjoy Chowdhury @ 2026-04-16 14:21 UTC (permalink / raw)
  To: Jori Koolstra, Dorjoy Chowdhury, linux-fsdevel, linux-kernel,
	linux-api, ceph-devel, gfs2, linux-nfs, linux-cifs, v9fs,
	linux-kselftest, viro, brauner, jack, jlayton, chuck.lever,
	alex.aring, arnd, adilger, mjguzik, smfrench, richard.henderson,
	mattst88, linmag7, tsbogend, James.Bottomley, deller, davem,
	andreas, idryomov, amarkuze, slava, agruenba, trondmy, anna,
	sfrench, pc, ronniesahlberg, sprasad, tom, bharathsm, shuah,
	miklos, hansg

On Thu, Apr 16, 2026 at 7:52 PM Jori Koolstra <jkoolstra@xs4all.nl> wrote:
>
> On Sat, Mar 28, 2026 at 11:22:22PM +0600, Dorjoy Chowdhury wrote:
> > diff --git a/arch/alpha/include/uapi/asm/fcntl.h b/arch/alpha/include/uapi/asm/fcntl.h
> > index 50bdc8e8a271..fe488bf7c18e 100644
> > --- a/arch/alpha/include/uapi/asm/fcntl.h
> > +++ b/arch/alpha/include/uapi/asm/fcntl.h
> > @@ -34,6 +34,7 @@
> >
> >  #define O_PATH               040000000
> >  #define __O_TMPFILE  0100000000
> > +#define OPENAT2_REGULAR      0200000000
> >
>
> I don't quite understand why we are adding OPENAT2_REGULAR inside the
> O_* flag range. Wasn't this supposed to be only supported for openat2()?
> If so, I don't see the need to waste an O_* flag bit. But maybe I am
> missing something.
>

Yes, OPENAT2_REGULAR is only supported for openat2. I am not sure if I
got a specific review to not add OPENAT2_REGULAR in the O_* flag 32
bit range. But as far as I understand, for the old open system calls
we can't easily add new O_* flags as the older codepaths don't strip
off unknown bits which openat2 does. It's not easy to add new O_*
flags for the old open system calls since that could break userspace
programs. So I guess it's okay to add OPENAT2_REGULAR in the 32 bits
range anyway? (Also lots of code paths take 32bit flags param right
now and those would need changing to take uint64_t instead but this is
of course not a reason to not add the new flag outside of the 32
bits).

Regards,
Dorjoy

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

* Re: [PATCH v6 1/4] openat2: new OPENAT2_REGULAR flag support
  2026-04-16 14:21     ` Dorjoy Chowdhury
@ 2026-04-16 15:03       ` Jori Koolstra
  2026-04-16 15:15         ` Christian Brauner
  2026-04-16 15:15       ` Aleksa Sarai
  1 sibling, 1 reply; 23+ messages in thread
From: Jori Koolstra @ 2026-04-16 15:03 UTC (permalink / raw)
  To: Dorjoy Chowdhury, linux-fsdevel, linux-kernel, linux-api,
	ceph-devel, gfs2, linux-nfs, linux-cifs, v9fs, linux-kselftest,
	viro, brauner, jack, jlayton, chuck.lever, alex.aring, arnd,
	adilger, mjguzik, smfrench, richard.henderson, mattst88, linmag7,
	tsbogend, James.Bottomley, deller, davem, andreas, idryomov,
	amarkuze, slava, agruenba, trondmy, anna, sfrench, pc,
	ronniesahlberg, sprasad, tom, bharathsm, shuah, miklos, hansg,
	Aleksa Sarai


> Op 16-04-2026 16:21 CEST schreef Dorjoy Chowdhury <dorjoychy111@gmail.com>:
> 
>  
> On Thu, Apr 16, 2026 at 7:52 PM Jori Koolstra <jkoolstra@xs4all.nl> wrote:
> >
> > On Sat, Mar 28, 2026 at 11:22:22PM +0600, Dorjoy Chowdhury wrote:
> > > diff --git a/arch/alpha/include/uapi/asm/fcntl.h b/arch/alpha/include/uapi/asm/fcntl.h
> > > index 50bdc8e8a271..fe488bf7c18e 100644
> > > --- a/arch/alpha/include/uapi/asm/fcntl.h
> > > +++ b/arch/alpha/include/uapi/asm/fcntl.h
> > > @@ -34,6 +34,7 @@
> > >
> > >  #define O_PATH               040000000
> > >  #define __O_TMPFILE  0100000000
> > > +#define OPENAT2_REGULAR      0200000000
> > >
> >
> > I don't quite understand why we are adding OPENAT2_REGULAR inside the
> > O_* flag range. Wasn't this supposed to be only supported for openat2()?
> > If so, I don't see the need to waste an O_* flag bit. But maybe I am
> > missing something.
> >
> 
> Yes, OPENAT2_REGULAR is only supported for openat2. I am not sure if I
> got a specific review to not add OPENAT2_REGULAR in the O_* flag 32
> bit range. But as far as I understand, for the old open system calls
> we can't easily add new O_* flags as the older codepaths don't strip
> off unknown bits which openat2 does. It's not easy to add new O_*
> flags for the old open system calls since that could break userspace
> programs.

If I recall correctly, Aleksa has suggested we might also want to add
O_EMPTYPATH to openat() instead of only allowing this for openat2().
I am waiting to see what Christian thinks of this.

I guess in that case it is relatively harmless to change UAPI
behavior because openat() with an empty path never works; so it
would be silly if there are userspace programs that make
this call, which always fails and does nothing, and somehow rely on
that.

> So I guess it's okay to add OPENAT2_REGULAR in the 32 bits
> range anyway? (Also lots of code paths take 32bit flags param right
> now and those would need changing to take uint64_t instead but this is
> of course not a reason to not add the new flag outside of the 32
> bits).
> 
> Regards,
> Dorjoy

Thanks,
Jori.

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

* Re: [PATCH v6 1/4] openat2: new OPENAT2_REGULAR flag support
  2026-04-16 14:21     ` Dorjoy Chowdhury
  2026-04-16 15:03       ` Jori Koolstra
@ 2026-04-16 15:15       ` Aleksa Sarai
  1 sibling, 0 replies; 23+ messages in thread
From: Aleksa Sarai @ 2026-04-16 15:15 UTC (permalink / raw)
  To: Dorjoy Chowdhury
  Cc: Jori Koolstra, linux-fsdevel, linux-kernel, linux-api, ceph-devel,
	gfs2, linux-nfs, linux-cifs, v9fs, linux-kselftest, viro, brauner,
	jack, jlayton, chuck.lever, alex.aring, arnd, adilger, mjguzik,
	smfrench, richard.henderson, mattst88, linmag7, tsbogend,
	James.Bottomley, deller, davem, andreas, idryomov, amarkuze,
	slava, agruenba, trondmy, anna, sfrench, pc, ronniesahlberg,
	sprasad, tom, bharathsm, shuah, miklos, hansg

[-- Attachment #1: Type: text/plain, Size: 2304 bytes --]

On 2026-04-16, Dorjoy Chowdhury <dorjoychy111@gmail.com> wrote:
> On Thu, Apr 16, 2026 at 7:52 PM Jori Koolstra <jkoolstra@xs4all.nl> wrote:
> >
> > On Sat, Mar 28, 2026 at 11:22:22PM +0600, Dorjoy Chowdhury wrote:
> > > diff --git a/arch/alpha/include/uapi/asm/fcntl.h b/arch/alpha/include/uapi/asm/fcntl.h
> > > index 50bdc8e8a271..fe488bf7c18e 100644
> > > --- a/arch/alpha/include/uapi/asm/fcntl.h
> > > +++ b/arch/alpha/include/uapi/asm/fcntl.h
> > > @@ -34,6 +34,7 @@
> > >
> > >  #define O_PATH               040000000
> > >  #define __O_TMPFILE  0100000000
> > > +#define OPENAT2_REGULAR      0200000000
> > >
> >
> > I don't quite understand why we are adding OPENAT2_REGULAR inside the
> > O_* flag range. Wasn't this supposed to be only supported for openat2()?
> > If so, I don't see the need to waste an O_* flag bit. But maybe I am
> > missing something.
> >
> 
> Yes, OPENAT2_REGULAR is only supported for openat2. I am not sure if I
> got a specific review to not add OPENAT2_REGULAR in the O_* flag 32
> bit range. But as far as I understand, for the old open system calls
> we can't easily add new O_* flags as the older codepaths don't strip
> off unknown bits which openat2 does. It's not easy to add new O_*
> flags for the old open system calls since that could break userspace
> programs. So I guess it's okay to add OPENAT2_REGULAR in the 32 bits
> range anyway? (Also lots of code paths take 32bit flags param right
> now and those would need changing to take uint64_t instead but this is
> of course not a reason to not add the new flag outside of the 32
> bits).

Oh, I didn't notice that this wasn't mentioned here, we had a separate
discussion about it in a thread with Jori and I must've assumed we
discussed it in both. (My brain is also really not wired up to read
large octal values easily.)

While it is hard to add new O_* flags (hence OPENAT2_REGULAR), it's not
/impossible/ (Jori has a patch for OPENAT2_EMPTY_PATH that is safe to
add to O_* flags because of some fun historical coincidences).

I would have a slight preference towards segregating the bits, ideally
at the top end but even 1<<31 would've been nice. Then again, I'm not
too fussed either way to be honest...

-- 
Aleksa Sarai
https://www.cyphar.com/

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 265 bytes --]

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

* Re: [PATCH v6 1/4] openat2: new OPENAT2_REGULAR flag support
  2026-04-16 15:03       ` Jori Koolstra
@ 2026-04-16 15:15         ` Christian Brauner
  0 siblings, 0 replies; 23+ messages in thread
From: Christian Brauner @ 2026-04-16 15:15 UTC (permalink / raw)
  To: Jori Koolstra
  Cc: Dorjoy Chowdhury, linux-fsdevel, linux-kernel, linux-api,
	ceph-devel, gfs2, linux-nfs, linux-cifs, v9fs, linux-kselftest,
	viro, jack, jlayton, chuck.lever, alex.aring, arnd, adilger,
	mjguzik, smfrench, richard.henderson, mattst88, linmag7, tsbogend,
	James.Bottomley, deller, davem, andreas, idryomov, amarkuze,
	slava, agruenba, trondmy, anna, sfrench, pc, ronniesahlberg,
	sprasad, tom, bharathsm, shuah, miklos, hansg, Aleksa Sarai

On Thu, Apr 16, 2026 at 05:03:26PM +0200, Jori Koolstra wrote:
> 
> > Op 16-04-2026 16:21 CEST schreef Dorjoy Chowdhury <dorjoychy111@gmail.com>:
> > 
> >  
> > On Thu, Apr 16, 2026 at 7:52 PM Jori Koolstra <jkoolstra@xs4all.nl> wrote:
> > >
> > > On Sat, Mar 28, 2026 at 11:22:22PM +0600, Dorjoy Chowdhury wrote:
> > > > diff --git a/arch/alpha/include/uapi/asm/fcntl.h b/arch/alpha/include/uapi/asm/fcntl.h
> > > > index 50bdc8e8a271..fe488bf7c18e 100644
> > > > --- a/arch/alpha/include/uapi/asm/fcntl.h
> > > > +++ b/arch/alpha/include/uapi/asm/fcntl.h
> > > > @@ -34,6 +34,7 @@
> > > >
> > > >  #define O_PATH               040000000
> > > >  #define __O_TMPFILE  0100000000
> > > > +#define OPENAT2_REGULAR      0200000000
> > > >
> > >
> > > I don't quite understand why we are adding OPENAT2_REGULAR inside the
> > > O_* flag range. Wasn't this supposed to be only supported for openat2()?
> > > If so, I don't see the need to waste an O_* flag bit. But maybe I am
> > > missing something.
> > >
> > 
> > Yes, OPENAT2_REGULAR is only supported for openat2. I am not sure if I
> > got a specific review to not add OPENAT2_REGULAR in the O_* flag 32
> > bit range. But as far as I understand, for the old open system calls
> > we can't easily add new O_* flags as the older codepaths don't strip
> > off unknown bits which openat2 does. It's not easy to add new O_*
> > flags for the old open system calls since that could break userspace
> > programs.
> 
> If I recall correctly, Aleksa has suggested we might also want to add
> O_EMPTYPATH to openat() instead of only allowing this for openat2().
> I am waiting to see what Christian thinks of this.

We can do that, yes. For O_EMPTYPATH that is workable.

I don't mind too much if we leave OPENAT2_REGUALR in the 32-bit flag
space. It'll silently be ignored but the flag name should give it away.

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

* Re: [PATCH v6 0/4] OPENAT2_REGULAR flag support for openat2
  2026-04-16 13:07 ` [PATCH v6 0/4] OPENAT2_REGULAR flag support for openat2 Christian Brauner
@ 2026-04-16 15:22   ` Dorjoy Chowdhury
  0 siblings, 0 replies; 23+ messages in thread
From: Dorjoy Chowdhury @ 2026-04-16 15:22 UTC (permalink / raw)
  To: Christian Brauner
  Cc: linux-fsdevel, linux-kernel, linux-api, ceph-devel, gfs2,
	linux-nfs, linux-cifs, v9fs, linux-kselftest, viro, jack, jlayton,
	chuck.lever, alex.aring, arnd, adilger, mjguzik, smfrench,
	richard.henderson, mattst88, linmag7, tsbogend, James.Bottomley,
	deller, davem, andreas, idryomov, amarkuze, slava, agruenba,
	trondmy, anna, sfrench, pc, ronniesahlberg, sprasad, tom,
	bharathsm, shuah, miklos, hansg

On Thu, Apr 16, 2026 at 7:07 PM Christian Brauner <brauner@kernel.org> wrote:
>
> On Sat, 28 Mar 2026 23:22:21 +0600, Dorjoy Chowdhury wrote:
> > I came upon this "Ability to only open regular files" uapi feature suggestion
> > from https://uapi-group.org/kernel-features/#ability-to-only-open-regular-files
> > and thought it would be something I could do as a first patch and get to
> > know the kernel code a bit better.
> >
> > The following filesystems have been tested by building and booting the kernel
> > x86 bzImage in a Fedora 43 VM in QEMU. I have tested with OPENAT2_REGULAR that
> > regular files can be successfully opened and non-regular files (directory, fifo etc)
> > return -EFTYPE.
> > - btrfs
> > - NFS (loopback)
> > - SMB (loopback)
> >
> > [...]
>
> - I've added an explanation why OPENAT2_REGULAR is only needed for some
>   ->atomic_open() implementers but not others. What I don't like is that
>   we need all that custom handling in there but it's managable.
>
> - I dropped the topmost style conversions. They really don't belong
>   there and if we switch to something better we should use (1 << <nr>).
>
> - I split the EFTYPE errno introduction into a separate patch.
>
> ---

Thanks for fixing up and picking this one up!

>
> Applied to the vfs-7.2.openat.regular branch of the vfs/vfs.git tree.
> Patches in the vfs-7.2.openat.regular branch should appear in linux-next soon.
>

I don't see a vfs-7.2.openat.regular branch in vfs/vfs.git tree in
git.kernel.org.  Maybe this hasn't been pushed yet?

> Please report any outstanding bugs that were missed during review in a
> new review to the original patch series allowing us to drop it.
>
> It's encouraged to provide Acked-bys and Reviewed-bys even though the
> patch has now been applied. If possible patch trailers will be updated.
>
> Note that commit hashes shown below are subject to change due to rebase,
> trailer updates or similar. If in doubt, please check the listed branch.
>
> tree:   https://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs.git
> branch: master
>

I guess you wanted to mean vfs-7.2.openat.regular here?

Regards,
Dorjoy

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

end of thread, other threads:[~2026-04-16 15:22 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-28 17:22 [PATCH v6 0/4] OPENAT2_REGULAR flag support for openat2 Dorjoy Chowdhury
2026-03-28 17:22 ` [PATCH v6 1/4] openat2: new OPENAT2_REGULAR flag support Dorjoy Chowdhury
2026-03-30 11:49   ` Jeff Layton
2026-03-30 15:07     ` Dorjoy Chowdhury
2026-04-01 19:02       ` Jeff Layton
2026-04-04 15:17         ` Dorjoy Chowdhury
2026-04-05 23:27           ` Jeff Layton
2026-04-06 15:30             ` Dorjoy Chowdhury
2026-04-14 17:33               ` Dorjoy Chowdhury
2026-04-16 11:41   ` Aleksa Sarai
2026-04-16 11:58     ` Dorjoy Chowdhury
2026-04-16 13:05       ` Aleksa Sarai
2026-04-16 13:28         ` Jeff Layton
2026-04-16 13:52   ` Jori Koolstra
2026-04-16 14:21     ` Dorjoy Chowdhury
2026-04-16 15:03       ` Jori Koolstra
2026-04-16 15:15         ` Christian Brauner
2026-04-16 15:15       ` Aleksa Sarai
2026-03-28 17:22 ` [PATCH v6 2/4] kselftest/openat2: test for OPENAT2_REGULAR flag Dorjoy Chowdhury
2026-03-28 17:22 ` [PATCH v6 3/4] sparc/fcntl.h: convert O_* flag macros from hex to octal Dorjoy Chowdhury
2026-03-28 17:22 ` [PATCH v6 4/4] mips/fcntl.h: " Dorjoy Chowdhury
2026-04-16 13:07 ` [PATCH v6 0/4] OPENAT2_REGULAR flag support for openat2 Christian Brauner
2026-04-16 15:22   ` Dorjoy Chowdhury

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox