Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

x86, pat: Fix memory leak in free_memtype

Reserve_memtype will allocate memory for new memtype, but
in free_memtype, after the memtype erased from rbtree, the
memory is not freed.

Changes since V1:
make rbt_memtype_erase return erased memtype so that
it can be freed in free_memtype.

[ hpa: not for -stable: 2.6.34 and earlier not affected ]

Signed-off-by: Xiaotian Feng <dfeng@redhat.com>
LKML-Reference: <1274838670-8731-1-git-send-email-dfeng@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
Cc: Jack Steiner <steiner@sgi.com>
Acked-by: Suresh Siddha <suresh.b.siddha@intel.com>
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>

authored by

Xiaotian Feng and committed by
H. Peter Anvin
20413f27 fe501f1e

+14 -9
+7 -3
arch/x86/mm/pat.c
··· 336 336 { 337 337 int err = -EINVAL; 338 338 int is_range_ram; 339 + struct memtype *entry; 339 340 340 341 if (!pat_enabled) 341 342 return 0; ··· 356 355 } 357 356 358 357 spin_lock(&memtype_lock); 359 - err = rbt_memtype_erase(start, end); 358 + entry = rbt_memtype_erase(start, end); 360 359 spin_unlock(&memtype_lock); 361 360 362 - if (err) { 361 + if (!entry) { 363 362 printk(KERN_INFO "%s:%d freeing invalid memtype %Lx-%Lx\n", 364 363 current->comm, current->pid, start, end); 364 + return -EINVAL; 365 365 } 366 + 367 + kfree(entry); 366 368 367 369 dprintk("free_memtype request 0x%Lx-0x%Lx\n", start, end); 368 370 369 - return err; 371 + return 0; 370 372 } 371 373 372 374
+3 -3
arch/x86/mm/pat_internal.h
··· 28 28 #ifdef CONFIG_X86_PAT 29 29 extern int rbt_memtype_check_insert(struct memtype *new, 30 30 unsigned long *new_type); 31 - extern int rbt_memtype_erase(u64 start, u64 end); 31 + extern struct memtype *rbt_memtype_erase(u64 start, u64 end); 32 32 extern struct memtype *rbt_memtype_lookup(u64 addr); 33 33 extern int rbt_memtype_copy_nth_element(struct memtype *out, loff_t pos); 34 34 #else 35 35 static inline int rbt_memtype_check_insert(struct memtype *new, 36 36 unsigned long *new_type) 37 37 { return 0; } 38 - static inline int rbt_memtype_erase(u64 start, u64 end) 39 - { return 0; } 38 + static inline struct memtype *rbt_memtype_erase(u64 start, u64 end) 39 + { return NULL; } 40 40 static inline struct memtype *rbt_memtype_lookup(u64 addr) 41 41 { return NULL; } 42 42 static inline int rbt_memtype_copy_nth_element(struct memtype *out, loff_t pos)
+4 -3
arch/x86/mm/pat_rbtree.c
··· 231 231 return err; 232 232 } 233 233 234 - int rbt_memtype_erase(u64 start, u64 end) 234 + struct memtype *rbt_memtype_erase(u64 start, u64 end) 235 235 { 236 236 struct memtype *data; 237 237 238 238 data = memtype_rb_exact_match(&memtype_rbroot, start, end); 239 239 if (!data) 240 - return -EINVAL; 240 + goto out; 241 241 242 242 rb_erase(&data->rb, &memtype_rbroot); 243 - return 0; 243 + out: 244 + return data; 244 245 } 245 246 246 247 struct memtype *rbt_memtype_lookup(u64 addr)