2009/11/9 Dan Kegel <d...@kegel.com>: > I've never used the security apis, so I'm pretty unfamiliar with them. > Valgrinding chromium's sandbox_unittests.exe shows the leak > > 16 bytes in 1 blocks are definitely lost in loss record 123 of 728 > at RtlAllocateHeap (heap.c:1423) > by RtlAllocateAndInitializeSid (sec.c:156) > by NtQueryInformationToken (nt.c:379) > by GetTokenInformation (security.c:676) > by ATL::CAccessToken::GetInfoConvert<ATL::CSid,_TOKEN_PRIMARY_GROUP> > (atlsecurity.h:754) > by ATL::CAccessToken::GetPrimaryGroup (atlsecurity.inl:3623) > by sandbox::RestrictedTokenTest_CustomInit_Test::TestBody > (restricted_token_unittest.cc:92) > > The test in question is on line 92 of > http://src.chromium.org/viewvc/chrome/trunk/src/sandbox/src/restricted_token_unittest.cc?revision=11651 > > Can someone familiar with this stuff have a look? > I suspect it's a problem with the test, but > can't figure out what's going on. I would > have thought the destructors for ATL::CAccessToken > and ATL::CSid would have freed everything. > (I think the code leaks token_handle, but fixing > that doesn't get rid of the reported leak.)
Hi Dan, The bug is in the Wine code. Try the attached patch, which should fix it as a side-effect. Thanks, -- Rob Shearman
From 766547300875c677ea9cfa6b3a10a3fb717c68ee Mon Sep 17 00:00:00 2001 From: Robert Shearman <robertshear...@gmail.com> Date: Mon, 27 Apr 2009 18:53:15 +0100 Subject: [PATCH] server: Extend get_token_user server call to also retrieve SIDs for the token's owner or primary group. To: wine-patches <wine-patc...@winehq.org> --- dlls/ntdll/nt.c | 51 ++++++++++++++++++++++++++++----------------------- server/protocol.def | 9 +++++---- server/token.c | 45 +++++++++++++++++++++++++++++++++++++-------- 3 files changed, 70 insertions(+), 35 deletions(-) diff --git a/dlls/ntdll/nt.c b/dlls/ntdll/nt.c index b29a8ae..bc01a4f 100644 --- a/dlls/ntdll/nt.c +++ b/dlls/ntdll/nt.c @@ -257,12 +257,6 @@ NTSTATUS WINAPI NtQueryInformationToken( switch (tokeninfoclass) { - case TokenOwner: - len = sizeof(TOKEN_OWNER) + sizeof(SID); - break; - case TokenPrimaryGroup: - len = sizeof(TOKEN_PRIMARY_GROUP); - break; case TokenSource: len = sizeof(TOKEN_SOURCE); break; @@ -287,16 +281,17 @@ NTSTATUS WINAPI NtQueryInformationToken( switch (tokeninfoclass) { case TokenUser: - SERVER_START_REQ( get_token_user ) + SERVER_START_REQ( get_token_sid ) { TOKEN_USER * tuser = tokeninfo; PSID sid = tuser + 1; DWORD sid_len = tokeninfolength < sizeof(TOKEN_USER) ? 0 : tokeninfolength - sizeof(TOKEN_USER); req->handle = wine_server_obj_handle( token ); + req->which_sid = tokeninfoclass; wine_server_set_reply( req, sid, sid_len ); status = wine_server_call( req ); - if (retlen) *retlen = reply->user_len + sizeof(TOKEN_USER); + if (retlen) *retlen = reply->sid_len + sizeof(TOKEN_USER); if (status == STATUS_SUCCESS) { tuser->User.Sid = sid; @@ -372,17 +367,21 @@ NTSTATUS WINAPI NtQueryInformationToken( break; } case TokenPrimaryGroup: - if (tokeninfo) + SERVER_START_REQ( get_token_sid ) { TOKEN_PRIMARY_GROUP *tgroup = tokeninfo; - SID_IDENTIFIER_AUTHORITY sid = {SECURITY_NT_AUTHORITY}; - RtlAllocateAndInitializeSid( &sid, - 2, - SECURITY_BUILTIN_DOMAIN_RID, - DOMAIN_ALIAS_RID_ADMINS, - 0, 0, 0, 0, 0, 0, - &(tgroup->PrimaryGroup)); + PSID sid = tgroup + 1; + DWORD sid_len = tokeninfolength < sizeof(TOKEN_PRIMARY_GROUP) ? 0 : tokeninfolength - sizeof(TOKEN_PRIMARY_GROUP); + + req->handle = wine_server_obj_handle( token ); + req->which_sid = tokeninfoclass; + wine_server_set_reply( req, sid, sid_len ); + status = wine_server_call( req ); + if (retlen) *retlen = reply->sid_len + sizeof(TOKEN_PRIMARY_GROUP); + if (status == STATUS_SUCCESS) + tgroup->PrimaryGroup = sid; } + SERVER_END_REQ; break; case TokenPrivileges: SERVER_START_REQ( get_token_privileges ) @@ -398,15 +397,21 @@ NTSTATUS WINAPI NtQueryInformationToken( SERVER_END_REQ; break; case TokenOwner: - if (tokeninfo) + SERVER_START_REQ( get_token_sid ) { - TOKEN_OWNER *owner = tokeninfo; - PSID sid = owner + 1; - SID_IDENTIFIER_AUTHORITY localSidAuthority = {SECURITY_NT_AUTHORITY}; - RtlInitializeSid(sid, &localSidAuthority, 1); - *(RtlSubAuthoritySid(sid, 0)) = SECURITY_INTERACTIVE_RID; - owner->Owner = sid; + TOKEN_OWNER *towner = tokeninfo; + PSID sid = towner + 1; + DWORD sid_len = tokeninfolength < sizeof(TOKEN_OWNER) ? 0 : tokeninfolength - sizeof(TOKEN_OWNER); + + req->handle = wine_server_obj_handle( token ); + req->which_sid = tokeninfoclass; + wine_server_set_reply( req, sid, sid_len ); + status = wine_server_call( req ); + if (retlen) *retlen = reply->sid_len + sizeof(TOKEN_OWNER); + if (status == STATUS_SUCCESS) + towner->Owner = sid; } + SERVER_END_REQ; break; case TokenImpersonationLevel: SERVER_START_REQ( get_token_impersonation_level ) diff --git a/server/protocol.def b/server/protocol.def index a0e1702..b99b911 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -2915,18 +2915,19 @@ enum message_type VARARG(privileges,LUID_AND_ATTRIBUTES); /* privileges used during access check */ @END -...@req(get_token_user) +...@req(get_token_sid) obj_handle_t handle; /* handle to the token */ + unsigned int which_sid; /* which SID to retrieve from the token */ @REPLY - data_size_t user_len; /* length needed to store user */ - VARARG(user,SID); /* sid of the user the token represents */ + data_size_t sid_len; /* length needed to store sid */ + VARARG(sid,SID); /* the sid specified by which_sid from the token */ @END @REQ(get_token_groups) obj_handle_t handle; /* handle to the token */ @REPLY data_size_t user_len; /* length needed to store user */ - VARARG(user,token_groups); /* groups the token's user belongs to */ + VARARG(user,token_groups); /* groups the token's user belongs to */ @END @REQ(get_token_default_dacl) diff --git a/server/token.c b/server/token.c index ce896ac..cf0750c 100644 --- a/server/token.c +++ b/server/token.c @@ -1225,27 +1225,56 @@ DECL_HANDLER(access_check) } /* retrieves the SID of the user that the token represents */ -DECL_HANDLER(get_token_user) +DECL_HANDLER(get_token_sid) { struct token *token; - reply->user_len = 0; + reply->sid_len = 0; if ((token = (struct token *)get_handle_obj( current->process, req->handle, TOKEN_QUERY, &token_ops ))) { - const SID *user = token->user; + const SID *sid = NULL; + + switch (req->which_sid) + { + case TokenUser: + assert(token->user); + sid = token->user; + break; + case TokenPrimaryGroup: + sid = token->primary_group; + break; + case TokenOwner: + { + struct group *group; + LIST_FOR_EACH_ENTRY( group, &token->groups, struct group, entry ) + { + if (group->owner) + { + sid = &group->sid; + break; + } + } + break; + } + default: + set_error( STATUS_INVALID_PARAMETER ); + goto cleanup; + } - reply->user_len = FIELD_OFFSET(SID, SubAuthority[user->SubAuthorityCount]); - if (reply->user_len <= get_reply_max_size()) + if (sid) + reply->sid_len = FIELD_OFFSET(SID, SubAuthority[sid->SubAuthorityCount]); + if (reply->sid_len <= get_reply_max_size()) { - SID *user_reply = set_reply_data_size( reply->user_len ); - if (user_reply) - memcpy( user_reply, user, reply->user_len ); + SID *sid_reply = set_reply_data_size( reply->sid_len ); + if (sid_reply) + memcpy( sid_reply, sid, reply->sid_len ); } else set_error( STATUS_BUFFER_TOO_SMALL ); +cleanup: release_object( token ); } } -- 1.5.4.3