This is an automatic generated email to let you know that the following patch 
were queued at the 
http://git.linuxtv.org/cgit.cgi/v4l-utils.git tree:

Subject: dvbv5-daemon: validate remote message lengths
Author:  Dominik "Disconnect3d" Czarnota <[email protected]>
Date:    Thu Jun 4 08:10:32 2026 +0000

dvbv5-daemon reads length-prefixed messages from TCP clients. The
message length is used as the size argument to recv() before checking
that it fits in the stack buffer.

scan_data() also copies length-prefixed strings into caller-provided
buffers without knowing their sizes. A remote client can use this to
overflow fixed stack buffers such as cmd[80].

Reject frames larger than the receive buffer before reading the frame
body, and make scan_data() require a destination size for each string
argument.

The issues can be reproduced against an affected daemon listening on TCP
port 1234 with:

python3 -c 'import sys,struct; p=b"B"*20000; 
sys.stdout.buffer.write(struct.pack(">I",len(p))+p)' | nc 127.0.0.1 1234

python3 -c 'import sys,struct; cmd=b"A"*50000; 
p=struct.pack(">I",1)+struct.pack(">I",len(cmd))+cmd;sys.stdout.buffer.write(struct.pack(">I",len(p))+p)'
 | nc -vvv 127.0.0.1 1234

Assisted-by: Codex:gpt-5.5-cyber-preview
Signed-off-by: Dominik "Disconnect3d" Czarnota 
<[email protected]>
Signed-off-by: Hans Verkuil <[email protected]>

 utils/dvb/dvbv5-daemon.c | 65 ++++++++++++++++++++++++++++++++----------------
 1 file changed, 43 insertions(+), 22 deletions(-)

---

http://git.linuxtv.org/cgit.cgi/v4l-utils.git/commit/?id=c24af758ab6cd64990f074838eb6f2fec0d2a7fb
diff --git a/utils/dvb/dvbv5-daemon.c b/utils/dvb/dvbv5-daemon.c
index 669b3321655e..3311967fdbb5 100644
--- a/utils/dvb/dvbv5-daemon.c
+++ b/utils/dvb/dvbv5-daemon.c
@@ -475,13 +475,10 @@ static ssize_t send_data(int fd, const char *fmt, ...)
        return send_buf(fd, buf, ret);
 }
 
-static ssize_t scan_data(char *buf, int buf_size, const char *fmt, ...)
-       __attribute__ (( format( scanf, 3, 4 )));
-
-static ssize_t scan_data(char *buf, int buf_size, const char *fmt, ...)
+static ssize_t scan_data(char *buf, size_t buf_size, const char *fmt, ...)
 {
        char *p = buf, *endp = &buf[buf_size], *s;
-       int len;
+       size_t len, max_len;
        int32_t *i32;
        uint64_t *u64;
        va_list ap;
@@ -493,17 +490,24 @@ static ssize_t scan_data(char *buf, int buf_size, const 
char *fmt, ...)
                switch (*fmt++) {
                case 's':              /* string */
                        s = va_arg(ap, char *);
+                       max_len = va_arg(ap, size_t);
                        if (p + 4 > endp) {
                                dbg("buffer to short for string length");
                                stack_dump();
-                               return -1;
+                               goto error;
                        }
-                       len = be32toh(*(int32_t *)p);
+                       len = be32toh(*(uint32_t *)p);
                        p += 4;
-                       if (p + len > endp) {
+                       if (len > (size_t)(endp - p)) {
                                dbg("buffer to short for string");
                                stack_dump();
-                               return -1;
+                               goto error;
+                       }
+                       if (len >= max_len) {
+                               dbg("string length %zu exceeds destination size 
%zu",
+                                   len, max_len);
+                               stack_dump();
+                               goto error;
                        }
 
                        memcpy(s, p, len);
@@ -514,7 +518,7 @@ static ssize_t scan_data(char *buf, int buf_size, const 
char *fmt, ...)
                        if (p + 4 > endp) {
                                dbg("buffer to short for int32_t");
                                stack_dump();
-                               return -1;
+                               goto error;
                        }
                        i32 = va_arg(ap, int32_t *);
 
@@ -530,7 +534,7 @@ static ssize_t scan_data(char *buf, int buf_size, const 
char *fmt, ...)
                        if (p + 8 > endp) {
                                dbg("buffer to short for uint64_t");
                                stack_dump();
-                               return -1;
+                               goto error;
                        }
                        u64 = va_arg(ap, uint64_t *);
 
@@ -547,6 +551,10 @@ static ssize_t scan_data(char *buf, int buf_size, const 
char *fmt, ...)
        va_end(ap);
 
        return p - buf;
+
+error:
+       va_end(ap);
+       return -1;
 }
 
 /*
@@ -652,7 +660,7 @@ static int dev_get_dev_info(uint32_t seq, char *cmd, int fd,
        char sysname[REMOTE_BUF_SIZE];
        int ret;
 
-       ret = scan_data(buf, size, "%s", sysname);
+       ret = scan_data(buf, size, "%s", sysname, sizeof(sysname));
        if (ret < 0)
                goto error;
 
@@ -788,7 +796,7 @@ static int dev_open(uint32_t seq, char *cmd, int fd, char 
*buf, ssize_t size)
                goto error;
        }
 
-       ret = scan_data(buf, size, "%s%i", sysname, &flags);
+       ret = scan_data(buf, size, "%s%i", sysname, sizeof(sysname), &flags);
        if (ret < 0) {
                free(desc);
                goto error;
@@ -971,7 +979,10 @@ static int dev_dmx_set_section_filter(uint32_t seq, char 
*cmd, int fd,
        unsigned char filter[17], mask[17], mode[17];
 
        ret = scan_data(buf, size, "%i%i%i%s%s%s%i",
-                       &uid, &pid, &filtsize, filter, mask, mode, &flags);
+                       &uid, &pid, &filtsize,
+                       (char *)filter, sizeof(filter),
+                       (char *)mask, sizeof(mask),
+                       (char *)mode, sizeof(mode), &flags);
        if (ret < 0)
                goto error;
 
@@ -1168,9 +1179,11 @@ static int dev_set_parms(uint32_t seq, char *cmd, int fd,
                old_lnb = par->lnb->name;
 
        ret = scan_data(p, size, "%i%i%s%i%i%i%i%s%s",
-                       &par->abort, &par->lna, new_lnb,
+                       &par->abort, &par->lna, new_lnb, sizeof(new_lnb),
                        &par->sat_number, &par->freq_bpf, &par->diseqc_wait,
-                       &par->verbose, default_charset, output_charset);
+                       &par->verbose,
+                       default_charset, sizeof(default_charset),
+                       output_charset, sizeof(output_charset));
 
        if (ret < 0)
                goto error;
@@ -1341,7 +1354,7 @@ static void *start_server(void *fd_pointer)
        int fd = *(int *)fd_pointer, ret, flag = 1;
        char buf[REMOTE_BUF_SIZE + 8], cmd[CMD_SIZE], *p;
        ssize_t size;
-       uint32_t seq;
+       uint32_t frame_size, seq;
        int bufsize;
 
        if (verbose)
@@ -1364,13 +1377,21 @@ static void *start_server(void *fd_pointer)
                size = recv(fd, buf, 4, MSG_WAITALL);
                if (size <= 0)
                        break;
-               size = (uint32_t)buf[0] << 24 | (uint32_t)buf[1] << 16 |
-                      (uint32_t)buf[2] << 8 | (uint32_t)buf[3];
-               size = recv(fd, buf, size, MSG_WAITALL);
-               if (size <= 0)
+               frame_size = (uint32_t)buf[0] << 24 | (uint32_t)buf[1] << 16 |
+                            (uint32_t)buf[2] << 8 | (uint32_t)buf[3];
+               if (frame_size > sizeof(buf)) {
+                       if (verbose)
+                               dbg("data length too big: %u", frame_size);
+                       send_data(fd, "%i%s%i%s", 0, "log", LOG_ERR,
+                                 "data length too big");
+                       break;
+               }
+
+               size = recv(fd, buf, frame_size, MSG_WAITALL);
+               if (size <= 0 || (uint32_t)size != frame_size)
                        break;
 
-               ret = scan_data(buf, size, "%i%s",  &seq, cmd);
+               ret = scan_data(buf, size, "%i%s",  &seq, cmd, sizeof(cmd));
                if (ret < 0) {
                        if (verbose)
                                dbg("message too short: %ld", size);
_______________________________________________
linuxtv-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to