Since 4.14 open_file() in source3/smbd/open.c has been restructured to use a function reopen_from_procfd(). This results in (when writing to an existing file) the following sequence of system calls:
fd = openat (AT_FDCWD, filename, O_RDONLY|O_NOFOLLOW);
new_fd = openat(AT_FDCWD, "/proc/self/fd/<fd>", O_RDWR|O_CREAT|O_NONBLOCK, 0744);
This works fine on Linux, but on NetBSD (and it seems FreeBSD and OpenBSD) the second openat() fails with an EEXIST.
The issue can be demonstrated by using notepad to edit an existing writable file on a samba share. Modify the file, at the point you try to "Save" you get a dialog box saying the file exists. The same works perfectly with 4.13.x.
Some discussion of the issue can be seen here:
The second openat() isn't specifying O_EXCL, so EEXIST would seem to be a kernel bug here.
The description of open error return codes says:
O_CREAT and O_EXCL are set, and the named file exists.
(In reply to Jeremy Allison from comment #1)
> The second openat() isn't specifying O_EXCL, so EEXIST would seem to be a
> kernel bug here.
You might consider that, but if so its a bug on all the BSD's
Yep, looks like a generic kernel bug in the *BSD's that they don't follow POSIX I'm afraid. You should log a bug with the OS's affected.
(In reply to Jeremy Allison from comment #3)
What if we just filter out the O_CREAT in this case? We know we're opening an existing file so we don't need to pass O_CREAT. Easy fix for the BSDs and not really a big heritage to carry along.
Yes, that might work. Worries me a bit though that the semantics around opening /proc/XX/fd's in the BSD's is not well defined though.
Having said that it's not well defined in Linux either, Linux is just the 800lb gorilla here.