From d4481329438d27a23ded85f01f5cf06725221d0e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 21 Nov 2008 12:32:11 -0800 Subject: [PATCH] Second part of the fix for bug #5903 - vfs_streams_xattr breaks contents of the file Jeremy. --- source/configure.in | 2 +- source/modules/vfs_streams_xattr.c | 61 +++++++++++++++++++++++++++++++++++++- source/smbd/open.c | 59 +++++++++++++++++++++++++++--------- 3 files changed, 106 insertions(+), 16 deletions(-) diff --git a/source/configure.in b/source/configure.in index 64a4681b5f3..733c31e975a 100644 --- a/source/configure.in +++ b/source/configure.in @@ -404,7 +404,7 @@ dnl These have to be built static: default_static_modules="pdb_smbpasswd pdb_tdbsam rpc_lsarpc rpc_samr rpc_winreg rpc_initshutdown rpc_dssetup rpc_wkssvc rpc_svcctl2 rpc_ntsvcs2 rpc_netlogon rpc_netdfs rpc_srvsvc rpc_spoolss rpc_eventlog2 auth_sam auth_unix auth_winbind auth_server auth_domain auth_builtin vfs_default nss_info_template" dnl These are preferably build shared, and static if dlopen() is not available -default_shared_modules="vfs_recycle vfs_audit vfs_extd_audit vfs_full_audit vfs_netatalk vfs_fake_perms vfs_default_quota vfs_readonly vfs_cap vfs_expand_msdfs vfs_shadow_copy vfs_shadow_copy2 charset_CP850 charset_CP437 auth_script vfs_readahead vfs_xattr_tdb vfs_streams_xattr vfs_smb_traffic_analyzer" +default_shared_modules="vfs_recycle vfs_audit vfs_extd_audit vfs_full_audit vfs_netatalk vfs_fake_perms vfs_default_quota vfs_readonly vfs_cap vfs_expand_msdfs vfs_shadow_copy vfs_shadow_copy2 charset_CP850 charset_CP437 auth_script vfs_readahead vfs_xattr_tdb vfs_streams_xattr vfs_streams_depot vfs_smb_traffic_analyzer" if test "x$developer" = xyes; then default_static_modules="$default_static_modules rpc_rpcecho" diff --git a/source/modules/vfs_streams_xattr.c b/source/modules/vfs_streams_xattr.c index b74c4f7902e..9df88e5e19b 100644 --- a/source/modules/vfs_streams_xattr.c +++ b/source/modules/vfs_streams_xattr.c @@ -624,7 +624,7 @@ static ssize_t streams_xattr_pread(vfs_handle_struct *handle, (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp); struct ea_struct ea; NTSTATUS status; - size_t length, overlap; + size_t length, overlap; if (sio == NULL) { return SMB_VFS_NEXT_PREAD(handle, fsp, data, n, offset); @@ -651,6 +651,63 @@ static ssize_t streams_xattr_pread(vfs_handle_struct *handle, return overlap; } +static int streams_xattr_ftruncate(struct vfs_handle_struct *handle, + struct files_struct *fsp, + SMB_OFF_T offset) +{ + int ret; + uint8 *tmp; + struct ea_struct ea; + NTSTATUS status; + struct stream_io *sio = + (struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp); + + DEBUG(10, ("streams_xattr_ftruncate called for file %s offset %.0f\n", + fsp->fsp_name, + (double)offset )); + + if (sio == NULL) { + return SMB_VFS_NEXT_FTRUNCATE(handle, fsp, offset); + } + + status = get_ea_value(talloc_tos(), handle->conn, fsp->base_fsp, + sio->base, sio->xattr_name, &ea); + if (!NT_STATUS_IS_OK(status)) { + return -1; + } + + tmp = TALLOC_REALLOC_ARRAY(talloc_tos(), ea.value.data, uint8, + offset + 1); + + if (tmp == NULL) { + TALLOC_FREE(ea.value.data); + errno = ENOMEM; + return -1; + } + + /* Did we expand ? */ + if (ea.value.length < offset + 1) { + memset(&tmp[ea.value.length], '\0', + offset + 1 - ea.value.length); + } + + ea.value.data = tmp; + ea.value.length = offset + 1; + ea.value.data[offset] = 0; + + ret = SMB_VFS_SETXATTR(fsp->conn, fsp->base_fsp->fsp_name, + sio->xattr_name, + ea.value.data, ea.value.length, 0); + + TALLOC_FREE(ea.value.data); + + if (ret == -1) { + return -1; + } + + return 0; +} + /* VFS operations structure */ static vfs_op_tuple streams_xattr_ops[] = { @@ -672,6 +729,8 @@ static vfs_op_tuple streams_xattr_ops[] = { SMB_VFS_LAYER_TRANSPARENT}, {SMB_VFS_OP(streams_xattr_unlink), SMB_VFS_OP_UNLINK, SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(streams_xattr_ftruncate), SMB_VFS_OP_FTRUNCATE, + SMB_VFS_LAYER_TRANSPARENT}, {SMB_VFS_OP(streams_xattr_streaminfo), SMB_VFS_OP_STREAMINFO, SMB_VFS_LAYER_OPAQUE}, {SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP} diff --git a/source/smbd/open.c b/source/smbd/open.c index 6ba6df2bc20..298d5e62628 100644 --- a/source/smbd/open.c +++ b/source/smbd/open.c @@ -2774,10 +2774,42 @@ NTSTATUS create_file_unixpath(connection_struct *conn, * Ordinary file case. */ - status = open_file_ntcreate( - conn, req, fname, &sbuf, access_mask, share_access, - create_disposition, create_options, file_attributes, - oplock_request, &info, &fsp); + if (base_fsp) { + /* + * We're opening the stream element of a base_fsp + * we already opened. We need to initialize + * the fsp first, and set up the base_fsp pointer. + */ + status = file_new(conn, &fsp); + if(!NT_STATUS_IS_OK(status)) { + goto fail; + } + + fsp->base_fsp = base_fsp; + + status = open_file_ntcreate_internal(conn, + req, + fname, + &sbuf, + access_mask, + share_access, + create_disposition, + create_options, + file_attributes, + oplock_request, + &info, + fsp); + + if(!NT_STATUS_IS_OK(status)) { + file_free(fsp); + fsp = NULL; + } + } else { + status = open_file_ntcreate( + conn, req, fname, &sbuf, access_mask, share_access, + create_disposition, create_options, file_attributes, + oplock_request, &info, &fsp); + } if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_IS_A_DIRECTORY)) { @@ -2804,6 +2836,8 @@ NTSTATUS create_file_unixpath(connection_struct *conn, goto fail; } + fsp->base_fsp = base_fsp; + /* * According to the MS documentation, the only time the security * descriptor is applied to the opened file is iff we *created* the @@ -2881,16 +2915,6 @@ NTSTATUS create_file_unixpath(connection_struct *conn, DEBUG(10, ("create_file_unixpath: info=%d\n", info)); - /* - * Set fsp->base_fsp late enough that we can't "goto fail" anymore. In - * the fail: branch we call close_file(fsp, ERROR_CLOSE) which would - * also close fsp->base_fsp which we have to also do explicitly in - * this routine here, as not in all "goto fail:" we have the fsp set - * up already to be initialized with the base_fsp. - */ - - fsp->base_fsp = base_fsp; - *result = fsp; if (pinfo != NULL) { *pinfo = info; @@ -2909,6 +2933,13 @@ NTSTATUS create_file_unixpath(connection_struct *conn, DEBUG(10, ("create_file_unixpath: %s\n", nt_errstr(status))); if (fsp != NULL) { + if (base_fsp && fsp->base_fsp == base_fsp) { + /* + * The close_file below will close + * fsp->base_fsp. + */ + base_fsp = NULL; + } close_file(fsp, ERROR_CLOSE); fsp = NULL; } -- 2.11.4.GIT