Notice that some flags have a bit shift value while other flags
are defined as 0. The flags defined as 0 have no bit set, as these
flags they are represent by the absence of the flag, that is they
are represent by a 0 value in the noted bit position; e.g. MS_RW is
true when MS_RDONLY is not set.
Each flags is encoded as a single byte value equal to its bit shift +
So MS_RDONLY is encoded as 0 + 1 = 1, and MS_RW is not directly
encoded. With each bit that is encoded being written in bit order.
For example, the flags set (MS_RDONLY | MS_NODEV | MS_NOACL | MS_NOUSER) is encoded as the ordered match:
Note: MS_NOACL is now represented by (MS_ACL shift + 1|), this
is because declaring a flag as a don't care value means it can take
on either value.
To match against a mount rule's flag set. The requested flag set
is search in bit order and match attempt are made against the set
bits. That is for a bit set (MS_RDONLY|MS_NODEV) only the character
(MS_RDONLY shift + 1) and (MS_NODEV shift + 1) are matched against
in that order.
E.G. the dfa state matching for (MS_RDONLY|MS_NODEV) is
A mount rule using = for its options (mount option=( )) encodes an
exact pattern of bits. Flags that are not specified are taken to be
their 0 value, and flags that have a 0 value are ignored. The string
of set flags makes a unique string much like the character string '1 3
7'. To match this string only those bits can be set in the flags mask,
an unset bit does not lead to progression through the match string,
a flag that is set that is not in the string results in match failure.
E.G. (MS_RDONLY shift | MS_NODEV shift | MS_ATIME | MS_ACL)
is encoded as the string '1 3 16', notice MS_ATIME is dropped.
Trying to match (MS_NOSUID) against this results in the string
of '2', which clearly does not match (it fails in the first
character), and can not progress, as 1 will never be matched as
the string is always generated in numerically increasing order.
Trying to match (MS_RDONLY shift | MS_NODEV shift ) against
it result in as string of '1 3' which will match the first 2
characters but can not progress to the last character.
Trying to match (MS_RDONLY shift | MS_NODEV shift | MS_ACL |
MS_NOUSER) results in a string of '1 3 16 32' which matches for
the requisite 3 characters, but the MS_NOUSER bit forces the match
to move out of an accepting state and fail. The accept permission
is encoded only in the on the states that exactly match and moving
out of them results in no permission.`
The DFA can efficiently encode multiple rules information, allowing
for a single pass match against all rules.
Encoding of flags when using options in (set)
When options are specified using the in keyword. The flags are
treated as don't care values because the in option defines a subset
of values that can be specified. Any flag that is not specified by
the in subset is treated as a 0 value unless there is also an
exact match options=() set.
This means that
options in (ro)
is equivalent to
and for allow rules is just a convenient short hand for expressing
a set of flags that may or may not be set. Matching of these values
works similar to the matches shown above except the string defines
a pattern match
Example: mount options in (ro,nouser):
defines the bitset (MS_RDONLY | MS_NOUSER), which makes the
match string (1|) (32|) which is equivalent to the following set
'' - the empty string '1'
'32' - '1 32'
Example: mount options in (ro,acl) options=(nodev,nouser)
defines the 2 bitsets (MS_RDONLY | MS_ACL) and (MS_NODEV |
MS_NOUSER) which defines the match string (1|) 3 (16|) 32 which
is equivalent to the following set of strings
'3 32''1 3 32''1 3 16 32''3 16 32'
Short cut encoding for all flags
If all flags are optional the regular expression [^\x00]* is used
Encoding deny flag rules
Because of the way flags are matched the strings used to match deny
rules need to be encoded differently in the don't care cases. The
exact match cases (options=()) follows the same encoding as the allow
rules. The reason two different string encodings are used is that
exact match cases defines exactly 1 string that can be matched but,
the don't care cases define a set of strings, and the semantics of
the set is inverted by the deny.
For example, deny options in (ro, acl), does NOT mean
Where deny options=(ro) means deny the case where ro is the only flag set.
To represent the don't care flags deny rule we use an alternation
with a pattern matching all flags
Example: options in (ro, acl), is represented as:
This allows the rule to intersect all mount rules that could contain
ro or acl flags.
combining don't care and exact match
When options and exact match string are combined the alternation gets modified
Short cut encoding for denying all flags
If a deny rule encodes both the set and unset forms of a flag
(eg. options=(rw,ro) or options in (ro)) this results in all flags
being denied because a positive flags match is not possible because
during a match there are only 2 possible values for each flag and
both values are denied.
This is match in this case is encoded with the regular expression