diff options
author | Michael Adam <obnox@samba.org> | 2014-09-10 00:31:25 +0200 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2014-09-10 19:24:13 +0200 |
commit | 8ae8c63da19459fd4f1166e11406da2c919b7ed0 (patch) | |
tree | 73ef9c54cd6c9926f3e2523c9d7c57d610f1ab42 | |
parent | 551ae16ab3be301ce5402e60f63f736960335d9f (diff) | |
download | samba-8ae8c63da19459fd4f1166e11406da2c919b7ed0.tar.gz samba-8ae8c63da19459fd4f1166e11406da2c919b7ed0.tar.xz samba-8ae8c63da19459fd4f1166e11406da2c919b7ed0.zip |
s3:smbd: fix a race in open code
The race is when a file vanishes between
existence check and acl check.
In this case, open_file_ncreate() returns
OBJECT_NAME_NOT_FOUND even if the create
was called with disposition OPEN_IF.
But in this case, the file should be created.
Signed-off-by: Michael Adam <obnox@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
-rw-r--r-- | source3/smbd/open.c | 59 |
1 files changed, 42 insertions, 17 deletions
diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 67ba25e254..a33cce19ad 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -819,24 +819,49 @@ static NTSTATUS open_file(files_struct *fsp, smb_fname, false, access_mask); - } else if (local_flags & O_CREAT){ - status = check_parent_access(conn, - smb_fname, - SEC_DIR_ADD_FILE); - } else { - /* File didn't exist and no O_CREAT. */ - return NT_STATUS_OBJECT_NAME_NOT_FOUND; + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("open_file: " + "smbd_check_access_rights " + "on file %s returned %s\n", + smb_fname_str_dbg(smb_fname), + nt_errstr(status))); + } + + if (!NT_STATUS_IS_OK(status) && + !NT_STATUS_EQUAL(status, + NT_STATUS_OBJECT_NAME_NOT_FOUND)) + { + return status; + } + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("open_file: " + "file %s vanished since we " + "checked for existence.\n", + smb_fname_str_dbg(smb_fname))); + file_existed = false; + SET_STAT_INVALID(fsp->fsp_name->st); + } } - if (!NT_STATUS_IS_OK(status)) { - DEBUG(10,("open_file: " - "%s on file " - "%s returned %s\n", - file_existed ? - "smbd_check_access_rights" : - "check_parent_access", - smb_fname_str_dbg(smb_fname), - nt_errstr(status) )); - return status; + + if (!file_existed) { + if (!(local_flags & O_CREAT)) { + /* File didn't exist and no O_CREAT. */ + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + + status = check_parent_access(conn, + smb_fname, + SEC_DIR_ADD_FILE); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("open_file: " + "check_parent_access on " + "file %s returned %s\n", + smb_fname_str_dbg(smb_fname), + nt_errstr(status) )); + return status; + } } } |