@@ -30,7 +33,7 @@
static inline unsigned long get_desc_base(struct desc_struct *desc)
{
unsigned long base;
- base = ((desc->a >> 16) & 0x0000ffff) |
+ base = (desc->a >> 16) |
Seemingly unrelated.
@@ -28,28 +28,27 @@
}
#endif
-static inline int alloc_ldt(mm_context_t *pc, const int oldsize, int mincount, const int reload)
+static inline int alloc_ldt(mm_context_t *pc, const int old_pages, int new_pages, const int reload)
{
- void *oldldt;
- void *newldt;
+ struct desc_struct *oldldt;
+ struct desc_struct *newldt;
Not quite related here (since change was introduced in earlier patch),
but old alloc_ldt special cased when room was available. This is gone,
so am I reading this correctly, each time through it will allocate a
new one, and free the old one (if it existed)? Just double checking
that change doesn't introduce possible mem leak.
- mincount = (mincount+511)&(~511);
- if (mincount*LDT_ENTRY_SIZE > PAGE_SIZE)
- newldt = vmalloc(mincount*LDT_ENTRY_SIZE);
+ if (new_pages > 1)
+ newldt = vmalloc(new_pages*PAGE_SIZE);
else
- newldt = kmalloc(mincount*LDT_ENTRY_SIZE, GFP_KERNEL);
+ newldt = kmalloc(PAGE_SIZE, GFP_KERNEL);
If so, then full page is likely to be reusable in common case, no? (If
there's such a thing as LDT common case ;-)
if (!newldt)
return -ENOMEM;
- if (oldsize)
- memcpy(newldt, pc->ldt, oldsize*LDT_ENTRY_SIZE);
+ if (old_pages)
+ memcpy(newldt, pc->ldt, old_pages*PAGE_SIZE);
oldldt = pc->ldt;
if (reload)
- memset(newldt+oldsize*LDT_ENTRY_SIZE, 0, (mincount-oldsize)*LDT_ENTRY_SIZE);
+ memset(newldt+old_pages*LDT_ENTRIES_PER_PAGE, 0, (new_pages-old_pages)*PAGE_SIZE);
In fact, I _think_ this causes a problem. Who says newldt is bigger
than old one? This looks like user-triggerable oops to me.
@@ -113,13 +114,13 @@
unsigned long size;
struct mm_struct * mm = current->mm;
- if (!mm->context.size)
+ if (!mm->context.ldt_pages)
return 0;
if (bytecount > LDT_ENTRY_SIZE*LDT_ENTRIES)
bytecount = LDT_ENTRY_SIZE*LDT_ENTRIES;
down(&mm->context.sem);
- size = mm->context.size*LDT_ENTRY_SIZE;
+ size = mm->context.ldt_pages*PAGE_SIZE;
if (size > bytecount)
size = bytecount;
This now looks like you can leak data? Since full page is unlikely
used, but accounting is done in page sizes. Asking to read_ldt with
bytcount of PAGE_SIZE could give some uninitialzed data back to user.
Did I miss the spot where this is always zero-filled?