http://bugs.winehq.org/show_bug.cgi?id=7690
------- Additional Comments From focht@gmx.net 2007-18-03 14:59 ------- Hello,
it was a bit difficult to track down but i think i found it ...
used: WINEDEBUG=+loaddll,+seh,+advapi,+ntdll,+relay
--- snip trace --- trace:ntdll:RtlMakeSelfRelativeSD 0x477a74 0x477a14 0x34fa00(0) trace:ntdll:RtlLengthSid sid=0x3d68 trace:seh:raise_exception code=c0000005 flags=0 addr=0x7bc51001 trace:seh:raise_exception info[0]=00000000 trace:seh:raise_exception info[1]=00003d69 trace:seh:raise_exception eax=00003d69 ebx=7bc7ae4c ecx=00000000 edx=00000024 esi=00003d68 edi=00477a74 trace:seh:raise_exception ebp=0034f954 esp=0034f930 cs=0073 ds=007b es=007b fs=0033 gs=003b flags=00210206 --- snip trace ---
RtlLengthSid() param doesnt look like valid SID pointer It gets called by following code snippet in RtlLengthSecurityDescriptor():
------ snip ntdll/sec.c:RtlLengthSecurityDescriptor ---
if ( lpsd->Owner != NULL ) Size += RtlLengthSid((PSID)((LPBYTE)lpsd->Owner + offset)); ------ snip ntdll/sec.c:RtlLengthSecurityDescriptor ---
"lpsd->Owner" isnt setup correctly or memory corruption somewhere.
So we need to evaluate how the SD is init (SD=0x477a74) A while earlier the following call sequence shows up in trace:
--- snip trace --- 0009:Call advapi32.MakeAbsoluteSD(00477a14,00000000,0034f9bc,00000000,0034f9c0,00000000,0034f9c4,00000000,0034f9c8,00000000,0034f9cc) ret=00443e4d 0009:Ret advapi32.MakeAbsoluteSD() retval=00000000 ret=00443e4d 0009:Call advapi32.MakeAbsoluteSD(00477a14,00477a74,0034f9bc,00477a8c,0034f9c0,00000000,0034f9c4,00000000,0034f9c8,00000000,0034f9cc) ret=00443e4d 0009:Ret advapi32.MakeAbsoluteSD() retval=00000001 ret=00443e4d --- snip trace ---
The first call is ok. The client app uses it to determine real out buffer length. The second call is our one. After adding lots of additional trace code, it boils down to the following:
---- snip ntdll/sec.c:RtlSelfRelativeToAbsoluteSD --- ... /* Copy structures */ pAbs->Revision = pRel->Revision; pAbs->Control = pRel->Control & ~SE_SELF_RELATIVE; ... if (pRel->Owner) { PSID psid = (PSID)((LPBYTE)pRel->Owner + (ULONG)pRel);
TRACE("pAbs->Owner=%p, pOwner=%p, pRel->Owner=%p, psid= %p\n",pAbs->Owner , pOwner, pRel->Owner, psid);
memcpy(pOwner, psid, RtlLengthSid(psid)); pAbs->Owner = pOwner;
TRACE("pAbs->Owner=%p, RtlLengthSid(psid)=%d\n", pAbs->Owner, RtlLengthSid(psid)); } ---- snip ntdll/sec.c:RtlSelfRelativeToAbsoluteSD ---
The problem is the client didnt set all the relative SD fields. Example: "pRel->Owner" == NULL -> owner and other SD stuff doesnt get copied.
Now guess: the client didnt initialize the "out" param absolute SD structure - of course it isnt required to do so. Basically the absolute SD (including "pAbs->Owner") is allocated by client app somewhere and passed down uninitialized to wine api call.
Later when a call to RtlMakeSelfRelativeSD() is made, the data gets accessed again, leading to access violation.
Solution: initialize all pointer fields to zero if you're not going to fill it with relative SD data.
I fixed and tested with following:
---- snip ntdll/sec.c:RtlSelfRelativeToAbsoluteSD --- ... /* Copy structures */ pAbs->Revision = pRel->Revision; pAbs->Control = pRel->Control & ~SE_SELF_RELATIVE;
/* reset !!! */ pAbs->Sacl = NULL; pAbs->Dacl = NULL; pAbs->Owner = NULL; pRel->Group = NULL; ... if( blah) ---- snip ntdll/sec.c:RtlSelfRelativeToAbsoluteSD ---
Now the tool "registryset.exe" runs and finishes without errors.
Regards