mirror of https://gitee.com/openkylin/linux.git
ipmi: msghandler: Fix potential Spectre v1 vulnerabilities
channel and addr->channel are indirectly controlled by user-space, hence leading to a potential exploitation of the Spectre variant 1 vulnerability. These issues were detected with the help of Smatch: drivers/char/ipmi/ipmi_msghandler.c:1381 ipmi_set_my_address() warn: potential spectre issue 'user->intf->addrinfo' [w] (local cap) drivers/char/ipmi/ipmi_msghandler.c:1401 ipmi_get_my_address() warn: potential spectre issue 'user->intf->addrinfo' [r] (local cap) drivers/char/ipmi/ipmi_msghandler.c:1421 ipmi_set_my_LUN() warn: potential spectre issue 'user->intf->addrinfo' [w] (local cap) drivers/char/ipmi/ipmi_msghandler.c:1441 ipmi_get_my_LUN() warn: potential spectre issue 'user->intf->addrinfo' [r] (local cap) drivers/char/ipmi/ipmi_msghandler.c:2260 check_addr() warn: potential spectre issue 'intf->addrinfo' [r] (local cap) Fix this by sanitizing channel and addr->channel before using them to index user->intf->addrinfo and intf->addrinfo, correspondingly. Notice that given that speculation windows are large, the policy is to kill the speculation on the first load and not worry if it can be completed with a dependent load/store [1]. [1] https://lore.kernel.org/lkml/20180423164740.GY17484@dhcp22.suse.cz/ Cc: stable@vger.kernel.org Signed-off-by: Gustavo A. R. Silva <gustavo@embeddedor.com> Signed-off-by: Corey Minyard <cminyard@mvista.com>
This commit is contained in:
parent
7d6380cd40
commit
a7102c7461
|
@ -32,6 +32,7 @@
|
||||||
#include <linux/moduleparam.h>
|
#include <linux/moduleparam.h>
|
||||||
#include <linux/workqueue.h>
|
#include <linux/workqueue.h>
|
||||||
#include <linux/uuid.h>
|
#include <linux/uuid.h>
|
||||||
|
#include <linux/nospec.h>
|
||||||
|
|
||||||
#define IPMI_DRIVER_VERSION "39.2"
|
#define IPMI_DRIVER_VERSION "39.2"
|
||||||
|
|
||||||
|
@ -1298,10 +1299,12 @@ int ipmi_set_my_address(struct ipmi_user *user,
|
||||||
if (!user)
|
if (!user)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
if (channel >= IPMI_MAX_CHANNELS)
|
if (channel >= IPMI_MAX_CHANNELS) {
|
||||||
rv = -EINVAL;
|
rv = -EINVAL;
|
||||||
else
|
} else {
|
||||||
|
channel = array_index_nospec(channel, IPMI_MAX_CHANNELS);
|
||||||
user->intf->addrinfo[channel].address = address;
|
user->intf->addrinfo[channel].address = address;
|
||||||
|
}
|
||||||
release_ipmi_user(user, index);
|
release_ipmi_user(user, index);
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
|
@ -1318,10 +1321,12 @@ int ipmi_get_my_address(struct ipmi_user *user,
|
||||||
if (!user)
|
if (!user)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
if (channel >= IPMI_MAX_CHANNELS)
|
if (channel >= IPMI_MAX_CHANNELS) {
|
||||||
rv = -EINVAL;
|
rv = -EINVAL;
|
||||||
else
|
} else {
|
||||||
|
channel = array_index_nospec(channel, IPMI_MAX_CHANNELS);
|
||||||
*address = user->intf->addrinfo[channel].address;
|
*address = user->intf->addrinfo[channel].address;
|
||||||
|
}
|
||||||
release_ipmi_user(user, index);
|
release_ipmi_user(user, index);
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
|
@ -1338,10 +1343,12 @@ int ipmi_set_my_LUN(struct ipmi_user *user,
|
||||||
if (!user)
|
if (!user)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
if (channel >= IPMI_MAX_CHANNELS)
|
if (channel >= IPMI_MAX_CHANNELS) {
|
||||||
rv = -EINVAL;
|
rv = -EINVAL;
|
||||||
else
|
} else {
|
||||||
|
channel = array_index_nospec(channel, IPMI_MAX_CHANNELS);
|
||||||
user->intf->addrinfo[channel].lun = LUN & 0x3;
|
user->intf->addrinfo[channel].lun = LUN & 0x3;
|
||||||
|
}
|
||||||
release_ipmi_user(user, index);
|
release_ipmi_user(user, index);
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
|
@ -1358,10 +1365,12 @@ int ipmi_get_my_LUN(struct ipmi_user *user,
|
||||||
if (!user)
|
if (!user)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
if (channel >= IPMI_MAX_CHANNELS)
|
if (channel >= IPMI_MAX_CHANNELS) {
|
||||||
rv = -EINVAL;
|
rv = -EINVAL;
|
||||||
else
|
} else {
|
||||||
|
channel = array_index_nospec(channel, IPMI_MAX_CHANNELS);
|
||||||
*address = user->intf->addrinfo[channel].lun;
|
*address = user->intf->addrinfo[channel].lun;
|
||||||
|
}
|
||||||
release_ipmi_user(user, index);
|
release_ipmi_user(user, index);
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
|
@ -2184,6 +2193,7 @@ static int check_addr(struct ipmi_smi *intf,
|
||||||
{
|
{
|
||||||
if (addr->channel >= IPMI_MAX_CHANNELS)
|
if (addr->channel >= IPMI_MAX_CHANNELS)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
addr->channel = array_index_nospec(addr->channel, IPMI_MAX_CHANNELS);
|
||||||
*lun = intf->addrinfo[addr->channel].lun;
|
*lun = intf->addrinfo[addr->channel].lun;
|
||||||
*saddr = intf->addrinfo[addr->channel].address;
|
*saddr = intf->addrinfo[addr->channel].address;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Reference in New Issue