aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/sched.c
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2007-05-08 18:23:28 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2007-05-09 17:57:59 -0400
commitaa3d1faebe6e214cd96be0e587571477ff6fd9fc (patch)
treed2295c15e30437a2bc693bd71b79a42c742ffc8b /net/sunrpc/sched.c
parente70c490810dc683fad39e57cf00e69d5f120c542 (diff)
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>
Diffstat (limited to 'net/sunrpc/sched.c')
-rw-r--r--net/sunrpc/sched.c22
1 files changed, 15 insertions, 7 deletions
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index 99014516b73c..b28a0b037f4f 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -736,6 +736,11 @@ static void rpc_async_schedule(struct work_struct *work)
736 __rpc_execute(container_of(work, struct rpc_task, u.tk_work)); 736 __rpc_execute(container_of(work, struct rpc_task, u.tk_work));
737} 737}
738 738
739struct rpc_buffer {
740 size_t len;
741 char data[];
742};
743
739/** 744/**
740 * rpc_malloc - allocate an RPC buffer 745 * rpc_malloc - allocate an RPC buffer
741 * @task: RPC task that will use this buffer 746 * @task: RPC task that will use this buffer
@@ -754,18 +759,18 @@ static void rpc_async_schedule(struct work_struct *work)
754 */ 759 */
755void *rpc_malloc(struct rpc_task *task, size_t size) 760void *rpc_malloc(struct rpc_task *task, size_t size)
756{ 761{
757 size_t *buf; 762 struct rpc_buffer *buf;
758 gfp_t gfp = RPC_IS_SWAPPER(task) ? GFP_ATOMIC : GFP_NOWAIT; 763 gfp_t gfp = RPC_IS_SWAPPER(task) ? GFP_ATOMIC : GFP_NOWAIT;
759 764
760 size += sizeof(size_t); 765 size += sizeof(struct rpc_buffer);
761 if (size <= RPC_BUFFER_MAXSIZE) 766 if (size <= RPC_BUFFER_MAXSIZE)
762 buf = mempool_alloc(rpc_buffer_mempool, gfp); 767 buf = mempool_alloc(rpc_buffer_mempool, gfp);
763 else 768 else
764 buf = kmalloc(size, gfp); 769 buf = kmalloc(size, gfp);
765 *buf = size; 770 buf->len = size;
766 dprintk("RPC: %5u allocated buffer of size %zu at %p\n", 771 dprintk("RPC: %5u allocated buffer of size %zu at %p\n",
767 task->tk_pid, size, buf); 772 task->tk_pid, size, buf);
768 return ++buf; 773 return &buf->data;
769} 774}
770 775
771/** 776/**
@@ -775,15 +780,18 @@ void *rpc_malloc(struct rpc_task *task, size_t size)
775 */ 780 */
776void rpc_free(void *buffer) 781void rpc_free(void *buffer)
777{ 782{
778 size_t size, *buf = buffer; 783 size_t size;
784 struct rpc_buffer *buf;
779 785
780 if (!buffer) 786 if (!buffer)
781 return; 787 return;
782 size = *buf; 788
783 buf--; 789 buf = container_of(buffer, struct rpc_buffer, data);
790 size = buf->len;
784 791
785 dprintk("RPC: freeing buffer of size %zu at %p\n", 792 dprintk("RPC: freeing buffer of size %zu at %p\n",
786 size, buf); 793 size, buf);
794
787 if (size <= RPC_BUFFER_MAXSIZE) 795 if (size <= RPC_BUFFER_MAXSIZE)
788 mempool_free(buf, rpc_buffer_mempool); 796 mempool_free(buf, rpc_buffer_mempool);
789 else 797 else