mirror of
https://github.com/moparisthebest/pacman
synced 2024-08-13 17:03:46 -04:00
Fix segfaults on opening invalid archive files
"invalid" in this case simply means files that may or may not be archives. Discovered via a `pacman -Sc` operation with delta files in the package cache directory, but can be triggered if any file is passed to `pacman -Ql` that isn't an archive, for instance, or if the sync database file is not an archive. Fix it up so we are more careful about calling archive_read_finish() only on archives that are valid and have not already been closed, and teach our archive open function to set the returned archive to NULL if we aren't going to be returning something valid anyway. Signed-off-by: Dan McGee <dan@archlinux.org>
This commit is contained in:
parent
6f9ab22fd8
commit
7f51ba99ae
@ -380,7 +380,7 @@ alpm_pkg_t *_alpm_pkg_load_internal(alpm_handle_t *handle,
|
|||||||
int ret, fd, config = 0;
|
int ret, fd, config = 0;
|
||||||
struct archive *archive;
|
struct archive *archive;
|
||||||
struct archive_entry *entry;
|
struct archive_entry *entry;
|
||||||
alpm_pkg_t *newpkg = NULL;
|
alpm_pkg_t *newpkg;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
size_t files_count = 0, files_size = 0;
|
size_t files_count = 0, files_size = 0;
|
||||||
alpm_file_t *files = NULL;
|
alpm_file_t *files = NULL;
|
||||||
@ -394,7 +394,7 @@ alpm_pkg_t *_alpm_pkg_load_internal(alpm_handle_t *handle,
|
|||||||
if(errno == ENOENT) {
|
if(errno == ENOENT) {
|
||||||
handle->pm_errno = ALPM_ERR_PKG_NOT_FOUND;
|
handle->pm_errno = ALPM_ERR_PKG_NOT_FOUND;
|
||||||
}
|
}
|
||||||
goto error;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
newpkg = _alpm_pkg_new();
|
newpkg = _alpm_pkg_new();
|
||||||
|
@ -391,7 +391,7 @@ static int sync_db_populate(alpm_db_t *db)
|
|||||||
{
|
{
|
||||||
const char *dbpath;
|
const char *dbpath;
|
||||||
size_t est_count;
|
size_t est_count;
|
||||||
int count = -1, fd;
|
int count, fd;
|
||||||
struct stat buf;
|
struct stat buf;
|
||||||
struct archive *archive;
|
struct archive *archive;
|
||||||
struct archive_entry *entry;
|
struct archive_entry *entry;
|
||||||
@ -412,13 +412,14 @@ static int sync_db_populate(alpm_db_t *db)
|
|||||||
fd = _alpm_open_archive(db->handle, dbpath, &buf,
|
fd = _alpm_open_archive(db->handle, dbpath, &buf,
|
||||||
&archive, ALPM_ERR_DB_OPEN);
|
&archive, ALPM_ERR_DB_OPEN);
|
||||||
if(fd < 0) {
|
if(fd < 0) {
|
||||||
goto cleanup;
|
return -1;
|
||||||
}
|
}
|
||||||
est_count = estimate_package_count(&buf, archive);
|
est_count = estimate_package_count(&buf, archive);
|
||||||
|
|
||||||
db->pkgcache = _alpm_pkghash_create(est_count);
|
db->pkgcache = _alpm_pkghash_create(est_count);
|
||||||
if(db->pkgcache == NULL) {
|
if(db->pkgcache == NULL) {
|
||||||
db->handle->pm_errno = ALPM_ERR_MEMORY;
|
db->handle->pm_errno = ALPM_ERR_MEMORY;
|
||||||
|
count = -1;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,6 +213,8 @@ size_t _alpm_strip_newline(char *str)
|
|||||||
* This takes care of creating the libarchive 'archive' struct, setting up
|
* This takes care of creating the libarchive 'archive' struct, setting up
|
||||||
* compression and format options, opening a file descriptor, setting up the
|
* compression and format options, opening a file descriptor, setting up the
|
||||||
* buffer size, and performing a stat on the path once opened.
|
* buffer size, and performing a stat on the path once opened.
|
||||||
|
* On error, no file descriptor is opened, and the archive pointer returned
|
||||||
|
* will be set to NULL.
|
||||||
* @param handle the context handle
|
* @param handle the context handle
|
||||||
* @param path the path of the archive to open
|
* @param path the path of the archive to open
|
||||||
* @param buf space for a stat buffer for the given path
|
* @param buf space for a stat buffer for the given path
|
||||||
@ -238,16 +240,13 @@ int _alpm_open_archive(alpm_handle_t *handle, const char *path,
|
|||||||
if(fd < 0) {
|
if(fd < 0) {
|
||||||
_alpm_log(handle, ALPM_LOG_ERROR,
|
_alpm_log(handle, ALPM_LOG_ERROR,
|
||||||
_("could not open file %s: %s\n"), path, strerror(errno));
|
_("could not open file %s: %s\n"), path, strerror(errno));
|
||||||
archive_read_finish(*archive);
|
goto error;
|
||||||
RET_ERR(handle, error, -1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(fstat(fd, buf) != 0) {
|
if(fstat(fd, buf) != 0) {
|
||||||
_alpm_log(handle, ALPM_LOG_ERROR,
|
_alpm_log(handle, ALPM_LOG_ERROR,
|
||||||
_("could not stat file %s: %s\n"), path, strerror(errno));
|
_("could not stat file %s: %s\n"), path, strerror(errno));
|
||||||
archive_read_finish(*archive);
|
goto error;
|
||||||
CLOSE(fd);
|
|
||||||
RET_ERR(handle, error, -1);
|
|
||||||
}
|
}
|
||||||
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
|
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
|
||||||
if(buf->st_blksize > ALPM_BUFFER_SIZE) {
|
if(buf->st_blksize > ALPM_BUFFER_SIZE) {
|
||||||
@ -258,12 +257,18 @@ int _alpm_open_archive(alpm_handle_t *handle, const char *path,
|
|||||||
if(archive_read_open_fd(*archive, fd, bufsize) != ARCHIVE_OK) {
|
if(archive_read_open_fd(*archive, fd, bufsize) != ARCHIVE_OK) {
|
||||||
_alpm_log(handle, ALPM_LOG_ERROR, _("could not open file %s: %s\n"),
|
_alpm_log(handle, ALPM_LOG_ERROR, _("could not open file %s: %s\n"),
|
||||||
path, archive_error_string(*archive));
|
path, archive_error_string(*archive));
|
||||||
archive_read_finish(*archive);
|
goto error;
|
||||||
CLOSE(fd);
|
|
||||||
RET_ERR(handle, error, -1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return fd;
|
return fd;
|
||||||
|
|
||||||
|
error:
|
||||||
|
archive_read_finish(*archive);
|
||||||
|
*archive = NULL;
|
||||||
|
if(fd >= 0) {
|
||||||
|
CLOSE(fd);
|
||||||
|
}
|
||||||
|
RET_ERR(handle, error, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Unpack a specific file in an archive.
|
/** Unpack a specific file in an archive.
|
||||||
|
Loading…
Reference in New Issue
Block a user