2000-09-03 06:16:35 +02:00
|
|
|
/* cygheap.h: Cygwin heap manager.
|
|
|
|
|
2003-01-17 06:18:30 +01:00
|
|
|
Copyright 2000, 2001, 2002, 2003 Red Hat, Inc.
|
2000-09-03 06:16:35 +02:00
|
|
|
|
|
|
|
This file is part of Cygwin.
|
|
|
|
|
|
|
|
This software is a copyrighted work licensed under the terms of the
|
|
|
|
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
|
|
|
details. */
|
|
|
|
|
|
|
|
#undef cfree
|
|
|
|
|
|
|
|
enum cygheap_types
|
|
|
|
{
|
|
|
|
HEAP_FHANDLER,
|
|
|
|
HEAP_STR,
|
|
|
|
HEAP_ARGV,
|
2000-09-27 07:12:09 +02:00
|
|
|
HEAP_BUF,
|
2001-06-03 04:31:16 +02:00
|
|
|
HEAP_MOUNT,
|
2000-09-27 07:12:09 +02:00
|
|
|
HEAP_1_START,
|
|
|
|
HEAP_1_STR,
|
|
|
|
HEAP_1_ARGV,
|
|
|
|
HEAP_1_BUF,
|
2000-09-30 06:54:11 +02:00
|
|
|
HEAP_1_EXEC,
|
|
|
|
HEAP_1_MAX = 100
|
2000-09-03 06:16:35 +02:00
|
|
|
};
|
|
|
|
|
2000-10-02 04:26:04 +02:00
|
|
|
#define incygheap(s) (cygheap && ((char *) (s) >= (char *) cygheap) && ((char *) (s) <= ((char *) cygheap_max)))
|
2000-09-03 06:16:35 +02:00
|
|
|
|
2000-11-14 06:53:32 +01:00
|
|
|
struct _cmalloc_entry
|
|
|
|
{
|
|
|
|
union
|
|
|
|
{
|
|
|
|
DWORD b;
|
|
|
|
char *ptr;
|
|
|
|
};
|
|
|
|
struct _cmalloc_entry *prev;
|
|
|
|
char data[0];
|
|
|
|
};
|
|
|
|
|
2001-06-03 04:31:16 +02:00
|
|
|
struct cygheap_root_mount_info
|
|
|
|
{
|
|
|
|
char posix_path[MAX_PATH];
|
|
|
|
unsigned posix_pathlen;
|
|
|
|
char native_path[MAX_PATH];
|
|
|
|
unsigned native_pathlen;
|
|
|
|
};
|
|
|
|
|
2001-06-04 03:28:09 +02:00
|
|
|
/* CGF: FIXME This doesn't belong here */
|
|
|
|
|
2000-11-15 01:13:09 +01:00
|
|
|
class cygheap_root
|
|
|
|
{
|
|
|
|
/* Root directory information.
|
|
|
|
This is used after a chroot is called. */
|
2001-06-03 04:31:16 +02:00
|
|
|
struct cygheap_root_mount_info *m;
|
|
|
|
|
2000-11-15 01:13:09 +01:00
|
|
|
public:
|
2001-06-03 04:31:16 +02:00
|
|
|
bool posix_ok (const char *path)
|
|
|
|
{
|
|
|
|
if (!m)
|
|
|
|
return 1;
|
|
|
|
return path_prefix_p (m->posix_path, path, m->posix_pathlen);
|
|
|
|
}
|
|
|
|
bool ischroot_native (const char *path)
|
|
|
|
{
|
|
|
|
if (!m)
|
|
|
|
return 1;
|
|
|
|
return strncasematch (m->native_path, path, m->native_pathlen)
|
2001-09-07 23:32:07 +02:00
|
|
|
&& (path[m->native_pathlen] == '\\' || !path[m->native_pathlen]);
|
2001-06-03 04:31:16 +02:00
|
|
|
}
|
|
|
|
const char *unchroot (const char *path)
|
|
|
|
{
|
|
|
|
if (!m)
|
|
|
|
return path;
|
|
|
|
const char *p = path + m->posix_pathlen;
|
|
|
|
if (!*p)
|
|
|
|
p = "/";
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
bool exists () {return !!m;}
|
|
|
|
void set (const char *posix, const char *native);
|
|
|
|
size_t posix_length () const { return m->posix_pathlen; }
|
|
|
|
const char *posix_path () const { return m->posix_path; }
|
|
|
|
size_t native_length () const { return m->native_pathlen; }
|
|
|
|
const char *native_path () const { return m->native_path; }
|
2000-11-15 01:13:09 +01:00
|
|
|
};
|
|
|
|
|
2002-06-12 07:13:54 +02:00
|
|
|
enum homebodies
|
|
|
|
{
|
|
|
|
CH_HOMEDRIVE,
|
|
|
|
CH_HOMEPATH,
|
|
|
|
CH_HOME
|
|
|
|
};
|
|
|
|
|
2001-01-17 15:57:09 +01:00
|
|
|
class cygheap_user
|
|
|
|
{
|
2000-11-15 01:13:09 +01:00
|
|
|
/* Extendend user information.
|
|
|
|
The information is derived from the internal_getlogin call
|
|
|
|
when on a NT system. */
|
2000-11-15 22:04:02 +01:00
|
|
|
char *pname; /* user's name */
|
|
|
|
char *plogsrv; /* Logon server, may be FQDN */
|
|
|
|
char *pdomain; /* Logon domain of the user */
|
2002-06-12 07:13:54 +02:00
|
|
|
char *homedrive; /* User's home drive */
|
|
|
|
char *homepath; /* User's home path */
|
2002-06-29 04:36:08 +02:00
|
|
|
char *pwinname; /* User's name as far as Windows knows it */
|
2002-06-27 22:44:27 +02:00
|
|
|
char *puserprof; /* User profile */
|
2000-11-15 22:04:02 +01:00
|
|
|
PSID psid; /* buffer for user's SID */
|
2002-05-08 16:21:08 +02:00
|
|
|
PSID orig_psid; /* Remains intact even after impersonation */
|
2000-11-15 01:13:09 +01:00
|
|
|
public:
|
2002-05-29 17:04:29 +02:00
|
|
|
__uid32_t orig_uid; /* Remains intact even after impersonation */
|
Change internal gid datatype from __gid16_t to __gid32_t
throughout.
* cygwin.din: Export new symbols chown32, fchown32, getegid32,
getgid32, getgrgid32, getgrnam32, getgroups32, initgroups32, lchown32,
setgid32, setegid32, getgrent32.
* grp.cc (grp32togrp16): New static function.
(getgrgid32): New function.
(getgrnam32): Ditto.
(getgrent32): Ditto.
(getgroups32): Change name of internal function from getgroups.
(getgroups32): New function.
(initgroups32): Ditto.
* syscalls.cc (chown32): Ditto.
(lchown32): Ditto.
(fchown32): Ditto.
(setegid32): Ditto.
(setgid32): Ditto.
* uinfo.cc (getgid32): Ditto.
(getegid32): Ditto.
* include/cygwin/grp.h: Remove declaration of getgrgid() and getgrnam().
Declare getgrgid32() and getgrnam32() instead. Declare getgid32().
2002-05-28 16:10:55 +02:00
|
|
|
__gid32_t orig_gid; /* Ditto */
|
2002-05-29 17:04:29 +02:00
|
|
|
__uid32_t real_uid; /* Remains intact on seteuid, replaced by setuid */
|
Change internal gid datatype from __gid16_t to __gid32_t
throughout.
* cygwin.din: Export new symbols chown32, fchown32, getegid32,
getgid32, getgrgid32, getgrnam32, getgroups32, initgroups32, lchown32,
setgid32, setegid32, getgrent32.
* grp.cc (grp32togrp16): New static function.
(getgrgid32): New function.
(getgrnam32): Ditto.
(getgrent32): Ditto.
(getgroups32): Change name of internal function from getgroups.
(getgroups32): New function.
(initgroups32): Ditto.
* syscalls.cc (chown32): Ditto.
(lchown32): Ditto.
(fchown32): Ditto.
(setegid32): Ditto.
(setgid32): Ditto.
* uinfo.cc (getgid32): Ditto.
(getegid32): Ditto.
* include/cygwin/grp.h: Remove declaration of getgrgid() and getgrnam().
Declare getgrgid32() and getgrnam32() instead. Declare getgid32().
2002-05-28 16:10:55 +02:00
|
|
|
__gid32_t real_gid; /* Ditto */
|
2002-07-29 14:51:52 +02:00
|
|
|
user_groups groups; /* Primary and supp SIDs */
|
2000-11-15 01:13:09 +01:00
|
|
|
|
2000-11-15 22:04:02 +01:00
|
|
|
/* token is needed if set(e)uid should be called. It can be set by a call
|
|
|
|
to `set_impersonation_token()'. */
|
2003-06-30 15:07:36 +02:00
|
|
|
HANDLE external_token;
|
|
|
|
HANDLE internal_token;
|
2003-07-14 19:04:21 +02:00
|
|
|
HANDLE current_token;
|
2000-11-15 22:04:02 +01:00
|
|
|
|
2002-06-27 22:44:27 +02:00
|
|
|
/* CGF 2002-06-27. I removed the initializaton from this constructor
|
|
|
|
since this class is always allocated statically. That means that everything
|
|
|
|
is zero anyway so there is no need to initialize it to zero. Since the
|
|
|
|
token initialization is always handled during process startup as well,
|
|
|
|
I've removed the constructor entirely. Please reinstate this f this
|
|
|
|
situation ever changes.
|
2001-06-04 16:29:54 +02:00
|
|
|
cygheap_user () : pname (NULL), plogsrv (NULL), pdomain (NULL),
|
2002-06-27 22:44:27 +02:00
|
|
|
homedrive (NULL), homepath (NULL), psid (NULL),
|
|
|
|
token (INVALID_HANDLE_VALUE) {}
|
|
|
|
*/
|
|
|
|
|
2000-11-15 01:13:09 +01:00
|
|
|
~cygheap_user ();
|
|
|
|
|
|
|
|
void set_name (const char *new_name);
|
|
|
|
const char *name () const { return pname; }
|
|
|
|
|
2002-06-29 04:36:08 +02:00
|
|
|
const char *env_logsrv (const char *, size_t);
|
|
|
|
const char *env_homepath (const char *, size_t);
|
|
|
|
const char *env_homedrive (const char *, size_t);
|
|
|
|
const char *env_userprofile (const char *, size_t);
|
|
|
|
const char *env_domain (const char *, size_t);
|
|
|
|
const char *env_name (const char *, size_t);
|
2000-11-15 01:13:09 +01:00
|
|
|
|
2002-06-29 04:36:08 +02:00
|
|
|
const char *logsrv ()
|
|
|
|
{
|
2002-06-30 00:05:30 +02:00
|
|
|
const char *p = env_logsrv ("LOGONSERVER=", sizeof ("LOGONSERVER=") - 1);
|
|
|
|
return (p == almost_null) ? NULL : p;
|
2002-06-29 04:36:08 +02:00
|
|
|
}
|
|
|
|
const char *winname ()
|
|
|
|
{
|
2002-06-30 00:05:30 +02:00
|
|
|
const char *p = env_name ("USERNAME=", sizeof ("USERNAME=") - 1);
|
|
|
|
return (p == almost_null) ? NULL : p;
|
2002-06-29 04:36:08 +02:00
|
|
|
}
|
|
|
|
const char *domain ()
|
|
|
|
{
|
2002-06-30 00:05:30 +02:00
|
|
|
const char *p = env_domain ("USERDOMAIN=", sizeof ("USERDOMAIN=") - 1);
|
|
|
|
return (p == almost_null) ? NULL : p;
|
2002-06-29 04:36:08 +02:00
|
|
|
}
|
2000-11-15 01:13:09 +01:00
|
|
|
BOOL set_sid (PSID new_sid);
|
2002-06-14 20:01:21 +02:00
|
|
|
BOOL set_orig_sid ();
|
2000-11-15 01:13:09 +01:00
|
|
|
PSID sid () const { return psid; }
|
2002-05-08 16:21:08 +02:00
|
|
|
PSID orig_sid () const { return orig_psid; }
|
2002-06-12 07:13:54 +02:00
|
|
|
const char *ontherange (homebodies what, struct passwd * = NULL);
|
2003-07-14 19:04:21 +02:00
|
|
|
bool issetuid () const { return current_token != INVALID_HANDLE_VALUE; }
|
|
|
|
HANDLE token () { return current_token; }
|
2003-06-30 15:07:36 +02:00
|
|
|
void deimpersonate ()
|
|
|
|
{
|
2003-07-14 19:04:21 +02:00
|
|
|
if (issetuid ())
|
2003-06-30 15:07:36 +02:00
|
|
|
RevertToSelf ();
|
|
|
|
}
|
|
|
|
void reimpersonate ()
|
|
|
|
{
|
2003-07-14 19:04:21 +02:00
|
|
|
if (issetuid ()
|
2003-06-30 15:07:36 +02:00
|
|
|
&& !ImpersonateLoggedOnUser (token ()))
|
|
|
|
system_printf ("ImpersonateLoggedOnUser: %E");
|
|
|
|
}
|
2003-07-14 19:04:21 +02:00
|
|
|
bool has_impersonation_tokens ()
|
|
|
|
{ return external_token != INVALID_HANDLE_VALUE
|
|
|
|
|| internal_token != INVALID_HANDLE_VALUE
|
|
|
|
|| current_token != INVALID_HANDLE_VALUE; }
|
2003-06-30 15:07:36 +02:00
|
|
|
void close_impersonation_tokens ()
|
|
|
|
{
|
2003-07-14 19:04:21 +02:00
|
|
|
if (current_token != INVALID_HANDLE_VALUE)
|
|
|
|
{
|
|
|
|
if( current_token != external_token && current_token != internal_token)
|
|
|
|
CloseHandle (current_token);
|
|
|
|
current_token = INVALID_HANDLE_VALUE;
|
|
|
|
}
|
|
|
|
if (external_token != INVALID_HANDLE_VALUE)
|
2003-06-30 15:07:36 +02:00
|
|
|
{
|
|
|
|
CloseHandle (external_token);
|
2003-07-14 19:04:21 +02:00
|
|
|
external_token = INVALID_HANDLE_VALUE;
|
2003-06-30 15:07:36 +02:00
|
|
|
}
|
2003-07-14 19:04:21 +02:00
|
|
|
if (internal_token != INVALID_HANDLE_VALUE)
|
2003-06-30 15:07:36 +02:00
|
|
|
{
|
|
|
|
CloseHandle (internal_token);
|
2003-07-14 19:04:21 +02:00
|
|
|
internal_token = INVALID_HANDLE_VALUE;
|
2003-06-30 15:07:36 +02:00
|
|
|
}
|
2002-06-17 01:34:43 +02:00
|
|
|
}
|
2002-06-29 04:36:08 +02:00
|
|
|
const char *cygheap_user::test_uid (char *&, const char *, size_t)
|
|
|
|
__attribute__ ((regparm (3)));
|
2000-11-15 01:13:09 +01:00
|
|
|
};
|
2000-11-14 06:53:32 +01:00
|
|
|
|
2001-04-17 05:52:08 +02:00
|
|
|
/* cwd cache stuff. */
|
|
|
|
|
|
|
|
class muto;
|
|
|
|
|
|
|
|
struct cwdstuff
|
|
|
|
{
|
|
|
|
char *posix;
|
|
|
|
char *win32;
|
|
|
|
DWORD hash;
|
2002-02-22 20:33:41 +01:00
|
|
|
muto *cwd_lock;
|
2001-04-17 05:52:08 +02:00
|
|
|
char *get (char *buf, int need_posix = 1, int with_chroot = 0, unsigned ulen = MAX_PATH);
|
|
|
|
DWORD get_hash ();
|
|
|
|
void init ();
|
|
|
|
void fixup_after_exec (char *win32, char *posix, DWORD hash);
|
|
|
|
bool get_initial ();
|
|
|
|
void set (const char *win32_cwd, const char *posix_cwd = NULL);
|
|
|
|
};
|
|
|
|
|
2002-07-13 22:00:27 +02:00
|
|
|
#ifdef DEBUGGING
|
|
|
|
struct cygheap_debug
|
|
|
|
{
|
|
|
|
handle_list starth;
|
|
|
|
handle_list *endh;
|
|
|
|
handle_list freeh[500];
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
2002-10-22 18:18:55 +02:00
|
|
|
struct user_heap_info
|
|
|
|
{
|
|
|
|
void *base;
|
|
|
|
void *ptr;
|
|
|
|
void *top;
|
|
|
|
unsigned chunk;
|
|
|
|
};
|
|
|
|
|
2000-11-14 06:53:32 +01:00
|
|
|
struct init_cygheap
|
|
|
|
{
|
|
|
|
_cmalloc_entry *chain;
|
2001-09-06 05:39:18 +02:00
|
|
|
char *buckets[32];
|
2000-11-15 01:13:09 +01:00
|
|
|
cygheap_root root;
|
|
|
|
cygheap_user user;
|
2002-10-22 18:18:55 +02:00
|
|
|
user_heap_info user_heap;
|
2000-11-14 06:53:32 +01:00
|
|
|
mode_t umask;
|
2001-01-28 06:51:15 +01:00
|
|
|
HANDLE shared_h;
|
|
|
|
HANDLE console_h;
|
2001-10-24 23:56:54 +02:00
|
|
|
char *cygwin_regname;
|
2001-04-17 05:52:08 +02:00
|
|
|
cwdstuff cwd;
|
2001-04-18 23:10:15 +02:00
|
|
|
dtable fdtab;
|
2002-07-13 22:00:27 +02:00
|
|
|
#ifdef DEBUGGING
|
|
|
|
cygheap_debug debug;
|
|
|
|
#endif
|
2000-11-14 06:53:32 +01:00
|
|
|
};
|
|
|
|
|
2002-10-09 06:08:05 +02:00
|
|
|
#define CYGHEAPSIZE (sizeof (init_cygheap) + (16000 * sizeof (fhandler_union)) + (4 * 65536))
|
2001-04-18 23:10:15 +02:00
|
|
|
|
2000-11-14 06:53:32 +01:00
|
|
|
extern init_cygheap *cygheap;
|
|
|
|
extern void *cygheap_max;
|
|
|
|
|
2001-10-16 01:39:33 +02:00
|
|
|
class cygheap_fdmanip
|
|
|
|
{
|
|
|
|
protected:
|
|
|
|
int fd;
|
|
|
|
fhandler_base **fh;
|
|
|
|
bool locked;
|
|
|
|
public:
|
2001-10-31 01:55:32 +01:00
|
|
|
cygheap_fdmanip (): fh (NULL) {}
|
2001-10-16 01:39:33 +02:00
|
|
|
virtual ~cygheap_fdmanip ()
|
|
|
|
{
|
|
|
|
if (locked)
|
|
|
|
ReleaseResourceLock (LOCK_FD_LIST, WRITE_LOCK | READ_LOCK, "cygheap_fdmanip");
|
|
|
|
}
|
|
|
|
void release ()
|
|
|
|
{
|
|
|
|
cygheap->fdtab.release (fd);
|
|
|
|
}
|
|
|
|
operator int &() {return fd;}
|
|
|
|
operator fhandler_base* &() {return *fh;}
|
|
|
|
void operator = (fhandler_base *fh) {*this->fh = fh;}
|
|
|
|
fhandler_base *operator -> () const {return *fh;}
|
2001-11-02 00:48:34 +01:00
|
|
|
bool isopen () const
|
|
|
|
{
|
|
|
|
if (*fh)
|
|
|
|
return true;
|
|
|
|
set_errno (EBADF);
|
|
|
|
return false;
|
|
|
|
}
|
2001-10-16 01:39:33 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
class cygheap_fdnew : public cygheap_fdmanip
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
cygheap_fdnew (int seed_fd = -1, bool lockit = true)
|
|
|
|
{
|
|
|
|
if (lockit)
|
|
|
|
SetResourceLock (LOCK_FD_LIST, WRITE_LOCK | READ_LOCK, "cygheap_fdnew");
|
|
|
|
if (seed_fd < 0)
|
|
|
|
fd = cygheap->fdtab.find_unused_handle ();
|
|
|
|
else
|
|
|
|
fd = cygheap->fdtab.find_unused_handle (seed_fd + 1);
|
|
|
|
if (fd >= 0)
|
|
|
|
{
|
|
|
|
locked = lockit;
|
|
|
|
fh = cygheap->fdtab + fd;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
set_errno (EMFILE);
|
|
|
|
if (lockit)
|
|
|
|
ReleaseResourceLock (LOCK_FD_LIST, WRITE_LOCK | READ_LOCK, "cygheap_fdnew");
|
|
|
|
locked = false;
|
|
|
|
}
|
|
|
|
}
|
2001-11-21 07:47:57 +01:00
|
|
|
void operator = (fhandler_base *fh) {*this->fh = fh;}
|
2001-10-16 01:39:33 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
class cygheap_fdget : public cygheap_fdmanip
|
|
|
|
{
|
|
|
|
public:
|
2001-10-16 05:31:50 +02:00
|
|
|
cygheap_fdget (int fd, bool lockit = false, bool do_set_errno = true)
|
2001-10-16 01:39:33 +02:00
|
|
|
{
|
|
|
|
if (lockit)
|
|
|
|
SetResourceLock (LOCK_FD_LIST, READ_LOCK, "cygheap_fdget");
|
|
|
|
if (fd >= 0 && fd < (int) cygheap->fdtab.size
|
|
|
|
&& *(fh = cygheap->fdtab + fd) != NULL)
|
|
|
|
{
|
|
|
|
this->fd = fd;
|
|
|
|
locked = lockit;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this->fd = -1;
|
2001-10-16 05:31:50 +02:00
|
|
|
if (do_set_errno)
|
2001-10-16 16:43:36 +02:00
|
|
|
set_errno (EBADF);
|
2001-10-16 01:39:33 +02:00
|
|
|
if (lockit)
|
|
|
|
ReleaseResourceLock (LOCK_FD_LIST, READ_LOCK, "cygheap_fdget");
|
|
|
|
locked = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2001-07-17 05:41:52 +02:00
|
|
|
class child_info;
|
2001-09-14 02:49:00 +02:00
|
|
|
void *__stdcall cygheap_setup_for_child (child_info *ci, bool dup_later) __attribute__ ((regparm(2)));
|
|
|
|
void __stdcall cygheap_setup_for_child_cleanup (void *, child_info *, bool) __attribute__ ((regparm(3)));
|
2002-06-15 23:59:32 +02:00
|
|
|
void __stdcall cygheap_fixup_in_child (bool);
|
2000-09-03 06:16:35 +02:00
|
|
|
extern "C" {
|
2000-10-17 01:55:58 +02:00
|
|
|
void __stdcall cfree (void *) __attribute__ ((regparm(1)));
|
|
|
|
void *__stdcall cmalloc (cygheap_types, DWORD) __attribute__ ((regparm(2)));
|
|
|
|
void *__stdcall crealloc (void *, DWORD) __attribute__ ((regparm(2)));
|
|
|
|
void *__stdcall ccalloc (cygheap_types, DWORD, DWORD) __attribute__ ((regparm(3)));
|
|
|
|
char *__stdcall cstrdup (const char *) __attribute__ ((regparm(1)));
|
|
|
|
char *__stdcall cstrdup1 (const char *) __attribute__ ((regparm(1)));
|
2002-06-27 22:44:27 +02:00
|
|
|
void __stdcall cfree_and_set (char *&, char * = NULL) __attribute__ ((regparm(2)));
|
2000-10-02 04:26:04 +02:00
|
|
|
void __stdcall cygheap_init ();
|
2002-08-27 06:10:54 +02:00
|
|
|
extern DWORD _cygheap_start;
|
2000-09-03 06:16:35 +02:00
|
|
|
}
|