]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
apparmor: remove explicit restriction that unconfined cannot use change_hat
authorJohn Johansen <john.johansen@canonical.com>
Fri, 19 Jan 2024 08:24:03 +0000 (00:24 -0800)
committerJohn Johansen <john.johansen@canonical.com>
Sat, 18 Jan 2025 14:47:12 +0000 (06:47 -0800)
There does not need to be an explicit restriction that unconfined
can't use change_hat. Traditionally unconfined doesn't have hats
so change_hat could not be used. But newer unconfined profiles have
the potential of having hats, and even system unconfined will be
able to be replaced with a profile that allows for hats.

To remain backwards compitible with expected return codes, continue
to return -EPERM if the unconfined profile does not have any hats.

Signed-off-by: John Johansen <john.johansen@canonical.com>
security/apparmor/apparmorfs.c
security/apparmor/domain.c

index 1bce9a7d21296914bd5ba0241338233e8d5f0116..e42ac7aadd31e2e2bba83b1678ec772abb29fe09 100644 (file)
@@ -2332,6 +2332,7 @@ static struct aa_sfs_entry aa_sfs_entry_attach[] = {
 static struct aa_sfs_entry aa_sfs_entry_domain[] = {
        AA_SFS_FILE_BOOLEAN("change_hat",       1),
        AA_SFS_FILE_BOOLEAN("change_hatv",      1),
+       AA_SFS_FILE_BOOLEAN("unconfined_allowed_children",      1),
        AA_SFS_FILE_BOOLEAN("change_onexec",    1),
        AA_SFS_FILE_BOOLEAN("change_profile",   1),
        AA_SFS_FILE_BOOLEAN("stack",            1),
index b1bf1a0b29bb8a010b7e2324b9bf8965d142f60c..af196005d5ee23bc87ca1d5bca65cc54b78f1b10 100644 (file)
@@ -1186,10 +1186,24 @@ int aa_change_hat(const char *hats[], int count, u64 token, int flags)
        if (task_no_new_privs(current) && !unconfined(label) && !ctx->nnp)
                ctx->nnp = aa_get_label(label);
 
+       /* return -EPERM when unconfined doesn't have children to avoid
+        * changing the traditional error code for unconfined.
+        */
        if (unconfined(label)) {
-               info = "unconfined can not change_hat";
-               error = -EPERM;
-               goto fail;
+               struct label_it i;
+               bool empty = true;
+
+               rcu_read_lock();
+               label_for_each_in_ns(i, labels_ns(label), label, profile) {
+                       empty &= list_empty(&profile->base.profiles);
+               }
+               rcu_read_unlock();
+
+               if (empty) {
+                       info = "unconfined can not change_hat";
+                       error = -EPERM;
+                       goto fail;
+               }
        }
 
        if (count) {