Commit 0c7d400f authored by Herbert Xu's avatar Herbert Xu

crypto: skcipher - Fix skcipher_dequeue_givcrypt NULL test

As struct skcipher_givcrypt_request includes struct crypto_request
at a non-zero offset, testing for NULL after converting the pointer
returned by crypto_dequeue_request does not work.  This can result
in IPsec crashes when the queue is depleted.

This patch fixes it by doing the pointer conversion only when the
return value is non-NULL.  In particular, we create a new function
__crypto_dequeue_request that does the pointer conversion.
Reported-by: default avatarBrad Bosch <bradbosch@comcast.net>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent b6f34d44
...@@ -692,7 +692,7 @@ int crypto_enqueue_request(struct crypto_queue *queue, ...@@ -692,7 +692,7 @@ int crypto_enqueue_request(struct crypto_queue *queue,
} }
EXPORT_SYMBOL_GPL(crypto_enqueue_request); EXPORT_SYMBOL_GPL(crypto_enqueue_request);
struct crypto_async_request *crypto_dequeue_request(struct crypto_queue *queue) void *__crypto_dequeue_request(struct crypto_queue *queue, unsigned int offset)
{ {
struct list_head *request; struct list_head *request;
...@@ -707,7 +707,14 @@ struct crypto_async_request *crypto_dequeue_request(struct crypto_queue *queue) ...@@ -707,7 +707,14 @@ struct crypto_async_request *crypto_dequeue_request(struct crypto_queue *queue)
request = queue->list.next; request = queue->list.next;
list_del(request); list_del(request);
return list_entry(request, struct crypto_async_request, list); return (char *)list_entry(request, struct crypto_async_request, list) -
offset;
}
EXPORT_SYMBOL_GPL(__crypto_dequeue_request);
struct crypto_async_request *crypto_dequeue_request(struct crypto_queue *queue)
{
return __crypto_dequeue_request(queue, 0);
} }
EXPORT_SYMBOL_GPL(crypto_dequeue_request); EXPORT_SYMBOL_GPL(crypto_dequeue_request);
......
...@@ -137,6 +137,7 @@ struct crypto_instance *crypto_alloc_instance(const char *name, ...@@ -137,6 +137,7 @@ struct crypto_instance *crypto_alloc_instance(const char *name,
void crypto_init_queue(struct crypto_queue *queue, unsigned int max_qlen); void crypto_init_queue(struct crypto_queue *queue, unsigned int max_qlen);
int crypto_enqueue_request(struct crypto_queue *queue, int crypto_enqueue_request(struct crypto_queue *queue,
struct crypto_async_request *request); struct crypto_async_request *request);
void *__crypto_dequeue_request(struct crypto_queue *queue, unsigned int offset);
struct crypto_async_request *crypto_dequeue_request(struct crypto_queue *queue); struct crypto_async_request *crypto_dequeue_request(struct crypto_queue *queue);
int crypto_tfm_in_queue(struct crypto_queue *queue, struct crypto_tfm *tfm); int crypto_tfm_in_queue(struct crypto_queue *queue, struct crypto_tfm *tfm);
......
...@@ -79,8 +79,8 @@ static inline int skcipher_enqueue_givcrypt( ...@@ -79,8 +79,8 @@ static inline int skcipher_enqueue_givcrypt(
static inline struct skcipher_givcrypt_request *skcipher_dequeue_givcrypt( static inline struct skcipher_givcrypt_request *skcipher_dequeue_givcrypt(
struct crypto_queue *queue) struct crypto_queue *queue)
{ {
return container_of(ablkcipher_dequeue_request(queue), return __crypto_dequeue_request(
struct skcipher_givcrypt_request, creq); queue, offsetof(struct skcipher_givcrypt_request, creq.base));
} }
static inline void *skcipher_givcrypt_reqctx( static inline void *skcipher_givcrypt_reqctx(
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment