15c48b108SAl Viro /*
25c48b108SAl Viro * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
35c48b108SAl Viro * Licensed under the GPL
45c48b108SAl Viro */
55c48b108SAl Viro
65c48b108SAl Viro #include <linux/mm.h>
75c48b108SAl Viro #include <linux/sched.h>
85c48b108SAl Viro #include <linux/slab.h>
9da20ab35SDave Hansen #include <linux/syscalls.h>
101d04c8d7SRichard Weinberger #include <linux/uaccess.h>
115c48b108SAl Viro #include <asm/unistd.h>
1237185b33SAl Viro #include <os.h>
1337185b33SAl Viro #include <skas.h>
1437185b33SAl Viro #include <sysdep/tls.h>
155c48b108SAl Viro
modify_ldt(int func,void * ptr,unsigned long bytecount)1637e81a01SHans-Werner Hilse static inline int modify_ldt (int func, void *ptr, unsigned long bytecount)
1737e81a01SHans-Werner Hilse {
1837e81a01SHans-Werner Hilse return syscall(__NR_modify_ldt, func, ptr, bytecount);
1937e81a01SHans-Werner Hilse }
205c48b108SAl Viro
write_ldt_entry(struct mm_id * mm_idp,int func,struct user_desc * desc,void ** addr,int done)215c48b108SAl Viro static long write_ldt_entry(struct mm_id *mm_idp, int func,
225c48b108SAl Viro struct user_desc *desc, void **addr, int done)
235c48b108SAl Viro {
245c48b108SAl Viro long res;
255c48b108SAl Viro void *stub_addr;
26*2a4a62a1SVincent Whitchurch
27*2a4a62a1SVincent Whitchurch BUILD_BUG_ON(sizeof(*desc) % sizeof(long));
28*2a4a62a1SVincent Whitchurch
295c48b108SAl Viro res = syscall_stub_data(mm_idp, (unsigned long *)desc,
30*2a4a62a1SVincent Whitchurch sizeof(*desc) / sizeof(long),
315c48b108SAl Viro addr, &stub_addr);
325c48b108SAl Viro if (!res) {
335c48b108SAl Viro unsigned long args[] = { func,
345c48b108SAl Viro (unsigned long)stub_addr,
355c48b108SAl Viro sizeof(*desc),
365c48b108SAl Viro 0, 0, 0 };
375c48b108SAl Viro res = run_syscall_stub(mm_idp, __NR_modify_ldt, args,
385c48b108SAl Viro 0, addr, done);
395c48b108SAl Viro }
405c48b108SAl Viro
415c48b108SAl Viro return res;
425c48b108SAl Viro }
435c48b108SAl Viro
445c48b108SAl Viro /*
455c48b108SAl Viro * In skas mode, we hold our own ldt data in UML.
465c48b108SAl Viro * Thus, the code implementing sys_modify_ldt_skas
475c48b108SAl Viro * is very similar to (and mostly stolen from) sys_modify_ldt
485c48b108SAl Viro * for arch/i386/kernel/ldt.c
495c48b108SAl Viro * The routines copied and modified in part are:
505c48b108SAl Viro * - read_ldt
515c48b108SAl Viro * - read_default_ldt
525c48b108SAl Viro * - write_ldt
535c48b108SAl Viro * - sys_modify_ldt_skas
545c48b108SAl Viro */
555c48b108SAl Viro
read_ldt(void __user * ptr,unsigned long bytecount)565c48b108SAl Viro static int read_ldt(void __user * ptr, unsigned long bytecount)
575c48b108SAl Viro {
585c48b108SAl Viro int i, err = 0;
595c48b108SAl Viro unsigned long size;
60b3ee571eSAl Viro uml_ldt_t *ldt = ¤t->mm->context.arch.ldt;
615c48b108SAl Viro
625c48b108SAl Viro if (!ldt->entry_count)
635c48b108SAl Viro goto out;
645c48b108SAl Viro if (bytecount > LDT_ENTRY_SIZE*LDT_ENTRIES)
655c48b108SAl Viro bytecount = LDT_ENTRY_SIZE*LDT_ENTRIES;
665c48b108SAl Viro err = bytecount;
675c48b108SAl Viro
685c48b108SAl Viro mutex_lock(&ldt->lock);
695c48b108SAl Viro if (ldt->entry_count <= LDT_DIRECT_ENTRIES) {
705c48b108SAl Viro size = LDT_ENTRY_SIZE*LDT_DIRECT_ENTRIES;
715c48b108SAl Viro if (size > bytecount)
725c48b108SAl Viro size = bytecount;
735c48b108SAl Viro if (copy_to_user(ptr, ldt->u.entries, size))
745c48b108SAl Viro err = -EFAULT;
755c48b108SAl Viro bytecount -= size;
765c48b108SAl Viro ptr += size;
775c48b108SAl Viro }
785c48b108SAl Viro else {
795c48b108SAl Viro for (i=0; i<ldt->entry_count/LDT_ENTRIES_PER_PAGE && bytecount;
805c48b108SAl Viro i++) {
815c48b108SAl Viro size = PAGE_SIZE;
825c48b108SAl Viro if (size > bytecount)
835c48b108SAl Viro size = bytecount;
845c48b108SAl Viro if (copy_to_user(ptr, ldt->u.pages[i], size)) {
855c48b108SAl Viro err = -EFAULT;
865c48b108SAl Viro break;
875c48b108SAl Viro }
885c48b108SAl Viro bytecount -= size;
895c48b108SAl Viro ptr += size;
905c48b108SAl Viro }
915c48b108SAl Viro }
925c48b108SAl Viro mutex_unlock(&ldt->lock);
935c48b108SAl Viro
945c48b108SAl Viro if (bytecount == 0 || err == -EFAULT)
955c48b108SAl Viro goto out;
965c48b108SAl Viro
975c48b108SAl Viro if (clear_user(ptr, bytecount))
985c48b108SAl Viro err = -EFAULT;
995c48b108SAl Viro
1005c48b108SAl Viro out:
1015c48b108SAl Viro return err;
1025c48b108SAl Viro }
1035c48b108SAl Viro
read_default_ldt(void __user * ptr,unsigned long bytecount)1045c48b108SAl Viro static int read_default_ldt(void __user * ptr, unsigned long bytecount)
1055c48b108SAl Viro {
1065c48b108SAl Viro int err;
1075c48b108SAl Viro
1085c48b108SAl Viro if (bytecount > 5*LDT_ENTRY_SIZE)
1095c48b108SAl Viro bytecount = 5*LDT_ENTRY_SIZE;
1105c48b108SAl Viro
1115c48b108SAl Viro err = bytecount;
1125c48b108SAl Viro /*
1135c48b108SAl Viro * UML doesn't support lcall7 and lcall27.
1145c48b108SAl Viro * So, we don't really have a default ldt, but emulate
1155c48b108SAl Viro * an empty ldt of common host default ldt size.
1165c48b108SAl Viro */
1175c48b108SAl Viro if (clear_user(ptr, bytecount))
1185c48b108SAl Viro err = -EFAULT;
1195c48b108SAl Viro
1205c48b108SAl Viro return err;
1215c48b108SAl Viro }
1225c48b108SAl Viro
write_ldt(void __user * ptr,unsigned long bytecount,int func)1235c48b108SAl Viro static int write_ldt(void __user * ptr, unsigned long bytecount, int func)
1245c48b108SAl Viro {
125b3ee571eSAl Viro uml_ldt_t *ldt = ¤t->mm->context.arch.ldt;
1265c48b108SAl Viro struct mm_id * mm_idp = ¤t->mm->context.id;
1275c48b108SAl Viro int i, err;
1285c48b108SAl Viro struct user_desc ldt_info;
1295c48b108SAl Viro struct ldt_entry entry0, *ldt_p;
1305c48b108SAl Viro void *addr = NULL;
1315c48b108SAl Viro
1325c48b108SAl Viro err = -EINVAL;
1335c48b108SAl Viro if (bytecount != sizeof(ldt_info))
1345c48b108SAl Viro goto out;
1355c48b108SAl Viro err = -EFAULT;
1365c48b108SAl Viro if (copy_from_user(&ldt_info, ptr, sizeof(ldt_info)))
1375c48b108SAl Viro goto out;
1385c48b108SAl Viro
1395c48b108SAl Viro err = -EINVAL;
1405c48b108SAl Viro if (ldt_info.entry_number >= LDT_ENTRIES)
1415c48b108SAl Viro goto out;
1425c48b108SAl Viro if (ldt_info.contents == 3) {
1435c48b108SAl Viro if (func == 1)
1445c48b108SAl Viro goto out;
1455c48b108SAl Viro if (ldt_info.seg_not_present == 0)
1465c48b108SAl Viro goto out;
1475c48b108SAl Viro }
1485c48b108SAl Viro
1495c48b108SAl Viro mutex_lock(&ldt->lock);
1505c48b108SAl Viro
1515c48b108SAl Viro err = write_ldt_entry(mm_idp, func, &ldt_info, &addr, 1);
1525c48b108SAl Viro if (err)
1535c48b108SAl Viro goto out_unlock;
1545c48b108SAl Viro
1555c48b108SAl Viro if (ldt_info.entry_number >= ldt->entry_count &&
1565c48b108SAl Viro ldt_info.entry_number >= LDT_DIRECT_ENTRIES) {
1575c48b108SAl Viro for (i=ldt->entry_count/LDT_ENTRIES_PER_PAGE;
1585c48b108SAl Viro i*LDT_ENTRIES_PER_PAGE <= ldt_info.entry_number;
1595c48b108SAl Viro i++) {
1605c48b108SAl Viro if (i == 0)
1615c48b108SAl Viro memcpy(&entry0, ldt->u.entries,
1625c48b108SAl Viro sizeof(entry0));
1635c48b108SAl Viro ldt->u.pages[i] = (struct ldt_entry *)
1645c48b108SAl Viro __get_free_page(GFP_KERNEL|__GFP_ZERO);
1655c48b108SAl Viro if (!ldt->u.pages[i]) {
1665c48b108SAl Viro err = -ENOMEM;
1675c48b108SAl Viro /* Undo the change in host */
1685c48b108SAl Viro memset(&ldt_info, 0, sizeof(ldt_info));
1695c48b108SAl Viro write_ldt_entry(mm_idp, 1, &ldt_info, &addr, 1);
1705c48b108SAl Viro goto out_unlock;
1715c48b108SAl Viro }
1725c48b108SAl Viro if (i == 0) {
1735c48b108SAl Viro memcpy(ldt->u.pages[0], &entry0,
1745c48b108SAl Viro sizeof(entry0));
1755c48b108SAl Viro memcpy(ldt->u.pages[0]+1, ldt->u.entries+1,
1765c48b108SAl Viro sizeof(entry0)*(LDT_DIRECT_ENTRIES-1));
1775c48b108SAl Viro }
1785c48b108SAl Viro ldt->entry_count = (i + 1) * LDT_ENTRIES_PER_PAGE;
1795c48b108SAl Viro }
1805c48b108SAl Viro }
1815c48b108SAl Viro if (ldt->entry_count <= ldt_info.entry_number)
1825c48b108SAl Viro ldt->entry_count = ldt_info.entry_number + 1;
1835c48b108SAl Viro
1845c48b108SAl Viro if (ldt->entry_count <= LDT_DIRECT_ENTRIES)
1855c48b108SAl Viro ldt_p = ldt->u.entries + ldt_info.entry_number;
1865c48b108SAl Viro else
1875c48b108SAl Viro ldt_p = ldt->u.pages[ldt_info.entry_number/LDT_ENTRIES_PER_PAGE] +
1885c48b108SAl Viro ldt_info.entry_number%LDT_ENTRIES_PER_PAGE;
1895c48b108SAl Viro
1905c48b108SAl Viro if (ldt_info.base_addr == 0 && ldt_info.limit == 0 &&
1915c48b108SAl Viro (func == 1 || LDT_empty(&ldt_info))) {
1925c48b108SAl Viro ldt_p->a = 0;
1935c48b108SAl Viro ldt_p->b = 0;
1945c48b108SAl Viro }
1955c48b108SAl Viro else{
1965c48b108SAl Viro if (func == 1)
1975c48b108SAl Viro ldt_info.useable = 0;
1985c48b108SAl Viro ldt_p->a = LDT_entry_a(&ldt_info);
1995c48b108SAl Viro ldt_p->b = LDT_entry_b(&ldt_info);
2005c48b108SAl Viro }
2015c48b108SAl Viro err = 0;
2025c48b108SAl Viro
2035c48b108SAl Viro out_unlock:
2045c48b108SAl Viro mutex_unlock(&ldt->lock);
2055c48b108SAl Viro out:
2065c48b108SAl Viro return err;
2075c48b108SAl Viro }
2085c48b108SAl Viro
do_modify_ldt_skas(int func,void __user * ptr,unsigned long bytecount)2095c48b108SAl Viro static long do_modify_ldt_skas(int func, void __user *ptr,
2105c48b108SAl Viro unsigned long bytecount)
2115c48b108SAl Viro {
2125c48b108SAl Viro int ret = -ENOSYS;
2135c48b108SAl Viro
2145c48b108SAl Viro switch (func) {
2155c48b108SAl Viro case 0:
2165c48b108SAl Viro ret = read_ldt(ptr, bytecount);
2175c48b108SAl Viro break;
2185c48b108SAl Viro case 1:
2195c48b108SAl Viro case 0x11:
2205c48b108SAl Viro ret = write_ldt(ptr, bytecount, func);
2215c48b108SAl Viro break;
2225c48b108SAl Viro case 2:
2235c48b108SAl Viro ret = read_default_ldt(ptr, bytecount);
2245c48b108SAl Viro break;
2255c48b108SAl Viro }
2265c48b108SAl Viro return ret;
2275c48b108SAl Viro }
2285c48b108SAl Viro
2295c48b108SAl Viro static DEFINE_SPINLOCK(host_ldt_lock);
2305c48b108SAl Viro static short dummy_list[9] = {0, -1};
2315c48b108SAl Viro static short * host_ldt_entries = NULL;
2325c48b108SAl Viro
ldt_get_host_info(void)2335c48b108SAl Viro static void ldt_get_host_info(void)
2345c48b108SAl Viro {
2355c48b108SAl Viro long ret;
2365c48b108SAl Viro struct ldt_entry * ldt;
2375c48b108SAl Viro short *tmp;
2385c48b108SAl Viro int i, size, k, order;
2395c48b108SAl Viro
2405c48b108SAl Viro spin_lock(&host_ldt_lock);
2415c48b108SAl Viro
2425c48b108SAl Viro if (host_ldt_entries != NULL) {
2435c48b108SAl Viro spin_unlock(&host_ldt_lock);
2445c48b108SAl Viro return;
2455c48b108SAl Viro }
2465c48b108SAl Viro host_ldt_entries = dummy_list+1;
2475c48b108SAl Viro
2485c48b108SAl Viro spin_unlock(&host_ldt_lock);
2495c48b108SAl Viro
2505c48b108SAl Viro for (i = LDT_PAGES_MAX-1, order=0; i; i>>=1, order++)
2515c48b108SAl Viro ;
2525c48b108SAl Viro
2535c48b108SAl Viro ldt = (struct ldt_entry *)
2545c48b108SAl Viro __get_free_pages(GFP_KERNEL|__GFP_ZERO, order);
2555c48b108SAl Viro if (ldt == NULL) {
2565c48b108SAl Viro printk(KERN_ERR "ldt_get_host_info: couldn't allocate buffer "
2575c48b108SAl Viro "for host ldt\n");
2585c48b108SAl Viro return;
2595c48b108SAl Viro }
2605c48b108SAl Viro
2615c48b108SAl Viro ret = modify_ldt(0, ldt, (1<<order)*PAGE_SIZE);
2625c48b108SAl Viro if (ret < 0) {
2635c48b108SAl Viro printk(KERN_ERR "ldt_get_host_info: couldn't read host ldt\n");
2645c48b108SAl Viro goto out_free;
2655c48b108SAl Viro }
2665c48b108SAl Viro if (ret == 0) {
2675c48b108SAl Viro /* default_ldt is active, simply write an empty entry 0 */
2685c48b108SAl Viro host_ldt_entries = dummy_list;
2695c48b108SAl Viro goto out_free;
2705c48b108SAl Viro }
2715c48b108SAl Viro
2725c48b108SAl Viro for (i=0, size=0; i<ret/LDT_ENTRY_SIZE; i++) {
2735c48b108SAl Viro if (ldt[i].a != 0 || ldt[i].b != 0)
2745c48b108SAl Viro size++;
2755c48b108SAl Viro }
2765c48b108SAl Viro
2775c48b108SAl Viro if (size < ARRAY_SIZE(dummy_list))
2785c48b108SAl Viro host_ldt_entries = dummy_list;
2795c48b108SAl Viro else {
2805c48b108SAl Viro size = (size + 1) * sizeof(dummy_list[0]);
2815c48b108SAl Viro tmp = kmalloc(size, GFP_KERNEL);
2825c48b108SAl Viro if (tmp == NULL) {
2835c48b108SAl Viro printk(KERN_ERR "ldt_get_host_info: couldn't allocate "
2845c48b108SAl Viro "host ldt list\n");
2855c48b108SAl Viro goto out_free;
2865c48b108SAl Viro }
2875c48b108SAl Viro host_ldt_entries = tmp;
2885c48b108SAl Viro }
2895c48b108SAl Viro
2905c48b108SAl Viro for (i=0, k=0; i<ret/LDT_ENTRY_SIZE; i++) {
2915c48b108SAl Viro if (ldt[i].a != 0 || ldt[i].b != 0)
2925c48b108SAl Viro host_ldt_entries[k++] = i;
2935c48b108SAl Viro }
2945c48b108SAl Viro host_ldt_entries[k] = -1;
2955c48b108SAl Viro
2965c48b108SAl Viro out_free:
2975c48b108SAl Viro free_pages((unsigned long)ldt, order);
2985c48b108SAl Viro }
2995c48b108SAl Viro
init_new_ldt(struct mm_context * new_mm,struct mm_context * from_mm)3005c48b108SAl Viro long init_new_ldt(struct mm_context *new_mm, struct mm_context *from_mm)
3015c48b108SAl Viro {
3025c48b108SAl Viro struct user_desc desc;
3035c48b108SAl Viro short * num_p;
3045c48b108SAl Viro int i;
3055c48b108SAl Viro long page, err=0;
3065c48b108SAl Viro void *addr = NULL;
3075c48b108SAl Viro
3085c48b108SAl Viro
309b3ee571eSAl Viro mutex_init(&new_mm->arch.ldt.lock);
3105c48b108SAl Viro
3115c48b108SAl Viro if (!from_mm) {
3125c48b108SAl Viro memset(&desc, 0, sizeof(desc));
3135c48b108SAl Viro /*
3145c48b108SAl Viro * Now we try to retrieve info about the ldt, we
3155c48b108SAl Viro * inherited from the host. All ldt-entries found
3165c48b108SAl Viro * will be reset in the following loop
3175c48b108SAl Viro */
3185c48b108SAl Viro ldt_get_host_info();
3195c48b108SAl Viro for (num_p=host_ldt_entries; *num_p != -1; num_p++) {
3205c48b108SAl Viro desc.entry_number = *num_p;
3215c48b108SAl Viro err = write_ldt_entry(&new_mm->id, 1, &desc,
3225c48b108SAl Viro &addr, *(num_p + 1) == -1);
3235c48b108SAl Viro if (err)
3245c48b108SAl Viro break;
3255c48b108SAl Viro }
326b3ee571eSAl Viro new_mm->arch.ldt.entry_count = 0;
3275c48b108SAl Viro
3285c48b108SAl Viro goto out;
3295c48b108SAl Viro }
3305c48b108SAl Viro
3315c48b108SAl Viro /*
3325c48b108SAl Viro * Our local LDT is used to supply the data for
3335c48b108SAl Viro * modify_ldt(READLDT), if PTRACE_LDT isn't available,
3345c48b108SAl Viro * i.e., we have to use the stub for modify_ldt, which
3355c48b108SAl Viro * can't handle the big read buffer of up to 64kB.
3365c48b108SAl Viro */
337b3ee571eSAl Viro mutex_lock(&from_mm->arch.ldt.lock);
338b3ee571eSAl Viro if (from_mm->arch.ldt.entry_count <= LDT_DIRECT_ENTRIES)
339b3ee571eSAl Viro memcpy(new_mm->arch.ldt.u.entries, from_mm->arch.ldt.u.entries,
340b3ee571eSAl Viro sizeof(new_mm->arch.ldt.u.entries));
3415c48b108SAl Viro else {
342b3ee571eSAl Viro i = from_mm->arch.ldt.entry_count / LDT_ENTRIES_PER_PAGE;
3435c48b108SAl Viro while (i-->0) {
3445c48b108SAl Viro page = __get_free_page(GFP_KERNEL|__GFP_ZERO);
3455c48b108SAl Viro if (!page) {
3465c48b108SAl Viro err = -ENOMEM;
3475c48b108SAl Viro break;
3485c48b108SAl Viro }
349b3ee571eSAl Viro new_mm->arch.ldt.u.pages[i] =
3505c48b108SAl Viro (struct ldt_entry *) page;
351b3ee571eSAl Viro memcpy(new_mm->arch.ldt.u.pages[i],
352b3ee571eSAl Viro from_mm->arch.ldt.u.pages[i], PAGE_SIZE);
3535c48b108SAl Viro }
3545c48b108SAl Viro }
355b3ee571eSAl Viro new_mm->arch.ldt.entry_count = from_mm->arch.ldt.entry_count;
356b3ee571eSAl Viro mutex_unlock(&from_mm->arch.ldt.lock);
3575c48b108SAl Viro
3585c48b108SAl Viro out:
3595c48b108SAl Viro return err;
3605c48b108SAl Viro }
3615c48b108SAl Viro
3625c48b108SAl Viro
free_ldt(struct mm_context * mm)3635c48b108SAl Viro void free_ldt(struct mm_context *mm)
3645c48b108SAl Viro {
3655c48b108SAl Viro int i;
3665c48b108SAl Viro
367d0b5e15fSRichard Weinberger if (mm->arch.ldt.entry_count > LDT_DIRECT_ENTRIES) {
368b3ee571eSAl Viro i = mm->arch.ldt.entry_count / LDT_ENTRIES_PER_PAGE;
3695c48b108SAl Viro while (i-- > 0)
370b3ee571eSAl Viro free_page((long) mm->arch.ldt.u.pages[i]);
3715c48b108SAl Viro }
372b3ee571eSAl Viro mm->arch.ldt.entry_count = 0;
3735c48b108SAl Viro }
3745c48b108SAl Viro
SYSCALL_DEFINE3(modify_ldt,int,func,void __user *,ptr,unsigned long,bytecount)375da20ab35SDave Hansen SYSCALL_DEFINE3(modify_ldt, int , func , void __user * , ptr ,
376da20ab35SDave Hansen unsigned long , bytecount)
3775c48b108SAl Viro {
378da20ab35SDave Hansen /* See non-um modify_ldt() for why we do this cast */
379da20ab35SDave Hansen return (unsigned int)do_modify_ldt_skas(func, ptr, bytecount);
3805c48b108SAl Viro }
381