vfs_fruit: avoid dereferencing fsp->base_fsp in fruit_fstat_meta_stream()
authorRalph Boehme <slow@samba.org>
Fri, 30 Nov 2018 09:27:19 +0000 (10:27 +0100)
committerJeremy Allison <jra@samba.org>
Sun, 2 Dec 2018 06:52:34 +0000 (07:52 +0100)
This helps avoiding a NULL dereference on systems where additional
patches modify the following condition in open_file()

  if ((open_access_mask & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) ||
      (!file_existed && (local_flags & O_CREAT)) ||
      ((local_flags & O_TRUNC) == O_TRUNC) ) {

to

  if ((open_access_mask & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE|DELETE_ACCESS)) ||
      (!file_existed && (local_flags & O_CREAT)) ||
      ((local_flags & O_TRUNC) == O_TRUNC) ) {

Ie addtionally check open_access_mask against DELETE_ACCESS. As a result
opens with DELETE_ACCESS go through the code that does an fd_open() plus
a subsequent fstat().

That will trigger a crash in fruit_fstat_meta_stream() when a client
wants to delete a file for deletion. When we open base file for delete,
we call open_streams_for_delete() which internally calls create-file
with NTCREATEX_OPTIONS_PRIVATE_STREAM_DELETE which prevents opening of
the base_fsp. Voila, combined with the change described above you get a
NULL deref.

Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
Autobuild-User(master): Jeremy Allison <jra@samba.org>
Autobuild-Date(master): Sun Dec  2 07:52:34 CET 2018 on sn-devel-144

source3/modules/vfs_fruit.c

index 50b6fac8b95fa2666f9fcb940fd521dfad6b01ea..19101efba740ce6de504cc97c2219add7101c34d 100644 (file)
@@ -5204,6 +5204,7 @@ static int fruit_fstat_meta_stream(vfs_handle_struct *handle,
                                   SMB_STRUCT_STAT *sbuf)
 {
        struct fio *fio = (struct fio *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
+       struct smb_filename smb_fname;
        ino_t ino;
        int ret;
 
@@ -5223,11 +5224,15 @@ static int fruit_fstat_meta_stream(vfs_handle_struct *handle,
                return 0;
        }
 
-       ret = fruit_stat_base(handle, fsp->base_fsp->fsp_name, false);
+       smb_fname = (struct smb_filename) {
+               .base_name = fsp->fsp_name->base_name,
+       };
+
+       ret = fruit_stat_base(handle, &smb_fname, false);
        if (ret != 0) {
                return -1;
        }
-       *sbuf = fsp->base_fsp->fsp_name->st;
+       *sbuf = smb_fname.st;
 
        ino = fruit_inode(sbuf, fsp->fsp_name->stream_name);