diff options
Diffstat (limited to 'xlators/nfs/server/src/acl3.c')
| -rw-r--r-- | xlators/nfs/server/src/acl3.c | 181 |
1 files changed, 134 insertions, 47 deletions
diff --git a/xlators/nfs/server/src/acl3.c b/xlators/nfs/server/src/acl3.c index 46431a475..08b099b4e 100644 --- a/xlators/nfs/server/src/acl3.c +++ b/xlators/nfs/server/src/acl3.c @@ -113,8 +113,10 @@ nfs3_fh_to_xlator (struct nfs3_state *nfs3, struct nfs3_fh *fh); xlatorp = nfs3_fh_to_xlator (cst->nfs3state, \ &cst->resolvefh); \ uuid_unparse (cst->resolvefh.gfid, gfid); \ - sprintf (buf, "(%s) %s : %s", trans->peerinfo.identifier,\ - xlatorp ? xlatorp->name : "ERR", gfid); \ + snprintf (buf, sizeof (buf), "(%s) %s : %s", \ + trans->peerinfo.identifier, \ + xlatorp ? xlatorp->name : "ERR", \ + gfid); \ gf_log (GF_ACL, GF_LOG_ERROR, "Unable to resolve FH"\ ": %s", buf); \ nfstat = nfs3_errno_to_nfsstat3 (cst->resolve_errno);\ @@ -126,9 +128,9 @@ nfs3_fh_to_xlator (struct nfs3_state *nfs3, struct nfs3_fh *fh); do { \ calls = nfs3_call_state_init ((nfs3state), (rq), v); \ if (!calls) { \ - gf_log (GF_NLM, GF_LOG_ERROR, "Failed to " \ + gf_log (GF_ACL, GF_LOG_ERROR, "Failed to " \ "init call state"); \ - opstat = nlm4_failed; \ + opstat = NFS3ERR_SERVERFAULT; \ rpcsvc_request_seterr (req, SYSTEM_ERR); \ goto errlabel; \ } \ @@ -138,10 +140,11 @@ nfs3_fh_to_xlator (struct nfs3_state *nfs3, struct nfs3_fh *fh); int acl3svc_submit_reply (rpcsvc_request_t *req, void *arg, acl3_serializer sfunc) { - struct iovec outmsg = {0, }; - struct iobuf *iob = NULL; - struct nfs3_state *nfs3 = NULL; - int ret = -1; + struct iovec outmsg = {0, }; + struct iobuf *iob = NULL; + struct nfs3_state *nfs3 = NULL; + int ret = -1; + ssize_t msglen = 0; struct iobref *iobref = NULL; if (!req) @@ -166,7 +169,12 @@ acl3svc_submit_reply (rpcsvc_request_t *req, void *arg, acl3_serializer sfunc) /* Use the given serializer to translate the give C structure in arg * to XDR format which will be written into the buffer in outmsg. */ - outmsg.iov_len = sfunc (outmsg, arg); + msglen = sfunc (outmsg, arg); + if (msglen < 0) { + gf_log (GF_ACL, GF_LOG_ERROR, "Failed to encode message"); + goto ret; + } + outmsg.iov_len = msglen; iobref = iobref_new (); if (iobref == NULL) { @@ -174,7 +182,11 @@ acl3svc_submit_reply (rpcsvc_request_t *req, void *arg, acl3_serializer sfunc) goto ret; } - iobref_add (iobref, iob); + ret = iobref_add (iobref, iob); + if (ret) { + gf_log (GF_ACL, GF_LOG_ERROR, "Failed to add iob to iobref"); + goto ret; + } /* Then, submit the message for transmission. */ ret = rpcsvc_submit_message (req, &outmsg, 1, NULL, 0, iobref); @@ -228,20 +240,25 @@ acl3_getacl_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int i = 0; getaclreply *getaclreply = NULL; + if (!frame->local) { + gf_log (GF_ACL, GF_LOG_ERROR, "Invalid argument," + " frame->local NULL"); + return EINVAL; + } cs = frame->local; + getaclreply = &cs->args.getaclreply; if (op_ret == -1) { - stat = nfs3_errno_to_nfsstat3 (op_errno); + stat = nfs3_cbk_errno_status (op_ret, op_errno); goto err; } - getaclreply = &cs->args.getaclreply; getaclreply->aclentry.aclentry_val = cs->aclentry; getaclreply->daclentry.daclentry_val = cs->daclentry; /* FIXME: use posix_acl_from_xattr() */ - data = dict_get (dict, "system.posix_acl_access"); + data = dict_get (dict, POSIX_ACL_ACCESS_XATTR); if (data && (p = data_to_bin (data))) { - /* POSIX_ACL_XATTR_VERSION */ + /* POSIX_ACL_VERSION */ p++; while ((char *)p < (data->data + data->len)) { getaclreply->aclentry.aclentry_val[i].type = *(*(short **)&p)++; @@ -253,9 +270,9 @@ acl3_getacl_cbk (call_frame_t *frame, void *cookie, xlator_t *this, } i = 0; - data = dict_get (dict, "system.posix_acl_default"); + data = dict_get (dict, POSIX_ACL_DEFAULT_XATTR); if (data && (p = data_to_bin (data))) { - /* POSIX_ACL_XATTR_VERSION */ + /* POSIX_ACL_VERSION */ p++; while ((char *)p < (data->data + data->len)) { getaclreply->daclentry.daclentry_val[i].type = *(*(short **)&p)++; @@ -271,7 +288,8 @@ acl3_getacl_cbk (call_frame_t *frame, void *cookie, xlator_t *this, return 0; err: - getaclreply->status = stat; + if (getaclreply) + getaclreply->status = stat; acl3_getacl_reply (cs, getaclreply); nfs3_call_state_wipe (cs); return 0; @@ -288,14 +306,20 @@ acl3_stat_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int ret = -1; nfs_user_t nfu = {0, }; + if (!frame->local) { + gf_log (GF_ACL, GF_LOG_ERROR, "Invalid argument," + " frame->local NULL"); + return EINVAL; + } + cs = frame->local; + getaclreply = &cs->args.getaclreply; + if (op_ret == -1) { - stat = nfs3_errno_to_nfsstat3 (op_errno); + stat = nfs3_cbk_errno_status (op_ret, op_errno); goto err; } - getaclreply = &cs->args.getaclreply; - getaclreply->attr_follows = 1; getaclreply->attr = nfs3_stat_to_fattr3 (buf); getaclreply->mask = 0xf; @@ -303,7 +327,7 @@ acl3_stat_cbk (call_frame_t *frame, void *cookie, xlator_t *this, ret = nfs_getxattr (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc, NULL, NULL, acl3_getacl_cbk, cs); if (ret == -1) { - stat = nfs3_errno_to_nfsstat3 (op_errno); + stat = nfs3_cbk_errno_status (op_ret, op_errno); goto err; } return 0; @@ -377,7 +401,7 @@ acl3svc_getacl (rpcsvc_request_t *req) vol, stat, rpcerr); cs->vol = vol; - acl3_volume_started_check (nfs3, vol, ret, rpcerr); + acl3_volume_started_check (nfs3, vol, ret, acl3err); ret = nfs3_fh_resolve_and_resume (cs, fhp, NULL, acl3_getacl_resume); @@ -385,9 +409,11 @@ acl3svc_getacl (rpcsvc_request_t *req) acl3err: if (ret < 0) { gf_log (GF_ACL, GF_LOG_ERROR, "unable to resolve and resume"); - cs->args.getaclreply.status = stat; - acl3_getacl_reply (cs, &cs->args.getaclreply); - nfs3_call_state_wipe (cs); + if (cs) { + cs->args.getaclreply.status = stat; + acl3_getacl_reply (cs, &cs->args.getaclreply); + nfs3_call_state_wipe (cs); + } return 0; } @@ -403,7 +429,8 @@ acl3_setacl_cbk (call_frame_t *frame, void *cookie, nfs3_call_state_t *cs = NULL; cs = frame->local; if (op_ret < 0) { - cs->args.setaclreply.status = nfs3_errno_to_nfsstat3 (op_errno); + nfsstat3 status = nfs3_cbk_errno_status (op_ret, op_errno); + cs->args.setaclreply.status = status; } acl3svc_submit_reply (cs->req, (void *)&cs->args.setaclreply, @@ -422,17 +449,16 @@ acl3_setacl_resume (void *carg) if (!carg) return ret; - cs = (nfs3_call_state_t *)carg; acl3_check_fh_resolve_status (cs, stat, acl3err); nfs_request_user_init (&nfu, cs->req); xattr = dict_new(); if (cs->aclcount) - ret = dict_set_static_bin (xattr, "system.posix_acl_access", cs->aclxattr, + ret = dict_set_static_bin (xattr, POSIX_ACL_ACCESS_XATTR, cs->aclxattr, cs->aclcount * 8 + 4); if (cs->daclcount) - ret = dict_set_static_bin (xattr, "system.posix_acl_default", cs->daclxattr, - cs->daclcount * 8 + 4); + ret = dict_set_static_bin (xattr, POSIX_ACL_DEFAULT_XATTR, + cs->daclxattr, cs->daclcount * 8 + 4); ret = nfs_setxattr (cs->nfsx, cs->vol, &nfu, &cs->resolvedloc, xattr, 0, NULL, acl3_setacl_cbk, cs); @@ -464,12 +490,24 @@ acl3svc_setacl (rpcsvc_request_t *req) struct nfs3_fh fh; struct nfs3_fh *fhp = NULL; setaclargs setaclargs; - aclentry aclentry[NFS_ACL_MAX_ENTRIES]; - struct aclentry daclentry[NFS_ACL_MAX_ENTRIES]; - int *p = NULL, i = 0; + aclentry *aclentry = NULL; + struct aclentry *daclentry = NULL; + int i = 0; + struct posix_acl_xattr_header *bufheader = NULL; + struct posix_acl_xattr_entry *bufentry = NULL; if (!req) return ret; + aclentry = GF_CALLOC (NFS_ACL_MAX_ENTRIES, sizeof(*aclentry), + gf_nfs_mt_arr); + if (!aclentry) { + goto rpcerr; + } + daclentry = GF_CALLOC (NFS_ACL_MAX_ENTRIES, sizeof(*daclentry), + gf_nfs_mt_arr); + if (!daclentry) { + goto rpcerr; + } acl3_validate_nfs3_state (req, nfs3, stat, rpcerr, ret); nfs = nfs_state (nfs3->nfsx); @@ -500,19 +538,58 @@ acl3svc_setacl (rpcsvc_request_t *req) (cs->daclcount > NFS_ACL_MAX_ENTRIES)) goto acl3err; /* FIXME: use posix_acl_to_xattr() */ - p = (int *)cs->aclxattr; - *(*(int **)&p)++ = POSIX_ACL_XATTR_VERSION; + /* Populate xattr buffer for user ACL */ + bufheader = (struct posix_acl_xattr_header *)(cs->aclxattr); + bufheader->version = htole32(POSIX_ACL_VERSION); + bufentry = bufheader->entries; for (i = 0; i < cs->aclcount; i++) { - *(*(short **)&p)++ = aclentry[i].type; - *(*(short **)&p)++ = aclentry[i].perm; - *(*(int **)&p)++ = aclentry[i].uid; + int uaceuid; + const struct aclentry *uace = &aclentry[i]; + switch (uace->type) { + case POSIX_ACL_USER: + case POSIX_ACL_GROUP: + uaceuid = uace->uid; + break; + default: + uaceuid = POSIX_ACL_UNDEFINED_ID; + break; + } + bufentry->tag = htole16(uace->type); + bufentry->perm = htole16(uace->perm); + bufentry->id = htole32(uaceuid); + + bufentry++; } - p = (int *)cs->daclxattr; - *(*(int **)&p)++ = POSIX_ACL_XATTR_VERSION; + + /* Populate xattr buffer for Default ACL */ + bufheader = (struct posix_acl_xattr_header *)(cs->aclxattr); + bufheader->version = htole32(POSIX_ACL_VERSION); + bufentry = bufheader->entries; for (i = 0; i < cs->daclcount; i++) { - *(*(short **)&p)++ = daclentry[i].type; - *(*(short **)&p)++ = daclentry[i].perm; - *(*(int **)&p)++ = daclentry[i].uid; + int daceuid; + int dacetype; + const struct aclentry *dace = &daclentry[i]; + /* + * For "default ACL", NFSv3 handles the 'type' differently + * i.e. by logical OR'ing 'type' with NFS_ACL_DEFAULT. + * Which the backend File system does not understand and + * that needs to be masked OFF. + */ + dacetype = (dace->type & ~(NFS_ACL_DEFAULT)); + switch (dacetype) { + case POSIX_ACL_USER: + case POSIX_ACL_GROUP: + daceuid = dace->uid; + break; + default: + daceuid = POSIX_ACL_UNDEFINED_ID; + break; + } + bufentry->tag = htole16(dacetype); + bufentry->perm = htole16(dace->perm); + bufentry->id = htole32(daceuid); + + bufentry++; } @@ -526,19 +603,23 @@ acl3err: acl3svc_submit_reply (cs->req, (void *)&cs->args.setaclreply, (acl3_serializer)xdr_serialize_setaclreply); nfs3_call_state_wipe (cs); + GF_FREE(aclentry); + GF_FREE(daclentry); return 0; } rpcerr: if (ret < 0) nfs3_call_state_wipe (cs); - + if (aclentry) + GF_FREE (aclentry); + if (daclentry) + GF_FREE (daclentry); return ret; } - rpcsvc_actor_t acl3svc_actors[ACL3_PROC_COUNT] = { {"NULL", ACL3_NULL, acl3svc_null, NULL, 0}, {"GETACL", ACL3_GETACL, acl3svc_getacl, NULL, 0}, @@ -548,7 +629,7 @@ rpcsvc_actor_t acl3svc_actors[ACL3_PROC_COUNT] = { rpcsvc_program_t acl3prog = { .progname = "ACL3", .prognum = ACL_PROGRAM, - .progver = ACL_V3, + .progver = ACLV3_VERSION, .progport = GF_NFS3_PORT, .actors = acl3svc_actors, .numactors = ACL3_PROC_COUNT, @@ -563,6 +644,11 @@ acl3svc_init(xlator_t *nfsx) dict_t *options = NULL; int ret = -1; char *portstr = NULL; + static gf_boolean_t acl3_inited = _gf_false; + + /* Already inited */ + if (acl3_inited) + return &acl3prog; nfs = (struct nfs_state*)nfsx->private; @@ -608,13 +694,14 @@ acl3svc_init(xlator_t *nfsx) goto err; } - rpcsvc_create_listeners (nfs->rpcsvc, options, "ACL"); + ret = rpcsvc_create_listeners (nfs->rpcsvc, options, "ACL"); if (ret == -1) { gf_log (GF_ACL, GF_LOG_ERROR, "Unable to create listeners"); dict_unref (options); goto err; } + acl3_inited = _gf_true; return &acl3prog; err: return NULL; |
