Overview:
In this bug report I will be outlining an issue I have discovered pertaining to the handling of /proc/cpuinfo by libvivoxsdk.so.
This bug results in the termination of the Vivox daemon (SLVoice) when an std::out_of_range exception is thrown by std::string::substr. I will include steps to reproduce the problem as well as a temporary solution for interested users.
Background:
When using the 1.19.0* and 1.19.1* clients I found myself unable to utilize features relating to voice communication. I noticed that the client was executing SLVoice but that the resulting process soon died. The output from the client on stdout and in the logs indicated that the client was reaching the stateConnecting internal state but that no further progress was made. I also witnessed output informing me that an std::out_of_range exception had been thrown. After checking the Vivox logs in ~/Library/Logs/Vivox/ I noticed the same output regarding an std::out_of_range exception in siplog.txt.
Investigation:
I decided to read the relevant sections of the Second Life client source code (llvoiceclient.cpp) to familiarize myself with its operation. I discovered that the client was requesting a "connector" object (LLVoiceClient::connectorCreate) from the daemon but would end up waiting for a response that never came.
Running SLVoice via strace (see attached) I confirmed that the daemon was successfully receiving requests from the client but aborted before a response could be sent. I also noticed that prior to its termination the last few system calls included a successful attempt to open and read from /proc/cpuinfo.
My next step was to generate a backtrace (see attached) of the stack in SLVoice using gdb. This revealed that the fatal call to std::string::substr originated in oscommon2::SplitNameValueFile called from oscommon2::MachineInfo::MachineInfo, both within libvivoxsdk.so. These names corresponded nicely with what I was seeing in the output of strace; with /proc/cpuinfo being regarded as "machine" information and being formatted with each line containing a "name" and "value" separated by a colon.
I soon came to the assumption that the problem lied with the handling of the /proc/cpuinfo format by libvivoxsdk.so in SplitNameValueFile. I decided the quickest way to test this hypothesis would be to create a copy of /proc/cpuinfo that was writable and to modify the string representation of the path to this file in libvivoxsdk.so (edited with vim in binary mode).
After a short period of experimentation I found that the exception was thrown if and only if a line terminated directly after a colon where a value was to be expected. If you look at the attached copy of my /proc/cpuinfo you can see that this occurs on the lines containing 'power management:\n'. Simply by removing these lines or modifying them to append a space to the colon I was able to successfully communicate with other residents via the Vivox daemon using voice communication.
Reproduction:
Reproducing this error requires that you run a GNU/Linux OS with the proc filesystem mounted and that the file /proc/cpuinfo contains at least one line in the form of 'name\t*:\n'.
If the latter is not the case then I propose that the simplest means to verify this is to copy the content of /proc/cpuinfo into a file with write permission, append to it a line in the above form (i.e. 'power management:\n') and modify the string representation of the path to cpuinfo within libvivoxsdk.so to point to the new file (either absolute or relative to the SLVoice executable).
The following is an example of a series commands that, when executed within the lib directory of the Second Life client's directory hierarchy, will perform the necessary operations to accomplish such a reproduction:
1. cat /proc/cpuinfo > cpuinfo
2. echo 'power management:' >> cpuinfo
3. cp libvivoxsdk.so libvivoxsdk.so.bak
4. sed -i 's/\/proc\/cpuinfo/lib\/cpuinfo\c@\c@/g' libvivoxsdk.so
I have wrapped these commands in a simple shell script which I have attached to this report: repro_cpuinfo.sh.
Temporary Solution:
For users who have identified that their system is affected by this issue I present the following series of commands (again assumed to be executed from within the client's lib dir) that work in much the same manner as the reproduction process above.
First, the data that comprises /proc/cpuinfo is copied (redirected) to a new, writable file; during this process a single space is appended to each colon which appears directly at the end of a line. Next, a copy of libvivoxsdk.so is created, its purpose is to serve as a backup. Finally, libvivoxsdk.so is overwritten to contain the modified path to cpuinfo.
1. sed 's/:$/: /g' /proc/cpuinfo > cpuinfo
2. cp libvivoxsdk.so libvivoxsdk.so.bak
3. sed -i 's/\/proc\/cpuinfo/lib\/cpuinfo\c@\c@/g' libvivoxsdk.so
I have wrapped these commands in a simple shell script which I have attached to this report: fix_cpuinfo.sh.
Conclusion:
It would appear that an incorrect assumption that a value will follow a colon in /proc/cpuinfo results in an out of bounds start position being passed to substr.
I hope that it is now apparent that the parsing of /proc/cpuinfo in libvivoxsdk.so needs to be improved. A more robust method of separating lines into name / value components is required so that it (the lib) may gracefully handle lines that do not conform to: 'name\t*: value\n'. The Second Life client successfully handles such cases (see LLCPUINFO::LLCPUINFO() in llsys.cpp) by simply discarding lines that do not match the desired format.
If this issue can be brought to the attention of the people at Vivox responsible for SLVoice/libvivoxsdk.so so that they can fully investigate and resolve this issue I would, as would the rest of the Second Life/Linux community, greatly appreciate it. I hope you find this information useful, please let me know if you require additional information.