1 /* cygheap.h: Cygwin heap manager.
3 This file is part of Cygwin.
5 This software is a copyrighted work licensed under the terms of the
6 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
10 #include "cygheap_malloc.h"
13 #define incygheap(s) (cygheap && ((char *) (s) >= (char *) cygheap) && ((char *) (s) <= ((char *) cygheap_max)))
22 struct _cmalloc_entry
*prev
;
26 struct cygheap_root_mount_info
28 char posix_path
[CYG_MAX_PATH
];
29 unsigned posix_pathlen
;
30 char native_path
[CYG_MAX_PATH
];
31 unsigned native_pathlen
;
35 /* CGF: FIXME This doesn't belong here */
39 /* Root directory information.
40 This is used after a chroot is called. */
41 struct cygheap_root_mount_info
*m
;
44 bool posix_ok (const char *path
)
48 return path_prefix_p (m
->posix_path
, path
, m
->posix_pathlen
,
51 bool ischroot_native (const char *path
)
55 return strncasematch (m
->native_path
, path
, m
->native_pathlen
)
56 && (path
[m
->native_pathlen
] == '\\' || !path
[m
->native_pathlen
]);
58 const char *unchroot (const char *path
)
62 const char *p
= path
+ m
->posix_pathlen
;
67 bool exists () {return !!m
;}
68 void set (const char *, const char *, bool);
69 size_t posix_length () const { return m
->posix_pathlen
; }
70 const char *posix_path () const { return m
->posix_path
; }
71 size_t native_length () const { return m
->native_pathlen
; }
72 const char *native_path () const { return m
->native_path
; }
84 /* Extendend user information.
85 The information is derived from the internal_getlogin call
86 when on a NT system. */
87 char *pname
; /* user's name */
88 char *plogsrv
; /* Logon server, may be FQDN */
89 char *pdomain
; /* Logon domain of the user */
90 char *homedrive
; /* User's home drive */
91 char *homepath
; /* User's home path */
92 char *psystemroot
; /* Value of SYSTEMROOT */
93 char *pwinname
; /* User's name as far as Windows knows it */
94 char *puserprof
; /* User profile */
95 cygsid effec_cygsid
; /* buffer for user's SID */
96 cygsid saved_cygsid
; /* Remains intact even after impersonation */
98 uid_t saved_uid
; /* Remains intact even after impersonation */
99 gid_t saved_gid
; /* Ditto */
100 uid_t real_uid
; /* Remains intact on seteuid, replaced by setuid */
101 gid_t real_gid
; /* Ditto */
102 user_groups groups
; /* Primary and supp SIDs */
104 HANDLE external_token
; /* token from set_impersonation_token call */
105 HANDLE internal_token
; /* password-less token fetched in seteuid */
106 HANDLE curr_primary_token
; /* Just a copy of external or internal token */
107 HANDLE curr_imp_token
; /* impersonation token derived from primary
109 bool ext_token_is_restricted
; /* external_token is restricted token */
110 bool curr_token_is_restricted
; /* curr_primary_token is restricted token */
111 bool setuid_to_restricted
; /* switch to restricted token by setuid () */
113 /* CGF 2002-06-27. I removed the initializaton from this constructor
114 since this class is always allocated statically. That means that everything
115 is zero anyway so there is no need to initialize it to zero. Since the
116 token initialization is always handled during process startup as well,
117 I've removed the constructor entirely. Please reinstate this if this
118 situation ever changes.
119 cygheap_user () : pname (NULL), plogsrv (NULL), pdomain (NULL),
120 homedrive (NULL), homepath (NULL),
121 token (INVALID_HANDLE_VALUE) {}
127 void set_name (const char *new_name
);
128 const char *name () const { return pname
; }
130 const char *env_logsrv (const char *, size_t);
131 const char *env_homepath (const char *, size_t);
132 const char *env_homedrive (const char *, size_t);
133 const char *env_userprofile (const char *, size_t);
134 const char *env_domain (const char *, size_t);
135 const char *env_name (const char *, size_t);
136 const char *env_systemroot (const char *, size_t);
138 const char *logsrv ()
140 const char *p
= env_logsrv ("LOGONSERVER=", sizeof ("LOGONSERVER=") - 1);
141 return (p
== almost_null
) ? NULL
: p
;
143 const char *winname ()
145 const char *p
= env_name ("USERNAME=", sizeof ("USERNAME=") - 1);
146 return (p
== almost_null
) ? NULL
: p
;
148 const char *domain ()
150 const char *p
= env_domain ("USERDOMAIN=", sizeof ("USERDOMAIN=") - 1);
151 return (p
== almost_null
) ? NULL
: p
;
153 void set_sid (PSID new_sid
) { effec_cygsid
= new_sid
;}
154 void set_saved_sid () { saved_cygsid
= effec_cygsid
; }
155 cygpsid
&sid () { return effec_cygsid
; }
156 cygpsid
&saved_sid () { return saved_cygsid
; }
157 const char *ontherange (homebodies what
, struct passwd
* = NULL
);
158 #define NO_IMPERSONATION NULL
159 bool issetuid () const { return curr_imp_token
!= NO_IMPERSONATION
; }
160 HANDLE
primary_token () { return curr_primary_token
; }
161 HANDLE
imp_token () { return curr_imp_token
; }
162 void deimpersonate ()
166 bool reimpersonate ()
169 return ImpersonateLoggedOnUser (primary_token ());
172 bool has_impersonation_tokens ()
173 { return external_token
!= NO_IMPERSONATION
174 || internal_token
!= NO_IMPERSONATION
175 || curr_primary_token
!= NO_IMPERSONATION
; }
176 void close_impersonation_tokens ()
178 if (curr_imp_token
!= NO_IMPERSONATION
)
179 CloseHandle (curr_imp_token
);
180 if (external_token
!= NO_IMPERSONATION
)
181 CloseHandle (external_token
);
182 if (internal_token
!= NO_IMPERSONATION
)
183 CloseHandle (internal_token
);
185 PWCHAR
get_windows_id (PWCHAR buf
)
187 return effec_cygsid
.string (buf
);
189 char *get_windows_id (char *buf
)
191 return effec_cygsid
.string (buf
);
194 const char *test_uid (char *&, const char *, size_t);
197 /* cwd cache stuff. */
199 /* This class is used to store the CWD. The CWD storage in the
200 RTL_USER_PROCESS_PARAMETERS block is only an afterthought now. The actual
201 CWD storage is a FAST_CWD structure which is allocated on the process heap.
202 The new method only requires minimal locking and it's much more multi-thread
203 friendly. Presumably it minimizes contention when accessing the CWD.
204 The class fcwd_access_t is supposed to encapsulate the gory implementation
205 details depending on OS version from the calling functions.
206 The layout of all structures has been tested on 32 and 64 bit. */
207 class fcwd_access_t
{
208 LONG ReferenceCount
; /* Only release when this is 0. */
209 HANDLE DirectoryHandle
;
210 ULONG OldDismountCount
; /* Reflects the system DismountCount
211 at the time the CWD has been set. */
212 UNICODE_STRING Path
; /* Path's Buffer member always refers
213 to the following Buffer array. */
214 LONG FSCharacteristics
; /* Taken from FileFsDeviceInformation */
215 /* fcwd_access_t is dynamically allocated with a size of
216 sizeof(fcwd_access_t) + cwd.Length. Preallocating 2 chars
217 here allows to append a trailing backslash and NUL. */
218 WCHAR Buffer
[2] __attribute ((aligned (8)));
221 void CopyPath (UNICODE_STRING
&target
);
222 void Free (PVOID heap
);
223 void FillIn (HANDLE dir
, PUNICODE_STRING name
, ULONG old_dismount_count
);
224 static void SetDirHandleFromBufferPointer (PWCHAR buf_p
, HANDLE dir
);
225 static void SetVersionFromPointer (PBYTE buf_p
, bool is_buffer
);
234 int error
; /* This contains an errno number which corresponds
235 to the problem with this path when trying to start
236 a native Win32 application. See cwdstuff::set for
237 how it gets set. See child_info_spawn::worker for how
240 friend class fcwd_access_t
;
241 /* fast_cwd_ptr is a pointer to the global RtlpCurDirRef pointer in
242 ntdll.dll pointing to the FAST_CWD structure which constitutes the CWD.
243 Unfortunately RtlpCurDirRef is not exported from ntdll.dll. */
244 fcwd_access_t
**fast_cwd_ptr
;
245 void override_win32_cwd (bool init
, ULONG old_dismount_count
);
248 UNICODE_STRING win32
;
249 static SRWLOCK NO_COPY cwd_lock
;
251 static void acquire_read () { AcquireSRWLockShared (&cwd_lock
); }
252 static void release_read () { ReleaseSRWLockShared (&cwd_lock
); }
253 static void acquire_write () { AcquireSRWLockExclusive (&cwd_lock
); }
254 static void release_write () { ReleaseSRWLockExclusive (&cwd_lock
); }
255 const char *get_posix () const { return posix
; };
256 void reset_posix (wchar_t *w_cwd
);
257 char *get (char *buf
, int need_posix
= 1, int with_chroot
= 0,
258 unsigned ulen
= NT_MAX_PATH
);
259 PWCHAR
get (PWCHAR buf
, unsigned buflen
= NT_MAX_PATH
)
263 wcsncat (buf
, win32
.Buffer
, buflen
- 1);
267 HANDLE
get_handle () { return dir
; }
268 DWORD
get_drive (char * dst
)
271 DWORD ret
= sys_wcstombs (dst
, NT_MAX_PATH
, win32
.Buffer
, drive_length
);
275 int get_error () const { return error
; }
276 const char *get_error_desc () const;
278 int set (path_conv
*, const char *);
285 handle_list freeh
[500];
289 struct cygheap_locale
294 struct user_heap_info
301 void *sbrk (ptrdiff_t);
305 /* This info is maintained for /proc/<PID>/maps ONLY! */
306 struct shared_region_info
308 void *cygwin_shared_addr
;
309 void *user_shared_addr
;
310 void *myself_shared_addr
;
311 void *console_shared_addr
;
314 class cygheap_domain_info
317 PWCHAR pdom_dns_name
;
323 PDS_DOMAIN_TRUSTSW tdom
;
326 PWCHAR rfc2307_domain_buf
;
331 inline PCWSTR
primary_flat_name () const { return pdom_name
; }
332 inline PCWSTR
primary_dns_name () const { return pdom_dns_name
; }
333 inline cygsid
&primary_sid () { return pdom_sid
; }
335 inline bool member_machine () const { return pdom_sid
!= NO_SID
; }
337 inline PCWSTR
account_flat_name () const { return adom_name
; }
338 inline cygsid
&account_sid () { return adom_sid
; }
340 inline PDS_DOMAIN_TRUSTSW
trusted_domain (ULONG idx
) const
341 { return (idx
< tdom_count
) ? tdom
+ idx
: NULL
; }
342 PDS_DOMAIN_TRUSTSW
add_domain (PCWSTR
, PSID
);
344 inline PWCHAR
get_rfc2307_domain () const
345 { return rfc2307_domain_buf
?: NULL
; }
348 #define NSS_SEPARATOR_STRING L"+"
349 #define NSS_SEPARATOR_CHAR (NSS_SEPARATOR_STRING[0])
354 enum nss_scheme_method
{
355 NSS_SCHEME_FALLBACK
= 0,
364 struct nss_scheme_t
{
365 nss_scheme_method method
;
374 #define NSS_SCHEME_MAX 4
375 nss_scheme_t home_scheme
[NSS_SCHEME_MAX
];
376 nss_scheme_t shell_scheme
[NSS_SCHEME_MAX
];
377 nss_scheme_t gecos_scheme
[NSS_SCHEME_MAX
];
382 void nss_init_line (const char *line
);
399 /* Implemented in ldap.cc */
400 PWCHAR
*ldap_user_attr
;
401 void init_ldap_user_attr ();
403 inline void nss_init () { if (!nss_inited
) _nss_init (); }
404 inline bool nss_pwd_files () const { return !!(pwd_src
& NSS_SRC_FILES
); }
405 inline bool nss_pwd_db () const { return !!(pwd_src
& NSS_SRC_DB
); }
406 inline int nss_pwd_src () const { return pwd_src
; } /* CW_GETNSS_PWD_SRC */
407 inline bool nss_grp_files () const { return !!(grp_src
& NSS_SRC_FILES
); }
408 inline bool nss_grp_db () const { return !!(grp_src
& NSS_SRC_DB
); }
409 inline int nss_grp_src () const { return grp_src
; } /* CW_GETNSS_GRP_SRC */
410 inline bool nss_cygserver_caching () const { return caching
; }
411 inline void nss_disable_cygserver_caching () { caching
= false; }
413 char *get_home (cyg_ldap
*pldap
, cygpsid
&sid
, PCWSTR dom
, PCWSTR dnsdomain
,
414 PCWSTR name
, bool fq
);
415 char *get_home (struct _USER_INFO_3
*ui
, cygpsid
&sid
, PCWSTR dom
,
416 PCWSTR name
, bool fq
);
418 char *get_shell (cyg_ldap
*pldap
, cygpsid
&sid
, PCWSTR dom
, PCWSTR dnsdomain
,
419 PCWSTR name
, bool fq
);
420 char *get_shell (struct _USER_INFO_3
*ui
, cygpsid
&sid
, PCWSTR dom
,
421 PCWSTR name
, bool fq
);
423 char *get_gecos (cyg_ldap
*pldap
, cygpsid
&sid
, PCWSTR dom
, PCWSTR dnsdomain
,
424 PCWSTR name
, bool fq
);
425 char *get_gecos (struct _USER_INFO_3
*ui
, cygpsid
&sid
, PCWSTR dom
,
426 PCWSTR name
, bool fq
);
428 inline int nss_db_enums () const { return enums
; }
429 inline PCWSTR
nss_db_enum_tdoms () const { return enum_tdoms
; }
432 class cygheap_ugid_cache
443 uint32_t get (uint32_t id
) const
445 for (uint32_t i
= 0; i
< _cnt
; ++i
)
446 if (_map
[i
].nfs_id
== id
)
447 return _map
[i
].cyg_id
;
448 return (uint32_t) -1;
450 uint32_t reverse_get (uint32_t id
) const
452 for (uint32_t i
= 0; i
< _cnt
; ++i
)
453 if (_map
[i
].cyg_id
== id
)
454 return _map
[i
].nfs_id
;
455 return (uint32_t) -1;
457 void add (uint32_t nfs_id
, uint32_t cyg_id
)
460 _map
= (idmap
*) crealloc (_map
, (_max
+= 10) * sizeof (*_map
));
461 _map
[_cnt
].nfs_id
= nfs_id
;
462 _map
[_cnt
].cyg_id
= cyg_id
;
470 uid_t
get_uid (uid_t uid
) const { return uids
.get (uid
); }
471 gid_t
get_gid (gid_t gid
) const { return gids
.get (gid
); }
472 uid_t
reverse_get_uid (uid_t uid
) const { return uids
.reverse_get (uid
); }
473 gid_t
reverse_get_gid (gid_t gid
) const { return gids
.reverse_get (gid
); }
474 void add_uid (uid_t nfs_uid
, uid_t cyg_uid
) { uids
.add (nfs_uid
, cyg_uid
); }
475 void add_gid (gid_t nfs_gid
, gid_t cyg_gid
) { gids
.add (nfs_gid
, cyg_gid
); }
482 struct hook_chain
*next
;
487 cygheap_locale locale
;
494 struct _cygtls
*thread
;
495 HANDLE mutex
; /* Used to avoid accessing tls area of
496 deleted thread. See comment in
497 cygheap::remove_tls for a description. */
500 struct init_cygheap
: public mini_cygheap
502 _cmalloc_entry
*chain
;
503 char *buckets
[NBUCKETS
];
504 UNICODE_STRING installation_root
;
505 WCHAR installation_root_buf
[PATH_MAX
];
506 UNICODE_STRING installation_dir
;
507 WCHAR installation_dir_buf
[PATH_MAX
];
508 UNICODE_STRING installation_key
;
509 WCHAR installation_key_buf
[18];
511 cygheap_domain_info dom
;
513 cygheap_ugid_cache ugid_cache
;
515 user_heap_info user_heap
;
516 shared_region_info shared_regions
;
519 unsigned long rlim_core
;
526 struct sigaction
*sigs
;
528 fhandler_termios
*ctty
; /* Current tty */
529 threadlist_t
*threadlist
;
531 pid_t pid
; /* my pid */
532 struct { /* Equivalent to using LIST_HEAD. */
533 struct inode_t
*lh_first
;
534 } inode_list
; /* Global inode pointer for adv. locking. */
537 void init_installation_root ();
538 void init_tls_list ();;
539 void add_tls (_cygtls
*);
540 HANDLE
remove_tls (_cygtls
*);
541 threadlist_t
*find_tls (_cygtls
*);
542 threadlist_t
*find_tls (int, bool&);
543 sigset_t
compute_sigblkmask ();
544 void unlock_tls (threadlist_t
*t
) { if (t
) ReleaseMutex (t
->mutex
); }
548 #define _CYGHEAPSIZE_SLOP (128 * 1024)
549 #define CYGHEAPSIZE (sizeof (init_cygheap) + (20000 * sizeof (fhandler_union)) + _CYGHEAPSIZE_SLOP)
550 #define CYGHEAPSIZE_MIN (sizeof (init_cygheap) + (10000 * sizeof (fhandler_union)))
552 extern init_cygheap
*cygheap
;
553 extern void *cygheap_max
;
555 class cygheap_fdmanip
561 cygheap_fdmanip (): fd (-1), locked (false) {}
562 virtual ~cygheap_fdmanip ()
565 cygheap
->fdtab
.unlock ();
567 virtual void release () { cygheap
->fdtab
.release (fd
); }
568 operator int &() {return fd
;}
569 operator fhandler_base
* &() {return cygheap
->fdtab
[fd
];}
570 operator fhandler_socket
* () const {return reinterpret_cast<fhandler_socket
*> (cygheap
->fdtab
[fd
]);}
571 operator fhandler_pipe
* () const {return reinterpret_cast<fhandler_pipe
*> (cygheap
->fdtab
[fd
]);}
572 void operator = (fhandler_base
*fh
) {cygheap
->fdtab
[fd
] = fh
;}
573 fhandler_base
*operator -> () const {return cygheap
->fdtab
[fd
];}
576 if (cygheap
->fdtab
[fd
])
583 class cygheap_fdnew
: public cygheap_fdmanip
586 cygheap_fdnew (int seed_fd
= -1, bool lockit
= true)
589 cygheap
->fdtab
.lock ();
591 fd
= cygheap
->fdtab
.find_unused_handle ();
593 fd
= cygheap
->fdtab
.find_unused_handle (seed_fd
+ 1);
598 /* errno set by find_unused_handle */
600 cygheap
->fdtab
.unlock ();
606 if (cygheap
->fdtab
[fd
])
607 cygheap
->fdtab
[fd
]->inc_refcnt ();
609 void operator = (fhandler_base
*fh
) {cygheap
->fdtab
[fd
] = fh
;}
612 class cygheap_fdget
: public cygheap_fdmanip
616 cygheap_fdget (int fd
, bool lockit
= false, bool do_set_errno
= true)
619 cygheap
->fdtab
.lock ();
620 if (fd
>= 0 && fd
< (int) cygheap
->fdtab
.size
&& cygheap
->fdtab
[fd
] != NULL
)
624 fh
= cygheap
->fdtab
[fd
];
633 cygheap
->fdtab
.unlock ();
640 if (fh
&& fh
->dec_refcnt () <= 0)
642 debug_only_printf ("deleting fh %p", fh
);
646 void release () { cygheap
->fdtab
.release (fd
); }
649 class cygheap_fdenum
: public cygheap_fdmanip
652 cygheap_fdenum (bool lockit
= false)
656 cygheap
->fdtab
.lock ();
661 while (++fd
< (int) cygheap
->fdtab
.size
)
662 if (cygheap
->fdtab
[fd
] != NULL
)
672 void cygheap_fixup_in_child (bool);
673 void cygheap_init ();
674 void setup_cygheap ();