[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