static int __rawobj_extract(rawobj_t *obj, __u32 **buf, __u32 *buflen, int alloc, int local) { __u32 len; if (*buflen < sizeof(__u32)) { CERROR("buflen %u\n", *buflen); return -EINVAL; } obj->len = *(*buf)++; if (!local) obj->len = le32_to_cpu(obj->len); *buflen -= sizeof(__u32); if (!obj->len) { obj->data = NULL; return 0; } len = local ? obj->len : cfs_size_round4(obj->len); if (*buflen < len) { CERROR("buflen %u < %u\n", *buflen, len); obj->len = 0; return -EINVAL; } if (!alloc) obj->data = (__u8 *) *buf; else { OBD_ALLOC_LARGE(obj->data, obj->len); if (!obj->data) { CERROR("fail to alloc %u bytes\n", obj->len); obj->len = 0; return -ENOMEM; } memcpy(obj->data, *buf, obj->len); } *((char **)buf) += len; *buflen -= len; return 0; }
int rawobj_serialize(rawobj_t *obj, __u32 **buf, __u32 *buflen) { __u32 len; LASSERT(obj); LASSERT(buf); LASSERT(buflen); len = cfs_size_round4(obj->len); if (*buflen < 4 + len) { CERROR("buflen %u < %u\n", *buflen, 4 + len); return -EINVAL; } *(*buf)++ = cpu_to_le32(obj->len); memcpy(*buf, obj->data, obj->len); *buf += (len >> 2); *buflen -= (4 + len); return 0; }
static int ctx_init_pack_request(struct obd_import *imp, struct ptlrpc_request *req, int lustre_srv, uid_t uid, gid_t gid, long token_size, char __user *token) { struct lustre_msg *msg = req->rq_reqbuf; struct gss_sec *gsec; struct gss_header *ghdr; struct ptlrpc_user_desc *pud; __u32 *p, size, offset = 2; rawobj_t obj; LASSERT(msg->lm_bufcount <= 4); LASSERT(req->rq_cli_ctx); LASSERT(req->rq_cli_ctx->cc_sec); /* gss hdr */ ghdr = lustre_msg_buf(msg, 0, sizeof(*ghdr)); ghdr->gh_version = PTLRPC_GSS_VERSION; ghdr->gh_sp = (__u8) imp->imp_sec->ps_part; ghdr->gh_flags = 0; ghdr->gh_proc = PTLRPC_GSS_PROC_INIT; ghdr->gh_seq = 0; ghdr->gh_svc = SPTLRPC_SVC_NULL; ghdr->gh_handle.len = 0; /* fix the user desc */ if (req->rq_pack_udesc) { ghdr->gh_flags |= LUSTRE_GSS_PACK_USER; pud = lustre_msg_buf(msg, offset, sizeof(*pud)); LASSERT(pud); pud->pud_uid = pud->pud_fsuid = uid; pud->pud_gid = pud->pud_fsgid = gid; pud->pud_cap = 0; pud->pud_ngroups = 0; offset++; } /* security payload */ p = lustre_msg_buf(msg, offset, 0); size = msg->lm_buflens[offset]; LASSERT(p); /* 1. lustre svc type */ LASSERT(size > 4); *p++ = cpu_to_le32(lustre_srv); size -= 4; /* 2. target uuid */ obj.len = strlen(imp->imp_obd->u.cli.cl_target_uuid.uuid) + 1; obj.data = imp->imp_obd->u.cli.cl_target_uuid.uuid; if (rawobj_serialize(&obj, &p, &size)) LBUG(); /* 3. reverse context handle. actually only needed by root user, * but we send it anyway. */ gsec = sec2gsec(req->rq_cli_ctx->cc_sec); obj.len = sizeof(gsec->gs_rvs_hdl); obj.data = (__u8 *) &gsec->gs_rvs_hdl; if (rawobj_serialize(&obj, &p, &size)) LBUG(); /* 4. now the token */ LASSERT(size >= (sizeof(__u32) + token_size)); *p++ = cpu_to_le32(((__u32) token_size)); if (copy_from_user(p, token, token_size)) { CERROR("can't copy token\n"); return -EFAULT; } size -= sizeof(__u32) + cfs_size_round4(token_size); req->rq_reqdata_len = lustre_shrink_msg(req->rq_reqbuf, offset, msg->lm_buflens[offset] - size, 0); return 0; }
static int ctx_init_parse_reply(struct lustre_msg *msg, int swabbed, char __user *outbuf, long outlen) { struct gss_rep_header *ghdr; __u32 obj_len, round_len; __u32 status, effective = 0; if (msg->lm_bufcount != 3) { CERROR("unexpected bufcount %u\n", msg->lm_bufcount); return -EPROTO; } ghdr = (struct gss_rep_header *) gss_swab_header(msg, 0, swabbed); if (ghdr == NULL) { CERROR("unable to extract gss reply header\n"); return -EPROTO; } if (ghdr->gh_version != PTLRPC_GSS_VERSION) { CERROR("invalid gss version %u\n", ghdr->gh_version); return -EPROTO; } if (outlen < (4 + 2) * 4 + cfs_size_round4(ghdr->gh_handle.len) + cfs_size_round4(msg->lm_buflens[2])) { CERROR("output buffer size %ld too small\n", outlen); return -EFAULT; } status = 0; effective = 0; if (copy_to_user(outbuf, &status, 4)) return -EFAULT; outbuf += 4; if (copy_to_user(outbuf, &ghdr->gh_major, 4)) return -EFAULT; outbuf += 4; if (copy_to_user(outbuf, &ghdr->gh_minor, 4)) return -EFAULT; outbuf += 4; if (copy_to_user(outbuf, &ghdr->gh_seqwin, 4)) return -EFAULT; outbuf += 4; effective += 4 * 4; /* handle */ obj_len = ghdr->gh_handle.len; round_len = (obj_len + 3) & ~3; if (copy_to_user(outbuf, &obj_len, 4)) return -EFAULT; outbuf += 4; if (copy_to_user(outbuf, (char *) ghdr->gh_handle.data, round_len)) return -EFAULT; outbuf += round_len; effective += 4 + round_len; /* out token */ obj_len = msg->lm_buflens[2]; round_len = (obj_len + 3) & ~3; if (copy_to_user(outbuf, &obj_len, 4)) return -EFAULT; outbuf += 4; if (copy_to_user(outbuf, lustre_msg_buf(msg, 2, 0), round_len)) return -EFAULT; outbuf += round_len; effective += 4 + round_len; return effective; }