Add allowed and denied parms to access check routines

Affects:

fsal_test_access
fsal_check_access
cache_inode_access_sw

These parms allow access check to return the specific access mask bits
that were allowed and denied if the caller desires.

These will be used by high level permission checking to make some
more complex decisions, also, it will allow the protocol ACCESS routines
to make a single access check and be able to identify which bits should
be returned to the client.

Also, a flag is added to allow ACL interpretation to not stop at first
applicable DENY ACE. This will be used by NFS v3 and v4 ACCESS ops to
determine access in a single pass.

Signed-off-by: Frank Filz <ffilz@us.ibm.com>
Make getattr optional with cache_inode_lookup and cache_inode_create

Not all callers of cache_inode_lookup need the attributes and we
are going to check permissions on getattr so it will be good to
not ask for them if we won't use them.

Signed-off-by: Frank Filz <ffilz@us.ibm.com>
Don't get attr via nfs_FhandleToCache if we don't need them

Signed-off-by: Frank Filz <ffilz@us.ibm.com>
Add FSAL_ATTRS_V3 to cover all attrs in fattr3 structure

In some cases we need to make sure we get all the FSAL attr flags
corresponding to the attributes present in NFS v3 fattr3 structure.

Signed-off-by: Frank S. Filz <ffilz@us.ibm.com>
Fixup some error translations

New error: CACHE_INODE_BADNAME

ERR_FSAL_ISDIR -> CACHE_INODE_IS_A_DIRECTORY
ERR_FSAL_ISDIR -> STATE_IS_A_DIRECTORY

CACHE_INODE_BADNAME -> STATE_INVALID_ARGUMENT
CACHE_INODE_BADNAME -> NFS4ERR_BADNAME
CACHE_INODE_BADNAME -> NFS3ERR_INVAL (v3 doesn't have BADNAME)
CACHE_INODE_BADNAME -> NFSERR_IO (v2 doesn't even have INVAL)

In nfs4_sanity_check_FH, if required_type is DIRECTORY, return
NFS4ERR_SYMLINK or NFS4ERR_NOTDIR as appropriate.

Signed-off-by: Frank S. Filz <ffilz@us.ibm.com>
Have cache_inode_get_changeid4 check trust of attrs

This makes changeid more resilient to attr changes outside Ganesha.

Signed-off-by: Frank S. Filz <ffilz@us.ibm.com>
Properly permission check cache_inode_readdir

Must have rx mode or ACE4_LIST_DIR | ACE4_EXECUTE (SEARCH) permission to
get the handle or attributes of entries in a directory. Additionally,
for NFS v4, if the ACL attribute is requested, we also require
ACE4_READ_ACL.

Intentionally. we never check ACE4_READ_ATTR. Per section 6.2.1.
Attribute 12: acl of RFC 3530 bis, a server may silently ignore an ACL
mask bit if it can not enforce that. Since Linux pretty much always
allows attributes, we choose not to enforce ACE4_READ_ATTR.

Must have r mode or ACE4_LIST_DIR to get the names in a directory. If
the ACL attribute is requested, then must also have ACE4_READ_ACL.

Do not provide ACL for a file if file does not have READ_ACL permission.

Signed-off-by: Frank Filz <ffilz@us.ibm.com>
Properly permission check cache_inode_getattr

Intentionally. we never check ACE4_READ_ATTR. Per section 6.2.1.
Attribute 12: acl of RFC 3530 bis, a server may silently ignore an ACL
mask bit if it can not enforce that. Since Linux pretty much always
allows attributes, we choose not to enforce ACE4_READ_ATTR.

We do require ACE4_READ_ACL be allowed in order to fetch the ACL
attribute. Otherwise, we assume that the attributes are available
to the client.

Signed-off-by: Frank Filz <ffilz@us.ibm.com>
Properly permission check cache_inode_lookup

Correct permissions for lookup are x mode or ACE4_EXECUTE ACL.

Also check object type correctly.

Signed-off-by: Frank Filz <ffilz@us.ibm.com>
Properly permission check cache_inode_create

Create requires wx mode or ACE4_EXECUTE and either ACE4_ADD_FILE or
ACE4_ADD_DIRECTORY depending on the type of object being created.

RFC 3530 bis doesn't explicitly indicate ACE4_EXECUTE is necessary
but it seems reasonable to match mode bit checking, especially if
mode bits are converted into an ACL.

Signed-off-by: Frank Filz <ffilz@us.ibm.com>
Properly permission check cache_inode_link

Link requires wx mode or ACE4_EXECUTE and ACE4_ADD_FILE.

RFC 3530 bis doesn't explicitly indicate ACE4_EXECUTE is necessary
but it seems reasonable to match mode bit checking, especially if
mode bits are converted into an ACL.

Signed-off-by: Frank Filz <ffilz@us.ibm.com>
Properly permission check cache_inode_rdwr

Permission checking will actually be done at protocol layer.

For NFS v4, we do permission checking on OPEN and on READ and WRITE
operations that use a special stateid.

NFS v3 operations as well as NFS v4 operations performed with a special
stateid will bypass permission checking if the user is the owner of the
file. This is in order to support client side POSIX behavior where a
file may be opened and then the permissions changed without affecting
the open (open(O_CREAT) may have the same effect). Since we don't have
a protocol open, we can not assume the file permissions have not
changed. The client will make an ACCESS call in conjunction with any
open system call that will verify if the open is allowed.

This "owner bypass" check must be done by the protocol layer and not
in the access check code. If done in the access check code, it would
confuse the ACCRESS operation.

NFS v4 OPEN will also result in read, write, or read/write permission
checking based on the type of open.

In all cases, a READ operation, or open for read only is also allowed
if the user has execute permission but not read permission. This is to
allow the client to read executables that do not allow read permission.
The client also has responsibility to make this work. If the client
makes an ACCESS call, read will be denied if the file is execute only.
Not all clients handle this condition properly, or do not handle it
properly for all types of executables.

Signed-off-by: Frank S. Filz <ffilz@us.ibm.com>
Properly permission check cache_inode_remove

For mode, remove requires wx on the directory, and if S_IVTX (sticky
bit) is set, the user must own the parent directory or the target.

For ACL, things are much more complicated.

Though the spec doesn't seem to require ACE4_EXECUTE, I believe this
permission is necessary to properly permission check remove when some
filesystem (such as GPFS) has converted mode bits into an ACL.

Section 6.2.1.3.2. ACE4_DELETE vs. ACE4_DELETE_CHILD of RFC 3530 bis has
an extensive description of how permission checking for remove should
occur, however, I think it is still not quite right. Things also get
a bit interesting if the parent directory has an ACL and the file only
has a mode, or visa versa. These situations can easily be resolved
however by simple logic.

There are some Rationale: sections below. Please note them, they reflect
conditions that are not implied by RFC 3530bis.

The complete order of permission checking is as follows. Evaluation
of these steps ends when a step indicates the operation is allowed or
denied.

1. Check for basic delete permission in the parent directory. This is
   done by checking for wx mode or ACE4_EXECUTE | ACE4_DELETE_CHILD.

   Rationale: Since Linux requires wx mode bits to remove a file, it
   seems like NFS v4 ACLs should also require ACE4_EXECUTE (SEARCH).
   Note that NFS v4 ACL effectively splits w permission for directories
   into ACE4_ADD_FILE and ACE4_DELETE_CHILD.

   The result of this permission check is saved for later use.

2. If check 1 failed, check for basic directory access (x mode or
   ACE4_EXECUTE ACL).

   Rationale: Even if the user is going to be allowed to delete the
   target based on ACE4_DELETE being allowed by the target's ACL, the
   user should still be allowed to see the target inode in the parent
   directory.

   If this check fails, the operation is denied.

3. At this point we know the user is allowed to look at the target...

4. If check 1 passed and the sticky bit is not set, the operation is
   allowed. If the sticky bit is set and the user owns the parent
   directory or the target, the operation is allowed.

5. Check for ACE4_DELETE on the target.

   NOTE: The sticky bit is ignored in this case.

   Rationale: if the file owner has explicitly given ACE4_DELETE to a
   user, that user should be able to delete the file. ACE4_DELETE is not
   typically granted in conversion of mode bits to ACL and is unlikely
   to be present in the inherited ACL of a sticky directory (such as
   an implementation of a /tmp style directory - at least not for
   non owners - a /tmp style directory could be implemented with
   ACLs and inheritance without the sticky bit by allowing ADD_FILE
   for the directory and havign an inherited ACL that grants the owner
   ACE4_DELETE).

   NOTE: This check specifically checks if the access check allowed
   ACE4_DELETE because it has an empty mode check, which will always
   succeed.

   If this check succeeds because ACE4_DELETE was allowed the
   operation is allowed. If this check fails, the operation is
   denied.

6. If the sticky bit is set and the user doesn't own the parent
   directory AND doesn't own the target, the operation is denied.

7. If check 1 failed because mode bits wx were not allowed, the
   operation is denied.

8. If check 1 failed because ACE4_DELETE_CHILD was explicitly
   denied, the operation is denied.

9. Now we can check the special case documented in Section
   6.2.1.3.2. ACE4_DELETE vs. ACE4_DELETE_CHILD of RFC 3530 bis.
   Check if the parent directory allows ACE4_ADD_FILE | ACE4_EXECUTE.

   Rationale: ACE4_EXECUTE is required for this check for the same
   reason as in the other checks. This special case handles a situation
   where a server may have done a simplistic conversion of rwx mode
   permission to an ACL.

   If this test passes, the operation is allowed otherwise the operation
   is denied.

Signed-off-by: Frank S. Filz <ffilz@us.ibm.com>
Simplify use of cache_inode_rename

Callers should let cache_inode_rename, and ultimately FSAL_rename do the
checking of various things. This allows checks for things like empty
directories before overwrite to be done by the actual atomic operation
and not dependent on our cache.

Trim down when cache_inode_rename holds content_lock.

Also, for NFS v3, we do the get post op attr in the operation rather than
burdening cache_inode_rename with it.

All callers of cache_inode_lookup_impl needed to take content_lock around
the call. Instead of making callers do it, push the lock/unlock into
cache_inode_lookup_impl.

If todir/newname exists, we handle removing the cache entry AFTER the
FSAL_rename code, rather than using cache_inode_remove. This makes the
operation more atomic.

Signed-off-by: Frank S. Filz <ffilz@us.ibm.com>
Handle EROFS in GPFS by converting to ERR_FSAL_ROFS

Signed-off-by: Frank S. Filz <ffilz@us.ibm.com>
Use allowed/denied return from cache_inode_access_sw to simplify v3/4 ACCESS

By using the ability of cache_inode_access_sw to return the set of
allowed bits combined with the ability to ask for ACL evaluation to not
terminate on an applicable DENY ACE, we can make the access determination
for ACCESS with a single permission evaluation.

Also, provide a shared routine for performing the ACCESS logic.

Signed-off-by: Frank S. Filz <ffilz@us.ibm.com>