s3: VFS: vfs_fruit. Fix the NetAtalk deny mode compatibility code.
This exhibited itself as a problem with OFD locks reported
as:
BUG: https://bugzilla.samba.org/show_bug.cgi?id=13770
However, due to underlying bugs in the vfs_fruit
code the file locks were not being properly applied.
There are two problems in fruit_check_access().
Problem #1:
Inside fruit_check_access() we have:
flags = fcntl(fsp->fh->fd, F_GETFL);
..
if (flags & (O_RDONLY|O_RDWR)) {
We shouldn't be calling fcntl(fsp->fh->fd, ..) directly.
fsp->fh->fd may be a made up number from an underlying
VFS module that has no meaning to a system call.
Secondly, in all POSIX systems - O_RDONLY is defined as
*zero*. O_RDWR = 2.
Which means flags & (O_RDONLY|O_RDWR) becomes (flags & 2),
not what we actually thought.
Problem #2:
deny_mode is *not* a bitmask, it's a set of discrete values.
Inside fruit_check_access() we have:
if (deny_mode & DENY_READ) and also (deny_mode & DENY_WRITE)
However, deny modes are defined as:
/* deny modes */
define DENY_DOS 0
define DENY_ALL 1
define DENY_WRITE 2
define DENY_READ 3
define DENY_NONE 4
define DENY_FCB 7
so if deny_mode = DENY_WRITE, or if deny_mode = DENY_READ
then it's going to trigger both the if (deny_mode & DENY_READ)
*and* the (deny_mode & DENY_WRITE) conditions.
These problems allowed the original test test_netatalk_lock code to
pass (which was added for BUG: https://bugzilla.samba.org/show_bug.cgi?id=13584
to demonstrate the lock order violation).
This patch refactors the fruit_check_access()
code to be much simpler (IMHO) to understand.
Firstly, pass in the SMB1/2 share mode, not old
DOS deny modes.
Secondly, read all the possible NetAtalk locks
into local variables:
netatalk_already_open_for_reading
netatalk_already_open_with_deny_read
netatalk_already_open_for_writing
netatalk_already_open_with_deny_write
Then do the share mode/access mode checks
with the requested values against any stored
netatalk modes/access modes.
Finally add in NetATalk compatible locks
that represent our share modes/access modes
into the file, with an early return if we don't
have FILE_READ_DATA (in which case we can't
write locks anyway).
The patch is easier to understand by looking
at the completed patched fruit_check_access()
function, rather than trying to look at the
diff.
Signed-off-by: Jeremy Allison <jra@samba.org>
Reviewed-by: Ralph Böhme <slow@samba.org>
(cherry picked from commit
3204dc66f6801a7c8c87c48f601e0ebdee9e3d40)