SUNRPC: Fix pointer arithmetic bug recently introduced in rpc_malloc/free
Use a cleaner method to find the size of an rpc_buffer. This actually works on x86-64! Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
This commit is contained in:
committed by
Trond Myklebust
parent
e70c490810
commit
aa3d1faebe
@@ -736,6 +736,11 @@ static void rpc_async_schedule(struct work_struct *work)
|
|||||||
__rpc_execute(container_of(work, struct rpc_task, u.tk_work));
|
__rpc_execute(container_of(work, struct rpc_task, u.tk_work));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct rpc_buffer {
|
||||||
|
size_t len;
|
||||||
|
char data[];
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* rpc_malloc - allocate an RPC buffer
|
* rpc_malloc - allocate an RPC buffer
|
||||||
* @task: RPC task that will use this buffer
|
* @task: RPC task that will use this buffer
|
||||||
@@ -754,18 +759,18 @@ static void rpc_async_schedule(struct work_struct *work)
|
|||||||
*/
|
*/
|
||||||
void *rpc_malloc(struct rpc_task *task, size_t size)
|
void *rpc_malloc(struct rpc_task *task, size_t size)
|
||||||
{
|
{
|
||||||
size_t *buf;
|
struct rpc_buffer *buf;
|
||||||
gfp_t gfp = RPC_IS_SWAPPER(task) ? GFP_ATOMIC : GFP_NOWAIT;
|
gfp_t gfp = RPC_IS_SWAPPER(task) ? GFP_ATOMIC : GFP_NOWAIT;
|
||||||
|
|
||||||
size += sizeof(size_t);
|
size += sizeof(struct rpc_buffer);
|
||||||
if (size <= RPC_BUFFER_MAXSIZE)
|
if (size <= RPC_BUFFER_MAXSIZE)
|
||||||
buf = mempool_alloc(rpc_buffer_mempool, gfp);
|
buf = mempool_alloc(rpc_buffer_mempool, gfp);
|
||||||
else
|
else
|
||||||
buf = kmalloc(size, gfp);
|
buf = kmalloc(size, gfp);
|
||||||
*buf = size;
|
buf->len = size;
|
||||||
dprintk("RPC: %5u allocated buffer of size %zu at %p\n",
|
dprintk("RPC: %5u allocated buffer of size %zu at %p\n",
|
||||||
task->tk_pid, size, buf);
|
task->tk_pid, size, buf);
|
||||||
return ++buf;
|
return &buf->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -775,15 +780,18 @@ void *rpc_malloc(struct rpc_task *task, size_t size)
|
|||||||
*/
|
*/
|
||||||
void rpc_free(void *buffer)
|
void rpc_free(void *buffer)
|
||||||
{
|
{
|
||||||
size_t size, *buf = buffer;
|
size_t size;
|
||||||
|
struct rpc_buffer *buf;
|
||||||
|
|
||||||
if (!buffer)
|
if (!buffer)
|
||||||
return;
|
return;
|
||||||
size = *buf;
|
|
||||||
buf--;
|
buf = container_of(buffer, struct rpc_buffer, data);
|
||||||
|
size = buf->len;
|
||||||
|
|
||||||
dprintk("RPC: freeing buffer of size %zu at %p\n",
|
dprintk("RPC: freeing buffer of size %zu at %p\n",
|
||||||
size, buf);
|
size, buf);
|
||||||
|
|
||||||
if (size <= RPC_BUFFER_MAXSIZE)
|
if (size <= RPC_BUFFER_MAXSIZE)
|
||||||
mempool_free(buf, rpc_buffer_mempool);
|
mempool_free(buf, rpc_buffer_mempool);
|
||||||
else
|
else
|
||||||
|
Reference in New Issue
Block a user