linux-integrity.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v10 0/4] evm: Do HMAC of multiple per LSM xattrs for new inodes
@ 2023-03-31 12:32 Roberto Sassu
  2023-03-31 12:32 ` [PATCH v10 1/4] reiserfs: Add security prefix to xattr name in reiserfs_security_write() Roberto Sassu
                   ` (4 more replies)
  0 siblings, 5 replies; 44+ messages in thread
From: Roberto Sassu @ 2023-03-31 12:32 UTC (permalink / raw)
  To: zohar, dmitry.kasatkin, paul, jmorris, serge,
	stephen.smalley.work, eparis, casey
  Cc: reiserfs-devel, linux-kernel, linux-integrity,
	linux-security-module, selinux, bpf, kpsingh, keescook,
	nicolas.bouchinet, Roberto Sassu

From: Roberto Sassu <roberto.sassu@huawei.com>

One of the major goals of LSM stacking is to run multiple LSMs side by side
without interfering with each other. The ultimate decision will depend on
individual LSM decision.

Several changes need to be made to the LSM infrastructure to be able to
support that. This patch set tackles one of them: gives to each LSM the
ability to specify one or multiple xattrs to be set at inode creation
time and, at the same time, gives to EVM the ability to access all those
xattrs and calculate the HMAC on them.

The first problem that this patch set addresses is to make the
inode_init_security hook definition suitable to use with EVM which, unlike
other LSMs, needs to have visibility of all xattrs and not only the one
that the LSM infrastructure passes to the LSM to be set.

The solution is to replace in the inode_init_security definition the
name/value/len parameters with the beginning of the array containing all
xattrs set by LSMs. Due to security_old_inode_init_security() API
limitation of setting only one xattr, it has been dropped and the remaining
users, ocfs2 and reiserfs, switch to security_inode_init_security().
However, due to the complexity of the changes required to fully exploit the
ability of security_inode_init_security() to set multiple xattrs, those
users can still set only one xattr (the first set in the xattr array) where
previously they called security_old_inode_init_security().

Furthermore, while EVM is invoked unlike before, its xattr will not be set
as it would not be the first set in the xattr array, or if it is the first,
there would not be protected xattrs to calculate the HMAC on.

Reiserfs, regardless of the switch had anyway another problem: it was
setting xattrs without the security prefix in the xattr name. That has been
solved too, by writing the full xattr name in a temporary buffer, before
passing it to the function which actually writes the xattr.

The second problem this patch set addresses is the limitation of the
call_int_hook() of stopping the loop when the return value from a hook
implementation is not zero. Unfortunately, for the inode_init_security hook
it is a legitimate case to return -EOPNOTSUPP, but this would not
necessarily mean that there is an error to report to the LSM infrastructure
but just that an LSM does not will to set an xattr. Other LSMs should be
still consulted as well.

The solution for this specific case is to replace the call_int_hook() with
the loop itself, so that -EOPNOTSUPP can be ignored. In addition, the
default return value of inode_init_security was changed to -EOPNOTSUPP, so
that BPF LSM follows the return value convention.

Next, this patch set removes the limitation of creating only two xattrs,
one by an active LSM and another by EVM. This patch set extends the
reservation mechanism of the LSM infrastructure, to allow each LSM to
request one or multiple xattrs. While this could potentially lead to
reaching the filesystem limits of number/size of the xattrs, it seems not
an issue that need to be solved by the LSM infrastructure but by the
filesystems themselves. Currently, if the limit is reached, the only
workaround would be to use fewer LSMs.

The reservation mechanism concept would have made it very easy for LSMs to
position themselves correctly in the xattr array, as the LSM infrastructure
at initialization time changes the number of xattrs requested by each LSM
with an offset.

However, this opens for the possibility of having gaps in the xattr array,
due to the fact that an LSM can request xattr slots to the LSM
infrastructure but not fill them (if it was loaded but not initialized).

Instead, the decision was to add an additional parameter to the
inode_init_security_hook, the number of filled slots in the xattr array,
which each LSM is expected to update for each xattr it provides. In this
way, the next LSM starts to fill after the last filled slot, regardless of
whether previous LSMs were initialized or not. SELinux, Smack and EVM have
been updated to use this new mechanism.

Finally, this patch set modifies the evm_inode_init_security() definition
to be compatible with the inode_init_security hook definition and adds
support for scanning the whole xattr array and for calculating the HMAC
on all xattrs provided by LSMs.

This patch set has been tested by introducing several instances of a
TestLSM (some providing an xattr, some not, one providing multiple xattrs
and another providing an xattr but in a disabled state). The patch is not
included in this set but it is available here:

https://github.com/robertosassu/linux/commit/f480654459f0501dad210e89eb7fb932415940c7

The test, added to ima-evm-utils, is available here:

https://github.com/robertosassu/ima-evm-utils/blob/evm-multiple-lsms-v10-devel-v1/tests/evm_multiple_lsms.test

The test takes a UML kernel built by Github Actions and launches it several
times, each time with a different combination of LSMs and filesystems (ext4,
reiserfs, ocfs2). After boot, it first checks that there is an xattr for each
LSM providing it (for reiserfs and ocfs2 just the first LSM), and then (for
ext4) calculates the HMAC in user space and compares it with the HMAC
calculated by EVM in kernel space.

A test report can be obtained here:

https://github.com/robertosassu/ima-evm-utils/actions/runs/4573146812/jobs/8074209275

The patch set has been tested with both the SElinux and Smack test suites.
Below, there is the summary of the test results:

SELinux Test Suite result (without patches):
All tests successful.
Files=76, Tests=1357, 230 wallclock secs ( 0.41 usr  0.14 sys + 12.27 cusr 16.04 csys = 28.86 CPU)
Result: PASS

SELinux Test Suite result (with patches):
All tests successful.
Files=76, Tests=1357, 228 wallclock secs ( 0.43 usr  0.12 sys + 12.31 cusr 15.13 csys = 27.99 CPU)
Result: PASS

Smack Test Suite result (without patches):
95 Passed, 0 Failed, 100% Success rate

Smack Test Suite result (with patches):
95 Passed, 0 Failed, 100% Success rate

Changelog

v9:
- Ensure in reiserfs_security_write() that the full xattr name is not
  larger than XATTR_NAME_MAX
- Rename num_filled_xattrs to xattr_count everywhere (suggested by Paul)
- Rename lsm_find_xattr_slot() to lsm_get_xattr_slot() and add a proper
  documentation (suggested by Paul)
- Return zero instead of -EOPNOTSUPP in evm_inode_init_security()
  (suggested by Paul)
- Remove additional checks of new_xattrs array in
  security_inode_init_security() (suggested by Paul)
- Handle the !initxattrs case similarly to the initxattrs case, except for
  not allocating the new_xattrs array in the former (suggested by Paul)
- Remove local variable xattr in security_inode_init_security(), and use
  xattr_count instead for loop termination (suggested by Paul)

v8:
- Add a new reiserfs patch to write the full xattr name
- Add num_filled_xattrs parameter to inode_init_security hook (suggested by
  Paul) and evm_inode_init_security()
- Change default return value of inode_init_security hook to -EOPNOTSUPP
- Rename lbs_xattr field of lsm_blob_sizes to lbs_xattr_count
- Introduce lsm_find_xattr_slot() helper
- Rename lsm_xattr parameter of evm_init_hmac() to xattrs
- Retrieve the EVM xattr slot with lsm_find_xattr_slot() and double check
  with the xattr array terminator
- Remove security_check_compact_filled_xattrs() (suggested by Paul)
- Update security_inode_init_security() documentation
- Ensure that inode_init_security hook incremented the number of filled
  slots if it returned zero
- Ensure that xattr name and value are non-NULL in the filled slots
- Add the xattr name assignment after the xattr value one (suggested by
  Paul)
- Drop patches 1 - 3 (already in lsm/next)

v7:
- Add a patch dependency comment in patch 1 (suggested by Mimi)
- Restore check of -EOPNOTSUPP status in ocfs2_mknod() and ocfs2_symlink()
  (reported by Mimi)
- Add explanation in evm_inode_init_security() why walking through the
  xattrs array is safe (suggested by Mimi)
- Document the lbs_xattr field of struct lsm_blob_sizes (suggested by
  Casey)
- Move documentation changes of the inode_init_security hook to security.c,
  after LSM documentation reorganization by Paul
- Use attributes in plural form in the description of the xattrs parameter
  of smack_inode_init_security()
- Check xattr name instead of xattr value in evm_inode_init_security(),
  for consistency with evm_init_hmac(); equivalent, since
  security_check_compact_filled_xattrs() rejects xattrs with xattr name
  NULL and value not NULL, and viceversa

v6:
- Add a comment in Smack to introduce its xattrs (suggested by Casey)
- Document the overloaded meaning of -EOPNOTSUPP in
  security_inode_init_security() (suggested by Mimi)

v5:
- Modify the cover letter to explain that the goal of this patch set is
  supporting multiple per LSM xattrs in EVM, and not moving IMA and EVM to
  the LSM infrastructure (suggested by Mimi)
- Remove references in the patches description about moving IMA and EVM
  to the LSM infrastructure (suggested by Mimi)
- Explain that the additional EVM invocation due to the switch to
  security_inode_init_security() will not cause the EVM xattr to be added
  (suggested by Mimi)

v4:
- Remove patch to call reiserfs_security_free(), already queued
- Switch ocfs2 and reiserfs to security_inode_init_security() (suggested by
  Mimi)
- Remove security_old_inode_init_security() (suggested by Paul)
- Rename security_check_compact_xattrs() to
  security_check_compact_filled_xattrs() and add function description
  (suggested by Mimi)
- Rename checked_xattrs parameter of security_check_compact_filled_xattrs()
  to num_filled_xattrs (suggested by Mimi)
- Rename cur_xattrs variable in security_inode_init_security() to
  num_filled_xattrs (suggested by Mimi)

v3:
- Don't free the xattr name in reiserfs_security_free()
- Don't include fs_data parameter in inode_init_security hook
- Don't change evm_inode_init_security(), as it will be removed if EVM is
  stacked
- Fix inode_init_security hook documentation
- Drop lsm_find_xattr_slot(), use simple xattr reservation mechanism and
  introduce security_check_compact_xattrs() to compact the xattr array
- Don't allocate xattr array if LSMs didn't reserve any xattr
- Return zero if initxattrs() is not provided to
  security_inode_init_security(), -EOPNOTSUPP if value is not provided to
  security_old_inode_init_security()
- Request LSMs to fill xattrs if only value (not the triple) is provided to
  security_old_inode_init_security(), to avoid unnecessary memory
  allocation

v2:
- rewrite selinux_old_inode_init_security() to use
  security_inode_init_security()
- add lbs_xattr field to lsm_blob_sizes structure, to give the ability to
  LSMs to reserve slots in the xattr array (suggested by Casey)
- add new parameter base_slot to inode_init_security hook definition

v1:
- add calls to reiserfs_security_free() and initialize sec->value to NULL
  (suggested by Tetsuo and Mimi)
- change definition of inode_init_security hook, replace the name, value
  and len triple with the xattr array (suggested by Casey)
- introduce lsm_find_xattr_slot() helper for LSMs to find an unused slot in
  the passed xattr array

Roberto Sassu (4):
  reiserfs: Add security prefix to xattr name in
    reiserfs_security_write()
  security: Allow all LSMs to provide xattrs for inode_init_security
    hook
  evm: Align evm_inode_init_security() definition with LSM
    infrastructure
  evm: Support multiple LSMs providing an xattr

 fs/reiserfs/xattr_security.c        |  8 +++-
 include/linux/evm.h                 | 13 ++---
 include/linux/lsm_hook_defs.h       |  6 +--
 include/linux/lsm_hooks.h           | 20 ++++++++
 security/integrity/evm/evm.h        |  4 +-
 security/integrity/evm/evm_crypto.c | 11 ++++-
 security/integrity/evm/evm_main.c   | 39 ++++++++++++---
 security/security.c                 | 73 +++++++++++++++++++----------
 security/selinux/hooks.c            | 17 +++----
 security/smack/smack_lsm.c          | 32 ++++++++-----
 10 files changed, 157 insertions(+), 66 deletions(-)

-- 
2.25.1


^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH v10 1/4] reiserfs: Add security prefix to xattr name in reiserfs_security_write()
  2023-03-31 12:32 [PATCH v10 0/4] evm: Do HMAC of multiple per LSM xattrs for new inodes Roberto Sassu
@ 2023-03-31 12:32 ` Roberto Sassu
  2023-04-04 18:25   ` Paul Moore
  2023-03-31 12:32 ` [PATCH v10 2/4] security: Allow all LSMs to provide xattrs for inode_init_security hook Roberto Sassu
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 44+ messages in thread
From: Roberto Sassu @ 2023-03-31 12:32 UTC (permalink / raw)
  To: zohar, dmitry.kasatkin, paul, jmorris, serge,
	stephen.smalley.work, eparis, casey
  Cc: reiserfs-devel, linux-kernel, linux-integrity,
	linux-security-module, selinux, bpf, kpsingh, keescook,
	nicolas.bouchinet, Roberto Sassu, stable

From: Roberto Sassu <roberto.sassu@huawei.com>

Reiserfs sets a security xattr at inode creation time in two stages: first,
it calls reiserfs_security_init() to obtain the xattr from active LSMs;
then, it calls reiserfs_security_write() to actually write that xattr.

Unfortunately, it seems there is a wrong expectation that LSMs provide the
full xattr name in the form 'security.<suffix>'. However, LSMs always
provided just the suffix, causing reiserfs to not write the xattr at all
(if the suffix is shorter than the prefix), or to write an xattr with the
wrong name.

Add a temporary buffer in reiserfs_security_write(), and write to it the
full xattr name, before passing it to reiserfs_xattr_set_handle().

Also replace the name length check with a check that the full xattr name is
not larger than XATTR_NAME_MAX.

Cc: stable@vger.kernel.org # v2.6.x
Fixes: 57fe60df6241 ("reiserfs: add atomic addition of selinux attributes during inode creation")
Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
---
 fs/reiserfs/xattr_security.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/fs/reiserfs/xattr_security.c b/fs/reiserfs/xattr_security.c
index 6bffdf9a4fd..6e0a099dd78 100644
--- a/fs/reiserfs/xattr_security.c
+++ b/fs/reiserfs/xattr_security.c
@@ -95,11 +95,15 @@ int reiserfs_security_write(struct reiserfs_transaction_handle *th,
 			    struct inode *inode,
 			    struct reiserfs_security_handle *sec)
 {
+	char xattr_name[XATTR_NAME_MAX + 1] = XATTR_SECURITY_PREFIX;
 	int error;
-	if (strlen(sec->name) < sizeof(XATTR_SECURITY_PREFIX))
+
+	if (XATTR_SECURITY_PREFIX_LEN + strlen(sec->name) > XATTR_NAME_MAX)
 		return -EINVAL;
 
-	error = reiserfs_xattr_set_handle(th, inode, sec->name, sec->value,
+	strlcat(xattr_name, sec->name, sizeof(xattr_name));
+
+	error = reiserfs_xattr_set_handle(th, inode, xattr_name, sec->value,
 					  sec->length, XATTR_CREATE);
 	if (error == -ENODATA || error == -EOPNOTSUPP)
 		error = 0;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v10 2/4] security: Allow all LSMs to provide xattrs for inode_init_security hook
  2023-03-31 12:32 [PATCH v10 0/4] evm: Do HMAC of multiple per LSM xattrs for new inodes Roberto Sassu
  2023-03-31 12:32 ` [PATCH v10 1/4] reiserfs: Add security prefix to xattr name in reiserfs_security_write() Roberto Sassu
@ 2023-03-31 12:32 ` Roberto Sassu
  2023-04-04 18:54   ` Paul Moore
  2023-04-11  7:22   ` Mimi Zohar
  2023-03-31 12:32 ` [PATCH v10 3/4] evm: Align evm_inode_init_security() definition with LSM infrastructure Roberto Sassu
                   ` (2 subsequent siblings)
  4 siblings, 2 replies; 44+ messages in thread
From: Roberto Sassu @ 2023-03-31 12:32 UTC (permalink / raw)
  To: zohar, dmitry.kasatkin, paul, jmorris, serge,
	stephen.smalley.work, eparis, casey
  Cc: reiserfs-devel, linux-kernel, linux-integrity,
	linux-security-module, selinux, bpf, kpsingh, keescook,
	nicolas.bouchinet, Roberto Sassu

From: Roberto Sassu <roberto.sassu@huawei.com>

Currently, security_inode_init_security() supports only one LSM providing
an xattr and EVM calculating the HMAC on that xattr, plus other inode
metadata.

Allow all LSMs to provide one or multiple xattrs, by extending the security
blob reservation mechanism. Introduce the new lbs_xattr_count field of the
lsm_blob_sizes structure, so that each LSM can specify how many xattrs it
needs, and the LSM infrastructure knows how many xattr slots it should
allocate.

Dynamically allocate the new_xattrs array to be populated by LSMs with the
inode_init_security hook, and pass it to the latter instead of the
name/value/len triple. Unify the !initxattrs and initxattrs case, simply
don't allocate the new_xattrs array in the former.

Also, pass to the hook the number of xattrs filled by each LSM, so that
there are no gaps when the next LSM fills the array. Gaps might occur
because an LSM can legitimately request xattrs to the LSM infrastructure,
but not fill the reserved slots, if it was not initialized.

Update the documentation of security_inode_init_security() to reflect the
changes, and fix the description of the xattr name, as it is not allocated
anymore.

Finally, adapt both SELinux and Smack to use the new definition of the
inode_init_security hook, and to fill the reserved slots in the xattr
array. Introduce the lsm_get_xattr_slot() helper to retrieve an available
slot to fill, and to increment the number of filled slots.

Move the xattr->name assignment after the xattr->value one, so that it is
done only in case of successful memory allocation. For Smack, also reserve
space for the other defined xattrs although they are not set yet in
smack_inode_init_security().

Reported-by: Nicolas Bouchinet <nicolas.bouchinet@clip-os.org> (EVM crash)
Link: https://lore.kernel.org/linux-integrity/Y1FTSIo+1x+4X0LS@archlinux/
Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
---
 include/linux/lsm_hook_defs.h |  6 +--
 include/linux/lsm_hooks.h     | 20 ++++++++++
 security/security.c           | 71 +++++++++++++++++++++++------------
 security/selinux/hooks.c      | 17 +++++----
 security/smack/smack_lsm.c    | 32 ++++++++++------
 5 files changed, 99 insertions(+), 47 deletions(-)

diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h
index 6bb55e61e8e..a1896f90089 100644
--- a/include/linux/lsm_hook_defs.h
+++ b/include/linux/lsm_hook_defs.h
@@ -111,9 +111,9 @@ LSM_HOOK(int, 0, path_notify, const struct path *path, u64 mask,
 	 unsigned int obj_type)
 LSM_HOOK(int, 0, inode_alloc_security, struct inode *inode)
 LSM_HOOK(void, LSM_RET_VOID, inode_free_security, struct inode *inode)
-LSM_HOOK(int, 0, inode_init_security, struct inode *inode,
-	 struct inode *dir, const struct qstr *qstr, const char **name,
-	 void **value, size_t *len)
+LSM_HOOK(int, -EOPNOTSUPP, inode_init_security, struct inode *inode,
+	 struct inode *dir, const struct qstr *qstr, struct xattr *xattrs,
+	 int *xattr_count)
 LSM_HOOK(int, 0, inode_init_security_anon, struct inode *inode,
 	 const struct qstr *name, const struct inode *context_inode)
 LSM_HOOK(int, 0, inode_create, struct inode *dir, struct dentry *dentry,
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index c2be66c669a..9eb9b686493 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -28,6 +28,7 @@
 #include <linux/security.h>
 #include <linux/init.h>
 #include <linux/rculist.h>
+#include <linux/xattr.h>
 
 union security_list_options {
 	#define LSM_HOOK(RET, DEFAULT, NAME, ...) RET (*NAME)(__VA_ARGS__);
@@ -63,8 +64,27 @@ struct lsm_blob_sizes {
 	int	lbs_ipc;
 	int	lbs_msg_msg;
 	int	lbs_task;
+	int	lbs_xattr_count; /* number of xattr slots in new_xattrs array */
 };
 
+/**
+ * lsm_get_xattr_slot - Return the next available slot and increment the index
+ * @xattrs: array storing LSM-provided xattrs
+ * @xattr_count: number of already stored xattrs (updated)
+ *
+ * Retrieve the first available slot in the @xattrs array to fill with an xattr,
+ * and increment @xattr_count.
+ *
+ * Return: The slot to fill in @xattrs if non-NULL, NULL otherwise.
+ */
+static inline struct xattr *lsm_get_xattr_slot(struct xattr *xattrs,
+					       int *xattr_count)
+{
+	if (unlikely(!xattrs))
+		return NULL;
+	return xattrs + (*xattr_count)++;
+}
+
 /*
  * LSM_RET_VOID is used as the default value in LSM_HOOK definitions for void
  * LSM hooks (in include/linux/lsm_hook_defs.h).
diff --git a/security/security.c b/security/security.c
index f4170efcddd..1aeaa8ce449 100644
--- a/security/security.c
+++ b/security/security.c
@@ -31,8 +31,6 @@
 #include <linux/msg.h>
 #include <net/flow.h>
 
-#define MAX_LSM_EVM_XATTR	2
-
 /* How many LSMs were built into the kernel? */
 #define LSM_COUNT (__end_lsm_info - __start_lsm_info)
 
@@ -212,6 +210,8 @@ static void __init lsm_set_blob_sizes(struct lsm_blob_sizes *needed)
 	lsm_set_blob_size(&needed->lbs_msg_msg, &blob_sizes.lbs_msg_msg);
 	lsm_set_blob_size(&needed->lbs_superblock, &blob_sizes.lbs_superblock);
 	lsm_set_blob_size(&needed->lbs_task, &blob_sizes.lbs_task);
+	lsm_set_blob_size(&needed->lbs_xattr_count,
+			  &blob_sizes.lbs_xattr_count);
 }
 
 /* Prepare LSM for initialization. */
@@ -378,6 +378,7 @@ static void __init ordered_lsm_init(void)
 	init_debug("msg_msg blob size    = %d\n", blob_sizes.lbs_msg_msg);
 	init_debug("superblock blob size = %d\n", blob_sizes.lbs_superblock);
 	init_debug("task blob size       = %d\n", blob_sizes.lbs_task);
+	init_debug("xattr slots          = %d\n", blob_sizes.lbs_xattr_count);
 
 	/*
 	 * Create any kmem_caches needed for blobs
@@ -1591,11 +1592,15 @@ EXPORT_SYMBOL(security_dentry_create_files_as);
  * created inode and set up the incore security field for the new inode.  This
  * hook is called by the fs code as part of the inode creation transaction and
  * provides for atomic labeling of the inode, unlike the post_create/mkdir/...
- * hooks called by the VFS.  The hook function is expected to allocate the name
- * and value via kmalloc, with the caller being responsible for calling kfree
- * after using them.  If the security module does not use security attributes
- * or does not wish to put a security attribute on this particular inode, then
- * it should return -EOPNOTSUPP to skip this processing.
+ * hooks called by the VFS.  The hook function is expected to populate the
+ * @xattrs array, by calling lsm_get_xattr_slot() to retrieve the slots
+ * reserved by the security module with the lbs_xattr_count field of the
+ * lsm_blob_sizes structure.  For each slot, the hook function should set ->name
+ * to the attribute name suffix (e.g. selinux), to allocate ->value (will be
+ * freed by the caller) and set it to the attribute value, to set ->value_len to
+ * the length of the value.  If the security module does not use security
+ * attributes or does not wish to put a security attribute on this particular
+ * inode, then it should return -EOPNOTSUPP to skip this processing.
  *
  * Return: Returns 0 on success, -EOPNOTSUPP if no security attribute is
  * needed, or -ENOMEM on memory allocation failure.
@@ -1604,33 +1609,51 @@ int security_inode_init_security(struct inode *inode, struct inode *dir,
 				 const struct qstr *qstr,
 				 const initxattrs initxattrs, void *fs_data)
 {
-	struct xattr new_xattrs[MAX_LSM_EVM_XATTR + 1];
-	struct xattr *lsm_xattr, *evm_xattr, *xattr;
-	int ret;
+	struct security_hook_list *P;
+	struct xattr *new_xattrs = NULL;
+	int ret = -EOPNOTSUPP, xattr_count = 0;
 
 	if (unlikely(IS_PRIVATE(inode)))
 		return 0;
 
-	if (!initxattrs)
-		return call_int_hook(inode_init_security, -EOPNOTSUPP, inode,
-				     dir, qstr, NULL, NULL, NULL);
-	memset(new_xattrs, 0, sizeof(new_xattrs));
-	lsm_xattr = new_xattrs;
-	ret = call_int_hook(inode_init_security, -EOPNOTSUPP, inode, dir, qstr,
-			    &lsm_xattr->name,
-			    &lsm_xattr->value,
-			    &lsm_xattr->value_len);
-	if (ret)
+	if (!blob_sizes.lbs_xattr_count)
+		return 0;
+
+	if (initxattrs) {
+		/* Allocate +1 for EVM and +1 as terminator. */
+		new_xattrs = kcalloc(blob_sizes.lbs_xattr_count + 2,
+				     sizeof(*new_xattrs), GFP_NOFS);
+		if (!new_xattrs)
+			return -ENOMEM;
+	}
+
+	hlist_for_each_entry(P, &security_hook_heads.inode_init_security,
+			     list) {
+		ret = P->hook.inode_init_security(inode, dir, qstr, new_xattrs,
+						  &xattr_count);
+		if (ret && ret != -EOPNOTSUPP)
+			goto out;
+		/*
+		 * As documented in lsm_hooks.h, -EOPNOTSUPP in this context
+		 * means that the LSM is not willing to provide an xattr, not
+		 * that it wants to signal an error. Thus, continue to invoke
+		 * the remaining LSMs.
+		 */
+	}
+
+	/* If initxattrs() is NULL, xattr_count is zero, skip the call. */
+	if (!xattr_count)
 		goto out;
 
-	evm_xattr = lsm_xattr + 1;
-	ret = evm_inode_init_security(inode, lsm_xattr, evm_xattr);
+	ret = evm_inode_init_security(inode, new_xattrs,
+				      new_xattrs + xattr_count);
 	if (ret)
 		goto out;
 	ret = initxattrs(inode, new_xattrs, fs_data);
 out:
-	for (xattr = new_xattrs; xattr->value != NULL; xattr++)
-		kfree(xattr->value);
+	for (; xattr_count > 0; xattr_count--)
+		kfree(new_xattrs[xattr_count - 1].value);
+	kfree(new_xattrs);
 	return (ret == -EOPNOTSUPP) ? 0 : ret;
 }
 EXPORT_SYMBOL(security_inode_init_security);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 9a5bdfc2131..882d6383b17 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -104,6 +104,8 @@
 #include "audit.h"
 #include "avc_ss.h"
 
+#define SELINUX_INODE_INIT_XATTRS 1
+
 struct selinux_state selinux_state;
 
 /* SECMARK reference count */
@@ -2868,11 +2870,11 @@ static int selinux_dentry_create_files_as(struct dentry *dentry, int mode,
 
 static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
 				       const struct qstr *qstr,
-				       const char **name,
-				       void **value, size_t *len)
+				       struct xattr *xattrs, int *xattr_count)
 {
 	const struct task_security_struct *tsec = selinux_cred(current_cred());
 	struct superblock_security_struct *sbsec;
+	struct xattr *xattr = lsm_get_xattr_slot(xattrs, xattr_count);
 	u32 newsid, clen;
 	int rc;
 	char *context;
@@ -2899,16 +2901,14 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
 	    !(sbsec->flags & SBLABEL_MNT))
 		return -EOPNOTSUPP;
 
-	if (name)
-		*name = XATTR_SELINUX_SUFFIX;
-
-	if (value && len) {
+	if (xattr) {
 		rc = security_sid_to_context_force(&selinux_state, newsid,
 						   &context, &clen);
 		if (rc)
 			return rc;
-		*value = context;
-		*len = clen;
+		xattr->value = context;
+		xattr->value_len = clen;
+		xattr->name = XATTR_SELINUX_SUFFIX;
 	}
 
 	return 0;
@@ -6918,6 +6918,7 @@ struct lsm_blob_sizes selinux_blob_sizes __lsm_ro_after_init = {
 	.lbs_ipc = sizeof(struct ipc_security_struct),
 	.lbs_msg_msg = sizeof(struct msg_security_struct),
 	.lbs_superblock = sizeof(struct superblock_security_struct),
+	.lbs_xattr_count = SELINUX_INODE_INIT_XATTRS,
 };
 
 #ifdef CONFIG_PERF_EVENTS
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index cfcbb748da2..8392983334b 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -52,6 +52,15 @@
 #define SMK_RECEIVING	1
 #define SMK_SENDING	2
 
+/*
+ * Smack uses multiple xattrs.
+ * SMACK64 - for access control, SMACK64EXEC - label for the program,
+ * SMACK64MMAP - controls library loading,
+ * SMACK64TRANSMUTE - label initialization,
+ * Not saved on files - SMACK64IPIN and SMACK64IPOUT
+ */
+#define SMACK_INODE_INIT_XATTRS 4
+
 #ifdef SMACK_IPV6_PORT_LABELING
 static DEFINE_MUTEX(smack_ipv6_lock);
 static LIST_HEAD(smk_ipv6_port_list);
@@ -939,26 +948,23 @@ static int smack_inode_alloc_security(struct inode *inode)
  * @inode: the newly created inode
  * @dir: containing directory object
  * @qstr: unused
- * @name: where to put the attribute name
- * @value: where to put the attribute value
- * @len: where to put the length of the attribute
+ * @xattrs: where to put the attributes
+ * @xattr_count: current number of LSM-provided xattrs (updated)
  *
  * Returns 0 if it all works out, -ENOMEM if there's no memory
  */
 static int smack_inode_init_security(struct inode *inode, struct inode *dir,
-				     const struct qstr *qstr, const char **name,
-				     void **value, size_t *len)
+				     const struct qstr *qstr,
+				     struct xattr *xattrs, int *xattr_count)
 {
 	struct inode_smack *issp = smack_inode(inode);
 	struct smack_known *skp = smk_of_current();
 	struct smack_known *isp = smk_of_inode(inode);
 	struct smack_known *dsp = smk_of_inode(dir);
+	struct xattr *xattr = lsm_get_xattr_slot(xattrs, xattr_count);
 	int may;
 
-	if (name)
-		*name = XATTR_SMACK_SUFFIX;
-
-	if (value && len) {
+	if (xattr) {
 		rcu_read_lock();
 		may = smk_access_entry(skp->smk_known, dsp->smk_known,
 				       &skp->smk_rules);
@@ -976,11 +982,12 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
 			issp->smk_flags |= SMK_INODE_CHANGED;
 		}
 
-		*value = kstrdup(isp->smk_known, GFP_NOFS);
-		if (*value == NULL)
+		xattr->value = kstrdup(isp->smk_known, GFP_NOFS);
+		if (xattr->value == NULL)
 			return -ENOMEM;
 
-		*len = strlen(isp->smk_known);
+		xattr->value_len = strlen(isp->smk_known);
+		xattr->name = XATTR_SMACK_SUFFIX;
 	}
 
 	return 0;
@@ -4854,6 +4861,7 @@ struct lsm_blob_sizes smack_blob_sizes __lsm_ro_after_init = {
 	.lbs_ipc = sizeof(struct smack_known *),
 	.lbs_msg_msg = sizeof(struct smack_known *),
 	.lbs_superblock = sizeof(struct superblock_smack),
+	.lbs_xattr_count = SMACK_INODE_INIT_XATTRS,
 };
 
 static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v10 3/4] evm: Align evm_inode_init_security() definition with LSM infrastructure
  2023-03-31 12:32 [PATCH v10 0/4] evm: Do HMAC of multiple per LSM xattrs for new inodes Roberto Sassu
  2023-03-31 12:32 ` [PATCH v10 1/4] reiserfs: Add security prefix to xattr name in reiserfs_security_write() Roberto Sassu
  2023-03-31 12:32 ` [PATCH v10 2/4] security: Allow all LSMs to provide xattrs for inode_init_security hook Roberto Sassu
@ 2023-03-31 12:32 ` Roberto Sassu
  2023-04-04 18:56   ` Paul Moore
  2023-04-11  7:22   ` Mimi Zohar
  2023-03-31 12:32 ` [PATCH v10 4/4] evm: Support multiple LSMs providing an xattr Roberto Sassu
  2023-04-03 10:36 ` [PATCH v10 0/4] evm: Do HMAC of multiple per LSM xattrs for new inodes Mimi Zohar
  4 siblings, 2 replies; 44+ messages in thread
From: Roberto Sassu @ 2023-03-31 12:32 UTC (permalink / raw)
  To: zohar, dmitry.kasatkin, paul, jmorris, serge,
	stephen.smalley.work, eparis, casey
  Cc: reiserfs-devel, linux-kernel, linux-integrity,
	linux-security-module, selinux, bpf, kpsingh, keescook,
	nicolas.bouchinet, Roberto Sassu

From: Roberto Sassu <roberto.sassu@huawei.com>

Change the evm_inode_init_security() definition to align with the LSM
infrastructure. Keep the existing behavior of including in the HMAC
calculation only the first xattr provided by LSMs.

Changing the evm_inode_init_security() definition requires passing the
xattr array allocated by security_inode_init_security(), and the number of
xattrs filled by previously invoked LSMs.

Use the newly introduced lsm_get_xattr_slot() to position EVM correctly in
the xattrs array, like a regular LSM, and to increment the number of filled
slots. For now, the LSM infrastructure allocates enough xattrs slots to
store the EVM xattr, without using the reservation mechanism.

Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
---
 include/linux/evm.h               | 13 +++++++------
 security/integrity/evm/evm_main.c | 16 ++++++++++------
 security/security.c               |  6 +++---
 3 files changed, 20 insertions(+), 15 deletions(-)

diff --git a/include/linux/evm.h b/include/linux/evm.h
index 7dc1ee74169..597632c71c7 100644
--- a/include/linux/evm.h
+++ b/include/linux/evm.h
@@ -56,9 +56,9 @@ static inline void evm_inode_post_set_acl(struct dentry *dentry,
 {
 	return evm_inode_post_setxattr(dentry, acl_name, NULL, 0);
 }
-extern int evm_inode_init_security(struct inode *inode,
-				   const struct xattr *xattr_array,
-				   struct xattr *evm);
+extern int evm_inode_init_security(struct inode *inode, struct inode *dir,
+				   const struct qstr *qstr,
+				   struct xattr *xattrs, int *xattr_count);
 extern bool evm_revalidate_status(const char *xattr_name);
 extern int evm_protected_xattr_if_enabled(const char *req_xattr_name);
 extern int evm_read_protected_xattrs(struct dentry *dentry, u8 *buffer,
@@ -157,9 +157,10 @@ static inline void evm_inode_post_set_acl(struct dentry *dentry,
 	return;
 }
 
-static inline int evm_inode_init_security(struct inode *inode,
-					  const struct xattr *xattr_array,
-					  struct xattr *evm)
+static inline int evm_inode_init_security(struct inode *inode, struct inode *dir,
+					  const struct qstr *qstr,
+					  struct xattr *xattrs,
+					  int *xattr_count)
 {
 	return 0;
 }
diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c
index cf24c525558..475196ce712 100644
--- a/security/integrity/evm/evm_main.c
+++ b/security/integrity/evm/evm_main.c
@@ -21,6 +21,7 @@
 #include <linux/evm.h>
 #include <linux/magic.h>
 #include <linux/posix_acl_xattr.h>
+#include <linux/lsm_hooks.h>
 
 #include <crypto/hash.h>
 #include <crypto/hash_info.h>
@@ -864,23 +865,26 @@ void evm_inode_post_setattr(struct dentry *dentry, int ia_valid)
 /*
  * evm_inode_init_security - initializes security.evm HMAC value
  */
-int evm_inode_init_security(struct inode *inode,
-				 const struct xattr *lsm_xattr,
-				 struct xattr *evm_xattr)
+int evm_inode_init_security(struct inode *inode, struct inode *dir,
+			    const struct qstr *qstr, struct xattr *xattrs,
+			    int *xattr_count)
 {
 	struct evm_xattr *xattr_data;
+	struct xattr *evm_xattr;
 	int rc;
 
-	if (!(evm_initialized & EVM_INIT_HMAC) ||
-	    !evm_protected_xattr(lsm_xattr->name))
+	if (!(evm_initialized & EVM_INIT_HMAC) || !xattrs ||
+	    !evm_protected_xattr(xattrs->name))
 		return 0;
 
+	evm_xattr = lsm_get_xattr_slot(xattrs, xattr_count);
+
 	xattr_data = kzalloc(sizeof(*xattr_data), GFP_NOFS);
 	if (!xattr_data)
 		return -ENOMEM;
 
 	xattr_data->data.type = EVM_XATTR_HMAC;
-	rc = evm_init_hmac(inode, lsm_xattr, xattr_data->digest);
+	rc = evm_init_hmac(inode, xattrs, xattr_data->digest);
 	if (rc < 0)
 		goto out;
 
diff --git a/security/security.c b/security/security.c
index 1aeaa8ce449..ef7779ec8b2 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1645,9 +1645,9 @@ int security_inode_init_security(struct inode *inode, struct inode *dir,
 	if (!xattr_count)
 		goto out;
 
-	ret = evm_inode_init_security(inode, new_xattrs,
-				      new_xattrs + xattr_count);
-	if (ret)
+	ret = evm_inode_init_security(inode, dir, qstr, new_xattrs,
+				      &xattr_count);
+	if (ret && ret != -EOPNOTSUPP)
 		goto out;
 	ret = initxattrs(inode, new_xattrs, fs_data);
 out:
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [PATCH v10 4/4] evm: Support multiple LSMs providing an xattr
  2023-03-31 12:32 [PATCH v10 0/4] evm: Do HMAC of multiple per LSM xattrs for new inodes Roberto Sassu
                   ` (2 preceding siblings ...)
  2023-03-31 12:32 ` [PATCH v10 3/4] evm: Align evm_inode_init_security() definition with LSM infrastructure Roberto Sassu
@ 2023-03-31 12:32 ` Roberto Sassu
  2023-04-11  7:22   ` Mimi Zohar
  2023-04-03 10:36 ` [PATCH v10 0/4] evm: Do HMAC of multiple per LSM xattrs for new inodes Mimi Zohar
  4 siblings, 1 reply; 44+ messages in thread
From: Roberto Sassu @ 2023-03-31 12:32 UTC (permalink / raw)
  To: zohar, dmitry.kasatkin, paul, jmorris, serge,
	stephen.smalley.work, eparis, casey
  Cc: reiserfs-devel, linux-kernel, linux-integrity,
	linux-security-module, selinux, bpf, kpsingh, keescook,
	nicolas.bouchinet, Roberto Sassu

From: Roberto Sassu <roberto.sassu@huawei.com>

Currently, evm_inode_init_security() processes a single LSM xattr from the
array passed by security_inode_init_security(), and calculates the HMAC on
it and other inode metadata.

As the LSM infrastructure now can pass to EVM an array with multiple
xattrs, scan them until the terminator (xattr name NULL), and calculate the
HMAC on all of them.

Also, double check that the xattrs array terminator is the first non-filled
slot (obtained with lsm_get_xattr_slot()). Consumers of the xattrs array,
such as the initxattrs() callbacks, rely on the terminator.

Finally, change the name of the lsm_xattr parameter of evm_init_hmac() to
xattrs, to reflect the new type of information passed.

Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
---
 security/integrity/evm/evm.h        |  4 +++-
 security/integrity/evm/evm_crypto.c | 11 +++++++++--
 security/integrity/evm/evm_main.c   | 29 +++++++++++++++++++++++++----
 3 files changed, 37 insertions(+), 7 deletions(-)

diff --git a/security/integrity/evm/evm.h b/security/integrity/evm/evm.h
index f8b8c5004fc..53bd7fec93f 100644
--- a/security/integrity/evm/evm.h
+++ b/security/integrity/evm/evm.h
@@ -46,6 +46,8 @@ struct evm_digest {
 	char digest[IMA_MAX_DIGEST_SIZE];
 } __packed;
 
+int evm_protected_xattr(const char *req_xattr_name);
+
 int evm_init_key(void);
 int evm_update_evmxattr(struct dentry *dentry,
 			const char *req_xattr_name,
@@ -58,7 +60,7 @@ int evm_calc_hash(struct dentry *dentry, const char *req_xattr_name,
 		  const char *req_xattr_value,
 		  size_t req_xattr_value_len, char type,
 		  struct evm_digest *data);
-int evm_init_hmac(struct inode *inode, const struct xattr *xattr,
+int evm_init_hmac(struct inode *inode, const struct xattr *xattrs,
 		  char *hmac_val);
 int evm_init_secfs(void);
 
diff --git a/security/integrity/evm/evm_crypto.c b/security/integrity/evm/evm_crypto.c
index 033804f5a5f..0fdd382b58e 100644
--- a/security/integrity/evm/evm_crypto.c
+++ b/security/integrity/evm/evm_crypto.c
@@ -385,10 +385,11 @@ int evm_update_evmxattr(struct dentry *dentry, const char *xattr_name,
 	return rc;
 }
 
-int evm_init_hmac(struct inode *inode, const struct xattr *lsm_xattr,
+int evm_init_hmac(struct inode *inode, const struct xattr *xattrs,
 		  char *hmac_val)
 {
 	struct shash_desc *desc;
+	const struct xattr *xattr;
 
 	desc = init_desc(EVM_XATTR_HMAC, HASH_ALGO_SHA1);
 	if (IS_ERR(desc)) {
@@ -396,7 +397,13 @@ int evm_init_hmac(struct inode *inode, const struct xattr *lsm_xattr,
 		return PTR_ERR(desc);
 	}
 
-	crypto_shash_update(desc, lsm_xattr->value, lsm_xattr->value_len);
+	for (xattr = xattrs; xattr->name != NULL; xattr++) {
+		if (!evm_protected_xattr(xattr->name))
+			continue;
+
+		crypto_shash_update(desc, xattr->value, xattr->value_len);
+	}
+
 	hmac_add_misc(desc, inode, EVM_XATTR_HMAC, hmac_val);
 	kfree(desc);
 	return 0;
diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c
index 475196ce712..e9441419a81 100644
--- a/security/integrity/evm/evm_main.c
+++ b/security/integrity/evm/evm_main.c
@@ -306,7 +306,7 @@ static int evm_protected_xattr_common(const char *req_xattr_name,
 	return found;
 }
 
-static int evm_protected_xattr(const char *req_xattr_name)
+int evm_protected_xattr(const char *req_xattr_name)
 {
 	return evm_protected_xattr_common(req_xattr_name, false);
 }
@@ -870,14 +870,35 @@ int evm_inode_init_security(struct inode *inode, struct inode *dir,
 			    int *xattr_count)
 {
 	struct evm_xattr *xattr_data;
-	struct xattr *evm_xattr;
+	struct xattr *xattr, *evm_xattr;
+	bool evm_protected_xattrs = false;
 	int rc;
 
-	if (!(evm_initialized & EVM_INIT_HMAC) || !xattrs ||
-	    !evm_protected_xattr(xattrs->name))
+	if (!(evm_initialized & EVM_INIT_HMAC) || !xattrs)
+		return 0;
+
+	/*
+	 * security_inode_init_security() makes sure that the xattrs array is
+	 * contiguous, there is enough space for security.evm, and that there is
+	 * a terminator at the end of the array.
+	 */
+	for (xattr = xattrs; xattr->name != NULL; xattr++) {
+		if (evm_protected_xattr(xattr->name))
+			evm_protected_xattrs = true;
+	}
+
+	/* EVM xattr not needed. */
+	if (!evm_protected_xattrs)
 		return 0;
 
 	evm_xattr = lsm_get_xattr_slot(xattrs, xattr_count);
+	/*
+	 * Array terminator (xattr name = NULL) must be the first non-filled
+	 * xattr slot.
+	 */
+	WARN_ONCE(evm_xattr != xattr,
+		  "%s: xattrs terminator is not the first non-filled slot\n",
+		  __func__);
 
 	xattr_data = kzalloc(sizeof(*xattr_data), GFP_NOFS);
 	if (!xattr_data)
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* Re: [PATCH v10 0/4] evm: Do HMAC of multiple per LSM xattrs for new inodes
  2023-03-31 12:32 [PATCH v10 0/4] evm: Do HMAC of multiple per LSM xattrs for new inodes Roberto Sassu
                   ` (3 preceding siblings ...)
  2023-03-31 12:32 ` [PATCH v10 4/4] evm: Support multiple LSMs providing an xattr Roberto Sassu
@ 2023-04-03 10:36 ` Mimi Zohar
  4 siblings, 0 replies; 44+ messages in thread
From: Mimi Zohar @ 2023-04-03 10:36 UTC (permalink / raw)
  To: Roberto Sassu, dmitry.kasatkin, paul, jmorris, serge,
	stephen.smalley.work, eparis, casey
  Cc: reiserfs-devel, linux-kernel, linux-integrity,
	linux-security-module, selinux, bpf, kpsingh, keescook,
	nicolas.bouchinet, Roberto Sassu

On Fri, 2023-03-31 at 14:32 +0200, Roberto Sassu wrote:

> Changelog
> 
> v9:
> - Ensure in reiserfs_security_write() that the full xattr name is not
>   larger than XATTR_NAME_MAX
> - Rename num_filled_xattrs to xattr_count everywhere (suggested by Paul)
> - Rename lsm_find_xattr_slot() to lsm_get_xattr_slot() and add a proper
>   documentation (suggested by Paul)
> - Return zero instead of -EOPNOTSUPP in evm_inode_init_security()
>   (suggested by Paul)
> - Remove additional checks of new_xattrs array in
>   security_inode_init_security() (suggested by Paul)
> - Handle the !initxattrs case similarly to the initxattrs case, except for
>   not allocating the new_xattrs array in the former (suggested by Paul)
> - Remove local variable xattr in security_inode_init_security(), and use
>   xattr_count instead for loop termination (suggested by Paul)
> 
> v8:
> - Add a new reiserfs patch to write the full xattr name
> - Add num_filled_xattrs parameter to inode_init_security hook (suggested by
>   Paul) and evm_inode_init_security()
> - Change default return value of inode_init_security hook to -EOPNOTSUPP
> - Rename lbs_xattr field of lsm_blob_sizes to lbs_xattr_count
> - Introduce lsm_find_xattr_slot() helper
> - Rename lsm_xattr parameter of evm_init_hmac() to xattrs
> - Retrieve the EVM xattr slot with lsm_find_xattr_slot() and double check
>   with the xattr array terminator
> - Remove security_check_compact_filled_xattrs() (suggested by Paul)

Much better without security_check_compact_filled_xattrs().  Thank you!

> - Update security_inode_init_security() documentation
> - Ensure that inode_init_security hook incremented the number of filled
>   slots if it returned zero
> - Ensure that xattr name and value are non-NULL in the filled slots
> - Add the xattr name assignment after the xattr value one (suggested by
>   Paul)
> - Drop patches 1 - 3 (already in lsm/next)
> 

-- 
thanks,

Mimi


^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v10 1/4] reiserfs: Add security prefix to xattr name in reiserfs_security_write()
  2023-03-31 12:32 ` [PATCH v10 1/4] reiserfs: Add security prefix to xattr name in reiserfs_security_write() Roberto Sassu
@ 2023-04-04 18:25   ` Paul Moore
  0 siblings, 0 replies; 44+ messages in thread
From: Paul Moore @ 2023-04-04 18:25 UTC (permalink / raw)
  To: Roberto Sassu
  Cc: zohar, dmitry.kasatkin, jmorris, serge, stephen.smalley.work,
	eparis, casey, reiserfs-devel, linux-kernel, linux-integrity,
	linux-security-module, selinux, bpf, kpsingh, keescook,
	nicolas.bouchinet, Roberto Sassu, stable

On Fri, Mar 31, 2023 at 8:33 AM Roberto Sassu
<roberto.sassu@huaweicloud.com> wrote:
>
> From: Roberto Sassu <roberto.sassu@huawei.com>
>
> Reiserfs sets a security xattr at inode creation time in two stages: first,
> it calls reiserfs_security_init() to obtain the xattr from active LSMs;
> then, it calls reiserfs_security_write() to actually write that xattr.
>
> Unfortunately, it seems there is a wrong expectation that LSMs provide the
> full xattr name in the form 'security.<suffix>'. However, LSMs always
> provided just the suffix, causing reiserfs to not write the xattr at all
> (if the suffix is shorter than the prefix), or to write an xattr with the
> wrong name.
>
> Add a temporary buffer in reiserfs_security_write(), and write to it the
> full xattr name, before passing it to reiserfs_xattr_set_handle().
>
> Also replace the name length check with a check that the full xattr name is
> not larger than XATTR_NAME_MAX.
>
> Cc: stable@vger.kernel.org # v2.6.x
> Fixes: 57fe60df6241 ("reiserfs: add atomic addition of selinux attributes during inode creation")
> Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
> ---
>  fs/reiserfs/xattr_security.c | 8 ++++++--
>  1 file changed, 6 insertions(+), 2 deletions(-)

This looks good to me, thanks.  While normally I would merge something
like this into the lsm/stable-X.Y branch, I'm going to merge it into
lsm/next to give it a week or two of extra testing.  I think anyone
who is using reiserfs+LSM (doubtful as it looks horribly broken) would
be okay with waiting a few more days at this point :)

-- 
paul-moore.com

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v10 2/4] security: Allow all LSMs to provide xattrs for inode_init_security hook
  2023-03-31 12:32 ` [PATCH v10 2/4] security: Allow all LSMs to provide xattrs for inode_init_security hook Roberto Sassu
@ 2023-04-04 18:54   ` Paul Moore
  2023-04-05  2:08     ` Casey Schaufler
  2023-04-11  7:22   ` Mimi Zohar
  1 sibling, 1 reply; 44+ messages in thread
From: Paul Moore @ 2023-04-04 18:54 UTC (permalink / raw)
  To: Roberto Sassu
  Cc: zohar, dmitry.kasatkin, jmorris, serge, stephen.smalley.work,
	eparis, casey, reiserfs-devel, linux-kernel, linux-integrity,
	linux-security-module, selinux, bpf, kpsingh, keescook,
	nicolas.bouchinet, Roberto Sassu

On Fri, Mar 31, 2023 at 8:33 AM Roberto Sassu
<roberto.sassu@huaweicloud.com> wrote:
>
> From: Roberto Sassu <roberto.sassu@huawei.com>
>
> Currently, security_inode_init_security() supports only one LSM providing
> an xattr and EVM calculating the HMAC on that xattr, plus other inode
> metadata.
>
> Allow all LSMs to provide one or multiple xattrs, by extending the security
> blob reservation mechanism. Introduce the new lbs_xattr_count field of the
> lsm_blob_sizes structure, so that each LSM can specify how many xattrs it
> needs, and the LSM infrastructure knows how many xattr slots it should
> allocate.
>
> Dynamically allocate the new_xattrs array to be populated by LSMs with the
> inode_init_security hook, and pass it to the latter instead of the
> name/value/len triple. Unify the !initxattrs and initxattrs case, simply
> don't allocate the new_xattrs array in the former.
>
> Also, pass to the hook the number of xattrs filled by each LSM, so that
> there are no gaps when the next LSM fills the array. Gaps might occur
> because an LSM can legitimately request xattrs to the LSM infrastructure,
> but not fill the reserved slots, if it was not initialized.
>
> Update the documentation of security_inode_init_security() to reflect the
> changes, and fix the description of the xattr name, as it is not allocated
> anymore.
>
> Finally, adapt both SELinux and Smack to use the new definition of the
> inode_init_security hook, and to fill the reserved slots in the xattr
> array. Introduce the lsm_get_xattr_slot() helper to retrieve an available
> slot to fill, and to increment the number of filled slots.
>
> Move the xattr->name assignment after the xattr->value one, so that it is
> done only in case of successful memory allocation. For Smack, also reserve
> space for the other defined xattrs although they are not set yet in
> smack_inode_init_security().
>
> Reported-by: Nicolas Bouchinet <nicolas.bouchinet@clip-os.org> (EVM crash)
> Link: https://lore.kernel.org/linux-integrity/Y1FTSIo+1x+4X0LS@archlinux/
> Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
> ---
>  include/linux/lsm_hook_defs.h |  6 +--
>  include/linux/lsm_hooks.h     | 20 ++++++++++
>  security/security.c           | 71 +++++++++++++++++++++++------------
>  security/selinux/hooks.c      | 17 +++++----
>  security/smack/smack_lsm.c    | 32 ++++++++++------
>  5 files changed, 99 insertions(+), 47 deletions(-)

This looks good aside from a few small things (below).  From what I
can see, there are only two outstanding issues to answer: the number
of Smack xattrs, sign-off from Casey for the Smack bits.

> diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h
> index 6bb55e61e8e..a1896f90089 100644
> --- a/include/linux/lsm_hook_defs.h
> +++ b/include/linux/lsm_hook_defs.h
> @@ -111,9 +111,9 @@ LSM_HOOK(int, 0, path_notify, const struct path *path, u64 mask,
>          unsigned int obj_type)
>  LSM_HOOK(int, 0, inode_alloc_security, struct inode *inode)
>  LSM_HOOK(void, LSM_RET_VOID, inode_free_security, struct inode *inode)
> -LSM_HOOK(int, 0, inode_init_security, struct inode *inode,
> -        struct inode *dir, const struct qstr *qstr, const char **name,
> -        void **value, size_t *len)
> +LSM_HOOK(int, -EOPNOTSUPP, inode_init_security, struct inode *inode,
> +        struct inode *dir, const struct qstr *qstr, struct xattr *xattrs,
> +        int *xattr_count)
>  LSM_HOOK(int, 0, inode_init_security_anon, struct inode *inode,
>          const struct qstr *name, const struct inode *context_inode)
>  LSM_HOOK(int, 0, inode_create, struct inode *dir, struct dentry *dentry,
> diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
> index c2be66c669a..9eb9b686493 100644
> --- a/include/linux/lsm_hooks.h
> +++ b/include/linux/lsm_hooks.h
> @@ -28,6 +28,7 @@
>  #include <linux/security.h>
>  #include <linux/init.h>
>  #include <linux/rculist.h>
> +#include <linux/xattr.h>
>
>  union security_list_options {
>         #define LSM_HOOK(RET, DEFAULT, NAME, ...) RET (*NAME)(__VA_ARGS__);
> @@ -63,8 +64,27 @@ struct lsm_blob_sizes {
>         int     lbs_ipc;
>         int     lbs_msg_msg;
>         int     lbs_task;
> +       int     lbs_xattr_count; /* number of xattr slots in new_xattrs array */
>  };
>
> +/**
> + * lsm_get_xattr_slot - Return the next available slot and increment the index
> + * @xattrs: array storing LSM-provided xattrs
> + * @xattr_count: number of already stored xattrs (updated)
> + *
> + * Retrieve the first available slot in the @xattrs array to fill with an xattr,
> + * and increment @xattr_count.
> + *
> + * Return: The slot to fill in @xattrs if non-NULL, NULL otherwise.
> + */
> +static inline struct xattr *lsm_get_xattr_slot(struct xattr *xattrs,
> +                                              int *xattr_count)
> +{
> +       if (unlikely(!xattrs))
> +               return NULL;
> +       return xattrs + (*xattr_count)++;
> +}
> +
>  /*
>   * LSM_RET_VOID is used as the default value in LSM_HOOK definitions for void
>   * LSM hooks (in include/linux/lsm_hook_defs.h).
> diff --git a/security/security.c b/security/security.c
> index f4170efcddd..1aeaa8ce449 100644
> --- a/security/security.c
> +++ b/security/security.c
> @@ -31,8 +31,6 @@
>  #include <linux/msg.h>
>  #include <net/flow.h>
>
> -#define MAX_LSM_EVM_XATTR      2
> -
>  /* How many LSMs were built into the kernel? */
>  #define LSM_COUNT (__end_lsm_info - __start_lsm_info)
>
> @@ -212,6 +210,8 @@ static void __init lsm_set_blob_sizes(struct lsm_blob_sizes *needed)
>         lsm_set_blob_size(&needed->lbs_msg_msg, &blob_sizes.lbs_msg_msg);
>         lsm_set_blob_size(&needed->lbs_superblock, &blob_sizes.lbs_superblock);
>         lsm_set_blob_size(&needed->lbs_task, &blob_sizes.lbs_task);
> +       lsm_set_blob_size(&needed->lbs_xattr_count,
> +                         &blob_sizes.lbs_xattr_count);
>  }
>
>  /* Prepare LSM for initialization. */
> @@ -378,6 +378,7 @@ static void __init ordered_lsm_init(void)
>         init_debug("msg_msg blob size    = %d\n", blob_sizes.lbs_msg_msg);
>         init_debug("superblock blob size = %d\n", blob_sizes.lbs_superblock);
>         init_debug("task blob size       = %d\n", blob_sizes.lbs_task);
> +       init_debug("xattr slots          = %d\n", blob_sizes.lbs_xattr_count);
>
>         /*
>          * Create any kmem_caches needed for blobs
> @@ -1591,11 +1592,15 @@ EXPORT_SYMBOL(security_dentry_create_files_as);
>   * created inode and set up the incore security field for the new inode.  This
>   * hook is called by the fs code as part of the inode creation transaction and
>   * provides for atomic labeling of the inode, unlike the post_create/mkdir/...
> - * hooks called by the VFS.  The hook function is expected to allocate the name
> - * and value via kmalloc, with the caller being responsible for calling kfree
> - * after using them.  If the security module does not use security attributes
> - * or does not wish to put a security attribute on this particular inode, then
> - * it should return -EOPNOTSUPP to skip this processing.
> + * hooks called by the VFS.  The hook function is expected to populate the
> + * @xattrs array, by calling lsm_get_xattr_slot() to retrieve the slots
> + * reserved by the security module with the lbs_xattr_count field of the
> + * lsm_blob_sizes structure.  For each slot, the hook function should set ->name
> + * to the attribute name suffix (e.g. selinux), to allocate ->value (will be
> + * freed by the caller) and set it to the attribute value, to set ->value_len to
> + * the length of the value.  If the security module does not use security
> + * attributes or does not wish to put a security attribute on this particular
> + * inode, then it should return -EOPNOTSUPP to skip this processing.
>   *
>   * Return: Returns 0 on success, -EOPNOTSUPP if no security attribute is
>   * needed, or -ENOMEM on memory allocation failure.
> @@ -1604,33 +1609,51 @@ int security_inode_init_security(struct inode *inode, struct inode *dir,
>                                  const struct qstr *qstr,
>                                  const initxattrs initxattrs, void *fs_data)
>  {
> -       struct xattr new_xattrs[MAX_LSM_EVM_XATTR + 1];
> -       struct xattr *lsm_xattr, *evm_xattr, *xattr;
> -       int ret;
> +       struct security_hook_list *P;
> +       struct xattr *new_xattrs = NULL;
> +       int ret = -EOPNOTSUPP, xattr_count = 0;
>
>         if (unlikely(IS_PRIVATE(inode)))
>                 return 0;
>
> -       if (!initxattrs)
> -               return call_int_hook(inode_init_security, -EOPNOTSUPP, inode,
> -                                    dir, qstr, NULL, NULL, NULL);
> -       memset(new_xattrs, 0, sizeof(new_xattrs));
> -       lsm_xattr = new_xattrs;
> -       ret = call_int_hook(inode_init_security, -EOPNOTSUPP, inode, dir, qstr,
> -                           &lsm_xattr->name,
> -                           &lsm_xattr->value,
> -                           &lsm_xattr->value_len);
> -       if (ret)
> +       if (!blob_sizes.lbs_xattr_count)
> +               return 0;
> +
> +       if (initxattrs) {
> +               /* Allocate +1 for EVM and +1 as terminator. */
> +               new_xattrs = kcalloc(blob_sizes.lbs_xattr_count + 2,
> +                                    sizeof(*new_xattrs), GFP_NOFS);
> +               if (!new_xattrs)
> +                       return -ENOMEM;
> +       }
> +
> +       hlist_for_each_entry(P, &security_hook_heads.inode_init_security,
> +                            list) {
> +               ret = P->hook.inode_init_security(inode, dir, qstr, new_xattrs,
> +                                                 &xattr_count);
> +               if (ret && ret != -EOPNOTSUPP)
> +                       goto out;
> +               /*
> +                * As documented in lsm_hooks.h, -EOPNOTSUPP in this context
> +                * means that the LSM is not willing to provide an xattr, not
> +                * that it wants to signal an error. Thus, continue to invoke
> +                * the remaining LSMs.
> +                */
> +       }
> +
> +       /* If initxattrs() is NULL, xattr_count is zero, skip the call. */
> +       if (!xattr_count)
>                 goto out;
>
> -       evm_xattr = lsm_xattr + 1;
> -       ret = evm_inode_init_security(inode, lsm_xattr, evm_xattr);
> +       ret = evm_inode_init_security(inode, new_xattrs,
> +                                     new_xattrs + xattr_count);

I think it's cleaner to write '&new_xattrs[xattr_count]' for the third
parameter above (no concerns around pointer math), and stylistically
it matches better with the for-kfree loop below.

>         if (ret)
>                 goto out;
>         ret = initxattrs(inode, new_xattrs, fs_data);
>  out:
> -       for (xattr = new_xattrs; xattr->value != NULL; xattr++)
> -               kfree(xattr->value);
> +       for (; xattr_count > 0; xattr_count--)
> +               kfree(new_xattrs[xattr_count - 1].value);
> +       kfree(new_xattrs);
>         return (ret == -EOPNOTSUPP) ? 0 : ret;
>  }
>  EXPORT_SYMBOL(security_inode_init_security);

...

> diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
> index cfcbb748da2..8392983334b 100644
> --- a/security/smack/smack_lsm.c
> +++ b/security/smack/smack_lsm.c
> @@ -52,6 +52,15 @@
>  #define SMK_RECEIVING  1
>  #define SMK_SENDING    2
>
> +/*
> + * Smack uses multiple xattrs.
> + * SMACK64 - for access control, SMACK64EXEC - label for the program,

I think it would be good to move SMACK64EXEC to its own line; it took
me a minute to figure out why SMACK_INODE_INIT_XATTRS was set to '4'
when I only say three comment lines ... ;)

> + * SMACK64MMAP - controls library loading,
> + * SMACK64TRANSMUTE - label initialization,
> + * Not saved on files - SMACK64IPIN and SMACK64IPOUT
> + */
> +#define SMACK_INODE_INIT_XATTRS 4

If smack_inode_init_security() only ever populates a single xattr, and
that is the only current user of SMACK_INODE_INIT_XATTRS, can we make
this '1' and shrink the xattr allocation a bit?

>  #ifdef SMACK_IPV6_PORT_LABELING
>  static DEFINE_MUTEX(smack_ipv6_lock);
>  static LIST_HEAD(smk_ipv6_port_list);
> @@ -939,26 +948,23 @@ static int smack_inode_alloc_security(struct inode *inode)
>   * @inode: the newly created inode
>   * @dir: containing directory object
>   * @qstr: unused
> - * @name: where to put the attribute name
> - * @value: where to put the attribute value
> - * @len: where to put the length of the attribute
> + * @xattrs: where to put the attributes
> + * @xattr_count: current number of LSM-provided xattrs (updated)
>   *
>   * Returns 0 if it all works out, -ENOMEM if there's no memory
>   */
>  static int smack_inode_init_security(struct inode *inode, struct inode *dir,
> -                                    const struct qstr *qstr, const char **name,
> -                                    void **value, size_t *len)
> +                                    const struct qstr *qstr,
> +                                    struct xattr *xattrs, int *xattr_count)
>  {
>         struct inode_smack *issp = smack_inode(inode);
>         struct smack_known *skp = smk_of_current();
>         struct smack_known *isp = smk_of_inode(inode);
>         struct smack_known *dsp = smk_of_inode(dir);
> +       struct xattr *xattr = lsm_get_xattr_slot(xattrs, xattr_count);
>         int may;
>
> -       if (name)
> -               *name = XATTR_SMACK_SUFFIX;
> -
> -       if (value && len) {
> +       if (xattr) {
>                 rcu_read_lock();
>                 may = smk_access_entry(skp->smk_known, dsp->smk_known,
>                                        &skp->smk_rules);
> @@ -976,11 +982,12 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
>                         issp->smk_flags |= SMK_INODE_CHANGED;
>                 }
>
> -               *value = kstrdup(isp->smk_known, GFP_NOFS);
> -               if (*value == NULL)
> +               xattr->value = kstrdup(isp->smk_known, GFP_NOFS);
> +               if (xattr->value == NULL)
>                         return -ENOMEM;
>
> -               *len = strlen(isp->smk_known);
> +               xattr->value_len = strlen(isp->smk_known);
> +               xattr->name = XATTR_SMACK_SUFFIX;
>         }
>
>         return 0;
> @@ -4854,6 +4861,7 @@ struct lsm_blob_sizes smack_blob_sizes __lsm_ro_after_init = {
>         .lbs_ipc = sizeof(struct smack_known *),
>         .lbs_msg_msg = sizeof(struct smack_known *),
>         .lbs_superblock = sizeof(struct superblock_smack),
> +       .lbs_xattr_count = SMACK_INODE_INIT_XATTRS,
>  };
>
>  static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {
> --
> 2.25.1

-- 
paul-moore.com

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v10 3/4] evm: Align evm_inode_init_security() definition with LSM infrastructure
  2023-03-31 12:32 ` [PATCH v10 3/4] evm: Align evm_inode_init_security() definition with LSM infrastructure Roberto Sassu
@ 2023-04-04 18:56   ` Paul Moore
  2023-04-11  7:22   ` Mimi Zohar
  1 sibling, 0 replies; 44+ messages in thread
From: Paul Moore @ 2023-04-04 18:56 UTC (permalink / raw)
  To: Roberto Sassu
  Cc: zohar, dmitry.kasatkin, jmorris, serge, stephen.smalley.work,
	eparis, casey, reiserfs-devel, linux-kernel, linux-integrity,
	linux-security-module, selinux, bpf, kpsingh, keescook,
	nicolas.bouchinet, Roberto Sassu

On Fri, Mar 31, 2023 at 8:33 AM Roberto Sassu
<roberto.sassu@huaweicloud.com> wrote:
>
> From: Roberto Sassu <roberto.sassu@huawei.com>
>
> Change the evm_inode_init_security() definition to align with the LSM
> infrastructure. Keep the existing behavior of including in the HMAC
> calculation only the first xattr provided by LSMs.
>
> Changing the evm_inode_init_security() definition requires passing the
> xattr array allocated by security_inode_init_security(), and the number of
> xattrs filled by previously invoked LSMs.
>
> Use the newly introduced lsm_get_xattr_slot() to position EVM correctly in
> the xattrs array, like a regular LSM, and to increment the number of filled
> slots. For now, the LSM infrastructure allocates enough xattrs slots to
> store the EVM xattr, without using the reservation mechanism.
>
> Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
> ---
>  include/linux/evm.h               | 13 +++++++------
>  security/integrity/evm/evm_main.c | 16 ++++++++++------
>  security/security.c               |  6 +++---
>  3 files changed, 20 insertions(+), 15 deletions(-)

This seems reasonable to me, but I'll want to see a sign-off from Mimi
for the EVM bits.  Same thing for patch 4/4.

-- 
paul-moore.com

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v10 2/4] security: Allow all LSMs to provide xattrs for inode_init_security hook
  2023-04-04 18:54   ` Paul Moore
@ 2023-04-05  2:08     ` Casey Schaufler
  2023-04-05  9:43       ` Roberto Sassu
  0 siblings, 1 reply; 44+ messages in thread
From: Casey Schaufler @ 2023-04-05  2:08 UTC (permalink / raw)
  To: Paul Moore, Roberto Sassu
  Cc: zohar, dmitry.kasatkin, jmorris, serge, stephen.smalley.work,
	eparis, reiserfs-devel, linux-kernel, linux-integrity,
	linux-security-module, selinux, bpf, kpsingh, keescook,
	nicolas.bouchinet, Roberto Sassu, Casey Schaufler

On 4/4/2023 11:54 AM, Paul Moore wrote:
> On Fri, Mar 31, 2023 at 8:33 AM Roberto Sassu
> <roberto.sassu@huaweicloud.com> wrote:
>> From: Roberto Sassu <roberto.sassu@huawei.com>
>>
>> Currently, security_inode_init_security() supports only one LSM providing
>> an xattr and EVM calculating the HMAC on that xattr, plus other inode
>> metadata.
>>
>> Allow all LSMs to provide one or multiple xattrs, by extending the security
>> blob reservation mechanism. Introduce the new lbs_xattr_count field of the
>> lsm_blob_sizes structure, so that each LSM can specify how many xattrs it
>> needs, and the LSM infrastructure knows how many xattr slots it should
>> allocate.
>>
>> Dynamically allocate the new_xattrs array to be populated by LSMs with the
>> inode_init_security hook, and pass it to the latter instead of the
>> name/value/len triple. Unify the !initxattrs and initxattrs case, simply
>> don't allocate the new_xattrs array in the former.
>>
>> Also, pass to the hook the number of xattrs filled by each LSM, so that
>> there are no gaps when the next LSM fills the array. Gaps might occur
>> because an LSM can legitimately request xattrs to the LSM infrastructure,
>> but not fill the reserved slots, if it was not initialized.
>>
>> Update the documentation of security_inode_init_security() to reflect the
>> changes, and fix the description of the xattr name, as it is not allocated
>> anymore.
>>
>> Finally, adapt both SELinux and Smack to use the new definition of the
>> inode_init_security hook, and to fill the reserved slots in the xattr
>> array. Introduce the lsm_get_xattr_slot() helper to retrieve an available
>> slot to fill, and to increment the number of filled slots.
>>
>> Move the xattr->name assignment after the xattr->value one, so that it is
>> done only in case of successful memory allocation. For Smack, also reserve
>> space for the other defined xattrs although they are not set yet in
>> smack_inode_init_security().
>>
>> Reported-by: Nicolas Bouchinet <nicolas.bouchinet@clip-os.org> (EVM crash)
>> Link: https://lore.kernel.org/linux-integrity/Y1FTSIo+1x+4X0LS@archlinux/
>> Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
>> ---
>>  include/linux/lsm_hook_defs.h |  6 +--
>>  include/linux/lsm_hooks.h     | 20 ++++++++++
>>  security/security.c           | 71 +++++++++++++++++++++++------------
>>  security/selinux/hooks.c      | 17 +++++----
>>  security/smack/smack_lsm.c    | 32 ++++++++++------
>>  5 files changed, 99 insertions(+), 47 deletions(-)
> This looks good aside from a few small things (below).  From what I
> can see, there are only two outstanding issues to answer: the number
> of Smack xattrs, sign-off from Casey for the Smack bits.
>
>> diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h
>> index 6bb55e61e8e..a1896f90089 100644
>> --- a/include/linux/lsm_hook_defs.h
>> +++ b/include/linux/lsm_hook_defs.h
>> @@ -111,9 +111,9 @@ LSM_HOOK(int, 0, path_notify, const struct path *path, u64 mask,
>>          unsigned int obj_type)
>>  LSM_HOOK(int, 0, inode_alloc_security, struct inode *inode)
>>  LSM_HOOK(void, LSM_RET_VOID, inode_free_security, struct inode *inode)
>> -LSM_HOOK(int, 0, inode_init_security, struct inode *inode,
>> -        struct inode *dir, const struct qstr *qstr, const char **name,
>> -        void **value, size_t *len)
>> +LSM_HOOK(int, -EOPNOTSUPP, inode_init_security, struct inode *inode,
>> +        struct inode *dir, const struct qstr *qstr, struct xattr *xattrs,
>> +        int *xattr_count)
>>  LSM_HOOK(int, 0, inode_init_security_anon, struct inode *inode,
>>          const struct qstr *name, const struct inode *context_inode)
>>  LSM_HOOK(int, 0, inode_create, struct inode *dir, struct dentry *dentry,
>> diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
>> index c2be66c669a..9eb9b686493 100644
>> --- a/include/linux/lsm_hooks.h
>> +++ b/include/linux/lsm_hooks.h
>> @@ -28,6 +28,7 @@
>>  #include <linux/security.h>
>>  #include <linux/init.h>
>>  #include <linux/rculist.h>
>> +#include <linux/xattr.h>
>>
>>  union security_list_options {
>>         #define LSM_HOOK(RET, DEFAULT, NAME, ...) RET (*NAME)(__VA_ARGS__);
>> @@ -63,8 +64,27 @@ struct lsm_blob_sizes {
>>         int     lbs_ipc;
>>         int     lbs_msg_msg;
>>         int     lbs_task;
>> +       int     lbs_xattr_count; /* number of xattr slots in new_xattrs array */
>>  };
>>
>> +/**
>> + * lsm_get_xattr_slot - Return the next available slot and increment the index
>> + * @xattrs: array storing LSM-provided xattrs
>> + * @xattr_count: number of already stored xattrs (updated)
>> + *
>> + * Retrieve the first available slot in the @xattrs array to fill with an xattr,
>> + * and increment @xattr_count.
>> + *
>> + * Return: The slot to fill in @xattrs if non-NULL, NULL otherwise.
>> + */
>> +static inline struct xattr *lsm_get_xattr_slot(struct xattr *xattrs,
>> +                                              int *xattr_count)
>> +{
>> +       if (unlikely(!xattrs))
>> +               return NULL;
>> +       return xattrs + (*xattr_count)++;
>> +}
>> +
>>  /*
>>   * LSM_RET_VOID is used as the default value in LSM_HOOK definitions for void
>>   * LSM hooks (in include/linux/lsm_hook_defs.h).
>> diff --git a/security/security.c b/security/security.c
>> index f4170efcddd..1aeaa8ce449 100644
>> --- a/security/security.c
>> +++ b/security/security.c
>> @@ -31,8 +31,6 @@
>>  #include <linux/msg.h>
>>  #include <net/flow.h>
>>
>> -#define MAX_LSM_EVM_XATTR      2
>> -
>>  /* How many LSMs were built into the kernel? */
>>  #define LSM_COUNT (__end_lsm_info - __start_lsm_info)
>>
>> @@ -212,6 +210,8 @@ static void __init lsm_set_blob_sizes(struct lsm_blob_sizes *needed)
>>         lsm_set_blob_size(&needed->lbs_msg_msg, &blob_sizes.lbs_msg_msg);
>>         lsm_set_blob_size(&needed->lbs_superblock, &blob_sizes.lbs_superblock);
>>         lsm_set_blob_size(&needed->lbs_task, &blob_sizes.lbs_task);
>> +       lsm_set_blob_size(&needed->lbs_xattr_count,
>> +                         &blob_sizes.lbs_xattr_count);
>>  }
>>
>>  /* Prepare LSM for initialization. */
>> @@ -378,6 +378,7 @@ static void __init ordered_lsm_init(void)
>>         init_debug("msg_msg blob size    = %d\n", blob_sizes.lbs_msg_msg);
>>         init_debug("superblock blob size = %d\n", blob_sizes.lbs_superblock);
>>         init_debug("task blob size       = %d\n", blob_sizes.lbs_task);
>> +       init_debug("xattr slots          = %d\n", blob_sizes.lbs_xattr_count);
>>
>>         /*
>>          * Create any kmem_caches needed for blobs
>> @@ -1591,11 +1592,15 @@ EXPORT_SYMBOL(security_dentry_create_files_as);
>>   * created inode and set up the incore security field for the new inode.  This
>>   * hook is called by the fs code as part of the inode creation transaction and
>>   * provides for atomic labeling of the inode, unlike the post_create/mkdir/...
>> - * hooks called by the VFS.  The hook function is expected to allocate the name
>> - * and value via kmalloc, with the caller being responsible for calling kfree
>> - * after using them.  If the security module does not use security attributes
>> - * or does not wish to put a security attribute on this particular inode, then
>> - * it should return -EOPNOTSUPP to skip this processing.
>> + * hooks called by the VFS.  The hook function is expected to populate the
>> + * @xattrs array, by calling lsm_get_xattr_slot() to retrieve the slots
>> + * reserved by the security module with the lbs_xattr_count field of the
>> + * lsm_blob_sizes structure.  For each slot, the hook function should set ->name
>> + * to the attribute name suffix (e.g. selinux), to allocate ->value (will be
>> + * freed by the caller) and set it to the attribute value, to set ->value_len to
>> + * the length of the value.  If the security module does not use security
>> + * attributes or does not wish to put a security attribute on this particular
>> + * inode, then it should return -EOPNOTSUPP to skip this processing.
>>   *
>>   * Return: Returns 0 on success, -EOPNOTSUPP if no security attribute is
>>   * needed, or -ENOMEM on memory allocation failure.
>> @@ -1604,33 +1609,51 @@ int security_inode_init_security(struct inode *inode, struct inode *dir,
>>                                  const struct qstr *qstr,
>>                                  const initxattrs initxattrs, void *fs_data)
>>  {
>> -       struct xattr new_xattrs[MAX_LSM_EVM_XATTR + 1];
>> -       struct xattr *lsm_xattr, *evm_xattr, *xattr;
>> -       int ret;
>> +       struct security_hook_list *P;
>> +       struct xattr *new_xattrs = NULL;
>> +       int ret = -EOPNOTSUPP, xattr_count = 0;
>>
>>         if (unlikely(IS_PRIVATE(inode)))
>>                 return 0;
>>
>> -       if (!initxattrs)
>> -               return call_int_hook(inode_init_security, -EOPNOTSUPP, inode,
>> -                                    dir, qstr, NULL, NULL, NULL);
>> -       memset(new_xattrs, 0, sizeof(new_xattrs));
>> -       lsm_xattr = new_xattrs;
>> -       ret = call_int_hook(inode_init_security, -EOPNOTSUPP, inode, dir, qstr,
>> -                           &lsm_xattr->name,
>> -                           &lsm_xattr->value,
>> -                           &lsm_xattr->value_len);
>> -       if (ret)
>> +       if (!blob_sizes.lbs_xattr_count)
>> +               return 0;
>> +
>> +       if (initxattrs) {
>> +               /* Allocate +1 for EVM and +1 as terminator. */
>> +               new_xattrs = kcalloc(blob_sizes.lbs_xattr_count + 2,
>> +                                    sizeof(*new_xattrs), GFP_NOFS);
>> +               if (!new_xattrs)
>> +                       return -ENOMEM;
>> +       }
>> +
>> +       hlist_for_each_entry(P, &security_hook_heads.inode_init_security,
>> +                            list) {
>> +               ret = P->hook.inode_init_security(inode, dir, qstr, new_xattrs,
>> +                                                 &xattr_count);
>> +               if (ret && ret != -EOPNOTSUPP)
>> +                       goto out;
>> +               /*
>> +                * As documented in lsm_hooks.h, -EOPNOTSUPP in this context
>> +                * means that the LSM is not willing to provide an xattr, not
>> +                * that it wants to signal an error. Thus, continue to invoke
>> +                * the remaining LSMs.
>> +                */
>> +       }
>> +
>> +       /* If initxattrs() is NULL, xattr_count is zero, skip the call. */
>> +       if (!xattr_count)
>>                 goto out;
>>
>> -       evm_xattr = lsm_xattr + 1;
>> -       ret = evm_inode_init_security(inode, lsm_xattr, evm_xattr);
>> +       ret = evm_inode_init_security(inode, new_xattrs,
>> +                                     new_xattrs + xattr_count);
> I think it's cleaner to write '&new_xattrs[xattr_count]' for the third
> parameter above (no concerns around pointer math), and stylistically
> it matches better with the for-kfree loop below.
>
>>         if (ret)
>>                 goto out;
>>         ret = initxattrs(inode, new_xattrs, fs_data);
>>  out:
>> -       for (xattr = new_xattrs; xattr->value != NULL; xattr++)
>> -               kfree(xattr->value);
>> +       for (; xattr_count > 0; xattr_count--)
>> +               kfree(new_xattrs[xattr_count - 1].value);
>> +       kfree(new_xattrs);
>>         return (ret == -EOPNOTSUPP) ? 0 : ret;
>>  }
>>  EXPORT_SYMBOL(security_inode_init_security);
> ..
>
>> diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
>> index cfcbb748da2..8392983334b 100644
>> --- a/security/smack/smack_lsm.c
>> +++ b/security/smack/smack_lsm.c
>> @@ -52,6 +52,15 @@
>>  #define SMK_RECEIVING  1
>>  #define SMK_SENDING    2
>>
>> +/*
>> + * Smack uses multiple xattrs.
>> + * SMACK64 - for access control, SMACK64EXEC - label for the program,
> I think it would be good to move SMACK64EXEC to its own line; it took
> me a minute to figure out why SMACK_INODE_INIT_XATTRS was set to '4'
> when I only say three comment lines ... ;)
>
>> + * SMACK64MMAP - controls library loading,
>> + * SMACK64TRANSMUTE - label initialization,
>> + * Not saved on files - SMACK64IPIN and SMACK64IPOUT
>> + */
>> +#define SMACK_INODE_INIT_XATTRS 4
> If smack_inode_init_security() only ever populates a single xattr, and
> that is the only current user of SMACK_INODE_INIT_XATTRS, can we make
> this '1' and shrink the xattr allocation a bit?

If the parent directory is marked with SMACK64_TRANSMUTE, the access
rule allowing the access has the "t" mode, and the object being initialized
is a directory, the new inode should get the SMACK64_TRANSMUTE attribute.
The callers of security_inode_init_security() don't seem to care.
I can't say if the evm code is getting SMACK64_TRANSMUTE or, for that
matter, SMACK64_EXEC and SMACK64_MMAP, some other way. The older system
allowed for multiple Smack xattrs, but I'm not clear on exactly how.


>>  #ifdef SMACK_IPV6_PORT_LABELING
>>  static DEFINE_MUTEX(smack_ipv6_lock);
>>  static LIST_HEAD(smk_ipv6_port_list);
>> @@ -939,26 +948,23 @@ static int smack_inode_alloc_security(struct inode *inode)
>>   * @inode: the newly created inode
>>   * @dir: containing directory object
>>   * @qstr: unused
>> - * @name: where to put the attribute name
>> - * @value: where to put the attribute value
>> - * @len: where to put the length of the attribute
>> + * @xattrs: where to put the attributes
>> + * @xattr_count: current number of LSM-provided xattrs (updated)
>>   *
>>   * Returns 0 if it all works out, -ENOMEM if there's no memory
>>   */
>>  static int smack_inode_init_security(struct inode *inode, struct inode *dir,
>> -                                    const struct qstr *qstr, const char **name,
>> -                                    void **value, size_t *len)
>> +                                    const struct qstr *qstr,
>> +                                    struct xattr *xattrs, int *xattr_count)
>>  {
>>         struct inode_smack *issp = smack_inode(inode);
>>         struct smack_known *skp = smk_of_current();
>>         struct smack_known *isp = smk_of_inode(inode);
>>         struct smack_known *dsp = smk_of_inode(dir);
>> +       struct xattr *xattr = lsm_get_xattr_slot(xattrs, xattr_count);
>>         int may;
>>
>> -       if (name)
>> -               *name = XATTR_SMACK_SUFFIX;
>> -
>> -       if (value && len) {
>> +       if (xattr) {
>>                 rcu_read_lock();
>>                 may = smk_access_entry(skp->smk_known, dsp->smk_known,
>>                                        &skp->smk_rules);
>> @@ -976,11 +982,12 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
>>                         issp->smk_flags |= SMK_INODE_CHANGED;
>>                 }
>>
>> -               *value = kstrdup(isp->smk_known, GFP_NOFS);
>> -               if (*value == NULL)
>> +               xattr->value = kstrdup(isp->smk_known, GFP_NOFS);
>> +               if (xattr->value == NULL)
>>                         return -ENOMEM;
>>
>> -               *len = strlen(isp->smk_known);
>> +               xattr->value_len = strlen(isp->smk_known);
>> +               xattr->name = XATTR_SMACK_SUFFIX;
>>         }
>>
>>         return 0;
>> @@ -4854,6 +4861,7 @@ struct lsm_blob_sizes smack_blob_sizes __lsm_ro_after_init = {
>>         .lbs_ipc = sizeof(struct smack_known *),
>>         .lbs_msg_msg = sizeof(struct smack_known *),
>>         .lbs_superblock = sizeof(struct superblock_smack),
>> +       .lbs_xattr_count = SMACK_INODE_INIT_XATTRS,
>>  };
>>
>>  static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {
>> --
>> 2.25.1

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v10 2/4] security: Allow all LSMs to provide xattrs for inode_init_security hook
  2023-04-05  2:08     ` Casey Schaufler
@ 2023-04-05  9:43       ` Roberto Sassu
  2023-04-05 19:59         ` Paul Moore
  0 siblings, 1 reply; 44+ messages in thread
From: Roberto Sassu @ 2023-04-05  9:43 UTC (permalink / raw)
  To: Casey Schaufler, Paul Moore
  Cc: zohar, dmitry.kasatkin, jmorris, serge, stephen.smalley.work,
	eparis, reiserfs-devel, linux-kernel, linux-integrity,
	linux-security-module, selinux, bpf, kpsingh, keescook,
	nicolas.bouchinet, Roberto Sassu

On 4/5/2023 4:08 AM, Casey Schaufler wrote:
> On 4/4/2023 11:54 AM, Paul Moore wrote:
>> On Fri, Mar 31, 2023 at 8:33 AM Roberto Sassu
>> <roberto.sassu@huaweicloud.com> wrote:
>>> From: Roberto Sassu <roberto.sassu@huawei.com>
>>>
>>> Currently, security_inode_init_security() supports only one LSM providing
>>> an xattr and EVM calculating the HMAC on that xattr, plus other inode
>>> metadata.
>>>
>>> Allow all LSMs to provide one or multiple xattrs, by extending the security
>>> blob reservation mechanism. Introduce the new lbs_xattr_count field of the
>>> lsm_blob_sizes structure, so that each LSM can specify how many xattrs it
>>> needs, and the LSM infrastructure knows how many xattr slots it should
>>> allocate.
>>>
>>> Dynamically allocate the new_xattrs array to be populated by LSMs with the
>>> inode_init_security hook, and pass it to the latter instead of the
>>> name/value/len triple. Unify the !initxattrs and initxattrs case, simply
>>> don't allocate the new_xattrs array in the former.
>>>
>>> Also, pass to the hook the number of xattrs filled by each LSM, so that
>>> there are no gaps when the next LSM fills the array. Gaps might occur
>>> because an LSM can legitimately request xattrs to the LSM infrastructure,
>>> but not fill the reserved slots, if it was not initialized.
>>>
>>> Update the documentation of security_inode_init_security() to reflect the
>>> changes, and fix the description of the xattr name, as it is not allocated
>>> anymore.
>>>
>>> Finally, adapt both SELinux and Smack to use the new definition of the
>>> inode_init_security hook, and to fill the reserved slots in the xattr
>>> array. Introduce the lsm_get_xattr_slot() helper to retrieve an available
>>> slot to fill, and to increment the number of filled slots.
>>>
>>> Move the xattr->name assignment after the xattr->value one, so that it is
>>> done only in case of successful memory allocation. For Smack, also reserve
>>> space for the other defined xattrs although they are not set yet in
>>> smack_inode_init_security().
>>>
>>> Reported-by: Nicolas Bouchinet <nicolas.bouchinet@clip-os.org> (EVM crash)
>>> Link: https://lore.kernel.org/linux-integrity/Y1FTSIo+1x+4X0LS@archlinux/
>>> Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
>>> ---
>>>   include/linux/lsm_hook_defs.h |  6 +--
>>>   include/linux/lsm_hooks.h     | 20 ++++++++++
>>>   security/security.c           | 71 +++++++++++++++++++++++------------
>>>   security/selinux/hooks.c      | 17 +++++----
>>>   security/smack/smack_lsm.c    | 32 ++++++++++------
>>>   5 files changed, 99 insertions(+), 47 deletions(-)
>> This looks good aside from a few small things (below).  From what I
>> can see, there are only two outstanding issues to answer: the number
>> of Smack xattrs, sign-off from Casey for the Smack bits.
>>
>>> diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h
>>> index 6bb55e61e8e..a1896f90089 100644
>>> --- a/include/linux/lsm_hook_defs.h
>>> +++ b/include/linux/lsm_hook_defs.h
>>> @@ -111,9 +111,9 @@ LSM_HOOK(int, 0, path_notify, const struct path *path, u64 mask,
>>>           unsigned int obj_type)
>>>   LSM_HOOK(int, 0, inode_alloc_security, struct inode *inode)
>>>   LSM_HOOK(void, LSM_RET_VOID, inode_free_security, struct inode *inode)
>>> -LSM_HOOK(int, 0, inode_init_security, struct inode *inode,
>>> -        struct inode *dir, const struct qstr *qstr, const char **name,
>>> -        void **value, size_t *len)
>>> +LSM_HOOK(int, -EOPNOTSUPP, inode_init_security, struct inode *inode,
>>> +        struct inode *dir, const struct qstr *qstr, struct xattr *xattrs,
>>> +        int *xattr_count)
>>>   LSM_HOOK(int, 0, inode_init_security_anon, struct inode *inode,
>>>           const struct qstr *name, const struct inode *context_inode)
>>>   LSM_HOOK(int, 0, inode_create, struct inode *dir, struct dentry *dentry,
>>> diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
>>> index c2be66c669a..9eb9b686493 100644
>>> --- a/include/linux/lsm_hooks.h
>>> +++ b/include/linux/lsm_hooks.h
>>> @@ -28,6 +28,7 @@
>>>   #include <linux/security.h>
>>>   #include <linux/init.h>
>>>   #include <linux/rculist.h>
>>> +#include <linux/xattr.h>
>>>
>>>   union security_list_options {
>>>          #define LSM_HOOK(RET, DEFAULT, NAME, ...) RET (*NAME)(__VA_ARGS__);
>>> @@ -63,8 +64,27 @@ struct lsm_blob_sizes {
>>>          int     lbs_ipc;
>>>          int     lbs_msg_msg;
>>>          int     lbs_task;
>>> +       int     lbs_xattr_count; /* number of xattr slots in new_xattrs array */
>>>   };
>>>
>>> +/**
>>> + * lsm_get_xattr_slot - Return the next available slot and increment the index
>>> + * @xattrs: array storing LSM-provided xattrs
>>> + * @xattr_count: number of already stored xattrs (updated)
>>> + *
>>> + * Retrieve the first available slot in the @xattrs array to fill with an xattr,
>>> + * and increment @xattr_count.
>>> + *
>>> + * Return: The slot to fill in @xattrs if non-NULL, NULL otherwise.
>>> + */
>>> +static inline struct xattr *lsm_get_xattr_slot(struct xattr *xattrs,
>>> +                                              int *xattr_count)
>>> +{
>>> +       if (unlikely(!xattrs))
>>> +               return NULL;
>>> +       return xattrs + (*xattr_count)++;
>>> +}
>>> +
>>>   /*
>>>    * LSM_RET_VOID is used as the default value in LSM_HOOK definitions for void
>>>    * LSM hooks (in include/linux/lsm_hook_defs.h).
>>> diff --git a/security/security.c b/security/security.c
>>> index f4170efcddd..1aeaa8ce449 100644
>>> --- a/security/security.c
>>> +++ b/security/security.c
>>> @@ -31,8 +31,6 @@
>>>   #include <linux/msg.h>
>>>   #include <net/flow.h>
>>>
>>> -#define MAX_LSM_EVM_XATTR      2
>>> -
>>>   /* How many LSMs were built into the kernel? */
>>>   #define LSM_COUNT (__end_lsm_info - __start_lsm_info)
>>>
>>> @@ -212,6 +210,8 @@ static void __init lsm_set_blob_sizes(struct lsm_blob_sizes *needed)
>>>          lsm_set_blob_size(&needed->lbs_msg_msg, &blob_sizes.lbs_msg_msg);
>>>          lsm_set_blob_size(&needed->lbs_superblock, &blob_sizes.lbs_superblock);
>>>          lsm_set_blob_size(&needed->lbs_task, &blob_sizes.lbs_task);
>>> +       lsm_set_blob_size(&needed->lbs_xattr_count,
>>> +                         &blob_sizes.lbs_xattr_count);
>>>   }
>>>
>>>   /* Prepare LSM for initialization. */
>>> @@ -378,6 +378,7 @@ static void __init ordered_lsm_init(void)
>>>          init_debug("msg_msg blob size    = %d\n", blob_sizes.lbs_msg_msg);
>>>          init_debug("superblock blob size = %d\n", blob_sizes.lbs_superblock);
>>>          init_debug("task blob size       = %d\n", blob_sizes.lbs_task);
>>> +       init_debug("xattr slots          = %d\n", blob_sizes.lbs_xattr_count);
>>>
>>>          /*
>>>           * Create any kmem_caches needed for blobs
>>> @@ -1591,11 +1592,15 @@ EXPORT_SYMBOL(security_dentry_create_files_as);
>>>    * created inode and set up the incore security field for the new inode.  This
>>>    * hook is called by the fs code as part of the inode creation transaction and
>>>    * provides for atomic labeling of the inode, unlike the post_create/mkdir/...
>>> - * hooks called by the VFS.  The hook function is expected to allocate the name
>>> - * and value via kmalloc, with the caller being responsible for calling kfree
>>> - * after using them.  If the security module does not use security attributes
>>> - * or does not wish to put a security attribute on this particular inode, then
>>> - * it should return -EOPNOTSUPP to skip this processing.
>>> + * hooks called by the VFS.  The hook function is expected to populate the
>>> + * @xattrs array, by calling lsm_get_xattr_slot() to retrieve the slots
>>> + * reserved by the security module with the lbs_xattr_count field of the
>>> + * lsm_blob_sizes structure.  For each slot, the hook function should set ->name
>>> + * to the attribute name suffix (e.g. selinux), to allocate ->value (will be
>>> + * freed by the caller) and set it to the attribute value, to set ->value_len to
>>> + * the length of the value.  If the security module does not use security
>>> + * attributes or does not wish to put a security attribute on this particular
>>> + * inode, then it should return -EOPNOTSUPP to skip this processing.
>>>    *
>>>    * Return: Returns 0 on success, -EOPNOTSUPP if no security attribute is
>>>    * needed, or -ENOMEM on memory allocation failure.
>>> @@ -1604,33 +1609,51 @@ int security_inode_init_security(struct inode *inode, struct inode *dir,
>>>                                   const struct qstr *qstr,
>>>                                   const initxattrs initxattrs, void *fs_data)
>>>   {
>>> -       struct xattr new_xattrs[MAX_LSM_EVM_XATTR + 1];
>>> -       struct xattr *lsm_xattr, *evm_xattr, *xattr;
>>> -       int ret;
>>> +       struct security_hook_list *P;
>>> +       struct xattr *new_xattrs = NULL;
>>> +       int ret = -EOPNOTSUPP, xattr_count = 0;
>>>
>>>          if (unlikely(IS_PRIVATE(inode)))
>>>                  return 0;
>>>
>>> -       if (!initxattrs)
>>> -               return call_int_hook(inode_init_security, -EOPNOTSUPP, inode,
>>> -                                    dir, qstr, NULL, NULL, NULL);
>>> -       memset(new_xattrs, 0, sizeof(new_xattrs));
>>> -       lsm_xattr = new_xattrs;
>>> -       ret = call_int_hook(inode_init_security, -EOPNOTSUPP, inode, dir, qstr,
>>> -                           &lsm_xattr->name,
>>> -                           &lsm_xattr->value,
>>> -                           &lsm_xattr->value_len);
>>> -       if (ret)
>>> +       if (!blob_sizes.lbs_xattr_count)
>>> +               return 0;
>>> +
>>> +       if (initxattrs) {
>>> +               /* Allocate +1 for EVM and +1 as terminator. */
>>> +               new_xattrs = kcalloc(blob_sizes.lbs_xattr_count + 2,
>>> +                                    sizeof(*new_xattrs), GFP_NOFS);
>>> +               if (!new_xattrs)
>>> +                       return -ENOMEM;
>>> +       }
>>> +
>>> +       hlist_for_each_entry(P, &security_hook_heads.inode_init_security,
>>> +                            list) {
>>> +               ret = P->hook.inode_init_security(inode, dir, qstr, new_xattrs,
>>> +                                                 &xattr_count);
>>> +               if (ret && ret != -EOPNOTSUPP)
>>> +                       goto out;
>>> +               /*
>>> +                * As documented in lsm_hooks.h, -EOPNOTSUPP in this context
>>> +                * means that the LSM is not willing to provide an xattr, not
>>> +                * that it wants to signal an error. Thus, continue to invoke
>>> +                * the remaining LSMs.
>>> +                */
>>> +       }
>>> +
>>> +       /* If initxattrs() is NULL, xattr_count is zero, skip the call. */
>>> +       if (!xattr_count)
>>>                  goto out;
>>>
>>> -       evm_xattr = lsm_xattr + 1;
>>> -       ret = evm_inode_init_security(inode, lsm_xattr, evm_xattr);
>>> +       ret = evm_inode_init_security(inode, new_xattrs,
>>> +                                     new_xattrs + xattr_count);
>> I think it's cleaner to write '&new_xattrs[xattr_count]' for the third
>> parameter above (no concerns around pointer math), and stylistically
>> it matches better with the for-kfree loop below.
>>
>>>          if (ret)
>>>                  goto out;
>>>          ret = initxattrs(inode, new_xattrs, fs_data);
>>>   out:
>>> -       for (xattr = new_xattrs; xattr->value != NULL; xattr++)
>>> -               kfree(xattr->value);
>>> +       for (; xattr_count > 0; xattr_count--)
>>> +               kfree(new_xattrs[xattr_count - 1].value);
>>> +       kfree(new_xattrs);
>>>          return (ret == -EOPNOTSUPP) ? 0 : ret;
>>>   }
>>>   EXPORT_SYMBOL(security_inode_init_security);
>> ..
>>
>>> diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
>>> index cfcbb748da2..8392983334b 100644
>>> --- a/security/smack/smack_lsm.c
>>> +++ b/security/smack/smack_lsm.c
>>> @@ -52,6 +52,15 @@
>>>   #define SMK_RECEIVING  1
>>>   #define SMK_SENDING    2
>>>
>>> +/*
>>> + * Smack uses multiple xattrs.
>>> + * SMACK64 - for access control, SMACK64EXEC - label for the program,
>> I think it would be good to move SMACK64EXEC to its own line; it took
>> me a minute to figure out why SMACK_INODE_INIT_XATTRS was set to '4'
>> when I only say three comment lines ... ;)
>>
>>> + * SMACK64MMAP - controls library loading,
>>> + * SMACK64TRANSMUTE - label initialization,
>>> + * Not saved on files - SMACK64IPIN and SMACK64IPOUT
>>> + */
>>> +#define SMACK_INODE_INIT_XATTRS 4
>> If smack_inode_init_security() only ever populates a single xattr, and
>> that is the only current user of SMACK_INODE_INIT_XATTRS, can we make
>> this '1' and shrink the xattr allocation a bit?
> 
> If the parent directory is marked with SMACK64_TRANSMUTE, the access
> rule allowing the access has the "t" mode, and the object being initialized
> is a directory, the new inode should get the SMACK64_TRANSMUTE attribute.
> The callers of security_inode_init_security() don't seem to care.
> I can't say if the evm code is getting SMACK64_TRANSMUTE or, for that
> matter, SMACK64_EXEC and SMACK64_MMAP, some other way. The older system
> allowed for multiple Smack xattrs, but I'm not clear on exactly how.

If you like to set an additional xattr, that would be possible now. 
Since we reserve multiple xattrs, we can call lsm_get_xattr_slot() 
another time and set SMACK64_TRANSMUTE.

I think, if the kernel config has CONFIG_EVM_EXTRA_SMACK_XATTRS set,
EVM would protect SMACK64_TRANSMUTE too.

Roberto

>>>   #ifdef SMACK_IPV6_PORT_LABELING
>>>   static DEFINE_MUTEX(smack_ipv6_lock);
>>>   static LIST_HEAD(smk_ipv6_port_list);
>>> @@ -939,26 +948,23 @@ static int smack_inode_alloc_security(struct inode *inode)
>>>    * @inode: the newly created inode
>>>    * @dir: containing directory object
>>>    * @qstr: unused
>>> - * @name: where to put the attribute name
>>> - * @value: where to put the attribute value
>>> - * @len: where to put the length of the attribute
>>> + * @xattrs: where to put the attributes
>>> + * @xattr_count: current number of LSM-provided xattrs (updated)
>>>    *
>>>    * Returns 0 if it all works out, -ENOMEM if there's no memory
>>>    */
>>>   static int smack_inode_init_security(struct inode *inode, struct inode *dir,
>>> -                                    const struct qstr *qstr, const char **name,
>>> -                                    void **value, size_t *len)
>>> +                                    const struct qstr *qstr,
>>> +                                    struct xattr *xattrs, int *xattr_count)
>>>   {
>>>          struct inode_smack *issp = smack_inode(inode);
>>>          struct smack_known *skp = smk_of_current();
>>>          struct smack_known *isp = smk_of_inode(inode);
>>>          struct smack_known *dsp = smk_of_inode(dir);
>>> +       struct xattr *xattr = lsm_get_xattr_slot(xattrs, xattr_count);
>>>          int may;
>>>
>>> -       if (name)
>>> -               *name = XATTR_SMACK_SUFFIX;
>>> -
>>> -       if (value && len) {
>>> +       if (xattr) {
>>>                  rcu_read_lock();
>>>                  may = smk_access_entry(skp->smk_known, dsp->smk_known,
>>>                                         &skp->smk_rules);
>>> @@ -976,11 +982,12 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
>>>                          issp->smk_flags |= SMK_INODE_CHANGED;
>>>                  }
>>>
>>> -               *value = kstrdup(isp->smk_known, GFP_NOFS);
>>> -               if (*value == NULL)
>>> +               xattr->value = kstrdup(isp->smk_known, GFP_NOFS);
>>> +               if (xattr->value == NULL)
>>>                          return -ENOMEM;
>>>
>>> -               *len = strlen(isp->smk_known);
>>> +               xattr->value_len = strlen(isp->smk_known);
>>> +               xattr->name = XATTR_SMACK_SUFFIX;
>>>          }
>>>
>>>          return 0;
>>> @@ -4854,6 +4861,7 @@ struct lsm_blob_sizes smack_blob_sizes __lsm_ro_after_init = {
>>>          .lbs_ipc = sizeof(struct smack_known *),
>>>          .lbs_msg_msg = sizeof(struct smack_known *),
>>>          .lbs_superblock = sizeof(struct superblock_smack),
>>> +       .lbs_xattr_count = SMACK_INODE_INIT_XATTRS,
>>>   };
>>>
>>>   static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {
>>> --
>>> 2.25.1


^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v10 2/4] security: Allow all LSMs to provide xattrs for inode_init_security hook
  2023-04-05  9:43       ` Roberto Sassu
@ 2023-04-05 19:59         ` Paul Moore
  2023-04-05 20:43           ` Casey Schaufler
  0 siblings, 1 reply; 44+ messages in thread
From: Paul Moore @ 2023-04-05 19:59 UTC (permalink / raw)
  To: Roberto Sassu
  Cc: Casey Schaufler, zohar, dmitry.kasatkin, jmorris, serge,
	stephen.smalley.work, eparis, reiserfs-devel, linux-kernel,
	linux-integrity, linux-security-module, selinux, bpf, kpsingh,
	keescook, nicolas.bouchinet, Roberto Sassu

On Wed, Apr 5, 2023 at 5:44 AM Roberto Sassu
<roberto.sassu@huaweicloud.com> wrote:
> On 4/5/2023 4:08 AM, Casey Schaufler wrote:
> > On 4/4/2023 11:54 AM, Paul Moore wrote:
> >> On Fri, Mar 31, 2023 at 8:33 AM Roberto Sassu
> >> <roberto.sassu@huaweicloud.com> wrote:

...

> >>> diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
> >>> index cfcbb748da2..8392983334b 100644
> >>> --- a/security/smack/smack_lsm.c
> >>> +++ b/security/smack/smack_lsm.c
> >>> @@ -52,6 +52,15 @@
> >>>   #define SMK_RECEIVING  1
> >>>   #define SMK_SENDING    2
> >>>
> >>> +/*
> >>> + * Smack uses multiple xattrs.
> >>> + * SMACK64 - for access control, SMACK64EXEC - label for the program,
> >> I think it would be good to move SMACK64EXEC to its own line; it took
> >> me a minute to figure out why SMACK_INODE_INIT_XATTRS was set to '4'
> >> when I only say three comment lines ... ;)
> >>
> >>> + * SMACK64MMAP - controls library loading,
> >>> + * SMACK64TRANSMUTE - label initialization,
> >>> + * Not saved on files - SMACK64IPIN and SMACK64IPOUT
> >>> + */
> >>> +#define SMACK_INODE_INIT_XATTRS 4
> >>
> >> If smack_inode_init_security() only ever populates a single xattr, and
> >> that is the only current user of SMACK_INODE_INIT_XATTRS, can we make
> >> this '1' and shrink the xattr allocation a bit?
> >
> > If the parent directory is marked with SMACK64_TRANSMUTE, the access
> > rule allowing the access has the "t" mode, and the object being initialized
> > is a directory, the new inode should get the SMACK64_TRANSMUTE attribute.
> > The callers of security_inode_init_security() don't seem to care.
> > I can't say if the evm code is getting SMACK64_TRANSMUTE or, for that
> > matter, SMACK64_EXEC and SMACK64_MMAP, some other way. The older system
> > allowed for multiple Smack xattrs, but I'm not clear on exactly how.
>
> If you like to set an additional xattr, that would be possible now.
> Since we reserve multiple xattrs, we can call lsm_get_xattr_slot()
> another time and set SMACK64_TRANSMUTE.
>
> I think, if the kernel config has CONFIG_EVM_EXTRA_SMACK_XATTRS set,
> EVM would protect SMACK64_TRANSMUTE too.

Ooookay, but can someone explain to me how either the current, or
patched, smack_inode_init_security() function can return multiple
xattrs via the security_inode_init_security() LSM hook?  I'm hoping
I'm missing something really obvious, but I can only see a single
Smack xattr being returned ...

-- 
paul-moore.com

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v10 2/4] security: Allow all LSMs to provide xattrs for inode_init_security hook
  2023-04-05 19:59         ` Paul Moore
@ 2023-04-05 20:43           ` Casey Schaufler
  2023-04-05 20:49             ` Paul Moore
  2023-04-06  9:08             ` Roberto Sassu
  0 siblings, 2 replies; 44+ messages in thread
From: Casey Schaufler @ 2023-04-05 20:43 UTC (permalink / raw)
  To: Paul Moore, Roberto Sassu
  Cc: zohar, dmitry.kasatkin, jmorris, serge, stephen.smalley.work,
	eparis, reiserfs-devel, linux-kernel, linux-integrity,
	linux-security-module, selinux, bpf, kpsingh, keescook,
	nicolas.bouchinet, Roberto Sassu, Casey Schaufler

On 4/5/2023 12:59 PM, Paul Moore wrote:
> On Wed, Apr 5, 2023 at 5:44 AM Roberto Sassu
> <roberto.sassu@huaweicloud.com> wrote:
>> On 4/5/2023 4:08 AM, Casey Schaufler wrote:
>>> On 4/4/2023 11:54 AM, Paul Moore wrote:
>>>> On Fri, Mar 31, 2023 at 8:33 AM Roberto Sassu
>>>> <roberto.sassu@huaweicloud.com> wrote:
> ..
>
>>>>> diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
>>>>> index cfcbb748da2..8392983334b 100644
>>>>> --- a/security/smack/smack_lsm.c
>>>>> +++ b/security/smack/smack_lsm.c
>>>>> @@ -52,6 +52,15 @@
>>>>>   #define SMK_RECEIVING  1
>>>>>   #define SMK_SENDING    2
>>>>>
>>>>> +/*
>>>>> + * Smack uses multiple xattrs.
>>>>> + * SMACK64 - for access control, SMACK64EXEC - label for the program,
>>>> I think it would be good to move SMACK64EXEC to its own line; it took
>>>> me a minute to figure out why SMACK_INODE_INIT_XATTRS was set to '4'
>>>> when I only say three comment lines ... ;)
>>>>
>>>>> + * SMACK64MMAP - controls library loading,
>>>>> + * SMACK64TRANSMUTE - label initialization,
>>>>> + * Not saved on files - SMACK64IPIN and SMACK64IPOUT
>>>>> + */
>>>>> +#define SMACK_INODE_INIT_XATTRS 4
>>>> If smack_inode_init_security() only ever populates a single xattr, and
>>>> that is the only current user of SMACK_INODE_INIT_XATTRS, can we make
>>>> this '1' and shrink the xattr allocation a bit?
>>> If the parent directory is marked with SMACK64_TRANSMUTE, the access
>>> rule allowing the access has the "t" mode, and the object being initialized
>>> is a directory, the new inode should get the SMACK64_TRANSMUTE attribute.
>>> The callers of security_inode_init_security() don't seem to care.
>>> I can't say if the evm code is getting SMACK64_TRANSMUTE or, for that
>>> matter, SMACK64_EXEC and SMACK64_MMAP, some other way. The older system
>>> allowed for multiple Smack xattrs, but I'm not clear on exactly how.
>> If you like to set an additional xattr, that would be possible now.
>> Since we reserve multiple xattrs, we can call lsm_get_xattr_slot()
>> another time and set SMACK64_TRANSMUTE.
>>
>> I think, if the kernel config has CONFIG_EVM_EXTRA_SMACK_XATTRS set,
>> EVM would protect SMACK64_TRANSMUTE too.
> Ooookay, but can someone explain to me how either the current, or
> patched, smack_inode_init_security() function can return multiple
> xattrs via the security_inode_init_security() LSM hook?

It can't.

>   I'm hoping
> I'm missing something really obvious, but I can only see a single
> Smack xattr being returned ...

Smack is setting the transmute attribute in smack_d_instantiate().
The exec and mmap attributes are always set explicitly.

I don't know how the "extra" Smack attributes were obtained by evm
before, and I haven't been looking at how they're doing it now.
I have assumed that CONFIG_EVM_EXTRA_SMACK_XATTRS does something
meaningful.


^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v10 2/4] security: Allow all LSMs to provide xattrs for inode_init_security hook
  2023-04-05 20:43           ` Casey Schaufler
@ 2023-04-05 20:49             ` Paul Moore
  2023-04-05 21:07               ` Casey Schaufler
  2023-04-06  9:08             ` Roberto Sassu
  1 sibling, 1 reply; 44+ messages in thread
From: Paul Moore @ 2023-04-05 20:49 UTC (permalink / raw)
  To: Casey Schaufler
  Cc: Roberto Sassu, zohar, dmitry.kasatkin, jmorris, serge,
	stephen.smalley.work, eparis, reiserfs-devel, linux-kernel,
	linux-integrity, linux-security-module, selinux, bpf, kpsingh,
	keescook, nicolas.bouchinet, Roberto Sassu

On Wed, Apr 5, 2023 at 4:43 PM Casey Schaufler <casey@schaufler-ca.com> wrote:
> On 4/5/2023 12:59 PM, Paul Moore wrote:
> > On Wed, Apr 5, 2023 at 5:44 AM Roberto Sassu
> > <roberto.sassu@huaweicloud.com> wrote:
> >> On 4/5/2023 4:08 AM, Casey Schaufler wrote:
> >>> On 4/4/2023 11:54 AM, Paul Moore wrote:
> >>>> On Fri, Mar 31, 2023 at 8:33 AM Roberto Sassu
> >>>> <roberto.sassu@huaweicloud.com> wrote:
> > ..
> >
> >>>>> diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
> >>>>> index cfcbb748da2..8392983334b 100644
> >>>>> --- a/security/smack/smack_lsm.c
> >>>>> +++ b/security/smack/smack_lsm.c
> >>>>> @@ -52,6 +52,15 @@
> >>>>>   #define SMK_RECEIVING  1
> >>>>>   #define SMK_SENDING    2
> >>>>>
> >>>>> +/*
> >>>>> + * Smack uses multiple xattrs.
> >>>>> + * SMACK64 - for access control, SMACK64EXEC - label for the program,
> >>>> I think it would be good to move SMACK64EXEC to its own line; it took
> >>>> me a minute to figure out why SMACK_INODE_INIT_XATTRS was set to '4'
> >>>> when I only say three comment lines ... ;)
> >>>>
> >>>>> + * SMACK64MMAP - controls library loading,
> >>>>> + * SMACK64TRANSMUTE - label initialization,
> >>>>> + * Not saved on files - SMACK64IPIN and SMACK64IPOUT
> >>>>> + */
> >>>>> +#define SMACK_INODE_INIT_XATTRS 4
> >>>> If smack_inode_init_security() only ever populates a single xattr, and
> >>>> that is the only current user of SMACK_INODE_INIT_XATTRS, can we make
> >>>> this '1' and shrink the xattr allocation a bit?
> >>> If the parent directory is marked with SMACK64_TRANSMUTE, the access
> >>> rule allowing the access has the "t" mode, and the object being initialized
> >>> is a directory, the new inode should get the SMACK64_TRANSMUTE attribute.
> >>> The callers of security_inode_init_security() don't seem to care.
> >>> I can't say if the evm code is getting SMACK64_TRANSMUTE or, for that
> >>> matter, SMACK64_EXEC and SMACK64_MMAP, some other way. The older system
> >>> allowed for multiple Smack xattrs, but I'm not clear on exactly how.
> >> If you like to set an additional xattr, that would be possible now.
> >> Since we reserve multiple xattrs, we can call lsm_get_xattr_slot()
> >> another time and set SMACK64_TRANSMUTE.
> >>
> >> I think, if the kernel config has CONFIG_EVM_EXTRA_SMACK_XATTRS set,
> >> EVM would protect SMACK64_TRANSMUTE too.
> >
> > Ooookay, but can someone explain to me how either the current, or
> > patched, smack_inode_init_security() function can return multiple
> > xattrs via the security_inode_init_security() LSM hook?
>
> It can't.

I didn't think so.

To be really specific, that's what we're talking about with this
patch: the number of xattrs that smack_inode_init_security() can
return to the LSM hook (and EVM, and the caller ...).  If it's only
ever going to be one, I think we can adjust the
'SMACK_INODE_INIT_XATTRS' down to '1' and save ourselves some
allocation space.

-- 
paul-moore.com

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v10 2/4] security: Allow all LSMs to provide xattrs for inode_init_security hook
  2023-04-05 20:49             ` Paul Moore
@ 2023-04-05 21:07               ` Casey Schaufler
  2023-04-06  9:14                 ` Roberto Sassu
  0 siblings, 1 reply; 44+ messages in thread
From: Casey Schaufler @ 2023-04-05 21:07 UTC (permalink / raw)
  To: Paul Moore
  Cc: Roberto Sassu, zohar, dmitry.kasatkin, jmorris, serge,
	stephen.smalley.work, eparis, reiserfs-devel, linux-kernel,
	linux-integrity, linux-security-module, selinux, bpf, kpsingh,
	keescook, nicolas.bouchinet, Roberto Sassu, Casey Schaufler

On 4/5/2023 1:49 PM, Paul Moore wrote:
> On Wed, Apr 5, 2023 at 4:43 PM Casey Schaufler <casey@schaufler-ca.com> wrote:
>> On 4/5/2023 12:59 PM, Paul Moore wrote:
>>> On Wed, Apr 5, 2023 at 5:44 AM Roberto Sassu
>>> <roberto.sassu@huaweicloud.com> wrote:
>>>> On 4/5/2023 4:08 AM, Casey Schaufler wrote:
>>>>> On 4/4/2023 11:54 AM, Paul Moore wrote:
>>>>>> On Fri, Mar 31, 2023 at 8:33 AM Roberto Sassu
>>>>>> <roberto.sassu@huaweicloud.com> wrote:
>>> ..
>>>
>>>>>>> diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
>>>>>>> index cfcbb748da2..8392983334b 100644
>>>>>>> --- a/security/smack/smack_lsm.c
>>>>>>> +++ b/security/smack/smack_lsm.c
>>>>>>> @@ -52,6 +52,15 @@
>>>>>>>   #define SMK_RECEIVING  1
>>>>>>>   #define SMK_SENDING    2
>>>>>>>
>>>>>>> +/*
>>>>>>> + * Smack uses multiple xattrs.
>>>>>>> + * SMACK64 - for access control, SMACK64EXEC - label for the program,
>>>>>> I think it would be good to move SMACK64EXEC to its own line; it took
>>>>>> me a minute to figure out why SMACK_INODE_INIT_XATTRS was set to '4'
>>>>>> when I only say three comment lines ... ;)
>>>>>>
>>>>>>> + * SMACK64MMAP - controls library loading,
>>>>>>> + * SMACK64TRANSMUTE - label initialization,
>>>>>>> + * Not saved on files - SMACK64IPIN and SMACK64IPOUT
>>>>>>> + */
>>>>>>> +#define SMACK_INODE_INIT_XATTRS 4
>>>>>> If smack_inode_init_security() only ever populates a single xattr, and
>>>>>> that is the only current user of SMACK_INODE_INIT_XATTRS, can we make
>>>>>> this '1' and shrink the xattr allocation a bit?
>>>>> If the parent directory is marked with SMACK64_TRANSMUTE, the access
>>>>> rule allowing the access has the "t" mode, and the object being initialized
>>>>> is a directory, the new inode should get the SMACK64_TRANSMUTE attribute.
>>>>> The callers of security_inode_init_security() don't seem to care.
>>>>> I can't say if the evm code is getting SMACK64_TRANSMUTE or, for that
>>>>> matter, SMACK64_EXEC and SMACK64_MMAP, some other way. The older system
>>>>> allowed for multiple Smack xattrs, but I'm not clear on exactly how.
>>>> If you like to set an additional xattr, that would be possible now.
>>>> Since we reserve multiple xattrs, we can call lsm_get_xattr_slot()
>>>> another time and set SMACK64_TRANSMUTE.
>>>>
>>>> I think, if the kernel config has CONFIG_EVM_EXTRA_SMACK_XATTRS set,
>>>> EVM would protect SMACK64_TRANSMUTE too.
>>> Ooookay, but can someone explain to me how either the current, or
>>> patched, smack_inode_init_security() function can return multiple
>>> xattrs via the security_inode_init_security() LSM hook?
>> It can't.
> I didn't think so.
>
> To be really specific, that's what we're talking about with this
> patch: the number of xattrs that smack_inode_init_security() can
> return to the LSM hook (and EVM, and the caller ...).  If it's only
> ever going to be one, I think we can adjust the
> 'SMACK_INODE_INIT_XATTRS' down to '1' and save ourselves some
> allocation space.

Does evm have an expectation that mumble_inode_init_security() is
going to report all the relevant attributes? It has to be getting
them somehow, which leads me to wonder if we might want to extend
smack_inode_init_security() to do so. Even if we did, the maximum
value would be '2', SMACK64 and SMACK64_TRANSMUTE. Now that would
require a whole lot of work in the calling filesystems, as setting
the transmute attribute would be moving out of smack_d_instantiate()
and into the callers. Or something like that. 


^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v10 2/4] security: Allow all LSMs to provide xattrs for inode_init_security hook
  2023-04-05 20:43           ` Casey Schaufler
  2023-04-05 20:49             ` Paul Moore
@ 2023-04-06  9:08             ` Roberto Sassu
  1 sibling, 0 replies; 44+ messages in thread
From: Roberto Sassu @ 2023-04-06  9:08 UTC (permalink / raw)
  To: Casey Schaufler, Paul Moore
  Cc: zohar, dmitry.kasatkin, jmorris, serge, stephen.smalley.work,
	eparis, reiserfs-devel, linux-kernel, linux-integrity,
	linux-security-module, selinux, bpf, kpsingh, keescook,
	nicolas.bouchinet, Roberto Sassu

On 4/5/2023 10:43 PM, Casey Schaufler wrote:
> On 4/5/2023 12:59 PM, Paul Moore wrote:
>> On Wed, Apr 5, 2023 at 5:44 AM Roberto Sassu
>> <roberto.sassu@huaweicloud.com> wrote:
>>> On 4/5/2023 4:08 AM, Casey Schaufler wrote:
>>>> On 4/4/2023 11:54 AM, Paul Moore wrote:
>>>>> On Fri, Mar 31, 2023 at 8:33 AM Roberto Sassu
>>>>> <roberto.sassu@huaweicloud.com> wrote:
>> ..
>>
>>>>>> diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
>>>>>> index cfcbb748da2..8392983334b 100644
>>>>>> --- a/security/smack/smack_lsm.c
>>>>>> +++ b/security/smack/smack_lsm.c
>>>>>> @@ -52,6 +52,15 @@
>>>>>>    #define SMK_RECEIVING  1
>>>>>>    #define SMK_SENDING    2
>>>>>>
>>>>>> +/*
>>>>>> + * Smack uses multiple xattrs.
>>>>>> + * SMACK64 - for access control, SMACK64EXEC - label for the program,
>>>>> I think it would be good to move SMACK64EXEC to its own line; it took
>>>>> me a minute to figure out why SMACK_INODE_INIT_XATTRS was set to '4'
>>>>> when I only say three comment lines ... ;)
>>>>>
>>>>>> + * SMACK64MMAP - controls library loading,
>>>>>> + * SMACK64TRANSMUTE - label initialization,
>>>>>> + * Not saved on files - SMACK64IPIN and SMACK64IPOUT
>>>>>> + */
>>>>>> +#define SMACK_INODE_INIT_XATTRS 4
>>>>> If smack_inode_init_security() only ever populates a single xattr, and
>>>>> that is the only current user of SMACK_INODE_INIT_XATTRS, can we make
>>>>> this '1' and shrink the xattr allocation a bit?
>>>> If the parent directory is marked with SMACK64_TRANSMUTE, the access
>>>> rule allowing the access has the "t" mode, and the object being initialized
>>>> is a directory, the new inode should get the SMACK64_TRANSMUTE attribute.
>>>> The callers of security_inode_init_security() don't seem to care.
>>>> I can't say if the evm code is getting SMACK64_TRANSMUTE or, for that
>>>> matter, SMACK64_EXEC and SMACK64_MMAP, some other way. The older system
>>>> allowed for multiple Smack xattrs, but I'm not clear on exactly how.
>>> If you like to set an additional xattr, that would be possible now.
>>> Since we reserve multiple xattrs, we can call lsm_get_xattr_slot()
>>> another time and set SMACK64_TRANSMUTE.
>>>
>>> I think, if the kernel config has CONFIG_EVM_EXTRA_SMACK_XATTRS set,
>>> EVM would protect SMACK64_TRANSMUTE too.
>> Ooookay, but can someone explain to me how either the current, or
>> patched, smack_inode_init_security() function can return multiple
>> xattrs via the security_inode_init_security() LSM hook?
> 
> It can't.
> 
>>    I'm hoping
>> I'm missing something really obvious, but I can only see a single
>> Smack xattr being returned ...
> 
> Smack is setting the transmute attribute in smack_d_instantiate().
> The exec and mmap attributes are always set explicitly.
> 
> I don't know how the "extra" Smack attributes were obtained by evm
> before, and I haven't been looking at how they're doing it now.
> I have assumed that CONFIG_EVM_EXTRA_SMACK_XATTRS does something
> meaningful.

EVM has a list of xattrs to protect. Without 
CONFIG_EVM_EXTRA_SMACK_XATTRS, EVM protects only security.SMACK64. With 
it, also the other Smack xattrs.

EVM calculates the HMAC of xattrs from that list at inode creation time 
(during the execution of security_inode_init_security(), after other 
LSMs) and during set/remove xattrs operations on the VFS.

Currently, Smack provides only security.SMACK64, so I agree with Paul 
that we should reserve as many xattr as we use. If in the future, we add 
security.SMACK_TRANSMUTE64, we can increase the number of reserved 
xattrs to 2.

Roberto


^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v10 2/4] security: Allow all LSMs to provide xattrs for inode_init_security hook
  2023-04-05 21:07               ` Casey Schaufler
@ 2023-04-06  9:14                 ` Roberto Sassu
  2023-04-06 16:17                   ` Casey Schaufler
  0 siblings, 1 reply; 44+ messages in thread
From: Roberto Sassu @ 2023-04-06  9:14 UTC (permalink / raw)
  To: Casey Schaufler, Paul Moore
  Cc: zohar, dmitry.kasatkin, jmorris, serge, stephen.smalley.work,
	eparis, reiserfs-devel, linux-kernel, linux-integrity,
	linux-security-module, selinux, bpf, kpsingh, keescook,
	nicolas.bouchinet, Roberto Sassu

On 4/5/2023 11:07 PM, Casey Schaufler wrote:
> On 4/5/2023 1:49 PM, Paul Moore wrote:
>> On Wed, Apr 5, 2023 at 4:43 PM Casey Schaufler <casey@schaufler-ca.com> wrote:
>>> On 4/5/2023 12:59 PM, Paul Moore wrote:
>>>> On Wed, Apr 5, 2023 at 5:44 AM Roberto Sassu
>>>> <roberto.sassu@huaweicloud.com> wrote:
>>>>> On 4/5/2023 4:08 AM, Casey Schaufler wrote:
>>>>>> On 4/4/2023 11:54 AM, Paul Moore wrote:
>>>>>>> On Fri, Mar 31, 2023 at 8:33 AM Roberto Sassu
>>>>>>> <roberto.sassu@huaweicloud.com> wrote:
>>>> ..
>>>>
>>>>>>>> diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
>>>>>>>> index cfcbb748da2..8392983334b 100644
>>>>>>>> --- a/security/smack/smack_lsm.c
>>>>>>>> +++ b/security/smack/smack_lsm.c
>>>>>>>> @@ -52,6 +52,15 @@
>>>>>>>>    #define SMK_RECEIVING  1
>>>>>>>>    #define SMK_SENDING    2
>>>>>>>>
>>>>>>>> +/*
>>>>>>>> + * Smack uses multiple xattrs.
>>>>>>>> + * SMACK64 - for access control, SMACK64EXEC - label for the program,
>>>>>>> I think it would be good to move SMACK64EXEC to its own line; it took
>>>>>>> me a minute to figure out why SMACK_INODE_INIT_XATTRS was set to '4'
>>>>>>> when I only say three comment lines ... ;)
>>>>>>>
>>>>>>>> + * SMACK64MMAP - controls library loading,
>>>>>>>> + * SMACK64TRANSMUTE - label initialization,
>>>>>>>> + * Not saved on files - SMACK64IPIN and SMACK64IPOUT
>>>>>>>> + */
>>>>>>>> +#define SMACK_INODE_INIT_XATTRS 4
>>>>>>> If smack_inode_init_security() only ever populates a single xattr, and
>>>>>>> that is the only current user of SMACK_INODE_INIT_XATTRS, can we make
>>>>>>> this '1' and shrink the xattr allocation a bit?
>>>>>> If the parent directory is marked with SMACK64_TRANSMUTE, the access
>>>>>> rule allowing the access has the "t" mode, and the object being initialized
>>>>>> is a directory, the new inode should get the SMACK64_TRANSMUTE attribute.
>>>>>> The callers of security_inode_init_security() don't seem to care.
>>>>>> I can't say if the evm code is getting SMACK64_TRANSMUTE or, for that
>>>>>> matter, SMACK64_EXEC and SMACK64_MMAP, some other way. The older system
>>>>>> allowed for multiple Smack xattrs, but I'm not clear on exactly how.
>>>>> If you like to set an additional xattr, that would be possible now.
>>>>> Since we reserve multiple xattrs, we can call lsm_get_xattr_slot()
>>>>> another time and set SMACK64_TRANSMUTE.
>>>>>
>>>>> I think, if the kernel config has CONFIG_EVM_EXTRA_SMACK_XATTRS set,
>>>>> EVM would protect SMACK64_TRANSMUTE too.
>>>> Ooookay, but can someone explain to me how either the current, or
>>>> patched, smack_inode_init_security() function can return multiple
>>>> xattrs via the security_inode_init_security() LSM hook?
>>> It can't.
>> I didn't think so.
>>
>> To be really specific, that's what we're talking about with this
>> patch: the number of xattrs that smack_inode_init_security() can
>> return to the LSM hook (and EVM, and the caller ...).  If it's only
>> ever going to be one, I think we can adjust the
>> 'SMACK_INODE_INIT_XATTRS' down to '1' and save ourselves some
>> allocation space.
> 
> Does evm have an expectation that mumble_inode_init_security() is
> going to report all the relevant attributes? It has to be getting
> them somehow, which leads me to wonder if we might want to extend
> smack_inode_init_security() to do so. Even if we did, the maximum
> value would be '2', SMACK64 and SMACK64_TRANSMUTE. Now that would
> require a whole lot of work in the calling filesystems, as setting
> the transmute attribute would be moving out of smack_d_instantiate()
> and into the callers. Or something like that.

After changing the inode_init_security hook definition to pass the full 
xattr array, this is not going to be a problem. EVM sees all xattrs that 
are going to be set when an inode is created, and adds its own too.

If you have enough information to set security.SMACK_TRANSMUTE64 in 
smack_inode_init_security(), this patch sets already allows to set both 
xattrs at the same time. We would just need to call lsm_get_xattr_slot() 
another time, assuming that we reserve two xattrs.

Roberto


^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v10 2/4] security: Allow all LSMs to provide xattrs for inode_init_security hook
  2023-04-06  9:14                 ` Roberto Sassu
@ 2023-04-06 16:17                   ` Casey Schaufler
  0 siblings, 0 replies; 44+ messages in thread
From: Casey Schaufler @ 2023-04-06 16:17 UTC (permalink / raw)
  To: Roberto Sassu, Paul Moore
  Cc: zohar, dmitry.kasatkin, jmorris, serge, stephen.smalley.work,
	eparis, reiserfs-devel, linux-kernel, linux-integrity,
	linux-security-module, selinux, bpf, kpsingh, keescook,
	nicolas.bouchinet, Roberto Sassu, Casey Schaufler

On 4/6/2023 2:14 AM, Roberto Sassu wrote:
> On 4/5/2023 11:07 PM, Casey Schaufler wrote:
>> On 4/5/2023 1:49 PM, Paul Moore wrote:
>>> On Wed, Apr 5, 2023 at 4:43 PM Casey Schaufler
>>> <casey@schaufler-ca.com> wrote:
>>>> On 4/5/2023 12:59 PM, Paul Moore wrote:
>>>>> On Wed, Apr 5, 2023 at 5:44 AM Roberto Sassu
>>>>> <roberto.sassu@huaweicloud.com> wrote:
>>>>>> On 4/5/2023 4:08 AM, Casey Schaufler wrote:
>>>>>>> On 4/4/2023 11:54 AM, Paul Moore wrote:
>>>>>>>> On Fri, Mar 31, 2023 at 8:33 AM Roberto Sassu
>>>>>>>> <roberto.sassu@huaweicloud.com> wrote:
>>>>> ..
>>>>>
>>>>>>>>> diff --git a/security/smack/smack_lsm.c
>>>>>>>>> b/security/smack/smack_lsm.c
>>>>>>>>> index cfcbb748da2..8392983334b 100644
>>>>>>>>> --- a/security/smack/smack_lsm.c
>>>>>>>>> +++ b/security/smack/smack_lsm.c
>>>>>>>>> @@ -52,6 +52,15 @@
>>>>>>>>>    #define SMK_RECEIVING  1
>>>>>>>>>    #define SMK_SENDING    2
>>>>>>>>>
>>>>>>>>> +/*
>>>>>>>>> + * Smack uses multiple xattrs.
>>>>>>>>> + * SMACK64 - for access control, SMACK64EXEC - label for the
>>>>>>>>> program,
>>>>>>>> I think it would be good to move SMACK64EXEC to its own line;
>>>>>>>> it took
>>>>>>>> me a minute to figure out why SMACK_INODE_INIT_XATTRS was set
>>>>>>>> to '4'
>>>>>>>> when I only say three comment lines ... ;)
>>>>>>>>
>>>>>>>>> + * SMACK64MMAP - controls library loading,
>>>>>>>>> + * SMACK64TRANSMUTE - label initialization,
>>>>>>>>> + * Not saved on files - SMACK64IPIN and SMACK64IPOUT
>>>>>>>>> + */
>>>>>>>>> +#define SMACK_INODE_INIT_XATTRS 4
>>>>>>>> If smack_inode_init_security() only ever populates a single
>>>>>>>> xattr, and
>>>>>>>> that is the only current user of SMACK_INODE_INIT_XATTRS, can
>>>>>>>> we make
>>>>>>>> this '1' and shrink the xattr allocation a bit?
>>>>>>> If the parent directory is marked with SMACK64_TRANSMUTE, the
>>>>>>> access
>>>>>>> rule allowing the access has the "t" mode, and the object being
>>>>>>> initialized
>>>>>>> is a directory, the new inode should get the SMACK64_TRANSMUTE
>>>>>>> attribute.
>>>>>>> The callers of security_inode_init_security() don't seem to care.
>>>>>>> I can't say if the evm code is getting SMACK64_TRANSMUTE or, for
>>>>>>> that
>>>>>>> matter, SMACK64_EXEC and SMACK64_MMAP, some other way. The older
>>>>>>> system
>>>>>>> allowed for multiple Smack xattrs, but I'm not clear on exactly
>>>>>>> how.
>>>>>> If you like to set an additional xattr, that would be possible now.
>>>>>> Since we reserve multiple xattrs, we can call lsm_get_xattr_slot()
>>>>>> another time and set SMACK64_TRANSMUTE.
>>>>>>
>>>>>> I think, if the kernel config has CONFIG_EVM_EXTRA_SMACK_XATTRS set,
>>>>>> EVM would protect SMACK64_TRANSMUTE too.
>>>>> Ooookay, but can someone explain to me how either the current, or
>>>>> patched, smack_inode_init_security() function can return multiple
>>>>> xattrs via the security_inode_init_security() LSM hook?
>>>> It can't.
>>> I didn't think so.
>>>
>>> To be really specific, that's what we're talking about with this
>>> patch: the number of xattrs that smack_inode_init_security() can
>>> return to the LSM hook (and EVM, and the caller ...).  If it's only
>>> ever going to be one, I think we can adjust the
>>> 'SMACK_INODE_INIT_XATTRS' down to '1' and save ourselves some
>>> allocation space.
>>
>> Does evm have an expectation that mumble_inode_init_security() is
>> going to report all the relevant attributes? It has to be getting
>> them somehow, which leads me to wonder if we might want to extend
>> smack_inode_init_security() to do so. Even if we did, the maximum
>> value would be '2', SMACK64 and SMACK64_TRANSMUTE. Now that would
>> require a whole lot of work in the calling filesystems, as setting
>> the transmute attribute would be moving out of smack_d_instantiate()
>> and into the callers. Or something like that.
>
> After changing the inode_init_security hook definition to pass the
> full xattr array, this is not going to be a problem. EVM sees all
> xattrs that are going to be set when an inode is created, and adds its
> own too.
>
> If you have enough information to set security.SMACK_TRANSMUTE64 in
> smack_inode_init_security(),

I think there's enough information to do that. I'm going to have to look
at your patch more closely.

> this patch sets already allows to set both xattrs at the same time. We
> would just need to call lsm_get_xattr_slot() another time, assuming
> that we reserve two xattrs.
>
> Roberto
>

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v10 2/4] security: Allow all LSMs to provide xattrs for inode_init_security hook
  2023-03-31 12:32 ` [PATCH v10 2/4] security: Allow all LSMs to provide xattrs for inode_init_security hook Roberto Sassu
  2023-04-04 18:54   ` Paul Moore
@ 2023-04-11  7:22   ` Mimi Zohar
  2023-04-11  7:53     ` Roberto Sassu
  1 sibling, 1 reply; 44+ messages in thread
From: Mimi Zohar @ 2023-04-11  7:22 UTC (permalink / raw)
  To: Roberto Sassu, dmitry.kasatkin, paul, jmorris, serge,
	stephen.smalley.work, eparis, casey
  Cc: reiserfs-devel, linux-kernel, linux-integrity,
	linux-security-module, selinux, bpf, kpsingh, keescook,
	nicolas.bouchinet, Roberto Sassu

Hi Roberto,

Sorry for the delay in responding...

The patch description reads as though support for per LSM multiple
xattrs is being added in this patch, though lsm_get_xattr_slot() only
ever is incremented once for each LSM.  To simplify review, it would be
nice to mention that lsm_get_xattr_slot() would be called multiple
times per LSM xattr.

On Fri, 2023-03-31 at 14:32 +0200, Roberto Sassu wrote:
> From: Roberto Sassu <roberto.sassu@huawei.com>
> 
> Currently, security_inode_init_security() supports only one LSM providing
> an xattr and EVM calculating the HMAC on that xattr, plus other inode
> metadata.
> 
> Allow all LSMs to provide one or multiple xattrs, by extending the security
> blob reservation mechanism. Introduce the new lbs_xattr_count field of the
> lsm_blob_sizes structure, so that each LSM can specify how many xattrs it
> needs, and the LSM infrastructure knows how many xattr slots it should
> allocate.
> 
> Dynamically allocate the new_xattrs array to be populated by LSMs with the
> inode_init_security hook, and pass it to the latter instead of the
> name/value/len triple. Unify the !initxattrs and initxattrs case, simply
> don't allocate the new_xattrs array in the former.
> 
> Also, pass to the hook the number of xattrs filled by each LSM, so that
> there are no gaps when the next LSM fills the array. Gaps might occur
> because an LSM can legitimately request xattrs to the LSM infrastructure,
> but not fill the reserved slots, if it was not initialized.

The number of security xattrs permitted per LSM was discussed in the
second paragraph.  The first line of this paragraph needs to be updated
to reflect the current number of security xattrs used, though that is
more related to the new lsm_get_xattr_slot().  Or perhaps the entire
paragraph is unnecessary, a remnant from
security_check_compact_filled_xattrs(), and should be removed.  

> 
> Update the documentation of security_inode_init_security() to reflect the
> changes, and fix the description of the xattr name, as it is not allocated
> anymore.
> 
> Finally, adapt both SELinux and Smack to use the new definition of the
> inode_init_security hook, and to fill the reserved slots in the xattr
> array. Introduce the lsm_get_xattr_slot() helper to retrieve an available
> slot to fill, and to increment the number of filled slots.
> 
> Move the xattr->name assignment after the xattr->value one, so that it is
> done only in case of successful memory allocation. For Smack, also reserve
> space for the other defined xattrs although they are not set yet in
> smack_inode_init_security().

This Smack comment should be moved to the previous paragraph and even
expanded explaining that lsm_get_xattr_slot() will be called for each
additional security xattr.

> 
> Reported-by: Nicolas Bouchinet <nicolas.bouchinet@clip-os.org> (EVM crash)
> Link: https://lore.kernel.org/linux-integrity/Y1FTSIo+1x+4X0LS@archlinux/
> Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
> ---

> diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
> index c2be66c669a..9eb9b686493 100644
> --- a/include/linux/lsm_hooks.h
> +++ b/include/linux/lsm_hooks.h
> @@ -28,6 +28,7 @@
>  #include <linux/security.h>
>  #include <linux/init.h>
>  #include <linux/rculist.h>
> +#include <linux/xattr.h>
>  
>  union security_list_options {
>  	#define LSM_HOOK(RET, DEFAULT, NAME, ...) RET (*NAME)(__VA_ARGS__);
> @@ -63,8 +64,27 @@ struct lsm_blob_sizes {
>  	int	lbs_ipc;
>  	int	lbs_msg_msg;
>  	int	lbs_task;
> +	int	lbs_xattr_count; /* number of xattr slots in new_xattrs array */
>  };
>  
> +/**
> + * lsm_get_xattr_slot - Return the next available slot and increment the index
> + * @xattrs: array storing LSM-provided xattrs
> + * @xattr_count: number of already stored xattrs (updated)
> + *
> + * Retrieve the first available slot in the @xattrs array to fill with an xattr,
> + * and increment @xattr_count.
> + *
> + * Return: The slot to fill in @xattrs if non-NULL, NULL otherwise.
> + */
> +static inline struct xattr *lsm_get_xattr_slot(struct xattr *xattrs,
> +					       int *xattr_count)
> +{
> +	if (unlikely(!xattrs))
> +		return NULL;
> +	return xattrs + (*xattr_count)++;

At some point, since lsm_get_xattr_slot() could be called multiple
times from the same LSM, shouldn't there be some sort of bounds
checking?

-- 
thanks,

Mimi


^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v10 3/4] evm: Align evm_inode_init_security() definition with LSM infrastructure
  2023-03-31 12:32 ` [PATCH v10 3/4] evm: Align evm_inode_init_security() definition with LSM infrastructure Roberto Sassu
  2023-04-04 18:56   ` Paul Moore
@ 2023-04-11  7:22   ` Mimi Zohar
  2023-04-11  7:58     ` Roberto Sassu
  1 sibling, 1 reply; 44+ messages in thread
From: Mimi Zohar @ 2023-04-11  7:22 UTC (permalink / raw)
  To: Roberto Sassu, dmitry.kasatkin, paul, jmorris, serge,
	stephen.smalley.work, eparis, casey
  Cc: reiserfs-devel, linux-kernel, linux-integrity,
	linux-security-module, selinux, bpf, kpsingh, keescook,
	nicolas.bouchinet, Roberto Sassu

On Fri, 2023-03-31 at 14:32 +0200, Roberto Sassu wrote:
> From: Roberto Sassu <roberto.sassu@huawei.com>
> 
> Change the evm_inode_init_security() definition to align with the LSM
> infrastructure. Keep the existing behavior of including in the HMAC
> calculation only the first xattr provided by LSMs.
> 
> Changing the evm_inode_init_security() definition requires passing the
> xattr array allocated by security_inode_init_security(), and the number of
> xattrs filled by previously invoked LSMs.
> 
> Use the newly introduced lsm_get_xattr_slot() to position EVM correctly in
> the xattrs array, like a regular LSM, and to increment the number of filled
> slots. For now, the LSM infrastructure allocates enough xattrs slots to
> store the EVM xattr, without using the reservation mechanism.
> 
> Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
> ---
>  include/linux/evm.h               | 13 +++++++------
>  security/integrity/evm/evm_main.c | 16 ++++++++++------
>  security/security.c               |  6 +++---
>  3 files changed, 20 insertions(+), 15 deletions(-)
> 
> diff --git a/include/linux/evm.h b/include/linux/evm.h
> index 7dc1ee74169..597632c71c7 100644
> --- a/include/linux/evm.h
> +++ b/include/linux/evm.h
> @@ -56,9 +56,9 @@ static inline void evm_inode_post_set_acl(struct dentry *dentry,
>  {
>  	return evm_inode_post_setxattr(dentry, acl_name, NULL, 0);
>  }
> -extern int evm_inode_init_security(struct inode *inode,
> -				   const struct xattr *xattr_array,
> -				   struct xattr *evm);
> +extern int evm_inode_init_security(struct inode *inode, struct inode *dir,
> +				   const struct qstr *qstr,
> +				   struct xattr *xattrs, int *xattr_count);
>  extern bool evm_revalidate_status(const char *xattr_name);
>  extern int evm_protected_xattr_if_enabled(const char *req_xattr_name);
>  extern int evm_read_protected_xattrs(struct dentry *dentry, u8 *buffer,
> @@ -157,9 +157,10 @@ static inline void evm_inode_post_set_acl(struct dentry *dentry,
>  	return;
>  }
>  
> -static inline int evm_inode_init_security(struct inode *inode,
> -					  const struct xattr *xattr_array,
> -					  struct xattr *evm)
> +static inline int evm_inode_init_security(struct inode *inode, struct inode *dir,
> +					  const struct qstr *qstr,
> +					  struct xattr *xattrs,
> +					  int *xattr_count)
>  {
>  	return 0;
>  }
> diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c
> index cf24c525558..475196ce712 100644
> --- a/security/integrity/evm/evm_main.c
> +++ b/security/integrity/evm/evm_main.c
> @@ -21,6 +21,7 @@
>  #include <linux/evm.h>
>  #include <linux/magic.h>
>  #include <linux/posix_acl_xattr.h>
> +#include <linux/lsm_hooks.h>
>  
>  #include <crypto/hash.h>
>  #include <crypto/hash_info.h>
> @@ -864,23 +865,26 @@ void evm_inode_post_setattr(struct dentry *dentry, int ia_valid)
>  /*
>   * evm_inode_init_security - initializes security.evm HMAC value
>   */
> -int evm_inode_init_security(struct inode *inode,
> -				 const struct xattr *lsm_xattr,
> -				 struct xattr *evm_xattr)
> +int evm_inode_init_security(struct inode *inode, struct inode *dir,
> +			    const struct qstr *qstr, struct xattr *xattrs,
> +			    int *xattr_count)
>  {
>  	struct evm_xattr *xattr_data;
> +	struct xattr *evm_xattr;
>  	int rc;
>  
> -	if (!(evm_initialized & EVM_INIT_HMAC) ||
> -	    !evm_protected_xattr(lsm_xattr->name))
> +	if (!(evm_initialized & EVM_INIT_HMAC) || !xattrs ||
> +	    !evm_protected_xattr(xattrs->name))
>  		return 0;
>  
> +	evm_xattr = lsm_get_xattr_slot(xattrs, xattr_count);
> +
>  	xattr_data = kzalloc(sizeof(*xattr_data), GFP_NOFS);
>  	if (!xattr_data)
>  		return -ENOMEM;
>  
>  	xattr_data->data.type = EVM_XATTR_HMAC;
> -	rc = evm_init_hmac(inode, lsm_xattr, xattr_data->digest);
> +	rc = evm_init_hmac(inode, xattrs, xattr_data->digest);
>  	if (rc < 0)
>  		goto out;
>  
> diff --git a/security/security.c b/security/security.c
> index 1aeaa8ce449..ef7779ec8b2 100644
> --- a/security/security.c
> +++ b/security/security.c
> @@ -1645,9 +1645,9 @@ int security_inode_init_security(struct inode *inode, struct inode *dir,
>  	if (!xattr_count)
>  		goto out;
>  
> -	ret = evm_inode_init_security(inode, new_xattrs,
> -				      new_xattrs + xattr_count);
> -	if (ret)
> +	ret = evm_inode_init_security(inode, dir, qstr, new_xattrs,
> +				      &xattr_count);
> +	if (ret && ret != -EOPNOTSUPP)

As previously discussed, -EOPNOTSUPP originally meant that the
filesystem itself did not support writing xattrs.  So there was no
point in trying to write the EVM security xattr.   With the change in
-EOPNOTSUPP meaning, it will now try to write the EVM security xattr. 
Instead of glossing over the change in behavior, it needs to at least
be mentioned in the patch description.

>  		goto out;
>  	ret = initxattrs(inode, new_xattrs, fs_data);
>  out:

-- 
thanks,

Mimi


^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v10 4/4] evm: Support multiple LSMs providing an xattr
  2023-03-31 12:32 ` [PATCH v10 4/4] evm: Support multiple LSMs providing an xattr Roberto Sassu
@ 2023-04-11  7:22   ` Mimi Zohar
  0 siblings, 0 replies; 44+ messages in thread
From: Mimi Zohar @ 2023-04-11  7:22 UTC (permalink / raw)
  To: Roberto Sassu, dmitry.kasatkin, paul, jmorris, serge,
	stephen.smalley.work, eparis, casey
  Cc: reiserfs-devel, linux-kernel, linux-integrity,
	linux-security-module, selinux, bpf, kpsingh, keescook,
	nicolas.bouchinet, Roberto Sassu

On Fri, 2023-03-31 at 14:32 +0200, Roberto Sassu wrote:
> From: Roberto Sassu <roberto.sassu@huawei.com>
> 
> Currently, evm_inode_init_security() processes a single LSM xattr from the
> array passed by security_inode_init_security(), and calculates the HMAC on
> it and other inode metadata.
> 
> As the LSM infrastructure now can pass to EVM an array with multiple
> xattrs, scan them until the terminator (xattr name NULL), and calculate the
> HMAC on all of them.
> 
> Also, double check that the xattrs array terminator is the first non-filled
> slot (obtained with lsm_get_xattr_slot()). Consumers of the xattrs array,
> such as the initxattrs() callbacks, rely on the terminator.
> 
> Finally, change the name of the lsm_xattr parameter of evm_init_hmac() to
> xattrs, to reflect the new type of information passed.
> 
> Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>

Reviewed-by: Mimi Zohar <zohar@linux.ibm.com>


^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v10 2/4] security: Allow all LSMs to provide xattrs for inode_init_security hook
  2023-04-11  7:22   ` Mimi Zohar
@ 2023-04-11  7:53     ` Roberto Sassu
  2023-04-11 16:42       ` Casey Schaufler
  0 siblings, 1 reply; 44+ messages in thread
From: Roberto Sassu @ 2023-04-11  7:53 UTC (permalink / raw)
  To: Mimi Zohar, dmitry.kasatkin, paul, jmorris, serge,
	stephen.smalley.work, eparis, casey
  Cc: reiserfs-devel, linux-kernel, linux-integrity,
	linux-security-module, selinux, bpf, kpsingh, keescook,
	nicolas.bouchinet, Roberto Sassu

On Tue, 2023-04-11 at 03:22 -0400, Mimi Zohar wrote:
> Hi Roberto,
> 
> Sorry for the delay in responding...

Hi Mimi

no worries!

> The patch description reads as though support for per LSM multiple
> xattrs is being added in this patch, though lsm_get_xattr_slot() only
> ever is incremented once for each LSM.  To simplify review, it would be
> nice to mention that lsm_get_xattr_slot() would be called multiple
> times per LSM xattr.

Ok, I will mention it.

> On Fri, 2023-03-31 at 14:32 +0200, Roberto Sassu wrote:
> > From: Roberto Sassu <roberto.sassu@huawei.com>
> > 
> > Currently, security_inode_init_security() supports only one LSM providing
> > an xattr and EVM calculating the HMAC on that xattr, plus other inode
> > metadata.
> > 
> > Allow all LSMs to provide one or multiple xattrs, by extending the security
> > blob reservation mechanism. Introduce the new lbs_xattr_count field of the
> > lsm_blob_sizes structure, so that each LSM can specify how many xattrs it
> > needs, and the LSM infrastructure knows how many xattr slots it should
> > allocate.
> > 
> > Dynamically allocate the new_xattrs array to be populated by LSMs with the
> > inode_init_security hook, and pass it to the latter instead of the
> > name/value/len triple. Unify the !initxattrs and initxattrs case, simply
> > don't allocate the new_xattrs array in the former.
> > 
> > Also, pass to the hook the number of xattrs filled by each LSM, so that
> > there are no gaps when the next LSM fills the array. Gaps might occur
> > because an LSM can legitimately request xattrs to the LSM infrastructure,
> > but not fill the reserved slots, if it was not initialized.
> 
> The number of security xattrs permitted per LSM was discussed in the
> second paragraph.  The first line of this paragraph needs to be updated
> to reflect the current number of security xattrs used, though that is
> more related to the new lsm_get_xattr_slot().  Or perhaps the entire
> paragraph is unnecessary, a remnant from
> security_check_compact_filled_xattrs(), and should be removed.  

I would probably say in that paragraph that the number specified for
the lbs_xattr_count field determines how many times an LSM can call
lsm_get_xattr_slot().

> > Update the documentation of security_inode_init_security() to reflect the
> > changes, and fix the description of the xattr name, as it is not allocated
> > anymore.
> > 
> > Finally, adapt both SELinux and Smack to use the new definition of the
> > inode_init_security hook, and to fill the reserved slots in the xattr
> > array. Introduce the lsm_get_xattr_slot() helper to retrieve an available
> > slot to fill, and to increment the number of filled slots.
> > 
> > Move the xattr->name assignment after the xattr->value one, so that it is
> > done only in case of successful memory allocation. For Smack, also reserve
> > space for the other defined xattrs although they are not set yet in
> > smack_inode_init_security().
> 
> This Smack comment should be moved to the previous paragraph and even
> expanded explaining that lsm_get_xattr_slot() will be called for each
> additional security xattr.

From previous Paul's and Casey's comments, Smack will have just two
xattrs, assuming that security.SMACK_TRASMUTE64 can be set in
smack_inode_init_security(). I will change this part accordingly once
Casey can have a look at the function.

> > Reported-by: Nicolas Bouchinet <nicolas.bouchinet@clip-os.org> (EVM crash)
> > Link: https://lore.kernel.org/linux-integrity/Y1FTSIo+1x+4X0LS@archlinux/
> > Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
> > ---
> > diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
> > index c2be66c669a..9eb9b686493 100644
> > --- a/include/linux/lsm_hooks.h
> > +++ b/include/linux/lsm_hooks.h
> > @@ -28,6 +28,7 @@
> >  #include <linux/security.h>
> >  #include <linux/init.h>
> >  #include <linux/rculist.h>
> > +#include <linux/xattr.h>
> >  
> >  union security_list_options {
> >  	#define LSM_HOOK(RET, DEFAULT, NAME, ...) RET (*NAME)(__VA_ARGS__);
> > @@ -63,8 +64,27 @@ struct lsm_blob_sizes {
> >  	int	lbs_ipc;
> >  	int	lbs_msg_msg;
> >  	int	lbs_task;
> > +	int	lbs_xattr_count; /* number of xattr slots in new_xattrs array */
> >  };
> >  
> > +/**
> > + * lsm_get_xattr_slot - Return the next available slot and increment the index
> > + * @xattrs: array storing LSM-provided xattrs
> > + * @xattr_count: number of already stored xattrs (updated)
> > + *
> > + * Retrieve the first available slot in the @xattrs array to fill with an xattr,
> > + * and increment @xattr_count.
> > + *
> > + * Return: The slot to fill in @xattrs if non-NULL, NULL otherwise.
> > + */
> > +static inline struct xattr *lsm_get_xattr_slot(struct xattr *xattrs,
> > +					       int *xattr_count)
> > +{
> > +	if (unlikely(!xattrs))
> > +		return NULL;
> > +	return xattrs + (*xattr_count)++;
> 
> At some point, since lsm_get_xattr_slot() could be called multiple
> times from the same LSM, shouldn't there be some sort of bounds
> checking?

From previous Paul's comments, I understood that he prefers to avoid
extra checks. It will be up to LSM developers to ensure that the API is
used correctly.

Thanks

Roberto


^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v10 3/4] evm: Align evm_inode_init_security() definition with LSM infrastructure
  2023-04-11  7:22   ` Mimi Zohar
@ 2023-04-11  7:58     ` Roberto Sassu
  0 siblings, 0 replies; 44+ messages in thread
From: Roberto Sassu @ 2023-04-11  7:58 UTC (permalink / raw)
  To: Mimi Zohar, dmitry.kasatkin, paul, jmorris, serge,
	stephen.smalley.work, eparis, casey
  Cc: reiserfs-devel, linux-kernel, linux-integrity,
	linux-security-module, selinux, bpf, kpsingh, keescook,
	nicolas.bouchinet, Roberto Sassu

On Tue, 2023-04-11 at 03:22 -0400, Mimi Zohar wrote:
> On Fri, 2023-03-31 at 14:32 +0200, Roberto Sassu wrote:
> > From: Roberto Sassu <roberto.sassu@huawei.com>
> > 
> > Change the evm_inode_init_security() definition to align with the LSM
> > infrastructure. Keep the existing behavior of including in the HMAC
> > calculation only the first xattr provided by LSMs.
> > 
> > Changing the evm_inode_init_security() definition requires passing the
> > xattr array allocated by security_inode_init_security(), and the number of
> > xattrs filled by previously invoked LSMs.
> > 
> > Use the newly introduced lsm_get_xattr_slot() to position EVM correctly in
> > the xattrs array, like a regular LSM, and to increment the number of filled
> > slots. For now, the LSM infrastructure allocates enough xattrs slots to
> > store the EVM xattr, without using the reservation mechanism.
> > 
> > Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
> > ---
> >  include/linux/evm.h               | 13 +++++++------
> >  security/integrity/evm/evm_main.c | 16 ++++++++++------
> >  security/security.c               |  6 +++---
> >  3 files changed, 20 insertions(+), 15 deletions(-)
> > 
> > diff --git a/include/linux/evm.h b/include/linux/evm.h
> > index 7dc1ee74169..597632c71c7 100644
> > --- a/include/linux/evm.h
> > +++ b/include/linux/evm.h
> > @@ -56,9 +56,9 @@ static inline void evm_inode_post_set_acl(struct dentry *dentry,
> >  {
> >  	return evm_inode_post_setxattr(dentry, acl_name, NULL, 0);
> >  }
> > -extern int evm_inode_init_security(struct inode *inode,
> > -				   const struct xattr *xattr_array,
> > -				   struct xattr *evm);
> > +extern int evm_inode_init_security(struct inode *inode, struct inode *dir,
> > +				   const struct qstr *qstr,
> > +				   struct xattr *xattrs, int *xattr_count);
> >  extern bool evm_revalidate_status(const char *xattr_name);
> >  extern int evm_protected_xattr_if_enabled(const char *req_xattr_name);
> >  extern int evm_read_protected_xattrs(struct dentry *dentry, u8 *buffer,
> > @@ -157,9 +157,10 @@ static inline void evm_inode_post_set_acl(struct dentry *dentry,
> >  	return;
> >  }
> >  
> > -static inline int evm_inode_init_security(struct inode *inode,
> > -					  const struct xattr *xattr_array,
> > -					  struct xattr *evm)
> > +static inline int evm_inode_init_security(struct inode *inode, struct inode *dir,
> > +					  const struct qstr *qstr,
> > +					  struct xattr *xattrs,
> > +					  int *xattr_count)
> >  {
> >  	return 0;
> >  }
> > diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c
> > index cf24c525558..475196ce712 100644
> > --- a/security/integrity/evm/evm_main.c
> > +++ b/security/integrity/evm/evm_main.c
> > @@ -21,6 +21,7 @@
> >  #include <linux/evm.h>
> >  #include <linux/magic.h>
> >  #include <linux/posix_acl_xattr.h>
> > +#include <linux/lsm_hooks.h>
> >  
> >  #include <crypto/hash.h>
> >  #include <crypto/hash_info.h>
> > @@ -864,23 +865,26 @@ void evm_inode_post_setattr(struct dentry *dentry, int ia_valid)
> >  /*
> >   * evm_inode_init_security - initializes security.evm HMAC value
> >   */
> > -int evm_inode_init_security(struct inode *inode,
> > -				 const struct xattr *lsm_xattr,
> > -				 struct xattr *evm_xattr)
> > +int evm_inode_init_security(struct inode *inode, struct inode *dir,
> > +			    const struct qstr *qstr, struct xattr *xattrs,
> > +			    int *xattr_count)
> >  {
> >  	struct evm_xattr *xattr_data;
> > +	struct xattr *evm_xattr;
> >  	int rc;
> >  
> > -	if (!(evm_initialized & EVM_INIT_HMAC) ||
> > -	    !evm_protected_xattr(lsm_xattr->name))
> > +	if (!(evm_initialized & EVM_INIT_HMAC) || !xattrs ||
> > +	    !evm_protected_xattr(xattrs->name))
> >  		return 0;
> >  
> > +	evm_xattr = lsm_get_xattr_slot(xattrs, xattr_count);
> > +
> >  	xattr_data = kzalloc(sizeof(*xattr_data), GFP_NOFS);
> >  	if (!xattr_data)
> >  		return -ENOMEM;
> >  
> >  	xattr_data->data.type = EVM_XATTR_HMAC;
> > -	rc = evm_init_hmac(inode, lsm_xattr, xattr_data->digest);
> > +	rc = evm_init_hmac(inode, xattrs, xattr_data->digest);
> >  	if (rc < 0)
> >  		goto out;
> >  
> > diff --git a/security/security.c b/security/security.c
> > index 1aeaa8ce449..ef7779ec8b2 100644
> > --- a/security/security.c
> > +++ b/security/security.c
> > @@ -1645,9 +1645,9 @@ int security_inode_init_security(struct inode *inode, struct inode *dir,
> >  	if (!xattr_count)
> >  		goto out;
> >  
> > -	ret = evm_inode_init_security(inode, new_xattrs,
> > -				      new_xattrs + xattr_count);
> > -	if (ret)
> > +	ret = evm_inode_init_security(inode, dir, qstr, new_xattrs,
> > +				      &xattr_count);
> > +	if (ret && ret != -EOPNOTSUPP)
> 
> As previously discussed, -EOPNOTSUPP originally meant that the
> filesystem itself did not support writing xattrs.  So there was no
> point in trying to write the EVM security xattr.   With the change in
> -EOPNOTSUPP meaning, it will now try to write the EVM security xattr. 
> Instead of glossing over the change in behavior, it needs to at least
> be mentioned in the patch description.

Oh, my mistake. I forgot to update this part (evm_inode_init_security()
now returns zero instead of -EOPNOTSUPP).

Thanks

Roberto

> >  		goto out;
> >  	ret = initxattrs(inode, new_xattrs, fs_data);
> >  out:


^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v10 2/4] security: Allow all LSMs to provide xattrs for inode_init_security hook
  2023-04-11  7:53     ` Roberto Sassu
@ 2023-04-11 16:42       ` Casey Schaufler
  2023-04-11 17:23         ` [PATCH] Smack modifications for: " Roberto Sassu
  2023-04-11 17:25         ` [PATCH v10 2/4] " Roberto Sassu
  0 siblings, 2 replies; 44+ messages in thread
From: Casey Schaufler @ 2023-04-11 16:42 UTC (permalink / raw)
  To: Roberto Sassu, Mimi Zohar, dmitry.kasatkin, paul, jmorris, serge,
	stephen.smalley.work, eparis
  Cc: reiserfs-devel, linux-kernel, linux-integrity,
	linux-security-module, selinux, bpf, kpsingh, keescook,
	nicolas.bouchinet, Roberto Sassu, Casey Schaufler

On 4/11/2023 12:53 AM, Roberto Sassu wrote:
> On Tue, 2023-04-11 at 03:22 -0400, Mimi Zohar wrote:
>> Hi Roberto,
>>
>> Sorry for the delay in responding...
> Hi Mimi
>
> no worries!
>
>> The patch description reads as though support for per LSM multiple
>> xattrs is being added in this patch, though lsm_get_xattr_slot() only
>> ever is incremented once for each LSM.  To simplify review, it would be
>> nice to mention that lsm_get_xattr_slot() would be called multiple
>> times per LSM xattr.
> Ok, I will mention it.
>
>> On Fri, 2023-03-31 at 14:32 +0200, Roberto Sassu wrote:
>>> From: Roberto Sassu <roberto.sassu@huawei.com>
>>>
>>> Currently, security_inode_init_security() supports only one LSM providing
>>> an xattr and EVM calculating the HMAC on that xattr, plus other inode
>>> metadata.
>>>
>>> Allow all LSMs to provide one or multiple xattrs, by extending the security
>>> blob reservation mechanism. Introduce the new lbs_xattr_count field of the
>>> lsm_blob_sizes structure, so that each LSM can specify how many xattrs it
>>> needs, and the LSM infrastructure knows how many xattr slots it should
>>> allocate.
>>>
>>> Dynamically allocate the new_xattrs array to be populated by LSMs with the
>>> inode_init_security hook, and pass it to the latter instead of the
>>> name/value/len triple. Unify the !initxattrs and initxattrs case, simply
>>> don't allocate the new_xattrs array in the former.
>>>
>>> Also, pass to the hook the number of xattrs filled by each LSM, so that
>>> there are no gaps when the next LSM fills the array. Gaps might occur
>>> because an LSM can legitimately request xattrs to the LSM infrastructure,
>>> but not fill the reserved slots, if it was not initialized.
>> The number of security xattrs permitted per LSM was discussed in the
>> second paragraph.  The first line of this paragraph needs to be updated
>> to reflect the current number of security xattrs used, though that is
>> more related to the new lsm_get_xattr_slot().  Or perhaps the entire
>> paragraph is unnecessary, a remnant from
>> security_check_compact_filled_xattrs(), and should be removed.  
> I would probably say in that paragraph that the number specified for
> the lbs_xattr_count field determines how many times an LSM can call
> lsm_get_xattr_slot().
>
>>> Update the documentation of security_inode_init_security() to reflect the
>>> changes, and fix the description of the xattr name, as it is not allocated
>>> anymore.
>>>
>>> Finally, adapt both SELinux and Smack to use the new definition of the
>>> inode_init_security hook, and to fill the reserved slots in the xattr
>>> array. Introduce the lsm_get_xattr_slot() helper to retrieve an available
>>> slot to fill, and to increment the number of filled slots.
>>>
>>> Move the xattr->name assignment after the xattr->value one, so that it is
>>> done only in case of successful memory allocation. For Smack, also reserve
>>> space for the other defined xattrs although they are not set yet in
>>> smack_inode_init_security().
>> This Smack comment should be moved to the previous paragraph and even
>> expanded explaining that lsm_get_xattr_slot() will be called for each
>> additional security xattr.
> >From previous Paul's and Casey's comments, Smack will have just two
> xattrs, assuming that security.SMACK_TRASMUTE64 can be set in
> smack_inode_init_security(). I will change this part accordingly once
> Casey can have a look at the function.

To be clear, Smack may use two xattrs from smack_inode_init_security(),
SMACK64 and SMACK64_TRANSMUTE. SMACK64_TRANSMUTE is only set on directories.
SMACK64_MMAP and SMACK64_EXEC can be set on files, but they have to be
set explicitly. A file may have three xattrs, but only one from
smack_inode_init_security().

I'm looking at the existing Smack function, and it includes checking for
the transmute attribute. Your patch seems to have dropped this important
behavior. That needs to be restored in any case. You can tell that you need
to include the SMACK64_TRANSMUTE xattr if setting it is detected.

>
>>> Reported-by: Nicolas Bouchinet <nicolas.bouchinet@clip-os.org> (EVM crash)
>>> Link: https://lore.kernel.org/linux-integrity/Y1FTSIo+1x+4X0LS@archlinux/
>>> Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
>>> ---
>>> diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
>>> index c2be66c669a..9eb9b686493 100644
>>> --- a/include/linux/lsm_hooks.h
>>> +++ b/include/linux/lsm_hooks.h
>>> @@ -28,6 +28,7 @@
>>>  #include <linux/security.h>
>>>  #include <linux/init.h>
>>>  #include <linux/rculist.h>
>>> +#include <linux/xattr.h>
>>>  
>>>  union security_list_options {
>>>  	#define LSM_HOOK(RET, DEFAULT, NAME, ...) RET (*NAME)(__VA_ARGS__);
>>> @@ -63,8 +64,27 @@ struct lsm_blob_sizes {
>>>  	int	lbs_ipc;
>>>  	int	lbs_msg_msg;
>>>  	int	lbs_task;
>>> +	int	lbs_xattr_count; /* number of xattr slots in new_xattrs array */
>>>  };
>>>  
>>> +/**
>>> + * lsm_get_xattr_slot - Return the next available slot and increment the index
>>> + * @xattrs: array storing LSM-provided xattrs
>>> + * @xattr_count: number of already stored xattrs (updated)
>>> + *
>>> + * Retrieve the first available slot in the @xattrs array to fill with an xattr,
>>> + * and increment @xattr_count.
>>> + *
>>> + * Return: The slot to fill in @xattrs if non-NULL, NULL otherwise.
>>> + */
>>> +static inline struct xattr *lsm_get_xattr_slot(struct xattr *xattrs,
>>> +					       int *xattr_count)
>>> +{
>>> +	if (unlikely(!xattrs))
>>> +		return NULL;
>>> +	return xattrs + (*xattr_count)++;
>> At some point, since lsm_get_xattr_slot() could be called multiple
>> times from the same LSM, shouldn't there be some sort of bounds
>> checking?
> >From previous Paul's comments, I understood that he prefers to avoid
> extra checks. It will be up to LSM developers to ensure that the API is
> used correctly.
>
> Thanks
>
> Roberto
>

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [PATCH] Smack modifications for: security: Allow all LSMs to provide xattrs for inode_init_security hook
  2023-04-11 16:42       ` Casey Schaufler
@ 2023-04-11 17:23         ` Roberto Sassu
  2023-04-11 17:54           ` Casey Schaufler
  2023-04-11 17:25         ` [PATCH v10 2/4] " Roberto Sassu
  1 sibling, 1 reply; 44+ messages in thread
From: Roberto Sassu @ 2023-04-11 17:23 UTC (permalink / raw)
  To: zohar, dmitry.kasatkin, paul, jmorris, serge,
	stephen.smalley.work, eparis, casey
  Cc: reiserfs-devel, linux-kernel, linux-integrity,
	linux-security-module, selinux, bpf, kpsingh, keescook,
	nicolas.bouchinet, Roberto Sassu

From: Roberto Sassu <roberto.sassu@huawei.com>

Very very quick modification. Not tested.

Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
---
 security/smack/smack.h     |  2 +-
 security/smack/smack_lsm.c | 42 ++++++++++++++++++++------------------
 2 files changed, 23 insertions(+), 21 deletions(-)

diff --git a/security/smack/smack.h b/security/smack/smack.h
index e2239be7bd6..f00c8498c60 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -127,7 +127,7 @@ struct task_smack {
 
 #define	SMK_INODE_INSTANT	0x01	/* inode is instantiated */
 #define	SMK_INODE_TRANSMUTE	0x02	/* directory is transmuting */
-#define	SMK_INODE_CHANGED	0x04	/* smack was transmuted */
+#define	SMK_INODE_CHANGED	0x04	/* smack was transmuted (unused) */
 #define	SMK_INODE_IMPURE	0x08	/* involved in an impure transaction */
 
 /*
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 8392983334b..b43820bdbd0 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -54,12 +54,12 @@
 
 /*
  * Smack uses multiple xattrs.
- * SMACK64 - for access control, SMACK64EXEC - label for the program,
- * SMACK64MMAP - controls library loading,
+ * SMACK64 - for access control,
  * SMACK64TRANSMUTE - label initialization,
- * Not saved on files - SMACK64IPIN and SMACK64IPOUT
+ * Not saved on files - SMACK64IPIN and SMACK64IPOUT,
+ * Must be set explicitly - SMACK64EXEC and SMACK64MMAP
  */
-#define SMACK_INODE_INIT_XATTRS 4
+#define SMACK_INODE_INIT_XATTRS 2
 
 #ifdef SMACK_IPV6_PORT_LABELING
 static DEFINE_MUTEX(smack_ipv6_lock);
@@ -957,11 +957,11 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
 				     const struct qstr *qstr,
 				     struct xattr *xattrs, int *xattr_count)
 {
-	struct inode_smack *issp = smack_inode(inode);
 	struct smack_known *skp = smk_of_current();
 	struct smack_known *isp = smk_of_inode(inode);
 	struct smack_known *dsp = smk_of_inode(dir);
 	struct xattr *xattr = lsm_get_xattr_slot(xattrs, xattr_count);
+	struct xattr *xattr2;
 	int may;
 
 	if (xattr) {
@@ -979,7 +979,17 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
 		if (may > 0 && ((may & MAY_TRANSMUTE) != 0) &&
 		    smk_inode_transmutable(dir)) {
 			isp = dsp;
-			issp->smk_flags |= SMK_INODE_CHANGED;
+			xattr2 = lsm_get_xattr_slot(xattrs, xattr_count);
+			if (xattr2) {
+				xattr2->value = kmemdup(TRANS_TRUE,
+							TRANS_TRUE_SIZE,
+							GFP_NOFS);
+				if (xattr2->value == NULL)
+					return -ENOMEM;
+
+				xattr2->value_len = TRANS_TRUE_SIZE;
+				xattr2->name = XATTR_NAME_SMACKTRANSMUTE;
+			}
 		}
 
 		xattr->value = kstrdup(isp->smk_known, GFP_NOFS);
@@ -3512,20 +3522,12 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
 			 * If there is a transmute attribute on the
 			 * directory mark the inode.
 			 */
-			if (isp->smk_flags & SMK_INODE_CHANGED) {
-				isp->smk_flags &= ~SMK_INODE_CHANGED;
-				rc = __vfs_setxattr(&nop_mnt_idmap, dp, inode,
-					XATTR_NAME_SMACKTRANSMUTE,
-					TRANS_TRUE, TRANS_TRUE_SIZE,
-					0);
-			} else {
-				rc = __vfs_getxattr(dp, inode,
-					XATTR_NAME_SMACKTRANSMUTE, trattr,
-					TRANS_TRUE_SIZE);
-				if (rc >= 0 && strncmp(trattr, TRANS_TRUE,
-						       TRANS_TRUE_SIZE) != 0)
-					rc = -EINVAL;
-			}
+			rc = __vfs_getxattr(dp, inode,
+					    XATTR_NAME_SMACKTRANSMUTE, trattr,
+					    TRANS_TRUE_SIZE);
+			if (rc >= 0 && strncmp(trattr, TRANS_TRUE,
+					       TRANS_TRUE_SIZE) != 0)
+				rc = -EINVAL;
 			if (rc >= 0)
 				transflag = SMK_INODE_TRANSMUTE;
 		}
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 44+ messages in thread

* Re: [PATCH v10 2/4] security: Allow all LSMs to provide xattrs for inode_init_security hook
  2023-04-11 16:42       ` Casey Schaufler
  2023-04-11 17:23         ` [PATCH] Smack modifications for: " Roberto Sassu
@ 2023-04-11 17:25         ` Roberto Sassu
  2023-04-11 17:40           ` Casey Schaufler
  1 sibling, 1 reply; 44+ messages in thread
From: Roberto Sassu @ 2023-04-11 17:25 UTC (permalink / raw)
  To: Casey Schaufler, Mimi Zohar, dmitry.kasatkin, paul, jmorris,
	serge, stephen.smalley.work, eparis
  Cc: reiserfs-devel, linux-kernel, linux-integrity,
	linux-security-module, selinux, bpf, kpsingh, keescook,
	nicolas.bouchinet, Roberto Sassu

On Tue, 2023-04-11 at 09:42 -0700, Casey Schaufler wrote:
> On 4/11/2023 12:53 AM, Roberto Sassu wrote:
> > On Tue, 2023-04-11 at 03:22 -0400, Mimi Zohar wrote:
> > > Hi Roberto,
> > > 
> > > Sorry for the delay in responding...
> > Hi Mimi
> > 
> > no worries!
> > 
> > > The patch description reads as though support for per LSM multiple
> > > xattrs is being added in this patch, though lsm_get_xattr_slot() only
> > > ever is incremented once for each LSM.  To simplify review, it would be
> > > nice to mention that lsm_get_xattr_slot() would be called multiple
> > > times per LSM xattr.
> > Ok, I will mention it.
> > 
> > > On Fri, 2023-03-31 at 14:32 +0200, Roberto Sassu wrote:
> > > > From: Roberto Sassu <roberto.sassu@huawei.com>
> > > > 
> > > > Currently, security_inode_init_security() supports only one LSM providing
> > > > an xattr and EVM calculating the HMAC on that xattr, plus other inode
> > > > metadata.
> > > > 
> > > > Allow all LSMs to provide one or multiple xattrs, by extending the security
> > > > blob reservation mechanism. Introduce the new lbs_xattr_count field of the
> > > > lsm_blob_sizes structure, so that each LSM can specify how many xattrs it
> > > > needs, and the LSM infrastructure knows how many xattr slots it should
> > > > allocate.
> > > > 
> > > > Dynamically allocate the new_xattrs array to be populated by LSMs with the
> > > > inode_init_security hook, and pass it to the latter instead of the
> > > > name/value/len triple. Unify the !initxattrs and initxattrs case, simply
> > > > don't allocate the new_xattrs array in the former.
> > > > 
> > > > Also, pass to the hook the number of xattrs filled by each LSM, so that
> > > > there are no gaps when the next LSM fills the array. Gaps might occur
> > > > because an LSM can legitimately request xattrs to the LSM infrastructure,
> > > > but not fill the reserved slots, if it was not initialized.
> > > The number of security xattrs permitted per LSM was discussed in the
> > > second paragraph.  The first line of this paragraph needs to be updated
> > > to reflect the current number of security xattrs used, though that is
> > > more related to the new lsm_get_xattr_slot().  Or perhaps the entire
> > > paragraph is unnecessary, a remnant from
> > > security_check_compact_filled_xattrs(), and should be removed.  
> > I would probably say in that paragraph that the number specified for
> > the lbs_xattr_count field determines how many times an LSM can call
> > lsm_get_xattr_slot().
> > 
> > > > Update the documentation of security_inode_init_security() to reflect the
> > > > changes, and fix the description of the xattr name, as it is not allocated
> > > > anymore.
> > > > 
> > > > Finally, adapt both SELinux and Smack to use the new definition of the
> > > > inode_init_security hook, and to fill the reserved slots in the xattr
> > > > array. Introduce the lsm_get_xattr_slot() helper to retrieve an available
> > > > slot to fill, and to increment the number of filled slots.
> > > > 
> > > > Move the xattr->name assignment after the xattr->value one, so that it is
> > > > done only in case of successful memory allocation. For Smack, also reserve
> > > > space for the other defined xattrs although they are not set yet in
> > > > smack_inode_init_security().
> > > This Smack comment should be moved to the previous paragraph and even
> > > expanded explaining that lsm_get_xattr_slot() will be called for each
> > > additional security xattr.
> > > From previous Paul's and Casey's comments, Smack will have just two
> > xattrs, assuming that security.SMACK_TRASMUTE64 can be set in
> > smack_inode_init_security(). I will change this part accordingly once
> > Casey can have a look at the function.
> 
> To be clear, Smack may use two xattrs from smack_inode_init_security(),
> SMACK64 and SMACK64_TRANSMUTE. SMACK64_TRANSMUTE is only set on directories.
> SMACK64_MMAP and SMACK64_EXEC can be set on files, but they have to be
> set explicitly. A file may have three xattrs, but only one from
> smack_inode_init_security().
> 
> I'm looking at the existing Smack function, and it includes checking for
> the transmute attribute. Your patch seems to have dropped this important
> behavior. That needs to be restored in any case. You can tell that you need
> to include the SMACK64_TRANSMUTE xattr if setting it is detected.

Uhm, I think it is simply omitted in the patch, not deleted.

I just sent a draft of the modifications required to set
SMACK64_TRANSMUTE in smack_inode_init_security().

Roberto

> > > > Reported-by: Nicolas Bouchinet <nicolas.bouchinet@clip-os.org> (EVM crash)
> > > > Link: https://lore.kernel.org/linux-integrity/Y1FTSIo+1x+4X0LS@archlinux/
> > > > Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
> > > > ---
> > > > diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
> > > > index c2be66c669a..9eb9b686493 100644
> > > > --- a/include/linux/lsm_hooks.h
> > > > +++ b/include/linux/lsm_hooks.h
> > > > @@ -28,6 +28,7 @@
> > > >  #include <linux/security.h>
> > > >  #include <linux/init.h>
> > > >  #include <linux/rculist.h>
> > > > +#include <linux/xattr.h>
> > > >  
> > > >  union security_list_options {
> > > >  	#define LSM_HOOK(RET, DEFAULT, NAME, ...) RET (*NAME)(__VA_ARGS__);
> > > > @@ -63,8 +64,27 @@ struct lsm_blob_sizes {
> > > >  	int	lbs_ipc;
> > > >  	int	lbs_msg_msg;
> > > >  	int	lbs_task;
> > > > +	int	lbs_xattr_count; /* number of xattr slots in new_xattrs array */
> > > >  };
> > > >  
> > > > +/**
> > > > + * lsm_get_xattr_slot - Return the next available slot and increment the index
> > > > + * @xattrs: array storing LSM-provided xattrs
> > > > + * @xattr_count: number of already stored xattrs (updated)
> > > > + *
> > > > + * Retrieve the first available slot in the @xattrs array to fill with an xattr,
> > > > + * and increment @xattr_count.
> > > > + *
> > > > + * Return: The slot to fill in @xattrs if non-NULL, NULL otherwise.
> > > > + */
> > > > +static inline struct xattr *lsm_get_xattr_slot(struct xattr *xattrs,
> > > > +					       int *xattr_count)
> > > > +{
> > > > +	if (unlikely(!xattrs))
> > > > +		return NULL;
> > > > +	return xattrs + (*xattr_count)++;
> > > At some point, since lsm_get_xattr_slot() could be called multiple
> > > times from the same LSM, shouldn't there be some sort of bounds
> > > checking?
> > > From previous Paul's comments, I understood that he prefers to avoid
> > extra checks. It will be up to LSM developers to ensure that the API is
> > used correctly.
> > 
> > Thanks
> > 
> > Roberto
> > 


^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH v10 2/4] security: Allow all LSMs to provide xattrs for inode_init_security hook
  2023-04-11 17:25         ` [PATCH v10 2/4] " Roberto Sassu
@ 2023-04-11 17:40           ` Casey Schaufler
  0 siblings, 0 replies; 44+ messages in thread
From: Casey Schaufler @ 2023-04-11 17:40 UTC (permalink / raw)
  To: Roberto Sassu, Mimi Zohar, dmitry.kasatkin, paul, jmorris, serge,
	stephen.smalley.work, eparis
  Cc: reiserfs-devel, linux-kernel, linux-integrity,
	linux-security-module, selinux, bpf, kpsingh, keescook,
	nicolas.bouchinet, Roberto Sassu, Casey Schaufler

On 4/11/2023 10:25 AM, Roberto Sassu wrote:
> On Tue, 2023-04-11 at 09:42 -0700, Casey Schaufler wrote:
>> On 4/11/2023 12:53 AM, Roberto Sassu wrote:
>>> On Tue, 2023-04-11 at 03:22 -0400, Mimi Zohar wrote:
>>>> Hi Roberto,
>>>>
>>>> Sorry for the delay in responding...
>>> Hi Mimi
>>>
>>> no worries!
>>>
>>>> The patch description reads as though support for per LSM multiple
>>>> xattrs is being added in this patch, though lsm_get_xattr_slot() only
>>>> ever is incremented once for each LSM.  To simplify review, it would be
>>>> nice to mention that lsm_get_xattr_slot() would be called multiple
>>>> times per LSM xattr.
>>> Ok, I will mention it.
>>>
>>>> On Fri, 2023-03-31 at 14:32 +0200, Roberto Sassu wrote:
>>>>> From: Roberto Sassu <roberto.sassu@huawei.com>
>>>>>
>>>>> Currently, security_inode_init_security() supports only one LSM providing
>>>>> an xattr and EVM calculating the HMAC on that xattr, plus other inode
>>>>> metadata.
>>>>>
>>>>> Allow all LSMs to provide one or multiple xattrs, by extending the security
>>>>> blob reservation mechanism. Introduce the new lbs_xattr_count field of the
>>>>> lsm_blob_sizes structure, so that each LSM can specify how many xattrs it
>>>>> needs, and the LSM infrastructure knows how many xattr slots it should
>>>>> allocate.
>>>>>
>>>>> Dynamically allocate the new_xattrs array to be populated by LSMs with the
>>>>> inode_init_security hook, and pass it to the latter instead of the
>>>>> name/value/len triple. Unify the !initxattrs and initxattrs case, simply
>>>>> don't allocate the new_xattrs array in the former.
>>>>>
>>>>> Also, pass to the hook the number of xattrs filled by each LSM, so that
>>>>> there are no gaps when the next LSM fills the array. Gaps might occur
>>>>> because an LSM can legitimately request xattrs to the LSM infrastructure,
>>>>> but not fill the reserved slots, if it was not initialized.
>>>> The number of security xattrs permitted per LSM was discussed in the
>>>> second paragraph.  The first line of this paragraph needs to be updated
>>>> to reflect the current number of security xattrs used, though that is
>>>> more related to the new lsm_get_xattr_slot().  Or perhaps the entire
>>>> paragraph is unnecessary, a remnant from
>>>> security_check_compact_filled_xattrs(), and should be removed.  
>>> I would probably say in that paragraph that the number specified for
>>> the lbs_xattr_count field determines how many times an LSM can call
>>> lsm_get_xattr_slot().
>>>
>>>>> Update the documentation of security_inode_init_security() to reflect the
>>>>> changes, and fix the description of the xattr name, as it is not allocated
>>>>> anymore.
>>>>>
>>>>> Finally, adapt both SELinux and Smack to use the new definition of the
>>>>> inode_init_security hook, and to fill the reserved slots in the xattr
>>>>> array. Introduce the lsm_get_xattr_slot() helper to retrieve an available
>>>>> slot to fill, and to increment the number of filled slots.
>>>>>
>>>>> Move the xattr->name assignment after the xattr->value one, so that it is
>>>>> done only in case of successful memory allocation. For Smack, also reserve
>>>>> space for the other defined xattrs although they are not set yet in
>>>>> smack_inode_init_security().
>>>> This Smack comment should be moved to the previous paragraph and even
>>>> expanded explaining that lsm_get_xattr_slot() will be called for each
>>>> additional security xattr.
>>>> From previous Paul's and Casey's comments, Smack will have just two
>>> xattrs, assuming that security.SMACK_TRASMUTE64 can be set in
>>> smack_inode_init_security(). I will change this part accordingly once
>>> Casey can have a look at the function.
>> To be clear, Smack may use two xattrs from smack_inode_init_security(),
>> SMACK64 and SMACK64_TRANSMUTE. SMACK64_TRANSMUTE is only set on directories.
>> SMACK64_MMAP and SMACK64_EXEC can be set on files, but they have to be
>> set explicitly. A file may have three xattrs, but only one from
>> smack_inode_init_security().
>>
>> I'm looking at the existing Smack function, and it includes checking for
>> the transmute attribute. Your patch seems to have dropped this important
>> behavior. That needs to be restored in any case. You can tell that you need
>> to include the SMACK64_TRANSMUTE xattr if setting it is detected.
> Uhm, I think it is simply omitted in the patch, not deleted.

Oops. Right you are.

>
> I just sent a draft of the modifications required to set
> SMACK64_TRANSMUTE in smack_inode_init_security().

Yup. I'll comment on that.

>
> Roberto
>
>>>>> Reported-by: Nicolas Bouchinet <nicolas.bouchinet@clip-os.org> (EVM crash)
>>>>> Link: https://lore.kernel.org/linux-integrity/Y1FTSIo+1x+4X0LS@archlinux/
>>>>> Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
>>>>> ---
>>>>> diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
>>>>> index c2be66c669a..9eb9b686493 100644
>>>>> --- a/include/linux/lsm_hooks.h
>>>>> +++ b/include/linux/lsm_hooks.h
>>>>> @@ -28,6 +28,7 @@
>>>>>  #include <linux/security.h>
>>>>>  #include <linux/init.h>
>>>>>  #include <linux/rculist.h>
>>>>> +#include <linux/xattr.h>
>>>>>  
>>>>>  union security_list_options {
>>>>>  	#define LSM_HOOK(RET, DEFAULT, NAME, ...) RET (*NAME)(__VA_ARGS__);
>>>>> @@ -63,8 +64,27 @@ struct lsm_blob_sizes {
>>>>>  	int	lbs_ipc;
>>>>>  	int	lbs_msg_msg;
>>>>>  	int	lbs_task;
>>>>> +	int	lbs_xattr_count; /* number of xattr slots in new_xattrs array */
>>>>>  };
>>>>>  
>>>>> +/**
>>>>> + * lsm_get_xattr_slot - Return the next available slot and increment the index
>>>>> + * @xattrs: array storing LSM-provided xattrs
>>>>> + * @xattr_count: number of already stored xattrs (updated)
>>>>> + *
>>>>> + * Retrieve the first available slot in the @xattrs array to fill with an xattr,
>>>>> + * and increment @xattr_count.
>>>>> + *
>>>>> + * Return: The slot to fill in @xattrs if non-NULL, NULL otherwise.
>>>>> + */
>>>>> +static inline struct xattr *lsm_get_xattr_slot(struct xattr *xattrs,
>>>>> +					       int *xattr_count)
>>>>> +{
>>>>> +	if (unlikely(!xattrs))
>>>>> +		return NULL;
>>>>> +	return xattrs + (*xattr_count)++;
>>>> At some point, since lsm_get_xattr_slot() could be called multiple
>>>> times from the same LSM, shouldn't there be some sort of bounds
>>>> checking?
>>>> From previous Paul's comments, I understood that he prefers to avoid
>>> extra checks. It will be up to LSM developers to ensure that the API is
>>> used correctly.
>>>
>>> Thanks
>>>
>>> Roberto
>>>

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH] Smack modifications for: security: Allow all LSMs to provide xattrs for inode_init_security hook
  2023-04-11 17:23         ` [PATCH] Smack modifications for: " Roberto Sassu
@ 2023-04-11 17:54           ` Casey Schaufler
  2023-04-12  7:22             ` Roberto Sassu
  0 siblings, 1 reply; 44+ messages in thread
From: Casey Schaufler @ 2023-04-11 17:54 UTC (permalink / raw)
  To: Roberto Sassu, zohar, dmitry.kasatkin, paul, jmorris, serge,
	stephen.smalley.work, eparis
  Cc: reiserfs-devel, linux-kernel, linux-integrity,
	linux-security-module, selinux, bpf, kpsingh, keescook,
	nicolas.bouchinet, Roberto Sassu, Casey Schaufler

On 4/11/2023 10:23 AM, Roberto Sassu wrote:
> From: Roberto Sassu <roberto.sassu@huawei.com>
>
> Very very quick modification. Not tested.
>
> Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
> ---
>  security/smack/smack.h     |  2 +-
>  security/smack/smack_lsm.c | 42 ++++++++++++++++++++------------------
>  2 files changed, 23 insertions(+), 21 deletions(-)
>
> diff --git a/security/smack/smack.h b/security/smack/smack.h
> index e2239be7bd6..f00c8498c60 100644
> --- a/security/smack/smack.h
> +++ b/security/smack/smack.h
> @@ -127,7 +127,7 @@ struct task_smack {
>  
>  #define	SMK_INODE_INSTANT	0x01	/* inode is instantiated */
>  #define	SMK_INODE_TRANSMUTE	0x02	/* directory is transmuting */
> -#define	SMK_INODE_CHANGED	0x04	/* smack was transmuted */
> +#define	SMK_INODE_CHANGED	0x04	/* smack was transmuted (unused) */

See below ...

>  #define	SMK_INODE_IMPURE	0x08	/* involved in an impure transaction */
>  
>  /*
> diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
> index 8392983334b..b43820bdbd0 100644
> --- a/security/smack/smack_lsm.c
> +++ b/security/smack/smack_lsm.c
> @@ -54,12 +54,12 @@
>  
>  /*
>   * Smack uses multiple xattrs.
> - * SMACK64 - for access control, SMACK64EXEC - label for the program,
> - * SMACK64MMAP - controls library loading,
> + * SMACK64 - for access control,
>   * SMACK64TRANSMUTE - label initialization,
> - * Not saved on files - SMACK64IPIN and SMACK64IPOUT
> + * Not saved on files - SMACK64IPIN and SMACK64IPOUT,
> + * Must be set explicitly - SMACK64EXEC and SMACK64MMAP
>   */
> -#define SMACK_INODE_INIT_XATTRS 4
> +#define SMACK_INODE_INIT_XATTRS 2
>  
>  #ifdef SMACK_IPV6_PORT_LABELING
>  static DEFINE_MUTEX(smack_ipv6_lock);
> @@ -957,11 +957,11 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
>  				     const struct qstr *qstr,
>  				     struct xattr *xattrs, int *xattr_count)
>  {
> -	struct inode_smack *issp = smack_inode(inode);
>  	struct smack_known *skp = smk_of_current();
>  	struct smack_known *isp = smk_of_inode(inode);
>  	struct smack_known *dsp = smk_of_inode(dir);
>  	struct xattr *xattr = lsm_get_xattr_slot(xattrs, xattr_count);
> +	struct xattr *xattr2;

I'm going to channel Paul and suggest this be xattr_transmute instead of xattr2.
It also looks like it could move to be declared in the if clause.

>  	int may;
>  
>  	if (xattr) {
> @@ -979,7 +979,17 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
>  		if (may > 0 && ((may & MAY_TRANSMUTE) != 0) &&
>  		    smk_inode_transmutable(dir)) {
>  			isp = dsp;
> -			issp->smk_flags |= SMK_INODE_CHANGED;

I think you need to keep this. More below.

> +			xattr2 = lsm_get_xattr_slot(xattrs, xattr_count);
> +			if (xattr2) {
> +				xattr2->value = kmemdup(TRANS_TRUE,
> +							TRANS_TRUE_SIZE,
> +							GFP_NOFS);
> +				if (xattr2->value == NULL)
> +					return -ENOMEM;
> +
> +				xattr2->value_len = TRANS_TRUE_SIZE;
> +				xattr2->name = XATTR_NAME_SMACKTRANSMUTE;
> +			}
>  		}
>  
>  		xattr->value = kstrdup(isp->smk_known, GFP_NOFS);
> @@ -3512,20 +3522,12 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
>  			 * If there is a transmute attribute on the
>  			 * directory mark the inode.
>  			 */
> -			if (isp->smk_flags & SMK_INODE_CHANGED) {
> -				isp->smk_flags &= ~SMK_INODE_CHANGED;
> -				rc = __vfs_setxattr(&nop_mnt_idmap, dp, inode,
> -					XATTR_NAME_SMACKTRANSMUTE,
> -					TRANS_TRUE, TRANS_TRUE_SIZE,
> -					0);
> -			} else {
> -				rc = __vfs_getxattr(dp, inode,
> -					XATTR_NAME_SMACKTRANSMUTE, trattr,
> -					TRANS_TRUE_SIZE);
> -				if (rc >= 0 && strncmp(trattr, TRANS_TRUE,
> -						       TRANS_TRUE_SIZE) != 0)
> -					rc = -EINVAL;
> -			}
> +			rc = __vfs_getxattr(dp, inode,
> +					    XATTR_NAME_SMACKTRANSMUTE, trattr,
> +					    TRANS_TRUE_SIZE);
> +			if (rc >= 0 && strncmp(trattr, TRANS_TRUE,
> +					       TRANS_TRUE_SIZE) != 0)
> +				rc = -EINVAL;

Where is the SMACK64_TRANSMUTE attribute going to get set on the file?
It's not going to get set in smack_init_inode_security(). The inode will
know it's transmuting, but it won't get to disk without the __vfs_setxattr()
here in smack_d_instantiate(). Now, it's been a long time since that code
was written, so I could be wrong, but I'm pretty sure about that.

I think that you should be fine with the changes in smack_init_inode_security(),
and leaving smack_d_instantiate() untouched. 

>  			if (rc >= 0)
>  				transflag = SMK_INODE_TRANSMUTE;
>  		}

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH] Smack modifications for: security: Allow all LSMs to provide xattrs for inode_init_security hook
  2023-04-11 17:54           ` Casey Schaufler
@ 2023-04-12  7:22             ` Roberto Sassu
  2023-04-12 20:29               ` Casey Schaufler
  0 siblings, 1 reply; 44+ messages in thread
From: Roberto Sassu @ 2023-04-12  7:22 UTC (permalink / raw)
  To: Casey Schaufler, zohar, dmitry.kasatkin, paul, jmorris, serge,
	stephen.smalley.work, eparis
  Cc: reiserfs-devel, linux-kernel, linux-integrity,
	linux-security-module, selinux, bpf, kpsingh, keescook,
	nicolas.bouchinet, Roberto Sassu

On Tue, 2023-04-11 at 10:54 -0700, Casey Schaufler wrote:
> On 4/11/2023 10:23 AM, Roberto Sassu wrote:
> > From: Roberto Sassu <roberto.sassu@huawei.com>
> > 
> > Very very quick modification. Not tested.
> > 
> > Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
> > ---
> >  security/smack/smack.h     |  2 +-
> >  security/smack/smack_lsm.c | 42 ++++++++++++++++++++------------------
> >  2 files changed, 23 insertions(+), 21 deletions(-)
> > 
> > diff --git a/security/smack/smack.h b/security/smack/smack.h
> > index e2239be7bd6..f00c8498c60 100644
> > --- a/security/smack/smack.h
> > +++ b/security/smack/smack.h
> > @@ -127,7 +127,7 @@ struct task_smack {
> >  
> >  #define	SMK_INODE_INSTANT	0x01	/* inode is instantiated */
> >  #define	SMK_INODE_TRANSMUTE	0x02	/* directory is transmuting */
> > -#define	SMK_INODE_CHANGED	0x04	/* smack was transmuted */
> > +#define	SMK_INODE_CHANGED	0x04	/* smack was transmuted (unused) */
> 
> See below ...
> 
> >  #define	SMK_INODE_IMPURE	0x08	/* involved in an impure transaction */
> >  
> >  /*
> > diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
> > index 8392983334b..b43820bdbd0 100644
> > --- a/security/smack/smack_lsm.c
> > +++ b/security/smack/smack_lsm.c
> > @@ -54,12 +54,12 @@
> >  
> >  /*
> >   * Smack uses multiple xattrs.
> > - * SMACK64 - for access control, SMACK64EXEC - label for the program,
> > - * SMACK64MMAP - controls library loading,
> > + * SMACK64 - for access control,
> >   * SMACK64TRANSMUTE - label initialization,
> > - * Not saved on files - SMACK64IPIN and SMACK64IPOUT
> > + * Not saved on files - SMACK64IPIN and SMACK64IPOUT,
> > + * Must be set explicitly - SMACK64EXEC and SMACK64MMAP
> >   */
> > -#define SMACK_INODE_INIT_XATTRS 4
> > +#define SMACK_INODE_INIT_XATTRS 2
> >  
> >  #ifdef SMACK_IPV6_PORT_LABELING
> >  static DEFINE_MUTEX(smack_ipv6_lock);
> > @@ -957,11 +957,11 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
> >  				     const struct qstr *qstr,
> >  				     struct xattr *xattrs, int *xattr_count)
> >  {
> > -	struct inode_smack *issp = smack_inode(inode);
> >  	struct smack_known *skp = smk_of_current();
> >  	struct smack_known *isp = smk_of_inode(inode);
> >  	struct smack_known *dsp = smk_of_inode(dir);
> >  	struct xattr *xattr = lsm_get_xattr_slot(xattrs, xattr_count);
> > +	struct xattr *xattr2;
> 
> I'm going to channel Paul and suggest this be xattr_transmute instead of xattr2.
> It also looks like it could move to be declared in the if clause.
> 
> >  	int may;
> >  
> >  	if (xattr) {
> > @@ -979,7 +979,17 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
> >  		if (may > 0 && ((may & MAY_TRANSMUTE) != 0) &&
> >  		    smk_inode_transmutable(dir)) {
> >  			isp = dsp;
> > -			issp->smk_flags |= SMK_INODE_CHANGED;
> 
> I think you need to keep this. More below.
> 
> > +			xattr2 = lsm_get_xattr_slot(xattrs, xattr_count);
> > +			if (xattr2) {
> > +				xattr2->value = kmemdup(TRANS_TRUE,
> > +							TRANS_TRUE_SIZE,
> > +							GFP_NOFS);
> > +				if (xattr2->value == NULL)
> > +					return -ENOMEM;
> > +
> > +				xattr2->value_len = TRANS_TRUE_SIZE;
> > +				xattr2->name = XATTR_NAME_SMACKTRANSMUTE;
> > +			}
> >  		}
> >  
> >  		xattr->value = kstrdup(isp->smk_known, GFP_NOFS);
> > @@ -3512,20 +3522,12 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
> >  			 * If there is a transmute attribute on the
> >  			 * directory mark the inode.
> >  			 */
> > -			if (isp->smk_flags & SMK_INODE_CHANGED) {
> > -				isp->smk_flags &= ~SMK_INODE_CHANGED;
> > -				rc = __vfs_setxattr(&nop_mnt_idmap, dp, inode,
> > -					XATTR_NAME_SMACKTRANSMUTE,
> > -					TRANS_TRUE, TRANS_TRUE_SIZE,
> > -					0);
> > -			} else {
> > -				rc = __vfs_getxattr(dp, inode,
> > -					XATTR_NAME_SMACKTRANSMUTE, trattr,
> > -					TRANS_TRUE_SIZE);
> > -				if (rc >= 0 && strncmp(trattr, TRANS_TRUE,
> > -						       TRANS_TRUE_SIZE) != 0)
> > -					rc = -EINVAL;
> > -			}
> > +			rc = __vfs_getxattr(dp, inode,
> > +					    XATTR_NAME_SMACKTRANSMUTE, trattr,
> > +					    TRANS_TRUE_SIZE);
> > +			if (rc >= 0 && strncmp(trattr, TRANS_TRUE,
> > +					       TRANS_TRUE_SIZE) != 0)
> > +				rc = -EINVAL;
> 
> Where is the SMACK64_TRANSMUTE attribute going to get set on the file?
> It's not going to get set in smack_init_inode_security(). The inode will

Isn't that the purpose of the inode_init_security hook?

After all LSMs provide one or multiple xattrs, xattrs are going to be
written to the disk with the initxattr() callback of filesystems.

There is a small mistake above (XATTR_SMACK_TRANSMUTE instead
of XATTR_NAME_SMACKTRANSMUTE, as we are providing just the suffix).

After fixing that, Smack tests succeed:

95 Passed, 0 Failed, 100% Success rate

There was a test failing in dir-transmute.sh, before I fixed the xattr
name.

Thanks

Roberto

> know it's transmuting, but it won't get to disk without the __vfs_setxattr()
> here in smack_d_instantiate(). Now, it's been a long time since that code
> was written, so I could be wrong, but I'm pretty sure about that.
> 
> I think that you should be fine with the changes in smack_init_inode_security(),
> and leaving smack_d_instantiate() untouched. 
> 
> >  			if (rc >= 0)
> >  				transflag = SMK_INODE_TRANSMUTE;
> >  		}


^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH] Smack modifications for: security: Allow all LSMs to provide xattrs for inode_init_security hook
  2023-04-12  7:22             ` Roberto Sassu
@ 2023-04-12 20:29               ` Casey Schaufler
  2023-04-13  7:11                 ` Roberto Sassu
  0 siblings, 1 reply; 44+ messages in thread
From: Casey Schaufler @ 2023-04-12 20:29 UTC (permalink / raw)
  To: Roberto Sassu, zohar, dmitry.kasatkin, paul, jmorris, serge,
	stephen.smalley.work, eparis
  Cc: reiserfs-devel, linux-kernel, linux-integrity,
	linux-security-module, selinux, bpf, kpsingh, keescook,
	nicolas.bouchinet, Roberto Sassu, Casey Schaufler

On 4/12/2023 12:22 AM, Roberto Sassu wrote:
> On Tue, 2023-04-11 at 10:54 -0700, Casey Schaufler wrote:
>> On 4/11/2023 10:23 AM, Roberto Sassu wrote:
>>> From: Roberto Sassu <roberto.sassu@huawei.com>
>>>
>>> Very very quick modification. Not tested.
>>>
>>> Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
>>> ---
>>>  security/smack/smack.h     |  2 +-
>>>  security/smack/smack_lsm.c | 42 ++++++++++++++++++++------------------
>>>  2 files changed, 23 insertions(+), 21 deletions(-)
>>>
>>> diff --git a/security/smack/smack.h b/security/smack/smack.h
>>> index e2239be7bd6..f00c8498c60 100644
>>> --- a/security/smack/smack.h
>>> +++ b/security/smack/smack.h
>>> @@ -127,7 +127,7 @@ struct task_smack {
>>>  
>>>  #define	SMK_INODE_INSTANT	0x01	/* inode is instantiated */
>>>  #define	SMK_INODE_TRANSMUTE	0x02	/* directory is transmuting */
>>> -#define	SMK_INODE_CHANGED	0x04	/* smack was transmuted */
>>> +#define	SMK_INODE_CHANGED	0x04	/* smack was transmuted (unused) */
>> See below ...
>>
>>>  #define	SMK_INODE_IMPURE	0x08	/* involved in an impure transaction */
>>>  
>>>  /*
>>> diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
>>> index 8392983334b..b43820bdbd0 100644
>>> --- a/security/smack/smack_lsm.c
>>> +++ b/security/smack/smack_lsm.c
>>> @@ -54,12 +54,12 @@
>>>  
>>>  /*
>>>   * Smack uses multiple xattrs.
>>> - * SMACK64 - for access control, SMACK64EXEC - label for the program,
>>> - * SMACK64MMAP - controls library loading,
>>> + * SMACK64 - for access control,
>>>   * SMACK64TRANSMUTE - label initialization,
>>> - * Not saved on files - SMACK64IPIN and SMACK64IPOUT
>>> + * Not saved on files - SMACK64IPIN and SMACK64IPOUT,
>>> + * Must be set explicitly - SMACK64EXEC and SMACK64MMAP
>>>   */
>>> -#define SMACK_INODE_INIT_XATTRS 4
>>> +#define SMACK_INODE_INIT_XATTRS 2
>>>  
>>>  #ifdef SMACK_IPV6_PORT_LABELING
>>>  static DEFINE_MUTEX(smack_ipv6_lock);
>>> @@ -957,11 +957,11 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
>>>  				     const struct qstr *qstr,
>>>  				     struct xattr *xattrs, int *xattr_count)
>>>  {
>>> -	struct inode_smack *issp = smack_inode(inode);
>>>  	struct smack_known *skp = smk_of_current();
>>>  	struct smack_known *isp = smk_of_inode(inode);
>>>  	struct smack_known *dsp = smk_of_inode(dir);
>>>  	struct xattr *xattr = lsm_get_xattr_slot(xattrs, xattr_count);
>>> +	struct xattr *xattr2;
>> I'm going to channel Paul and suggest this be xattr_transmute instead of xattr2.
>> It also looks like it could move to be declared in the if clause.
>>
>>>  	int may;
>>>  
>>>  	if (xattr) {
>>> @@ -979,7 +979,17 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
>>>  		if (may > 0 && ((may & MAY_TRANSMUTE) != 0) &&
>>>  		    smk_inode_transmutable(dir)) {
>>>  			isp = dsp;
>>> -			issp->smk_flags |= SMK_INODE_CHANGED;
>> I think you need to keep this. More below.
>>
>>> +			xattr2 = lsm_get_xattr_slot(xattrs, xattr_count);
>>> +			if (xattr2) {
>>> +				xattr2->value = kmemdup(TRANS_TRUE,
>>> +							TRANS_TRUE_SIZE,
>>> +							GFP_NOFS);
>>> +				if (xattr2->value == NULL)
>>> +					return -ENOMEM;
>>> +
>>> +				xattr2->value_len = TRANS_TRUE_SIZE;
>>> +				xattr2->name = XATTR_NAME_SMACKTRANSMUTE;
>>> +			}
>>>  		}
>>>  
>>>  		xattr->value = kstrdup(isp->smk_known, GFP_NOFS);
>>> @@ -3512,20 +3522,12 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
>>>  			 * If there is a transmute attribute on the
>>>  			 * directory mark the inode.
>>>  			 */
>>> -			if (isp->smk_flags & SMK_INODE_CHANGED) {
>>> -				isp->smk_flags &= ~SMK_INODE_CHANGED;
>>> -				rc = __vfs_setxattr(&nop_mnt_idmap, dp, inode,
>>> -					XATTR_NAME_SMACKTRANSMUTE,
>>> -					TRANS_TRUE, TRANS_TRUE_SIZE,
>>> -					0);
>>> -			} else {
>>> -				rc = __vfs_getxattr(dp, inode,
>>> -					XATTR_NAME_SMACKTRANSMUTE, trattr,
>>> -					TRANS_TRUE_SIZE);
>>> -				if (rc >= 0 && strncmp(trattr, TRANS_TRUE,
>>> -						       TRANS_TRUE_SIZE) != 0)
>>> -					rc = -EINVAL;
>>> -			}
>>> +			rc = __vfs_getxattr(dp, inode,
>>> +					    XATTR_NAME_SMACKTRANSMUTE, trattr,
>>> +					    TRANS_TRUE_SIZE);
>>> +			if (rc >= 0 && strncmp(trattr, TRANS_TRUE,
>>> +					       TRANS_TRUE_SIZE) != 0)
>>> +				rc = -EINVAL;
>> Where is the SMACK64_TRANSMUTE attribute going to get set on the file?
>> It's not going to get set in smack_init_inode_security(). The inode will
> Isn't that the purpose of the inode_init_security hook?

No. It initializes the in-memory inode. 

> After all LSMs provide one or multiple xattrs, xattrs are going to be
> written to the disk with the initxattr() callback of filesystems.
>
> There is a small mistake above (XATTR_SMACK_TRANSMUTE instead
> of XATTR_NAME_SMACKTRANSMUTE, as we are providing just the suffix).
>
> After fixing that, Smack tests succeed:

It's over a decade since I seriously looked at this code path,
but I'm pretty sure the __vfs_setxattr() call is necessary to get
the attribute written out. With your change the in-memory inode will
get the attribute, but if you reboot it won't be on the directory.

>
> 95 Passed, 0 Failed, 100% Success rate
>
> There was a test failing in dir-transmute.sh, before I fixed the xattr
> name.
>
> Thanks
>
> Roberto
>
>> know it's transmuting, but it won't get to disk without the __vfs_setxattr()
>> here in smack_d_instantiate(). Now, it's been a long time since that code
>> was written, so I could be wrong, but I'm pretty sure about that.
>>
>> I think that you should be fine with the changes in smack_init_inode_security(),
>> and leaving smack_d_instantiate() untouched. 
>>
>>>  			if (rc >= 0)
>>>  				transflag = SMK_INODE_TRANSMUTE;
>>>  		}

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH] Smack modifications for: security: Allow all LSMs to provide xattrs for inode_init_security hook
  2023-04-12 20:29               ` Casey Schaufler
@ 2023-04-13  7:11                 ` Roberto Sassu
  2023-04-17 16:41                   ` Casey Schaufler
  0 siblings, 1 reply; 44+ messages in thread
From: Roberto Sassu @ 2023-04-13  7:11 UTC (permalink / raw)
  To: Casey Schaufler, zohar, dmitry.kasatkin, paul, jmorris, serge,
	stephen.smalley.work, eparis
  Cc: reiserfs-devel, linux-kernel, linux-integrity,
	linux-security-module, selinux, bpf, kpsingh, keescook,
	nicolas.bouchinet, Roberto Sassu

On Wed, 2023-04-12 at 13:29 -0700, Casey Schaufler wrote:
> On 4/12/2023 12:22 AM, Roberto Sassu wrote:
> > On Tue, 2023-04-11 at 10:54 -0700, Casey Schaufler wrote:
> > > On 4/11/2023 10:23 AM, Roberto Sassu wrote:
> > > > From: Roberto Sassu <roberto.sassu@huawei.com>
> > > > 
> > > > Very very quick modification. Not tested.
> > > > 
> > > > Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
> > > > ---
> > > >  security/smack/smack.h     |  2 +-
> > > >  security/smack/smack_lsm.c | 42 ++++++++++++++++++++------------------
> > > >  2 files changed, 23 insertions(+), 21 deletions(-)
> > > > 
> > > > diff --git a/security/smack/smack.h b/security/smack/smack.h
> > > > index e2239be7bd6..f00c8498c60 100644
> > > > --- a/security/smack/smack.h
> > > > +++ b/security/smack/smack.h
> > > > @@ -127,7 +127,7 @@ struct task_smack {
> > > >  
> > > >  #define	SMK_INODE_INSTANT	0x01	/* inode is instantiated */
> > > >  #define	SMK_INODE_TRANSMUTE	0x02	/* directory is transmuting */
> > > > -#define	SMK_INODE_CHANGED	0x04	/* smack was transmuted */
> > > > +#define	SMK_INODE_CHANGED	0x04	/* smack was transmuted (unused) */
> > > See below ...
> > > 
> > > >  #define	SMK_INODE_IMPURE	0x08	/* involved in an impure transaction */
> > > >  
> > > >  /*
> > > > diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
> > > > index 8392983334b..b43820bdbd0 100644
> > > > --- a/security/smack/smack_lsm.c
> > > > +++ b/security/smack/smack_lsm.c
> > > > @@ -54,12 +54,12 @@
> > > >  
> > > >  /*
> > > >   * Smack uses multiple xattrs.
> > > > - * SMACK64 - for access control, SMACK64EXEC - label for the program,
> > > > - * SMACK64MMAP - controls library loading,
> > > > + * SMACK64 - for access control,
> > > >   * SMACK64TRANSMUTE - label initialization,
> > > > - * Not saved on files - SMACK64IPIN and SMACK64IPOUT
> > > > + * Not saved on files - SMACK64IPIN and SMACK64IPOUT,
> > > > + * Must be set explicitly - SMACK64EXEC and SMACK64MMAP
> > > >   */
> > > > -#define SMACK_INODE_INIT_XATTRS 4
> > > > +#define SMACK_INODE_INIT_XATTRS 2
> > > >  
> > > >  #ifdef SMACK_IPV6_PORT_LABELING
> > > >  static DEFINE_MUTEX(smack_ipv6_lock);
> > > > @@ -957,11 +957,11 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
> > > >  				     const struct qstr *qstr,
> > > >  				     struct xattr *xattrs, int *xattr_count)
> > > >  {
> > > > -	struct inode_smack *issp = smack_inode(inode);
> > > >  	struct smack_known *skp = smk_of_current();
> > > >  	struct smack_known *isp = smk_of_inode(inode);
> > > >  	struct smack_known *dsp = smk_of_inode(dir);
> > > >  	struct xattr *xattr = lsm_get_xattr_slot(xattrs, xattr_count);
> > > > +	struct xattr *xattr2;
> > > I'm going to channel Paul and suggest this be xattr_transmute instead of xattr2.
> > > It also looks like it could move to be declared in the if clause.
> > > 
> > > >  	int may;
> > > >  
> > > >  	if (xattr) {
> > > > @@ -979,7 +979,17 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
> > > >  		if (may > 0 && ((may & MAY_TRANSMUTE) != 0) &&
> > > >  		    smk_inode_transmutable(dir)) {
> > > >  			isp = dsp;
> > > > -			issp->smk_flags |= SMK_INODE_CHANGED;
> > > I think you need to keep this. More below.
> > > 
> > > > +			xattr2 = lsm_get_xattr_slot(xattrs, xattr_count);
> > > > +			if (xattr2) {
> > > > +				xattr2->value = kmemdup(TRANS_TRUE,
> > > > +							TRANS_TRUE_SIZE,
> > > > +							GFP_NOFS);
> > > > +				if (xattr2->value == NULL)
> > > > +					return -ENOMEM;
> > > > +
> > > > +				xattr2->value_len = TRANS_TRUE_SIZE;
> > > > +				xattr2->name = XATTR_NAME_SMACKTRANSMUTE;
> > > > +			}
> > > >  		}
> > > >  
> > > >  		xattr->value = kstrdup(isp->smk_known, GFP_NOFS);
> > > > @@ -3512,20 +3522,12 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
> > > >  			 * If there is a transmute attribute on the
> > > >  			 * directory mark the inode.
> > > >  			 */
> > > > -			if (isp->smk_flags & SMK_INODE_CHANGED) {
> > > > -				isp->smk_flags &= ~SMK_INODE_CHANGED;
> > > > -				rc = __vfs_setxattr(&nop_mnt_idmap, dp, inode,
> > > > -					XATTR_NAME_SMACKTRANSMUTE,
> > > > -					TRANS_TRUE, TRANS_TRUE_SIZE,
> > > > -					0);
> > > > -			} else {
> > > > -				rc = __vfs_getxattr(dp, inode,
> > > > -					XATTR_NAME_SMACKTRANSMUTE, trattr,
> > > > -					TRANS_TRUE_SIZE);
> > > > -				if (rc >= 0 && strncmp(trattr, TRANS_TRUE,
> > > > -						       TRANS_TRUE_SIZE) != 0)
> > > > -					rc = -EINVAL;
> > > > -			}
> > > > +			rc = __vfs_getxattr(dp, inode,
> > > > +					    XATTR_NAME_SMACKTRANSMUTE, trattr,
> > > > +					    TRANS_TRUE_SIZE);
> > > > +			if (rc >= 0 && strncmp(trattr, TRANS_TRUE,
> > > > +					       TRANS_TRUE_SIZE) != 0)
> > > > +				rc = -EINVAL;
> > > Where is the SMACK64_TRANSMUTE attribute going to get set on the file?
> > > It's not going to get set in smack_init_inode_security(). The inode will
> > Isn't that the purpose of the inode_init_security hook?
> 
> No. It initializes the in-memory inode. 

I hope I'm not mistaken here...

I make a small example. Filesystems call
security_inode_init_security(). Ext4 does:

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/fs/ext4/xattr_security.c?h=v6.3-rc6#n54

security_inode_init_security() allocates new_xattrs. Each LSM fills
new_xattrs. At the end of the loop, if there is at least one xattr
filled, the initxattrs() callback passed by the caller of
security_inode_init_security() is called.

The ext4 initxattrs() callback is:

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/fs/ext4/xattr_security.c?h=v6.3-rc6#n35

which scans the xattr array and, for each xattr,
calls ext4_xattr_set_handle().

Maybe I'm overlooking it, but ext4_xattr_set_handle() is setting xattrs
on the disk. Am I wrong?

Thanks

Roberto

> > After all LSMs provide one or multiple xattrs, xattrs are going to be
> > written to the disk with the initxattr() callback of filesystems.
> > 
> > There is a small mistake above (XATTR_SMACK_TRANSMUTE instead
> > of XATTR_NAME_SMACKTRANSMUTE, as we are providing just the suffix).
> > 
> > After fixing that, Smack tests succeed:
> 
> It's over a decade since I seriously looked at this code path,
> but I'm pretty sure the __vfs_setxattr() call is necessary to get
> the attribute written out. With your change the in-memory inode will
> get the attribute, but if you reboot it won't be on the directory.
> 
> > 95 Passed, 0 Failed, 100% Success rate
> > 
> > There was a test failing in dir-transmute.sh, before I fixed the xattr
> > name.
> > 
> > Thanks
> > 
> > Roberto
> > 
> > > know it's transmuting, but it won't get to disk without the __vfs_setxattr()
> > > here in smack_d_instantiate(). Now, it's been a long time since that code
> > > was written, so I could be wrong, but I'm pretty sure about that.
> > > 
> > > I think that you should be fine with the changes in smack_init_inode_security(),
> > > and leaving smack_d_instantiate() untouched. 
> > > 
> > > >  			if (rc >= 0)
> > > >  				transflag = SMK_INODE_TRANSMUTE;
> > > >  		}


^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH] Smack modifications for: security: Allow all LSMs to provide xattrs for inode_init_security hook
  2023-04-13  7:11                 ` Roberto Sassu
@ 2023-04-17 16:41                   ` Casey Schaufler
  2023-04-18  7:05                     ` Roberto Sassu
  0 siblings, 1 reply; 44+ messages in thread
From: Casey Schaufler @ 2023-04-17 16:41 UTC (permalink / raw)
  To: Roberto Sassu, zohar, dmitry.kasatkin, paul, jmorris, serge,
	stephen.smalley.work, eparis
  Cc: reiserfs-devel, linux-kernel, linux-integrity,
	linux-security-module, selinux, bpf, kpsingh, keescook,
	nicolas.bouchinet, Roberto Sassu, Casey Schaufler

On 4/13/2023 12:11 AM, Roberto Sassu wrote:
> On Wed, 2023-04-12 at 13:29 -0700, Casey Schaufler wrote:
>> On 4/12/2023 12:22 AM, Roberto Sassu wrote:
>>> On Tue, 2023-04-11 at 10:54 -0700, Casey Schaufler wrote:
>>>> On 4/11/2023 10:23 AM, Roberto Sassu wrote:
>>>>> From: Roberto Sassu <roberto.sassu@huawei.com>
>>>>>
>>>>> Very very quick modification. Not tested.
>>>>>
>>>>> Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
>>>>> ---
>>>>>  security/smack/smack.h     |  2 +-
>>>>>  security/smack/smack_lsm.c | 42 ++++++++++++++++++++------------------
>>>>>  2 files changed, 23 insertions(+), 21 deletions(-)
>>>>>
>>>>> diff --git a/security/smack/smack.h b/security/smack/smack.h
>>>>> index e2239be7bd6..f00c8498c60 100644
>>>>> --- a/security/smack/smack.h
>>>>> +++ b/security/smack/smack.h
>>>>> @@ -127,7 +127,7 @@ struct task_smack {
>>>>>  
>>>>>  #define	SMK_INODE_INSTANT	0x01	/* inode is instantiated */
>>>>>  #define	SMK_INODE_TRANSMUTE	0x02	/* directory is transmuting */
>>>>> -#define	SMK_INODE_CHANGED	0x04	/* smack was transmuted */
>>>>> +#define	SMK_INODE_CHANGED	0x04	/* smack was transmuted (unused) */
>>>> See below ...
>>>>
>>>>>  #define	SMK_INODE_IMPURE	0x08	/* involved in an impure transaction */
>>>>>  
>>>>>  /*
>>>>> diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
>>>>> index 8392983334b..b43820bdbd0 100644
>>>>> --- a/security/smack/smack_lsm.c
>>>>> +++ b/security/smack/smack_lsm.c
>>>>> @@ -54,12 +54,12 @@
>>>>>  
>>>>>  /*
>>>>>   * Smack uses multiple xattrs.
>>>>> - * SMACK64 - for access control, SMACK64EXEC - label for the program,
>>>>> - * SMACK64MMAP - controls library loading,
>>>>> + * SMACK64 - for access control,
>>>>>   * SMACK64TRANSMUTE - label initialization,
>>>>> - * Not saved on files - SMACK64IPIN and SMACK64IPOUT
>>>>> + * Not saved on files - SMACK64IPIN and SMACK64IPOUT,
>>>>> + * Must be set explicitly - SMACK64EXEC and SMACK64MMAP
>>>>>   */
>>>>> -#define SMACK_INODE_INIT_XATTRS 4
>>>>> +#define SMACK_INODE_INIT_XATTRS 2
>>>>>  
>>>>>  #ifdef SMACK_IPV6_PORT_LABELING
>>>>>  static DEFINE_MUTEX(smack_ipv6_lock);
>>>>> @@ -957,11 +957,11 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
>>>>>  				     const struct qstr *qstr,
>>>>>  				     struct xattr *xattrs, int *xattr_count)
>>>>>  {
>>>>> -	struct inode_smack *issp = smack_inode(inode);
>>>>>  	struct smack_known *skp = smk_of_current();
>>>>>  	struct smack_known *isp = smk_of_inode(inode);
>>>>>  	struct smack_known *dsp = smk_of_inode(dir);
>>>>>  	struct xattr *xattr = lsm_get_xattr_slot(xattrs, xattr_count);
>>>>> +	struct xattr *xattr2;
>>>> I'm going to channel Paul and suggest this be xattr_transmute instead of xattr2.
>>>> It also looks like it could move to be declared in the if clause.
>>>>
>>>>>  	int may;
>>>>>  
>>>>>  	if (xattr) {
>>>>> @@ -979,7 +979,17 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
>>>>>  		if (may > 0 && ((may & MAY_TRANSMUTE) != 0) &&
>>>>>  		    smk_inode_transmutable(dir)) {
>>>>>  			isp = dsp;
>>>>> -			issp->smk_flags |= SMK_INODE_CHANGED;
>>>> I think you need to keep this. More below.
>>>>
>>>>> +			xattr2 = lsm_get_xattr_slot(xattrs, xattr_count);
>>>>> +			if (xattr2) {
>>>>> +				xattr2->value = kmemdup(TRANS_TRUE,
>>>>> +							TRANS_TRUE_SIZE,
>>>>> +							GFP_NOFS);
>>>>> +				if (xattr2->value == NULL)
>>>>> +					return -ENOMEM;
>>>>> +
>>>>> +				xattr2->value_len = TRANS_TRUE_SIZE;
>>>>> +				xattr2->name = XATTR_NAME_SMACKTRANSMUTE;
>>>>> +			}
>>>>>  		}
>>>>>  
>>>>>  		xattr->value = kstrdup(isp->smk_known, GFP_NOFS);
>>>>> @@ -3512,20 +3522,12 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
>>>>>  			 * If there is a transmute attribute on the
>>>>>  			 * directory mark the inode.
>>>>>  			 */
>>>>> -			if (isp->smk_flags & SMK_INODE_CHANGED) {
>>>>> -				isp->smk_flags &= ~SMK_INODE_CHANGED;
>>>>> -				rc = __vfs_setxattr(&nop_mnt_idmap, dp, inode,
>>>>> -					XATTR_NAME_SMACKTRANSMUTE,
>>>>> -					TRANS_TRUE, TRANS_TRUE_SIZE,
>>>>> -					0);
>>>>> -			} else {
>>>>> -				rc = __vfs_getxattr(dp, inode,
>>>>> -					XATTR_NAME_SMACKTRANSMUTE, trattr,
>>>>> -					TRANS_TRUE_SIZE);
>>>>> -				if (rc >= 0 && strncmp(trattr, TRANS_TRUE,
>>>>> -						       TRANS_TRUE_SIZE) != 0)
>>>>> -					rc = -EINVAL;
>>>>> -			}
>>>>> +			rc = __vfs_getxattr(dp, inode,
>>>>> +					    XATTR_NAME_SMACKTRANSMUTE, trattr,
>>>>> +					    TRANS_TRUE_SIZE);
>>>>> +			if (rc >= 0 && strncmp(trattr, TRANS_TRUE,
>>>>> +					       TRANS_TRUE_SIZE) != 0)
>>>>> +				rc = -EINVAL;
>>>> Where is the SMACK64_TRANSMUTE attribute going to get set on the file?
>>>> It's not going to get set in smack_init_inode_security(). The inode will
>>> Isn't that the purpose of the inode_init_security hook?
>> No. It initializes the in-memory inode. 
> I hope I'm not mistaken here...
>
> I make a small example. Filesystems call
> security_inode_init_security(). Ext4 does:
>
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/fs/ext4/xattr_security.c?h=v6.3-rc6#n54
>
> security_inode_init_security() allocates new_xattrs. Each LSM fills
> new_xattrs. At the end of the loop, if there is at least one xattr
> filled, the initxattrs() callback passed by the caller of
> security_inode_init_security() is called.
>
> The ext4 initxattrs() callback is:
>
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/fs/ext4/xattr_security.c?h=v6.3-rc6#n35
>
> which scans the xattr array and, for each xattr,
> calls ext4_xattr_set_handle().
>
> Maybe I'm overlooking it, but ext4_xattr_set_handle() is setting xattrs
> on the disk. Am I wrong?

Yes, you're wrong. I tried your change, and the SMACK64_TRANSMUTE isn't
set on the sub-directory when it's created. The __vfs_setxattr() call really
is necessary. 

>
> Thanks
>
> Roberto
>
>>> After all LSMs provide one or multiple xattrs, xattrs are going to be
>>> written to the disk with the initxattr() callback of filesystems.
>>>
>>> There is a small mistake above (XATTR_SMACK_TRANSMUTE instead
>>> of XATTR_NAME_SMACKTRANSMUTE, as we are providing just the suffix).
>>>
>>> After fixing that, Smack tests succeed:
>> It's over a decade since I seriously looked at this code path,
>> but I'm pretty sure the __vfs_setxattr() call is necessary to get
>> the attribute written out. With your change the in-memory inode will
>> get the attribute, but if you reboot it won't be on the directory.
>>
>>> 95 Passed, 0 Failed, 100% Success rate
>>>
>>> There was a test failing in dir-transmute.sh, before I fixed the xattr
>>> name.
>>>
>>> Thanks
>>>
>>> Roberto
>>>
>>>> know it's transmuting, but it won't get to disk without the __vfs_setxattr()
>>>> here in smack_d_instantiate(). Now, it's been a long time since that code
>>>> was written, so I could be wrong, but I'm pretty sure about that.
>>>>
>>>> I think that you should be fine with the changes in smack_init_inode_security(),
>>>> and leaving smack_d_instantiate() untouched. 
>>>>
>>>>>  			if (rc >= 0)
>>>>>  				transflag = SMK_INODE_TRANSMUTE;
>>>>>  		}

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH] Smack modifications for: security: Allow all LSMs to provide xattrs for inode_init_security hook
  2023-04-17 16:41                   ` Casey Schaufler
@ 2023-04-18  7:05                     ` Roberto Sassu
  2023-04-18 16:02                       ` Casey Schaufler
  0 siblings, 1 reply; 44+ messages in thread
From: Roberto Sassu @ 2023-04-18  7:05 UTC (permalink / raw)
  To: Casey Schaufler, zohar, dmitry.kasatkin, paul, jmorris, serge,
	stephen.smalley.work, eparis
  Cc: reiserfs-devel, linux-kernel, linux-integrity,
	linux-security-module, selinux, bpf, kpsingh, keescook,
	nicolas.bouchinet, Roberto Sassu

On Mon, 2023-04-17 at 09:41 -0700, Casey Schaufler wrote:
> On 4/13/2023 12:11 AM, Roberto Sassu wrote:
> > On Wed, 2023-04-12 at 13:29 -0700, Casey Schaufler wrote:
> > > On 4/12/2023 12:22 AM, Roberto Sassu wrote:
> > > > On Tue, 2023-04-11 at 10:54 -0700, Casey Schaufler wrote:
> > > > > On 4/11/2023 10:23 AM, Roberto Sassu wrote:
> > > > > > From: Roberto Sassu <roberto.sassu@huawei.com>
> > > > > > 
> > > > > > Very very quick modification. Not tested.
> > > > > > 
> > > > > > Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
> > > > > > ---
> > > > > >  security/smack/smack.h     |  2 +-
> > > > > >  security/smack/smack_lsm.c | 42 ++++++++++++++++++++------------------
> > > > > >  2 files changed, 23 insertions(+), 21 deletions(-)
> > > > > > 
> > > > > > diff --git a/security/smack/smack.h b/security/smack/smack.h
> > > > > > index e2239be7bd6..f00c8498c60 100644
> > > > > > --- a/security/smack/smack.h
> > > > > > +++ b/security/smack/smack.h
> > > > > > @@ -127,7 +127,7 @@ struct task_smack {
> > > > > >  
> > > > > >  #define	SMK_INODE_INSTANT	0x01	/* inode is instantiated */
> > > > > >  #define	SMK_INODE_TRANSMUTE	0x02	/* directory is transmuting */
> > > > > > -#define	SMK_INODE_CHANGED	0x04	/* smack was transmuted */
> > > > > > +#define	SMK_INODE_CHANGED	0x04	/* smack was transmuted (unused) */
> > > > > See below ...
> > > > > 
> > > > > >  #define	SMK_INODE_IMPURE	0x08	/* involved in an impure transaction */
> > > > > >  
> > > > > >  /*
> > > > > > diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
> > > > > > index 8392983334b..b43820bdbd0 100644
> > > > > > --- a/security/smack/smack_lsm.c
> > > > > > +++ b/security/smack/smack_lsm.c
> > > > > > @@ -54,12 +54,12 @@
> > > > > >  
> > > > > >  /*
> > > > > >   * Smack uses multiple xattrs.
> > > > > > - * SMACK64 - for access control, SMACK64EXEC - label for the program,
> > > > > > - * SMACK64MMAP - controls library loading,
> > > > > > + * SMACK64 - for access control,
> > > > > >   * SMACK64TRANSMUTE - label initialization,
> > > > > > - * Not saved on files - SMACK64IPIN and SMACK64IPOUT
> > > > > > + * Not saved on files - SMACK64IPIN and SMACK64IPOUT,
> > > > > > + * Must be set explicitly - SMACK64EXEC and SMACK64MMAP
> > > > > >   */
> > > > > > -#define SMACK_INODE_INIT_XATTRS 4
> > > > > > +#define SMACK_INODE_INIT_XATTRS 2
> > > > > >  
> > > > > >  #ifdef SMACK_IPV6_PORT_LABELING
> > > > > >  static DEFINE_MUTEX(smack_ipv6_lock);
> > > > > > @@ -957,11 +957,11 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
> > > > > >  				     const struct qstr *qstr,
> > > > > >  				     struct xattr *xattrs, int *xattr_count)
> > > > > >  {
> > > > > > -	struct inode_smack *issp = smack_inode(inode);
> > > > > >  	struct smack_known *skp = smk_of_current();
> > > > > >  	struct smack_known *isp = smk_of_inode(inode);
> > > > > >  	struct smack_known *dsp = smk_of_inode(dir);
> > > > > >  	struct xattr *xattr = lsm_get_xattr_slot(xattrs, xattr_count);
> > > > > > +	struct xattr *xattr2;
> > > > > I'm going to channel Paul and suggest this be xattr_transmute instead of xattr2.
> > > > > It also looks like it could move to be declared in the if clause.
> > > > > 
> > > > > >  	int may;
> > > > > >  
> > > > > >  	if (xattr) {
> > > > > > @@ -979,7 +979,17 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
> > > > > >  		if (may > 0 && ((may & MAY_TRANSMUTE) != 0) &&
> > > > > >  		    smk_inode_transmutable(dir)) {
> > > > > >  			isp = dsp;
> > > > > > -			issp->smk_flags |= SMK_INODE_CHANGED;
> > > > > I think you need to keep this. More below.
> > > > > 
> > > > > > +			xattr2 = lsm_get_xattr_slot(xattrs, xattr_count);
> > > > > > +			if (xattr2) {
> > > > > > +				xattr2->value = kmemdup(TRANS_TRUE,
> > > > > > +							TRANS_TRUE_SIZE,
> > > > > > +							GFP_NOFS);
> > > > > > +				if (xattr2->value == NULL)
> > > > > > +					return -ENOMEM;
> > > > > > +
> > > > > > +				xattr2->value_len = TRANS_TRUE_SIZE;
> > > > > > +				xattr2->name = XATTR_NAME_SMACKTRANSMUTE;
> > > > > > +			}
> > > > > >  		}
> > > > > >  
> > > > > >  		xattr->value = kstrdup(isp->smk_known, GFP_NOFS);
> > > > > > @@ -3512,20 +3522,12 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
> > > > > >  			 * If there is a transmute attribute on the
> > > > > >  			 * directory mark the inode.
> > > > > >  			 */
> > > > > > -			if (isp->smk_flags & SMK_INODE_CHANGED) {
> > > > > > -				isp->smk_flags &= ~SMK_INODE_CHANGED;
> > > > > > -				rc = __vfs_setxattr(&nop_mnt_idmap, dp, inode,
> > > > > > -					XATTR_NAME_SMACKTRANSMUTE,
> > > > > > -					TRANS_TRUE, TRANS_TRUE_SIZE,
> > > > > > -					0);
> > > > > > -			} else {
> > > > > > -				rc = __vfs_getxattr(dp, inode,
> > > > > > -					XATTR_NAME_SMACKTRANSMUTE, trattr,
> > > > > > -					TRANS_TRUE_SIZE);
> > > > > > -				if (rc >= 0 && strncmp(trattr, TRANS_TRUE,
> > > > > > -						       TRANS_TRUE_SIZE) != 0)
> > > > > > -					rc = -EINVAL;
> > > > > > -			}
> > > > > > +			rc = __vfs_getxattr(dp, inode,
> > > > > > +					    XATTR_NAME_SMACKTRANSMUTE, trattr,
> > > > > > +					    TRANS_TRUE_SIZE);
> > > > > > +			if (rc >= 0 && strncmp(trattr, TRANS_TRUE,
> > > > > > +					       TRANS_TRUE_SIZE) != 0)
> > > > > > +				rc = -EINVAL;
> > > > > Where is the SMACK64_TRANSMUTE attribute going to get set on the file?
> > > > > It's not going to get set in smack_init_inode_security(). The inode will
> > > > Isn't that the purpose of the inode_init_security hook?
> > > No. It initializes the in-memory inode. 
> > I hope I'm not mistaken here...
> > 
> > I make a small example. Filesystems call
> > security_inode_init_security(). Ext4 does:
> > 
> > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/fs/ext4/xattr_security.c?h=v6.3-rc6#n54
> > 
> > security_inode_init_security() allocates new_xattrs. Each LSM fills
> > new_xattrs. At the end of the loop, if there is at least one xattr
> > filled, the initxattrs() callback passed by the caller of
> > security_inode_init_security() is called.
> > 
> > The ext4 initxattrs() callback is:
> > 
> > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/fs/ext4/xattr_security.c?h=v6.3-rc6#n35
> > 
> > which scans the xattr array and, for each xattr,
> > calls ext4_xattr_set_handle().
> > 
> > Maybe I'm overlooking it, but ext4_xattr_set_handle() is setting xattrs
> > on the disk. Am I wrong?
> 
> Yes, you're wrong. I tried your change, and the SMACK64_TRANSMUTE isn't
> set on the sub-directory when it's created. The __vfs_setxattr() call really
> is necessary. 

Could you please also check if there is any change with this fix:

Replace:

	xattr2->name = XATTR_NAME_SMACKTRANSMUTE;

with:

	xattr2->name = XATTR_SMACK_TRANSMUTE;

Thanks

Roberto

> > Thanks
> > 
> > Roberto
> > 
> > > > After all LSMs provide one or multiple xattrs, xattrs are going to be
> > > > written to the disk with the initxattr() callback of filesystems.
> > > > 
> > > > There is a small mistake above (XATTR_SMACK_TRANSMUTE instead
> > > > of XATTR_NAME_SMACKTRANSMUTE, as we are providing just the suffix).
> > > but I'm pretty sure the __vfs_setxattr() call is necessary to get
> > > the attribute written out. With your change the in-memory inode will
> > > get the attribute, but if you reboot it won't be on the directory.
> > > 
> > > > 95 Passed, 0 Failed, 100% Success rate
> > > > 
> > > > There was a test failing in dir-transmute.sh, before I fixed the xattr
> > > > name.
> > > > 
> > > > Thanks
> > > > 
> > > > Roberto
> > > > 
> > > > > know it's transmuting, but it won't get to disk without the __vfs_setxattr()
> > > > > here in smack_d_instantiate(). Now, it's been a long time since that code
> > > > > was written, so I could be wrong, but I'm pretty sure about that.
> > > > > 
> > > > > I think that you should be fine with the changes in smack_init_inode_security(),
> > > > > and leaving smack_d_instantiate() untouched. 
> > > > > 
> > > > > >  			if (rc >= 0)
> > > > > >  				transflag = SMK_INODE_TRANSMUTE;
> > > > > >  		}


^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH] Smack modifications for: security: Allow all LSMs to provide xattrs for inode_init_security hook
  2023-04-18  7:05                     ` Roberto Sassu
@ 2023-04-18 16:02                       ` Casey Schaufler
  2023-04-19 13:46                         ` Roberto Sassu
  0 siblings, 1 reply; 44+ messages in thread
From: Casey Schaufler @ 2023-04-18 16:02 UTC (permalink / raw)
  To: Roberto Sassu, zohar, dmitry.kasatkin, paul, jmorris, serge,
	stephen.smalley.work, eparis
  Cc: reiserfs-devel, linux-kernel, linux-integrity,
	linux-security-module, selinux, bpf, kpsingh, keescook,
	nicolas.bouchinet, Roberto Sassu, Casey Schaufler

[-- Attachment #1: Type: text/plain, Size: 7970 bytes --]

On 4/18/2023 12:05 AM, Roberto Sassu wrote:
> On Mon, 2023-04-17 at 09:41 -0700, Casey Schaufler wrote:
>> On 4/13/2023 12:11 AM, Roberto Sassu wrote:
>>> On Wed, 2023-04-12 at 13:29 -0700, Casey Schaufler wrote:
>>>> On 4/12/2023 12:22 AM, Roberto Sassu wrote:
>>>>> On Tue, 2023-04-11 at 10:54 -0700, Casey Schaufler wrote:
>>>>>> On 4/11/2023 10:23 AM, Roberto Sassu wrote:
>>>>>>> From: Roberto Sassu <roberto.sassu@huawei.com>
>>>>>>>
>>>>>>> Very very quick modification. Not tested.
>>>>>>>
>>>>>>> Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
>>>>>>> ---
>>>>>>>  security/smack/smack.h     |  2 +-
>>>>>>>  security/smack/smack_lsm.c | 42 ++++++++++++++++++++------------------
>>>>>>>  2 files changed, 23 insertions(+), 21 deletions(-)
>>>>>>>
>>>>>>> diff --git a/security/smack/smack.h b/security/smack/smack.h
>>>>>>> index e2239be7bd6..f00c8498c60 100644
>>>>>>> --- a/security/smack/smack.h
>>>>>>> +++ b/security/smack/smack.h
>>>>>>> @@ -127,7 +127,7 @@ struct task_smack {
>>>>>>>  
>>>>>>>  #define	SMK_INODE_INSTANT	0x01	/* inode is instantiated */
>>>>>>>  #define	SMK_INODE_TRANSMUTE	0x02	/* directory is transmuting */
>>>>>>> -#define	SMK_INODE_CHANGED	0x04	/* smack was transmuted */
>>>>>>> +#define	SMK_INODE_CHANGED	0x04	/* smack was transmuted (unused) */
>>>>>> See below ...
>>>>>>
>>>>>>>  #define	SMK_INODE_IMPURE	0x08	/* involved in an impure transaction */
>>>>>>>  
>>>>>>>  /*
>>>>>>> diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
>>>>>>> index 8392983334b..b43820bdbd0 100644
>>>>>>> --- a/security/smack/smack_lsm.c
>>>>>>> +++ b/security/smack/smack_lsm.c
>>>>>>> @@ -54,12 +54,12 @@
>>>>>>>  
>>>>>>>  /*
>>>>>>>   * Smack uses multiple xattrs.
>>>>>>> - * SMACK64 - for access control, SMACK64EXEC - label for the program,
>>>>>>> - * SMACK64MMAP - controls library loading,
>>>>>>> + * SMACK64 - for access control,
>>>>>>>   * SMACK64TRANSMUTE - label initialization,
>>>>>>> - * Not saved on files - SMACK64IPIN and SMACK64IPOUT
>>>>>>> + * Not saved on files - SMACK64IPIN and SMACK64IPOUT,
>>>>>>> + * Must be set explicitly - SMACK64EXEC and SMACK64MMAP
>>>>>>>   */
>>>>>>> -#define SMACK_INODE_INIT_XATTRS 4
>>>>>>> +#define SMACK_INODE_INIT_XATTRS 2
>>>>>>>  
>>>>>>>  #ifdef SMACK_IPV6_PORT_LABELING
>>>>>>>  static DEFINE_MUTEX(smack_ipv6_lock);
>>>>>>> @@ -957,11 +957,11 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
>>>>>>>  				     const struct qstr *qstr,
>>>>>>>  				     struct xattr *xattrs, int *xattr_count)
>>>>>>>  {
>>>>>>> -	struct inode_smack *issp = smack_inode(inode);
>>>>>>>  	struct smack_known *skp = smk_of_current();
>>>>>>>  	struct smack_known *isp = smk_of_inode(inode);
>>>>>>>  	struct smack_known *dsp = smk_of_inode(dir);
>>>>>>>  	struct xattr *xattr = lsm_get_xattr_slot(xattrs, xattr_count);
>>>>>>> +	struct xattr *xattr2;
>>>>>> I'm going to channel Paul and suggest this be xattr_transmute instead of xattr2.
>>>>>> It also looks like it could move to be declared in the if clause.
>>>>>>
>>>>>>>  	int may;
>>>>>>>  
>>>>>>>  	if (xattr) {
>>>>>>> @@ -979,7 +979,17 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
>>>>>>>  		if (may > 0 && ((may & MAY_TRANSMUTE) != 0) &&
>>>>>>>  		    smk_inode_transmutable(dir)) {
>>>>>>>  			isp = dsp;
>>>>>>> -			issp->smk_flags |= SMK_INODE_CHANGED;
>>>>>> I think you need to keep this. More below.
>>>>>>
>>>>>>> +			xattr2 = lsm_get_xattr_slot(xattrs, xattr_count);
>>>>>>> +			if (xattr2) {
>>>>>>> +				xattr2->value = kmemdup(TRANS_TRUE,
>>>>>>> +							TRANS_TRUE_SIZE,
>>>>>>> +							GFP_NOFS);
>>>>>>> +				if (xattr2->value == NULL)
>>>>>>> +					return -ENOMEM;
>>>>>>> +
>>>>>>> +				xattr2->value_len = TRANS_TRUE_SIZE;
>>>>>>> +				xattr2->name = XATTR_NAME_SMACKTRANSMUTE;
>>>>>>> +			}
>>>>>>>  		}
>>>>>>>  
>>>>>>>  		xattr->value = kstrdup(isp->smk_known, GFP_NOFS);
>>>>>>> @@ -3512,20 +3522,12 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
>>>>>>>  			 * If there is a transmute attribute on the
>>>>>>>  			 * directory mark the inode.
>>>>>>>  			 */
>>>>>>> -			if (isp->smk_flags & SMK_INODE_CHANGED) {
>>>>>>> -				isp->smk_flags &= ~SMK_INODE_CHANGED;
>>>>>>> -				rc = __vfs_setxattr(&nop_mnt_idmap, dp, inode,
>>>>>>> -					XATTR_NAME_SMACKTRANSMUTE,
>>>>>>> -					TRANS_TRUE, TRANS_TRUE_SIZE,
>>>>>>> -					0);
>>>>>>> -			} else {
>>>>>>> -				rc = __vfs_getxattr(dp, inode,
>>>>>>> -					XATTR_NAME_SMACKTRANSMUTE, trattr,
>>>>>>> -					TRANS_TRUE_SIZE);
>>>>>>> -				if (rc >= 0 && strncmp(trattr, TRANS_TRUE,
>>>>>>> -						       TRANS_TRUE_SIZE) != 0)
>>>>>>> -					rc = -EINVAL;
>>>>>>> -			}
>>>>>>> +			rc = __vfs_getxattr(dp, inode,
>>>>>>> +					    XATTR_NAME_SMACKTRANSMUTE, trattr,
>>>>>>> +					    TRANS_TRUE_SIZE);
>>>>>>> +			if (rc >= 0 && strncmp(trattr, TRANS_TRUE,
>>>>>>> +					       TRANS_TRUE_SIZE) != 0)
>>>>>>> +				rc = -EINVAL;
>>>>>> Where is the SMACK64_TRANSMUTE attribute going to get set on the file?
>>>>>> It's not going to get set in smack_init_inode_security(). The inode will
>>>>> Isn't that the purpose of the inode_init_security hook?
>>>> No. It initializes the in-memory inode. 
>>> I hope I'm not mistaken here...
>>>
>>> I make a small example. Filesystems call
>>> security_inode_init_security(). Ext4 does:
>>>
>>> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/fs/ext4/xattr_security.c?h=v6.3-rc6#n54
>>>
>>> security_inode_init_security() allocates new_xattrs. Each LSM fills
>>> new_xattrs. At the end of the loop, if there is at least one xattr
>>> filled, the initxattrs() callback passed by the caller of
>>> security_inode_init_security() is called.
>>>
>>> The ext4 initxattrs() callback is:
>>>
>>> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/fs/ext4/xattr_security.c?h=v6.3-rc6#n35
>>>
>>> which scans the xattr array and, for each xattr,
>>> calls ext4_xattr_set_handle().
>>>
>>> Maybe I'm overlooking it, but ext4_xattr_set_handle() is setting xattrs
>>> on the disk. Am I wrong?
>> Yes, you're wrong. I tried your change, and the SMACK64_TRANSMUTE isn't
>> set on the sub-directory when it's created. The __vfs_setxattr() call really
>> is necessary. 
> Could you please also check if there is any change with this fix:
>
> Replace:
>
> 	xattr2->name = XATTR_NAME_SMACKTRANSMUTE;
>
> with:
>
> 	xattr2->name = XATTR_SMACK_TRANSMUTE;
>
> Thanks

Unless I'm missing something really obvious there's no way that any
of the evm/ima changes would obviate the need for the __vfs_setxattr() call.
It's real easy to verify correct behavior, see the attached script.
(you'll want to change the "notroot" value to a user on your system)

>
> Roberto
>
>>> Thanks
>>>
>>> Roberto
>>>
>>>>> After all LSMs provide one or multiple xattrs, xattrs are going to be
>>>>> written to the disk with the initxattr() callback of filesystems.
>>>>>
>>>>> There is a small mistake above (XATTR_SMACK_TRANSMUTE instead
>>>>> of XATTR_NAME_SMACKTRANSMUTE, as we are providing just the suffix).
>>>> but I'm pretty sure the __vfs_setxattr() call is necessary to get
>>>> the attribute written out. With your change the in-memory inode will
>>>> get the attribute, but if you reboot it won't be on the directory.
>>>>
>>>>> 95 Passed, 0 Failed, 100% Success rate
>>>>>
>>>>> There was a test failing in dir-transmute.sh, before I fixed the xattr
>>>>> name.
>>>>>
>>>>> Thanks
>>>>>
>>>>> Roberto
>>>>>
>>>>>> know it's transmuting, but it won't get to disk without the __vfs_setxattr()
>>>>>> here in smack_d_instantiate(). Now, it's been a long time since that code
>>>>>> was written, so I could be wrong, but I'm pretty sure about that.
>>>>>>
>>>>>> I think that you should be fine with the changes in smack_init_inode_security(),
>>>>>> and leaving smack_d_instantiate() untouched. 
>>>>>>
>>>>>>>  			if (rc >= 0)
>>>>>>>  				transflag = SMK_INODE_TRANSMUTE;
>>>>>>>  		}

[-- Attachment #2: testtransmute.sh --]
[-- Type: text/plain, Size: 9694 bytes --]

#! /bin/sh
#
#

TESTDIR="/tmp/transmute-test"
TESTFILE="$TESTDIR"/file
TESTSUBDIR="$TESTDIR"/subdir
TESTSUB2DIR="$TESTSUBDIR"/subdir
TESTSUB3DIR="$TESTSUB2DIR"/subdir
USERID=`/usr/bin/id -u`
LOAD=/sys/fs/smackfs/load2

if [ "$USERID" != "0" ]
then
	echo User ID $USERID is not root.
	exit 1
fi

notroot="cschaufler"
# NOTROOT=`tail -1 /etc/passwd | sed -e 's/:.*//'`
# echo Using '"'$NOTROOT'"' as a test user.

RUNAS=`cat /proc/self/attr/current`

rm -rf $TESTDIR
mkdir $TESTDIR
grep `cat /proc/self/attr/current` $LOAD
echo Dir: `attr -q -S -g SMACK64 $TESTDIR 2> /dev/null` `ls -id $TESTDIR` `attr -q -S -g SMACK64TRANSMUTE $TESTDIR 2> /dev/null`

#
# Simple set/list/get tests
#
TLABEL=`attr -q -S -g SMACK64TRANSMUTE $TESTDIR 2> /dev/null`
if [ "x""$TLABEL" != "x" ]
then
	echo Initial transmute label is unexpectedly '"'"$TLABEL"'"'.
	exit 1
fi

attr -q -S -s SMACK64TRANSMUTE -V WILL $TESTDIR 2> /dev/null
TLABEL=`attr -q -S -g SMACK64TRANSMUTE $TESTDIR 2> /dev/null`
if [ "x""$TLABEL" != "x" ]
then
	echo Setting transmute label should not have gotten '"'"$TLABEL"'"'.
	exit 1
fi

TLIST=`attr -q -S -l $TESTDIR | grep TRANSMUTE`
if [ "x""$TLIST" != "x" ]
then
	echo Setting transmute label listed incorrectly as '"'"$TLIST"'"'.
	exit 1
fi

attr -q -S -s SMACK64TRANSMUTE -V TRUE $TESTDIR 2> /dev/null
TLABEL=`attr -q -S -g SMACK64TRANSMUTE $TESTDIR 2> /dev/null`
if [ "x""$TLABEL" != "xTRUE" ]
then
	echo Setting transmute label should not have gotten '"'"$TLABEL"'"'.
	exit 1
fi

TLIST=`attr -q -S -l $TESTDIR | grep TRANSMUTE`
if [ "x""$TLIST" != "xSMACK64TRANSMUTE" ]
then
	echo Setting transmute label listed incorrectly as '"'"$TLIST"'"'.
	exit 1
fi

attr -q -S -r SMACK64TRANSMUTE $TESTDIR 2> /dev/null
TLABEL=`attr -q -S -g SMACK64TRANSMUTE $TESTDIR 2> /dev/null`
if [ "x""$TLABEL" != "x" ]
then
	echo Removing transmute label left '"'"$TLABEL"'"' behind.
	exit 1
fi

rm -rf $TESTDIR

#
# Rule setting tests
#
#          1         2         3         4         5         6
# 1234567890123456789012345678901234567890123456789012345678901234567890
# subject-label.......... object-label........... rwxat
#

#                 1         2         3
#        123456789012345678901234567890
SUBJECT="Snap                   "
SUBNAME="Snap"

#                1         2         3
#       123456789012345678901234567890
OBJECT="Crackle                "
OBNAME="Crackle"

OLDRULE=`grep '^'"$SUBNAME"' '"$OBNAME" $LOAD`

echo -n "$SUBJECT"' '"$OBJECT"' ''rwxa' > $LOAD
RULE=`grep '^'"$SUBNAME"' '"$OBNAME" $LOAD`
if [ "x""$RULE" != "x""$SUBNAME"' '"$OBNAME"' rwxa' ]
then
	echo Setting rule without '"'t'"' unexpectedly '"'"$RULE"'"'.
	exit 1
fi

echo -n "$SUBJECT"' '"$OBJECT"' ''rwxat' > $LOAD
RULE=`grep '^'"$SUBNAME"' '"$OBNAME" $LOAD`
if [ "x""$RULE" != "x""$SUBNAME"' '"$OBNAME"' rwxat' ]
then
	echo Setting rule with '"'t'"' unexpectedly '"'"$RULE"'"'.
	exit 1
fi

#
# Verify correct label behavior with neither a transmute
# directory nor a transmute rule.
#

rm -rf $TESTDIR
mkdir $TESTDIR
grep `cat /proc/self/attr/current` $LOAD
echo Dir: `attr -q -S -g SMACK64 $TESTDIR 2> /dev/null` `ls -id $TESTDIR` `attr -q -S -g SMACK64TRANSMUTE $TESTDIR 2> /dev/null`
chmod 777 $TESTDIR
attr -q -S -s SMACK64 -V $OBNAME $TESTDIR
echo -n "$SUBJECT"' '"$OBJECT"' ''rwxa' > $LOAD

echo "$SUBNAME" > /proc/self/attr/current
su - $NOTROOT -c "date > $TESTFILE"
echo "$RUNAS" > /proc/self/attr/current
GOT=`attr -q -S -g SMACK64 $TESTFILE`

if [ 'x'"$SUBNAME" != 'x'"$GOT" ]
then
	echo Expected '"'$SUBNAME'"' but got '"'$GOT'"'.
	exit 1
fi

#
# Verify correct label behavior with a transmute
# directory but not a transmute rule.
#

rm -rf $TESTDIR
mkdir $TESTDIR
grep `cat /proc/self/attr/current` $LOAD
echo Dir: `attr -q -S -g SMACK64 $TESTDIR 2> /dev/null` `ls -id $TESTDIR` `attr -q -S -g SMACK64TRANSMUTE $TESTDIR 2> /dev/null`
chmod 777 $TESTDIR
attr -q -S -s SMACK64 -V $OBNAME $TESTDIR
attr -q -S -s SMACK64TRANSMUTE -V TRUE $TESTDIR
echo -n "$SUBJECT"' '"$OBJECT"' ''rwxa' > $LOAD

echo "$SUBNAME" > /proc/self/attr/current
su - $NOTROOT -c "date > $TESTFILE"
echo "$RUNAS" > /proc/self/attr/current
GOT=`attr -q -S -g SMACK64 $TESTFILE`

if [ 'x'"$SUBNAME" != 'x'"$GOT" ]
then
	echo Expected '"'$SUBNAME'"' but got '"'$GOT'"'.
	exit 1
fi

#
# Verify correct label behavior without  a transmute
# directory but with a transmute rule.
#

rm -rf $TESTDIR
mkdir $TESTDIR
grep `cat /proc/self/attr/current` $LOAD
echo Dir: `attr -q -S -g SMACK64 $TESTDIR 2> /dev/null` `ls -id $TESTDIR` `attr -q -S -g SMACK64TRANSMUTE $TESTDIR 2> /dev/null`
chmod 777 $TESTDIR
attr -q -S -s SMACK64 -V $OBNAME $TESTDIR
echo -n "$SUBJECT"' '"$OBJECT"' ''rwxat' > $LOAD

echo "$SUBNAME" > /proc/self/attr/current
su - $NOTROOT -c "date > $TESTFILE"
echo "$RUNAS" > /proc/self/attr/current
GOT=`attr -q -S -g SMACK64 $TESTFILE`

if [ 'x'"$SUBNAME" != 'x'"$GOT" ]
then
	echo Expected '"'$SUBNAME'"' but got '"'$GOT'"'.
	exit 1
fi

#
# Verify correct label behavior with a transmute
# directory and a transmute rule.
#

rm -rf $TESTDIR
mkdir $TESTDIR
grep `cat /proc/self/attr/current` $LOAD
echo Dir: `attr -q -S -g SMACK64 $TESTDIR 2> /dev/null` `ls -id $TESTDIR` `attr -q -S -g SMACK64TRANSMUTE $TESTDIR 2> /dev/null`
chmod 777 $TESTDIR
attr -q -S -s SMACK64 -V $OBNAME $TESTDIR
attr -q -S -s SMACK64TRANSMUTE -V TRUE $TESTDIR
grep `cat /proc/self/attr/current` $LOAD
echo Dir: `attr -q -S -g SMACK64 $TESTDIR 2> /dev/null` `ls -id $TESTDIR` `attr -q -S -g SMACK64TRANSMUTE $TESTDIR 2> /dev/null`
echo -n "$SUBJECT"' '"$OBJECT"' ''rwxat' > $LOAD

echo "$SUBNAME" > /proc/self/attr/current
su - $NOTROOT -c "date > $TESTFILE"
echo "$RUNAS" > /proc/self/attr/current
GOT=`attr -q -S -g SMACK64 $TESTFILE`

if [ 'x'"$OBNAME" != 'x'"$GOT" ]
then
	echo Expected '"'$OBNAME'"' but got '"'$GOT'"'.
	attr -l -S $TESTDIR
	attr -S -g SMACK64 $TESTFILE
	grep '^'"$SUBNAME"' '"$OBNAME" $LOAD
	exit 1
else
	echo Expected '"'$OBNAME'"' and got '"'$GOT'"' successfully.
fi

#
# Verify correct label behavior with a transmute
# directory and subdirectories
#

echo "$SUBNAME" > /proc/self/attr/current
rm -rf $TESTSUBDIR
su - $NOTROOT -c "mkdir $TESTSUBDIR"
grep `cat /proc/self/attr/current` $LOAD
echo Dir: `attr -q -S -g SMACK64 $TESTDIR 2> /dev/null` `ls -id $TESTDIR` `attr -q -S -g SMACK64TRANSMUTE $TESTDIR 2> /dev/null`
echo Dir: `attr -q -S -g SMACK64 $TESTSUBDIR 2> /dev/null` `ls -id $TESTSUBDIR` `attr -q -S -g SMACK64TRANSMUTE $TESTSUBDIR 2> /dev/null`
echo "$RUNAS" > /proc/self/attr/current
GOT=`attr -q -S -g SMACK64 $TESTSUBDIR`
if [ 'x'"$OBNAME" != 'x'"$GOT" ]
then
	echo Expected '"'$OBNAME'"' but got '"'$GOT'"'.
else
	echo Expected '"'$OBNAME'"' and got '"'$GOT'"' successfully.
fi

echo "$SUBNAME" > /proc/self/attr/current
rm -rf $TESTSUB2DIR
su - $NOTROOT -c "mkdir $TESTSUB2DIR"
grep `cat /proc/self/attr/current` $LOAD
echo Dir: `attr -q -S -g SMACK64 $TESTDIR 2> /dev/null` `ls -id $TESTDIR` `attr -q -S -g SMACK64TRANSMUTE $TESTDIR 2> /dev/null`
echo Dir: `attr -q -S -g SMACK64 $TESTSUBDIR 2> /dev/null` `ls -id $TESTSUBDIR` `attr -q -S -g SMACK64TRANSMUTE $TESTSUBDIR 2> /dev/null`
echo Dir: `attr -q -S -g SMACK64 $TESTSUB2DIR 2> /dev/null` `ls -id $TESTSUB2DIR` `attr -q -S -g SMACK64TRANSMUTE $TESTSUB2DIR 2> /dev/null`
echo "$RUNAS" > /proc/self/attr/current
GOT=`attr -q -S -g SMACK64 $TESTSUB2DIR`
if [ 'x'"$OBNAME" != 'x'"$GOT" ]
then
	echo Expected '"'$OBNAME'"' but got '"'$GOT'"'.
else
	echo Expected '"'$OBNAME'"' and got '"'$GOT'"' successfully.
fi

echo "$SUBNAME" > /proc/self/attr/current
rm -rf $TESTSUB3DIR
su - $NOTROOT -c "mkdir $TESTSUB3DIR"
grep `cat /proc/self/attr/current` $LOAD
echo Dir: `attr -q -S -g SMACK64 $TESTDIR 2> /dev/null` `ls -id $TESTDIR` `attr -q -S -g SMACK64TRANSMUTE $TESTDIR 2> /dev/null`
echo Dir: `attr -q -S -g SMACK64 $TESTSUBDIR 2> /dev/null` `ls -id $TESTSUBDIR` `attr -q -S -g SMACK64TRANSMUTE $TESTSUBDIR 2> /dev/null`
echo Dir: `attr -q -S -g SMACK64 $TESTSUB2DIR 2> /dev/null` `ls -id $TESTSUB2DIR` `attr -q -S -g SMACK64TRANSMUTE $TESTSUB2DIR 2> /dev/null`
echo Dir: `attr -q -S -g SMACK64 $TESTSUB3DIR 2> /dev/null` `ls -id $TESTSUB3DIR` `attr -q -S -g SMACK64TRANSMUTE $TESTSUB3DIR 2> /dev/null`
echo "$RUNAS" > /proc/self/attr/current
GOT=`attr -q -S -g SMACK64 $TESTSUB3DIR`
if [ 'x'"$OBNAME" != 'x'"$GOT" ]
then
	echo Expected '"'$OBNAME'"' but got '"'$GOT'"'.
else
	echo Expected '"'$OBNAME'"' and got '"'$GOT'"' successfully.
fi

#
# test SMACK64TRANSMUTE removal
#
echo test SMACK64TRANSMUTE removal

attr -S -g SMACK64TRANSMUTE $TESTSUB3DIR
rm -rf $TESTSUB3DIR
attr -S -r SMACK64TRANSMUTE $TESTSUB2DIR
su - $NOTROOT -c "mkdir $TESTSUB3DIR"
attr -S -g SMACK64TRANSMUTE $TESTSUB2DIR
attr -S -g SMACK64TRANSMUTE $TESTSUB3DIR

rm -rf $TESTDIR
#
# Restore old label rule.
#
if [ "x""$OLDRULE" != "x" ]
then
	RAWOLDMODE=`echo $OLDRULE | sed -e 's/.* //'`

	I=`echo $RAWOLDMODE | grep 'r'`
	if [ "x""$I" = "x" ]
	then
		OLDMODE="-"
	else
		OLDMODE="r"
	fi
	I=`echo $RAWOLDMODE | grep 'w'`
	if [ "x""$I" = "x" ]
	then
		OLDMODE="$OLDMODE""-"
	else
		OLDMODE="$OLDMODE""w"
	fi
	I=`echo $RAWOLDMODE | grep 'x'`
	if [ "x""$I" = "x" ]
	then
		OLDMODE="$OLDMODE""-"
	else
		OLDMODE="$OLDMODE""x"
	fi
	I=`echo $RAWOLDMODE | grep 'a'`
	if [ "x""$I" = "x" ]
	then
		OLDMODE="$OLDMODE""-"
	else
		OLDMODE="$OLDMODE""a"
	fi
	I=`echo $RAWOLDMODE | grep 't'`
	if [ "x""$I" = "x" ]
	then
		OLDMODE="$OLDMODE""-"
	else
		OLDMODE="$OLDMODE""t"
	fi

	echo -n "$SUBJECT"' '"$OBJECT"' '"$OLDMODE" > $LOAD
	# echo Rule reset to '"'"$SUBNAME"' '"$OBNAME"' '"$OLDMODE"'"'
else
	echo -n "$SUBJECT"' '"$OBJECT"' ''-----' > $LOAD
	# echo Rule reset to '"'"$SUBNAME"' '"$OBNAME"' '"-----"'"'
fi

echo "$RUNAS" > /proc/self/attr/current
rm -rf $TESTDIR

exit 0

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH] Smack modifications for: security: Allow all LSMs to provide xattrs for inode_init_security hook
  2023-04-18 16:02                       ` Casey Schaufler
@ 2023-04-19 13:46                         ` Roberto Sassu
  2023-04-19 19:25                           ` Mengchi Cheng
  2023-04-19 21:00                           ` Casey Schaufler
  0 siblings, 2 replies; 44+ messages in thread
From: Roberto Sassu @ 2023-04-19 13:46 UTC (permalink / raw)
  To: Casey Schaufler, zohar, dmitry.kasatkin, paul, jmorris, serge,
	stephen.smalley.work, eparis
  Cc: reiserfs-devel, linux-kernel, linux-integrity,
	linux-security-module, selinux, bpf, kpsingh, keescook,
	nicolas.bouchinet, Roberto Sassu, Mengchi Cheng, miklos,
	linux-unionfs, kamatam, yoonjaeh

On Tue, 2023-04-18 at 09:02 -0700, Casey Schaufler wrote:
> On 4/18/2023 12:05 AM, Roberto Sassu wrote:
> > On Mon, 2023-04-17 at 09:41 -0700, Casey Schaufler wrote:
> > > On 4/13/2023 12:11 AM, Roberto Sassu wrote:
> > > > On Wed, 2023-04-12 at 13:29 -0700, Casey Schaufler wrote:
> > > > > On 4/12/2023 12:22 AM, Roberto Sassu wrote:
> > > > > > On Tue, 2023-04-11 at 10:54 -0700, Casey Schaufler wrote:
> > > > > > > On 4/11/2023 10:23 AM, Roberto Sassu wrote:
> > > > > > > > From: Roberto Sassu <roberto.sassu@huawei.com>
> > > > > > > > 
> > > > > > > > Very very quick modification. Not tested.
> > > > > > > > 
> > > > > > > > Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
> > > > > > > > ---
> > > > > > > >  security/smack/smack.h     |  2 +-
> > > > > > > >  security/smack/smack_lsm.c | 42 ++++++++++++++++++++------------------
> > > > > > > >  2 files changed, 23 insertions(+), 21 deletions(-)
> > > > > > > > 
> > > > > > > > diff --git a/security/smack/smack.h b/security/smack/smack.h
> > > > > > > > index e2239be7bd6..f00c8498c60 100644
> > > > > > > > --- a/security/smack/smack.h
> > > > > > > > +++ b/security/smack/smack.h
> > > > > > > > @@ -127,7 +127,7 @@ struct task_smack {
> > > > > > > >  
> > > > > > > >  #define	SMK_INODE_INSTANT	0x01	/* inode is instantiated */
> > > > > > > >  #define	SMK_INODE_TRANSMUTE	0x02	/* directory is transmuting */
> > > > > > > > -#define	SMK_INODE_CHANGED	0x04	/* smack was transmuted */
> > > > > > > > +#define	SMK_INODE_CHANGED	0x04	/* smack was transmuted (unused) */
> > > > > > > See below ...
> > > > > > > 
> > > > > > > >  #define	SMK_INODE_IMPURE	0x08	/* involved in an impure transaction */
> > > > > > > >  
> > > > > > > >  /*
> > > > > > > > diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
> > > > > > > > index 8392983334b..b43820bdbd0 100644
> > > > > > > > --- a/security/smack/smack_lsm.c
> > > > > > > > +++ b/security/smack/smack_lsm.c
> > > > > > > > @@ -54,12 +54,12 @@
> > > > > > > >  
> > > > > > > >  /*
> > > > > > > >   * Smack uses multiple xattrs.
> > > > > > > > - * SMACK64 - for access control, SMACK64EXEC - label for the program,
> > > > > > > > - * SMACK64MMAP - controls library loading,
> > > > > > > > + * SMACK64 - for access control,
> > > > > > > >   * SMACK64TRANSMUTE - label initialization,
> > > > > > > > - * Not saved on files - SMACK64IPIN and SMACK64IPOUT
> > > > > > > > + * Not saved on files - SMACK64IPIN and SMACK64IPOUT,
> > > > > > > > + * Must be set explicitly - SMACK64EXEC and SMACK64MMAP
> > > > > > > >   */
> > > > > > > > -#define SMACK_INODE_INIT_XATTRS 4
> > > > > > > > +#define SMACK_INODE_INIT_XATTRS 2
> > > > > > > >  
> > > > > > > >  #ifdef SMACK_IPV6_PORT_LABELING
> > > > > > > >  static DEFINE_MUTEX(smack_ipv6_lock);
> > > > > > > > @@ -957,11 +957,11 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
> > > > > > > >  				     const struct qstr *qstr,
> > > > > > > >  				     struct xattr *xattrs, int *xattr_count)
> > > > > > > >  {
> > > > > > > > -	struct inode_smack *issp = smack_inode(inode);
> > > > > > > >  	struct smack_known *skp = smk_of_current();
> > > > > > > >  	struct smack_known *isp = smk_of_inode(inode);
> > > > > > > >  	struct smack_known *dsp = smk_of_inode(dir);
> > > > > > > >  	struct xattr *xattr = lsm_get_xattr_slot(xattrs, xattr_count);
> > > > > > > > +	struct xattr *xattr2;
> > > > > > > I'm going to channel Paul and suggest this be xattr_transmute instead of xattr2.
> > > > > > > It also looks like it could move to be declared in the if clause.
> > > > > > > 
> > > > > > > >  	int may;
> > > > > > > >  
> > > > > > > >  	if (xattr) {
> > > > > > > > @@ -979,7 +979,17 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
> > > > > > > >  		if (may > 0 && ((may & MAY_TRANSMUTE) != 0) &&
> > > > > > > >  		    smk_inode_transmutable(dir)) {
> > > > > > > >  			isp = dsp;
> > > > > > > > -			issp->smk_flags |= SMK_INODE_CHANGED;
> > > > > > > I think you need to keep this. More below.
> > > > > > > 
> > > > > > > > +			xattr2 = lsm_get_xattr_slot(xattrs, xattr_count);
> > > > > > > > +			if (xattr2) {
> > > > > > > > +				xattr2->value = kmemdup(TRANS_TRUE,
> > > > > > > > +							TRANS_TRUE_SIZE,
> > > > > > > > +							GFP_NOFS);
> > > > > > > > +				if (xattr2->value == NULL)
> > > > > > > > +					return -ENOMEM;
> > > > > > > > +
> > > > > > > > +				xattr2->value_len = TRANS_TRUE_SIZE;
> > > > > > > > +				xattr2->name = XATTR_NAME_SMACKTRANSMUTE;
> > > > > > > > +			}
> > > > > > > >  		}
> > > > > > > >  
> > > > > > > >  		xattr->value = kstrdup(isp->smk_known, GFP_NOFS);
> > > > > > > > @@ -3512,20 +3522,12 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
> > > > > > > >  			 * If there is a transmute attribute on the
> > > > > > > >  			 * directory mark the inode.
> > > > > > > >  			 */
> > > > > > > > -			if (isp->smk_flags & SMK_INODE_CHANGED) {
> > > > > > > > -				isp->smk_flags &= ~SMK_INODE_CHANGED;
> > > > > > > > -				rc = __vfs_setxattr(&nop_mnt_idmap, dp, inode,
> > > > > > > > -					XATTR_NAME_SMACKTRANSMUTE,
> > > > > > > > -					TRANS_TRUE, TRANS_TRUE_SIZE,
> > > > > > > > -					0);
> > > > > > > > -			} else {
> > > > > > > > -				rc = __vfs_getxattr(dp, inode,
> > > > > > > > -					XATTR_NAME_SMACKTRANSMUTE, trattr,
> > > > > > > > -					TRANS_TRUE_SIZE);
> > > > > > > > -				if (rc >= 0 && strncmp(trattr, TRANS_TRUE,
> > > > > > > > -						       TRANS_TRUE_SIZE) != 0)
> > > > > > > > -					rc = -EINVAL;
> > > > > > > > -			}
> > > > > > > > +			rc = __vfs_getxattr(dp, inode,
> > > > > > > > +					    XATTR_NAME_SMACKTRANSMUTE, trattr,
> > > > > > > > +					    TRANS_TRUE_SIZE);
> > > > > > > > +			if (rc >= 0 && strncmp(trattr, TRANS_TRUE,
> > > > > > > > +					       TRANS_TRUE_SIZE) != 0)
> > > > > > > > +				rc = -EINVAL;
> > > > > > > Where is the SMACK64_TRANSMUTE attribute going to get set on the file?
> > > > > > > It's not going to get set in smack_init_inode_security(). The inode will
> > > > > > Isn't that the purpose of the inode_init_security hook?
> > > > > No. It initializes the in-memory inode. 
> > > > I hope I'm not mistaken here...
> > > > 
> > > > I make a small example. Filesystems call
> > > > security_inode_init_security(). Ext4 does:
> > > > 
> > > > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/fs/ext4/xattr_security.c?h=v6.3-rc6#n54
> > > > 
> > > > security_inode_init_security() allocates new_xattrs. Each LSM fills
> > > > new_xattrs. At the end of the loop, if there is at least one xattr
> > > > filled, the initxattrs() callback passed by the caller of
> > > > security_inode_init_security() is called.
> > > > 
> > > > The ext4 initxattrs() callback is:
> > > > 
> > > > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/fs/ext4/xattr_security.c?h=v6.3-rc6#n35
> > > > 
> > > > which scans the xattr array and, for each xattr,
> > > > calls ext4_xattr_set_handle().
> > > > 
> > > > Maybe I'm overlooking it, but ext4_xattr_set_handle() is setting xattrs
> > > > on the disk. Am I wrong?
> > > Yes, you're wrong. I tried your change, and the SMACK64_TRANSMUTE isn't
> > > set on the sub-directory when it's created. The __vfs_setxattr() call really
> > > is necessary. 
> > Could you please also check if there is any change with this fix:
> > 
> > Replace:
> > 
> > 	xattr2->name = XATTR_NAME_SMACKTRANSMUTE;
> > 
> > with:
> > 
> > 	xattr2->name = XATTR_SMACK_TRANSMUTE;
> > 
> > Thanks
> 
> Unless I'm missing something really obvious there's no way that any
> of the evm/ima changes would obviate the need for the __vfs_setxattr() call.
> It's real easy to verify correct behavior, see the attached script.
> (you'll want to change the "notroot" value to a user on your system)

I got some errors during xattr removal, so not sure if my patch was
working properly or not (it happened also without it, didn't
investigate more).

However, I saw another discussion related to transmute:

https://lore.kernel.org/linux-security-module/20230419002338.566487-1-mengcc@amazon.com/

I add the people in CC.

The steps described were so easy to understand and executed, I tried
without and with overlayfs.

Without:

# echo "_ system rwxatl" > /sys/fs/smackfs/load2
# mkdir /data
# chsmack -a "system" /data
# chsmack -t /data
# mkdir -p /data/dir1/dir2
# chsmack /data/dir1
/data/dir1 access="system" transmute="TRUE"
# chsmack /data/dir1/dir2
/data/dir1/dir2 access="system" transmute="TRUE"

It seems to work, right?

With overlay fs it didn't work, same result as the one Mengchi
reported. Since Mengchi's solution was to set SMK_INODE_CHANGED, and I
want to get rid of it, I thought to investigate more.

Looking at smack_dentry_create_files_as(), I see that the label of the
process is overwritten with the label of the transmuting directory.

That causes smack_inode_init_security() to lookup the transmuting rule
on the overridden credential, and not on the original one.

In the example above, it means that, when overlayfs is creating the new
inode, the label of the process is system, not _. So no transmute
permission, and also the xattr will not be added, as observed by
Mengchi.

Hopefully I undertood the code, so in this particular case we would not
need to override the label of the process in smack_dentry_create_files_
as().

If you see smack_inode_init_security():

	struct smack_known *skp = smk_of_current();
	struct smack_known *isp = smk_of_inode(inode);
	struct smack_known *dsp = smk_of_inode(dir);

[...]

		if (may > 0 && ((may & MAY_TRANSMUTE) != 0) &&
		    smk_inode_transmutable(dir)) {
			isp = dsp;
[...]

		xattr->value = kstrdup(isp->smk_known, GFP_NOFS);

This code is telling, if there is a transmute rule, and the directory
is transmuting, set the label of the new inode to the label of the
directory. That should be already the result that we wanted to obtain.

The current code should have been doing it by overriding the label of
the process in smack_dentry_create_files_as() with the label of the
parent directory, and letting the inode being created with the
overridden label of the process. The transmute xattr is not set due to
the problem described above.

So, as a quick test, I kept this patch with the change to xattr2->name, 
and skipped the label override in smack_dentry_create_files_as(). It
worked, I get the same result as without overlayfs. Wondering if the
process label override is necessary in other cases.

Roberto

> > Roberto
> > 
> > > > Thanks
> > > > 
> > > > Roberto
> > > > 
> > > > > > After all LSMs provide one or multiple xattrs, xattrs are going to be
> > > > > > written to the disk with the initxattr() callback of filesystems.
> > > > > > 
> > > > > > There is a small mistake above (XATTR_SMACK_TRANSMUTE instead
> > > > > > of XATTR_NAME_SMACKTRANSMUTE, as we are providing just the suffix).
> > > > > but I'm pretty sure the __vfs_setxattr() call is necessary to get
> > > > > the attribute written out. With your change the in-memory inode will
> > > > > get the attribute, but if you reboot it won't be on the directory.
> > > > > 
> > > > > > 95 Passed, 0 Failed, 100% Success rate
> > > > > > 
> > > > > > There was a test failing in dir-transmute.sh, before I fixed the xattr
> > > > > > name.
> > > > > > 
> > > > > > Thanks
> > > > > > 
> > > > > > Roberto
> > > > > > 
> > > > > > > know it's transmuting, but it won't get to disk without the __vfs_setxattr()
> > > > > > > here in smack_d_instantiate(). Now, it's been a long time since that code
> > > > > > > was written, so I could be wrong, but I'm pretty sure about that.
> > > > > > > 
> > > > > > > I think that you should be fine with the changes in smack_init_inode_security(),
> > > > > > > and leaving smack_d_instantiate() untouched. 
> > > > > > > 
> > > > > > > >  			if (rc >= 0)
> > > > > > > >  				transflag = SMK_INODE_TRANSMUTE;
> > > > > > > >  		}


^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH] Smack modifications for: security: Allow all LSMs to provide xattrs for inode_init_security hook
  2023-04-19 13:46                         ` Roberto Sassu
@ 2023-04-19 19:25                           ` Mengchi Cheng
  2023-04-20  8:48                             ` Roberto Sassu
  2023-04-19 21:00                           ` Casey Schaufler
  1 sibling, 1 reply; 44+ messages in thread
From: Mengchi Cheng @ 2023-04-19 19:25 UTC (permalink / raw)
  To: roberto.sassu
  Cc: bpf, casey, dmitry.kasatkin, eparis, jmorris, kamatam, keescook,
	kpsingh, linux-integrity, linux-kernel, linux-security-module,
	linux-unionfs, mengcc, miklos, nicolas.bouchinet, paul,
	reiserfs-devel, roberto.sassu, selinux, serge,
	stephen.smalley.work, yoonjaeh, zohar

> 
> I got some errors during xattr removal, so not sure if my patch was
> working properly or not (it happened also without it, didn't
> investigate more).
> 
> However, I saw another discussion related to transmute:
> 
> https://lore.kernel.org/linux-security-module/20230419002338.566487-1-mengcc@amazon.com/
> 
> I add the people in CC.
> 
> The steps described were so easy to understand and executed, I tried
> without and with overlayfs.
> 
> Without:
> 
> # echo "_ system rwxatl" > /sys/fs/smackfs/load2
> # mkdir /data
> # chsmack -a "system" /data
> # chsmack -t /data
> # mkdir -p /data/dir1/dir2
> # chsmack /data/dir1
> /data/dir1 access="system" transmute="TRUE"
> # chsmack /data/dir1/dir2
> /data/dir1/dir2 access="system" transmute="TRUE"
> 
> It seems to work, right?
> 
> With overlay fs it didn't work, same result as the one Mengchi
> reported. Since Mengchi's solution was to set SMK_INODE_CHANGED, and I
> want to get rid of it, I thought to investigate more.
> 
> Looking at smack_dentry_create_files_as(), I see that the label of the
> process is overwritten with the label of the transmuting directory.
> 
> That causes smack_inode_init_security() to lookup the transmuting rule
> on the overridden credential, and not on the original one.
> 
> In the example above, it means that, when overlayfs is creating the new
> inode, the label of the process is system, not _. So no transmute
> permission, and also the xattr will not be added, as observed by
> Mengchi.
> 
> Hopefully I undertood the code, so in this particular case we would not
> need to override the label of the process in smack_dentry_create_files_
> as().
> 
> If you see smack_inode_init_security():
> 
> 	struct smack_known *skp = smk_of_current();
> 	struct smack_known *isp = smk_of_inode(inode);
> 	struct smack_known *dsp = smk_of_inode(dir);
> 
> [...]
> 
> 		if (may > 0 && ((may & MAY_TRANSMUTE) != 0) &&
> 		    smk_inode_transmutable(dir)) {
> 			isp = dsp;
> [...]
> 
> 		xattr->value = kstrdup(isp->smk_known, GFP_NOFS);
> 
> This code is telling, if there is a transmute rule, and the directory
> is transmuting, set the label of the new inode to the label of the
> directory. That should be already the result that we wanted to obtain.
> 
> The current code should have been doing it by overriding the label of
> the process in smack_dentry_create_files_as() with the label of the
> parent directory, and letting the inode being created with the
> overridden label of the process. The transmute xattr is not set due to
> the problem described above.
> 
> So, as a quick test, I kept this patch with the change to xattr2->name, 
> and skipped the label override in smack_dentry_create_files_as(). It
> worked, I get the same result as without overlayfs. Wondering if the
> process label override is necessary in other cases.

If I understand correctly, removing the if block below is what you suggested.

diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index cfcbb748da25..a867288e9de9 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -4769,8 +4769,8 @@ static int smack_dentry_create_files_as(struct dentry *dentry, int mode,
                 * providing access is transmuting use the containing
                 * directory label instead of the process label.
                 */
-               if (may > 0 && (may & MAY_TRANSMUTE))
-                       ntsp->smk_task = isp->smk_inode;
+//             if (may > 0 && (may & MAY_TRANSMUTE))
+//                     ntsp->smk_task = isp->smk_inode;
        }
        return 0;
 }

This way will have issue in the following situation on the vanila kernel.
data in the lowerdir has "_" label before overlay and dir1 is already
created in the lowerdir.
# chsmack /data
/data access="_"
# chsmack /data/dir1
/data/dir1 access="system" transmute="TRUE"
Apply overlay on data directory and set the smack rule in the same way.
data has the same smack label.
# chsmack /data
/data access="system" transmute="TRUE"
After that, remove dir1 and mkdir dir1 again. dir1 did not get the correct
label.
# rm -r /data/dir1
# mkdir -p /data/dir1
# chsmack /data/dir1
/data/dir1 access="_"

Since I am not very familiar your change. Could you help check with your
patch will this issue also happen? 


Best,
Mengchi

>  
> Roberto

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* Re: [PATCH] Smack modifications for: security: Allow all LSMs to provide xattrs for inode_init_security hook
  2023-04-19 13:46                         ` Roberto Sassu
  2023-04-19 19:25                           ` Mengchi Cheng
@ 2023-04-19 21:00                           ` Casey Schaufler
  2023-04-20  8:50                             ` Roberto Sassu
  1 sibling, 1 reply; 44+ messages in thread
From: Casey Schaufler @ 2023-04-19 21:00 UTC (permalink / raw)
  To: Roberto Sassu, zohar, dmitry.kasatkin, paul, jmorris, serge,
	stephen.smalley.work, eparis
  Cc: reiserfs-devel, linux-kernel, linux-integrity,
	linux-security-module, selinux, bpf, kpsingh, keescook,
	nicolas.bouchinet, Roberto Sassu, Mengchi Cheng, miklos,
	linux-unionfs, kamatam, yoonjaeh, Casey Schaufler

On 4/19/2023 6:46 AM, Roberto Sassu wrote:
> On Tue, 2023-04-18 at 09:02 -0700, Casey Schaufler wrote:
>> On 4/18/2023 12:05 AM, Roberto Sassu wrote:
>>> On Mon, 2023-04-17 at 09:41 -0700, Casey Schaufler wrote:
>>>> On 4/13/2023 12:11 AM, Roberto Sassu wrote:
>>>>> On Wed, 2023-04-12 at 13:29 -0700, Casey Schaufler wrote:
>>>>>> On 4/12/2023 12:22 AM, Roberto Sassu wrote:
>>>>>>> On Tue, 2023-04-11 at 10:54 -0700, Casey Schaufler wrote:
>>>>>>>> On 4/11/2023 10:23 AM, Roberto Sassu wrote:
>>>>>>>>> From: Roberto Sassu <roberto.sassu@huawei.com>
>>>>>>>>>
>>>>>>>>> Very very quick modification. Not tested.
>>>>>>>>>
>>>>>>>>> Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
>>>>>>>>> ---
>>>>>>>>>  security/smack/smack.h     |  2 +-
>>>>>>>>>  security/smack/smack_lsm.c | 42 ++++++++++++++++++++------------------
>>>>>>>>>  2 files changed, 23 insertions(+), 21 deletions(-)
>>>>>>>>>
>>>>>>>>> diff --git a/security/smack/smack.h b/security/smack/smack.h
>>>>>>>>> index e2239be7bd6..f00c8498c60 100644
>>>>>>>>> --- a/security/smack/smack.h
>>>>>>>>> +++ b/security/smack/smack.h
>>>>>>>>> @@ -127,7 +127,7 @@ struct task_smack {
>>>>>>>>>  
>>>>>>>>>  #define	SMK_INODE_INSTANT	0x01	/* inode is instantiated */
>>>>>>>>>  #define	SMK_INODE_TRANSMUTE	0x02	/* directory is transmuting */
>>>>>>>>> -#define	SMK_INODE_CHANGED	0x04	/* smack was transmuted */
>>>>>>>>> +#define	SMK_INODE_CHANGED	0x04	/* smack was transmuted (unused) */
>>>>>>>> See below ...
>>>>>>>>
>>>>>>>>>  #define	SMK_INODE_IMPURE	0x08	/* involved in an impure transaction */
>>>>>>>>>  
>>>>>>>>>  /*
>>>>>>>>> diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
>>>>>>>>> index 8392983334b..b43820bdbd0 100644
>>>>>>>>> --- a/security/smack/smack_lsm.c
>>>>>>>>> +++ b/security/smack/smack_lsm.c
>>>>>>>>> @@ -54,12 +54,12 @@
>>>>>>>>>  
>>>>>>>>>  /*
>>>>>>>>>   * Smack uses multiple xattrs.
>>>>>>>>> - * SMACK64 - for access control, SMACK64EXEC - label for the program,
>>>>>>>>> - * SMACK64MMAP - controls library loading,
>>>>>>>>> + * SMACK64 - for access control,
>>>>>>>>>   * SMACK64TRANSMUTE - label initialization,
>>>>>>>>> - * Not saved on files - SMACK64IPIN and SMACK64IPOUT
>>>>>>>>> + * Not saved on files - SMACK64IPIN and SMACK64IPOUT,
>>>>>>>>> + * Must be set explicitly - SMACK64EXEC and SMACK64MMAP
>>>>>>>>>   */
>>>>>>>>> -#define SMACK_INODE_INIT_XATTRS 4
>>>>>>>>> +#define SMACK_INODE_INIT_XATTRS 2
>>>>>>>>>  
>>>>>>>>>  #ifdef SMACK_IPV6_PORT_LABELING
>>>>>>>>>  static DEFINE_MUTEX(smack_ipv6_lock);
>>>>>>>>> @@ -957,11 +957,11 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
>>>>>>>>>  				     const struct qstr *qstr,
>>>>>>>>>  				     struct xattr *xattrs, int *xattr_count)
>>>>>>>>>  {
>>>>>>>>> -	struct inode_smack *issp = smack_inode(inode);
>>>>>>>>>  	struct smack_known *skp = smk_of_current();
>>>>>>>>>  	struct smack_known *isp = smk_of_inode(inode);
>>>>>>>>>  	struct smack_known *dsp = smk_of_inode(dir);
>>>>>>>>>  	struct xattr *xattr = lsm_get_xattr_slot(xattrs, xattr_count);
>>>>>>>>> +	struct xattr *xattr2;
>>>>>>>> I'm going to channel Paul and suggest this be xattr_transmute instead of xattr2.
>>>>>>>> It also looks like it could move to be declared in the if clause.
>>>>>>>>
>>>>>>>>>  	int may;
>>>>>>>>>  
>>>>>>>>>  	if (xattr) {
>>>>>>>>> @@ -979,7 +979,17 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
>>>>>>>>>  		if (may > 0 && ((may & MAY_TRANSMUTE) != 0) &&
>>>>>>>>>  		    smk_inode_transmutable(dir)) {
>>>>>>>>>  			isp = dsp;
>>>>>>>>> -			issp->smk_flags |= SMK_INODE_CHANGED;
>>>>>>>> I think you need to keep this. More below.
>>>>>>>>
>>>>>>>>> +			xattr2 = lsm_get_xattr_slot(xattrs, xattr_count);
>>>>>>>>> +			if (xattr2) {
>>>>>>>>> +				xattr2->value = kmemdup(TRANS_TRUE,
>>>>>>>>> +							TRANS_TRUE_SIZE,
>>>>>>>>> +							GFP_NOFS);
>>>>>>>>> +				if (xattr2->value == NULL)
>>>>>>>>> +					return -ENOMEM;
>>>>>>>>> +
>>>>>>>>> +				xattr2->value_len = TRANS_TRUE_SIZE;
>>>>>>>>> +				xattr2->name = XATTR_NAME_SMACKTRANSMUTE;
>>>>>>>>> +			}
>>>>>>>>>  		}
>>>>>>>>>  
>>>>>>>>>  		xattr->value = kstrdup(isp->smk_known, GFP_NOFS);
>>>>>>>>> @@ -3512,20 +3522,12 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
>>>>>>>>>  			 * If there is a transmute attribute on the
>>>>>>>>>  			 * directory mark the inode.
>>>>>>>>>  			 */
>>>>>>>>> -			if (isp->smk_flags & SMK_INODE_CHANGED) {
>>>>>>>>> -				isp->smk_flags &= ~SMK_INODE_CHANGED;
>>>>>>>>> -				rc = __vfs_setxattr(&nop_mnt_idmap, dp, inode,
>>>>>>>>> -					XATTR_NAME_SMACKTRANSMUTE,
>>>>>>>>> -					TRANS_TRUE, TRANS_TRUE_SIZE,
>>>>>>>>> -					0);
>>>>>>>>> -			} else {
>>>>>>>>> -				rc = __vfs_getxattr(dp, inode,
>>>>>>>>> -					XATTR_NAME_SMACKTRANSMUTE, trattr,
>>>>>>>>> -					TRANS_TRUE_SIZE);
>>>>>>>>> -				if (rc >= 0 && strncmp(trattr, TRANS_TRUE,
>>>>>>>>> -						       TRANS_TRUE_SIZE) != 0)
>>>>>>>>> -					rc = -EINVAL;
>>>>>>>>> -			}
>>>>>>>>> +			rc = __vfs_getxattr(dp, inode,
>>>>>>>>> +					    XATTR_NAME_SMACKTRANSMUTE, trattr,
>>>>>>>>> +					    TRANS_TRUE_SIZE);
>>>>>>>>> +			if (rc >= 0 && strncmp(trattr, TRANS_TRUE,
>>>>>>>>> +					       TRANS_TRUE_SIZE) != 0)
>>>>>>>>> +				rc = -EINVAL;
>>>>>>>> Where is the SMACK64_TRANSMUTE attribute going to get set on the file?
>>>>>>>> It's not going to get set in smack_init_inode_security(). The inode will
>>>>>>> Isn't that the purpose of the inode_init_security hook?
>>>>>> No. It initializes the in-memory inode. 
>>>>> I hope I'm not mistaken here...
>>>>>
>>>>> I make a small example. Filesystems call
>>>>> security_inode_init_security(). Ext4 does:
>>>>>
>>>>> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/fs/ext4/xattr_security.c?h=v6.3-rc6#n54
>>>>>
>>>>> security_inode_init_security() allocates new_xattrs. Each LSM fills
>>>>> new_xattrs. At the end of the loop, if there is at least one xattr
>>>>> filled, the initxattrs() callback passed by the caller of
>>>>> security_inode_init_security() is called.
>>>>>
>>>>> The ext4 initxattrs() callback is:
>>>>>
>>>>> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/fs/ext4/xattr_security.c?h=v6.3-rc6#n35
>>>>>
>>>>> which scans the xattr array and, for each xattr,
>>>>> calls ext4_xattr_set_handle().
>>>>>
>>>>> Maybe I'm overlooking it, but ext4_xattr_set_handle() is setting xattrs
>>>>> on the disk. Am I wrong?
>>>> Yes, you're wrong. I tried your change, and the SMACK64_TRANSMUTE isn't
>>>> set on the sub-directory when it's created. The __vfs_setxattr() call really
>>>> is necessary. 
>>> Could you please also check if there is any change with this fix:
>>>
>>> Replace:
>>>
>>> 	xattr2->name = XATTR_NAME_SMACKTRANSMUTE;
>>>
>>> with:
>>>
>>> 	xattr2->name = XATTR_SMACK_TRANSMUTE;
>>>
>>> Thanks
>> Unless I'm missing something really obvious there's no way that any
>> of the evm/ima changes would obviate the need for the __vfs_setxattr() call.
>> It's real easy to verify correct behavior, see the attached script.
>> (you'll want to change the "notroot" value to a user on your system)
> I got some errors during xattr removal, so not sure if my patch was
> working properly or not (it happened also without it, didn't
> investigate more).

The script is demonstrating that those xattrs don't exist when they
shouldn't, si all is good there.

>
> However, I saw another discussion related to transmute:
>
> https://lore.kernel.org/linux-security-module/20230419002338.566487-1-mengcc@amazon.com/
>
> I add the people in CC.
>
> The steps described were so easy to understand and executed, I tried
> without and with overlayfs.
>
> Without:
>
> # echo "_ system rwxatl" > /sys/fs/smackfs/load2
> # mkdir /data
> # chsmack -a "system" /data
> # chsmack -t /data
> # mkdir -p /data/dir1/dir2
> # chsmack /data/dir1
> /data/dir1 access="system" transmute="TRUE"
> # chsmack /data/dir1/dir2
> /data/dir1/dir2 access="system" transmute="TRUE"
>
> It seems to work, right?
>
> With overlay fs it didn't work, same result as the one Mengchi
> reported. Since Mengchi's solution was to set SMK_INODE_CHANGED, and I
> want to get rid of it, I thought to investigate more.
>
> Looking at smack_dentry_create_files_as(), I see that the label of the
> process is overwritten with the label of the transmuting directory.
>
> That causes smack_inode_init_security() to lookup the transmuting rule
> on the overridden credential, and not on the original one.
>
> In the example above, it means that, when overlayfs is creating the new
> inode, the label of the process is system, not _. So no transmute
> permission, and also the xattr will not be added, as observed by
> Mengchi.

OK, I see that. Looks like the original implementation was poorly
thought out/tested.

> Hopefully I undertood the code, so in this particular case we would not
> need to override the label of the process in smack_dentry_create_files_
> as().
>
> If you see smack_inode_init_security():
>
> 	struct smack_known *skp = smk_of_current();
> 	struct smack_known *isp = smk_of_inode(inode);
> 	struct smack_known *dsp = smk_of_inode(dir);
>
> [...]
>
> 		if (may > 0 && ((may & MAY_TRANSMUTE) != 0) &&
> 		    smk_inode_transmutable(dir)) {
> 			isp = dsp;
> [...]
>
> 		xattr->value = kstrdup(isp->smk_known, GFP_NOFS);
>
> This code is telling, if there is a transmute rule, and the directory
> is transmuting, set the label of the new inode to the label of the
> directory. That should be already the result that we wanted to obtain.
>
> The current code should have been doing it by overriding the label of
> the process in smack_dentry_create_files_as() with the label of the
> parent directory, and letting the inode being created with the
> overridden label of the process. The transmute xattr is not set due to
> the problem described above.

That would explain the observed behavior.

> So, as a quick test, I kept this patch with the change to xattr2->name, 
> and skipped the label override in smack_dentry_create_files_as(). It
> worked, I get the same result as without overlayfs. Wondering if the
> process label override is necessary in other cases.

It's possible. It's been a long time since I've looked at this.
I'm tempted to take a change to make overlayfs work upstream and
then worry about the ima changes. There seems to be a lot more
going on with the ima changes than is obvious from what's in the
Smack code.

>
> Roberto
>
>>> Roberto
>>>
>>>>> Thanks
>>>>>
>>>>> Roberto
>>>>>
>>>>>>> After all LSMs provide one or multiple xattrs, xattrs are going to be
>>>>>>> written to the disk with the initxattr() callback of filesystems.
>>>>>>>
>>>>>>> There is a small mistake above (XATTR_SMACK_TRANSMUTE instead
>>>>>>> of XATTR_NAME_SMACKTRANSMUTE, as we are providing just the suffix).
>>>>>> but I'm pretty sure the __vfs_setxattr() call is necessary to get
>>>>>> the attribute written out. With your change the in-memory inode will
>>>>>> get the attribute, but if you reboot it won't be on the directory.
>>>>>>
>>>>>>> 95 Passed, 0 Failed, 100% Success rate
>>>>>>>
>>>>>>> There was a test failing in dir-transmute.sh, before I fixed the xattr
>>>>>>> name.
>>>>>>>
>>>>>>> Thanks
>>>>>>>
>>>>>>> Roberto
>>>>>>>
>>>>>>>> know it's transmuting, but it won't get to disk without the __vfs_setxattr()
>>>>>>>> here in smack_d_instantiate(). Now, it's been a long time since that code
>>>>>>>> was written, so I could be wrong, but I'm pretty sure about that.
>>>>>>>>
>>>>>>>> I think that you should be fine with the changes in smack_init_inode_security(),
>>>>>>>> and leaving smack_d_instantiate() untouched. 
>>>>>>>>
>>>>>>>>>  			if (rc >= 0)
>>>>>>>>>  				transflag = SMK_INODE_TRANSMUTE;
>>>>>>>>>  		}

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH] Smack modifications for: security: Allow all LSMs to provide xattrs for inode_init_security hook
  2023-04-19 19:25                           ` Mengchi Cheng
@ 2023-04-20  8:48                             ` Roberto Sassu
  2023-05-08 12:29                               ` Roberto Sassu
  0 siblings, 1 reply; 44+ messages in thread
From: Roberto Sassu @ 2023-04-20  8:48 UTC (permalink / raw)
  To: Mengchi Cheng
  Cc: bpf, casey, dmitry.kasatkin, eparis, jmorris, kamatam, keescook,
	kpsingh, linux-integrity, linux-kernel, linux-security-module,
	linux-unionfs, miklos, nicolas.bouchinet, paul, reiserfs-devel,
	roberto.sassu, selinux, serge, stephen.smalley.work, yoonjaeh,
	zohar

On Wed, 2023-04-19 at 12:25 -0700, Mengchi Cheng wrote:
> > I got some errors during xattr removal, so not sure if my patch was
> > working properly or not (it happened also without it, didn't
> > investigate more).
> > 
> > However, I saw another discussion related to transmute:
> > 
> > https://lore.kernel.org/linux-security-module/20230419002338.566487-1-mengcc@amazon.com/
> > 
> > I add the people in CC.
> > 
> > The steps described were so easy to understand and executed, I tried
> > without and with overlayfs.
> > 
> > Without:
> > 
> > # echo "_ system rwxatl" > /sys/fs/smackfs/load2
> > # mkdir /data
> > # chsmack -a "system" /data
> > # chsmack -t /data
> > # mkdir -p /data/dir1/dir2
> > # chsmack /data/dir1
> > /data/dir1 access="system" transmute="TRUE"
> > # chsmack /data/dir1/dir2
> > /data/dir1/dir2 access="system" transmute="TRUE"
> > 
> > It seems to work, right?
> > 
> > With overlay fs it didn't work, same result as the one Mengchi
> > reported. Since Mengchi's solution was to set SMK_INODE_CHANGED, and I
> > want to get rid of it, I thought to investigate more.
> > 
> > Looking at smack_dentry_create_files_as(), I see that the label of the
> > process is overwritten with the label of the transmuting directory.
> > 
> > That causes smack_inode_init_security() to lookup the transmuting rule
> > on the overridden credential, and not on the original one.
> > 
> > In the example above, it means that, when overlayfs is creating the new
> > inode, the label of the process is system, not _. So no transmute
> > permission, and also the xattr will not be added, as observed by
> > Mengchi.
> > 
> > Hopefully I undertood the code, so in this particular case we would not
> > need to override the label of the process in smack_dentry_create_files_
> > as().
> > 
> > If you see smack_inode_init_security():
> > 
> > 	struct smack_known *skp = smk_of_current();
> > 	struct smack_known *isp = smk_of_inode(inode);
> > 	struct smack_known *dsp = smk_of_inode(dir);
> > 
> > [...]
> > 
> > 		if (may > 0 && ((may & MAY_TRANSMUTE) != 0) &&
> > 		    smk_inode_transmutable(dir)) {
> > 			isp = dsp;
> > [...]
> > 
> > 		xattr->value = kstrdup(isp->smk_known, GFP_NOFS);
> > 
> > This code is telling, if there is a transmute rule, and the directory
> > is transmuting, set the label of the new inode to the label of the
> > directory. That should be already the result that we wanted to obtain.
> > 
> > The current code should have been doing it by overriding the label of
> > the process in smack_dentry_create_files_as() with the label of the
> > parent directory, and letting the inode being created with the
> > overridden label of the process. The transmute xattr is not set due to
> > the problem described above.
> > 
> > So, as a quick test, I kept this patch with the change to xattr2->name, 
> > and skipped the label override in smack_dentry_create_files_as(). It
> > worked, I get the same result as without overlayfs. Wondering if the
> > process label override is necessary in other cases.
> 
> If I understand correctly, removing the if block below is what you suggested.

Yes, more or less is what I did.

> diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
> index cfcbb748da25..a867288e9de9 100644
> --- a/security/smack/smack_lsm.c
> +++ b/security/smack/smack_lsm.c
> @@ -4769,8 +4769,8 @@ static int smack_dentry_create_files_as(struct dentry *dentry, int mode,
>                  * providing access is transmuting use the containing
>                  * directory label instead of the process label.
>                  */
> -               if (may > 0 && (may & MAY_TRANSMUTE))
> -                       ntsp->smk_task = isp->smk_inode;
> +//             if (may > 0 && (may & MAY_TRANSMUTE))
> +//                     ntsp->smk_task = isp->smk_inode;
>         }
>         return 0;
>  }
> 
> This way will have issue in the following situation on the vanila kernel.
> data in the lowerdir has "_" label before overlay and dir1 is already
> created in the lowerdir.
> # chsmack /data
> /data access="_"
> # chsmack /data/dir1
> /data/dir1 access="system" transmute="TRUE"
> Apply overlay on data directory and set the smack rule in the same way.
> data has the same smack label.
> # chsmack /data
> /data access="system" transmute="TRUE"

I'm using an older kernel, but I get _ instead of system.

> After that, remove dir1 and mkdir dir1 again. dir1 did not get the correct
> label.
> # rm -r /data/dir1
> # mkdir -p /data/dir1
> # chsmack /data/dir1
> /data/dir1 access="_"

Unfortunately, it cannot work:

Thread 3 hit Breakpoint 1, smack_inode_init_security (...) at security/smack/smack_lsm.c:959
959	{
(gdb) p dir->i_ino
$12 = 9169116
(gdb) p dsp
$13 = (struct smack_known *) 0xffffffff831fc0a0 <smack_known_floor>


ls -i /home/root/data_work/
9169116 work

So, transmuting is decided on the working directory.

If I do:

# chsmack -a system -t /home/root/data_work/work/
# mkdir /data/dir1
# chsmack /data/dir1
/data/dir1 access="system" transmute="TRUE"

I obtain the expected result. However, this problem is due to how overlayfs works:

static int ovl_create_over_whiteout(struct dentry *dentry, struct inode *inode,
				    struct ovl_cattr *cattr)
{

[...]

	newdentry = ovl_create_temp(ofs, workdir, cattr);
	err = PTR_ERR(newdentry);
	if (IS_ERR(newdentry))
		goto out_dput;


The good news seems to be that, once you set the label to the correct
directory, transmuting works with the changes I proposed.

Roberto

> Since I am not very familiar your change. Could you help check with your
> patch will this issue also happen? 
> 
> 
> Best,
> Mengchi
> 
> >  
> > Roberto


^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH] Smack modifications for: security: Allow all LSMs to provide xattrs for inode_init_security hook
  2023-04-19 21:00                           ` Casey Schaufler
@ 2023-04-20  8:50                             ` Roberto Sassu
  2023-04-20 10:44                               ` Mimi Zohar
  0 siblings, 1 reply; 44+ messages in thread
From: Roberto Sassu @ 2023-04-20  8:50 UTC (permalink / raw)
  To: Casey Schaufler, zohar, dmitry.kasatkin, paul, jmorris, serge,
	stephen.smalley.work, eparis
  Cc: reiserfs-devel, linux-kernel, linux-integrity,
	linux-security-module, selinux, bpf, kpsingh, keescook,
	nicolas.bouchinet, Roberto Sassu, Mengchi Cheng, miklos,
	linux-unionfs, kamatam, yoonjaeh

On Wed, 2023-04-19 at 14:00 -0700, Casey Schaufler wrote:
> On 4/19/2023 6:46 AM, Roberto Sassu wrote:
> > On Tue, 2023-04-18 at 09:02 -0700, Casey Schaufler wrote:
> > > On 4/18/2023 12:05 AM, Roberto Sassu wrote:
> > > > On Mon, 2023-04-17 at 09:41 -0700, Casey Schaufler wrote:
> > > > > On 4/13/2023 12:11 AM, Roberto Sassu wrote:
> > > > > > On Wed, 2023-04-12 at 13:29 -0700, Casey Schaufler wrote:
> > > > > > > On 4/12/2023 12:22 AM, Roberto Sassu wrote:
> > > > > > > > On Tue, 2023-04-11 at 10:54 -0700, Casey Schaufler wrote:
> > > > > > > > > On 4/11/2023 10:23 AM, Roberto Sassu wrote:
> > > > > > > > > > From: Roberto Sassu <roberto.sassu@huawei.com>
> > > > > > > > > > 
> > > > > > > > > > Very very quick modification. Not tested.
> > > > > > > > > > 
> > > > > > > > > > Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
> > > > > > > > > > ---
> > > > > > > > > >  security/smack/smack.h     |  2 +-
> > > > > > > > > >  security/smack/smack_lsm.c | 42 ++++++++++++++++++++------------------
> > > > > > > > > >  2 files changed, 23 insertions(+), 21 deletions(-)
> > > > > > > > > > 
> > > > > > > > > > diff --git a/security/smack/smack.h b/security/smack/smack.h
> > > > > > > > > > index e2239be7bd6..f00c8498c60 100644
> > > > > > > > > > --- a/security/smack/smack.h
> > > > > > > > > > +++ b/security/smack/smack.h
> > > > > > > > > > @@ -127,7 +127,7 @@ struct task_smack {
> > > > > > > > > >  
> > > > > > > > > >  #define	SMK_INODE_INSTANT	0x01	/* inode is instantiated */
> > > > > > > > > >  #define	SMK_INODE_TRANSMUTE	0x02	/* directory is transmuting */
> > > > > > > > > > -#define	SMK_INODE_CHANGED	0x04	/* smack was transmuted */
> > > > > > > > > > +#define	SMK_INODE_CHANGED	0x04	/* smack was transmuted (unused) */
> > > > > > > > > See below ...
> > > > > > > > > 
> > > > > > > > > >  #define	SMK_INODE_IMPURE	0x08	/* involved in an impure transaction */
> > > > > > > > > >  
> > > > > > > > > >  /*
> > > > > > > > > > diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
> > > > > > > > > > index 8392983334b..b43820bdbd0 100644
> > > > > > > > > > --- a/security/smack/smack_lsm.c
> > > > > > > > > > +++ b/security/smack/smack_lsm.c
> > > > > > > > > > @@ -54,12 +54,12 @@
> > > > > > > > > >  
> > > > > > > > > >  /*
> > > > > > > > > >   * Smack uses multiple xattrs.
> > > > > > > > > > - * SMACK64 - for access control, SMACK64EXEC - label for the program,
> > > > > > > > > > - * SMACK64MMAP - controls library loading,
> > > > > > > > > > + * SMACK64 - for access control,
> > > > > > > > > >   * SMACK64TRANSMUTE - label initialization,
> > > > > > > > > > - * Not saved on files - SMACK64IPIN and SMACK64IPOUT
> > > > > > > > > > + * Not saved on files - SMACK64IPIN and SMACK64IPOUT,
> > > > > > > > > > + * Must be set explicitly - SMACK64EXEC and SMACK64MMAP
> > > > > > > > > >   */
> > > > > > > > > > -#define SMACK_INODE_INIT_XATTRS 4
> > > > > > > > > > +#define SMACK_INODE_INIT_XATTRS 2
> > > > > > > > > >  
> > > > > > > > > >  #ifdef SMACK_IPV6_PORT_LABELING
> > > > > > > > > >  static DEFINE_MUTEX(smack_ipv6_lock);
> > > > > > > > > > @@ -957,11 +957,11 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
> > > > > > > > > >  				     const struct qstr *qstr,
> > > > > > > > > >  				     struct xattr *xattrs, int *xattr_count)
> > > > > > > > > >  {
> > > > > > > > > > -	struct inode_smack *issp = smack_inode(inode);
> > > > > > > > > >  	struct smack_known *skp = smk_of_current();
> > > > > > > > > >  	struct smack_known *isp = smk_of_inode(inode);
> > > > > > > > > >  	struct smack_known *dsp = smk_of_inode(dir);
> > > > > > > > > >  	struct xattr *xattr = lsm_get_xattr_slot(xattrs, xattr_count);
> > > > > > > > > > +	struct xattr *xattr2;
> > > > > > > > > I'm going to channel Paul and suggest this be xattr_transmute instead of xattr2.
> > > > > > > > > It also looks like it could move to be declared in the if clause.
> > > > > > > > > 
> > > > > > > > > >  	int may;
> > > > > > > > > >  
> > > > > > > > > >  	if (xattr) {
> > > > > > > > > > @@ -979,7 +979,17 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
> > > > > > > > > >  		if (may > 0 && ((may & MAY_TRANSMUTE) != 0) &&
> > > > > > > > > >  		    smk_inode_transmutable(dir)) {
> > > > > > > > > >  			isp = dsp;
> > > > > > > > > > -			issp->smk_flags |= SMK_INODE_CHANGED;
> > > > > > > > > I think you need to keep this. More below.
> > > > > > > > > 
> > > > > > > > > > +			xattr2 = lsm_get_xattr_slot(xattrs, xattr_count);
> > > > > > > > > > +			if (xattr2) {
> > > > > > > > > > +				xattr2->value = kmemdup(TRANS_TRUE,
> > > > > > > > > > +							TRANS_TRUE_SIZE,
> > > > > > > > > > +							GFP_NOFS);
> > > > > > > > > > +				if (xattr2->value == NULL)
> > > > > > > > > > +					return -ENOMEM;
> > > > > > > > > > +
> > > > > > > > > > +				xattr2->value_len = TRANS_TRUE_SIZE;
> > > > > > > > > > +				xattr2->name = XATTR_NAME_SMACKTRANSMUTE;
> > > > > > > > > > +			}
> > > > > > > > > >  		}
> > > > > > > > > >  
> > > > > > > > > >  		xattr->value = kstrdup(isp->smk_known, GFP_NOFS);
> > > > > > > > > > @@ -3512,20 +3522,12 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
> > > > > > > > > >  			 * If there is a transmute attribute on the
> > > > > > > > > >  			 * directory mark the inode.
> > > > > > > > > >  			 */
> > > > > > > > > > -			if (isp->smk_flags & SMK_INODE_CHANGED) {
> > > > > > > > > > -				isp->smk_flags &= ~SMK_INODE_CHANGED;
> > > > > > > > > > -				rc = __vfs_setxattr(&nop_mnt_idmap, dp, inode,
> > > > > > > > > > -					XATTR_NAME_SMACKTRANSMUTE,
> > > > > > > > > > -					TRANS_TRUE, TRANS_TRUE_SIZE,
> > > > > > > > > > -					0);
> > > > > > > > > > -			} else {
> > > > > > > > > > -				rc = __vfs_getxattr(dp, inode,
> > > > > > > > > > -					XATTR_NAME_SMACKTRANSMUTE, trattr,
> > > > > > > > > > -					TRANS_TRUE_SIZE);
> > > > > > > > > > -				if (rc >= 0 && strncmp(trattr, TRANS_TRUE,
> > > > > > > > > > -						       TRANS_TRUE_SIZE) != 0)
> > > > > > > > > > -					rc = -EINVAL;
> > > > > > > > > > -			}
> > > > > > > > > > +			rc = __vfs_getxattr(dp, inode,
> > > > > > > > > > +					    XATTR_NAME_SMACKTRANSMUTE, trattr,
> > > > > > > > > > +					    TRANS_TRUE_SIZE);
> > > > > > > > > > +			if (rc >= 0 && strncmp(trattr, TRANS_TRUE,
> > > > > > > > > > +					       TRANS_TRUE_SIZE) != 0)
> > > > > > > > > > +				rc = -EINVAL;
> > > > > > > > > Where is the SMACK64_TRANSMUTE attribute going to get set on the file?
> > > > > > > > > It's not going to get set in smack_init_inode_security(). The inode will
> > > > > > > > Isn't that the purpose of the inode_init_security hook?
> > > > > > > No. It initializes the in-memory inode. 
> > > > > > I hope I'm not mistaken here...
> > > > > > 
> > > > > > I make a small example. Filesystems call
> > > > > > security_inode_init_security(). Ext4 does:
> > > > > > 
> > > > > > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/fs/ext4/xattr_security.c?h=v6.3-rc6#n54
> > > > > > 
> > > > > > security_inode_init_security() allocates new_xattrs. Each LSM fills
> > > > > > new_xattrs. At the end of the loop, if there is at least one xattr
> > > > > > filled, the initxattrs() callback passed by the caller of
> > > > > > security_inode_init_security() is called.
> > > > > > 
> > > > > > The ext4 initxattrs() callback is:
> > > > > > 
> > > > > > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/fs/ext4/xattr_security.c?h=v6.3-rc6#n35
> > > > > > 
> > > > > > which scans the xattr array and, for each xattr,
> > > > > > calls ext4_xattr_set_handle().
> > > > > > 
> > > > > > Maybe I'm overlooking it, but ext4_xattr_set_handle() is setting xattrs
> > > > > > on the disk. Am I wrong?
> > > > > Yes, you're wrong. I tried your change, and the SMACK64_TRANSMUTE isn't
> > > > > set on the sub-directory when it's created. The __vfs_setxattr() call really
> > > > > is necessary. 
> > > > Could you please also check if there is any change with this fix:
> > > > 
> > > > Replace:
> > > > 
> > > > 	xattr2->name = XATTR_NAME_SMACKTRANSMUTE;
> > > > 
> > > > with:
> > > > 
> > > > 	xattr2->name = XATTR_SMACK_TRANSMUTE;
> > > > 
> > > > Thanks
> > > Unless I'm missing something really obvious there's no way that any
> > > of the evm/ima changes would obviate the need for the __vfs_setxattr() call.
> > > It's real easy to verify correct behavior, see the attached script.
> > > (you'll want to change the "notroot" value to a user on your system)
> > I got some errors during xattr removal, so not sure if my patch was
> > working properly or not (it happened also without it, didn't
> > investigate more).
> 
> The script is demonstrating that those xattrs don't exist when they
> shouldn't, si all is good there.
> 
> > However, I saw another discussion related to transmute:
> > 
> > https://lore.kernel.org/linux-security-module/20230419002338.566487-1-mengcc@amazon.com/
> > 
> > I add the people in CC.
> > 
> > The steps described were so easy to understand and executed, I tried
> > without and with overlayfs.
> > 
> > Without:
> > 
> > # echo "_ system rwxatl" > /sys/fs/smackfs/load2
> > # mkdir /data
> > # chsmack -a "system" /data
> > # chsmack -t /data
> > # mkdir -p /data/dir1/dir2
> > # chsmack /data/dir1
> > /data/dir1 access="system" transmute="TRUE"
> > # chsmack /data/dir1/dir2
> > /data/dir1/dir2 access="system" transmute="TRUE"
> > 
> > It seems to work, right?
> > 
> > With overlay fs it didn't work, same result as the one Mengchi
> > reported. Since Mengchi's solution was to set SMK_INODE_CHANGED, and I
> > want to get rid of it, I thought to investigate more.
> > 
> > Looking at smack_dentry_create_files_as(), I see that the label of the
> > process is overwritten with the label of the transmuting directory.
> > 
> > That causes smack_inode_init_security() to lookup the transmuting rule
> > on the overridden credential, and not on the original one.
> > 
> > In the example above, it means that, when overlayfs is creating the new
> > inode, the label of the process is system, not _. So no transmute
> > permission, and also the xattr will not be added, as observed by
> > Mengchi.
> 
> OK, I see that. Looks like the original implementation was poorly
> thought out/tested.
> 
> > Hopefully I undertood the code, so in this particular case we would not
> > need to override the label of the process in smack_dentry_create_files_
> > as().
> > 
> > If you see smack_inode_init_security():
> > 
> > 	struct smack_known *skp = smk_of_current();
> > 	struct smack_known *isp = smk_of_inode(inode);
> > 	struct smack_known *dsp = smk_of_inode(dir);
> > 
> > [...]
> > 
> > 		if (may > 0 && ((may & MAY_TRANSMUTE) != 0) &&
> > 		    smk_inode_transmutable(dir)) {
> > 			isp = dsp;
> > [...]
> > 
> > 		xattr->value = kstrdup(isp->smk_known, GFP_NOFS);
> > 
> > This code is telling, if there is a transmute rule, and the directory
> > is transmuting, set the label of the new inode to the label of the
> > directory. That should be already the result that we wanted to obtain.
> > 
> > The current code should have been doing it by overriding the label of
> > the process in smack_dentry_create_files_as() with the label of the
> > parent directory, and letting the inode being created with the
> > overridden label of the process. The transmute xattr is not set due to
> > the problem described above.
> 
> That would explain the observed behavior.
> 
> > So, as a quick test, I kept this patch with the change to xattr2->name, 
> > and skipped the label override in smack_dentry_create_files_as(). It
> > worked, I get the same result as without overlayfs. Wondering if the
> > process label override is necessary in other cases.
> 
> It's possible. It's been a long time since I've looked at this.
> I'm tempted to take a change to make overlayfs work upstream and
> then worry about the ima changes. There seems to be a lot more
> going on with the ima changes than is obvious from what's in the
> Smack code.

We could also set only SMACK64 in smack_inode_init_security(), and move
SMACKTRANSMUTE64 later, when we figure out how to fix the case of
overlayfs.

IMA and EVM would work in both cases.

Roberto

> > Roberto
> > 
> > > > Roberto
> > > > 
> > > > > > Thanks
> > > > > > 
> > > > > > Roberto
> > > > > > 
> > > > > > > > After all LSMs provide one or multiple xattrs, xattrs are going to be
> > > > > > > > written to the disk with the initxattr() callback of filesystems.
> > > > > > > > 
> > > > > > > > There is a small mistake above (XATTR_SMACK_TRANSMUTE instead
> > > > > > > > of XATTR_NAME_SMACKTRANSMUTE, as we are providing just the suffix).
> > > > > > > but I'm pretty sure the __vfs_setxattr() call is necessary to get
> > > > > > > the attribute written out. With your change the in-memory inode will
> > > > > > > get the attribute, but if you reboot it won't be on the directory.
> > > > > > > 
> > > > > > > > 95 Passed, 0 Failed, 100% Success rate
> > > > > > > > 
> > > > > > > > There was a test failing in dir-transmute.sh, before I fixed the xattr
> > > > > > > > name.
> > > > > > > > 
> > > > > > > > Thanks
> > > > > > > > 
> > > > > > > > Roberto
> > > > > > > > 
> > > > > > > > > know it's transmuting, but it won't get to disk without the __vfs_setxattr()
> > > > > > > > > here in smack_d_instantiate(). Now, it's been a long time since that code
> > > > > > > > > was written, so I could be wrong, but I'm pretty sure about that.
> > > > > > > > > 
> > > > > > > > > I think that you should be fine with the changes in smack_init_inode_security(),
> > > > > > > > > and leaving smack_d_instantiate() untouched. 
> > > > > > > > > 
> > > > > > > > > >  			if (rc >= 0)
> > > > > > > > > >  				transflag = SMK_INODE_TRANSMUTE;
> > > > > > > > > >  		}


^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH] Smack modifications for: security: Allow all LSMs to provide xattrs for inode_init_security hook
  2023-04-20  8:50                             ` Roberto Sassu
@ 2023-04-20 10:44                               ` Mimi Zohar
  2023-04-20 14:10                                 ` Roberto Sassu
  0 siblings, 1 reply; 44+ messages in thread
From: Mimi Zohar @ 2023-04-20 10:44 UTC (permalink / raw)
  To: Roberto Sassu, Casey Schaufler, dmitry.kasatkin, paul, jmorris,
	serge, stephen.smalley.work, eparis
  Cc: reiserfs-devel, linux-kernel, linux-integrity,
	linux-security-module, selinux, bpf, kpsingh, keescook,
	nicolas.bouchinet, Roberto Sassu, Mengchi Cheng, miklos,
	linux-unionfs, kamatam, yoonjaeh

On Thu, 2023-04-20 at 10:50 +0200, Roberto Sassu wrote:
> > 
> > It's possible. It's been a long time since I've looked at this.
> > I'm tempted to take a change to make overlayfs work upstream and
> > then worry about the ima changes. There seems to be a lot more
> > going on with the ima changes than is obvious from what's in the
> > Smack code.

It doesn't sound like the patch set introduces the overlayfs bug.

The security_inode_init_security() change to initialize multiple LSMs
and IMA xattrs and include them in the EVM hmac calculation is straight
forward.

In addition, the patch set creates the infrastructure for allowing
multiple per LSM xattrs, as requested, to be initialized in
security_inode_init_security() and included in the EVM hmac.

Mimi

> We could also set only SMACK64 in smack_inode_init_security(), and move
> SMACKTRANSMUTE64 later, when we figure out how to fix the case of
> overlayfs.
> 
> IMA and EVM would work in both cases.


^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH] Smack modifications for: security: Allow all LSMs to provide xattrs for inode_init_security hook
  2023-04-20 10:44                               ` Mimi Zohar
@ 2023-04-20 14:10                                 ` Roberto Sassu
  0 siblings, 0 replies; 44+ messages in thread
From: Roberto Sassu @ 2023-04-20 14:10 UTC (permalink / raw)
  To: Mimi Zohar, Casey Schaufler, dmitry.kasatkin, paul, jmorris,
	serge, stephen.smalley.work, eparis
  Cc: reiserfs-devel, linux-kernel, linux-integrity,
	linux-security-module, selinux, bpf, kpsingh, keescook,
	nicolas.bouchinet, Roberto Sassu, Mengchi Cheng, miklos,
	linux-unionfs, kamatam, yoonjaeh

On Thu, 2023-04-20 at 06:44 -0400, Mimi Zohar wrote:
> On Thu, 2023-04-20 at 10:50 +0200, Roberto Sassu wrote:
> > > It's possible. It's been a long time since I've looked at this.
> > > I'm tempted to take a change to make overlayfs work upstream and
> > > then worry about the ima changes. There seems to be a lot more
> > > going on with the ima changes than is obvious from what's in the
> > > Smack code.
> 
> It doesn't sound like the patch set introduces the overlayfs bug.

Correct.

The first problem of overlayfs is that smack_dentry_create_files_as()
override the credentials in a way that transmuting is not detected
correctly anymore in smack_inode_init_security(). The process label is
already overwritten with the directory label, at the time smack_inode_i
nit_security() calls smk_access_entry(), so the latter will not find
the transmuting rule that refers to the original process label.

The second problem is that overlayfs temporarily creates the new
directory in the working directory, that does not necessarily have the
same label of the parent directory the new file/directory will be added
to, causing the transmuting to be computed incorrectly.

> The security_inode_init_security() change to initialize multiple LSMs
> and IMA xattrs and include them in the EVM hmac calculation is straight
> forward.
> 
> In addition, the patch set creates the infrastructure for allowing
> multiple per LSM xattrs, as requested, to be initialized in
> security_inode_init_security() and included in the EVM hmac.
> 
> Mimi
> 
> > We could also set only SMACK64 in smack_inode_init_security(), and move
> > SMACKTRANSMUTE64 later, when we figure out how to fix the case of
> > overlayfs.
> > 
> > IMA and EVM would work in both cases.

Thanks to Mimi, I realized that adding SMACKTRANSMUTE64 in
smack_inode_init_security() is actually necessary.
Calling __vfs_getxattr() in smack_d_instantiate() causes the xattr to
be added without EVM updating the HMAC (thus, making the HMAC invalid).

Thanks

Roberto


^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH] Smack modifications for: security: Allow all LSMs to provide xattrs for inode_init_security hook
  2023-04-20  8:48                             ` Roberto Sassu
@ 2023-05-08 12:29                               ` Roberto Sassu
  2023-05-09 23:44                                 ` Mengchi Cheng
  0 siblings, 1 reply; 44+ messages in thread
From: Roberto Sassu @ 2023-05-08 12:29 UTC (permalink / raw)
  To: Mengchi Cheng
  Cc: bpf, casey, dmitry.kasatkin, eparis, jmorris, kamatam, keescook,
	kpsingh, linux-integrity, linux-kernel, linux-security-module,
	linux-unionfs, miklos, nicolas.bouchinet, paul, reiserfs-devel,
	roberto.sassu, selinux, serge, stephen.smalley.work, yoonjaeh,
	zohar

On Thu, 2023-04-20 at 10:48 +0200, Roberto Sassu wrote:
> On Wed, 2023-04-19 at 12:25 -0700, Mengchi Cheng wrote:
> > > I got some errors during xattr removal, so not sure if my patch was
> > > working properly or not (it happened also without it, didn't
> > > investigate more).
> > > 
> > > However, I saw another discussion related to transmute:
> > > 
> > > https://lore.kernel.org/linux-security-module/20230419002338.566487-1-mengcc@amazon.com/
> > > 
> > > I add the people in CC.
> > > 
> > > The steps described were so easy to understand and executed, I tried
> > > without and with overlayfs.
> > > 
> > > Without:
> > > 
> > > # echo "_ system rwxatl" > /sys/fs/smackfs/load2
> > > # mkdir /data
> > > # chsmack -a "system" /data
> > > # chsmack -t /data
> > > # mkdir -p /data/dir1/dir2
> > > # chsmack /data/dir1
> > > /data/dir1 access="system" transmute="TRUE"
> > > # chsmack /data/dir1/dir2
> > > /data/dir1/dir2 access="system" transmute="TRUE"
> > > 
> > > It seems to work, right?
> > > 
> > > With overlay fs it didn't work, same result as the one Mengchi
> > > reported. Since Mengchi's solution was to set SMK_INODE_CHANGED, and I
> > > want to get rid of it, I thought to investigate more.
> > > 
> > > Looking at smack_dentry_create_files_as(), I see that the label of the
> > > process is overwritten with the label of the transmuting directory.
> > > 
> > > That causes smack_inode_init_security() to lookup the transmuting rule
> > > on the overridden credential, and not on the original one.
> > > 
> > > In the example above, it means that, when overlayfs is creating the new
> > > inode, the label of the process is system, not _. So no transmute
> > > permission, and also the xattr will not be added, as observed by
> > > Mengchi.
> > > 
> > > Hopefully I undertood the code, so in this particular case we would not
> > > need to override the label of the process in smack_dentry_create_files_
> > > as().
> > > 
> > > If you see smack_inode_init_security():
> > > 
> > > 	struct smack_known *skp = smk_of_current();
> > > 	struct smack_known *isp = smk_of_inode(inode);
> > > 	struct smack_known *dsp = smk_of_inode(dir);
> > > 
> > > [...]
> > > 
> > > 		if (may > 0 && ((may & MAY_TRANSMUTE) != 0) &&
> > > 		    smk_inode_transmutable(dir)) {
> > > 			isp = dsp;
> > > [...]
> > > 
> > > 		xattr->value = kstrdup(isp->smk_known, GFP_NOFS);
> > > 
> > > This code is telling, if there is a transmute rule, and the directory
> > > is transmuting, set the label of the new inode to the label of the
> > > directory. That should be already the result that we wanted to obtain.
> > > 
> > > The current code should have been doing it by overriding the label of
> > > the process in smack_dentry_create_files_as() with the label of the
> > > parent directory, and letting the inode being created with the
> > > overridden label of the process. The transmute xattr is not set due to
> > > the problem described above.
> > > 
> > > So, as a quick test, I kept this patch with the change to xattr2->name, 
> > > and skipped the label override in smack_dentry_create_files_as(). It
> > > worked, I get the same result as without overlayfs. Wondering if the
> > > process label override is necessary in other cases.
> > 
> > If I understand correctly, removing the if block below is what you suggested.
> 
> Yes, more or less is what I did.
> 
> > diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
> > index cfcbb748da25..a867288e9de9 100644
> > --- a/security/smack/smack_lsm.c
> > +++ b/security/smack/smack_lsm.c
> > @@ -4769,8 +4769,8 @@ static int smack_dentry_create_files_as(struct dentry *dentry, int mode,
> >                  * providing access is transmuting use the containing
> >                  * directory label instead of the process label.
> >                  */
> > -               if (may > 0 && (may & MAY_TRANSMUTE))
> > -                       ntsp->smk_task = isp->smk_inode;
> > +//             if (may > 0 && (may & MAY_TRANSMUTE))
> > +//                     ntsp->smk_task = isp->smk_inode;
> >         }
> >         return 0;
> >  }
> > 
> > This way will have issue in the following situation on the vanila kernel.
> > data in the lowerdir has "_" label before overlay and dir1 is already
> > created in the lowerdir.
> > # chsmack /data
> > /data access="_"
> > # chsmack /data/dir1
> > /data/dir1 access="system" transmute="TRUE"
> > Apply overlay on data directory and set the smack rule in the same way.
> > data has the same smack label.
> > # chsmack /data
> > /data access="system" transmute="TRUE"
> 
> I'm using an older kernel, but I get _ instead of system.
> 
> > After that, remove dir1 and mkdir dir1 again. dir1 did not get the correct
> > label.
> > # rm -r /data/dir1
> > # mkdir -p /data/dir1
> > # chsmack /data/dir1
> > /data/dir1 access="_"
> 
> Unfortunately, it cannot work:
> 
> Thread 3 hit Breakpoint 1, smack_inode_init_security (...) at security/smack/smack_lsm.c:959
> 959	{
> (gdb) p dir->i_ino
> $12 = 9169116
> (gdb) p dsp
> $13 = (struct smack_known *) 0xffffffff831fc0a0 <smack_known_floor>
> 
> 
> ls -i /home/root/data_work/
> 9169116 work
> 
> So, transmuting is decided on the working directory.

Actually, after studying the code better, this is
what security_dentry_create_files_as() is useful for.

 * Compute a context for a dentry as the inode is not yet available and set
 * that context in passed in creds so that new files are created using that
 * context. Context is calculated using the passed in creds and not the creds
 * of the caller.

And Smack is doing:

		if (may > 0 && (may & MAY_TRANSMUTE)) {
			ntsp->smk_task = isp->smk_inode;

The new inode will be created with the label of the current task, that
was replaced with the label of the parent directory (see above) in smac
k_dentry_create_files_as().

I think the reason why Mengchi was not obtaining the desired label when
replacing /data/dir1 was because /data is incorrectly labeled.

To ensure that /data has label 'system' and transmute is true, I added
smackfstransmute=system to the mount options.

However, at the beginning, it seemed that it didn't work:

# mount -t overlay overlay -o lowerdir=/data,upperdir=/home/root/data,workdir=/home/root/data_work,smackfstransmute=system /data
# chsmack /data
/data access="system"

I found that the reason for this is that smack_inode_getsecurity()
retrieves metadata from the inode only for SMACK64, and the rest from
xattrs (which would not work for mount options). I just made a patch to
handle SMACK64TRANSMUTE too.

With the patch applied, I correctly get:

# mount -t overlay overlay -o lowerdir=/data,upperdir=/home/root/data,workdir=/home/root/data_work,smackfstransmute=system /data
# chsmack /data
/data access="system" transmute="TRUE"

With the root inode correctly labeled, I get:

# mount -t overlay overlay -o lowerdir=/data,upperdir=/home/root/data,workdir=/home/root/data_work,smackfstransmute=system /data
# rm -Rf /data/dir1
# mkdir /data/dir1
# chsmack /data/dir1
/data/dir1 access="system"

This is partially correct, transmute="TRUE" is missing.

Judging from smk_task, we cannot determine in smack_inode_init_security
() if transmuting was successful in smack_dentry_create_files_as(). We
need an extra information.

Mengchi's solution was to add the new inode as parameter
to security_dentry_create_files_as(), so that SMK_INODE_CHANGED can be
set in smk_flags, and SMACK64TRANSMUTE is set in smack_d_instantiate().

One concern could be that preallocating the inode maybe is overlayfs-
specific? A comment also says that we might not use that one:

	err = ovl_create_or_link(dentry, inode, &attr, false);
	/* Did we end up using the preallocated inode? */
	if (inode != d_inode(dentry))

We could achieve the same goal without adding a new parameter to security_dentry_create_files_as() and, instead, by adding a new field
in the task_smack structure, smk_transmuted, that is set to smk_task
when transmuting is successful.

Then, if smk_task == smk_transmuted, smack_inode_init_security() would
set SMK_INODE_CHANGED. On top of that, I would instead just provide the
second xattr SMACK64TRANSMUTE, in addition to SMACK64.

Will send the patches for upstream first, and then switch to providing 
SMACK64TRANSMUTE in smack_inode_init_security(), in a new version of
the EVM patch set.

Thanks

Roberto

> If I do:
> 
> # chsmack -a system -t /home/root/data_work/work/
> # mkdir /data/dir1
> # chsmack /data/dir1
> /data/dir1 access="system" transmute="TRUE"
> 
> I obtain the expected result. However, this problem is due to how overlayfs works:
> 
> static int ovl_create_over_whiteout(struct dentry *dentry, struct inode *inode,
> 				    struct ovl_cattr *cattr)
> {
> 
> [...]
> 
> 	newdentry = ovl_create_temp(ofs, workdir, cattr);
> 	err = PTR_ERR(newdentry);
> 	if (IS_ERR(newdentry))
> 		goto out_dput;
> 
> 
> The good news seems to be that, once you set the label to the correct
> directory, transmuting works with the changes I proposed.
> 
> Roberto
> 
> > Since I am not very familiar your change. Could you help check with your
> > patch will this issue also happen? 
> > 
> > 
> > Best,
> > Mengchi
> > 
> > >  
> > > Roberto


^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH] Smack modifications for: security: Allow all LSMs to provide xattrs for inode_init_security hook
  2023-05-08 12:29                               ` Roberto Sassu
@ 2023-05-09 23:44                                 ` Mengchi Cheng
  2023-05-09 23:56                                   ` Casey Schaufler
  0 siblings, 1 reply; 44+ messages in thread
From: Mengchi Cheng @ 2023-05-09 23:44 UTC (permalink / raw)
  To: roberto.sassu
  Cc: bpf, casey, dmitry.kasatkin, eparis, jmorris, kamatam, keescook,
	kpsingh, linux-integrity, linux-kernel, linux-security-module,
	linux-unionfs, mengcc, miklos, nicolas.bouchinet, paul,
	reiserfs-devel, roberto.sassu, selinux, serge,
	stephen.smalley.work, yoonjaeh, zohar

On Mon, 2023-05-08 12:29:42 +0000, Roberto Sassu wrote:
>
> On Thu, 2023-04-20 at 10:48 +0200, Roberto Sassu wrote:
> > On Wed, 2023-04-19 at 12:25 -0700, Mengchi Cheng wrote:
> > > > I got some errors during xattr removal, so not sure if my patch was
> > > > working properly or not (it happened also without it, didn't
> > > > investigate more).
> > > > 
> > > > However, I saw another discussion related to transmute:
> > > > 
> > > > https://lore.kernel.org/linux-security-module/20230419002338.566487-1-mengcc@amazon.com/
> > > > 
> > > > I add the people in CC.
> > > > 
> > > > The steps described were so easy to understand and executed, I tried
> > > > without and with overlayfs.
> > > > 
> > > > Without:
> > > > 
> > > > # echo "_ system rwxatl" > /sys/fs/smackfs/load2
> > > > # mkdir /data
> > > > # chsmack -a "system" /data
> > > > # chsmack -t /data
> > > > # mkdir -p /data/dir1/dir2
> > > > # chsmack /data/dir1
> > > > /data/dir1 access="system" transmute="TRUE"
> > > > # chsmack /data/dir1/dir2
> > > > /data/dir1/dir2 access="system" transmute="TRUE"
> > > > 
> > > > It seems to work, right?
> > > > 
> > > > With overlay fs it didn't work, same result as the one Mengchi
> > > > reported. Since Mengchi's solution was to set SMK_INODE_CHANGED, and I
> > > > want to get rid of it, I thought to investigate more.
> > > > 
> > > > Looking at smack_dentry_create_files_as(), I see that the label of the
> > > > process is overwritten with the label of the transmuting directory.
> > > > 
> > > > That causes smack_inode_init_security() to lookup the transmuting rule
> > > > on the overridden credential, and not on the original one.
> > > > 
> > > > In the example above, it means that, when overlayfs is creating the new
> > > > inode, the label of the process is system, not _. So no transmute
> > > > permission, and also the xattr will not be added, as observed by
> > > > Mengchi.
> > > > 
> > > > Hopefully I undertood the code, so in this particular case we would not
> > > > need to override the label of the process in smack_dentry_create_files_
> > > > as().
> > > > 
> > > > If you see smack_inode_init_security():
> > > > 
> > > > 	struct smack_known *skp = smk_of_current();
> > > > 	struct smack_known *isp = smk_of_inode(inode);
> > > > 	struct smack_known *dsp = smk_of_inode(dir);
> > > > 
> > > > [...]
> > > > 
> > > > 		if (may > 0 && ((may & MAY_TRANSMUTE) != 0) &&
> > > > 		    smk_inode_transmutable(dir)) {
> > > > 			isp = dsp;
> > > > [...]
> > > > 
> > > > 		xattr->value = kstrdup(isp->smk_known, GFP_NOFS);
> > > > 
> > > > This code is telling, if there is a transmute rule, and the directory
> > > > is transmuting, set the label of the new inode to the label of the
> > > > directory. That should be already the result that we wanted to obtain.
> > > > 
> > > > The current code should have been doing it by overriding the label of
> > > > the process in smack_dentry_create_files_as() with the label of the
> > > > parent directory, and letting the inode being created with the
> > > > overridden label of the process. The transmute xattr is not set due to
> > > > the problem described above.
> > > > 
> > > > So, as a quick test, I kept this patch with the change to xattr2->name, 
> > > > and skipped the label override in smack_dentry_create_files_as(). It
> > > > worked, I get the same result as without overlayfs. Wondering if the
> > > > process label override is necessary in other cases.
> > > 
> > > If I understand correctly, removing the if block below is what you suggested.
> > 
> > Yes, more or less is what I did.
> > 
> > > diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
> > > index cfcbb748da25..a867288e9de9 100644
> > > --- a/security/smack/smack_lsm.c
> > > +++ b/security/smack/smack_lsm.c
> > > @@ -4769,8 +4769,8 @@ static int smack_dentry_create_files_as(struct dentry *dentry, int mode,
> > >                  * providing access is transmuting use the containing
> > >                  * directory label instead of the process label.
> > >                  */
> > > -               if (may > 0 && (may & MAY_TRANSMUTE))
> > > -                       ntsp->smk_task = isp->smk_inode;
> > > +//             if (may > 0 && (may & MAY_TRANSMUTE))
> > > +//                     ntsp->smk_task = isp->smk_inode;
> > >         }
> > >         return 0;
> > >  }
> > > 
> > > This way will have issue in the following situation on the vanila kernel.
> > > data in the lowerdir has "_" label before overlay and dir1 is already
> > > created in the lowerdir.
> > > # chsmack /data
> > > /data access="_"
> > > # chsmack /data/dir1
> > > /data/dir1 access="system" transmute="TRUE"
> > > Apply overlay on data directory and set the smack rule in the same way.
> > > data has the same smack label.
> > > # chsmack /data
> > > /data access="system" transmute="TRUE"
> > 
> > I'm using an older kernel, but I get _ instead of system.
> > 
> > > After that, remove dir1 and mkdir dir1 again. dir1 did not get the correct
> > > label.
> > > # rm -r /data/dir1
> > > # mkdir -p /data/dir1
> > > # chsmack /data/dir1
> > > /data/dir1 access="_"
> > 
> > Unfortunately, it cannot work:
> > 
> > Thread 3 hit Breakpoint 1, smack_inode_init_security (...) at security/smack/smack_lsm.c:959
> > 959	{
> > (gdb) p dir->i_ino
> > $12 = 9169116
> > (gdb) p dsp
> > $13 = (struct smack_known *) 0xffffffff831fc0a0 <smack_known_floor>
> > 
> > 
> > ls -i /home/root/data_work/
> > 9169116 work
> > 
> > So, transmuting is decided on the working directory.
> 
> Actually, after studying the code better, this is
> what security_dentry_create_files_as() is useful for.
> 
>  * Compute a context for a dentry as the inode is not yet available and set
>  * that context in passed in creds so that new files are created using that
>  * context. Context is calculated using the passed in creds and not the creds
>  * of the caller.
> 
> And Smack is doing:
> 
> 		if (may > 0 && (may & MAY_TRANSMUTE)) {
> 			ntsp->smk_task = isp->smk_inode;
> 
> The new inode will be created with the label of the current task, that
> was replaced with the label of the parent directory (see above) in smac
> k_dentry_create_files_as().
> 
> I think the reason why Mengchi was not obtaining the desired label when
> replacing /data/dir1 was because /data is incorrectly labeled.
> 
> To ensure that /data has label 'system' and transmute is true, I added
> smackfstransmute=system to the mount options.
> 
> However, at the beginning, it seemed that it didn't work:
> 
> # mount -t overlay overlay -o lowerdir=/data,upperdir=/home/root/data,workdir=/home/root/data_work,smackfstransmute=system /data
> # chsmack /data
> /data access="system"
> 
> I found that the reason for this is that smack_inode_getsecurity()
> retrieves metadata from the inode only for SMACK64, and the rest from
> xattrs (which would not work for mount options). I just made a patch to
> handle SMACK64TRANSMUTE too.
> 
> With the patch applied, I correctly get:
> 
> # mount -t overlay overlay -o lowerdir=/data,upperdir=/home/root/data,workdir=/home/root/data_work,smackfstransmute=system /data
> # chsmack /data
> /data access="system" transmute="TRUE"
> 
> With the root inode correctly labeled, I get:
> 
> # mount -t overlay overlay -o lowerdir=/data,upperdir=/home/root/data,workdir=/home/root/data_work,smackfstransmute=system /data
> # rm -Rf /data/dir1
> # mkdir /data/dir1
> # chsmack /data/dir1
> /data/dir1 access="system"
> 
> This is partially correct, transmute="TRUE" is missing.
> 
> Judging from smk_task, we cannot determine in smack_inode_init_security
> () if transmuting was successful in smack_dentry_create_files_as(). We
> need an extra information.
> 
> Mengchi's solution was to add the new inode as parameter
> to security_dentry_create_files_as(), so that SMK_INODE_CHANGED can be
> set in smk_flags, and SMACK64TRANSMUTE is set in smack_d_instantiate().
> 
> One concern could be that preallocating the inode maybe is overlayfs-
> specific? A comment also says that we might not use that one:

security_dentry_create_files_as() is only referred in the fs/overlayfs/dir.c.
inode is for sure preallocated in this case.
I am glad you find a way without modifying security api. I did some tests
with your patch on our system. It works as expected. I am ok to drop mine.

Best,
Mengchi

> 
> 	err = ovl_create_or_link(dentry, inode, &attr, false);
> 	/* Did we end up using the preallocated inode? */
> 	if (inode != d_inode(dentry))
> 
> We could achieve the same goal without adding a new parameter to security_dentry_create_files_as() and, instead, by adding a new field
> in the task_smack structure, smk_transmuted, that is set to smk_task
> when transmuting is successful.
> 
> Then, if smk_task == smk_transmuted, smack_inode_init_security() would
> set SMK_INODE_CHANGED. On top of that, I would instead just provide the
> second xattr SMACK64TRANSMUTE, in addition to SMACK64.
> 
> Will send the patches for upstream first, and then switch to providing 
> SMACK64TRANSMUTE in smack_inode_init_security(), in a new version of
> the EVM patch set.
> 
> Thanks
> 
> Roberto
> 
> > If I do:
> > 
> > # chsmack -a system -t /home/root/data_work/work/
> > # mkdir /data/dir1
> > # chsmack /data/dir1
> > /data/dir1 access="system" transmute="TRUE"
> > 
> > I obtain the expected result. However, this problem is due to how overlayfs works:
> > 
> > static int ovl_create_over_whiteout(struct dentry *dentry, struct inode *inode,
> > 				    struct ovl_cattr *cattr)
> > {
> > 
> > [...]
> > 
> > 	newdentry = ovl_create_temp(ofs, workdir, cattr);
> > 	err = PTR_ERR(newdentry);
> > 	if (IS_ERR(newdentry))
> > 		goto out_dput;
> > 
> > 
> > The good news seems to be that, once you set the label to the correct
> > directory, transmuting works with the changes I proposed.
> > 
> > Roberto
> > 
> > > Since I am not very familiar your change. Could you help check with your
> > > patch will this issue also happen? 
> > > 
> > > 
> > > Best,
> > > Mengchi
> > > 
> > > >  
> > > > Roberto
> 
> 

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [PATCH] Smack modifications for: security: Allow all LSMs to provide xattrs for inode_init_security hook
  2023-05-09 23:44                                 ` Mengchi Cheng
@ 2023-05-09 23:56                                   ` Casey Schaufler
  0 siblings, 0 replies; 44+ messages in thread
From: Casey Schaufler @ 2023-05-09 23:56 UTC (permalink / raw)
  To: Mengchi Cheng, roberto.sassu
  Cc: bpf, dmitry.kasatkin, eparis, jmorris, kamatam, keescook,
	kpsingh, linux-integrity, linux-kernel, linux-security-module,
	linux-unionfs, miklos, nicolas.bouchinet, paul, reiserfs-devel,
	roberto.sassu, selinux, serge, stephen.smalley.work, yoonjaeh,
	zohar, Casey Schaufler

On 5/9/2023 4:44 PM, Mengchi Cheng wrote:
> On Mon, 2023-05-08 12:29:42 +0000, Roberto Sassu wrote:
>> On Thu, 2023-04-20 at 10:48 +0200, Roberto Sassu wrote:
>>> On Wed, 2023-04-19 at 12:25 -0700, Mengchi Cheng wrote:
>>>>> I got some errors during xattr removal, so not sure if my patch was
>>>>> working properly or not (it happened also without it, didn't
>>>>> investigate more).
>>>>>
>>>>> However, I saw another discussion related to transmute:
>>>>>
>>>>> https://lore.kernel.org/linux-security-module/20230419002338.566487-1-mengcc@amazon.com/
>>>>>
>>>>> I add the people in CC.
>>>>>
>>>>> The steps described were so easy to understand and executed, I tried
>>>>> without and with overlayfs.
>>>>>
>>>>> Without:
>>>>>
>>>>> # echo "_ system rwxatl" > /sys/fs/smackfs/load2
>>>>> # mkdir /data
>>>>> # chsmack -a "system" /data
>>>>> # chsmack -t /data
>>>>> # mkdir -p /data/dir1/dir2
>>>>> # chsmack /data/dir1
>>>>> /data/dir1 access="system" transmute="TRUE"
>>>>> # chsmack /data/dir1/dir2
>>>>> /data/dir1/dir2 access="system" transmute="TRUE"
>>>>>
>>>>> It seems to work, right?
>>>>>
>>>>> With overlay fs it didn't work, same result as the one Mengchi
>>>>> reported. Since Mengchi's solution was to set SMK_INODE_CHANGED, and I
>>>>> want to get rid of it, I thought to investigate more.
>>>>>
>>>>> Looking at smack_dentry_create_files_as(), I see that the label of the
>>>>> process is overwritten with the label of the transmuting directory.
>>>>>
>>>>> That causes smack_inode_init_security() to lookup the transmuting rule
>>>>> on the overridden credential, and not on the original one.
>>>>>
>>>>> In the example above, it means that, when overlayfs is creating the new
>>>>> inode, the label of the process is system, not _. So no transmute
>>>>> permission, and also the xattr will not be added, as observed by
>>>>> Mengchi.
>>>>>
>>>>> Hopefully I undertood the code, so in this particular case we would not
>>>>> need to override the label of the process in smack_dentry_create_files_
>>>>> as().
>>>>>
>>>>> If you see smack_inode_init_security():
>>>>>
>>>>> 	struct smack_known *skp = smk_of_current();
>>>>> 	struct smack_known *isp = smk_of_inode(inode);
>>>>> 	struct smack_known *dsp = smk_of_inode(dir);
>>>>>
>>>>> [...]
>>>>>
>>>>> 		if (may > 0 && ((may & MAY_TRANSMUTE) != 0) &&
>>>>> 		    smk_inode_transmutable(dir)) {
>>>>> 			isp = dsp;
>>>>> [...]
>>>>>
>>>>> 		xattr->value = kstrdup(isp->smk_known, GFP_NOFS);
>>>>>
>>>>> This code is telling, if there is a transmute rule, and the directory
>>>>> is transmuting, set the label of the new inode to the label of the
>>>>> directory. That should be already the result that we wanted to obtain.
>>>>>
>>>>> The current code should have been doing it by overriding the label of
>>>>> the process in smack_dentry_create_files_as() with the label of the
>>>>> parent directory, and letting the inode being created with the
>>>>> overridden label of the process. The transmute xattr is not set due to
>>>>> the problem described above.
>>>>>
>>>>> So, as a quick test, I kept this patch with the change to xattr2->name, 
>>>>> and skipped the label override in smack_dentry_create_files_as(). It
>>>>> worked, I get the same result as without overlayfs. Wondering if the
>>>>> process label override is necessary in other cases.
>>>> If I understand correctly, removing the if block below is what you suggested.
>>> Yes, more or less is what I did.
>>>
>>>> diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
>>>> index cfcbb748da25..a867288e9de9 100644
>>>> --- a/security/smack/smack_lsm.c
>>>> +++ b/security/smack/smack_lsm.c
>>>> @@ -4769,8 +4769,8 @@ static int smack_dentry_create_files_as(struct dentry *dentry, int mode,
>>>>                  * providing access is transmuting use the containing
>>>>                  * directory label instead of the process label.
>>>>                  */
>>>> -               if (may > 0 && (may & MAY_TRANSMUTE))
>>>> -                       ntsp->smk_task = isp->smk_inode;
>>>> +//             if (may > 0 && (may & MAY_TRANSMUTE))
>>>> +//                     ntsp->smk_task = isp->smk_inode;
>>>>         }
>>>>         return 0;
>>>>  }
>>>>
>>>> This way will have issue in the following situation on the vanila kernel.
>>>> data in the lowerdir has "_" label before overlay and dir1 is already
>>>> created in the lowerdir.
>>>> # chsmack /data
>>>> /data access="_"
>>>> # chsmack /data/dir1
>>>> /data/dir1 access="system" transmute="TRUE"
>>>> Apply overlay on data directory and set the smack rule in the same way.
>>>> data has the same smack label.
>>>> # chsmack /data
>>>> /data access="system" transmute="TRUE"
>>> I'm using an older kernel, but I get _ instead of system.
>>>
>>>> After that, remove dir1 and mkdir dir1 again. dir1 did not get the correct
>>>> label.
>>>> # rm -r /data/dir1
>>>> # mkdir -p /data/dir1
>>>> # chsmack /data/dir1
>>>> /data/dir1 access="_"
>>> Unfortunately, it cannot work:
>>>
>>> Thread 3 hit Breakpoint 1, smack_inode_init_security (...) at security/smack/smack_lsm.c:959
>>> 959	{
>>> (gdb) p dir->i_ino
>>> $12 = 9169116
>>> (gdb) p dsp
>>> $13 = (struct smack_known *) 0xffffffff831fc0a0 <smack_known_floor>
>>>
>>>
>>> ls -i /home/root/data_work/
>>> 9169116 work
>>>
>>> So, transmuting is decided on the working directory.
>> Actually, after studying the code better, this is
>> what security_dentry_create_files_as() is useful for.
>>
>>  * Compute a context for a dentry as the inode is not yet available and set
>>  * that context in passed in creds so that new files are created using that
>>  * context. Context is calculated using the passed in creds and not the creds
>>  * of the caller.
>>
>> And Smack is doing:
>>
>> 		if (may > 0 && (may & MAY_TRANSMUTE)) {
>> 			ntsp->smk_task = isp->smk_inode;
>>
>> The new inode will be created with the label of the current task, that
>> was replaced with the label of the parent directory (see above) in smac
>> k_dentry_create_files_as().
>>
>> I think the reason why Mengchi was not obtaining the desired label when
>> replacing /data/dir1 was because /data is incorrectly labeled.
>>
>> To ensure that /data has label 'system' and transmute is true, I added
>> smackfstransmute=system to the mount options.
>>
>> However, at the beginning, it seemed that it didn't work:
>>
>> # mount -t overlay overlay -o lowerdir=/data,upperdir=/home/root/data,workdir=/home/root/data_work,smackfstransmute=system /data
>> # chsmack /data
>> /data access="system"
>>
>> I found that the reason for this is that smack_inode_getsecurity()
>> retrieves metadata from the inode only for SMACK64, and the rest from
>> xattrs (which would not work for mount options). I just made a patch to
>> handle SMACK64TRANSMUTE too.
>>
>> With the patch applied, I correctly get:
>>
>> # mount -t overlay overlay -o lowerdir=/data,upperdir=/home/root/data,workdir=/home/root/data_work,smackfstransmute=system /data
>> # chsmack /data
>> /data access="system" transmute="TRUE"
>>
>> With the root inode correctly labeled, I get:
>>
>> # mount -t overlay overlay -o lowerdir=/data,upperdir=/home/root/data,workdir=/home/root/data_work,smackfstransmute=system /data
>> # rm -Rf /data/dir1
>> # mkdir /data/dir1
>> # chsmack /data/dir1
>> /data/dir1 access="system"
>>
>> This is partially correct, transmute="TRUE" is missing.
>>
>> Judging from smk_task, we cannot determine in smack_inode_init_security
>> () if transmuting was successful in smack_dentry_create_files_as(). We
>> need an extra information.
>>
>> Mengchi's solution was to add the new inode as parameter
>> to security_dentry_create_files_as(), so that SMK_INODE_CHANGED can be
>> set in smk_flags, and SMACK64TRANSMUTE is set in smack_d_instantiate().
>>
>> One concern could be that preallocating the inode maybe is overlayfs-
>> specific? A comment also says that we might not use that one:
> security_dentry_create_files_as() is only referred in the fs/overlayfs/dir.c.
> inode is for sure preallocated in this case.
> I am glad you find a way without modifying security api. I did some tests
> with your patch on our system. It works as expected. I am ok to drop mine.

Excellent. Thank you for verifying the patches. I have a few tests of my
own to complete, but I expect to move it into next shortly.

>
> Best,
> Mengchi
>
>> 	err = ovl_create_or_link(dentry, inode, &attr, false);
>> 	/* Did we end up using the preallocated inode? */
>> 	if (inode != d_inode(dentry))
>>
>> We could achieve the same goal without adding a new parameter to security_dentry_create_files_as() and, instead, by adding a new field
>> in the task_smack structure, smk_transmuted, that is set to smk_task
>> when transmuting is successful.
>>
>> Then, if smk_task == smk_transmuted, smack_inode_init_security() would
>> set SMK_INODE_CHANGED. On top of that, I would instead just provide the
>> second xattr SMACK64TRANSMUTE, in addition to SMACK64.
>>
>> Will send the patches for upstream first, and then switch to providing 
>> SMACK64TRANSMUTE in smack_inode_init_security(), in a new version of
>> the EVM patch set.
>>
>> Thanks
>>
>> Roberto
>>
>>> If I do:
>>>
>>> # chsmack -a system -t /home/root/data_work/work/
>>> # mkdir /data/dir1
>>> # chsmack /data/dir1
>>> /data/dir1 access="system" transmute="TRUE"
>>>
>>> I obtain the expected result. However, this problem is due to how overlayfs works:
>>>
>>> static int ovl_create_over_whiteout(struct dentry *dentry, struct inode *inode,
>>> 				    struct ovl_cattr *cattr)
>>> {
>>>
>>> [...]
>>>
>>> 	newdentry = ovl_create_temp(ofs, workdir, cattr);
>>> 	err = PTR_ERR(newdentry);
>>> 	if (IS_ERR(newdentry))
>>> 		goto out_dput;
>>>
>>>
>>> The good news seems to be that, once you set the label to the correct
>>> directory, transmuting works with the changes I proposed.
>>>
>>> Roberto
>>>
>>>> Since I am not very familiar your change. Could you help check with your
>>>> patch will this issue also happen? 
>>>>
>>>>
>>>> Best,
>>>> Mengchi
>>>>
>>>>>  
>>>>> Roberto
>>

^ permalink raw reply	[flat|nested] 44+ messages in thread

end of thread, other threads:[~2023-05-09 23:56 UTC | newest]

Thread overview: 44+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-03-31 12:32 [PATCH v10 0/4] evm: Do HMAC of multiple per LSM xattrs for new inodes Roberto Sassu
2023-03-31 12:32 ` [PATCH v10 1/4] reiserfs: Add security prefix to xattr name in reiserfs_security_write() Roberto Sassu
2023-04-04 18:25   ` Paul Moore
2023-03-31 12:32 ` [PATCH v10 2/4] security: Allow all LSMs to provide xattrs for inode_init_security hook Roberto Sassu
2023-04-04 18:54   ` Paul Moore
2023-04-05  2:08     ` Casey Schaufler
2023-04-05  9:43       ` Roberto Sassu
2023-04-05 19:59         ` Paul Moore
2023-04-05 20:43           ` Casey Schaufler
2023-04-05 20:49             ` Paul Moore
2023-04-05 21:07               ` Casey Schaufler
2023-04-06  9:14                 ` Roberto Sassu
2023-04-06 16:17                   ` Casey Schaufler
2023-04-06  9:08             ` Roberto Sassu
2023-04-11  7:22   ` Mimi Zohar
2023-04-11  7:53     ` Roberto Sassu
2023-04-11 16:42       ` Casey Schaufler
2023-04-11 17:23         ` [PATCH] Smack modifications for: " Roberto Sassu
2023-04-11 17:54           ` Casey Schaufler
2023-04-12  7:22             ` Roberto Sassu
2023-04-12 20:29               ` Casey Schaufler
2023-04-13  7:11                 ` Roberto Sassu
2023-04-17 16:41                   ` Casey Schaufler
2023-04-18  7:05                     ` Roberto Sassu
2023-04-18 16:02                       ` Casey Schaufler
2023-04-19 13:46                         ` Roberto Sassu
2023-04-19 19:25                           ` Mengchi Cheng
2023-04-20  8:48                             ` Roberto Sassu
2023-05-08 12:29                               ` Roberto Sassu
2023-05-09 23:44                                 ` Mengchi Cheng
2023-05-09 23:56                                   ` Casey Schaufler
2023-04-19 21:00                           ` Casey Schaufler
2023-04-20  8:50                             ` Roberto Sassu
2023-04-20 10:44                               ` Mimi Zohar
2023-04-20 14:10                                 ` Roberto Sassu
2023-04-11 17:25         ` [PATCH v10 2/4] " Roberto Sassu
2023-04-11 17:40           ` Casey Schaufler
2023-03-31 12:32 ` [PATCH v10 3/4] evm: Align evm_inode_init_security() definition with LSM infrastructure Roberto Sassu
2023-04-04 18:56   ` Paul Moore
2023-04-11  7:22   ` Mimi Zohar
2023-04-11  7:58     ` Roberto Sassu
2023-03-31 12:32 ` [PATCH v10 4/4] evm: Support multiple LSMs providing an xattr Roberto Sassu
2023-04-11  7:22   ` Mimi Zohar
2023-04-03 10:36 ` [PATCH v10 0/4] evm: Do HMAC of multiple per LSM xattrs for new inodes Mimi Zohar

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).