Skip to content

Commit c45be7c

Browse files
committed
Merge tag 'for-linus-7.0-1' of https://github.com/cminyard/linux-ipmi
Pull IPMI driver fixes from Corey Minyard: "This mostly revolves around getting the driver to behave when the IPMI device misbehaves. Past attempts have not worked very well because I didn't have hardware I could make do this, and AI was fairly useless for help on this. So I modified qemu and my test suite so I could reproduce a misbehaving IPMI device, and with that I was able to fix the issues" * tag 'for-linus-7.0-1' of https://github.com/cminyard/linux-ipmi: ipmi:si: Fix check for a misbehaving BMC ipmi:msghandler: Handle error returns from the SMI sender ipmi:si: Don't block module unload if the BMC is messed up ipmi:si: Use a long timeout when the BMC is misbehaving ipmi:si: Handle waiting messages when BMC failure detected ipmi:ls2k: Make ipmi_ls2k_platform_driver static ipmi: ipmb: initialise event handler read bytes ipmi: Consolidate the run to completion checking for xmit msgs lock ipmi: Fix use-after-free and list corruption on sender error
2 parents 3f4a08e + cae66f1 commit c45be7c

4 files changed

Lines changed: 125 additions & 60 deletions

File tree

drivers/char/ipmi/ipmi_ipmb.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,11 +202,16 @@ static int ipmi_ipmb_slave_cb(struct i2c_client *client,
202202
break;
203203

204204
case I2C_SLAVE_READ_REQUESTED:
205+
*val = 0xff;
206+
ipmi_ipmb_check_msg_done(iidev);
207+
break;
208+
205209
case I2C_SLAVE_STOP:
206210
ipmi_ipmb_check_msg_done(iidev);
207211
break;
208212

209213
case I2C_SLAVE_READ_PROCESSED:
214+
*val = 0xff;
210215
break;
211216
}
212217

drivers/char/ipmi/ipmi_msghandler.c

Lines changed: 95 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -602,6 +602,22 @@ static int __ipmi_bmc_register(struct ipmi_smi *intf,
602602
static int __scan_channels(struct ipmi_smi *intf,
603603
struct ipmi_device_id *id, bool rescan);
604604

605+
static void ipmi_lock_xmit_msgs(struct ipmi_smi *intf, int run_to_completion,
606+
unsigned long *flags)
607+
{
608+
if (run_to_completion)
609+
return;
610+
spin_lock_irqsave(&intf->xmit_msgs_lock, *flags);
611+
}
612+
613+
static void ipmi_unlock_xmit_msgs(struct ipmi_smi *intf, int run_to_completion,
614+
unsigned long *flags)
615+
{
616+
if (run_to_completion)
617+
return;
618+
spin_unlock_irqrestore(&intf->xmit_msgs_lock, *flags);
619+
}
620+
605621
static void free_ipmi_user(struct kref *ref)
606622
{
607623
struct ipmi_user *user = container_of(ref, struct ipmi_user, refcount);
@@ -1869,21 +1885,32 @@ static struct ipmi_smi_msg *smi_add_send_msg(struct ipmi_smi *intf,
18691885
return smi_msg;
18701886
}
18711887

1872-
static void smi_send(struct ipmi_smi *intf,
1888+
static int smi_send(struct ipmi_smi *intf,
18731889
const struct ipmi_smi_handlers *handlers,
18741890
struct ipmi_smi_msg *smi_msg, int priority)
18751891
{
18761892
int run_to_completion = READ_ONCE(intf->run_to_completion);
18771893
unsigned long flags = 0;
1894+
int rv = 0;
18781895

1879-
if (!run_to_completion)
1880-
spin_lock_irqsave(&intf->xmit_msgs_lock, flags);
1896+
ipmi_lock_xmit_msgs(intf, run_to_completion, &flags);
18811897
smi_msg = smi_add_send_msg(intf, smi_msg, priority);
1882-
if (!run_to_completion)
1883-
spin_unlock_irqrestore(&intf->xmit_msgs_lock, flags);
1898+
ipmi_unlock_xmit_msgs(intf, run_to_completion, &flags);
18841899

1885-
if (smi_msg)
1886-
handlers->sender(intf->send_info, smi_msg);
1900+
if (smi_msg) {
1901+
rv = handlers->sender(intf->send_info, smi_msg);
1902+
if (rv) {
1903+
ipmi_lock_xmit_msgs(intf, run_to_completion, &flags);
1904+
intf->curr_msg = NULL;
1905+
ipmi_unlock_xmit_msgs(intf, run_to_completion, &flags);
1906+
/*
1907+
* Something may have been added to the transmit
1908+
* queue, so schedule a check for that.
1909+
*/
1910+
queue_work(system_wq, &intf->smi_work);
1911+
}
1912+
}
1913+
return rv;
18871914
}
18881915

18891916
static bool is_maintenance_mode_cmd(struct kernel_ipmi_msg *msg)
@@ -2296,6 +2323,7 @@ static int i_ipmi_request(struct ipmi_user *user,
22962323
struct ipmi_recv_msg *recv_msg;
22972324
int run_to_completion = READ_ONCE(intf->run_to_completion);
22982325
int rv = 0;
2326+
bool in_seq_table = false;
22992327

23002328
if (supplied_recv) {
23012329
recv_msg = supplied_recv;
@@ -2349,33 +2377,50 @@ static int i_ipmi_request(struct ipmi_user *user,
23492377
rv = i_ipmi_req_ipmb(intf, addr, msgid, msg, smi_msg, recv_msg,
23502378
source_address, source_lun,
23512379
retries, retry_time_ms);
2380+
in_seq_table = true;
23522381
} else if (is_ipmb_direct_addr(addr)) {
23532382
rv = i_ipmi_req_ipmb_direct(intf, addr, msgid, msg, smi_msg,
23542383
recv_msg, source_lun);
23552384
} else if (is_lan_addr(addr)) {
23562385
rv = i_ipmi_req_lan(intf, addr, msgid, msg, smi_msg, recv_msg,
23572386
source_lun, retries, retry_time_ms);
2387+
in_seq_table = true;
23582388
} else {
2359-
/* Unknown address type. */
2389+
/* Unknown address type. */
23602390
ipmi_inc_stat(intf, sent_invalid_commands);
23612391
rv = -EINVAL;
23622392
}
23632393

2364-
if (rv) {
2365-
out_err:
2366-
if (!supplied_smi)
2367-
ipmi_free_smi_msg(smi_msg);
2368-
if (!supplied_recv)
2369-
ipmi_free_recv_msg(recv_msg);
2370-
} else {
2394+
if (!rv) {
23712395
dev_dbg(intf->si_dev, "Send: %*ph\n",
23722396
smi_msg->data_size, smi_msg->data);
23732397

2374-
smi_send(intf, intf->handlers, smi_msg, priority);
2398+
rv = smi_send(intf, intf->handlers, smi_msg, priority);
2399+
if (rv != IPMI_CC_NO_ERROR)
2400+
/* smi_send() returns an IPMI err, return a Linux one. */
2401+
rv = -EIO;
2402+
if (rv && in_seq_table) {
2403+
/*
2404+
* If it's in the sequence table, it will be
2405+
* retried later, so ignore errors.
2406+
*/
2407+
rv = 0;
2408+
/* But we need to fix the timeout. */
2409+
intf_start_seq_timer(intf, smi_msg->msgid);
2410+
ipmi_free_smi_msg(smi_msg);
2411+
smi_msg = NULL;
2412+
}
23752413
}
2414+
out_err:
23762415
if (!run_to_completion)
23772416
mutex_unlock(&intf->users_mutex);
23782417

2418+
if (rv) {
2419+
if (!supplied_smi)
2420+
ipmi_free_smi_msg(smi_msg);
2421+
if (!supplied_recv)
2422+
ipmi_free_recv_msg(recv_msg);
2423+
}
23792424
return rv;
23802425
}
23812426

@@ -3949,12 +3994,12 @@ static int handle_ipmb_get_msg_cmd(struct ipmi_smi *intf,
39493994
dev_dbg(intf->si_dev, "Invalid command: %*ph\n",
39503995
msg->data_size, msg->data);
39513996

3952-
smi_send(intf, intf->handlers, msg, 0);
3953-
/*
3954-
* We used the message, so return the value that
3955-
* causes it to not be freed or queued.
3956-
*/
3957-
rv = -1;
3997+
if (smi_send(intf, intf->handlers, msg, 0) == IPMI_CC_NO_ERROR)
3998+
/*
3999+
* We used the message, so return the value that
4000+
* causes it to not be freed or queued.
4001+
*/
4002+
rv = -1;
39584003
} else if (!IS_ERR(recv_msg)) {
39594004
/* Extract the source address from the data. */
39604005
ipmb_addr = (struct ipmi_ipmb_addr *) &recv_msg->addr;
@@ -4028,12 +4073,12 @@ static int handle_ipmb_direct_rcv_cmd(struct ipmi_smi *intf,
40284073
msg->data[4] = IPMI_INVALID_CMD_COMPLETION_CODE;
40294074
msg->data_size = 5;
40304075

4031-
smi_send(intf, intf->handlers, msg, 0);
4032-
/*
4033-
* We used the message, so return the value that
4034-
* causes it to not be freed or queued.
4035-
*/
4036-
rv = -1;
4076+
if (smi_send(intf, intf->handlers, msg, 0) == IPMI_CC_NO_ERROR)
4077+
/*
4078+
* We used the message, so return the value that
4079+
* causes it to not be freed or queued.
4080+
*/
4081+
rv = -1;
40374082
} else if (!IS_ERR(recv_msg)) {
40384083
/* Extract the source address from the data. */
40394084
daddr = (struct ipmi_ipmb_direct_addr *)&recv_msg->addr;
@@ -4173,7 +4218,7 @@ static int handle_lan_get_msg_cmd(struct ipmi_smi *intf,
41734218
struct ipmi_smi_msg *msg)
41744219
{
41754220
struct cmd_rcvr *rcvr;
4176-
int rv = 0;
4221+
int rv = 0; /* Free by default */
41774222
unsigned char netfn;
41784223
unsigned char cmd;
41794224
unsigned char chan;
@@ -4226,12 +4271,12 @@ static int handle_lan_get_msg_cmd(struct ipmi_smi *intf,
42264271
dev_dbg(intf->si_dev, "Invalid command: %*ph\n",
42274272
msg->data_size, msg->data);
42284273

4229-
smi_send(intf, intf->handlers, msg, 0);
4230-
/*
4231-
* We used the message, so return the value that
4232-
* causes it to not be freed or queued.
4233-
*/
4234-
rv = -1;
4274+
if (smi_send(intf, intf->handlers, msg, 0) == IPMI_CC_NO_ERROR)
4275+
/*
4276+
* We used the message, so return the value that
4277+
* causes it to not be freed or queued.
4278+
*/
4279+
rv = -1;
42354280
} else if (!IS_ERR(recv_msg)) {
42364281
/* Extract the source address from the data. */
42374282
lan_addr = (struct ipmi_lan_addr *) &recv_msg->addr;
@@ -4824,8 +4869,7 @@ static void smi_work(struct work_struct *t)
48244869
* message delivery.
48254870
*/
48264871
restart:
4827-
if (!run_to_completion)
4828-
spin_lock_irqsave(&intf->xmit_msgs_lock, flags);
4872+
ipmi_lock_xmit_msgs(intf, run_to_completion, &flags);
48294873
if (intf->curr_msg == NULL && !intf->in_shutdown) {
48304874
struct list_head *entry = NULL;
48314875

@@ -4841,17 +4885,19 @@ static void smi_work(struct work_struct *t)
48414885
intf->curr_msg = newmsg;
48424886
}
48434887
}
4844-
if (!run_to_completion)
4845-
spin_unlock_irqrestore(&intf->xmit_msgs_lock, flags);
4888+
ipmi_unlock_xmit_msgs(intf, run_to_completion, &flags);
48464889

48474890
if (newmsg) {
48484891
cc = intf->handlers->sender(intf->send_info, newmsg);
48494892
if (cc) {
48504893
if (newmsg->recv_msg)
48514894
deliver_err_response(intf,
48524895
newmsg->recv_msg, cc);
4853-
else
4854-
ipmi_free_smi_msg(newmsg);
4896+
ipmi_lock_xmit_msgs(intf, run_to_completion, &flags);
4897+
intf->curr_msg = NULL;
4898+
ipmi_unlock_xmit_msgs(intf, run_to_completion, &flags);
4899+
ipmi_free_smi_msg(newmsg);
4900+
newmsg = NULL;
48554901
goto restart;
48564902
}
48574903
}
@@ -4919,16 +4965,14 @@ void ipmi_smi_msg_received(struct ipmi_smi *intf,
49194965
spin_unlock_irqrestore(&intf->waiting_rcv_msgs_lock,
49204966
flags);
49214967

4922-
if (!run_to_completion)
4923-
spin_lock_irqsave(&intf->xmit_msgs_lock, flags);
4968+
ipmi_lock_xmit_msgs(intf, run_to_completion, &flags);
49244969
/*
49254970
* We can get an asynchronous event or receive message in addition
49264971
* to commands we send.
49274972
*/
49284973
if (msg == intf->curr_msg)
49294974
intf->curr_msg = NULL;
4930-
if (!run_to_completion)
4931-
spin_unlock_irqrestore(&intf->xmit_msgs_lock, flags);
4975+
ipmi_unlock_xmit_msgs(intf, run_to_completion, &flags);
49324976

49334977
if (run_to_completion)
49344978
smi_work(&intf->smi_work);
@@ -5041,7 +5085,12 @@ static void check_msg_timeout(struct ipmi_smi *intf, struct seq_table *ent,
50415085
ipmi_inc_stat(intf,
50425086
retransmitted_ipmb_commands);
50435087

5044-
smi_send(intf, intf->handlers, smi_msg, 0);
5088+
/* If this fails we'll retry later or timeout. */
5089+
if (smi_send(intf, intf->handlers, smi_msg, 0) != IPMI_CC_NO_ERROR) {
5090+
/* But fix the timeout. */
5091+
intf_start_seq_timer(intf, smi_msg->msgid);
5092+
ipmi_free_smi_msg(smi_msg);
5093+
}
50455094
} else
50465095
ipmi_free_smi_msg(smi_msg);
50475096

drivers/char/ipmi/ipmi_si_intf.c

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -809,6 +809,12 @@ static enum si_sm_result smi_event_handler(struct smi_info *smi_info,
809809
*/
810810
return_hosed_msg(smi_info, IPMI_BUS_ERR);
811811
}
812+
if (smi_info->waiting_msg != NULL) {
813+
/* Also handle if there was a message waiting. */
814+
smi_info->curr_msg = smi_info->waiting_msg;
815+
smi_info->waiting_msg = NULL;
816+
return_hosed_msg(smi_info, IPMI_BUS_ERR);
817+
}
812818
smi_mod_timer(smi_info, jiffies + SI_TIMEOUT_HOSED);
813819
goto out;
814820
}
@@ -918,9 +924,14 @@ static int sender(void *send_info, struct ipmi_smi_msg *msg)
918924
{
919925
struct smi_info *smi_info = send_info;
920926
unsigned long flags;
927+
int rv = IPMI_CC_NO_ERROR;
921928

922929
debug_timestamp(smi_info, "Enqueue");
923930

931+
/*
932+
* Check here for run to completion mode. A check under lock is
933+
* later.
934+
*/
924935
if (smi_info->si_state == SI_HOSED)
925936
return IPMI_BUS_ERR;
926937

@@ -934,18 +945,15 @@ static int sender(void *send_info, struct ipmi_smi_msg *msg)
934945
}
935946

936947
spin_lock_irqsave(&smi_info->si_lock, flags);
937-
/*
938-
* The following two lines don't need to be under the lock for
939-
* the lock's sake, but they do need SMP memory barriers to
940-
* avoid getting things out of order. We are already claiming
941-
* the lock, anyway, so just do it under the lock to avoid the
942-
* ordering problem.
943-
*/
944-
BUG_ON(smi_info->waiting_msg);
945-
smi_info->waiting_msg = msg;
946-
check_start_timer_thread(smi_info);
948+
if (smi_info->si_state == SI_HOSED) {
949+
rv = IPMI_BUS_ERR;
950+
} else {
951+
BUG_ON(smi_info->waiting_msg);
952+
smi_info->waiting_msg = msg;
953+
check_start_timer_thread(smi_info);
954+
}
947955
spin_unlock_irqrestore(&smi_info->si_lock, flags);
948-
return IPMI_CC_NO_ERROR;
956+
return rv;
949957
}
950958

951959
static void set_run_to_completion(void *send_info, bool i_run_to_completion)
@@ -1113,7 +1121,9 @@ static void smi_timeout(struct timer_list *t)
11131121
* SI_USEC_PER_JIFFY);
11141122
smi_result = smi_event_handler(smi_info, time_diff);
11151123

1116-
if ((smi_info->io.irq) && (!smi_info->interrupt_disabled)) {
1124+
if (smi_info->si_state == SI_HOSED) {
1125+
timeout = jiffies + SI_TIMEOUT_HOSED;
1126+
} else if ((smi_info->io.irq) && (!smi_info->interrupt_disabled)) {
11171127
/* Running with interrupts, only do long timeouts. */
11181128
timeout = jiffies + SI_TIMEOUT_JIFFIES;
11191129
smi_inc_stat(smi_info, long_timeouts);
@@ -2226,7 +2236,8 @@ static void wait_msg_processed(struct smi_info *smi_info)
22262236
unsigned long jiffies_now;
22272237
long time_diff;
22282238

2229-
while (smi_info->curr_msg || (smi_info->si_state != SI_NORMAL)) {
2239+
while (smi_info->si_state != SI_HOSED &&
2240+
(smi_info->curr_msg || (smi_info->si_state != SI_NORMAL))) {
22302241
jiffies_now = jiffies;
22312242
time_diff = (((long)jiffies_now - (long)smi_info->last_timeout_jiffies)
22322243
* SI_USEC_PER_JIFFY);

drivers/char/ipmi/ipmi_si_ls2k.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ static void ipmi_ls2k_remove(struct platform_device *pdev)
168168
ipmi_si_remove_by_dev(&pdev->dev);
169169
}
170170

171-
struct platform_driver ipmi_ls2k_platform_driver = {
171+
static struct platform_driver ipmi_ls2k_platform_driver = {
172172
.driver = {
173173
.name = "ls2k-ipmi-si",
174174
},

0 commit comments

Comments
 (0)