audit: fix protection mask of non-db directories
If a directory has protection mask, but does not exist in db, we do not handle it right unless we calculate the protection mask by hand, or create temporary db dir entry for it. For simplicity create always the db dir entry -- depending on audit type we likely need to create it anyway. This commit also caches the db dir entry in the audit tree context to avoid duplicate lookups. ref #1241.cute-signatures
parent
5aa6998459
commit
ea5b08d1d5
|
@ -173,6 +173,8 @@ struct apk_name *apk_db_get_name(struct apk_database *db, apk_blob_t name);
|
||||||
struct apk_name *apk_db_query_name(struct apk_database *db, apk_blob_t name);
|
struct apk_name *apk_db_query_name(struct apk_database *db, apk_blob_t name);
|
||||||
int apk_db_get_tag_id(struct apk_database *db, apk_blob_t tag);
|
int apk_db_get_tag_id(struct apk_database *db, apk_blob_t tag);
|
||||||
|
|
||||||
|
struct apk_db_dir *apk_db_dir_ref(struct apk_db_dir *dir);
|
||||||
|
void apk_db_dir_unref(struct apk_database *db, struct apk_db_dir *dir, int allow_rmdir);
|
||||||
struct apk_db_dir *apk_db_dir_get(struct apk_database *db, apk_blob_t name);
|
struct apk_db_dir *apk_db_dir_get(struct apk_database *db, apk_blob_t name);
|
||||||
struct apk_db_dir *apk_db_dir_query(struct apk_database *db, apk_blob_t name);
|
struct apk_db_dir *apk_db_dir_query(struct apk_database *db, apk_blob_t name);
|
||||||
struct apk_db_file *apk_db_file_query(struct apk_database *db,
|
struct apk_db_file *apk_db_file_query(struct apk_database *db,
|
||||||
|
|
48
src/audit.c
48
src/audit.c
|
@ -62,6 +62,7 @@ static int audit_parse(void *ctx, struct apk_db_options *dbopts,
|
||||||
struct audit_tree_ctx {
|
struct audit_tree_ctx {
|
||||||
struct audit_ctx *actx;
|
struct audit_ctx *actx;
|
||||||
struct apk_database *db;
|
struct apk_database *db;
|
||||||
|
struct apk_db_dir *dir;
|
||||||
size_t pathlen;
|
size_t pathlen;
|
||||||
char path[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
};
|
};
|
||||||
|
@ -144,17 +145,13 @@ static int audit_directory_tree_item(void *ctx, int dirfd, const char *name)
|
||||||
apk_blob_t bfull;
|
apk_blob_t bfull;
|
||||||
struct audit_ctx *actx = atctx->actx;
|
struct audit_ctx *actx = atctx->actx;
|
||||||
struct apk_database *db = atctx->db;
|
struct apk_database *db = atctx->db;
|
||||||
struct apk_db_dir *dbd;
|
struct apk_db_dir *dir = atctx->dir, *child = NULL;
|
||||||
struct apk_file_info fi;
|
struct apk_file_info fi;
|
||||||
int reason = 0;
|
int reason = 0;
|
||||||
|
|
||||||
if (bdir.len + bent.len + 1 >= sizeof(atctx->path))
|
if (bdir.len + bent.len + 1 >= sizeof(atctx->path))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
dbd = apk_db_dir_get(db, bdir);
|
|
||||||
if (dbd == NULL)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
if (apk_file_get_info(dirfd, name, APK_FI_NOFOLLOW, &fi) < 0)
|
if (apk_file_get_info(dirfd, name, APK_FI_NOFOLLOW, &fi) < 0)
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
|
|
||||||
|
@ -163,26 +160,20 @@ static int audit_directory_tree_item(void *ctx, int dirfd, const char *name)
|
||||||
bfull = APK_BLOB_PTR_LEN(atctx->path, atctx->pathlen);
|
bfull = APK_BLOB_PTR_LEN(atctx->path, atctx->pathlen);
|
||||||
|
|
||||||
if (S_ISDIR(fi.mode)) {
|
if (S_ISDIR(fi.mode)) {
|
||||||
struct apk_db_dir *child;
|
|
||||||
int recurse = TRUE;
|
int recurse = TRUE;
|
||||||
|
|
||||||
child = apk_db_dir_query(db, bfull);
|
if (actx->mode == MODE_BACKUP) {
|
||||||
if (child != NULL) {
|
child = apk_db_dir_get(db, bfull);
|
||||||
if (actx->mode == MODE_BACKUP) {
|
if (!child->has_protected_children)
|
||||||
if (!child->has_protected_children)
|
|
||||||
recurse = FALSE;
|
|
||||||
if (!child->protected)
|
|
||||||
goto recurse_check;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (actx->mode == MODE_BACKUP) {
|
|
||||||
if (!dbd->has_protected_children)
|
|
||||||
recurse = FALSE;
|
|
||||||
if (!dbd->protected)
|
|
||||||
goto recurse_check;
|
|
||||||
} else {
|
|
||||||
recurse = FALSE;
|
recurse = FALSE;
|
||||||
}
|
if (!child->protected)
|
||||||
|
goto recurse_check;
|
||||||
|
} else {
|
||||||
|
child = apk_db_dir_query(db, bfull);
|
||||||
|
if (child == NULL)
|
||||||
|
recurse = FALSE;
|
||||||
|
else
|
||||||
|
child = apk_db_dir_ref(child);
|
||||||
}
|
}
|
||||||
|
|
||||||
reason = audit_directory(actx, db, child, &fi);
|
reason = audit_directory(actx, db, child, &fi);
|
||||||
|
@ -200,16 +191,18 @@ recurse_check:
|
||||||
bfull.len++;
|
bfull.len++;
|
||||||
report_audit(actx, reason, bfull, NULL);
|
report_audit(actx, reason, bfull, NULL);
|
||||||
if (recurse) {
|
if (recurse) {
|
||||||
|
atctx->dir = child;
|
||||||
reason = apk_dir_foreach_file(
|
reason = apk_dir_foreach_file(
|
||||||
openat(dirfd, name, O_RDONLY|O_CLOEXEC),
|
openat(dirfd, name, O_RDONLY|O_CLOEXEC),
|
||||||
audit_directory_tree_item, atctx);
|
audit_directory_tree_item, atctx);
|
||||||
|
atctx->dir = dir;
|
||||||
}
|
}
|
||||||
bfull.len--;
|
bfull.len--;
|
||||||
atctx->pathlen--;
|
atctx->pathlen--;
|
||||||
} else {
|
} else {
|
||||||
struct apk_db_file *dbf;
|
struct apk_db_file *dbf;
|
||||||
struct apk_protected_path_array *ppaths = dbd->protected_paths;
|
struct apk_protected_path_array *ppaths = dir->protected_paths;
|
||||||
int i, protected = dbd->protected, symlinks_only = dbd->symlinks_only;
|
int i, protected = dir->protected, symlinks_only = dir->symlinks_only;
|
||||||
|
|
||||||
/* inherit file's protection mask */
|
/* inherit file's protection mask */
|
||||||
for (i = 0; i < ppaths->num; i++) {
|
for (i = 0; i < ppaths->num; i++) {
|
||||||
|
@ -243,6 +236,9 @@ recurse_check:
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
if (child)
|
||||||
|
apk_db_dir_unref(db, child, FALSE);
|
||||||
|
|
||||||
atctx->pathlen -= bent.len;
|
atctx->pathlen -= bent.len;
|
||||||
return reason < 0 ? reason : 0;
|
return reason < 0 ? reason : 0;
|
||||||
}
|
}
|
||||||
|
@ -258,7 +254,9 @@ static int audit_main(void *ctx, struct apk_database *db, int argc, char **argv)
|
||||||
atctx.path[0] = 0;
|
atctx.path[0] = 0;
|
||||||
|
|
||||||
if (argc == 0) {
|
if (argc == 0) {
|
||||||
|
atctx.dir = apk_db_dir_get(db, APK_BLOB_PTR_LEN(atctx.path, atctx.pathlen));
|
||||||
r = apk_dir_foreach_file(dup(db->root_fd), audit_directory_tree_item, &atctx);
|
r = apk_dir_foreach_file(dup(db->root_fd), audit_directory_tree_item, &atctx);
|
||||||
|
apk_db_dir_unref(db, atctx.dir, FALSE);
|
||||||
} else {
|
} else {
|
||||||
for (i = 0; i < argc; i++) {
|
for (i = 0; i < argc; i++) {
|
||||||
if (argv[i][0] != '/') {
|
if (argv[i][0] != '/') {
|
||||||
|
@ -272,9 +270,11 @@ static int audit_main(void *ctx, struct apk_database *db, int argc, char **argv)
|
||||||
if (atctx.path[atctx.pathlen-1] != '/')
|
if (atctx.path[atctx.pathlen-1] != '/')
|
||||||
atctx.path[atctx.pathlen++] = '/';
|
atctx.path[atctx.pathlen++] = '/';
|
||||||
|
|
||||||
|
atctx.dir = apk_db_dir_get(db, APK_BLOB_PTR_LEN(atctx.path, atctx.pathlen));
|
||||||
r |= apk_dir_foreach_file(
|
r |= apk_dir_foreach_file(
|
||||||
openat(db->root_fd, argv[i], O_RDONLY|O_CLOEXEC),
|
openat(db->root_fd, argv[i], O_RDONLY|O_CLOEXEC),
|
||||||
audit_directory_tree_item, &atctx);
|
audit_directory_tree_item, &atctx);
|
||||||
|
apk_db_dir_unref(db, atctx.dir, FALSE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
|
|
|
@ -240,8 +240,7 @@ static void apk_db_dir_mkdir(struct apk_database *db, struct apk_db_dir *dir)
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void apk_db_dir_unref(struct apk_database *db, struct apk_db_dir *dir,
|
void apk_db_dir_unref(struct apk_database *db, struct apk_db_dir *dir, int allow_rmdir)
|
||||||
int allow_rmdir)
|
|
||||||
{
|
{
|
||||||
dir->refs--;
|
dir->refs--;
|
||||||
if (dir->refs > 0) {
|
if (dir->refs > 0) {
|
||||||
|
@ -274,7 +273,7 @@ static void apk_db_dir_unref(struct apk_database *db, struct apk_db_dir *dir,
|
||||||
apk_db_dir_unref(db, dir->parent, allow_rmdir);
|
apk_db_dir_unref(db, dir->parent, allow_rmdir);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct apk_db_dir *apk_db_dir_ref(struct apk_db_dir *dir)
|
struct apk_db_dir *apk_db_dir_ref(struct apk_db_dir *dir)
|
||||||
{
|
{
|
||||||
dir->refs++;
|
dir->refs++;
|
||||||
return dir;
|
return dir;
|
||||||
|
|
Loading…
Reference in New Issue