Show Source

This is meant to be an informative document of the current behavior of OpenAFS file servers’ permission management logic. It is being written in hopes of its ultimate utility towards a normative specification document.

Note

We will often need to refer to line numbers of the code; for the sake of consistency, we will always tag these with the git revision control hash (abbreviated, thankfully) so that there is no risk of ambiguity even as this document and the code undergo parallel revisions.

References are given by [git revision:]file name[:command], where “command” is either a line number or a / followed by a POSIX regex. Due to AFS source conventions, function names will often appear as “f.c:/^Func”.

Descriptive Vocabulary

The OpenAFS file server logic checks several bits of data within the system when it makes a permission decision. Below, we will use certain shorthands for these fields.

  • Client membership an “administrative” group, which defaults to system:administrators (PTS ID well-known as -204). (ADMIN) (See 6e167d4:src/viced/viced.c:/SystemId for details of group selection.)
  • Client rights as specified in the ACL of the directory containing the target. (ACL)
  • The UNIX owner UID field (holding a PTS ID) of the target of the operation. (UID)
  • The UNIX user permission flags of the target of the operation. (UMODE, part of the UNIX MODE bits: OWNERREAD, OWNERWRITE, OWNEREXEC)
  • The UNIX owner UID field of the root directory of the volume containing the target. This field holds a PTS ID which is said to be the volume owner. (VOLUID)
  • The UNIX mode special bits (SPEC), notably S_ISUID (04000) and S_ISGID (02000).

Optionally, the server may be compiled with -DUSE_GROUP_PERMS (it is not by default) which brings in additional checks of the UNIX group owner (GID) and permission flags (GMODE, part of the UNIX MODE bits: GROUPREAD, GROUPWRITE, GROUPREXEC) of the target of the operation.

Note that all other UNIX mode bits (S_IRWXO, S_ISVTX, and 010000 and above) are ignored. (If USE_GROUP_PERMS is disabled, which is the default, the S_IRWXG bits are also ignored.)

Permission Flags

OpenAFS defines several ACL flags. Much of this information is available in the manual pages for fs setacl and fs listacl but is reproduced here for completeness. Each directory object has its associated ACL, which is a collection of Positive and Negative Access List Entries, which are in turn a pair of a PTS identity and a set of permission flags.

The permission flags defined are as follows; in all cases, the direct object of the definition is restricted to those objects in the current directory.

Administrate Adjust this ACL
Lookup Enumerate the objects.
Delete Remove objects.
Read Fetch the contents of file objects.
Write Mutate the contents of file objects.
Insert Create new objects.
locK Acquire locks on files.
A - H Eight flag bits defined solely for user applications’ use. These are (intended to be) uninterpreted by AFS itself.

These flags are stored by the AFS file server in a 32-bit word thus (see libacl/prs_fs.h and 6e167d4:venus/fs.c:/^PRights [there is a patch pending that would make this libacl/aclprint.c]):

H G F E D C B A                                   a k d l i w r

Unallocated bits are communicated during ACL operations but ignored during server processing (indeed, libacl/aclprocs.c:/^acl_Externalize_pr simply prints out the field with the sprintf format code %d; libacl/aclprocs.c:/^acl_Internalize_pr dually uses sscanf %d).

Interpreting an ACL

The AFS User Guide, in section “The AFS ACL Permissions”, details the process of computing the rights conferred by a given ACL a given PTS ID. A slight formalization is attempted here.

  1. The permissions of each entry which names either

    • the given ID explicitly or
    • a group to which that ID belongs

    are ORed together to compute positive permissions. That is, if any entry asserts a flag, that flag is asserted at the end of this scan.

  2. The same process is repeated on the negative ACL entries, computing a set of negative permissions.

  3. The final result is the postive permissions bitwise-anded with the negation of the negative permissions.

This is implemented in src/viced/afsfileprocs.c:/^GetRights.

Todo

Which has not yet been audited to verify its conformance.

Implicit Permissions

  • The insert flag is intended to allow users to also establish the contents of file objects; as such it confers the rights to write to file objects whose UID matches the client’s PTS ID. (Specified in the manual for fs setacl section DROPBOXES; CODE: 6e167d4:src/viced/afsfileprocs.c:1080) There are some caveats relevant here:

    • The manual pages describe “dropbox” permissions (list & insert) as conferring the ability to write a file’s contents once and never again. This is at best viewed as a suggestion of client cache manager behavior; it is not possible to implement this in OpenAFS as the server has no notion of opened or closed files, so the description given in this document above is more accurate from a server and protocol perspective.
    • It appears to be permitted, from the documentation of fs setacl that a server may, but is not obligated to, refuse read requests by anonymous clients of files whose containing directory confers “dropbox” permissions to any PTS ID. This does not appear to be implemented in the present OpenAFS source code, as of 6e167d4.
    • The same paragraph as above suggests that the server is permitted to fail creation or write requests from anonymous clients even if the permissions calculated would (otherwise) permit it. This does not appear to be implemented in the present OpenAFS source code, as of 6e167d4.
  • The VOLUID PTS ID implicitly has Administrate permission on all directories contained in that volume. This cannot be removed, even with negative access list entries. See the call to VolumeOwner at 6e167d4:src/viced/afsfileprocs.c:1108 in the store (and CHK_STOREACL) branch of src/viced/afsfileprocs.c:/^Check_PermissionRights.

    Note

    In prior releases, the UID PTS ID of each directory also had implicit Administrate permission within that directory, but this is no longer true.

  • Members of the administrative group (ADMIN) implicitly have all permissions specified by the server’s -implicit argument, which defaults to Lookup. See 6e167d4:src/viced/afsfileprocs.c:778 (in /^GetRights) and 6e167d4:src/viced/viced.c:133. Note that this impacts every condition that tests ACL in this document.

  • Members of the administrative group (ADMIN) may additionally implicitly have Lookup permission for certain tests if the server is compiled with -DADMIN_IMPLICIT_LOOKUP (not default). (This is not implemented in /^GetRights and so does not affect the use of ACL)

  • Members of the administrative group (ADMIN) additionally implicitly have Administrate permission (6e167d4:src/viced/afsfileprocs.c:1107 in /^Check_PermissionRights) and others. Membership testing is performed by src/viced/viced.c:/^VanillaUser and this is called in several places. (This, too, is not implemented in /^GetRights and so does not affect the use of ACL)

    Todo

    Which should be enumerated here!

Default Permissions and Ownership

The act of creating an object is complicated and is orchestrated by src/viced/afsfileprocs.c:/^SRXAFSS_CreateFile or src/viced/afsfileprocs.c:/^SRXAFS_MakeDir as appropriate. See below for details, but an attempt at a short story is:

  • Whenever a directory is created, it inherits the ACL from its parent directory. (src/viced/afsfileprocs.c:/^SAFSS_MakeDir, specifically 6e167d4:src/viced/afsfileprocs.c:4484.)

  • Whenever an object of any type is created

    • The GID is inherited from the parent object: (overseen by src/viced/afsfileprocs.c:/^Alloc_NewVnode; see in particular 6e167d4:src/viced/afsfileprocs.c:1921).
    • The MODE is set to 0777. That is, the UMODE and GMODE bits are made all-permissive; the S_IRWXO bits are also all-permissive, but recall that these bits are ignored. (src/viced/afsfileprocs.c:/^Update_TargetVnodeStatus, in particular 6e167d4:src/viced/afsfileprocs.c:1680)
    • The client PTS ID is used to set the UID. (src/viced/afsfileprocs.c:/^Update_TargetVnodeStatus, in particular 6e167d4:src/viced/afsfileprocs.c:1681)
  • All creation operations allow the client to additionally specify metadata about the object to be created, notably including UID, GID, and MODE. If requested at creation, these operations will be performed, with some caveats: UID and GID may be changed arbitrarily, but MODE will always be restricted to a subset of 0777 unless the requesting client is an ADMIN. For details, see the internals of vnode update.

    Warning

    This should perhaps be moderately alarming!

    Because the create operations MakeDir, Symlink, and CreateFile all simply call CheckWriteMode and then pass their given struct AFSStoreStatus parameters to Update_TargetVnodeStatus, it is possible to create objects with arbitrary UID and GID; the checks that would be done on a StoreStatus call (in Check_PermissionRights) are bypassed.

    It is worth pointing out, perhaps, that the only reason that existing AFS deployments end up with UID being equal to the creating client’s PTS ID is because the existing CMs do not request SETOWNER on CreateFile. They do, however, request SETGROUP, which is permitted, making a likely laughingstock of most GID values.

    The author of this document is deeply confused as to why Check_PermissionRights then refuses to change GID fields (and possibly UID fields as well!); see below.

Client Operations

The current AFS file server RPC interface is defined in src/fsint/afsint.xg and enumerates the following 41 RPCs:

  • Data fetch calls: FetchData (130) and FetchData64 (65537)
  • Metadata fetch calls: FetchACL (131) and FetchStatus (132)
  • Data store calls: StoreData (133) and StoreData64 (65538)
  • Metadata store calls: StoreACL (134), StoreStatus (135), BulkStatus (155), and InlineBulkStatus (65536).
  • Deletion calls: RemoveFile (136) and RemoveDir (142)
  • Creation calls: CreateFile (137) and MakeDir (141)
  • Rename (138)
  • Link calls: Symlink (139), Link (140), and DFSSymlink (163)
  • “Old” locking calls: OldSetLock (143), OldExtendLock (144), OldReleaseLock (145)
  • “New” locking calls: SetLock (156), ExtendLock (157), ReleaseLock (158)
  • Callback manipulation calls: GiveUpCallBacks (147) GiveUpAllCallBacks (65539) CallBackRxConnAddr (65541)
  • Other: GetStatistics (146) GetVolumeInfo (148) GetVolumeStatus (149) SetVolumeStatus (150) GetRootVolume (151) CheckToken (152) GetTime (153) NGetVolumeInfo (154) XStatsVersion (159) GetXStats (160) Lookup (161) FlushCPS (162) FsCmd (220) GetCapabilities (65540)

Many mutation calls (StoreStatus, CreateFile, Symlink, and MakeDir) take a struct AFSStoreStatus which specifies a bitmask of features to be changed, which is drawn from a set defined at 6e167d4:src/fsint/afsint.xg:116. Three flags concern us:

  • SETOWNER to adjust the UID
  • SETGROUP to adjust the GID
  • SETMODE to adjust the MODE

While the remainder (MODTIME, SETSEGSIZE, and FSYNC) do not.

Client Operations Vs Required Permissions

Update Internals

Before we discuss pre-flight permissions checks, we focus on src/viced/afsfileprocs.c:/^Update_TargetVnodeStatus, which serves to actually carry out writes to vnode status fields but also contains some permission logic. This function is called by most mutation functions:

  • common_StoreData64 at 6e167d4:src/viced/afsfileprocs.c:2989
  • SAFSS_StoreStatus at 6e167d4:src/viced/afsfileprocs.c:3200
  • SAFSS_CreateFile at 6e167d4:src/viced/afsfileprocs.c:3464
  • SAFSS_Symlink at 6e167d4:src/viced/afsfileprocs.c:4131
  • SAFSS_MakeDir at 6e167d4:src/viced/afsfileprocs.c:4489

This function modifies the request in several ways as a result of permissions:

  • If the originating call is StoreData64 (see 6e167d4:src/viced/afsfileprocs.c:1729 and following):

    • The setuid SPEC bit is cleared unless the requestor is an ADMIN.
    • If the server has been compiled -DCREATE_SGUID_ADMIN_ONLY (which it is, by default, at 6e167d4:src/viced/afsfileprocs.c:152), the setgid SPEC bit is cleared unless the requestor is an ADMIN.
  • If the originating call requests a set of ownership (UID) (by asserting AFS_SETOWNER in the incoming status mask; see 6e167d4:src/viced/afsfileprocs.c:1749 and following), the same tests and clearings as the previous point are applied.

    Note that changes of GID are always performed if requested, and will not cause any bits (most notably S_ISGID) to be cleared.

  • If the originating call requests a set of all MODE bits (by asserting AFS_SETMODE in the incoming status mask) AND the server is built with CREATE_SGUID_ADMIN_ONLY defined (which it is by default) AND the caller is not ADMIN, the MODE bits are restricted to the three RWX triples (i.e., all SPEC bits are cleared). This has the effect of prohibiting all users other than ADMIN from setting the masked bits. (See 6e167d4:src/viced/afsfileprocs.c:1767 and following.)

The contained permissions checks would all be overridden if the remote flag is set (which it isn’t in any existing call) as part of the effort towards RW replication.

Simpler Client Operations

A separate pre-flight permissions check exists for many operations, a relatively simple src/viced/afsfileprocs.c:/^CheckWriteMode, which succeeds so long as the operation is targeted at a read-write volume, the caller has the required rights (as indicated in call) in the containing directory ACL, and either the target is a directory or the OWNERWRITE MODE bit is set. In particular,

  • RemoveFile requires delete rights (at 6e167d4:src/viced/afsfileprocs.c:3307),

  • CreateFile requires insert rights (at 6e167d4:src/viced/afsfileprocs.c:3488);

  • Rename performs two such calls, requiring delete rights in the old directory (at 6e167d4:src/viced/afsfileprocs.c:3644) and insert rights in the new (at 6e167d4:src/viced/afsfileprocs.c:3647) (Note that these may be the same!),

  • Symlink requires insert rights in the directory where the link will be created (at 6e167d4:src/viced/afsfileprocs.c:4094),

  • Link requires insert rights in the directory where the link will be created (at 6e167d4:src/viced/afsfileprocs.c:4276),

  • RemoveDir requires delete rights of the containing directory (at 6e167d4:src/viced/afsfileprocs.c:4613),

  • MakeDir can be built with one of two permissions models (see 6e167d4:src/viced/afsfileprocs.c:4455):

    • Require both insert and write rights in the containing directory, if built with -DDIRCREATE_NEED_WRITE (not default), or
    • Require just insert rights, otherwise.

    By default, the latter strategy is used. The justification for the former strategy hinged on the old implicit Administrate permission given to the owner of a directory, which is no longer the case (see Implicit Admin on Dir).

Complex Client Operations

A single function, src/viced/afsfileprocs.c:/^Check_PermissionRights, contains the permission logic for the ten calls comprising fetch and set of data, ACL, and status:

  • FetchData64 (and FetchData) at 6e167d4:src/viced/afsfileprocs.c:2325
  • FetchACL at 6e167d4:src/viced/afsfileprocs.c:2466
  • FetchStatus at 6e167d4:src/viced/afsfileprocs.c:2544
  • BulkStatus at 6e167d4:src/viced/afsfileprocs.c:2644
  • InlineBulkStatus at 6e167d4:src/viced/afsfileprocs.c:2788
  • StoreData64 (and StoreData) at 6e167d4:src/viced/afsfileprocs.c:2956
  • StoreACL at 6e167d4:src/viced/afsfileprocs.c:3100
  • StoreStatus at 6e167d4:src/viced/afsfileprocs.c:3186

The operation of this pre-flight test is somewhat opaque. Here is our current best attempt at its description:

  • Read operations are a mess; see 6e167d4:src/viced/afsfileprocs.c:1030 and following. The code is a series of checks for reasons for the operation to fail.

    • Reading the contents of directories or symlinks fails if the ACL does not grant r, -DADMIN_IMPLICIT_LOOKUP is defined and the client is not an ADMIN, and the client is not the VOLUID.

      Phrased positively, this succeeds if the ACL grants r, -DADMIN_IMPLICIT_LOOKUP is defined and the client is an ADMIN, or the client is the VOLUID.

    • Reading the contents of files fails under the same conditions as for directories, as well as the following conditions:

      • -DUSE_GROUP_PERMS is not in effect and the client does not match UID and the client is not an ADMIN and the MODE bits do have OWNERREAD or OWNEREXEC asserted. (6e167d4:src/viced/afsfileprocs.c:1067)

        This is documented as a “kludge” to handle the case when MODE is 0 (possibly from creation) and the UID is set incorrectly.

        Note

        That is, in net, AFS allows, in addition to administrator and owner, any user’s read request if there are no read UMODE bits asserted. This is, shall we say, a litte different from the usual semantics of UMODE.

      • -DUSE_GROUP_PERMS being in effect generalizes this test...

        Todo

        working here

    • Reading an ACL or status information while not being an ADMIN requires the same conditions as reading the contents of the object, as if it were a directory. (Note that this fact is confusingly encoded in the implementation as || VanillaUser(client).)

    • Reading an ACL or status information while being an ADMIN will never fail.

  • Write operations are no better; see 6e167d4:src/viced/afsfileprocs.c:1079 and following.

    • A store of data to a file, when client matches UID and the ACL grants the client i, is permitted (unless the server is readonly).

    • A store of stat metadata to a file, when client matches UID and the ACL grants the client i, is permitted on a non-readonly server if either:

      • the UID and GID are not being modified.
      • the client is an ADMIN.
    • All other non-data stores are explicitly permitted if the client is an ADMIN (6e167d4:src/viced/afsfileprocs.c:1098) even if the server is readonly.

    • All other stores fail if the server is readonly. (All subsequent tests of this are superfluous and elided from this description.)

    • A store of an ACL is permitted only if the ACL grants a or the client matches the VOLUID. (6e167d4:src/viced/afsfileprocs.c:1107)

    • A store of status which changes UID or GID will fail unless the client is an ADMIN (6e167d4:src/viced/afsfileprocs.c:1111)

    • A store which mutates the SPEC bits S_ISUID or S_ISGID will fail unless the client is an ADMIN (6e167d4:src/viced/afsfileprocs.c:1123)

    • A store of data will fail unless the ACL grants the client w (6e167d4:src/viced/afsfileprocs.c:1142)

    • -DUSE_GROUP_PERMS induces some complexity at this point...

      Todo

      oh yeah, that

    • A store of data to a non-directory (i.e. file or symlink) without the UMODE including write will fail unless the client is an ADMIN (6e167d4:src/viced/afsfileprocs.c:1167)

    • A store of status to a directory will fail without the ACL granting both di (6e167d4:src/viced/afsfileprocs.c:1182)

    • A store of status to a file will fail without the ACL granting w (6e167d4:src/viced/afsfileprocs.c:1186)

    • A store that has not yet failed will succeed.

Todo

Working here.