diff options
author | Miloslav Trmač <mitr@redhat.com> | 2010-08-16 22:50:56 +0200 |
---|---|---|
committer | Miloslav Trmač <mitr@redhat.com> | 2010-08-24 23:49:09 +0200 |
commit | 7017a63132bc03462ba75e399c083e00f4e19573 (patch) | |
tree | ba790f1e3e542492640e6bf63ad1f3d6f62153e3 /ncr-sessions.c | |
parent | e536df1a394cf653ecc5964ece0551b0259abeb4 (diff) | |
download | cryptodev-linux-7017a63132bc03462ba75e399c083e00f4e19573.tar.gz cryptodev-linux-7017a63132bc03462ba75e399c083e00f4e19573.tar.xz cryptodev-linux-7017a63132bc03462ba75e399c083e00f4e19573.zip |
Convert *_SESSION_*
Diffstat (limited to 'ncr-sessions.c')
-rw-r--r-- | ncr-sessions.c | 514 |
1 files changed, 253 insertions, 261 deletions
diff --git a/ncr-sessions.c b/ncr-sessions.c index 320a061..8f3e721 100644 --- a/ncr-sessions.c +++ b/ncr-sessions.c @@ -31,7 +31,8 @@ #include <linux/scatterlist.h> #include <net/netlink.h> -static int _ncr_session_update_key(struct ncr_lists* lists, struct ncr_session_op_st* op); +static int _ncr_session_update_key(struct ncr_lists *lists, ncr_session_t ses, + struct nlattr *tb[]); static void _ncr_session_remove(struct ncr_lists *lst, ncr_session_t desc); static int session_list_deinit_fn(int id, void *item, void *unused) @@ -222,8 +223,28 @@ const struct algo_properties_st *_ncr_nla_to_properties(const struct nlattr *nla return _ncr_algo_to_properties(nla_get_u32(nla)); } -static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* session) +static int key_item_get_nla_read(struct key_item_st **st, + struct ncr_lists *lists, + const struct nlattr *nla) { + int ret; + + if (nla == NULL) { + err(); + return -EINVAL; + } + ret = ncr_key_item_get_read(st, lists, nla_get_u32(nla)); + if (ret < 0) { + err(); + return ret; + } + return ret; +} + +static int _ncr_session_init(struct ncr_lists *lists, ncr_crypto_op_t op, + struct nlattr *tb[]) +{ + const struct nlattr *nla; struct session_item_st* ns = NULL; int ret; const struct algo_properties_st *sign_hash; @@ -234,15 +255,15 @@ static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* ses return -ENOMEM; } - ns->op = session->op; - ns->algorithm = _ncr_algo_to_properties(session->algorithm); + ns->op = op; + ns->algorithm = _ncr_nla_to_properties(tb[NCR_ATTR_ALGORITHM]); if (ns->algorithm == NULL) { err(); ret = -EINVAL; goto fail; } - switch(session->op) { + switch(op) { case NCR_OP_ENCRYPT: case NCR_OP_DECRYPT: if (!ns->algorithm->can_encrypt) { @@ -252,7 +273,8 @@ static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* ses } /* read key */ - ret = ncr_key_item_get_read( &ns->key, lists, session->key); + ret = key_item_get_nla_read(&ns->key, lists, + tb[NCR_ATTR_KEY]); if (ret < 0) { err(); goto fail; @@ -269,7 +291,7 @@ static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* ses if (ns->key->type == NCR_KEY_TYPE_SECRET) { int keysize = ns->key->key.secret.size; - if (session->algorithm == NCR_ALG_NULL) + if (ns->algorithm->algo == NCR_ALG_NULL) keysize = 0; if (ns->algorithm->kstr == NULL) { @@ -286,16 +308,19 @@ static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* ses } if (ns->algorithm->needs_iv) { - if (session->params.params.cipher.iv_size > sizeof(session->params.params.cipher.iv)) { + nla = tb[NCR_ATTR_IV]; + if (nla == NULL) { err(); ret = -EINVAL; goto fail; } - cryptodev_cipher_set_iv(&ns->cipher, session->params.params.cipher.iv, session->params.params.cipher.iv_size); + cryptodev_cipher_set_iv(&ns->cipher, + nla_data(nla), + nla_len(nla)); } } else if (ns->key->type == NCR_KEY_TYPE_PRIVATE || ns->key->type == NCR_KEY_TYPE_PUBLIC) { ret = ncr_pk_cipher_init(ns->algorithm, &ns->pk, - &session->params, ns->key, NULL); + tb, ns->key, NULL); if (ret < 0) { err(); goto fail; @@ -330,7 +355,8 @@ static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* ses } else { /* read key */ - ret = ncr_key_item_get_read( &ns->key, lists, session->key); + ret = key_item_get_nla_read(&ns->key, lists, + tb[NCR_ATTR_KEY]); if (ret < 0) { err(); goto fail; @@ -359,10 +385,11 @@ static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* ses } } else if (ns->algorithm->is_pk && (ns->key->type == NCR_KEY_TYPE_PRIVATE || ns->key->type == NCR_KEY_TYPE_PUBLIC)) { - sign_hash = ncr_key_params_get_sign_hash(ns->key->algorithm, &session->params); - if (IS_ERR(sign_hash)) { + nla = tb[NCR_ATTR_SIGNATURE_HASH_ALGORITHM]; + sign_hash = _ncr_nla_to_properties(nla); + if (sign_hash == NULL) { err(); - ret = PTR_ERR(sign_hash); + ret = -EINVAL; goto fail; } @@ -379,7 +406,7 @@ static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* ses } ret = ncr_pk_cipher_init(ns->algorithm, &ns->pk, - &session->params, ns->key, sign_hash); + tb, ns->key, sign_hash); if (ret < 0) { err(); goto fail; @@ -404,8 +431,7 @@ static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* ses goto fail; } - ret = 0; - session->ses = ns->desc; + ret = ns->desc; fail: if (ret < 0) { @@ -416,29 +442,11 @@ fail: return ret; } -int ncr_session_init(struct ncr_lists* lists, void __user* arg) +int ncr_session_init(struct ncr_lists *lists, + const struct ncr_session_init *session, + struct nlattr *tb[]) { - struct ncr_session_st session; - int ret; - - if (unlikely(copy_from_user(&session, arg, sizeof(session)))) { - err(); - return -EFAULT; - } - - ret = _ncr_session_init(lists, &session); - if (unlikely(ret)) { - err(); - return ret; - } - - ret = copy_to_user( arg, &session, sizeof(session)); - if (unlikely(ret)) { - err(); - _ncr_session_remove(lists, session.ses); - return -EFAULT; - } - return ret; + return _ncr_session_init(lists, session->op, tb); } static int _ncr_session_encrypt(struct session_item_st* sess, const struct scatterlist* input, unsigned input_cnt, @@ -542,66 +550,64 @@ static int _ncr_session_grow_pages(struct session_item_st *ses, int pagecount) return 0; } -/* Only the output buffer is given as scatterlist */ -static int get_userbuf1(struct session_item_st* ses, - void __user * udata, size_t udata_size, struct scatterlist **dst_sg, unsigned *dst_cnt) +/* Make NCR_ATTR_UPDATE_INPUT_DATA and NCR_ATTR_UPDATE_OUTPUT_BUFFER available + in scatterlists */ +static int get_userbuf2(struct session_item_st *ses, struct nlattr *tb[], + struct scatterlist **src_sg, unsigned *src_cnt, + size_t *src_size, struct ncr_session_output_buffer *dst, + struct scatterlist **dst_sg, unsigned *dst_cnt, + int compat) { - int pagecount = 0; - - if (unlikely(udata == NULL)) { - err(); - return -EINVAL; - } + const struct nlattr *src_nla, *dst_nla; + struct ncr_session_input_data src; + int src_pagecount, dst_pagecount = 0, pagecount, write_src = 1, ret; + size_t input_size; - pagecount = PAGECOUNT(udata, udata_size); - _ncr_session_grow_pages(ses, pagecount); + src_nla = tb[NCR_ATTR_UPDATE_INPUT_DATA]; + dst_nla = tb[NCR_ATTR_UPDATE_OUTPUT_BUFFER]; - if (__get_userbuf(udata, udata_size, 1, - pagecount, ses->pages, ses->sg)) { + ret = ncr_session_input_data_from_nla(&src, src_nla, compat); + if (unlikely(ret != 0)) { err(); - return -EINVAL; + return ret; } - (*dst_sg) = ses->sg; - *dst_cnt = pagecount; + *src_size = src.data_size; - ses->available_pages = pagecount; - - return 0; -} - -/* make op->data.udata.input and op->data.udata.output available in scatterlists */ -static int get_userbuf2(struct session_item_st* ses, - struct ncr_session_op_st* op, struct scatterlist **src_sg, - unsigned *src_cnt, struct scatterlist **dst_sg, unsigned *dst_cnt) -{ - int src_pagecount, dst_pagecount = 0, pagecount, write_src = 1; - size_t input_size = op->data.udata.input_size; - - if (unlikely(op->data.udata.input == NULL)) { - err(); - return -EINVAL; + if (dst_nla != NULL) { + ret = ncr_session_output_buffer_from_nla(dst, dst_nla, compat); + if (unlikely(ret != 0)) { + err(); + return ret; + } } - src_pagecount = PAGECOUNT(op->data.udata.input, input_size); + input_size = src.data_size; + src_pagecount = PAGECOUNT(src.data, input_size); - if (op->data.udata.input != op->data.udata.output) { /* non-in-situ transformation */ + if (dst_nla == NULL || src.data != dst->buffer) { /* non-in-situ transformation */ write_src = 0; - if (op->data.udata.output != NULL) { - dst_pagecount = PAGECOUNT(op->data.udata.output, op->data.udata.output_size); + if (dst_nla != NULL) { + dst_pagecount = PAGECOUNT(dst->buffer, + dst->buffer_size); } else { dst_pagecount = 0; } } else { - src_pagecount = max((int)(PAGECOUNT(op->data.udata.output, op->data.udata.output_size)), - src_pagecount); - input_size = max(input_size, (size_t)op->data.udata.output_size); + src_pagecount = max((int)(PAGECOUNT(dst->buffer, + dst->buffer_size)), + src_pagecount); + input_size = max(input_size, dst->buffer_size); } pagecount = src_pagecount + dst_pagecount; - _ncr_session_grow_pages(ses, pagecount); + ret = _ncr_session_grow_pages(ses, pagecount); + if (ret != 0) { + err(); + return ret; + } - if (__get_userbuf(op->data.udata.input, input_size, write_src, - src_pagecount, ses->pages, ses->sg)) { + if (__get_userbuf((void __user *)src.data, input_size, write_src, + src_pagecount, ses->pages, ses->sg)) { err(); printk("write: %d\n", write_src); return -EINVAL; @@ -613,14 +619,15 @@ static int get_userbuf2(struct session_item_st* ses, *dst_cnt = dst_pagecount; (*dst_sg) = ses->sg + src_pagecount; - if (__get_userbuf(op->data.udata.output, op->data.udata.output_size, 1, dst_pagecount, - ses->pages + src_pagecount, *dst_sg)) { + if (__get_userbuf(dst->buffer, dst->buffer_size, 1, + dst_pagecount, ses->pages + src_pagecount, + *dst_sg)) { err(); release_user_pages(ses->pages, src_pagecount); return -EINVAL; } } else { - if (op->data.udata.output != NULL) { + if (dst_nla != NULL) { *dst_cnt = src_pagecount; (*dst_sg) = (*src_sg); } else { @@ -635,16 +642,18 @@ static int get_userbuf2(struct session_item_st* ses, } /* Called when userspace buffers are used */ -static int _ncr_session_update(struct ncr_lists* lists, struct ncr_session_op_st* op) +static int _ncr_session_update(struct ncr_lists *lists, ncr_session_t ses, + struct nlattr *tb[], int compat) { int ret; struct session_item_st* sess; - struct scatterlist *isg; - struct scatterlist *osg; + struct scatterlist *isg = NULL; + struct scatterlist *osg = NULL; unsigned osg_cnt=0, isg_cnt=0; - size_t isg_size, osg_size; + size_t isg_size = 0, osg_size; + struct ncr_session_output_buffer out; - sess = ncr_sessions_item_get(lists, op->ses); + sess = ncr_sessions_item_get(lists, ses); if (sess == NULL) { err(); return -EINVAL; @@ -656,13 +665,12 @@ static int _ncr_session_update(struct ncr_lists* lists, struct ncr_session_op_st return -ERESTARTSYS; } - ret = get_userbuf2(sess, op, &isg, &isg_cnt, &osg, &osg_cnt); + ret = get_userbuf2(sess, tb, &isg, &isg_cnt, &isg_size, &out, &osg, + &osg_cnt, compat); if (ret < 0) { err(); goto fail; } - isg_size = op->data.udata.input_size; - osg_size = op->data.udata.output_size; switch(sess->op) { case NCR_OP_ENCRYPT: @@ -672,6 +680,7 @@ static int _ncr_session_update(struct ncr_lists* lists, struct ncr_session_op_st goto fail; } + osg_size = out.buffer_size; if (osg_size < isg_size) { err(); ret = -EINVAL; @@ -684,8 +693,13 @@ static int _ncr_session_update(struct ncr_lists* lists, struct ncr_session_op_st err(); goto fail; } - op->data.udata.output_size = osg_size; - + + ret = ncr_session_output_buffer_set_size(&out, osg_size, + compat); + if (ret != 0) { + err(); + goto fail; + } break; case NCR_OP_DECRYPT: if (osg == NULL) { @@ -694,6 +708,7 @@ static int _ncr_session_update(struct ncr_lists* lists, struct ncr_session_op_st goto fail; } + osg_size = out.buffer_size; if (osg_size < isg_size) { err(); ret = -EINVAL; @@ -706,8 +721,13 @@ static int _ncr_session_update(struct ncr_lists* lists, struct ncr_session_op_st err(); goto fail; } - op->data.udata.output_size = osg_size; + ret = ncr_session_output_buffer_set_size(&out, osg_size, + compat); + if (ret != 0) { + err(); + goto fail; + } break; case NCR_OP_SIGN: @@ -737,40 +757,34 @@ fail: return ret; } -static int try_session_update(struct ncr_lists* lists, struct ncr_session_op_st* op) +static int try_session_update(struct ncr_lists *lists, ncr_session_t ses, + struct nlattr *tb[], int compat) { - if (op->type == NCR_KEY_DATA) { - if (op->data.kdata.input != NCR_KEY_INVALID) - return _ncr_session_update_key(lists, op); - } else if (op->type == NCR_DIRECT_DATA) { - if (op->data.udata.input != NULL) - return _ncr_session_update(lists, op); - } + if (tb[NCR_ATTR_UPDATE_INPUT_KEY_AS_DATA] != NULL) + return _ncr_session_update_key(lists, ses, tb); + else if (tb[NCR_ATTR_UPDATE_INPUT_DATA] != NULL) + return _ncr_session_update(lists, ses, tb, compat); return 0; } -static int _ncr_session_final(struct ncr_lists* lists, struct ncr_session_op_st* op) +static int _ncr_session_final(struct ncr_lists *lists, ncr_session_t ses, + struct nlattr *tb[], int compat) { + const struct nlattr *nla; int ret; struct session_item_st* sess; int digest_size; uint8_t digest[NCR_HASH_MAX_OUTPUT_SIZE]; - uint8_t vdigest[NCR_HASH_MAX_OUTPUT_SIZE]; - struct scatterlist *osg; - unsigned osg_cnt=0; - size_t osg_size = 0; - size_t orig_osg_size; - void __user * udata = NULL; - size_t *udata_size; - - sess = ncr_sessions_item_get(lists, op->ses); + void *buffer = NULL; + + sess = ncr_sessions_item_get(lists, ses); if (sess == NULL) { err(); return -EINVAL; } - ret = try_session_update(lists, op); + ret = try_session_update(lists, ses, tb, compat); if (ret < 0) { err(); _ncr_sessions_item_put(sess); @@ -782,129 +796,138 @@ static int _ncr_session_final(struct ncr_lists* lists, struct ncr_session_op_st* _ncr_sessions_item_put(sess); return -ERESTARTSYS; } - - if (op->type == NCR_DIRECT_DATA) { - udata = op->data.udata.output; - udata_size = &op->data.udata.output_size; - } else if (op->type == NCR_KEY_DATA) { - udata = op->data.kdata.output; - udata_size = &op->data.kdata.output_size; - } else { - err(); - ret = -EINVAL; - goto fail; - } switch(sess->op) { - case NCR_OP_ENCRYPT: - case NCR_OP_DECRYPT: - break; - case NCR_OP_VERIFY: - ret = get_userbuf1(sess, udata, *udata_size, &osg, &osg_cnt); + case NCR_OP_ENCRYPT: + case NCR_OP_DECRYPT: + break; + case NCR_OP_VERIFY: { + struct ncr_session_input_data src; + + nla = tb[NCR_ATTR_FINAL_INPUT_DATA]; + ret = ncr_session_input_data_from_nla(&src, nla, compat); + if (unlikely(ret != 0)) { + err(); + goto fail; + } + + buffer = kmalloc(src.data_size, GFP_KERNEL); + if (buffer == NULL) { + err(); + ret = -ENOMEM; + goto fail; + } + if (unlikely(copy_from_user(buffer, src.data, src.data_size))) { + err(); + ret = -EFAULT; + goto fail; + } + + digest_size = sess->hash.digestsize; + if (digest_size == 0 || sizeof(digest) < digest_size) { + err(); + ret = -EINVAL; + goto fail; + } + ret = cryptodev_hash_final(&sess->hash, digest); + if (ret < 0) { + err(); + goto fail; + } + + if (!sess->algorithm->is_pk) + ret = (digest_size == src.data_size + && memcmp(buffer, digest, digest_size) == 0); + else { + ret = ncr_pk_cipher_verify(&sess->pk, buffer, + src.data_size, digest, + digest_size); if (ret < 0) { err(); goto fail; } - orig_osg_size = osg_size = *udata_size; + } + break; + } - digest_size = sess->hash.digestsize; - if (digest_size == 0 || sizeof(digest) < digest_size) { - err(); - ret = -EINVAL; - goto fail; - } - ret = cryptodev_hash_final(&sess->hash, digest); - if (ret < 0) { + case NCR_OP_SIGN: { + struct ncr_session_output_buffer dst; + size_t output_size; + + nla = tb[NCR_ATTR_FINAL_OUTPUT_BUFFER]; + ret = ncr_session_output_buffer_from_nla(&dst, nla, compat); + if (unlikely(ret != 0)) { + err(); + goto fail; + } + + digest_size = sess->hash.digestsize; + if (digest_size == 0) { + err(); + ret = -EINVAL; + goto fail; + } + + ret = cryptodev_hash_final(&sess->hash, digest); + if (ret < 0) { + err(); + goto fail; + } + + cryptodev_hash_deinit(&sess->hash); + + if (!sess->algorithm->is_pk) { + if (dst.buffer_size < digest_size) { err(); + ret = -ERANGE; goto fail; } - - if (sess->algorithm->is_hmac) { - ret = sg_copy_to_buffer(osg, osg_cnt, vdigest, digest_size); - if (ret != digest_size) { - err(); - ret = -EINVAL; - goto fail; - } - - if (digest_size != osg_size || - memcmp(vdigest, digest, digest_size) != 0) { - - op->err = NCR_VERIFICATION_FAILED; - } else { - op->err = NCR_SUCCESS; - } - } else { - /* PK signature */ - ret = ncr_pk_cipher_verify(&sess->pk, osg, osg_cnt, osg_size, - digest, digest_size, &op->err); - if (ret < 0) { - err(); - goto fail; - } - } - break; - - case NCR_OP_SIGN: - ret = get_userbuf1(sess, udata, *udata_size, &osg, &osg_cnt); - if (ret < 0) { + if (unlikely(copy_to_user(dst.buffer, digest, + digest_size))) { err(); + ret = -EFAULT; goto fail; } - orig_osg_size = osg_size = *udata_size; - - digest_size = sess->hash.digestsize; - if (digest_size == 0 || osg_size < digest_size) { + output_size = digest_size; + } else { + output_size = dst.buffer_size; + buffer = kmalloc(output_size, GFP_KERNEL); + if (buffer == NULL) { err(); - ret = -EINVAL; + ret = -ENOMEM; goto fail; } - - ret = cryptodev_hash_final(&sess->hash, digest); + ret = ncr_pk_cipher_sign(&sess->pk, digest, digest_size, + buffer, &output_size); if (ret < 0) { err(); goto fail; } - - ret = sg_copy_from_buffer(osg, osg_cnt, digest, digest_size); - if (ret != digest_size) { + if (unlikely(copy_to_user(dst.buffer, buffer, + output_size))) { err(); - ret = -EINVAL; + ret = -EFAULT; goto fail; } - osg_size = digest_size; - - cryptodev_hash_deinit(&sess->hash); + } - if (sess->algorithm->is_pk) { - /* PK signature */ - - ret = ncr_pk_cipher_sign(&sess->pk, osg, osg_cnt, osg_size, - osg, osg_cnt, &orig_osg_size); - if (ret < 0) { - err(); - goto fail; - } - osg_size = orig_osg_size; - } - break; - default: + ret = ncr_session_output_buffer_set_size(&dst, output_size, + compat); + if (ret != 0) { err(); - ret = -EINVAL; goto fail; + } + break; + } + default: + err(); + ret = -EINVAL; + goto fail; } - - if (osg_size > 0) - *udata_size = osg_size; - - ret = 0; fail: - if (sess->available_pages) { - release_user_pages(sess->pages, sess->available_pages); - sess->available_pages = 0; - } mutex_unlock(&sess->mem_mutex); + kfree(buffer); cryptodev_hash_deinit(&sess->hash); if (sess->algorithm->is_symmetric) { @@ -914,27 +937,28 @@ fail: } _ncr_sessions_item_put(sess); - _ncr_session_remove(lists, op->ses); + _ncr_session_remove(lists, ses); return ret; } /* Direct with key: Allows to hash a key */ -/* Called when userspace buffers are used */ -static int _ncr_session_update_key(struct ncr_lists* lists, struct ncr_session_op_st* op) +static int _ncr_session_update_key(struct ncr_lists *lists, ncr_session_t ses, + struct nlattr *tb[]) { int ret; struct session_item_st* sess; struct key_item_st* key = NULL; - sess = ncr_sessions_item_get(lists, op->ses); + sess = ncr_sessions_item_get(lists, ses); if (sess == NULL) { err(); return -EINVAL; } /* read key */ - ret = ncr_key_item_get_read( &key, lists, op->data.kdata.input); + ret = key_item_get_nla_read(&key, lists, + tb[NCR_ATTR_UPDATE_INPUT_KEY_AS_DATA]); if (ret < 0) { err(); goto fail; @@ -976,20 +1000,16 @@ fail: return ret; } -int ncr_session_update(struct ncr_lists* lists, void __user* arg) +int ncr_session_update(struct ncr_lists *lists, + const struct ncr_session_update *op, struct nlattr *tb[], + int compat) { - struct ncr_session_op_st op; int ret; - if (unlikely(copy_from_user( &op, arg, sizeof(op)))) { - err(); - return -EFAULT; - } - - if (op.type == NCR_DIRECT_DATA) - ret = _ncr_session_update(lists, &op); - else if (op.type == NCR_KEY_DATA) - ret = _ncr_session_update_key(lists, &op); + if (tb[NCR_ATTR_UPDATE_INPUT_DATA] != NULL) + ret = _ncr_session_update(lists, op->ses, tb, compat); + else if (tb[NCR_ATTR_UPDATE_INPUT_KEY_AS_DATA] != NULL) + ret = _ncr_session_update_key(lists, op->ses, tb); else ret = -EINVAL; @@ -998,61 +1018,33 @@ int ncr_session_update(struct ncr_lists* lists, void __user* arg) return ret; } - if (unlikely(copy_to_user(arg, &op, sizeof(op)))) { - err(); - return -EFAULT; - } - return 0; } -int ncr_session_final(struct ncr_lists* lists, void __user* arg) +int ncr_session_final(struct ncr_lists *lists, + const struct ncr_session_final *op, struct nlattr *tb[], + int compat) { - struct ncr_session_op_st op; - int ret; - - if (unlikely(copy_from_user(&op, arg, sizeof(op)))) { - err(); - return -EFAULT; - } - - ret = _ncr_session_final(lists, &op); - if (unlikely(ret)) { - err(); - return ret; - } - - if (unlikely(copy_to_user(arg, &op, sizeof(op)))) { - err(); - return -EFAULT; - } - return 0; + return _ncr_session_final(lists, op->ses, tb, compat); } -int ncr_session_once(struct ncr_lists* lists, void __user* arg) +int ncr_session_once(struct ncr_lists *lists, + const struct ncr_session_once *once, struct nlattr *tb[], + int compat) { - struct ncr_session_once_op_st kop; int ret; - if (unlikely(copy_from_user(&kop, arg, sizeof(kop)))) { - err(); - return -EFAULT; - } - - ret = _ncr_session_init(lists, &kop.init); + ret = _ncr_session_init(lists, once->op, tb); if (ret < 0) { err(); return ret; } - kop.op.ses = kop.init.ses; - ret = _ncr_session_final(lists, &kop.op); + ret = _ncr_session_final(lists, ret, tb, compat); if (ret < 0) { err(); return ret; } - if (unlikely(copy_to_user(arg, &kop, sizeof(kop)))) - return -EFAULT; - return 0; + return ret; } |