0001
0002 #include <linux/kernel.h>
0003 #include <linux/errno.h>
0004 #include <linux/sched.h>
0005 #include <linux/user.h>
0006 #include <linux/regset.h>
0007 #include <linux/syscalls.h>
0008 #include <linux/nospec.h>
0009
0010 #include <linux/uaccess.h>
0011 #include <asm/desc.h>
0012 #include <asm/ldt.h>
0013 #include <asm/processor.h>
0014 #include <asm/proto.h>
0015
0016 #include "tls.h"
0017
0018
0019
0020
0021 static int get_free_idx(void)
0022 {
0023 struct thread_struct *t = ¤t->thread;
0024 int idx;
0025
0026 for (idx = 0; idx < GDT_ENTRY_TLS_ENTRIES; idx++)
0027 if (desc_empty(&t->tls_array[idx]))
0028 return idx + GDT_ENTRY_TLS_MIN;
0029 return -ESRCH;
0030 }
0031
0032 static bool tls_desc_okay(const struct user_desc *info)
0033 {
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055 if (LDT_empty(info) || LDT_zero(info))
0056 return true;
0057
0058
0059
0060
0061
0062 if (!info->seg_32bit)
0063 return false;
0064
0065
0066 if (info->contents > 1)
0067 return false;
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078 if (info->seg_not_present)
0079 return false;
0080
0081 return true;
0082 }
0083
0084 static void set_tls_desc(struct task_struct *p, int idx,
0085 const struct user_desc *info, int n)
0086 {
0087 struct thread_struct *t = &p->thread;
0088 struct desc_struct *desc = &t->tls_array[idx - GDT_ENTRY_TLS_MIN];
0089 int cpu;
0090
0091
0092
0093
0094 cpu = get_cpu();
0095
0096 while (n-- > 0) {
0097 if (LDT_empty(info) || LDT_zero(info))
0098 memset(desc, 0, sizeof(*desc));
0099 else
0100 fill_ldt(desc, info);
0101 ++info;
0102 ++desc;
0103 }
0104
0105 if (t == ¤t->thread)
0106 load_TLS(t, cpu);
0107
0108 put_cpu();
0109 }
0110
0111
0112
0113
0114 int do_set_thread_area(struct task_struct *p, int idx,
0115 struct user_desc __user *u_info,
0116 int can_allocate)
0117 {
0118 struct user_desc info;
0119 unsigned short __maybe_unused sel, modified_sel;
0120
0121 if (copy_from_user(&info, u_info, sizeof(info)))
0122 return -EFAULT;
0123
0124 if (!tls_desc_okay(&info))
0125 return -EINVAL;
0126
0127 if (idx == -1)
0128 idx = info.entry_number;
0129
0130
0131
0132
0133
0134 if (idx == -1 && can_allocate) {
0135 idx = get_free_idx();
0136 if (idx < 0)
0137 return idx;
0138 if (put_user(idx, &u_info->entry_number))
0139 return -EFAULT;
0140 }
0141
0142 if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
0143 return -EINVAL;
0144
0145 set_tls_desc(p, idx, &info, 1);
0146
0147
0148
0149
0150
0151
0152 modified_sel = (idx << 3) | 3;
0153
0154 if (p == current) {
0155 #ifdef CONFIG_X86_64
0156 savesegment(ds, sel);
0157 if (sel == modified_sel)
0158 loadsegment(ds, sel);
0159
0160 savesegment(es, sel);
0161 if (sel == modified_sel)
0162 loadsegment(es, sel);
0163
0164 savesegment(fs, sel);
0165 if (sel == modified_sel)
0166 loadsegment(fs, sel);
0167 #endif
0168
0169 savesegment(gs, sel);
0170 if (sel == modified_sel)
0171 load_gs_index(sel);
0172 } else {
0173 #ifdef CONFIG_X86_64
0174 if (p->thread.fsindex == modified_sel)
0175 p->thread.fsbase = info.base_addr;
0176
0177 if (p->thread.gsindex == modified_sel)
0178 p->thread.gsbase = info.base_addr;
0179 #endif
0180 }
0181
0182 return 0;
0183 }
0184
0185 SYSCALL_DEFINE1(set_thread_area, struct user_desc __user *, u_info)
0186 {
0187 return do_set_thread_area(current, -1, u_info, 1);
0188 }
0189
0190
0191
0192
0193
0194
0195 static void fill_user_desc(struct user_desc *info, int idx,
0196 const struct desc_struct *desc)
0197
0198 {
0199 memset(info, 0, sizeof(*info));
0200 info->entry_number = idx;
0201 info->base_addr = get_desc_base(desc);
0202 info->limit = get_desc_limit(desc);
0203 info->seg_32bit = desc->d;
0204 info->contents = desc->type >> 2;
0205 info->read_exec_only = !(desc->type & 2);
0206 info->limit_in_pages = desc->g;
0207 info->seg_not_present = !desc->p;
0208 info->useable = desc->avl;
0209 #ifdef CONFIG_X86_64
0210 info->lm = desc->l;
0211 #endif
0212 }
0213
0214 int do_get_thread_area(struct task_struct *p, int idx,
0215 struct user_desc __user *u_info)
0216 {
0217 struct user_desc info;
0218 int index;
0219
0220 if (idx == -1 && get_user(idx, &u_info->entry_number))
0221 return -EFAULT;
0222
0223 if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
0224 return -EINVAL;
0225
0226 index = idx - GDT_ENTRY_TLS_MIN;
0227 index = array_index_nospec(index,
0228 GDT_ENTRY_TLS_MAX - GDT_ENTRY_TLS_MIN + 1);
0229
0230 fill_user_desc(&info, idx, &p->thread.tls_array[index]);
0231
0232 if (copy_to_user(u_info, &info, sizeof(info)))
0233 return -EFAULT;
0234 return 0;
0235 }
0236
0237 SYSCALL_DEFINE1(get_thread_area, struct user_desc __user *, u_info)
0238 {
0239 return do_get_thread_area(current, -1, u_info);
0240 }
0241
0242 int regset_tls_active(struct task_struct *target,
0243 const struct user_regset *regset)
0244 {
0245 struct thread_struct *t = &target->thread;
0246 int n = GDT_ENTRY_TLS_ENTRIES;
0247 while (n > 0 && desc_empty(&t->tls_array[n - 1]))
0248 --n;
0249 return n;
0250 }
0251
0252 int regset_tls_get(struct task_struct *target, const struct user_regset *regset,
0253 struct membuf to)
0254 {
0255 const struct desc_struct *tls;
0256 struct user_desc v;
0257 int pos;
0258
0259 for (pos = 0, tls = target->thread.tls_array; to.left; pos++, tls++) {
0260 fill_user_desc(&v, GDT_ENTRY_TLS_MIN + pos, tls);
0261 membuf_write(&to, &v, sizeof(v));
0262 }
0263 return 0;
0264 }
0265
0266 int regset_tls_set(struct task_struct *target, const struct user_regset *regset,
0267 unsigned int pos, unsigned int count,
0268 const void *kbuf, const void __user *ubuf)
0269 {
0270 struct user_desc infobuf[GDT_ENTRY_TLS_ENTRIES];
0271 const struct user_desc *info;
0272 int i;
0273
0274 if (pos >= GDT_ENTRY_TLS_ENTRIES * sizeof(struct user_desc) ||
0275 (pos % sizeof(struct user_desc)) != 0 ||
0276 (count % sizeof(struct user_desc)) != 0)
0277 return -EINVAL;
0278
0279 if (kbuf)
0280 info = kbuf;
0281 else if (__copy_from_user(infobuf, ubuf, count))
0282 return -EFAULT;
0283 else
0284 info = infobuf;
0285
0286 for (i = 0; i < count / sizeof(struct user_desc); i++)
0287 if (!tls_desc_okay(info + i))
0288 return -EINVAL;
0289
0290 set_tls_desc(target,
0291 GDT_ENTRY_TLS_MIN + (pos / sizeof(struct user_desc)),
0292 info, count / sizeof(struct user_desc));
0293
0294 return 0;
0295 }