summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/internal/ntapi.c20
-rw-r--r--src/internal/ntapi_fnapi.h4
-rw-r--r--src/internal/ntapi_impl.h26
-rw-r--r--src/ipc/ntapi_ipc_connect.c249
-rw-r--r--src/process/ntapi_tt_fork.c20
5 files changed, 317 insertions, 2 deletions
diff --git a/src/internal/ntapi.c b/src/internal/ntapi.c
index 336b5db..da91cfe 100644
--- a/src/internal/ntapi.c
+++ b/src/internal/ntapi.c
@@ -130,6 +130,20 @@ static int32_t __fastcall __ntapi_init_once(ntapi_vtbl ** pvtbl)
if (status != NT_STATUS_SUCCESS)
return status;
+ /* ipc connection list */
+ if ((status = dalist_init_ex(
+ &internals->ipc_conns,
+ sizeof(nt_ipc_conn),
+ NT_ALLOCATION_GRANULARITY,
+ __ntapi_ipc_page_alloc,
+ DALIST_MEMFN_CUSTOM)))
+ return status;
+
+ dalist_deposit_memory_block(
+ &internals->ipc_conns,
+ &__ntapi_img_bss.ipc_buffer,
+ __NT_BSS_IPC_BUFFER_SIZE);
+
/* hashed import table */
__ntapi_tt_populate_hashed_import_table(
pe_get_ntdll_module_handle(),
@@ -165,6 +179,12 @@ static int32_t __fastcall __ntapi_init_once(ntapi_vtbl ** pvtbl)
__ntapi->tt_open_logical_parent_directory = __ntapi_tt_open_logical_parent_directory;
__ntapi->tt_open_physical_parent_directory = __ntapi_tt_open_physical_parent_directory;
+ /* nt_ipc.h */
+ __ntapi->ipc_connect_by_attr = __ntapi_ipc_connect_by_attr;
+ __ntapi->ipc_connect_by_name = __ntapi_ipc_connect_by_name;
+ __ntapi->ipc_connect_by_symlink = __ntapi_ipc_connect_by_symlink;
+ __ntapi->ipc_connect_by_port = __ntapi_ipc_connect_by_port;
+
/* nt_ldr.h */
__ntapi->ldr_load_system_dll = __ntapi_ldr_load_system_dll;
__ntapi->ldr_create_state_snapshot = __ntapi_ldr_create_state_snapshot;
diff --git a/src/internal/ntapi_fnapi.h b/src/internal/ntapi_fnapi.h
index 546c335..8ff01f5 100644
--- a/src/internal/ntapi_fnapi.h
+++ b/src/internal/ntapi_fnapi.h
@@ -46,6 +46,10 @@ ntapi_tt_open_physical_parent_directory __ntapi_tt_open_physical_parent_directo
/* nt_ipc.h */
+ntapi_ipc_connect_by_attr __ntapi_ipc_connect_by_attr;
+ntapi_ipc_connect_by_name __ntapi_ipc_connect_by_name;
+ntapi_ipc_connect_by_symlink __ntapi_ipc_connect_by_symlink;
+ntapi_ipc_connect_by_port __ntapi_ipc_connect_by_port;
ntapi_ipc_create_pipe __ntapi_ipc_create_pipe_v1;
ntapi_ipc_create_pipe __ntapi_ipc_create_pipe_v2;
diff --git a/src/internal/ntapi_impl.h b/src/internal/ntapi_impl.h
index aca201b..870e5fd 100644
--- a/src/internal/ntapi_impl.h
+++ b/src/internal/ntapi_impl.h
@@ -39,6 +39,10 @@
#ifndef __NT_SYNC_BLOCK_LOCK_TRIES
#define __NT_SYNC_BLOCK_LOCK_TRIES 1024
#endif
+
+#ifndef __NT_IPC_PAGES
+#define __NT_IPC_PAGES 64
+#endif
/* user-defined options: tail */
/* internal page size */
@@ -48,23 +52,27 @@
/* .bss section */
#ifndef __NT_BSS_RESERVED_PAGES
-#define __NT_BSS_RESERVED_PAGES 8
+#define __NT_BSS_RESERVED_PAGES 10
#endif
/* runtime buffers */
#define __NT_BSS_ARGV_BUFFER_SIZE __NT_INTERNAL_PAGE_SIZE * 2
+#define __NT_BSS_IPC_BUFFER_SIZE __NT_INTERNAL_PAGE_SIZE * 2
+
#define __NT_BSS_ARGV_MAX_IDX __NT_BSS_ARGV_BUFFER_SIZE \
/ sizeof(uintptr_t)
#define __NT_BSS_ARGS_BUFFER_SIZE __NT_INTERNAL_PAGE_SIZE \
* __NT_BSS_RESERVED_PAGES \
- - __NT_BSS_ARGV_BUFFER_SIZE
+ - __NT_BSS_ARGV_BUFFER_SIZE \
+ - __NT_BSS_IPC_BUFFER_SIZE
/* ntapi .bss section structure */
typedef struct ___ntapi_img_sec_bss {
wchar16_t * argv_envp_array[__NT_BSS_ARGV_MAX_IDX];
char args_envs_buffer[__NT_BSS_ARGS_BUFFER_SIZE];
+ size_t ipc_buffer[__NT_BSS_IPC_BUFFER_SIZE / sizeof(size_t)];
} __ntapi_img_sec_bss;
@@ -85,6 +93,9 @@ typedef struct __attr_ptr_size_aligned__ _ntapi_internals {
void ** csr_port_handle_addr;
void * hdev_mount_point_mgr;
void * hany[8];
+ struct dalist_ex ipc_conns;
+ void * ipc_pages[__NT_IPC_PAGES];
+ int32_t ipc_page;
intptr_t hlock;
uintptr_t v1_pipe_counter;
ntapi_tt_get_csr_port_handle_addr_by_logic * tt_get_csr_port_handle_addr_by_logic;
@@ -92,6 +103,15 @@ typedef struct __attr_ptr_size_aligned__ _ntapi_internals {
} ntapi_internals;
+/* ipc internals */
+typedef struct _nt_ipc_conn {
+ nt_port_attr attr;
+ void * hsection;
+ void * secaddr;
+ size_t secsize;
+} nt_ipc_conn;
+
+
/* __ntapi_img_sec_data */
typedef struct __attr_ptr_size_aligned__ ___ntapi_img_sec_rdata {
ntapi_hashed_symbol __ntapi_import_table[__NT_IMPORTED_SYMBOLS_ARRAY_SIZE];
@@ -120,6 +140,8 @@ ntapi_internals * __cdecl __ntapi_internals(void);
int32_t __ntapi_tt_open_file_utf8(void ** hfile, void * hat, const char * arg, int fprivate, wchar16_t *, uint32_t);
int32_t __ntapi_tt_open_dir_utf8(void ** hfile, void * hat, const char * arg, int fprivate, wchar16_t *, uint32_t);
+/* ipc internals */
+int __ntapi_ipc_page_alloc(struct dalist_ex * dlist, void ** addr, size_t * alloc_size);
/* debug */
#define __ntidx(x) (&(((ntapi_vtbl *)0)->x)) / sizeof(size_t)
diff --git a/src/ipc/ntapi_ipc_connect.c b/src/ipc/ntapi_ipc_connect.c
new file mode 100644
index 0000000..d61e869
--- /dev/null
+++ b/src/ipc/ntapi_ipc_connect.c
@@ -0,0 +1,249 @@
+/********************************************************/
+/* ntapi: Native API core library */
+/* Copyright (C) 2013--2017 Z. Gilboa */
+/* Released under GPLv2 and GPLv3; see COPYING.NTAPI. */
+/********************************************************/
+
+#include <psxtypes/psxtypes.h>
+#include <ntapi/nt_file.h>
+#include <ntapi/nt_string.h>
+#include <ntapi/nt_atomic.h>
+#include <ntapi/ntapi.h>
+#include "ntapi_impl.h"
+
+static int32_t __ipc_connect_return(
+ intptr_t * hlock,
+ int32_t status)
+{
+ at_store(hlock,0);
+ return status;
+}
+
+
+static int32_t __ipc_connect_by_attr(
+ void ** hport,
+ const nt_port_attr * attr,
+ nt_unicode_string * str,
+ void * hconn,
+ __out void ** hsection,
+ __out void ** secaddr,
+ __out size_t * secsize)
+{
+ int32_t status;
+ struct dalist_node_ex * node;
+ const nt_port_attr * conn;
+ nt_port_attr * nconn;
+ nt_ipc_conn * ipc;
+ intptr_t * hlock;
+ ntapi_internals * __internals;
+
+ /* init */
+ __internals = __ntapi_internals();
+
+ /* lock */
+ hlock = &(__internals->hlock);
+
+ if (at_locked_cas(hlock,0,1))
+ return NT_STATUS_RESOURCE_NOT_OWNED;
+
+ /* already connected? */
+ node = (struct dalist_node_ex *)__internals->ipc_conns.head;
+
+ for (; node; node=node->next) {
+ ipc = (nt_ipc_conn *)&node->dblock;
+ conn = &ipc->attr;
+
+ if ((attr->keys.key[0] == conn->keys.key[0])
+ && (attr->keys.key[1] == conn->keys.key[1])
+ && (attr->keys.key[2] == conn->keys.key[2])
+ && (attr->keys.key[3] == conn->keys.key[3])
+ && (attr->keys.key[4] == conn->keys.key[4])
+ && (attr->keys.key[5] == conn->keys.key[5])
+ && !__ntapi->tt_guid_compare(
+ &attr->guid,
+ &conn->guid)) {
+ /* already connected */
+ if (hconn)
+ return __ipc_connect_return(
+ hlock,
+ ((uintptr_t)hconn == node->key)
+ ? NT_STATUS_SUCCESS
+ : NT_STATUS_CONTEXT_MISMATCH);
+
+ *hport = (void *)node->key;
+ *hsection = ipc->hsection;
+ *secaddr = ipc->secaddr;
+ *secsize = ipc->secsize;
+
+ return __ipc_connect_return(hlock,NT_STATUS_SUCCESS);
+ }
+ }
+
+ /* allocate list node */
+ if ((status = dalist_get_free_node(
+ &__internals->ipc_conns,
+ (void **)&node)))
+ return __ipc_connect_return(hlock,status);
+
+ /* connect as needed */
+ if (!hconn) {
+ status = __ntapi->zw_connect_port(
+ &hconn,str,0,0,0,0,0,0);
+
+ if (status) {
+ dalist_deposit_free_node(
+ &__internals->ipc_conns,
+ node);
+
+ return __ipc_connect_return(hlock,status);
+ }
+ }
+
+ /* add connection */
+ node->key = (uintptr_t)hconn;
+ ipc = (nt_ipc_conn *)&node->dblock;
+ nconn = &ipc->attr;
+
+ __ntapi->tt_aligned_block_memcpy(
+ (uintptr_t *)nconn,
+ (uintptr_t *)attr,
+ sizeof(nt_port_attr));
+
+ ipc->hsection = 0;
+ ipc->secaddr = 0;
+ ipc->secsize = 0;
+
+ dalist_insert_node_by_key(
+ &__internals->ipc_conns,
+ node);
+
+ /* all done */
+ *hport = hconn;
+ *hsection = 0;
+ *secaddr = 0;
+ *secsize = 0;
+
+ return __ipc_connect_return(hlock,NT_STATUS_SUCCESS);
+}
+
+
+int32_t __stdcall __ntapi_ipc_connect_by_attr(
+ __out void ** hport,
+ __in nt_port_attr * attr)
+{
+ nt_port_name name;
+ nt_unicode_string str;
+
+ __ntapi->tt_port_name_from_attr(
+ &name,attr);
+
+ str.strlen = ((size_t)&(((nt_port_name *)0)->null_termination));
+ str.maxlen = 0;
+ str.buffer = &name.base_named_objects[0];
+
+ return __ipc_connect_by_attr(
+ hport,attr,&str,0,
+ &(void *){0},
+ &(void *){0},
+ &(size_t){0});
+}
+
+
+int32_t __stdcall __ntapi_ipc_connect_by_name(
+ __out void ** hport,
+ __in nt_port_name * name)
+{
+ int32_t status;
+ nt_port_attr attr;
+ nt_unicode_string str;
+
+ if ((status = __ntapi->tt_port_attr_from_name(&attr,name)))
+ return status;
+
+ str.strlen = ((size_t)&(((nt_port_name *)0)->null_termination));
+ str.maxlen = 0;
+ str.buffer = &name->base_named_objects[0];
+
+ return __ipc_connect_by_attr(
+ hport,&attr,&str,0,
+ &(void *){0},
+ &(void *){0},
+ &(size_t){0});
+}
+
+
+int32_t __stdcall __ntapi_ipc_connect_by_symlink(
+ __out void ** hport,
+ __in void * hsymlink)
+{
+ int32_t status;
+ nt_port_attr attr;
+ nt_port_name * name;
+ size_t namelen;
+ uintptr_t buffer[512/sizeof(uintptr_t)];
+ nt_unicode_string * str;
+
+ str = (nt_unicode_string *)buffer;
+ str->strlen = 0;
+ str->maxlen = sizeof(buffer) - sizeof(nt_unicode_string);
+ str->buffer = (wchar16_t *)&str[1];
+
+ if ((status = __ntapi->zw_query_symbolic_link_object(
+ hsymlink,str,&namelen)))
+ return status;
+
+ if (str->strlen != ((size_t)&(((nt_port_name *)0)->null_termination)))
+ return NT_STATUS_INVALID_PORT_ATTRIBUTES;
+
+ name = (nt_port_name *)str->buffer;
+
+ if ((status = __ntapi->tt_port_attr_from_name(&attr,name)))
+ return status;
+
+ return __ipc_connect_by_attr(
+ hport,&attr,str,0,
+ &(void *){0},
+ &(void *){0},
+ &(size_t){0});
+}
+
+
+int32_t __stdcall __ntapi_ipc_connect_by_port(
+ __in void * hconn,
+ __in nt_port_attr * attr)
+{
+ return __ipc_connect_by_attr(
+ &(void *){0},attr,0,hconn,
+ &(void *){0},
+ &(void *){0},
+ &(size_t){0});
+}
+
+
+int __ntapi_ipc_page_alloc(
+ struct dalist_ex * dlist,
+ void ** addr,
+ size_t * alloc_size)
+{
+ int32_t status;
+ ntapi_internals * __internals;
+
+ __internals = __ntapi_internals();
+
+ if (__internals->ipc_page == __NT_IPC_PAGES)
+ return NT_STATUS_QUOTA_EXCEEDED;
+
+ if ((status = __ntapi->zw_allocate_virtual_memory(
+ NT_CURRENT_PROCESS_HANDLE,
+ addr,0,alloc_size,
+ NT_MEM_COMMIT,
+ NT_PAGE_READWRITE)))
+ return status;
+
+ dalist_deposit_memory_block(
+ dlist,*addr,*alloc_size);
+
+ __internals->ipc_pages[__internals->ipc_page++] = *addr;
+
+ return 0;
+}
diff --git a/src/process/ntapi_tt_fork.c b/src/process/ntapi_tt_fork.c
index 58cf2c3..9c0d2de 100644
--- a/src/process/ntapi_tt_fork.c
+++ b/src/process/ntapi_tt_fork.c
@@ -24,6 +24,7 @@ static intptr_t __fastcall __ntapi_tt_fork_finalize(
int32_t status;
nt_oa oa;
nt_cid cid;
+ int page;
ntapi_internals * __internals;
__internals = __ntapi_internals();
@@ -53,6 +54,25 @@ static intptr_t __fastcall __ntapi_tt_fork_finalize(
&oa,&cid)))
return status;
+ if ((status = dalist_init_ex(
+ &__internals->ipc_conns,
+ sizeof(nt_ipc_conn),
+ NT_ALLOCATION_GRANULARITY,
+ __ntapi_ipc_page_alloc,
+ DALIST_MEMFN_CUSTOM)))
+ return status;
+
+ dalist_deposit_memory_block(
+ &__internals->ipc_conns,
+ __internals->ntapi_img_sec_bss->ipc_buffer,
+ __NT_BSS_IPC_BUFFER_SIZE);
+
+ for (page=0; __internals->ipc_page; page++)
+ dalist_deposit_memory_block(
+ &__internals->ipc_conns,
+ __internals->ipc_pages[page],
+ NT_ALLOCATION_GRANULARITY);
+
return 0;
}