Re: [PATCH v22 05/23] LSM: Use lsmblob in security_secctx_to_secid

2020-11-09 Thread James Morris
On Wed, 4 Nov 2020, 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.
> 
> Signed-off-by: Casey Schaufler 
> Cc: net...@vger.kernel.org

You probably need to include Netfilter maintainers specifically for this 
(added them + the Netfilter list).

This also needs signoffs from LSM owners.

-- 
James Morris




[PATCH v22 05/23] LSM: Use lsmblob in security_secctx_to_secid

2020-11-04 Thread Casey Schaufler
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.

Signed-off-by: Casey Schaufler 
Cc: net...@vger.kernel.org
---
 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 948d12a5eb25..0766725a6b21 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -191,6 +191,27 @@ static inline bool lsmblob_equal(struct lsmblob *bloba, 
struct lsmblob *blobb)
return !memcmp(bloba, blobb, sizeof(*bloba));
 }
 
+/**
+ * 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);
@@ -508,7 +529,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);
@@ -1335,7 +1357,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 22e0e7cbefde..848306c7d823 100644
--- a/kernel/cred.c
+++ b/kernel/cred.c
@@ -757,14 +757,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 b37bd02448d8..f1b9b0021414 100644
--- a/net/netfilter/nft_meta.c
+++ b/net/netfilter/nft_meta.c
@@ -811,21 +811,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 75625d13e976..9845d98e6b77 100644
--- a/net/netfilter/xt_SECMARK.c
+++ b/net/netfilter/xt_SECMARK.c
@@ -43,13 +43,14 @@ secmark_tg(struct sk_buff *skb, const struct 
xt_action_param *par)
 
 static int checkentry_lsm(struct xt_secmark_target_info *info)
 {
+   struct lsmblob blob;
int err;
 
info->secctx[SECMARK_SECCTX_MAX - 1] = '\0';
info->secid = 0;
 
err = security_secctx_to_secid(info->secctx, s

[PATCH v22 05/23] LSM: Use lsmblob in security_secctx_to_secid

2020-11-04 Thread Casey Schaufler
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.

Signed-off-by: Casey Schaufler 
Cc: net...@vger.kernel.org
---
 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 948d12a5eb25..0766725a6b21 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -191,6 +191,27 @@ static inline bool lsmblob_equal(struct lsmblob *bloba, 
struct lsmblob *blobb)
return !memcmp(bloba, blobb, sizeof(*bloba));
 }
 
+/**
+ * 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);
@@ -508,7 +529,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);
@@ -1335,7 +1357,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 22e0e7cbefde..848306c7d823 100644
--- a/kernel/cred.c
+++ b/kernel/cred.c
@@ -757,14 +757,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 b37bd02448d8..f1b9b0021414 100644
--- a/net/netfilter/nft_meta.c
+++ b/net/netfilter/nft_meta.c
@@ -811,21 +811,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 75625d13e976..9845d98e6b77 100644
--- a/net/netfilter/xt_SECMARK.c
+++ b/net/netfilter/xt_SECMARK.c
@@ -43,13 +43,14 @@ secmark_tg(struct sk_buff *skb, const struct 
xt_action_param *par)
 
 static int checkentry_lsm(struct xt_secmark_target_info *info)
 {
+   struct lsmblob blob;
int err;
 
info->secctx[SECMARK_SECCTX_MAX - 1] = '\0';
info->secid = 0;
 
err = security_secctx_to_secid(info->secctx, s