lkml.org 
[lkml]   [2020]   [Jan]   [10]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v2] drivers: char: ipmi: ipmi_msghandler: Pass lockdep expression to RCU lists
    Date
    intf->cmd_rcvrs is traversed with list_for_each_entry_rcu
    outside an RCU read-side critical section but under the
    protection of intf->cmd_rcvrs_mutex.

    ipmi_interfaces is traversed using list_for_each_entry_rcu
    outside an RCU read-side critical section but under the protection
    of ipmi_interfaces_mutex.

    Hence, add the corresponding lockdep expression to the list traversal
    primitive to silence false-positive lockdep warnings, and
    harden RCU lists.

    Add macro for the corresponding lockdep expression to make the code
    clean and concise.

    Signed-off-by: Amol Grover <frextrite@gmail.com>
    ---
    v2:
    - Fix sparse error
    CHECK: Alignment should match open parenthesis

    drivers/char/ipmi/ipmi_msghandler.c | 16 ++++++++++++----
    1 file changed, 12 insertions(+), 4 deletions(-)

    diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
    index cad9563f8f48..1cbeacb1e8b9 100644
    --- a/drivers/char/ipmi/ipmi_msghandler.c
    +++ b/drivers/char/ipmi/ipmi_msghandler.c
    @@ -35,6 +35,8 @@
    #include <linux/nospec.h>

    #define IPMI_DRIVER_VERSION "39.2"
    +#define cmd_rcvrs_mutex_held() \
    + lockdep_is_held(&intf->cmd_rcvrs_mutex)

    static struct ipmi_recv_msg *ipmi_alloc_recv_msg(void);
    static int ipmi_init_msghandler(void);
    @@ -618,6 +620,8 @@ static DEFINE_MUTEX(ipmidriver_mutex);

    static LIST_HEAD(ipmi_interfaces);
    static DEFINE_MUTEX(ipmi_interfaces_mutex);
    +#define ipmi_interfaces_mutex_held() \
    + lockdep_is_held(&ipmi_interfaces_mutex)
    static struct srcu_struct ipmi_interfaces_srcu;

    /*
    @@ -1321,7 +1325,8 @@ static void _ipmi_destroy_user(struct ipmi_user *user)
    * synchronize_srcu()) then free everything in that list.
    */
    mutex_lock(&intf->cmd_rcvrs_mutex);
    - list_for_each_entry_rcu(rcvr, &intf->cmd_rcvrs, link) {
    + list_for_each_entry_rcu(rcvr, &intf->cmd_rcvrs, link,
    + cmd_rcvrs_mutex_held()) {
    if (rcvr->user == user) {
    list_del_rcu(&rcvr->link);
    rcvr->next = rcvrs;
    @@ -1599,7 +1604,8 @@ static struct cmd_rcvr *find_cmd_rcvr(struct ipmi_smi *intf,
    {
    struct cmd_rcvr *rcvr;

    - list_for_each_entry_rcu(rcvr, &intf->cmd_rcvrs, link) {
    + list_for_each_entry_rcu(rcvr, &intf->cmd_rcvrs, link,
    + rcu_read_lock_held() || cmd_rcvrs_mutex_held()) {
    if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)
    && (rcvr->chans & (1 << chan)))
    return rcvr;
    @@ -1614,7 +1620,8 @@ static int is_cmd_rcvr_exclusive(struct ipmi_smi *intf,
    {
    struct cmd_rcvr *rcvr;

    - list_for_each_entry_rcu(rcvr, &intf->cmd_rcvrs, link) {
    + list_for_each_entry_rcu(rcvr, &intf->cmd_rcvrs, link,
    + cmd_rcvrs_mutex_held()) {
    if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)
    && (rcvr->chans & chans))
    return 0;
    @@ -3450,7 +3457,8 @@ int ipmi_add_smi(struct module *owner,
    /* Look for a hole in the numbers. */
    i = 0;
    link = &ipmi_interfaces;
    - list_for_each_entry_rcu(tintf, &ipmi_interfaces, link) {
    + list_for_each_entry_rcu(tintf, &ipmi_interfaces, link,
    + ipmi_interfaces_mutex_held()) {
    if (tintf->intf_num != i) {
    link = &tintf->link;
    break;
    --
    2.24.1
    \
     
     \ /
      Last update: 2020-01-10 17:49    [W:3.104 / U:0.300 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site