Cope with a (non-security) open race we've had for ever as NTCreateX isn't atomic...
authorJeremy Allison <jra@samba.org>
Tue, 10 Jul 2012 17:15:07 +0000 (10:15 -0700)
committerJeremy Allison <jra@samba.org>
Tue, 10 Jul 2012 19:57:33 +0000 (21:57 +0200)
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

source3/smbd/open.c

index 79f830583688d1721b4eb7e66b5549a5a54360fc..0f4a5889995da1721e76b0df7f0ca7279a06c4b6 100644 (file)
@@ -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;