This is the mail archive of the libc-hacker@sourceware.cygnus.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: recvmsg bug


On Sat, 1 Aug 1998 09:52:38 +0200, Thorsten Kukuk wrote:
>On Sam, 01 Aug 1998, Zack Weinberg wrote:
>
>>>>I'm confused.  The space check does need to go first, because we need
>>>>enough space for the user-side cmcred struct.  If there isn't enough,
>>>>it's wrong to make the syscall anyway - data could be lost that way.
>>>
>>>We don't need this check, because we wouldn't do it, too, if we don't
>>>have to copy the struct.  We have no syscall wrapper only for
>>>checking, if the user calls the syscall with a big enough buffer.
>>>And the user supplied buffer should be big enough, since the he
>>>expect a bigger result struct then the kernel supplies.
>>
>>Normal syscalls don't need checks in the wrapper because the kernel
>>does it.  If an old program calls recvmsg() set up for the old
>>Linux-specific SCM_CREDS structure and we don't check the buffer size,
>>we'll stomp memory.
>
>That is, what I wrote in the first mail: We need to check the buffer size, but
>after the syscall. Before the syscall,  there is no way to get the needed
>buffer size.

...but failing after the syscall is wrong, because data has already
been transferred.

>Maybe we should use both, SCM_CREDENTIALS, for the old programs, and SCM_CRED
>with a new id for newer programs ? We only need to copy the data and change
>SCM_CREDENTIALS to SCM_CRED. But with old programs, you never know,
>if they expect the kernel ucred, or the version with the bigger glibc
>types, or the new SCM_CRED struct.

I thought about doing it this way, but it needs help from the kernel.
The kernel now will only provide the old SCM_CREDENTIALS tag so we
have no way of knowing what the structure size should be -- just as
you say.

>>>In recvmsg, you check, if the SCM_CRED tag and the length fields are
>>>set. But they couldn't be set. We receive the data from the kernel,
>>>not send them. We get from the user a pointer to a memory block. This
>>>memory block is uninitialized, the data in the length field could be
>>>much greater, then we hav e memory allocated. So you read memory,
>>>which isn't owned by us, and there is the seg.fault.
>>
>>Maybe I don't know how recvmsg works.  I thought that you had to
>>initialize the cmsghdr part of the memory block at least, so that the
>>kernel knew what you were expecting.
>
>No, you don't need to initialize the cmsghdr part.  You have one recvmsg, and
>one sendmsg. The kernel only copies the data from the sendmsg call to the
>recvmsg call and checks, if the data is valid (uid/gid/pid etc.).

Ah.  In that case I think no wrapper can be correct in all cases.  The
best we could do is blindly assume the user wants the new cmcred
struct always, and they've provided enough space.  That will break
programs compiled to glibc2.0 that used the kernel structure directly.

Maybe you could patch the kernel to know a new cmsghdr type, with the
same semantics as the existing SCM_CREDENTIALS call but using the
structure layout from glibc - members _and_ sizes.  Then we can throw
away the recvmsg wrapper and just initialize the buffer in the sendmsg
wrapper.  That'd also open the way for a proper BSD-compatible
SCM_CREDS in kernel 2.3.

zw


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]