"stat open" lseek(fd = -1)

Jeremy Allison jra at samba.org
Fri Mar 1 21:36:49 UTC 2019


On Wed, Feb 27, 2019 at 04:52:28PM +0100, David Disseldorp via samba-technical wrote:
> Hi Samba archaeologists,
> 
> Explicit "stat open" tracking was removed way back in 2002 with
> b9e91d2a8e41a43d7ebb7d7eed807a7d8de9b329. This change instead added a
> "fd == -1" check to the vfs_default lseek handler, which has remained to
> this day.
> Does anybody know whether this lseek(fd = -1) condition can still /
> could ever be triggered? If so, how?

Looking at current code in master, we have:

static off_t vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, off_t offset, int whence)
{
        off_t result = 0;

        START_PROFILE(syscall_lseek);

        /* Cope with 'stat' file opens. */
        if (fsp->fh->fd != -1)
                result = lseek(fsp->fh->fd, offset, whence);

        /*
         * We want to maintain the fiction that we can seek
         * on a fifo for file system purposes. This allows
         * people to set up UNIX fifo's that feed data to Windows
         * applications. JRA.
         */

        if((result == -1) && (errno == ESPIPE)) {
                result = 0;
                errno = 0;
        }

        END_PROFILE(syscall_lseek);
        return result;
}

fsp->fh->fd == -1 can certainly happen - inside source3/smbd/open.c
we have:

1378                 fsp->fh->fd = -1; /* What we used to call a stat open. */
1379                 if (!file_existed) {
1380                         /* File must exist for a stat open. */
1381                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1382                 }

which occurs on SMB2_CREATE with an access mask of FILE_READ_ATTRIBUTES
only.

So the only question is SMB_VFS_LSEEK still used as we now use pread
for everything (or we should).

$ git grep SMB_VFS_LSEEK gives:

docs-xml/Samba-Developers-Guide/vfs.xml:#define SMB_VFS_LSEEK(fsp, fd, offset, whence) \
source3/include/vfs_macros.h:#define SMB_VFS_LSEEK(fsp, offset, whence) \
source3/smbd/reply.c:           if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
source3/smbd/reply.c:                                   res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
source3/smbd/reply.c:           ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
source3/smbd/smb2_ioctl_filesys.c:              data_off = SMB_VFS_LSEEK(fsp, curr_off, SEEK_DATA);
source3/smbd/smb2_ioctl_filesys.c:              hole_off = SMB_VFS_LSEEK(fsp, data_off, SEEK_HOLE);
source3/torture/cmd_vfs.c:      pos = SMB_VFS_LSEEK(vfs->files[fd], offset, whence);

The calls inside smb2_ioctl_filesys.c are protected
by:

       /* READ_DATA permission is required */
        status = check_access_fsp(fsp, FILE_READ_DATA);

so they should be OK.

source3/torture/cmd_vfs.c is merely a test.

The calls in reply.c come from:

1). reply_lseek(), which doesn't check access permissions (so might
be called on a stat open).

2). reply_copy(), which opens src and dest as real, not stat
files.

So I think SMB1 with an SMBlseek call is the only possible
caller here.

Does that help ?



More information about the samba-technical mailing list