[Date Prev][Date Next]
[Chronological]
[Thread]
[Top]
Re: (ITS#3388) Seg11 when used with pam_ldap under dtlogin
Hi, Howard,
I've tried to put this together to make it more clear what the problem
I'm seeing is... This is the call tree which results in the bug. As
things are pushed onto the stack, I indent. When it's done, I
un-indent. if something allocates, i mark it with a -->. I've removed
anything that isn't relevant to the problem at hand (ie, assert()s,
error checks, unrelated assignments, etc).
If you've got alternatives or can explain why this isn't the cause of
the crash, please!, i'm very interested. I'd really like to get this
problem solved, so a refutal would tell me where i should look instead.
As it stands, this "feels" like an OpenLDAP issue.
pam_ldap code
ldap_search_s
ldap_search
ldap_build_search_req
ldap_alloc_ber_with_options
ber_alloc_t
LBER_CALLOC --> ber
ber->valid = LBER_VALID_BERELEMENT;
ber->ber_tag = LBER_DEFAULT;
ber->ber_options = options;
ber->ber_debug = ber_int_debug;
LDAP_NEXT_MSGID
ber_printf(ld, "{it{seeiib", ...)
ber_start_seq
ber_start_seqorset
ber_mamcalloc_x --> new
1 new->sos_first = ber->ber_ptr;
1 new->sos_ptr = new->sos_first + ber_calc_taglen(tag) +
FOUR_BYTE_LEN;
ber->ber_sos = new
ber_put_int
ber_put_int_or_enum
ber_put_tag
ber_write
if ( nosos || ber->ber_sos == NULL ) { ber->ber_sos same as
new above, so !NULL
2 if ( ber->ber_ptr + len > ber->ber_end ) { } ber->ber_ptr ==
0, ber->ber_end == 0
3 ber_realloc( ber, len )
}
AC_MEMCPY( ber->ber_ptr, buf, (size_t)len );
ber->ber_ptr += len;
The two lines marked (1) lines are the problem, as far as i can tell.
ber->ber_ptr is NULL. Nothing ever set it to non-NULL after the calloc
in ber_alloc_t. So new->sos_first is 0, ber_calc_taglen(tag) == 1, and
FOUR_BYTE_LEN == 5. new->sos_ptr becomes 0x6, and then we dereference
it in ber_write()'s memcpy (much later).
It isn't clear what the results of (2) are, but it seems likely to
evaluate true, as ber->ber_ptr is 6, len is at least something, and
ber->ber_end is probably (never got set to anything else).
ber->berber_realloc (3) is the only place that ber->ber_ptr can
possibly move. It getting moved depends on ber_memrealloc_x()
returning moved memory. It isn't clear how it really behaves here,
though -- if it moves at all, ber->ber_ptr = (ber->ber_buf +
(ber->ber_ptr - oldbuf)); when ber->ber_ptr is 0x6, and we're
subtracting oldbuf. We'll end up with total trash on ber->ber_ptr.
That's if it moves. If it doesn't, ber->ber_ptr continues to be 0x6,
which is what i've seen in the AC_MEMCPY() call.
Maybe this problem only comes up when ber_memrealloc_x() returns a
moved region. This would explain why i see it under dtlogin, but don't
usually see it otherwise. I have verified that ber->ber_ptr is 0x6 at
the point ber_printf() is called when debugging under a working case,
but haven't had a lot of luck identifying why it then continues to work
(my "working" test case involves time limits because it's under
login(1), and i just can't get to the call quickly enough).
Again, thanks for your time, I realize i'm being more irritating at
following this up than most people are. I'm just firmly convinced i'm
right, that this really is an OpenLDAP issue, as, so far, there's
something to suggest there's a different issue at-fault.
- joel
On Nov 10, 2004, at 7:44 AM, Howard Chu wrote:
> As pam_ldap is not a component of OpenLDAP software, this bug report
> doesn't belong here.
>
> In general, problems on Solaris result from the Solaris native
> binaries being linked against Sun's libldap/liblber and thus the wrong
> liblber getting used when OpenLDAP's libldap is invoked. Resolving
> this library conflict is just a matter of using the right linker flags
> when building pam_ldap/nss_ldap. With that said, I am closing this
> ITS.
>
> jdb@force10networks.com wrote:
>
>> Full_Name: Joel Boutros
>> Version: 2.2.18
>> OS: Solaris8
>> URL: Submission from: (NULL) (206.54.51.125)
>>
>>
>> I have reproduced this problem with 2.2.18, 2.2.17, and 2.0.107(?).
>>
>> I'm using pam_ldap 1.76, linked against the static version of
>> OpenLDAP 2.2.18,
>> on Solaris8 (also happens with dynamicly linked version, but my
>> version of gdb
>> can't get symbols out of liblber, so i switched to static). I am
>> getting
>> crashes under dtlogin. The call-stack (as far as OpenLDAP sees) is
>> as follows
>> (some strings have been replaced by XXX for security reasons. the
>> addresses
>> remain the same):
>>
>> Program received signal SIGSEGV, Segmentation fault.
>> 0xfeda0620 in memcpy () from
>> /usr/platform/SUNW,Ultra-60/lib/libc_psr.so.1
>> (gdb) bt
>> #0 0xfeda0620 in memcpy () from
>> /usr/platform/SUNW,Ultra-60/lib/libc_psr.so.1
>> #1 0xfdf2b4b8 in ber_write (ber=0xfe122d98, buf=0xffbee4b3 "\002",
>> len=1, nosos=0) at io.c:97
>> #2 0xfdf29f8c in ber_put_tag (ber=0xfe122d98, tag=0, nosos=0) at
>> encode.c:97
>> #3 0xfdf2a1dc in ber_put_int_or_enum (ber=0xfe122d98, num=1, tag=2)
>> at encode.c:225
>> #4 0xfdf2b050 in ber_printf (ber=0xfe122d98, fmt=0xfdfcbb81
>> "it{seeiib")
>> at encode.c:723
>> #5 0xfdf31c98 in ldap_build_search_req (ld=0x619a8, base=0x5f8c8
>> "CN=XXX,DC=XXX,DC=com", scope=2, filter=0xffbeebb0
>> "(&(objectclass=User)(objectclass=User)(sAMAccountName=XXX))",
>> attrs=0x0,
>> attrsonly=0, sctrls=0x0, cctrls=0x0, timelimit=-1, sizelimit=-1,
>> idp=0x2) at search.c:278
>> #6 0xfdf31ba8 in ldap_search (ld=0x619a8, base=0x5f8c8
>> "CN=XXX,DC=XXX,DC=com", scope=2, filter=0xffbeebb0
>> "(&(objectclass=User)(objectclass=User)(sAMAccountName=XXX))",
>> attrs=0x0,
>> attrsonly=0) at search.c:192
>> #7 0xfdf31e38 in ldap_search_s (ld=0x619a8, base=0x5f8c8
>> "CN=XXX,DC=XXX,DC=com", scope=2, filter=0xffbeebb0
>> "(&(objectclass=User)(objectclass=User)(sAMAccountName=XXX))",
>> attrs=0x0,
>> attrsonly=0, res=0xffbee798) at search.c:360
>> #8 0xfdf253dc in _get_user_info (session=0xfe212950, user=0xfe302ba0
>> "XXX")
>> at pam_ldap.c:2476
>> #9 0xfdf25ac4 in _do_authentication (pamh=0x52a58,
>> session=0xfe212950, user=0xfe302ba0 "XXX", password=0xfe302bd8
>> "XXX") at pam_ldap.c:2768
>> #10 0xfdf26488 in pam_sm_authenticate (pamh=0x52a58, flags=0, argc=0,
>> argv=0x0)
>> at pam_ldap.c:3203
>> ...
>> (gdb) fr 1
>> #1 0xfdf2b4b8 in ber_write (ber=0xfe122d98, buf=0xffbee4b3 "\002",
>> len=1, nosos=0) at io.c:97
>> 97 AC_MEMCPY( ber->ber_sos->sos_ptr, buf,
>> (size_t)len );
>> (gdb) p *ber
>> $1 = {ber_opts = {lbo_valid = 2, lbo_options = 1, lbo_debug = 0,
>> lbo_meminuse = 0}, ber_tag = 4294967295, ber_len = 0, ber_usertag =
>> 0, ber_buf = 0xfe122d98 "", ber_ptr = 0x0, ber_end = 0x30 <Address
>> 0x30 out of bounds>, ber_sos = 0xfe122db0, ber_rwptr = 0x6 <Address
>> 0x6 out of bounds>, ber_memctx = 0x0}
>> (gdb) p *ber->ber_sos
>> $2 = {sos_ber = 0xfe122d98, sos_clen = 0, sos_tag = 48, sos_first =
>> 0xfe122db0 "?\022-\230", sos_ptr = 0x6 <Address 0x6 out of bounds>,
>> sos_next = 0x0}
>>
>>> From what I can tell, it looks like when ber is allocated in
>> ldap_build_search_req, it is zeroed out (calloc()), but then
>> ber->ber_ptr is
>> reset, and at openldap-2.2.18/libraries/liblber/encode.c:465, it uses
>> new->sos_first (which is derived from ber->ber_ptr) in some pointer
>> arithmetic,
>> producing 0x06 as a result (new->sos_ptr = NULL +
>> ber_calc_taglen(tag) + 5). Then new->sos_ptr is later used in a
>> memcpy(), causing the crash.
>>
>> Interestingly enough, I'm not seeing problems like this under other
>> pam-enabled
>> applications. But, it looks like the behavior is the same in both
>> cases -- it
>> is always dereferencing this pointer. So it seems like dtlogin's
>> environment is
>> helping to expose a latent problem?
>>
>> Any ideas how to fix this? I can't figure out how ber->ber_ptr
>> should be at
>> initialized. I tried setting it to ber->ber_val, but it crashes in
>> other ways
>> later, so that wasn't right...
>>
>> If you need any further data, please let me know.
>>
>> Thanks!
>>
>> - joel
>>
>>
>>
>
>
> --
> -- Howard Chu
> Chief Architect, Symas Corp. Director, Highland Sun
> http://www.symas.com http://highlandsun.com/hyc
> Symas: Premier OpenSource Development and Support
>