[pacman-dev] [PATCH] validate %FILEPATH% when parsing repo dbs

Allan McRae allan at archlinux.org
Wed May 8 23:29:26 EDT 2013


On 09/05/13 12:05, Simon Gomizelj wrote:
> Currently we make no effort to validate the %FILENAME% field in the
> repo db. This allows for relative paths to be considered valid.
> 
> A carefully crafted db entry with a malicious relative path,
> (e.g. `../../../../etc/passwd`) will cause pacman to to
> overwrite _any_ file on the target's machine.
> 
> Signed-off-by: Simon Gomizelj <simongmzlj at gmail.com>
> ---
>  lib/libalpm/be_sync.c | 31 +++++++++++++++++++++++++++++++
>  1 file changed, 31 insertions(+)
> 
> diff --git a/lib/libalpm/be_sync.c b/lib/libalpm/be_sync.c
> index 1cbe055..059c18a 100644
> --- a/lib/libalpm/be_sync.c
> +++ b/lib/libalpm/be_sync.c
> @@ -479,6 +479,34 @@ cleanup:
>  	return count;
>  }
>  
> +/* This function validates %FILENAME%. filename must be between 3 and
> + * PATH_MAX characters and cannot be contain a path */

I still do not understand the lower bound of 3.  Surely any file name is
fine - pacman/libarchive does not use the file name to determine
compression.

The file name also needs to be less than:
  PATH_MAX - strlen(dbpath) - strlen(rootpath)
or whatever those variables are called...  the root might already be in
dbpath.

> +static int _alpm_validate_filename(alpm_db_t *db, const char *pkgname,
> +		const char *filename)
> +{
> +	size_t len = strlen(filename);
> +
> +	if(len < 3) {
> +		errno = EINVAL;
> +		_alpm_log(db->handle, ALPM_LOG_ERROR, _("%s database is inconsistent: filename "
> +					"of package %s is too short\n"), db->treename, pkgname);
> +		return -1;
> +	} else if(len > PATH_MAX) {
> +		errno = EINVAL;
> +		db->handle->
> +		_alpm_log(db->handle, ALPM_LOG_ERROR, _("%s database is inconsistent: filename "
> +					"of package %s is too long\n"), db->treename, pkgname);
> +		return -1;
> +	} else if(memchr(filename, '/', len) != NULL) {
> +		errno = EINVAL;
> +		_alpm_log(db->handle, ALPM_LOG_ERROR, _("%s database is inconsistent: filename "
> +					"of package %s is illegal\n"), db->treename, pkgname);

Why "database is inconsistent"?   That does not really correspond to the
error we are checking.

> +		return -1;
> +	}
> +
> +	return 0;
> +}
> +
>  #define READ_NEXT() do { \
>  	if(_alpm_archive_fgets(archive, &buf) != ARCHIVE_OK) goto error; \
>  	line = buf.line; \
> @@ -558,6 +586,9 @@ static int sync_db_read(alpm_db_t *db, struct archive *archive,
>  				}
>  			} else if(strcmp(line, "%FILENAME%") == 0) {
>  				READ_AND_STORE(pkg->filename);
> +				if(_alpm_validate_filename(db, pkg->name, pkg->filename) < 0) {
> +					return -1;
> +				}
>  			} else if(strcmp(line, "%DESC%") == 0) {
>  				READ_AND_STORE(pkg->desc);
>  			} else if(strcmp(line, "%GROUPS%") == 0) {
> 



More information about the pacman-dev mailing list