summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/apk_database.h13
-rw-r--r--src/audit.c27
-rw-r--r--src/database.c50
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 ||