[bug report] cifs: missed ref-counting smb session in find

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello Shyam Prasad N,

The patch e695a9ad0305: "cifs: missed ref-counting smb session in
find" from May 23, 2021 (linux-next), leads to the following Smatch
static checker warning:

	fs/smb/client/connect.c:1636 cifs_put_tcp_session()
	warn: sleeping in atomic context

What happened here is that we recently shuffled some code around so
now Smatch is aware that cancel_delayed_work_sync() is a might sleep
function.

fs/smb/client/smb2transport.c
   204  smb2_find_smb_tcon(struct TCP_Server_Info *server, __u64 ses_id, __u32  tid)
   205  {
   206          struct cifs_ses *ses;
   207          struct cifs_tcon *tcon;
   208  
   209          spin_lock(&cifs_tcp_ses_lock);
   210          ses = smb2_find_smb_ses_unlocked(server, ses_id);
   211          if (!ses) {
   212                  spin_unlock(&cifs_tcp_ses_lock);
   213                  return NULL;
   214          }
   215          tcon = smb2_find_smb_sess_tcon_unlocked(ses, tid);
   216          if (!tcon) {
   217                  cifs_put_smb_ses(ses);
   218                  spin_unlock(&cifs_tcp_ses_lock);

Smatch thinks calling cifs_put_smb_ses() might be a problem.  This is
a cross function thing involving reference counting and I haven't worked
through where we're holding references so it might be a false positive...
But I see below we drop the lock before calling cifs_put_smb_ses() so
maybe it's okay here too?

   219                  return NULL;
   220          }
   221          spin_unlock(&cifs_tcp_ses_lock);
   222          /* tcon already has a ref to ses, so we don't need ses anymore */
   223          cifs_put_smb_ses(ses);
   224  
   225          return tcon;
   226  }

The call tree Smatch warns about is:

smb2_find_smb_tcon() <- disables preempt
-> cifs_put_smb_ses()
   -> __cifs_put_smb_ses()
      -> cifs_put_tcp_session()

fs/smb/client/connect.c
    1617 void
    1618 cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect)
    1619 {
    1620         struct task_struct *task;
    1621 
    1622         spin_lock(&cifs_tcp_ses_lock);
    1623         if (--server->srv_count > 0) {
    1624                 spin_unlock(&cifs_tcp_ses_lock);
    1625                 return;
    1626         }
    1627 
    1628         /* srv_count can never go negative */
    1629         WARN_ON(server->srv_count < 0);
    1630 
    1631         put_net(cifs_net_ns(server));
    1632 
    1633         list_del_init(&server->tcp_ses_list);
    1634         spin_unlock(&cifs_tcp_ses_lock);
    1635 
--> 1636         cancel_delayed_work_sync(&server->echo);
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Sleeps.

    1637 
    1638         if (from_reconnect)
    1639                 /*

regards,
dan carpenter




[Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux