Skip to contentSkip to conversation

New: Funcation tcp_v6_md5_do_del return has error.

Bugme-new Andrew Morton 2 participants 2 messages Nov 20, 2007 – Nov 21, 2007 1 message not in the archive

Subsystems (2)
lore
Share & tools
lore

A message that is not in the archive (sent off-list or not yet received): [email protected]/

#1 lore raw
Quoted 60 lines · On Tue, 20 Nov 2007 07:13:00 -0800 (PST) [email protected] wrote:

http://bugzilla.kernel.org/show_bug.cgi?id=9418

           Summary: Funcation tcp_v6_md5_do_del return has error.
           Product: Networking
           Version: 2.5
     KernelVersion: 2.6.23
          Platform: All
        OS/Version: Linux
              Tree: Mainline
            Status: NEW
          Severity: normal
          Priority: P1
         Component: IPV6
        AssignedTo: [email protected]
        ReportedBy: [email protected]

Most recent kernel where this bug did not occur:
None, I always had this problem with the md5 in tcpv6. Distribution:
Hardware Environment:
Software Environment:
Problem Description:
When you creat two or more tcpv6 md5 entries,and you may del someone.For example, if you added two ipv6 address(2000::9, 2000::10) to a sk, so the sk first md5 entry is for 2000::9 and second entry is for 2000::10, and then the sk has two entries. If you want to del the second md5 entry , the funcation "tcp_v6_md5_do_del" will not sub the tp->md5sig_info->entries6 for the first loop, because this time the address is not 2000::9.For the second loop, the tp->md5sig_info->entries6 will sub 1,but this time tp->md5sig_info->entries6 is not 0 but 1, so the funcation return -ENOENT.When application get the return vlaue may occur error.

for (i = 0; i < tp->md5sig_info->entries6; i++) {
    if (ipv6_addr_cmp(&tp->md5sig_info->keys6[i].addr, peer) == 0) {
        /* Free the key */
        kfree(tp->md5sig_info->keys6[i].base.key);
        tp->md5sig_info->entries6--;

        if (tp->md5sig_info->entries6 == 0) {
            kfree(tp->md5sig_info->keys6);
            tp->md5sig_info->keys6 = NULL;
            tp->md5sig_info->alloced6 = 0;

            tcp_free_md5sig_pool();

            /*return 0;*/    /*not in here*/
        } else {
            /* shrink the database */
            if (tp->md5sig_info->entries6 != i)
                memmove(&tp->md5sig_info->keys6[i],
                    &tp->md5sig_info->keys6[i+1],
                    (tp->md5sig_info->entries6 - i)
                    * sizeof (tp->md5sig_info->keys6[0]));
        }
    }
    return 0;/*should be return here*/
}
Quoted 3 lines

Steps to reproduce:
Create two tcpv6 md5 entry ,and then delete the second.

and

Quoted 34 lines

I have a mistake. The code shoule be :
static int tcp_v6_md5_do_del(struct sock *sk, struct in6_addr *peer)

{
    struct tcp_sock *tp = tcp_sk(sk);
    int i;

    for (i = 0; i < tp->md5sig_info->entries6; i++) {
        if (ipv6_addr_cmp(&tp->md5sig_info->keys6[i].addr, peer) == 0) {
            /* Free the key */
            kfree(tp->md5sig_info->keys6[i].base.key);
            tp->md5sig_info->entries6--;

            if (tp->md5sig_info->entries6 == 0) {
                kfree(tp->md5sig_info->keys6);
                tp->md5sig_info->keys6 = NULL;
                tp->md5sig_info->alloced6 = 0;

                /*tcp_free_md5sig_pool();*/   /*this also wrong*/

                /*return 0;*/    /*not in here*/
            } else {
                /* shrink the database */
                if (tp->md5sig_info->entries6 != i)
                    memmove(&tp->md5sig_info->keys6[i],
                        &tp->md5sig_info->keys6[i+1],
                        (tp->md5sig_info->entries6 - i)
                        * sizeof (tp->md5sig_info->keys6[0]));
            }
            tcp_free_md5sig_pool();   /*should be put here*/
            return 0;           /*should be return here*/
        }
    }
    return -ENOENT;
}
maintainer
#2 lore raw

Yoshifuji just posted 4 patches which together should fix this one, I'll add them to my net-2.6 tree.

Thanks.