xref: /openbmc/linux/arch/x86/um/ldt.c (revision 10995a38)
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;
2610995a38SVincent Whitchurch 
2710995a38SVincent Whitchurch 	BUILD_BUG_ON(sizeof(*desc) % sizeof(long));
2810995a38SVincent Whitchurch 
295c48b108SAl Viro 	res = syscall_stub_data(mm_idp, (unsigned long *)desc,
3010995a38SVincent 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 = &current->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 = &current->mm->context.arch.ldt;
1265c48b108SAl Viro 	struct mm_id * mm_idp = &current->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