Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F160596335
D57136.id180309.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
10 KB
Referenced Files
None
Subscribers
None
D57136.id180309.diff
View Options
diff --git a/sys/fs/cd9660/cd9660_rrip.c b/sys/fs/cd9660/cd9660_rrip.c
--- a/sys/fs/cd9660/cd9660_rrip.c
+++ b/sys/fs/cd9660/cd9660_rrip.c
@@ -48,7 +48,7 @@
#include <fs/cd9660/cd9660_rrip.h>
#include <fs/cd9660/iso_rrip.h>
-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 @@
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 @@
* 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 @@
/*
* 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 @@
/* 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 @@
* 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 @@
/* 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 @@
* 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 @@
* 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 @@
}
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 @@
}
ana->fields &= ~ISO_SUSP_TSTAMP;
return (ISO_SUSP_TSTAMP);
+
+bad:
+ ana->error = true;
+ return (0);
}
static void
@@ -387,10 +439,15 @@
* 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 @@
* 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 @@
* 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 @@
* 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 @@
* 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 @@
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 @@
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 @@
} else
break;
}
+error:
if (bp)
brelse(bp);
/*
diff --git a/sys/fs/cd9660/iso_rrip.h b/sys/fs/cd9660/iso_rrip.h
--- a/sys/fs/cd9660/iso_rrip.h
+++ b/sys/fs/cd9660/iso_rrip.h
@@ -68,6 +68,7 @@
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;
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Jun 27, 1:04 AM (9 h, 59 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
34352499
Default Alt Text
D57136.id180309.diff (10 KB)
Attached To
Mode
D57136: cd9660: Add various length checks when parsing RRIP extensions
Attached
Detach File
Event Timeline
Log In to Comment