From: Jeremy Allison Date: Tue, 10 Jul 2012 17:15:07 +0000 (-0700) Subject: Cope with a (non-security) open race we've had for ever as NTCreateX isn't atomic... X-Git-Url: http://git.samba.org/?p=mat%2Fsamba.git;a=commitdiff_plain;h=6d903bf1899987adaeaaf6608ac318aca4588590 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 Autobuild-Date(master): Tue Jul 10 21:57:33 CEST 2012 on sn-devel-104 --- 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;