Skip to main content

The Network File System Access Control List Protocol
draft-ietf-nfsv4-nfs-acl-05

Document Type Active Internet-Draft (nfsv4 WG)
Author Chuck Lever
Last updated 2026-09-15
Replaces draft-cel-nfsv4-nfs-acl
RFC stream Internet Engineering Task Force (IETF)
Intended RFC status (None)
Formats
Additional resources GitHub Repository
Mailing list discussion
Stream WG state WG Document
Document shepherd (None)
IESG IESG state I-D Exists
Consensus boilerplate Unknown
Telechat date (None)
Responsible AD (None)
Send notices to (None)
draft-ietf-nfsv4-nfs-acl-05
Network File System Version 4                              C. Lever, Ed.
Internet-Draft                                               Independent
Intended status: Informational                         15 September 2026
Expires: 19 March 2027

          The Network File System Access Control List Protocol
                      draft-ietf-nfsv4-nfs-acl-05

Abstract

   This Informational document describes the NFS_ACL protocol.  NFS_ACL
   is a legacy member of the Network File System family of protocols
   that NFS clients use to view and update Access Control Lists stored
   on an NFS version 2 or version 3 server.

About This Document

   This note is to be removed before publishing as an RFC.

   The latest revision of this draft can be found at https://ietf-wg-
   nfsv4.github.io/i-d-nfs-acl/draft-ietf-nfsv4-nfs-acl.html.  Status
   information for this document may be found at
   https://datatracker.ietf.org/doc/draft-ietf-nfsv4-nfs-acl/.

   Discussion of this document takes place on the Network File System
   Version 4 Working Group mailing list (mailto:nfsv4@ietf.org), which
   is archived at https://mailarchive.ietf.org/arch/browse/nfsv4/.
   Subscribe at https://www.ietf.org/mailman/listinfo/nfsv4/.

   Source for this draft and an issue tracker can be found at
   https://github.com/ietf-wg-nfsv4/i-d-nfs-acl.

Status of This Memo

   This Internet-Draft is submitted in full conformance with the
   provisions of BCP 78 and BCP 79.

   Internet-Drafts are working documents of the Internet Engineering
   Task Force (IETF).  Note that other groups may also distribute
   working documents as Internet-Drafts.  The list of current Internet-
   Drafts is at https://datatracker.ietf.org/drafts/current/.

   Internet-Drafts are draft documents valid for a maximum of six months
   and may be updated, replaced, or obsoleted by other documents at any
   time.  It is inappropriate to use Internet-Drafts as reference
   material or to cite them other than as "work in progress."

Lever                     Expires 19 March 2027                 [Page 1]
Internet-Draft              NFS ACL Protocol              September 2026

   This Internet-Draft will expire on 19 March 2027.

Copyright Notice

   Copyright (c) 2026 IETF Trust and the persons identified as the
   document authors.  All rights reserved.

   This document is subject to BCP 78 and the IETF Trust's Legal
   Provisions Relating to IETF Documents (https://trustee.ietf.org/
   license-info) in effect on the date of publication of this document.
   Please review these documents carefully, as they describe your rights
   and restrictions with respect to this document.  Code Components
   extracted from this document must include Revised BSD License text as
   described in Section 4.e of the Trust Legal Provisions and are
   provided without warranty as described in the Revised BSD License.

   This document may contain material from IETF Documents or IETF
   Contributions published or made publicly available before November
   10, 2008.  The person(s) controlling the copyright in some of this
   material may not have granted the IETF Trust the right to allow
   modifications of such material outside the IETF Standards Process.
   Without obtaining an adequate license from the person(s) controlling
   the copyright in such materials, this document may not be modified
   outside the IETF Standards Process, and derivative works of it may
   not be created outside the IETF Standards Process, except to format
   it for publication as an RFC or to translate it into languages other
   than English.

Table of Contents

   1.  Introduction  . . . . . . . . . . . . . . . . . . . . . . . .   4
   2.  Conventions and Definitions . . . . . . . . . . . . . . . . .   5
     2.1.  Glossary  . . . . . . . . . . . . . . . . . . . . . . . .   5
   3.  General Concepts  . . . . . . . . . . . . . . . . . . . . . .   6
     3.1.  Remote Procedure Call . . . . . . . . . . . . . . . . . .   6
     3.2.  External Data Representation  . . . . . . . . . . . . . .   6
       3.2.1.  XDR Types Not Defined in RFC 4506 . . . . . . . . . .   6
     3.3.  Authentication and Authorization  . . . . . . . . . . . .   7
     3.4.  File Access Control . . . . . . . . . . . . . . . . . . .   8
       3.4.1.  File Ownership  . . . . . . . . . . . . . . . . . . .   8
       3.4.2.  Categories of Access  . . . . . . . . . . . . . . . .   9
       3.4.3.  Traditional Permission Bits . . . . . . . . . . . . .   9
       3.4.4.  Access Control Lists  . . . . . . . . . . . . . . . .   9
   4.  Protocol Elements Common to Both Versions . . . . . . . . . .  14
     4.1.  RPC Authentication  . . . . . . . . . . . . . . . . . . .  14
     4.2.  Constants . . . . . . . . . . . . . . . . . . . . . . . .  14
     4.3.  Transport address . . . . . . . . . . . . . . . . . . . .  14
     4.4.  Sizes . . . . . . . . . . . . . . . . . . . . . . . . . .  15

Lever                     Expires 19 March 2027                 [Page 2]
Internet-Draft              NFS ACL Protocol              September 2026

     4.5.  Basic Data Types  . . . . . . . . . . . . . . . . . . . .  15
     4.6.  Structured Data types . . . . . . . . . . . . . . . . . .  15
       4.6.1.  aclent  . . . . . . . . . . . . . . . . . . . . . . .  15
       4.6.2.  secattr . . . . . . . . . . . . . . . . . . . . . . .  16
       4.6.3.  Interoperability Considerations . . . . . . . . . . .  18
   5.  NFS_ACL Version 2 . . . . . . . . . . . . . . . . . . . . . .  19
     5.1.  Data types inherited from NFS version 2 . . . . . . . . .  19
       5.1.1.  ftype . . . . . . . . . . . . . . . . . . . . . . . .  19
       5.1.2.  fhandle . . . . . . . . . . . . . . . . . . . . . . .  19
       5.1.3.  timeval . . . . . . . . . . . . . . . . . . . . . . .  20
       5.1.4.  nfsfattr  . . . . . . . . . . . . . . . . . . . . . .  20
       5.1.5.  Defined Error Numbers . . . . . . . . . . . . . . . .  20
     5.2.  Server Procedures . . . . . . . . . . . . . . . . . . . .  22
       5.2.1.  Procedure 0: NULL - No Operation  . . . . . . . . . .  22
       5.2.2.  Procedure 1: GETACL - Retrieve an Access Control
               List  . . . . . . . . . . . . . . . . . . . . . . . .  23
       5.2.3.  Procedure 2: SETACL - Set or replace an Access Control
               List  . . . . . . . . . . . . . . . . . . . . . . . .  24
       5.2.4.  Procedure 3: GETATTR - Get file attributes  . . . . .  27
       5.2.5.  Procedure 4: ACCESS - Check access permission . . . .  28
       5.2.6.  Procedure 5: GETXATTRDIR - Get named attribute
               directory . . . . . . . . . . . . . . . . . . . . . .  30
   6.  NFS_ACL Version 3 . . . . . . . . . . . . . . . . . . . . . .  32
     6.1.  Data types inherited from NFS version 3 . . . . . . . . .  32
       6.1.1.  Scalar Data types . . . . . . . . . . . . . . . . . .  32
       6.1.2.  ftype3  . . . . . . . . . . . . . . . . . . . . . . .  33
       6.1.3.  specdata3 . . . . . . . . . . . . . . . . . . . . . .  33
       6.1.4.  nfs_fh3 . . . . . . . . . . . . . . . . . . . . . . .  33
       6.1.5.  nfstime3  . . . . . . . . . . . . . . . . . . . . . .  34
       6.1.6.  nfsfattr3 . . . . . . . . . . . . . . . . . . . . . .  34
       6.1.7.  post_op_attr  . . . . . . . . . . . . . . . . . . . .  35
     6.2.  Error Values  . . . . . . . . . . . . . . . . . . . . . .  35
     6.3.  Server Procedures . . . . . . . . . . . . . . . . . . . .  37
       6.3.1.  Procedure 0: NULL - No Operation  . . . . . . . . . .  37
       6.3.2.  Procedure 1: GETACL - Retrieve an Access Control
               List  . . . . . . . . . . . . . . . . . . . . . . . .  37
       6.3.3.  Procedure 2: SETACL - Set or replace an Access Control
               List  . . . . . . . . . . . . . . . . . . . . . . . .  39
       6.3.4.  Procedure 3: GETXATTRDIR - Get named attribute
               directory . . . . . . . . . . . . . . . . . . . . . .  42
   7.  Implementation Issues . . . . . . . . . . . . . . . . . . . .  44
     7.1.  Permission issues . . . . . . . . . . . . . . . . . . . .  44
     7.2.  Duplicate Request Cache . . . . . . . . . . . . . . . . .  45
     7.3.  Caching Policies  . . . . . . . . . . . . . . . . . . . .  46
   8.  XDR Protocol Definition . . . . . . . . . . . . . . . . . . .  46
     8.1.  Code Component License  . . . . . . . . . . . . . . . . .  47
     8.2.  NFS_ACL Version 2 . . . . . . . . . . . . . . . . . . . .  50
     8.3.  NFS_ACL Version 3 . . . . . . . . . . . . . . . . . . . .  54

Lever                     Expires 19 March 2027                 [Page 3]
Internet-Draft              NFS ACL Protocol              September 2026

   9.  Implementation Status . . . . . . . . . . . . . . . . . . . .  57
     9.1.  Solaris NFS server and client . . . . . . . . . . . . . .  58
     9.2.  Linux NFS server and client . . . . . . . . . . . . . . .  58
   10. Security Considerations . . . . . . . . . . . . . . . . . . .  59
     10.1.  Attacks on an Unprotected Exchange . . . . . . . . . . .  59
     10.2.  Protecting an Exchange . . . . . . . . . . . . . . . . .  60
     10.3.  Residual Risk  . . . . . . . . . . . . . . . . . . . . .  61
   11. IANA Considerations . . . . . . . . . . . . . . . . . . . . .  61
   12. References  . . . . . . . . . . . . . . . . . . . . . . . . .  61
     12.1.  Normative References . . . . . . . . . . . . . . . . . .  61
     12.2.  Informative References . . . . . . . . . . . . . . . . .  61
   Appendix A.  Source Material  . . . . . . . . . . . . . . . . . .  64
     A.1.  Redaction of NFS_ACL Version 4  . . . . . . . . . . . . .  64
     A.2.  Extension of NFS_ACL  . . . . . . . . . . . . . . . . . .  64
     A.3.  Code Compilation Requirements . . . . . . . . . . . . . .  64
   Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . . .  65
   Author's Address  . . . . . . . . . . . . . . . . . . . . . . . .  65

1.  Introduction

   The Network File System protocol (NFS) was introduced by Sun
   Microsystems in the 1980s.  This protocol enabled applications to
   access and modify files, via local POSIX system interfaces, that
   reside on a remote host [RFC1094].

   Traditionally, permission to access files stored in NFS file systems
   is granted by permission bits, mimicking [POSIX].  Permission bits
   provide coarse-grained access control.  The file owner can control
   only whether members of her group can read, write, or execute the
   file contents, or whether anyone else (without exception) has those
   rights.

   An Access Control List, or ACL, is a mechanism that enables file
   owners to grant specific users fine-grained access rights to file
   content [IEEE].

   Version 2 of NFS is described in [RFC1094], and version 3 in
   [RFC1813].  Neither of these protocols include a method for managing
   ACLs associated with files shared via the NFS protocol, even though
   the local file systems shared via NFS often implemented ACLs and gave
   local users mechanisms to read and update them.

   Sun created the NFS_ACL protocol to provide that mechanism for files
   accessed remotely via NFS.  Later, other operating systems, including
   Linux, implemented NFS_ACL for similar reasons.

Lever                     Expires 19 March 2027                 [Page 4]
Internet-Draft              NFS ACL Protocol              September 2026

   This document describes the protocol based on the nfs_acl.x file that
   is publicly available in the OpenSolaris code base [OpenSolaris].
   The editor has attempted to introduce no changes to the protocol as
   it is implemented in OpenSolaris and in Linux.

   The document assumes readers are already familiar with the NFS
   version 2 or 3 protocols and at least one implementation of them.

   Issues of compatibility between the protocol described in this
   document and NFSv4 ACLs (as described by [RFC8881]) are considered
   out of scope.  More information on this topic is available in
   [I-D.ietf-nfsv4-posix-acls].

   Local file systems on NFSv2 and NFSv3 servers determine the
   particular semantics of each Access Control List -- in other words,
   how the server uses each Access Control List to authorize access to
   file content.  This document serves only as a description of the
   network protocol used to exchange ACLs between NFS clients and
   servers.

2.  Conventions and Definitions

   As an Informational document, this RFC does not make compliance
   mandates on implementations of the protocol described herein.
   Therefore it does not make use of the conformance language described
   in BCP 14 [RFC2119] [RFC8174].  A capitalized key word that appears
   in text quoted from another document carries the meaning that
   document gives it.

2.1.  Glossary

   The following are a set of foundational terms used throughout this
   document.

   application:  A program that executes on a client system.

   client:  A computer system that utilizes compute resources provided
      by one or more servers.

   file:  A unit of data storage consisting of an ordered stream of
      bytes and a set of metadata attributes.

   gid:  A 32-bit unsigned integer that represents a group of users.

   server:  A computer system that provides compute resources to network
      peers.

   uid:  A 32-bit unsigned integer that represents a specific user.

Lever                     Expires 19 March 2027                 [Page 5]
Internet-Draft              NFS ACL Protocol              September 2026

   user:  A person logged in on a client system.

3.  General Concepts

3.1.  Remote Procedure Call

   The Sun Remote Procedure Call (SunRPC) protocol provides a procedure-
   oriented interface to remote services.  Each server supplies a
   program, which is a set of procedures.  The NFS service is one such
   program.  The combination of host address, program number, version
   number, and procedure number specify one remote service procedure.
   Servers can support multiple versions of a program that are accessed
   using different protocol version numbers.

   The NFS and NFS_ACL protocols are both based on SunRPC.  The
   remainder of this document assumes an NFS environment that is
   implemented on top of SunRPC, as it is specified in [RFC5531].

3.2.  External Data Representation

   The eXternal Data Representation (XDR) specification provides a
   standard way of representing a set of data types on a network.  XDR
   addresses the problem of communication between network peers with
   different byte orders, structure alignment, and data type
   representation.

   This document utilizes the RPC Data Description Language to specify
   the XDR format arguments and results to each of the RPC service
   procedures that an NFS_ACL server provides.

   Readers can find a full guide to XDR and the RPC Data Description
   Language in [RFC4506].

3.2.1.  XDR Types Not Defined in RFC 4506

   The original NFS_ACL RPC language specification uses the "unsigned
   short" and "unsigned long" types.  [RFC4506] describes neither,
   though most current implementations of the rpcgen program accept
   both.  This section describes the "unsigned short" and "unsigned
   long" integer types as used in this document, based on those
   implementations, so that the NFS_ACL RPC language specification
   appearing here accurately reflects the wire behavior of existing
   implementations.  It does not add these types to the RPC Data
   Description Language.

Lever                     Expires 19 March 2027                 [Page 6]
Internet-Draft              NFS ACL Protocol              September 2026

   The XDR wire representation of each of these types is a network-
   endian 32-bit integer.  This maintains XDR's consistent 4-octet
   alignment for all basic integer types while allowing applications to
   use narrower types internally.  The subsections below describe how a
   value of each type occupies that 32-bit field.

3.2.1.1.  unsigned short

   The unsigned short type is zero-extended, with the high-order two
   octets each containing zeroes on the wire.  The value range of this
   type is zero to 65,535, inclusive.

   Example: 0xFFFF (65535) appears as 0x0000FFFF on the wire.

3.2.1.2.  unsigned long

   The unsigned long type occupies all four octets of the 32-bit field
   and requires no extension.  Its wire representation is identical to
   that of the "unsigned int" type described in Section 4.2 of
   [RFC4506].  The value range of this type is zero to 4,294,967,295,
   inclusive.

   The NFS version 3 protocol specification [RFC1813] uses this type
   name for 32-bit unsigned quantities, and this document retains it in
   the data types that it inherits from that protocol.

3.3.  Authentication and Authorization

   The RPC protocol includes fields in every procedure call for user
   authentication parameters.  The specific content of the
   authentication parameters is determined by the type of authentication
   used by the server and client.  A discussion of the mechanics of RPC
   user authentication appears in [RFC5531], in particular Sections 9
   and 10.

   For NFS ACLs, the user ID carried in RPC calls is used for two
   purposes:

   *  When setting an ACL via the SETACL procedure, the NFS_ACL service
      verifies that the calling user has been granted permission to
      perform the procedure.  The GETACL procedure carries no such check
      of its own.  The server passes the calling user's credential to
      the local file system, which may or may not restrict who can read
      an object's ACL.

Lever                     Expires 19 March 2027                 [Page 7]
Internet-Draft              NFS ACL Protocol              September 2026

   *  Each Access Control Entry (see below) contains an element that
      identifies the user to which the ACE applies.  That user is
      represented by a 32-bit user ID.  The value of the user ID in each
      ACE has the same meaning and mapping as the value of incoming RPC
      calls.

   Using user ids and group ids implies that the client and server
   either share the same ID list or do local user and group ID mapping.
   Servers and clients must agree on the mapping from user to uid and
   from group to gid, for those sites that do not implement a consistent
   user ID and group ID number space.  In practice, such mapping is
   typically performed on the server, following a static mapping scheme
   or a mapping established by the user from a client at mount time.

   RPCSEC_GSS authentication provides stronger security through the use
   of cryptographic authentication.  The server and client must agree on
   the mapping of the user's GSS principal to a local UID on the server,
   but the name to identity mapping is more operating system independent
   than the uid and gid mapping in AUTH_SYS.

3.4.  File Access Control

   This section describes the abstractions that an NFS server uses to
   determine whether an access or modification to a file is permitted.
   The exact behavior of a server implementation may vary.

3.4.1.  File Ownership

   A file's "owner" is the designated user that is always granted
   permission to update that file's security attributes.  As part of
   creating a file, the NFS server assigns the file's owner.  Under
   normal circumstances the initial file owner is the RPC user who
   issued the NFS CREATE procedure.  However, server security policies
   can mandate replacement of that user (also known as user squashing)
   as part of processing a CREATE procedure.

   An existing file's designated owner can subsequently be changed by an
   NFS SETATTR procedure.  After that change, the new owner is granted
   permission to update the file's security attributes and the old owner
   is no longer treated specially.

   A file's "owner group" is a short list of users that have similar
   privileges as the file's owner, but are treated as a separate
   category for the purpose of permission checking.

   Any user who is not a file's owner or a member of its owner group
   falls into the third category, known as "everyone" or "other".

Lever                     Expires 19 March 2027                 [Page 8]
Internet-Draft              NFS ACL Protocol              September 2026

3.4.1.1.  Superuser Access

   On most operating systems, there is a category of users known as
   privileged users or superusers.  These users can bypass most or all
   access controls on files.

3.4.2.  Categories of Access

   In NFS versions 2 and 3, there are three rudimentary categories of
   access:

   Read access:  Read access grants permission for a user to read a file
      or directory.

   Write access:  Write access grants permission for a user to modify a
      file or directory.

   Execute access:  For a file, execute access grants permission for the
      user to treat the file content as executable.  For a directory
      object, execute access grants permission for the user to perform a
      lookup in that directory.

3.4.3.  Traditional Permission Bits

   Permission bits, or mode bits, are the simplest and perhaps oldest
   form of access control.  Each file object has a set of mode bits
   [POSIX].

   Each of the user categories is given a set of three access type bits.
   Altogether there are then nine bit flags for every file object.

3.4.4.  Access Control Lists

   An Access Control Entry, or ACE, represents a set of access
   categories and a specific user or group.  An Access Control List is a
   list of ACEs.

   Mode bits, as explained in the previous section, are essentially an
   ACL that always contains exactly three ACEs: one for the file's
   owner, one for the file's owner group, and one for everyone else.

3.4.4.1.  Interpreting Access Control Lists

   NFS clients do not perform access checks based on their
   interpretation of an ACL read from the server.  NFS servers are
   solely responsible for authorizing and restricting access to file
   content via the NFS protocol.

Lever                     Expires 19 March 2027                 [Page 9]
Internet-Draft              NFS ACL Protocol              September 2026

   An NFS Access Control List is a list of three or more Access Control
   Entries (ACEs) associated with one file system object.  Each Access
   Control Entry in this list specifies a user and a set of access types
   granted to that user.

   Only ACEs that match the requester are considered.  Each ACE is
   processed until all of the bits of the requester's access have been
   ALLOWED.  Once a bit has been ALLOWED, that bit is no longer
   considered in the processing of subsequent ACEs in the list.

   When the ACL has been fully processed, if there are bits in the
   requester's mask that have not been ALLOWED, access of that type is
   denied.

   Note that an ACL might not be the sole determiner of access.  For
   example:

   *  In the case of a file system exported as read-only, the server may
      deny write access even though an object's ACL grants it.

   *  Server implementations can grant some limited permission to update
      an ACL in order to prevent a situation from arising in which there
      is no valid way to ever modify the ACL.

   *  Server implementations can allow a user to read the data of a file
      when only the execute permission is granted (that is, when the ACL
      denies the user NA_READ but allows NA_EXEC), since a server has to
      read the file to execute it.

   *  Some server implementations have the notion of owner-override, in
      which the owner of the object is allowed to override accesses that
      are denied by the ACL.  This can be helpful, for example, to allow
      users continued access to open files on which the permissions have
      changed.

   *  Some server implementations have the notion of a "superuser" that
      has privileges beyond an ordinary user.  The superuser may be able
      to read or write data or metadata in ways that would otherwise not
      be permitted by the object's ACL.

   NFS clients can use either the NFS_ACL version 2 ACCESS procedure or
   the NFS version 3 ACCESS procedure to ask the server to perform an
   access check based on the requesting user and the ACL present on a
   file system object.  Clients are also free to simply try an operation
   to see what works, then recover if the server denies access.

Lever                     Expires 19 March 2027                [Page 10]
Internet-Draft              NFS ACL Protocol              September 2026

3.4.4.2.  ACLs in Operation

   The SETACL procedure sets two types of Access Control Lists:

   Access:  An NFS access ACL specifies the access permission for a file
      object.  Access Control Entries in an ACL's "aclent" field
      comprise the object's access ACL.

   Default:  An NFS default ACL specifies the default ACL that is set on
      objects that are children of a directory.  Access Control Entries
      in an ACL's "dfaclent" comprise an object's default ACL.  The
      default ACL does not affect access to the object on which it is
      set.

   An access ACL, and a default ACL that has any ACEs, must have one ACE
   for each of NA_USER_OBJ, NA_GROUP_OBJ, and NA_OTHER_OBJ.  An NFS ACL
   that consists only of these three ACEs is referred to as a minimal
   NFS ACL.  A default ACL with no ACEs means the directory has no
   default ACL.

   An NFS ACL may have zero or more NA_USER and/or NA_GROUP ACEs.

   On the wire, a minimal NFS ACL is represented as either three or four
   Access Control Entries.

   *  A sender can send the list as the file system stores it.  Such a
      sender sends three entries for an object whose ACL has no mask
      entry, and four for a manufactured ACL (Section 4.6.3.3), which
      always occupies four entries in the "aclent" array and none in the
      "dfaclent" array and whose NA_CLASS_OBJ entry is not always formed
      as described above.  A receiver accepts either representation in
      either array.

   *  A sender can expand a three-entry list to four.  Such a sender
      adds an NA_CLASS_OBJ entry to the NA_USER_OBJ, NA_GROUP_OBJ, and
      NA_OTHER_OBJ entries, and derives that entry's "perm" element from
      the permission bits of the object's owning group, in both the
      "aclent" and the "dfaclent" array.

   The two representations are not interchangeable in every case.
   Implementations follow different drafts of POSIX 1003.1e, and the
   drafts differ in their treatment of the mask entry in a four-entry
   ACL; [Gruenbacher] describes the difference.  A receiver that follows
   draft 17 removes the NA_CLASS_OBJ entry from a four-entry list when
   its "perm" element equals that of the NA_GROUP_OBJ entry, restoring
   the three-entry form, and keeps the entry when the two differ.

Lever                     Expires 19 March 2027                [Page 11]
Internet-Draft              NFS ACL Protocol              September 2026

   The Access Control Entries in the "aclent" and "dfaclent" arrays can
   appear in any order.  A receiver does not depend on the order in
   which the entries arrive.

   When a client presents a SETACL operation that a server finds is
   invalid or it cannot process, the server responds with ACL2ERR_INVAL
   or ACL3ERR_INVAL, depending on the version of NFS_ACL that is in use.
   ACLs that are not valid include:

   *  The presented ACL does not contain one ACE for each of
      NA_USER_OBJ, NA_GROUP_OBJ, and NA_OTHER_OBJ

   *  The presented ACL contains an NA_GROUP ACE but no NA_CLASS_OBJ ACE

   *  The presented ACL is a default ACL but the target object is not a
      directory

   *  The presented ACL contains an ACE whose "type" field sets more
      than one of the base type values NA_USER_OBJ, NA_USER,
      NA_GROUP_OBJ, NA_GROUP, NA_CLASS_OBJ, and NA_OTHER_OBJ (the
      NA_ACL_DEFAULT flag may accompany exactly one such value)

   *  The presented ACL contains an ACE whose type or perm field has a
      bit set that is not defined by this protocol

   *  The count for a non-empty "aclent" or "dfaclent" array differs
      from the number of entries in that array

   Whether an ACL that contains an NA_USER ACE but no NA_CLASS_OBJ ACE
   is valid depends on the exported file system.  A server responds with
   ACL2ERR_INVAL or ACL3ERR_INVAL when the exported file system rejects
   such an ACL.

   An ACL that has no more than NFS_ACL_MAX_ENTRIES entries in each
   array can still exceed what the exported file system stores in one
   ACL.  A server reports that with ACL2ERR_NOSPC or ACL3ERR_NOSPC, or
   with ACL2ERR_INVAL or ACL3ERR_INVAL when the file system rejects the
   list as invalid.

Lever                     Expires 19 March 2027                [Page 12]
Internet-Draft              NFS ACL Protocol              September 2026

   The NA_ACL_DEFAULT bit is a flag that a sender combines with one of
   the base type values (for example, NA_ACL_DEFAULT | NA_USER_OBJ) to
   mark an Access Control Entry as a default entry: one that a directory
   contributes to its newly created children rather than one that
   controls access to the directory itself.  Every entry in the
   "dfaclent" array has the NA_ACL_DEFAULT bit set in its "type" field,
   and no entry in the "aclent" array has it set.  Segregating default
   entries into the separate "dfaclent" array makes the flag redundant
   on the wire; a sender nonetheless sets it on every "dfaclent" entry
   so that a receiver can reconstruct the single, flag-tagged Access
   Control list that some file access APIs present to applications.

   The "id" field in an Access Control Entry is interpreted as follows:

   *  For an ACE that specifies an NA_USER_OBJ, NA_USER, NA_GROUP, and
      NA_GROUP_OBJ, the "id" field contains a UID or GID value that
      identifies the user on the server whose access permission is being
      set.

   *  For an ACE that specifies other types of permission (for example,
      NA_CLASS_OBJ or NA_OTHER_OBJ), the "id" field is undefined.  A
      sender sets this field to zero, and a receiver ignores its value.

3.4.4.3.  Relationship Between ACLs and Other File Attributes

   When an ACL is present on a file, the ACL controls the requesting
   user's access to the file.  Typically the NFS server ignores the
   file's mode bits.

   Depending on the behavior of the local file system implementation,
   changing the file's ACL via the SETACL procedure may alter the file's
   mode bits, and changing the mode bits via the SETATTR procedure may
   alter the content of the ACL in any way.  NFS clients should refresh
   cached ACLs or file modes after one of these operations.

   When an ACL is present on a file, changing the file's owner (say, via
   the SETATTR operation) may alter the server's interpretation of any
   ACE that targets NA_USER_OBJ.

   When an ACL is present on a file, changing the file's group (say, via
   the SETATTR operation) may alter the server's interpretation of any
   ACE that targets NA_GROUP_OBJ.

   If an NFS client observes that a file's ctime attribute has changed,
   it should assume that any ACLs that are present might have been
   modified.

Lever                     Expires 19 March 2027                [Page 13]
Internet-Draft              NFS ACL Protocol              September 2026

3.4.4.4.  ACL Inheritance

   A directory's default ACL takes effect when a client uses one of the
   NFS CREATE, MKDIR, or MKNOD procedures to create an object in that
   directory.  The exported file system derives the new object's access
   ACL and mode bits from the parent's default ACL and the mode the
   client requested, and gives a new directory the parent's default ACL
   as its own.  That derivation is a property of the exported file
   system rather than of this protocol.  [Gruenbacher] describes the
   POSIX 1003.1e rules for that derivation, including how a default ACL
   takes the place of the umask.  A client observes the result by
   retrieving the new object's ACL with GETACL.

3.4.4.5.  Historical References

   The section entitled "The POSIX 1003.1e/1003.2c Working Group" in
   [Gruenbacher] details the history of POSIX standards efforts with
   regard to file access control.  The editor recommends that readers
   familiarize themselves with the extent to which POSIX specifies the
   content and behavior of ACLs.

4.  Protocol Elements Common to Both Versions

4.1.  RPC Authentication

   The NFS_ACL service uses AUTH_NONE in the NULL procedure.  All RPC
   authentication flavors may be used for other procedures.  That
   records what implementations accept, not what a deployment should
   use; see Section 10.1 and Section 10.2.

4.2.  Constants

   These are the RPC constants needed to call the NFS_ACL service.  They
   are given in decimal.

   100227  The RPC program number for the NFS_ACL protocol

   This document describes versions 2 and 3 of this RPC program.
   Version 4 was used by a Solaris prototype and is not available for
   reuse (see Appendix A.1).

4.3.  Transport address

   The NFS_ACL protocol can operate over the TCP and UDP transport
   protocols, on port 2049, and over RPC-over-RDMA version 1 [RFC8166],
   on port 20049.  In each case this is the port of the NFS service that
   NFS_ACL accompanies.  Section 5.2 of [RFC8267] gives the upper-layer
   binding for NFS_ACL on RPC-over-RDMA.

Lever                     Expires 19 March 2027                [Page 14]
Internet-Draft              NFS ACL Protocol              September 2026

4.4.  Sizes

   NFS_ACL_MAX_ENTRIES 1024

   The maximum number of Access Control Entries allowed in one Access
   Control List array.

4.5.  Basic Data Types

   The following XDR definitions are basic scalar types that are used in
   other structures.

   typedef unsigned int uid;

   typedef unsigned short o_mode;

4.6.  Structured Data types

   The following XDR definitions are common structured data types that
   are used in all versions of the NFS_ACL protocol.

4.6.1.  aclent

   This structure represents a single entry in an Access Control List.

   struct aclent {
       int type;
       uid id;
       o_mode perm;
   };

   The "type" element in an Access Control Entry is a bit mask.  The bit
   field values in this mask are defined as follows:

   const NA_USER_OBJ = 0x1;        /* object owner */
   const NA_USER = 0x2;            /* additional users */
   const NA_GROUP_OBJ = 0x4;       /* owning group of the object */
   const NA_GROUP = 0x8;           /* additional groups */
   const NA_CLASS_OBJ = 0x10;      /* file group class and mask entry */
   const NA_OTHER_OBJ = 0x20;      /* other entry for the object */
   const NA_ACL_DEFAULT = 0x1000;  /* default flag */

   The "perm" element in an Access Control Entry is also a bit mask.
   The bit field values in this mask are defined as follows:

   const NA_READ = 0x4;            /* read permission */
   const NA_WRITE = 0x2;           /* write permission */
   const NA_EXEC = 0x1;            /* exec permission */

Lever                     Expires 19 March 2027                [Page 15]
Internet-Draft              NFS ACL Protocol              September 2026

4.6.2.  secattr

   The secattr structure represents, on the wire, the full Access
   Control List for one file system object.  This list contains an array
   of Access Control Entries that apply to the object, plus an array of
   default Access Control Entries that are inherited by the object's
   children.

   struct secattr {
       unsigned int mask;
       int aclcnt;
       aclent aclent<NFS_ACL_MAX_ENTRIES>;
       int dfaclcnt;
       aclent dfaclent<NFS_ACL_MAX_ENTRIES>;
   };

   The "aclcnt" and "dfaclcnt" elements carry the number of Access
   Control Entries in the object's access ACL and default ACL.  A count
   is meaningful whether or not its array is present: a GETACL reply
   carries a count for an array whose count bit alone is set, and
   carries that array empty (see Section 5.2.2 and Section 6.3.2).

   The "mask" element of the secattr structure is a bit mask.  The bit
   field values in this mask are defined as follows:

   const NA_ACL = 0x1;         /* aclent contains a valid list */
   const NA_ACLCNT = 0x2;      /* number of entries in the aclent list */
   const NA_DFACL = 0x4;       /* dfaclent contains a valid list */
   const NA_DFACLCNT = 0x8;    /* number of entries in the dfaclent list */

   These bit field values are also used in the "mask" element of the
   GETACL2args and GETACL3args structures.

   In a GETACL reply, the "mask" element of the returned secattr
   structure carries the same value as the "mask" element of the
   request.  Because the server fills in fields as the request's "mask"
   selects them, the reply's "mask" also identifies which arrays the
   reply carries.  A client decodes a GETACL reply according to the
   reply's "mask" and treats a reply whose "mask" lacks a bit the
   request set as an error.

   A sender sets no bit in a "mask" element other than the four defined
   here.  A server that receives a request with an undefined bit set
   either responds with ACL2ERR_INVAL or ACL3ERR_INVAL or ignores the
   bit and processes the defined ones.  Because a GETACL reply's "mask"
   echoes the request, the reply can carry the undefined bit.

Lever                     Expires 19 March 2027                [Page 16]
Internet-Draft              NFS ACL Protocol              September 2026

4.6.2.1.  The "mask" Element in a SETACL Request

   In a GETACL request the "mask" element selects which fields the
   server fills in, as described in Section 5.2.2 and Section 6.3.2.  In
   a SETACL request the element carries the same bit values, and a
   server interprets it in one of two ways.

   A server can treat the element as selective.  Such a server replaces
   the object's access ACL only when NA_ACL is set and the object's
   default ACL only when NA_DFACL is set, and leaves an unselected list
   as it found it.

   A server can instead disregard the element and store the entries the
   request carries.  Such a server rejects a request whose "mask" is
   zero with ACL2ERR_INVAL or ACL3ERR_INVAL, and otherwise replaces both
   of the object's lists on every SETACL, so the entries of a list the
   sender leaves empty are removed from the object rather than
   preserved.  When the exported file system does not store the form of
   ACL that NFS_ACL carries, such a server responds with ACL2ERR_NOTSUPP
   or ACL3ERR_NOTSUPP as described in Section 4.6.3.3.

   A SETACL that sets one of NA_ACL and NA_DFACL and clears the other
   therefore has no single meaning.  Sent to a directory that holds both
   an access ACL and a default ACL, it preserves the unselected list on
   a server that treats the element as selective and removes that list's
   entries on a server that stores what it receives.

   A client cannot tell from the SETACL reply which way the server
   behaved.  A SETACL that sets both bits and carries both lists has the
   same effect on either server, so a client that reads back the list it
   does not intend to change and sends it unaltered is unaffected by the
   divergence.  A client that discards its cached copy after a SETACL
   rather than caching what it sent is likewise unaffected by any
   difference between what it sent and what the server stored.

   A client that instead sends the "mask" element as the local
   application supplied it, without reading back the other list, can
   send a SETACL that carries one bit without the other.  Such a request
   relies on the server storing exactly what it receives.  A server that
   treats the element as selective leaves the unsent list as it found
   it, so the object ends up with a different ACL than the application
   supplied.

Lever                     Expires 19 March 2027                [Page 17]
Internet-Draft              NFS ACL Protocol              September 2026

4.6.3.  Interoperability Considerations

   Interoperability between NFS peers that do not implement the NFS_ACL
   protocol is what we already have today.  Interoperability between
   peers that both implement the NFS_ACL protocol is described in the
   rest of this document.

   The following subsections briefly discuss three new interoperability
   scenarios.

4.6.3.1.  Client Implements NFS_ACL, Server Does Not

   An NFS server that implements the NFS_ACL program can advertise it
   via an rpcbind registration [RFC1833].

   A client can query rpcbind before its first NFS_ACL procedure, or it
   can send a procedure and treat the outcome as a probe for service
   availability.  When a client sends an NFS_ACL procedure to a server
   that does not implement the program, the server responds with an RPC
   accept_stat of PROG_UNAVAIL (Section 9 of [RFC5531]).

4.6.3.2.  Server Implements NFS_ACL, Client Does Not

   An NFS server that implements advanced access control can deny
   requests made by a client by responding with NFSERR_ACCES or
   NFS3ERR_ACCES status codes, and an NFS client has no visibility as to
   why the denial occurred.  Neither can that client send operations to
   update the access control on file objects.

   This is a quality of implementation issue for the client.

4.6.3.3.  Client Implements, Exported File System Does Not

   An NFS server that implements the NFS_ACL protocol might share both
   file systems that implement ACLs and file systems that do not.  In
   this case, NFS clients detect the presence of an NFS_ACL service on
   the NFS server.

   A file system that implements access control lists of a different
   form than NFS_ACL carries behaves as this section describes for every
   object it holds.  GETACL returns a manufactured ACL, and SETACL
   fails.

   For file objects that do not implement ACL support:

   *  The server responds to a GETACL procedure by returning a
      manufactured minimal ACL that reflects the current mode bits of
      the object.  The manufactured ACL has four Access Control Entries

Lever                     Expires 19 March 2027                [Page 18]
Internet-Draft              NFS ACL Protocol              September 2026

      in the "aclent" array and none in the "dfaclent" array; the server
      does not manufacture a default ACL.  The "perm" element of the
      manufactured NA_CLASS_OBJ entry either reflects the permission
      bits of the object's owning group, as Section 3.4.4.2 describes
      for an expanded list, or is 7 (NA_READ, NA_WRITE, and NA_EXEC)
      regardless of those bits.  A receiver therefore cannot take a
      manufactured ACL whose NA_CLASS_OBJ and NA_GROUP_OBJ "perm"
      elements differ as evidence of an extended ACL.

   *  The server responds to a SETACL version 3 procedure by returning
      ACL3ERR_NOTSUPP.

   *  The server responds to a SETACL version 2 procedure by returning
      ACL2ERR_NOTSUPP.

5.  NFS_ACL Version 2

   Version 2 of the NFS_ACL protocol is used in conjunction only with
   version 2 of the NFS protocol.

5.1.  Data types inherited from NFS version 2

5.1.1.  ftype

   The enumeration "ftype" gives the type of an NFS version 2 file.
   This definition comes from Section 2.3.2 of [RFC1094]:

   enum ftype {
       NFNON = 0,
       NFREG = 1,
       NFDIR = 2,
       NFBLK = 3,
       NFCHR = 4,
       NFLNK = 5
   };

5.1.2.  fhandle

   NFS version 2 uses a fixed-size file handle.  The following
   definition comes from Section 2.3.3 of [RFC1094]:

   const FHSIZE = 32;

   typedef opaque fhandle[FHSIZE];

Lever                     Expires 19 March 2027                [Page 19]
Internet-Draft              NFS ACL Protocol              September 2026

5.1.3.  timeval

   NFS version 2's "timeval" structure represents the number of seconds
   and microseconds since midnight January 1, 1970, Greenwich Mean Time.
   This definition comes from Section 2.3.4 of [RFC1094]:

   struct timeval {
       unsigned int seconds;
       unsigned int useconds;
   };

5.1.4.  nfsfattr

   This document refers to NFS version 2's file attribute structure as
   "nfsfattr".  This is the same as the fattr structure described in
   Section 2.3.5 of [RFC1094]:

   struct fattr {
       ftype        type;
       unsigned int mode;
       unsigned int nlink;
       unsigned int uid;
       unsigned int gid;
       unsigned int size;
       unsigned int blocksize;
       unsigned int rdev;
       unsigned int blocks;
       unsigned int fsid;
       unsigned int fileid;
       timeval      atime;
       timeval      mtime;
       timeval      ctime;
   };

5.1.5.  Defined Error Numbers

   Section 2.3.1 of [RFC1094] describes an enumerated type called "stat"
   which provides a status code for NFS version 2 results.  A matching
   type called "aclstat2" is defined in this document for the similar
   purpose of returning NFS_ACL version 2 procedure status codes.  The
   numeric values of these two types match up, though aclstat2 omits
   some codes that are not relevant to the NFS_ACL protocol.

Lever                     Expires 19 March 2027                [Page 20]
Internet-Draft              NFS ACL Protocol              September 2026

   The "stat" type in Section 2.3.1 of [RFC1094] does not define a
   status code corresponding to the POSIX EINVAL error.  However,
   existing NFS_ACL version 2 server implementations return the value 22
   (the numeric value of EINVAL) when a client presents an invalid
   argument to a procedure.  The aclstat2 type therefore defines
   ACL2ERR_INVAL with that value, even though the NFS version 2 "stat"
   type has no matching code.

   Similarly, the "stat" type does not define a status code that reports
   that a requested operation is not supported.  The original NFS_ACL
   version 2 server implementation returns the value 45 (its
   NFSERR_OPNOTSUPP status code) when a client directs an operation at a
   file object whose file system does not support ACLs.  The aclstat2
   type therefore defines ACL2ERR_NOTSUPP with that value.  A server
   returns ACL2ERR_NOTSUPP in NFS_ACL version 2 results; the numeric
   value 10004 that NFS version 3 assigns to NFS3ERR_NOTSUPP is not used
   in NFS_ACL version 2 results.

   enum aclstat2 {
       ACL2_OK = 0,
       ACL2ERR_PERM = 1,
       ACL2ERR_NOENT = 2,
       ACL2ERR_IO = 5,
       ACL2ERR_ACCES = 13,
       ACL2ERR_INVAL = 22,
       ACL2ERR_NOSPC = 28,
       ACL2ERR_ROFS = 30,
       ACL2ERR_NOTSUPP = 45,
       ACL2ERR_DQUOT = 69,
       ACL2ERR_STALE = 70
   };

   These status codes carry the following meanings:

   ACL2ERR_PERM  Not owner.  The caller does not have correct ownership
      to perform the requested operation.

   ACL2ERR_NOENT  No such file or directory.  The file or directory name
      specified does not exist.

   ACL2ERR_IO  Some sort of hard error occurred when the operation was
      in progress.  This could be a disk error, for example.

   ACL2ERR_ACCES  Permission denied.  The caller does not have the
      correct permission to perform the requested operation.

   ACL2ERR_INVAL  An invalid or unsupported argument was specified for
      procedure.

Lever                     Expires 19 March 2027                [Page 21]
Internet-Draft              NFS ACL Protocol              September 2026

   ACL2ERR_NOSPC  No space left on device.  The operation caused the
      server's file system to reach its limit.

   ACL2ERR_ROFS  Read-only file system.  Write attempted on a read-only
      file system.

   ACL2ERR_NOTSUPP  Operation is not supported.

   ACL2ERR_DQUOT  Disk quota exceeded.  The client's disk quota on the
      server has been exceeded.

   ACL2ERR_STALE  The "fhandle" given in the arguments was invalid.
      That is, the file referred to by that file handle no longer
      exists, or access to it has been revoked.

5.2.  Server Procedures

   The ERRORS subsection of each procedure enumerates the status values
   a server returns from that procedure.

5.2.1.  Procedure 0: NULL - No Operation

5.2.1.1.  ARGUMENTS

   void;

5.2.1.2.  RESULTS

   void;

5.2.1.3.  DESCRIPTION

   This is the usual NULL procedure with a void argument and void
   result.

5.2.1.4.  IMPLEMENTATION

   It is important that this procedure do no work at all so that clients
   can use it to measure the overhead of processing a service request.
   By convention, the NULL procedure should never require any
   authentication.  A server implementation may choose to ignore this
   convention, if responding to the NULL procedure call acknowledges the
   existence of a resource to an unauthenticated client.

Lever                     Expires 19 March 2027                [Page 22]
Internet-Draft              NFS ACL Protocol              September 2026

5.2.1.5.  ERRORS

   Since the NULL procedure returns no result, it can not return an
   NFS_ACL error status code.  However, some server implementations may
   return RPC-level errors based on security or authentication policy
   settings.

5.2.2.  Procedure 1: GETACL - Retrieve an Access Control List

5.2.2.1.  ARGUMENTS

   struct GETACL2args {
       fhandle fh;
       unsigned int mask;
   };

5.2.2.2.  RESULTS

   struct GETACL2resok {
       fattr attr;
       secattr acl;
   };

   union GETACL2res switch (aclstat2 status) {
   case ACL2_OK:
       GETACL2resok resok;
   default:
       void;
   };

5.2.2.3.  DESCRIPTION

   The GETACL procedure retrieves Access Control List information
   associated with the file system object specified by the
   GETACL2args.fh field.  The client obtains this file handle using one
   of the NFS version 2 LOOKUP, CREATE, MKDIR, or SYMLINK procedures, or
   the MOUNT service, as described in [RFC1094].

   The GETACL2args.mask field specifies which information is to be
   returned in the response:

   *  If the NA_ACL bit is set, the server fills in the object's access
      ACL.

   *  If the NA_ACLCNT bit is set, the server fills in the number of
      ACEs that are in the object's access ACL.

Lever                     Expires 19 March 2027                [Page 23]
Internet-Draft              NFS ACL Protocol              September 2026

   *  If the NA_DFACL bit is set, the server fills in the object's
      default ACL.

   *  If the NA_DFACLCNT bit is set, the server fills in the number of
      ACEs that are in the object's default ACL.

   The server fills in a count whenever either bit for that array is
   set, and fills in the array itself only when the array's own bit is
   set.  An array the server does not fill in is empty on the wire.  The
   reply's "mask" element carries the request's value (see
   Section 4.6.2).

   If the GETACL procedure is successful, the server sets the
   GETACL2res.status field to ACL2_OK.  It fills in the
   GETACL2resok.attr field with the file object's current file
   attributes, as detailed in [RFC1094].  Lastly, it fills in the
   GETACL2resok.acl field with two counted arrays of Access Control
   Entries (ACEs).

   Otherwise, GETACL2res.status contains an error status on failure and
   no other results are returned.

5.2.2.4.  IMPLEMENTATION

   When GETACL2args.fh represents a file object that does not currently
   have an ACL associated with it or does not implement support for
   ACLs, the server responds by returning a manufactured minimal NFS ACL
   that reflects the current owner, group, and mode bits of the object
   (see Section 4.6.3.3).

   A default ACL applies only to a directory object.  When
   GETACL2args.fh represents an object that is not a directory, that
   object has no default ACL.  If the request's NA_DFACL or NA_DFACLCNT
   bit is set, the server returns an empty dfaclent array and a dfaclcnt
   of zero rather than reporting an error.

5.2.2.5.  ERRORS

   *  ACL2ERR_IO

   *  ACL2ERR_ACCES

   *  ACL2ERR_INVAL

   *  ACL2ERR_STALE

5.2.3.  Procedure 2: SETACL - Set or replace an Access Control List

Lever                     Expires 19 March 2027                [Page 24]
Internet-Draft              NFS ACL Protocol              September 2026

5.2.3.1.  ARGUMENTS

   struct SETACL2args {
       fhandle fh;
       secattr acl;
   };

5.2.3.2.  RESULTS

   struct SETACL2resok {
       fattr attr;
   };

   union SETACL2res switch (aclstat2 status) {
   case ACL2_OK:
       SETACL2resok resok;
   default:
       void;
   };

5.2.3.3.  DESCRIPTION

   The SETACL procedure replaces the Access Control Lists associated
   with the file system object specified by the SETACL2args.fh field
   with the ACLs specified by the SETACL2args.acl field.  The client
   obtains the file handle using one of the NFS version 3 LOOKUP,
   CREATE, MKDIR, SYMLINK procedures, or the MOUNT service, as described
   in [RFC1094].

   To remove extended access control from a file object, a client uses
   SETACL to replace the object's ACL with a minimal NFS ACL (see
   Section 3.4.4.2).  To remove a directory's default ACL, a client
   sends a SETACL with both the NA_ACL and NA_DFACL bits set, an empty
   "dfaclent" array, and the directory's current access ACL in "aclent"
   (see Section 4.6.2.1).

   If the SETACL procedure is successful, the server sets the
   SETACL2res.status field to ACL2_OK and fills in the SETACL2resok.attr
   field with the file object's new file attributes, as detailed in
   [RFC1094].

   Otherwise, SETACL2res.status contains an error status on failure and
   no other results are returned.

Lever                     Expires 19 March 2027                [Page 25]
Internet-Draft              NFS ACL Protocol              September 2026

5.2.3.4.  IMPLEMENTATION

   A successful reply means that the exported file system has verified
   the new ACL, but does not mean that the change has reached stable
   storage.

   Changing a file object's ACL changes the object's ctime.  The ctime
   change is reflected in the attributes returned in the SETACL
   response.

   A high-quality server implementation ensures that a GETACL procedure
   running concurrently with a SETACL procedure does not return
   partially updated (torn) ACL contents.  However, a failed SETACL may
   partially change a file's ACLs.

   When SETACL2args.fh represents a file object that does not implement
   support for ACLs, the server responds by setting SETACL2res.status to
   ACL2ERR_NOTSUPP.

   When the new ACL does not contain at least the minimal set of ACEs
   (as described in Section 3.4.4.2), the server responds by setting
   SETACL2res.status to ACL2ERR_INVAL.

   Servers differ in how they treat the "mask" element of
   SETACL2args.acl.  Section 4.6.2.1 describes the divergence and how a
   client avoids it.

5.2.3.5.  ERRORS

   *  ACL2ERR_ROFS

   *  ACL2ERR_PERM

   *  ACL2ERR_IO

   *  ACL2ERR_ACCES

   *  ACL2ERR_INVAL

   *  ACL2ERR_NOSPC

   *  ACL2ERR_NOTSUPP

   *  ACL2ERR_DQUOT

   *  ACL2ERR_STALE

Lever                     Expires 19 March 2027                [Page 26]
Internet-Draft              NFS ACL Protocol              September 2026

5.2.4.  Procedure 3: GETATTR - Get file attributes

5.2.4.1.  ARGUMENTS

   struct GETATTR2args {
       fhandle fh;
   };

5.2.4.2.  RESULTS

   struct GETATTR2resok {
       fattr attr;
   };

   union GETATTR2res switch (aclstat2 status) {
   case ACL2_OK:
       GETATTR2resok resok;
   default:
       void;
   };

5.2.4.3.  DESCRIPTION

   The GETATTR procedure retrieves the current file attributes
   associated with the file system object specified by the
   GETATTR2args.fh field.  The client obtains this file handle using one
   of the NFS version 2 LOOKUP, CREATE, MKDIR, SYMLINK procedures, or
   the MOUNT service, as described in [RFC1094].

   If the GETATTR procedure is successful, the server sets the
   GETATTR2res.status field to ACL2_OK, and fills in the
   GETATTR2resok.attr field with the file object's current file
   attributes, as detailed in [RFC1094].

   Otherwise, GETATTR2res.status contains an error status on failure and
   no other results are returned.

5.2.4.4.  IMPLEMENTATION

   Refer to Section 2.3.5 of [RFC1094] for details about the content of
   the returned file attributes.

5.2.4.5.  ERRORS

   *  ACL2ERR_IO

   *  ACL2ERR_STALE

Lever                     Expires 19 March 2027                [Page 27]
Internet-Draft              NFS ACL Protocol              September 2026

5.2.5.  Procedure 4: ACCESS - Check access permission

5.2.5.1.  ARGUMENTS

   struct ACCESS2args {
       fhandle fh;
       unsigned int access;
   };

5.2.5.2.  RESULTS

   const ACCESS2_READ = 0x1;       /* read data or readdir a directory */
   const ACCESS2_LOOKUP = 0x2;     /* lookup a name in a directory */
   const ACCESS2_MODIFY = 0x4;     /* rewrite existing file data or */
                                   /* modify existing directory entries */
   const ACCESS2_EXTEND = 0x8;     /* write new data or add directory entries */
   const ACCESS2_DELETE = 0x10;    /* delete existing directory entry */
   const ACCESS2_EXECUTE = 0x20;   /* execute file (no meaning for a directory) */

   struct ACCESS2resok {
       fattr attr;
       unsigned int access;
   };

   union ACCESS2res switch (aclstat2 status) {
   case ACL2_OK:
       ACCESS2resok resok;
   default:
       void;
   };

5.2.5.3.  DESCRIPTION

   The ACCESS procedure determines the access rights that a user, as
   identified by the RPC credentials in the request, has with respect to
   the file handle specified by the ACCESS2args.fh field.  The client
   obtains this file handle using one of the NFS version 2 LOOKUP,
   CREATE, MKDIR, SYMLINK procedures, or the MOUNT service, as described
   in [RFC1094].  The client encodes the set of permissions that are to
   be checked in the ACCESS2args.access field.

   The following access permissions may be requested:

   ACCESS2_READ  Read data from file or read a directory.

   ACCESS2_LOOKUP  Look up a name in a directory (no meaning for non-
      directory objects).

Lever                     Expires 19 March 2027                [Page 28]
Internet-Draft              NFS ACL Protocol              September 2026

   ACCESS2_MODIFY  Rewrite existing file data or modify existing
      directory entries.

   ACCESS2_EXTEND  Write new data or add directory entries.

   ACCESS2_DELETE  Delete an existing directory entry (no meaning for
      non-directory objects).

   ACCESS2_EXECUTE  Execute file (no meaning for a directory).

   A server grants no permission that this protocol does not define.  A
   bit set in ACCESS2args.access that is not listed above is clear in
   ACCESS2resok.access.

   If the ACCESS procedure is successful, the server sets the
   ACCESS2res.status field to ACL2_OK.  It fills in the
   ACCESS2resok.attr field with the file object's current file
   attributes, as detailed in [RFC1094].  Lastly, it encodes the set of
   permissions that the requesting user is granted in the
   ACCESS2resok.access field.

5.2.5.4.  IMPLEMENTATION

   In the NFS version 2 protocol, the only reliable way to determine
   whether an operation is allowed is to try it and see if it succeeded
   or failed.  Using the ACCESS procedure in the NFS_ACL version 2
   protocol, a client can ask the server to indicate whether or not one
   or more classes of operations are permitted.

   In general, it is not sufficient for a client to attempt to deduce
   access permissions by inspecting the uid, gid, and mode fields in the
   file attributes, since the server may perform uid or gid mapping or
   enforce additional access control restrictions.  It is also possible
   that the NFS version 2 protocol server may not be in the same ID
   space as the NFS version 2 protocol client.  In these cases, the NFS
   version 2 protocol client can not reliably perform an access check
   with only current file attributes.

   The information returned by the server in response to an ACCESS call
   is advisory only.  It was correct at the exact time that the server
   performed the checks, but not necessarily afterwards.  The server can
   revoke access permission to a file object at any time.

   The NFS_ACL version 2 protocol client should use the effective
   credentials of the user to build the authentication information in
   the ACCESS request used to determine access rights.  It is the
   effective user and group credentials that are used in subsequent read
   and write operations.

Lever                     Expires 19 March 2027                [Page 29]
Internet-Draft              NFS ACL Protocol              September 2026

   Many implementations do not directly support the ACCESS2_DELETE
   permission.  Operating systems like UNIX may ignore the
   ACCESS2_DELETE bit if set on an access request on a non-directory
   object.  In these systems, delete permission on a file is determined
   by the access permissions on the directory in which the file resides,
   instead of being determined by the permissions of the file itself.
   Thus, the bit mask returned for such a request will have the
   ACCESS2_DELETE bit set to 0, indicating that the client does not have
   this permission.

   The server should return a status of ACL2_OK if no errors occurred
   that prevented the server from making the required access checks.

5.2.5.5.  ERRORS

   *  ACL2ERR_IO

   *  ACL2ERR_STALE

5.2.6.  Procedure 5: GETXATTRDIR - Get named attribute directory

5.2.6.1.  ARGUMENTS

   struct GETXATTRDIR2args {
       fhandle fh;
       bool create;
   };

5.2.6.2.  RESULTS

   struct GETXATTRDIR2resok {
       fhandle fh;
       fattr attr;
   };

   union GETXATTRDIR2res switch (aclstat2 status) {
   case ACL2_OK:
       GETXATTRDIR2resok resok;
   default:
       void;
   };

5.2.6.3.  DESCRIPTION

   Section 5.3 of [RFC8881] defines a set of generic file attributes
   known as "named attributes".  The GETXATTRDIR procedure extends this
   facility into the NFSv2 protocol.

Lever                     Expires 19 March 2027                [Page 30]
Internet-Draft              NFS ACL Protocol              September 2026

   The GETXATTRDIR procedure obtains the file handle of the named
   attribute directory associated with the file handle in the
   GETXATTRDIR2args.fh field.  This directory contains only objects of
   type NFREG.

   If the GETXATTRDIR procedure is successful, the server sets the
   GETXATTRDIR2res.status field to ACL2_OK.  It fills in the
   GETXATTRDIR2resok.fh field with a file handle that the client may use
   to look up the target file's named attributes.  It fills in the
   GETXATTRDIR2resok.attr field with the named attribute directory's
   current file attributes, as detailed in [RFC1094].

   Using the file handle returned in GETXATTRDIR2resok.fh, a client can
   utilize the READDIR and LOOKUP procedures to obtain file handles for
   the named attributes associated with the target file system object.

   If the target file object does not currently have a named attribute
   directory associated with it and the GETXATTRDIR2args.create boolean
   field is set to false, the server returns ACL2ERR_NOENT.  If the
   target file object does not currently have a named attribute
   directory associated with it and the GETXATTRDIR2args.create boolean
   field is set to true, the server attempts to create the named
   attribute directory before returning a result.  If the target file
   currently has a named attribute directory associated with it and the
   GETXATTRDIR2args.create boolean is set to true, the server returns
   the file handle of that named attribute directory.

   If the RPC user does not have read access to the target file, or if
   the GETXATTRDIR operation is to create a named attribute directory
   and the RPC user does not have permission to do so, the server
   returns ACL2ERR_ACCES in the GETXATTRDIR2res.status field.

   If the target file handle designates an object not of type NFREG or
   NFDIR, the server returns the value ACL2ERR_INVAL in the
   GETXATTRDIR2res.status field.  Neither named attributes nor named
   attribute directories have their own named attributes.

   Note: This operation is equivalent to the NFSv4 OPENATTR operation as
   specified in Section 16.17 of [RFC7530] and Section 18.17 of
   [RFC8881].

5.2.6.4.  IMPLEMENTATION

   Server implementers are free to choose not to implement this
   procedure.  In this case, the server returns the RPC-level error
   PROC_UNAVAIL.

Lever                     Expires 19 March 2027                [Page 31]
Internet-Draft              NFS ACL Protocol              September 2026

   If the server implementation does implement the GETXATTRDIR procedure
   but the shared file system containing the file object specified by
   the file handle in the GETXATTRDIR2args.fh field does not support
   named attributes, the server returns ACL2ERR_NOTSUPP in the
   GETXATTRDIR2res.status field.

5.2.6.5.  ERRORS

   *  ACL2ERR_PERM

   *  ACL2ERR_NOENT

   *  ACL2ERR_IO

   *  ACL2ERR_ACCES

   *  ACL2ERR_INVAL

   *  ACL2ERR_NOSPC

   *  ACL2ERR_ROFS

   *  ACL2ERR_STALE

   *  ACL2ERR_NOTSUPP

6.  NFS_ACL Version 3

   Version 3 of the NFS_ACL protocol is used in conjunction only with
   version 3 of the NFS protocol.

6.1.  Data types inherited from NFS version 3

6.1.1.  Scalar Data types

   These are defined in Section 2.5 of [RFC1813].

   typedef unsigned hyper uint64;

   typedef unsigned long uint32;

   typedef uint64 fileid3;

   typedef uint32 uid3;

   typedef uint32 gid3;

   typedef uint64 size3;

Lever                     Expires 19 March 2027                [Page 32]
Internet-Draft              NFS ACL Protocol              September 2026

   typedef uint32 mode3;

6.1.2.  ftype3

   The enumeration "ftype3" represents the type of a file object.  This
   definition is further explained in Section 2.6 of [RFC1813].

   enum ftype3 {
       NF3REG    = 1,
       NF3DIR    = 2,
       NF3BLK    = 3,
       NF3CHR    = 4,
       NF3LNK    = 5,
       NF3SOCK   = 6,
       NF3FIFO   = 7
   };

6.1.3.  specdata3

   struct specdata3 {
       uint32     specdata1;
       uint32     specdata2;
   };

   The interpretation of the two words depends on the type of file
   system object.  For a block special (NF3BLK) or character special
   (NF3CHR) file, specdata1 and specdata2 are the major and minor device
   numbers, respectively.  For all other file types, these two elements
   should either be set to 0 or the values should be agreed upon by the
   client and server.

   Further detail is available in Section 2.6 of [RFC1813].

6.1.4.  nfs_fh3

   The nfs_fh3 data type is a variable-length opaque object returned by
   the NFS version 3 LOOKUP, CREATE, MKDIR, SYMLINK, MKNOD, or
   READDIRPLUS procedures.  A client uses this handle during subsequent
   NFS operations to reference the file.  This definition comes from
   Section 2.6 of [RFC1813].

   NFS3_FHSIZE 64

   The maximum size in bytes of the opaque file handle.

   struct nfs_fh3 {
       opaque       data<NFS3_FHSIZE>;
   };

Lever                     Expires 19 March 2027                [Page 33]
Internet-Draft              NFS ACL Protocol              September 2026

   To the client, a file handle is opaque.  The client stores file
   handles for use in a later request and can compare two file handles
   from the same server for equality by doing a byte-by-byte comparison,
   but cannot otherwise interpret the contents of file handles.
   Further, if two file handles from the same server are equal, they
   must refer to the same file, but if they are not equal, no
   conclusions can be drawn.

   Servers may revoke access provided by a file handle at any time.  If
   the file handle passed in a call refers to a file system object that
   no longer exists on the server or access for that file handle has
   been revoked, the error, ACL3ERR_STALE, is returned.

6.1.5.  nfstime3

   NFS version 3's "nfstime3" structure represents the number of seconds
   and nanoseconds since midnight January 1, 1970 Greenwich Mean Time.
   Further details are in Section 2.6 of [RFC1813].

   struct nfstime3 {
       uint32   seconds;
       uint32   nseconds;
   };

6.1.6.  nfsfattr3

   This document refers to NFS version 3's file attribute structure as
   "nfsfattr3".  This is the same as the fattr3 structure described in
   Section 2.6 of [RFC1813].  A definition of the bit fields in the
   "mode" element, which relate to traditional file system access
   permissions, can also be found there.

   struct fattr3 {
       ftype3     type;
       mode3      mode;
       uint32     nlink;
       uid3       uid;
       gid3       gid;
       size3      size;
       size3      used;
       specdata3  rdev;
       uint64     fsid;
       fileid3    fileid;
       nfstime3   atime;
       nfstime3   mtime;
       nfstime3   ctime;
   };

Lever                     Expires 19 March 2027                [Page 34]
Internet-Draft              NFS ACL Protocol              September 2026

6.1.7.  post_op_attr

   The NFS version 3 "post_op_attr" data type returns file attributes
   that are not directly involved in the requested procedure.  See
   Section 2.6 of [RFC1813] for more information.

   union post_op_attr switch (bool attributes_follow) {
   case TRUE:
       fattr3   attributes;
   case FALSE:
       void;
   };

   The format of this data type appears to make returning file
   attributes optional.  However, server implementers are strongly
   encouraged to make a best effort to return attributes whenever
   possible, even when returning an error.

6.2.  Error Values

   Section 2.5 of [RFC1813] describes an enumerated type called
   "nfsstat3" which provides a status code for NFS version 3 procedure
   results.  A matching type called "aclstat3" is defined in this
   document for the similar purpose of returning NFS_ACL version 3
   procedure status codes.  The numeric values of these two types match
   up, although aclstat3 omits some codes that are not relevant to the
   NFS_ACL protocol.

   enum aclstat3 {
       ACL3_OK             = 0,
       ACL3ERR_PERM        = 1,
       ACL3ERR_NOENT       = 2,
       ACL3ERR_IO          = 5,
       ACL3ERR_ACCES       = 13,
       ACL3ERR_INVAL       = 22,
       ACL3ERR_NOSPC       = 28,
       ACL3ERR_ROFS        = 30,
       ACL3ERR_DQUOT       = 69,
       ACL3ERR_STALE       = 70,
       ACL3ERR_BADHANDLE   = 10001,
       ACL3ERR_NOTSUPP     = 10004,
       ACL3ERR_SERVERFAULT = 10006,
       ACL3ERR_JUKEBOX     = 10008
   };

   These status codes carry the following meanings:

   ACL3_OK  Indicates the call completed successfully.

Lever                     Expires 19 March 2027                [Page 35]
Internet-Draft              NFS ACL Protocol              September 2026

   ACL3ERR_PERM  Not owner.  The operation was not allowed because the
      caller is either not a privileged user (root) or not the owner of
      the target of the operation.

   ACL3ERR_NOENT  No such file or directory.  The file or directory name
      specified does not exist.

   ACL3ERR_IO  I/O error.  A hard error (for example, a disk error)
      occurred while processing the requested operation.

   ACL3ERR_ACCES  Permission denied.  The caller does not have the
      correct permission to perform the requested operation.  Contrast
      this with ACL3ERR_PERM, which restricts itself to owner or
      privileged user permission failures.

   ACL3ERR_INVAL  An invalid or unsupported argument was specified for
      procedure.

   ACL3ERR_NOSPC  No space left on device.  The operation would have
      caused the server's file system to exceed its limit.

   ACL3ERR_ROFS  Read-only file system.  A modifying operation was
      attempted on a read-only file system.

   ACL3ERR_DQUOT  Resource (quota) hard limit exceeded.  The user's
      resource limit on the server has been exceeded.

   ACL3ERR_STALE  Invalid file handle.  The file handle given in the
      arguments was invalid.  The file referred to by that file handle
      no longer exists or access to it has been revoked.

   ACL3ERR_BADHANDLE  Illegal NFS file handle.  The file handle failed
      internal consistency checks.

   ACL3ERR_NOTSUPP  Operation is not supported.

   ACL3ERR_SERVERFAULT  An error occurred on the server which does not
      map to any of the legal NFS version 3 protocol error values.  The
      client should translate this into an appropriate error.  UNIX
      clients may choose to translate this to EIO.

   ACL3ERR_JUKEBOX  The server initiated the request, but was not able
      to complete it in a timely fashion.  The client should wait and
      then try the request with a new RPC transaction ID.  For example,
      this error should be returned from a server that supports
      hierarchical storage and receives a request to process a file that
      has been migrated.  In this case, the server should start the
      immigration process and respond to client with this error.

Lever                     Expires 19 March 2027                [Page 36]
Internet-Draft              NFS ACL Protocol              September 2026

6.3.  Server Procedures

   The ERRORS subsection of each procedure enumerates the status values
   a server returns from that procedure.

6.3.1.  Procedure 0: NULL - No Operation

6.3.1.1.  ARGUMENTS

   void;

6.3.1.2.  RESULTS

   void;

6.3.1.3.  DESCRIPTION

   This is the usual NULL procedure with a void argument and void
   result.

6.3.1.4.  IMPLEMENTATION

   It is important that this procedure do no work at all so that clients
   can use it to measure the overhead of processing a service request.
   By convention, the NULL procedure should never require any
   authentication.  A server implementation may choose to ignore this
   convention, if responding to the NULL procedure call acknowledges the
   existence of a resource to an unauthenticated client.

6.3.1.5.  ERRORS

   Since the NULL procedure takes no argument and returns no result, it
   can not return an NFS or NFS_ACL error status code.  However, some
   server implementations may return RPC errors based on security or
   authentication policy settings.

6.3.2.  Procedure 1: GETACL - Retrieve an Access Control List

6.3.2.1.  ARGUMENTS

   struct GETACL3args {
       nfs_fh3 fh;
       unsigned int mask;
   };

6.3.2.2.  RESULTS

Lever                     Expires 19 March 2027                [Page 37]
Internet-Draft              NFS ACL Protocol              September 2026

   struct GETACL3resok {
       post_op_attr attr;
       secattr acl;
   };

   struct GETACL3resfail {
       post_op_attr attr;
   };

   union GETACL3res switch (aclstat3 status) {
   case ACL3_OK:
       GETACL3resok resok;
   default:
       GETACL3resfail resfail;
   };

6.3.2.3.  DESCRIPTION

   The GETACL procedure retrieves Access Control List information
   associated with the file system object specified by the
   GETACL3args.fh field.  The client obtains this file handle using one
   of the NFS version 2 LOOKUP, CREATE, MKDIR, SYMLINK, MKNOD, or
   READDIRPLUS procedures, or the MOUNT service, as described in
   [RFC1813].

   The GETACL3args.mask field specifies which information is to be
   returned in the response:

   *  If the NA_ACL bit is set, the server fills in the object's access
      ACL.

   *  If the NA_ACLCNT bit is set, the server fills in the number of
      ACEs that are in the object's access ACL.

   *  If the NA_DFACL bit is set, the server fills in the object's
      default ACL.

   *  If the NA_DFACLCNT bit is set, the server fills in the number of
      ACEs that are in the object's default ACL.

   The server fills in a count whenever either bit for that array is
   set, and fills in the array itself only when the array's own bit is
   set.  An array the server does not fill in is empty on the wire.  The
   reply's "mask" element carries the request's value (see
   Section 4.6.2).

Lever                     Expires 19 March 2027                [Page 38]
Internet-Draft              NFS ACL Protocol              September 2026

   If the GETACL procedure is successful, the server sets the
   GETACL3res.status field to ACL3_OK.  It fills in the
   GETACL3resok.attr field with the file object's post operation file
   attributes, as detailed in [RFC1813].  Lastly, it fills in the
   GETACL3resok.acl field with two counted arrays of Access Control
   Entries (ACEs).

   Otherwise, GETACL3res.status contains an error status on failure and
   no other results are returned.

6.3.2.4.  IMPLEMENTATION

   When GETACL3args.fh represents a file object that does not currently
   have an ACL associated with it or does not implement support for
   ACLs, the server responds by returning a manufactured minimal NFS ACL
   that reflects the current owner, group, and mode bits of the object
   (see Section 4.6.3.3).

   A default ACL applies only to a directory object.  When
   GETACL3args.fh represents an object that is not a directory, that
   object has no default ACL.  If the request's NA_DFACL or NA_DFACLCNT
   bit is set, the server returns an empty dfaclent array and a dfaclcnt
   of zero rather than reporting an error.

6.3.2.5.  ERRORS

   *  ACL3ERR_IO

   *  ACL3ERR_ACCES

   *  ACL3ERR_INVAL

   *  ACL3ERR_STALE

   *  ACL3ERR_BADHANDLE

   *  ACL3ERR_SERVERFAULT

   *  ACL3ERR_JUKEBOX

6.3.3.  Procedure 2: SETACL - Set or replace an Access Control List

6.3.3.1.  ARGUMENTS

   struct SETACL3args {
       nfs_fh3 fh;
       secattr acl;
   };

Lever                     Expires 19 March 2027                [Page 39]
Internet-Draft              NFS ACL Protocol              September 2026

6.3.3.2.  RESULTS

   struct SETACL3resok {
       post_op_attr attr;
   };

   struct SETACL3resfail {
       post_op_attr attr;
   };

   union SETACL3res switch (aclstat3 status) {
   case ACL3_OK:
       SETACL3resok resok;
   default:
       SETACL3resfail resfail;
   };

6.3.3.3.  DESCRIPTION

   The SETACL procedure replaces the Access Control Lists associated
   with the file system object specified by the SETACL3args.fh field
   with the ACLs specified by the SETACL3args.acl field.  The client
   obtains the file handle using one of the NFS version 3 LOOKUP,
   CREATE, MKDIR, MKNOD, SYMLINK, or READDIRPLUS procedures, or the
   MOUNT service, as described in [RFC1813].

   To remove extended access control from a file object, a client uses
   SETACL to replace the object's ACL with a minimal NFS ACL (see
   Section 3.4.4.2).  To remove a directory's default ACL, a client
   sends a SETACL with both the NA_ACL and NA_DFACL bits set, an empty
   "dfaclent" array, and the directory's current access ACL in "aclent"
   (see Section 4.6.2.1).

   If the SETACL procedure is successful, the server sets the
   SETACL3res.status field to ACL3_OK and fills in the SETACL3resok.attr
   field with the file object's post operation file attributes, as
   detailed in [RFC1813].

   Otherwise, SETACL3res.status contains an error status on failure and
   no other results are returned.

6.3.3.4.  IMPLEMENTATION

   A successful reply means that the exported file system has verified
   the new ACL, but does not mean that the change has reached stable
   storage.

Lever                     Expires 19 March 2027                [Page 40]
Internet-Draft              NFS ACL Protocol              September 2026

   Changing a file object's ACL changes the object's ctime.  The ctime
   change is reflected in the attributes returned in the SETACL
   response.

   A high-quality server implementation ensures that a GETACL procedure
   running concurrently with a SETACL procedure does not return
   partially updated (torn) ACL contents.  However, a failed SETACL may
   partially change a file's ACLs.

   When SETACL3args.fh represents a file object that does not implement
   support for ACLs, the server responds by setting SETACL3res.status to
   ACL3ERR_NOTSUPP.

   When SETACL3args.acl does not contain at least the minimal set of
   ACEs (as described in Section 3.4.4.2), the server responds by
   setting SETACL3res.status to ACL3ERR_INVAL.

   Servers differ in how they treat the "mask" element of
   SETACL3args.acl.  Section 4.6.2.1 describes the divergence and how a
   client avoids it.

6.3.3.5.  ERRORS

   *  ACL3ERR_PERM

   *  ACL3ERR_IO

   *  ACL3ERR_ACCES

   *  ACL3ERR_INVAL

   *  ACL3ERR_NOSPC

   *  ACL3ERR_ROFS

   *  ACL3ERR_DQUOT

   *  ACL3ERR_STALE

   *  ACL3ERR_BADHANDLE

   *  ACL3ERR_NOTSUPP

   *  ACL3ERR_SERVERFAULT

   *  ACL3ERR_JUKEBOX

Lever                     Expires 19 March 2027                [Page 41]
Internet-Draft              NFS ACL Protocol              September 2026

6.3.4.  Procedure 3: GETXATTRDIR - Get named attribute directory

6.3.4.1.  ARGUMENTS

   struct GETXATTRDIR3args {
       nfs_fh3 fh;
       bool create;
   };

6.3.4.2.  RESULTS

   struct GETXATTRDIR3resok {
       nfs_fh3 fh;
       post_op_attr attr;
   };

   union GETXATTRDIR3res switch (aclstat3 status) {
   case ACL3_OK:
       GETXATTRDIR3resok resok;
   default:
       void;
   };

6.3.4.3.  DESCRIPTION

   Section 5.3 of [RFC8881] defines a set of generic file attributes
   known as "named attributes".  The GETXATTRDIR procedure extends this
   facility into the NFSv3 protocol.

   The GETXATTRDIR procedure obtains the file handle of the named
   attribute directory associated with the file handle in the
   GETXATTRDIR3args.fh field.  This directory contains only objects of
   type NF3REG.

   If the GETXATTRDIR procedure is successful, the server sets the
   GETXATTRDIR3res.status field to ACL3_OK.  It fills in the
   GETXATTRDIR3resok.fh field with a file handle that the client may use
   to look up the target file's named attributes.  It fills in the
   GETXATTRDIR3resok.attr field with the named attribute directory's
   current file attributes, as detailed in [RFC1813].

   Using the file handle returned in GETXATTRDIR3resok.fh, a client can
   utilize the READDIR and LOOKUP procedures to obtain file handles for
   the named attributes associated with the target file system object.

   If the target file object does not currently have a named attribute
   directory associated with it and the GETXATTRDIR3args.create boolean
   field is set to false, the server returns ACL3ERR_NOENT.  If the

Lever                     Expires 19 March 2027                [Page 42]
Internet-Draft              NFS ACL Protocol              September 2026

   target file object does not currently have a named attribute
   directory associated with it and the GETXATTRDIR3args.create boolean
   field is set to true, the server attempts to create the named
   attribute directory before returning a result.  If the target file
   currently has a named attribute directory associated with it and the
   GETXATTRDIR3args.create boolean is set to true, the server returns
   the file handle of that named attribute directory.

   If the RPC user does not have read access to the target file, or if
   the GETXATTRDIR operation is to create a named attribute directory
   and the RPC user does not have permission to do so, the server
   returns ACL3ERR_ACCES in the GETXATTRDIR3res.status field.

   If the target file handle designates an object not of type NF3REG or
   NF3DIR, the server returns the value ACL3ERR_INVAL in the
   GETXATTRDIR3res.status field.  Neither named attributes nor named
   attribute directories have their own named attributes.

   Note: This operation is equivalent to the NFSv4 OPENATTR operation as
   specified in Section 16.17 of [RFC7530] and Section 18.17 of
   [RFC8881].

6.3.4.4.  IMPLEMENTATION

   Server implementers are free to choose not to implement this
   procedure.  In this case, the server returns the RPC-level error
   PROC_UNAVAIL.

   If the server implementation does implement the GETXATTRDIR procedure
   but the shared file system containing the file object specified by
   the file handle in the GETXATTRDIR3args.fh field does not support
   named attributes, the server returns ACL3ERR_NOTSUPP in the
   GETXATTRDIR3res.status field.

6.3.4.5.  ERRORS

   *  ACL3ERR_PERM

   *  ACL3ERR_NOENT

   *  ACL3ERR_IO

   *  ACL3ERR_ACCES

   *  ACL3ERR_INVAL

   *  ACL3ERR_NOSPC

Lever                     Expires 19 March 2027                [Page 43]
Internet-Draft              NFS ACL Protocol              September 2026

   *  ACL3ERR_ROFS

   *  ACL3ERR_STALE

   *  ACL3ERR_BADHANDLE

   *  ACL3ERR_NOTSUPP

   *  ACL3ERR_SERVERFAULT

   *  ACL3ERR_JUKEBOX

7.  Implementation Issues

7.1.  Permission issues

   The NFS protocol, strictly speaking, does not define the permission
   checking used by NFS servers.  However, it is expected that an NFS
   server will do normal operating system permission checking using
   AUTH_SYS style authentication as the basis of its protection
   mechanism, or another stronger form of authentication such as
   RPCSEC_GSS.  With AUTH_SYS authentication, the server gets the
   client's effective uid, effective gid, and groups on each call and
   uses them to check permission.  These are the so-called UNIX
   credentials.

   Using uid and gid implies that the client and server share the same
   uid list.  Every server and client pair must have the same mapping
   from user to uid and from group to gid.  Since every client can also
   be a server, this tends to imply that the whole network shares the
   same uid/gid space.  If this is not the case, then it usually falls
   upon the server to perform some custom mapping of credentials from
   one authentication domain into another.  A discussion of techniques
   for managing a shared user space or for providing mechanisms for user
   ID mapping is beyond the scope of this specification.

   In POSIX-based operating systems, a particular user (on UNIX, the uid
   0) has access to all files, no matter what permission and ownership
   they have.  This superuser permission may not be allowed on the
   server, since anyone who can become superuser on their client could
   gain access to all remote files.  A POSIX-based NFS server by default
   maps uid 0 to a distinguished value (for instance, UID_NOBODY), as
   well as mapping the groups list, before doing its access checking.  A
   server implementation may provide a mechanism to change this mapping.

Lever                     Expires 19 March 2027                [Page 44]
Internet-Draft              NFS ACL Protocol              September 2026

7.2.  Duplicate Request Cache

   The typical NFS protocol failure recovery model uses client time-out
   and retry to handle server crashes, network partitions, and lost
   server replies.  A retried request is referred to as a duplicate of
   the original.

   When used in a file server context, the term idempotent can be used
   to distinguish between operation types.  An idempotent request is one
   that a server can perform more than once with equivalent results
   (though it may in fact change, as a side effect, the access time on a
   file, say for READ).  Some NFS operations are obviously non-
   idempotent.  They cannot be reprocessed without special attention
   simply because they may fail if tried a second time.  A CREATE
   request, for example, can be used to create a file for which the
   owner does not have write permission.  A duplicate of this request
   cannot succeed if the original succeeded.  Likewise, a file can be
   removed only once.

   The side effects caused by performing a duplicate non-idempotent
   request can be destructive.  A duplicate file truncation can result
   in lost writes.  It is the inherent stateless design of the NFS
   protocol on top of an unreliable RPC transport that yields the
   possibility of destructive replays of non-idempotent requests.  Even
   in an implementation of the NFS protocol over a reliable connection-
   oriented transport, a connection break with automatic reestablishment
   requires duplicate request processing: the client retransmits
   requests that were pending before the connection loss, and the server
   needs to recognize and deal with potential duplicate non-idempotent
   requests.

   Most NFS server implementations maintain a cache of recent requests,
   called the duplicate request cache, for recognizing duplicate non-
   idempotent requests.  If the server receives a request and recognizes
   it as a duplicate of a recently completed request, the server returns
   the original completion status instead of processing the duplicate
   request again.

   A description of an early implementation of a duplicate request cache
   can be found in [Juszczak].

   A retransmitted SETACL that a server processes after a later SETACL
   on the same object reinstates the older ACL.  A duplicate request
   cache narrows that window but does not close it: the cache is finite,
   and an entry can age out before the retransmission arrives (see
   Section 10.1).  A client therefore cannot depend on whether a server
   caches SETACL replies.

Lever                     Expires 19 March 2027                [Page 45]
Internet-Draft              NFS ACL Protocol              September 2026

7.3.  Caching Policies

   The NFS protocol does not define a policy for caching on the client
   or server.  In particular, there is no support for strict cache
   consistency between a client and server, nor between different
   clients.

   The NFS_ACL protocol does not mandate a specific caching policy for
   ACLs or information retrieved via the ACCESS procedure.  However, a
   high-quality client implementation that seeks good performance might
   choose to revalidate cached access control information with the same
   regularity that it invalidates normal file attributes.

8.  XDR Protocol Definition

   This section contains a description of the core features of the
   NFS_ACL protocol, version 2 and version 3, expressed in the XDR
   language [RFC4506].

   NFS_ACL version 2 and NFS_ACL version 3 are independent versions of a
   single RPC program.  Their XDR definitions are given here as two
   separate specifications, one in Section 8.2 and one in Section 8.3,
   and each version is intended to form its own XDR file.  Presenting
   the two versions as separate files lets an implementer extract and
   compile only the protocol version of interest.  The code component
   license and the data types common to both versions appear once, in
   Section 8.1.  Prepending those common definitions to the definitions
   of a single version yields a complete, independently compilable XDR
   file for that version: nfs_acl2.x for version 2, and nfs_acl3.x for
   version 3.

   This description is provided in a way that makes it simple to extract
   into ready-to-compile form.  In the sections that follow, each line
   of XDR text is preceded by the marker "///".  A line of the form "///
   @@FILE name" marks the start of the version-specific definitions
   belonging to the file "name"; the XDR text preceding the first such
   marker, in Section 8.1, is common to both files.  The reader can
   apply the following shell script to this document to extract the two
   XDR files.

Lever                     Expires 19 March 2027                [Page 46]
Internet-Draft              NFS ACL Protocol              September 2026

   <CODE BEGINS>
   #!/bin/sh
   awk '
     /^ *\/\/\// {
       line = $0
       sub(/^ *\/\/\/ ?/, "", line)
       if (line ~ /^@@FILE /) { split(line, a, " "); f = a[2]; next }
       if (f == "") common = common line "\n"
       else         part[f] = part[f] line "\n"
       next
     }
     END { for (f in part) printf "%s%s", common, part[f] > f }
   '
   <CODE ENDS>

   That is, if the above script is stored in a file called "extract.sh"
   and this document is in a file called "spec.txt", then

   <CODE BEGINS>
   sh extract.sh < spec.txt
   <CODE ENDS>

   writes two files into the current directory: nfs_acl2.x, containing
   the common definitions followed by the NFS_ACL version 2 definitions
   of Section 8.2, and nfs_acl3.x, containing the common definitions
   followed by the NFS_ACL version 3 definitions of Section 8.3.  Each
   file is a complete and independently compilable XDR description of
   one protocol version.

8.1.  Code Component License

   Code components extracted from this document must include the
   following license text.  When the extracted XDR code is combined with
   other complementary XDR code which itself has an identical license,
   only a single copy of the license text need be preserved.

   <CODE BEGINS>
   /// /*
   ///  * Copyright (c) 2024 IETF Trust and the persons
   ///  * identified as authors of the code.  All rights reserved.
   ///  *
   ///  * The authors of the code are:
   ///  * Oracle
   ///  *
   ///  * Redistribution and use in source and binary forms, with
   ///  * or without modification, are permitted provided that the
   ///  * following conditions are met:
   ///  *

Lever                     Expires 19 March 2027                [Page 47]
Internet-Draft              NFS ACL Protocol              September 2026

   ///  * - Redistributions of source code must retain the above
   ///  *   copyright notice, this list of conditions and the
   ///  *   following disclaimer.
   ///  *
   ///  * - Redistributions in binary form must reproduce the above
   ///  *   copyright notice, this list of conditions and the
   ///  *   following disclaimer in the documentation and/or other
   ///  *   materials provided with the distribution.
   ///  *
   ///  * - Neither the name of Internet Society, IETF or IETF
   ///  *   Trust, nor the names of specific contributors, may be
   ///  *   used to endorse or promote products derived from this
   ///  *   software without specific prior written permission.
   ///  *
   ///  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS
   ///  *   AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
   ///  *   WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   ///  *   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
   ///  *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO
   ///  *   EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
   ///  *   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
   ///  *   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   ///  *   NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
   ///  *   SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   ///  *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   ///  *   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   ///  *   OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
   ///  *   IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
   ///  *   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   ///  */
   ///
   /// const NFS_ACL_MAX_ENTRIES = 1024;
   ///
   /// typedef unsigned int uid;
   /// typedef unsigned short o_mode;
   ///
   /// /*
   ///  * This is the format of an ACL which is passed over the network.
   ///  */
   /// struct aclent {
   ///     int type;
   ///     uid id;
   ///     o_mode perm;
   /// };
   ///
   /// /*
   ///  * The values for the type element of the aclent structure.
   ///  */

Lever                     Expires 19 March 2027                [Page 48]
Internet-Draft              NFS ACL Protocol              September 2026

   /// const NA_USER_OBJ = 0x1;          /* object owner */
   /// const NA_USER = 0x2;              /* additional users */
   /// const NA_GROUP_OBJ = 0x4;         /* owning group of the object */
   /// const NA_GROUP = 0x8;             /* additional groups */
   /// const NA_CLASS_OBJ = 0x10;        /* file group class and */
   ///                                   /* mask entry */
   /// const NA_OTHER_OBJ = 0x20;        /* other entry for the object */
   /// const NA_ACL_DEFAULT = 0x1000;    /* default flag */
   ///
   /// /*
   ///  * The bit field values for the perm element of the aclent
   ///  * structure.  The three values can be combined to form any
   ///  * of the 8 combinations.
   ///  */
   /// const NA_READ = 0x4;                /* read permission */
   /// const NA_WRITE = 0x2;               /* write permission */
   /// const NA_EXEC = 0x1;                /* exec permission */
   ///
   /// /*
   ///  * This is the structure which contains the ACL entries for a
   ///  * particular entity.  It contains the ACL entries which apply
   ///  * to this object plus any default ACL entries which are
   ///  * inherited by its children.
   ///  *
   ///  * The values for the mask field are defined below.
   ///  */
   /// struct secattr {
   ///     unsigned int mask;
   ///     int aclcnt;
   ///     aclent aclent<NFS_ACL_MAX_ENTRIES>;
   ///     int dfaclcnt;
   ///     aclent dfaclent<NFS_ACL_MAX_ENTRIES>;
   /// };
   ///
   /// /*
   ///  * The values for the mask element of the secattr struct as well
   ///  * as for the mask element in the arguments in the GETACL2 and
   ///  * GETACL3 procedures.
   ///  */
   /// const NA_ACL = 0x1;             /* aclent contains a valid list */
   /// const NA_ACLCNT = 0x2;          /* number of entries in the */
   ///                                 /* aclent list */
   /// const NA_DFACL = 0x4;           /* dfaclent contains a valid list */
   /// const NA_DFACLCNT = 0x8;        /* number of entries in the */
   ///                                 /* dfaclent list */
   ///
   /// /*
   ///  * Share the ports with the NFS service.

Lever                     Expires 19 March 2027                [Page 49]
Internet-Draft              NFS ACL Protocol              September 2026

   ///  */
   /// const NFS_ACL_PORT = 2049;
   /// const NFS_ACL_RDMA_PORT = 20049;
   <CODE ENDS>

8.2.  NFS_ACL Version 2

   The following definitions, together with the common definitions in
   Section 8.1, form the file nfs_acl2.x.

   <CODE BEGINS>
   /// @@FILE nfs_acl2.x
   ///
   /// /*
   ///  * XDR data types inherited from the NFS version 2 protocol
   ///  */
   ///
   /// enum ftype {
   ///     NFNON = 0,
   ///     NFREG = 1,
   ///     NFDIR = 2,
   ///     NFBLK = 3,
   ///     NFCHR = 4,
   ///     NFLNK = 5
   /// };
   ///
   /// const FHSIZE = 32;
   /// typedef opaque fhandle[FHSIZE];
   ///
   /// struct timeval {
   ///     unsigned int seconds;
   ///     unsigned int useconds;
   /// };
   ///
   /// struct fattr {
   ///     ftype        type;
   ///     unsigned int mode;
   ///     unsigned int nlink;
   ///     unsigned int uid;
   ///     unsigned int gid;
   ///     unsigned int size;
   ///     unsigned int blocksize;
   ///     unsigned int rdev;
   ///     unsigned int blocks;
   ///     unsigned int fsid;
   ///     unsigned int fileid;
   ///     timeval      atime;
   ///     timeval      mtime;

Lever                     Expires 19 March 2027                [Page 50]
Internet-Draft              NFS ACL Protocol              September 2026

   ///     timeval      ctime;
   /// };
   ///
   /// /*
   ///  * ACL error codes; the numeric values match codes with the same
   ///  * name used in NFS version 2.
   ///  */
   /// enum aclstat2 {
   ///     ACL2_OK = 0,
   ///     ACL2ERR_PERM = 1,
   ///     ACL2ERR_NOENT = 2,
   ///     ACL2ERR_IO = 5,
   ///     ACL2ERR_ACCES = 13,
   ///     ACL2ERR_INVAL = 22,
   ///     ACL2ERR_NOSPC = 28,
   ///     ACL2ERR_ROFS = 30,
   ///     ACL2ERR_NOTSUPP = 45,
   ///     ACL2ERR_DQUOT = 69,
   ///     ACL2ERR_STALE = 70
   /// };
   ///
   /// /*
   ///  * NFS_ACL version 2 procedure arguments and results
   ///  */
   ///
   /// struct GETACL2args {
   ///     fhandle fh;
   ///     unsigned int mask;
   /// };
   ///
   /// struct GETACL2resok {
   ///     fattr attr;
   ///     secattr acl;
   /// };
   ///
   /// union GETACL2res switch (aclstat2 status) {
   /// case ACL2_OK:
   ///     GETACL2resok resok;
   /// default:
   ///     void;
   /// };
   ///
   /// struct SETACL2args {
   ///     fhandle fh;
   ///     secattr acl;
   /// };
   ///
   /// struct SETACL2resok {

Lever                     Expires 19 March 2027                [Page 51]
Internet-Draft              NFS ACL Protocol              September 2026

   ///     fattr attr;
   /// };
   ///
   /// union SETACL2res switch (aclstat2 status) {
   /// case ACL2_OK:
   ///     SETACL2resok resok;
   /// default:
   ///     void;
   /// };
   ///
   /// struct GETATTR2args {
   ///     fhandle fh;
   /// };
   ///
   /// struct GETATTR2resok {
   ///     fattr attr;
   /// };
   ///
   /// union GETATTR2res switch (aclstat2 status) {
   /// case ACL2_OK:
   ///     GETATTR2resok resok;
   /// default:
   ///     void;
   /// };
   ///
   /// struct ACCESS2args {
   ///     fhandle fh;
   ///     unsigned int access;
   /// };
   ///
   /// const ACCESS2_READ = 0x1;     /* read data or */
   ///                               /* readdir a directory */
   /// const ACCESS2_LOOKUP = 0x2;   /* lookup a name in a directory */
   /// const ACCESS2_MODIFY = 0x4;   /* rewrite existing file data or */
   ///                               /* modify existing directory */
   ///                               /* entries */
   /// const ACCESS2_EXTEND = 0x8;   /* write new data or */
   ///                               /* add directory entries */
   /// const ACCESS2_DELETE = 0x10;  /* delete existing directory entry */
   /// const ACCESS2_EXECUTE = 0x20; /* execute file */
   ///                               /* (no meaning for a directory) */
   ///
   /// struct ACCESS2resok {
   ///     fattr attr;
   ///     unsigned int access;
   /// };
   ///
   /// union ACCESS2res switch (aclstat2 status) {

Lever                     Expires 19 March 2027                [Page 52]
Internet-Draft              NFS ACL Protocol              September 2026

   /// case ACL2_OK:
   ///     ACCESS2resok resok;
   /// default:
   ///     void;
   /// };
   ///
   /// /*
   ///  * This is the definition for the GETXATTRDIR procedure which
   ///  * applies to NFS Version 2 files.
   ///  */
   /// struct GETXATTRDIR2args {
   ///     fhandle fh;
   ///     bool create;
   /// };
   ///
   /// struct GETXATTRDIR2resok {
   ///     fhandle fh;
   ///     fattr attr;
   /// };
   ///
   /// union GETXATTRDIR2res switch (aclstat2 status) {
   /// case ACL2_OK:
   ///     GETXATTRDIR2resok resok;
   /// default:
   ///     void;
   /// };
   ///
   /// program NFS_ACL_PROGRAM {
   ///     version NFS_ACL_V2 {
   ///         void
   ///             ACLPROC2_NULL(void) = 0;
   ///         GETACL2res
   ///             ACLPROC2_GETACL(GETACL2args) = 1;
   ///         SETACL2res
   ///             ACLPROC2_SETACL(SETACL2args) = 2;
   ///         GETATTR2res
   ///             ACLPROC2_GETATTR(GETATTR2args) = 3;
   ///         ACCESS2res
   ///             ACLPROC2_ACCESS(ACCESS2args) = 4;
   ///         GETXATTRDIR2res
   ///             ACLPROC2_GETXATTRDIR(GETXATTRDIR2args) = 5;
   ///     } = 2;
   /// } = 100227;
   <CODE ENDS>

Lever                     Expires 19 March 2027                [Page 53]
Internet-Draft              NFS ACL Protocol              September 2026

8.3.  NFS_ACL Version 3

   The following definitions, together with the common definitions in
   Section 8.1, form the file nfs_acl3.x.

   <CODE BEGINS>
   /// @@FILE nfs_acl3.x
   ///
   /// /*
   ///  * XDR data types inherited from the NFS version 3 protocol
   ///  */
   ///
   /// typedef unsigned hyper uint64;
   /// typedef unsigned long uint32;
   /// typedef uint64 fileid3;
   /// typedef uint32 uid3;
   /// typedef uint32 gid3;
   /// typedef uint64 size3;
   /// typedef uint32 mode3;
   ///
   /// enum ftype3 {
   ///     NF3REG    = 1,
   ///     NF3DIR    = 2,
   ///     NF3BLK    = 3,
   ///     NF3CHR    = 4,
   ///     NF3LNK    = 5,
   ///     NF3SOCK   = 6,
   ///     NF3FIFO   = 7
   /// };
   ///
   /// struct specdata3 {
   ///     uint32     specdata1;
   ///     uint32     specdata2;
   /// };
   ///
   /// const NFS3_FHSIZE = 64;
   ///
   /// struct nfs_fh3 {
   ///     opaque       data<NFS3_FHSIZE>;
   /// };
   ///
   /// struct nfstime3 {
   ///     uint32   seconds;
   ///     uint32   nseconds;
   /// };
   ///
   /// struct fattr3 {
   ///     ftype3     type;

Lever                     Expires 19 March 2027                [Page 54]
Internet-Draft              NFS ACL Protocol              September 2026

   ///     mode3      mode;
   ///     uint32     nlink;
   ///     uid3       uid;
   ///     gid3       gid;
   ///     size3      size;
   ///     size3      used;
   ///     specdata3  rdev;
   ///     uint64     fsid;
   ///     fileid3    fileid;
   ///     nfstime3   atime;
   ///     nfstime3   mtime;
   ///     nfstime3   ctime;
   /// };
   ///
   /// union post_op_attr switch (bool attributes_follow) {
   /// case TRUE:
   ///     fattr3   attributes;
   /// case FALSE:
   ///     void;
   /// };
   ///
   /// /*
   ///  * ACL error codes; the numeric values match codes with the same
   ///  * name used in NFS version 3.
   ///  */
   /// enum aclstat3 {
   ///     ACL3_OK = 0,
   ///     ACL3ERR_PERM = 1,
   ///     ACL3ERR_NOENT = 2,
   ///     ACL3ERR_IO = 5,
   ///     ACL3ERR_ACCES = 13,
   ///     ACL3ERR_INVAL = 22,
   ///     ACL3ERR_NOSPC = 28,
   ///     ACL3ERR_ROFS = 30,
   ///     ACL3ERR_DQUOT = 69,
   ///     ACL3ERR_STALE = 70,
   ///     ACL3ERR_BADHANDLE = 10001,
   ///     ACL3ERR_NOTSUPP = 10004,
   ///     ACL3ERR_SERVERFAULT = 10006,
   ///     ACL3ERR_JUKEBOX = 10008
   /// };
   ///
   /// /*
   ///  * NFS_ACL version 3 procedure arguments and results
   ///  */
   ///
   /// struct GETACL3args {
   ///     nfs_fh3 fh;

Lever                     Expires 19 March 2027                [Page 55]
Internet-Draft              NFS ACL Protocol              September 2026

   ///     unsigned int mask;
   /// };
   ///
   /// struct GETACL3resok {
   ///     post_op_attr attr;
   ///     secattr acl;
   /// };
   ///
   /// struct GETACL3resfail {
   ///     post_op_attr attr;
   /// };
   ///
   /// union GETACL3res switch (aclstat3 status) {
   /// case ACL3_OK:
   ///     GETACL3resok resok;
   /// default:
   ///     GETACL3resfail resfail;
   /// };
   ///
   /// struct SETACL3args {
   ///     nfs_fh3 fh;
   ///     secattr acl;
   /// };
   ///
   /// struct SETACL3resok {
   ///     post_op_attr attr;
   /// };
   ///
   /// struct SETACL3resfail {
   ///     post_op_attr attr;
   /// };
   ///
   /// union SETACL3res switch (aclstat3 status) {
   /// case ACL3_OK:
   ///     SETACL3resok resok;
   /// default:
   ///     SETACL3resfail resfail;
   /// };
   ///
   /// /*
   ///  * This is the definition for the GETXATTRDIR procedure which
   ///  * applies to NFS Version 3 files.
   ///  */
   /// struct GETXATTRDIR3args {
   ///     nfs_fh3 fh;
   ///     bool create;
   /// };
   ///

Lever                     Expires 19 March 2027                [Page 56]
Internet-Draft              NFS ACL Protocol              September 2026

   /// struct GETXATTRDIR3resok {
   ///     nfs_fh3 fh;
   ///     post_op_attr attr;
   /// };
   ///
   /// union GETXATTRDIR3res switch (aclstat3 status) {
   /// case ACL3_OK:
   ///     GETXATTRDIR3resok resok;
   /// default:
   ///     void;
   /// };
   ///
   /// program NFS_ACL_PROGRAM {
   ///     version NFS_ACL_V3 {
   ///         void
   ///             ACLPROC3_NULL(void) = 0;
   ///         GETACL3res
   ///             ACLPROC3_GETACL(GETACL3args) = 1;
   ///         SETACL3res
   ///             ACLPROC3_SETACL(SETACL3args) = 2;
   ///         GETXATTRDIR3res
   ///             ACLPROC3_GETXATTRDIR(GETXATTRDIR3args) = 3;
   ///     } = 3;
   /// } = 100227;
   <CODE ENDS>

9.  Implementation Status

      |  This section is to be removed before publishing this document
      |  as an RFC.

   This section records the status of known implementations of the
   protocol defined by this specification at the time of posting of this
   Internet-Draft, and is based on a proposal described in [RFC7942].
   The description of implementations in this section is intended to
   assist the IETF in its decision processes in progressing drafts to
   RFCs.

   Please note that the listing of any individual implementation here
   does not imply endorsement by the IETF.  Furthermore, no effort has
   been spent to verify the information presented here that was supplied
   by IETF contributors.  This is not intended as, and must not be
   construed to be, a catalog of available implementations or their
   features.  Readers are advised to note that other implementations may
   exist.

Lever                     Expires 19 March 2027                [Page 57]
Internet-Draft              NFS ACL Protocol              September 2026

9.1.  Solaris NFS server and client

   Organization: Oracle

   URL: https://www.oracle.com (https://www.oracle.com)

   Maturity: Complete.

   Coverage: All procedures are implemented.

   Licensing: CDDL

   Implementation experience: The Solaris implementation is the origin
   of the nfs_acl.x file from which this document is derived
   [OpenSolaris].  Its server does not consult the "mask" element of a
   SETACL request, and what it stores and returns depends on the
   exported file system: UFS stores exactly the entries a SETACL
   carries, while ZFS rejects SETACL with ACL2ERR_NOTSUPP or
   ACL3ERR_NOTSUPP and answers GETACL with a manufactured ACL (see
   Section 4.6.2.1 and Section 4.6.3.3).

9.2.  Linux NFS server and client

   Organization: The Linux Foundation

   URL: https://www.kernel.org (https://www.kernel.org)

   Maturity: Complete.

   Coverage: The Linux NFS server implements all procedures except
   GETXATTRDIR in both versions of the protocol.  The Linux NFS client
   implements the NFS_ACL protocol only for version 3; it does not
   implement NFS_ACL version 2.

   Licensing: GPLv2

   Implementation experience: The initial Linux implementation of the
   NFS_ACL protocol is described in [Gruenbacher], and subsequent
   modifications can be found in the Linux kernel source code repository
   [Linux].

   [Gruenbacher] notes several minor differences between the Linux and
   Solaris implementations of ACLs.  The one visible on the wire, the
   treatment of the mask entry in a four-entry ACL, is described in
   Section 3.4.4.2.

Lever                     Expires 19 March 2027                [Page 58]
Internet-Draft              NFS ACL Protocol              September 2026

   The Linux NFS_ACL implementation already builds the version 2 and
   version 3 protocols from two separate source files, presently
   maintained by hand.  Work is underway to generate those files from
   the separate XDR descriptions in Section 8.2 and Section 8.3 instead.

10.  Security Considerations

   NFS_ACL was designed for a single administrative domain on a
   physically protected network.  This section considers a broader
   environment: deployment across the global Internet, spanning
   administrative boundaries, with no firewall assumed between a client
   and its server.

   NFS_ACL carries no security mechanism of its own.  It inherits what
   the RPC layer provides, and it names the users and groups in an
   Access Control Entry using the identities that layer supplies (see
   Section 3.3).  What follows therefore turns on the choice of RPC
   authentication flavor and transport.

   Attacks on the NFS version 2 and version 3 protocols themselves are
   out of scope.  An attacker who can read or alter file content
   directly through NFS gains nothing by attacking the ACL that governs
   it, and [RFC2623] covers those protocols.  Attacks on the local file
   system that stores an ACL, and on the mechanism by which a site maps
   users to uid and gid values, are out of scope as well: both are
   shared with the NFS service that NFS_ACL accompanies, and neither is
   reachable through the NFS_ACL protocol itself.

10.1.  Attacks on an Unprotected Exchange

   Running NFS_ACL over AUTH_SYS on an unprotected transport defends
   against none of the following.

   Eavesdropping:  A GETACL reply carries an object's full Access
      Control List.  An observer learns which users and groups hold
      access to the object, and the uid and gid values that name them.
      The list is worth reading even when the file content is not.

   Modification and man-in-the-middle:  Altering a SETACL argument
      changes the access control the server installs.  Altering a GETACL
      reply gives the client a false view of it.  Altering an ACCESS
      reply misleads a client that uses the result to decide whether to
      attempt an operation.

   Message insertion:  AUTH_SYS supplies no verifier by which a
      credential can be validated (Section 14 of [RFC5531]).  An
      attacker who can reach the server and holds a file handle for an
      object can forge a SETACL request bearing the file owner's uid.

Lever                     Expires 19 March 2027                [Page 59]
Internet-Draft              NFS ACL Protocol              September 2026

   Replay:  SETACL is not idempotent.  A replayed SETACL reinstates an
      ACL that the file owner has since replaced.  The duplicate request
      cache (Section 7.2) recognizes a retransmission, but it is finite:
      a replay delayed beyond its reach is processed as a new request.

   Message deletion and denial of service:  Discarding NFS_ACL messages
      denies a client the ability to read or change an ACL.  An attacker
      positioned to do this can discard the NFS traffic alongside it, so
      NFS_ACL neither adds to nor reduces the exposure.

   Section 14 of [RFC5531] states that AUTH_SYS should not be used for
   services that permit clients to modify data.  SETACL modifies the
   data that governs every other access to the object.  Section 4.1
   reports that implementations permit any authentication flavor on
   procedures other than NULL.  That records what implementations
   accept; it does not recommend AUTH_SYS for SETACL.  Section 10.2
   states what a deployment should do instead.

10.2.  Protecting an Exchange

   Two mechanisms available to an NFS version 2 or version 3 deployment
   apply unchanged to NFS_ACL, which shares the transport and port of
   the NFS service it accompanies.

   RPCSEC_GSS [RFC2203] [RFC7861] replaces AUTH_SYS with a GSS-API
   mechanism.  Its integrity service authenticates the RPC peer and
   detects alteration of each call and reply, addressing insertion,
   modification, and man-in-the-middle.  Per-request sequence numbers
   detect replay within a window the server sizes.  Integrity leaves ACL
   content readable on the wire; the privacy service encrypts arguments
   and results and closes that gap.  [RFC2623] describes how the NFS
   version 2 and version 3 protocols use RPCSEC_GSS and Kerberos V5.

   RPC-over-TLS [RFC9289] protects the transport connection rather than
   the individual RPC message.  It supplies confidentiality and
   integrity for everything on the connection and can authenticate the
   peer host.  It does not authenticate the RPC user, so a server
   relying on it alone still takes on trust the uid and gid each request
   carries.

   A deployment that exposes NFS_ACL beyond a physically protected
   network should protect the exchange with a mechanism that detects
   alteration of each call and reply and that authenticates the source
   of each request, so that neither the uid and gid a request carries
   nor the ACL entries in its arguments and results can be altered by a
   man-in-the-middle, and so that a forged credential is detected.

Lever                     Expires 19 March 2027                [Page 60]
Internet-Draft              NFS ACL Protocol              September 2026

10.3.  Residual Risk

   Neither mechanism changes what an authenticated caller may do.
   GETACL carries no permission check of its own (see Section 3.3), so a
   caller holding a file handle can often read the object's ACL and the
   user and group IDs it names.  A deployment that treats ACL membership
   as sensitive cannot rely on the protocol to withhold it.

   A server that maps a privileged caller to a less privileged identity
   (see Section 7.1) decides on the strength of the uid the request
   carries.  Under AUTH_SYS the client supplies that value, so the
   mapping deters accident rather than attack.

   The "id" element of an Access Control Entry is a uid or gid in the
   server's numeric space.  RPCSEC_GSS maps the caller's principal to a
   local identity (see Section 3.3), but no authentication flavor
   translates the identities an ACL names.  Across an administrative
   boundary, a client that writes an ACL names users and groups by
   numbers it cannot confirm are the server's, and a client that reads
   one cannot resolve the numbers it receives.

   An ACL a client has read, and the result of an ACCESS procedure,
   describe the server's decision at the moment it was made.  The server
   alone authorizes access (see Section 3.4.4.1) and can revoke it at
   any time.  A client that caches either and relies on it later may be
   relying on information that no longer holds.

11.  IANA Considerations

   In accordance with Section 13 of [RFC5531], the editor requests that
   IANA update the entry for the NFS ACL service in the RPC Program
   Numbers registry to add the current document as a Reference.

12.  References

12.1.  Normative References

   [RFC4506]  Eisler, M., Ed., "XDR: External Data Representation
              Standard", STD 67, RFC 4506, DOI 10.17487/RFC4506, May
              2006, <https://www.rfc-editor.org/rfc/rfc4506>.

   [RFC5531]  Thurlow, R., "RPC: Remote Procedure Call Protocol
              Specification Version 2", RFC 5531, DOI 10.17487/RFC5531,
              May 2009, <https://www.rfc-editor.org/rfc/rfc5531>.

12.2.  Informative References

Lever                     Expires 19 March 2027                [Page 61]
Internet-Draft              NFS ACL Protocol              September 2026

   [Gruenbacher]
              Grünbacher, A., "POSIX Access Control Lists on Linux",
              Proceedings of the FREENIX Track: 2003 USENIX Annual
              Technical Conference, pp. 259-272, ISBN 1-931971-11-0,
              January 2003.

   [I-D.ietf-nfsv4-posix-acls]
              Macklem, R., "POSIX Draft ACL support for Network File
              System Version 4, Minor Version 2", Work in Progress,
              Internet-Draft, draft-ietf-nfsv4-posix-acls-02, 7
              September 2026, <https://datatracker.ietf.org/doc/html/
              draft-ietf-nfsv4-posix-acls-02>.

   [IEEE]     Institute of Electrical and Electronics Engineers, "IEEE
              1003.1e and 1003.2c: Draft Standard for Information
              Technology-- Portable Operating System Interface (POSIX)--
              Part 1: System Application Program Interface (API) and
              Part 2: Shell and Utilities, draft 17", January 1997.

   [Juszczak] Juszczak, C., "Improving the Performance and Correctness
              of an NFS Server", USENIX Conference Proceedings, USENIX
              Association, Berkeley, CA, pp. 53-63, January 1989.

   [Linux]    "Linux kernel source code", n.d.,
              <https://www.kernel.org>.

   [OpenSolaris]
              "Archived OpenSolaris source code: usr/src/head/rpcsvc/
              nfs_acl.x", June 2005,
              <https://github.com/kofemann/opensolaris/blob/3dfbd886134b95a44386706352b92788c30f9569/usr/src/
              head/rpcsvc/nfs_acl.x>.

   [POSIX]    Institute of Electrical and Electronics Engineers, "IEEE
              Std 1003.1-2001 (Open Group Technical Standard, Issue 6),
              Standard for Information Technology-- Portable Operating
              System Interface (POSIX)", ISBN 0-7381-3010-9, 2001.

   [RFC1094]  Nowicki, B., "NFS: Network File System Protocol
              specification", RFC 1094, DOI 10.17487/RFC1094, March
              1989, <https://www.rfc-editor.org/rfc/rfc1094>.

   [RFC1813]  Callaghan, B., Pawlowski, B., and P. Staubach, "NFS
              Version 3 Protocol Specification", RFC 1813,
              DOI 10.17487/RFC1813, June 1995,
              <https://www.rfc-editor.org/rfc/rfc1813>.

Lever                     Expires 19 March 2027                [Page 62]
Internet-Draft              NFS ACL Protocol              September 2026

   [RFC1833]  Srinivasan, R., "Binding Protocols for ONC RPC Version 2",
              RFC 1833, DOI 10.17487/RFC1833, August 1995,
              <https://www.rfc-editor.org/rfc/rfc1833>.

   [RFC2119]  Bradner, S., "Key words for use in RFCs to Indicate
              Requirement Levels", BCP 14, RFC 2119,
              DOI 10.17487/RFC2119, March 1997,
              <https://www.rfc-editor.org/rfc/rfc2119>.

   [RFC2203]  Eisler, M., Chiu, A., and L. Ling, "RPCSEC_GSS Protocol
              Specification", RFC 2203, DOI 10.17487/RFC2203, September
              1997, <https://www.rfc-editor.org/rfc/rfc2203>.

   [RFC2623]  Eisler, M., "NFS Version 2 and Version 3 Security Issues
              and the NFS Protocol's Use of RPCSEC_GSS and Kerberos V5",
              RFC 2623, DOI 10.17487/RFC2623, June 1999,
              <https://www.rfc-editor.org/rfc/rfc2623>.

   [RFC7530]  Haynes, T., Ed. and D. Noveck, Ed., "Network File System
              (NFS) Version 4 Protocol", RFC 7530, DOI 10.17487/RFC7530,
              March 2015, <https://www.rfc-editor.org/rfc/rfc7530>.

   [RFC7861]  Adamson, A. and N. Williams, "Remote Procedure Call (RPC)
              Security Version 3", RFC 7861, DOI 10.17487/RFC7861,
              November 2016, <https://www.rfc-editor.org/rfc/rfc7861>.

   [RFC7942]  Sheffer, Y. and A. Farrel, "Improving Awareness of Running
              Code: The Implementation Status Section", BCP 205,
              RFC 7942, DOI 10.17487/RFC7942, July 2016,
              <https://www.rfc-editor.org/rfc/rfc7942>.

   [RFC8166]  Lever, C., Ed., Simpson, W., and T. Talpey, "Remote Direct
              Memory Access Transport for Remote Procedure Call Version
              1", RFC 8166, DOI 10.17487/RFC8166, June 2017,
              <https://www.rfc-editor.org/rfc/rfc8166>.

   [RFC8174]  Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC
              2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174,
              May 2017, <https://www.rfc-editor.org/rfc/rfc8174>.

   [RFC8267]  Lever, C., "Network File System (NFS) Upper-Layer Binding
              to RPC-over-RDMA Version 1", RFC 8267,
              DOI 10.17487/RFC8267, October 2017,
              <https://www.rfc-editor.org/rfc/rfc8267>.

Lever                     Expires 19 March 2027                [Page 63]
Internet-Draft              NFS ACL Protocol              September 2026

   [RFC8881]  Noveck, D., Ed. and C. Lever, "Network File System (NFS)
              Version 4 Minor Version 1 Protocol", RFC 8881,
              DOI 10.17487/RFC8881, August 2020,
              <https://www.rfc-editor.org/rfc/rfc8881>.

   [RFC9289]  Myklebust, T. and C. Lever, Ed., "Towards Remote Procedure
              Call Encryption by Default", RFC 9289,
              DOI 10.17487/RFC9289, September 2022,
              <https://www.rfc-editor.org/rfc/rfc9289>.

Appendix A.  Source Material

   The on-the-wire protocol described here is intended to match existing
   de facto implementations of NFS_ACL.

   The source for the XDR specification provided in this document is the
   nfs_acl.x file as found in published versions of the OpenSolaris
   source code base [OpenSolaris], an open source descendant of Solaris.

   However, there are a few changes to the protocol as it was originally
   described in the OpenSolaris source code base.

A.1.  Redaction of NFS_ACL Version 4

   Version 4 of NFS_ACL is described in the original nfs_acl.x source
   file this way:

      This is a transitional interface to enable Solaris NFSv4 clients
      to manipulate ACLs on Solaris servers until the spec is complete
      enough to implement this inside the NFSv4 protocol itself.  NFSv4
      does handle extended attributes in-band.

   Because the two non-NULL procedures in this version of the NFS_ACL
   protocol were used only as part of a Solaris prototype and there are
   no other implementations of NFS_ACL version 4, it is not included in
   the protocol description appearing in this document.

A.2.  Extension of NFS_ACL

   Extension of this legacy protocol is out of scope for an
   Informational document whose purpose is to describe existing
   implementations.

A.3.  Code Compilation Requirements

   The original nfs_acl.x file that appears in the OpenSolaris code base
   did not compile using the widely-available rpcgen tool.

Lever                     Expires 19 March 2027                [Page 64]
Internet-Draft              NFS ACL Protocol              September 2026

   *  The file does not include a definition of the ACL2_OK or ACL3_OK
      constants used in definitions of result unions.

   *  The file does not include definitions of NFS protocol elements
      that are shared with the NFS_ACL protocol, such as fhandle and
      post_op_attr.

   The XDR specification provided in this document rectifies those
   omissions to provide a complete and compilable XDR language
   description of the NFS_ACL protocol.

Acknowledgments

   The editor is grateful to Bill Baker, Frank Batschulat, Wim
   Coekaerts, Andreas Gruenbacher, Rick Macklem, Greg Marsden, Martin
   Thomson, Rob Thurlow, and Jim Wright for their input and support.

   Special thanks to Area Director Gorry Fairhurst, NFSV4 Working Group
   Chair Brian Pawlowski, and NFSV4 Working Group Secretary Thomas
   Haynes for their patience, guidance, and oversight.

Author's Address

   Chuck Lever (editor)
   Independent
   United States of America
   Email: cel-ietf@chucklever.net

Lever                     Expires 19 March 2027                [Page 65]