mailing list of musl libc
 help / color / mirror / code / Atom feed
acc73f46e72608419affe3ac7782cc6ebc4f21f0 blob 3713 bytes (raw)

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
 
#if SEP_STACK_SEG

#define _GNU_SOURCE
#include "atomic.h"
#include "libc.h"
#include "syscall.h"
#include <ldt.h>
#include <malloc.h>
#include <stdint.h>
#include <string.h>

extern uintptr_t __stack_base;

static int modify_ldt(int func, void *ptr, unsigned long bytecount) {
	return syscall(SYS_modify_ldt, func, ptr, bytecount);
}

static void update_ldt(int idx, unsigned long addr, size_t len) {
	struct user_desc stack_desc;
	stack_desc.entry_number = idx;
	stack_desc.base_addr = (unsigned long)addr;
	stack_desc.contents = 0; /* data */
	stack_desc.limit = (int)((len - 1) >> 12);
	stack_desc.limit_in_pages = 1;
	stack_desc.read_exec_only = 0;
	stack_desc.seg_not_present = 0;
	stack_desc.seg_32bit = 1;
	stack_desc.useable = 1;

	if (modify_ldt(1, &stack_desc, sizeof(stack_desc)) == -1)
		a_crash();
}

static int find_available_ldt_slot(void) {
	static const int SEG_DESC_P_BIT_OFF = 47;

	uint64_t ldt[1];

	/* read the current LDT */
	int ldt_len = modify_ldt(0, ldt, sizeof(ldt));
	if (ldt_len == -1)
		a_crash();

	if (ldt_len == 0)
		/* LDT is currently empty */
		return 0;

	for (int i = 0; i < (ldt_len/sizeof(ldt[0])); i++)
		if (((ldt[i] >> SEG_DESC_P_BIT_OFF) & 1) == 0)
			return i;

	/* crash if no available slot was found */
	a_crash();

	/* unreachable; just for suppressing compiler warning */
	return 0;
}

#define SEG_SEL_LDT 4
#define SEG_SEL_CPL3 3
#define SEG_SEL_TO_IDX(sel) ((sel) >> 3)
#define SEG_IDX_TO_LDT_SEL(idx) ((idx) | SEG_SEL_LDT | SEG_SEL_CPL3)

__attribute__((__visibility__("hidden")))
void __restrict_segments(void)
{
	uintptr_t limit, stack_base = __stack_base;
	int data_seg_sel, data_ldt_sel;

	__asm__ __volatile__ ("mov %%ds, %0" : "=r"(data_seg_sel));

	if ((data_seg_sel & SEG_SEL_LDT) == SEG_SEL_LDT) {
		data_ldt_sel = data_seg_sel;

		/* Read the current limit from the segment register rather than
		 * relying on __stack_base, since __stack_base is in the
		 * default data segment and could potentially be subject to
		 * memory corruption. */
		__asm__ __volatile__ ("lsl %1, %0" : "=r"(limit) : "m"(data_seg_sel));

		if (limit < stack_base)
			return;
	} else
		data_ldt_sel = SEG_IDX_TO_LDT_SEL(find_available_ldt_slot());

	update_ldt(SEG_SEL_TO_IDX(data_ldt_sel), 0, stack_base);

	/* Reload the DS and ES segment registers from the new or updated LDT
	 * entry. */
	__asm__ __volatile__ (
	  "mov %0, %%ds\n\t"
	  "mov %0, %%es\n\t"
	  ::
	  "r"(data_ldt_sel)
	);
}

extern char **__environ;

/* Programs and much of the libc code expect to be able to access the arguments,
 * environment, and auxv in DS, but they are initially located on the stack.  This
 * function moves them to the heap. This uses strdup to copy data from the stack,
 * so it must run before segment limits are restricted.
 */
__attribute__((__visibility__("hidden")))
void __safestack_dup_argv_env_aux(int argc, char ***argvp, char ***envpp)
{
	char **argv = *argvp;
	char **envp = *envpp;
	char **environ_end = envp;
	size_t *auxv, *auxv_end;
	char **new_argv = 0;

	while (*environ_end) environ_end++;

	auxv_end = (size_t *)environ_end + 1;
	while (*auxv_end) auxv_end++;
	auxv_end++;

	new_argv = malloc((uintptr_t)auxv_end - (uintptr_t)argvp);
	if (!new_argv)
		a_crash();

	*new_argv = (char *)argc;
	new_argv++;

	*argvp = new_argv;

	for (int i = 0; i < argc; i++)
		new_argv[i] = strdup(argv[i]);
	new_argv += argc;
	*new_argv = NULL;
	new_argv++;

	*envpp = __environ = new_argv;
	while (envp != environ_end) {
		*new_argv = strdup(*envp);
		envp++;
		new_argv++;
	}
	*new_argv = NULL;
	envp++;
	new_argv++;

	libc.auxv = (size_t *)new_argv;
	memcpy(new_argv, envp, (uintptr_t)auxv_end - (uintptr_t)envp);

	__restrict_segments();
}

#endif /*SEP_STACK_SEG*/
debug log:

solving acc73f4 ...
found acc73f4 in https://inbox.vuxu.org/musl/390CE752059EB848A71F4F676EBAB76D3AC263D2@ORSMSX114.amr.corp.intel.com/

applying [1/1] https://inbox.vuxu.org/musl/390CE752059EB848A71F4F676EBAB76D3AC263D2@ORSMSX114.amr.corp.intel.com/
diff --git a/src/internal/i386/separate_stack_seg.c b/src/internal/i386/separate_stack_seg.c
new file mode 100644
index 0000000..acc73f4

Checking patch src/internal/i386/separate_stack_seg.c...
Applied patch src/internal/i386/separate_stack_seg.c cleanly.

index at:
100644 acc73f46e72608419affe3ac7782cc6ebc4f21f0	src/internal/i386/separate_stack_seg.c

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/musl/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).