Split from https://gitlab.winehq.org/wine/wine/-/merge_requests/8875
-- v3: ntdll: Check inproc sync signal rights in signal and wait. server: Use a specific type for internal inproc event syncs.
From: Rémi Bernon rbernon@codeweavers.com
--- server/inproc_sync.c | 14 ++++++++++---- server/object.h | 2 +- server/protocol.def | 4 ++-- server/queue.c | 2 +- 4 files changed, 14 insertions(+), 8 deletions(-)
diff --git a/server/inproc_sync.c b/server/inproc_sync.c index f20410c85ed..1452cbfac5c 100644 --- a/server/inproc_sync.c +++ b/server/inproc_sync.c @@ -87,15 +87,21 @@ static const struct object_ops inproc_sync_ops = inproc_sync_destroy, /* destroy */ };
-struct inproc_sync *create_inproc_event_sync( int manual, int signaled ) +struct inproc_sync *create_inproc_internal_sync( int manual, int signaled ) { struct ntsync_event_args args = {.signaled = signaled, .manual = manual}; struct inproc_sync *event;
if (!(event = alloc_object( &inproc_sync_ops ))) return NULL; - event->type = INPROC_SYNC_EVENT; - event->fd = ioctl( get_inproc_device_fd(), NTSYNC_IOC_CREATE_EVENT, &args ); + event->type = INPROC_SYNC_INTERNAL; + event->fd = ioctl( get_inproc_device_fd(), NTSYNC_IOC_CREATE_EVENT, &args );
+ if (event->fd == -1) + { + set_error( STATUS_NO_MORE_FILES ); + release_object( event ); + return NULL; + } return event; }
@@ -154,7 +160,7 @@ int get_inproc_device_fd(void) return -1; }
-struct inproc_sync *create_inproc_event_sync( int manual, int signaled ) +struct inproc_sync *create_inproc_internal_sync( int manual, int signaled ) { return NULL; } diff --git a/server/object.h b/server/object.h index 51b74429e73..203734a565f 100644 --- a/server/object.h +++ b/server/object.h @@ -244,7 +244,7 @@ extern void abandon_mutexes( struct thread *thread );
struct inproc_sync; extern int get_inproc_device_fd(void); -extern struct inproc_sync *create_inproc_event_sync( int manual, int signaled ); +extern struct inproc_sync *create_inproc_internal_sync( int manual, int signaled ); extern void signal_inproc_sync( struct inproc_sync *sync ); extern void reset_inproc_sync( struct inproc_sync *sync );
diff --git a/server/protocol.def b/server/protocol.def index 6bb7ae155c6..785f0e26d4e 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -4126,8 +4126,8 @@ struct handle_info
enum inproc_sync_type { - INPROC_SYNC_UNKNOWN = 0, - INPROC_SYNC_EVENT = 1, + INPROC_SYNC_UNKNOWN = 0, + INPROC_SYNC_INTERNAL = 1, };
/* Get the in-process synchronization fd associated with the waitable handle */ diff --git a/server/queue.c b/server/queue.c index 596742bc64c..0e286063285 100644 --- a/server/queue.c +++ b/server/queue.c @@ -328,7 +328,7 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_ list_init( &queue->expired_timers ); for (i = 0; i < NB_MSG_KINDS; i++) list_init( &queue->msg_list[i] );
- if (get_inproc_device_fd() >= 0 && !(queue->inproc_sync = create_inproc_event_sync( 1, 0 ))) goto error; + if (get_inproc_device_fd() >= 0 && !(queue->inproc_sync = create_inproc_internal_sync( 1, 0 ))) goto error; if (!(queue->shared = alloc_shared_object())) goto error;
SHARED_WRITE_BEGIN( queue->shared, queue_shm_t )
From: Elizabeth Figura zfigura@codeweavers.com
--- dlls/ntdll/unix/sync.c | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-)
diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c index acdb7b3d9f8..a07ff3ddecf 100644 --- a/dlls/ntdll/unix/sync.c +++ b/dlls/ntdll/unix/sync.c @@ -309,9 +309,9 @@ static unsigned int validate_open_object_attributes( const OBJECT_ATTRIBUTES *at
struct inproc_sync { - int fd; - unsigned int access; - unsigned int type : 2; + int fd; /* unix file descriptor */ + unsigned int access; /* handle access rights */ + unsigned int type; /* enum inproc_sync_type */ };
static void release_inproc_sync( struct inproc_sync *sync ) @@ -355,6 +355,18 @@ static NTSTATUS get_inproc_sync( HANDLE handle, ACCESS_MASK desired_access, stru return STATUS_SUCCESS; }
+extern NTSTATUS check_signal_access( struct inproc_sync *sync ) +{ + switch (sync->type) + { + case INPROC_SYNC_INTERNAL: + return STATUS_OBJECT_TYPE_MISMATCH; + } + + assert( 0 ); + return STATUS_OBJECT_TYPE_MISMATCH; +} + static NTSTATUS inproc_release_semaphore( HANDLE handle, ULONG count, ULONG *prev_count ) { if (inproc_device_fd < 0) return STATUS_NOT_IMPLEMENTED; @@ -429,7 +441,26 @@ static NTSTATUS inproc_wait( DWORD count, const HANDLE *handles, BOOLEAN wait_an static NTSTATUS inproc_signal_and_wait( HANDLE signal, HANDLE wait, BOOLEAN alertable, const LARGE_INTEGER *timeout ) { + struct inproc_sync stack_signal, stack_wait, *signal_sync = &stack_signal, *wait_sync = &stack_wait; + NTSTATUS ret; + if (inproc_device_fd < 0) return STATUS_NOT_IMPLEMENTED; + + if ((ret = get_inproc_sync( signal, 0, signal_sync ))) return ret; + if ((ret = check_signal_access( signal_sync ))) + { + release_inproc_sync( signal_sync ); + return ret; + } + + if ((ret = get_inproc_sync( wait, SYNCHRONIZE, wait_sync ))) + { + release_inproc_sync( signal_sync ); + return ret; + } + + release_inproc_sync( signal_sync ); + release_inproc_sync( wait_sync ); return STATUS_NOT_IMPLEMENTED; }
v2: Handle fd allocation failure.