io, db: id cache should be specific to database root, not system root
Otherwise we end up using wrong uid/gid mappings when doing install to alternate system root. Fixes #434.cute-signatures
parent
a31948ae26
commit
19419f1a88
|
@ -248,7 +248,6 @@ int main(int argc, char **argv)
|
|||
memset(&dbopts, 0, sizeof(dbopts));
|
||||
list_init(&dbopts.repository_list);
|
||||
umask(0);
|
||||
apk_id_cache_init();
|
||||
|
||||
applet = deduce_applet(argc, argv);
|
||||
num_options = ARRAY_SIZE(generic_options) + 1;
|
||||
|
@ -370,7 +369,6 @@ int main(int argc, char **argv)
|
|||
|
||||
r = applet->main(ctx, &db, argc, argv);
|
||||
apk_db_close(&db);
|
||||
apk_id_cache_free();
|
||||
|
||||
if (r == -EINVAL)
|
||||
return usage(applet);
|
||||
|
|
|
@ -22,7 +22,7 @@ typedef int (*apk_archive_entry_parser)(void *ctx,
|
|||
|
||||
int apk_tar_parse(struct apk_istream *,
|
||||
apk_archive_entry_parser parser, void *ctx,
|
||||
int soft_checksums);
|
||||
int soft_checksums, struct apk_id_cache *);
|
||||
int apk_tar_write_entry(struct apk_ostream *, const struct apk_file_info *ae,
|
||||
const char *data);
|
||||
int apk_tar_write_padding(struct apk_ostream *, const struct apk_file_info *ae);
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "apk_hash.h"
|
||||
#include "apk_archive.h"
|
||||
#include "apk_package.h"
|
||||
#include "apk_io.h"
|
||||
|
||||
#define APK_MAX_REPOS 32
|
||||
#define APK_CACHE_CSUM_BYTES 4
|
||||
|
@ -109,6 +110,7 @@ struct apk_database {
|
|||
struct apk_dependency_array *world;
|
||||
struct apk_string_array *protected_paths;
|
||||
struct apk_repository repos[APK_MAX_REPOS];
|
||||
struct apk_id_cache id_cache;
|
||||
|
||||
struct {
|
||||
struct apk_hash names;
|
||||
|
|
18
src/apk_io.h
18
src/apk_io.h
|
@ -15,6 +15,14 @@
|
|||
|
||||
#include "apk_defines.h"
|
||||
#include "apk_blob.h"
|
||||
#include "apk_hash.h"
|
||||
|
||||
struct apk_id_cache {
|
||||
int root_fd;
|
||||
unsigned int genid;
|
||||
struct apk_hash uid_cache;
|
||||
struct apk_hash gid_cache;
|
||||
};
|
||||
|
||||
struct apk_file_info {
|
||||
char *name;
|
||||
|
@ -95,10 +103,10 @@ int apk_file_get_info(int atfd, const char *filename, unsigned int flags,
|
|||
int apk_url_download(const char *url, int atfd, const char *file);
|
||||
const char *apk_url_local_file(const char *url);
|
||||
|
||||
void apk_id_cache_init(void);
|
||||
void apk_id_cache_free(void);
|
||||
void apk_id_cache_reset(void);
|
||||
uid_t apk_resolve_uid(const char *username, uid_t default_uid);
|
||||
uid_t apk_resolve_gid(const char *groupname, uid_t default_gid);
|
||||
void apk_id_cache_init(struct apk_id_cache *idc, int root_fd);
|
||||
void apk_id_cache_free(struct apk_id_cache *idc);
|
||||
void apk_id_cache_reset(struct apk_id_cache *idc);
|
||||
uid_t apk_resolve_uid(struct apk_id_cache *idc, const char *username, uid_t default_uid);
|
||||
uid_t apk_resolve_gid(struct apk_id_cache *idc, const char *groupname, uid_t default_gid);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -143,8 +143,9 @@ void apk_pkg_uninstall(struct apk_database *db, struct apk_package *pkg);
|
|||
int apk_ipkg_add_script(struct apk_installed_package *ipkg,
|
||||
struct apk_istream *is,
|
||||
unsigned int type, unsigned int size);
|
||||
int apk_ipkg_run_script(struct apk_installed_package *ipkg, int root_fd,
|
||||
unsigned int type, char **argv);
|
||||
int apk_ipkg_run_script(struct apk_installed_package *ipkg,
|
||||
struct apk_database *db,
|
||||
unsigned int type, char **argv);
|
||||
|
||||
struct apk_package *apk_pkg_parse_index_entry(struct apk_database *db, apk_blob_t entry);
|
||||
int apk_pkg_write_index_entry(struct apk_package *pkg, struct apk_ostream *os);
|
||||
|
|
|
@ -117,7 +117,7 @@ static void tar_entry_close(void *stream)
|
|||
}
|
||||
|
||||
int apk_tar_parse(struct apk_istream *is, apk_archive_entry_parser parser,
|
||||
void *ctx, int soft_checksums)
|
||||
void *ctx, int soft_checksums, struct apk_id_cache *idc)
|
||||
{
|
||||
struct apk_file_info entry;
|
||||
struct apk_tar_entry_istream teis = {
|
||||
|
@ -146,8 +146,8 @@ int apk_tar_parse(struct apk_istream *is, apk_archive_entry_parser parser,
|
|||
|
||||
entry = (struct apk_file_info){
|
||||
.size = GET_OCTAL(buf.size),
|
||||
.uid = apk_resolve_uid(buf.uname, GET_OCTAL(buf.uid)),
|
||||
.gid = apk_resolve_gid(buf.gname, GET_OCTAL(buf.gid)),
|
||||
.uid = apk_resolve_uid(idc, buf.uname, GET_OCTAL(buf.uid)),
|
||||
.gid = apk_resolve_gid(idc, buf.gname, GET_OCTAL(buf.gid)),
|
||||
.mode = GET_OCTAL(buf.mode) & 07777,
|
||||
.mtime = GET_OCTAL(buf.mtime),
|
||||
.name = entry.name,
|
||||
|
|
|
@ -472,7 +472,7 @@ int apk_cache_download(struct apk_database *db, const char *url,
|
|||
apk_bstream_from_file(db->cachetmp_fd, cacheitem),
|
||||
apk_sign_ctx_mpart_cb, &sctx);
|
||||
|
||||
r = apk_tar_parse(is, apk_sign_ctx_verify_tar, &sctx, FALSE);
|
||||
r = apk_tar_parse(is, apk_sign_ctx_verify_tar, &sctx, FALSE, &db->id_cache);
|
||||
is->close(is);
|
||||
apk_sign_ctx_free(&sctx);
|
||||
if (r != 0) {
|
||||
|
@ -916,7 +916,7 @@ static int apk_db_read_state(struct apk_database *db, int flags)
|
|||
is = apk_istream_from_file(db->root_fd, "var/lib/apk/scripts.tar");
|
||||
if (is != NULL) {
|
||||
apk_tar_parse(is, apk_read_script_archive_entry, db,
|
||||
FALSE);
|
||||
FALSE, &db->id_cache);
|
||||
} else {
|
||||
is = apk_istream_from_file(db->root_fd, "var/lib/apk/scripts");
|
||||
if (is != NULL)
|
||||
|
@ -1177,6 +1177,8 @@ int apk_db_open(struct apk_database *db, struct apk_db_options *dbopts)
|
|||
goto ret_r;
|
||||
}
|
||||
|
||||
apk_id_cache_init(&db->id_cache, db->root_fd);
|
||||
|
||||
return rr;
|
||||
|
||||
ret_errno:
|
||||
|
@ -1266,6 +1268,8 @@ void apk_db_close(struct apk_database *db)
|
|||
struct hlist_node *dc, *dn;
|
||||
int i;
|
||||
|
||||
apk_id_cache_free(&db->id_cache);
|
||||
|
||||
list_for_each_entry(ipkg, &db->installed.packages, installed_pkgs_list) {
|
||||
hlist_for_each_entry_safe(diri, dc, dn, &ipkg->owned_dirs, pkg_dirs_list) {
|
||||
apk_db_diri_free(db, diri, APK_DISALLOW_RMDIR);
|
||||
|
@ -1343,7 +1347,7 @@ int apk_db_run_triggers(struct apk_database *db)
|
|||
continue;
|
||||
|
||||
*apk_string_array_add(&ipkg->pending_triggers) = NULL;
|
||||
apk_ipkg_run_script(ipkg, db->root_fd, APK_SCRIPT_TRIGGER,
|
||||
apk_ipkg_run_script(ipkg, db, APK_SCRIPT_TRIGGER,
|
||||
ipkg->pending_triggers->item);
|
||||
apk_string_array_free(&ipkg->pending_triggers);
|
||||
}
|
||||
|
@ -1520,7 +1524,7 @@ static int load_index(struct apk_database *db, struct apk_bstream *bs,
|
|||
ctx.found = 0;
|
||||
apk_sign_ctx_init(&ctx.sctx, APK_SIGN_VERIFY, NULL, db->keys_fd);
|
||||
is = apk_bstream_gunzip_mpart(bs, apk_sign_ctx_mpart_cb, &ctx.sctx);
|
||||
r = apk_tar_parse(is, load_apkindex, &ctx, FALSE);
|
||||
r = apk_tar_parse(is, load_apkindex, &ctx, FALSE, &db->id_cache);
|
||||
is->close(is);
|
||||
apk_sign_ctx_free(&ctx.sctx);
|
||||
if (ctx.found == 0)
|
||||
|
@ -1624,7 +1628,7 @@ static int apk_db_run_pending_script(struct install_ctx *ctx)
|
|||
return 0;
|
||||
|
||||
ctx->script_pending = FALSE;
|
||||
r = apk_ipkg_run_script(ctx->ipkg, ctx->db->root_fd, ctx->script,
|
||||
r = apk_ipkg_run_script(ctx->ipkg, ctx->db, ctx->script,
|
||||
ctx->script_args);
|
||||
if (r != 0)
|
||||
apk_error("%s-%s: Failed to execute "
|
||||
|
@ -2043,7 +2047,7 @@ static int apk_db_unpack_pkg(struct apk_database *db,
|
|||
apk_name_array_init(&ctx.replaces);
|
||||
apk_sign_ctx_init(&ctx.sctx, APK_SIGN_VERIFY_IDENTITY, &pkg->csum, db->keys_fd);
|
||||
tar = apk_bstream_gunzip_mpart(bs, apk_sign_ctx_mpart_cb, &ctx.sctx);
|
||||
r = apk_tar_parse(tar, apk_db_install_archive_entry, &ctx, TRUE);
|
||||
r = apk_tar_parse(tar, apk_db_install_archive_entry, &ctx, TRUE, &db->id_cache);
|
||||
apk_sign_ctx_free(&ctx.sctx);
|
||||
apk_name_array_free(&ctx.replaces);
|
||||
tar->close(tar);
|
||||
|
@ -2098,13 +2102,13 @@ int apk_db_install_pkg(struct apk_database *db,
|
|||
if (ipkg == NULL)
|
||||
return 0;
|
||||
|
||||
r = apk_ipkg_run_script(ipkg, db->root_fd,
|
||||
r = apk_ipkg_run_script(ipkg, db,
|
||||
APK_SCRIPT_PRE_DEINSTALL, script_args);
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
apk_db_purge_pkg(db, ipkg, NULL);
|
||||
r = apk_ipkg_run_script(ipkg, db->root_fd,
|
||||
r = apk_ipkg_run_script(ipkg, db,
|
||||
APK_SCRIPT_POST_DEINSTALL, script_args);
|
||||
apk_pkg_uninstall(db, oldpkg);
|
||||
|
||||
|
@ -2135,7 +2139,7 @@ int apk_db_install_pkg(struct apk_database *db,
|
|||
apk_pkg_uninstall(db, oldpkg);
|
||||
}
|
||||
|
||||
r = apk_ipkg_run_script(ipkg, db->root_fd,
|
||||
r = apk_ipkg_run_script(ipkg, db,
|
||||
(oldpkg == NULL) ?
|
||||
APK_SCRIPT_POST_INSTALL : APK_SCRIPT_POST_UPGRADE,
|
||||
script_args);
|
||||
|
|
88
src/io.c
88
src/io.c
|
@ -766,48 +766,55 @@ static struct cache_item *resolve_cache_item(struct apk_hash *hash, apk_blob_t n
|
|||
return ci;
|
||||
}
|
||||
|
||||
static unsigned int id_genid = 0;
|
||||
static struct apk_hash uid_cache, gid_cache;
|
||||
|
||||
void apk_id_cache_init(void)
|
||||
void apk_id_cache_init(struct apk_id_cache *idc, int root_fd)
|
||||
{
|
||||
apk_hash_init(&uid_cache, &id_hash_ops, 256);
|
||||
apk_hash_init(&gid_cache, &id_hash_ops, 256);
|
||||
id_genid = 1;
|
||||
idc->root_fd = root_fd;
|
||||
idc->genid = 1;
|
||||
apk_hash_init(&idc->uid_cache, &id_hash_ops, 256);
|
||||
apk_hash_init(&idc->gid_cache, &id_hash_ops, 256);
|
||||
}
|
||||
|
||||
void apk_id_cache_free(void)
|
||||
void apk_id_cache_free(struct apk_id_cache *idc)
|
||||
{
|
||||
apk_hash_free(&uid_cache);
|
||||
apk_hash_free(&gid_cache);
|
||||
apk_hash_free(&idc->uid_cache);
|
||||
apk_hash_free(&idc->gid_cache);
|
||||
}
|
||||
|
||||
void apk_id_cache_reset(void)
|
||||
void apk_id_cache_reset(struct apk_id_cache *idc)
|
||||
{
|
||||
id_genid++;
|
||||
if (id_genid == 0)
|
||||
id_genid = 1;
|
||||
idc->genid++;
|
||||
if (idc->genid == 0)
|
||||
idc->genid = 1;
|
||||
}
|
||||
|
||||
uid_t apk_resolve_uid(const char *username, uid_t default_uid)
|
||||
uid_t apk_resolve_uid(struct apk_id_cache *idc, const char *username, uid_t default_uid)
|
||||
{
|
||||
struct cache_item *ci;
|
||||
struct passwd pwent, *pwd;
|
||||
char buf[1024];
|
||||
int r;
|
||||
FILE *in;
|
||||
|
||||
ci = resolve_cache_item(&uid_cache, APK_BLOB_STR(username));
|
||||
ci = resolve_cache_item(&idc->uid_cache, APK_BLOB_STR(username));
|
||||
if (ci == NULL)
|
||||
return default_uid;
|
||||
|
||||
if (ci->genid != id_genid) {
|
||||
r = getpwnam_r(username, &pwent, buf, sizeof(buf), &pwd);
|
||||
if (pwd != NULL)
|
||||
ci->uid = pwd->pw_uid;
|
||||
else
|
||||
ci->uid = -1;
|
||||
if (r == 0)
|
||||
ci->genid = id_genid;
|
||||
if (ci->genid != idc->genid) {
|
||||
ci->genid = idc->genid;
|
||||
ci->uid = -1;
|
||||
|
||||
in = fdopen(openat(idc->root_fd, "etc/passwd", O_RDONLY|O_CLOEXEC), "r");
|
||||
if (in != NULL) {
|
||||
do {
|
||||
fgetpwent_r(in, &pwent, buf, sizeof(buf), &pwd);
|
||||
if (pwd == NULL)
|
||||
break;
|
||||
if (strcmp(pwd->pw_name, username) == 0) {
|
||||
ci->uid = pwd->pw_uid;
|
||||
break;
|
||||
}
|
||||
} while (1);
|
||||
fclose(in);
|
||||
}
|
||||
}
|
||||
|
||||
if (ci->uid != -1)
|
||||
|
@ -816,25 +823,34 @@ uid_t apk_resolve_uid(const char *username, uid_t default_uid)
|
|||
return default_uid;
|
||||
}
|
||||
|
||||
uid_t apk_resolve_gid(const char *groupname, uid_t default_gid)
|
||||
uid_t apk_resolve_gid(struct apk_id_cache *idc, const char *groupname, uid_t default_gid)
|
||||
{
|
||||
struct cache_item *ci;
|
||||
struct group grent, *grp;
|
||||
char buf[1024];
|
||||
int r;
|
||||
FILE *in;
|
||||
|
||||
ci = resolve_cache_item(&gid_cache, APK_BLOB_STR(groupname));
|
||||
ci = resolve_cache_item(&idc->gid_cache, APK_BLOB_STR(groupname));
|
||||
if (ci == NULL)
|
||||
return default_gid;
|
||||
|
||||
if (ci->genid != id_genid) {
|
||||
r = getgrnam_r(groupname, &grent, buf, sizeof(buf), &grp);
|
||||
if (grp != NULL)
|
||||
ci->gid = grp->gr_gid;
|
||||
else
|
||||
ci->gid = -1;
|
||||
if (r == 0)
|
||||
ci->genid = id_genid;
|
||||
if (ci->genid != idc->genid) {
|
||||
ci->genid = idc->genid;
|
||||
ci->gid = -1;
|
||||
|
||||
in = fdopen(openat(idc->root_fd, "etc/passwd", O_RDONLY|O_CLOEXEC), "r");
|
||||
if (in != NULL) {
|
||||
do {
|
||||
fgetgrent_r(in, &grent, buf, sizeof(buf), &grp);
|
||||
if (grp == NULL)
|
||||
break;
|
||||
if (strcmp(grp->gr_name, groupname) == 0) {
|
||||
ci->gid = grp->gr_gid;
|
||||
break;
|
||||
}
|
||||
} while (1);
|
||||
fclose(in);
|
||||
}
|
||||
}
|
||||
|
||||
if (ci->gid != -1)
|
||||
|
|
|
@ -793,7 +793,7 @@ int apk_pkg_read(struct apk_database *db, const char *file,
|
|||
ctx.pkg->size = fi.size;
|
||||
|
||||
tar = apk_bstream_gunzip_mpart(bs, apk_sign_ctx_mpart_cb, sctx);
|
||||
r = apk_tar_parse(tar, read_info_entry, &ctx, FALSE);
|
||||
r = apk_tar_parse(tar, read_info_entry, &ctx, FALSE, &db->id_cache);
|
||||
tar->close(tar);
|
||||
if (r < 0 && r != -ECANCELED)
|
||||
goto err;
|
||||
|
@ -856,7 +856,8 @@ int apk_ipkg_add_script(struct apk_installed_package *ipkg,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int apk_ipkg_run_script(struct apk_installed_package *ipkg, int root_fd,
|
||||
int apk_ipkg_run_script(struct apk_installed_package *ipkg,
|
||||
struct apk_database *db,
|
||||
unsigned int type, char **argv)
|
||||
{
|
||||
static char * const environment[] = {
|
||||
|
@ -865,7 +866,7 @@ int apk_ipkg_run_script(struct apk_installed_package *ipkg, int root_fd,
|
|||
};
|
||||
struct apk_package *pkg = ipkg->pkg;
|
||||
char fn[PATH_MAX];
|
||||
int fd, status;
|
||||
int fd, status, root_fd = db->root_fd;
|
||||
pid_t pid;
|
||||
|
||||
if (type >= APK_SCRIPT_MAX)
|
||||
|
@ -911,7 +912,7 @@ int apk_ipkg_run_script(struct apk_installed_package *ipkg, int root_fd,
|
|||
}
|
||||
waitpid(pid, &status, 0);
|
||||
unlinkat(root_fd, fn, 0);
|
||||
apk_id_cache_reset();
|
||||
apk_id_cache_reset(&db->id_cache);
|
||||
|
||||
if (WIFEXITED(status))
|
||||
return WEXITSTATUS(status);
|
||||
|
|
|
@ -33,7 +33,7 @@ static int verify_main(void *ctx, struct apk_database *db, int argc, char **argv
|
|||
rc++;
|
||||
continue;
|
||||
}
|
||||
r = apk_tar_parse(is, apk_sign_ctx_verify_tar, &sctx, FALSE);
|
||||
r = apk_tar_parse(is, apk_sign_ctx_verify_tar, &sctx, FALSE, &db->id_cache);
|
||||
is->close(is);
|
||||
ok = sctx.control_verified && sctx.data_verified;
|
||||
if (apk_verbosity >= 1)
|
||||
|
|
Loading…
Reference in New Issue