Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2)  * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Licensed under the GPL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <linux/syscalls.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <asm/unistd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <os.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <skas.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <sysdep/tls.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) static inline int modify_ldt (int func, void *ptr, unsigned long bytecount)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) 	return syscall(__NR_modify_ldt, func, ptr, bytecount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) static long write_ldt_entry(struct mm_id *mm_idp, int func,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 		     struct user_desc *desc, void **addr, int done)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 	long res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 	void *stub_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 	res = syscall_stub_data(mm_idp, (unsigned long *)desc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 				(sizeof(*desc) + sizeof(long) - 1) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 				    ~(sizeof(long) - 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 				addr, &stub_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 	if (!res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 		unsigned long args[] = { func,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 					 (unsigned long)stub_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 					 sizeof(*desc),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 					 0, 0, 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 		res = run_syscall_stub(mm_idp, __NR_modify_ldt, args,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 				       0, addr, done);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 	return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43)  * In skas mode, we hold our own ldt data in UML.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44)  * Thus, the code implementing sys_modify_ldt_skas
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45)  * is very similar to (and mostly stolen from) sys_modify_ldt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46)  * for arch/i386/kernel/ldt.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47)  * The routines copied and modified in part are:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48)  * - read_ldt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49)  * - read_default_ldt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50)  * - write_ldt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51)  * - sys_modify_ldt_skas
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) static int read_ldt(void __user * ptr, unsigned long bytecount)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	int i, err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	unsigned long size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 	uml_ldt_t *ldt = &current->mm->context.arch.ldt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 	if (!ldt->entry_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	if (bytecount > LDT_ENTRY_SIZE*LDT_ENTRIES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 		bytecount = LDT_ENTRY_SIZE*LDT_ENTRIES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	err = bytecount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	mutex_lock(&ldt->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	if (ldt->entry_count <= LDT_DIRECT_ENTRIES) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 		size = LDT_ENTRY_SIZE*LDT_DIRECT_ENTRIES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 		if (size > bytecount)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 			size = bytecount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 		if (copy_to_user(ptr, ldt->u.entries, size))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 			err = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 		bytecount -= size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 		ptr += size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 		for (i=0; i<ldt->entry_count/LDT_ENTRIES_PER_PAGE && bytecount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 		     i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 			size = PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 			if (size > bytecount)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 				size = bytecount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 			if (copy_to_user(ptr, ldt->u.pages[i], size)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 				err = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 			bytecount -= size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 			ptr += size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	mutex_unlock(&ldt->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	if (bytecount == 0 || err == -EFAULT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	if (clear_user(ptr, bytecount))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 		err = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) static int read_default_ldt(void __user * ptr, unsigned long bytecount)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	if (bytecount > 5*LDT_ENTRY_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 		bytecount = 5*LDT_ENTRY_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	err = bytecount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	 * UML doesn't support lcall7 and lcall27.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	 * So, we don't really have a default ldt, but emulate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 	 * an empty ldt of common host default ldt size.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	if (clear_user(ptr, bytecount))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 		err = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) static int write_ldt(void __user * ptr, unsigned long bytecount, int func)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	uml_ldt_t *ldt = &current->mm->context.arch.ldt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	struct mm_id * mm_idp = &current->mm->context.id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	int i, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	struct user_desc ldt_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	struct ldt_entry entry0, *ldt_p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	void *addr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	if (bytecount != sizeof(ldt_info))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	err = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	if (copy_from_user(&ldt_info, ptr, sizeof(ldt_info)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	if (ldt_info.entry_number >= LDT_ENTRIES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	if (ldt_info.contents == 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 		if (func == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 		if (ldt_info.seg_not_present == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	mutex_lock(&ldt->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 	err = write_ldt_entry(mm_idp, func, &ldt_info, &addr, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 	if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 		goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	if (ldt_info.entry_number >= ldt->entry_count &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	    ldt_info.entry_number >= LDT_DIRECT_ENTRIES) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 		for (i=ldt->entry_count/LDT_ENTRIES_PER_PAGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 		     i*LDT_ENTRIES_PER_PAGE <= ldt_info.entry_number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 		     i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 			if (i == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 				memcpy(&entry0, ldt->u.entries,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 				       sizeof(entry0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 			ldt->u.pages[i] = (struct ldt_entry *)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 				__get_free_page(GFP_KERNEL|__GFP_ZERO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 			if (!ldt->u.pages[i]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 				err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 				/* Undo the change in host */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 				memset(&ldt_info, 0, sizeof(ldt_info));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 				write_ldt_entry(mm_idp, 1, &ldt_info, &addr, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 				goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 			if (i == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 				memcpy(ldt->u.pages[0], &entry0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 				       sizeof(entry0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 				memcpy(ldt->u.pages[0]+1, ldt->u.entries+1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 				       sizeof(entry0)*(LDT_DIRECT_ENTRIES-1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 			ldt->entry_count = (i + 1) * LDT_ENTRIES_PER_PAGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	if (ldt->entry_count <= ldt_info.entry_number)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 		ldt->entry_count = ldt_info.entry_number + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	if (ldt->entry_count <= LDT_DIRECT_ENTRIES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 		ldt_p = ldt->u.entries + ldt_info.entry_number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 		ldt_p = ldt->u.pages[ldt_info.entry_number/LDT_ENTRIES_PER_PAGE] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 			ldt_info.entry_number%LDT_ENTRIES_PER_PAGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	if (ldt_info.base_addr == 0 && ldt_info.limit == 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 	   (func == 1 || LDT_empty(&ldt_info))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 		ldt_p->a = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 		ldt_p->b = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 	else{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 		if (func == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 			ldt_info.useable = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 		ldt_p->a = LDT_entry_a(&ldt_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 		ldt_p->b = LDT_entry_b(&ldt_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 	err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) out_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 	mutex_unlock(&ldt->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) static long do_modify_ldt_skas(int func, void __user *ptr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 			       unsigned long bytecount)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 	int ret = -ENOSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 	switch (func) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 		case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 			ret = read_ldt(ptr, bytecount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 		case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 		case 0x11:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 			ret = write_ldt(ptr, bytecount, func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 		case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 			ret = read_default_ldt(ptr, bytecount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) static DEFINE_SPINLOCK(host_ldt_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) static short dummy_list[9] = {0, -1};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) static short * host_ldt_entries = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) static void ldt_get_host_info(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 	long ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 	struct ldt_entry * ldt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 	short *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 	int i, size, k, order;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 	spin_lock(&host_ldt_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 	if (host_ldt_entries != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 		spin_unlock(&host_ldt_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 	host_ldt_entries = dummy_list+1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 	spin_unlock(&host_ldt_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 	for (i = LDT_PAGES_MAX-1, order=0; i; i>>=1, order++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 		;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 	ldt = (struct ldt_entry *)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 	      __get_free_pages(GFP_KERNEL|__GFP_ZERO, order);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 	if (ldt == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 		printk(KERN_ERR "ldt_get_host_info: couldn't allocate buffer "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 		       "for host ldt\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 	ret = modify_ldt(0, ldt, (1<<order)*PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 		printk(KERN_ERR "ldt_get_host_info: couldn't read host ldt\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 		goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 	if (ret == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 		/* default_ldt is active, simply write an empty entry 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 		host_ldt_entries = dummy_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 		goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 	for (i=0, size=0; i<ret/LDT_ENTRY_SIZE; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 		if (ldt[i].a != 0 || ldt[i].b != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 			size++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 	if (size < ARRAY_SIZE(dummy_list))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 		host_ldt_entries = dummy_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 	else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 		size = (size + 1) * sizeof(dummy_list[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 		tmp = kmalloc(size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 		if (tmp == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 			printk(KERN_ERR "ldt_get_host_info: couldn't allocate "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 			       "host ldt list\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 			goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 		host_ldt_entries = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 	for (i=0, k=0; i<ret/LDT_ENTRY_SIZE; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 		if (ldt[i].a != 0 || ldt[i].b != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 			host_ldt_entries[k++] = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 	host_ldt_entries[k] = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) out_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 	free_pages((unsigned long)ldt, order);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) long init_new_ldt(struct mm_context *new_mm, struct mm_context *from_mm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 	struct user_desc desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 	short * num_p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 	long page, err=0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 	void *addr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 	mutex_init(&new_mm->arch.ldt.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 	if (!from_mm) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 		memset(&desc, 0, sizeof(desc));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 		 * Now we try to retrieve info about the ldt, we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 		 * inherited from the host. All ldt-entries found
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 		 * will be reset in the following loop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 		ldt_get_host_info();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 		for (num_p=host_ldt_entries; *num_p != -1; num_p++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 			desc.entry_number = *num_p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 			err = write_ldt_entry(&new_mm->id, 1, &desc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 					      &addr, *(num_p + 1) == -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 			if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 		new_mm->arch.ldt.entry_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 	 * Our local LDT is used to supply the data for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 	 * modify_ldt(READLDT), if PTRACE_LDT isn't available,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 	 * i.e., we have to use the stub for modify_ldt, which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 	 * can't handle the big read buffer of up to 64kB.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 	mutex_lock(&from_mm->arch.ldt.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 	if (from_mm->arch.ldt.entry_count <= LDT_DIRECT_ENTRIES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 		memcpy(new_mm->arch.ldt.u.entries, from_mm->arch.ldt.u.entries,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 		       sizeof(new_mm->arch.ldt.u.entries));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 	else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 		i = from_mm->arch.ldt.entry_count / LDT_ENTRIES_PER_PAGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 		while (i-->0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 			page = __get_free_page(GFP_KERNEL|__GFP_ZERO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 			if (!page) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 				err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 			new_mm->arch.ldt.u.pages[i] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 				(struct ldt_entry *) page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 			memcpy(new_mm->arch.ldt.u.pages[i],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 			       from_mm->arch.ldt.u.pages[i], PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 	new_mm->arch.ldt.entry_count = from_mm->arch.ldt.entry_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 	mutex_unlock(&from_mm->arch.ldt.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)     out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) void free_ldt(struct mm_context *mm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 	if (mm->arch.ldt.entry_count > LDT_DIRECT_ENTRIES) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 		i = mm->arch.ldt.entry_count / LDT_ENTRIES_PER_PAGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 		while (i-- > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 			free_page((long) mm->arch.ldt.u.pages[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 	mm->arch.ldt.entry_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) SYSCALL_DEFINE3(modify_ldt, int , func , void __user * , ptr ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 		unsigned long , bytecount)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 	/* See non-um modify_ldt() for why we do this cast */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 	return (unsigned int)do_modify_ldt_skas(func, ptr, bytecount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) }