Re: [PATCH] cifs: update the same create_guid on replay

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

 



On Sat, Feb 10, 2024 at 11:52 AM Steve French <smfrench@xxxxxxxxx> wrote:
>
> It needed a small rebase to work around one of Paulo's patches which
> it depended on (which is for 6.9-rc) but was wondering if you want
> this patch in before 6.9 because its change to smb2_compound_op below
> has a dependency on another patch - can that change be safely removed?
>
It will be good to have this in 6.8-rc4, if it will be accepted. It's
the same small change made in several places.
It avoids a possible handle leak on the server.

> replay_again:
>         /* reinitialize for possible replay */
>         flags = 0;
>         oplock = SMB2_OPLOCK_LEVEL_NONE;
>         num_rqst = 0;
>         server = cifs_pick_channel(ses);
>         oparms->replay = !!(retries);
>
> On Fri, Feb 9, 2024 at 5:25 AM <nspmangalore@xxxxxxxxx> wrote:
> >
> > From: Shyam Prasad N <sprasad@xxxxxxxxxxxxx>
> >
> > File open requests made to the server contain a
> > CreateGuid, which is used by the server to identify
> > the open request. If the same request needs to be
> > replayed, it needs to be sent with the same CreateGuid
> > in the durable handle v2 context.
> >
> > Without doing so, we could end up leaking handles on
> > the server when:
> > 1. multichannel is used AND
> > 2. connection goes down, but not for all channels
> >
> > This is because the replayed open request would have a
> > new CreateGuid and the server will treat this as a new
> > request and open a new handle.
> >
> > This change fixes this by reusing the existing create_guid
> > stored in the cached fid struct.
> >
> > REF: MS-SMB2 4.9 Replay Create Request on an Alternate Channel
> >
> > Fixes: 4f1fffa23769 ("cifs: commands that are retried should have replay flag set")
> > Signed-off-by: Shyam Prasad N <sprasad@xxxxxxxxxxxxx>
> > ---
> >  fs/smb/client/cached_dir.c |  1 +
> >  fs/smb/client/cifsglob.h   |  1 +
> >  fs/smb/client/smb2inode.c  |  1 +
> >  fs/smb/client/smb2ops.c    |  4 ++++
> >  fs/smb/client/smb2pdu.c    | 10 ++++++++--
> >  5 files changed, 15 insertions(+), 2 deletions(-)
> >
> > diff --git a/fs/smb/client/cached_dir.c b/fs/smb/client/cached_dir.c
> > index 1daeb5714faa..3de5047a7ff9 100644
> > --- a/fs/smb/client/cached_dir.c
> > +++ b/fs/smb/client/cached_dir.c
> > @@ -242,6 +242,7 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
> >                 .desired_access =  FILE_READ_DATA | FILE_READ_ATTRIBUTES,
> >                 .disposition = FILE_OPEN,
> >                 .fid = pfid,
> > +               .replay = !!(retries),
> >         };
> >
> >         rc = SMB2_open_init(tcon, server,
> > diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h
> > index cac10f8e17e4..efab4769de4e 100644
> > --- a/fs/smb/client/cifsglob.h
> > +++ b/fs/smb/client/cifsglob.h
> > @@ -1373,6 +1373,7 @@ struct cifs_open_parms {
> >         struct cifs_fid *fid;
> >         umode_t mode;
> >         bool reconnect:1;
> > +       bool replay:1; /* indicates that this open is for a replay */
> >         struct kvec *ea_cctx;
> >  };
> >
> > diff --git a/fs/smb/client/smb2inode.c b/fs/smb/client/smb2inode.c
> > index 63485078a6df..22bd01e7bf6e 100644
> > --- a/fs/smb/client/smb2inode.c
> > +++ b/fs/smb/client/smb2inode.c
> > @@ -203,6 +203,7 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
> >         oplock = SMB2_OPLOCK_LEVEL_NONE;
> >         num_rqst = 0;
> >         server = cifs_pick_channel(ses);
> > +       oparms->replay = !!(retries);
> >
> >         vars = kzalloc(sizeof(*vars), GFP_ATOMIC);
> >         if (vars == NULL)
> > diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c
> > index 8d674aef8dd9..c0da1935b0bd 100644
> > --- a/fs/smb/client/smb2ops.c
> > +++ b/fs/smb/client/smb2ops.c
> > @@ -1205,6 +1205,7 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon,
> >                 .disposition = FILE_OPEN,
> >                 .create_options = cifs_create_options(cifs_sb, 0),
> >                 .fid = &fid,
> > +               .replay = !!(retries),
> >         };
> >
> >         rc = SMB2_open_init(tcon, server,
> > @@ -1570,6 +1571,7 @@ smb2_ioctl_query_info(const unsigned int xid,
> >                 .disposition = FILE_OPEN,
> >                 .create_options = cifs_create_options(cifs_sb, create_options),
> >                 .fid = &fid,
> > +               .replay = !!(retries),
> >         };
> >
> >         if (qi.flags & PASSTHRU_FSCTL) {
> > @@ -2296,6 +2298,7 @@ smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon,
> >                 .disposition = FILE_OPEN,
> >                 .create_options = cifs_create_options(cifs_sb, 0),
> >                 .fid = fid,
> > +               .replay = !!(retries),
> >         };
> >
> >         rc = SMB2_open_init(tcon, server,
> > @@ -2682,6 +2685,7 @@ smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon,
> >                 .disposition = FILE_OPEN,
> >                 .create_options = cifs_create_options(cifs_sb, 0),
> >                 .fid = &fid,
> > +               .replay = !!(retries),
> >         };
> >
> >         rc = SMB2_open_init(tcon, server,
> > diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c
> > index 2ecc5f210329..1ce9be3a7ca7 100644
> > --- a/fs/smb/client/smb2pdu.c
> > +++ b/fs/smb/client/smb2pdu.c
> > @@ -2406,8 +2406,13 @@ create_durable_v2_buf(struct cifs_open_parms *oparms)
> >          */
> >         buf->dcontext.Timeout = cpu_to_le32(oparms->tcon->handle_timeout);
> >         buf->dcontext.Flags = cpu_to_le32(SMB2_DHANDLE_FLAG_PERSISTENT);
> > -       generate_random_uuid(buf->dcontext.CreateGuid);
> > -       memcpy(pfid->create_guid, buf->dcontext.CreateGuid, 16);
> > +
> > +       /* for replay, we should not overwrite the existing create guid */
> > +       if (!oparms->replay) {
> > +               generate_random_uuid(buf->dcontext.CreateGuid);
> > +               memcpy(pfid->create_guid, buf->dcontext.CreateGuid, 16);
> > +       } else
> > +               memcpy(buf->dcontext.CreateGuid, pfid->create_guid, 16);
> >
> >         /* SMB2_CREATE_DURABLE_HANDLE_REQUEST is "DH2Q" */
> >         buf->Name[0] = 'D';
> > @@ -3156,6 +3161,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
> >         /* reinitialize for possible replay */
> >         flags = 0;
> >         server = cifs_pick_channel(ses);
> > +       oparms->replay = !!(retries);
> >
> >         cifs_dbg(FYI, "create/open\n");
> >         if (!ses || !server)
> > --
> > 2.34.1
> >
>
>
> --
> Thanks,
>
> Steve



-- 
Regards,
Shyam





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

  Powered by Linux