Summary:ASTERISK-03724: Segmentation Fault with Realtime
Reporter:cheojr (cheojr)Labels:
Date Opened:2005-03-20 16:30:20.000-0600Date Closed:2005-03-31 20:57:58.000-0600
Versions:Frequency of
Environment:Attachments:( 0) sip_realtime_crash_rev0.diff
Description:Segmentation Fault when using the realtime module.  The functions keeps using a null variable that cause the segmentation fault when doing a comparison with the strcasecmp function.


(gdb) backtrace
#0  0x007642b8 in strcasecmp () from /lib/tls/libc.so.6
#1  0xf6eb58c0 in build_peer (name=0x0, v=0x95fa370, realtime=0)
 at chan_sip.c:9255
#2  0xf6eb67b0 in find_peer (peer=0x0, sin=0x9642fd4, realtime=1)
 at chan_sip.c:1222
#3  0xf6ebea77 in check_user_full (p=0x9642e78, req=0xf6e9bb50,
 cmd=0xf6e9bd64 "SUBSCRIBE", uri=0xf6e9bd6e "sip:1002@XXX.XXX.XXX.XXX:5060",
 reliable=0, sin=0xf6e9bb40, ignore=0, mailbox=0xf6e920a0 "",
 mailboxlen=106) at chan_sip.c:5844
#4  0xf6ec3129 in handle_request (p=0x9642e78, req=0xf6e9bb50, sin=0xf6e9bb40,
 recount=0x6a, nounlock=0xf6e9b9c8) at chan_sip.c:8384
ASTERISK-1  0xf6ec5281 in sipsock_read (id=0x960dc50, fd=13, events=1, ignore=0x0)
 at chan_sip.c:8598
ASTERISK-2  0x0805378f in ast_io_wait (ioc=0x960dc10, howlong=106) at io.c:267
ASTERISK-3  0xf6ec89b2 in do_monitor (data=0x0) at chan_sip.c:8745
ASTERISK-4  0x008661d5 in start_thread () from /lib/tls/libpthread.so.0
ASTERISK-5  0x007c02da in clone () from /lib/tls/libc.so.6

I replaced my ip with the XXX.XXX.XXX.XXX.  But it is my server ip.


Here is what is happening in the calls:

We call find peer with the first parameter NULL
peer = find_peer(NULL, &p->recv, 1);

find_peer function tries to assign p.  If p=NULL we send the peer variable to realtime which in the previous call was a NULL variable.
/*--- find_peer: Locate peer by name or ip address */
static struct sip_peer *find_peer(const char *peer, struct sockaddr_in *sin, int realtime)
  struct sip_peer *p = NULL;

  if (peer)
      p = ASTOBJ_CONTAINER_FIND(&peerl,peer);
      p = ASTOBJ_CONTAINER_FIND_FULL(&peerl,sin,name,sip_addr_hashfunc,1,sip_addrcmp);

  if (!p && realtime) {
      p = realtime_peer(peer, sin);


In this code without doing any change to the peername variable we call build_peer with peername = NULL

static struct sip_peer *realtime_peer(const char *peername, struct sockaddr_in *sin)
  struct sip_peer *peer=NULL;
  struct ast_variable *var;
  struct ast_variable *tmp;

  /* First check on peer name */
  if (peername)
      var = ast_load_realtime("sippeers", "name", peername, NULL);
  else if (sin) {    /* Then check on IP address */
      char iabuf[80];

      ast_inet_ntoa(iabuf, sizeof(iabuf), sin->sin_addr);
      var = ast_load_realtime("sippeers", "ipaddr", iabuf, NULL);
  } else
      return NULL;

  if (!var)
      return NULL;

  tmp = var;
  /* If this is type=user, then skip this object. */
  while(tmp) {
      if (!strcasecmp(tmp->name, "type") &&
          !strcasecmp(tmp->value, "user")) {
          return NULL;
      tmp = tmp->next;

  peer = build_peer(peername, var, ast_test_flag((&global_flags_page2), SIP_PAGE2_RTCACHEFRIENDS) ? 0 : 1);

Then Here we call ASTOBJ_CONTAINER_FIND_UNLINK(&peerl, name) with name = NULL, because name was previously peername = NULL

static struct sip_peer *build_peer(const char *name, struct ast_variable *v, int realtime)
  struct sip_peer *peer = NULL;
  struct ast_ha *oldha = NULL;
  int maskfound=0;
  int obproxyfound=0;
  int found=0;

  int format=0;        /* Ama flags */
  time_t regseconds;
  char *varname = NULL, *varval = NULL;/
  struct ast_variable *tmpvar = NULL;

  if (!realtime)
      /* Note we do NOT use find_peer here, to avoid realtime recursion */
      peer = ASTOBJ_CONTAINER_FIND_UNLINK(&peerl, name);

This macro makes a comparison of a Null variable, which leads to the segmentation fault.
#define ASTOBJ_CONTAINER_FIND_UNLINK(container,namestr) \
  ({ \
      typeof((container)->head) found = NULL; \
      typeof((container)->head) prev = NULL; \
      ASTOBJ_CONTAINER_TRAVERSE(container, !found, do { \
          if (!(strcasecmp(iterator->name, (namestr)))) { \
              found = iterator; \
              found->next[0] = NULL; \
              ASTOBJ_CONTAINER_WRLOCK(container); \
              if (prev) \
                  prev->next[0] = next; \
              else \
                  (container)->head = next; \
              ASTOBJ_CONTAINER_UNLOCK(container); \
          } \
          prev = iterator; \
      } while (0)); \
      found; \


I also noticed that to be in find_peer realtime=1 because we called find_peer with 1 in the parameter.  But then in buil_peer  ASTOBJ_CONTAINER_FIND_UNLINK is called because realtime = 0. It is 0 because of ast_test_flag((&global_flags_page2), SIP_PAGE2_RTCACHEFRIENDS) ? 0 : 1);

The cvs version I'm working is: /chan_sip.c/1.674/Thu Mar 17 16:11:19 2005
Comments:By: Kevin P. Fleming (kpfleming) 2005-03-20 17:42:01.000-0600

As noted on asterisk-dev, this problem was introduced when Realtime caching was added... when caching is turned on, build_peer is no longer told that the peer is to be "realtime", and it acts in a different fashion (assuming it is being passed a peer name).

By: Anthony Minessale (anthm) 2005-03-21 09:06:15.000-0600

It looks like some code has been shuffled around because when the original patch was released it didn't have this issue.

Try this patch it's only from eyeballing it because I dont have any test env set up atm so try it.

Disclaimer on file

edited on: 03-21-05 09:06

By: adomjan (adomjan) 2005-03-21 09:30:50.000-0600

It has fixed another problem.
I did a sip reload, and phones register after the registry expired I saw on console the phone registred but not when i typed show sip peers.

By: Mark Spencer (markster) 2005-03-21 22:24:18.000-0600

Fixed in CVS head, thanks!