From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.7 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B06EFC433E7 for ; Mon, 12 Oct 2020 20:32:59 +0000 (UTC) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [216.205.24.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 11E2820BED for ; Mon, 12 Oct 2020 20:32:58 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 11E2820BED Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=schaufler-ca.com Authentication-Results: mail.kernel.org; spf=tempfail smtp.mailfrom=linux-audit-bounces@redhat.com Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-455-sbUWFlokNFOGmqoWW3gvCw-1; Mon, 12 Oct 2020 16:32:56 -0400 X-MC-Unique: sbUWFlokNFOGmqoWW3gvCw-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 770DE107464C; Mon, 12 Oct 2020 20:32:52 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 4ED6576674; Mon, 12 Oct 2020 20:32:52 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 1DBB958106; Mon, 12 Oct 2020 20:32:52 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id 09CKWoj0019874 for ; Mon, 12 Oct 2020 16:32:50 -0400 Received: by smtp.corp.redhat.com (Postfix) id 860872BBA0D; Mon, 12 Oct 2020 20:32:50 +0000 (UTC) Received: from mimecast-mx02.redhat.com (mimecast06.extmail.prod.ext.rdu2.redhat.com [10.11.55.22]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 7F8AC2BFEA3 for ; Mon, 12 Oct 2020 20:32:47 +0000 (UTC) Received: from us-smtp-1.mimecast.com (us-smtp-1.mimecast.com [205.139.110.61]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id E62E3182360B for ; Mon, 12 Oct 2020 20:32:46 +0000 (UTC) Received: from sonic317-38.consmr.mail.ne1.yahoo.com (sonic317-38.consmr.mail.ne1.yahoo.com [66.163.184.49]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-542-bCA7EM1iO3mY576lU5Najg-1; Mon, 12 Oct 2020 16:32:43 -0400 X-MC-Unique: bCA7EM1iO3mY576lU5Najg-1 X-SONIC-DKIM-SIGN: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.com; s=s2048; t=1602534763; bh=BuY+UA5427zuO2r8FpjgLNNvFrIPIBn7I9F3H3+tqWn=; h=From:To:Subject:Date; b=HUjH9FLJBxFGwR9ZbA7W0Ro/fuuNM23XUyddwKRImpMcH2Mgd4DcKn+shZxdlERBBP8YlE47vtO7LBAyeYyh5NWhGgIAW9ycKzhfWMFVVN4Q0XYzqmxjcZtsrX7iQ6DL88nAOmbHqayIVdLYT8mCDpC7cxXpYObGpMmIapKvQW3QtGq9YJpa3dmYjjL3WuN9sMB1+QwwS/cxivu8Rjofbcu8f3uysr4sfl/3Sjjk7QYFRXgsiYExZKQRMRn+Ja/l3ju9VtSPc5mj0jpELb3/SBZEDzyntJZ7O++sr2nPUV42XXtN6L+fsf5Jj4o4Pab1jgBlpih6dRJyjvrWj7iwCw== X-YMail-OSG: E0HI.D4VM1mh2fxoevuSSV_abVcNh6hC8uVZjwN5_CmzXbDubUNiXTIQCevmmJZ vf6Y4unzht4DFK0md2M3Dka.CTM3pPAvP3JTYmtfemAuNPBE14kUkbSENKW0q6MAmirFfxDhUYNZ e68VUlVofTGnDvg2P7p_Gx34gjQX0V8pM7MyyFQv8E5ix12EkemBcObo6ai4iu_nMFWH7rhFcaqQ oTz8HumWDQy4p0M4cwxAe6E8IPklVo11D83T7x2I.5YMArntX1wTkb0NP0Di6cUI8BSLY_J7Rf9a w4x0ysOTnEA_Tgzr5U75eVa2iTd79U7qBXFS3jtag3QTI_vEXxMhtYehLumMVg7.Szs72dwKWFyA WpiS0da8BCNqo7LDqYE1BgTipYa7ZY4_LZ1Bn4VxRGVN4O_apduhnPfhjVOpD8nZPanOUyKV9t2i 1RxNHhN4KMhcq85A7gftyaWe9AXdrE7CtXp51oKhQe.TkpYpphG8XYvoKueVrSS.C9h3tLS.g0eU IZgFrttJUpMdJi5W5SW1KcIY4AgYpTgv65ZJJri6471hFA7MADzhZLTaOQ5bqrcKBj9LlZAQ0d5u grcC4HmJ0ktZqYzf8mwpEsxdM_lzhEIETo70OqXZtXXaN48ryKHPU56BwNXm.MKSxHwSYl1dONWd S0Btk0KxUZBE7yXDGf0D8EhtFdbDM9KwWUFANApfocDz8zr95ubD9t5MHo5CDMjpJyQ7_vi9FTnZ ZQ.j_fxBymggzwyilwFJDPdC7GC_8CKW3eFFmi2fux85gCe6MocJ._z.Gkn.J3kYihrN2DFSlnWh 9t6O2_PgILoL.zSFmcl6JzU_5_27TThvsWW23qEaPXXAZvG8XEM1kafP6S1p6ZmRzymW0T6KC9_z 1ik0HHu4mX90wkKNKPwyzVm7lVVnlZ6m3QDl2ww0NPtIYlVmBt4yPYh2kELGU30KI7lcgpSnVaLC rjjvEYuUfsaMo0K68kx5ASt3YxLT87YpW6eh_zVhDOhgvFLu9cXMG7u305KPZKEqBN8RdQje9_JB sImPes7WEyfJqUNWVIaIdO.wB57_.DYcIDgqYlxrNcyru6vdZoJ9OsIIzzvTv5g1CbThbczf9il. sPxepHJcGf9lGQoA3amo5bemC7JOhlfOyxgP.3gciigyBj4oo_Wu.zH4JXZoPDKEAIJlkXvosT0S v5XltC4.XIWSh1t8tBH_wgERJBgjK19IWHBcvPcT_KmkuCrKBOV2DH5_vO9qaPIvuj7UlJrOUgD0 ai6CB8RSe8nFCxgWYcgU_hwFhr9S3FuayJ35h1U6C68R.4gfeN3821PhYjmi0uBpArMDDcsnxWdC 3h7gZSTr5od1zPSYiekkS4Nq0r6t12JZMpDUjcsGFYHqVVLUzaE3ym50ZeX6i4vd6uze0XleP.Hn CRkR.d8ZG4bPTqNjnuYY2Bnd0b9mRRZvDM166j5bQ9.M6LcqZ3Gmk5k4Y_pqLcIHs.STtiSmrilY HZuc5qfgYrrnwHemvL5GcmlFexFmsKrCB472lzJSzcJaGv67_u.NcpBjqIndp0boOnAc2pvH73QD Xkq2dGfHLnhmzrFH.6FHgNwq1fAOSDYIf0SXf21w- Received: from sonic.gate.mail.ne1.yahoo.com by sonic317.consmr.mail.ne1.yahoo.com with HTTP; Mon, 12 Oct 2020 20:32:43 +0000 Received: by smtp422.mail.gq1.yahoo.com (VZM Hermes SMTP Server) with ESMTPA ID 300b70b03849136b3a84dcc0e77df0d5; Mon, 12 Oct 2020 20:32:38 +0000 (UTC) From: Casey Schaufler To: casey.schaufler@intel.com, jmorris@namei.org, linux-security-module@vger.kernel.org, selinux@vger.kernel.org Subject: [PATCH v21 12/23] LSM: Specify which LSM to display Date: Mon, 12 Oct 2020 13:19:13 -0700 Message-Id: <20201012201924.71463-13-casey@schaufler-ca.com> In-Reply-To: <20201012201924.71463-1-casey@schaufler-ca.com> References: <20201012201924.71463-1-casey@schaufler-ca.com> MIME-Version: 1.0 X-Mimecast-Impersonation-Protect: Policy=CLT - Impersonation Protection Definition; Similar Internal Domain=false; Similar Monitored External Domain=false; Custom External Domain=false; Mimecast External Domain=false; Newly Observed Domain=false; Internal User Name=false; Custom Display Name List=false; Reply-to Address Mismatch=false; Targeted Threat Dictionary=false; Mimecast Threat Dictionary=false; Custom Threat Dictionary=false X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-loop: linux-audit@redhat.com Cc: john.johansen@canonical.com, linux-audit@redhat.com, sds@tycho.nsa.gov X-BeenThere: linux-audit@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Linux Audit Discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: linux-audit-bounces@redhat.com Errors-To: linux-audit-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=linux-audit-bounces@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Create a new entry "display" in the procfs attr directory for controlling which LSM security information is displayed for a process. A process can only read or write its own display value. The name of an active LSM that supplies hooks for human readable data may be written to "display" to set the value. The name of the LSM currently in use can be read from "display". At this point there can only be one LSM capable of display active. A helper function lsm_task_display() is provided to get the display slot for a task_struct. Setting the "display" requires that all security modules using setprocattr hooks allow the action. Each security module is responsible for defining its policy. AppArmor hook provided by John Johansen SELinux hook provided by Stephen Smalley Reviewed-by: Kees Cook Acked-by: Stephen Smalley Acked-by: Paul Moore Signed-off-by: Casey Schaufler --- fs/proc/base.c | 1 + include/linux/lsm_hooks.h | 17 +++ security/apparmor/include/apparmor.h | 3 +- security/apparmor/lsm.c | 32 +++++ security/security.c | 169 ++++++++++++++++++++++++--- security/selinux/hooks.c | 11 ++ security/selinux/include/classmap.h | 2 +- security/smack/smack_lsm.c | 7 ++ 8 files changed, 223 insertions(+), 19 deletions(-) diff --git a/fs/proc/base.c b/fs/proc/base.c index 617db4e0faa0..2edb51d4c725 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -2803,6 +2803,7 @@ static const struct pid_entry attr_dir_stuff[] = { ATTR(NULL, "fscreate", 0666), ATTR(NULL, "keycreate", 0666), ATTR(NULL, "sockcreate", 0666), + ATTR(NULL, "display", 0666), #ifdef CONFIG_SECURITY_SMACK DIR("smack", 0555, proc_smack_attr_dir_inode_ops, proc_smack_attr_dir_ops), diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 983008c6fede..e559df1df169 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -1647,4 +1647,21 @@ static inline void security_delete_hooks(struct security_hook_list *hooks, extern int lsm_inode_alloc(struct inode *inode); +/** + * lsm_task_display - the "display" LSM for this task + * @task: The task to report on + * + * Returns the task's display LSM slot. + */ +static inline int lsm_task_display(struct task_struct *task) +{ +#ifdef CONFIG_SECURITY + int *display = task->security; + + if (display) + return *display; +#endif + return LSMBLOB_INVALID; +} + #endif /* ! __LINUX_LSM_HOOKS_H */ diff --git a/security/apparmor/include/apparmor.h b/security/apparmor/include/apparmor.h index 1fbabdb565a8..b1622fcb4394 100644 --- a/security/apparmor/include/apparmor.h +++ b/security/apparmor/include/apparmor.h @@ -28,8 +28,9 @@ #define AA_CLASS_SIGNAL 10 #define AA_CLASS_NET 14 #define AA_CLASS_LABEL 16 +#define AA_CLASS_DISPLAY_LSM 17 -#define AA_CLASS_LAST AA_CLASS_LABEL +#define AA_CLASS_LAST AA_CLASS_DISPLAY_LSM /* Control parameters settable through module/boot flags */ extern enum audit_mode aa_g_audit; diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index 432915c1d427..31a6f11890f1 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -612,6 +612,25 @@ static int apparmor_getprocattr(struct task_struct *task, char *name, return error; } + +static int profile_display_lsm(struct aa_profile *profile, + struct common_audit_data *sa) +{ + struct aa_perms perms = { }; + unsigned int state; + + state = PROFILE_MEDIATES(profile, AA_CLASS_DISPLAY_LSM); + if (state) { + aa_compute_perms(profile->policy.dfa, state, &perms); + aa_apply_modes_to_perms(profile, &perms); + aad(sa)->label = &profile->label; + + return aa_check_perms(profile, &perms, AA_MAY_WRITE, sa, NULL); + } + + return 0; +} + static int apparmor_setprocattr(const char *name, void *value, size_t size) { @@ -623,6 +642,19 @@ static int apparmor_setprocattr(const char *name, void *value, if (size == 0) return -EINVAL; + /* LSM infrastructure does actual setting of display if allowed */ + if (!strcmp(name, "display")) { + struct aa_profile *profile; + struct aa_label *label; + + aad(&sa)->info = "set display lsm"; + label = begin_current_label_crit_section(); + error = fn_for_each_confined(label, profile, + profile_display_lsm(profile, &sa)); + end_current_label_crit_section(label); + return error; + } + /* AppArmor requires that the buffer must be null terminated atm */ if (args[size - 1] != '\0') { /* null terminate */ diff --git a/security/security.c b/security/security.c index ce220810e7f9..8b0ede277d6f 100644 --- a/security/security.c +++ b/security/security.c @@ -75,7 +75,16 @@ static struct kmem_cache *lsm_file_cache; static struct kmem_cache *lsm_inode_cache; char *lsm_names; -static struct lsm_blob_sizes blob_sizes __lsm_ro_after_init; + +/* + * The task blob includes the "display" slot used for + * chosing which module presents contexts. + * Using a long to avoid potential alignment issues with + * module assigned task blobs. + */ +static struct lsm_blob_sizes blob_sizes __lsm_ro_after_init = { + .lbs_task = sizeof(long), +}; /* Boot-time LSM user choice */ static __initdata const char *chosen_lsm_order; @@ -470,8 +479,10 @@ static int lsm_append(const char *new, char **result) /* * Current index to use while initializing the lsmblob secid list. + * Pointers to the LSM id structures for local use. */ static int lsm_slot __lsm_ro_after_init; +static struct lsm_id *lsm_slotlist[LSMBLOB_ENTRIES]; /** * security_add_hooks - Add a modules hooks to the hook lists. @@ -491,6 +502,7 @@ void __init security_add_hooks(struct security_hook_list *hooks, int count, if (lsmid->slot == LSMBLOB_NEEDED) { if (lsm_slot >= LSMBLOB_ENTRIES) panic("%s Too many LSMs registered.\n", __func__); + lsm_slotlist[lsm_slot] = lsmid; lsmid->slot = lsm_slot++; init_debug("%s assigned lsmblob slot %d\n", lsmid->lsm, lsmid->slot); @@ -620,6 +632,8 @@ int lsm_inode_alloc(struct inode *inode) */ static int lsm_task_alloc(struct task_struct *task) { + int *display; + if (blob_sizes.lbs_task == 0) { task->security = NULL; return 0; @@ -628,6 +642,15 @@ static int lsm_task_alloc(struct task_struct *task) task->security = kzalloc(blob_sizes.lbs_task, GFP_KERNEL); if (task->security == NULL) return -ENOMEM; + + /* + * The start of the task blob contains the "display" LSM slot number. + * Start with it set to the invalid slot number, indicating that the + * default first registered LSM be displayed. + */ + display = task->security; + *display = LSMBLOB_INVALID; + return 0; } @@ -1628,14 +1651,26 @@ int security_file_open(struct file *file) int security_task_alloc(struct task_struct *task, unsigned long clone_flags) { + int *odisplay = current->security; + int *ndisplay; int rc = lsm_task_alloc(task); - if (rc) + if (unlikely(rc)) return rc; + rc = call_int_hook(task_alloc, 0, task, clone_flags); - if (unlikely(rc)) + if (unlikely(rc)) { security_task_free(task); - return rc; + return rc; + } + + if (odisplay) { + ndisplay = task->security; + if (ndisplay) + *ndisplay = *odisplay; + } + + return 0; } void security_task_free(struct task_struct *task) @@ -2038,23 +2073,110 @@ int security_getprocattr(struct task_struct *p, const char *lsm, char *name, char **value) { struct security_hook_list *hp; + int display = lsm_task_display(current); + int slot = 0; + + if (!strcmp(name, "display")) { + /* + * lsm_slot will be 0 if there are no displaying modules. + */ + if (lsm_slot == 0) + return -EINVAL; + + /* + * Only allow getting the current process' display. + * There are too few reasons to get another process' + * display and too many LSM policy issues. + */ + if (current != p) + return -EINVAL; + + display = lsm_task_display(p); + if (display != LSMBLOB_INVALID) + slot = display; + *value = kstrdup(lsm_slotlist[slot]->lsm, GFP_KERNEL); + if (*value) + return strlen(*value); + return -ENOMEM; + } hlist_for_each_entry(hp, &security_hook_heads.getprocattr, list) { if (lsm != NULL && strcmp(lsm, hp->lsmid->lsm)) continue; + if (lsm == NULL && display != LSMBLOB_INVALID && + display != hp->lsmid->slot) + continue; return hp->hook.getprocattr(p, name, value); } return LSM_RET_DEFAULT(getprocattr); } +/** + * security_setprocattr - Set process attributes via /proc + * @lsm: name of module involved, or NULL + * @name: name of the attribute + * @value: value to set the attribute to + * @size: size of the value + * + * Set the process attribute for the specified security module + * to the specified value. Note that this can only be used to set + * the process attributes for the current, or "self" process. + * The /proc code has already done this check. + * + * Returns 0 on success, an appropriate code otherwise. + */ int security_setprocattr(const char *lsm, const char *name, void *value, size_t size) { struct security_hook_list *hp; + char *termed; + char *copy; + int *display = current->security; + int rc = -EINVAL; + int slot = 0; + + if (!strcmp(name, "display")) { + /* + * Change the "display" value only if all the security + * modules that support setting a procattr allow it. + * It is assumed that all such security modules will be + * cooperative. + */ + if (size == 0) + return -EINVAL; + + hlist_for_each_entry(hp, &security_hook_heads.setprocattr, + list) { + rc = hp->hook.setprocattr(name, value, size); + if (rc < 0) + return rc; + } + + rc = -EINVAL; + + copy = kmemdup_nul(value, size, GFP_KERNEL); + if (copy == NULL) + return -ENOMEM; + + termed = strsep(©, " \n"); + + for (slot = 0; slot < lsm_slot; slot++) + if (!strcmp(termed, lsm_slotlist[slot]->lsm)) { + *display = lsm_slotlist[slot]->slot; + rc = size; + break; + } + + kfree(termed); + return rc; + } hlist_for_each_entry(hp, &security_hook_heads.setprocattr, list) { if (lsm != NULL && strcmp(lsm, hp->lsmid->lsm)) continue; + if (lsm == NULL && *display != LSMBLOB_INVALID && + *display != hp->lsmid->slot) + continue; return hp->hook.setprocattr(name, value, size); } return LSM_RET_DEFAULT(setprocattr); @@ -2074,15 +2196,15 @@ EXPORT_SYMBOL(security_ismaclabel); int security_secid_to_secctx(struct lsmblob *blob, char **secdata, u32 *seclen) { struct security_hook_list *hp; - int rc; + int display = lsm_task_display(current); hlist_for_each_entry(hp, &security_hook_heads.secid_to_secctx, list) { if (WARN_ON(hp->lsmid->slot < 0 || hp->lsmid->slot >= lsm_slot)) continue; - rc = hp->hook.secid_to_secctx(blob->secid[hp->lsmid->slot], - secdata, seclen); - if (rc != LSM_RET_DEFAULT(secid_to_secctx)) - return rc; + if (display == LSMBLOB_INVALID || display == hp->lsmid->slot) + return hp->hook.secid_to_secctx( + blob->secid[hp->lsmid->slot], + secdata, seclen); } return LSM_RET_DEFAULT(secid_to_secctx); @@ -2093,16 +2215,15 @@ int security_secctx_to_secid(const char *secdata, u32 seclen, struct lsmblob *blob) { struct security_hook_list *hp; - int rc; + int display = lsm_task_display(current); lsmblob_init(blob, 0); hlist_for_each_entry(hp, &security_hook_heads.secctx_to_secid, list) { if (WARN_ON(hp->lsmid->slot < 0 || hp->lsmid->slot >= lsm_slot)) continue; - rc = hp->hook.secctx_to_secid(secdata, seclen, - &blob->secid[hp->lsmid->slot]); - if (rc != 0) - return rc; + if (display == LSMBLOB_INVALID || display == hp->lsmid->slot) + return hp->hook.secctx_to_secid(secdata, seclen, + &blob->secid[hp->lsmid->slot]); } return 0; } @@ -2110,7 +2231,14 @@ EXPORT_SYMBOL(security_secctx_to_secid); void security_release_secctx(char *secdata, u32 seclen) { - call_void_hook(release_secctx, secdata, seclen); + struct security_hook_list *hp; + int display = lsm_task_display(current); + + hlist_for_each_entry(hp, &security_hook_heads.release_secctx, list) + if (display == LSMBLOB_INVALID || display == hp->lsmid->slot) { + hp->hook.release_secctx(secdata, seclen); + return; + } } EXPORT_SYMBOL(security_release_secctx); @@ -2251,8 +2379,15 @@ EXPORT_SYMBOL(security_sock_rcv_skb); int security_socket_getpeersec_stream(struct socket *sock, char __user *optval, int __user *optlen, unsigned len) { - return call_int_hook(socket_getpeersec_stream, -ENOPROTOOPT, sock, - optval, optlen, len); + int display = lsm_task_display(current); + struct security_hook_list *hp; + + hlist_for_each_entry(hp, &security_hook_heads.socket_getpeersec_stream, + list) + if (display == LSMBLOB_INVALID || display == hp->lsmid->slot) + return hp->hook.socket_getpeersec_stream(sock, optval, + optlen, len); + return -ENOPROTOOPT; } int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 0442e1ff52ea..2a5cd0c5b0b7 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -6329,6 +6329,17 @@ static int selinux_setprocattr(const char *name, void *value, size_t size) /* * Basic control over ability to set these attributes at all. */ + + /* + * For setting display, we only perform a permission check; + * the actual update to the display value is handled by the + * LSM framework. + */ + if (!strcmp(name, "display")) + return avc_has_perm(&selinux_state, + mysid, mysid, SECCLASS_PROCESS2, + PROCESS2__SETDISPLAY, NULL); + if (!strcmp(name, "exec")) error = avc_has_perm(&selinux_state, mysid, mysid, SECCLASS_PROCESS, diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h index 40cebde62856..1858aa47b32a 100644 --- a/security/selinux/include/classmap.h +++ b/security/selinux/include/classmap.h @@ -53,7 +53,7 @@ struct security_class_mapping secclass_map[] = { "execmem", "execstack", "execheap", "setkeycreate", "setsockcreate", "getrlimit", NULL } }, { "process2", - { "nnp_transition", "nosuid_transition", NULL } }, + { "nnp_transition", "nosuid_transition", "setdisplay", NULL } }, { "system", { "ipc_info", "syslog_read", "syslog_mod", "syslog_console", "module_request", "module_load", NULL } }, diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 5aee8f7609b5..ceeddf45f775 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -3494,6 +3494,13 @@ static int smack_setprocattr(const char *name, void *value, size_t size) struct smack_known_list_elem *sklep; int rc; + /* + * Allow the /proc/.../attr/current and SO_PEERSEC "display" + * to be reset at will. + */ + if (strcmp(name, "display") == 0) + return 0; + if (!smack_privileged(CAP_MAC_ADMIN) && list_empty(&tsp->smk_relabel)) return -EPERM; -- 2.24.1 -- Linux-audit mailing list Linux-audit@redhat.com https://www.redhat.com/mailman/listinfo/linux-audit