mirror of
https://github.com/samba-team/samba.git
synced 2025-01-11 05:18:09 +03:00
smbd: reuse smb_fname->fsp in create_file_default()
This is the big bang for the internal pathref fsps: up to this point the pathref fsps were lingering around unused inside smb_fname->fsp. With this change, the internal fsp will be the one that is going to be returned from SMB_VFS_CREATE_FILE() if the client requested access mask matches the criteria in open_file(): uint32_t need_fd_mask = FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_EXECUTE | WRITE_DAC_ACCESS | WRITE_OWNER_ACCESS | SEC_FLAG_SYSTEM_SECURITY | READ_CONTROL_ACCESS; As long as the client doesn't request any of the access rights listed above, we reuse the smb_fname->fsp, otherwise we close the smb_fname->fsp and call fd_open() to open a new fsp. In the future we can remove the four non-IO related access rights from the list: WRITE_DAC_ACCESS | WRITE_OWNER_ACCESS | SEC_FLAG_SYSTEM_SECURITY | READ_CONTROL_ACCESS Signed-off-by: Ralph Boehme <slow@samba.org> Reviewed-by: Jeremy Allison <jra@samba.org>
This commit is contained in:
parent
c21890d128
commit
d00d09fdcf
@ -1366,6 +1366,16 @@ static NTSTATUS open_file(files_struct *fsp,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Close the existing pathref fd and set fsp_flags.is_pathref to
|
||||
* false so we get a full fd this time.
|
||||
*/
|
||||
status = fd_close(fsp);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
fsp->fsp_flags.is_pathref = false;
|
||||
|
||||
/*
|
||||
* Actually do the open - if O_TRUNC is needed handle it
|
||||
* below under the share mode lock.
|
||||
@ -1468,6 +1478,33 @@ static NTSTATUS open_file(files_struct *fsp,
|
||||
return NT_STATUS_OBJECT_PATH_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (!fsp->fsp_flags.is_pathref) {
|
||||
/*
|
||||
* There is only one legit case where end up here:
|
||||
* openat_pathref_fsp() failed to open a symlink, so the
|
||||
* fsp was created by fsp_new() which doesn't set
|
||||
* is_pathref. Other then that, we should always have a
|
||||
* pathref fsp at this point. The subsequent checks
|
||||
* assert this.
|
||||
*/
|
||||
if (!(smb_fname->flags & SMB_FILENAME_POSIX_PATH)) {
|
||||
DBG_ERR("[%s] is not a POSIX pathname\n",
|
||||
smb_fname_str_dbg(smb_fname));
|
||||
return NT_STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
if (!S_ISLNK(smb_fname->st.st_ex_mode)) {
|
||||
DBG_ERR("[%s] is not a symlink\n",
|
||||
smb_fname_str_dbg(smb_fname));
|
||||
return NT_STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
if (fsp_get_pathref_fd(fsp) != -1) {
|
||||
DBG_ERR("fd for [%s] is not -1: fd [%d]\n",
|
||||
smb_fname_str_dbg(smb_fname),
|
||||
fsp_get_pathref_fd(fsp));
|
||||
return NT_STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
status = smbd_check_access_rights(conn,
|
||||
conn->cwd_fsp,
|
||||
smb_fname,
|
||||
@ -4486,6 +4523,11 @@ static NTSTATUS open_directory(connection_struct *conn,
|
||||
}
|
||||
}
|
||||
|
||||
status = fd_close(fsp);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup the files_struct for it.
|
||||
*/
|
||||
@ -4520,6 +4562,16 @@ static NTSTATUS open_directory(connection_struct *conn,
|
||||
*/
|
||||
mtimespec = make_omit_timespec();
|
||||
|
||||
/*
|
||||
* Close the existing pathref fd and set fsp_flags.is_pathref to
|
||||
* false so we get a full fd this time.
|
||||
*/
|
||||
status = fd_close(fsp);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
fsp->fsp_flags.is_pathref = false;
|
||||
|
||||
/* POSIX allows us to open a directory with O_RDONLY. */
|
||||
flags = O_RDONLY;
|
||||
#ifdef O_DIRECTORY
|
||||
@ -5658,14 +5710,45 @@ static NTSTATUS create_file_unixpath(connection_struct *conn,
|
||||
}
|
||||
}
|
||||
|
||||
status = file_new(req, conn, &fsp);
|
||||
if(!NT_STATUS_IS_OK(status)) {
|
||||
goto fail;
|
||||
/*
|
||||
* Now either reuse smb_fname->fsp or allocate a new fsp if
|
||||
* smb_fname->fsp is NULL. The latter will be the case when processing a
|
||||
* request to create a file that doesn't exist.
|
||||
*/
|
||||
if (smb_fname->fsp != NULL) {
|
||||
fsp = smb_fname->fsp;
|
||||
|
||||
/*
|
||||
* Unlink the fsp from the smb_fname so the fsp is not
|
||||
* autoclosed by the smb_fname pathref fsp talloc destructor.
|
||||
*/
|
||||
smb_fname_fsp_unlink(smb_fname);
|
||||
|
||||
status = fsp_bind_smb(fsp, req);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
file_free(req, fsp);
|
||||
return status;
|
||||
}
|
||||
|
||||
if (fsp->base_fsp != NULL) {
|
||||
fd_close(fsp->base_fsp);
|
||||
file_free(NULL, fsp->base_fsp);
|
||||
fsp->base_fsp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
status = fsp_set_smb_fname(fsp, smb_fname);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
goto fail;
|
||||
if (fsp == NULL) {
|
||||
/* Creating file */
|
||||
status = file_new(req, conn, &fsp);
|
||||
if(!NT_STATUS_IS_OK(status)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
status = fsp_set_smb_fname(fsp, smb_fname);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
goto fail;
|
||||
}
|
||||
fsp->fsp_name->fsp = fsp;
|
||||
}
|
||||
|
||||
if (base_fsp) {
|
||||
|
Loading…
Reference in New Issue
Block a user