diff options
author | Jeremy Allison <jra@samba.org> | 2021-06-23 10:43:51 -0700 |
---|---|---|
committer | Ralph Boehme <slow@samba.org> | 2021-06-25 15:53:31 +0000 |
commit | 243bce415830885a70ff0aba0b829291bb0dc760 (patch) | |
tree | 4574230ef9b16641dbad772dfd4f29ed5a8ba4f8 /source3 | |
parent | d2b78728514a68df29efc483ede90cd804880685 (diff) | |
download | samba-243bce415830885a70ff0aba0b829291bb0dc760.tar.gz |
s3: VFS: fake_acls: In fake_acls_stat() - use openat_pathref_fsp() to always get a pathref fsp.
Add a recursion guard so that openat_pathref_fsp() doesn't
end up recursing into itself when it calls SMB_VFS_STAT().
We now always have a valid fsp inside fake_acls_stat().
Signed-off-by: Jeremy Allison <jra@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
Diffstat (limited to 'source3')
-rw-r--r-- | source3/modules/vfs_fake_acls.c | 67 |
1 files changed, 62 insertions, 5 deletions
diff --git a/source3/modules/vfs_fake_acls.c b/source3/modules/vfs_fake_acls.c index c675479cea7..5dd3cddccb7 100644 --- a/source3/modules/vfs_fake_acls.c +++ b/source3/modules/vfs_fake_acls.c @@ -112,14 +112,27 @@ static int fake_acls_stat(vfs_handle_struct *handle, struct smb_filename *smb_fname) { int ret = -1; + static bool in_openat_pathref_fsp = false; ret = SMB_VFS_NEXT_STAT(handle, smb_fname); if (ret == 0) { - struct smb_filename smb_fname_base = { - .base_name = smb_fname->base_name - }; + struct smb_filename *smb_fname_cp = NULL; struct files_struct *fsp = NULL; + /* + * Ensure openat_pathref_fsp() + * can't recurse into fake_acls_stat(). + * openat_pathref_fsp() doesn't care + * about the uid/gid values, it only + * wants a valid/invalid stat answer + * and we know smb_fname exists as + * the SMB_VFS_NEXT_STAT() returned + * zero above. + */ + if (in_openat_pathref_fsp) { + return 0; + } + if (smb_fname->fsp != NULL) { fsp = smb_fname->fsp; if (fsp->base_fsp != NULL) { @@ -129,6 +142,47 @@ static int fake_acls_stat(vfs_handle_struct *handle, */ fsp = fsp->base_fsp; } + } else { + NTSTATUS status; + /* + * openat_pathref_fsp() expects a talloc'ed + * smb_filename. stat can be passed a struct + * from the stack. Make a talloc'ed copy + * so openat_pathref_fsp() can add its + * destructor. + */ + smb_fname_cp = cp_smb_filename(talloc_tos(), + smb_fname); + /* Recursion guard. */ + in_openat_pathref_fsp = true; + status = openat_pathref_fsp(handle->conn->cwd_fsp, + smb_fname_cp); + /* End recursion guard. */ + in_openat_pathref_fsp = false; + + if (!NT_STATUS_IS_OK(status)) { + /* + * Ignore errors here. We know + * the path exists (the SMB_VFS_NEXT_STAT() + * above succeeded. So being unable to + * open a pathref fsp can be due to a + * range of errors (startup path beginning + * with '/' for example, path = ".." when + * enumerating a directory. Just treat this + * the same way as the path not having the + * FAKE_UID or FAKE_GID EA's present. For the + * test purposes of this module (fake NT ACLs + * from windows clients) this is close enough. + * Just report for debugging purposes. + */ + DBG_DEBUG("Unable to get pathref fsp on %s. " + "Error %s\n", + smb_fname_str_dbg(smb_fname_cp), + nt_errstr(status)); + TALLOC_FREE(smb_fname_cp); + return 0; + } + fsp = smb_fname_cp->fsp; } if (fsp != NULL) { @@ -136,10 +190,11 @@ static int fake_acls_stat(vfs_handle_struct *handle, fsp, &smb_fname->st.st_ex_uid); } else { - ret = fake_acls_uid(handle, &smb_fname_base, + ret = fake_acls_uid(handle, smb_fname_cp, &smb_fname->st.st_ex_uid); } if (ret != 0) { + TALLOC_FREE(smb_fname_cp); return ret; } if (fsp != NULL) { @@ -147,12 +202,14 @@ static int fake_acls_stat(vfs_handle_struct *handle, fsp, &smb_fname->st.st_ex_gid); } else { - ret = fake_acls_gid(handle, &smb_fname_base, + ret = fake_acls_gid(handle, smb_fname_cp, &smb_fname->st.st_ex_gid); } if (ret != 0) { + TALLOC_FREE(smb_fname_cp); return ret; } + TALLOC_FREE(smb_fname_cp); } return ret; |