diff options
-rw-r--r-- | src/apk_database.h | 13 | ||||
-rw-r--r-- | src/audit.c | 27 | ||||
-rw-r--r-- | src/database.c | 50 |
3 files changed, 50 insertions, 40 deletions
diff --git a/src/apk_database.h b/src/apk_database.h index 3d557bd..74af494 100644 --- a/src/apk_database.h +++ b/src/apk_database.h @@ -38,10 +38,16 @@ struct apk_db_file { char name[]; }; +enum apk_protect_mode { + APK_PROTECT_NONE = 0, + APK_PROTECT_CHANGED, + APK_PROTECT_SYMLINKS_ONLY, + APK_PROTECT_ALL, +}; + struct apk_protected_path { char *relative_pattern; - unsigned protected : 1; - unsigned symlinks_only : 1; + unsigned protect_mode : 4; }; APK_ARRAY(apk_protected_path_array, struct apk_protected_path); @@ -58,8 +64,7 @@ struct apk_db_dir { unsigned short refs; unsigned short namelen; - unsigned protected : 1; - unsigned symlinks_only : 1; + unsigned protect_mode : 4; unsigned has_protected_children : 1; unsigned modified : 1; unsigned recalc_mode : 1; diff --git a/src/audit.c b/src/audit.c index 1b82c28..1c94a1c 100644 --- a/src/audit.c +++ b/src/audit.c @@ -167,7 +167,7 @@ static int audit_directory_tree_item(void *ctx, int dirfd, const char *name) child = apk_db_dir_get(db, bfull); if (!child->has_protected_children) recurse = FALSE; - if (!child->protected) + if (child->protect_mode == APK_PROTECT_NONE) goto recurse_check; } else { child = apk_db_dir_query(db, bfull); @@ -196,7 +196,7 @@ recurse_check: } else { struct apk_db_file *dbf; struct apk_protected_path *ppath; - int protected = dir->protected, symlinks_only = dir->symlinks_only; + int protect_mode = dir->protect_mode; /* inherit file's protection mask */ foreach_array_item(ppath, dir->protected_paths) { @@ -204,23 +204,32 @@ recurse_check: if (slash == NULL) { if (fnmatch(ppath->relative_pattern, name, FNM_PATHNAME) != 0) continue; - protected = ppath->protected; - symlinks_only = ppath->symlinks_only; + protect_mode = ppath->protect_mode; } } if (actx->mode == MODE_BACKUP) { - if (!protected) - goto done; - if (symlinks_only && !S_ISLNK(fi.mode)) + switch (protect_mode) { + case APK_PROTECT_NONE: goto done; + case APK_PROTECT_CHANGED: + break; + case APK_PROTECT_SYMLINKS_ONLY: + if (!S_ISLNK(fi.mode)) + goto done; + break; + case APK_PROTECT_ALL: + reason = 'A'; + break; + } } else { - if (protected) + if (protect_mode != APK_PROTECT_NONE) goto done; } dbf = apk_db_file_query(db, bdir, bent); - reason = audit_file(actx, db, dbf, dirfd, name); + if (reason == 0) + reason = audit_file(actx, db, dbf, dirfd, name); if (reason < 0) goto done; if (reason == 'A' && actx->mode == MODE_SYSTEM) diff --git a/src/database.c b/src/database.c index 9eadb44..7fb700b 100644 --- a/src/database.c +++ b/src/database.c @@ -325,9 +325,8 @@ struct apk_db_dir *apk_db_dir_get(struct apk_database *db, apk_blob_t name) ppaths = NULL; } else if (apk_blob_rsplit(name, '/', &bparent, NULL)) { dir->parent = apk_db_dir_get(db, bparent); - dir->protected = dir->parent->protected; - dir->has_protected_children = dir->protected; - dir->symlinks_only = dir->parent->symlinks_only; + dir->protect_mode = dir->parent->protect_mode; + dir->has_protected_children = (dir->protect_mode != APK_PROTECT_NONE); ppaths = dir->parent->protected_paths; } else { dir->parent = apk_db_dir_get(db, APK_BLOB_NULL); @@ -350,17 +349,15 @@ struct apk_db_dir *apk_db_dir_get(struct apk_database *db, apk_blob_t name) *apk_protected_path_array_add(&dir->protected_paths) = (struct apk_protected_path) { .relative_pattern = slash + 1, - .protected = ppath->protected, - .symlinks_only = ppath->symlinks_only, + .protect_mode = ppath->protect_mode, }; } else { if (fnmatch(ppath->relative_pattern, relative_name, FNM_PATHNAME) != 0) continue; - dir->protected = ppath->protected; - dir->symlinks_only = ppath->symlinks_only; + dir->protect_mode = ppath->protect_mode; } - dir->has_protected_children |= ppath->protected; + dir->has_protected_children |= (ppath->protect_mode != APK_PROTECT_NONE); } return dir; @@ -1239,7 +1236,7 @@ int apk_db_index_write(struct apk_database *db, struct apk_ostream *os) static int add_protected_path(void *ctx, apk_blob_t blob) { struct apk_database *db = (struct apk_database *) ctx; - int protected = 0, symlinks_only = 0; + int protect_mode = APK_PROTECT_NONE; /* skip empty lines and comments */ if (blob.len == 0) @@ -1249,25 +1246,25 @@ static int add_protected_path(void *ctx, apk_blob_t blob) case '#': return 0; case '-': - blob.ptr++; - blob.len--; + protect_mode = APK_PROTECT_NONE; + break; + case '+': + protect_mode = APK_PROTECT_CHANGED; break; case '@': - protected = 1; - symlinks_only = 1; - blob.ptr++; - blob.len--; + protect_mode = APK_PROTECT_SYMLINKS_ONLY; break; - case '+': - protected = 1; - blob.ptr++; - blob.len--; + case '!': + protect_mode = APK_PROTECT_ALL; break; default: - protected = 1; - break; + protect_mode = APK_PROTECT_CHANGED; + goto no_mode_char; } + blob.ptr++; + blob.len--; +no_mode_char: /* skip leading and trailing path separators */ while (blob.len && blob.ptr[0] == '/') blob.ptr++, blob.len--; @@ -1276,8 +1273,7 @@ static int add_protected_path(void *ctx, apk_blob_t blob) *apk_protected_path_array_add(&db->protected_paths) = (struct apk_protected_path) { .relative_pattern = apk_blob_cstr(blob), - .protected = protected, - .symlinks_only = symlinks_only, + .protect_mode = protect_mode, }; return 0; @@ -1559,7 +1555,7 @@ int apk_db_open(struct apk_database *db, struct apk_db_options *dbopts) apk_blob_to_file(db->root_fd, apk_arch_file, *db->arch, APK_BTF_ADD_EOL); } - blob = APK_BLOB_STR("+etc\n" "@etc/init.d\n"); + blob = APK_BLOB_STR("+etc\n" "@etc/init.d\n" "!etc/apk\n"); apk_blob_for_each_segment(blob, "\n", add_protected_path, db); apk_dir_foreach_file(openat(db->root_fd, "etc/apk/protected_paths.d", O_RDONLY | O_CLOEXEC), @@ -2417,7 +2413,7 @@ static void apk_db_purge_pkg(struct apk_database *db, .filename = APK_BLOB_PTR_LEN(file->name, file->namelen), }; hash = apk_blob_hash_seed(key.filename, diri->dir->hash); - if ((!diri->dir->protected) || + if ((diri->dir->protect_mode == APK_PROTECT_NONE) || (apk_flags & APK_PURGE) || (file->csum.type != APK_CHECKSUM_NONE && apk_file_get_info(db->root_fd, name, APK_FI_NOFOLLOW | file->csum.type, &fi) == 0 && @@ -2474,7 +2470,7 @@ static void apk_db_migrate_files(struct apk_database *db, /* We want to compare checksums only if one exists * in db, and the file is in a protected path */ cstype = APK_CHECKSUM_NONE; - if (ofile != NULL && diri->dir->protected) + if (ofile != NULL && diri->dir->protect_mode != APK_PROTECT_NONE) cstype = ofile->csum.type; cstype |= APK_FI_NOFOLLOW; @@ -2483,7 +2479,7 @@ static void apk_db_migrate_files(struct apk_database *db, /* File was from overlay, delete the * packages version */ unlinkat(db->root_fd, tmpname, 0); - } else if ((diri->dir->protected) && + } else if ((diri->dir->protect_mode != APK_PROTECT_NONE) && (r == 0) && (ofile == NULL || ofile->csum.type == APK_CHECKSUM_NONE || |