1 /*
2 * Copyright (c) 2023 Institute of Parallel And Distributed Systems (IPADS), Shanghai Jiao Tong University (SJTU)
3 * Licensed under the Mulan PSL v2.
4 * You can use this software according to the terms and conditions of the Mulan PSL v2.
5 * You may obtain a copy of Mulan PSL v2 at:
6 * http://license.coscl.org.cn/MulanPSL2
7 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
8 * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
9 * PURPOSE.
10 * See the Mulan PSL v2 for more details.
11 */
12 #include <mm/mm.h>
13 #include <common/util.h>
14
15 #include "thread_env.h"
16
17 /*
18 * Setup the initial environment for a user process (main thread).
19 *
20 * According to Libc convention, we current set the environment
21 * on the user stack.
22 *
23 */
24
25 #define AT_NULL 0 /* end of vector */
26 #define AT_IGNORE 1 /* entry should be ignored */
27 #define AT_EXECFD 2 /* file descriptor of program */
28 #define AT_PHDR 3 /* program headers for program */
29 #define AT_PHENT 4 /* size of program header entry */
30 #define AT_PHNUM 5 /* number of program headers */
31 #define AT_PAGESZ 6 /* system page size */
32 #define AT_BASE 7 /* base address of interpreter */
33 #define AT_FLAGS 8 /* flags */
34 #define AT_ENTRY 9 /* entry point of program */
35 #define AT_NOTELF 10 /* program is not ELF */
36 #define AT_UID 11 /* real uid */
37 #define AT_EUID 12 /* effective uid */
38 #define AT_GID 13 /* real gid */
39 #define AT_EGID 14 /* effective gid */
40 #define AT_PLATFORM 15 /* string identifying CPU for optimizations */
41 #define AT_HWCAP 16 /* arch dependent hints at CPU capabilities */
42 #define AT_CLKTCK 17 /* frequency at which times() increments */
43 /* AT_* values 18 through 22 are reserved */
44 #define AT_SECURE 23 /* secure mode boolean */
45 /* string identifying real platform, may differ from AT_PLATFORM. */
46 #define AT_BASE_PLATFORM 24
47 #define AT_RANDOM 25 /* address of 16 random bytes */
48 #define AT_HWCAP2 26 /* extension of AT_HWCAP */
49 #define AT_EXECFN 31 /* filename of program */
50
51 #if defined(CHCORE_ARCH_X86_64)
52 const char PLAT[] = "x86_64";
53 #elif defined(CHCORE_ARCH_AARCH64)
54 const char PLAT[] = "aarch64";
55 #else
56 const char PLAT[] = "unknown";
57 #endif
58
59 struct env_buf {
60 unsigned long *entries_tail;
61 unsigned long *entries_end;
62 char *strings_tail;
63 char *strings_end;
64 unsigned long strings_offset;
65 };
66
env_buf_append_int(struct env_buf * env_buf,unsigned long val)67 static void env_buf_append_int(struct env_buf *env_buf, unsigned long val)
68 {
69 BUG_ON(env_buf->entries_tail >= env_buf->entries_end);
70 *(env_buf->entries_tail++) = val;
71 }
72
env_buf_append_str(struct env_buf * env_buf,const char * val)73 static void env_buf_append_str(struct env_buf *env_buf, const char *val)
74 {
75 int i = 0;
76 int val_size = strlen(val) + 1;
77
78 BUG_ON(env_buf->strings_tail + val_size > env_buf->strings_end);
79 while (val[i] != '\0') {
80 env_buf->strings_tail[i] = val[i];
81 i++;
82 }
83 env_buf_append_int(env_buf,
84 (unsigned long)env_buf->strings_tail
85 + env_buf->strings_offset);
86 env_buf->strings_tail += val_size;
87 }
88
env_buf_append_int_auxv(struct env_buf * env_buf,unsigned long type,unsigned long val)89 static void env_buf_append_int_auxv(struct env_buf *env_buf, unsigned long type,
90 unsigned long val)
91 {
92 env_buf_append_int(env_buf, type);
93 env_buf_append_int(env_buf, val);
94 }
95
env_buf_append_str_auxv(struct env_buf * env_buf,unsigned long type,const char * val)96 static void env_buf_append_str_auxv(struct env_buf *env_buf, unsigned long type,
97 const char *val)
98 {
99 env_buf_append_int(env_buf, type);
100 env_buf_append_str(env_buf, val);
101 }
102
103 #define FAKE_UGID 1000
104 #define FAKE_CLKTLK 100
105 #define FAKE_RANDOM_OFF 64
106
107 /*
108 * For setting up the stack (env) of some process.
109 *
110 * env: stack top address used by kernel
111 * top_vaddr: stack top address mapped to user
112 */
prepare_env(char * env,vaddr_t top_vaddr,char * name,struct process_metadata * meta)113 void prepare_env(char *env, vaddr_t top_vaddr, char *name,
114 struct process_metadata *meta)
115 {
116 struct env_buf env_buf;
117 /* clear env */
118 memset(env, 0, ENV_SIZE_ON_STACK);
119
120 env_buf.entries_tail = (unsigned long *)env;
121 env_buf.entries_end = (unsigned long *)(env + ENV_SIZE_ON_STACK / 2);
122 env_buf.strings_tail = (char *)env_buf.entries_end;
123 env_buf.strings_end = env + ENV_SIZE_ON_STACK;
124 env_buf.strings_offset = top_vaddr - ENV_SIZE_ON_STACK - (long)env;
125
126 /** argc */
127 env_buf_append_int(&env_buf, 1);
128 /** argv(only program cmd) */
129 env_buf_append_str(&env_buf, name);
130
131 /** end of argv */
132 env_buf_append_int(&env_buf, 0);
133
134 /** end of envp(empty envp) */
135 env_buf_append_int(&env_buf, 0);
136
137 env_buf_append_int_auxv(&env_buf, AT_SECURE, 0);
138 env_buf_append_int_auxv(&env_buf, AT_PAGESZ, PAGE_SIZE);
139 env_buf_append_int_auxv(&env_buf, AT_PHDR, meta->phdr_addr);
140 env_buf_append_int_auxv(&env_buf, AT_PHENT, meta->phentsize);
141 env_buf_append_int_auxv(&env_buf, AT_PHNUM, meta->phnum);
142 env_buf_append_int_auxv(&env_buf, AT_FLAGS, meta->flags);
143 env_buf_append_int_auxv(&env_buf, AT_ENTRY, meta->entry);
144 env_buf_append_int_auxv(&env_buf, AT_UID, FAKE_UGID);
145 env_buf_append_int_auxv(&env_buf, AT_EUID, FAKE_UGID);
146 env_buf_append_int_auxv(&env_buf, AT_GID, FAKE_UGID);
147 env_buf_append_int_auxv(&env_buf, AT_EGID, FAKE_UGID);
148 env_buf_append_int_auxv(&env_buf, AT_CLKTCK, FAKE_CLKTLK);
149 env_buf_append_int_auxv(&env_buf, AT_HWCAP, 0);
150 env_buf_append_str_auxv(&env_buf, AT_PLATFORM, PLAT);
151 env_buf_append_int_auxv(&env_buf, AT_RANDOM, top_vaddr - FAKE_RANDOM_OFF);
152 env_buf_append_int_auxv(&env_buf, AT_NULL, 0);
153
154 /* add more auxv here */
155 }
156