[Pkg-samba-maint] Bug#959211: utimensat system call no working properly on SMB shares

Alberto Sentieri 22t at tripolho.com
Thu Apr 30 21:59:56 BST 2020


Package: samba
Version: 4.5.16

The system call utimensat is failing when the protocol version is 2.0 or 
upper is selected.

The package samba version 2:4.5.16+dfsg-1+deb9u2 is the last one 
available for Debian stretch. Its interaction with Debian buster using 
cifs-utils version 2:6.8-2 is causing the particular system call to 
fail. In my case, the samba server is running under debian stretch, 
while the workstation is running debian buster. A simple program like 
</bin/cp -p> of </bin/mv> from a ext4 file system to the SMB file system 
will store the incorrect time stamp on the samba server.

/bin/cp program executes some code like this, before finishing:

write (fd, buffer, length);
utimensat (fd, NULL, timestamps, 0);
close (fd);

I create a C program which will execute this sequence of statements. 
Curiously the time stamp is correct for a small amount of time, and then 
it switches to the current time. The program, which I called x2, will be 
run by the following batch script:

#!/bin/bash
NAME='/samba_share/test2.txt'
rm -f "${NAME}"
ls -ls "${NAME}"
./x2 "${NAME}"
ls -ls "${NAME}"
sleep 1
ls -ls "${NAME}"

The result of running the script is:

$ ./script.sh
ls: cannot access '/samba_share/test2.txt': No such file or directory
0 -rwxr-xr-x 1 u1 u1 10 Feb  5  2017 /samba_share/test2.txt
1024 -rwxr-xr-x 1 u1 u1 10 Apr 30 16:33 /samba_share/test2.txt

As one can see, the file time stamp is correct just after x2 finishes, 
and it become incorrect one second later. If, while mounting the share 
with mount.cifs, I specify -o vers=1.0, then the problem does not 
happen, I mean, the time stamp will be the same (Feb 5 2017) just after 
x2 ends and 1 second after its end.

The program x2 uses the same sequence of commands that /bin/cp -p or 
/bin/mv uses. Here is its source code:

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/syscall.h>

static char *data = "test data\n";
static struct timespec timestamps [2] = {
     { 1588174263, 908624390 },
     { 1486350336, 481422339 }
};

int main (int argc, char **argv)
{
     int fd;

     if (argc > 1) {
         fd = openat (AT_FDCWD, argv [1], O_WRONLY|O_CREAT, 0666);
         if (fd >= 0) {
             write (fd, data, strlen (data));
             /* do not use glibc utimensat directly, it does not allow 
NULL as a second argument */
             syscall (SYS_utimensat, fd, NULL, timestamps, 0);
             close (fd);
             return 0;
         }
     }
     printf ("something went wrong\n");
     return 0;
}

it can be easily compiled by <gcc -o x2 x2.c>.

I used tcpdump to capture the traffic between the workstation running x2 
and the samba server. I noticed that gnome3 file manager works correctly 
even when a protocol referred as SMB2 by wireshark is used. I mean that 
a file copied from ext4 to smb by file manager has the correct time 
stamp under protocol version 2.0 and above, which does not happen with 
the x2 program displayed above.

Based on the network traffic, I have the impression that the gnome3 file 
manager uses a sequence like the one below:
write
close
open
utimensat
close

So, after the last write the file is closed and opened again before 
executing utimensat.



More information about the Pkg-samba-maint mailing list