mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-21 14:37:50 +00:00
libc/oss: check argp per ioctl
... as some ioctls do not require a valid pointer.
This commit is contained in:
parent
5c82045170
commit
2ba5e4a5b1
@ -1173,16 +1173,13 @@ Libc::Vfs_plugin::_ioctl_dio(File_descriptor *fd, unsigned long request, char *a
|
||||
Libc::Vfs_plugin::Ioctl_result
|
||||
Libc::Vfs_plugin::_ioctl_sndctl(File_descriptor *fd, unsigned long request, char *argp)
|
||||
{
|
||||
if (!argp)
|
||||
return { true, EINVAL };
|
||||
|
||||
bool handled = false;
|
||||
/*
|
||||
* Initialize to "success" and any ioctl is required to set
|
||||
* in case of error.
|
||||
*
|
||||
* This method will either return handled equals true if the I/O control
|
||||
* was handled successfully or failed and the result is not successfull
|
||||
* was handled successfully or failed and the result is not successful
|
||||
* (see the end of this method).
|
||||
*
|
||||
*/
|
||||
@ -1190,12 +1187,16 @@ Libc::Vfs_plugin::_ioctl_sndctl(File_descriptor *fd, unsigned long request, char
|
||||
|
||||
if (request == OSS_GETVERSION) {
|
||||
|
||||
if (!argp) return { true, EINVAL };
|
||||
|
||||
*(int *)argp = SOUND_VERSION;
|
||||
|
||||
handled = true;
|
||||
|
||||
} else if (request == SNDCTL_DSP_CHANNELS) {
|
||||
|
||||
if (!argp) return { true, EINVAL };
|
||||
|
||||
monitor().monitor([&] {
|
||||
_with_info(*fd, [&] (Xml_node info) {
|
||||
if (info.type() != "oss") {
|
||||
@ -1230,6 +1231,8 @@ Libc::Vfs_plugin::_ioctl_sndctl(File_descriptor *fd, unsigned long request, char
|
||||
|
||||
} else if (request == SNDCTL_DSP_CURRENT_OPTR) {
|
||||
|
||||
if (!argp) return { true, EINVAL };
|
||||
|
||||
monitor().monitor([&] {
|
||||
_with_info(*fd, [&] (Xml_node info) {
|
||||
|
||||
@ -1258,6 +1261,8 @@ Libc::Vfs_plugin::_ioctl_sndctl(File_descriptor *fd, unsigned long request, char
|
||||
|
||||
} else if (request == SNDCTL_DSP_GETERROR) {
|
||||
|
||||
if (!argp) return { true, EINVAL };
|
||||
|
||||
int play_underruns = 0;
|
||||
|
||||
monitor().monitor([&] {
|
||||
@ -1305,6 +1310,8 @@ Libc::Vfs_plugin::_ioctl_sndctl(File_descriptor *fd, unsigned long request, char
|
||||
|
||||
} else if (request == SNDCTL_DSP_GETISPACE) {
|
||||
|
||||
if (!argp) return { true, EINVAL };
|
||||
|
||||
/* dummy implementation */
|
||||
|
||||
audio_buf_info &abinfo = *(audio_buf_info *)argp;
|
||||
@ -1319,6 +1326,8 @@ Libc::Vfs_plugin::_ioctl_sndctl(File_descriptor *fd, unsigned long request, char
|
||||
|
||||
} else if (request == SNDCTL_DSP_GETOPTR) {
|
||||
|
||||
if (!argp) return { true, EINVAL };
|
||||
|
||||
/* dummy implementation */
|
||||
|
||||
count_info &ci = *(count_info *)argp;
|
||||
@ -1332,6 +1341,8 @@ Libc::Vfs_plugin::_ioctl_sndctl(File_descriptor *fd, unsigned long request, char
|
||||
|
||||
} else if (request == SNDCTL_DSP_GETOSPACE) {
|
||||
|
||||
if (!argp) return { true, EINVAL };
|
||||
|
||||
monitor().monitor([&] {
|
||||
_with_info(*fd, [&] (Xml_node info) {
|
||||
if (info.type() != "oss") {
|
||||
@ -1373,6 +1384,8 @@ Libc::Vfs_plugin::_ioctl_sndctl(File_descriptor *fd, unsigned long request, char
|
||||
|
||||
} else if (request == SNDCTL_DSP_GETPLAYVOL) {
|
||||
|
||||
if (!argp) return { true, EINVAL };
|
||||
|
||||
/* dummy implementation */
|
||||
|
||||
int *vol = (int *)argp;
|
||||
@ -1383,6 +1396,8 @@ Libc::Vfs_plugin::_ioctl_sndctl(File_descriptor *fd, unsigned long request, char
|
||||
|
||||
} else if (request == SNDCTL_DSP_LOW_WATER) {
|
||||
|
||||
if (!argp) return { true, EINVAL };
|
||||
|
||||
/* dummy implementation */
|
||||
|
||||
int *val = (int *)argp;
|
||||
@ -1404,9 +1419,12 @@ Libc::Vfs_plugin::_ioctl_sndctl(File_descriptor *fd, unsigned long request, char
|
||||
} else if (request == SNDCTL_DSP_RESET) {
|
||||
|
||||
handled = true;
|
||||
warning("SNDCTL_DSP_RESET handled=", handled, " result=", result);
|
||||
|
||||
} else if (request == SNDCTL_DSP_SAMPLESIZE) {
|
||||
|
||||
if (!argp) return { true, EINVAL };
|
||||
|
||||
monitor().monitor([&] {
|
||||
_with_info(*fd, [&] (Xml_node info) {
|
||||
if (info.type() != "oss") {
|
||||
@ -1435,6 +1453,8 @@ Libc::Vfs_plugin::_ioctl_sndctl(File_descriptor *fd, unsigned long request, char
|
||||
|
||||
} else if (request == SNDCTL_DSP_SETFRAGMENT) {
|
||||
|
||||
if (!argp) return { true, EINVAL };
|
||||
|
||||
int *frag = (int *)argp;
|
||||
int max_fragments = *frag >> 16;
|
||||
int size_selector = *frag & ((1<<16) - 1);
|
||||
@ -1492,6 +1512,8 @@ Libc::Vfs_plugin::_ioctl_sndctl(File_descriptor *fd, unsigned long request, char
|
||||
|
||||
} else if (request == SNDCTL_DSP_SETPLAYVOL) {
|
||||
|
||||
if (!argp) return { true, EINVAL };
|
||||
|
||||
/* dummy implementation */
|
||||
|
||||
int *vol = (int *)argp;
|
||||
@ -1502,12 +1524,16 @@ Libc::Vfs_plugin::_ioctl_sndctl(File_descriptor *fd, unsigned long request, char
|
||||
|
||||
} else if (request == SNDCTL_DSP_SETTRIGGER) {
|
||||
|
||||
if (!argp) return { true, EINVAL };
|
||||
|
||||
/* dummy implementation */
|
||||
|
||||
handled = true;
|
||||
|
||||
} else if (request == SNDCTL_DSP_SPEED) {
|
||||
|
||||
if (!argp) return { true, EINVAL };
|
||||
|
||||
monitor().monitor([&] {
|
||||
_with_info(*fd, [&] (Xml_node info) {
|
||||
if (info.type() != "oss") {
|
||||
@ -1540,8 +1566,41 @@ Libc::Vfs_plugin::_ioctl_sndctl(File_descriptor *fd, unsigned long request, char
|
||||
return Fn::COMPLETE;
|
||||
});
|
||||
|
||||
} else if (request == SNDCTL_DSP_SYNC) {
|
||||
|
||||
/*
|
||||
* SNDCTL_DSP_SYNC should be implemented like follows, but we disabled
|
||||
* the implementation and just return for two reasons. The VirtualBox 6
|
||||
* backend requires the sync operation to complete with very tight
|
||||
* timing in a special thread, which our current implementation can't
|
||||
* assure. Also, the OSS documentation (and examples) advise against the
|
||||
* use of this feature in new programs.
|
||||
*/
|
||||
if (0) monitor().monitor([&] {
|
||||
|
||||
auto result = Fn::INCOMPLETE;
|
||||
|
||||
_with_info(*fd, [&] (Xml_node info) {
|
||||
|
||||
if (info.type() != "oss") return;
|
||||
|
||||
unsigned int const ofrag_avail =
|
||||
info.attribute_value("ofrag_avail", 0U);
|
||||
unsigned int const ofrag_total =
|
||||
info.attribute_value("ofrag_total", 0U);
|
||||
|
||||
result = (ofrag_avail == ofrag_total ? Fn::COMPLETE : Fn::INCOMPLETE);
|
||||
});
|
||||
|
||||
return result;
|
||||
});
|
||||
|
||||
handled = true;
|
||||
|
||||
} else if (request == SNDCTL_SYSINFO) {
|
||||
|
||||
if (!argp) return { true, EINVAL };
|
||||
|
||||
/* dummy implementation */
|
||||
|
||||
oss_sysinfo *si = (oss_sysinfo *)argp;
|
||||
@ -1554,6 +1613,8 @@ Libc::Vfs_plugin::_ioctl_sndctl(File_descriptor *fd, unsigned long request, char
|
||||
* Either handled or a failed attempt will mark the I/O control
|
||||
* as handled.
|
||||
*/
|
||||
if (request == SNDCTL_DSP_RESET)
|
||||
warning("SNDCTL_DSP_RESET handled=", handled, " result=", result);
|
||||
return { handled || result != 0, result };
|
||||
}
|
||||
|
||||
@ -1590,6 +1651,7 @@ int Libc::Vfs_plugin::ioctl(File_descriptor *fd, unsigned long request, char *ar
|
||||
case SNDCTL_DSP_SETPLAYVOL:
|
||||
case SNDCTL_DSP_SETTRIGGER:
|
||||
case SNDCTL_DSP_SPEED:
|
||||
case SNDCTL_DSP_SYNC:
|
||||
case SNDCTL_SYSINFO:
|
||||
result = _ioctl_sndctl(fd, request, argp);
|
||||
break;
|
||||
@ -1598,6 +1660,8 @@ int Libc::Vfs_plugin::ioctl(File_descriptor *fd, unsigned long request, char *ar
|
||||
}
|
||||
|
||||
if (result.handled) {
|
||||
if (result.error)
|
||||
error("XXXXX error=", result.error, " request=", Hex(request), "/", (request==SNDCTL_DSP_RESET?"":"!"), "SNDCTL_DSP_RESET");
|
||||
return result.error ? Errno(result.error) : 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user