lkml.org 
[lkml]   [2020]   [Jun]   [23]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.4 082/314] apparmor: fix nnp subset test for unconfined
    Date
    From: John Johansen <john.johansen@canonical.com>

    [ Upstream commit 3ed4aaa94fc07db3cd0c91be95e3e1b9782a2710 ]

    The subset test is not taking into account the unconfined exception
    which will cause profile transitions in the stacked confinement
    case to fail when no_new_privs is applied.

    This fixes a regression introduced in the fix for
    https://bugs.launchpad.net/bugs/1839037

    BugLink: https://bugs.launchpad.net/bugs/1844186
    Signed-off-by: John Johansen <john.johansen@canonical.com>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    security/apparmor/domain.c | 9 +++++----
    security/apparmor/include/label.h | 1 +
    security/apparmor/label.c | 33 +++++++++++++++++++++++++++++++
    3 files changed, 39 insertions(+), 4 deletions(-)

    diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c
    index 5dedc0173b024..1a33f490e6670 100644
    --- a/security/apparmor/domain.c
    +++ b/security/apparmor/domain.c
    @@ -935,7 +935,8 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
    * aways results in a further reduction of permissions.
    */
    if ((bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS) &&
    - !unconfined(label) && !aa_label_is_subset(new, ctx->nnp)) {
    + !unconfined(label) &&
    + !aa_label_is_unconfined_subset(new, ctx->nnp)) {
    error = -EPERM;
    info = "no new privs";
    goto audit;
    @@ -1213,7 +1214,7 @@ int aa_change_hat(const char *hats[], int count, u64 token, int flags)
    * reduce restrictions.
    */
    if (task_no_new_privs(current) && !unconfined(label) &&
    - !aa_label_is_subset(new, ctx->nnp)) {
    + !aa_label_is_unconfined_subset(new, ctx->nnp)) {
    /* not an apparmor denial per se, so don't log it */
    AA_DEBUG("no_new_privs - change_hat denied");
    error = -EPERM;
    @@ -1234,7 +1235,7 @@ int aa_change_hat(const char *hats[], int count, u64 token, int flags)
    * reduce restrictions.
    */
    if (task_no_new_privs(current) && !unconfined(label) &&
    - !aa_label_is_subset(previous, ctx->nnp)) {
    + !aa_label_is_unconfined_subset(previous, ctx->nnp)) {
    /* not an apparmor denial per se, so don't log it */
    AA_DEBUG("no_new_privs - change_hat denied");
    error = -EPERM;
    @@ -1429,7 +1430,7 @@ check:
    * reduce restrictions.
    */
    if (task_no_new_privs(current) && !unconfined(label) &&
    - !aa_label_is_subset(new, ctx->nnp)) {
    + !aa_label_is_unconfined_subset(new, ctx->nnp)) {
    /* not an apparmor denial per se, so don't log it */
    AA_DEBUG("no_new_privs - change_hat denied");
    error = -EPERM;
    diff --git a/security/apparmor/include/label.h b/security/apparmor/include/label.h
    index 47942c4ba7ca7..255764ab06e2f 100644
    --- a/security/apparmor/include/label.h
    +++ b/security/apparmor/include/label.h
    @@ -281,6 +281,7 @@ bool aa_label_init(struct aa_label *label, int size, gfp_t gfp);
    struct aa_label *aa_label_alloc(int size, struct aa_proxy *proxy, gfp_t gfp);

    bool aa_label_is_subset(struct aa_label *set, struct aa_label *sub);
    +bool aa_label_is_unconfined_subset(struct aa_label *set, struct aa_label *sub);
    struct aa_profile *__aa_label_next_not_in_set(struct label_it *I,
    struct aa_label *set,
    struct aa_label *sub);
    diff --git a/security/apparmor/label.c b/security/apparmor/label.c
    index 6c3acae701efd..5f324d63ceaa3 100644
    --- a/security/apparmor/label.c
    +++ b/security/apparmor/label.c
    @@ -550,6 +550,39 @@ bool aa_label_is_subset(struct aa_label *set, struct aa_label *sub)
    return __aa_label_next_not_in_set(&i, set, sub) == NULL;
    }

    +/**
    + * aa_label_is_unconfined_subset - test if @sub is a subset of @set
    + * @set: label to test against
    + * @sub: label to test if is subset of @set
    + *
    + * This checks for subset but taking into account unconfined. IF
    + * @sub contains an unconfined profile that does not have a matching
    + * unconfined in @set then this will not cause the test to fail.
    + * Conversely we don't care about an unconfined in @set that is not in
    + * @sub
    + *
    + * Returns: true if @sub is special_subset of @set
    + * else false
    + */
    +bool aa_label_is_unconfined_subset(struct aa_label *set, struct aa_label *sub)
    +{
    + struct label_it i = { };
    + struct aa_profile *p;
    +
    + AA_BUG(!set);
    + AA_BUG(!sub);
    +
    + if (sub == set)
    + return true;
    +
    + do {
    + p = __aa_label_next_not_in_set(&i, set, sub);
    + if (p && !profile_unconfined(p))
    + break;
    + } while (p);
    +
    + return p == NULL;
    +}


    /**
    --
    2.25.1


    \
     
     \ /
      Last update: 2020-06-23 23:21    [W:4.068 / U:0.060 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site