5/10 ----------------------------
commit 66329cffcdf3124b6b391e20b39568a2c031bd77 Author: Jaren Johnston <jaren's email> Date: Fri Jun 8 15:48:57 2012 -0700 handle null IO buffers gracefully Change-Id: I9039b49d719318e82dd30845029081b162c759e9 diff --git a/zc.c b/zc.c index ce929f0..96a011d 100644 --- a/zc.c +++ b/zc.c @@ -135,71 +135,86 @@ int get_userbuf(struct csession *ses, struct scatterlist **src_sg, struct scatterlist **dst_sg) { - int src_pagecount, dst_pagecount = 0, pagecount, write_src = 1; + int src_pagecount, dst_pagecount; int rc; - if (src == NULL) - return -EINVAL; + /* Empty input is a valid option to many algorithms & is tested by NIST/FIPS */ + /* Make sure NULL input has 0 length */ + if (!src && src_len) { src_len = 0; } + + /* I don't know that null output is ever useful, but we can handle it gracefully */ + /* Make sure NULL output has 0 length */ + if (!dst && dst_len) { dst_len = 0; } if (ses->alignmask && !IS_ALIGNED((unsigned long)src, ses->alignmask)) { dprintk(2, KERN_WARNING, "%s: careful - source address %lx is not %d byte aligned\n", __func__, (unsigned long)src, ses->alignmask + 1); } - if (src == dst) { - /* dst == src */ - src_len = max(src_len, dst_len); - dst_len = src_len; - } + if (ses->alignmask && !IS_ALIGNED((unsigned long)dst, ses->alignmask)) { + dprintk(2, KERN_WARNING, "%s: careful - destination address %lx is not %d byte aligned\n", + __func__, (unsigned long)dst, ses->alignmask + 1); + } src_pagecount = PAGECOUNT(src, src_len); - if (!ses->cdata.init) { /* hashing only */ - write_src = 0; - } else if (src != dst) { /* non-in-situ transformation */ - if (dst == NULL) - return -EINVAL; + dst_pagecount = PAGECOUNT(dst, dst_len); - dst_pagecount = PAGECOUNT(dst, dst_len); - write_src = 0; + ses->used_pages = (src == dst) ? max(src_pagecount, dst_pagecount) + : src_pagecount + dst_pagecount; - if (ses->alignmask && !IS_ALIGNED((unsigned long)dst, ses->alignmask)) { - dprintk(2, KERN_WARNING, "%s: careful - destination address %lx is not %d byte aligned\n", - __func__, (unsigned long)dst, ses->alignmask + 1); - } - } - ses->used_pages = pagecount = src_pagecount + dst_pagecount; + ses->readonly_pages = (src == dst) ? 0 : src_pagecount; - if (write_src) ses->readonly_pages = 0; - else ses->readonly_pages = src_pagecount; - - if (pagecount > ses->array_size) { - rc = adjust_sg_array(ses, pagecount); + if (ses->used_pages > ses->array_size) { + rc = adjust_sg_array(ses, ses->used_pages); if (rc) return rc; } - rc = __get_userbuf(src, src_len, write_src, src_pagecount, - ses->pages, ses->sg, task, mm); - if (unlikely(rc)) { - dprintk(1, KERN_ERR, - "failed to get user pages for data input\n"); - return -EINVAL; + if (src == dst) { + rc = __get_userbuf(src, src_len, 1, ses->used_pages, + ses->pages, ses->sg, task, mm); + if (unlikely(rc)) { + dprintk(1, KERN_ERR, + "failed to get user pages for data IO\n"); + return rc; + } + (*src_sg) = (*dst_sg) = ses->sg; } - (*src_sg) = (*dst_sg) = ses->sg; - - if (!dst_pagecount) - return 0; - - (*dst_sg) = ses->sg + src_pagecount; - - rc = __get_userbuf(dst, dst_len, 1, dst_pagecount, - ses->pages + src_pagecount, *dst_sg, - task, mm); - if (unlikely(rc)) { - dprintk(1, KERN_ERR, - "failed to get user pages for data output\n"); - release_user_pages(ses); - return -EINVAL; + else { + const unsigned int readonly_pages = ses->readonly_pages; + const unsigned int writable_pages = ses->used_pages - readonly_pages; + + if(likely(src)) { + rc = __get_userbuf(src, src_len, 0, readonly_pages, + ses->pages, ses->sg, task, mm); + if (unlikely(rc)) { + dprintk(1, KERN_ERR, + "failed to get user pages for data input\n"); + return rc; + } + *src_sg = ses->sg; + } + else { + *src_sg = NULL; // no input + } + + if(likely(dst)) { + struct page **dst_pages = ses->pages + readonly_pages; + *dst_sg = ses->sg + readonly_pages; + + rc = __get_userbuf(dst, dst_len, 1, writable_pages, + dst_pages, *dst_sg, task, mm); + if (unlikely(rc)) { + dprintk(1, KERN_ERR, + "failed to get user pages for data output\n"); + release_user_pages(ses); /* FIXME: use __release_userbuf(src, ...) */ + return rc; + } + } + else { + *dst_sg = NULL; // ignore output + } } return 0; } +
_______________________________________________ Cryptodev-linux-devel mailing list Cryptodev-linux-devel@gna.org https://mail.gna.org/listinfo/cryptodev-linux-devel