diff options
author | Alan Coopersmith <alan.coopersmith@oracle.com> | 2013-03-02 12:01:39 -0800 |
---|---|---|
committer | Alan Coopersmith <alan.coopersmith@oracle.com> | 2013-05-09 18:59:52 -0700 |
commit | 236b603d235dc264d1c6250dca09c745458a9088 (patch) | |
tree | a80d778be29d154b3da18286c877a790a4506f82 | |
parent | 076428918e6c35f66b9b55c3fa097ff06496d155 (diff) |
Unbounded recursion in GetDatabase() when parsing include files [CVE-2013-2004 1/2]
GetIncludeFile() can call GetDatabase() which can call GetIncludeFile()
which can call GetDatabase() which can call GetIncludeFile() ....
eventually causing recursive stack overflow and crash.
Easily reproduced with a resource file that #includes itself.
Limit is set to a include depth of 100 files, which should be enough
for all known use cases, but could be adjusted later if necessary.
Reported-by: Ilja Van Sprundel <ivansprundel@ioactive.com>
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
Reviewed-by: Matthieu Herrb <matthieu.herrb@laas.fr>
-rw-r--r-- | src/Xrm.c | 24 |
1 files changed, 15 insertions, 9 deletions
@@ -1088,13 +1088,15 @@ static void GetIncludeFile( | |||
1088 | XrmDatabase db, | 1088 | XrmDatabase db, |
1089 | _Xconst char *base, | 1089 | _Xconst char *base, |
1090 | _Xconst char *fname, | 1090 | _Xconst char *fname, |
1091 | int fnamelen); | 1091 | int fnamelen, |
1092 | int depth); | ||
1092 | 1093 | ||
1093 | static void GetDatabase( | 1094 | static void GetDatabase( |
1094 | XrmDatabase db, | 1095 | XrmDatabase db, |
1095 | _Xconst char *str, | 1096 | _Xconst char *str, |
1096 | _Xconst char *filename, | 1097 | _Xconst char *filename, |
1097 | Bool doall) | 1098 | Bool doall, |
1099 | int depth) | ||
1098 | { | 1100 | { |
1099 | char *rhs; | 1101 | char *rhs; |
1100 | char *lhs, lhs_s[DEF_BUFF_SIZE]; | 1102 | char *lhs, lhs_s[DEF_BUFF_SIZE]; |
@@ -1204,7 +1206,8 @@ static void GetDatabase( | |||
1204 | } while (c != '"' && !is_EOL(bits)); | 1206 | } while (c != '"' && !is_EOL(bits)); |
1205 | /* must have an ending " */ | 1207 | /* must have an ending " */ |
1206 | if (c == '"') | 1208 | if (c == '"') |
1207 | GetIncludeFile(db, filename, fname, str - len - fname); | 1209 | GetIncludeFile(db, filename, fname, str - len - fname, |
1210 | depth); | ||
1208 | } | 1211 | } |
1209 | } | 1212 | } |
1210 | /* spin to next newline */ | 1213 | /* spin to next newline */ |
@@ -1545,7 +1548,7 @@ XrmPutLineResource( | |||
1545 | { | 1548 | { |
1546 | if (!*pdb) *pdb = NewDatabase(); | 1549 | if (!*pdb) *pdb = NewDatabase(); |
1547 | _XLockMutex(&(*pdb)->linfo); | 1550 | _XLockMutex(&(*pdb)->linfo); |
1548 | GetDatabase(*pdb, line, (char *)NULL, False); | 1551 | GetDatabase(*pdb, line, (char *)NULL, False, 0); |
1549 | _XUnlockMutex(&(*pdb)->linfo); | 1552 | _XUnlockMutex(&(*pdb)->linfo); |
1550 | } | 1553 | } |
1551 | 1554 | ||
@@ -1557,7 +1560,7 @@ XrmGetStringDatabase( | |||
1557 | 1560 | ||
1558 | db = NewDatabase(); | 1561 | db = NewDatabase(); |
1559 | _XLockMutex(&db->linfo); | 1562 | _XLockMutex(&db->linfo); |
1560 | GetDatabase(db, data, (char *)NULL, True); | 1563 | GetDatabase(db, data, (char *)NULL, True, 0); |
1561 | _XUnlockMutex(&db->linfo); | 1564 | _XUnlockMutex(&db->linfo); |
1562 | return db; | 1565 | return db; |
1563 | } | 1566 | } |
@@ -1636,7 +1639,8 @@ GetIncludeFile( | |||
1636 | XrmDatabase db, | 1639 | XrmDatabase db, |
1637 | _Xconst char *base, | 1640 | _Xconst char *base, |
1638 | _Xconst char *fname, | 1641 | _Xconst char *fname, |
1639 | int fnamelen) | 1642 | int fnamelen, |
1643 | int depth) | ||
1640 | { | 1644 | { |
1641 | int len; | 1645 | int len; |
1642 | char *str; | 1646 | char *str; |
@@ -1644,6 +1648,8 @@ GetIncludeFile( | |||
1644 | 1648 | ||
1645 | if (fnamelen <= 0 || fnamelen >= BUFSIZ) | 1649 | if (fnamelen <= 0 || fnamelen >= BUFSIZ) |
1646 | return; | 1650 | return; |
1651 | if (depth >= MAXDBDEPTH) | ||
1652 | return; | ||
1647 | if (*fname != '/' && base && (str = strrchr(base, '/'))) { | 1653 | if (*fname != '/' && base && (str = strrchr(base, '/'))) { |
1648 | len = str - base + 1; | 1654 | len = str - base + 1; |
1649 | if (len + fnamelen >= BUFSIZ) | 1655 | if (len + fnamelen >= BUFSIZ) |
@@ -1657,7 +1663,7 @@ GetIncludeFile( | |||
1657 | } | 1663 | } |
1658 | if (!(str = ReadInFile(realfname))) | 1664 | if (!(str = ReadInFile(realfname))) |
1659 | return; | 1665 | return; |
1660 | GetDatabase(db, str, realfname, True); | 1666 | GetDatabase(db, str, realfname, True, depth + 1); |
1661 | Xfree(str); | 1667 | Xfree(str); |
1662 | } | 1668 | } |
1663 | 1669 | ||
@@ -1673,7 +1679,7 @@ XrmGetFileDatabase( | |||
1673 | 1679 | ||
1674 | db = NewDatabase(); | 1680 | db = NewDatabase(); |
1675 | _XLockMutex(&db->linfo); | 1681 | _XLockMutex(&db->linfo); |
1676 | GetDatabase(db, str, filename, True); | 1682 | GetDatabase(db, str, filename, True, 0); |
1677 | _XUnlockMutex(&db->linfo); | 1683 | _XUnlockMutex(&db->linfo); |
1678 | Xfree(str); | 1684 | Xfree(str); |
1679 | return db; | 1685 | return db; |
@@ -1697,7 +1703,7 @@ XrmCombineFileDatabase( | |||
1697 | } else | 1703 | } else |
1698 | db = NewDatabase(); | 1704 | db = NewDatabase(); |
1699 | _XLockMutex(&db->linfo); | 1705 | _XLockMutex(&db->linfo); |
1700 | GetDatabase(db, str, filename, True); | 1706 | GetDatabase(db, str, filename, True, 0); |
1701 | _XUnlockMutex(&db->linfo); | 1707 | _XUnlockMutex(&db->linfo); |
1702 | Xfree(str); | 1708 | Xfree(str); |
1703 | if (!override) | 1709 | if (!override) |