Bug#483507: mount.cifs: brl option does not produce documented semantics for fcntl(F_SETLK)

2008-05-29 Thread Daniel Kahn Gillmor
On Thu 2008-05-29 01:12:23 -0400, Daniel Kahn Gillmor wrote:

 Attached is the test program that displays this behavior.  It should
 fail with write lock failed: Permission denied when used on a file
 on a CIFS mount, and it has succeeded quietly on every other
 filesystem i've tried.

In particular, the test program even succeeds (with the exception of
NFSv3) on non-cifs filesystems mounted with the mand option, and
with files whose mode was set with chmod g+s,g-x, which i believe is
the documented way to turn on mandatory locking [0].

here's it working on a tmpfs mounted with mand:

[0 [EMAIL PROTECTED] ~]$ grep mnt /proc/mounts 
/root/foo /mnt tmpfs rw,mand 0 0
[0 [EMAIL PROTECTED] ~]$ echo -n a   /mnt/foo
[0 [EMAIL PROTECTED] ~]$ chmod g+s,g-x /mnt/foo
[0 [EMAIL PROTECTED] ~]$ ls -la /mnt/foo 
-rw-r-Sr-- 1 dkg dkg 1 2008-05-29 15:56 /mnt/foo
[0 [EMAIL PROTECTED] ~]$ ~/src/cmrg/test/testlocking/testlocking /mnt/foo 
[0 [EMAIL PROTECTED] ~]$ 

and here's an ext3 fs mounted with mand:

[0 [EMAIL PROTECTED] ~]$ grep mnt /proc/mounts 
/dev/mapper/squeak0-tester /mnt ext3 rw,mand,data=ordered 0 0
[0 [EMAIL PROTECTED] ~]$ echo -n a   /mnt/foo
[0 [EMAIL PROTECTED] ~]$ chmod g+s,g-x /mnt/foo
[0 [EMAIL PROTECTED] ~]$ ls -la /mnt/foo 
-rw-r-Sr-- 1 dkg dkg 1 2008-05-29 15:59 /mnt/foo
[0 [EMAIL PROTECTED] ~]$ ~/src/cmrg/test/testlocking/testlocking /mnt/foo 
[0 [EMAIL PROTECTED] ~]$ 

and vfat (i couldn't set the group setuid bit on vfat, but the test
program still worked):

[0 [EMAIL PROTECTED] ~]$ grep mnt /proc/mounts 
/dev/mapper/squeak0-tester /mnt vfat 
rw,mand,uid=1000,gid=1000,fmask=0033,dmask=0022,codepage=cp437,iocharset=iso8859-1
 0 0
[0 [EMAIL PROTECTED] ~]$ echo -n a   /mnt/foo
[0 [EMAIL PROTECTED] ~]$ chmod g+s,g-x /mnt/foo
chmod: changing permissions of `/mnt/foo': Operation not permitted
[1 [EMAIL PROTECTED] ~]$ ~/src/cmrg/test/testlocking/testlocking /mnt/foo 
[0 [EMAIL PROTECTED] ~]$ 

and xfs with mand:

[0 [EMAIL PROTECTED] ~]$ grep mnt /proc/mounts 
/dev/mapper/squeak0-tester /mnt xfs rw,mand,ikeep,noquota 0 0
[0 [EMAIL PROTECTED] ~]$ echo -n a   /mnt/foo
[0 [EMAIL PROTECTED] ~]$ chmod g+s,g-x /mnt/foo
[0 [EMAIL PROTECTED] ~]$ ls -la /mnt/foo 
-rw-r-Sr-- 1 dkg dkg 1 2008-05-29 16:07 /mnt/foo
[0 [EMAIL PROTECTED] ~]$ ~/src/cmrg/test/testlocking/testlocking /mnt/foo 
[0 [EMAIL PROTECTED] ~]$ 


However, on NFSv3 (exported from an up-to-date etch nfs-kernel-server
with (rw,subtree_check), and mounted with all kinds of different
options (with and without mand), my little test program continually
fails *at the read lock* stage if the file is mode g+s,g-x:

[0 [EMAIL PROTECTED] ~]$ grep mnt /proc/mounts 
bob:/srv/dmz /mnt nfs 
rw,vers=3,rsize=32768,wsize=32768,hard,nointr,proto=tcp,timeo=600,retrans=2,sec=sys,addr=192.168.2.99
 0 0
[0 [EMAIL PROTECTED] ~]$ ls -la  /mnt/foo
-rw-r--r-- 1 dkg dkg 1 2008-05-29 17:04 /mnt/foo
[0 [EMAIL PROTECTED] ~]$ ~/src/cmrg/test/testlocking/testlocking /mnt/foo 
[0 [EMAIL PROTECTED] ~]$ chmod g+x /mnt/foo
[0 [EMAIL PROTECTED] ~]$ ~/src/cmrg/test/testlocking/testlocking /mnt/foo 
[0 [EMAIL PROTECTED] ~]$ chmod g+s /mnt/foo
[0 [EMAIL PROTECTED] ~]$ ~/src/cmrg/test/testlocking/testlocking /mnt/foo 
[0 [EMAIL PROTECTED] ~]$ chmod g-x /mnt/foo
[0 [EMAIL PROTECTED] ~]$ ~/src/cmrg/test/testlocking/testlocking /mnt/foo 
read lock failed: No locks available
[1 [EMAIL PROTECTED] ~]$ 

so, interestingly, the nfs client appears to think that the mode bits
alone are sufficient to indicate mandatory (as opposed to advisory)
locking, and it apparently knows that NFSv3 is incapable of providing
mandatory locks.

At any rate, the behavior of cifs with the brl option is clearly
divergent from the behavior of the other filesystems.

  --dkg

[0] from fcntl(2):

   To  make use of mandatory locks, mandatory locking must be enabled both
   on the file system that contains the file to be locked, and on the file
   itself.   Mandatory  locking  is enabled on a file system using the -o
   mand option to mount(8), or the MS_MANDLOCK flag for mount(2).  Manda-
   tory locking is enabled on a file by disabling group execute permission
   on the file and enabling the set-group-ID permission bit (see  chmod(1)
   and chmod(2)).


pgpUoci7qyTPA.pgp
Description: PGP signature


Bug#483507: mount.cifs: brl option does not produce documented semantics for fcntl(F_SETLK)

2008-05-28 Thread Daniel Kahn Gillmor
Package: smbfs
Version: 1:3.0.28a-3
Severity: normal

-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

In http://bugs.debian.org/483502, i wrote:

 locking a certain range of a file with a read lock and then locking
 the same range with a write lock gives an error when a CIFS share is
 mounted with brl.  This doesn't make much sense to me, but i'm
 willing to accept it as intended for now.

After doing more reading, it still doesn't make sense: the filesystem
is behaving with non-POSIX semantics, which causes breakage in other
packages (for example, see http://bugs.debian.org/483216).

In particular, the semantics specified by fcntl(2) for setting a lock
state:

  A single process can hold only one type of lock on a file
  region; if a new lock is applied to an already-locked region,
  then the existing lock is converted to the new lock type.

(this appears to be true for both advisory *and* mandatory locks)

However, when accessing a CIFS share mounted with with brl (standard
CIFS-style server-side byte-range locking), converting a read lock to
a write lock gives a permission denied error.

The same error does *not* occur when using the CIFS share mounted with
nobrl, or when attempting the same series of operations against a
tmpfs (whether or not the tmpfs is mounted with -o mand).  Shouldn't
mount.cifs do its best to mimic the expected semantics of
fcntl(F_SETLK) using the underlying CIFS semantics?  If CIFS has no
explicit lock upgrade/downgrade operations, as long as the protocol is
capable of dropping a lock and acquiring a new one, these two
primitives used in sequence could be used to emulate a lock
upgrade/downgrade.

Attached is the test program that displays this behavior.  It should
fail with write lock failed: Permission denied when used on a file
on a CIFS mount, and it has succeeded quietly on every other
filesystem i've tried.  the latest version of the source can be found
at
http://cmrg.fifthhorseman.net/browser/trunk/test/testlocking/testlocking.c

Thanks for maintaining samba in debian!

Regards,

--dkg

- -- System Information:
Debian Release: lenny/sid
  APT prefers testing
  APT policy: (500, 'testing'), (200, 'unstable'), (101, 'experimental')
Architecture: i386 (i686)

Kernel: Linux 2.6.24-1-686 (SMP w/1 CPU core)
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/bash

Versions of packages smbfs depends on:
ii  libc62.7-10  GNU C Library: Shared libraries
ii  netbase  4.32Basic TCP/IP networking system
ii  samba-common 1:3.0.28a-3 Samba common files used by both th

smbfs recommends no packages.

- -- no debconf information

-BEGIN PGP SIGNATURE-
Version: GnuPG v1.4.6 (GNU/Linux)

iQIVAwUBSD47NszS7ZTSFznpAQIv4A/+O3ofw/kIzXJuvtertKI2nPqcsiOT27Fl
Pf7f1Mp+qhEeVrbZ6ESZA1SSuHBeT7JKYurrsw/z7y2D6nuapqqR6DXihj9QdbIi
gZoHZhVH1tCDeuAv9pR8avV8QHXcE8BSu0vZQuaMI/zLbkxln4qbDCtOPvAmowfr
vBIKsE9Zb/hYdFCkdYP2lYGXVfTlZo26JMNKsrA+jezLk1xBPmT/UtpvD1L//19+
CNlPfTqsqAksFAqLD6TLUVgLeNv1MiMGEj9sOGiGuDXvixeCcGleemQkmbKm/ihl
viXBHYh2M9ZZtKU3I2R0tnKrwCnL1ZsU/QQb70/d3fKhJeoQrsd9jgnS0jeArLLy
RwTSWnvj1WcxId0+JT4nL6gvRNLs64fyI6QzZ/6eLHrPBQtRxEf055I2UvjO81tE
n9YA0nfIxeyeGc1+XqnE4FUmY0LEhuJT48PbsrHP5WT4XCb3mIhKg42EJ+r6WQIn
G8I0TzMZsDxXZ6vYnd4BfNKhpf0qSn2CoEcj1Jtg4lovLltc5j0VWji4iuXaLiJ3
o5rao7F0yk12iomSE2XE7gIwU7YUOHGzcqx011cDNmv/z2Vdr8tFCB8Svh7Y6VMA
0LcDH8LLVGSlXneP5frzUimBS1A6ogu8ocYxhIp4ww60Lqq1TOOIebj2m/znaaj4
CWuXI6GnK+w=
=y3y4
-END PGP SIGNATURE-
/* grep open(2) for O_LARGEFILE to explain this: */
#define _FILE_OFFSET_BITS 64

#include sys/types.h
#include sys/stat.h
#include unistd.h
#include fcntl.h
#include stdio.h

/* 
   Author: Daniel Kahn Gillmor [EMAIL PROTECTED]
   Date: 2008-05-28

   This is a demonstration program for testing
   http://bugs.debian.org/483216
 */

int main(int argc, char* argv[]) {
  struct flock flock;
  int fd;

  flock.l_whence=SEEK_SET;

  /* open file, get file descriptor */
  fd = open(argv[1], O_RDWR|O_CREAT, 0644);

  fcntl(fd, F_SETFD, FD_CLOEXEC | fcntl(fd, F_GETFD));

  /* get read lock: */
  flock.l_type=F_RDLCK;
  flock.l_start=0;
  flock.l_len = 1;
  if (0 != fcntl(fd, F_SETLK64, flock)) {
perror(read lock failed);
return 1;
  }

  /* get write lock for same range: */
  flock.l_type=F_WRLCK;
  if (0 != fcntl(fd, F_SETLK64, flock)) {
/* fails here when used on CIFS share mounted without nobrl option */
perror(write lock failed);
return 1;
  }

  return 0;
}