diff options
author | Jeremy Allison <jra@samba.org> | 2011-02-08 17:04:19 -0800 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2011-02-09 21:21:04 +0100 |
commit | 8c363e9252cfaeb1a7d30870e3a0d44cb9d8a39b (patch) | |
tree | a60b8fad7a189a9c56b5179ddf659682f9a9a67a /source3 | |
parent | 65e6dea73fe6b15171dfea5c620d37bab5e77483 (diff) | |
download | samba-8c363e9252cfaeb1a7d30870e3a0d44cb9d8a39b.tar.gz samba-8c363e9252cfaeb1a7d30870e3a0d44cb9d8a39b.tar.bz2 samba-8c363e9252cfaeb1a7d30870e3a0d44cb9d8a39b.zip |
Move to opening an fd on directory opens. Get more careful about symlink races.
Diffstat (limited to 'source3')
-rw-r--r-- | source3/smbd/open.c | 38 |
1 files changed, 37 insertions, 1 deletions
diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 2379b8ebb2..89d137506b 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2525,6 +2525,22 @@ static NTSTATUS mkdir_internal(connection_struct *conn, } /**************************************************************************** + Ensure we didn't get symlink raced on opening a directory. +****************************************************************************/ + +static bool check_same_stat(const SMB_STRUCT_STAT *sbuf1, + const SMB_STRUCT_STAT *sbuf2) +{ + if (sbuf1->st_ex_uid != sbuf2->st_ex_uid || + sbuf1->st_ex_gid != sbuf2->st_ex_gid || + sbuf1->st_ex_dev != sbuf2->st_ex_dev || + sbuf1->st_ex_ino != sbuf2->st_ex_ino) { + return false; + } + return true; +} + +/**************************************************************************** Open a directory from an NT SMB call. ****************************************************************************/ @@ -2726,6 +2742,10 @@ static NTSTATUS open_directory(connection_struct *conn, #ifdef O_DIRECTORY status = fd_open(conn, fsp, O_RDONLY|O_DIRECTORY, 0); +#else + /* POSIX allows us to open a directory with O_RDONLY. */ + status = fd_open(conn, fsp, O_RDONLY, 0); +#endif if (!NT_STATUS_IS_OK(status)) { DEBUG(5, ("open_directory: Could not open fd for " "%s (%s)\n", @@ -2734,7 +2754,23 @@ static NTSTATUS open_directory(connection_struct *conn, file_free(req, fsp); return status; } -#endif + + status = vfs_stat_fsp(fsp); + if (NT_STATUS_IS_OK(status)) { + fd_close(fsp); + file_free(req, fsp); + return status; + } + + /* Ensure there was no race condition. */ + if (!check_same_stat(&smb_dname->st, &fsp->fsp_name->st)) { + DEBUG(5,("open_directory: stat struct differs for " + "directory %s.\n", + smb_fname_str_dbg(smb_dname))); + fd_close(fsp); + file_free(req, fsp); + return NT_STATUS_ACCESS_DENIED; + } lck = get_share_mode_lock(talloc_tos(), fsp->file_id, conn->connectpath, smb_dname, &mtimespec); |