]> git.puffer.fish Git - mirror/frr.git/commitdiff
isisd: Fix use beyond end of stream of ASLA Sub-TLV parsing 13758/head
authorCarmine Scarpitta <carmine.scarpitta@uniroma2.it>
Sat, 10 Jun 2023 14:08:25 +0000 (16:08 +0200)
committerCarmine Scarpitta <carmine.scarpitta@uniroma2.it>
Wed, 14 Jun 2023 06:31:32 +0000 (08:31 +0200)
Fixes a crash associated with attempting to read beyond the end of the
stream when parsing ASLA Sub-TLV.

```
Program received signal SIGABRT, Aborted.
__GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
50 ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) bt
    subtlv_len=13 '\r') at isisd/isis_tlvs.c:1473
    at isisd/isis_tlvs.c:3264
    context=<optimized out>, mtid=<optimized out>) at isisd/isis_tlvs.c:6078
    indent=4) at isisd/isis_tlvs.c:6142
    avail_len=<optimized out>, context=<optimized out>) at isisd/isis_tlvs.c:7032
    at isisd/isis_tlvs.c:7054
(gdb)
```

Caught by fuzzer.

Signed-off-by: Carmine Scarpitta <carmine.scarpitta@uniroma2.it>
isisd/isis_tlvs.c

index 4ad877ce0f19054c4ad91606a61f82d3e8a94ae7..e871ae8c4f99404e81566dbce520b6b6c9515495 100644 (file)
@@ -1133,7 +1133,7 @@ static int unpack_item_ext_subtlv_asla(uint16_t mtid, uint8_t subtlv_len,
        uint8_t uabm_flag_len;
        uint8_t sabm[ASLA_APP_IDENTIFIER_BIT_LENGTH] = {0};
        uint8_t uabm[ASLA_APP_IDENTIFIER_BIT_LENGTH] = {0};
-       uint8_t readable;
+       uint8_t readable = subtlv_len;
        uint8_t subsubtlv_type;
        uint8_t subsubtlv_len;
        size_t nb_groups;
@@ -1156,15 +1156,23 @@ static int unpack_item_ext_subtlv_asla(uint16_t mtid, uint8_t subtlv_len,
        asla->standard_apps_length = ASLA_APPS_LENGTH_MASK & sabm_flag_len;
        asla->user_def_apps_length = ASLA_APPS_LENGTH_MASK & uabm_flag_len;
 
+       readable -= ISIS_SUBSUBTLV_HDR_SIZE;
+       if (readable <
+           asla->standard_apps_length + asla->user_def_apps_length) {
+               TLV_SIZE_MISMATCH(log, indent, "ASLA");
+               return -1;
+       }
+
        for (int i = 0; i < asla->standard_apps_length; i++)
                sabm[i] = stream_getc(s);
        for (int i = 0; i < asla->user_def_apps_length; i++)
                uabm[i] = stream_getc(s);
 
+       readable -= (asla->standard_apps_length + asla->user_def_apps_length);
+
        asla->standard_apps = sabm[0];
        asla->user_def_apps = uabm[0];
 
-       readable = subtlv_len - 4;
        while (readable > 0) {
                if (readable < ISIS_SUBSUBTLV_HDR_SIZE) {
                        TLV_SIZE_MISMATCH(log, indent, "ASLA Sub TLV");