Changing smb_filename->base_name in VFS module.

Vadim Lazovskiy vadim.lazovskiy at gmail.com
Wed Aug 29 11:35:51 UTC 2018


Hello.

I've encountered an issue after upgrading samba 3.6 to 4.5.
My VFS module stopped working as expected.

Briefly, module implements caching on SSD by searching file in several
configured locations on file open:

static int ssdcache_open(vfs_handle_struct *handle, struct smb_filename
*smb_fname,
    files_struct *fsp, int flags, mode_t mode)
{
        ...
        ...

        /* Calculate maximum basename length */
        max_len = 0;
        for (i = 0; cache_paths[i]; i++) {
                len = strlen(cache_paths[i]);

                if(len > max_len) {
                        max_len = len;
                }
        }

        max_len += strlen(smb_fname->base_name) + 2; // for slash and \0
        new_base_name = talloc_zero_size(talloc_tos(), max_len);

        if (new_base_name == NULL) {
                errno = ENOMEM;
                return -1;
        }

        /* Allocate new smb_filename structure */
        smb_fname_new = synthetic_smb_fname(talloc_tos(), new_base_name,
NULL, NULL, smb_fname->flags);

        if (smb_fname_new == NULL) {
                errno = ENOMEM;
                return -1;
        }

        for (i = 0; cache_paths[i]; i++) {
                strlcat(smb_fname_new->base_name, cache_paths[i], max_len);
                strlcat(smb_fname_new->base_name, "/", max_len);
                strlcat(smb_fname_new->base_name, smb_fname->base_name,
max_len);

                if (SMB_VFS_STAT(handle->conn, smb_fname_new) == 0) {
                        break;
                }

                *smb_fname_new->base_name = '\0';
        }

        if (*smb_fname_new->base_name == '\0') {
                strlcat(smb_fname_new->base_name, smb_fname->base_name,
max_len);
        }

        return SMB_VFS_NEXT_OPEN(handle, smb_fname_new, fsp, flags, mode);
}

After some debugging I found out the point where I get ACCESS_DENIED:
static NTSTATUS open_file_ntcreate
in source3/smbd/open.c:

        if (file_existed && !check_same_dev_ino(&saved_stat,
&smb_fname->st)) {
                /*
                 * The file did exist, but some other (local or NFS)
                 * process either renamed/unlinked and re-created the
                 * file with different dev/ino after we walked the path,
                 * but before we did the open. We could retry the
                 * open but it's a rare enough case it's easier to
                 * just fail the open to prevent creating any problems
                 * in the open file db having the wrong dev/ino key.
                 */
                fd_close(fsp);

This seems reasonable for sure because original file is not the same as
cached file.
Could you please explain how should I change my module implementation to
mitigate this issue.
Thank you!

-- 
WBR,
Vadim Lazovskiy


More information about the samba-technical mailing list