Received: by 2002:a05:6602:2086:0:0:0:0 with SMTP id a6csp4456795ioa; Wed, 27 Apr 2022 04:24:55 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyDN1B7cMTvLUxPKROuWs1oGADwWQ0K+pJruNveSqxqJUbf8fH/aVu6FHCP/qHe6Oismi63 X-Received: by 2002:a17:90b:4c86:b0:1d9:aff5:ffe8 with SMTP id my6-20020a17090b4c8600b001d9aff5ffe8mr9034758pjb.133.1651058695086; Wed, 27 Apr 2022 04:24:55 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1651058695; cv=none; d=google.com; s=arc-20160816; b=yb1u+hVcyHcf21UG9zdy0IRpya6pKi9F6ozlocxZ3kkS23RoszNltlTG5aLMWP2bo6 5A5wz0+QZzKmXkpxj4SZMQ1H+JKbQns+nePTwJjuc/EE1dERcbRk815UUs1ylXngSWgS nJ2RSYySkH/acYDAKqfAwaw0ypXebnGPIk8CPvLnBABp6k3BwBjF62Z9jgFpK+NtaO/d 1aPpSLigJbymHVEgQQdYSUGpU1R4rnC8tH8S2hE8sqRU0EmgOS78xFPa5w6xL2rBAot3 XNBwMX4MoGNpBMicZ79W9ETcQO9dQnZSVb1J5iJCqAV8KYO42t3Cusw/L/s28CXUC6Ox 899A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:in-reply-to :organization:from:references:cc:to:content-language:subject :user-agent:mime-version:date:message-id:dkim-signature; bh=I7+zcYF8QLc268zL8zDKCWLmq8xiUApEbjYZ+StRn3U=; b=QQAbi7B2sGDOQ2jkBe2Vfcl92Phk/yvdrByBU8106ThJFrtWSYj4d3J34wUqafHjPn HKslwLyfZ79GmX8sHn6zdgz7AupSeKw9Hb3i219d8XvTag/hvUl4JTUk4vtV9Rt9MB53 LnZERUS46eXX4kBRBS0YklTXWz2bFTUXCVJ4OkcmEIshGZahmlBC2ajbNQHgCjoPwnj1 5Nyhh0nHduL2bzyAAMfbwHnAIiOEHuLQOjrk66vuOg2FUXTJ+o2AZBxcZilkAEJ5LVJg pCaGQ0Jw1y1jUQ5uvC/WplC3ODCLfMvCXp5IDpVDpaVWUhT7yfPTjw6LE/EEodGKyHSd z4ZA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@canonical.com header.s=20210705 header.b=sNLQO6FS; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=canonical.com Return-Path: Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net. [2620:137:e000::1:18]) by mx.google.com with ESMTPS id f20-20020a056a00229400b004faa473dabcsi1163948pfe.301.2022.04.27.04.24.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 27 Apr 2022 04:24:55 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:18 as permitted sender) client-ip=2620:137:e000::1:18; Authentication-Results: mx.google.com; dkim=pass header.i=@canonical.com header.s=20210705 header.b=sNLQO6FS; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=canonical.com Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 815193677F0; Wed, 27 Apr 2022 03:20:33 -0700 (PDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1356422AbiD0Am0 (ORCPT + 99 others); Tue, 26 Apr 2022 20:42:26 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60136 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1356393AbiD0AmY (ORCPT ); Tue, 26 Apr 2022 20:42:24 -0400 Received: from smtp-relay-canonical-0.canonical.com (smtp-relay-canonical-0.canonical.com [185.125.188.120]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4040338D83; Tue, 26 Apr 2022 17:39:12 -0700 (PDT) Received: from [192.168.192.153] (unknown [50.126.114.69]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by smtp-relay-canonical-0.canonical.com (Postfix) with ESMTPSA id 737AC3F1BD; Wed, 27 Apr 2022 00:39:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=canonical.com; s=20210705; t=1651019950; bh=I7+zcYF8QLc268zL8zDKCWLmq8xiUApEbjYZ+StRn3U=; h=Message-ID:Date:MIME-Version:Subject:To:Cc:References:From: In-Reply-To:Content-Type; b=sNLQO6FS2xs5PHuaYB9mERrK7Gvh5Y1Ql0mHYv1KNL96j1Jt/nzu6xSrdE7t1JgYK YjLTjZ9VsxHcaFL56ZIqs5Wny+rMxXs0ed0Rsjd3qS1nzkloAOgIfPbdqqee6vXUJ8 ap+oLttRWdGEDH1TMnyTNro85gKafpFNnVlgW8QXjdfd3WLuQHkYHGMQL0Dqjw+fjl 2mTIsTHw3c6Ne9bxO90GYCFDS2t/HRjlIkkKe81KeBSAG3wyZof9wxZT9ESZaH5Zw7 EkLDVrPs3h7D6lgY1obxqpRfo7GF1WWpnY8AiCBglhaCj5iuzXoW9OsIYwbaDaBHVF h/d9YcSWD7Y8g== Message-ID: <1795819d-661a-3859-39e2-ba17a84508dd@canonical.com> Date: Tue, 26 Apr 2022 17:38:55 -0700 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.7.0 Subject: Re: [PATCH v35 08/29] LSM: Use lsmblob in security_secctx_to_secid Content-Language: en-US To: Casey Schaufler , casey.schaufler@intel.com, jmorris@namei.org, linux-security-module@vger.kernel.org, selinux@vger.kernel.org Cc: linux-audit@redhat.com, keescook@chromium.org, penguin-kernel@i-love.sakura.ne.jp, paul@paul-moore.com, stephen.smalley.work@gmail.com, linux-kernel@vger.kernel.org, netdev@vger.kernel.org, netfilter-devel@vger.kernel.org References: <20220418145945.38797-1-casey@schaufler-ca.com> <20220418145945.38797-9-casey@schaufler-ca.com> From: John Johansen Organization: Canonical In-Reply-To: <20220418145945.38797-9-casey@schaufler-ca.com> Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=-4.4 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,NICE_REPLY_A,RDNS_NONE,SPF_HELO_NONE autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On 4/18/22 07:59, Casey Schaufler wrote: > Change the security_secctx_to_secid interface to use a lsmblob > structure in place of the single u32 secid in support of > module stacking. Change its callers to do the same. > > The security module hook is unchanged, still passing back a secid. > The infrastructure passes the correct entry from the lsmblob. > > Acked-by: Paul Moore > Reviewed-by: Kees Cook > Signed-off-by: Casey Schaufler > Cc: netdev@vger.kernel.org > Cc: netfilter-devel@vger.kernel.org > To: Pablo Neira Ayuso Reviewed-by: John Johansen > --- > include/linux/security.h | 26 ++++++++++++++++++-- > kernel/cred.c | 4 +--- > net/netfilter/nft_meta.c | 10 ++++---- > net/netfilter/xt_SECMARK.c | 7 +++++- > net/netlabel/netlabel_unlabeled.c | 23 +++++++++++------- > security/security.c | 40 ++++++++++++++++++++++++++----- > 6 files changed, 85 insertions(+), 25 deletions(-) > > diff --git a/include/linux/security.h b/include/linux/security.h > index 68ab0add23d3..57879f0b9f89 100644 > --- a/include/linux/security.h > +++ b/include/linux/security.h > @@ -199,6 +199,27 @@ static inline bool lsmblob_equal(const struct lsmblob *bloba, > extern int lsm_name_to_slot(char *name); > extern const char *lsm_slot_to_name(int slot); > > +/** > + * lsmblob_value - find the first non-zero value in an lsmblob structure. > + * @blob: Pointer to the data > + * > + * This needs to be used with extreme caution, as the cases where > + * it is appropriate are rare. > + * > + * Return the first secid value set in the lsmblob. > + * There should only be one. > + */ > +static inline u32 lsmblob_value(const struct lsmblob *blob) > +{ > + int i; > + > + for (i = 0; i < LSMBLOB_ENTRIES; i++) > + if (blob->secid[i]) > + return blob->secid[i]; > + > + return 0; > +} > + > /* These functions are in security/commoncap.c */ > extern int cap_capable(const struct cred *cred, struct user_namespace *ns, > int cap, unsigned int opts); > @@ -529,7 +550,8 @@ int security_setprocattr(const char *lsm, const char *name, void *value, > int security_netlink_send(struct sock *sk, struct sk_buff *skb); > int security_ismaclabel(const char *name); > int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen); > -int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid); > +int security_secctx_to_secid(const char *secdata, u32 seclen, > + struct lsmblob *blob); > void security_release_secctx(char *secdata, u32 seclen); > void security_inode_invalidate_secctx(struct inode *inode); > int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen); > @@ -1384,7 +1406,7 @@ static inline int security_secid_to_secctx(u32 secid, char **secdata, u32 *secle > > static inline int security_secctx_to_secid(const char *secdata, > u32 seclen, > - u32 *secid) > + struct lsmblob *blob) > { > return -EOPNOTSUPP; > } > diff --git a/kernel/cred.c b/kernel/cred.c > index 3925d38f49f4..adea727744f4 100644 > --- a/kernel/cred.c > +++ b/kernel/cred.c > @@ -791,14 +791,12 @@ EXPORT_SYMBOL(set_security_override); > int set_security_override_from_ctx(struct cred *new, const char *secctx) > { > struct lsmblob blob; > - u32 secid; > int ret; > > - ret = security_secctx_to_secid(secctx, strlen(secctx), &secid); > + ret = security_secctx_to_secid(secctx, strlen(secctx), &blob); > if (ret < 0) > return ret; > > - lsmblob_init(&blob, secid); > return set_security_override(new, &blob); > } > EXPORT_SYMBOL(set_security_override_from_ctx); > diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c > index ac4859241e17..fc0028c9e33d 100644 > --- a/net/netfilter/nft_meta.c > +++ b/net/netfilter/nft_meta.c > @@ -860,21 +860,21 @@ static const struct nla_policy nft_secmark_policy[NFTA_SECMARK_MAX + 1] = { > > static int nft_secmark_compute_secid(struct nft_secmark *priv) > { > - u32 tmp_secid = 0; > + struct lsmblob blob; > int err; > > - err = security_secctx_to_secid(priv->ctx, strlen(priv->ctx), &tmp_secid); > + err = security_secctx_to_secid(priv->ctx, strlen(priv->ctx), &blob); > if (err) > return err; > > - if (!tmp_secid) > + if (!lsmblob_is_set(&blob)) > return -ENOENT; > > - err = security_secmark_relabel_packet(tmp_secid); > + err = security_secmark_relabel_packet(lsmblob_value(&blob)); > if (err) > return err; > > - priv->secid = tmp_secid; > + priv->secid = lsmblob_value(&blob); > return 0; > } > > diff --git a/net/netfilter/xt_SECMARK.c b/net/netfilter/xt_SECMARK.c > index 498a0bf6f044..87ca3a537d1c 100644 > --- a/net/netfilter/xt_SECMARK.c > +++ b/net/netfilter/xt_SECMARK.c > @@ -42,13 +42,14 @@ secmark_tg(struct sk_buff *skb, const struct xt_secmark_target_info_v1 *info) > > static int checkentry_lsm(struct xt_secmark_target_info_v1 *info) > { > + struct lsmblob blob; > int err; > > info->secctx[SECMARK_SECCTX_MAX - 1] = '\0'; > info->secid = 0; > > err = security_secctx_to_secid(info->secctx, strlen(info->secctx), > - &info->secid); > + &blob); > if (err) { > if (err == -EINVAL) > pr_info_ratelimited("invalid security context \'%s\'\n", > @@ -56,6 +57,10 @@ static int checkentry_lsm(struct xt_secmark_target_info_v1 *info) > return err; > } > > + /* xt_secmark_target_info can't be changed to use lsmblobs because > + * it is exposed as an API. Use lsmblob_value() to get the one > + * value that got set by security_secctx_to_secid(). */ > + info->secid = lsmblob_value(&blob); > if (!info->secid) { > pr_info_ratelimited("unable to map security context \'%s\'\n", > info->secctx); > diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c > index 8490e46359ae..f3e2cde76919 100644 > --- a/net/netlabel/netlabel_unlabeled.c > +++ b/net/netlabel/netlabel_unlabeled.c > @@ -880,7 +880,7 @@ static int netlbl_unlabel_staticadd(struct sk_buff *skb, > void *addr; > void *mask; > u32 addr_len; > - u32 secid; > + struct lsmblob blob; > struct netlbl_audit audit_info; > > /* Don't allow users to add both IPv4 and IPv6 addresses for a > @@ -904,13 +904,18 @@ static int netlbl_unlabel_staticadd(struct sk_buff *skb, > ret_val = security_secctx_to_secid( > nla_data(info->attrs[NLBL_UNLABEL_A_SECCTX]), > nla_len(info->attrs[NLBL_UNLABEL_A_SECCTX]), > - &secid); > + &blob); > if (ret_val != 0) > return ret_val; > > + /* netlbl_unlhsh_add will be changed to pass a struct lsmblob * > + * instead of a u32 later in this patch set. security_secctx_to_secid() > + * will only be setting one entry in the lsmblob struct, so it is > + * safe to use lsmblob_value() to get that one value. */ > + > return netlbl_unlhsh_add(&init_net, > - dev_name, addr, mask, addr_len, secid, > - &audit_info); > + dev_name, addr, mask, addr_len, > + lsmblob_value(&blob), &audit_info); > } > > /** > @@ -931,7 +936,7 @@ static int netlbl_unlabel_staticadddef(struct sk_buff *skb, > void *addr; > void *mask; > u32 addr_len; > - u32 secid; > + struct lsmblob blob; > struct netlbl_audit audit_info; > > /* Don't allow users to add both IPv4 and IPv6 addresses for a > @@ -953,13 +958,15 @@ static int netlbl_unlabel_staticadddef(struct sk_buff *skb, > ret_val = security_secctx_to_secid( > nla_data(info->attrs[NLBL_UNLABEL_A_SECCTX]), > nla_len(info->attrs[NLBL_UNLABEL_A_SECCTX]), > - &secid); > + &blob); > if (ret_val != 0) > return ret_val; > > + /* security_secctx_to_secid() will only put one secid into the lsmblob > + * so it's safe to use lsmblob_value() to get the secid. */ > return netlbl_unlhsh_add(&init_net, > - NULL, addr, mask, addr_len, secid, > - &audit_info); > + NULL, addr, mask, addr_len, > + lsmblob_value(&blob), &audit_info); > } > > /** > diff --git a/security/security.c b/security/security.c > index e9f1487af0e5..f814a41c5d9f 100644 > --- a/security/security.c > +++ b/security/security.c > @@ -2211,10 +2211,22 @@ int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) > } > EXPORT_SYMBOL(security_secid_to_secctx); > > -int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid) > +int security_secctx_to_secid(const char *secdata, u32 seclen, > + struct lsmblob *blob) > { > - *secid = 0; > - return call_int_hook(secctx_to_secid, 0, secdata, seclen, secid); > + struct security_hook_list *hp; > + int rc; > + > + 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; > + } > + return 0; > } > EXPORT_SYMBOL(security_secctx_to_secid); > > @@ -2365,10 +2377,26 @@ int security_socket_getpeersec_stream(struct socket *sock, char __user *optval, > optval, optlen, len); > } > > -int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid) > +int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, > + u32 *secid) > { > - return call_int_hook(socket_getpeersec_dgram, -ENOPROTOOPT, sock, > - skb, secid); > + struct security_hook_list *hp; > + int rc = -ENOPROTOOPT; > + > + /* > + * Only one security module should provide a real hook for > + * this. A stub or bypass like is used in BPF should either > + * (somehow) leave rc unaltered or return -ENOPROTOOPT. > + */ > + hlist_for_each_entry(hp, &security_hook_heads.socket_getpeersec_dgram, > + list) { > + if (WARN_ON(hp->lsmid->slot < 0 || hp->lsmid->slot >= lsm_slot)) > + continue; > + rc = hp->hook.socket_getpeersec_dgram(sock, skb, secid); > + if (rc != -ENOPROTOOPT) > + break; > + } > + return rc; > } > EXPORT_SYMBOL(security_socket_getpeersec_dgram); >