Received: by 2002:ac0:a5b6:0:0:0:0:0 with SMTP id m51-v6csp4535098imm; Wed, 30 May 2018 07:24:35 -0700 (PDT) X-Google-Smtp-Source: ADUXVKJnZiNXXrZbPNAiROuWCHZCU7TnEEUbAyckEl/aZ2WZxlbe0ywZ9QbDYlVYUS8ywVRnqtIJ X-Received: by 2002:a63:6f4c:: with SMTP id k73-v6mr2380683pgc.303.1527690275144; Wed, 30 May 2018 07:24:35 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1527690275; cv=none; d=google.com; s=arc-20160816; b=Jx1OpSxrPMt9su99cQ1rdhU5i8bOdeTnI+hl04++DM1q1a8d87Zx7lwU3NFVJ/CgxL JsTHh+/mJ59/wPiO7oe1gHWkNzNlN93ZKeu9Zbn9Ml90FU1xIpSDhUo4FKAbtKyAFS/r hAScRt7UTKzIVGMbFJiGMUqWMU7fR7KoQZM4pFsugnd/JC9pWOqZLOBRJMZC0eDhnmxO SDvtYTexkb1/Bk1d2RVwSBgrWCWD4gQqmUf9IirSAyO9suaQEpnOeh7eUezGH1pCWlAF gA9zy48581IYSrSavEZ/BjHPpUlsNKGd6VJn/L0o5A/Qz1d/GFWZ5JepkS7Po2JwWEKz KRbQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:references:in-reply-to :message-id:date:subject:to:from:arc-authentication-results; bh=PPcNIkQfObZRcNlPAxeFaUt4W4ALDoZuXZVVHRg7UV4=; b=okxZzXYQgS01PSXAPJC2YesBSRVAHb5VBmzmR+hIsV5MEIbxT0Bf2vx/pC0OOcU1Gc Nnx24YZqyWIQGJCbIMAYegEcA6E5ve4Lt+BcrLeFXevGV3lcKPW4ygBK8+I5R4QbeHqu zMIA16iJwe4AoK1GyPbgkzhZZtF1mMtXt25JS2Tgn6JsMjQpmKUfID67nilsHafe+Vbj fhGoN6NtAda+ENilWXWgGOD1ko5EDBAKN6+99hhhOg955OlX172mdHCsUrQDABzjzwHr mWmC5yYFj8Jc6X4p1fg+xzx3KqvIyIJkiSjK9K7NnJuQinf4EN0qAeYTWlOVQrwGpRkp rDMA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id f6-v6si8447915plm.448.2018.05.30.07.24.21; Wed, 30 May 2018 07:24:35 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751567AbeE3OWe (ORCPT + 99 others); Wed, 30 May 2018 10:22:34 -0400 Received: from seldsegrel01.sonyericsson.com ([37.139.156.29]:11384 "EHLO SELDSEGREL01.sonyericsson.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753121AbeE3OVj (ORCPT ); Wed, 30 May 2018 10:21:39 -0400 From: Peter Enderborg To: , Paul Moore , Stephen Smalley , Eric Paris , James Morris , Daniel Jurgens , Doug Ledford , , , , "Serge E . Hallyn" , "Paul E . McKenney" Subject: [PATCH V3 4/5 selinux-next] selinux: seqno separation Date: Wed, 30 May 2018 16:11:03 +0200 Message-ID: <20180530141104.28569-5-peter.enderborg@sony.com> X-Mailer: git-send-email 2.15.1 In-Reply-To: <20180530141104.28569-1-peter.enderborg@sony.com> References: <20180530141104.28569-1-peter.enderborg@sony.com> MIME-Version: 1.0 Content-Type: text/plain Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This patch separtate the locks for read and write, and to be sure that they are using the same structure the seqno is used. If the seqno is changed from the read to write section the function reportes an eagain error. Signed-off-by: Peter Enderborg --- security/selinux/ss/services.c | 143 ++++++++++++++++++++++++++++------------- 1 file changed, 98 insertions(+), 45 deletions(-) diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 2be471d72c85..954ebe490516 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -2104,6 +2104,9 @@ int security_load_policy(struct selinux_state *state, void *data, size_t len) u32 seqno; int rc = 0; struct selinux_ruleset *next_set, *old_set; + size_t size; + void *storage; + struct policydb *pdc; struct policy_file file = { data, len }, *fp = &file; next_set = kzalloc(sizeof(struct selinux_ruleset), GFP_KERNEL); @@ -2111,14 +2114,15 @@ int security_load_policy(struct selinux_state *state, void *data, size_t len) rc = -ENOMEM; goto out; } + next_set->sidtab = kzalloc(sizeof(struct sidtab), GFP_KERNEL); if (!next_set->sidtab) { rc = -ENOMEM; - kfree(next_set); - goto out; + goto nexterr; } if (!state->initialized) { + /* sidtab exist before inititalisation */ old_set = state->ss->active_set; rc = policydb_read(&next_set->policydb, fp); if (rc) @@ -2152,57 +2156,80 @@ int security_load_policy(struct selinux_state *state, void *data, size_t len) kfree(old_set); goto out; } + + pdc = kzalloc(sizeof(struct selinux_ruleset), GFP_KERNEL); + if (!pdc) + goto allocerr; + + rc = policydb_flattened_alloc(&state->ss->active_set->policydb, + &storage, &size); + if (rc) + goto pdcerr; + + read_lock(&state->ss->policy_rwlock); old_set = state->ss->active_set; + rc = policydb_copy(&old_set->policydb, pdc, &storage, size); + + /* save seq */ + seqno = state->ss->latest_granting; + + read_unlock(&state->ss->policy_rwlock); + + policydb_flattened_free(storage); + + if (rc) + goto cpyerr; + #if 0 sidtab_hash_eval(sidtab, "sids"); #endif - rc = policydb_read(&next_set->policydb, fp); if (rc) - goto out; + goto cpyerr; next_set->policydb.len = len; /* If switching between different policy types, log MLS status */ - if (old_set->policydb.mls_enabled && !next_set->policydb.mls_enabled) + if (pdc->mls_enabled && !next_set->policydb.mls_enabled) printk(KERN_INFO "SELinux: Disabling MLS support...\n"); - else if (!old_set->policydb.mls_enabled + else if (!pdc->mls_enabled && next_set->policydb.mls_enabled) printk(KERN_INFO "SELinux: Enabling MLS support...\n"); + rc = policydb_load_isids(&next_set->policydb, next_set->sidtab); if (rc) { printk(KERN_ERR "SELinux: unable to load the initial SIDs\n"); - policydb_destroy(&next_set->policydb); - goto out; + goto cpyerr; } rc = selinux_set_mapping(&next_set->policydb, secclass_map, &newmap); if (rc) - goto err; + goto loaderr; rc = security_preserve_bools(state, &next_set->policydb); if (rc) { printk(KERN_ERR "SELinux: unable to preserve booleans\n"); - goto err; + goto maperr; } rc = sidtab_clone(old_set->sidtab, next_set->sidtab); if (rc) - goto err; + goto maperr; /* * Convert the internal representations of contexts * in the new SID table. */ args.state = state; - args.oldp = &old_set->policydb; + args.oldp = pdc; args.newp = &next_set->policydb; + rc = sidtab_map(next_set->sidtab, convert_context, &args); if (rc) { printk(KERN_ERR "SELinux: unable to convert the internal" " representation of contexts in the new SID" " table\n"); - goto err; + goto maperr; } next_set->map.mapping = newmap.mapping; @@ -2210,30 +2237,44 @@ int security_load_policy(struct selinux_state *state, void *data, size_t len) /* Install the new policydb and SID table. */ write_lock_irq(&state->ss->policy_rwlock); - security_load_policycaps(state, &next_set->policydb); - seqno = ++state->ss->latest_granting; - state->ss->active_set = next_set; - write_unlock_irq(&state->ss->policy_rwlock); - - avc_ss_reset(state->avc, seqno); - selnl_notify_policyload(seqno); - selinux_status_update_policyload(state, seqno); - selinux_netlbl_cache_invalidate(); - selinux_xfrm_notify_policyload(); - - /* Free the old policydb and SID table. */ - policydb_destroy(&old_set->policydb); - sidtab_destroy(old_set->sidtab); - kfree(old_set->sidtab); - kfree(old_set->map.mapping); - kfree(old_set); - rc = 0; - goto out; + if (seqno == state->ss->latest_granting) { + security_load_policycaps(state, &next_set->policydb); + seqno = ++state->ss->latest_granting; + state->ss->active_set = next_set; + write_unlock_irq(&state->ss->policy_rwlock); -err: + avc_ss_reset(state->avc, seqno); + selnl_notify_policyload(seqno); + selinux_status_update_policyload(state, seqno); + selinux_netlbl_cache_invalidate(); + selinux_xfrm_notify_policyload(); + + /* Free the old policydb and SID table. */ + policydb_destroy(pdc); + kfree(pdc); + sidtab_destroy(old_set->sidtab); + policydb_destroy(&old_set->policydb); + kfree(old_set->sidtab); + kfree(old_set->map.mapping); + kfree(old_set); + rc = 0; + goto out; + } else { + write_unlock_irq(&state->ss->policy_rwlock); + rc = -EAGAIN; + } +maperr: kfree(newmap.mapping); +loaderr: sidtab_destroy(next_set->sidtab); +cpyerr: policydb_destroy(&next_set->policydb); + policydb_destroy(pdc); +pdcerr: + kfree(pdc); +allocerr: + kfree(next_set->sidtab); +nexterr: kfree(next_set); out: return rc; @@ -2873,11 +2914,13 @@ int security_set_bools(struct selinux_state *state, int len, int *values) goto errout; } - write_lock_irq(&state->ss->policy_rwlock); + read_lock(&state->ss->policy_rwlock); old_set = state->ss->active_set; + seqno = state->ss->latest_granting; memcpy(next_set, old_set, sizeof(struct selinux_ruleset)); rc = policydb_copy(&old_set->policydb, &next_set->policydb, &storage, size); + read_unlock(&state->ss->policy_rwlock); if (rc) goto out; @@ -2913,19 +2956,29 @@ int security_set_bools(struct selinux_state *state, int len, int *values) rc = 0; out: if (!rc) { - seqno = ++state->ss->latest_granting; - state->ss->active_set = next_set; - rc = 0; - write_unlock_irq(&state->ss->policy_rwlock); - avc_ss_reset(state->avc, seqno); - selnl_notify_policyload(seqno); - selinux_status_update_policyload(state, seqno); - selinux_xfrm_notify_policyload(); - policydb_destroy(&old_set->policydb); - kfree(old_set); + write_lock_irq(&state->ss->policy_rwlock); + if (seqno == state->ss->latest_granting) { + seqno = ++state->ss->latest_granting; + state->ss->active_set = next_set; + rc = 0; + write_unlock_irq(&state->ss->policy_rwlock); + avc_ss_reset(state->avc, seqno); + selnl_notify_policyload(seqno); + selinux_status_update_policyload(state, seqno); + selinux_xfrm_notify_policyload(); + policydb_destroy(&old_set->policydb); + kfree(old_set); + } else { + rc = -ENOMEM; + write_unlock_irq(&state->ss->policy_rwlock); + printk(KERN_ERR "SELinux: %s failed in seqno %d\n", + __func__, rc); + policydb_destroy(&next_set->policydb); + kfree(next_set); + } } else { printk(KERN_ERR "SELinux: %s failed %d\n", __func__, rc); - write_unlock_irq(&state->ss->policy_rwlock); + policydb_destroy(&next_set->policydb); kfree(next_set); } policydb_flattened_free(storage); -- 2.15.1