summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Werth <alexander.werth@de.ibm.com>2014-02-04 17:50:54 +0100
committerJeremy Allison <jra@samba.org>2014-04-05 00:50:14 +0200
commit69b7631ca712046eab2bf4d8dae666718c46cb82 (patch)
tree0b397b15f349d736dd4c15fd32066e498cb6bcdf
parenta5d5bdc36b7e3c7a73984968013be50682c8eb77 (diff)
downloadsamba-69b7631ca712046eab2bf4d8dae666718c46cb82.tar.gz
samba-69b7631ca712046eab2bf4d8dae666718c46cb82.tar.xz
samba-69b7631ca712046eab2bf4d8dae666718c46cb82.zip
vfs: Store ACL control flags in gpfs vfs module.
Use literals to allow a compile and execution on gpfs 3.4. Signed-off-by: Alexander Werth <alexander.werth@de.ibm.com> Reviewed-by: Christof Schmitt <cs@samba.org> Reviewed-by: Jeremy Allison <jra@samba.org>
-rw-r--r--source3/modules/vfs_gpfs.c137
1 files changed, 114 insertions, 23 deletions
diff --git a/source3/modules/vfs_gpfs.c b/source3/modules/vfs_gpfs.c
index 73ab4a463d9..edbc88573ba 100644
--- a/source3/modules/vfs_gpfs.c
+++ b/source3/modules/vfs_gpfs.c
@@ -52,6 +52,24 @@ struct gpfs_config_data {
bool recalls;
};
+static inline unsigned int gpfs_acl_flags(gpfs_acl_t *gacl)
+{
+ if (gacl->acl_level == 1) { /* GPFS_ACL_LEVEL_V4FLAGS */
+ /* gacl->v4Level1.acl_flags requires gpfs 3.5 */
+ return *(unsigned int *)&gacl->ace_v4;
+ }
+ return 0;
+}
+
+static inline gpfs_ace_v4_t *gpfs_ace_ptr(gpfs_acl_t *gacl, unsigned int i)
+{
+ if (gacl->acl_level == 1) { /* GPFS_ACL_LEVEL_V4FLAGS */
+ /* &gacl->v4Level1.ace_v4[i] requires gpfs 3.5 */
+ char *ptr = (char *)&gacl->ace_v4[i] + sizeof(unsigned int);
+ return (gpfs_ace_v4_t *)ptr;
+ }
+ return &gacl->ace_v4[i];
+}
static int vfs_gpfs_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
uint32 share_mode, uint32 access_mask)
@@ -208,6 +226,34 @@ static int vfs_gpfs_get_real_filename(struct vfs_handle_struct *handle,
return 0;
}
+static void sd2gpfs_control(uint16_t control, struct gpfs_acl *gacl)
+{
+ unsigned int gpfs_aclflags = 0;
+ control &= SEC_DESC_DACL_PROTECTED | SEC_DESC_SACL_PROTECTED |
+ SEC_DESC_DACL_AUTO_INHERITED | SEC_DESC_SACL_AUTO_INHERITED |
+ SEC_DESC_DACL_DEFAULTED | SEC_DESC_SACL_DEFAULTED |
+ SEC_DESC_DACL_PRESENT | SEC_DESC_SACL_PRESENT;
+ gpfs_aclflags = control << 8;
+ if (!(control & SEC_DESC_DACL_PRESENT))
+ gpfs_aclflags |= 0x00800000; /* ACL4_FLAG_NULL_DACL; */
+ if (!(control & SEC_DESC_SACL_PRESENT))
+ gpfs_aclflags |= 0x01000000; /* ACL4_FLAG_NULL_SACL; */
+ gacl->acl_level = 1; /* GPFS_ACL_LEVEL_V4FLAGS*/
+ /* gacl->v4Level1.acl_flags requires gpfs 3.5 */
+ *(unsigned int *)&gacl->ace_v4 = gpfs_aclflags;
+}
+
+static uint16_t gpfs2sd_control(unsigned int gpfs_aclflags)
+{
+ uint16_t control = gpfs_aclflags >> 8;
+ control &= SEC_DESC_DACL_PROTECTED | SEC_DESC_SACL_PROTECTED |
+ SEC_DESC_DACL_AUTO_INHERITED | SEC_DESC_SACL_AUTO_INHERITED |
+ SEC_DESC_DACL_DEFAULTED | SEC_DESC_SACL_DEFAULTED |
+ SEC_DESC_DACL_PRESENT | SEC_DESC_SACL_PRESENT;
+ control |= SEC_DESC_SELF_RELATIVE;
+ return control;
+}
+
static void gpfs_dumpacl(int level, struct gpfs_acl *gacl)
{
gpfs_aclCount_t i;
@@ -217,14 +263,18 @@ static void gpfs_dumpacl(int level, struct gpfs_acl *gacl)
return;
}
- DEBUG(level, ("gpfs acl: nace: %d, type:%d, version:%d, level:%d, len:%d\n",
- gacl->acl_nace, gacl->acl_type, gacl->acl_version, gacl->acl_level, gacl->acl_len));
+ DEBUG(level, ("len: %d, level: %d, version: %d, nace: %d, "
+ "control: %x\n",
+ gacl->acl_len, gacl->acl_level, gacl->acl_version,
+ gacl->acl_nace, gpfs_acl_flags(gacl)));
+
for(i=0; i<gacl->acl_nace; i++)
{
- struct gpfs_ace_v4 *gace = gacl->ace_v4 + i;
- DEBUG(level, ("\tace[%d]: type:%d, flags:0x%x, mask:0x%x, iflags:0x%x, who:%u\n",
- i, gace->aceType, gace->aceFlags, gace->aceMask,
- gace->aceIFlags, gace->aceWho));
+ struct gpfs_ace_v4 *gace = gpfs_ace_ptr(gacl, i);
+ DEBUG(level, ("\tace[%d]: type:%d, flags:0x%x, mask:0x%x, "
+ "iflags:0x%x, who:%u\n",
+ i, gace->aceType, gace->aceFlags, gace->aceMask,
+ gace->aceIFlags, gace->aceWho));
}
}
@@ -266,9 +316,11 @@ again:
} else {
struct gpfs_acl *buf = (struct gpfs_acl *) aclbuf;
buf->acl_type = type;
+ buf->acl_level = 1; /* GPFS_ACL_LEVEL_V4FLAGS */
flags = GPFS_GETACL_STRUCT;
len = &(buf->acl_len);
- struct_size = sizeof(struct gpfs_acl);
+ /* reserve space for control flags in gpfs 3.5 and beyond */
+ struct_size = sizeof(struct gpfs_acl) + sizeof(unsigned int);
}
/* set the length of the buffer as input value */
@@ -331,12 +383,17 @@ static int gpfs_get_nfs4_acl(TALLOC_CTX *mem_ctx, const char *fname, SMB4ACL_T *
*ppacl = smb_create_smb4acl(mem_ctx);
- DEBUG(10, ("len: %d, level: %d, version: %d, nace: %d\n",
+ if (gacl->acl_level == 1) { /* GPFS_ACL_LEVEL_V4FLAGS */
+ uint16_t control = gpfs2sd_control(gpfs_acl_flags(gacl));
+ smbacl4_set_controlflags(*ppacl, control);
+ }
+
+ DEBUG(10, ("len: %d, level: %d, version: %d, nace: %d, control: %x\n",
gacl->acl_len, gacl->acl_level, gacl->acl_version,
- gacl->acl_nace));
+ gacl->acl_nace, gpfs_acl_flags(gacl)));
for (i=0; i<gacl->acl_nace; i++) {
- struct gpfs_ace_v4 *gace = &gacl->ace_v4[i];
+ struct gpfs_ace_v4 *gace = gpfs_ace_ptr(gacl, i);
SMB_ACE4PROP_T smbace;
DEBUG(10, ("type: %d, iflags: %x, flags: %x, mask: %x, "
"who: %d\n", gace->aceType, gace->aceIFlags,
@@ -369,7 +426,7 @@ static int gpfs_get_nfs4_acl(TALLOC_CTX *mem_ctx, const char *fname, SMB4ACL_T *
/* remove redundant deny entries */
if (i > 0 && gace->aceType == SMB_ACE4_ACCESS_DENIED_ACE_TYPE) {
- struct gpfs_ace_v4 *prev = &gacl->ace_v4[i-1];
+ struct gpfs_ace_v4 *prev = gpfs_ace_ptr(gacl, i - 1);
if (prev->aceType == SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE &&
prev->aceFlags == gace->aceFlags &&
prev->aceIFlags == gace->aceIFlags &&
@@ -377,7 +434,7 @@ static int gpfs_get_nfs4_acl(TALLOC_CTX *mem_ctx, const char *fname, SMB4ACL_T *
gace->aceWho == prev->aceWho) {
/* it's redundant - skip it */
continue;
- }
+ }
}
smbace.aceType = gace->aceType;
@@ -484,32 +541,37 @@ static NTSTATUS gpfsacl_get_nt_acl(vfs_handle_struct *handle,
return map_nt_error_from_unix(errno);
}
-static bool gpfsacl_process_smbacl(vfs_handle_struct *handle, files_struct *fsp, SMB4ACL_T *smbacl)
+static struct gpfs_acl *vfs_gpfs_smbacl2gpfsacl(TALLOC_CTX *mem_ctx,
+ files_struct *fsp,
+ SMB4ACL_T *smbacl,
+ bool controlflags)
{
- int ret;
- gpfs_aclLen_t gacl_len;
- SMB4ACE_T *smbace;
struct gpfs_acl *gacl;
- TALLOC_CTX *mem_ctx = talloc_tos();
+ gpfs_aclLen_t gacl_len;
+ SMB4ACE_T *smbace;
- gacl_len = offsetof(gpfs_acl_t, ace_v4) + smb_get_naces(smbacl) *
- sizeof(gpfs_ace_v4_t);
+ gacl_len = offsetof(gpfs_acl_t, ace_v4) + sizeof(unsigned int)
+ + smb_get_naces(smbacl) * sizeof(gpfs_ace_v4_t);
gacl = (struct gpfs_acl *)TALLOC_SIZE(mem_ctx, gacl_len);
if (gacl == NULL) {
DEBUG(0, ("talloc failed\n"));
errno = ENOMEM;
- return False;
+ return NULL;
}
- gacl->acl_len = gacl_len;
- gacl->acl_level = 0;
+ gacl->acl_level = 0; /* GPFS_ACL_LEVEL_BASE */
gacl->acl_version = GPFS_ACL_VERSION_NFS4;
gacl->acl_type = GPFS_ACL_TYPE_NFS4;
gacl->acl_nace = 0; /* change later... */
+ if (controlflags) {
+ gacl->acl_level = 1; /* GPFS_ACL_LEVEL_V4FLAGS */
+ sd2gpfs_control(smbacl4_get_controlflags(smbacl), gacl);
+ }
+
for (smbace=smb_first_ace4(smbacl); smbace!=NULL; smbace = smb_next_ace4(smbace)) {
- struct gpfs_ace_v4 *gace = &gacl->ace_v4[gacl->acl_nace];
+ struct gpfs_ace_v4 *gace = gpfs_ace_ptr(gacl, gacl->acl_nace);
SMB_ACE4PROP_T *aceprop = smb_get_ace4(smbace);
gace->aceType = aceprop->aceType;
@@ -567,9 +629,38 @@ static bool gpfsacl_process_smbacl(vfs_handle_struct *handle, files_struct *fsp,
gacl->acl_nace++;
}
+ gacl->acl_len = (char *)gpfs_ace_ptr(gacl, gacl->acl_nace)
+ - (char *)gacl;
+ return gacl;
+}
+static bool gpfsacl_process_smbacl(vfs_handle_struct *handle,
+ files_struct *fsp,
+ SMB4ACL_T *smbacl)
+{
+ int ret;
+ struct gpfs_acl *gacl;
+ TALLOC_CTX *mem_ctx = talloc_tos();
+
+ gacl = vfs_gpfs_smbacl2gpfsacl(mem_ctx, fsp, smbacl, true);
+ if (gacl == NULL) { /* out of memory */
+ return False;
+ }
ret = smbd_gpfs_putacl(fsp->fsp_name->base_name,
GPFS_PUTACL_STRUCT | GPFS_ACL_SAMBA, gacl);
+
+ if ((ret != 0) && (errno == EINVAL)) {
+ DEBUG(10, ("Retry without nfs41 control flags\n"));
+ talloc_free(gacl);
+ gacl = vfs_gpfs_smbacl2gpfsacl(mem_ctx, fsp, smbacl, false);
+ if (gacl == NULL) { /* out of memory */
+ return False;
+ }
+ ret = smbd_gpfs_putacl(fsp->fsp_name->base_name,
+ GPFS_PUTACL_STRUCT | GPFS_ACL_SAMBA,
+ gacl);
+ }
+
if (ret != 0) {
DEBUG(8, ("gpfs_putacl failed with %s\n", strerror(errno)));
gpfs_dumpacl(8, gacl);