summaryrefslogtreecommitdiff
path: root/source3/smbd
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2012-07-10 10:15:07 -0700
committerJeremy Allison <jra@samba.org>2012-07-10 21:57:33 +0200
commit6d903bf1899987adaeaaf6608ac318aca4588590 (patch)
treef15b7a7807569754e0efa4893fc8934e04e50231 /source3/smbd
parent69a3e947b60397c9bb9175cf52fe009b6b057350 (diff)
downloadsamba-6d903bf1899987adaeaaf6608ac318aca4588590.tar.gz
samba-6d903bf1899987adaeaaf6608ac318aca4588590.tar.bz2
samba-6d903bf1899987adaeaaf6608ac318aca4588590.zip
Cope with a (non-security) open race we've had for ever as NTCreateX isn't atomic on POSIX.
On open without create, 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. Autobuild-User(master): Jeremy Allison <jra@samba.org> Autobuild-Date(master): Tue Jul 10 21:57:33 CEST 2012 on sn-devel-104
Diffstat (limited to 'source3/smbd')
-rw-r--r--source3/smbd/open.c25
1 files changed, 25 insertions, 0 deletions
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index 79f8305836..0f4a588999 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -1810,6 +1810,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
uint32 open_access_mask = access_mask;
NTSTATUS status;
char *parent_dir;
+ SMB_STRUCT_STAT saved_stat = smb_fname->st;
if (conn->printer) {
/*
@@ -2349,6 +2350,30 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
return fsp_open;
}
+ 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.
+ */
+ TALLOC_FREE(lck);
+ fd_close(fsp);
+ DEBUG(1,("open_file_ntcreate: file %s - dev/ino mismatch. "
+ "Old (dev=0x%llu, ino =0x%llu). "
+ "New (dev=0x%llu, ino=0x%llu). Failing open "
+ " with NT_STATUS_ACCESS_DENIED.\n",
+ smb_fname_str_dbg(smb_fname),
+ (unsigned long long)saved_stat.st_ex_dev,
+ (unsigned long long)saved_stat.st_ex_ino,
+ (unsigned long long)smb_fname->st.st_ex_dev,
+ (unsigned long long)smb_fname->st.st_ex_ino));
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
if (!file_existed) {
struct share_mode_entry *batch_entry = NULL;
struct share_mode_entry *exclusive_entry = NULL;