[asterisk-dev] [Code Review]: Fix a large variety of errors caused by negative return codes

Tilghman Lesher reviewboard at asterisk.org
Sun Apr 15 15:29:01 CDT 2012



> On April 13, 2012, 2:42 p.m., rmudgett wrote:
> > /branches/1.8/main/manager.c, lines 3624-3645
> > <https://reviewboard.asterisk.org/r/1863/diff/3/?file=27253#file27253line3624>
> >
> >     You cannot use astman_send_error here since you have a partially created command response already.  You need to use astman_append instead to output your error message as part of the command response.
> 
> Matt Jordan wrote:
>     I'm not sure about that, although I agree that astman_send_error without first terminating the in flight event isn't correct either.
>     
>     As I see it, we have three options:
>     
>     1. When an error occurs during response construction, we immediately terminate the current response, and send an error message.  This would look like:
>     
>     Response: Follows
>     Privilege: Command
>     ActionID: 1234
>     blah blah blah yackity I'm a CLI output
>     and now I've failed
>     --END COMMAND--
>     
>     
>     Response: Failure
>     ActionID: 1234
>     Message: Command response construction error
>     
>     2. When an error occurs during response construction, we instead embed the failure as a sort of warning in the response.  This would look like:
>     Response: Follows
>     Privilege: Command
>     ActionID: 1234
>     blah blah blah yackity I'm a CLI output
>     and now I've failed
>     --END COMMAND--
>     Message: Command response construction error
>     
>     3. Or, we attempt to buffer the whole CLI response in memory before sending it.  This would allows us to either send the whole thing successfully, or an error response.  I'm concerned about this approach only because the CLI output could be rather largish (memory allocations comes to mind), and trying to buffer it all in memory may be a bad idea.
>     
>     My preference would be to do #1, since it doesn't mess around with any current response parsing, and both messages are in the format currently expected.  I'm not sure if anyone expects to get two Response events however.
>     
>
> 
> Matt Jordan wrote:
>     After some discussion, there isn't a very good approach to this problem that doesn't change existing behavior.  Instead of trying to send an error message back to the connected AMI session, the least intrusive approach will probably be to just end the message with an "--END COMMAND--" and log an error in Asterisk.

We already buffer the entire CLI response.  That's what this file is:  the contents of the entire output of the CLI command.  We do this because CLI commands have the potential to take up quite a bit of time (for example, dealing with channel locks when executing 'core show channels'), and we don't want to lock out all asynchronous events on a particular AMI connection (if we didn't lock, we could get other events in the middle of our CLI output).

The rest of the code is dealing with the possible error of not being able to set the file position back to 0 on a file created with mkstemp(), or reading the file back out of that temporary file, which is likely all cached in kernel memory anyway.  As far as error checking, for lseek(), there are four on the Linux manpage:  EBADF is the only one that seems possible, since we don't check the FD returned from mkstemp for validity (in which case, we should fail sooner).  All of the others deal with invalid inputs, which are not possible with these particular constant inputs.  For the read(), we should probably be checking for EINTR and restarting, which is what the current code effectively does.  EIO is the only other possible error, and given that the entire file is cached in memory, it also seems unlikely.

I understand that you're eliminating warnings from a static checker, and that's fine.  But the only possible error from lseek() should be caught on the mkstemp(), before ast_cli_command() is called.  Add to this the case of EIO on the read(), and I don't think we need to take error handling any further.


- Tilghman


-----------------------------------------------------------
This is an automatically generated e-mail. To reply, visit:
https://reviewboard.asterisk.org/r/1863/#review5992
-----------------------------------------------------------


On April 13, 2012, 4:46 p.m., Matt Jordan wrote:
> 
> -----------------------------------------------------------
> This is an automatically generated e-mail. To reply, visit:
> https://reviewboard.asterisk.org/r/1863/
> -----------------------------------------------------------
> 
> (Updated April 13, 2012, 4:46 p.m.)
> 
> 
> Review request for Asterisk Developers.
> 
> 
> Summary
> -------
> 
> Through a static analysis tool, a large number of errors were found that dealt with using potential negative return values in harmful ways.  The following is a summary of the changes for the various affected files:
> 
> * app_voicemail
>   - a negative result from lseek is later passed into mmap as the size of the memory map
>   - a negative result from read closes the various file descriptors and unlinks the output file, but the next check against the return value only checks to see if its non-zero
> * chan_agent - ast_channel_unlock returns a negative value if the item passed to it is NULL or an invalid ao2 object.  strerror cannot accept a negative value.
> * chan_dahdi - if dahdi_get_index returns a negative value, we index directly into an array
> * format_* - various errors not checking return values of ftello and fseek, and passing the results into functions that expect non-negative values
> * func_env - various places where the result of ftello was directly used as input to functions that expect non-negative values
> * asterisk
>   - the request to read returns a negative value.  This causes us to enter into the retry logic.  If we attempt to reconnect and succeed, we would normally proceed in the for(;;) loop and attempt to index into buf using the negative return value from read.  Instead, if we do reconnect, we immediately return to the beginning of the for(;;) loop and attempt a new read.
>   - similar situation - if a read fails, don't attempt to index into a buffer using the return value
> * frame - if we can't determine a preferred codec using the provided values, don't attempt to use an index value that never got set
> * manager 
>   - various failures of mkstemp, lseek were not checked for and could be provided to methods that don't handle negative numbers
>   - passing a negative result from lseek into mmap as the size of the memory map
> * translate - powerof can return a negative result if no bits are set, which would then be used as an index into an array
> * res_agi - if read returns an error, we treated it as if bytes were read from the pipe
> * res_musiconhold - if we fail to spawn spawn_mp3 returns a negative number, we wait a bit and attempt again later.  However, the return 'file descriptor' srcfd is later passed into read.
> * res_rtp_asterisk - ast_rtp_codecs_payload_code can return a negative value if no codecs are found that match between instance1 and the specified payload.  If that's the case, the bridge should be broken, as there are no compatible formats between the two different endpoints (and we shouldn't index into an array using the return value)
> 
> 
> Diffs
> -----
> 
>   /branches/1.8/apps/app_voicemail.c 362134 
>   /branches/1.8/channels/chan_agent.c 362134 
>   /branches/1.8/channels/chan_dahdi.c 362134 
>   /branches/1.8/formats/format_g719.c 362134 
>   /branches/1.8/formats/format_g723.c 362134 
>   /branches/1.8/formats/format_g729.c 362134 
>   /branches/1.8/formats/format_gsm.c 362134 
>   /branches/1.8/formats/format_h263.c 362134 
>   /branches/1.8/formats/format_h264.c 362134 
>   /branches/1.8/formats/format_ilbc.c 362134 
>   /branches/1.8/formats/format_pcm.c 362134 
>   /branches/1.8/formats/format_siren14.c 362134 
>   /branches/1.8/formats/format_siren7.c 362134 
>   /branches/1.8/formats/format_sln.c 362134 
>   /branches/1.8/formats/format_sln16.c 362134 
>   /branches/1.8/formats/format_vox.c 362134 
>   /branches/1.8/formats/format_wav.c 362134 
>   /branches/1.8/formats/format_wav_gsm.c 362134 
>   /branches/1.8/funcs/func_env.c 362134 
>   /branches/1.8/main/asterisk.c 362134 
>   /branches/1.8/main/frame.c 362134 
>   /branches/1.8/main/manager.c 362134 
>   /branches/1.8/main/translate.c 362134 
>   /branches/1.8/res/res_agi.c 362134 
>   /branches/1.8/res/res_musiconhold.c 362134 
>   /branches/1.8/res/res_rtp_asterisk.c 362134 
> 
> Diff: https://reviewboard.asterisk.org/r/1863/diff
> 
> 
> Testing
> -------
> 
> 
> Thanks,
> 
> Matt
> 
>

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-dev/attachments/20120415/eeabf227/attachment-0001.htm>


More information about the asterisk-dev mailing list