From nobody Mon Jun 22 16:47:27 2026 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4gkYyr4wD3z6hY9J for ; Mon, 22 Jun 2026 16:47:32 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "YR1" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4gkYyr4NQhz3R3c for ; Mon, 22 Jun 2026 16:47:32 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1782146852; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=1IPPb7EcKyKSYTmu9Rt5o0Lij/K79cgmY96psR1qbPE=; b=yk6luGVCxV/BGATOkTLPqL3SXwVZ7Yn0tFoBb50W2az+kOpQo3Vquv2O4MVvhc/gv9+CuF 3tx9B7cfP3aBDVH0mAV9W6oSkdh8GO1pEeZqk5/3tHHaxNGvnFdnFzVeNw7ZHHCpqzqnbd ufVf+29io21BTEyKq9ZH6EHemAwVkhOytwhgf6w9eA9XVZ4Gkju9OBo/SFIRSuhOJzLwfL Lv60gOjfeB0ly5YfojgSsc/sE1Kc8ZjUdb9oZk8NzxbljsLy7RxJpR4mlA1AtDErRXuHaa myvpYhfLdc6gcnEvcKvZTbfhbVVPgA0G/6PaIFOhw7K8DKgLf1D4GpE463RwLQ== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1782146852; a=rsa-sha256; cv=none; b=RKx0//Bl0/mzGNr5pT8WHAs/f2DMPrnBRel4I70llJPGdR5AiGKqykBJ1UWyIU8pNMB7Wd 2S5J4pXTrdNDRy8m1CxFionleHg05ZTjnDNtN3+9beo4vBojEAjzFjFCt8vWWaWpSbXwe4 D+6GziO9wLSMNyjBlfotu8PclXNBXeDCTr7xHNE0Mc7l7KpAoWaj+X6GC5T1v2YnL3QOrA 2FAfs8ERgLAry1WTgh9kSDD2c8J5ZTaBFe6Atii0CHO7dgpftVjRnlSLaJYUWEyEwKezZg CuohkO1Gay5wgHFJZr+Z+4RNCyMX89hz4aOV83fsvVDBhgMZajZQxmVBGgJoOQ== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1782146852; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=1IPPb7EcKyKSYTmu9Rt5o0Lij/K79cgmY96psR1qbPE=; b=BIktnVkD5s1KBpYeIejnFrnbwdaJPYFscQyfVvxBhTKKrgaUOWbjmOLBdJQzMV1jVBLrAY 6kp+zq8d3Qwje0cZ7sJWgsLoG3KaLoYZzPN/1UMpyYd2sTbSuczRqe/uBIeLq5rHoUBj/j C85SwShPdRcy7A2EEw9Zc4oD8lWvK+MILyFvqAg7nUTr/sgPxVL9WbqIk+e2XoguwBKswA xjmhKbDsQ0jZ2iKI9wFmj3KE9UyPXFSWbtkkr9qHQKx6tm5pvZogmVqHs7jMK4hiyPzKMS Ss+v0ra7hGn4L+3BH9DQBUpFpJ/jkwc6Uh135D+EaOF/DEVFXI6mYLn8GLAXng== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4gkYyr30x5zw7T for ; Mon, 22 Jun 2026 16:47:32 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 1ebae by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Mon, 22 Jun 2026 16:47:27 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: John Baldwin Subject: git: 9cd0d6231311 - main - cd9660: Add various length checks when parsing RRIP extensions List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: jhb X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 9cd0d6231311bc5609403fb35377a7bb97a3cfaf Auto-Submitted: auto-generated Date: Mon, 22 Jun 2026 16:47:27 +0000 Message-Id: <6a39671f.1ebae.7bd39f4d@gitrepo.freebsd.org> The branch main has been updated by jhb: URL: https://cgit.FreeBSD.org/src/commit/?id=9cd0d6231311bc5609403fb35377a7bb97a3cfaf commit 9cd0d6231311bc5609403fb35377a7bb97a3cfaf Author: John Baldwin AuthorDate: 2026-06-22 16:41:04 +0000 Commit: John Baldwin CommitDate: 2026-06-22 16:41:04 +0000 cd9660: Add various length checks when parsing RRIP extensions Pass the length of a RockRidge attribute to the handler functions and validate that length in each handler. If a parsing error is detected, abort the entire parsing pass. Reviewed by: des Differential Revision: https://reviews.freebsd.org/D57136 --- sys/fs/cd9660/cd9660_rrip.c | 186 ++++++++++++++++++++++++++++++++------------ sys/fs/cd9660/iso_rrip.h | 1 + 2 files changed, 136 insertions(+), 51 deletions(-) diff --git a/sys/fs/cd9660/cd9660_rrip.c b/sys/fs/cd9660/cd9660_rrip.c index db87f6d1223e..e3aab4fa6115 100644 --- a/sys/fs/cd9660/cd9660_rrip.c +++ b/sys/fs/cd9660/cd9660_rrip.c @@ -48,7 +48,7 @@ #include #include -typedef int rrt_func_t(void *, ISO_RRIP_ANALYZE *ana); +typedef int rrt_func_t(void *, size_t, ISO_RRIP_ANALYZE *ana); typedef struct { char type[2]; @@ -57,32 +57,48 @@ typedef struct { int result; } RRIP_TABLE; -static int cd9660_rrip_altname(ISO_RRIP_ALTNAME *p, ISO_RRIP_ANALYZE *ana); -static int cd9660_rrip_attr(ISO_RRIP_ATTR *p, ISO_RRIP_ANALYZE *ana); -static int cd9660_rrip_cont(ISO_RRIP_CONT *p, ISO_RRIP_ANALYZE *ana); +static int cd9660_rrip_altname(ISO_RRIP_ALTNAME *p, size_t len, + ISO_RRIP_ANALYZE *ana); +static int cd9660_rrip_attr(ISO_RRIP_ATTR *p, size_t len, + ISO_RRIP_ANALYZE *ana); +static int cd9660_rrip_cont(ISO_RRIP_CONT *p, size_t len, + ISO_RRIP_ANALYZE *ana); static void cd9660_rrip_defattr(struct iso_directory_record *isodir, ISO_RRIP_ANALYZE *ana); static void cd9660_rrip_defname(struct iso_directory_record *isodir, ISO_RRIP_ANALYZE *ana); static void cd9660_rrip_deftstamp(struct iso_directory_record *isodir, ISO_RRIP_ANALYZE *ana); -static int cd9660_rrip_device(ISO_RRIP_DEVICE *p, ISO_RRIP_ANALYZE *ana); -static int cd9660_rrip_extref(ISO_RRIP_EXTREF *p, ISO_RRIP_ANALYZE *ana); -static int cd9660_rrip_idflag(ISO_RRIP_IDFLAG *p, ISO_RRIP_ANALYZE *ana); +static int cd9660_rrip_device(ISO_RRIP_DEVICE *p, size_t len, + ISO_RRIP_ANALYZE *ana); +static int cd9660_rrip_extref(ISO_RRIP_EXTREF *p, size_t len, + ISO_RRIP_ANALYZE *ana); +static int cd9660_rrip_idflag(ISO_RRIP_IDFLAG *p, size_t len, + ISO_RRIP_ANALYZE *ana); static int cd9660_rrip_loop(struct iso_directory_record *isodir, ISO_RRIP_ANALYZE *ana, RRIP_TABLE *table); -static int cd9660_rrip_pclink(ISO_RRIP_CLINK *p, ISO_RRIP_ANALYZE *ana); -static int cd9660_rrip_reldir(ISO_RRIP_RELDIR *p, ISO_RRIP_ANALYZE *ana); -static int cd9660_rrip_slink(ISO_RRIP_SLINK *p, ISO_RRIP_ANALYZE *ana); -static int cd9660_rrip_stop(ISO_SUSP_HEADER *p, ISO_RRIP_ANALYZE *ana); -static int cd9660_rrip_tstamp(ISO_RRIP_TSTAMP *p, ISO_RRIP_ANALYZE *ana); +static int cd9660_rrip_pclink(ISO_RRIP_CLINK *p, size_t len, + ISO_RRIP_ANALYZE *ana); +static int cd9660_rrip_reldir(ISO_RRIP_RELDIR *p, size_t len, + ISO_RRIP_ANALYZE *ana); +static int cd9660_rrip_slink(ISO_RRIP_SLINK *p, size_t len, + ISO_RRIP_ANALYZE *ana); +static int cd9660_rrip_stop(ISO_SUSP_HEADER *p, size_t len, + ISO_RRIP_ANALYZE *ana); +static int cd9660_rrip_tstamp(ISO_RRIP_TSTAMP *p, size_t len, + ISO_RRIP_ANALYZE *ana); /* * POSIX file attribute */ static int -cd9660_rrip_attr(ISO_RRIP_ATTR *p, ISO_RRIP_ANALYZE *ana) +cd9660_rrip_attr(ISO_RRIP_ATTR *p, size_t len, ISO_RRIP_ANALYZE *ana) { + if (len < sizeof(*p)) { + ana->error = true; + return (0); + } + ana->inop->inode.iso_mode = isonum_733(p->mode); ana->inop->inode.iso_uid = isonum_733(p->uid); ana->inop->inode.iso_gid = isonum_733(p->gid); @@ -103,16 +119,23 @@ cd9660_rrip_defattr(struct iso_directory_record *isodir, ISO_RRIP_ANALYZE *ana) * Symbolic Links */ static int -cd9660_rrip_slink(ISO_RRIP_SLINK *p, ISO_RRIP_ANALYZE *ana) +cd9660_rrip_slink(ISO_RRIP_SLINK *p, size_t plen, ISO_RRIP_ANALYZE *ana) { ISO_RRIP_SLINK_COMPONENT *pcomp; ISO_RRIP_SLINK_COMPONENT *pcompe; + ISO_RRIP_SLINK_COMPONENT *pcompn; int len, wlen, cont; char *outbuf, *inbuf; char hostbuf[MAXHOSTNAMELEN]; + /* This requires at least one byte of a component. */ + if (plen < sizeof(*p)) { + ana->error = true; + return (0); + } + pcomp = (ISO_RRIP_SLINK_COMPONENT *)p->component; - pcompe = (ISO_RRIP_SLINK_COMPONENT *)((char *)p + isonum_711(p->h.length)); + pcompe = (ISO_RRIP_SLINK_COMPONENT *)((char *)p + plen); len = *ana->outlen; outbuf = ana->outbuf; cont = ana->cont; @@ -120,10 +143,16 @@ cd9660_rrip_slink(ISO_RRIP_SLINK *p, ISO_RRIP_ANALYZE *ana) /* * Gathering a Symbolic name from each component with path */ - for (; - pcomp < pcompe; - pcomp = (ISO_RRIP_SLINK_COMPONENT *)((char *)pcomp + ISO_RRIP_SLSIZ - + isonum_711(pcomp->clen))) { + for (; pcomp < pcompe; pcomp = pcompn) { + pcompn = (ISO_RRIP_SLINK_COMPONENT *)((char *)pcomp + + ISO_RRIP_SLSIZ + isonum_711(pcomp->clen)); + + /* If this component overflows the buffer, abort parsing. */ + if (pcompn > pcompe) { + ana->error = true; + return (0); + } + if (!cont) { if (len < ana->maxlen) { len++; @@ -175,21 +204,15 @@ cd9660_rrip_slink(ISO_RRIP_SLINK *p, ISO_RRIP_ANALYZE *ana) /* Inserting component */ wlen = isonum_711(pcomp->clen); inbuf = pcomp->name; - if (inbuf + wlen > (char *)pcompe) - wlen = ana->maxlen + 1; break; default: printf("RRIP with incorrect flags?"); - wlen = ana->maxlen + 1; - break; + ana->error = true; + return (0); } if (len + wlen > ana->maxlen) { - /* indicate error to caller */ - ana->cont = 1; - ana->fields = 0; - ana->outbuf -= *ana->outlen; - *ana->outlen = 0; + ana->error = true; return (0); } @@ -212,13 +235,18 @@ cd9660_rrip_slink(ISO_RRIP_SLINK *p, ISO_RRIP_ANALYZE *ana) * Alternate name */ static int -cd9660_rrip_altname(ISO_RRIP_ALTNAME *p, ISO_RRIP_ANALYZE *ana) +cd9660_rrip_altname(ISO_RRIP_ALTNAME *p, size_t len, ISO_RRIP_ANALYZE *ana) { char *inbuf; int wlen; int cont; char hostbuf[MAXHOSTNAMELEN]; + if (len < sizeof(*p)) { + ana->error = true; + return (0); + } + inbuf = ".."; wlen = 0; cont = 0; @@ -246,23 +274,18 @@ cd9660_rrip_altname(ISO_RRIP_ALTNAME *p, ISO_RRIP_ANALYZE *ana) /* FALLTHROUGH */ case 0: /* Inserting component */ - wlen = isonum_711(p->h.length) - 5; - inbuf = (char *)p + 5; - if (wlen < 0) - wlen = ana->maxlen + 1; + wlen = len - sizeof(*p); + inbuf = (char *)(p + 1); break; default: printf("RRIP with incorrect NM flags?\n"); - wlen = ana->maxlen + 1; - break; + ana->error = true; + return (0); } if ((*ana->outlen += wlen) > ana->maxlen) { - /* treat as no name field */ - ana->fields &= ~ISO_SUSP_ALTNAME; - ana->outbuf -= *ana->outlen - wlen; - *ana->outlen = 0; + ana->error = true; return (0); } @@ -299,8 +322,13 @@ cd9660_rrip_defname(struct iso_directory_record *isodir, ISO_RRIP_ANALYZE *ana) * Parent or Child Link */ static int -cd9660_rrip_pclink(ISO_RRIP_CLINK *p, ISO_RRIP_ANALYZE *ana) +cd9660_rrip_pclink(ISO_RRIP_CLINK *p, size_t len, ISO_RRIP_ANALYZE *ana) { + if (len < sizeof(*p)) { + ana->error = true; + return (0); + } + *ana->inump = isonum_733(p->dir_loc) << ana->imp->im_bshift; ana->fields &= ~(ISO_SUSP_CLINK | ISO_SUSP_PLINK); return (*p->h.type == 'C' ? ISO_SUSP_CLINK : ISO_SUSP_PLINK); @@ -310,7 +338,7 @@ cd9660_rrip_pclink(ISO_RRIP_CLINK *p, ISO_RRIP_ANALYZE *ana) * Relocated directory */ static int -cd9660_rrip_reldir(ISO_RRIP_RELDIR *p, ISO_RRIP_ANALYZE *ana) +cd9660_rrip_reldir(ISO_RRIP_RELDIR *p, size_t len, ISO_RRIP_ANALYZE *ana) { /* special hack to make caller aware of RE field */ *ana->outlen = 0; @@ -319,9 +347,29 @@ cd9660_rrip_reldir(ISO_RRIP_RELDIR *p, ISO_RRIP_ANALYZE *ana) } static int -cd9660_rrip_tstamp(ISO_RRIP_TSTAMP *p, ISO_RRIP_ANALYZE *ana) +cd9660_rrip_tstamp(ISO_RRIP_TSTAMP *p, size_t len, ISO_RRIP_ANALYZE *ana) { u_char *ptime; + u_int count; + + if (len < sizeof(*p)) + goto bad; + + count = 0; + if (*p->flags & ISO_SUSP_TSTAMP_CREAT) + count++; + if (*p->flags & ISO_SUSP_TSTAMP_MODIFY) + count++; + if (*p->flags & ISO_SUSP_TSTAMP_ACCESS) + count++; + if (*p->flags & ISO_SUSP_TSTAMP_ATTR) + count++; + if (*p->flags & ISO_SUSP_TSTAMP_FORM17) + count *= 17; + else + count *= 7; + if (offsetof(ISO_RRIP_TSTAMP, time) + count > len) + goto bad; ptime = p->time; @@ -374,6 +422,10 @@ cd9660_rrip_tstamp(ISO_RRIP_TSTAMP *p, ISO_RRIP_ANALYZE *ana) } ana->fields &= ~ISO_SUSP_TSTAMP; return (ISO_SUSP_TSTAMP); + +bad: + ana->error = true; + return (0); } static void @@ -387,10 +439,15 @@ cd9660_rrip_deftstamp(struct iso_directory_record *isodir, * POSIX device modes */ static int -cd9660_rrip_device(ISO_RRIP_DEVICE *p, ISO_RRIP_ANALYZE *ana) +cd9660_rrip_device(ISO_RRIP_DEVICE *p, size_t len, ISO_RRIP_ANALYZE *ana) { u_int high, low; + if (len < sizeof(*p)) { + ana->error = true; + return (0); + } + high = isonum_733(p->dev_t_high); low = isonum_733(p->dev_t_low); @@ -406,12 +463,17 @@ cd9660_rrip_device(ISO_RRIP_DEVICE *p, ISO_RRIP_ANALYZE *ana) * Flag indicating */ static int -cd9660_rrip_idflag(ISO_RRIP_IDFLAG *p, ISO_RRIP_ANALYZE *ana) +cd9660_rrip_idflag(ISO_RRIP_IDFLAG *p, size_t len, ISO_RRIP_ANALYZE *ana) { + if (len < sizeof(*p)) { + ana->error = true; + return (0); + } + ana->fields &= isonum_711(p->flags) | ~0xff; /* don't touch high bits */ /* special handling of RE field */ if (ana->fields & ISO_SUSP_RELDIR) - return (cd9660_rrip_reldir(/* XXX */ (ISO_RRIP_RELDIR *)p, ana)); + return (cd9660_rrip_reldir(/* XXX */ (ISO_RRIP_RELDIR *)p, len, ana)); return (ISO_SUSP_IDFLAG); } @@ -420,8 +482,13 @@ cd9660_rrip_idflag(ISO_RRIP_IDFLAG *p, ISO_RRIP_ANALYZE *ana) * Continuation pointer */ static int -cd9660_rrip_cont(ISO_RRIP_CONT *p, ISO_RRIP_ANALYZE *ana) +cd9660_rrip_cont(ISO_RRIP_CONT *p, size_t len, ISO_RRIP_ANALYZE *ana) { + if (len < sizeof(*p)) { + ana->error = true; + return (0); + } + ana->iso_ce_blk = isonum_733(p->location); ana->iso_ce_off = isonum_733(p->offset); ana->iso_ce_len = isonum_733(p->length); @@ -432,7 +499,7 @@ cd9660_rrip_cont(ISO_RRIP_CONT *p, ISO_RRIP_ANALYZE *ana) * System Use end */ static int -cd9660_rrip_stop(ISO_SUSP_HEADER *p, ISO_RRIP_ANALYZE *ana) +cd9660_rrip_stop(ISO_SUSP_HEADER *p, size_t len, ISO_RRIP_ANALYZE *ana) { return (ISO_SUSP_STOP); } @@ -441,11 +508,18 @@ cd9660_rrip_stop(ISO_SUSP_HEADER *p, ISO_RRIP_ANALYZE *ana) * Extension reference */ static int -cd9660_rrip_extref(ISO_RRIP_EXTREF *p, ISO_RRIP_ANALYZE *ana) +cd9660_rrip_extref(ISO_RRIP_EXTREF *p, size_t plen, ISO_RRIP_ANALYZE *ana) { - size_t len = isonum_711(p->len_id); - char *data = (char *)(p + 1); + size_t len; + char *data; + + if (plen < sizeof(*p)) { + ana->error = true; + return (0); + } + len = isonum_711(p->len_id); + data = (char *)(p + 1); if ((len == 10 && memcmp(data, "RRIP_1991A", len) == 0) || (len == 10 && memcmp(data, "IEEE_P1282", len) == 0) || (len == 9 && memcmp(data, "IEEE_1282", len) == 0)) { @@ -490,6 +564,7 @@ cd9660_rrip_loop(struct iso_directory_record *isodir, ISO_RRIP_ANALYZE *ana, pend = (ISO_SUSP_HEADER *)((char *)isodir + isonum_711(isodir->length)); result = 0; + ana->error = false; while (1) { ana->iso_ce_len = 0; /* @@ -515,10 +590,18 @@ cd9660_rrip_loop(struct iso_directory_record *isodir, ISO_RRIP_ANALYZE *ana, for (ptable = table; ptable->func; ptable++) { if (phead->type[0] == ptable->type[0] && phead->type[1] == ptable->type[1]) { - result |= ptable->func(phead, ana); + result |= ptable->func(phead, + isonum_711(phead->length), + ana); break; } } + if (ana->error) { + *ana->outlen = 0; + result = 0; + goto error; + } + if (!ana->fields) break; } @@ -550,6 +633,7 @@ cd9660_rrip_loop(struct iso_directory_record *isodir, ISO_RRIP_ANALYZE *ana, } else break; } +error: if (bp) brelse(bp); /* diff --git a/sys/fs/cd9660/iso_rrip.h b/sys/fs/cd9660/iso_rrip.h index 5a75beb08d93..934a9f7bd2da 100644 --- a/sys/fs/cd9660/iso_rrip.h +++ b/sys/fs/cd9660/iso_rrip.h @@ -68,6 +68,7 @@ typedef struct { u_short *outlen; /* length of above */ u_short maxlen; /* maximum length of above */ int cont; /* continuation of above */ + bool error; /* parsing error occurred */ } ISO_RRIP_ANALYZE; struct iso_directory_record;