Fix potential kfree on vmalloc-ed area of request_sock_queue
Subsystems (3)
PATCH 1/2 Fix potential kfree on vmalloc-ed area of request_sock_queue
The request_sock_queue's listen_opt is either vmalloc-ed or kmalloc-ed depending on the number of table entries. Thus it is expected to be handled properly on free, which is done in the reqsk_queue_destroy().
However the error path in inet_csk_listen_start() calls the lite version of reqsk_queue_destroy, called __reqsk_queue_destroy, which calls the kfree unconditionally.
Fix this and move the __reqsk_queue_destroy into a .c file as it looks too big to be inline.
---
include/net/request_sock.h +1 -5
@@ -136,11 +136,7 @@ static inline struct listen_sock *reqsk_queue_yank_listen_sk(struct request_sockreturn lopt; } -static inline void __reqsk_queue_destroy (struct request_sock_queue *queue) -{ -kfree (reqsk_queue_yank_listen_sk (queue)); -} - +extern void __reqsk_queue_destroy (struct request_sock_queue *queue);extern void reqsk_queue_destroy (struct request_sock_queue *queue); static inline struct request_sock *
net/core/request_sock.c +14 -0
@@ -71,6 +71,20 @@ int reqsk_queue_alloc(struct request_sock_queue *queue,EXPORT_SYMBOL (reqsk_queue_alloc); +void __reqsk_queue_destroy (struct request_sock_queue *queue) +{ +struct listen_sock *lopt =reqsk_queue_yank_listen_sk (queue); +size_t lopt_size =sizeof (struct listen_sock ) + + lopt->nr_table_entries *sizeof (struct request_sock *); + +if (lopt_size >PAGE_SIZE ) +vfree (lopt); +else +kfree (lopt); +} + +EXPORT_SYMBOL (__reqsk_queue_destroy); +void reqsk_queue_destroy (struct request_sock_queue *queue) {/* make all the listen_opt local to us */
Quoted 17 lines · On Wed, 14 Nov 2007 21:08:29 +0300 Pavel Emelyanov <[email protected]> wrote:
The request_sock_queue's
listen_optis either vmalloc-ed or kmalloc-ed depending on the number of table entries. Thus it is expected to be handled properly on free, which is done in thereqsk_queue_destroy().However the error path in
inet_csk_listen_start()calls the lite version ofreqsk_queue_destroy, called__reqsk_queue_destroy, which calls the kfree unconditionally.Fix this and move the
__reqsk_queue_destroyinto a .c file as it looks too big to be inline.Signed-off-by Pavel Emelyanov <[email protected]>---
net/core/request_sock.c int reqsk_queue_alloc(struct request_sock_queue *queue, · line 76
Quoted 3 lines
net/core/request_sock.c +3
-0+void __reqsk_queue_destroy (struct request_sock_queue *queue) +{ +struct listen_sock *lopt =reqsk_queue_yank_listen_sk (queue);
WARNING : lopt can be NULL here (or else the locking in reqsk_queue_yank_listen_sk() would be useless ?)
kfree(NULL) was ok, not NULL->nr_table_entries :)
Quoted 8 lines
net/core/request_sock.c +8
-0+size_t lopt_size =sizeof (struct listen_sock ) + + lopt->nr_table_entries *sizeof (struct request_sock *); + +if (lopt_size >PAGE_SIZE ) +vfree (lopt); +else +kfree (lopt); +}
David Miller
maintainerFrom: Eric Dumazet <[email protected]>
Date: Wed, 14 Nov 2007 20:42:38 +0100
Quoted 20 lines
Quoted 16 lines · On Wed, 14 Nov 2007 21:08:29 +0300 Pavel Emelyanov <[email protected]> wrote:
The request_sock_queue's
listen_optis either vmalloc-ed or kmalloc-ed depending on the number of table entries. Thus it is expected to be handled properly on free, which is done in thereqsk_queue_destroy().However the error path in
inet_csk_listen_start()calls the lite version ofreqsk_queue_destroy, called__reqsk_queue_destroy, which calls the kfree unconditionally.Fix this and move the
__reqsk_queue_destroyinto a .c file as it looks too big to be inline.Signed-off-by Pavel Emelyanov <[email protected]>---
Quoted 7 lines
net/core/request_sock.c int reqsk_queue_alloc(struct request_sock_queue *queue, · line 76
Quoted 3 lines
net/core/request_sock.c +3
-0+void __reqsk_queue_destroy (struct request_sock_queue *queue) +{ +struct listen_sock *lopt =reqsk_queue_yank_listen_sk (queue);WARNING : lopt can be NULL here (or else the locking in
reqsk_queue_yank_listen_sk()would be useless ?)kfree(NULL) was ok, not
NULL->nr_table_entries:)
I think for the error recovery case he is trying to fix all of this locking is unnecessary and we know lopt is not NULL.
Pavel can you rework your fix a bit to deal with this?
Thanks a lot.