server: Check duplicated handle access against the calling thread token and target process token.
Signed-off-by: Zebediah Figura <z.figura12@gmail.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
d0bea3d702
commit
fa1b0fcf6c
|
@ -7704,8 +7704,8 @@ static void test_duplicate_handle_access(void)
|
||||||
|
|
||||||
SetLastError(0xdeadbeef);
|
SetLastError(0xdeadbeef);
|
||||||
ret = DuplicateHandle(GetCurrentProcess(), sync_event, pi.hProcess, &event2, EVENT_MODIFY_STATE, FALSE, 0);
|
ret = DuplicateHandle(GetCurrentProcess(), sync_event, pi.hProcess, &event2, EVENT_MODIFY_STATE, FALSE, 0);
|
||||||
todo_wine ok(!ret, "expected failure\n");
|
ok(!ret, "expected failure\n");
|
||||||
todo_wine ok(GetLastError() == ERROR_ACCESS_DENIED, "got error %u\n", GetLastError());
|
ok(GetLastError() == ERROR_ACCESS_DENIED, "got error %u\n", GetLastError());
|
||||||
|
|
||||||
ret = WaitForSingleObject(pi.hProcess, 1000);
|
ret = WaitForSingleObject(pi.hProcess, 1000);
|
||||||
ok(!ret, "wait failed\n");
|
ok(!ret, "wait failed\n");
|
||||||
|
@ -7736,7 +7736,7 @@ static void test_duplicate_handle_access_child(void)
|
||||||
ok(GetLastError() == ERROR_ACCESS_DENIED, "got error %u\n", GetLastError());
|
ok(GetLastError() == ERROR_ACCESS_DENIED, "got error %u\n", GetLastError());
|
||||||
|
|
||||||
ret = DuplicateHandle(process, event, process, &event2, EVENT_MODIFY_STATE, FALSE, 0);
|
ret = DuplicateHandle(process, event, process, &event2, EVENT_MODIFY_STATE, FALSE, 0);
|
||||||
todo_wine ok(ret, "got error %u\n", GetLastError());
|
ok(ret, "got error %u\n", GetLastError());
|
||||||
|
|
||||||
SetLastError(0xdeadbeef);
|
SetLastError(0xdeadbeef);
|
||||||
ret = DuplicateHandle(process, event, GetCurrentProcess(), &event2, EVENT_MODIFY_STATE, FALSE, 0);
|
ret = DuplicateHandle(process, event, GetCurrentProcess(), &event2, EVENT_MODIFY_STATE, FALSE, 0);
|
||||||
|
|
|
@ -286,7 +286,7 @@ obj_handle_t alloc_handle( struct process *process, void *ptr, unsigned int acce
|
||||||
{
|
{
|
||||||
struct object *obj = ptr;
|
struct object *obj = ptr;
|
||||||
access = obj->ops->map_access( obj, access ) & ~RESERVED_ALL;
|
access = obj->ops->map_access( obj, access ) & ~RESERVED_ALL;
|
||||||
if (access && !check_object_access( obj, &access )) return 0;
|
if (access && !check_object_access( NULL, obj, &access )) return 0;
|
||||||
return alloc_handle_entry( process, ptr, access, attr );
|
return alloc_handle_entry( process, ptr, access, attr );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -308,7 +308,7 @@ static obj_handle_t alloc_global_handle_no_access_check( void *obj, unsigned int
|
||||||
/* return the handle, or 0 on error */
|
/* return the handle, or 0 on error */
|
||||||
static obj_handle_t alloc_global_handle( void *obj, unsigned int access )
|
static obj_handle_t alloc_global_handle( void *obj, unsigned int access )
|
||||||
{
|
{
|
||||||
if (access && !check_object_access( obj, &access )) return 0;
|
if (access && !check_object_access( NULL, obj, &access )) return 0;
|
||||||
return alloc_global_handle_no_access_check( obj, access );
|
return alloc_global_handle_no_access_check( obj, access );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -558,10 +558,17 @@ obj_handle_t duplicate_handle( struct process *src, obj_handle_t src_handle, str
|
||||||
/* asking for the more access rights than src_access? */
|
/* asking for the more access rights than src_access? */
|
||||||
if (access & ~src_access)
|
if (access & ~src_access)
|
||||||
{
|
{
|
||||||
|
if ((current->token && !check_object_access( current->token, obj, &access )) ||
|
||||||
|
!check_object_access( dst->token, obj, &access ))
|
||||||
|
{
|
||||||
|
release_object( obj );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (options & DUP_HANDLE_MAKE_GLOBAL)
|
if (options & DUP_HANDLE_MAKE_GLOBAL)
|
||||||
res = alloc_global_handle( obj, access );
|
res = alloc_global_handle( obj, access );
|
||||||
else
|
else
|
||||||
res = alloc_handle( dst, obj, access, attr );
|
res = alloc_handle_no_access_check( dst, obj, access, attr );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -86,7 +86,7 @@ static inline int security_equal_sid( const SID *sid1, const SID *sid2 )
|
||||||
|
|
||||||
extern void security_set_thread_token( struct thread *thread, obj_handle_t handle );
|
extern void security_set_thread_token( struct thread *thread, obj_handle_t handle );
|
||||||
extern const SID *security_unix_uid_to_sid( uid_t uid );
|
extern const SID *security_unix_uid_to_sid( uid_t uid );
|
||||||
extern int check_object_access( struct object *obj, unsigned int *access );
|
extern int check_object_access( struct token *token, struct object *obj, unsigned int *access );
|
||||||
|
|
||||||
static inline int thread_single_check_privilege( struct thread *thread, const LUID *priv)
|
static inline int thread_single_check_privilege( struct thread *thread, const LUID *priv)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1208,13 +1208,15 @@ const SID *token_get_primary_group( struct token *token )
|
||||||
return token->primary_group;
|
return token->primary_group;
|
||||||
}
|
}
|
||||||
|
|
||||||
int check_object_access(struct object *obj, unsigned int *access)
|
int check_object_access(struct token *token, struct object *obj, unsigned int *access)
|
||||||
{
|
{
|
||||||
GENERIC_MAPPING mapping;
|
GENERIC_MAPPING mapping;
|
||||||
struct token *token = current->token ? current->token : current->process->token;
|
|
||||||
unsigned int status;
|
unsigned int status;
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
|
if (!token)
|
||||||
|
token = current->token ? current->token : current->process->token;
|
||||||
|
|
||||||
mapping.GenericAll = obj->ops->map_access( obj, GENERIC_ALL );
|
mapping.GenericAll = obj->ops->map_access( obj, GENERIC_ALL );
|
||||||
|
|
||||||
if (!obj->sd)
|
if (!obj->sd)
|
||||||
|
|
|
@ -717,7 +717,7 @@ DECL_HANDLER(enum_winstation)
|
||||||
{
|
{
|
||||||
unsigned int access = WINSTA_ENUMERATE;
|
unsigned int access = WINSTA_ENUMERATE;
|
||||||
if (req->index > index++) continue;
|
if (req->index > index++) continue;
|
||||||
if (!check_object_access( &winsta->obj, &access )) continue;
|
if (!check_object_access( NULL, &winsta->obj, &access )) continue;
|
||||||
clear_error();
|
clear_error();
|
||||||
reply->next = index;
|
reply->next = index;
|
||||||
if ((name = get_object_name( &winsta->obj, &len )))
|
if ((name = get_object_name( &winsta->obj, &len )))
|
||||||
|
@ -746,7 +746,7 @@ DECL_HANDLER(enum_desktop)
|
||||||
unsigned int access = DESKTOP_ENUMERATE;
|
unsigned int access = DESKTOP_ENUMERATE;
|
||||||
if (req->index > index++) continue;
|
if (req->index > index++) continue;
|
||||||
if (!desktop->obj.name) continue;
|
if (!desktop->obj.name) continue;
|
||||||
if (!check_object_access( &desktop->obj, &access )) continue;
|
if (!check_object_access( NULL, &desktop->obj, &access )) continue;
|
||||||
if ((name = get_object_name( &desktop->obj, &len )))
|
if ((name = get_object_name( &desktop->obj, &len )))
|
||||||
set_reply_data( name, min( len, get_reply_max_size() ));
|
set_reply_data( name, min( len, get_reply_max_size() ));
|
||||||
release_object( winstation );
|
release_object( winstation );
|
||||||
|
|
Loading…
Reference in New Issue