xref: /openbmc/linux/arch/x86/um/ldt.c (revision 1d04c8d7)
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>
91d04c8d7SRichard Weinberger #include <linux/uaccess.h>
105c48b108SAl Viro #include <asm/unistd.h>
1137185b33SAl Viro #include <os.h>
1237185b33SAl Viro #include <skas.h>
1337185b33SAl Viro #include <sysdep/tls.h>
145c48b108SAl Viro 
155c48b108SAl Viro extern int modify_ldt(int func, void *ptr, unsigned long bytecount);
165c48b108SAl Viro 
175c48b108SAl Viro static long write_ldt_entry(struct mm_id *mm_idp, int func,
185c48b108SAl Viro 		     struct user_desc *desc, void **addr, int done)
195c48b108SAl Viro {
205c48b108SAl Viro 	long res;
215c48b108SAl Viro 	void *stub_addr;
225c48b108SAl Viro 	res = syscall_stub_data(mm_idp, (unsigned long *)desc,
235c48b108SAl Viro 				(sizeof(*desc) + sizeof(long) - 1) &
245c48b108SAl Viro 				    ~(sizeof(long) - 1),
255c48b108SAl Viro 				addr, &stub_addr);
265c48b108SAl Viro 	if (!res) {
275c48b108SAl Viro 		unsigned long args[] = { func,
285c48b108SAl Viro 					 (unsigned long)stub_addr,
295c48b108SAl Viro 					 sizeof(*desc),
305c48b108SAl Viro 					 0, 0, 0 };
315c48b108SAl Viro 		res = run_syscall_stub(mm_idp, __NR_modify_ldt, args,
325c48b108SAl Viro 				       0, addr, done);
335c48b108SAl Viro 	}
345c48b108SAl Viro 
355c48b108SAl Viro 	return res;
365c48b108SAl Viro }
375c48b108SAl Viro 
385c48b108SAl Viro /*
395c48b108SAl Viro  * In skas mode, we hold our own ldt data in UML.
405c48b108SAl Viro  * Thus, the code implementing sys_modify_ldt_skas
415c48b108SAl Viro  * is very similar to (and mostly stolen from) sys_modify_ldt
425c48b108SAl Viro  * for arch/i386/kernel/ldt.c
435c48b108SAl Viro  * The routines copied and modified in part are:
445c48b108SAl Viro  * - read_ldt
455c48b108SAl Viro  * - read_default_ldt
465c48b108SAl Viro  * - write_ldt
475c48b108SAl Viro  * - sys_modify_ldt_skas
485c48b108SAl Viro  */
495c48b108SAl Viro 
505c48b108SAl Viro static int read_ldt(void __user * ptr, unsigned long bytecount)
515c48b108SAl Viro {
525c48b108SAl Viro 	int i, err = 0;
535c48b108SAl Viro 	unsigned long size;
54b3ee571eSAl Viro 	uml_ldt_t *ldt = &current->mm->context.arch.ldt;
555c48b108SAl Viro 
565c48b108SAl Viro 	if (!ldt->entry_count)
575c48b108SAl Viro 		goto out;
585c48b108SAl Viro 	if (bytecount > LDT_ENTRY_SIZE*LDT_ENTRIES)
595c48b108SAl Viro 		bytecount = LDT_ENTRY_SIZE*LDT_ENTRIES;
605c48b108SAl Viro 	err = bytecount;
615c48b108SAl Viro 
625c48b108SAl Viro 	mutex_lock(&ldt->lock);
635c48b108SAl Viro 	if (ldt->entry_count <= LDT_DIRECT_ENTRIES) {
645c48b108SAl Viro 		size = LDT_ENTRY_SIZE*LDT_DIRECT_ENTRIES;
655c48b108SAl Viro 		if (size > bytecount)
665c48b108SAl Viro 			size = bytecount;
675c48b108SAl Viro 		if (copy_to_user(ptr, ldt->u.entries, size))
685c48b108SAl Viro 			err = -EFAULT;
695c48b108SAl Viro 		bytecount -= size;
705c48b108SAl Viro 		ptr += size;
715c48b108SAl Viro 	}
725c48b108SAl Viro 	else {
735c48b108SAl Viro 		for (i=0; i<ldt->entry_count/LDT_ENTRIES_PER_PAGE && bytecount;
745c48b108SAl Viro 		     i++) {
755c48b108SAl Viro 			size = PAGE_SIZE;
765c48b108SAl Viro 			if (size > bytecount)
775c48b108SAl Viro 				size = bytecount;
785c48b108SAl Viro 			if (copy_to_user(ptr, ldt->u.pages[i], size)) {
795c48b108SAl Viro 				err = -EFAULT;
805c48b108SAl Viro 				break;
815c48b108SAl Viro 			}
825c48b108SAl Viro 			bytecount -= size;
835c48b108SAl Viro 			ptr += size;
845c48b108SAl Viro 		}
855c48b108SAl Viro 	}
865c48b108SAl Viro 	mutex_unlock(&ldt->lock);
875c48b108SAl Viro 
885c48b108SAl Viro 	if (bytecount == 0 || err == -EFAULT)
895c48b108SAl Viro 		goto out;
905c48b108SAl Viro 
915c48b108SAl Viro 	if (clear_user(ptr, bytecount))
925c48b108SAl Viro 		err = -EFAULT;
935c48b108SAl Viro 
945c48b108SAl Viro out:
955c48b108SAl Viro 	return err;
965c48b108SAl Viro }
975c48b108SAl Viro 
985c48b108SAl Viro static int read_default_ldt(void __user * ptr, unsigned long bytecount)
995c48b108SAl Viro {
1005c48b108SAl Viro 	int err;
1015c48b108SAl Viro 
1025c48b108SAl Viro 	if (bytecount > 5*LDT_ENTRY_SIZE)
1035c48b108SAl Viro 		bytecount = 5*LDT_ENTRY_SIZE;
1045c48b108SAl Viro 
1055c48b108SAl Viro 	err = bytecount;
1065c48b108SAl Viro 	/*
1075c48b108SAl Viro 	 * UML doesn't support lcall7 and lcall27.
1085c48b108SAl Viro 	 * So, we don't really have a default ldt, but emulate
1095c48b108SAl Viro 	 * an empty ldt of common host default ldt size.
1105c48b108SAl Viro 	 */
1115c48b108SAl Viro 	if (clear_user(ptr, bytecount))
1125c48b108SAl Viro 		err = -EFAULT;
1135c48b108SAl Viro 
1145c48b108SAl Viro 	return err;
1155c48b108SAl Viro }
1165c48b108SAl Viro 
1175c48b108SAl Viro static int write_ldt(void __user * ptr, unsigned long bytecount, int func)
1185c48b108SAl Viro {
119b3ee571eSAl Viro 	uml_ldt_t *ldt = &current->mm->context.arch.ldt;
1205c48b108SAl Viro 	struct mm_id * mm_idp = &current->mm->context.id;
1215c48b108SAl Viro 	int i, err;
1225c48b108SAl Viro 	struct user_desc ldt_info;
1235c48b108SAl Viro 	struct ldt_entry entry0, *ldt_p;
1245c48b108SAl Viro 	void *addr = NULL;
1255c48b108SAl Viro 
1265c48b108SAl Viro 	err = -EINVAL;
1275c48b108SAl Viro 	if (bytecount != sizeof(ldt_info))
1285c48b108SAl Viro 		goto out;
1295c48b108SAl Viro 	err = -EFAULT;
1305c48b108SAl Viro 	if (copy_from_user(&ldt_info, ptr, sizeof(ldt_info)))
1315c48b108SAl Viro 		goto out;
1325c48b108SAl Viro 
1335c48b108SAl Viro 	err = -EINVAL;
1345c48b108SAl Viro 	if (ldt_info.entry_number >= LDT_ENTRIES)
1355c48b108SAl Viro 		goto out;
1365c48b108SAl Viro 	if (ldt_info.contents == 3) {
1375c48b108SAl Viro 		if (func == 1)
1385c48b108SAl Viro 			goto out;
1395c48b108SAl Viro 		if (ldt_info.seg_not_present == 0)
1405c48b108SAl Viro 			goto out;
1415c48b108SAl Viro 	}
1425c48b108SAl Viro 
1435c48b108SAl Viro 	mutex_lock(&ldt->lock);
1445c48b108SAl Viro 
1455c48b108SAl Viro 	err = write_ldt_entry(mm_idp, func, &ldt_info, &addr, 1);
1465c48b108SAl Viro 	if (err)
1475c48b108SAl Viro 		goto out_unlock;
1485c48b108SAl Viro 
1495c48b108SAl Viro 	if (ldt_info.entry_number >= ldt->entry_count &&
1505c48b108SAl Viro 	    ldt_info.entry_number >= LDT_DIRECT_ENTRIES) {
1515c48b108SAl Viro 		for (i=ldt->entry_count/LDT_ENTRIES_PER_PAGE;
1525c48b108SAl Viro 		     i*LDT_ENTRIES_PER_PAGE <= ldt_info.entry_number;
1535c48b108SAl Viro 		     i++) {
1545c48b108SAl Viro 			if (i == 0)
1555c48b108SAl Viro 				memcpy(&entry0, ldt->u.entries,
1565c48b108SAl Viro 				       sizeof(entry0));
1575c48b108SAl Viro 			ldt->u.pages[i] = (struct ldt_entry *)
1585c48b108SAl Viro 				__get_free_page(GFP_KERNEL|__GFP_ZERO);
1595c48b108SAl Viro 			if (!ldt->u.pages[i]) {
1605c48b108SAl Viro 				err = -ENOMEM;
1615c48b108SAl Viro 				/* Undo the change in host */
1625c48b108SAl Viro 				memset(&ldt_info, 0, sizeof(ldt_info));
1635c48b108SAl Viro 				write_ldt_entry(mm_idp, 1, &ldt_info, &addr, 1);
1645c48b108SAl Viro 				goto out_unlock;
1655c48b108SAl Viro 			}
1665c48b108SAl Viro 			if (i == 0) {
1675c48b108SAl Viro 				memcpy(ldt->u.pages[0], &entry0,
1685c48b108SAl Viro 				       sizeof(entry0));
1695c48b108SAl Viro 				memcpy(ldt->u.pages[0]+1, ldt->u.entries+1,
1705c48b108SAl Viro 				       sizeof(entry0)*(LDT_DIRECT_ENTRIES-1));
1715c48b108SAl Viro 			}
1725c48b108SAl Viro 			ldt->entry_count = (i + 1) * LDT_ENTRIES_PER_PAGE;
1735c48b108SAl Viro 		}
1745c48b108SAl Viro 	}
1755c48b108SAl Viro 	if (ldt->entry_count <= ldt_info.entry_number)
1765c48b108SAl Viro 		ldt->entry_count = ldt_info.entry_number + 1;
1775c48b108SAl Viro 
1785c48b108SAl Viro 	if (ldt->entry_count <= LDT_DIRECT_ENTRIES)
1795c48b108SAl Viro 		ldt_p = ldt->u.entries + ldt_info.entry_number;
1805c48b108SAl Viro 	else
1815c48b108SAl Viro 		ldt_p = ldt->u.pages[ldt_info.entry_number/LDT_ENTRIES_PER_PAGE] +
1825c48b108SAl Viro 			ldt_info.entry_number%LDT_ENTRIES_PER_PAGE;
1835c48b108SAl Viro 
1845c48b108SAl Viro 	if (ldt_info.base_addr == 0 && ldt_info.limit == 0 &&
1855c48b108SAl Viro 	   (func == 1 || LDT_empty(&ldt_info))) {
1865c48b108SAl Viro 		ldt_p->a = 0;
1875c48b108SAl Viro 		ldt_p->b = 0;
1885c48b108SAl Viro 	}
1895c48b108SAl Viro 	else{
1905c48b108SAl Viro 		if (func == 1)
1915c48b108SAl Viro 			ldt_info.useable = 0;
1925c48b108SAl Viro 		ldt_p->a = LDT_entry_a(&ldt_info);
1935c48b108SAl Viro 		ldt_p->b = LDT_entry_b(&ldt_info);
1945c48b108SAl Viro 	}
1955c48b108SAl Viro 	err = 0;
1965c48b108SAl Viro 
1975c48b108SAl Viro out_unlock:
1985c48b108SAl Viro 	mutex_unlock(&ldt->lock);
1995c48b108SAl Viro out:
2005c48b108SAl Viro 	return err;
2015c48b108SAl Viro }
2025c48b108SAl Viro 
2035c48b108SAl Viro static long do_modify_ldt_skas(int func, void __user *ptr,
2045c48b108SAl Viro 			       unsigned long bytecount)
2055c48b108SAl Viro {
2065c48b108SAl Viro 	int ret = -ENOSYS;
2075c48b108SAl Viro 
2085c48b108SAl Viro 	switch (func) {
2095c48b108SAl Viro 		case 0:
2105c48b108SAl Viro 			ret = read_ldt(ptr, bytecount);
2115c48b108SAl Viro 			break;
2125c48b108SAl Viro 		case 1:
2135c48b108SAl Viro 		case 0x11:
2145c48b108SAl Viro 			ret = write_ldt(ptr, bytecount, func);
2155c48b108SAl Viro 			break;
2165c48b108SAl Viro 		case 2:
2175c48b108SAl Viro 			ret = read_default_ldt(ptr, bytecount);
2185c48b108SAl Viro 			break;
2195c48b108SAl Viro 	}
2205c48b108SAl Viro 	return ret;
2215c48b108SAl Viro }
2225c48b108SAl Viro 
2235c48b108SAl Viro static DEFINE_SPINLOCK(host_ldt_lock);
2245c48b108SAl Viro static short dummy_list[9] = {0, -1};
2255c48b108SAl Viro static short * host_ldt_entries = NULL;
2265c48b108SAl Viro 
2275c48b108SAl Viro static void ldt_get_host_info(void)
2285c48b108SAl Viro {
2295c48b108SAl Viro 	long ret;
2305c48b108SAl Viro 	struct ldt_entry * ldt;
2315c48b108SAl Viro 	short *tmp;
2325c48b108SAl Viro 	int i, size, k, order;
2335c48b108SAl Viro 
2345c48b108SAl Viro 	spin_lock(&host_ldt_lock);
2355c48b108SAl Viro 
2365c48b108SAl Viro 	if (host_ldt_entries != NULL) {
2375c48b108SAl Viro 		spin_unlock(&host_ldt_lock);
2385c48b108SAl Viro 		return;
2395c48b108SAl Viro 	}
2405c48b108SAl Viro 	host_ldt_entries = dummy_list+1;
2415c48b108SAl Viro 
2425c48b108SAl Viro 	spin_unlock(&host_ldt_lock);
2435c48b108SAl Viro 
2445c48b108SAl Viro 	for (i = LDT_PAGES_MAX-1, order=0; i; i>>=1, order++)
2455c48b108SAl Viro 		;
2465c48b108SAl Viro 
2475c48b108SAl Viro 	ldt = (struct ldt_entry *)
2485c48b108SAl Viro 	      __get_free_pages(GFP_KERNEL|__GFP_ZERO, order);
2495c48b108SAl Viro 	if (ldt == NULL) {
2505c48b108SAl Viro 		printk(KERN_ERR "ldt_get_host_info: couldn't allocate buffer "
2515c48b108SAl Viro 		       "for host ldt\n");
2525c48b108SAl Viro 		return;
2535c48b108SAl Viro 	}
2545c48b108SAl Viro 
2555c48b108SAl Viro 	ret = modify_ldt(0, ldt, (1<<order)*PAGE_SIZE);
2565c48b108SAl Viro 	if (ret < 0) {
2575c48b108SAl Viro 		printk(KERN_ERR "ldt_get_host_info: couldn't read host ldt\n");
2585c48b108SAl Viro 		goto out_free;
2595c48b108SAl Viro 	}
2605c48b108SAl Viro 	if (ret == 0) {
2615c48b108SAl Viro 		/* default_ldt is active, simply write an empty entry 0 */
2625c48b108SAl Viro 		host_ldt_entries = dummy_list;
2635c48b108SAl Viro 		goto out_free;
2645c48b108SAl Viro 	}
2655c48b108SAl Viro 
2665c48b108SAl Viro 	for (i=0, size=0; i<ret/LDT_ENTRY_SIZE; i++) {
2675c48b108SAl Viro 		if (ldt[i].a != 0 || ldt[i].b != 0)
2685c48b108SAl Viro 			size++;
2695c48b108SAl Viro 	}
2705c48b108SAl Viro 
2715c48b108SAl Viro 	if (size < ARRAY_SIZE(dummy_list))
2725c48b108SAl Viro 		host_ldt_entries = dummy_list;
2735c48b108SAl Viro 	else {
2745c48b108SAl Viro 		size = (size + 1) * sizeof(dummy_list[0]);
2755c48b108SAl Viro 		tmp = kmalloc(size, GFP_KERNEL);
2765c48b108SAl Viro 		if (tmp == NULL) {
2775c48b108SAl Viro 			printk(KERN_ERR "ldt_get_host_info: couldn't allocate "
2785c48b108SAl Viro 			       "host ldt list\n");
2795c48b108SAl Viro 			goto out_free;
2805c48b108SAl Viro 		}
2815c48b108SAl Viro 		host_ldt_entries = tmp;
2825c48b108SAl Viro 	}
2835c48b108SAl Viro 
2845c48b108SAl Viro 	for (i=0, k=0; i<ret/LDT_ENTRY_SIZE; i++) {
2855c48b108SAl Viro 		if (ldt[i].a != 0 || ldt[i].b != 0)
2865c48b108SAl Viro 			host_ldt_entries[k++] = i;
2875c48b108SAl Viro 	}
2885c48b108SAl Viro 	host_ldt_entries[k] = -1;
2895c48b108SAl Viro 
2905c48b108SAl Viro out_free:
2915c48b108SAl Viro 	free_pages((unsigned long)ldt, order);
2925c48b108SAl Viro }
2935c48b108SAl Viro 
2945c48b108SAl Viro long init_new_ldt(struct mm_context *new_mm, struct mm_context *from_mm)
2955c48b108SAl Viro {
2965c48b108SAl Viro 	struct user_desc desc;
2975c48b108SAl Viro 	short * num_p;
2985c48b108SAl Viro 	int i;
2995c48b108SAl Viro 	long page, err=0;
3005c48b108SAl Viro 	void *addr = NULL;
3015c48b108SAl Viro 
3025c48b108SAl Viro 
303b3ee571eSAl Viro 	mutex_init(&new_mm->arch.ldt.lock);
3045c48b108SAl Viro 
3055c48b108SAl Viro 	if (!from_mm) {
3065c48b108SAl Viro 		memset(&desc, 0, sizeof(desc));
3075c48b108SAl Viro 		/*
3085c48b108SAl Viro 		 * Now we try to retrieve info about the ldt, we
3095c48b108SAl Viro 		 * inherited from the host. All ldt-entries found
3105c48b108SAl Viro 		 * will be reset in the following loop
3115c48b108SAl Viro 		 */
3125c48b108SAl Viro 		ldt_get_host_info();
3135c48b108SAl Viro 		for (num_p=host_ldt_entries; *num_p != -1; num_p++) {
3145c48b108SAl Viro 			desc.entry_number = *num_p;
3155c48b108SAl Viro 			err = write_ldt_entry(&new_mm->id, 1, &desc,
3165c48b108SAl Viro 					      &addr, *(num_p + 1) == -1);
3175c48b108SAl Viro 			if (err)
3185c48b108SAl Viro 				break;
3195c48b108SAl Viro 		}
320b3ee571eSAl Viro 		new_mm->arch.ldt.entry_count = 0;
3215c48b108SAl Viro 
3225c48b108SAl Viro 		goto out;
3235c48b108SAl Viro 	}
3245c48b108SAl Viro 
3255c48b108SAl Viro 	/*
3265c48b108SAl Viro 	 * Our local LDT is used to supply the data for
3275c48b108SAl Viro 	 * modify_ldt(READLDT), if PTRACE_LDT isn't available,
3285c48b108SAl Viro 	 * i.e., we have to use the stub for modify_ldt, which
3295c48b108SAl Viro 	 * can't handle the big read buffer of up to 64kB.
3305c48b108SAl Viro 	 */
331b3ee571eSAl Viro 	mutex_lock(&from_mm->arch.ldt.lock);
332b3ee571eSAl Viro 	if (from_mm->arch.ldt.entry_count <= LDT_DIRECT_ENTRIES)
333b3ee571eSAl Viro 		memcpy(new_mm->arch.ldt.u.entries, from_mm->arch.ldt.u.entries,
334b3ee571eSAl Viro 		       sizeof(new_mm->arch.ldt.u.entries));
3355c48b108SAl Viro 	else {
336b3ee571eSAl Viro 		i = from_mm->arch.ldt.entry_count / LDT_ENTRIES_PER_PAGE;
3375c48b108SAl Viro 		while (i-->0) {
3385c48b108SAl Viro 			page = __get_free_page(GFP_KERNEL|__GFP_ZERO);
3395c48b108SAl Viro 			if (!page) {
3405c48b108SAl Viro 				err = -ENOMEM;
3415c48b108SAl Viro 				break;
3425c48b108SAl Viro 			}
343b3ee571eSAl Viro 			new_mm->arch.ldt.u.pages[i] =
3445c48b108SAl Viro 				(struct ldt_entry *) page;
345b3ee571eSAl Viro 			memcpy(new_mm->arch.ldt.u.pages[i],
346b3ee571eSAl Viro 			       from_mm->arch.ldt.u.pages[i], PAGE_SIZE);
3475c48b108SAl Viro 		}
3485c48b108SAl Viro 	}
349b3ee571eSAl Viro 	new_mm->arch.ldt.entry_count = from_mm->arch.ldt.entry_count;
350b3ee571eSAl Viro 	mutex_unlock(&from_mm->arch.ldt.lock);
3515c48b108SAl Viro 
3525c48b108SAl Viro     out:
3535c48b108SAl Viro 	return err;
3545c48b108SAl Viro }
3555c48b108SAl Viro 
3565c48b108SAl Viro 
3575c48b108SAl Viro void free_ldt(struct mm_context *mm)
3585c48b108SAl Viro {
3595c48b108SAl Viro 	int i;
3605c48b108SAl Viro 
361d0b5e15fSRichard Weinberger 	if (mm->arch.ldt.entry_count > LDT_DIRECT_ENTRIES) {
362b3ee571eSAl Viro 		i = mm->arch.ldt.entry_count / LDT_ENTRIES_PER_PAGE;
3635c48b108SAl Viro 		while (i-- > 0)
364b3ee571eSAl Viro 			free_page((long) mm->arch.ldt.u.pages[i]);
3655c48b108SAl Viro 	}
366b3ee571eSAl Viro 	mm->arch.ldt.entry_count = 0;
3675c48b108SAl Viro }
3685c48b108SAl Viro 
3695c48b108SAl Viro int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount)
3705c48b108SAl Viro {
3715c48b108SAl Viro 	return do_modify_ldt_skas(func, ptr, bytecount);
3725c48b108SAl Viro }
373