18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci#include <linux/kernel.h> 38c2ecf20Sopenharmony_ci#include <linux/errno.h> 48c2ecf20Sopenharmony_ci#include <linux/sched.h> 58c2ecf20Sopenharmony_ci#include <linux/user.h> 68c2ecf20Sopenharmony_ci#include <linux/regset.h> 78c2ecf20Sopenharmony_ci#include <linux/syscalls.h> 88c2ecf20Sopenharmony_ci#include <linux/nospec.h> 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/uaccess.h> 118c2ecf20Sopenharmony_ci#include <asm/desc.h> 128c2ecf20Sopenharmony_ci#include <asm/ldt.h> 138c2ecf20Sopenharmony_ci#include <asm/processor.h> 148c2ecf20Sopenharmony_ci#include <asm/proto.h> 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#include "tls.h" 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci/* 198c2ecf20Sopenharmony_ci * sys_alloc_thread_area: get a yet unused TLS descriptor index. 208c2ecf20Sopenharmony_ci */ 218c2ecf20Sopenharmony_cistatic int get_free_idx(void) 228c2ecf20Sopenharmony_ci{ 238c2ecf20Sopenharmony_ci struct thread_struct *t = ¤t->thread; 248c2ecf20Sopenharmony_ci int idx; 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci for (idx = 0; idx < GDT_ENTRY_TLS_ENTRIES; idx++) 278c2ecf20Sopenharmony_ci if (desc_empty(&t->tls_array[idx])) 288c2ecf20Sopenharmony_ci return idx + GDT_ENTRY_TLS_MIN; 298c2ecf20Sopenharmony_ci return -ESRCH; 308c2ecf20Sopenharmony_ci} 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_cistatic bool tls_desc_okay(const struct user_desc *info) 338c2ecf20Sopenharmony_ci{ 348c2ecf20Sopenharmony_ci /* 358c2ecf20Sopenharmony_ci * For historical reasons (i.e. no one ever documented how any 368c2ecf20Sopenharmony_ci * of the segmentation APIs work), user programs can and do 378c2ecf20Sopenharmony_ci * assume that a struct user_desc that's all zeros except for 388c2ecf20Sopenharmony_ci * entry_number means "no segment at all". This never actually 398c2ecf20Sopenharmony_ci * worked. In fact, up to Linux 3.19, a struct user_desc like 408c2ecf20Sopenharmony_ci * this would create a 16-bit read-write segment with base and 418c2ecf20Sopenharmony_ci * limit both equal to zero. 428c2ecf20Sopenharmony_ci * 438c2ecf20Sopenharmony_ci * That was close enough to "no segment at all" until we 448c2ecf20Sopenharmony_ci * hardened this function to disallow 16-bit TLS segments. Fix 458c2ecf20Sopenharmony_ci * it up by interpreting these zeroed segments the way that they 468c2ecf20Sopenharmony_ci * were almost certainly intended to be interpreted. 478c2ecf20Sopenharmony_ci * 488c2ecf20Sopenharmony_ci * The correct way to ask for "no segment at all" is to specify 498c2ecf20Sopenharmony_ci * a user_desc that satisfies LDT_empty. To keep everything 508c2ecf20Sopenharmony_ci * working, we accept both. 518c2ecf20Sopenharmony_ci * 528c2ecf20Sopenharmony_ci * Note that there's a similar kludge in modify_ldt -- look at 538c2ecf20Sopenharmony_ci * the distinction between modes 1 and 0x11. 548c2ecf20Sopenharmony_ci */ 558c2ecf20Sopenharmony_ci if (LDT_empty(info) || LDT_zero(info)) 568c2ecf20Sopenharmony_ci return true; 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci /* 598c2ecf20Sopenharmony_ci * espfix is required for 16-bit data segments, but espfix 608c2ecf20Sopenharmony_ci * only works for LDT segments. 618c2ecf20Sopenharmony_ci */ 628c2ecf20Sopenharmony_ci if (!info->seg_32bit) 638c2ecf20Sopenharmony_ci return false; 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci /* Only allow data segments in the TLS array. */ 668c2ecf20Sopenharmony_ci if (info->contents > 1) 678c2ecf20Sopenharmony_ci return false; 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci /* 708c2ecf20Sopenharmony_ci * Non-present segments with DPL 3 present an interesting attack 718c2ecf20Sopenharmony_ci * surface. The kernel should handle such segments correctly, 728c2ecf20Sopenharmony_ci * but TLS is very difficult to protect in a sandbox, so prevent 738c2ecf20Sopenharmony_ci * such segments from being created. 748c2ecf20Sopenharmony_ci * 758c2ecf20Sopenharmony_ci * If userspace needs to remove a TLS entry, it can still delete 768c2ecf20Sopenharmony_ci * it outright. 778c2ecf20Sopenharmony_ci */ 788c2ecf20Sopenharmony_ci if (info->seg_not_present) 798c2ecf20Sopenharmony_ci return false; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci return true; 828c2ecf20Sopenharmony_ci} 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_cistatic void set_tls_desc(struct task_struct *p, int idx, 858c2ecf20Sopenharmony_ci const struct user_desc *info, int n) 868c2ecf20Sopenharmony_ci{ 878c2ecf20Sopenharmony_ci struct thread_struct *t = &p->thread; 888c2ecf20Sopenharmony_ci struct desc_struct *desc = &t->tls_array[idx - GDT_ENTRY_TLS_MIN]; 898c2ecf20Sopenharmony_ci int cpu; 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci /* 928c2ecf20Sopenharmony_ci * We must not get preempted while modifying the TLS. 938c2ecf20Sopenharmony_ci */ 948c2ecf20Sopenharmony_ci cpu = get_cpu(); 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci while (n-- > 0) { 978c2ecf20Sopenharmony_ci if (LDT_empty(info) || LDT_zero(info)) 988c2ecf20Sopenharmony_ci memset(desc, 0, sizeof(*desc)); 998c2ecf20Sopenharmony_ci else 1008c2ecf20Sopenharmony_ci fill_ldt(desc, info); 1018c2ecf20Sopenharmony_ci ++info; 1028c2ecf20Sopenharmony_ci ++desc; 1038c2ecf20Sopenharmony_ci } 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci if (t == ¤t->thread) 1068c2ecf20Sopenharmony_ci load_TLS(t, cpu); 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci put_cpu(); 1098c2ecf20Sopenharmony_ci} 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci/* 1128c2ecf20Sopenharmony_ci * Set a given TLS descriptor: 1138c2ecf20Sopenharmony_ci */ 1148c2ecf20Sopenharmony_ciint do_set_thread_area(struct task_struct *p, int idx, 1158c2ecf20Sopenharmony_ci struct user_desc __user *u_info, 1168c2ecf20Sopenharmony_ci int can_allocate) 1178c2ecf20Sopenharmony_ci{ 1188c2ecf20Sopenharmony_ci struct user_desc info; 1198c2ecf20Sopenharmony_ci unsigned short __maybe_unused sel, modified_sel; 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci if (copy_from_user(&info, u_info, sizeof(info))) 1228c2ecf20Sopenharmony_ci return -EFAULT; 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci if (!tls_desc_okay(&info)) 1258c2ecf20Sopenharmony_ci return -EINVAL; 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci if (idx == -1) 1288c2ecf20Sopenharmony_ci idx = info.entry_number; 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci /* 1318c2ecf20Sopenharmony_ci * index -1 means the kernel should try to find and 1328c2ecf20Sopenharmony_ci * allocate an empty descriptor: 1338c2ecf20Sopenharmony_ci */ 1348c2ecf20Sopenharmony_ci if (idx == -1 && can_allocate) { 1358c2ecf20Sopenharmony_ci idx = get_free_idx(); 1368c2ecf20Sopenharmony_ci if (idx < 0) 1378c2ecf20Sopenharmony_ci return idx; 1388c2ecf20Sopenharmony_ci if (put_user(idx, &u_info->entry_number)) 1398c2ecf20Sopenharmony_ci return -EFAULT; 1408c2ecf20Sopenharmony_ci } 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX) 1438c2ecf20Sopenharmony_ci return -EINVAL; 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci set_tls_desc(p, idx, &info, 1); 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci /* 1488c2ecf20Sopenharmony_ci * If DS, ES, FS, or GS points to the modified segment, forcibly 1498c2ecf20Sopenharmony_ci * refresh it. Only needed on x86_64 because x86_32 reloads them 1508c2ecf20Sopenharmony_ci * on return to user mode. 1518c2ecf20Sopenharmony_ci */ 1528c2ecf20Sopenharmony_ci modified_sel = (idx << 3) | 3; 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci if (p == current) { 1558c2ecf20Sopenharmony_ci#ifdef CONFIG_X86_64 1568c2ecf20Sopenharmony_ci savesegment(ds, sel); 1578c2ecf20Sopenharmony_ci if (sel == modified_sel) 1588c2ecf20Sopenharmony_ci loadsegment(ds, sel); 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci savesegment(es, sel); 1618c2ecf20Sopenharmony_ci if (sel == modified_sel) 1628c2ecf20Sopenharmony_ci loadsegment(es, sel); 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci savesegment(fs, sel); 1658c2ecf20Sopenharmony_ci if (sel == modified_sel) 1668c2ecf20Sopenharmony_ci loadsegment(fs, sel); 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci savesegment(gs, sel); 1698c2ecf20Sopenharmony_ci if (sel == modified_sel) 1708c2ecf20Sopenharmony_ci load_gs_index(sel); 1718c2ecf20Sopenharmony_ci#endif 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci#ifdef CONFIG_X86_32_LAZY_GS 1748c2ecf20Sopenharmony_ci savesegment(gs, sel); 1758c2ecf20Sopenharmony_ci if (sel == modified_sel) 1768c2ecf20Sopenharmony_ci loadsegment(gs, sel); 1778c2ecf20Sopenharmony_ci#endif 1788c2ecf20Sopenharmony_ci } else { 1798c2ecf20Sopenharmony_ci#ifdef CONFIG_X86_64 1808c2ecf20Sopenharmony_ci if (p->thread.fsindex == modified_sel) 1818c2ecf20Sopenharmony_ci p->thread.fsbase = info.base_addr; 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci if (p->thread.gsindex == modified_sel) 1848c2ecf20Sopenharmony_ci p->thread.gsbase = info.base_addr; 1858c2ecf20Sopenharmony_ci#endif 1868c2ecf20Sopenharmony_ci } 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci return 0; 1898c2ecf20Sopenharmony_ci} 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ciSYSCALL_DEFINE1(set_thread_area, struct user_desc __user *, u_info) 1928c2ecf20Sopenharmony_ci{ 1938c2ecf20Sopenharmony_ci return do_set_thread_area(current, -1, u_info, 1); 1948c2ecf20Sopenharmony_ci} 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci/* 1988c2ecf20Sopenharmony_ci * Get the current Thread-Local Storage area: 1998c2ecf20Sopenharmony_ci */ 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_cistatic void fill_user_desc(struct user_desc *info, int idx, 2028c2ecf20Sopenharmony_ci const struct desc_struct *desc) 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci{ 2058c2ecf20Sopenharmony_ci memset(info, 0, sizeof(*info)); 2068c2ecf20Sopenharmony_ci info->entry_number = idx; 2078c2ecf20Sopenharmony_ci info->base_addr = get_desc_base(desc); 2088c2ecf20Sopenharmony_ci info->limit = get_desc_limit(desc); 2098c2ecf20Sopenharmony_ci info->seg_32bit = desc->d; 2108c2ecf20Sopenharmony_ci info->contents = desc->type >> 2; 2118c2ecf20Sopenharmony_ci info->read_exec_only = !(desc->type & 2); 2128c2ecf20Sopenharmony_ci info->limit_in_pages = desc->g; 2138c2ecf20Sopenharmony_ci info->seg_not_present = !desc->p; 2148c2ecf20Sopenharmony_ci info->useable = desc->avl; 2158c2ecf20Sopenharmony_ci#ifdef CONFIG_X86_64 2168c2ecf20Sopenharmony_ci info->lm = desc->l; 2178c2ecf20Sopenharmony_ci#endif 2188c2ecf20Sopenharmony_ci} 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ciint do_get_thread_area(struct task_struct *p, int idx, 2218c2ecf20Sopenharmony_ci struct user_desc __user *u_info) 2228c2ecf20Sopenharmony_ci{ 2238c2ecf20Sopenharmony_ci struct user_desc info; 2248c2ecf20Sopenharmony_ci int index; 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci if (idx == -1 && get_user(idx, &u_info->entry_number)) 2278c2ecf20Sopenharmony_ci return -EFAULT; 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX) 2308c2ecf20Sopenharmony_ci return -EINVAL; 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci index = idx - GDT_ENTRY_TLS_MIN; 2338c2ecf20Sopenharmony_ci index = array_index_nospec(index, 2348c2ecf20Sopenharmony_ci GDT_ENTRY_TLS_MAX - GDT_ENTRY_TLS_MIN + 1); 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci fill_user_desc(&info, idx, &p->thread.tls_array[index]); 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci if (copy_to_user(u_info, &info, sizeof(info))) 2398c2ecf20Sopenharmony_ci return -EFAULT; 2408c2ecf20Sopenharmony_ci return 0; 2418c2ecf20Sopenharmony_ci} 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ciSYSCALL_DEFINE1(get_thread_area, struct user_desc __user *, u_info) 2448c2ecf20Sopenharmony_ci{ 2458c2ecf20Sopenharmony_ci return do_get_thread_area(current, -1, u_info); 2468c2ecf20Sopenharmony_ci} 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ciint regset_tls_active(struct task_struct *target, 2498c2ecf20Sopenharmony_ci const struct user_regset *regset) 2508c2ecf20Sopenharmony_ci{ 2518c2ecf20Sopenharmony_ci struct thread_struct *t = &target->thread; 2528c2ecf20Sopenharmony_ci int n = GDT_ENTRY_TLS_ENTRIES; 2538c2ecf20Sopenharmony_ci while (n > 0 && desc_empty(&t->tls_array[n - 1])) 2548c2ecf20Sopenharmony_ci --n; 2558c2ecf20Sopenharmony_ci return n; 2568c2ecf20Sopenharmony_ci} 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ciint regset_tls_get(struct task_struct *target, const struct user_regset *regset, 2598c2ecf20Sopenharmony_ci struct membuf to) 2608c2ecf20Sopenharmony_ci{ 2618c2ecf20Sopenharmony_ci const struct desc_struct *tls; 2628c2ecf20Sopenharmony_ci struct user_desc v; 2638c2ecf20Sopenharmony_ci int pos; 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ci for (pos = 0, tls = target->thread.tls_array; to.left; pos++, tls++) { 2668c2ecf20Sopenharmony_ci fill_user_desc(&v, GDT_ENTRY_TLS_MIN + pos, tls); 2678c2ecf20Sopenharmony_ci membuf_write(&to, &v, sizeof(v)); 2688c2ecf20Sopenharmony_ci } 2698c2ecf20Sopenharmony_ci return 0; 2708c2ecf20Sopenharmony_ci} 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ciint regset_tls_set(struct task_struct *target, const struct user_regset *regset, 2738c2ecf20Sopenharmony_ci unsigned int pos, unsigned int count, 2748c2ecf20Sopenharmony_ci const void *kbuf, const void __user *ubuf) 2758c2ecf20Sopenharmony_ci{ 2768c2ecf20Sopenharmony_ci struct user_desc infobuf[GDT_ENTRY_TLS_ENTRIES]; 2778c2ecf20Sopenharmony_ci const struct user_desc *info; 2788c2ecf20Sopenharmony_ci int i; 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci if (pos >= GDT_ENTRY_TLS_ENTRIES * sizeof(struct user_desc) || 2818c2ecf20Sopenharmony_ci (pos % sizeof(struct user_desc)) != 0 || 2828c2ecf20Sopenharmony_ci (count % sizeof(struct user_desc)) != 0) 2838c2ecf20Sopenharmony_ci return -EINVAL; 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci if (kbuf) 2868c2ecf20Sopenharmony_ci info = kbuf; 2878c2ecf20Sopenharmony_ci else if (__copy_from_user(infobuf, ubuf, count)) 2888c2ecf20Sopenharmony_ci return -EFAULT; 2898c2ecf20Sopenharmony_ci else 2908c2ecf20Sopenharmony_ci info = infobuf; 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_ci for (i = 0; i < count / sizeof(struct user_desc); i++) 2938c2ecf20Sopenharmony_ci if (!tls_desc_okay(info + i)) 2948c2ecf20Sopenharmony_ci return -EINVAL; 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_ci set_tls_desc(target, 2978c2ecf20Sopenharmony_ci GDT_ENTRY_TLS_MIN + (pos / sizeof(struct user_desc)), 2988c2ecf20Sopenharmony_ci info, count / sizeof(struct user_desc)); 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci return 0; 3018c2ecf20Sopenharmony_ci} 302