Commit aa3d1fae authored by Chuck Lever's avatar Chuck Lever Committed by Trond Myklebust

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: default avatarChuck Lever <chuck.lever@oracle.com>
Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent e70c4908
...@@ -736,6 +736,11 @@ static void rpc_async_schedule(struct work_struct *work) ...@@ -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) ...@@ -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) ...@@ -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
......
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