Subject: richacl(7) man page review comments

Hi Andreas,

I'll probably have quite a few more comments on this page as I get to
understand RichACLs better. Here's some comments from an initial
reading.

So, an initial comment. It seems to me to that this page (but
not setrichacl(1) and getrichacl(1)) should ultimately land in
man-pages (just like acl(7)), since we're talking about a kernel
feature. Make sense?

> .\"
> .\" Richacl Manual Pages
> .\"
> .\" Copyright (C) 2015 Red Hat, Inc.
> .\" Written by Andreas Gruenbacher <[email protected]>
> .\" This is free documentation; you can redistribute it and/or
> .\" modify it under the terms of the GNU General Public License as
> .\" published by the Free Software Foundation; either version 2 of
> .\" the License, or (at your option) any later version.
> .\"
> .\" The GNU General Public License's references to "object code"
> .\" and "executables" are to be interpreted as the output of any
> .\" document formatting or typesetting system, including
> .\" intermediate and printed output.
> .\"
> .\" This manual is distributed in the hope that it will be useful,
> .\" but WITHOUT ANY WARRANTY; without even the implied warranty of
> .\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> .\" GNU General Public License for more details.
> .\"
> .\" You should have received a copy of the GNU General Public
> .\" License along with this manual. If not, see
> .\" <http://www.gnu.org/licenses/>.
> .\"
> .de URL
> \\$2 \(laURL: \\$1 \(ra\\$3
> ..
> .if \n[.g] .mso www.tmac
> .TH RICHACL 7 2015-09-01 "Linux" "Rich Access Control Lists"
> .SH NAME
> richacl \- Rich Access Control Lists
> .SH DESCRIPTION
> Rich Access Control Lists (richacls) are an extension of the POSIX file

For what it's worth, I think it would be worthwhile to start with
a consistent abbreviation comment here (and use it throughout all of the
man pages): "RichACL" (or "richACL"), rather than "richacl"; that seems
more consistent with the traditional abbreviation "ACL".

> permission model to support

Make this:

permission mode (see
.BR acl (7))
to support

> .URL https://tools.ietf.org/rfc/rfc5661.txt "NFSv4 Access Control Lists"
> on local and remote-mounted filesystems.
>
> Richacls support file masks which allow to apply a file mode to an existing

s/which allow to apply/which can be used to apply/

> NFSv4 ACL without destructive side effects: the file mode determines the values
> of the file masks; the file masks restrict the permissions granted by the NFSv4
> ACL. When a less restrictive file mode is applied later, the file masks become
> less restrictive, and more of the original permissions can become effective.
>
> A richacl can always be translated into an equivalent NFSv4 ACL which grants
> the same permissions.
>
> Richacls can be enabled on supported filesystems. This disables POSIX Access
> Control Lists; the two ACL models will not coexist on the same filesystem.

s/will not/can not/ ?

>
> When used on a filesystem that does not support richacls, the getrichacl and

Use
.BR getrichacl (1)
for cross-references.

> setrichacl utilities will operate on the file permission bits instead:
> getrichacl will display the file permission bits as a richacl; when a richacl

Use
.BR getrichacl (1)
for cross-references.

> is set with setrichacl which can be represented exactly by the file permission

Use
.BR setrichacl (1)
for cross-references.

> bits, setrichacl will set the file permission bits instead.

Use
.BR setrichacl (1)
for cross-references.

Here, I think it would be helpful to add a sentence:

"An attempt to set a richacl that cannot be represented exactly by the
file permission bits results in an error."

(If that sentence is correct, of course.)

>
> .SH STRUCTURE OF RICHACLS

For all of the "nonstandard" (see man-pages(7)) ".SH" sections here, I'd
be inclined to switch to using ".SS" subsections. There are downsides to
multiple nonstandard section headings (e.g., automated TOCs for
Section headings become clumsy and long), and I don't think your use of
.SH vs .SS really helps much to structure the information in this page.

>
> Richacls consist of a number of ACL entries, three file masks, and some flags.

s/some flags./some flags specifying attributes of the ACL as whole (by
contrast with the per-ACL-entry flags described below)./

> Each of the ACL entries allows or denies some permissions to a particular user,
> group, or special entity. Each acl entry consists of:

s/acl//

> .IP \(bu 4
> The user (with prefix

s/The user/A tag which specifies the user/

(Is "tag" the right word? In any case, what would helpful to have here
is the generic term for this component of the ACL.)

> .B user:
> or
> .BR u: ),
> group (with prefix
> .B group:
> or
> .BR g: ),
> or special identifier the entry applies to. Special
> identifiers can be the file owner
> .RB ( owner@ ),
> the owning group
> .RB ( group@ ),
> or everyone
> .RB ( everyone@ ).
> .IP \(bu
> A set of permissions the entry allows or denies.
> .IP \(bu
> A set of flags that indicate whether the user or group identifier is mapped or
> unmapped, and whether the entry has been and can be inherited.
> .IP \(bu 4
> A field indicating whether the entry allows or denies access.
> .PP
> The owner, group, and other file masks further control which permissions the
> ACL grants, subject to the
> .B masked
> .RB ( m )
> and
> .B write_through
> .RB ( w )
> ACL flags.
>
> Note that entries with the identifier
> .B everyone@
> apply to all processes, whereas the \(lqother\(rq file permissions and
> \(lqother\(rq entries in POSIX ACLs apply to all processes which are not the
> owner, are not in the owning group, and do not match a user or group mentioned
> in the acl.

s/acl/ACL/

> Richacls do not have separate \(lqaccess\(rq ACLs that define the access
> permissions and \(lqdefault\(rq ACLs that define the inheritable permissions as
> POSIX ACLs.

I'd restructure the preceding sentence as:

"Unlike POSIX ACLs, richacls do not.... that define the inheritable
permissions."

> Instead, whether an ACL entry is effective during access checks
> and/or inheritable is determined by the ACL entry flags.
>
> .SS ACL Flags

I'd use lower case in the above for all words except the first.
(That's the convention in man-pages.)

>
> The following flags on ACLs are defined:
>
> .RS 4
> .HP 4

s/4/8/ in the preceding two lines. I think more indentation would make
this (and the similar lists below) more readable.

> .B masked
> .RB ( m ):

I'd write each of these list entries starting here, and below, in the
form:

.BR masked "\ (" m ):

This form is a little easier to read in the source, and
it forces just a single space before the "(", which looks
a little better, I find.

> When set, the file masks define upper limits on the permissions the ACL may
> grant.
> .HP
> .B write_through
> .RB ( w ):
> When this flag and the masked flag are both set, the owner and other file masks

.B masked

> define the actual permissions granted to the file owner and to others instead
> of an upper limit.
> .HP
> .B auto_inherit
> .RB ( a ):
> Automatic Inheritance is enabled for the file the ACL is
> attached to. See
> .IR "Automatic Inheritance" .
> .HP
> .B protected
> .RB ( p ):
> The ACL is protected from modification by Automatic
> Inheritance.
> .HP
> .B defaulted
> .RB ( d ):
> The ACL has been assigned by default. Automatic Inheritance should completely
> replace the ACL.
> .RE
>
> .SS ACL Entry Flags
>
> The following flags on ACL entries are defined:
>
> .RS 4
> .HP 4

s/4/8/ in the preceding two lines.

> .B file_inherit
> .RB ( f ):
> The entry is inheritable for files.
> .HP
> .B dir_inherit
> .RB ( d ):
> The entry is inheritable for directories.
> .HP
> .B no_propagate
> .RB ( n ):
> Inheritance stops at the next subdirectory level.
> .HP
> .B inherit_only
> .RB ( i ):
> The entry defines inheritable permissions only and is ignored for access
> checking.
> .HP
> .B inherited
> .RB ( a ):
> The entry has been automatically inherited from the parent directory; the
> ACL's auto_inherit

Use
.B auto_inherit

> .RB ( a )
> flag should be on.
> .HP
> .B unmapped
> .RB ( u ):
> The user or group identifier is a textual string and has no mapping to a
> numeric user or group identifier.

So here, I think there should be a sentence that explains how a meaning
is attached to the strings? Is this for NFS, for Windows, for something
else?

> .RE
>
> .SS Permissions
>
> The following permissions are defined for richacl entries and for the three
> file masks:
>
> .RS 4
> .HP 4

s/4/8/ in the preceding two lines.

> .B read_data
> /
> .B list_directory
> .RB ( r ):

Replace the preceding four lines by

.BR read_data / list_directory "\ (" r )

and do similar for the next two list entried below.
Note that "\ (" will force just a singlke space before the "(".

> Read the data of a file.
> List the contents of a directory.

In the above list entry, and the next two, I find the layout ("xxx/yyy (z)")
confusing. A closer reading indicates that in each case, the "xxx"
applies for files and he "yyy" is for directories. But I think the text
could make this point a little easier to grasp. In each of these three
list entries this could be done something lke the following:

"For a file: read the data of the file. For a directory: list the
contents of the directory."

By the way, can the terms "read_data" and "list_directory" be used
interchangeably? That is, can you employ (say) "read_data" when setting
an ACL entry for a directory? (I'm assuming the answer is "yes".)
If the terms are just interchangeable synonyms, perhas it's worth
making that point explicitly in the text.

> .HP
> .B write_data
> /
> .B add_file
> .RB ( w ):
> Modify the data of a file. Add a new file in a directory.

See above comment re file/directory.

> .HP
> .B append_data
> /
> .B add_subdirectory
> .RB ( p ):
> Open a file in append mode. Create a subdirectory in a directory.

So, in other words, if append mode is denied, then the file can be
opened for writing (contingent on write permission being granted), but
can't be opened with O_APPEND? Is that correct? This point needs to be
made clearer.

> .HP
> .B execute
> .RB ( x ):
> Execute a file. Traverse / search a directory.

See above comment re file/directory.

> .HP
> .B delete_child
> .RB ( d ):
> Delete a file or directory within a directory.
> .HP
> .B delete
> .RB ( D ):
> Delete the file or directory.
> .HP
> .B read_attributes
> .RB ( a ):
> Read basic attributes of a file or directory.

What are "attributes" in this context? Does this mean stat(2)? Make this
explicit.

> This permission is always implicitly granted.
> .HP
> .B write_attributes
> .RB ( A ):
> Change the times associated with a file or directory to an arbitrary value.
> This permission is always implicitly granted to the file owner.
> .HP
> .B read_acl
> .RB ( c ):
> Read the ACL of a file or directory. This permission is always
> implicitly granted.
> .HP
> .B write_acl
> .RB ( C ):
> Change the ACL or file mode of a file or directory.
> .HP
> .B write_owner
> .RB ( o ):
> Take ownership of a file or directory. Change the owning group of a file or
> directory to a group of which the calling process is a member.
> .HP
> .B read_named_attrs
> .RB ( R ),
> .B write_named_attrs
> .RB ( W ),
> .B synchronize
> .RB ( S ),
> .B write_retention
> .RB ( e ),
> .B write_retention_hold
> .RB ( E ):
> These permissions can be stored, but do not have a local meaning.

So, I thenk that a sentence here should explain why these permissions
exist. Is if for future extension, because they are meaningful in NFS,
or something else?

> .RE
>
> .SH TEXT FORM
>
> The common textual representation of richacl consists of the colon separated

s/richacl/richacls/ (or, "RichACLs"/"richACLs")

s/colon separated/colon-separated/

> fields of the the acl flags, file masks, and acl entries in the following

s/acl/ACL/ (*2)

> format:
> .TP
> \fBflags:\fR\fIacl_flags\fR
> The ACL flags.
> .TP
> \fBowner:\fR\fIperm\fR\fB::mask\fR, \fBgroup:\fR\fIperm\fR\fB::mask\fR, \fBother:\fR\fIperm\fR\fB::mask\fR
> The file masks and their permissions.
> .TP
> \fIwho\fR\fB:\fR\fIperm\fR\fB:\fR\fIflags\fR\fB:allow\fR, \fIwho\fR\fB:\fR\fIperm\fR\fB:\fR\fIflags\fR\fB:deny\fR
> For each ACL entry, who the entry applies to, the permissions of the entry, the
> entry flags, and whether the entry allows or denies permissions. The who field has

s/who/\\fIwho\\fP/

> no prefix for special identifiers, a
> .B user:
> or
> .B u:
> prefix for regular users, and a
> .B group:
> or
> .B g:
> prefix for regular groups.
> .PP
> The entries are comma, whitespace or newline separated.

s/whitespace/whitespace,/

>
> Flags and permissions have single-letter as well as long forms as listed under

s/forms/forms,/

> .IR "ACL Flags" ,
> .IR "ACL Entry Flags" ,
> and
> .IR Permissions .

If you follow my suggestion about capitalization in the ".SS" entries,
you'll need to change the capitalization in the above phrases.

> When the single-letter forms are used, the flags or permissions are
> concatenated. When the long forms are used, the flags or permissions are
> separated by slashes. To align permissions or flags vertically, dashes can be
> use for padding.

s/use/used/

>
> .SH SETTING AND MODIFYING FILE PERMISSIONS
> The access permissions for a file can either be set by assigning an access
> control list (setrichacl) or by changing the file mode permission bits (chmod).

Use
.RB ( setrichacl (1))
for cross-reference.

Use
.RB ( chmod (1)).

> In addition, a file can inherit an ACL from its parent
> directory at create time; the inherited ACL is then further

s/create/creation/

> restricted by the creating system call's mode parameter (see the creat(2)
> manual page).

creat(2) is pretty much history. I suggest writing

(as given to
.BR open (2),
.BR mkdir (2),
and similar).

And here, I think we need a statement about whether the process umask
has an effect or not...

>
> .SS Assigning An Access Control List
> When assigning an ACL to a file, unless explicitly specified, the owner, group,
> and other file masks will be computed from the ACL entries as described in
> section
> .IR "COMPUTING THE MAXIMUM FILE MASKS" .
> The owner, group, and other file mode permission bits are then each set from
> the owner, group, and other file mask as follows:
> .IP \(bu 4
> If the file mask includes the
> .B r
> permission, the read
> file mode permission bit will be set.
> .IP \(bu
> If the file mask includes the
> .B w
> or
> .B p
> permission, the write file mode permission bit will be set.
> .IP \(bu
> If the file mask includes the
> .B x
> permission, the execute file mode permission bit will be set.
> .PP
> If the ACL can be represented exactly by the file mode
> permission bits, the file permission bits are set to match the access control
> list and the ACL is not stored. (When the reverse happens and

s/and/and the/

> ACL of a file is requested which doesn't have an explicit
> ACL, the file mode permission bits are converted into an
> equivalent richacl.)
>
> .SS Changing The File Mode Permission Bits

I'd use lower case in the above for all words except the first

> When changing the file mode permission bits with chmod(2), the owner, group,

.BR chmod (2)

> and other file permission bits are set to the permission bits in the new mode,
> and the file masks each are set based on the new mode bits as follows:
> .IP \(bu 4
> If the read bit in a set of permissions is set, the
> .B r
> permission in the corresponding file mask will be set.
> .IP \(bu
> If the write bit in a set of permissions is set, the
> .B w
> and
> .B p
> permissions in the corresponding file mask will be set.
> .IP \(bu
> If the execute bit in a set of permissions is set, the
> .B x
> permission in the corresponding file mask will be set.
> .PP
> In addition, the
> .B masked
> and
> .B write_through
> ACL flags are set. This has the
> effect of limiting the permissions granted by the ACL to the file mode
> permission bits; in addition, the owner is granted the owner mode bits and
> others are granted the other mode bits. If the
> .B auto_inherit
> flag is set, the
> .B protected
> flag is also set to prevent the Automatic Inheritance algorithm from modifying
> the ACL.
>
> .SS Permissions At File Create Time

s/File Create/file-creation/

I'd use lower case in the above for all words except the first

> When a directory has inheritable ACL entries, the following
> happens when a file or directory is created inside that directory:
> .RS 4
> .IP 1. 4
> A file created inside that directory will inherit all entries with the

s/all entries with/all of the directories entries that/

> .B file_inherit
> flag set, and all inheritance-related flags in the inherited entries will be
> cleared.
>
> A subdirectory will inherit all entries with the
> .B file_inherit
> or
> .B dir_inherit
> flag set. Entries whose
> .B no_propagate
> flag is set will have all inheritance-related flags cleared. Entries whose
> .B no_propagate
> and
> .B dir_inherit
> flags are not set and whose
> .B file_inherit
> is set will have their
> .B inherit_only
> flag set.
> .IP 2.
> If the parent directory's ACL has the
> .B auto_inherit
> flag set, the inherited ACL will have its
> .B auto_inherit
> flag set, and all entries will have their
> .B inherited
> flag set.
> .IP 3.
> The three file masks are computed from the inherited ACL as described in
> section
> .IR "COMPUTING THE MAXIMUM FILE MASKS" .
> .IP 4.
> The three sets of permissions for the owner, the group, and for others in
> the mode parameter of the creating system call are converted into sets of
> richacl permissions as described in section

s/in/in the/

> .IR "Changing The File Mode Permission Bits" .
> Any richacl permissions not included in those sets are
> removed from the owner, group, and other file masks. The file mode permission
> bits are then computed from the file masks as described in section

s/in/in the/

> .IR "Assigning An Access Control List" .
> .IP 5.
> The
> .B masked
> ACL flag is set. The
> .B write_through
> ACL flag remains cleared. In addition, if the
> .B auto_inherit
> flag of the inherited ACL is set, the
> .B protected
> flag is also set to prevent the Automatic Inheritance algorithm from modifying
> the ACL.
> .RE
> .PP
> When a directory does not have inheritable ACL entries, files
> and directories created inside that directory will not be assigned access
> control lists and the file mode permission bits will be set to (mode\ &\
> ~umask).

will be set to

(mode & umask)

where
.I mode
is the permission mode argument of the relevant system call and
.I umask
is the process umask (see
.BR umask (2)).

>
> .SS Automatic Inheritance

I'd use lower case in the above for all words except the first

> Automatic Inheritance allows permission changes to propagate from a directory
> to files and subdirectories inside that directory, recursively. Carrying out
> this propagation of permissions is the responsibility of the process changing
> the directory permissions (usually, setrichacl(1)).

I'm confused by the previous sentence. the feature is labeled "Automatic
Inheritance", implying that the user/process need do nothing. The next
sentence says "propagation ... is the responsibility of the process".
These two points seem contradictory. I think something more needs to be
said here.

>
> A significant limitation is that this mechanism works only as long as files
> are created without explicitly specifying the file permissions to use. The
> standard system calls for creating files an directories (creat(2), open(2),
> mkdir(2), mkfifo(2), mknod(2)) all have mandatory mode parameters which define

Format that system call list as
.RB ( creat (2),
.BR open (2),
.BR mkdir (2),
.BR mknod (2))

Note that I removed mkfifo(): it's a library functionlayered on
mkonod(2).

> the maximum allowed permissions of the new files. To take account of this
> restriction, the
> .B protected
> ACL flag must be set if the
> .B inherited
> flag is set. This effectively disables Automatic Inheritance for that
> particular file.
>
> Automatic Inheritance still remains useful for network protocols like NFSv4 and
> SMB, which both support creating files and directories without defining which
> permissions: they can implement those operations by using the standard system
> calls and by then undoing the effect of applying the mode parameters.
>
> When the ACL of a directory is changed, the following should

Why "should"?

> happen for each entry inside that directory (for each \(lqchild\(rq):

Make the preceding line:

happen for each entry (\(lqchild\(rq) inside that directory:

> .IP 1. 4
> If the entry is a symblic link, skip the child.
> .IP 2.
> If the
> .B auto_inherit
> flag of the entry's ACL is not set or the
> .B protected
> flag is set, skip the child.
> .IP 3.
> With the child's ACL:
> .RS 4
> .IP 1. 4

s/1./a)/

(i.e., use a different labeling scheme for the sublist)

> If the
> .B defaulted
> flag is set, replace the ACL with an empty ACL
> with the
> .B auto_inherit
> flag set.
> .IP 2.

s/2./b)/

> Delete all entries which have the
> .B inherited
> flag set.
> .IP 3.

s/3./c)/

> Append all entries inherited from the parent directory according to step 1 of
> the algorithm described under
> .IR "Permissions At File Create Time".
> Set the
> .B inherited
> flag of each of these entries.
> .IP 4.

s/4./d)/

> Recompute the file masks.
> .RE
> .IP 4.
> If the child is a directory, recursively apply this algorithm.
>
> .SH ACCESS CHECK ALGORITHM
>
> When a process requests a particular kind of access to a file defined by a set

s/defined/protected/ (?)

> of richacl permissions, the following algorithm determines if the access is

s/if/whether/

> granted or denied:
>
> .IP 1. 4
> If the
> .B masked
> ACL flag is set, then:
> .RS 4
> .IP 1. 4

s/1./a)/

Use a different numbering scheme for sublists.

> if the

s/if/If/

> .B write_through
> ACL flag is set, then:
> .RS 4
> .IP \(bu 4
> if the requesting process is the file owner, then access is granted if the

s/if/If/

> owner mask includes the requested permissions, and is otherwise denied.
> .IP \(bu
> if the requesting process is not the file owner, is not in the owning group,

s/if/If/

> and no ACL entries other than
> .B everyone@
> match the process, then access is granted if the other mask includes the
> requested permissions, and is otherwise denied.
> .RE
> .IP 2.

s/2./b)/

> if any of the following is true:

s/if/If/

> .RS 4
> .IP \(bu 4
> the requesting process is the file owner and the owner mask does no include all

s/no /not /

> requested permissions,
> .IP \(bu 4
> the requesting process is not the file owner and it is in the owning group or
> matches any ACL entries other than
> .BR everyone@ ,
> and the group mask does no include all requested permissions,
> .IP \(bu 4
> the requesting process is not the file owner, not in the owning group, it
> matches no ACL entries other than
> .BR everyone@ ,
> and the other mask does no include all requested permissions,
> .PP
> then access is denied.
> .RE
> .RE
> .IP 2.
> Set the remaining permissions to the requested permissions. Go through all ACL
> entries. For each entry:
> .RS 4
> .IP 1. 4

s/1./a)/

Use a different numbering scheme for sublists.

> if the
> .B inherit_only
> or
> .B unmapped
> flags are set, continue with the next ACL entry.
> .IP 2.

s/2./b)/

> if any of the following is true:
> .RS 4
> .IP \(bu 4
> the entry's identifier is
> .B owner@
> and the requesting process is the file owner,
> .IP \(bu
> the entry's identifier is
> .B group@
> and the requesting process is in the owning group,
> .IP \(bu
> the entry's identifier is a user and the requesting process is owned by that
> user,
> .IP \(bu
> the entry's identifier is a group and the requesting process is a member in
> that group,
> .IP \(bu
> the entry's identifier is
> .BR everyone@ ,
> .PP
> the entry matches the process; proceed. Otherwise, continue with the next ACL

s/proceed/proceed to the next step/ (?)

> entry.
> .RE
> .IP 3.

s/3./c)/

> If the entry denies any of the remaining permissions, access is denied.
> .IP 4.

s/4./d)/

> If the entry allows any of the remaining permissions, then:
> .RS 4
> .IP \(bu 4
> if the
> .B masked
> ACL flag is set and the entry's identifier is not
> .B owner@
> or
> .BR everyone@
> or is a user entry matching the file owner, remove all permissions from the
> remaining permissions which are both allowed by the entry and included in the
> group mask,
> .IP \(bu
> otherwise, remove all permissions from the remaining permissions wich are
> allowed by the entry.
> .RE
> .RE
> .IP 3.
> If there are no more remaining permissions, access is allowed. Otherwise,
> access is denied.
>
> .SH COMPUTING THE MAXIMUM FILE MASKS
> When setting an ACL and no file masks have been explicitly specified and when
> inheriting an ACL from the parent directory, the following algorithm is used
> for computing the file masks:
>
> .IP 1. 4
> Clear the owner, group, and other file masks. Remember which permissions have
> already been processed (initially, the empty set).
> .IP 2.
> For each ACL entry:
> .RS 4
> .IP \(bu 4
> If the
> .B inherit_only
> flag is set, skip the entry.
> .IP \(bu 4
> Otherwise, compute which permissions the entry allows or denies that have not
> been processed yet (the remaining permissions).
> .IP \(bu
> If the entry is an
> .B owner@
> entry, add the remaining permissions to the owner mask for
> .B allow
> entries, and remove the remaining permissions from the owner mask for
> .B deny
> entries.
> .IP \(bu
> Otherwise, if the entry is an
> .B everyone@
> entry, proceed as with
> .B owner@
> entries but add or remove the remaining permissions from the owner, group, and
> other file masks.
> .IP \(bu
> Otherwise, proceed as with
> .B owner@
> entries but add or remove the remaining permissions from the owner and group
> file masks.
> .IP \(bu
> Add the entry's permissions to the processed permissions.
> .RE
> .PP
> The resulting file masks represent the ACL as closely as possible. With these
> file masks, if the
> .B masked
> ACL flag is set, the effective permissions still stay the same.

This page is in *desperate* need of *multiple* examples, starting simple,
and building up in complexity, with walkthogh text explaining how the
permisssions are interpreted and how the masks are generated.
Having read the page multiple times (and having little knowledge
of NFS ACLs), I'm still struggling to put all the pieces together.
Probably some examples that relate to an NFS context would also be
helpful.

> .\" .SH BUGS
> .SH AUTHOR
> Written by Andreas Grünbacher <[email protected]>.
>
> Please send your bug reports, suggested features and comments to the above address.
>
> .SH CONFORMING TO
> Rich Access Control Lists are Linux-specific.
> .SH SEE ALSO
> .BR chmod (1),
> .BR getrichacl (1),
> .BR ls (1),
> .BR setrichacl (1)
> .BR stat (2),
> .BR umask (2),
> .BR acl (7)
> .\" librichacl

Cheers,

Michael


--
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Linux/UNIX System Programming Training: http://man7.org/training/


2016-02-10 19:34:04

by J. Bruce Fields

[permalink] [raw]
Subject: Re: richacl(7) man page review comments

On Sun, Feb 07, 2016 at 05:35:46PM +0100, Michael Kerrisk (man-pages) wrote:
> > This permission is always implicitly granted.
> > .HP
> > .B write_attributes
> > .RB ( A ):
> > Change the times associated with a file or directory to an arbitrary value.
> > This permission is always implicitly granted to the file owner.
> > .HP
> > .B read_acl
> > .RB ( c ):
> > Read the ACL of a file or directory. This permission is always
> > implicitly granted.
> > .HP
> > .B write_acl
> > .RB ( C ):
> > Change the ACL or file mode of a file or directory.
> > .HP
> > .B write_owner
> > .RB ( o ):
> > Take ownership of a file or directory. Change the owning group of a file or
> > directory to a group of which the calling process is a member.
> > .HP
> > .B read_named_attrs
> > .RB ( R ),
> > .B write_named_attrs
> > .RB ( W ),
> > .B synchronize
> > .RB ( S ),
> > .B write_retention
> > .RB ( e ),
> > .B write_retention_hold
> > .RB ( E ):
> > These permissions can be stored, but do not have a local meaning.
>
> So, I thenk that a sentence here should explain why these permissions
> exist. Is if for future extension, because they are meaningful in NFS,
> or something else?

Yeah, "synchronize" is something only Windows clients care about, as I
understand it. The others are for NFS features that nobody has tried to
implement yet. It's useful to store those bits but they don't do
anything at this point. We could provie FC references, I guess, but
it's probably not worth going into much detail about.

> > Automatic Inheritance allows permission changes to propagate from a directory
> > to files and subdirectories inside that directory, recursively. Carrying out
> > this propagation of permissions is the responsibility of the process changing
> > the directory permissions (usually, setrichacl(1)).
>
> I'm confused by the previous sentence. the feature is labeled "Automatic
> Inheritance", implying that the user/process need do nothing. The next
> sentence says "propagation ... is the responsibility of the process".
> These two points seem contradictory. I think something more needs to be
> said here.

Yeah, the "automatic" name is probably misleading, but I think we're
stuck with that name and just need to make the point a bit more
forcefully.

Userland utilities take responsibility for the actual recursive
propagation of changes, all the kernel does is provide a few bits which
help to do it correctly (e.g. to distinguish between ACEs that ewre
inherited inherited (and can be blown away by propagation) and those
that were added locally).

--b.

2016-02-12 22:25:30

by Andreas Gruenbacher

[permalink] [raw]
Subject: Re: richacl(7) man page review comments

Hi Michael,

On Sun, Feb 7, 2016 at 5:35 PM, Michael Kerrisk (man-pages)
<[email protected]> wrote:
> Hi Andreas,
>
> I'll probably have quite a few more comments on this page as I get to
> understand RichACLs better. Here's some comments from an initial
> reading.

thanks a lot for all the feedback to the man-pages. I've more or less
made all the suggested changes but didn't get to adding examples yet
(that's not so easy).

The changes are here:

https://github.com/andreas-gruenbacher/richacl

> So, an initial comment. It seems to me to that this page (but
> not setrichacl(1) and getrichacl(1)) should ultimately land in
> man-pages (just like acl(7)), since we're talking about a kernel
> feature. Make sense?

We could sure move acl(5) and richacl(7) there.

>> .\"
>> .\" Richacl Manual Pages
>> .\"
>> .\" Copyright (C) 2015 Red Hat, Inc.
>> .\" Written by Andreas Gruenbacher <[email protected]>
>> .\" This is free documentation; you can redistribute it and/or
>> .\" modify it under the terms of the GNU General Public License as
>> .\" published by the Free Software Foundation; either version 2 of
>> .\" the License, or (at your option) any later version.
>> .\"
>> .\" The GNU General Public License's references to "object code"
>> .\" and "executables" are to be interpreted as the output of any
>> .\" document formatting or typesetting system, including
>> .\" intermediate and printed output.
>> .\"
>> .\" This manual is distributed in the hope that it will be useful,
>> .\" but WITHOUT ANY WARRANTY; without even the implied warranty of
>> .\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>> .\" GNU General Public License for more details.
>> .\"
>> .\" You should have received a copy of the GNU General Public
>> .\" License along with this manual. If not, see
>> .\" <http://www.gnu.org/licenses/>.
>> .\"
>> .de URL
>> \\$2 \(laURL: \\$1 \(ra\\$3
>> ..
>> .if \n[.g] .mso www.tmac
>> .TH RICHACL 7 2015-09-01 "Linux" "Rich Access Control Lists"
>> .SH NAME
>> richacl \- Rich Access Control Lists
>> .SH DESCRIPTION
>> Rich Access Control Lists (richacls) are an extension of the POSIX file
>
> For what it's worth, I think it would be worthwhile to start with
> a consistent abbreviation comment here (and use it throughout all of the
> man pages): "RichACL" (or "richACL"), rather than "richacl"; that seems
> more consistent with the traditional abbreviation "ACL".
>
>> permission model to support
>
> Make this:
>
> permission mode (see
> .BR acl (7))
> to support
>
>> .URL https://tools.ietf.org/rfc/rfc5661.txt "NFSv4 Access Control Lists"
>> on local and remote-mounted filesystems.
>>
>> Richacls support file masks which allow to apply a file mode to an existing
>
> s/which allow to apply/which can be used to apply/
>
>> NFSv4 ACL without destructive side effects: the file mode determines the values
>> of the file masks; the file masks restrict the permissions granted by the NFSv4
>> ACL. When a less restrictive file mode is applied later, the file masks become
>> less restrictive, and more of the original permissions can become effective.
>>
>> A richacl can always be translated into an equivalent NFSv4 ACL which grants
>> the same permissions.
>>
>> Richacls can be enabled on supported filesystems. This disables POSIX Access
>> Control Lists; the two ACL models will not coexist on the same filesystem.
>
> s/will not/can not/ ?
>
>>
>> When used on a filesystem that does not support richacls, the getrichacl and
>
> Use
> .BR getrichacl (1)
> for cross-references.
>
>> setrichacl utilities will operate on the file permission bits instead:
>> getrichacl will display the file permission bits as a richacl; when a richacl
>
> Use
> .BR getrichacl (1)
> for cross-references.
>
>> is set with setrichacl which can be represented exactly by the file permission
>
> Use
> .BR setrichacl (1)
> for cross-references.
>
>> bits, setrichacl will set the file permission bits instead.
>
> Use
> .BR setrichacl (1)
> for cross-references.
>
> Here, I think it would be helpful to add a sentence:
>
> "An attempt to set a richacl that cannot be represented exactly by the
> file permission bits results in an error."
>
> (If that sentence is correct, of course.)
>
>>
>> .SH STRUCTURE OF RICHACLS
>
> For all of the "nonstandard" (see man-pages(7)) ".SH" sections here, I'd
> be inclined to switch to using ".SS" subsections. There are downsides to
> multiple nonstandard section headings (e.g., automated TOCs for
> Section headings become clumsy and long), and I don't think your use of
> .SH vs .SS really helps much to structure the information in this page.
>
>>
>> Richacls consist of a number of ACL entries, three file masks, and some flags.
>
> s/some flags./some flags specifying attributes of the ACL as whole (by
> contrast with the per-ACL-entry flags described below)./
>
>> Each of the ACL entries allows or denies some permissions to a particular user,
>> group, or special entity. Each acl entry consists of:
>
> s/acl//
>
>> .IP \(bu 4
>> The user (with prefix
>
> s/The user/A tag which specifies the user/
>
> (Is "tag" the right word? In any case, what would helpful to have here
> is the generic term for this component of the ACL.)

Tag should do; I'm not aware of a better term.

>> .B user:
>> or
>> .BR u: ),
>> group (with prefix
>> .B group:
>> or
>> .BR g: ),
>> or special identifier the entry applies to. Special
>> identifiers can be the file owner
>> .RB ( owner@ ),
>> the owning group
>> .RB ( group@ ),
>> or everyone
>> .RB ( everyone@ ).
>> .IP \(bu
>> A set of permissions the entry allows or denies.
>> .IP \(bu
>> A set of flags that indicate whether the user or group identifier is mapped or
>> unmapped, and whether the entry has been and can be inherited.
>> .IP \(bu 4
>> A field indicating whether the entry allows or denies access.
>> .PP
>> The owner, group, and other file masks further control which permissions the
>> ACL grants, subject to the
>> .B masked
>> .RB ( m )
>> and
>> .B write_through
>> .RB ( w )
>> ACL flags.
>>
>> Note that entries with the identifier
>> .B everyone@
>> apply to all processes, whereas the \(lqother\(rq file permissions and
>> \(lqother\(rq entries in POSIX ACLs apply to all processes which are not the
>> owner, are not in the owning group, and do not match a user or group mentioned
>> in the acl.
>
> s/acl/ACL/
>
>> Richacls do not have separate \(lqaccess\(rq ACLs that define the access
>> permissions and \(lqdefault\(rq ACLs that define the inheritable permissions as
>> POSIX ACLs.
>
> I'd restructure the preceding sentence as:
>
> "Unlike POSIX ACLs, richacls do not.... that define the inheritable
> permissions."
>
>> Instead, whether an ACL entry is effective during access checks
>> and/or inheritable is determined by the ACL entry flags.
>>
>> .SS ACL Flags
>
> I'd use lower case in the above for all words except the first.
> (That's the convention in man-pages.)
>
>> The following flags on ACLs are defined:
>>
>> .RS 4
>> .HP 4
>
> s/4/8/ in the preceding two lines. I think more indentation would make
> this (and the similar lists below) more readable.
>
>> .B masked
>> .RB ( m ):
>
> I'd write each of these list entries starting here, and below, in the
> form:
>
> .BR masked "\ (" m ):
>
> This form is a little easier to read in the source, and
> it forces just a single space before the "(", which looks
> a little better, I find.
>
>> When set, the file masks define upper limits on the permissions the ACL may
>> grant.
>> .HP
>> .B write_through
>> .RB ( w ):
>> When this flag and the masked flag are both set, the owner and other file masks
>
> .B masked
>
>> define the actual permissions granted to the file owner and to others instead
>> of an upper limit.
>> .HP
>> .B auto_inherit
>> .RB ( a ):
>> Automatic Inheritance is enabled for the file the ACL is
>> attached to. See
>> .IR "Automatic Inheritance" .
>> .HP
>> .B protected
>> .RB ( p ):
>> The ACL is protected from modification by Automatic
>> Inheritance.
>> .HP
>> .B defaulted
>> .RB ( d ):
>> The ACL has been assigned by default. Automatic Inheritance should completely
>> replace the ACL.
>> .RE
>>
>> .SS ACL Entry Flags
>>
>> The following flags on ACL entries are defined:
>>
>> .RS 4
>> .HP 4
>
> s/4/8/ in the preceding two lines.
>
>> .B file_inherit
>> .RB ( f ):
>> The entry is inheritable for files.
>> .HP
>> .B dir_inherit
>> .RB ( d ):
>> The entry is inheritable for directories.
>> .HP
>> .B no_propagate
>> .RB ( n ):
>> Inheritance stops at the next subdirectory level.
>> .HP
>> .B inherit_only
>> .RB ( i ):
>> The entry defines inheritable permissions only and is ignored for access
>> checking.
>> .HP
>> .B inherited
>> .RB ( a ):
>> The entry has been automatically inherited from the parent directory; the
>> ACL's auto_inherit
>
> Use
> .B auto_inherit
>
>> .RB ( a )
>> flag should be on.
>> .HP
>> .B unmapped
>> .RB ( u ):
>> The user or group identifier is a textual string and has no mapping to a
>> numeric user or group identifier.
>
> So here, I think there should be a sentence that explains how a meaning
> is attached to the strings? Is this for NFS, for Windows, for something
> else?

On NFS clients only. I've tried to clarify that.

>> .RE
>>
>> .SS Permissions
>>
>> The following permissions are defined for richacl entries and for the three
>> file masks:
>>
>> .RS 4
>> .HP 4
>
> s/4/8/ in the preceding two lines.
>
>> .B read_data
>> /
>> .B list_directory
>> .RB ( r ):
>
> Replace the preceding four lines by
>
> .BR read_data / list_directory "\ (" r )
>
> and do similar for the next two list entried below.
> Note that "\ (" will force just a singlke space before the "(".
>
>> Read the data of a file.
>> List the contents of a directory.
>
> In the above list entry, and the next two, I find the layout ("xxx/yyy (z)")
> confusing. A closer reading indicates that in each case, the "xxx"
> applies for files and he "yyy" is for directories. But I think the text
> could make this point a little easier to grasp. In each of these three
> list entries this could be done something lke the following:
>
> "For a file: read the data of the file. For a directory: list the
> contents of the directory."
>
> By the way, can the terms "read_data" and "list_directory" be used
> interchangeably? That is, can you employ (say) "read_data" when setting
> an ACL entry for a directory? (I'm assuming the answer is "yes".)
> If the terms are just interchangeable synonyms, perhas it's worth
> making that point explicitly in the text.

richacl_from_text() doesn't distinguish between file and directory
flags, but richacl_to_text() will use the appropriate version in
long-format strings depending on the context (file type). ACLs that
have this wrong would be very confusing to read.

>> .HP
>> .B write_data
>> /
>> .B add_file
>> .RB ( w ):
>> Modify the data of a file. Add a new file in a directory.
>
> See above comment re file/directory.
>
>> .HP
>> .B append_data
>> /
>> .B add_subdirectory
>> .RB ( p ):
>> Open a file in append mode. Create a subdirectory in a directory.
>
> So, in other words, if append mode is denied, then the file can be
> opened for writing (contingent on write permission being granted), but
> can't be opened with O_APPEND? Is that correct? This point needs to be
> made clearer.

Yes, that's correct.

>> .HP
>> .B execute
>> .RB ( x ):
>> Execute a file. Traverse / search a directory.
>
> See above comment re file/directory.
>
>> .HP
>> .B delete_child
>> .RB ( d ):
>> Delete a file or directory within a directory.
>> .HP
>> .B delete
>> .RB ( D ):
>> Delete the file or directory.
>> .HP
>> .B read_attributes
>> .RB ( a ):
>> Read basic attributes of a file or directory.
>
> What are "attributes" in this context? Does this mean stat(2)? Make this
> explicit.

Yes.

>> This permission is always implicitly granted.
>> .HP
>> .B write_attributes
>> .RB ( A ):
>> Change the times associated with a file or directory to an arbitrary value.
>> This permission is always implicitly granted to the file owner.
>> .HP
>> .B read_acl
>> .RB ( c ):
>> Read the ACL of a file or directory. This permission is always
>> implicitly granted.
>> .HP
>> .B write_acl
>> .RB ( C ):
>> Change the ACL or file mode of a file or directory.
>> .HP
>> .B write_owner
>> .RB ( o ):
>> Take ownership of a file or directory. Change the owning group of a file or
>> directory to a group of which the calling process is a member.
>> .HP
>> .B read_named_attrs
>> .RB ( R ),
>> .B write_named_attrs
>> .RB ( W ),
>> .B synchronize
>> .RB ( S ),
>> .B write_retention
>> .RB ( e ),
>> .B write_retention_hold
>> .RB ( E ):
>> These permissions can be stored, but do not have a local meaning.
>
> So, I thenk that a sentence here should explain why these permissions
> exist. Is if for future extension, because they are meaningful in NFS,
> or something else?

Yes, they are defined by NFS.

>> .RE
>>
>> .SH TEXT FORM
>>
>> The common textual representation of richacl consists of the colon separated
>
> s/richacl/richacls/ (or, "RichACLs"/"richACLs")
>
> s/colon separated/colon-separated/
>
>> fields of the the acl flags, file masks, and acl entries in the following
>
> s/acl/ACL/ (*2)
>
>> format:
>> .TP
>> \fBflags:\fR\fIacl_flags\fR
>> The ACL flags.
>> .TP
>> \fBowner:\fR\fIperm\fR\fB::mask\fR, \fBgroup:\fR\fIperm\fR\fB::mask\fR, \fBother:\fR\fIperm\fR\fB::mask\fR
>> The file masks and their permissions.
>> .TP
>> \fIwho\fR\fB:\fR\fIperm\fR\fB:\fR\fIflags\fR\fB:allow\fR, \fIwho\fR\fB:\fR\fIperm\fR\fB:\fR\fIflags\fR\fB:deny\fR
>> For each ACL entry, who the entry applies to, the permissions of the entry, the
>> entry flags, and whether the entry allows or denies permissions. The who field has
>
> s/who/\\fIwho\\fP/
>
>> no prefix for special identifiers, a
>> .B user:
>> or
>> .B u:
>> prefix for regular users, and a
>> .B group:
>> or
>> .B g:
>> prefix for regular groups.
>> .PP
>> The entries are comma, whitespace or newline separated.
>
> s/whitespace/whitespace,/
>
>>
>> Flags and permissions have single-letter as well as long forms as listed under
>
> s/forms/forms,/
>
>> .IR "ACL Flags" ,
>> .IR "ACL Entry Flags" ,
>> and
>> .IR Permissions .
>
> If you follow my suggestion about capitalization in the ".SS" entries,
> you'll need to change the capitalization in the above phrases.
>
>> When the single-letter forms are used, the flags or permissions are
>> concatenated. When the long forms are used, the flags or permissions are
>> separated by slashes. To align permissions or flags vertically, dashes can be
>> use for padding.
>
> s/use/used/
>
>>
>> .SH SETTING AND MODIFYING FILE PERMISSIONS
>> The access permissions for a file can either be set by assigning an access
>> control list (setrichacl) or by changing the file mode permission bits (chmod).
>
> Use
> .RB ( setrichacl (1))
> for cross-reference.
>
> Use
> .RB ( chmod (1)).
>
>> In addition, a file can inherit an ACL from its parent
>> directory at create time; the inherited ACL is then further
>
> s/create/creation/
>
>> restricted by the creating system call's mode parameter (see the creat(2)
>> manual page).
>
> creat(2) is pretty much history. I suggest writing
>
> (as given to
> .BR open (2),
> .BR mkdir (2),
> and similar).
>
> And here, I think we need a statement about whether the process umask
> has an effect or not...
>
>>
>> .SS Assigning An Access Control List
>> When assigning an ACL to a file, unless explicitly specified, the owner, group,
>> and other file masks will be computed from the ACL entries as described in
>> section
>> .IR "COMPUTING THE MAXIMUM FILE MASKS" .
>> The owner, group, and other file mode permission bits are then each set from
>> the owner, group, and other file mask as follows:
>> .IP \(bu 4
>> If the file mask includes the
>> .B r
>> permission, the read
>> file mode permission bit will be set.
>> .IP \(bu
>> If the file mask includes the
>> .B w
>> or
>> .B p
>> permission, the write file mode permission bit will be set.
>> .IP \(bu
>> If the file mask includes the
>> .B x
>> permission, the execute file mode permission bit will be set.
>> .PP
>> If the ACL can be represented exactly by the file mode
>> permission bits, the file permission bits are set to match the access control
>> list and the ACL is not stored. (When the reverse happens and
>
> s/and/and the/
>
>> ACL of a file is requested which doesn't have an explicit
>> ACL, the file mode permission bits are converted into an
>> equivalent richacl.)
>>
>> .SS Changing The File Mode Permission Bits
>
> I'd use lower case in the above for all words except the first
>
>> When changing the file mode permission bits with chmod(2), the owner, group,
>
> .BR chmod (2)
>
>> and other file permission bits are set to the permission bits in the new mode,
>> and the file masks each are set based on the new mode bits as follows:
>> .IP \(bu 4
>> If the read bit in a set of permissions is set, the
>> .B r
>> permission in the corresponding file mask will be set.
>> .IP \(bu
>> If the write bit in a set of permissions is set, the
>> .B w
>> and
>> .B p
>> permissions in the corresponding file mask will be set.
>> .IP \(bu
>> If the execute bit in a set of permissions is set, the
>> .B x
>> permission in the corresponding file mask will be set.
>> .PP
>> In addition, the
>> .B masked
>> and
>> .B write_through
>> ACL flags are set. This has the
>> effect of limiting the permissions granted by the ACL to the file mode
>> permission bits; in addition, the owner is granted the owner mode bits and
>> others are granted the other mode bits. If the
>> .B auto_inherit
>> flag is set, the
>> .B protected
>> flag is also set to prevent the Automatic Inheritance algorithm from modifying
>> the ACL.
>>
>> .SS Permissions At File Create Time
>
> s/File Create/file-creation/
>
> I'd use lower case in the above for all words except the first
>
>> When a directory has inheritable ACL entries, the following
>> happens when a file or directory is created inside that directory:
>> .RS 4
>> .IP 1. 4
>> A file created inside that directory will inherit all entries with the
>
> s/all entries with/all of the directories entries that/

It's ACL entries, not directory entries, here.

>> .B file_inherit
>> flag set, and all inheritance-related flags in the inherited entries will be
>> cleared.
>>
>> A subdirectory will inherit all entries with the
>> .B file_inherit
>> or
>> .B dir_inherit
>> flag set. Entries whose
>> .B no_propagate
>> flag is set will have all inheritance-related flags cleared. Entries whose
>> .B no_propagate
>> and
>> .B dir_inherit
>> flags are not set and whose
>> .B file_inherit
>> is set will have their
>> .B inherit_only
>> flag set.
>> .IP 2.
>> If the parent directory's ACL has the
>> .B auto_inherit
>> flag set, the inherited ACL will have its
>> .B auto_inherit
>> flag set, and all entries will have their
>> .B inherited
>> flag set.
>> .IP 3.
>> The three file masks are computed from the inherited ACL as described in
>> section
>> .IR "COMPUTING THE MAXIMUM FILE MASKS" .
>> .IP 4.
>> The three sets of permissions for the owner, the group, and for others in
>> the mode parameter of the creating system call are converted into sets of
>> richacl permissions as described in section
>
> s/in/in the/
>
>> .IR "Changing The File Mode Permission Bits" .
>> Any richacl permissions not included in those sets are
>> removed from the owner, group, and other file masks. The file mode permission
>> bits are then computed from the file masks as described in section
>
> s/in/in the/
>
>> .IR "Assigning An Access Control List" .
>> .IP 5.
>> The
>> .B masked
>> ACL flag is set. The
>> .B write_through
>> ACL flag remains cleared. In addition, if the
>> .B auto_inherit
>> flag of the inherited ACL is set, the
>> .B protected
>> flag is also set to prevent the Automatic Inheritance algorithm from modifying
>> the ACL.
>> .RE
>> .PP
>> When a directory does not have inheritable ACL entries, files
>> and directories created inside that directory will not be assigned access
>> control lists and the file mode permission bits will be set to (mode\ &\
>> ~umask).
>
> will be set to
>
> (mode & ~umask)
>
> where
> .I mode
> is the permission mode argument of the relevant system call and
> .I umask
> is the process umask (see
> .BR umask (2)).
>
>>
>> .SS Automatic Inheritance
>
> I'd use lower case in the above for all words except the first

"Automatic Inheritance" is a technical term though.

>> Automatic Inheritance allows permission changes to propagate from a directory
>> to files and subdirectories inside that directory, recursively. Carrying out
>> this propagation of permissions is the responsibility of the process changing
>> the directory permissions (usually, setrichacl(1)).
>
> I'm confused by the previous sentence. the feature is labeled "Automatic
> Inheritance", implying that the user/process need do nothing. The next
> sentence says "propagation ... is the responsibility of the process".
> These two points seem contradictory. I think something more needs to be
> said here.

Let's try this maybe:

Automatic Inheritance is a mechanism that allows permission changes to
propagate from a directory to files and subdirectories inside that directory,
recursively. Propagation is carried out by the process changing the directory
permissions (usually,
.BR setrichacl (1));
it happens without user intervention albeit not entirely automatically.

>> A significant limitation is that this mechanism works only as long as files
>> are created without explicitly specifying the file permissions to use. The
>> standard system calls for creating files an directories (creat(2), open(2),
>> mkdir(2), mkfifo(2), mknod(2)) all have mandatory mode parameters which define
>
> Format that system call list as
> .RB ( creat (2),
> .BR open (2),
> .BR mkdir (2),
> .BR mknod (2))
>
> Note that I removed mkfifo(): it's a library functionlayered on
> mkonod(2).
>
>> the maximum allowed permissions of the new files. To take account of this
>> restriction, the
>> .B protected
>> ACL flag must be set if the
>> .B inherited
>> flag is set. This effectively disables Automatic Inheritance for that
>> particular file.
>>
>> Automatic Inheritance still remains useful for network protocols like NFSv4 and
>> SMB, which both support creating files and directories without defining which
>> permissions: they can implement those operations by using the standard system
>> calls and by then undoing the effect of applying the mode parameters.
>>
>> When the ACL of a directory is changed, the following should
>
> Why "should"?
>
>> happen for each entry inside that directory (for each \(lqchild\(rq):
>
> Make the preceding line:
>
> happen for each entry (\(lqchild\(rq) inside that directory:
>
>> .IP 1. 4
>> If the entry is a symblic link, skip the child.
>> .IP 2.
>> If the
>> .B auto_inherit
>> flag of the entry's ACL is not set or the
>> .B protected
>> flag is set, skip the child.
>> .IP 3.
>> With the child's ACL:
>> .RS 4
>> .IP 1. 4
>
> s/1./a)/
>
> (i.e., use a different labeling scheme for the sublist)
>
>> If the
>> .B defaulted
>> flag is set, replace the ACL with an empty ACL
>> with the
>> .B auto_inherit
>> flag set.
>> .IP 2.
>
> s/2./b)/
>
>> Delete all entries which have the
>> .B inherited
>> flag set.
>> .IP 3.
>
> s/3./c)/
>
>> Append all entries inherited from the parent directory according to step 1 of
>> the algorithm described under
>> .IR "Permissions At File Create Time".
>> Set the
>> .B inherited
>> flag of each of these entries.
>> .IP 4.
>
> s/4./d)/
>
>> Recompute the file masks.
>> .RE
>> .IP 4.
>> If the child is a directory, recursively apply this algorithm.
>>
>> .SH ACCESS CHECK ALGORITHM
>>
>> When a process requests a particular kind of access to a file defined by a set
>
> s/defined/protected/ (?)
>
>> of richacl permissions, the following algorithm determines if the access is
>
> s/if/whether/
>
>> granted or denied:
>>
>> .IP 1. 4
>> If the
>> .B masked
>> ACL flag is set, then:
>> .RS 4
>> .IP 1. 4
>
> s/1./a)/
>
> Use a different numbering scheme for sublists.
>
>> if the
>
> s/if/If/
>
>> .B write_through
>> ACL flag is set, then:
>> .RS 4
>> .IP \(bu 4
>> if the requesting process is the file owner, then access is granted if the
>
> s/if/If/
>
>> owner mask includes the requested permissions, and is otherwise denied.
>> .IP \(bu
>> if the requesting process is not the file owner, is not in the owning group,
>
> s/if/If/
>
>> and no ACL entries other than
>> .B everyone@
>> match the process, then access is granted if the other mask includes the
>> requested permissions, and is otherwise denied.
>> .RE
>> .IP 2.
>
> s/2./b)/
>
>> if any of the following is true:
>
> s/if/If/
>
>> .RS 4
>> .IP \(bu 4
>> the requesting process is the file owner and the owner mask does no include all
>
> s/no /not /
>
>> requested permissions,
>> .IP \(bu 4
>> the requesting process is not the file owner and it is in the owning group or
>> matches any ACL entries other than
>> .BR everyone@ ,
>> and the group mask does no include all requested permissions,
>> .IP \(bu 4
>> the requesting process is not the file owner, not in the owning group, it
>> matches no ACL entries other than
>> .BR everyone@ ,
>> and the other mask does no include all requested permissions,
>> .PP
>> then access is denied.
>> .RE
>> .RE
>> .IP 2.
>> Set the remaining permissions to the requested permissions. Go through all ACL
>> entries. For each entry:
>> .RS 4
>> .IP 1. 4
>
> s/1./a)/
>
> Use a different numbering scheme for sublists.
>
>> if the
>> .B inherit_only
>> or
>> .B unmapped
>> flags are set, continue with the next ACL entry.
>> .IP 2.
>
> s/2./b)/
>
>> if any of the following is true:
>> .RS 4
>> .IP \(bu 4
>> the entry's identifier is
>> .B owner@
>> and the requesting process is the file owner,
>> .IP \(bu
>> the entry's identifier is
>> .B group@
>> and the requesting process is in the owning group,
>> .IP \(bu
>> the entry's identifier is a user and the requesting process is owned by that
>> user,
>> .IP \(bu
>> the entry's identifier is a group and the requesting process is a member in
>> that group,
>> .IP \(bu
>> the entry's identifier is
>> .BR everyone@ ,
>> .PP
>> the entry matches the process; proceed. Otherwise, continue with the next ACL
>
> s/proceed/proceed to the next step/ (?)
>
>> entry.
>> .RE
>> .IP 3.
>
> s/3./c)/
>
>> If the entry denies any of the remaining permissions, access is denied.
>> .IP 4.
>
> s/4./d)/
>
>> If the entry allows any of the remaining permissions, then:
>> .RS 4
>> .IP \(bu 4
>> if the
>> .B masked
>> ACL flag is set and the entry's identifier is not
>> .B owner@
>> or
>> .BR everyone@
>> or is a user entry matching the file owner, remove all permissions from the
>> remaining permissions which are both allowed by the entry and included in the
>> group mask,
>> .IP \(bu
>> otherwise, remove all permissions from the remaining permissions wich are
>> allowed by the entry.
>> .RE
>> .RE
>> .IP 3.
>> If there are no more remaining permissions, access is allowed. Otherwise,
>> access is denied.
>>
>> .SH COMPUTING THE MAXIMUM FILE MASKS
>> When setting an ACL and no file masks have been explicitly specified and when
>> inheriting an ACL from the parent directory, the following algorithm is used
>> for computing the file masks:
>>
>> .IP 1. 4
>> Clear the owner, group, and other file masks. Remember which permissions have
>> already been processed (initially, the empty set).
>> .IP 2.
>> For each ACL entry:
>> .RS 4
>> .IP \(bu 4
>> If the
>> .B inherit_only
>> flag is set, skip the entry.
>> .IP \(bu 4
>> Otherwise, compute which permissions the entry allows or denies that have not
>> been processed yet (the remaining permissions).
>> .IP \(bu
>> If the entry is an
>> .B owner@
>> entry, add the remaining permissions to the owner mask for
>> .B allow
>> entries, and remove the remaining permissions from the owner mask for
>> .B deny
>> entries.
>> .IP \(bu
>> Otherwise, if the entry is an
>> .B everyone@
>> entry, proceed as with
>> .B owner@
>> entries but add or remove the remaining permissions from the owner, group, and
>> other file masks.
>> .IP \(bu
>> Otherwise, proceed as with
>> .B owner@
>> entries but add or remove the remaining permissions from the owner and group
>> file masks.
>> .IP \(bu
>> Add the entry's permissions to the processed permissions.
>> .RE
>> .PP
>> The resulting file masks represent the ACL as closely as possible. With these
>> file masks, if the
>> .B masked
>> ACL flag is set, the effective permissions still stay the same.
>
> This page is in *desperate* need of *multiple* examples, starting simple,
> and building up in complexity, with walkthogh text explaining how the
> permisssions are interpreted and how the masks are generated.
> Having read the page multiple times (and having little knowledge
> of NFS ACLs), I'm still struggling to put all the pieces together.

You are probably right. I'm not sure if they should go on the same man-page.

> Probably some examples that relate to an NFS context would also be
> helpful.

Hmm, I'm not sure about the difference between NFS examples and
non-NFS examples I suppose.

>> .\" .SH BUGS
>> .SH AUTHOR
>> Written by Andreas Grünbacher <[email protected]>.
>>
>> Please send your bug reports, suggested features and comments to the above address.
>>
>> .SH CONFORMING TO
>> Rich Access Control Lists are Linux-specific.
>> .SH SEE ALSO
>> .BR chmod (1),
>> .BR getrichacl (1),
>> .BR ls (1),
>> .BR setrichacl (1)
>> .BR stat (2),
>> .BR umask (2),
>> .BR acl (7)
>> .\" librichacl

Thanks a lot,
Andreas

Subject: Re: richacl(7) man page review comments

On 02/12/2016 11:25 PM, Andreas Gruenbacher wrote:
> Hi Michael,
>
> On Sun, Feb 7, 2016 at 5:35 PM, Michael Kerrisk (man-pages)
> <[email protected]> wrote:
>> Hi Andreas,
>>
>> I'll probably have quite a few more comments on this page as I get to
>> understand RichACLs better. Here's some comments from an initial
>> reading.
>
> thanks a lot for all the feedback to the man-pages. I've more or less
> made all the suggested changes but didn't get to adding examples yet
> (that's not so easy).
>
> The changes are here:
>
> https://github.com/andreas-gruenbacher/richacl

Thanks. I'll send a few further comments. But I hope to send
more in the future.

>> So, an initial comment. It seems to me to that this page (but
>> not setrichacl(1) and getrichacl(1)) should ultimately land in
>> man-pages (just like acl(7)), since we're talking about a kernel
>> feature. Make sense?
>
> We could sure move acl(5) and richacl(7) there.

We already have acl(5) (now "acl(7)" in man pages) ;-).

Cheers,

Michael



--
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Linux/UNIX System Programming Training: http://man7.org/training/

Subject: Re: richacl(7) man page review comments

Hi Andreas,

Here's a few more comments on the current richacl(7) page
that I fetched from the git repo.

> .\"
> .\" RichACL Manual Pages
> .\"
> .\" Copyright (C) 2015,2016 Red Hat, Inc.
> .\" Written by Andreas Gruenbacher <[email protected]>
> .\" This is free documentation; you can redistribute it and/or
> .\" modify it under the terms of the GNU General Public License as
> .\" published by the Free Software Foundation; either version 2 of
> .\" the License, or (at your option) any later version.
> .\"
> .\" The GNU General Public License's references to "object code"
> .\" and "executables" are to be interpreted as the output of any
> .\" document formatting or typesetting system, including
> .\" intermediate and printed output.
> .\"
> .\" This manual is distributed in the hope that it will be useful,
> .\" but WITHOUT ANY WARRANTY; without even the implied warranty of
> .\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> .\" GNU General Public License for more details.
> .\"
> .\" You should have received a copy of the GNU General Public
> .\" License along with this manual. If not, see
> .\" <http://www.gnu.org/licenses/>.
> .\"
> .de URL
> \\$2 \(laURL: \\$1 \(ra\\$3
> ..
> .if \n[.g] .mso www.tmac
> .TH RICHACL 7 2015-09-01 "Linux" "Rich Access Control Lists"
> .SH NAME
> richacl \- Rich Access Control Lists
> .SH DESCRIPTION
> Rich Access Control Lists (RichACLs) are an extension of the POSIX file
> permission model (see
> .BR acl (5))
> to support
> .URL https://tools.ietf.org/rfc/rfc5661.txt "NFSv4 Access Control Lists"
> on local and remote-mounted filesystems.

Having read the following paragraph a number of times (and being
ignorant of NFS ACLs), I find that I'm none the wiser about what you are
trying to say. What does it mean to "apply a file mode to an... ACL"?
Likewise, how does "the file mode determine the values of the file
masks"? This isn't clear in the following paragraph, and doesn't seem to
be alborated in the rest of the page. Could you add some text somehwere
to explain these points?

> RichACLs support file masks which can be used to apply a file mode to an existing
> NFSv4 ACL without destructive side effects: the file mode determines the values
> of the file masks; the file masks restrict the permissions granted by the NFSv4
> ACL. When a less restrictive file mode is applied later, the file masks become
> less restrictive, and more of the original permissions can become effective.
>
> A RichACL can always be translated into an equivalent NFSv4 ACL which grants
> the same permissions.
>
> RichACLs can be enabled on supported filesystems. This disables POSIX Access

I think it might be helpful here to list which filesystems so far
support RichACLs.

> Control Lists; the two ACL models cannot coexist on the same filesystem.
>
> When used on a filesystem that does not support RichACLs, the
> .BR getrichacl (1)
> and
> .BR setrichacl (1)
> utilities will operate on the file permission bits instead:
> .BR getrichacl (1)
> will display the file permission bits as a RichACL; when a RichACL
> is set with
> .BR setrichacl (1)
> which can be represented exactly by the file permission bits,
> .BR setrichacl (1)
> will set the file permission bits instead. An attempt to set a RichACL that
> cannot be represented exactly by the file permission bits results in an error.
>
> .SS Structure of RichACLs
>
> RichACLs consist of a number of ACL entries, three file masks, and some flags
> specifying attributes of the ACL as whole (by contrast with the per-ACL-entry
> flags described below).

Insert a blank line here, to start a new paragraph.

> Each of the ACL entries allows or denies some permissions to a particular user,
> group, or special entity. Each entry consists of:

In the previous line you write "entity". In the lines below you use
"identifier". The terminology switch is confusing. Use just one
term.

> .IP \(bu 4
> A tag which specifies the user (with prefix
> .B user:
> or
> .BR u: ),
> group (with prefix
> .B group:
> or
> .BR g: ),
> or special identifier the entry applies to. Special
> identifiers can be the file owner
> .RB ( owner@ ),
> the owning group
> .RB ( group@ ),
> or everyone
> .RB ( everyone@ ).
> .IP \(bu
> A set of permissions the entry allows or denies.
> .IP \(bu
> A set of flags that indicate whether the user or group identifier is mapped or
> unmapped, and whether the entry has been and can be inherited.
> .IP \(bu 4
> A field indicating whether the entry allows or denies access.

Does this field have a name? It would make dicussing it easier
to give it a name. That is, an ACL entry consists of four fields:

* a tag
* permissions
* flags
* ??? ("type"?)

> .PP
> The owner, group, and other file masks further control which permissions the
> ACL grants, subject to the
> .BR masked "\ (" m )
> and
> .BR write_through "\ (" w )
> ACL flags.
>
> Note that entries with the identifier
> .B everyone@
> apply to all processes, whereas the \(lqother\(rq file permissions and
> \(lqother\(rq entries in POSIX ACLs apply to all processes which are not the
> owner, are not in the owning group, and do not match a user or group mentioned
> in the ACL.
>
> Unlike POSIX ACLs, RichACLs do not have separate \(lqaccess\(rq ACLs that
> define the access permissions and \(lqdefault\(rq ACLs that define the
> inheritable permissions. Instead, flags on each ACL entry determine whether
> the entry is effective during access checks and/or inheritable.
>
>
> .SS ACL flags
>
> The following flags on ACLs are defined:
>
> .RS
> .HP

I don't think the heavy indentation here is helpful, and it narrors the
text considerably. I suggest replacing the preceding .RS+.HP with .TP,
and changing ewach .HP below to .TP, and remove the colon at the end of
each line that follows the .TP lines.

> .BR masked "\ (" m ):
> When set, the file masks define upper limits on the permissions the ACL may
> grant.
> .HP
> .BR write_through "\ (" w ):
> When this flag and the
> .B masked
> flag are both set, the owner and other file masks define the actual permissions
> granted to the file owner and to others instead of an upper limit.

There needs to be a statement here about what 'write_through' does if
'masked' is not set.

> .HP
> .BR auto_inherit "\ (" a ):
> Automatic Inheritance is enabled for the file the ACL is
> attached to. See
> .IR "Automatic Inheritance" .
> .HP
> .BR protected "\ (" p ):
> The ACL is protected from modification by Automatic
> Inheritance.
> .HP
> .BR defaulted "\ (" d ):
> The ACL has been assigned by default. Automatic Inheritance should completely

What does "assigned by default" mean? That it was inherited because of
'dir_inherit' or 'file_inherit' in the pareent directory? This needs to
be clearer.


> replace the ACL.
> .RE

If you follow my suggestion above, delete the preceding .RE

> .SS ACL entry flags
>
> The following flags on ACL entries are defined:
>
> .RS
> .HP

See above. Possibly change .RS+.HP to .TP

> .BR file_inherit "\ (" f ):
> The entry is inheritable for files.

Maybe this would be better as:

"When this flag appears in the ACL entry of a directory, then that entry is
inherited by new files created in the directory."

Is that text that I propose correct?

> .HP
> .BR dir_inherit "\ (" d ):
> The entry is inheritable for directories.

"When this flag appears in the ACL entry of a directory, then that entry is
inherited by new subdirectories created in the directory."

Is that text that I propose correct?

> .HP
> .BR no_propagate "\ (" n ):
> Inheritance stops at the next subdirectory level.
> .HP
> .BR inherit_only "\ (" i ):
> The entry defines inheritable permissions only and is ignored for access
> checking.
> .HP
> .BR inherited "\ (" a ):
> The entry has been automatically inherited from the parent directory; the
> ACL's
> .B auto_inherit
> flag should be on.
> .HP
> .BR unmapped "\ (" u ):
> The user or group identifier is a textual string and is not mapped to a numeric
> user or group identifier. ACLs with unmapped identifiers can occur on NFSv4
> mounted filesystems when the client cannot determine numeric user or group
> identifiers for some of the NFSv4 user@domain or group@domain who values. They
> cannot be assigned to local files or directories.
> .RE

If you follow my suggestion above, delete the preceding .RE

>
> .SS Permissions
>
> The following permissions are defined for RichACL entries and for the three
> file masks:
>
> .RS
> .HP

See above. Possibly change .RS+.HP yo .TP

> .BR read_data " / " list_directory "\ (" r ):
> For a file: read the data of the file.
> For a directory: list the contents of the directory.
> .HP
> .BR write_data " / " add_file "\ (" w ):
> For a file: modify the data of the file; does not include opening the file in
> append mode.
> For a directory: add a new file in the directory.
> .HP
> .BR append_data " / " add_subdirectory "\ (" p ):
> For a file: open the file in append mode.
> For a directory: create a subdirectory in the directory.
> .HP
> .BR execute "\ (" x ):
> For a file: execute the file.
> For a directory: traverse / search the directory.
> .HP
> .BR delete_child "\ (" d ):
> Delete a file or directory within a directory.
> .HP
> .BR delete "\ (" D ):
> Delete the file or directory.
> .HP
> .BR read_attributes "\ (" a ):
> Read basic attributes of a file or directory (see
> .BR stat (2)).
> This permission is always implicitly granted.

So, can this permission ever be taken away? If yes, say so. If not, why
does this permission exist? (And maybe say something about that.)

> .HP
> .BR write_attributes "\ (" A ):
> Change the times associated with a file or directory to an arbitrary value.
> This permission is always implicitly granted to the file owner.
> .HP
> .BR read_acl "\ (" c ):
> Read the ACL of a file or directory. This permission is always
> implicitly granted.
> .HP
> .BR write_acl "\ (" C ):
> Change the ACL or file mode of a file or directory.
> .HP
> .BR write_owner "\ (" o ):
> Take ownership of a file or directory. Change the owning group of a file or
> directory to a group of which the calling process is a member.
> .HP
> .BR read_named_attrs "\ (" R ),
> .BR write_named_attrs "\ (" W ),
> .BR synchronize "\ (" S ),
> .BR write_retention "\ (" e ),
> .BR write_retention_hold "\ (" E ):

If you follow my .TP suggestion above, then the above lines would need
to be rewritten sometinh like:

.BR read_named_attrs "\ (" R "), " write_named_attrs "\ (" W "), " \
synchronize "\ (" S "), " write_retention "\ (" e "), " \
write_retention_hold "\ (" E )

> These permissions are defined by NFSv4 / NFSv4.1. They can be stored, but are
> not used.
> .RE

If you follow my suggestion above, delete the preceding .RE and
add .PP

>
> For the
> .BR r ", " w ", and " p
> permissions which have different long forms for files and directories, the
> .BR getrichacl (1)
> utility will output the appropriate form(s) depending on the context.
> The
> .BR setrichacl (1)
> utility will accept either form for any file type.
>
> .SS Text form
> The common textual representation of a RichACL consists of the colon-separated
> fields of the the ACL flags, file masks, and ACL entries in the following

s/the the/the/

> format:
> .TP
> \fBflags:\fR\fIacl_flags\fR
> The ACL flags.
> .TP
> \fBowner:\fR\fIperm\fR\fB::mask\fR, \fBgroup:\fR\fIperm\fR\fB::mask\fR, \fBother:\fR\fIperm\fR\fB::mask\fR
> The file masks and their permissions.
> .TP
> \fIwho\fR\fB:\fR\fIperm\fR\fB:\fR\fIflags\fR\fB:allow\fR, \fIwho\fR\fB:\fR\fIperm\fR\fB:\fR\fIflags\fR\fB:deny\fR
> For each ACL entry, who the entry applies to, the permissions of the entry, the
> entry flags, and whether the entry allows or denies permissions. The \fIwho\fR
> field has no prefix for special identifiers, a
> .B user:
> or
> .B u:
> prefix for regular users, and a
> .B group:
> or
> .B g:
> prefix for regular groups.

I think the preceding sentence could be clearer. How about something
like the following (if correct):

[[
The who field is one of the following:

* One of the special identifiers: owner@, group@, or everyone@
* A user: or u: prefix followed by a [user name, user ID?] that designates
s specific user
* A group: or g: prefix followed by a [group name, group ID?] that designates
s specific group
]]

> .PP
> The entries are comma, whitespace, or newline separated.
>
> Flags and permissions have single-letter as well as long forms, as listed under
> .IR "ACL flags" ,
> .IR "ACL entry flags" ,
> and
> .IR Permissions .
> When the single-letter forms are used, the flags or permissions are
> concatenated. When the long forms are used, the flags or permissions are
> separated by slashes. To align permissions or flags vertically, dashes can be
> used for padding.
>
> .SS Setting and modifying file permissions
> The access permissions for a file can either be set by assigning an access
> control list
> .RB ( setrichacl (1))
> or by changing the file mode permission bits
> .RB ( chmod (1)).
> In addition, a file can inherit an ACL from its parent directory at creation
> time as described under
> .IR "Permissions at file-creation time" .
>
> .SS Assigning an Access Control List
> When assigning an ACL to a file, unless explicitly specified, the owner, group,
> and other file masks will be computed from the ACL entries as described in
> the section
> .IR "Computing the maximum file masks" .
> The owner, group, and other file mode permission bits are then each set from
> the owner, group, and other file mask as follows:
> .IP \(bu 4
> If the file mask includes the
> .B r
> permission, the read
> file mode permission bit will be set.
> .IP \(bu
> If the file mask includes the
> .B w
> or
> .B p
> permission, the write file mode permission bit will be set.
> .IP \(bu
> If the file mask includes the
> .B x
> permission, the execute file mode permission bit will be set.
> .PP
> If the ACL can be represented exactly by the file mode
> permission bits, the file permission bits are set to match the ACL and the ACL
> is not stored. (When the ACL of a file is requested which doesn't have an ACL,
> the file mode permission bits are converted into an equivalent ACL.)
>
> .SS Changing the file mode permission bits
> When changing the file mode permission bits with
> .BR chmod (1),
> the owner, group,
> and other file permission bits are set to the permission bits in the new mode,
> and the file masks each are set based on the new mode bits as follows:
> .IP \(bu 4
> If the read bit in a set of permissions is set, the
> .B r
> permission in the corresponding file mask will be set.
> .IP \(bu
> If the write bit in a set of permissions is set, the
> .B w
> and
> .B p
> permissions in the corresponding file mask will be set.
> .IP \(bu
> If the execute bit in a set of permissions is set, the
> .B x
> permission in the corresponding file mask will be set.
> .PP
> In addition, the
> .B masked
> and
> .B write_through
> ACL flags are set. This has the
> effect of limiting the permissions granted by the ACL to the file mode
> permission bits; in addition, the owner is granted the owner mode bits and
> others are granted the other mode bits. If the
> .B auto_inherit
> flag is set, the
> .B protected
> flag is also set to prevent the Automatic Inheritance algorithm from modifying
> the ACL.
>
> .SS Permissions at file-creation time
> When a directory has inheritable ACL entries, the following
> happens when a file or directory is created inside that directory:
> .RS 4
> .IP 1. 4
> A file created inside that directory will inherit all of the ACL entries that
> have the
> .B file_inherit
> flag set, and all inheritance-related flags in the inherited entries will be
> cleared.
>
> A subdirectory created inside that directory will inherit all of the ACL
> entries that have the
> .B file_inherit
> or
> .B dir_inherit
> flag set. Entries whose
> .B no_propagate
> flag is set will have all inheritance-related flags cleared. Entries whose
> .B no_propagate
> and
> .B dir_inherit
> flags are not set and whose
> .B file_inherit
> is set will have their
> .B inherit_only
> flag set.
> .IP 2.
> If the parent directory's ACL has the
> .B auto_inherit
> flag set, the inherited ACL will have its
> .B auto_inherit
> flag set, and all entries will have their
> .B inherited
> flag set.
> .IP 3.
> The three file masks are computed from the inherited ACL as described in
> the section
> .IR "Computing the maximum file masks" .
> .IP 4.
> The three sets of permissions for the owner, the group, and for others in
> the \fImode\fR parameter as given to
> .BR open (2),
> .BR mkdir (2),
> and similar are converted into sets of RichACL permissions as described in
> the section
> .IR "Changing the file mode permission bits" .
> Any RichACL permissions not included in those sets are
> removed from the owner, group, and other file masks. The file mode permission
> bits are then computed from the file masks as described in the section
> .IR "Assigning an Access Control List" .
> The process umask (see
> .BR umask (2))
> is ignored.
> .IP 5.
> The
> .B masked
> ACL flag is set. The
> .B write_through
> ACL flag remains cleared. In addition, if the
> .B auto_inherit
> flag of the inherited ACL is set, the
> .B protected
> flag is also set to prevent the Automatic Inheritance algorithm from modifying
> the ACL.
> .RE
> .PP
> When a directory does not have inheritable ACL entries, files and directories
> created inside that directory will not be assigned access control lists and the
> file mode permission bits will be set to (\fImode\fR\ &\ ~\fIumask\fR) where
> \fImode\fR is the mode argument of the relevant system call and \fIumask\fR is
> the process umask (see
> .BR umask (2)).
>
> .SS Automatic Inheritance
> Automatic Inheritance is a mechanism that allows permission changes to
> propagate from a directory to files and subdirectories inside that directory,
> recursively. Propagation is carried out by the process changing the directory
> permissions (usually,
> .BR setrichacl (1));
> it happens without user intervention albeit not entirely automatically.
>
> A significant limitation is that this mechanism works only as long as files
> are created without explicitly specifying the file permissions to use. The
> standard system calls for creating files an directories (

s/an /and /
s/ ($//

> .BR creat (2),

Make that last line:

.RM ( creat (2),

> .BR open (2),
> .BR mkdir (2),
> .BR mknod (2))
> all have mandatory mode parameters which define the maximum allowed permissions
> of the new files. To take account of this restriction, the
> .B protected
> ACL flag must be set if the
> .B inherited
> flag is set. This effectively disables Automatic Inheritance for that
> particular file.
>
> Automatic Inheritance still remains useful for network protocols like NFSv4 and
> SMB, which both support creating files and directories without defining which

s/which$/their/

> permissions: they can implement those operations by using the standard system
> calls and by then undoing the effect of applying the mode parameters.
>
> When the ACL of a directory is changed, the following happens for each entry
> (\(lqchild\(rq) inside that directory:
> .IP 1. 4
> If the entry is a symblic link, skip the child.
> .IP 2.
> If the
> .B auto_inherit
> flag of the entry's ACL is not set or the
> .B protected
> flag is set, skip the child.
> .IP 3.
> With the child's ACL:
> .RS 4
> .IP a) 4
> If the
> .B defaulted
> flag is set, replace the ACL with an empty ACL
> with the
> .B auto_inherit
> flag set.
> .IP b)
> Delete all entries which have the
> .B inherited
> flag set.
> .IP c)
> Append all entries inherited from the parent directory according to step 1 of
> the algorithm described under
> .IR "Permissions at file-creation time".
> Set the
> .B inherited
> flag of each of these entries.
> .IP d)
> Recompute the file masks.
> .RE
> .IP 4.
> If the child is a directory, recursively apply this algorithm.
>
> .SS Access check algorithm
>
> When a process requests a particular kind of access (expressed as a set of
> RichACL permissions) to a file, the following algorithm determines whether the
> access is granted or denied:
>
> .IP 1. 4
> If the
> .B masked
> ACL flag is set, then:
> .RS 4
> .IP a) 4
> If the
> .B write_through
> ACL flag is set, then:
> .RS 4
> .IP \(bu 4
> If the requesting process is the file owner, then access is granted if the
> owner mask includes the requested permissions, and is otherwise denied.
> .IP \(bu
> If the requesting process is not the file owner, is not in the owning group,
> and no ACL entries other than
> .B everyone@
> match the process, then access is granted if the other mask includes the
> requested permissions, and is otherwise denied.
> .RE
> .IP b)
> If any of the following is true:
> .RS 4
> .IP \(bu 4
> the requesting process is the file owner and the owner mask does not include all
> requested permissions,
> .IP \(bu 4
> the requesting process is not the file owner and it is in the owning group or
> matches any ACL entries other than
> .BR everyone@ ,
> and the group mask does not include all requested permissions,
> .IP \(bu 4
> the requesting process is not the file owner, not in the owning group, it
> matches no ACL entries other than
> .BR everyone@ ,
> and the other mask does not include all requested permissions,
> .PP
> then access is denied.
> .RE
> .RE
> .IP 2.
> Set the remaining permissions to the requested permissions. Go through all ACL
> entries. For each entry:
> .RS 4
> .IP a) 4
> If the
> .B inherit_only
> or
> .B unmapped
> flags are set, continue with the next ACL entry.
> .IP b)
> If any of the following is true:
> .RS 4
> .IP \(bu 4
> the entry's identifier is
> .B owner@
> and the requesting process is the file owner,
> .IP \(bu
> the entry's identifier is
> .B group@
> and the requesting process is in the owning group,
> .IP \(bu
> the entry's identifier is a user and the requesting process is owned by that
> user,
> .IP \(bu
> the entry's identifier is a group and the requesting process is a member in
> that group,
> .IP \(bu
> the entry's identifier is
> .BR everyone@ ,
> .PP
> then the entry matches the process; proceed to the next step. Otherwise,
> continue with the next ACL entry.
> .RE
> .IP c)
> If the entry denies any of the remaining permissions, access is denied.
> .IP d)
> If the entry allows any of the remaining permissions, then:
> .RS 4
> .IP \(bu 4
> If the
> .B masked
> ACL flag is set and the entry's identifier is not
> .B owner@
> or
> .BR everyone@
> or is a user entry matching the file owner, remove all permissions from the
> remaining permissions which are both allowed by the entry and included in the
> group mask,
> .IP \(bu
> Otherwise, remove all permissions from the remaining permissions wich are
> allowed by the entry.
> .RE
> .RE
> .IP 3.
> If there are no more remaining permissions, access is allowed. Otherwise,
> access is denied.
>
> .SS Computing the maximum file masks
> When setting an ACL and no file masks have been explicitly specified and when
> inheriting an ACL from the parent directory, the following algorithm is used
> for computing the file masks:
>
> .IP 1. 4
> Clear the owner, group, and other file masks. Remember which permissions have
> already been processed (initially, the empty set).
> .IP 2.
> For each ACL entry:
> .RS 4
> .IP \(bu 4
> If the
> .B inherit_only
> flag is set, skip the entry.
> .IP \(bu 4
> Otherwise, compute which permissions the entry allows or denies that have not
> been processed yet (the remaining permissions).
> .IP \(bu
> If the entry is an
> .B owner@
> entry, add the remaining permissions to the owner mask for
> .B allow
> entries, and remove the remaining permissions from the owner mask for
> .B deny
> entries.
> .IP \(bu
> Otherwise, if the entry is an
> .B everyone@
> entry, proceed as with
> .B owner@
> entries but add or remove the remaining permissions from the owner, group, and
> other file masks.
> .IP \(bu
> Otherwise, proceed as with
> .B owner@
> entries but add or remove the remaining permissions from the owner and group
> file masks.
> .IP \(bu
> Add the entry's permissions to the processed permissions.
> .RE
> .PP
> The resulting file masks represent the ACL as closely as possible. With these
> file masks, if the
> .B masked
> ACL flag is set, the effective permissions still stay the same.
>
> .\" .SH BUGS
> .SH AUTHOR
> Written by Andreas Grünbacher <[email protected]>.
>
> Please send your bug reports, suggested features and comments to the above address.

Could we start with just a few simple examples already, and build up
over future iterations of this page?

> .SH CONFORMING TO
> Rich Access Control Lists are Linux-specific.
> .SH SEE ALSO
> .BR acl (5),
> .BR chmod (1),
> .BR getrichacl (1),
> .BR ls (1),
> .BR setrichacl (1)
> .BR stat (2),
> .BR umask (2)
> .\" librichacl

Thanks,

Michael

--
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Linux/UNIX System Programming Training: http://man7.org/training/

2016-02-14 23:12:21

by Andreas Gruenbacher

[permalink] [raw]
Subject: Re: richacl(7) man page review comments

On Sun, Feb 14, 2016 at 10:27 PM, Michael Kerrisk (man-pages)
<[email protected]> wrote:
> On 02/12/2016 11:25 PM, Andreas Gruenbacher wrote:
>> We could sure move acl(5) and richacl(7) there.
>
> We already have acl(5) (now "acl(7)" in man pages) ;-).

Hmm, I can't find that page either in
git://git.kernel.org/pub/scm/docs/man-pages/man-pages or on
http://man7.org/. Are you sure you don't mean xattr.7 == attr.5 which
documents the xattr syscall interface?

Andreas

_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs

Subject: Re: richacl(7) man page review comments

Hi Andreas,

On 02/15/2016 12:12 AM, Andreas Gruenbacher wrote:
> On Sun, Feb 14, 2016 at 10:27 PM, Michael Kerrisk (man-pages)
> <[email protected]> wrote:
>> On 02/12/2016 11:25 PM, Andreas Gruenbacher wrote:
>>> We could sure move acl(5) and richacl(7) there.
>>
>> We already have acl(5) (now "acl(7)" in man pages) ;-).
>
> Hmm, I can't find that page either in
> git://git.kernel.org/pub/scm/docs/man-pages/man-pages or on
> http://man7.org/. Are you sure you don't mean xattr.7 == attr.5 which
> documents the xattr syscall interface?

You're right. I was confusing with xattr(7). So, I think it might
make some sense to eventually move both of these into man-pages (for
richacl(7), at least, it's probably worth delaying this for a bit),
since they're describing kernel-user-space interfaces. I can see
counter-arguments too, such as these pages are closely related to
the corresponding user-space libraries you maintain. What do you
think?

Thanks,

Michael



--
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Linux/UNIX System Programming Training: http://man7.org/training/

2016-02-15 11:35:14

by Andreas Gruenbacher

[permalink] [raw]
Subject: Re: richacl(7) man page review comments

On Mon, Feb 15, 2016 at 11:25 AM, Michael Kerrisk (man-pages)
<[email protected]> wrote:
> You're right. I was confusing with xattr(7). So, I think it might
> make some sense to eventually move both of these into man-pages (for
> richacl(7), at least, it's probably worth delaying this for a bit),
> since they're describing kernel-user-space interfaces.

Well, the actual user-space interface is xattrs in both cases.

> I can see counter-arguments too, such as these pages are closely
> related to the corresponding user-space libraries you maintain.
> What do you think?

I would keep the man-pages where they are right now, but I don't have
a strong preference.

Andreas

Subject: Re: richacl(7) man page review comments

On 15 February 2016 at 12:35, Andreas Gruenbacher <[email protected]> wrote:
> On Mon, Feb 15, 2016 at 11:25 AM, Michael Kerrisk (man-pages)
> <[email protected]> wrote:
>> You're right. I was confusing with xattr(7). So, I think it might
>> make some sense to eventually move both of these into man-pages (for
>> richacl(7), at least, it's probably worth delaying this for a bit),
>> since they're describing kernel-user-space interfaces.
>
> Well, the actual user-space interface is xattrs in both cases.

Yes, xattrs are the base of the framework, but I was using "interface"
in a very broad way: ACLs and RichACLs are exposing kernel-defined
policies and rules about file permissions to user space (much as say
chmod(2) and the file mode bits). That's why it seems to make some
sense to place those pages with the other pages that describe
kernel-user-spaces interfaces. Plus, they'd now and then get some
man-pages love :-).

>> I can see counter-arguments too, such as these pages are closely
>> related to the corresponding user-space libraries you maintain.
>> What do you think?
>
> I would keep the man-pages where they are right now, but I don't have
> a strong preference.

I'd be happy to see acl(5) and eventually richacl(7) in man pages, but
it's your call in the end, of course.

Cheers,

Michael

--
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Linux/UNIX System Programming Training: http://man7.org/training/

2016-02-20 16:37:21

by Andreas Gruenbacher

[permalink] [raw]
Subject: Re: richacl(7) man page review comments

Hi Michael,

thanks again for all the feedback. I've followed all your suggestions;
again, please see the github repo for the latest version:

https://github.com/andreas-gruenbacher/richacl

On Sun, Feb 14, 2016 at 10:31 PM, Michael Kerrisk (man-pages)
<[email protected]> wrote:
> Hi Andreas,
>
> Here's a few more comments on the current richacl(7) page
> that I fetched from the git repo.
>
>> .\"
>> .\" RichACL Manual Pages
>> .\"
>> .\" Copyright (C) 2015,2016 Red Hat, Inc.
>> .\" Written by Andreas Gruenbacher <[email protected]>
>> .\" This is free documentation; you can redistribute it and/or
>> .\" modify it under the terms of the GNU General Public License as
>> .\" published by the Free Software Foundation; either version 2 of
>> .\" the License, or (at your option) any later version.
>> .\"
>> .\" The GNU General Public License's references to "object code"
>> .\" and "executables" are to be interpreted as the output of any
>> .\" document formatting or typesetting system, including
>> .\" intermediate and printed output.
>> .\"
>> .\" This manual is distributed in the hope that it will be useful,
>> .\" but WITHOUT ANY WARRANTY; without even the implied warranty of
>> .\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>> .\" GNU General Public License for more details.
>> .\"
>> .\" You should have received a copy of the GNU General Public
>> .\" License along with this manual. If not, see
>> .\" <http://www.gnu.org/licenses/>.
>> .\"
>> .de URL
>> \\$2 \(laURL: \\$1 \(ra\\$3
>> ..
>> .if \n[.g] .mso www.tmac
>> .TH RICHACL 7 2015-09-01 "Linux" "Rich Access Control Lists"
>> .SH NAME
>> richacl \- Rich Access Control Lists
>> .SH DESCRIPTION
>> Rich Access Control Lists (RichACLs) are an extension of the POSIX file
>> permission model (see
>> .BR acl (5))
>> to support
>> .URL https://tools.ietf.org/rfc/rfc5661.txt "NFSv4 Access Control Lists"
>> on local and remote-mounted filesystems.
>
> Having read the following paragraph a number of times (and being
> ignorant of NFS ACLs), I find that I'm none the wiser about what you are
> trying to say. What does it mean to "apply a file mode to an... ACL"?
> Likewise, how does "the file mode determine the values of the file
> masks"? This isn't clear in the following paragraph, and doesn't seem to
> be elborated in the rest of the page. Could you add some text somehwere
> to explain these points?

I've removed this paragraph and I've tried to explain what the masks
do in the Structure of RichACLs section.

>> RichACLs support file masks which can be used to apply a file mode to an existing
>> NFSv4 ACL without destructive side effects: the file mode determines the values
>> of the file masks; the file masks restrict the permissions granted by the NFSv4
>> ACL. When a less restrictive file mode is applied later, the file masks become
>> less restrictive, and more of the original permissions can become effective.
>>
>> A RichACL can always be translated into an equivalent NFSv4 ACL which grants
>> the same permissions.
>>
>> RichACLs can be enabled on supported filesystems. This disables POSIX Access
>
> I think it might be helpful here to list which filesystems so far
> support RichACLs.
>
>> Control Lists; the two ACL models cannot coexist on the same filesystem.
>>
>> When used on a filesystem that does not support RichACLs, the
>> .BR getrichacl (1)
>> and
>> .BR setrichacl (1)
>> utilities will operate on the file permission bits instead:
>> .BR getrichacl (1)
>> will display the file permission bits as a RichACL; when a RichACL
>> is set with
>> .BR setrichacl (1)
>> which can be represented exactly by the file permission bits,
>> .BR setrichacl (1)
>> will set the file permission bits instead. An attempt to set a RichACL that
>> cannot be represented exactly by the file permission bits results in an error.
>>
>> .SS Structure of RichACLs
>>
>> RichACLs consist of a number of ACL entries, three file masks, and some flags
>> specifying attributes of the ACL as whole (by contrast with the per-ACL-entry
>> flags described below).
>
> Insert a blank line here, to start a new paragraph.
>
>> Each of the ACL entries allows or denies some permissions to a particular user,
>> group, or special entity. Each entry consists of:
>
> In the previous line you write "entity". In the lines below you use
> "identifier". The terminology switch is confusing. Use just one
> term.
>
>> .IP \(bu 4
>> A tag which specifies the user (with prefix
>> .B user:
>> or
>> .BR u: ),
>> group (with prefix
>> .B group:
>> or
>> .BR g: ),
>> or special identifier the entry applies to. Special
>> identifiers can be the file owner
>> .RB ( owner@ ),
>> the owning group
>> .RB ( group@ ),
>> or everyone
>> .RB ( everyone@ ).
>> .IP \(bu
>> A set of permissions the entry allows or denies.
>> .IP \(bu
>> A set of flags that indicate whether the user or group identifier is mapped or
>> unmapped, and whether the entry has been and can be inherited.
>> .IP \(bu 4
>> A field indicating whether the entry allows or denies access.
>
> Does this field have a name? It would make dicussing it easier
> to give it a name. That is, an ACL entry consists of four fields:
>
> * a tag
> * permissions
> * flags
> * ??? ("type"?)
>
>> .PP
>> The owner, group, and other file masks further control which permissions the
>> ACL grants, subject to the
>> .BR masked "\ (" m )
>> and
>> .BR write_through "\ (" w )
>> ACL flags.
>>
>> Note that entries with the identifier
>> .B everyone@
>> apply to all processes, whereas the \(lqother\(rq file permissions and
>> \(lqother\(rq entries in POSIX ACLs apply to all processes which are not the
>> owner, are not in the owning group, and do not match a user or group mentioned
>> in the ACL.
>>
>> Unlike POSIX ACLs, RichACLs do not have separate \(lqaccess\(rq ACLs that
>> define the access permissions and \(lqdefault\(rq ACLs that define the
>> inheritable permissions. Instead, flags on each ACL entry determine whether
>> the entry is effective during access checks and/or inheritable.
>>
>>
>> .SS ACL flags
>>
>> The following flags on ACLs are defined:
>>
>> .RS
>> .HP
>
> I don't think the heavy indentation here is helpful, and it narrors the
> text considerably. I suggest replacing the preceding .RS+.HP with .TP,
> and changing ewach .HP below to .TP, and remove the colon at the end of
> each line that follows the .TP lines.

That's what I thought too, and that's why I had ".RS 4" and ".HP 4"
here originally.

>> .BR masked "\ (" m ):
>> When set, the file masks define upper limits on the permissions the ACL may
>> grant.
>> .HP
>> .BR write_through "\ (" w ):
>> When this flag and the
>> .B masked
>> flag are both set, the owner and other file masks define the actual permissions
>> granted to the file owner and to others instead of an upper limit.
>
> There needs to be a statement here about what 'write_through' does if
> 'masked' is not set.
>
>> .HP
>> .BR auto_inherit "\ (" a ):
>> Automatic Inheritance is enabled for the file the ACL is
>> attached to. See
>> .IR "Automatic Inheritance" .
>> .HP
>> .BR protected "\ (" p ):
>> The ACL is protected from modification by Automatic
>> Inheritance.
>> .HP
>> .BR defaulted "\ (" d ):
>> The ACL has been assigned by default. Automatic Inheritance should completely
>
> What does "assigned by default" mean? That it was inherited because of
> 'dir_inherit' or 'file_inherit' in the pareent directory? This needs to
> be clearer.
>
>
>> replace the ACL.
>> .RE
>
> If you follow my suggestion above, delete the preceding .RE
>
>> .SS ACL entry flags
>>
>> The following flags on ACL entries are defined:
>>
>> .RS
>> .HP
>
> See above. Possibly change .RS+.HP to .TP
>
>> .BR file_inherit "\ (" f ):
>> The entry is inheritable for files.
>
> Maybe this would be better as:
>
> "When this flag appears in the ACL entry of a directory, then that entry is
> inherited by new files created in the directory."
>
> Is that text that I propose correct?
>
>> .HP
>> .BR dir_inherit "\ (" d ):
>> The entry is inheritable for directories.
>
> "When this flag appears in the ACL entry of a directory, then that entry is
> inherited by new subdirectories created in the directory."
>
> Is that text that I propose correct?

It's not entirely wrong, but only a small part of the truth. Entries
are inherited such that the permissions in file_inherit entries become
effective for access checking for new files, and the permissions in
dir_inherit entries become effective for access checking for new
directories, recursively.

Your feedback prompted me to look into the inheritance flag
computation more closely once again, and I found bugs. The steps of
the algorithm are explained in the section "Permissions at
file-creation time", by the way.

>> .HP
>> .BR no_propagate "\ (" n ):
>> Inheritance stops at the next subdirectory level.
>> .HP
>> .BR inherit_only "\ (" i ):
>> The entry defines inheritable permissions only and is ignored for access
>> checking.
>> .HP
>> .BR inherited "\ (" a ):
>> The entry has been automatically inherited from the parent directory; the
>> ACL's
>> .B auto_inherit
>> flag should be on.
>> .HP
>> .BR unmapped "\ (" u ):
>> The user or group identifier is a textual string and is not mapped to a numeric
>> user or group identifier. ACLs with unmapped identifiers can occur on NFSv4
>> mounted filesystems when the client cannot determine numeric user or group
>> identifiers for some of the NFSv4 user@domain or group@domain who values. They
>> cannot be assigned to local files or directories.
>> .RE
>
> If you follow my suggestion above, delete the preceding .RE
>
>>
>> .SS Permissions
>>
>> The following permissions are defined for RichACL entries and for the three
>> file masks:
>>
>> .RS
>> .HP
>
> See above. Possibly change .RS+.HP yo .TP
>
>> .BR read_data " / " list_directory "\ (" r ):
>> For a file: read the data of the file.
>> For a directory: list the contents of the directory.
>> .HP
>> .BR write_data " / " add_file "\ (" w ):
>> For a file: modify the data of the file; does not include opening the file in
>> append mode.
>> For a directory: add a new file in the directory.
>> .HP
>> .BR append_data " / " add_subdirectory "\ (" p ):
>> For a file: open the file in append mode.
>> For a directory: create a subdirectory in the directory.
>> .HP
>> .BR execute "\ (" x ):
>> For a file: execute the file.
>> For a directory: traverse / search the directory.
>> .HP
>> .BR delete_child "\ (" d ):
>> Delete a file or directory within a directory.
>> .HP
>> .BR delete "\ (" D ):
>> Delete the file or directory.
>> .HP
>> .BR read_attributes "\ (" a ):
>> Read basic attributes of a file or directory (see
>> .BR stat (2)).
>> This permission is always implicitly granted.
>
> So, can this permission ever be taken away? If yes, say so. If not, why
> does this permission exist? (And maybe say something about that.)
>
>> .HP
>> .BR write_attributes "\ (" A ):
>> Change the times associated with a file or directory to an arbitrary value.
>> This permission is always implicitly granted to the file owner.
>> .HP
>> .BR read_acl "\ (" c ):
>> Read the ACL of a file or directory. This permission is always
>> implicitly granted.
>> .HP
>> .BR write_acl "\ (" C ):
>> Change the ACL or file mode of a file or directory.
>> .HP
>> .BR write_owner "\ (" o ):
>> Take ownership of a file or directory. Change the owning group of a file or
>> directory to a group of which the calling process is a member.
>> .HP
>> .BR read_named_attrs "\ (" R ),
>> .BR write_named_attrs "\ (" W ),
>> .BR synchronize "\ (" S ),
>> .BR write_retention "\ (" e ),
>> .BR write_retention_hold "\ (" E ):
>
> If you follow my .TP suggestion above, then the above lines would need
> to be rewritten sometinh like:
>
> .BR read_named_attrs "\ (" R "), " write_named_attrs "\ (" W "), " \
> synchronize "\ (" S "), " write_retention "\ (" e "), " \
> write_retention_hold "\ (" E )
>
>> These permissions are defined by NFSv4 / NFSv4.1. They can be stored, but are
>> not used.
>> .RE
>
> If you follow my suggestion above, delete the preceding .RE and
> add .PP
>
>>
>> For the
>> .BR r ", " w ", and " p
>> permissions which have different long forms for files and directories, the
>> .BR getrichacl (1)
>> utility will output the appropriate form(s) depending on the context.
>> The
>> .BR setrichacl (1)
>> utility will accept either form for any file type.
>>
>> .SS Text form
>> The common textual representation of a RichACL consists of the colon-separated
>> fields of the the ACL flags, file masks, and ACL entries in the following
>
> s/the the/the/
>
>> format:
>> .TP
>> \fBflags:\fR\fIacl_flags\fR
>> The ACL flags.
>> .TP
>> \fBowner:\fR\fIperm\fR\fB::mask\fR, \fBgroup:\fR\fIperm\fR\fB::mask\fR, \fBother:\fR\fIperm\fR\fB::mask\fR
>> The file masks and their permissions.
>> .TP
>> \fIwho\fR\fB:\fR\fIperm\fR\fB:\fR\fIflags\fR\fB:allow\fR, \fIwho\fR\fB:\fR\fIperm\fR\fB:\fR\fIflags\fR\fB:deny\fR
>> For each ACL entry, who the entry applies to, the permissions of the entry, the
>> entry flags, and whether the entry allows or denies permissions. The \fIwho\fR
>> field has no prefix for special identifiers, a
>> .B user:
>> or
>> .B u:
>> prefix for regular users, and a
>> .B group:
>> or
>> .B g:
>> prefix for regular groups.
>
> I think the preceding sentence could be clearer. How about something
> like the following (if correct):
>
> [[
> The who field is one of the following:
>
> * One of the special identifiers: owner@, group@, or everyone@
> * A user: or u: prefix followed by a [user name, user ID?] that designates
> s specific user
> * A group: or g: prefix followed by a [group name, group ID?] that designates
> s specific group
> ]]
>
>> .PP
>> The entries are comma, whitespace, or newline separated.
>>
>> Flags and permissions have single-letter as well as long forms, as listed under
>> .IR "ACL flags" ,
>> .IR "ACL entry flags" ,
>> and
>> .IR Permissions .
>> When the single-letter forms are used, the flags or permissions are
>> concatenated. When the long forms are used, the flags or permissions are
>> separated by slashes. To align permissions or flags vertically, dashes can be
>> used for padding.
>>
>> .SS Setting and modifying file permissions
>> The access permissions for a file can either be set by assigning an access
>> control list
>> .RB ( setrichacl (1))
>> or by changing the file mode permission bits
>> .RB ( chmod (1)).
>> In addition, a file can inherit an ACL from its parent directory at creation
>> time as described under
>> .IR "Permissions at file-creation time" .
>>
>> .SS Assigning an Access Control List
>> When assigning an ACL to a file, unless explicitly specified, the owner, group,
>> and other file masks will be computed from the ACL entries as described in
>> the section
>> .IR "Computing the maximum file masks" .
>> The owner, group, and other file mode permission bits are then each set from
>> the owner, group, and other file mask as follows:
>> .IP \(bu 4
>> If the file mask includes the
>> .B r
>> permission, the read
>> file mode permission bit will be set.
>> .IP \(bu
>> If the file mask includes the
>> .B w
>> or
>> .B p
>> permission, the write file mode permission bit will be set.
>> .IP \(bu
>> If the file mask includes the
>> .B x
>> permission, the execute file mode permission bit will be set.
>> .PP
>> If the ACL can be represented exactly by the file mode
>> permission bits, the file permission bits are set to match the ACL and the ACL
>> is not stored. (When the ACL of a file is requested which doesn't have an ACL,
>> the file mode permission bits are converted into an equivalent ACL.)
>>
>> .SS Changing the file mode permission bits
>> When changing the file mode permission bits with
>> .BR chmod (1),
>> the owner, group,
>> and other file permission bits are set to the permission bits in the new mode,
>> and the file masks each are set based on the new mode bits as follows:
>> .IP \(bu 4
>> If the read bit in a set of permissions is set, the
>> .B r
>> permission in the corresponding file mask will be set.
>> .IP \(bu
>> If the write bit in a set of permissions is set, the
>> .B w
>> and
>> .B p
>> permissions in the corresponding file mask will be set.
>> .IP \(bu
>> If the execute bit in a set of permissions is set, the
>> .B x
>> permission in the corresponding file mask will be set.
>> .PP
>> In addition, the
>> .B masked
>> and
>> .B write_through
>> ACL flags are set. This has the
>> effect of limiting the permissions granted by the ACL to the file mode
>> permission bits; in addition, the owner is granted the owner mode bits and
>> others are granted the other mode bits. If the
>> .B auto_inherit
>> flag is set, the
>> .B protected
>> flag is also set to prevent the Automatic Inheritance algorithm from modifying
>> the ACL.
>>
>> .SS Permissions at file-creation time
>> When a directory has inheritable ACL entries, the following
>> happens when a file or directory is created inside that directory:
>> .RS 4
>> .IP 1. 4
>> A file created inside that directory will inherit all of the ACL entries that
>> have the
>> .B file_inherit
>> flag set, and all inheritance-related flags in the inherited entries will be
>> cleared.
>>
>> A subdirectory created inside that directory will inherit all of the ACL
>> entries that have the
>> .B file_inherit
>> or
>> .B dir_inherit
>> flag set. Entries whose
>> .B no_propagate
>> flag is set will have all inheritance-related flags cleared. Entries whose
>> .B no_propagate
>> and
>> .B dir_inherit
>> flags are not set and whose
>> .B file_inherit
>> is set will have their
>> .B inherit_only
>> flag set.
>> .IP 2.
>> If the parent directory's ACL has the
>> .B auto_inherit
>> flag set, the inherited ACL will have its
>> .B auto_inherit
>> flag set, and all entries will have their
>> .B inherited
>> flag set.
>> .IP 3.
>> The three file masks are computed from the inherited ACL as described in
>> the section
>> .IR "Computing the maximum file masks" .
>> .IP 4.
>> The three sets of permissions for the owner, the group, and for others in
>> the \fImode\fR parameter as given to
>> .BR open (2),
>> .BR mkdir (2),
>> and similar are converted into sets of RichACL permissions as described in
>> the section
>> .IR "Changing the file mode permission bits" .
>> Any RichACL permissions not included in those sets are
>> removed from the owner, group, and other file masks. The file mode permission
>> bits are then computed from the file masks as described in the section
>> .IR "Assigning an Access Control List" .
>> The process umask (see
>> .BR umask (2))
>> is ignored.
>> .IP 5.
>> The
>> .B masked
>> ACL flag is set. The
>> .B write_through
>> ACL flag remains cleared. In addition, if the
>> .B auto_inherit
>> flag of the inherited ACL is set, the
>> .B protected
>> flag is also set to prevent the Automatic Inheritance algorithm from modifying
>> the ACL.
>> .RE
>> .PP
>> When a directory does not have inheritable ACL entries, files and directories
>> created inside that directory will not be assigned access control lists and the
>> file mode permission bits will be set to (\fImode\fR\ &\ ~\fIumask\fR) where
>> \fImode\fR is the mode argument of the relevant system call and \fIumask\fR is
>> the process umask (see
>> .BR umask (2)).
>>
>> .SS Automatic Inheritance
>> Automatic Inheritance is a mechanism that allows permission changes to
>> propagate from a directory to files and subdirectories inside that directory,
>> recursively. Propagation is carried out by the process changing the directory
>> permissions (usually,
>> .BR setrichacl (1));
>> it happens without user intervention albeit not entirely automatically.
>>
>> A significant limitation is that this mechanism works only as long as files
>> are created without explicitly specifying the file permissions to use. The
>> standard system calls for creating files an directories (
>
> s/an /and /
> s/ ($//
>
>> .BR creat (2),
>
> Make that last line:
>
> .RM ( creat (2),
>
>> .BR open (2),
>> .BR mkdir (2),
>> .BR mknod (2))
>> all have mandatory mode parameters which define the maximum allowed permissions
>> of the new files. To take account of this restriction, the
>> .B protected
>> ACL flag must be set if the
>> .B inherited
>> flag is set. This effectively disables Automatic Inheritance for that
>> particular file.
>>
>> Automatic Inheritance still remains useful for network protocols like NFSv4 and
>> SMB, which both support creating files and directories without defining which
>
> s/which$/their/
>
>> permissions: they can implement those operations by using the standard system
>> calls and by then undoing the effect of applying the mode parameters.
>>
>> When the ACL of a directory is changed, the following happens for each entry
>> (\(lqchild\(rq) inside that directory:
>> .IP 1. 4
>> If the entry is a symblic link, skip the child.
>> .IP 2.
>> If the
>> .B auto_inherit
>> flag of the entry's ACL is not set or the
>> .B protected
>> flag is set, skip the child.
>> .IP 3.
>> With the child's ACL:
>> .RS 4
>> .IP a) 4
>> If the
>> .B defaulted
>> flag is set, replace the ACL with an empty ACL
>> with the
>> .B auto_inherit
>> flag set.
>> .IP b)
>> Delete all entries which have the
>> .B inherited
>> flag set.
>> .IP c)
>> Append all entries inherited from the parent directory according to step 1 of
>> the algorithm described under
>> .IR "Permissions at file-creation time".
>> Set the
>> .B inherited
>> flag of each of these entries.
>> .IP d)
>> Recompute the file masks.
>> .RE
>> .IP 4.
>> If the child is a directory, recursively apply this algorithm.
>>
>> .SS Access check algorithm
>>
>> When a process requests a particular kind of access (expressed as a set of
>> RichACL permissions) to a file, the following algorithm determines whether the
>> access is granted or denied:
>>
>> .IP 1. 4
>> If the
>> .B masked
>> ACL flag is set, then:
>> .RS 4
>> .IP a) 4
>> If the
>> .B write_through
>> ACL flag is set, then:
>> .RS 4
>> .IP \(bu 4
>> If the requesting process is the file owner, then access is granted if the
>> owner mask includes the requested permissions, and is otherwise denied.
>> .IP \(bu
>> If the requesting process is not the file owner, is not in the owning group,
>> and no ACL entries other than
>> .B everyone@
>> match the process, then access is granted if the other mask includes the
>> requested permissions, and is otherwise denied.
>> .RE
>> .IP b)
>> If any of the following is true:
>> .RS 4
>> .IP \(bu 4
>> the requesting process is the file owner and the owner mask does not include all
>> requested permissions,
>> .IP \(bu 4
>> the requesting process is not the file owner and it is in the owning group or
>> matches any ACL entries other than
>> .BR everyone@ ,
>> and the group mask does not include all requested permissions,
>> .IP \(bu 4
>> the requesting process is not the file owner, not in the owning group, it
>> matches no ACL entries other than
>> .BR everyone@ ,
>> and the other mask does not include all requested permissions,
>> .PP
>> then access is denied.
>> .RE
>> .RE
>> .IP 2.
>> Set the remaining permissions to the requested permissions. Go through all ACL
>> entries. For each entry:
>> .RS 4
>> .IP a) 4
>> If the
>> .B inherit_only
>> or
>> .B unmapped
>> flags are set, continue with the next ACL entry.
>> .IP b)
>> If any of the following is true:
>> .RS 4
>> .IP \(bu 4
>> the entry's identifier is
>> .B owner@
>> and the requesting process is the file owner,
>> .IP \(bu
>> the entry's identifier is
>> .B group@
>> and the requesting process is in the owning group,
>> .IP \(bu
>> the entry's identifier is a user and the requesting process is owned by that
>> user,
>> .IP \(bu
>> the entry's identifier is a group and the requesting process is a member in
>> that group,
>> .IP \(bu
>> the entry's identifier is
>> .BR everyone@ ,
>> .PP
>> then the entry matches the process; proceed to the next step. Otherwise,
>> continue with the next ACL entry.
>> .RE
>> .IP c)
>> If the entry denies any of the remaining permissions, access is denied.
>> .IP d)
>> If the entry allows any of the remaining permissions, then:
>> .RS 4
>> .IP \(bu 4
>> If the
>> .B masked
>> ACL flag is set and the entry's identifier is not
>> .B owner@
>> or
>> .BR everyone@
>> or is a user entry matching the file owner, remove all permissions from the
>> remaining permissions which are both allowed by the entry and included in the
>> group mask,
>> .IP \(bu
>> Otherwise, remove all permissions from the remaining permissions wich are
>> allowed by the entry.
>> .RE
>> .RE
>> .IP 3.
>> If there are no more remaining permissions, access is allowed. Otherwise,
>> access is denied.
>>
>> .SS Computing the maximum file masks
>> When setting an ACL and no file masks have been explicitly specified and when
>> inheriting an ACL from the parent directory, the following algorithm is used
>> for computing the file masks:
>>
>> .IP 1. 4
>> Clear the owner, group, and other file masks. Remember which permissions have
>> already been processed (initially, the empty set).
>> .IP 2.
>> For each ACL entry:
>> .RS 4
>> .IP \(bu 4
>> If the
>> .B inherit_only
>> flag is set, skip the entry.
>> .IP \(bu 4
>> Otherwise, compute which permissions the entry allows or denies that have not
>> been processed yet (the remaining permissions).
>> .IP \(bu
>> If the entry is an
>> .B owner@
>> entry, add the remaining permissions to the owner mask for
>> .B allow
>> entries, and remove the remaining permissions from the owner mask for
>> .B deny
>> entries.
>> .IP \(bu
>> Otherwise, if the entry is an
>> .B everyone@
>> entry, proceed as with
>> .B owner@
>> entries but add or remove the remaining permissions from the owner, group, and
>> other file masks.
>> .IP \(bu
>> Otherwise, proceed as with
>> .B owner@
>> entries but add or remove the remaining permissions from the owner and group
>> file masks.
>> .IP \(bu
>> Add the entry's permissions to the processed permissions.
>> .RE
>> .PP
>> The resulting file masks represent the ACL as closely as possible. With these
>> file masks, if the
>> .B masked
>> ACL flag is set, the effective permissions still stay the same.
>>
>> .\" .SH BUGS
>> .SH AUTHOR
>> Written by Andreas Grünbacher <[email protected]>.
>>
>> Please send your bug reports, suggested features and comments to the above address.
>
> Could we start with just a few simple examples already, and build up
> over future iterations of this page?
>
>> .SH CONFORMING TO
>> Rich Access Control Lists are Linux-specific.
>> .SH SEE ALSO
>> .BR acl (5),
>> .BR chmod (1),
>> .BR getrichacl (1),
>> .BR ls (1),
>> .BR setrichacl (1)
>> .BR stat (2),
>> .BR umask (2)
>> .\" librichacl

Thanks,
Andreas

Subject: Re: richacl(7) man page review comments

On 02/20/2016 05:37 PM, Andreas Gruenbacher wrote:
> Hi Michael,
>
> thanks again for all the feedback. I've followed all your suggestions;
> again, please see the github repo for the latest version:
>
> https://github.com/andreas-gruenbacher/richacl
>
> On Sun, Feb 14, 2016 at 10:31 PM, Michael Kerrisk (man-pages)
> <[email protected]> wrote:
>> Hi Andreas,
>>
>> Here's a few more comments on the current richacl(7) page
>> that I fetched from the git repo.
>>

[...]

>>> .HP
>>> .BR dir_inherit "\ (" d ):
>>> The entry is inheritable for directories.
>>
>> "When this flag appears in the ACL entry of a directory, then that entry is
>> inherited by new subdirectories created in the directory."
>>
>> Is that text that I propose correct?
>
> It's not entirely wrong, but only a small part of the truth. Entries
> are inherited such that the permissions in file_inherit entries become
> effective for access checking for new files, and the permissions in
> dir_inherit entries become effective for access checking for new
> directories, recursively.
>
> Your feedback prompted me to look into the inheritance flag
> computation more closely once again, and I found bugs. The steps of
> the algorithm are explained in the section "Permissions at
> file-creation time", by the way.

Hmmm... writing and refining documentation helps find code bugs.
Who knew? :-)

Cheers,

Michael

--
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Linux/UNIX System Programming Training: http://man7.org/training/

Subject: Re: richacl(7) man page review comments

Hello Andreas,

On 02/20/2016 05:37 PM, Andreas Gruenbacher wrote:
> Hi Michael,
>
> thanks again for all the feedback. I've followed all your suggestions;
> again, please see the github repo for the latest version:
>
> https://github.com/andreas-gruenbacher/richacl

I've once more pulled from the latest git; here's some more comments.

> .\"
> .\" RichACL Manual Pages
> .\"
> .\" Copyright (C) 2015,2016 Red Hat, Inc.
> .\" Written by Andreas Gruenbacher <[email protected]>
> .\" This is free documentation; you can redistribute it and/or
> .\" modify it under the terms of the GNU General Public License as
> .\" published by the Free Software Foundation; either version 2 of
> .\" the License, or (at your option) any later version.
> .\"
> .\" The GNU General Public License's references to "object code"
> .\" and "executables" are to be interpreted as the output of any
> .\" document formatting or typesetting system, including
> .\" intermediate and printed output.
> .\"
> .\" This manual is distributed in the hope that it will be useful,
> .\" but WITHOUT ANY WARRANTY; without even the implied warranty of
> .\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> .\" GNU General Public License for more details.
> .\"
> .\" You should have received a copy of the GNU General Public
> .\" License along with this manual. If not, see
> .\" <http://www.gnu.org/licenses/>.
> .\"
> .de URL
> \\$2 \(laURL: \\$1 \(ra\\$3
> ..
> .if \n[.g] .mso www.tmac
> .TH RICHACL 7 2015-09-01 "Linux" "Rich Access Control Lists"
> .SH NAME
> richacl \- Rich Access Control Lists
> .SH DESCRIPTION
> Rich Access Control Lists (RichACLs) are an extension of the POSIX file
> permission model (see
> .BR acl (5))
> to support
> .URL https://tools.ietf.org/rfc/rfc5661.txt "NFSv4 Access Control Lists"
> on local and remote-mounted filesystems.
>
> A RichACL can always be translated into an equivalent NFSv4 ACL which grants
> the same permissions.
>
> RichACLs can be enabled on supported local filesystems (currently, ext4 and
> XFS). This disables POSIX Access Control Lists; the two ACL models cannot
> coexist on the same filesystem.
>
> The in-kernel NFSv4 server and client also include RichACL support.

Rewrite the preceding two paras in a better logical split and order:

[[
RichACLs can be enabled on supported local filesystems (currently, ext4 and
XFS). The in-kernel NFSv4 server and client also include RichACL support.

Enabling RichACLs disables POSIX Access Control Lists;
the two ACL models cannot coexist on the same filesystem.
]]

>
> When used on a filesystem that does not support RichACLs, the
> .BR getrichacl (1)
> and
> .BR setrichacl (1)
> utilities will operate on the file permission bits instead:
> .BR getrichacl (1)
> will display the file permission bits as a RichACL; when a RichACL
> is set with
> .BR setrichacl (1)
> which can be represented exactly by the file permission bits,
> .BR setrichacl (1)
> will set the file permission bits instead. An attempt to set a RichACL that
> cannot be represented exactly by the file permission bits results in an error.
>
> .SS Structure of RichACLs
>
> RichACLs consist of a number of ACL entries, three file masks, and some flags

s/some flags/a set of flags/

> specifying attributes of the ACL as whole (by contrast with the per-ACL-entry

s/whole/a whole/

> flags described below).
>
> Each of the ACL entries allows or denies some permissions to a particular user,
> group, or special identifier. An ACL entry consists of four fields:
>
> .IP \(bu 4

s/4/2/

> A tag which specifies the user, group, or special identifier the entry applies
> to. Special identifiers can be the file owner, the owning group, or everyone.

==>
Special identifiers correspond to one of three file masks for the file owner
.RB ( owner@ ),
the owning group
.RB ( group@ ),
or everyone
.RB ( everyone@ ).

> .IP \(bu
> A set of permissions the entry allows or denies.
> .IP \(bu
> A set of flags that indicate whether the user or group identifier is mapped or
> unmapped, and whether the entry has been and can be inherited.
> .IP \(bu 4

s/ 4//

> A type field indicating whether the entry allows or denies access.

s/access/the permissions specified in the second field/

> .PP
> The owner, group, and other file masks further control which permissions the
> ACL grants, subject to the
> .BR masked "\ (" m )
> and
> .BR write_through "\ (" w )
> ACL flags: when the permissions of a file or directory are changed with
> .BR chmod (2),
> the file masks are set based on the new file mode, and the
> .B masked
> and
> .B write_through
> ACL flags are set. Likewise, when a new file or directory inherits an ACL from
> its parent directory, the file masks are set to the intersection between the
> permissions granted by the inherited ACL and the
> .I mode
> parameter as given to
> .BR open "(2), " mkdir (2),
> and similar, and the
> .B masked
> ACL flag is set. In both cases, the file masks limit the permissions that the
> ACL will grant.
>
> The advantage of this approach over directly modifying the ACL entries is that
> permissions defined in ACL entries are not lot when the file masks are later

s/lot/lost/

> set to be less restrictive.

(I think) I know what you are trying to say in the previous paragraph,
but "this approach" and "directly modifying the ACL entries" is a little
vague. Masks are about solving the hysteresis problem, right? So, how
about some text along the following lines (I'm sure you can improve):

[[
The purpose of the file masks is to allow applications that are unaware
of RichACLs to place limits on the permissions granted by various
classes of RichACL in a manner that corresponds to the traditional
user/group/other semantics, without modifying the ACL entries in those
classes. Without the file masks, the only alternative would be for the
kernel to directly modify the ACL entries in those classes. However,
this latter approach could have a "hysteresis effect", whereby
a RichACL-unaware application that performs a transition from one file
mode to another file mode and then back to the original file mode
could cause destruction of the permission information in ACL entries.
]]

>
> Note that entries with the identifier
> .B everyone@
> apply to all processes, whereas the \(lqother\(rq file permissions and
> \(lqother\(rq entries in POSIX ACLs apply to all processes which are not the

I'd be inclined to use (or add) \fBACL_OTHER\fP instead of "other"
in the preceding line. Things makes things IMO a little clearer when
you try to distinguish from "other" file permissions.

> owner, are not in the owning group, and do not match a user or group mentioned
> in the ACL.
>
> Unlike POSIX ACLs, RichACLs do not have separate \(lqaccess\(rq ACLs that
> define the access permissions and \(lqdefault\(rq ACLs that define the
> inheritable permissions. Instead, flags on each ACL entry determine whether
> the entry is effective during access checks and/or inheritable.
>
>
> .SS ACL flags
>
> The following flags on ACLs are defined:

s/flags on ACLs/ACL flags/

>
> .TP
> .BR masked "\ (" m )
> When set, the file masks define upper limits on the permissions the ACL may
> grant. When not set, the file masks are ignored.
> .TP
> .BR write_through "\ (" w )
> When this flag and the
> .B masked
> flag are both set, the owner and other file masks define the actual permissions
> granted to the file owner and to others instead of defining an upper limit.
> When the
> .B masked
> flag is not set, the write_through flag has no effect.

Use .BR write_through for preceding line

> .TP
> .BR auto_inherit "\ (" a )
> Automatic Inheritance is enabled. See
> .IR "Automatic Inheritance" .
> .TP
> .BR protected "\ (" p )
> The ACL is protected from modification by Automatic
> Inheritance.
> .TP
> .BR defaulted "\ (" d )
> Indicates that the ACL has been assigned in an application-dependent way when
> the file or directory was created; it has neither been inherited nor set
> explicitly. ACLs of files created on Linux will never have the
> .B defaulted
> flag set.

The preceding sentence immediately triggers an obvious question for the
reader. So, do we need a sentence here to say when/where the "defaulted"
flag is set?
> When this flag is set for an ACL, Automatic Inheritance will
> completely replace the ACL.
>
> .SS ACL entry flags
>
> The following flags on ACL entries are defined:
>
> .TP
> .BR file_inherit "\ (" f )
> When this flag appears in the ACL entry of a directory, then:
> .RS
> .IP \(bu 4
> That entry is inherited by new files created in the directory such that the

s/4/2/

> permissions of the entry apply to the file (the inheritance flags of the
> inherited entry are cleared).
> .IP \(bu 4
> The entry is is inherited by new subdirectories created in the directory such

s/ 4//

> that the permissions of the entry will apply to new files created in the
> subdirectory.
> .RE
> .TP
> .BR dir_inherit "\ (" d )
> When this flag appears in the ACL entry of a directory, then that entry is
> inherited by new subdirectories created in the directory such that the
> permissions of the entry apply to the subdirectory (the
> .B inherit_only
> flag is cleared).
> .TP
> .BR no_propagate "\ (" n )
> Inheritance stops at the next subdirectory level. When a file or directory
> inherits an entry that has this flag set, the
> .BR file_inherit ", " dir_inherit ", " no_propagate ", and " inherit_only
> flags are cleared.
> .TP
> .BR inherit_only "\ (" i )
> The entry defines inheritable permissions only and is ignored for access
> checking. When a file or directory inherits an entry that has this flag set,
> the flag is cleared.
> .TP
> .BR inherited "\ (" a )
> The entry has been automatically inherited from the parent directory; the
> ACL's
> .B auto_inherit
> flag should be on.

Why "should be" in the previous sentence? I think a little explanation
is needed here...
> .TP
> .BR unmapped "\ (" u )
> The user or group identifier is a textual string and is not mapped to a numeric
> user or group identifier. ACLs with unmapped identifiers can occur on NFSv4
> mounted filesystems when the client cannot determine numeric user or group
> identifiers for some of the NFSv4 user@domain or group@domain who values. They
> cannot be assigned to local files or directories.
>
> .SS Permissions
>
> The following permissions are defined for RichACL entries and for the three
> file masks:
>
> .TP
> .BR read_data " / " list_directory "\ (" r )
> For a file: read the data of the file.
> For a directory: list the contents of the directory.
> .TP
> .BR write_data " / " add_file "\ (" w )
> For a file: modify the data of the file; does not include opening the file in
> append mode.
> For a directory: add a new file in the directory.
> .TP
> .BR append_data " / " add_subdirectory "\ (" p )
> For a file: open the file in append mode.
> For a directory: create a subdirectory in the directory.
> .TP
> .BR execute "\ (" x )
> For a file: execute the file.
> For a directory: traverse / search the directory.

s%traverse / search%traverse (search)%
> .TP
> .BR delete_child "\ (" d )
> Delete a file or directory within a directory. This permission is meaningless
> for non-directories.

==> "This permission is meanungful only for directories."

> .TP
> .BR delete "\ (" D )
> Delete the file or directory.
> .TP
> .BR read_attributes "\ (" a )
> Read basic attributes of a file or directory (see
> .BR stat (2)).
> This permission is defined by NFSv4. It is stored, but ignored. Reading basic
> attributes of files and directories is always allowed on Linux.
> .TP
> .BR write_attributes "\ (" A )
> Change the times associated with a file or directory to an arbitrary value.
> This permission is always implicitly granted to the file owner.
> .TP
> .BR read_acl "\ (" c )
> Read the ACL of a file or directory. This permission is always
> implicitly granted.

So, I think a sentence explaining why "read_acl" exists would be
helpful, since the reader is left a little puzzled about its purpose if
it is always implicitly granted.

> .TP
> .BR write_acl "\ (" C )
> Change the ACL or file mode of a file or directory.
> .TP
> .BR write_owner "\ (" o )
> Take ownership of a file or directory. Change the owning group of a file or
> directory to a group of which the calling process is a member.
> .TP

Formatting tweak: add ".ad l" before the following line amd ".ad" after
the line.

> .BR read_named_attrs "\ (" R "), " write_named_attrs "\ (" W "), " synchronize "\ (" S "), " write_retention "\ (" e "), " write_retention_hold "\ (" E )
> These permissions are defined by NFSv4 / NFSv4.1. They are stored, but ignored.

s%/%and%

> .PP
> For the
> .BR r ", " w ", and " p
> permissions which have different long forms for files and directories, the

s/permissions/permissions,/

> .BR getrichacl (1)
> utility will output the appropriate form(s) depending on the context.
> The
> .BR setrichacl (1)
> utility will accept either form for any file type.
>
> .SS Text form
> The common textual representation of a RichACL consists of the colon-separated
> fields of the ACL flags, file masks, and ACL entries in the following
> format:
> .TP
> \fBflags:\fR\fIacl_flags\fR
> The ACL flags.
> .TP
> \fBowner:\fR\fIperm\fR\fB::mask\fR, \fBgroup:\fR\fIperm\fR\fB::mask\fR, \fBother:\fR\fIperm\fR\fB::mask\fR
> The file masks and their permissions.
> .TP
> \fIwho\fR\fB:\fR\fIperm\fR\fB:\fR\fIflags\fR\fB:allow\fR, \fIwho\fR\fB:\fR\fIperm\fR\fB:\fR\fIflags\fR\fB:deny\fR
> For each ACL entry, who the entry applies to, the permissions of the entry, the
> entry flags, and the entry type. The who field is one of the following:

s/who/\\fIwho\\fP/

> .RS
> .IP \(bu 4

s/4/2/

> One of the special identifiers:
> .BR owner@ ", " group@ ", or " everyone@ ,
> .IP \(bu
> A
> .BR user: " or " u:
> prefix followed by a user name or user ID that designates a specific user,
> .IP \(bu
> A
> .BR group: " or " g:
> prefix followed by a group name or group ID that designates a specific group.
> .RE
> .PP
> The entries are comma, whitespace, or newline separated.
>
> Flags and permissions have single-letter as well as long forms, as listed under
> .IR "ACL flags" ,
> .IR "ACL entry flags" ,
> and
> .IR Permissions .
> When the single-letter forms are used, the flags or permissions are
> concatenated. When the long forms are used, the flags or permissions are
> separated by slashes. To align permissions or flags vertically, dashes can be
> used for padding.
>
> .SS Setting and modifying file permissions
> The access permissions for a file can either be set by assigning an Access
> Control List
> .RB ( setrichacl (1))
> or by changing the file mode permission bits
> .RB ( chmod (1)).
> In addition, a file can inherit an ACL from its parent directory at creation
> time as described under
> .IR "Permissions at file-creation time" .
>
> .SS Assigning an Access Control List
> When assigning an ACL to a file, unless explicitly specified, the owner, group,
> and other file masks will be computed from the ACL entries as described in
> the section
> .IR "Computing the maximum file masks" .
> The owner, group, and other file mode permission bits are then each set from
> the owner, group, and other file mask as follows:
> .IP \(bu 4

s/4/2/

> If the file mask includes the
> .B r
> permission, the read
> file mode permission bit will be set.
> .IP \(bu
> If the file mask includes the
> .B w
> or
> .B p
> permission, the write file mode permission bit will be set.
> .IP \(bu
> If the file mask includes the
> .B x
> permission, the execute file mode permission bit will be set.
> .PP
> If the ACL can be represented exactly by the file mode
> permission bits, the file permission bits are set to match the ACL and the ACL
> is not stored.

Maybe better: "...and no ACL is stored"

> (When the ACL of a file is requested which doesn't have an ACL,
> the file mode permission bits are converted into an equivalent ACL.)
>
> .SS Changing the file mode permission bits
> When changing the file mode permission bits with
> .BR chmod (1),
> the owner, group, and other file permission bits are set to the permission bits
> in the new mode, and the owner, group, and other file masks are set based on
> the new mode bits as follows:
> .IP \(bu 4

s/4/2/

> If the read bit in a set of permissions is set, the
> .B r
> permission in the corresponding file mask will be set.
> .IP \(bu
> If the write bit in a set of permissions is set, the
> .B w
> and
> .B p
> permissions in the corresponding file mask will be set.
> .IP \(bu
> If the execute bit in a set of permissions is set, the
> .B x
> permission in the corresponding file mask will be set.
> .PP
> In addition, the
> .B masked
> and
> .B write_through
> ACL flags are set. This has the
> effect of limiting the permissions granted by the ACL to the file mode
> permission bits; in addition, the owner is granted the owner mode bits and
> others are granted the other mode bits. If the
> .B auto_inherit
> flag is set, the
> .B protected
> flag is also set to prevent the Automatic Inheritance algorithm from modifying
> the ACL.
>
> .SS Permissions at file-creation time
> When a directory has inheritable ACL entries, the following

s/has/has an/

> happens when a file or directory is created inside that directory:
> .RS 4
> .IP 1. 4
> A file created inside that directory will inherit all of the ACL entries that
> have the
> .B file_inherit
> flag set, and all inheritance-related flags in the inherited entries flag will
> be cleared.
>
> A subdirectory created inside that directory will inherit all of the ACL
> entries that either have the
> .B dir_inherit
> flag set, or the
> .B file_inherit
> flag set and the
> .B no_propagate
> flag not set. Entries whose
> .B dir_inherit
> flag is set will have their
> .B inherit_only
> flag cleared, and entries whose
> .B dir_inherit
> flag is not set will have their
> .B inherit_only
> flag set. Finally, entries whose
> .B no_propagate
> flag is set will have all inheritance-related flags cleared.
> .IP 2.
> If the parent directory's ACL has the
> .B auto_inherit
> flag set, the inherited ACL will have its
> .B auto_inherit
> flag set, and all entries will have their
> .B inherited
> flag set. Otherwise, the
> .B auto_inherit
> and
> .B inherited
> flags are cleared.
> .IP 3.
> The three file masks are computed from the inherited ACL as described in
> the section
> .IR "Computing the maximum file masks" .
> .IP 4.
> The three sets of permissions for the owner, the group, and for others in
> the \fImode\fR parameter as given to
> .BR open (2),
> .BR mkdir (2),
> and similar are converted into sets of RichACL permissions. The correspondence
> between mask flags and RichACL permission bits is described in the section
> .IR "Changing the file mode permission bits" .
> Any RichACL permissions not included in those sets are
> removed from the owner, group, and other file masks. The file mode permission
> bits are then computed from the file masks as described in the section
> .IR "Assigning an Access Control List" .
> The process umask (see
> .BR umask (2))
> is ignored.
> .IP 5.
> The
> .B masked
> ACL flag is set. The
> .B write_through
> ACL flag remains cleared. In addition, if the
> .B auto_inherit
> flag of the inherited ACL is set, the
> .B protected
> flag is also set to prevent the Automatic Inheritance algorithm from modifying
> the ACL.
> .RE
> .PP
> When a directory does not have inheritable ACL entries, files and directories
> created inside that directory will not be assigned Access Control Lists and the
> file mode permission bits will be set to (\fImode\fR\ &\ ~\fIumask\fR) where
> \fImode\fR is the mode argument of the relevant system call and \fIumask\fR is
> the process umask (see
> .BR umask (2)).
>
> .SS Automatic Inheritance
> Automatic Inheritance is a mechanism that allows permission changes to
> propagate from a directory to files and subdirectories inside that directory,
> recursively. Propagation is carried out by the process changing the directory
> permissions (usually,
> .BR setrichacl (1));
> it happens without user intervention albeit not entirely automatically.
>
> A significant limitation is that this mechanism works only as long as files
> are created without explicitly specifying the file permissions to use. The
> standard system calls for creating files and directories
> .RB ( creat (2),
> .BR open (2),
> .BR mkdir (2),
> .BR mknod (2))
> all have mandatory mode parameters which define the maximum allowed permissions
> of the new files. To take account of this restriction, the
> .B protected
> ACL flag must be set if the
> .B inherited
> flag is set. This effectively disables Automatic Inheritance for that
> particular file.
>

Add the following at the start of the next paragraph:

"Motwithstanding the aforementioned limitation,"
> Automatic Inheritance still remains useful for network protocols like NFSv4 and
> SMB, which both support creating files and directories without defining their
> permissions: they can implement those operations by using the standard system

s/: they/. These protocols/
(To avoid an excessively long sentence.)

> calls and by then undoing the effect of applying the mode parameters.
>
> When the ACL of a directory is changed, the following happens for each entry
> (\(lqchild\(rq) inside that directory:
> .IP 1. 4
> If the entry is a symblic link, skip the child.

s/symblic/symbolic/

> .IP 2.
> If the
> .B auto_inherit
> flag of the entry's ACL is not set or the
> .B protected
> flag is set, skip the child.
> .IP 3.
> With the child's ACL:
> .RS 4
> .IP a) 4
> If the
> .B defaulted
> flag is set, replace the ACL with an empty ACL
> with the
> .B auto_inherit
> flag set.
> .IP b)
> Delete all entries which have the
> .B inherited
> flag set.
> .IP c)
> Append all entries inherited from the parent directory according to step 1 of
> the algorithm described under
> .IR "Permissions at file-creation time".
> Set the
> .B inherited
> flag of each of these entries.
> .IP d)
> Recompute the file masks.
> .RE
> .IP 4.
> If the child is a directory, recursively apply this algorithm.
>
> .SS Access check algorithm
>
> When a process requests a particular kind of access (expressed as a set of
> RichACL permissions) to a file, the following algorithm determines whether the
> access is granted or denied:
>
> .IP 1. 4
> If the
> .B masked
> ACL flag is set, then:
> .RS 4
> .IP a) 4
> If the
> .B write_through
> ACL flag is set, then:
> .RS 4

s/4/2/

> .IP \(bu 4

s/4/2/

> If the requesting process is the file owner, then access is granted if the
> owner mask includes the requested permissions, and is otherwise denied.
> .IP \(bu
> If the requesting process is not the file owner, is not in the owning group,
> and no ACL entries other than
> .B everyone@
> match the process, then access is granted if the other mask includes the
> requested permissions, and is otherwise denied.

So, in the above subcases, the following does not seem to be covered:
(1) "masked" ACL flag is set AND
(2) requesting process *is* in owning group *or* an ACL other
than "everyone@"matches the process.

What happens in this case? I suspect that somehow we are supposed to
fall through to part "b)" below (and possibly into clause "2."?), but
the logical structure of the clauses does not reflect this.

> .RE
> .IP b)
> If any of the following is true:
> .RS 4

s/4/2/

> .IP \(bu 4

s/4/2/

> the requesting process is the file owner and the owner mask does not include all
> requested permissions,
> .IP \(bu 4

s/ 4//

> the requesting process is not the file owner and it is in the owning group or
> matches any ACL entries other than
> .BR everyone@ ,
> and the group mask does not include all requested permissions,
> .IP \(bu 4

s/ 4//

> the requesting process is not the file owner, not in the owning group, it
> matches no ACL entries other than
> .BR everyone@ ,
> and the other mask does not include all requested permissions,
> .PP
> then access is denied.
> .RE
> .RE

At some point, perhaps in the next paragraph, I think that it needs to
be clarified that unlike POSIX ACLs, a process can gain the permissions
it requires by accumulating them from multiple RichACL enties. (That's
correct, is it not?)

> .IP 2.
> Set the remaining permissions to the requested permissions. Go through all ACL
> entries. For each entry:

So, perhaps replace the preceding two lines with something like:

[[
Upon reaching this point, the determination of whether or not access is
granted is made by scanning all ACL entries to see if one or more
applicable entries together grant a cumulative set of permissions that
matches the requested permissions or there is an applicable entry that
explicitly denies one or more of the requested permissions.
The scan of all ACL entries begins by
first initializing the set of remaining permissions (i.e., those that have
not yet been satisfied during the scan) to be the set of requested
permissions. Then the ACL entries are scanned
.IR "in order" ,
and for each entry:
]]

> .RS 4
> .IP a) 4
> If the
> .B inherit_only
> or
> .B unmapped
> flags are set, continue with the next ACL entry.
> .IP b)
> If any of the following is true:
> .RS 4

s/4/2/

> .IP \(bu 4

s/4/2/

> the entry's identifier is
> .B owner@
> and the requesting process is the file owner,
> .IP \(bu
> the entry's identifier is
> .B group@
> and the requesting process is in the owning group,
> .IP \(bu
> the entry's identifier is a user and the requesting process is owned by that
> user,
> .IP \(bu
> the entry's identifier is a group and the requesting process is a member in
> that group,
> .IP \(bu
> the entry's identifier is
> .BR everyone@ ,
> .PP
> then the entry matches the process; proceed to the next step. Otherwise,
> continue with the next ACL entry.
> .RE
> .IP c)
> If the entry denies any of the remaining permissions, access is denied.
> .IP d)
> If the entry allows any of the remaining permissions, then:
> .RS 4

s/4/2/

> .IP \(bu 4

s/4/2/

> If the
> .B masked
> ACL flag is set and the entry's identifier is not
> .B owner@
> or
> .BR everyone@
> or is a user entry matching the file owner, remove all permissions from the
> remaining permissions which are both allowed by the entry and included in the
> group mask,
> .IP \(bu
> Otherwise, remove all permissions from the remaining permissions wich are

s/wich/which

> allowed by the entry.
> .RE
> .RE
> .IP 3.
> If there are no more remaining permissions, access is allowed. Otherwise,
> access is denied.
>
> .SS Computing the maximum file masks
> When setting an ACL and no file masks have been explicitly specified and when
> inheriting an ACL from the parent directory, the following algorithm is used
> for computing the file masks:
>
> .IP 1. 4
> Clear the owner, group, and other file masks. Remember which permissions have
> already been processed (initially, the empty set).
> .IP 2.
> For each ACL entry:
> .RS 4

s/4/2/

> .IP \(bu 4

s/4/2/

> If the
> .B inherit_only
> flag is set, skip the entry.
> .IP \(bu 4

s/ 4//

> Otherwise, compute which permissions the entry allows or denies that have not
> been processed yet (the remaining permissions).
> .IP \(bu
> If the entry is an
> .B owner@
> entry, add the remaining permissions to the owner mask for
> .B allow
> entries, and remove the remaining permissions from the owner mask for
> .B deny
> entries.
> .IP \(bu
> Otherwise, if the entry is an
> .B everyone@
> entry, proceed as with
> .B owner@
> entries but add or remove the remaining permissions from the owner, group, and
> other file masks.
> .IP \(bu
> Otherwise, proceed as with
> .B owner@
> entries but add or remove the remaining permissions from the owner and group
> file masks.
> .IP \(bu
> Add the entry's permissions to the processed permissions.
> .RE
> .PP
> The resulting file masks represent the ACL as closely as possible. With these
> file masks, if the
> .B masked
> ACL flag is set, the effective permissions still stay the same.

The meaing of "will stay the same" is not quite clear "will stay the
same *as what*"?). I suspect I know what you mean, but it needs to be
made more obvious.

>
> .\" .SH BUGS
> .SH AUTHOR
> Written by Andreas Grünbacher <[email protected]>.
>
> Please send your bug reports, suggested features and comments to the above address.
>

I'm going to play the broken record :-)

Could we start with just a few simple examples already, and build up
over future iterations of this page?

> .SH CONFORMING TO
> Rich Access Control Lists are Linux-specific.
> .SH SEE ALSO
> .BR acl (5),

Move this entry to the point XXX below.

> .BR chmod (1),
> .BR getrichacl (1),
> .BR ls (1),
> .BR setrichacl (1)
> .BR stat (2),
> .BR umask (2)
> .\" librichacl

XXX

By the way, are there already man pages for the librichacl functions?

Cheers,

Michael

--
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Linux/UNIX System Programming Training: http://man7.org/training/

2016-02-22 14:46:41

by Andreas Gruenbacher

[permalink] [raw]
Subject: Re: richacl(7) man page review comments

Hi Michael,

On Sun, Feb 21, 2016 at 10:40 PM, Michael Kerrisk (man-pages)
<[email protected]> wrote:
> I've once more pulled from the latest git; here's some more comments.

thanks again. I've updated the repo with your changes.

>> .\"
>> .\" RichACL Manual Pages
>> .\"
>> .\" Copyright (C) 2015,2016 Red Hat, Inc.
>> .\" Written by Andreas Gruenbacher <[email protected]>
>> .\" This is free documentation; you can redistribute it and/or
>> .\" modify it under the terms of the GNU General Public License as
>> .\" published by the Free Software Foundation; either version 2 of
>> .\" the License, or (at your option) any later version.
>> .\"
>> .\" The GNU General Public License's references to "object code"
>> .\" and "executables" are to be interpreted as the output of any
>> .\" document formatting or typesetting system, including
>> .\" intermediate and printed output.
>> .\"
>> .\" This manual is distributed in the hope that it will be useful,
>> .\" but WITHOUT ANY WARRANTY; without even the implied warranty of
>> .\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>> .\" GNU General Public License for more details.
>> .\"
>> .\" You should have received a copy of the GNU General Public
>> .\" License along with this manual. If not, see
>> .\" <http://www.gnu.org/licenses/>.
>> .\"
>> .de URL
>> \\$2 \(laURL: \\$1 \(ra\\$3
>> ..
>> .if \n[.g] .mso www.tmac
>> .TH RICHACL 7 2015-09-01 "Linux" "Rich Access Control Lists"
>> .SH NAME
>> richacl \- Rich Access Control Lists
>> .SH DESCRIPTION
>> Rich Access Control Lists (RichACLs) are an extension of the POSIX file
>> permission model (see
>> .BR acl (5))
>> to support
>> .URL https://tools.ietf.org/rfc/rfc5661.txt "NFSv4 Access Control Lists"
>> on local and remote-mounted filesystems.
>>
>> A RichACL can always be translated into an equivalent NFSv4 ACL which grants
>> the same permissions.
>>
>> RichACLs can be enabled on supported local filesystems (currently, ext4 and
>> XFS). This disables POSIX Access Control Lists; the two ACL models cannot
>> coexist on the same filesystem.
>>
>> The in-kernel NFSv4 server and client also include RichACL support.
>
> Rewrite the preceding two paras in a better logical split and order:
>
> [[
> RichACLs can be enabled on supported local filesystems (currently, ext4 and
> XFS). The in-kernel NFSv4 server and client also include RichACL support.
>
> Enabling RichACLs disables POSIX Access Control Lists;
> the two ACL models cannot coexist on the same filesystem.
> ]]
>
>>
>> When used on a filesystem that does not support RichACLs, the
>> .BR getrichacl (1)
>> and
>> .BR setrichacl (1)
>> utilities will operate on the file permission bits instead:
>> .BR getrichacl (1)
>> will display the file permission bits as a RichACL; when a RichACL
>> is set with
>> .BR setrichacl (1)
>> which can be represented exactly by the file permission bits,
>> .BR setrichacl (1)
>> will set the file permission bits instead. An attempt to set a RichACL that
>> cannot be represented exactly by the file permission bits results in an error.
>>
>> .SS Structure of RichACLs
>>
>> RichACLs consist of a number of ACL entries, three file masks, and some flags
>
> s/some flags/a set of flags/
>
>> specifying attributes of the ACL as whole (by contrast with the per-ACL-entry
>
> s/whole/a whole/
>
>> flags described below).
>>
>> Each of the ACL entries allows or denies some permissions to a particular user,
>> group, or special identifier. An ACL entry consists of four fields:
>>
>> .IP \(bu 4
>
> s/4/2/
>
>> A tag which specifies the user, group, or special identifier the entry applies
>> to. Special identifiers can be the file owner, the owning group, or everyone.
>
> ==>
> Special identifiers correspond to one of three file masks for the file owner
> .RB ( owner@ ),
> the owning group
> .RB ( group@ ),
> or everyone
> .RB ( everyone@ ).

No, owner@, group@, and everyone@ entries do not correspond to the
file masks in that way.

>> .IP \(bu
>> A set of permissions the entry allows or denies.
>> .IP \(bu
>> A set of flags that indicate whether the user or group identifier is mapped or
>> unmapped, and whether the entry has been and can be inherited.
>> .IP \(bu 4
>
> s/ 4//
>
>> A type field indicating whether the entry allows or denies access.
>
> s/access/the permissions specified in the second field/
>
>> .PP
>> The owner, group, and other file masks further control which permissions the
>> ACL grants, subject to the
>> .BR masked "\ (" m )
>> and
>> .BR write_through "\ (" w )
>> ACL flags: when the permissions of a file or directory are changed with
>> .BR chmod (2),
>> the file masks are set based on the new file mode, and the
>> .B masked
>> and
>> .B write_through
>> ACL flags are set. Likewise, when a new file or directory inherits an ACL from
>> its parent directory, the file masks are set to the intersection between the
>> permissions granted by the inherited ACL and the
>> .I mode
>> parameter as given to
>> .BR open "(2), " mkdir (2),
>> and similar, and the
>> .B masked
>> ACL flag is set. In both cases, the file masks limit the permissions that the
>> ACL will grant.
>>
>> The advantage of this approach over directly modifying the ACL entries is that
>> permissions defined in ACL entries are not lot when the file masks are later
>
> s/lot/lost/
>
>> set to be less restrictive.
>
> (I think) I know what you are trying to say in the previous paragraph,
> but "this approach" and "directly modifying the ACL entries" is a little
> vague. Masks are about solving the hysteresis problem, right? So, how
> about some text along the following lines (I'm sure you can improve):
>
> [[
> The purpose of the file masks is to allow applications that are unaware
> of RichACLs to place limits on the permissions granted by various
> classes of RichACL in a manner that corresponds to the traditional
> user/group/other semantics, without modifying the ACL entries in those
> classes. Without the file masks, the only alternative would be for the
> kernel to directly modify the ACL entries in those classes. However,
> this latter approach could have a "hysteresis effect", whereby
> a RichACL-unaware application that performs a transition from one file
> mode to another file mode and then back to the original file mode
> could cause destruction of the permission information in ACL entries.
> ]]

Let's try it this way:

"The purpose of the file masks is to allow traditional POSIX applications which
are unaware of RichACLs to place limits on the permissions granted by the
RichACL without causing the ACL entries to be modified. Without the file mask,
the only alternative would be for the kernel to directly modify the ACL
entries. However, this latter approach could have a "hysteresis effect",
whereby a RichACL-unaware application that performs a transition from one file
mode to another file mode and then back to the original file mode could cause
destruction of the permission information in ACL entries. When creating files
or directories, the mode parameter to open(2), mkdir(2), and similar would
cause the same effect."

>>
>> Note that entries with the identifier
>> .B everyone@
>> apply to all processes, whereas the \(lqother\(rq file permissions and
>> \(lqother\(rq entries in POSIX ACLs apply to all processes which are not the
>
> I'd be inclined to use (or add) \fBACL_OTHER\fP instead of "other"
> in the preceding line. Things makes things IMO a little clearer when
> you try to distinguish from "other" file permissions.

This man page is explaining things in terms of the RichACL text form,
that's why I've chose to use the POSIX ACL text form here as well.

>> owner, are not in the owning group, and do not match a user or group mentioned
>> in the ACL.
>>
>> Unlike POSIX ACLs, RichACLs do not have separate \(lqaccess\(rq ACLs that
>> define the access permissions and \(lqdefault\(rq ACLs that define the
>> inheritable permissions. Instead, flags on each ACL entry determine whether
>> the entry is effective during access checks and/or inheritable.
>>
>>
>> .SS ACL flags
>>
>> The following flags on ACLs are defined:
>
> s/flags on ACLs/ACL flags/
>
>>
>> .TP
>> .BR masked "\ (" m )
>> When set, the file masks define upper limits on the permissions the ACL may
>> grant. When not set, the file masks are ignored.
>> .TP
>> .BR write_through "\ (" w )
>> When this flag and the
>> .B masked
>> flag are both set, the owner and other file masks define the actual permissions
>> granted to the file owner and to others instead of defining an upper limit.
>> When the
>> .B masked
>> flag is not set, the write_through flag has no effect.
>
> Use .BR write_through for preceding line
>
>> .TP
>> .BR auto_inherit "\ (" a )
>> Automatic Inheritance is enabled. See
>> .IR "Automatic Inheritance" .
>> .TP
>> .BR protected "\ (" p )
>> The ACL is protected from modification by Automatic
>> Inheritance.
>> .TP
>> .BR defaulted "\ (" d )
>> Indicates that the ACL has been assigned in an application-dependent way when
>> the file or directory was created; it has neither been inherited nor set
>> explicitly. ACLs of files created on Linux will never have the
>> .B defaulted
>> flag set.

"ACLs of files created on Linux will never have the defaulted flag set, but the
flag may be set on files created on or copied over from other operating
systems."

> The preceding sentence immediately triggers an obvious question for the
> reader. So, do we need a sentence here to say when/where the "defaulted"
> flag is set?
>> When this flag is set for an ACL, Automatic Inheritance will
>> completely replace the ACL.
>>
>> .SS ACL entry flags
>>
>> The following flags on ACL entries are defined:
>>
>> .TP
>> .BR file_inherit "\ (" f )
>> When this flag appears in the ACL entry of a directory, then:
>> .RS
>> .IP \(bu 4
>> That entry is inherited by new files created in the directory such that the
>
> s/4/2/
>
>> permissions of the entry apply to the file (the inheritance flags of the
>> inherited entry are cleared).
>> .IP \(bu 4
>> The entry is is inherited by new subdirectories created in the directory such
>
> s/ 4//
>
>> that the permissions of the entry will apply to new files created in the
>> subdirectory.
>> .RE
>> .TP
>> .BR dir_inherit "\ (" d )
>> When this flag appears in the ACL entry of a directory, then that entry is
>> inherited by new subdirectories created in the directory such that the
>> permissions of the entry apply to the subdirectory (the
>> .B inherit_only
>> flag is cleared).
>> .TP
>> .BR no_propagate "\ (" n )
>> Inheritance stops at the next subdirectory level. When a file or directory
>> inherits an entry that has this flag set, the
>> .BR file_inherit ", " dir_inherit ", " no_propagate ", and " inherit_only
>> flags are cleared.
>> .TP
>> .BR inherit_only "\ (" i )
>> The entry defines inheritable permissions only and is ignored for access
>> checking. When a file or directory inherits an entry that has this flag set,
>> the flag is cleared.
>> .TP
>> .BR inherited "\ (" a )
>> The entry has been automatically inherited from the parent directory; the
>> ACL's
>> .B auto_inherit
>> flag should be on.
>
> Why "should be" in the previous sentence? I think a little explanation
> is needed here...

I've removed the second part of the sentence instead.

>> .TP
>> .BR unmapped "\ (" u )
>> The user or group identifier is a textual string and is not mapped to a numeric
>> user or group identifier. ACLs with unmapped identifiers can occur on NFSv4
>> mounted filesystems when the client cannot determine numeric user or group
>> identifiers for some of the NFSv4 user@domain or group@domain who values. They
>> cannot be assigned to local files or directories.
>>
>> .SS Permissions
>>
>> The following permissions are defined for RichACL entries and for the three
>> file masks:
>>
>> .TP
>> .BR read_data " / " list_directory "\ (" r )
>> For a file: read the data of the file.
>> For a directory: list the contents of the directory.
>> .TP
>> .BR write_data " / " add_file "\ (" w )
>> For a file: modify the data of the file; does not include opening the file in
>> append mode.
>> For a directory: add a new file in the directory.
>> .TP
>> .BR append_data " / " add_subdirectory "\ (" p )
>> For a file: open the file in append mode.
>> For a directory: create a subdirectory in the directory.
>> .TP
>> .BR execute "\ (" x )
>> For a file: execute the file.
>> For a directory: traverse / search the directory.
>
> s%traverse / search%traverse (search)%
>> .TP
>> .BR delete_child "\ (" d )
>> Delete a file or directory within a directory. This permission is meaningless
>> for non-directories.
>
> ==> "This permission is meanungful only for directories."
>
>> .TP
>> .BR delete "\ (" D )
>> Delete the file or directory.
>> .TP
>> .BR read_attributes "\ (" a )
>> Read basic attributes of a file or directory (see
>> .BR stat (2)).
>> This permission is defined by NFSv4. It is stored, but ignored. Reading basic
>> attributes of files and directories is always allowed on Linux.
>> .TP
>> .BR write_attributes "\ (" A )
>> Change the times associated with a file or directory to an arbitrary value.
>> This permission is always implicitly granted to the file owner.
>> .TP
>> .BR read_acl "\ (" c )
>> Read the ACL of a file or directory. This permission is always
>> implicitly granted.
>
> So, I think a sentence explaining why "read_acl" exists would be
> helpful, since the reader is left a little puzzled about its purpose if
> it is always implicitly granted.

"Like reading the basic file attributes (the read_attributes permission),
reading ACLs is always allowed in Linux."

>> .TP
>> .BR write_acl "\ (" C )
>> Change the ACL or file mode of a file or directory.
>> .TP
>> .BR write_owner "\ (" o )
>> Take ownership of a file or directory. Change the owning group of a file or
>> directory to a group of which the calling process is a member.
>> .TP
>
> Formatting tweak: add ".ad l" before the following line amd ".ad" after
> the line.
>
>> .BR read_named_attrs "\ (" R "), " write_named_attrs "\ (" W "), " synchronize "\ (" S "), " write_retention "\ (" e "), " write_retention_hold "\ (" E )
>> These permissions are defined by NFSv4 / NFSv4.1. They are stored, but ignored.
>
> s%/%and%
>
>> .PP
>> For the
>> .BR r ", " w ", and " p
>> permissions which have different long forms for files and directories, the
>
> s/permissions/permissions,/
>
>> .BR getrichacl (1)
>> utility will output the appropriate form(s) depending on the context.
>> The
>> .BR setrichacl (1)
>> utility will accept either form for any file type.
>>
>> .SS Text form
>> The common textual representation of a RichACL consists of the colon-separated
>> fields of the ACL flags, file masks, and ACL entries in the following
>> format:
>> .TP
>> \fBflags:\fR\fIacl_flags\fR
>> The ACL flags.
>> .TP
>> \fBowner:\fR\fIperm\fR\fB::mask\fR, \fBgroup:\fR\fIperm\fR\fB::mask\fR, \fBother:\fR\fIperm\fR\fB::mask\fR
>> The file masks and their permissions.
>> .TP
>> \fIwho\fR\fB:\fR\fIperm\fR\fB:\fR\fIflags\fR\fB:allow\fR, \fIwho\fR\fB:\fR\fIperm\fR\fB:\fR\fIflags\fR\fB:deny\fR
>> For each ACL entry, who the entry applies to, the permissions of the entry, the
>> entry flags, and the entry type. The who field is one of the following:
>
> s/who/\\fIwho\\fP/
>
>> .RS
>> .IP \(bu 4
>
> s/4/2/
>
>> One of the special identifiers:
>> .BR owner@ ", " group@ ", or " everyone@ ,
>> .IP \(bu
>> A
>> .BR user: " or " u:
>> prefix followed by a user name or user ID that designates a specific user,
>> .IP \(bu
>> A
>> .BR group: " or " g:
>> prefix followed by a group name or group ID that designates a specific group.
>> .RE
>> .PP
>> The entries are comma, whitespace, or newline separated.
>>
>> Flags and permissions have single-letter as well as long forms, as listed under
>> .IR "ACL flags" ,
>> .IR "ACL entry flags" ,
>> and
>> .IR Permissions .
>> When the single-letter forms are used, the flags or permissions are
>> concatenated. When the long forms are used, the flags or permissions are
>> separated by slashes. To align permissions or flags vertically, dashes can be
>> used for padding.
>>
>> .SS Setting and modifying file permissions
>> The access permissions for a file can either be set by assigning an Access
>> Control List
>> .RB ( setrichacl (1))
>> or by changing the file mode permission bits
>> .RB ( chmod (1)).
>> In addition, a file can inherit an ACL from its parent directory at creation
>> time as described under
>> .IR "Permissions at file-creation time" .
>>
>> .SS Assigning an Access Control List
>> When assigning an ACL to a file, unless explicitly specified, the owner, group,
>> and other file masks will be computed from the ACL entries as described in
>> the section
>> .IR "Computing the maximum file masks" .
>> The owner, group, and other file mode permission bits are then each set from
>> the owner, group, and other file mask as follows:
>> .IP \(bu 4
>
> s/4/2/
>
>> If the file mask includes the
>> .B r
>> permission, the read
>> file mode permission bit will be set.
>> .IP \(bu
>> If the file mask includes the
>> .B w
>> or
>> .B p
>> permission, the write file mode permission bit will be set.
>> .IP \(bu
>> If the file mask includes the
>> .B x
>> permission, the execute file mode permission bit will be set.
>> .PP
>> If the ACL can be represented exactly by the file mode
>> permission bits, the file permission bits are set to match the ACL and the ACL
>> is not stored.
>
> Maybe better: "...and no ACL is stored"
>
>> (When the ACL of a file is requested which doesn't have an ACL,
>> the file mode permission bits are converted into an equivalent ACL.)
>>
>> .SS Changing the file mode permission bits
>> When changing the file mode permission bits with
>> .BR chmod (1),
>> the owner, group, and other file permission bits are set to the permission bits
>> in the new mode, and the owner, group, and other file masks are set based on
>> the new mode bits as follows:
>> .IP \(bu 4
>
> s/4/2/
>
>> If the read bit in a set of permissions is set, the
>> .B r
>> permission in the corresponding file mask will be set.
>> .IP \(bu
>> If the write bit in a set of permissions is set, the
>> .B w
>> and
>> .B p
>> permissions in the corresponding file mask will be set.
>> .IP \(bu
>> If the execute bit in a set of permissions is set, the
>> .B x
>> permission in the corresponding file mask will be set.
>> .PP
>> In addition, the
>> .B masked
>> and
>> .B write_through
>> ACL flags are set. This has the
>> effect of limiting the permissions granted by the ACL to the file mode
>> permission bits; in addition, the owner is granted the owner mode bits and
>> others are granted the other mode bits. If the
>> .B auto_inherit
>> flag is set, the
>> .B protected
>> flag is also set to prevent the Automatic Inheritance algorithm from modifying
>> the ACL.
>>
>> .SS Permissions at file-creation time
>> When a directory has inheritable ACL entries, the following
>
> s/has/has an/
>
>> happens when a file or directory is created inside that directory:
>> .RS 4
>> .IP 1. 4
>> A file created inside that directory will inherit all of the ACL entries that
>> have the
>> .B file_inherit
>> flag set, and all inheritance-related flags in the inherited entries flag will
>> be cleared.
>>
>> A subdirectory created inside that directory will inherit all of the ACL
>> entries that either have the
>> .B dir_inherit
>> flag set, or the
>> .B file_inherit
>> flag set and the
>> .B no_propagate
>> flag not set. Entries whose
>> .B dir_inherit
>> flag is set will have their
>> .B inherit_only
>> flag cleared, and entries whose
>> .B dir_inherit
>> flag is not set will have their
>> .B inherit_only
>> flag set. Finally, entries whose
>> .B no_propagate
>> flag is set will have all inheritance-related flags cleared.
>> .IP 2.
>> If the parent directory's ACL has the
>> .B auto_inherit
>> flag set, the inherited ACL will have its
>> .B auto_inherit
>> flag set, and all entries will have their
>> .B inherited
>> flag set. Otherwise, the
>> .B auto_inherit
>> and
>> .B inherited
>> flags are cleared.
>> .IP 3.
>> The three file masks are computed from the inherited ACL as described in
>> the section
>> .IR "Computing the maximum file masks" .
>> .IP 4.
>> The three sets of permissions for the owner, the group, and for others in
>> the \fImode\fR parameter as given to
>> .BR open (2),
>> .BR mkdir (2),
>> and similar are converted into sets of RichACL permissions. The correspondence
>> between mask flags and RichACL permission bits is described in the section
>> .IR "Changing the file mode permission bits" .
>> Any RichACL permissions not included in those sets are
>> removed from the owner, group, and other file masks. The file mode permission
>> bits are then computed from the file masks as described in the section
>> .IR "Assigning an Access Control List" .
>> The process umask (see
>> .BR umask (2))
>> is ignored.
>> .IP 5.
>> The
>> .B masked
>> ACL flag is set. The
>> .B write_through
>> ACL flag remains cleared. In addition, if the
>> .B auto_inherit
>> flag of the inherited ACL is set, the
>> .B protected
>> flag is also set to prevent the Automatic Inheritance algorithm from modifying
>> the ACL.
>> .RE
>> .PP
>> When a directory does not have inheritable ACL entries, files and directories
>> created inside that directory will not be assigned Access Control Lists and the
>> file mode permission bits will be set to (\fImode\fR\ &\ ~\fIumask\fR) where
>> \fImode\fR is the mode argument of the relevant system call and \fIumask\fR is
>> the process umask (see
>> .BR umask (2)).
>>
>> .SS Automatic Inheritance
>> Automatic Inheritance is a mechanism that allows permission changes to
>> propagate from a directory to files and subdirectories inside that directory,
>> recursively. Propagation is carried out by the process changing the directory
>> permissions (usually,
>> .BR setrichacl (1));
>> it happens without user intervention albeit not entirely automatically.
>>
>> A significant limitation is that this mechanism works only as long as files
>> are created without explicitly specifying the file permissions to use. The
>> standard system calls for creating files and directories
>> .RB ( creat (2),
>> .BR open (2),
>> .BR mkdir (2),
>> .BR mknod (2))
>> all have mandatory mode parameters which define the maximum allowed permissions
>> of the new files. To take account of this restriction, the
>> .B protected
>> ACL flag must be set if the
>> .B inherited
>> flag is set. This effectively disables Automatic Inheritance for that
>> particular file.
>>
>
> Add the following at the start of the next paragraph:
>
> "Motwithstanding the aforementioned limitation,"
>> Automatic Inheritance still remains useful for network protocols like NFSv4 and
>> SMB, which both support creating files and directories without defining their
>> permissions: they can implement those operations by using the standard system
>
> s/: they/. These protocols/
> (To avoid an excessively long sentence.)
>
>> calls and by then undoing the effect of applying the mode parameters.
>>
>> When the ACL of a directory is changed, the following happens for each entry
>> (\(lqchild\(rq) inside that directory:
>> .IP 1. 4
>> If the entry is a symblic link, skip the child.
>
> s/symblic/symbolic/
>
>> .IP 2.
>> If the
>> .B auto_inherit
>> flag of the entry's ACL is not set or the
>> .B protected
>> flag is set, skip the child.
>> .IP 3.
>> With the child's ACL:
>> .RS 4
>> .IP a) 4
>> If the
>> .B defaulted
>> flag is set, replace the ACL with an empty ACL
>> with the
>> .B auto_inherit
>> flag set.
>> .IP b)
>> Delete all entries which have the
>> .B inherited
>> flag set.
>> .IP c)
>> Append all entries inherited from the parent directory according to step 1 of
>> the algorithm described under
>> .IR "Permissions at file-creation time".
>> Set the
>> .B inherited
>> flag of each of these entries.
>> .IP d)
>> Recompute the file masks.
>> .RE
>> .IP 4.
>> If the child is a directory, recursively apply this algorithm.
>>
>> .SS Access check algorithm
>>
>> When a process requests a particular kind of access (expressed as a set of
>> RichACL permissions) to a file, the following algorithm determines whether the
>> access is granted or denied:
>>
>> .IP 1. 4
>> If the
>> .B masked
>> ACL flag is set, then:
>> .RS 4
>> .IP a) 4
>> If the
>> .B write_through
>> ACL flag is set, then:
>> .RS 4
>
> s/4/2/
>
>> .IP \(bu 4
>
> s/4/2/
>
>> If the requesting process is the file owner, then access is granted if the
>> owner mask includes the requested permissions, and is otherwise denied.
>> .IP \(bu
>> If the requesting process is not the file owner, is not in the owning group,
>> and no ACL entries other than
>> .B everyone@
>> match the process, then access is granted if the other mask includes the
>> requested permissions, and is otherwise denied.
>
> So, in the above subcases, the following does not seem to be covered:
> (1) "masked" ACL flag is set AND
> (2) requesting process *is* in owning group *or* an ACL other
> than "everyone@"matches the process.
>
> What happens in this case? I suspect that somehow we are supposed to
> fall through to part "b)" below (and possibly into clause "2."?), but
> the logical structure of the clauses does not reflect this.

Yes. I've added this bullet point between the existing two now:

"If the requesting process is not the file owner and it is in the owning group
or matches any ACL entries other than everyone@, proceed to step b)."

>> .RE
>> .IP b)
>> If any of the following is true:
>> .RS 4
>
> s/4/2/
>
>> .IP \(bu 4
>
> s/4/2/
>
>> the requesting process is the file owner and the owner mask does not include all
>> requested permissions,
>> .IP \(bu 4
>
> s/ 4//
>
>> the requesting process is not the file owner and it is in the owning group or
>> matches any ACL entries other than
>> .BR everyone@ ,
>> and the group mask does not include all requested permissions,
>> .IP \(bu 4
>
> s/ 4//
>
>> the requesting process is not the file owner, not in the owning group, it
>> matches no ACL entries other than
>> .BR everyone@ ,
>> and the other mask does not include all requested permissions,
>> .PP
>> then access is denied.
>> .RE
>> .RE
>
> At some point, perhaps in the next paragraph, I think that it needs to
> be clarified that unlike POSIX ACLs, a process can gain the permissions
> it requires by accumulating them from multiple RichACL enties. (That's
> correct, is it not?)

Yes. I've added the following at the end of the section:

"In this algorithm, a process can gain the permissions it requires by
accumulating them from multiple RichACL entries. This is in contrast with
POSIX ACLs, where access is only granted if an ACL entry exists that matches
the requesting process and includes all the requested permissions."

>> .IP 2.
>> Set the remaining permissions to the requested permissions. Go through all ACL
>> entries. For each entry:
>
> So, perhaps replace the preceding two lines with something like:
>
> [[
> Upon reaching this point, the determination of whether or not access is
> granted is made by scanning all ACL entries to see if one or more
> applicable entries together grant a cumulative set of permissions that
> matches the requested permissions or there is an applicable entry that
> explicitly denies one or more of the requested permissions.
> The scan of all ACL entries begins by
> first initializing the set of remaining permissions (i.e., those that have
> not yet been satisfied during the scan) to be the set of requested
> permissions. Then the ACL entries are scanned
> .IR "in order" ,
> and for each entry:
> ]]

ok

>> .RS 4
>> .IP a) 4
>> If the
>> .B inherit_only
>> or
>> .B unmapped
>> flags are set, continue with the next ACL entry.
>> .IP b)
>> If any of the following is true:
>> .RS 4
>
> s/4/2/
>
>> .IP \(bu 4
>
> s/4/2/
>
>> the entry's identifier is
>> .B owner@
>> and the requesting process is the file owner,
>> .IP \(bu
>> the entry's identifier is
>> .B group@
>> and the requesting process is in the owning group,
>> .IP \(bu
>> the entry's identifier is a user and the requesting process is owned by that
>> user,
>> .IP \(bu
>> the entry's identifier is a group and the requesting process is a member in
>> that group,
>> .IP \(bu
>> the entry's identifier is
>> .BR everyone@ ,
>> .PP
>> then the entry matches the process; proceed to the next step. Otherwise,
>> continue with the next ACL entry.
>> .RE
>> .IP c)
>> If the entry denies any of the remaining permissions, access is denied.
>> .IP d)
>> If the entry allows any of the remaining permissions, then:
>> .RS 4
>
> s/4/2/
>
>> .IP \(bu 4
>
> s/4/2/
>
>> If the
>> .B masked
>> ACL flag is set and the entry's identifier is not
>> .B owner@
>> or
>> .BR everyone@
>> or is a user entry matching the file owner, remove all permissions from the
>> remaining permissions which are both allowed by the entry and included in the
>> group mask,
>> .IP \(bu
>> Otherwise, remove all permissions from the remaining permissions wich are
>
> s/wich/which
>
>> allowed by the entry.
>> .RE
>> .RE
>> .IP 3.
>> If there are no more remaining permissions, access is allowed. Otherwise,
>> access is denied.
>>
>> .SS Computing the maximum file masks
>> When setting an ACL and no file masks have been explicitly specified and when
>> inheriting an ACL from the parent directory, the following algorithm is used
>> for computing the file masks:
>>
>> .IP 1. 4
>> Clear the owner, group, and other file masks. Remember which permissions have
>> already been processed (initially, the empty set).
>> .IP 2.
>> For each ACL entry:
>> .RS 4
>
> s/4/2/
>
>> .IP \(bu 4
>
> s/4/2/
>
>> If the
>> .B inherit_only
>> flag is set, skip the entry.
>> .IP \(bu 4
>
> s/ 4//
>
>> Otherwise, compute which permissions the entry allows or denies that have not
>> been processed yet (the remaining permissions).
>> .IP \(bu
>> If the entry is an
>> .B owner@
>> entry, add the remaining permissions to the owner mask for
>> .B allow
>> entries, and remove the remaining permissions from the owner mask for
>> .B deny
>> entries.
>> .IP \(bu
>> Otherwise, if the entry is an
>> .B everyone@
>> entry, proceed as with
>> .B owner@
>> entries but add or remove the remaining permissions from the owner, group, and
>> other file masks.
>> .IP \(bu
>> Otherwise, proceed as with
>> .B owner@
>> entries but add or remove the remaining permissions from the owner and group
>> file masks.
>> .IP \(bu
>> Add the entry's permissions to the processed permissions.
>> .RE
>> .PP
>> The resulting file masks represent the ACL as closely as possible. With these
>> file masks, if the
>> .B masked
>> ACL flag is set, the effective permissions still stay the same.
>
> The meaing of "will stay the same" is not quite clear "will stay the
> same *as what*"?). I suspect I know what you mean, but it needs to be
> made more obvious.

"With these file masks, the effective permissions that the ACL grants
will be the same when the masked flag is set as when it is not set."

>>
>> .\" .SH BUGS
>> .SH AUTHOR
>> Written by Andreas Grünbacher <[email protected]>.
>>
>> Please send your bug reports, suggested features and comments to the above address.
>>
>
> I'm going to play the broken record :-)
>
> Could we start with just a few simple examples already, and build up
> over future iterations of this page?

Yes, as soon as I'll get to it :)

>> .SH CONFORMING TO
>> Rich Access Control Lists are Linux-specific.
>> .SH SEE ALSO
>> .BR acl (5),
>
> Move this entry to the point XXX below.
>
>> .BR chmod (1),
>> .BR getrichacl (1),
>> .BR ls (1),
>> .BR setrichacl (1)
>> .BR stat (2),
>> .BR umask (2)
>> .\" librichacl
>
> XXX
>
> By the way, are there already man pages for the librichacl functions?

Not yet, no.

Cheers,
Andreas

Subject: Re: richacl(7) man page review comments

Hi Andreas,

On 02/22/2016 03:46 PM, Andreas Gruenbacher wrote:
> Hi Michael,
>
> On Sun, Feb 21, 2016 at 10:40 PM, Michael Kerrisk (man-pages)
> <[email protected]> wrote:
>> I've once more pulled from the latest git; here's some more comments.
>
> thanks again. I've updated the repo with your changes.

Thanks!

[...]

>> I'm going to play the broken record :-)
>>
>> Could we start with just a few simple examples already, and build up
>> over future iterations of this page?
>
> Yes, as soon as I'll get to it :)

Sure. But, to press the point home, I'm interested to do further
review, but I feel like the lack of examples is limiting my ability to
understand what's going on and deepen the feedback that I provide in
future iterations. So, start please, even if only starting small :-).

Cheers,

Michael


--
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Linux/UNIX System Programming Training: http://man7.org/training/

2016-02-23 10:28:39

by Andreas Gruenbacher

[permalink] [raw]
Subject: Re: richacl(7) man page review comments

On Tue, Feb 23, 2016 at 11:16 AM, Michael Kerrisk (man-pages)
<[email protected]> wrote:
> On 02/22/2016 03:46 PM, Andreas Gruenbacher wrote:
>> On Sun, Feb 21, 2016 at 10:40 PM, Michael Kerrisk (man-pages) <[email protected]> wrote:
>>> Could we start with just a few simple examples already, and build up
>>> over future iterations of this page?
>>
>> Yes, as soon as I'll get to it :)
>
> Sure. But, to press the point home, I'm interested to do further
> review, but I feel like the lack of examples is limiting my ability to
> understand what's going on and deepen the feedback that I provide in
> future iterations. So, start please, even if only starting small :-).

Sure, I understand that.

In case you didn't stumble upon this page before, a few very simple
examples showing how things interact can be found here:

http://www.bestbits.at/richacl/examples.html

Thanks,
Andreas

Subject: Re: richacl(7) man page review comments

Hi Andreas,

On 02/22/2016 03:46 PM, Andreas Gruenbacher wrote:
> Hi Michael,
>
> On Sun, Feb 21, 2016 at 10:40 PM, Michael Kerrisk (man-pages)
> <[email protected]> wrote:
>> I've once more pulled from the latest git; here's some more comments.
>
> thanks again. I've updated the repo with your changes.

Next round :-). Just a few quick comments while I'm on a train ride.

> .\"
> .\" RichACL Manual Pages
> .\"
> .\" Copyright (C) 2015,2016 Red Hat, Inc.
> .\" Written by Andreas Gruenbacher <[email protected]>
> .\" This is free documentation; you can redistribute it and/or
> .\" modify it under the terms of the GNU General Public License as
> .\" published by the Free Software Foundation; either version 2 of
> .\" the License, or (at your option) any later version.
> .\"
> .\" The GNU General Public License's references to "object code"
> .\" and "executables" are to be interpreted as the output of any
> .\" document formatting or typesetting system, including
> .\" intermediate and printed output.
> .\"
> .\" This manual is distributed in the hope that it will be useful,
> .\" but WITHOUT ANY WARRANTY; without even the implied warranty of
> .\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> .\" GNU General Public License for more details.
> .\"
> .\" You should have received a copy of the GNU General Public
> .\" License along with this manual. If not, see
> .\" <http://www.gnu.org/licenses/>.
> .\"
> .de URL
> \\$2 \(laURL: \\$1 \(ra\\$3
> ..
> .if \n[.g] .mso www.tmac
> .TH RICHACL 7 2015-09-01 "Linux" "Rich Access Control Lists"
> .SH NAME
> richacl \- Rich Access Control Lists
> .SH DESCRIPTION
> Rich Access Control Lists (RichACLs) are an extension of the POSIX file
> permission model (see
> .BR acl (5))
> to support
> .URL https://tools.ietf.org/rfc/rfc5661.txt "NFSv4 Access Control Lists"
> on local and remote-mounted filesystems.
>
> A RichACL can always be translated into an equivalent NFSv4 ACL which grants
> the same permissions.
>
> RichACLs can be enabled on supported local filesystems (currently, ext4 and
> XFS). The in-kernel NFSv4 server and client also include RichACL support.
>
> Enabling RichACLs disables POSIX Access Control Lists; the two ACL models
> cannot coexist on the same filesystem.
>
> When used on a filesystem that does not support RichACLs, the
> .BR getrichacl (1)
> and
> .BR setrichacl (1)
> utilities will operate on the file permission bits instead:
> .BR getrichacl (1)
> will display the file permission bits as a RichACL; when a RichACL
> is set with
> .BR setrichacl (1)
> which can be represented exactly by the file permission bits,
> .BR setrichacl (1)
> will set the file permission bits instead. An attempt to set a RichACL that
> cannot be represented exactly by the file permission bits results in an error.
>
> .SS Structure of RichACLs
>
> RichACLs consist of a number of ACL entries, three file masks, and a set of
> flags specifying attributes of the ACL as a whole (by contrast with the
> per-ACL-entry flags described below).
>
> Each of the ACL entries allows or denies some permissions to a particular user,
> group, or special identifier. An ACL entry consists of four fields:
>
> .IP \(bu 2
> A tag which specifies the user, group, or special identifier the entry applies
> to. Special identifiers can be the file owner
> .RB ( owner@ ),
> the owning group
> .RB ( group@ ),
> or everyone
> .RB ( everyone@ ).
> .IP \(bu
> A set of permissions the entry allows or denies.
> .IP \(bu
> A set of flags that indicate whether the user or group identifier is mapped or
> unmapped, and whether the entry has been and can be inherited.
> .IP \(bu
> A type field indicating whether the entry allows or denies the permissions
> specified in the second field.
> .PP
> The owner, group, and other file masks further control which permissions the
> ACL grants, subject to the
> .BR masked "\ (" m )
> and
> .BR write_through "\ (" w )
> ACL flags: when the permissions of a file or directory are changed with
> .BR chmod (2),
> the file masks are set based on the new file mode, and the
> .B masked
> and
> .B write_through
> ACL flags are set. Likewise, when a new file or directory inherits an ACL from
> its parent directory, the file masks are set to the intersection between the
> permissions granted by the inherited ACL and the
> .I mode
> parameter as given to
> .BR open "(2), " mkdir (2),
> and similar, and the
> .B masked
> ACL flag is set. In both cases, the file masks limit the permissions that the
> ACL will grant.
>
> The purpose of the file masks is to allow traditional POSIX applications which
> are unaware of RichACLs to place limits on the permissions granted by the
> RichACL without causing the ACL entries to be modified. Without the file mask,
> the only alternative would be for the kernel to directly modify the ACL
> entries. However, this latter approach could have a "hysteresis effect",
> whereby a RichACL-unaware application that performs a transition from one file
> mode to another file mode and then back to the original file mode could cause
> destruction of the permission information in ACL entries. When creating files
> or directories, the
> .I mode
> parameter to
> .BR open "(2), " mkdir (2),
> and similar would cause the same effect.

s/cause/have/

>
> Note that entries with the identifier
> .B everyone@
> apply to all processes, whereas the \(lqother\(rq file permissions and
> \(lqother\(rq entries in POSIX ACLs apply to all processes which are not the

So, I still think it's helpful to mention ACL_OTHER here. How about:

s/\\(lqother\\(rq/\\(lqother\\(rq (\\fBACL_OTHER\\fP)/

> owner, are not in the owning group, and do not match a user or group mentioned
> in the ACL.
>
> Unlike POSIX ACLs, RichACLs do not have separate \(lqaccess\(rq ACLs that
> define the access permissions and \(lqdefault\(rq ACLs that define the
> inheritable permissions. Instead, flags on each ACL entry determine whether
> the entry is effective during access checks and/or inheritable.
>
>
> .SS ACL flags
>
> The following ACL flags are defined:
>
> .TP
> .BR masked "\ (" m )
> When set, the file masks define upper limits on the permissions the ACL may
> grant. When not set, the file masks are ignored.
> .TP
> .BR write_through "\ (" w )
> When this flag and the
> .B masked
> flag are both set, the owner and other file masks define the actual permissions
> granted to the file owner and to others instead of defining an upper limit.
> When the
> .B masked
> flag is not set, the
> .B write_through
> flag has no effect.
> .TP
> .BR auto_inherit "\ (" a )
> Automatic Inheritance is enabled. See
> .IR "Automatic Inheritance" .
> .TP
> .BR protected "\ (" p )
> The ACL is protected from modification by Automatic
> Inheritance.
> .TP
> .BR defaulted "\ (" d )
> Indicates that the ACL has been assigned in an application-dependent way when
> the file or directory was created; it has neither been inherited nor set
> explicitly. ACLs of files created on Linux will never have the
> .B defaulted
> flag set, but the flag may be set on files created on or copied over from
> other operating systems. When this flag is set for an ACL, Automatic
> Inheritance will completely replace the ACL.
>
> .SS ACL entry flags
>
> The following flags on ACL entries are defined:
>
> .TP
> .BR file_inherit "\ (" f )
> When this flag appears in the ACL entry of a directory, then:
> .RS
> .IP \(bu 2
> That entry is inherited by new files created in the directory such that the
> permissions of the entry apply to the file (the inheritance flags of the
> inherited entry are cleared).
> .IP \(bu
> The entry is is inherited by new subdirectories created in the directory such
> that the permissions of the entry will apply to new files created in the
> subdirectory.
> .RE
> .TP
> .BR dir_inherit "\ (" d )
> When this flag appears in the ACL entry of a directory, then that entry is
> inherited by new subdirectories created in the directory such that the
> permissions of the entry apply to the subdirectory (the
> .B inherit_only
> flag is cleared).
> .TP
> .BR no_propagate "\ (" n )
> Inheritance stops at the next subdirectory level. When a file or directory
> inherits an entry that has this flag set, the
> .BR file_inherit ", " dir_inherit ", " no_propagate ", and " inherit_only
> flags are cleared.
> .TP
> .BR inherit_only "\ (" i )
> The entry defines inheritable permissions only and is ignored for access
> checking. When a file or directory inherits an entry that has this flag set,
> the flag is cleared.
> .TP
> .BR inherited "\ (" a )
> The entry has been automatically inherited from the parent directory.
> .TP
> .BR unmapped "\ (" u )
> The user or group identifier is a textual string and is not mapped to a numeric
> user or group identifier. ACLs with unmapped identifiers can occur on NFSv4
> mounted filesystems when the client cannot determine numeric user or group
> identifiers for some of the NFSv4 user@domain or group@domain who values. They
> cannot be assigned to local files or directories.
>
> .SS Permissions
>
> The following permissions are defined for RichACL entries and for the three
> file masks:
>
> .TP
> .BR read_data " / " list_directory "\ (" r )
> For a file: read the data of the file.
> For a directory: list the contents of the directory.
> .TP
> .BR write_data " / " add_file "\ (" w )
> For a file: modify the data of the file; does not include opening the file in
> append mode.
> For a directory: add a new file in the directory.
> .TP
> .BR append_data " / " add_subdirectory "\ (" p )
> For a file: open the file in append mode.
> For a directory: create a subdirectory in the directory.
> .TP
> .BR execute "\ (" x )
> For a file: execute the file.
> For a directory: traverse (search) the directory.
> .TP
> .BR delete_child "\ (" d )
> Delete a file or directory within a directory. This permission is meaningful
> only for directories.
> .TP
> .BR delete "\ (" D )
> Delete the file or directory.
> .TP
> .BR read_attributes "\ (" a )
> Read basic attributes of a file or directory (see
> .BR stat (2)).
> This permission is defined by NFSv4. It is stored, but ignored. Reading basic
> attributes of files and directories is always allowed on Linux.
> .TP
> .BR write_attributes "\ (" A )
> Change the times associated with a file or directory to an arbitrary value.
> This permission is always implicitly granted to the file owner.
> .TP
> .BR read_acl "\ (" c )
> Read the ACL of a file or directory. Like reading the basic file attributes (the
> .B read_attributes
> permission), reading ACLs is always allowed in Linux.
> .TP
> .BR write_acl "\ (" C )
> Change the ACL or file mode of a file or directory.
> .TP
> .BR write_owner "\ (" o )
> Take ownership of a file or directory. Change the owning group of a file or
> directory to a group of which the calling process is a member.
> .TP
> .ad l
> .BR read_named_attrs "\ (" R "), " write_named_attrs "\ (" W "), " synchronize "\ (" S "), " write_retention "\ (" e "), " write_retention_hold "\ (" E )
> .ad
> These permissions are defined by NFSv4 and NFSv4.1. They are stored, but ignored.
> .PP
> For the
> .BR r ", " w ", and " p
> permissions, which have different long forms for files and directories, the
> .BR getrichacl (1)
> utility will output the appropriate form(s) depending on the context.
> The
> .BR setrichacl (1)
> utility will accept either form for any file type.
>
> .SS Text form
> The common textual representation of a RichACL consists of the colon-separated
> fields of the ACL flags, file masks, and ACL entries in the following
> format:
> .TP
> \fBflags:\fR\fIacl_flags\fR
> The ACL flags.
> .TP
> \fBowner:\fR\fIperm\fR\fB::mask\fR, \fBgroup:\fR\fIperm\fR\fB::mask\fR, \fBother:\fR\fIperm\fR\fB::mask\fR
> The file masks and their permissions.
> .TP
> \fIwho\fR\fB:\fR\fIperm\fR\fB:\fR\fIflags\fR\fB:allow\fR, \fIwho\fR\fB:\fR\fIperm\fR\fB:\fR\fIflags\fR\fB:deny\fR
> For each ACL entry, who the entry applies to, the permissions of the entry, the
> entry flags, and the entry type. The \fIwho\fR field is one of the following:
> .RS
> .IP \(bu 2
> One of the special identifiers:
> .BR owner@ ", " group@ ", or " everyone@ ,
> .IP \(bu
> A
> .BR user: " or " u:
> prefix followed by a user name or user ID that designates a specific user,
> .IP \(bu
> A
> .BR group: " or " g:
> prefix followed by a group name or group ID that designates a specific group.
> .RE
> .PP
> The entries are comma, whitespace, or newline separated.

s/entries/fields of an ACL entry/ (?)

>
> Flags and permissions have single-letter as well as long forms, as listed under
> .IR "ACL flags" ,
> .IR "ACL entry flags" ,
> and
> .IR Permissions .
> When the single-letter forms are used, the flags or permissions are
> concatenated. When the long forms are used, the flags or permissions are
> separated by slashes. To align permissions or flags vertically, dashes can be
> used for padding.
>
> .SS Setting and modifying file permissions
> The access permissions for a file can either be set by assigning an Access
> Control List
> .RB ( setrichacl (1))
> or by changing the file mode permission bits
> .RB ( chmod (1)).
> In addition, a file can inherit an ACL from its parent directory at creation
> time as described under
> .IR "Permissions at file-creation time" .
>
> .SS Assigning an Access Control List
> When assigning an ACL to a file, unless explicitly specified, the owner, group,
> and other file masks will be computed from the ACL entries as described in
> the section
> .IR "Computing the maximum file masks" .
> The owner, group, and other file mode permission bits are then each set from
> the owner, group, and other file mask as follows:
> .IP \(bu 2
> If the file mask includes the
> .B r
> permission, the read
> file mode permission bit will be set.
> .IP \(bu
> If the file mask includes the
> .B w
> or
> .B p
> permission, the write file mode permission bit will be set.
> .IP \(bu
> If the file mask includes the
> .B x
> permission, the execute file mode permission bit will be set.
> .PP
> If the ACL can be represented exactly by the file mode permission bits, the
> file permission bits are set to match the ACL and no ACL is stored. (When the
> ACL of a file is requested which doesn't have an ACL, the file mode permission
> bits are converted into an equivalent ACL.)
>
> .SS Changing the file mode permission bits
> When changing the file mode permission bits with
> .BR chmod (1),
> the owner, group, and other file permission bits are set to the permission bits
> in the new mode, and the owner, group, and other file masks are set based on
> the new mode bits as follows:
> .IP \(bu 2
> If the read bit in a set of permissions is set, the
> .B r
> permission in the corresponding file mask will be set.
> .IP \(bu
> If the write bit in a set of permissions is set, the
> .B w
> and
> .B p
> permissions in the corresponding file mask will be set.
> .IP \(bu
> If the execute bit in a set of permissions is set, the
> .B x
> permission in the corresponding file mask will be set.
> .PP
> In addition, the
> .B masked
> and
> .B write_through
> ACL flags are set. This has the
> effect of limiting the permissions granted by the ACL to the file mode
> permission bits; in addition, the owner is granted the owner mode bits and
> others are granted the other mode bits. If the
> .B auto_inherit
> flag is set, the
> .B protected
> flag is also set to prevent the Automatic Inheritance algorithm from modifying
> the ACL.
>
> .SS Permissions at file-creation time
> When a directory has any inheritable ACL entries, the following
> happens when a file or directory is created inside that directory:
> .RS 4

Remove preceding line.

> .IP 1. 4
> A file created inside that directory will inherit all of the ACL entries that
> have the
> .B file_inherit
> flag set, and all inheritance-related flags in the inherited entries flag will
> be cleared.
>
> A subdirectory created inside that directory will inherit all of the ACL
> entries that either have the
> .B dir_inherit
> flag set, or the
> .B file_inherit
> flag set and the
> .B no_propagate
> flag not set. Entries whose
> .B dir_inherit
> flag is set will have their
> .B inherit_only
> flag cleared, and entries whose
> .B dir_inherit
> flag is not set will have their
> .B inherit_only
> flag set. Finally, entries whose
> .B no_propagate
> flag is set will have all inheritance-related flags cleared.
> .IP 2.
> If the parent directory's ACL has the
> .B auto_inherit
> flag set, the inherited ACL will have its

s/the/then the/
(For ease of parsing)

> .B auto_inherit
> flag set, and all entries will have their
> .B inherited
> flag set. Otherwise, the
> .B auto_inherit
> and
> .B inherited
> flags are cleared.
> .IP 3.
> The three file masks are computed from the inherited ACL as described in
> the section
> .IR "Computing the maximum file masks" .
> .IP 4.
> The three sets of permissions for the owner, the group, and for others in
> the \fImode\fR parameter as given to
> .BR open (2),
> .BR mkdir (2),
> and similar are converted into sets of RichACL permissions. The correspondence
> between mask flags and RichACL permission bits is described in the section
> .IR "Changing the file mode permission bits" .
> Any RichACL permissions not included in those sets are
> removed from the owner, group, and other file masks. The file mode permission
> bits are then computed from the file masks as described in the section
> .IR "Assigning an Access Control List" .
> The process umask (see
> .BR umask (2))
> is ignored.
> .IP 5.
> The
> .B masked
> ACL flag is set. The
> .B write_through
> ACL flag remains cleared. In addition, if the
> .B auto_inherit
> flag of the inherited ACL is set, the
> .B protected
> flag is also set to prevent the Automatic Inheritance algorithm from modifying
> the ACL.
> .RE

Remove preceding line.

> .PP
> When a directory does not have inheritable ACL entries, files and directories
> created inside that directory will not be assigned Access Control Lists and the
> file mode permission bits will be set to (\fImode\fR\ &\ ~\fIumask\fR) where
> \fImode\fR is the mode argument of the relevant system call and \fIumask\fR is
> the process umask (see
> .BR umask (2)).
>
> .SS Automatic Inheritance
> Automatic Inheritance is a mechanism that allows permission changes to
> propagate from a directory to files and subdirectories inside that directory,
> recursively. Propagation is carried out by the process changing the directory
> permissions (usually,
> .BR setrichacl (1));
> it happens without user intervention albeit not entirely automatically.
>
> A significant limitation is that this mechanism works only as long as files

s/limitation/limitation of the Automatic Inheritance feature/

> are created without explicitly specifying the file permissions to use. The
> standard system calls for creating files and directories
> .RB ( creat (2),
> .BR open (2),
> .BR mkdir (2),
> .BR mknod (2))

s/)$/,\nand so on)/

(And, I'd drop creat(2) from that list of examples. It's ancient and
obsolete; no need to encourageits use.)

> all have mandatory mode parameters which define the maximum allowed permissions
> of the new files. To take account of this restriction, the
> .B protected
> ACL flag must be set if the
> .B inherited
> flag is set. This effectively disables Automatic Inheritance for that
> particular file.
>
> Notwithstanding the aforementioned limitation, Automatic Inheritance still
> remains useful for network protocols like NFSv4 and SMB, which both support
> creating files and directories without defining their permissions. These
> protocols can implement those operations by using the standard system calls and
> by then undoing the effect of applying the mode parameters.
>
> When the ACL of a directory is changed, the following happens for each entry
> (\(lqchild\(rq) inside that directory:
> .IP 1. 4
> If the entry is a symbolic link, skip the child.
> .IP 2.
> If the
> .B auto_inherit
> flag of the entry's ACL is not set or the
> .B protected
> flag is set, skip the child.
> .IP 3.
> With the child's ACL:
> .RS 4
> .IP a) 4
> If the
> .B defaulted
> flag is set, replace the ACL with an empty ACL
> with the
> .B auto_inherit
> flag set.
> .IP b)
> Delete all entries which have the
> .B inherited
> flag set.
> .IP c)
> Append all entries inherited from the parent directory according to step 1 of
> the algorithm described under
> .IR "Permissions at file-creation time".
> Set the
> .B inherited
> flag of each of these entries.
> .IP d)
> Recompute the file masks.

At th end of the last section, add:

as descibed in the section "...."

> .RE
> .IP 4.
> If the child is a directory, recursively apply this algorithm.
>
> .SS Access check algorithm
>
> When a process requests a particular kind of access (expressed as a set of
> RichACL permissions) to a file, the following algorithm determines whether the
> access is granted or denied:
>
> .IP 1. 4
> If the
> .B masked
> ACL flag is set, then:
> .RS 4
> .IP a) 4
> If the
> .B write_through
> ACL flag is set, then:
> .RS 4
> .IP \(bu 2
> If the requesting process is the file owner, then access is granted if the
> owner mask includes the requested permissions, and is otherwise denied.
> .IP \(bu
> If the requesting process is not the file owner and it is in the owning group or matches any ACL entries other than
> .BR everyone@ ,
> proceed to step b).
> .IP \(bu
> If the requesting process is not the file owner, is not in the owning group,
> and no ACL entries other than
> .B everyone@
> match the process, then access is granted if the other mask includes the
> requested permissions, and is otherwise denied.
> .RE
> .IP b)
> If any of the following is true:
> .RS 4
> .IP \(bu 2
> the requesting process is the file owner and the owner mask does not include all
> requested permissions,
> .IP \(bu
> the requesting process is not the file owner and it is in the owning group or
> matches any ACL entries other than
> .BR everyone@ ,
> and the group mask does not include all requested permissions,
> .IP \(bu
> the requesting process is not the file owner, not in the owning group, it
> matches no ACL entries other than
> .BR everyone@ ,
> and the other mask does not include all requested permissions,
> .PP
> then access is denied.
> .RE
> .RE
> .IP 2.
> Upon reaching this point, the determination of whether or not access is granted
> is made by scanning all ACL entries to see if one or more applicable entries
> together grant a cumulative set of permissions that matches the requested
> permissions or there is an applicable entry that explicitly denies one or more
> of the requested permissions. The scan of all ACL entries begins by first
> initializing the set of remaining permissions (i.e., those that have not yet
> been satisfied during the scan) to be the set of requested permissions. Then
> the ACL entries are scanned
> .IR "in order" ,
> and for each entry:
> .RS 4
> .IP a) 4
> If the
> .B inherit_only
> or
> .B unmapped
> flags are set, continue with the next ACL entry.
> .IP b)
> If any of the following is true:
> .RS 4
> .IP \(bu 2
> the entry's identifier is
> .B owner@
> and the requesting process is the file owner,
> .IP \(bu
> the entry's identifier is
> .B group@
> and the requesting process is in the owning group,
> .IP \(bu
> the entry's identifier is a user and the requesting process is owned by that
> user,
> .IP \(bu
> the entry's identifier is a group and the requesting process is a member in
> that group,
> .IP \(bu
> the entry's identifier is
> .BR everyone@ ,
> .PP
> then the entry matches the process; proceed to the next step. Otherwise,
> continue with the next ACL entry.
> .RE
> .IP c)
> If the entry denies any of the remaining permissions, access is denied.
> .IP d)
> If the entry allows any of the remaining permissions, then:
> .RS 4
> .IP \(bu 2
> If the
> .B masked
> ACL flag is set and the entry's identifier is not
> .B owner@
> or
> .BR everyone@
> or is a user entry matching the file owner, remove all permissions from the
> remaining permissions which are both allowed by the entry and included in the
> group mask,
> .IP \(bu
> Otherwise, remove all permissions from the remaining permissions which are
> allowed by the entry.
> .RE
> .RE
> .IP 3.
> If there are no more remaining permissions, access is allowed. Otherwise,
> access is denied.
> .PP
> In this algorithm, a process can gain the permissions it requires by
> accumulating them from multiple RichACL entries. This is in contrast with
> POSIX ACLs, where access is only granted if an ACL entry exists that matches
> the requesting process and includes all the requested permissions.
>
> .SS Computing the maximum file masks
> When setting an ACL and no file masks have been explicitly specified and when
> inheriting an ACL from the parent directory, the following algorithm is used

s/directory/directory (as described in section "....")/

> for computing the file masks:
>
> .IP 1. 4
> Clear the owner, group, and other file masks. Remember which permissions have
> already been processed (initially, the empty set).
> .IP 2.
> For each ACL entry:
> .RS 4
> .IP \(bu 2
> If the
> .B inherit_only
> flag is set, skip the entry.
> .IP \(bu
> Otherwise, compute which permissions the entry allows or denies that have not
> been processed yet (the remaining permissions).
> .IP \(bu
> If the entry is an
> .B owner@
> entry, add the remaining permissions to the owner mask for
> .B allow
> entries, and remove the remaining permissions from the owner mask for
> .B deny
> entries.
> .IP \(bu
> Otherwise, if the entry is an
> .B everyone@
> entry, proceed as with
> .B owner@
> entries but add or remove the remaining permissions from the owner, group, and
> other file masks.
> .IP \(bu
> Otherwise, proceed as with
> .B owner@
> entries but add or remove the remaining permissions from the owner and group
> file masks.
> .IP \(bu
> Add the entry's permissions to the processed permissions.
> .RE
> .PP
> The resulting file masks represent the ACL as closely as possible. With these
> file masks, the effective permissions that the ACL grants will be the same when
> the
> .B masked
> flag is set as when it is not set.
>
> .\" .SH BUGS
> .SH AUTHOR
> Written by Andreas Grünbacher <[email protected]>.
>
> Please send your bug reports, suggested features and comments to the above address.
>
> .SH CONFORMING TO
> Rich Access Control Lists are Linux-specific.
> .SH SEE ALSO
> .BR chmod (1),
> .BR getrichacl (1),
> .BR ls (1),
> .BR setrichacl (1)
> .BR stat (2),
> .BR umask (2),
> .BR acl (5)
> .\" librichacl

So, in terms of actually testing this stuff, is it just a matter of
applying your patch series to the kernel, building the kernel, pulling
the RichACL user-space tools from Git, and mount(8)ing a filesystem with
the right option?

Cheers,

Michael




--
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Linux/UNIX System Programming Training: http://man7.org/training/

2016-02-23 11:14:35

by Andreas Gruenbacher

[permalink] [raw]
Subject: Re: richacl(7) man page review comments

On Tue, Feb 23, 2016 at 11:58 AM, Michael Kerrisk (man-pages)
<[email protected]> wrote:
> So, in terms of actually testing this stuff, is it just a matter of
> applying your patch series to the kernel, building the kernel, pulling
> the RichACL user-space tools from Git, and mount(8)ing a filesystem with
> the right option?

You'd create a test filesystem with the appropriate feature flag set
(mkfs.ext4 -O richacl2 / mkfs.xfs -m richacl=1), RichACLs are not
enabled by mount options anymore. This will obviously require versions
of e2fsprogs / xfsprogs that understand the feature. If you want
coreutils support which isn't strictly necessary, you'll need the
patched version too. Other than that, it's really simple.

Andreas

2016-02-23 15:09:02

by Andreas Gruenbacher

[permalink] [raw]
Subject: Re: richacl(7) man page review comments

Hi Michael,

On Tue, Feb 23, 2016 at 11:58 AM, Michael Kerrisk (man-pages)
<[email protected]> wrote:
> On 02/22/2016 03:46 PM, Andreas Gruenbacher wrote:
>> On Sun, Feb 21, 2016 at 10:40 PM, Michael Kerrisk (man-pages) <[email protected]> wrote:
>>> I've once more pulled from the latest git; here's some more comments.
>>
>> thanks again. I've updated the repo with your changes.
>
> Next round :-). Just a few quick comments while I'm on a train ride.

applied, thanks.

>> .\"
>> .\" RichACL Manual Pages
>> .\"
>> .\" Copyright (C) 2015,2016 Red Hat, Inc.
>> .\" Written by Andreas Gruenbacher <[email protected]>
>> .\" This is free documentation; you can redistribute it and/or
>> .\" modify it under the terms of the GNU General Public License as
>> .\" published by the Free Software Foundation; either version 2 of
>> .\" the License, or (at your option) any later version.
>> .\"
>> .\" The GNU General Public License's references to "object code"
>> .\" and "executables" are to be interpreted as the output of any
>> .\" document formatting or typesetting system, including
>> .\" intermediate and printed output.
>> .\"
>> .\" This manual is distributed in the hope that it will be useful,
>> .\" but WITHOUT ANY WARRANTY; without even the implied warranty of
>> .\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>> .\" GNU General Public License for more details.
>> .\"
>> .\" You should have received a copy of the GNU General Public
>> .\" License along with this manual. If not, see
>> .\" <http://www.gnu.org/licenses/>.
>> .\"
>> .de URL
>> \\$2 \(laURL: \\$1 \(ra\\$3
>> ..
>> .if \n[.g] .mso www.tmac
>> .TH RICHACL 7 2015-09-01 "Linux" "Rich Access Control Lists"
>> .SH NAME
>> richacl \- Rich Access Control Lists
>> .SH DESCRIPTION
>> Rich Access Control Lists (RichACLs) are an extension of the POSIX file
>> permission model (see
>> .BR acl (5))
>> to support
>> .URL https://tools.ietf.org/rfc/rfc5661.txt "NFSv4 Access Control Lists"
>> on local and remote-mounted filesystems.
>>
>> A RichACL can always be translated into an equivalent NFSv4 ACL which grants
>> the same permissions.
>>
>> RichACLs can be enabled on supported local filesystems (currently, ext4 and
>> XFS). The in-kernel NFSv4 server and client also include RichACL support.
>>
>> Enabling RichACLs disables POSIX Access Control Lists; the two ACL models
>> cannot coexist on the same filesystem.
>>
>> When used on a filesystem that does not support RichACLs, the
>> .BR getrichacl (1)
>> and
>> .BR setrichacl (1)
>> utilities will operate on the file permission bits instead:
>> .BR getrichacl (1)
>> will display the file permission bits as a RichACL; when a RichACL
>> is set with
>> .BR setrichacl (1)
>> which can be represented exactly by the file permission bits,
>> .BR setrichacl (1)
>> will set the file permission bits instead. An attempt to set a RichACL that
>> cannot be represented exactly by the file permission bits results in an error.
>>
>> .SS Structure of RichACLs
>>
>> RichACLs consist of a number of ACL entries, three file masks, and a set of
>> flags specifying attributes of the ACL as a whole (by contrast with the
>> per-ACL-entry flags described below).
>>
>> Each of the ACL entries allows or denies some permissions to a particular user,
>> group, or special identifier. An ACL entry consists of four fields:
>>
>> .IP \(bu 2
>> A tag which specifies the user, group, or special identifier the entry applies
>> to. Special identifiers can be the file owner
>> .RB ( owner@ ),
>> the owning group
>> .RB ( group@ ),
>> or everyone
>> .RB ( everyone@ ).
>> .IP \(bu
>> A set of permissions the entry allows or denies.
>> .IP \(bu
>> A set of flags that indicate whether the user or group identifier is mapped or
>> unmapped, and whether the entry has been and can be inherited.
>> .IP \(bu
>> A type field indicating whether the entry allows or denies the permissions
>> specified in the second field.
>> .PP
>> The owner, group, and other file masks further control which permissions the
>> ACL grants, subject to the
>> .BR masked "\ (" m )
>> and
>> .BR write_through "\ (" w )
>> ACL flags: when the permissions of a file or directory are changed with
>> .BR chmod (2),
>> the file masks are set based on the new file mode, and the
>> .B masked
>> and
>> .B write_through
>> ACL flags are set. Likewise, when a new file or directory inherits an ACL from
>> its parent directory, the file masks are set to the intersection between the
>> permissions granted by the inherited ACL and the
>> .I mode
>> parameter as given to
>> .BR open "(2), " mkdir (2),
>> and similar, and the
>> .B masked
>> ACL flag is set. In both cases, the file masks limit the permissions that the
>> ACL will grant.
>>
>> The purpose of the file masks is to allow traditional POSIX applications which
>> are unaware of RichACLs to place limits on the permissions granted by the
>> RichACL without causing the ACL entries to be modified. Without the file mask,
>> the only alternative would be for the kernel to directly modify the ACL
>> entries. However, this latter approach could have a "hysteresis effect",
>> whereby a RichACL-unaware application that performs a transition from one file
>> mode to another file mode and then back to the original file mode could cause
>> destruction of the permission information in ACL entries. When creating files
>> or directories, the
>> .I mode
>> parameter to
>> .BR open "(2), " mkdir (2),
>> and similar would cause the same effect.
>
> s/cause/have/
>
>>
>> Note that entries with the identifier
>> .B everyone@
>> apply to all processes, whereas the \(lqother\(rq file permissions and
>> \(lqother\(rq entries in POSIX ACLs apply to all processes which are not the
>
> So, I still think it's helpful to mention ACL_OTHER here. How about:
>
> s/\\(lqother\\(rq/\\(lqother\\(rq (\\fBACL_OTHER\\fP)/
>
>> owner, are not in the owning group, and do not match a user or group mentioned
>> in the ACL.
>>
>> Unlike POSIX ACLs, RichACLs do not have separate \(lqaccess\(rq ACLs that
>> define the access permissions and \(lqdefault\(rq ACLs that define the
>> inheritable permissions. Instead, flags on each ACL entry determine whether
>> the entry is effective during access checks and/or inheritable.
>>
>>
>> .SS ACL flags
>>
>> The following ACL flags are defined:
>>
>> .TP
>> .BR masked "\ (" m )
>> When set, the file masks define upper limits on the permissions the ACL may
>> grant. When not set, the file masks are ignored.
>> .TP
>> .BR write_through "\ (" w )
>> When this flag and the
>> .B masked
>> flag are both set, the owner and other file masks define the actual permissions
>> granted to the file owner and to others instead of defining an upper limit.
>> When the
>> .B masked
>> flag is not set, the
>> .B write_through
>> flag has no effect.
>> .TP
>> .BR auto_inherit "\ (" a )
>> Automatic Inheritance is enabled. See
>> .IR "Automatic Inheritance" .
>> .TP
>> .BR protected "\ (" p )
>> The ACL is protected from modification by Automatic
>> Inheritance.
>> .TP
>> .BR defaulted "\ (" d )
>> Indicates that the ACL has been assigned in an application-dependent way when
>> the file or directory was created; it has neither been inherited nor set
>> explicitly. ACLs of files created on Linux will never have the
>> .B defaulted
>> flag set, but the flag may be set on files created on or copied over from
>> other operating systems. When this flag is set for an ACL, Automatic
>> Inheritance will completely replace the ACL.
>>
>> .SS ACL entry flags
>>
>> The following flags on ACL entries are defined:
>>
>> .TP
>> .BR file_inherit "\ (" f )
>> When this flag appears in the ACL entry of a directory, then:
>> .RS
>> .IP \(bu 2
>> That entry is inherited by new files created in the directory such that the
>> permissions of the entry apply to the file (the inheritance flags of the
>> inherited entry are cleared).
>> .IP \(bu
>> The entry is is inherited by new subdirectories created in the directory such
>> that the permissions of the entry will apply to new files created in the
>> subdirectory.
>> .RE
>> .TP
>> .BR dir_inherit "\ (" d )
>> When this flag appears in the ACL entry of a directory, then that entry is
>> inherited by new subdirectories created in the directory such that the
>> permissions of the entry apply to the subdirectory (the
>> .B inherit_only
>> flag is cleared).
>> .TP
>> .BR no_propagate "\ (" n )
>> Inheritance stops at the next subdirectory level. When a file or directory
>> inherits an entry that has this flag set, the
>> .BR file_inherit ", " dir_inherit ", " no_propagate ", and " inherit_only
>> flags are cleared.
>> .TP
>> .BR inherit_only "\ (" i )
>> The entry defines inheritable permissions only and is ignored for access
>> checking. When a file or directory inherits an entry that has this flag set,
>> the flag is cleared.
>> .TP
>> .BR inherited "\ (" a )
>> The entry has been automatically inherited from the parent directory.
>> .TP
>> .BR unmapped "\ (" u )
>> The user or group identifier is a textual string and is not mapped to a numeric
>> user or group identifier. ACLs with unmapped identifiers can occur on NFSv4
>> mounted filesystems when the client cannot determine numeric user or group
>> identifiers for some of the NFSv4 user@domain or group@domain who values. They
>> cannot be assigned to local files or directories.
>>
>> .SS Permissions
>>
>> The following permissions are defined for RichACL entries and for the three
>> file masks:
>>
>> .TP
>> .BR read_data " / " list_directory "\ (" r )
>> For a file: read the data of the file.
>> For a directory: list the contents of the directory.
>> .TP
>> .BR write_data " / " add_file "\ (" w )
>> For a file: modify the data of the file; does not include opening the file in
>> append mode.
>> For a directory: add a new file in the directory.
>> .TP
>> .BR append_data " / " add_subdirectory "\ (" p )
>> For a file: open the file in append mode.
>> For a directory: create a subdirectory in the directory.
>> .TP
>> .BR execute "\ (" x )
>> For a file: execute the file.
>> For a directory: traverse (search) the directory.
>> .TP
>> .BR delete_child "\ (" d )
>> Delete a file or directory within a directory. This permission is meaningful
>> only for directories.
>> .TP
>> .BR delete "\ (" D )
>> Delete the file or directory.
>> .TP
>> .BR read_attributes "\ (" a )
>> Read basic attributes of a file or directory (see
>> .BR stat (2)).
>> This permission is defined by NFSv4. It is stored, but ignored. Reading basic
>> attributes of files and directories is always allowed on Linux.
>> .TP
>> .BR write_attributes "\ (" A )
>> Change the times associated with a file or directory to an arbitrary value.
>> This permission is always implicitly granted to the file owner.
>> .TP
>> .BR read_acl "\ (" c )
>> Read the ACL of a file or directory. Like reading the basic file attributes (the
>> .B read_attributes
>> permission), reading ACLs is always allowed in Linux.
>> .TP
>> .BR write_acl "\ (" C )
>> Change the ACL or file mode of a file or directory.
>> .TP
>> .BR write_owner "\ (" o )
>> Take ownership of a file or directory. Change the owning group of a file or
>> directory to a group of which the calling process is a member.
>> .TP
>> .ad l
>> .BR read_named_attrs "\ (" R "), " write_named_attrs "\ (" W "), " synchronize "\ (" S "), " write_retention "\ (" e "), " write_retention_hold "\ (" E )
>> .ad
>> These permissions are defined by NFSv4 and NFSv4.1. They are stored, but ignored.
>> .PP
>> For the
>> .BR r ", " w ", and " p
>> permissions, which have different long forms for files and directories, the
>> .BR getrichacl (1)
>> utility will output the appropriate form(s) depending on the context.
>> The
>> .BR setrichacl (1)
>> utility will accept either form for any file type.
>>
>> .SS Text form
>> The common textual representation of a RichACL consists of the colon-separated
>> fields of the ACL flags, file masks, and ACL entries in the following
>> format:
>> .TP
>> \fBflags:\fR\fIacl_flags\fR
>> The ACL flags.
>> .TP
>> \fBowner:\fR\fIperm\fR\fB::mask\fR, \fBgroup:\fR\fIperm\fR\fB::mask\fR, \fBother:\fR\fIperm\fR\fB::mask\fR
>> The file masks and their permissions.
>> .TP
>> \fIwho\fR\fB:\fR\fIperm\fR\fB:\fR\fIflags\fR\fB:allow\fR, \fIwho\fR\fB:\fR\fIperm\fR\fB:\fR\fIflags\fR\fB:deny\fR
>> For each ACL entry, who the entry applies to, the permissions of the entry, the
>> entry flags, and the entry type. The \fIwho\fR field is one of the following:
>> .RS
>> .IP \(bu 2
>> One of the special identifiers:
>> .BR owner@ ", " group@ ", or " everyone@ ,
>> .IP \(bu
>> A
>> .BR user: " or " u:
>> prefix followed by a user name or user ID that designates a specific user,
>> .IP \(bu
>> A
>> .BR group: " or " g:
>> prefix followed by a group name or group ID that designates a specific group.
>> .RE
>> .PP
>> The entries are comma, whitespace, or newline separated.
>
> s/entries/fields of an ACL entry/ (?)

No, the fields in each of the different kinds of entries are colon separated.

"The ACL flags, file masks, and ACL entries are comma, whitespace, or newline
separated."

>> Flags and permissions have single-letter as well as long forms, as listed under
>> .IR "ACL flags" ,
>> .IR "ACL entry flags" ,
>> and
>> .IR Permissions .
>> When the single-letter forms are used, the flags or permissions are
>> concatenated. When the long forms are used, the flags or permissions are
>> separated by slashes. To align permissions or flags vertically, dashes can be
>> used for padding.
>>
>> .SS Setting and modifying file permissions
>> The access permissions for a file can either be set by assigning an Access
>> Control List
>> .RB ( setrichacl (1))
>> or by changing the file mode permission bits
>> .RB ( chmod (1)).
>> In addition, a file can inherit an ACL from its parent directory at creation
>> time as described under
>> .IR "Permissions at file-creation time" .
>>
>> .SS Assigning an Access Control List
>> When assigning an ACL to a file, unless explicitly specified, the owner, group,
>> and other file masks will be computed from the ACL entries as described in
>> the section
>> .IR "Computing the maximum file masks" .
>> The owner, group, and other file mode permission bits are then each set from
>> the owner, group, and other file mask as follows:
>> .IP \(bu 2
>> If the file mask includes the
>> .B r
>> permission, the read
>> file mode permission bit will be set.
>> .IP \(bu
>> If the file mask includes the
>> .B w
>> or
>> .B p
>> permission, the write file mode permission bit will be set.
>> .IP \(bu
>> If the file mask includes the
>> .B x
>> permission, the execute file mode permission bit will be set.
>> .PP
>> If the ACL can be represented exactly by the file mode permission bits, the
>> file permission bits are set to match the ACL and no ACL is stored. (When the
>> ACL of a file is requested which doesn't have an ACL, the file mode permission
>> bits are converted into an equivalent ACL.)
>>
>> .SS Changing the file mode permission bits
>> When changing the file mode permission bits with
>> .BR chmod (1),
>> the owner, group, and other file permission bits are set to the permission bits
>> in the new mode, and the owner, group, and other file masks are set based on
>> the new mode bits as follows:
>> .IP \(bu 2
>> If the read bit in a set of permissions is set, the
>> .B r
>> permission in the corresponding file mask will be set.
>> .IP \(bu
>> If the write bit in a set of permissions is set, the
>> .B w
>> and
>> .B p
>> permissions in the corresponding file mask will be set.
>> .IP \(bu
>> If the execute bit in a set of permissions is set, the
>> .B x
>> permission in the corresponding file mask will be set.
>> .PP
>> In addition, the
>> .B masked
>> and
>> .B write_through
>> ACL flags are set. This has the
>> effect of limiting the permissions granted by the ACL to the file mode
>> permission bits; in addition, the owner is granted the owner mode bits and
>> others are granted the other mode bits. If the
>> .B auto_inherit
>> flag is set, the
>> .B protected
>> flag is also set to prevent the Automatic Inheritance algorithm from modifying
>> the ACL.
>>
>> .SS Permissions at file-creation time
>> When a directory has any inheritable ACL entries, the following
>> happens when a file or directory is created inside that directory:
>> .RS 4
>
> Remove preceding line.
>
>> .IP 1. 4
>> A file created inside that directory will inherit all of the ACL entries that
>> have the
>> .B file_inherit
>> flag set, and all inheritance-related flags in the inherited entries flag will
>> be cleared.
>>
>> A subdirectory created inside that directory will inherit all of the ACL
>> entries that either have the
>> .B dir_inherit
>> flag set, or the
>> .B file_inherit
>> flag set and the
>> .B no_propagate
>> flag not set. Entries whose
>> .B dir_inherit
>> flag is set will have their
>> .B inherit_only
>> flag cleared, and entries whose
>> .B dir_inherit
>> flag is not set will have their
>> .B inherit_only
>> flag set. Finally, entries whose
>> .B no_propagate
>> flag is set will have all inheritance-related flags cleared.
>> .IP 2.
>> If the parent directory's ACL has the
>> .B auto_inherit
>> flag set, the inherited ACL will have its
>
> s/the/then the/
> (For ease of parsing)
>
>> .B auto_inherit
>> flag set, and all entries will have their
>> .B inherited
>> flag set. Otherwise, the
>> .B auto_inherit
>> and
>> .B inherited
>> flags are cleared.
>> .IP 3.
>> The three file masks are computed from the inherited ACL as described in
>> the section
>> .IR "Computing the maximum file masks" .
>> .IP 4.
>> The three sets of permissions for the owner, the group, and for others in
>> the \fImode\fR parameter as given to
>> .BR open (2),
>> .BR mkdir (2),
>> and similar are converted into sets of RichACL permissions. The correspondence
>> between mask flags and RichACL permission bits is described in the section
>> .IR "Changing the file mode permission bits" .
>> Any RichACL permissions not included in those sets are
>> removed from the owner, group, and other file masks. The file mode permission
>> bits are then computed from the file masks as described in the section
>> .IR "Assigning an Access Control List" .
>> The process umask (see
>> .BR umask (2))
>> is ignored.
>> .IP 5.
>> The
>> .B masked
>> ACL flag is set. The
>> .B write_through
>> ACL flag remains cleared. In addition, if the
>> .B auto_inherit
>> flag of the inherited ACL is set, the
>> .B protected
>> flag is also set to prevent the Automatic Inheritance algorithm from modifying
>> the ACL.
>> .RE
>
> Remove preceding line.
>
>> .PP
>> When a directory does not have inheritable ACL entries, files and directories
>> created inside that directory will not be assigned Access Control Lists and the
>> file mode permission bits will be set to (\fImode\fR\ &\ ~\fIumask\fR) where
>> \fImode\fR is the mode argument of the relevant system call and \fIumask\fR is
>> the process umask (see
>> .BR umask (2)).
>>
>> .SS Automatic Inheritance
>> Automatic Inheritance is a mechanism that allows permission changes to
>> propagate from a directory to files and subdirectories inside that directory,
>> recursively. Propagation is carried out by the process changing the directory
>> permissions (usually,
>> .BR setrichacl (1));
>> it happens without user intervention albeit not entirely automatically.
>>
>> A significant limitation is that this mechanism works only as long as files
>
> s/limitation/limitation of the Automatic Inheritance feature/
>
>> are created without explicitly specifying the file permissions to use. The
>> standard system calls for creating files and directories
>> .RB ( creat (2),
>> .BR open (2),
>> .BR mkdir (2),
>> .BR mknod (2))
>
> s/)$/,\nand so on)/
>
> (And, I'd drop creat(2) from that list of examples. It's ancient and
> obsolete; no need to encourageits use.)
>
>> all have mandatory mode parameters which define the maximum allowed permissions
>> of the new files. To take account of this restriction, the
>> .B protected
>> ACL flag must be set if the
>> .B inherited
>> flag is set. This effectively disables Automatic Inheritance for that
>> particular file.
>>
>> Notwithstanding the aforementioned limitation, Automatic Inheritance still
>> remains useful for network protocols like NFSv4 and SMB, which both support
>> creating files and directories without defining their permissions. These
>> protocols can implement those operations by using the standard system calls and
>> by then undoing the effect of applying the mode parameters.
>>
>> When the ACL of a directory is changed, the following happens for each entry
>> (\(lqchild\(rq) inside that directory:
>> .IP 1. 4
>> If the entry is a symbolic link, skip the child.
>> .IP 2.
>> If the
>> .B auto_inherit
>> flag of the entry's ACL is not set or the
>> .B protected
>> flag is set, skip the child.
>> .IP 3.
>> With the child's ACL:
>> .RS 4
>> .IP a) 4
>> If the
>> .B defaulted
>> flag is set, replace the ACL with an empty ACL
>> with the
>> .B auto_inherit
>> flag set.
>> .IP b)
>> Delete all entries which have the
>> .B inherited
>> flag set.
>> .IP c)
>> Append all entries inherited from the parent directory according to step 1 of
>> the algorithm described under
>> .IR "Permissions at file-creation time".
>> Set the
>> .B inherited
>> flag of each of these entries.
>> .IP d)
>> Recompute the file masks.
>
> At th end of the last section, add:
>
> as descibed in the section "...."
>
>> .RE
>> .IP 4.
>> If the child is a directory, recursively apply this algorithm.
>>
>> .SS Access check algorithm
>>
>> When a process requests a particular kind of access (expressed as a set of
>> RichACL permissions) to a file, the following algorithm determines whether the
>> access is granted or denied:
>>
>> .IP 1. 4
>> If the
>> .B masked
>> ACL flag is set, then:
>> .RS 4
>> .IP a) 4
>> If the
>> .B write_through
>> ACL flag is set, then:
>> .RS 4
>> .IP \(bu 2
>> If the requesting process is the file owner, then access is granted if the
>> owner mask includes the requested permissions, and is otherwise denied.
>> .IP \(bu
>> If the requesting process is not the file owner and it is in the owning group or matches any ACL entries other than
>> .BR everyone@ ,
>> proceed to step b).
>> .IP \(bu
>> If the requesting process is not the file owner, is not in the owning group,
>> and no ACL entries other than
>> .B everyone@
>> match the process, then access is granted if the other mask includes the
>> requested permissions, and is otherwise denied.
>> .RE
>> .IP b)
>> If any of the following is true:
>> .RS 4
>> .IP \(bu 2
>> the requesting process is the file owner and the owner mask does not include all
>> requested permissions,
>> .IP \(bu
>> the requesting process is not the file owner and it is in the owning group or
>> matches any ACL entries other than
>> .BR everyone@ ,
>> and the group mask does not include all requested permissions,
>> .IP \(bu
>> the requesting process is not the file owner, not in the owning group, it
>> matches no ACL entries other than
>> .BR everyone@ ,
>> and the other mask does not include all requested permissions,
>> .PP
>> then access is denied.
>> .RE
>> .RE
>> .IP 2.
>> Upon reaching this point, the determination of whether or not access is granted
>> is made by scanning all ACL entries to see if one or more applicable entries
>> together grant a cumulative set of permissions that matches the requested
>> permissions or there is an applicable entry that explicitly denies one or more
>> of the requested permissions. The scan of all ACL entries begins by first
>> initializing the set of remaining permissions (i.e., those that have not yet
>> been satisfied during the scan) to be the set of requested permissions. Then
>> the ACL entries are scanned
>> .IR "in order" ,
>> and for each entry:
>> .RS 4
>> .IP a) 4
>> If the
>> .B inherit_only
>> or
>> .B unmapped
>> flags are set, continue with the next ACL entry.
>> .IP b)
>> If any of the following is true:
>> .RS 4
>> .IP \(bu 2
>> the entry's identifier is
>> .B owner@
>> and the requesting process is the file owner,
>> .IP \(bu
>> the entry's identifier is
>> .B group@
>> and the requesting process is in the owning group,
>> .IP \(bu
>> the entry's identifier is a user and the requesting process is owned by that
>> user,
>> .IP \(bu
>> the entry's identifier is a group and the requesting process is a member in
>> that group,
>> .IP \(bu
>> the entry's identifier is
>> .BR everyone@ ,
>> .PP
>> then the entry matches the process; proceed to the next step. Otherwise,
>> continue with the next ACL entry.
>> .RE
>> .IP c)
>> If the entry denies any of the remaining permissions, access is denied.
>> .IP d)
>> If the entry allows any of the remaining permissions, then:
>> .RS 4
>> .IP \(bu 2
>> If the
>> .B masked
>> ACL flag is set and the entry's identifier is not
>> .B owner@
>> or
>> .BR everyone@
>> or is a user entry matching the file owner, remove all permissions from the
>> remaining permissions which are both allowed by the entry and included in the
>> group mask,
>> .IP \(bu
>> Otherwise, remove all permissions from the remaining permissions which are
>> allowed by the entry.
>> .RE
>> .RE
>> .IP 3.
>> If there are no more remaining permissions, access is allowed. Otherwise,
>> access is denied.
>> .PP
>> In this algorithm, a process can gain the permissions it requires by
>> accumulating them from multiple RichACL entries. This is in contrast with
>> POSIX ACLs, where access is only granted if an ACL entry exists that matches
>> the requesting process and includes all the requested permissions.
>>
>> .SS Computing the maximum file masks
>> When setting an ACL and no file masks have been explicitly specified and when
>> inheriting an ACL from the parent directory, the following algorithm is used
>
> s/directory/directory (as described in section "....")/

Presumably "in the section" here as well.

>> for computing the file masks:
>>
>> .IP 1. 4
>> Clear the owner, group, and other file masks. Remember which permissions have
>> already been processed (initially, the empty set).
>> .IP 2.
>> For each ACL entry:
>> .RS 4
>> .IP \(bu 2
>> If the
>> .B inherit_only
>> flag is set, skip the entry.
>> .IP \(bu
>> Otherwise, compute which permissions the entry allows or denies that have not
>> been processed yet (the remaining permissions).
>> .IP \(bu
>> If the entry is an
>> .B owner@
>> entry, add the remaining permissions to the owner mask for
>> .B allow
>> entries, and remove the remaining permissions from the owner mask for
>> .B deny
>> entries.
>> .IP \(bu
>> Otherwise, if the entry is an
>> .B everyone@
>> entry, proceed as with
>> .B owner@
>> entries but add or remove the remaining permissions from the owner, group, and
>> other file masks.
>> .IP \(bu
>> Otherwise, proceed as with
>> .B owner@
>> entries but add or remove the remaining permissions from the owner and group
>> file masks.
>> .IP \(bu
>> Add the entry's permissions to the processed permissions.
>> .RE
>> .PP
>> The resulting file masks represent the ACL as closely as possible. With these
>> file masks, the effective permissions that the ACL grants will be the same when
>> the
>> .B masked
>> flag is set as when it is not set.
>>
>> .\" .SH BUGS
>> .SH AUTHOR
>> Written by Andreas Grünbacher <[email protected]>.
>>
>> Please send your bug reports, suggested features and comments to the above address.
>>
>> .SH CONFORMING TO
>> Rich Access Control Lists are Linux-specific.
>> .SH SEE ALSO
>> .BR chmod (1),
>> .BR getrichacl (1),
>> .BR ls (1),
>> .BR setrichacl (1)
>> .BR stat (2),
>> .BR umask (2),
>> .BR acl (5)
>> .\" librichacl

2016-02-23 19:01:20

by Andreas Gruenbacher

[permalink] [raw]
Subject: Re: richacl(7) man page review comments

On Tue, Feb 23, 2016 at 4:09 PM, Andreas Gruenbacher
<[email protected]> wrote:
> Hi Michael,
>
> On Tue, Feb 23, 2016 at 11:58 AM, Michael Kerrisk (man-pages)
> <[email protected]> wrote:
>> On 02/22/2016 03:46 PM, Andreas Gruenbacher wrote:
>>> On Sun, Feb 21, 2016 at 10:40 PM, Michael Kerrisk (man-pages) <[email protected]> wrote:
>>>> I've once more pulled from the latest git; here's some more comments.
>>>
>>> thanks again. I've updated the repo with your changes.
>>
>> Next round :-). Just a few quick comments while I'm on a train ride.
>
> applied, thanks.

I've fixed the following additional problems:

> diff --git a/man/richacl.7 b/man/richacl.7
> index acdff31..1c82644 100644
> --- a/man/richacl.7
> +++ b/man/richacl.7
> @@ -30,10 +30,8 @@
> .SH NAME
> richacl \- Rich Access Control Lists
> .SH DESCRIPTION
> -Rich Access Control Lists (RichACLs) are an extension of the POSIX file
> -permission model (see
> -.BR acl (5))
> -to support
> +Rich Access Control Lists (RichACLs) are an extension of the traditional POSIX
> +file permission model to support
> .URL https://tools.ietf.org/rfc/rfc5661.txt "NFSv4 Access Control Lists"
> on local and remote-mounted filesystems.

RichACLs are an extension of the traditional POSIX file permission
model, not of the POSIX ACL model.

Unfortunately, there doesn't seem to be a man-page covering POSIX File
Access Permissions as in Appendix A of
http://www.bestbits.at/richacl/draft-gruenbacher-nfsv4-acls-in-posix-00.html.

A lot of the gaps between paragraphs were wrong when rendered for printing.

The modification dates were outdated.

Andreas

2016-02-28 22:11:57

by Andreas Gruenbacher

[permalink] [raw]
Subject: Re: richacl(7) man page review comments

On Tue, Feb 23, 2016 at 11:16 AM, Michael Kerrisk (man-pages)
<[email protected]> wrote:
> On 02/22/2016 03:46 PM, Andreas Gruenbacher wrote:
>> On Sun, Feb 21, 2016 at 10:40 PM, Michael Kerrisk (man-pages) <[email protected]> wrote:
>>> I've once more pulled from the latest git; here's some more comments.
>>
>> thanks again. I've updated the repo with your changes.
>
> Thanks!
>
> [...]
>
>>> I'm going to play the broken record :-)
>>>
>>> Could we start with just a few simple examples already, and build up
>>> over future iterations of this page?
>>
>> Yes, as soon as I'll get to it :)
>
> Sure. But, to press the point home, I'm interested to do further
> review, but I feel like the lack of examples is limiting my ability to
> understand what's going on and deepen the feedback that I provide in
> future iterations. So, start please, even if only starting small :-).

I've added a richaclex(7) examples man page now. What did I miss to explain?

Thanks,
Andreas