< Previous by Date Date Index Next by Date >
< Previous in Thread Thread Index  

Re: [reSIProcate-users] branch not unique in reinvites


Hi Vasanthi,

Based upon your tests 1-3, esp the logs for #3, I suspect that some "other" code in your application is calling srandom() with a fixed value. If I understand correctly, you are writing a test application, and maybe some other code in your system needs random numbers (maybe for delays) and is calling srandom(). This is resetting the shared random number generator back to the same starting point each time, leading to duplicate tids. I searched the resip code base and the only other srandom call in stun code and only occurs once.

Your test 4 is as I would expect. You're not seeing duplicates between the two threads because your time-slice interval is greater than few ms, and I didn't see any case where both threads ran within the same ms-interval.

Your test 5 case will work so long as you don't generate two random numbers (or tids) in the same us-interval. That said,you might as well skip the srandom() and random() calls and just return the us-interval number.

Anyways, suggest hunting for the malicious srandom() call in your application -- even if you work around this issue within resip, it will cause the rest of your app to act weird.

Regards,
Kennard

On Tue, Nov 30, 2010 at 2:06 PM, Vasanthi Ramasamy <Vasanthi.Ramasamy@xxxxxxxxxx> wrote:

Hey Kenneth,

 

Thanks a lot for your response. I did some experimentation with random number generation in our application which uses RedHat 5  (32 bit).  To me it looks like nature of 32 bit random number generator of the platform causing the issue.

 

1.       If I run the code you gave me, I don’t see any duplicates in RedHat 5 linux (32 bit) systems. I don’t know why the same logic in resiprocate gives duplicates in our application.

2.       I tried initistate(), setstate() with statelen= 32 and I still see duplicates in our application.

3.       We use different threads for Stack and Dum. I changed that to single thread servicing both stack and DUM, I still see duplicates.  I also tested “two threads with mutexes” logic, that also gave me duplicates.

4.       I changed Random.cxx so that it  creates a new seed for every call to generate random number (by setting mIsInitialized = false;  in  getRandom()).  This gave me some interesting results. Random number generated were the same for 1 millisec., but different for different threads (stack thread got the same random number for 1 milli sec. and DUM thread got the same random number for 1 millisec.  But random numbers for stack and DUM were different.  I didn’t change the logic in seeding the random number, it was seeded by the current time in millisec. as in the existing logic. Reinvite scenario worked fine in this  case. I didn’t see any branch/transaction-ids being the same.

5.       I repeated step 4, but with a seed of current time in microsecs (unsigned int seed = static_cast<unsigned int>(Timer::getTimeMicroSec());)  instead of millisecs. And this gave me random numbers which were totally unique every time. In  this case too, I could see the reinvite scenario worked fine.

 

I have attached logs from Resiprocate (I added additional logs in Randcom.cxx to print the random number generated).  In steps 2-3, you can see that random numbers generated are repeated as blocks of 4-6. And stack thread gets one set and  DUM get another set of numbers. And to me it looks like they are repeated for 1 sec. approximately and then the new set starts. Puzzled by this.

 

Random number logged are the output of “int  Random::getRandom()”  in Random.cxx.  For time being, I will go ahead and use step 5’s logic for our application.

 

Vasanthi

 

 

From: Kennard White [mailto:kennard_white@xxxxxxxxxxxx]
Sent: Wednesday, November 24, 2010 7:42 PM
To: Vasanthi Ramasamy
Cc: Jeremy Geras; Scott Godin; resiprocate-users@xxxxxxxxxxxxxxx


Subject: Re: [reSIProcate-users] branch not unique in reinvites

 

Hi Vasanthi,

I think there are a few different things going on here:

1. In resip Random class, the /dev/urandom call is used only to initialize the SSL subsystem, it isn't used for the "normal" data such as used to generate branches.
The flow is:
    - get a weak random number
    - initialize libc srandom() generator as seed with weak random number
    - use libc random() generator as needed

2. In your test program below, the access to /dev/urandom isn't doing anything. The srandom call has already been made.

3. Unfortunately, the above doesn't change the fact that the numbers returned by random() repeat generally within <100K calls.

4. I don't think this has anything to do with the level of randomness of the OS, but rather the nature of a 32-bit random number generator. Interestingly, using random with 8-byte state (see initstate()) prevents duplicates because I think it is falling back to a linear method, while for any statelen >=16 bytes it uses a "better" method that tends to be repeat within around 100K trials. I suspect this is just the birthday problem odds.

5. The BranchParameter class, and specifically its reset() method, generates 64-bit transaction ids (two 32-bit random calls). I extended your test program, and when taking two random numbers back-to-back to get 64-bit numbers, didn't get any repeats in reasonable time.

6. Thus I don't know how you're getting repeats.

7. One possible issue is thread safety: the srandom() and random() calls are not thread safe. Random gets called from both dum and sipstack (I think). Could either add a thread lock or try to use srandom_r() and random_r(), but plumbing isn't really there for that.

8. RFC 3261 sec 8.1.1.7 requires branches to be unique accross time and space for a given UA. Within a given reboot cycle, we could ensure this by adding a counting serial number. This would add 8 more characters (4 bytes hex encoded) to an already long branch. Or perhaps replace one of the current random 32-bits with a counter.

9. Uniqueness accross reboots is even harder. Could encode starttime of process into another section of the branch. But that is another ~32bits, 8 characters.

Anyways, before doing anything would be good to understand why you are getting repeat branches even with 64-bit tags. Is it something about the platform's random number generator, a threading bug, old code, or something else?

Kennard

On Wed, Nov 24, 2010 at 1:41 PM, Vasanthi Ramasamy <Vasanthi.Ramasamy@xxxxxxxxxx> wrote:

We are using Linux RedHat 5 and there is  seriously an insufficient randomness issue. Look at the given code (uses the logic from  Resiprocate source code).  I see that the random numbers generated are repeated in re-invite scenario between 200 – 300 millsecs., leading to branch/transaction-ids not unique.

 

Trying to come up something using Boost library’s random number generators at this point. Resiprocate developers have to definitely think of something for this issue.   

 

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

#include <unistd.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <sys/time.h>

#include <unistd.h>

#include <map>

#include <iostream>

 

typedef unsigned long long UInt64;

using namespace std;

 

UInt64 getSystemTime() {

    struct timeval now;

       UInt64 time=0;

    gettimeofday( &now , NULL );

    time = now.tv_sec;

    time = time*1000000;

    time += now.tv_usec;

    return time;

}

 

int main() {

         map<int, int> random_map;

 

         unsigned int seed = static_cast<unsigned int> (getSystemTime()/1000LL);

         srandom(seed);

 

 

         int fd = open("/dev/urandom", O_RDONLY);

         if ( fd != -1 )

         {

            int s = read( fd,&seed,sizeof(seed) ); //!ah! blocks if /dev/random on embedded sys

 

            if ( s != sizeof(seed) )

            {

               cout  << "System is short of randomness" << endl ; // !ah! never prints

            }

            ::close(fd);

         }

         else

         {

            cout << "Could not open /dev/urandom" ;

         }

 

 

        for (int i = 0;  i < 100000; i++) {

                pair<map<int, int>::iterator,bool> ret;

                int rand = random();

                ret=random_map.insert(make_pair(rand, 0));

                if (ret.second==false)

                {

                        cout << "ERROR !!! sizeofmap:" << random_map.size() << endl;

                        break;

                }

        }

        random_map.clear();

        return 0;

}

 

 

 

From: Jeremy Geras [mailto:jgeras@xxxxxxxxxxxxxxx]
Sent: Wednesday, November 24, 2010 11:54 AM
To: Vasanthi Ramasamy; Scott Godin

Subject: RE: [reSIProcate-users] branch not unique in reinvites

 

We've hit this before as well -- it manifested itself in our unit tests, where generation of branch parameters, etc., happens more frequently than in typical real-life usage.

 

I've attached our version of Random which uses RtlGenRandom on Windows to get around the insufficient randomness issue.

 

(Note that this fix is sitting around on our last contrib branch at https://svn.resiprocate.org/rep/resiprocate/branches/b-ctpc-fixes-20090113 -- the branch is somewhat old, but nonetheless if anyone has time to give it a review then maybe we can merge it to mainline...)

 

Jeremy


From: resiprocate-users-bounces@xxxxxxxxxxxxxxx [resiprocate-users-bounces@xxxxxxxxxxxxxxx] on behalf of Vasanthi Ramasamy [Vasanthi.Ramasamy@xxxxxxxxxx]
Sent: Wednesday, November 24, 2010 6:12 AM
To: Scott Godin
Cc: resiprocate-users@xxxxxxxxxxxxxxx
Subject: Re: [reSIProcate-users] branch not unique in reinvites

Yes I’m using provideOffer().

 

I’m looking at the random number generation code in rutil/Random.cxx  to crack it down.  I will update you with my findings.

 

From: slgodin@xxxxxxxxx [mailto:slgodin@xxxxxxxxx] On Behalf Of Scott Godin
Sent: Wednesday, November 24, 2010 9:10 AM
To: Vasanthi Ramasamy
Cc: resiprocate-users@xxxxxxxxxxxxxxx
Subject: Re: [reSIProcate-users] branch not unique in reinvites

 

That doesn't sound right - resip will automatically generate a new via for each outbound request.  I don't remember any known issues with this in the past.  Are you using DUM and the provideOffer API to send the re-invite?

On Tue, Nov 23, 2010 at 2:21 PM, Vasanthi Ramasamy <Vasanthi.Ramasamy@xxxxxxxxxx> wrote:

Hi,

I'm trying to test re-invite scenario using Resiprocate and I see this behavior where branch in Via is not unique (leading to lots of issues). In a re-invited scenario, where my application sends a reinvite, it uses the same branch in Via, either for the re-invite or for the ACK generated for the re-invite (in response to 200 OK from remote end) for calls which are totally un-related. Am I missing anything here ? How can I make resiprocate to create a unique branch for Via ?

I'm using Resiprocate 1.5

Thanks,
Vasanthi
_______________________________________________
resiprocate-users mailing list
resiprocate-users@xxxxxxxxxxxxxxx
List Archive: http://list.resiprocate.org/archive/resiprocate-users/

 


_______________________________________________
resiprocate-users mailing list
resiprocate-users@xxxxxxxxxxxxxxx
List Archive: http://list.resiprocate.org/archive/resiprocate-users/