1/*
2 * Copyright (C) 2001, 2004 Hewlett-Packard Co
3 *	David Mosberger-Tang <davidm@hpl.hp.com>
4 *
5 * Adapted from arch/i386/kernel/ldt.c
6 */
7
8#include <linux/errno.h>
9#include <linux/sched.h>
10#include <linux/string.h>
11#include <linux/mm.h>
12#include <linux/smp.h>
13#include <linux/vmalloc.h>
14
15#include <asm/uaccess.h>
16
17#include "ia32priv.h"
18
19/*
20 * read_ldt() is not really atomic - this is not a problem since synchronization of reads
21 * and writes done to the LDT has to be assured by user-space anyway. Writes are atomic,
22 * to protect the security checks done on new descriptors.
23 */
24static int
25read_ldt (void __user *ptr, unsigned long bytecount)
26{
27	unsigned long bytes_left, n;
28	char __user *src, *dst;
29	char buf[256];	/* temporary buffer (don't overflow kernel stack!) */
30
31	if (bytecount > IA32_LDT_ENTRIES*IA32_LDT_ENTRY_SIZE)
32		bytecount = IA32_LDT_ENTRIES*IA32_LDT_ENTRY_SIZE;
33
34	bytes_left = bytecount;
35
36	src = (void __user *) IA32_LDT_OFFSET;
37	dst = ptr;
38
39	while (bytes_left) {
40		n = sizeof(buf);
41		if (n > bytes_left)
42			n = bytes_left;
43
44		/*
45		 * We know we're reading valid memory, but we still must guard against
46		 * running out of memory.
47		 */
48		if (__copy_from_user(buf, src, n))
49			return -EFAULT;
50
51		if (copy_to_user(dst, buf, n))
52			return -EFAULT;
53
54		src += n;
55		dst += n;
56		bytes_left -= n;
57	}
58	return bytecount;
59}
60
61static int
62read_default_ldt (void __user * ptr, unsigned long bytecount)
63{
64	unsigned long size;
65	int err;
66
67	err = 0;
68	size = 8;
69	if (size > bytecount)
70		size = bytecount;
71
72	err = size;
73	if (clear_user(ptr, size))
74		err = -EFAULT;
75
76	return err;
77}
78
79static int
80write_ldt (void __user * ptr, unsigned long bytecount, int oldmode)
81{
82	struct ia32_user_desc ldt_info;
83	__u64 entry;
84	int ret;
85
86	if (bytecount != sizeof(ldt_info))
87		return -EINVAL;
88	if (copy_from_user(&ldt_info, ptr, sizeof(ldt_info)))
89		return -EFAULT;
90
91	if (ldt_info.entry_number >= IA32_LDT_ENTRIES)
92		return -EINVAL;
93	if (ldt_info.contents == 3) {
94		if (oldmode)
95			return -EINVAL;
96		if (ldt_info.seg_not_present == 0)
97			return -EINVAL;
98	}
99
100	if (ldt_info.base_addr == 0 && ldt_info.limit == 0
101	    && (oldmode || (ldt_info.contents == 0 && ldt_info.read_exec_only == 1
102			    && ldt_info.seg_32bit == 0 && ldt_info.limit_in_pages == 0
103			    && ldt_info.seg_not_present == 1 && ldt_info.useable == 0)))
104		/* allow LDTs to be cleared by the user */
105		entry = 0;
106	else
107		/* we must set the "Accessed" bit as IVE doesn't emulate it */
108		entry = IA32_SEG_DESCRIPTOR(ldt_info.base_addr, ldt_info.limit,
109					    (((ldt_info.read_exec_only ^ 1) << 1)
110					     | (ldt_info.contents << 2)) | 1,
111					    1, 3, ldt_info.seg_not_present ^ 1,
112					    (oldmode ? 0 : ldt_info.useable),
113					    ldt_info.seg_32bit,
114					    ldt_info.limit_in_pages);
115	/*
116	 * Install the new entry.  We know we're accessing valid (mapped) user-level
117	 * memory, but we still need to guard against out-of-memory, hence we must use
118	 * put_user().
119	 */
120	ret = __put_user(entry, (__u64 __user *) IA32_LDT_OFFSET + ldt_info.entry_number);
121	ia32_load_segment_descriptors(current);
122	return ret;
123}
124
125asmlinkage int
126sys32_modify_ldt (int func, unsigned int ptr, unsigned int bytecount)
127{
128	int ret = -ENOSYS;
129
130	switch (func) {
131	      case 0:
132		ret = read_ldt(compat_ptr(ptr), bytecount);
133		break;
134	      case 1:
135		ret = write_ldt(compat_ptr(ptr), bytecount, 1);
136		break;
137	      case 2:
138		ret = read_default_ldt(compat_ptr(ptr), bytecount);
139		break;
140	      case 0x11:
141		ret = write_ldt(compat_ptr(ptr), bytecount, 0);
142		break;
143	}
144	return ret;
145}
146