### Description

We've been experiencing random Kamailio crashes related to invalid memory 
access attempts at `0xffff` in `w_save` call, `ims_registrar_scscf_mod.c`:

```
Core was generated by `kamailio -w /home -DD -E -e -f 
/etc/kamailio/kamailio_scscf.cfg'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x00007f5be796c452 in w_save (_m=0x7f5beafa5188, _route=0x7f5beaeab988 " 
\b\361\352[\177", _d=0x7f5be3bf8200 "", mode=0x7f5beafa5188 "4", _cflags=0xffff 
<error: Cannot access memory at address 0xffff>)
   at ims_registrar_scscf_mod.c:628
```

We are running the latest Kamailio 5.6.4 using the official Docker image.


### Analysis

We were able to analyze corresponding core dump using `gdb` and determine the 
cause of those random crashes. It turns out that it is related to calling the 
`save` function of IMS Registrar SCSCF module with 2 arguments.

Example configuration:
```
save("REG_SAR_REPLY", "location");
```

According to documentation, this call is valid, as `mode` and `flags` 
parameters are optional:
https://kamailio.org/docs/modules/5.6.x/modules/ims_registrar_scscf.html#idm230

The `save` function is exported in `ims_registrar_scscf_mod.c` as follows:
```
/*! \brief
 * Exported functions
 */
static cmd_export_t cmds[] = {
    {"save", (cmd_function) w_save, 2, assign_save_fixup3_async, 0, 
REQUEST_ROUTE | ONREPLY_ROUTE},
    {"save", (cmd_function) w_save, 3, assign_save_fixup3_async, 0, 
REQUEST_ROUTE | ONREPLY_ROUTE},
    {"save", (cmd_function) w_save, 4, save_fixup3, free_uint_fixup, 
REQUEST_ROUTE | ONREPLY_ROUTE},
    ...
}
```

And implemented as:
```
/*! \brief
 * Wrapper to save(location)
 */
static int w_save(struct sip_msg* _m, char* _route, char* _d, char* mode, char* 
_cflags) {
    if(_cflags){
        return save(_m, _d, _route, ((int)(*_cflags)));
    }

    return save(_m, _d, _route, 0);
}
```

Using the 2-argument `save` variant in configuration effectively causes the 
`w_save` to be called from `src/core/action.c :: do_action` via a 3-argument 
function-pointer cast:
```
  case MODULE2_T:
    MODF_CALL(cmd_function, h, msg, a->val,
          (char*)a->val[2].u.data,
          (char*)a->val[3].u.data
      );
    break;
```

Unfortunately, this cast is inherently unsafe - it leaves the `mode` and 
`_cflags` undetermined. They are probably effectively bound to some memory area 
beyond the parameter values of the stack frame corresponding to the function 
call.

Our guess is that incidentally `_cflags == 0x0000` for most of those calls, due 
to how the stack is structured. But sometimes `_cflags == 0xFFFF`  which 
satisfies the condition in `w_save`, causes `(int)(*_cflags)` dereference 
attempt and leads to the segmentation fault we've encountered.


### Workaround

Based on source code analysis, we have determined that always using `save` with 
a full set of arguments (including optional ones) will result in `w_save` being 
called via a 5-argument function pointer, which matches its signature and 
avoids the issue.

Example configuration with workaround applied:
```
save("REG_SAR_REPLY", "location", "0", "0");
```

After introducing this workaround on target environment we are no longer 
experiencing the problem.

-- 
Reply to this email directly or view it on GitHub:
https://github.com/kamailio/kamailio/issues/3412
You are receiving this because you are subscribed to this thread.

Message ID: <kamailio/kamailio/issues/[email protected]>
_______________________________________________
Kamailio (SER) - Development Mailing List
To unsubscribe send an email to [email protected]

Reply via email to