diff --git a/src/apk_database.h b/src/apk_database.h index 731a5fd..089cdd8 100644 --- a/src/apk_database.h +++ b/src/apk_database.h @@ -24,16 +24,21 @@ struct apk_name; APK_ARRAY(apk_name_array, struct apk_name *); +struct apk_db_acl { + mode_t mode; + uid_t uid; + gid_t gid; +}; + struct apk_db_file { struct hlist_node hash_node; struct hlist_node diri_files_list; struct apk_db_dir_instance *diri; - mode_t mode; - uid_t uid; - gid_t gid; + struct apk_db_acl *acl; - unsigned short namelen; + unsigned short audited : 1; + unsigned short namelen : 15; struct apk_checksum csum; char name[]; }; @@ -84,9 +89,7 @@ struct apk_db_dir_instance { struct hlist_head owned_files; struct apk_package *pkg; struct apk_db_dir *dir; - mode_t mode; - uid_t uid; - gid_t gid; + struct apk_db_acl *acl; }; struct apk_name { diff --git a/src/audit.c b/src/audit.c index 0d1ca5c..e7440de 100644 --- a/src/audit.c +++ b/src/audit.c @@ -97,7 +97,7 @@ static int audit_file(struct audit_ctx *actx, if (dbf == NULL) return 'A'; - dbf->mode |= S_SEENFLAG; + dbf->audited = 1; if (apk_file_get_info(dirfd, name, APK_FI_NOFOLLOW | dbf->csum.type, &fi) != 0) return -EPERM; @@ -109,11 +109,10 @@ static int audit_file(struct audit_ctx *actx, if (S_ISLNK(fi.mode) && dbf->csum.type == APK_CHECKSUM_NONE) return 'U'; - if (actx->check_permissions && - (dbf->mode != 0 || dbf->uid != 0 || dbf->gid != 0)) { - if ((fi.mode & 07777) != (dbf->mode & 07777)) + if (actx->check_permissions) { + if ((fi.mode & 07777) != (dbf->acl->mode & 07777)) return 'M'; - if (fi.uid != dbf->uid || fi.gid != dbf->gid) + if (fi.uid != dbf->acl->uid || fi.gid != dbf->acl->gid) return 'M'; } @@ -293,8 +292,7 @@ static int audit_missing_files(apk_hash_item item, void *pctx) char path[PATH_MAX]; int len; - if (file->mode & S_SEENFLAG) - return 0; + if (file->audited) return 0; dir = file->diri->dir; if (dir->mode & S_SEENFLAG) { diff --git a/src/database.c b/src/database.c index f511125..b763c43 100644 --- a/src/database.c +++ b/src/database.c @@ -72,6 +72,8 @@ const char * const apk_installed_file = "lib/apk/db/installed"; static const char * const apk_installed_file_tmp = "lib/apk/db/installed.new"; static const char * const apk_installed_file_old = "var/lib/apk/installed"; +static struct apk_db_acl *apk_default_acl_dir, *apk_default_acl_file; + struct install_ctx { struct apk_database *db; struct apk_package *pkg; @@ -222,6 +224,14 @@ struct apk_name *apk_db_get_name(struct apk_database *db, apk_blob_t name) return pn; } +static struct apk_db_acl *apk_db_acl_atomize(mode_t mode, uid_t uid, gid_t gid) +{ + struct apk_db_acl acl = { .mode = mode & 07777, .uid = uid, .gid = gid }; + apk_blob_t *b; + b = apk_blob_atomize_dup(APK_BLOB_STRUCT(acl)); + return (struct apk_db_acl *) b->ptr; +} + static void apk_db_dir_prepare(struct apk_database *db, struct apk_db_dir *dir, mode_t newmode) { struct stat st; @@ -356,6 +366,7 @@ static struct apk_db_dir_instance *apk_db_diri_new(struct apk_database *db, *after = &diri->pkg_dirs_list.next; diri->dir = apk_db_dir_get(db, name); diri->pkg = pkg; + diri->acl = apk_default_acl_dir; } return diri; @@ -364,23 +375,20 @@ static struct apk_db_dir_instance *apk_db_diri_new(struct apk_database *db, static void apk_db_dir_apply_diri_permissions(struct apk_db_dir_instance *diri) { struct apk_db_dir *dir = diri->dir; + struct apk_db_acl *acl = diri->acl; - if (diri->uid < dir->uid || - (diri->uid == dir->uid && diri->gid < dir->gid)) { - dir->uid = diri->uid; - dir->gid = diri->gid; - dir->mode = diri->mode; - } else if (diri->uid == dir->uid && diri->gid == dir->gid) { - dir->mode &= diri->mode; + if (acl->uid < dir->uid || (acl->uid == dir->uid && acl->gid < dir->gid)) { + dir->uid = acl->uid; + dir->gid = acl->gid; + dir->mode = acl->mode; + } else if (acl->uid == dir->uid && acl->gid == dir->gid) { + dir->mode &= acl->mode; } } -static void apk_db_diri_set(struct apk_db_dir_instance *diri, mode_t mode, - uid_t uid, gid_t gid) +static void apk_db_diri_set(struct apk_db_dir_instance *diri, struct apk_db_acl *acl) { - diri->mode = mode & 07777; - diri->uid = uid; - diri->gid = gid; + diri->acl = acl; apk_db_dir_apply_diri_permissions(diri); } @@ -431,19 +439,13 @@ static struct apk_db_file *apk_db_file_new(struct apk_db_dir_instance *diri, file->namelen = name.len; file->diri = diri; + file->acl = apk_default_acl_file; hlist_add_after(&file->diri_files_list, *after); *after = &file->diri_files_list.next; return file; } -static void apk_db_file_set(struct apk_db_file *file, mode_t mode, uid_t uid, gid_t gid) -{ - file->mode = mode & 07777; - file->uid = uid; - file->gid = gid; -} - static struct apk_db_file *apk_db_file_get(struct apk_database *db, struct apk_db_dir_instance *diri, apk_blob_t name, @@ -737,6 +739,7 @@ int apk_db_index_read(struct apk_database *db, struct apk_bstream *bs, int repo) struct apk_installed_package *ipkg = NULL; struct apk_db_dir_instance *diri = NULL; struct apk_db_file *file = NULL; + struct apk_db_acl *acl; struct hlist_node **diri_node = NULL; struct hlist_node **file_diri_node = NULL; apk_blob_t token = APK_BLOB_STR("\n"), l; @@ -813,10 +816,11 @@ int apk_db_index_read(struct apk_database *db, struct apk_bstream *bs, int repo) gid = apk_blob_pull_uint(&l, 10); apk_blob_pull_char(&l, ':'); mode = apk_blob_pull_uint(&l, 8); + acl = apk_db_acl_atomize(mode, uid, gid); if (field == 'M') - apk_db_diri_set(diri, mode, uid, gid); + apk_db_diri_set(diri, acl); else - apk_db_file_set(file, mode, uid, gid); + file->acl = acl; break; case 'R': if (diri == NULL) goto bad_entry; @@ -866,6 +870,19 @@ bad_entry: return -1; } +static void apk_blob_push_db_acl(apk_blob_t *b, char field, struct apk_db_acl *acl) +{ + char hdr[2] = { field, ':' }; + + apk_blob_push_blob(b, APK_BLOB_BUF(hdr)); + apk_blob_push_uint(b, acl->uid, 10); + apk_blob_push_blob(b, APK_BLOB_STR(":")); + apk_blob_push_uint(b, acl->gid, 10); + apk_blob_push_blob(b, APK_BLOB_STR(":")); + apk_blob_push_uint(b, acl->mode, 8); + apk_blob_push_blob(b, APK_BLOB_STR("\n")); +} + static int apk_db_write_fdb(struct apk_database *db, struct apk_ostream *os) { struct apk_installed_package *ipkg; @@ -909,31 +926,25 @@ static int apk_db_write_fdb(struct apk_database *db, struct apk_ostream *os) hlist_for_each_entry(diri, c1, &ipkg->owned_dirs, pkg_dirs_list) { apk_blob_push_blob(&bbuf, APK_BLOB_STR("F:")); apk_blob_push_blob(&bbuf, APK_BLOB_PTR_LEN(diri->dir->name, diri->dir->namelen)); - apk_blob_push_blob(&bbuf, APK_BLOB_STR("\nM:")); - apk_blob_push_uint(&bbuf, diri->uid, 10); - apk_blob_push_blob(&bbuf, APK_BLOB_STR(":")); - apk_blob_push_uint(&bbuf, diri->gid, 10); - apk_blob_push_blob(&bbuf, APK_BLOB_STR(":")); - apk_blob_push_uint(&bbuf, diri->mode, 8); apk_blob_push_blob(&bbuf, APK_BLOB_STR("\n")); + if (1 || diri->acl != apk_default_acl_dir) + apk_blob_push_db_acl(&bbuf, 'M', diri->acl); + hlist_for_each_entry(file, c2, &diri->owned_files, diri_files_list) { apk_blob_push_blob(&bbuf, APK_BLOB_STR("R:")); apk_blob_push_blob(&bbuf, APK_BLOB_PTR_LEN(file->name, file->namelen)); - if (file->mode != 0 || file->uid != 0 || file->gid != 0) { - apk_blob_push_blob(&bbuf, APK_BLOB_STR("\na:")); - apk_blob_push_uint(&bbuf, file->uid, 10); - apk_blob_push_blob(&bbuf, APK_BLOB_STR(":")); - apk_blob_push_uint(&bbuf, file->gid, 10); - apk_blob_push_blob(&bbuf, APK_BLOB_STR(":")); - apk_blob_push_uint(&bbuf, file->mode, 8); - } - if (file->csum.type != APK_CHECKSUM_NONE) { - apk_blob_push_blob(&bbuf, APK_BLOB_STR("\nZ:")); - apk_blob_push_csum(&bbuf, &file->csum); - } apk_blob_push_blob(&bbuf, APK_BLOB_STR("\n")); + if (1 || file->acl != apk_default_acl_file) + apk_blob_push_db_acl(&bbuf, 'a', file->acl); + + if (file->csum.type != APK_CHECKSUM_NONE) { + apk_blob_push_blob(&bbuf, APK_BLOB_STR("Z:")); + apk_blob_push_csum(&bbuf, &file->csum); + apk_blob_push_blob(&bbuf, APK_BLOB_STR("\n")); + } + if (os->write(os, buf, bbuf.ptr - buf) != bbuf.ptr - buf) return -EIO; bbuf = APK_BLOB_BUF(buf); @@ -1440,6 +1451,9 @@ int apk_db_open(struct apk_database *db, struct apk_db_options *dbopts) apk_blob_t blob; int r, fd, write_arch = FALSE; + apk_default_acl_dir = apk_db_acl_atomize(0755, 0, 0); + apk_default_acl_file = apk_db_acl_atomize(0644, 0, 0); + memset(db, 0, sizeof(*db)); if (apk_flags & APK_SIMULATE) { dbopts->open_flags &= ~(APK_OPENF_CREATE | APK_OPENF_WRITE); @@ -2363,7 +2377,7 @@ static int apk_db_install_archive_entry(void *_ctx, apk_message("%s", ae->name); /* Extract the file as name.apk-new */ - apk_db_file_set(file, ae->mode, ae->uid, ae->gid); + file->acl = apk_db_acl_atomize(ae->mode, ae->uid, ae->gid); r = apk_archive_entry_extract(db->root_fd, ae, ".apk-new", is, extract_cb, ctx); @@ -2405,7 +2419,7 @@ static int apk_db_install_archive_entry(void *_ctx, diri = apk_db_install_directory_entry(ctx, name); apk_db_dir_prepare(db, diri->dir, ae->mode); - apk_db_diri_set(diri, ae->mode, ae->uid, ae->gid); + apk_db_diri_set(diri, apk_db_acl_atomize(ae->mode, ae->uid, ae->gid)); } ctx->installed_size += ctx->current_file_size;