]>
Commit | Line | Data |
---|---|---|
b0e82b74 CF |
1 | /* cygheap.h: Cygwin heap manager. |
2 | ||
a7d2cc16 | 3 | Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Red Hat, Inc. |
b0e82b74 CF |
4 | |
5 | This file is part of Cygwin. | |
6 | ||
7 | This software is a copyrighted work licensed under the terms of the | |
8 | Cygwin license. Please consult the file "CYGWIN_LICENSE" for | |
9 | details. */ | |
10 | ||
72319550 CF |
11 | #include "hires.h" |
12 | ||
b0e82b74 CF |
13 | #undef cfree |
14 | ||
15 | enum cygheap_types | |
16 | { | |
17 | HEAP_FHANDLER, | |
18 | HEAP_STR, | |
19 | HEAP_ARGV, | |
e5648465 | 20 | HEAP_BUF, |
7ceb1cac | 21 | HEAP_MOUNT, |
c0a9bffd | 22 | HEAP_SIGS, |
8e10c431 | 23 | HEAP_ARCHETYPES, |
2d1d1eb1 | 24 | HEAP_TLS, |
14c4d65e | 25 | HEAP_COMMUNE, |
e5648465 | 26 | HEAP_1_START, |
b1d9a0bd | 27 | HEAP_1_HOOK, |
e5648465 CF |
28 | HEAP_1_STR, |
29 | HEAP_1_ARGV, | |
30 | HEAP_1_BUF, | |
8d82847a | 31 | HEAP_1_EXEC, |
5c6497b4 | 32 | HEAP_1_MAX = 100, |
3a83d3a8 | 33 | HEAP_2_STR, |
5c6497b4 | 34 | HEAP_MMAP = 200 |
b0e82b74 CF |
35 | }; |
36 | ||
9fc09d00 | 37 | #define incygheap(s) (cygheap && ((char *) (s) >= (char *) cygheap) && ((char *) (s) <= ((char *) cygheap_max))) |
b0e82b74 | 38 | |
a4785603 CF |
39 | struct _cmalloc_entry |
40 | { | |
41 | union | |
42 | { | |
43 | DWORD b; | |
44 | char *ptr; | |
45 | }; | |
46 | struct _cmalloc_entry *prev; | |
47 | char data[0]; | |
48 | }; | |
49 | ||
7ceb1cac CF |
50 | struct cygheap_root_mount_info |
51 | { | |
95d02d5b | 52 | char posix_path[CYG_MAX_PATH]; |
7ceb1cac | 53 | unsigned posix_pathlen; |
95d02d5b | 54 | char native_path[CYG_MAX_PATH]; |
7ceb1cac CF |
55 | unsigned native_pathlen; |
56 | }; | |
57 | ||
ac5561f2 CF |
58 | /* CGF: FIXME This doesn't belong here */ |
59 | ||
1f0f8e12 CV |
60 | class cygheap_root |
61 | { | |
62 | /* Root directory information. | |
63 | This is used after a chroot is called. */ | |
7ceb1cac CF |
64 | struct cygheap_root_mount_info *m; |
65 | ||
1f0f8e12 | 66 | public: |
7ceb1cac CF |
67 | bool posix_ok (const char *path) |
68 | { | |
7ceb1cac CF |
69 | if (!m) |
70 | return 1; | |
71 | return path_prefix_p (m->posix_path, path, m->posix_pathlen); | |
72 | } | |
73 | bool ischroot_native (const char *path) | |
74 | { | |
75 | if (!m) | |
76 | return 1; | |
77 | return strncasematch (m->native_path, path, m->native_pathlen) | |
1ff9f4b9 | 78 | && (path[m->native_pathlen] == '\\' || !path[m->native_pathlen]); |
7ceb1cac CF |
79 | } |
80 | const char *unchroot (const char *path) | |
81 | { | |
82 | if (!m) | |
83 | return path; | |
84 | const char *p = path + m->posix_pathlen; | |
85 | if (!*p) | |
86 | p = "/"; | |
87 | return p; | |
88 | } | |
89 | bool exists () {return !!m;} | |
71af2ed3 | 90 | void set (const char *, const char *); |
7ceb1cac CF |
91 | size_t posix_length () const { return m->posix_pathlen; } |
92 | const char *posix_path () const { return m->posix_path; } | |
93 | size_t native_length () const { return m->native_pathlen; } | |
94 | const char *native_path () const { return m->native_path; } | |
1f0f8e12 CV |
95 | }; |
96 | ||
da086d02 CF |
97 | enum homebodies |
98 | { | |
99 | CH_HOMEDRIVE, | |
100 | CH_HOMEPATH, | |
101 | CH_HOME | |
102 | }; | |
103 | ||
a7cde2b9 CF |
104 | class cygheap_user |
105 | { | |
1f0f8e12 CV |
106 | /* Extendend user information. |
107 | The information is derived from the internal_getlogin call | |
108 | when on a NT system. */ | |
66c161ba CV |
109 | char *pname; /* user's name */ |
110 | char *plogsrv; /* Logon server, may be FQDN */ | |
111 | char *pdomain; /* Logon domain of the user */ | |
da086d02 CF |
112 | char *homedrive; /* User's home drive */ |
113 | char *homepath; /* User's home path */ | |
60cb120f | 114 | char *psystemroot; /* Value of SYSTEMROOT */ |
094d5193 | 115 | char *pwinname; /* User's name as far as Windows knows it */ |
179cae11 | 116 | char *puserprof; /* User profile */ |
6806a8b5 PH |
117 | cygsid effec_cygsid; /* buffer for user's SID */ |
118 | cygsid saved_cygsid; /* Remains intact even after impersonation */ | |
1f0f8e12 | 119 | public: |
1498189c CV |
120 | __uid32_t saved_uid; /* Remains intact even after impersonation */ |
121 | __gid32_t saved_gid; /* Ditto */ | |
a8d7ae61 | 122 | __uid32_t real_uid; /* Remains intact on seteuid, replaced by setuid */ |
57196405 | 123 | __gid32_t real_gid; /* Ditto */ |
5519d543 | 124 | user_groups groups; /* Primary and supp SIDs */ |
1f0f8e12 | 125 | |
66c161ba CV |
126 | /* token is needed if set(e)uid should be called. It can be set by a call |
127 | to `set_impersonation_token()'. */ | |
70249d56 CV |
128 | HANDLE external_token; |
129 | HANDLE internal_token; | |
f4a1f8a1 | 130 | HANDLE curr_primary_token; |
77ee8805 | 131 | HANDLE curr_imp_token; |
66c161ba | 132 | |
179cae11 CF |
133 | /* CGF 2002-06-27. I removed the initializaton from this constructor |
134 | since this class is always allocated statically. That means that everything | |
135 | is zero anyway so there is no need to initialize it to zero. Since the | |
136 | token initialization is always handled during process startup as well, | |
2e008fb9 | 137 | I've removed the constructor entirely. Please reinstate this if this |
179cae11 | 138 | situation ever changes. |
f7fa593d | 139 | cygheap_user () : pname (NULL), plogsrv (NULL), pdomain (NULL), |
1498189c | 140 | homedrive (NULL), homepath (NULL), |
179cae11 CF |
141 | token (INVALID_HANDLE_VALUE) {} |
142 | */ | |
143 | ||
1f0f8e12 CV |
144 | ~cygheap_user (); |
145 | ||
0efafbfb | 146 | void init (); |
1f0f8e12 CV |
147 | void set_name (const char *new_name); |
148 | const char *name () const { return pname; } | |
149 | ||
094d5193 CF |
150 | const char *env_logsrv (const char *, size_t); |
151 | const char *env_homepath (const char *, size_t); | |
152 | const char *env_homedrive (const char *, size_t); | |
153 | const char *env_userprofile (const char *, size_t); | |
154 | const char *env_domain (const char *, size_t); | |
155 | const char *env_name (const char *, size_t); | |
60cb120f | 156 | const char *env_systemroot (const char *, size_t); |
1f0f8e12 | 157 | |
094d5193 CF |
158 | const char *logsrv () |
159 | { | |
efc1575e CF |
160 | const char *p = env_logsrv ("LOGONSERVER=", sizeof ("LOGONSERVER=") - 1); |
161 | return (p == almost_null) ? NULL : p; | |
094d5193 CF |
162 | } |
163 | const char *winname () | |
164 | { | |
efc1575e CF |
165 | const char *p = env_name ("USERNAME=", sizeof ("USERNAME=") - 1); |
166 | return (p == almost_null) ? NULL : p; | |
094d5193 CF |
167 | } |
168 | const char *domain () | |
169 | { | |
efc1575e CF |
170 | const char *p = env_domain ("USERDOMAIN=", sizeof ("USERDOMAIN=") - 1); |
171 | return (p == almost_null) ? NULL : p; | |
094d5193 | 172 | } |
6806a8b5 PH |
173 | BOOL set_sid (PSID new_sid) {return (BOOL) (effec_cygsid = new_sid);} |
174 | BOOL set_saved_sid () { return (BOOL) (saved_cygsid = effec_cygsid); } | |
175 | PSID sid () { return effec_cygsid; } | |
176 | PSID saved_sid () { return saved_cygsid; } | |
da086d02 | 177 | const char *ontherange (homebodies what, struct passwd * = NULL); |
53197923 | 178 | #define NO_IMPERSONATION NULL |
77ee8805 | 179 | bool issetuid () const { return curr_imp_token != NO_IMPERSONATION; } |
f4a1f8a1 | 180 | HANDLE primary_token () { return curr_primary_token; } |
77ee8805 | 181 | HANDLE imp_token () { return curr_imp_token; } |
70249d56 CV |
182 | void deimpersonate () |
183 | { | |
a0e1630a | 184 | RevertToSelf (); |
70249d56 | 185 | } |
f4a1f8a1 | 186 | bool reimpersonate () |
70249d56 | 187 | { |
5684cfeb | 188 | if (issetuid ()) |
77ee8805 | 189 | return ImpersonateLoggedOnUser (primary_token ()); |
5684cfeb | 190 | return true; |
70249d56 | 191 | } |
ea3ba114 | 192 | bool has_impersonation_tokens () |
53197923 PH |
193 | { return external_token != NO_IMPERSONATION |
194 | || internal_token != NO_IMPERSONATION | |
f4a1f8a1 | 195 | || curr_primary_token != NO_IMPERSONATION; } |
70249d56 CV |
196 | void close_impersonation_tokens () |
197 | { | |
77ee8805 CV |
198 | if (curr_imp_token != NO_IMPERSONATION) |
199 | CloseHandle (curr_imp_token); | |
f4a1f8a1 CV |
200 | if (curr_primary_token != NO_IMPERSONATION |
201 | && curr_primary_token != external_token | |
202 | && curr_primary_token != internal_token) | |
203 | CloseHandle (curr_primary_token); | |
53197923 | 204 | if (external_token != NO_IMPERSONATION) |
f4a1f8a1 | 205 | CloseHandle (external_token); |
53197923 | 206 | if (internal_token != NO_IMPERSONATION) |
f4a1f8a1 | 207 | CloseHandle (internal_token); |
e40670ee | 208 | } |
7b4b41ab CV |
209 | PWCHAR get_windows_id (PWCHAR buf) |
210 | { | |
211 | return effec_cygsid.string (buf); | |
212 | } | |
213 | char *get_windows_id (char *buf) | |
e70bea19 | 214 | { |
570858c3 | 215 | return effec_cygsid.string (buf); |
e70bea19 | 216 | } |
264f41f0 | 217 | |
f62412f2 | 218 | const char *test_uid (char *&, const char *, size_t) |
094d5193 | 219 | __attribute__ ((regparm (3))); |
1f0f8e12 | 220 | }; |
a4785603 | 221 | |
431ba7dd CF |
222 | /* cwd cache stuff. */ |
223 | ||
224 | class muto; | |
225 | ||
226 | struct cwdstuff | |
227 | { | |
228 | char *posix; | |
09ecdc85 | 229 | UNICODE_STRING win32; |
8e87af7e | 230 | HANDLE dir; |
a4563209 | 231 | DWORD drive_length; |
322c131f | 232 | static muto cwd_lock; |
752b16ce | 233 | char *get (char *, int = 1, int = 0, unsigned = NT_MAX_PATH); |
8e87af7e | 234 | HANDLE get_handle () { return dir; } |
264f41f0 | 235 | DWORD get_drive (char * dst) |
a4563209 | 236 | { |
09ecdc85 | 237 | cwd_lock.acquire (); |
7b4b41ab | 238 | DWORD ret = sys_wcstombs (dst, NT_MAX_PATH, win32.Buffer, drive_length); |
322c131f | 239 | cwd_lock.release (); |
09ecdc85 | 240 | return ret; |
a4563209 | 241 | } |
431ba7dd | 242 | void init (); |
09ecdc85 | 243 | int set (PUNICODE_STRING, const char *, bool); |
431ba7dd CF |
244 | }; |
245 | ||
0301bfd0 CF |
246 | #ifdef DEBUGGING |
247 | struct cygheap_debug | |
248 | { | |
249 | handle_list starth; | |
250 | handle_list *endh; | |
251 | handle_list freeh[500]; | |
252 | }; | |
253 | #endif | |
254 | ||
1cc651ec CF |
255 | struct user_heap_info |
256 | { | |
257 | void *base; | |
258 | void *ptr; | |
259 | void *top; | |
897c6b52 | 260 | void *max; |
1cc651ec | 261 | unsigned chunk; |
c2b10dc4 | 262 | unsigned slop; |
1cc651ec CF |
263 | }; |
264 | ||
b1d9a0bd CF |
265 | struct hook_chain |
266 | { | |
267 | void **loc; | |
268 | const void *func; | |
269 | struct hook_chain *next; | |
270 | }; | |
271 | ||
a4785603 CF |
272 | struct init_cygheap |
273 | { | |
274 | _cmalloc_entry *chain; | |
4ce15a49 | 275 | char *buckets[32]; |
1f0f8e12 CV |
276 | cygheap_root root; |
277 | cygheap_user user; | |
1cc651ec | 278 | user_heap_info user_heap; |
a4785603 | 279 | mode_t umask; |
2a6fc028 | 280 | HANDLE console_h; |
431ba7dd | 281 | cwdstuff cwd; |
0381fec6 | 282 | dtable fdtab; |
0301bfd0 CF |
283 | #ifdef DEBUGGING |
284 | cygheap_debug debug; | |
285 | #endif | |
c0a9bffd | 286 | struct sigaction *sigs; |
2e008fb9 | 287 | |
8e10c431 | 288 | fhandler_tty_slave *ctty; /* Current tty */ |
f7239090 | 289 | #ifdef NEWVFORK |
e80cbe3e | 290 | fhandler_tty_slave *ctty_on_hold; |
f7239090 | 291 | #endif |
e431827c | 292 | struct _cygtls **threadlist; |
2d1d1eb1 | 293 | size_t sthreads; |
d584454c | 294 | pid_t pid; /* my pid */ |
8cb359d9 | 295 | HANDLE pid_handle; /* handle for my pid */ |
a998dd70 CV |
296 | struct { /* Equivalent to using LIST_HEAD. */ |
297 | struct inode_t *lh_first; | |
298 | } inode_list; /* Global inode pointer for adv. locking. */ | |
b1d9a0bd | 299 | hook_chain hooks; |
2d1d1eb1 | 300 | void close_ctty (); |
59297e04 CF |
301 | int manage_console_count (const char *, int, bool = false) __attribute__ ((regparm (3))); |
302 | private: | |
303 | int console_count; | |
a4785603 CF |
304 | }; |
305 | ||
59297e04 | 306 | |
0cb38eb5 | 307 | #define _CYGHEAPSIZE_SLOP (128 * 1024) |
d8f87fba CF |
308 | #define CYGHEAPSIZE (sizeof (init_cygheap) + (20000 * sizeof (fhandler_union)) + _CYGHEAPSIZE_SLOP) |
309 | #define CYGHEAPSIZE_MIN (sizeof (init_cygheap) + (10000 * sizeof (fhandler_union))) | |
0381fec6 | 310 | |
a4785603 CF |
311 | extern init_cygheap *cygheap; |
312 | extern void *cygheap_max; | |
313 | ||
df63bd49 CF |
314 | class cygheap_fdmanip |
315 | { | |
316 | protected: | |
317 | int fd; | |
318 | fhandler_base **fh; | |
319 | bool locked; | |
320 | public: | |
6ea0c04e | 321 | cygheap_fdmanip (): fh (NULL) {} |
df63bd49 CF |
322 | virtual ~cygheap_fdmanip () |
323 | { | |
324 | if (locked) | |
2d1d1eb1 | 325 | cygheap->fdtab.unlock (); |
df63bd49 CF |
326 | } |
327 | void release () | |
328 | { | |
329 | cygheap->fdtab.release (fd); | |
330 | } | |
331 | operator int &() {return fd;} | |
332 | operator fhandler_base* &() {return *fh;} | |
7ac61736 | 333 | operator fhandler_socket* () const {return reinterpret_cast<fhandler_socket *> (*fh);} |
7d880770 | 334 | operator fhandler_pipe* () const {return reinterpret_cast<fhandler_pipe *> (*fh);} |
df63bd49 CF |
335 | void operator = (fhandler_base *fh) {*this->fh = fh;} |
336 | fhandler_base *operator -> () const {return *fh;} | |
53f00290 CF |
337 | bool isopen () const |
338 | { | |
339 | if (*fh) | |
340 | return true; | |
341 | set_errno (EBADF); | |
342 | return false; | |
343 | } | |
df63bd49 CF |
344 | }; |
345 | ||
346 | class cygheap_fdnew : public cygheap_fdmanip | |
347 | { | |
348 | public: | |
349 | cygheap_fdnew (int seed_fd = -1, bool lockit = true) | |
350 | { | |
351 | if (lockit) | |
2d1d1eb1 | 352 | cygheap->fdtab.lock (); |
df63bd49 CF |
353 | if (seed_fd < 0) |
354 | fd = cygheap->fdtab.find_unused_handle (); | |
355 | else | |
356 | fd = cygheap->fdtab.find_unused_handle (seed_fd + 1); | |
357 | if (fd >= 0) | |
358 | { | |
359 | locked = lockit; | |
360 | fh = cygheap->fdtab + fd; | |
361 | } | |
362 | else | |
363 | { | |
364 | set_errno (EMFILE); | |
365 | if (lockit) | |
2d1d1eb1 | 366 | cygheap->fdtab.unlock (); |
df63bd49 CF |
367 | locked = false; |
368 | } | |
369 | } | |
7903ee69 | 370 | void operator = (fhandler_base *fh) {*this->fh = fh;} |
df63bd49 CF |
371 | }; |
372 | ||
373 | class cygheap_fdget : public cygheap_fdmanip | |
374 | { | |
375 | public: | |
0f4db8cb | 376 | cygheap_fdget (int fd, bool lockit = false, bool do_set_errno = true) |
df63bd49 CF |
377 | { |
378 | if (lockit) | |
2d1d1eb1 | 379 | cygheap->fdtab.lock (); |
df63bd49 CF |
380 | if (fd >= 0 && fd < (int) cygheap->fdtab.size |
381 | && *(fh = cygheap->fdtab + fd) != NULL) | |
382 | { | |
383 | this->fd = fd; | |
384 | locked = lockit; | |
385 | } | |
386 | else | |
387 | { | |
388 | this->fd = -1; | |
0f4db8cb | 389 | if (do_set_errno) |
2ac3bab6 | 390 | set_errno (EBADF); |
df63bd49 | 391 | if (lockit) |
2d1d1eb1 | 392 | cygheap->fdtab.unlock (); |
df63bd49 CF |
393 | locked = false; |
394 | } | |
395 | } | |
396 | }; | |
397 | ||
4f27e288 CV |
398 | class cygheap_fdenum : public cygheap_fdmanip |
399 | { | |
4f27e288 | 400 | public: |
16bbf0cc | 401 | cygheap_fdenum (bool lockit = false) |
4f27e288 | 402 | { |
82c925af | 403 | locked = lockit; |
4f27e288 CV |
404 | if (lockit) |
405 | cygheap->fdtab.lock (); | |
16bbf0cc | 406 | fd = -1; |
4f27e288 CV |
407 | } |
408 | int next () | |
409 | { | |
410 | while (++fd < (int) cygheap->fdtab.size) | |
411 | if (*(fh = cygheap->fdtab + fd) != NULL) | |
05726ddd | 412 | return fd; |
4f27e288 CV |
413 | return -1; |
414 | } | |
415 | void rewind () | |
416 | { | |
16bbf0cc | 417 | fd = -1; |
4f27e288 CV |
418 | } |
419 | }; | |
420 | ||
5457dfcb | 421 | class child_info; |
6ea3e429 | 422 | void __stdcall cygheap_fixup_in_child (bool); |
b0e82b74 | 423 | extern "C" { |
166b2571 | 424 | void __stdcall cfree (void *) __attribute__ ((regparm(1))); |
166b2571 CF |
425 | void *__stdcall cmalloc (cygheap_types, DWORD) __attribute__ ((regparm(2))); |
426 | void *__stdcall crealloc (void *, DWORD) __attribute__ ((regparm(2))); | |
427 | void *__stdcall ccalloc (cygheap_types, DWORD, DWORD) __attribute__ ((regparm(3))); | |
ee4388c4 CF |
428 | void *__stdcall cmalloc_abort (cygheap_types, DWORD) __attribute__ ((regparm(2))); |
429 | void *__stdcall crealloc_abort (void *, DWORD) __attribute__ ((regparm(2))); | |
430 | void *__stdcall ccalloc_abort (cygheap_types, DWORD, DWORD) __attribute__ ((regparm(3))); | |
7b4b41ab CV |
431 | PWCHAR __stdcall cwcsdup (const PWCHAR) __attribute__ ((regparm(1))); |
432 | PWCHAR __stdcall cwcsdup1 (const PWCHAR) __attribute__ ((regparm(1))); | |
166b2571 CF |
433 | char *__stdcall cstrdup (const char *) __attribute__ ((regparm(1))); |
434 | char *__stdcall cstrdup1 (const char *) __attribute__ ((regparm(1))); | |
179cae11 | 435 | void __stdcall cfree_and_set (char *&, char * = NULL) __attribute__ ((regparm(2))); |
9fc09d00 | 436 | void __stdcall cygheap_init (); |
ce95c640 | 437 | extern char _cygheap_start[] __attribute__((section(".idata"))); |
1ed8d187 | 438 | } |