Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
Simplify a bit the internal API by always trying to use fd
Baptiste Daroussin committed 9 years ago
commit 8efc943ec6db606108febe7b2d858f6bba17c7af
parent 7ea4379
7 files changed +72 -115
modified libpkg/pkg_repo.c
@@ -513,7 +513,7 @@ pkg_repo_parse_sigkeys(const char *in, int inlen, struct sig_cert **sc)

static int
pkg_repo_archive_extract_archive(int fd, const char *file,
-
    const char *dest, struct pkg_repo *repo, int dest_fd,
+
    struct pkg_repo *repo, int dest_fd,
    struct sig_cert **signatures)
{
	struct sig_cert *sc = NULL, *s;
@@ -531,23 +531,7 @@ pkg_repo_archive_extract_archive(int fd, const char *file,

	cbdata.afd = fd;
	cbdata.fname = file;
-
	if (dest_fd != -1) {
-
		cbdata.tfd = dest_fd;
-
	}
-
	else if (dest != NULL) {
-
		cbdata.tfd = open (dest, O_WRONLY | O_CREAT | O_TRUNC,
-
				0644);
-
		if (cbdata.tfd == -1) {
-
			pkg_emit_errno("archive_read_extract", "open error");
-
			rc = EPKG_FATAL;
-
			goto cleanup;
-
		}
-
		fchown (fd, 0, 0);
-
	}
-
	else {
-
		pkg_emit_error("internal error: both fd and name are invalid");
-
		return (EPKG_FATAL);
-
	}
+
	cbdata.tfd = dest_fd;

	if (pkg_repo_signature_type(repo) == SIG_PUBKEY) {
		cbdata.need_sig = true;
@@ -592,7 +576,6 @@ pkg_repo_archive_extract_archive(int fd, const char *file,
	if (dest_fd != -1)
		(void)lseek(dest_fd, 0, SEEK_SET);

-
cleanup:
	if (rc == EPKG_OK) {
		if (signatures != NULL)
			*signatures = sc;
@@ -603,22 +586,19 @@ cleanup:
		pkg_repo_signatures_free(sc);
	}

-
	if (rc != EPKG_OK)
-
		unlink(dest);
-

	return rc;
}

static int
pkg_repo_archive_extract_check_archive(int fd, const char *file,
-
    const char *dest, struct pkg_repo *repo, int dest_fd)
+
    struct pkg_repo *repo, int dest_fd)
{
	struct sig_cert *sc = NULL, *s, *stmp;
	int ret, rc;

	ret = rc = EPKG_OK;

-
	if (pkg_repo_archive_extract_archive(fd, file, dest, repo, dest_fd, &sc)
+
	if (pkg_repo_archive_extract_archive(fd, file, repo, dest_fd, &sc)
			!= EPKG_OK)
		return (EPKG_FATAL);

@@ -627,13 +607,13 @@ pkg_repo_archive_extract_check_archive(int fd, const char *file,
			pkg_emit_error("No PUBKEY defined. Removing "
			    "repository.");
			rc = EPKG_FATAL;
-
			goto cleanup;
+
			goto out;
		}
		if (sc == NULL) {
			pkg_emit_error("No signature found in the repository.  "
					"Can not validate against %s key.", pkg_repo_key(repo));
			rc = EPKG_FATAL;
-
			goto cleanup;
+
			goto out;
		}
		/*
		 * Here are dragons:
@@ -642,18 +622,18 @@ pkg_repo_archive_extract_check_archive(int fd, const char *file,
		 *
		 * by @bdrewery
		 */
-
		ret = rsa_verify(dest, pkg_repo_key(repo), sc->sig, sc->siglen - 1,
-
				dest_fd);
+
		ret = rsa_verify(pkg_repo_key(repo), sc->sig, sc->siglen - 1,
+
		    dest_fd);
		if (ret != EPKG_OK) {
			pkg_emit_error("Invalid signature, "
					"removing repository.");
			rc = EPKG_FATAL;
-
			goto cleanup;
+
			goto out;
		}
	}
	else if (pkg_repo_signature_type(repo) == SIG_FINGERPRINT) {
		HASH_ITER(hh, sc, s, stmp) {
-
			ret = rsa_verify_cert(dest, s->cert, s->certlen, s->sig, s->siglen,
+
			ret = rsa_verify_cert(NULL, s->cert, s->certlen, s->sig, s->siglen,
				dest_fd);
			if (ret == EPKG_OK && s->trusted) {
				break;
@@ -664,14 +644,11 @@ pkg_repo_archive_extract_check_archive(int fd, const char *file,
			pkg_emit_error("No trusted certificate has been used "
			    "to sign the repository");
			rc = EPKG_FATAL;
-
			goto cleanup;
+
			goto out;
		}
	}

-
cleanup:
-
	if (rc != EPKG_OK && dest != NULL)
-
		unlink(dest);
-

+
out:
	return rc;
}

@@ -704,7 +681,7 @@ pkg_repo_fetch_remote_extract_fd(struct pkg_repo *repo, const char *filename,
	}

	(void)unlink(tmp);
-
	if (pkg_repo_archive_extract_check_archive(fd, filename, NULL, repo, dest_fd)
+
	if (pkg_repo_archive_extract_check_archive(fd, filename, repo, dest_fd)
			!= EPKG_OK) {
		*rc = EPKG_FATAL;
		close(dest_fd);
@@ -794,29 +771,27 @@ pkg_repo_fetch_meta(struct pkg_repo *repo, time_t *t)
	char filepath[MAXPATHLEN];
	struct pkg_repo_meta *nmeta;
	struct stat st;
-
	const char *dbdir = NULL;
	unsigned char *map = NULL;
-
	int fd;
+
	int fd, dbdirfd, metafd;
	int rc = EPKG_OK, ret;
	struct sig_cert *sc = NULL, *s, *stmp;
	struct pkg_repo_check_cbdata cbdata;

-
	dbdir = pkg_object_string(pkg_config_get("PKG_DBDIR"));
-

+
	dbdirfd = pkg_get_dbdirfd();
	fd = pkg_repo_fetch_remote_tmp(repo, "meta", "txz", t, &rc);
	if (fd == -1)
		return (rc);

-
	snprintf(filepath, sizeof(filepath), "%s/%s.meta", dbdir, pkg_repo_name(repo));
+
	snprintf(filepath, sizeof(filepath), "%s.meta", pkg_repo_name(repo));

-
	/* Remove old metafile */
-
	if (unlink (filepath) == -1 && errno != ENOENT) {
+
	metafd = openat(dbdirfd, filepath, O_RDWR|O_CREAT|O_TRUNC, 0644);
+
	if (metafd == -1) {
		close(fd);
-
		return (EPKG_FATAL);
+
		return (rc);
	}

	if (pkg_repo_signature_type(repo) == SIG_PUBKEY) {
-
		if ((rc = pkg_repo_archive_extract_check_archive(fd, "meta", filepath, repo, -1)) != EPKG_OK) {
+
		if ((rc = pkg_repo_archive_extract_check_archive(fd, "meta", repo, metafd)) != EPKG_OK) {
			close (fd);
			return (rc);
		}
@@ -829,11 +804,14 @@ pkg_repo_fetch_meta(struct pkg_repo *repo, time_t *t)
	 * a corresponding key from meta file.
	 */

-
	if ((rc = pkg_repo_archive_extract_archive(fd, "meta", filepath, repo, -1, &sc)) != EPKG_OK) {
+
	if ((rc = pkg_repo_archive_extract_archive(fd, "meta", repo,
+
	    metafd, &sc)) != EPKG_OK) {
+
		close(metafd);
+
		unlinkat(dbdirfd, filepath, 0);
		close (fd);
		return (rc);
	}
-

+
	close(metafd);
	close(fd);

	if (repo->signature_type == SIG_FINGERPRINT && repo->trusted_fp == NULL) {
@@ -842,20 +820,19 @@ pkg_repo_fetch_meta(struct pkg_repo *repo, time_t *t)
	}

	/* Map meta file for extracting pubkeys from it */
-
	if ((fd = open(filepath, O_RDONLY)) == -1) {
+
	if ((metafd = openat(dbdirfd, filepath, O_RDONLY)) == -1) {
		pkg_emit_errno("pkg_repo_fetch_meta", "cannot open meta fetched");
		rc = EPKG_FATAL;
		goto cleanup;
	}

-
	if (fstat(fd, &st) == -1) {
+
	if (fstat(metafd, &st) == -1) {
		pkg_emit_errno("pkg_repo_fetch_meta", "cannot stat meta fetched");
		rc = EPKG_FATAL;
		goto cleanup;
	}

	map = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
-
	close(fd);
	if (map == MAP_FAILED) {
		pkg_emit_errno("pkg_repo_fetch_meta", "cannot mmap meta fetched");
		rc = EPKG_FATAL;
@@ -886,8 +863,8 @@ pkg_repo_fetch_meta(struct pkg_repo *repo, time_t *t)
		}

		HASH_ITER(hh, sc, s, stmp) {
-
			ret = rsa_verify_cert(filepath, s->cert, s->certlen, s->sig, s->siglen,
-
				-1);
+
			ret = rsa_verify_cert(NULL, s->cert, s->certlen, s->sig, s->siglen,
+
				metafd);
			if (ret == EPKG_OK && s->trusted)
				break;

@@ -902,7 +879,7 @@ pkg_repo_fetch_meta(struct pkg_repo *repo, time_t *t)
	}

load_meta:
-
	if ((rc = pkg_repo_meta_load(filepath, &nmeta)) != EPKG_OK) {
+
	if ((rc = pkg_repo_meta_load(metafd, &nmeta)) != EPKG_OK) {
		if (map != NULL)
			munmap(map, st.st_size);

@@ -922,7 +899,7 @@ cleanup:
		pkg_repo_signatures_free(sc);

	if (rc != EPKG_OK)
-
		unlink(filepath);
+
		unlinkat(dbdirfd, filepath, 0);

	return (rc);
}
modified libpkg/pkg_repo_create.c
@@ -539,12 +539,18 @@ pkg_create_repo(char *path, const char *output_dir, bool filelist,
	}

	if (metafile != NULL) {
-
		if (pkg_repo_meta_load(metafile, &meta) != EPKG_OK) {
+
		fd = open(metafile, O_RDONLY);
+
		if (fd == -1) {
			pkg_emit_error("meta loading error while trying %s", metafile);
			return (EPKG_FATAL);
		}
-
	}
-
	else {
+
		if (pkg_repo_meta_load(fd, &meta) != EPKG_OK) {
+
			pkg_emit_error("meta loading error while trying %s", metafile);
+
			close(fd);
+
			return (EPKG_FATAL);
+
		}
+
		close(fd);
+
	} else {
		meta = pkg_repo_meta_default();
	}

@@ -913,7 +919,7 @@ pkg_finish_repo(const char *output_dir, pkg_password_cb *password_cb,
	struct rsa_key *rsa = NULL;
	struct pkg_repo_meta *meta;
	struct stat st;
-
	int ret = EPKG_OK, nfile = 0;
+
	int ret = EPKG_OK, nfile = 0, fd;
	const int files_to_pack = 4;
	bool legacy = false;

@@ -942,13 +948,13 @@ pkg_finish_repo(const char *output_dir, pkg_password_cb *password_cb,
	/*
	 * If no meta is defined, then it is a legacy repo
	 */
-
	if (access(repo_path, R_OK) != -1) {
-
		if (pkg_repo_meta_load(repo_path, &meta) != EPKG_OK) {
+
	if ((fd = open(repo_path, O_RDONLY)) != -1) {
+
		if (pkg_repo_meta_load(fd, &meta) != EPKG_OK) {
			pkg_emit_error("meta loading error while trying %s", repo_path);
			rsa_free(rsa);
+
			close(fd);
			return (EPKG_FATAL);
-
		}
-
		else {
+
		} else {
			meta = pkg_repo_meta_default();
		}
		if (pkg_repo_pack_db(repo_meta_file, repo_path, repo_path, rsa, meta,
modified libpkg/pkg_repo_meta.c
@@ -247,7 +247,7 @@ pkg_repo_meta_version(ucl_object_t *top)
}

int
-
pkg_repo_meta_load(const char *file, struct pkg_repo_meta **target)
+
pkg_repo_meta_load(const int fd, struct pkg_repo_meta **target)
{
	struct ucl_parser *parser;
	ucl_object_t *top, *schema;
@@ -256,8 +256,8 @@ pkg_repo_meta_load(const char *file, struct pkg_repo_meta **target)

	parser = ucl_parser_new(UCL_PARSER_KEY_LOWERCASE);

-
	if (!ucl_parser_add_file(parser, file)) {
-
		pkg_emit_error("cannot parse repository meta from %s: %s", file,
+
	if (!ucl_parser_add_fd(parser, fd)) {
+
		pkg_emit_error("cannot parse repository meta: %s",
				ucl_parser_get_error(parser));
		ucl_parser_free(parser);
		return (EPKG_FATAL);
@@ -268,7 +268,7 @@ pkg_repo_meta_load(const char *file, struct pkg_repo_meta **target)

	version = pkg_repo_meta_version(top);
	if (version == -1) {
-
		pkg_emit_error("repository meta %s has wrong version or wrong format", file);
+
		pkg_emit_error("repository meta has wrong version or wrong format");
		ucl_object_unref(top);
		return (EPKG_FATAL);
	}
@@ -279,14 +279,14 @@ pkg_repo_meta_load(const char *file, struct pkg_repo_meta **target)

		if (schema != NULL) {
			if (!ucl_object_validate(schema, top, &err)) {
-
				pkg_emit_error("repository meta %s cannot be validated: %s", file, err.msg);
+
				pkg_emit_error("repository meta cannot be validated: %s", err.msg);
				ucl_object_unref(top);
				return (EPKG_FATAL);
			}
		}
	}
	else {
-
		pkg_emit_error("repository meta %s has wrong version %d", file, version);
+
		pkg_emit_error("repository meta has wrong version %d", version);
		ucl_object_unref(top);
		return (EPKG_FATAL);
	}
modified libpkg/private/pkg.h
@@ -643,7 +643,7 @@ int pkg_repo_fetch_remote_extract_fd(struct pkg_repo *repo,
int pkg_repo_fetch_meta(struct pkg_repo *repo, time_t *t);

struct pkg_repo_meta *pkg_repo_meta_default(void);
-
int pkg_repo_meta_load(const char *file, struct pkg_repo_meta **target);
+
int pkg_repo_meta_load(const int fd, struct pkg_repo_meta **target);
void pkg_repo_meta_free(struct pkg_repo_meta *meta);
ucl_object_t * pkg_repo_meta_to_ucl(struct pkg_repo_meta *meta);
bool pkg_repo_meta_is_special_file(const char *file, struct pkg_repo_meta *meta);
modified libpkg/private/utils.h
@@ -73,8 +73,7 @@ int is_dir(const char *);
int rsa_new(struct rsa_key **, pkg_password_cb *, char *path);
void rsa_free(struct rsa_key *);
int rsa_sign(char *path, struct rsa_key *rsa, unsigned char **sigret, unsigned int *siglen);
-
int rsa_verify(const char *path, const char *key,
-
		unsigned char *sig, unsigned int sig_len, int fd);
+
int rsa_verify(const char *key, unsigned char *sig, unsigned int sig_len, int fd);
int rsa_verify_cert(const char *path, unsigned char *cert,
    int certlen, unsigned char *sig, int sig_len, int fd);

modified libpkg/repo/binary/init.c
@@ -26,6 +26,7 @@

#include <assert.h>
#include <errno.h>
+
#include <fcntl.h>
#include <regex.h>
#include <grp.h>
#include <stdlib.h>
@@ -297,37 +298,37 @@ int
pkg_repo_binary_open(struct pkg_repo *repo, unsigned mode)
{
	char filepath[MAXPATHLEN];
-
	const char *dbdir = NULL;
	sqlite3 *sqlite = NULL;
-
	int flags;
+
	int flags, dbdirfd, fd;
	int64_t res;
	struct pkg_repo_it *it;
	struct pkg *pkg = NULL;

-
	dbdir = pkg_object_string(pkg_config_get("PKG_DBDIR"));
	sqlite3_initialize();

	pkgdb_setup_lock();
	pkgdb_syscall_overload();

-
	snprintf(filepath, sizeof(filepath), "%s/%s.meta",
-
		dbdir, pkg_repo_name(repo));
+
	dbdirfd = pkg_get_dbdirfd();
+
	snprintf(filepath, sizeof(filepath), "%s.meta", pkg_repo_name(repo));

	/* Open metafile */
-
	if (access(filepath, R_OK) != -1) {
-
		if (pkg_repo_meta_load(filepath, &repo->meta) != EPKG_OK) {
+
	if ((fd = openat(dbdirfd, filepath, O_RDONLY)) != -1) {
+
		if (pkg_repo_meta_load(fd, &repo->meta) != EPKG_OK) {
			pkg_emit_error("Repository %s load error: "
					"meta cannot be loaded %s", pkg_repo_name(repo),
					strerror(errno));
+
			close(fd);
			return (EPKG_FATAL);
		}
+
		close(fd);
	}

-
	snprintf(filepath, sizeof(filepath), "%s/%s",
-
		dbdir, pkg_repo_binary_get_filename(pkg_repo_name(repo)));
+
	snprintf(filepath, sizeof(filepath), "%s",
+
		pkg_repo_binary_get_filename(pkg_repo_name(repo)));

	/* Always want read mode here */
-
	if (access(filepath, R_OK | mode) != 0) {
+
	if (faccessat(dbdirfd, filepath, R_OK | mode, 0) != 0) {
		pkg_emit_error("Repository %s load error: "
				"access repo file(%s) failed: %s", pkg_repo_name(repo),
				filepath,
@@ -411,37 +412,20 @@ int
pkg_repo_binary_create(struct pkg_repo *repo)
{
	char filepath[MAXPATHLEN];
-
	const char *dbdir = NULL;
	sqlite3 *sqlite = NULL;
-
	int retcode;
+
	int retcode, dbdirfd;

	sqlite3_initialize();
-
	dbdir = pkg_object_string(pkg_config_get("PKG_DBDIR"));

-
	snprintf(filepath, sizeof(filepath), "%s/%s",
-
		dbdir, pkg_repo_binary_get_filename(pkg_repo_name(repo)));
+
	dbdirfd = pkg_get_dbdirfd();
+
	snprintf(filepath, sizeof(filepath), "%s",
+
		pkg_repo_binary_get_filename(pkg_repo_name(repo)));
	/* Should never ever happen */
-
	if (access(filepath, R_OK) == 0)
+
	if (faccessat(dbdirfd, filepath, R_OK, 0) == 0)
		return (EPKG_CONFLICT);

-
	/*
-
	 * Fall back on unix-dotfile locking strategy if on a network filesystem
-
	 */
-
#if defined(HAVE_SYS_STATVFS_H) && defined(ST_LOCAL)
-
	struct statvfs stfs;
-

-
	if (statvfs(dbdir, &stfs) == 0) {
-
		if ((stfs.f_flag & ST_LOCAL) != ST_LOCAL)
-
			sqlite3_vfs_register(sqlite3_vfs_find("unix-dotfile"), 1);
-
	}
-
#elif defined(HAVE_STATFS) && defined(MNT_LOCAL)
-
	struct statfs stfs;
-

-
	if (statfs(dbdir, &stfs) == 0) {
-
		if ((stfs.f_flags & MNT_LOCAL) != MNT_LOCAL)
-
			sqlite3_vfs_register(sqlite3_vfs_find("unix-dotfile"), 1);
-
	}
-
#endif
+
	pkgdb_setup_lock();
+
	pkgdb_syscall_overload();

	/* Open for read/write/create */
	if (sqlite3_open(filepath, &sqlite) != SQLITE_OK)
modified libpkg/rsa.c
@@ -201,8 +201,7 @@ rsa_verify_cb(int fd, void *ud)
}

int
-
rsa_verify(const char *path, const char *key, unsigned char *sig,
-
    unsigned int sig_len, int fd)
+
rsa_verify(const char *key, unsigned char *sig, unsigned int sig_len, int fd)
{
	int ret;
	bool need_close = false;
@@ -215,14 +214,6 @@ rsa_verify(const char *path, const char *key, unsigned char *sig,
		return (EPKG_FATAL);
	}

-
	if (fd == -1) {
-
		if ((fd = open(path, O_RDONLY)) == -1) {
-
			pkg_emit_errno("fopen", path);
-
			free(key_buf);
-
			return (EPKG_FATAL);
-
		}
-
		need_close = true;
-
	}
	(void)lseek(fd, 0, SEEK_SET);

	cbdata.key = key_buf;