mirror of
https://github.com/samba-team/samba.git
synced 2025-01-11 05:18:09 +03:00
vfs_nfs4acl_xattr: add POSIX mode check and reset
The vfs_nfs4acl_xattr VFS module is supposed to work the same as vfs_acl_xattr|tdb with "ignore system acls" set to true. That is, filesystem permissions should never restrict access and the actual access checks are done by smbd in userspace. To better cope with POSIX mode changes via other protocols (eg NFS) or local filesystem access, add the following tweaks: o validate ACL blob: if POSIX mode is not 0777/0666 discard the ACL blob from the xattr and synthesize a default ACL based on the POSIX mode o when setting an ACL, check and reset POSIX mode to 0777/0666 Signed-off-by: Ralph Boehme <slow@samba.org> Reviewed-by: Jeremy Allison <jra@samba.org>
This commit is contained in:
parent
b4072961c6
commit
0fdbe624fd
@ -29,6 +29,7 @@
|
||||
#include "includes.h"
|
||||
#include "system/filesys.h"
|
||||
#include "smbd/smbd.h"
|
||||
#include "libcli/security/security_token.h"
|
||||
#include "nfs4_acls.h"
|
||||
#include "librpc/gen_ndr/ndr_nfs4acl.h"
|
||||
#include "nfs4acl_xattr.h"
|
||||
@ -42,6 +43,55 @@ static const struct enum_list nfs4acl_encoding[] = {
|
||||
{NFS4ACL_ENCODING_XDR, "xdr"},
|
||||
};
|
||||
|
||||
/*
|
||||
* Check if someone changed the POSIX mode, for files we expect 0666, for
|
||||
* directories 0777. Discard the ACL blob if the mode is different.
|
||||
*/
|
||||
static bool nfs4acl_validate_blob(vfs_handle_struct *handle,
|
||||
const struct smb_filename *smb_fname)
|
||||
{
|
||||
struct nfs4acl_config *config = NULL;
|
||||
mode_t expected_mode;
|
||||
int saved_errno = 0;
|
||||
int ret;
|
||||
|
||||
SMB_VFS_HANDLE_GET_DATA(handle, config,
|
||||
struct nfs4acl_config,
|
||||
return false);
|
||||
|
||||
if (!VALID_STAT(smb_fname->st)) {
|
||||
/* might be a create */
|
||||
return true;
|
||||
}
|
||||
|
||||
if (S_ISDIR(smb_fname->st.st_ex_mode)) {
|
||||
expected_mode = 0777;
|
||||
} else {
|
||||
expected_mode = 0666;
|
||||
}
|
||||
if ((smb_fname->st.st_ex_mode & expected_mode) == expected_mode) {
|
||||
return true;
|
||||
}
|
||||
|
||||
become_root();
|
||||
ret = SMB_VFS_NEXT_REMOVEXATTR(handle,
|
||||
smb_fname,
|
||||
config->xattr_name);
|
||||
if (ret != 0) {
|
||||
saved_errno = errno;
|
||||
}
|
||||
unbecome_root();
|
||||
if (saved_errno != 0) {
|
||||
errno = saved_errno;
|
||||
}
|
||||
if (ret != 0 && errno != ENOATTR) {
|
||||
DBG_ERR("Removing NFS4 xattr failed: %s\n", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static NTSTATUS nfs4acl_get_blob(struct vfs_handle_struct *handle,
|
||||
files_struct *fsp,
|
||||
const struct smb_filename *smb_fname_in,
|
||||
@ -71,6 +121,11 @@ static NTSTATUS nfs4acl_get_blob(struct vfs_handle_struct *handle,
|
||||
return NT_STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
ok = nfs4acl_validate_blob(handle, smb_fname);
|
||||
if (!ok) {
|
||||
return NT_STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
do {
|
||||
int saved_errno = 0;
|
||||
|
||||
@ -304,17 +359,68 @@ static NTSTATUS nfs4acl_xattr_fset_nt_acl(vfs_handle_struct *handle,
|
||||
const struct security_descriptor *psd)
|
||||
{
|
||||
struct nfs4acl_config *config = NULL;
|
||||
mode_t existing_mode;
|
||||
mode_t expected_mode;
|
||||
mode_t restored_mode;
|
||||
NTSTATUS status;
|
||||
int ret;
|
||||
|
||||
SMB_VFS_HANDLE_GET_DATA(handle, config,
|
||||
struct nfs4acl_config,
|
||||
return NT_STATUS_INTERNAL_ERROR);
|
||||
|
||||
return smb_set_nt_acl_nfs4(handle,
|
||||
fsp,
|
||||
&config->nfs4_params,
|
||||
security_info_sent,
|
||||
psd,
|
||||
nfs4acl_smb4acl_set_fn);
|
||||
if (!VALID_STAT(fsp->fsp_name->st)) {
|
||||
DBG_ERR("Invalid stat info on [%s]\n", fsp_str_dbg(fsp));
|
||||
return NT_STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
existing_mode = fsp->fsp_name->st.st_ex_mode;
|
||||
if (S_ISDIR(existing_mode)) {
|
||||
expected_mode = 0777;
|
||||
} else {
|
||||
expected_mode = 0666;
|
||||
}
|
||||
if ((existing_mode & expected_mode) != expected_mode) {
|
||||
int saved_errno = 0;
|
||||
|
||||
restored_mode = existing_mode | expected_mode;
|
||||
|
||||
become_root();
|
||||
if (fsp->fh->fd != -1) {
|
||||
ret = SMB_VFS_NEXT_FCHMOD(handle,
|
||||
fsp,
|
||||
restored_mode);
|
||||
} else {
|
||||
ret = SMB_VFS_NEXT_CHMOD(handle,
|
||||
fsp->fsp_name,
|
||||
restored_mode);
|
||||
}
|
||||
if (ret != 0) {
|
||||
saved_errno = errno;
|
||||
}
|
||||
unbecome_root();
|
||||
if (saved_errno != 0) {
|
||||
errno = saved_errno;
|
||||
}
|
||||
if (ret != 0) {
|
||||
DBG_ERR("Resetting POSIX mode on [%s] from [0%o]: %s\n",
|
||||
fsp_str_dbg(fsp), existing_mode,
|
||||
strerror(errno));
|
||||
return map_nt_error_from_unix(errno);
|
||||
}
|
||||
}
|
||||
|
||||
status = smb_set_nt_acl_nfs4(handle,
|
||||
fsp,
|
||||
&config->nfs4_params,
|
||||
security_info_sent,
|
||||
psd,
|
||||
nfs4acl_smb4acl_set_fn);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
static int nfs4acl_connect(struct vfs_handle_struct *handle,
|
||||
|
Loading…
Reference in New Issue
Block a user