From 01580c7480497ee68abccfa7a55093872d5d112f Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Thu, 8 Jun 2017 19:05:48 +0200 Subject: [PATCH 1/3] s3/smbd: handling of failed DOS attributes reading Only fall back to using UNIX modes if we get NOT_IMPLEMENTED. This is exactly what we already do when setting DOS attributes. Bug: https://bugzilla.samba.org/show_bug.cgi?id=12944 Signed-off-by: Ralph Boehme Reviewed-by: Christof Schmitt (cherry picked from commit 9de1411d9e7c7ac3da544345d4dea7fd73dff01b) --- source3/smbd/dosmode.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index c80d240..65f47ee 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -617,7 +617,12 @@ uint32_t dos_mode(connection_struct *conn, struct smb_filename *smb_fname) /* Get the DOS attributes via the VFS if we can */ status = SMB_VFS_GET_DOS_ATTRIBUTES(conn, smb_fname, &result); if (!NT_STATUS_IS_OK(status)) { - result |= dos_mode_from_sbuf(conn, smb_fname); + /* + * Only fall back to using UNIX modes if we get NOT_IMPLEMENTED. + */ + if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) { + result |= dos_mode_from_sbuf(conn, smb_fname); + } } offline = SMB_VFS_IS_OFFLINE(conn, smb_fname, &smb_fname->st); -- 2.9.4 From 25a3c96aac623e315347fa5d566bb5354e7f2c32 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Thu, 8 Jun 2017 19:10:20 +0200 Subject: [PATCH 2/3] s3/smbd: handle EACCES when fetching DOS attributes from xattr When trying to fetch the DOS attributes xattr via SMB_VFS_GETXATTR() if the filesystem doesn't grant read access to the file the xattr read request fails with EACCESS. But according to MS-FSA 2.1.5.1.2.1 "Algorithm to Check Access to an Existing File" FILE_LIST_DIRECTORY on a directory implies FILE_READ_ATTRIBUTES for directory entries. So if the user can open the parent directory for reading this implies FILE_LIST_DIRECTORY and we can safely call SMB_VFS_GETXATTR() as root, ensuring we can read the DOS attributes xattr. Bug: https://bugzilla.samba.org/show_bug.cgi?id=12944 Signed-off-by: Ralph Boehme Reviewed-by: Christof Schmitt (backported from commit c54fcb7cbd0de244eed4134e877da6e9c16e7aab) --- source3/smbd/dosmode.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 65f47ee..49ddd90 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -281,6 +281,42 @@ NTSTATUS get_ea_dos_attribute(connection_struct *conn, sizeret = SMB_VFS_GETXATTR(conn, smb_fname->base_name, SAMBA_XATTR_DOS_ATTRIB, attrstr, sizeof(attrstr)); + if (sizeret == -1 && errno == EACCES) { + int saved_errno = 0; + + /* + * According to MS-FSA 2.1.5.1.2.1 "Algorithm to Check Access to + * an Existing File" FILE_LIST_DIRECTORY on a directory implies + * FILE_READ_ATTRIBUTES for directory entries. Being able to + * stat() a file implies FILE_LIST_DIRECTORY for the directory + * containing the file. + */ + + if (!VALID_STAT(smb_fname->st)) { + /* + * Safety net: dos_mode() already checks this, but as we + * become root based on this, add an additional layer of + * defense. + */ + DBG_ERR("Rejecting root override, invalid stat [%s]\n", + smb_fname_str_dbg(smb_fname)); + return NT_STATUS_ACCESS_DENIED; + } + + become_root(); + sizeret = SMB_VFS_GETXATTR(conn, smb_fname->base_name, + SAMBA_XATTR_DOS_ATTRIB, + attrstr, + sizeof(attrstr)); + if (sizeret == -1) { + saved_errno = errno; + } + unbecome_root(); + + if (saved_errno != 0) { + errno = saved_errno; + } + } if (sizeret == -1) { DBG_INFO("Cannot get attribute " "from EA on file %s: Error = %s\n", -- 2.9.4 From 1a35647c956676b87d4ffc1ae6645849043b0940 Mon Sep 17 00:00:00 2001 From: Ralph Boehme Date: Thu, 8 Jun 2017 19:18:36 +0200 Subject: [PATCH 3/3] vfs_gpfs: handle EACCES when fetching DOS attributes from xattr MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When trying to fetch the DOS attributes via gpfswrap_get_winattrs_path() if the filesystem doesn't grant READ_ATTR to the file the function fails with EACCESS. But according to MS-FSA 2.1.5.1.2.1 "Algorithm to Check Access to an Existing File" FILE_LIST_DIRECTORY on a directory implies FILE_READ_ATTRIBUTES for directory entries. So if the user can open the parent directory for reading this implies FILE_LIST_DIRECTORY and we can safely call gpfswrap_get_winattrs_path() with DAC_OVERRIDE_CAPABILITY. Bug: https://bugzilla.samba.org/show_bug.cgi?id=12944 Signed-off-by: Ralph Boehme Reviewed-by: Christof Schmitt Autobuild-User(master): Ralph Böhme Autobuild-Date(master): Wed Aug 9 01:21:14 CEST 2017 on sn-devel-144 (cherry picked from commit 62d73f5b936550d623ef4f31c7438ac3c90105b9) --- source3/modules/vfs_gpfs.c | 69 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) diff --git a/source3/modules/vfs_gpfs.c b/source3/modules/vfs_gpfs.c index f096dd5..78ebd54 100644 --- a/source3/modules/vfs_gpfs.c +++ b/source3/modules/vfs_gpfs.c @@ -1520,6 +1520,47 @@ static unsigned int vfs_gpfs_dosmode_to_winattrs(uint32_t dosmode) return winattrs; } +static int get_dos_attr_with_capability(struct smb_filename *smb_fname, + struct gpfs_winattr *attr) +{ + int saved_errno = 0; + int ret; + + /* + * According to MS-FSA 2.1.5.1.2.1 "Algorithm to Check Access to an + * Existing File" FILE_LIST_DIRECTORY on a directory implies + * FILE_READ_ATTRIBUTES for directory entries. Being able to stat() a + * file implies FILE_LIST_DIRECTORY for the directory containing the + * file. + */ + + if (!VALID_STAT(smb_fname->st)) { + /* + * Safety net: dos_mode() already checks this, but as we set + * DAC_OVERRIDE_CAPABILITY based on this, add an additional + * layer of defense. + */ + DBG_ERR("Rejecting DAC override, invalid stat [%s]\n", + smb_fname_str_dbg(smb_fname)); + errno = EACCES; + return -1; + } + + set_effective_capability(DAC_OVERRIDE_CAPABILITY); + + ret = gpfswrap_get_winattrs_path(smb_fname->base_name, attr); + if (ret == -1) { + saved_errno = errno; + } + + drop_effective_capability(DAC_OVERRIDE_CAPABILITY); + + if (saved_errno != 0) { + errno = saved_errno; + } + return ret; +} + static NTSTATUS vfs_gpfs_get_dos_attributes(struct vfs_handle_struct *handle, struct smb_filename *smb_fname, uint32_t *dosmode) @@ -1542,7 +1583,9 @@ static NTSTATUS vfs_gpfs_get_dos_attributes(struct vfs_handle_struct *handle, return SMB_VFS_NEXT_GET_DOS_ATTRIBUTES(handle, smb_fname, dosmode); } - + if (ret == -1 && errno == EACCES) { + ret = get_dos_attr_with_capability(smb_fname, &attrs); + } if (ret == -1) { DBG_WARNING("Getting winattrs failed for %s: %s\n", smb_fname->base_name, strerror(errno)); @@ -1575,6 +1618,30 @@ static NTSTATUS vfs_gpfs_fget_dos_attributes(struct vfs_handle_struct *handle, return SMB_VFS_NEXT_FGET_DOS_ATTRIBUTES(handle, fsp, dosmode); } + if (ret == -1 && errno == EACCES) { + int saved_errno = 0; + + /* + * According to MS-FSA 2.1.5.1.2.1 "Algorithm to Check Access to + * an Existing File" FILE_LIST_DIRECTORY on a directory implies + * FILE_READ_ATTRIBUTES for directory entries. Being able to + * open a file implies FILE_LIST_DIRECTORY. + */ + + set_effective_capability(DAC_OVERRIDE_CAPABILITY); + + ret = gpfswrap_get_winattrs(fsp->fh->fd, &attrs); + if (ret == -1) { + saved_errno = errno; + } + + drop_effective_capability(DAC_OVERRIDE_CAPABILITY); + + if (saved_errno != 0) { + errno = saved_errno; + } + } + if (ret == -1) { DBG_WARNING("Getting winattrs failed for %s: %s\n", fsp->fsp_name->base_name, strerror(errno)); -- 2.9.4