📄 cygserver.cc
字号:
/* cygserver.cc Copyright 2001, 2002 Red Hat Inc. Written by Egor Duda <deo@logos-m.ru>This file is part of Cygwin.This software is a copyrighted work licensed under the terms of theCygwin license. Please consult the file "CYGWIN_LICENSE" fordetails. */#include "woutsup.h"#include <sys/types.h>#include <assert.h>#include <ctype.h>#include <errno.h>#include <getopt.h>#include <signal.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include "cygerrno.h"#include "cygwin_version.h"#include "cygwin/cygserver.h"#include "cygwin/cygserver_process.h"#include "cygwin/cygserver_transport.h"// Version string.static const char version[] = "$Revision: 1.5 $";/* * Support function for the XXX_printf () macros in "woutsup.h". * Copied verbatim from "strace.cc". */static intgetfunc (char *in_dst, const char *func){ const char *p; const char *pe; char *dst = in_dst; for (p = func; (pe = strchr (p, '(')); p = pe + 1) if (isalnum ((int)pe[-1]) || pe[-1] == '_') break; else if (isspace ((int)pe[-1])) { pe--; break; } if (!pe) pe = strchr (func, '\0'); for (p = pe; p > func; p--) if (p != pe && *p == ' ') { p++; break; } if (*p == '*') p++; while (p < pe) *dst++ = *p++; *dst++ = ':'; *dst++ = ' '; *dst = '\0'; return dst - in_dst;}/* * Support function for the XXX_printf () macros in "woutsup.h". */extern "C" void__cygserver__printf (const char *const function, const char *const fmt, ...){ const DWORD lasterror = GetLastError (); const int lasterrno = errno; va_list ap; char *const buf = (char *) alloca (BUFSIZ); assert (buf); int len = 0; if (function) len += getfunc (buf, function); va_start (ap, fmt); len += vsnprintf (buf + len, BUFSIZ - len, fmt, ap); va_end (ap); len += snprintf (buf + len, BUFSIZ - len, "\n"); const int actual = (len > BUFSIZ ? BUFSIZ : len); write (2, buf, actual); errno = lasterrno; SetLastError (lasterror); return;}#ifdef DEBUGGINGint __stdcall__set_errno (const char *func, int ln, int val){ debug_printf ("%s:%d val %d", func, ln, val); return _impure_ptr->_errno = val;}#endif /* DEBUGGING */GENERIC_MAPPING access_mapping;static BOOLsetup_privileges (){ BOOL rc, ret_val; HANDLE hToken = NULL; TOKEN_PRIVILEGES sPrivileges; rc = OpenProcessToken (GetCurrentProcess () , TOKEN_ALL_ACCESS , &hToken) ; if (!rc) { system_printf ("error opening process token (%lu)", GetLastError ()); ret_val = FALSE; goto out; } rc = LookupPrivilegeValue (NULL, SE_DEBUG_NAME, &sPrivileges.Privileges[0].Luid); if (!rc) { system_printf ("error getting privilege luid (%lu)", GetLastError ()); ret_val = FALSE; goto out; } sPrivileges.PrivilegeCount = 1 ; sPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED ; rc = AdjustTokenPrivileges (hToken, FALSE, &sPrivileges, 0, NULL, NULL) ; if (!rc) { system_printf ("error adjusting privilege level. (%lu)", GetLastError ()); ret_val = FALSE; goto out; } access_mapping.GenericRead = FILE_READ_DATA; access_mapping.GenericWrite = FILE_WRITE_DATA; access_mapping.GenericExecute = 0; access_mapping.GenericAll = FILE_READ_DATA | FILE_WRITE_DATA; ret_val = TRUE;out: CloseHandle (hToken); return ret_val;}intcheck_and_dup_handle (HANDLE from_process, HANDLE to_process, HANDLE from_process_token, DWORD access, HANDLE from_handle, HANDLE *to_handle_ptr, BOOL bInheritHandle = FALSE){ HANDLE local_handle = NULL; int ret_val = EACCES; if (from_process != GetCurrentProcess ()) { if (!DuplicateHandle (from_process, from_handle, GetCurrentProcess (), &local_handle, 0, bInheritHandle, DUPLICATE_SAME_ACCESS)) { system_printf ("error getting handle(%u) to server (%lu)", (unsigned int)from_handle, GetLastError ()); goto out; } } else local_handle = from_handle; if (!wincap.has_security ()) assert (!from_process_token); else { char sd_buf [1024]; PSECURITY_DESCRIPTOR sd = (PSECURITY_DESCRIPTOR) &sd_buf; DWORD bytes_needed; PRIVILEGE_SET ps; DWORD ps_len = sizeof (ps); BOOL status; if (!GetKernelObjectSecurity (local_handle, (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION), sd, sizeof (sd_buf), &bytes_needed)) { system_printf ("error getting handle SD (%lu)", GetLastError ()); goto out; } MapGenericMask (&access, &access_mapping); if (!AccessCheck (sd, from_process_token, access, &access_mapping, &ps, &ps_len, &access, &status)) { system_printf ("error checking access rights (%lu)", GetLastError ()); goto out; } if (!status) { system_printf ("access to object denied"); goto out; } } if (!DuplicateHandle (from_process, from_handle, to_process, to_handle_ptr, access, bInheritHandle, 0)) { system_printf ("error getting handle to client (%lu)", GetLastError ()); goto out; } // verbose: debug_printf ("Duplicated %p to %p", from_handle, *to_handle_ptr); ret_val = 0; out: if (local_handle && from_process != GetCurrentProcess ()) CloseHandle (local_handle); return (ret_val);}/* * client_request_attach_tty::serve () */voidclient_request_attach_tty::serve (transport_layer_base *const conn, process_cache *){ assert (conn); assert (!error_code ()); if (!wincap.has_security ()) { syscall_printf ("operation only supported on systems with security"); error_code (EINVAL); msglen (0); return; } if (msglen () != sizeof (req)) { syscall_printf ("bad request body length: expecting %lu bytes, got %lu", sizeof (req), msglen ()); error_code (EINVAL); msglen (0); return; } msglen (0); // Until we fill in some fields. // verbose: debug_printf ("pid %ld:(%p,%p) -> pid %ld", // req.master_pid, req.from_master, req.to_master, // req.pid); // verbose: debug_printf ("opening process %ld", req.master_pid); const HANDLE from_process_handle = OpenProcess (PROCESS_DUP_HANDLE, FALSE, req.master_pid); if (!from_process_handle) { system_printf ("error opening `from' process, error = %lu", GetLastError ()); error_code (EACCES); return; } // verbose: debug_printf ("opening process %ld", req.pid); const HANDLE to_process_handle = OpenProcess (PROCESS_DUP_HANDLE, FALSE, req.pid); if (!to_process_handle) { system_printf ("error opening `to' process, error = %lu", GetLastError ()); CloseHandle (from_process_handle); error_code (EACCES); return; } // verbose: debug_printf ("Impersonating client"); conn->impersonate_client (); HANDLE token_handle = NULL; // verbose: debug_printf ("about to open thread token"); const DWORD rc = OpenThreadToken (GetCurrentThread (), TOKEN_QUERY, TRUE, &token_handle); // verbose: debug_printf ("opened thread token, rc=%lu", rc); conn->revert_to_self (); if (!rc) { system_printf ("error opening thread token, error = %lu", GetLastError ()); CloseHandle (from_process_handle); CloseHandle (to_process_handle); error_code (EACCES); return; } // From this point on, a reply body is returned to the client. const HANDLE from_master = req.from_master; const HANDLE to_master = req.to_master; req.from_master = NULL; req.to_master = NULL; msglen (sizeof (req)); if (from_master) if (check_and_dup_handle (from_process_handle, to_process_handle, token_handle, GENERIC_READ, from_master, &req.from_master, TRUE) != 0) { system_printf ("error duplicating from_master handle, error = %lu", GetLastError ()); error_code (EACCES); } if (to_master) if (check_and_dup_handle (from_process_handle, to_process_handle, token_handle, GENERIC_WRITE, to_master, &req.to_master, TRUE) != 0) { system_printf ("error duplicating to_master handle, error = %lu", GetLastError ()); error_code (EACCES); } CloseHandle (from_process_handle); CloseHandle (to_process_handle); CloseHandle (token_handle); debug_printf ("%lu(%lu, %lu) -> %lu(%lu,%lu)", req.master_pid, from_master, to_master, req.pid, req.from_master, req.to_master); return;}voidclient_request_get_version::serve (transport_layer_base *, process_cache *){ assert (!error_code ()); if (msglen ()) syscall_printf ("unexpected request body ignored: %lu bytes", msglen ()); msglen (sizeof (version));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -