Overflow in read()? (Sockets)



  • Hallo,

    ich wollte mal fragen, wie sieht das mit Buffer Overflows in read() aus in den sockets? Wenn ich folgenden Code habe:

    // notwendige Header ;-)
    
    int main(void)
    {
        char buf[BUFSIZ];
        int n = 0;
    
        // ... socket code
        n = read(sockfd, buf, BUFSIZ);
        if(n < 0) {
            // Fehlerbehandlung
        }
    
        // Sonstige Anweisungen ...
    }
    

    Ist hier in irgendeiner Weise ein Overflow möglich? Ich meine dadurch, dass ich BUFSIZ an read() übergebe, ist die Obergrenze ja bekannt. Und selbst wenn weniger Zeichen übertragen werden, weil das Paket zu klein ist oder weil es irgendwie nicht ganz ankommt (wobei dann würde es ja verworfen?), sollte hier kein Overflow möglich sein.

    Sehe ich das richtig?

    Vielen Dank!



  • Mal abgesehen davon dass ich keine Socketfunktion "read" kenne:
    Nein, du übergibst ihm einen Buffer und die Länge des Buffers, du hast dann alles richtig gemacht. 😉



  • Ich meinte natürlich die read()-Funktion, mit der ich von dem Socket lese. 😛 http://man7.org/linux/man-pages/man2/read.2.html

    Der Professor meinte in der Vorlesung, dass man hier ganz einfach Buffer-Overflows erzeugen könne, wo ich nun aber keine Möglichkeit sehe, daher meine Frage.



  • Naja man kann auch ganz einfach Bufferoverflows erzeugen. 😉
    Mal ein ganz blödes Beispiel:

    char buf[2048];
        int messageLength;
    
        read(sockfd, &messageLength, sizeof(int));
    
        read(sockfd, buf, messageLength);
    

    Ohne Fehlerbehandlung und unportabel.

    Solange der Client sicherstellt dass die Nachricht klein genug ist, kein Problem.
    Aber jetzt stell dir vor der Client sendet aus Bosheit eine Nachricht die nicht wie üblich in die 2048 Bytes passt... 😉



  • Ja das macht Sinn. Aber was genau macht deine dritte Zeile?

    read(sockfd, &messageLength, sizeof(int));
    

    Wenn ich allerdings anstatt messageLength die 2048 übergebe, kann es denn dann noch dazu kommen? Und reicht es dann, wenn ich danach, wie in meinem ursprünglichen Code eine if-Abfrage habe, die schaut ob der Rückgabewert von read() größer 0 ist? Wie kann ich sicherstellen, dass auch wirklich nur die 2048 Byte gelesen werden, egal was der Client macht?

    Vielen Dank.



  • Der Sinn bei meinem Beispiel ist, dass der Client erst die Länge der Nachricht sendet und dann die Nachricht. Wenn der Empfänger das nicht überprüft führt das zu Problemen.

    char buf[2048];
    int messageLength;
    
    //Liest (binär) einen Int ein, wie gesagt unschön und nur für Demonstrationszwecke
    //Diese Zahl gibt die Länge der Nachricht an die folgt
    read(sockfd, &messageLength, sizeof(int));
    
    //Liest die Nachricht ein, führt zu Problemen wenn die Länge größer 2048 oder kleiner als 0 ist
    read(sockfd, buf, messageLength);
    

    Dudu schrieb:

    Wenn ich allerdings anstatt messageLength die 2048 übergebe, kann es denn dann noch dazu kommen?

    Meinst du das?

    read(sockfd, buf, 2048);
    

    Was ist wenn der Client aber 10 Nachrichten mit je nur 5 Bytes sendet? Dann behandelst die alle als eine Nachticht. Oder wartest ewig auf die restlichen Bytes die nie kommen.
    Wenn der Client mehr als 2048 Bytes sendet, müsstest du die Nachricht auf mehrere Male einlesen. So würde man das machen, aber da brauchts noch mehr Code. 😉

    Dudu schrieb:

    Und reicht es dann, wenn ich danach, wie in meinem ursprünglichen Code eine if-Abfrage habe, die schaut ob der Rückgabewert von read() größer 0 ist? Wie kann ich sicherstellen, dass auch wirklich nur die 2048 Byte gelesen werden, egal was der Client macht?

    Entweder sorgst du dafür dass der Buffer groß genug ist (malloc/free) oder du ließt die Nachricht auf mehrere Male ein.


Log in to reply