CVE-2022-49771
Severity CVSS v4.0:
Pending analysis
Type:
Unavailable / Other
Publication date:
01/05/2025
Last modified:
02/05/2025
Description
In the Linux kernel, the following vulnerability has been resolved:<br />
<br />
dm ioctl: fix misbehavior if list_versions races with module loading<br />
<br />
__list_versions will first estimate the required space using the<br />
"dm_target_iterate(list_version_get_needed, &needed)" call and then will<br />
fill the space using the "dm_target_iterate(list_version_get_info,<br />
&iter_info)" call. Each of these calls locks the targets using the<br />
"down_read(&_lock)" and "up_read(&_lock)" calls, however between the first<br />
and second "dm_target_iterate" there is no lock held and the target<br />
modules can be loaded at this point, so the second "dm_target_iterate"<br />
call may need more space than what was the first "dm_target_iterate"<br />
returned.<br />
<br />
The code tries to handle this overflow (see the beginning of<br />
list_version_get_info), however this handling is incorrect.<br />
<br />
The code sets "param->data_size = param->data_start + needed" and<br />
"iter_info.end = (char *)vers+len" - "needed" is the size returned by the<br />
first dm_target_iterate call; "len" is the size of the buffer allocated by<br />
userspace.<br />
<br />
"len" may be greater than "needed"; in this case, the code will write up<br />
to "len" bytes into the buffer, however param->data_size is set to<br />
"needed", so it may write data past the param->data_size value. The ioctl<br />
interface copies only up to param->data_size into userspace, thus part of<br />
the result will be truncated.<br />
<br />
Fix this bug by setting "iter_info.end = (char *)vers + needed;" - this<br />
guarantees that the second "dm_target_iterate" call will write only up to<br />
the "needed" buffer and it will exit with "DM_BUFFER_FULL_FLAG" if it<br />
overflows the "needed" space - in this case, userspace will allocate a<br />
larger buffer and retry.<br />
<br />
Note that there is also a bug in list_version_get_needed - we need to add<br />
"strlen(tt->name) + 1" to the needed size, not "strlen(tt->name)".
Impact
References to Advisories, Solutions, and Tools
- https://git.kernel.org/stable/c/0c8d4112df329bf3dfbf27693f918c3b08676538
- https://git.kernel.org/stable/c/3a1c35d72dc0b34d1e746ed705790c0f630aa427
- https://git.kernel.org/stable/c/4fe1ec995483737f3d2a14c3fe1d8fe634972979
- https://git.kernel.org/stable/c/5398b8e275bf81a2517b327d216c0f37ac9ac5ae
- https://git.kernel.org/stable/c/6a818db0d5aecf80d4ba9e10ac153f60adc629ca
- https://git.kernel.org/stable/c/6ffce7a92ef5c68f7e5d6f4d722c2f96280c064b
- https://git.kernel.org/stable/c/b545c0e1e4094d4de2bdfe9a3823f9154b0c0005
- https://git.kernel.org/stable/c/f59f5a269ca5e43c567aca7f1f52500a0186e9b7