Re: [PATCH 1/2] cifs: force a reconnect if there are too many MIDs in flight

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

 



On Sat, Jan 29, 2011 at 6:02 AM, Jeff Layton <jlayton@xxxxxxxxxx> wrote:
> Currently, we allow the pending_mid_q to grow without bound with
> SIGKILL'ed processes. This could eventually be a DoS'able problem. An
> unprivileged user could a process that does a long-running call and then
> SIGKILL it.
>
> If he can also intercept the NT_CANCEL calls or the replies from the
> server, then the pending_mid_q could grow very large, possibly even to
> 2^16 entries which might leave GetNextMid in an infinite loop. Fix this
> by imposing a hard limit of 32k calls per server. If we cross that
> limit, set the tcpStatus to CifsNeedReconnect to force cifsd to
> eventually reconnect the socket and clean out the pending_mid_q.
>
> While we're at it, clean up the function a bit and eliminate an
> unnecessary NULL pointer check.
>
> Signed-off-by: Jeff Layton <jlayton@xxxxxxxxxx>
> ---
>  fs/cifs/misc.c |   37 ++++++++++++++++++++++++-------------
>  1 files changed, 24 insertions(+), 13 deletions(-)
>
> diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
> index 77dc732..2a930a7 100644
> --- a/fs/cifs/misc.c
> +++ b/fs/cifs/misc.c
> @@ -236,10 +236,7 @@ __u16 GetNextMid(struct TCP_Server_Info *server)
>  {
>        __u16 mid = 0;
>        __u16 last_mid;
> -       int   collision;
> -
> -       if (server == NULL)
> -               return mid;
> +       bool collision;
>
>        spin_lock(&GlobalMid_Lock);
>        last_mid = server->CurrentMid; /* we do not want to loop forever */
> @@ -252,24 +249,38 @@ __u16 GetNextMid(struct TCP_Server_Info *server)
>        (and it would also have to have been a request that
>         did not time out) */
>        while (server->CurrentMid != last_mid) {
> -               struct list_head *tmp;
>                struct mid_q_entry *mid_entry;
> +               unsigned int num_mids;
>
> -               collision = 0;
> +               collision = false;
>                if (server->CurrentMid == 0)
>                        server->CurrentMid++;
>
> -               list_for_each(tmp, &server->pending_mid_q) {
> -                       mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
> -
> -                       if ((mid_entry->mid == server->CurrentMid) &&
> -                           (mid_entry->midState == MID_REQUEST_SUBMITTED)) {
> +               num_mids = 0;
> +               list_for_each_entry(mid_entry, &server->pending_mid_q, qhead) {
> +                       ++num_mids;
> +                       if (mid_entry->mid == server->CurrentMid &&
> +                           mid_entry->midState == MID_REQUEST_SUBMITTED) {
>                                /* This mid is in use, try a different one */
> -                               collision = 1;
> +                               collision = true;
>                                break;
>                        }
>                }
> -               if (collision == 0) {
> +
> +               /*
> +                * if we have more than 32k mids in the list, then something
> +                * is very wrong. Possibly a local user is trying to DoS the
> +                * box by issuing long-running calls and SIGKILL'ing them. If
> +                * we get to 2^16 mids then we're in big trouble as this
> +                * function could loop forever.
> +                *
> +                * Go ahead and assign out the mid in this situation, but force
> +                * an eventual reconnect to clean out the pending_mid_q.
> +                */
> +               if (num_mids > 32768)
> +                       server->tcpStatus = CifsNeedReconnect;
> +
> +               if (!collision) {
>                        mid = server->CurrentMid;
>                        break;
>                }
> --
> 1.7.3.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

Looks correct.

Reviewed-by: Shirish Pargaonkar <shirishpargaonkar@xxxxxxxxx>
--
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


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

  Powered by Linux