ossrs / srs

SRS is a simple, high-efficiency, real-time video server supporting RTMP, WebRTC, HLS, HTTP-FLV, SRT, MPEG-DASH, and GB28181.

Home Page:https://ossrs.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

When the length of the log content of the 'srs_error' level exceeds 4096, it will cause a memory overflow, leading to a stack corruption and a crash.

dean-river opened this issue · comments

The code is as follows:

void SrsFastLog::error(const char* tag, int context_id, const char* fmt, ...)
{
    if (_level > SrsLogLevel::Error) {
        return;
    }
    
    int size = 0;
    if (!generate_header(true, tag, context_id, "error", &size)) {
        return;
    }
    
    va_list ap;
    va_start(ap, fmt);
    // we reserved 1 bytes for the new line.
    size += vsnprintf(log_data + size, LOG_MAX_SIZE - size, fmt, ap);
    va_end(ap);

    // add strerror() to error msg.
    if (errno != 0) {
        size += snprintf(log_data + size, LOG_MAX_SIZE - size, "(%s)", strerror(errno));
    }

    write_log(fd, log_data, size, SrsLogLevel::Error);
}

Due to vsnprintf, when the content to be written is greater than LOG_MAX_SIZE - size, its return value is not the actual length written, but rather the length that should be written. The standard states it as follows:

If the resulting string would be longer than n-1 characters, 
the remaining characters are discarded and not stored, 
but counted for the value returned by the function.

So, when the content of the fmt, ap part is greater than LOG_MAX_SIZE, the size returned by vsnprintf will also be greater than LOG_MAX_SIZE. Therefore, the subsequent snprintf will cause a memory overflow and corrupt the stack. It is recommended to place the content to be written by snprintf before vsnprintf.

TRANS_BY_GPT3

Can you help submit a Pull Request? Please make sure to maintain the markdown structure.

TRANS_BY_GPT3

I checked the manual:

     int printf(const char * restrict format, ...);
     int sprintf(char * restrict str, const char * restrict format, ...);
     int snprintf(char * restrict str, size_t size, const char * restrict format, ...);
     int vsnprintf(char * restrict str, size_t size, const char * restrict format, va_list ap);

RETURN VALUES
     These functions return the number of characters printed (not including the trailing `\0' used to end output to strings), except for
     snprintf() and vsnprintf(), which return the number of characters that would have been printed if the size were unlimited (again, not
     including the final `\0').  These functions return a negative value if an error occurs.

The single test program is as follows:

#define _ARRAY_INIT(buf, sz, val) \
    for (int i = 0; i < (int)sz; i++) buf[i]=val

VOID TEST(CoreLogger, CheckVsnprintf)
{
    if (true) {
        char buf[1024];
        _ARRAY_INIT(buf, sizeof(buf), 0xf);

        // Return the number of characters printed.
        EXPECT_EQ(6, sprintf(buf, "%s", "Hello!"));
        EXPECT_EQ('H', buf[0]);
        EXPECT_EQ('!', buf[5]);
        EXPECT_EQ(0x0, buf[6]);
        EXPECT_EQ(0xf, buf[7]);
    }

    if (true) {
        char buf[1024];
        _ARRAY_INIT(buf, sizeof(buf), 0xf);

        // Return the number of characters that would have been printed if the size were unlimited.
        EXPECT_EQ(6, snprintf(buf, 3, "%s", "Hello!"));
        EXPECT_EQ('H', buf[0]);
        EXPECT_EQ('e', buf[1]);
        EXPECT_EQ(0, buf[2]);
        EXPECT_EQ(0xf, buf[3]);
    }
}

This risk has been resolved at 78da67e.

There may be security risks with sprintf and vsprintf due to the lack of string length restrictions.

SECURITY CONSIDERATIONS
     The sprintf() and vsprintf() functions are easily misused in a manner which enables malicious users to arbitrarily change a running pro-
     gram's functionality through a buffer overflow attack.  Because sprintf() and vsprintf() assume an infinitely long string, callers must
     be careful not to overflow the actual space; this is often hard to assure.  For safety, programmers should use the snprintf() interface
     instead.

SRS is mainly used in HDS and has been fixed at ad70589. It is also used in JSON and appears to have no risks.

Thank you @dean-river 👍

TRANS_BY_GPT3