From: Paul Gofman Subject: [PATCH v3 1/4] server: Allow named pipes creation with device file as root directory. Message-Id: <20201118131231.138372-1-pgofman@codeweavers.com> Date: Wed, 18 Nov 2020 16:12:28 +0300 Signed-off-by: Paul Gofman --- v2: - do not require directrory parent in get_req_object_attributes(). v3: - avoid explicit symlink check in get_req_object_attributes(). dlls/ntdll/tests/pipe.c | 34 ++++++++++++++++++++++++++++++++-- server/named_pipe.c | 2 +- server/object.c | 3 ++- server/object.h | 1 - server/request.c | 3 ++- 5 files changed, 37 insertions(+), 6 deletions(-) diff --git a/dlls/ntdll/tests/pipe.c b/dlls/ntdll/tests/pipe.c index 9e8b623d75b..bfc8dc0b3be 100644 --- a/dlls/ntdll/tests/pipe.c +++ b/dlls/ntdll/tests/pipe.c @@ -65,6 +65,7 @@ typedef struct { #endif static NTSTATUS (WINAPI *pNtFsControlFile) (HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, PVOID apc_context, PIO_STATUS_BLOCK io, ULONG code, PVOID in_buffer, ULONG in_size, PVOID out_buffer, ULONG out_size); +static NTSTATUS (WINAPI *pNtCreateDirectoryObject)(HANDLE *, ACCESS_MASK, OBJECT_ATTRIBUTES *); static NTSTATUS (WINAPI *pNtCreateNamedPipeFile) (PHANDLE handle, ULONG access, POBJECT_ATTRIBUTES attr, PIO_STATUS_BLOCK iosb, ULONG sharing, ULONG dispo, ULONG options, @@ -73,6 +74,7 @@ static NTSTATUS (WINAPI *pNtCreateNamedPipeFile) (PHANDLE handle, ULONG access, ULONG inbound_quota, ULONG outbound_quota, PLARGE_INTEGER timeout); static NTSTATUS (WINAPI *pNtQueryInformationFile) (IN HANDLE FileHandle, OUT PIO_STATUS_BLOCK IoStatusBlock, OUT PVOID FileInformation, IN ULONG Length, IN FILE_INFORMATION_CLASS FileInformationClass); +static NTSTATUS (WINAPI *pNtQueryObject)(HANDLE, OBJECT_INFORMATION_CLASS, void *, ULONG, ULONG *); static NTSTATUS (WINAPI *pNtQueryVolumeInformationFile)(HANDLE handle, PIO_STATUS_BLOCK io, void *buffer, ULONG length, FS_INFORMATION_CLASS info_class); static NTSTATUS (WINAPI *pNtSetInformationFile) (HANDLE handle, PIO_STATUS_BLOCK io, PVOID ptr, ULONG len, FILE_INFORMATION_CLASS class); static NTSTATUS (WINAPI *pNtCancelIoFile) (HANDLE hFile, PIO_STATUS_BLOCK io_status); @@ -94,8 +96,10 @@ static BOOL init_func_ptrs(void) } loadfunc(NtFsControlFile) + loadfunc(NtCreateDirectoryObject) loadfunc(NtCreateNamedPipeFile) loadfunc(NtQueryInformationFile) + loadfunc(NtQueryObject) loadfunc(NtQueryVolumeInformationFile) loadfunc(NtSetInformationFile) loadfunc(NtCancelIoFile) @@ -2405,14 +2409,20 @@ static void test_security_info(void) static void test_empty_name(void) { HANDLE hdirectory, hpipe, hwrite, handle; + OBJECT_TYPE_INFORMATION *type_info; + OBJECT_NAME_INFORMATION *name_info; OBJECT_ATTRIBUTES attr; LARGE_INTEGER timeout; UNICODE_STRING name; IO_STATUS_BLOCK io; DWORD data, length; + char buffer[1024]; NTSTATUS status; BOOL ret; + type_info = (OBJECT_TYPE_INFORMATION *)buffer; + name_info = (OBJECT_NAME_INFORMATION *)buffer; + hpipe = hwrite = NULL; attr.Length = sizeof(attr); @@ -2438,13 +2448,17 @@ static void test_empty_name(void) &io, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_CREATE, FILE_SYNCHRONOUS_IO_NONALERT, 0, 0, 0, 3, 4096, 4096, &timeout); todo_wine ok(status == STATUS_OBJECT_NAME_INVALID, "Got unexpected status %#x.\n", status); - + if (!status) + CloseHandle(hpipe); CloseHandle(hdirectory); pRtlInitUnicodeString(&name, L"\\Device\\NamedPipe\\"); attr.RootDirectory = 0; attr.ObjectName = &name; + status = pNtCreateDirectoryObject(&hdirectory, GENERIC_READ | SYNCHRONIZE, &attr); + todo_wine ok(status == STATUS_OBJECT_TYPE_MISMATCH, "Got unexpected status %#x.\n", status); + status = NtCreateFile(&hdirectory, GENERIC_READ | SYNCHRONIZE, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0, NULL, 0 ); ok(!status, "Got unexpected status %#x.\n", status); @@ -2454,10 +2468,18 @@ static void test_empty_name(void) name.MaximumLength = 0; attr.RootDirectory = hdirectory; + hpipe = NULL; status = pNtCreateNamedPipeFile(&hpipe, GENERIC_READ | SYNCHRONIZE, &attr, &io, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_CREATE, FILE_SYNCHRONOUS_IO_NONALERT, 0, 0, 0, 3, 4096, 4096, &timeout); - todo_wine ok(!status, "Got unexpected status %#x.\n", status); + ok(!status, "Got unexpected status %#x.\n", status); + type_info->TypeName.Buffer = NULL; + status = pNtQueryObject(hpipe, ObjectTypeInformation, type_info, sizeof(buffer), NULL); + ok(!status, "Got unexpected status %#x.\n", status); + ok(type_info->TypeName.Buffer && !wcscmp(type_info->TypeName.Buffer, L"File"), + "Got unexpected type %s.\n", debugstr_w(type_info->TypeName.Buffer)); + status = pNtQueryObject(hpipe, ObjectNameInformation, name_info, sizeof(buffer), NULL); + todo_wine ok(status == STATUS_OBJECT_PATH_INVALID, "Got unexpected status %#x.\n", status); status = pNtCreateNamedPipeFile(&handle, GENERIC_READ | SYNCHRONIZE, &attr, &io, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, @@ -2469,6 +2491,14 @@ static void test_empty_name(void) FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 ); todo_wine ok(!status, "Got unexpected status %#x.\n", status); + type_info->TypeName.Buffer = NULL; + status = pNtQueryObject(hwrite, ObjectTypeInformation, type_info, sizeof(buffer), NULL); + todo_wine ok(!status, "Got unexpected status %#x.\n", status); + todo_wine ok(type_info->TypeName.Buffer && !wcscmp(type_info->TypeName.Buffer, L"File"), + "Got unexpected type %s.\n", debugstr_w(type_info->TypeName.Buffer)); + status = pNtQueryObject(hwrite, ObjectNameInformation, name_info, sizeof(buffer), NULL); + todo_wine ok(status == STATUS_OBJECT_PATH_INVALID, "Got unexpected status %#x.\n", status); + attr.RootDirectory = hpipe; status = NtCreateFile(&handle, GENERIC_READ | SYNCHRONIZE, &attr, &io, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, diff --git a/server/named_pipe.c b/server/named_pipe.c index 60bd059d93d..3a8cd2fb919 100644 --- a/server/named_pipe.c +++ b/server/named_pipe.c @@ -1371,7 +1371,7 @@ DECL_HANDLER(create_named_pipe) set_error( STATUS_OBJECT_PATH_SYNTAX_BAD ); return; } - if (!(root = get_directory_obj( current->process, objattr->rootdir ))) return; + if (!(root = get_handle_obj( current->process, objattr->rootdir, 0, NULL ))) return; } pipe = create_named_object( root, &named_pipe_ops, &name, objattr->attributes | OBJ_OPENIF, NULL ); diff --git a/server/object.c b/server/object.c index 9f26a6fea36..20db6b6d73c 100644 --- a/server/object.c +++ b/server/object.c @@ -337,7 +337,8 @@ void *create_named_object( struct object *parent, const struct object_ops *ops, return obj; } - new_obj = create_object( obj, ops, &new_name, attributes, sd ); + new_obj = create_object( parent && get_path_element(name->str, name->len) == name->len + ? parent : obj, ops, &new_name, attributes, sd ); release_object( obj ); done: diff --git a/server/object.h b/server/object.h index 394a4aac463..e0ae01634f6 100644 --- a/server/object.h +++ b/server/object.h @@ -253,7 +253,6 @@ extern struct object *create_obj_symlink( struct object *root, const struct unic extern struct object *create_symlink( struct object *root, const struct unicode_str *name, unsigned int attr, const struct unicode_str *target, const struct security_descriptor *sd ); - /* global variables */ /* command-line options */ diff --git a/server/request.c b/server/request.c index 97bf1a746d2..24cfda26110 100644 --- a/server/request.c +++ b/server/request.c @@ -66,6 +66,7 @@ #include "process.h" #include "thread.h" #include "security.h" +#include "handle.h" #define WANT_REQUEST_HANDLERS #include "request.h" @@ -205,7 +206,7 @@ const struct object_attributes *get_req_object_attributes( const struct security } if (root && attr->rootdir && attr->name_len) { - if (!(*root = get_directory_obj( current->process, attr->rootdir ))) return NULL; + if (!(*root = get_handle_obj( current->process, attr->rootdir, 0, NULL ))) return NULL; } *sd = attr->sd_len ? (const struct security_descriptor *)(attr + 1) : NULL; name->len = attr->name_len; -- 2.28.0