^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 = ¤t->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 = ¤t->mm->context.arch.ldt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) struct mm_id * mm_idp = ¤t->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) }