Summary: | ASTERISK-03724: Segmentation Fault with Realtime | ||
Reporter: | cheojr (cheojr) | Labels: | |
Date Opened: | 2005-03-20 16:30:20.000-0600 | Date Closed: | 2005-03-31 20:57:58.000-0600 |
Priority: | Critical | Regression? | No |
Status: | Closed/Complete | Components: | Core/General |
Versions: | Frequency of Occurrence | ||
Related Issues: | |||
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. ****** ADDITIONAL INFORMATION ****** (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 (gdb) 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); else p = ASTOBJ_CONTAINER_FIND_FULL(&peerl,sin,name,sip_addr_hashfunc,1,sip_addrcmp); if (!p && realtime) { p = realtime_peer(peer, sin); } return(p); } 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")) { ast_variables_destroy(var); 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 anthmct@yahoo.com edited on: 03-21-05 09:06 By: adomjan (adomjan) 2005-03-21 09:30:50.000-0600 thanks! 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! |