]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
Add RPC language definition of NFSv4 POSIX ACL extension
authorChuck Lever <chuck.lever@oracle.com>
Fri, 9 Jan 2026 16:21:32 +0000 (11:21 -0500)
committerChuck Lever <chuck.lever@oracle.com>
Thu, 29 Jan 2026 14:48:33 +0000 (09:48 -0500)
The language definition was extracted from the new
draft-ietf-nfsv4-posix-acls specification. This ensures good
constant and type name alignment between the spec and the Linux
kernel source code, and brings in some basic XDR utilities for
handling NFSv4 POSIX draft ACLs.

Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Documentation/sunrpc/xdr/nfs4_1.x
fs/nfsd/nfs4xdr_gen.c
fs/nfsd/nfs4xdr_gen.h
include/linux/nfs4.h
include/linux/sunrpc/xdrgen/nfs4_1.h

index ca95150a3a29fc5418991bf2395326bd73645ea8..5b45547b2ebc854d726ff34927087331c4d121ab 100644 (file)
@@ -53,6 +53,11 @@ typedef unsigned int uint32_t;
  */
 typedef uint32_t       bitmap4<>;
 
+typedef opaque         utf8string<>;
+typedef utf8string     utf8str_cis;
+typedef utf8string     utf8str_cs;
+typedef utf8string     utf8str_mixed;
+
 /*
  * Timeval
  */
@@ -184,3 +189,59 @@ enum open_delegation_type4 {
        OPEN_DELEGATE_READ_ATTRS_DELEG      = 4,
        OPEN_DELEGATE_WRITE_ATTRS_DELEG     = 5
 };
+
+
+/*
+ * The following content was extracted from draft-ietf-nfsv4-posix-acls
+ */
+
+enum aclmodel4 {
+       ACL_MODEL_NFS4          = 1,
+       ACL_MODEL_POSIX_DRAFT   = 2,
+       ACL_MODEL_NONE          = 3
+};
+pragma public aclmodel4;
+
+enum aclscope4 {
+       ACL_SCOPE_FILE_OBJECT   = 1,
+       ACL_SCOPE_FILE_SYSTEM   = 2,
+       ACL_SCOPE_SERVER        = 3
+};
+pragma public aclscope4;
+
+enum posixacetag4 {
+       POSIXACE4_TAG_USER_OBJ  = 1,
+       POSIXACE4_TAG_USER      = 2,
+       POSIXACE4_TAG_GROUP_OBJ = 3,
+       POSIXACE4_TAG_GROUP     = 4,
+       POSIXACE4_TAG_MASK      = 5,
+       POSIXACE4_TAG_OTHER     = 6
+};
+pragma public posixacetag4;
+
+typedef uint32_t       posixaceperm4;
+pragma public posixaceperm4;
+
+/* Bit definitions for posixaceperm4. */
+const POSIXACE4_PERM_EXECUTE   = 0x00000001;
+const POSIXACE4_PERM_WRITE     = 0x00000002;
+const POSIXACE4_PERM_READ      = 0x00000004;
+
+struct posixace4 {
+       posixacetag4            tag;
+       posixaceperm4           perm;
+       utf8str_mixed           who;
+};
+
+typedef aclmodel4      fattr4_acl_trueform;
+typedef aclscope4      fattr4_acl_trueform_scope;
+typedef posixace4      fattr4_posix_default_acl<>;
+typedef posixace4      fattr4_posix_access_acl<>;
+
+%/*
+% * New for POSIX ACL extension
+% */
+const FATTR4_ACL_TRUEFORM      = 89;
+const FATTR4_ACL_TRUEFORM_SCOPE        = 90;
+const FATTR4_POSIX_DEFAULT_ACL = 91;
+const FATTR4_POSIX_ACCESS_ACL  = 92;
index ce5c36e9070a6eabf9abeede1690160ffffb0c6a..824497051b876a51c578c13b7ffd99f14334c376 100644 (file)
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 // Generated by xdrgen. Manual edits will be lost.
 // XDR specification file: ../../Documentation/sunrpc/xdr/nfs4_1.x
-// XDR specification modification time: Thu Jan  8 23:11:48 2026
+// XDR specification modification time: Thu Jan  8 23:12:07 2026
 
 #include <linux/sunrpc/svc.h>
 
@@ -30,6 +30,30 @@ xdrgen_decode_bitmap4(struct xdr_stream *xdr, bitmap4 *ptr)
        return true;
 }
 
+static bool __maybe_unused
+xdrgen_decode_utf8string(struct xdr_stream *xdr, utf8string *ptr)
+{
+       return xdrgen_decode_opaque(xdr, ptr, 0);
+}
+
+static bool __maybe_unused
+xdrgen_decode_utf8str_cis(struct xdr_stream *xdr, utf8str_cis *ptr)
+{
+       return xdrgen_decode_utf8string(xdr, ptr);
+}
+
+static bool __maybe_unused
+xdrgen_decode_utf8str_cs(struct xdr_stream *xdr, utf8str_cs *ptr)
+{
+       return xdrgen_decode_utf8string(xdr, ptr);
+}
+
+static bool __maybe_unused
+xdrgen_decode_utf8str_mixed(struct xdr_stream *xdr, utf8str_mixed *ptr)
+{
+       return xdrgen_decode_utf8string(xdr, ptr);
+}
+
 static bool __maybe_unused
 xdrgen_decode_nfstime4(struct xdr_stream *xdr, struct nfstime4 *ptr)
 {
@@ -222,6 +246,125 @@ xdrgen_decode_open_delegation_type4(struct xdr_stream *xdr, open_delegation_type
        return true;
 }
 
+bool
+xdrgen_decode_aclmodel4(struct xdr_stream *xdr, aclmodel4 *ptr)
+{
+       u32 val;
+
+       if (xdr_stream_decode_u32(xdr, &val) < 0)
+               return false;
+       /* Compiler may optimize to a range check for dense enums */
+       switch (val) {
+       case ACL_MODEL_NFS4:
+       case ACL_MODEL_POSIX_DRAFT:
+       case ACL_MODEL_NONE:
+               break;
+       default:
+               return false;
+       }
+       *ptr = val;
+       return true;
+}
+
+bool
+xdrgen_decode_aclscope4(struct xdr_stream *xdr, aclscope4 *ptr)
+{
+       u32 val;
+
+       if (xdr_stream_decode_u32(xdr, &val) < 0)
+               return false;
+       /* Compiler may optimize to a range check for dense enums */
+       switch (val) {
+       case ACL_SCOPE_FILE_OBJECT:
+       case ACL_SCOPE_FILE_SYSTEM:
+       case ACL_SCOPE_SERVER:
+               break;
+       default:
+               return false;
+       }
+       *ptr = val;
+       return true;
+}
+
+bool
+xdrgen_decode_posixacetag4(struct xdr_stream *xdr, posixacetag4 *ptr)
+{
+       u32 val;
+
+       if (xdr_stream_decode_u32(xdr, &val) < 0)
+               return false;
+       /* Compiler may optimize to a range check for dense enums */
+       switch (val) {
+       case POSIXACE4_TAG_USER_OBJ:
+       case POSIXACE4_TAG_USER:
+       case POSIXACE4_TAG_GROUP_OBJ:
+       case POSIXACE4_TAG_GROUP:
+       case POSIXACE4_TAG_MASK:
+       case POSIXACE4_TAG_OTHER:
+               break;
+       default:
+               return false;
+       }
+       *ptr = val;
+       return true;
+}
+
+bool
+xdrgen_decode_posixaceperm4(struct xdr_stream *xdr, posixaceperm4 *ptr)
+{
+       return xdrgen_decode_uint32_t(xdr, ptr);
+}
+
+static bool __maybe_unused
+xdrgen_decode_posixace4(struct xdr_stream *xdr, struct posixace4 *ptr)
+{
+       if (!xdrgen_decode_posixacetag4(xdr, &ptr->tag))
+               return false;
+       if (!xdrgen_decode_posixaceperm4(xdr, &ptr->perm))
+               return false;
+       if (!xdrgen_decode_utf8str_mixed(xdr, &ptr->who))
+               return false;
+       return true;
+}
+
+static bool __maybe_unused
+xdrgen_decode_fattr4_acl_trueform(struct xdr_stream *xdr, fattr4_acl_trueform *ptr)
+{
+       return xdrgen_decode_aclmodel4(xdr, ptr);
+}
+
+static bool __maybe_unused
+xdrgen_decode_fattr4_acl_trueform_scope(struct xdr_stream *xdr, fattr4_acl_trueform_scope *ptr)
+{
+       return xdrgen_decode_aclscope4(xdr, ptr);
+}
+
+static bool __maybe_unused
+xdrgen_decode_fattr4_posix_default_acl(struct xdr_stream *xdr, fattr4_posix_default_acl *ptr)
+{
+       if (xdr_stream_decode_u32(xdr, &ptr->count) < 0)
+               return false;
+       for (u32 i = 0; i < ptr->count; i++)
+               if (!xdrgen_decode_posixace4(xdr, &ptr->element[i]))
+                       return false;
+       return true;
+}
+
+static bool __maybe_unused
+xdrgen_decode_fattr4_posix_access_acl(struct xdr_stream *xdr, fattr4_posix_access_acl *ptr)
+{
+       if (xdr_stream_decode_u32(xdr, &ptr->count) < 0)
+               return false;
+       for (u32 i = 0; i < ptr->count; i++)
+               if (!xdrgen_decode_posixace4(xdr, &ptr->element[i]))
+                       return false;
+       return true;
+}
+
+/*
+ * New for POSIX ACL extension
+ */
+
 static bool __maybe_unused
 xdrgen_encode_int64_t(struct xdr_stream *xdr, const int64_t value)
 {
@@ -245,6 +388,30 @@ xdrgen_encode_bitmap4(struct xdr_stream *xdr, const bitmap4 value)
        return true;
 }
 
+static bool __maybe_unused
+xdrgen_encode_utf8string(struct xdr_stream *xdr, const utf8string value)
+{
+       return xdr_stream_encode_opaque(xdr, value.data, value.len) >= 0;
+}
+
+static bool __maybe_unused
+xdrgen_encode_utf8str_cis(struct xdr_stream *xdr, const utf8str_cis value)
+{
+       return xdrgen_encode_utf8string(xdr, value);
+}
+
+static bool __maybe_unused
+xdrgen_encode_utf8str_cs(struct xdr_stream *xdr, const utf8str_cs value)
+{
+       return xdrgen_encode_utf8string(xdr, value);
+}
+
+static bool __maybe_unused
+xdrgen_encode_utf8str_mixed(struct xdr_stream *xdr, const utf8str_mixed value)
+{
+       return xdrgen_encode_utf8string(xdr, value);
+}
+
 static bool __maybe_unused
 xdrgen_encode_nfstime4(struct xdr_stream *xdr, const struct nfstime4 *value)
 {
@@ -330,3 +497,73 @@ xdrgen_encode_open_delegation_type4(struct xdr_stream *xdr, open_delegation_type
 {
        return xdr_stream_encode_u32(xdr, value) == XDR_UNIT;
 }
+
+bool
+xdrgen_encode_aclmodel4(struct xdr_stream *xdr, aclmodel4 value)
+{
+       return xdr_stream_encode_u32(xdr, value) == XDR_UNIT;
+}
+
+bool
+xdrgen_encode_aclscope4(struct xdr_stream *xdr, aclscope4 value)
+{
+       return xdr_stream_encode_u32(xdr, value) == XDR_UNIT;
+}
+
+bool
+xdrgen_encode_posixacetag4(struct xdr_stream *xdr, posixacetag4 value)
+{
+       return xdr_stream_encode_u32(xdr, value) == XDR_UNIT;
+}
+
+bool
+xdrgen_encode_posixaceperm4(struct xdr_stream *xdr, const posixaceperm4 value)
+{
+       return xdrgen_encode_uint32_t(xdr, value);
+}
+
+static bool __maybe_unused
+xdrgen_encode_posixace4(struct xdr_stream *xdr, const struct posixace4 *value)
+{
+       if (!xdrgen_encode_posixacetag4(xdr, value->tag))
+               return false;
+       if (!xdrgen_encode_posixaceperm4(xdr, value->perm))
+               return false;
+       if (!xdrgen_encode_utf8str_mixed(xdr, value->who))
+               return false;
+       return true;
+}
+
+static bool __maybe_unused
+xdrgen_encode_fattr4_acl_trueform(struct xdr_stream *xdr, const fattr4_acl_trueform value)
+{
+       return xdrgen_encode_aclmodel4(xdr, value);
+}
+
+static bool __maybe_unused
+xdrgen_encode_fattr4_acl_trueform_scope(struct xdr_stream *xdr, const fattr4_acl_trueform_scope value)
+{
+       return xdrgen_encode_aclscope4(xdr, value);
+}
+
+static bool __maybe_unused
+xdrgen_encode_fattr4_posix_default_acl(struct xdr_stream *xdr, const fattr4_posix_default_acl value)
+{
+       if (xdr_stream_encode_u32(xdr, value.count) != XDR_UNIT)
+               return false;
+       for (u32 i = 0; i < value.count; i++)
+               if (!xdrgen_encode_posixace4(xdr, &value.element[i]))
+                       return false;
+       return true;
+}
+
+static bool __maybe_unused
+xdrgen_encode_fattr4_posix_access_acl(struct xdr_stream *xdr, const fattr4_posix_access_acl value)
+{
+       if (xdr_stream_encode_u32(xdr, value.count) != XDR_UNIT)
+               return false;
+       for (u32 i = 0; i < value.count; i++)
+               if (!xdrgen_encode_posixace4(xdr, &value.element[i]))
+                       return false;
+       return true;
+}
index 8dfe10246506e37be3ac7d3fbf017b109b674fad..1c487f1a11ab2f0d94b24342f17c5f4df361dbe3 100644 (file)
@@ -1,7 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /* Generated by xdrgen. Manual edits will be lost. */
 /* XDR specification file: ../../Documentation/sunrpc/xdr/nfs4_1.x */
-/* XDR specification modification time: Thu Jan  8 23:11:48 2026 */
+/* XDR specification modification time: Thu Jan  8 23:12:07 2026 */
 
 #ifndef _LINUX_XDRGEN_NFS4_1_DECL_H
 #define _LINUX_XDRGEN_NFS4_1_DECL_H
@@ -21,5 +21,15 @@ bool xdrgen_encode_fattr4_time_deleg_access(struct xdr_stream *xdr, const fattr4
 
 bool xdrgen_decode_fattr4_time_deleg_modify(struct xdr_stream *xdr, fattr4_time_deleg_modify *ptr);
 bool xdrgen_encode_fattr4_time_deleg_modify(struct xdr_stream *xdr, const fattr4_time_deleg_modify *value);
+bool xdrgen_decode_aclmodel4(struct xdr_stream *xdr, aclmodel4 *ptr);
+bool xdrgen_encode_aclmodel4(struct xdr_stream *xdr, aclmodel4 value);
+bool xdrgen_decode_aclscope4(struct xdr_stream *xdr, aclscope4 *ptr);
+bool xdrgen_encode_aclscope4(struct xdr_stream *xdr, aclscope4 value);
+bool xdrgen_decode_posixacetag4(struct xdr_stream *xdr, posixacetag4 *ptr);
+bool xdrgen_encode_posixacetag4(struct xdr_stream *xdr, posixacetag4 value);
+
+bool xdrgen_decode_posixaceperm4(struct xdr_stream *xdr, posixaceperm4 *ptr);
+bool xdrgen_encode_posixaceperm4(struct xdr_stream *xdr, const posixaceperm4 value);
+
 
 #endif /* _LINUX_XDRGEN_NFS4_1_DECL_H */
index e947af6a3684a4ae4abedbc56ff1811d15c23f3c..d87be1f25273a7f415a9e7d6c1850bece7269c09 100644 (file)
@@ -598,6 +598,10 @@ enum {
 #define FATTR4_WORD2_TIME_DELEG_ACCESS BIT(FATTR4_TIME_DELEG_ACCESS - 64)
 #define FATTR4_WORD2_TIME_DELEG_MODIFY BIT(FATTR4_TIME_DELEG_MODIFY - 64)
 #define FATTR4_WORD2_OPEN_ARGUMENTS    BIT(FATTR4_OPEN_ARGUMENTS - 64)
+#define FATTR4_WORD2_ACL_TRUEFORM      BIT(FATTR4_ACL_TRUEFORM - 64)
+#define FATTR4_WORD2_ACL_TRUEFORM_SCOPE        BIT(FATTR4_ACL_TRUEFORM_SCOPE - 64)
+#define FATTR4_WORD2_POSIX_DEFAULT_ACL BIT(FATTR4_POSIX_DEFAULT_ACL - 64)
+#define FATTR4_WORD2_POSIX_ACCESS_ACL  BIT(FATTR4_POSIX_ACCESS_ACL - 64)
 
 /* MDS threshold bitmap bits */
 #define THRESHOLD_RD                    (1UL << 0)
index 5283739242c72b591b3743a28ce5e58100bcd943..4ac54bdbd335b93dd82d6d0877775c81e32b8ee2 100644 (file)
@@ -1,7 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /* Generated by xdrgen. Manual edits will be lost. */
 /* XDR specification file: ../../Documentation/sunrpc/xdr/nfs4_1.x */
-/* XDR specification modification time: Thu Jan  8 23:11:48 2026 */
+/* XDR specification modification time: Thu Jan  8 23:12:07 2026 */
 
 #ifndef _LINUX_XDRGEN_NFS4_1_DEF_H
 #define _LINUX_XDRGEN_NFS4_1_DEF_H
@@ -18,6 +18,14 @@ typedef struct {
        uint32_t *element;
 } bitmap4;
 
+typedef opaque utf8string;
+
+typedef utf8string utf8str_cis;
+
+typedef utf8string utf8str_cs;
+
+typedef utf8string utf8str_mixed;
+
 struct nfstime4 {
        int64_t seconds;
        uint32_t nseconds;
@@ -141,11 +149,85 @@ enum open_delegation_type4 {
 
 typedef enum open_delegation_type4 open_delegation_type4;
 
+enum aclmodel4 {
+       ACL_MODEL_NFS4 = 1,
+       ACL_MODEL_POSIX_DRAFT = 2,
+       ACL_MODEL_NONE = 3,
+};
+
+typedef enum aclmodel4 aclmodel4;
+
+enum aclscope4 {
+       ACL_SCOPE_FILE_OBJECT = 1,
+       ACL_SCOPE_FILE_SYSTEM = 2,
+       ACL_SCOPE_SERVER = 3,
+};
+
+typedef enum aclscope4 aclscope4;
+
+enum posixacetag4 {
+       POSIXACE4_TAG_USER_OBJ = 1,
+       POSIXACE4_TAG_USER = 2,
+       POSIXACE4_TAG_GROUP_OBJ = 3,
+       POSIXACE4_TAG_GROUP = 4,
+       POSIXACE4_TAG_MASK = 5,
+       POSIXACE4_TAG_OTHER = 6,
+};
+
+typedef enum posixacetag4 posixacetag4;
+
+typedef uint32_t posixaceperm4;
+
+enum { POSIXACE4_PERM_EXECUTE = 0x00000001 };
+
+enum { POSIXACE4_PERM_WRITE = 0x00000002 };
+
+enum { POSIXACE4_PERM_READ = 0x00000004 };
+
+struct posixace4 {
+       posixacetag4 tag;
+       posixaceperm4 perm;
+       utf8str_mixed who;
+};
+
+typedef aclmodel4 fattr4_acl_trueform;
+
+typedef aclscope4 fattr4_acl_trueform_scope;
+
+typedef struct {
+       u32 count;
+       struct posixace4 *element;
+} fattr4_posix_default_acl;
+
+typedef struct {
+       u32 count;
+       struct posixace4 *element;
+} fattr4_posix_access_acl;
+
+/*
+ * New for POSIX ACL extension
+ */
+
+enum { FATTR4_ACL_TRUEFORM = 89 };
+
+enum { FATTR4_ACL_TRUEFORM_SCOPE = 90 };
+
+enum { FATTR4_POSIX_DEFAULT_ACL = 91 };
+
+enum { FATTR4_POSIX_ACCESS_ACL = 92 };
+
 #define NFS4_int64_t_sz                 \
        (XDR_hyper)
 #define NFS4_uint32_t_sz                \
        (XDR_unsigned_int)
 #define NFS4_bitmap4_sz                 (XDR_unsigned_int)
+#define NFS4_utf8string_sz              (XDR_unsigned_int)
+#define NFS4_utf8str_cis_sz             \
+       (NFS4_utf8string_sz)
+#define NFS4_utf8str_cs_sz              \
+       (NFS4_utf8string_sz)
+#define NFS4_utf8str_mixed_sz           \
+       (NFS4_utf8string_sz)
 #define NFS4_nfstime4_sz                \
        (NFS4_int64_t_sz + NFS4_uint32_t_sz)
 #define NFS4_fattr4_offline_sz          \
@@ -164,5 +246,18 @@ typedef enum open_delegation_type4 open_delegation_type4;
 #define NFS4_fattr4_time_deleg_modify_sz \
        (NFS4_nfstime4_sz)
 #define NFS4_open_delegation_type4_sz   (XDR_int)
+#define NFS4_aclmodel4_sz               (XDR_int)
+#define NFS4_aclscope4_sz               (XDR_int)
+#define NFS4_posixacetag4_sz            (XDR_int)
+#define NFS4_posixaceperm4_sz           \
+       (NFS4_uint32_t_sz)
+#define NFS4_posixace4_sz               \
+       (NFS4_posixacetag4_sz + NFS4_posixaceperm4_sz + NFS4_utf8str_mixed_sz)
+#define NFS4_fattr4_acl_trueform_sz     \
+       (NFS4_aclmodel4_sz)
+#define NFS4_fattr4_acl_trueform_scope_sz \
+       (NFS4_aclscope4_sz)
+#define NFS4_fattr4_posix_default_acl_sz (XDR_unsigned_int)
+#define NFS4_fattr4_posix_access_acl_sz (XDR_unsigned_int)
 
 #endif /* _LINUX_XDRGEN_NFS4_1_DEF_H */