From: Justin Suess <utilityemal77@gmail.com>
To: gnoack3000@gmail.com, mic@digikod.net
Cc: linux-kernel@vger.kernel.org,
linux-security-module@vger.kernel.org,
Justin Suess <utilityemal77@gmail.com>
Subject: [PATCH v8 09/10] selftests/landlock: Add selftests for LANDLOCK_ADD_RULE_NO_INHERIT
Date: Thu, 28 May 2026 21:52:08 -0400 [thread overview]
Message-ID: <20260529015210.500291-10-utilityemal77@gmail.com> (raw)
In-Reply-To: <20260529015210.500291-1-utilityemal77@gmail.com>
Add test coverage for the new flag:
- New layout1_no_inherit fixture with five variants covering NO_INHERIT
on leaf, middle, and root directories, RW-over-RO expansion, and a
regular file target. Three tests per variant exercise inheritance
blocking, topology sealing, and layered (multi-domain) NO_INHERIT.
- A new layout4_disconnected_leafs variant exercising NO_INHERIT applied
through a bind mount, asserting that ancestors in both the bind and
source paths are sealed.
- A new audit_no_inherit fixture verifying that the flag interacts
correctly with the quiet flag: a quiet ancestor does not suppress
audit on a descendant that has crossed a NO_INHERIT boundary.
Signed-off-by: Justin Suess <utilityemal77@gmail.com>
---
Notes:
v7..v8 changes:
* Reorganized the new fs_test.c coverage around fixtures and
variants instead of one TEST_F_FORK per scenario:
- New layout1_no_inherit fixture with five FIXTURE_VARIANT_ADD
cases (rw_parent_ro_leaf, rw_parent_ro_middle, rw_parent_ro_root,
ro_parent_rw_middle, rw_parent_read_file) collapse what were
eight near-duplicate layout1 tests in v7 into three shared
tests (blocks_inheritance, seals_topology, layered_no_inherit).
- New layout4_disconnected_leafs variant 'no_inherit_mount' with a
single 'no_inherit_seals_mount' test replaces the four
v7 layout4 tests (no_inherit_mount_parent_{rename,rmdir,link}
and no_inherit_source_parent_rename) by exercising all four
sealed topology operations in one test.
- New audit_no_inherit fixture with three variants
(parent_is_logged, blocks_quiet_inheritance, quiet_parent)
covers the quiet/no_inherit interaction previously inlined
into an ad hoc audit test.
* Net change: 705 added lines in v7 -> 419 added lines in v8, with
equivalent coverage.
tools/testing/selftests/landlock/fs_test.c | 419 +++++++++++++++++++++
1 file changed, 419 insertions(+)
diff --git a/tools/testing/selftests/landlock/fs_test.c b/tools/testing/selftests/landlock/fs_test.c
index 2e32295258f9..625ff1afecb0 100644
--- a/tools/testing/selftests/landlock/fs_test.c
+++ b/tools/testing/selftests/landlock/fs_test.c
@@ -1429,6 +1429,224 @@ TEST_F_FORK(layout1, inherit_superset)
ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
}
+FIXTURE(layout1_no_inherit) {};
+
+FIXTURE_SETUP(layout1_no_inherit)
+{
+ prepare_layout(_metadata);
+ create_layout1(_metadata);
+}
+
+FIXTURE_TEARDOWN_PARENT(layout1_no_inherit)
+{
+ remove_layout1(_metadata);
+ cleanup_layout(_metadata);
+}
+
+FIXTURE_VARIANT(layout1_no_inherit)
+{
+ const char *ni_path;
+ const __u64 ni_access;
+ const char *ni_file;
+ const char *desc_file;
+ const int expected_ni_write;
+ const int expected_ni_read;
+ const int expected_desc_write;
+ const int expected_desc_read;
+};
+
+/* NO_INHERIT on leaf directory: blocks parent's RW, grants only RO. */
+/* clang-format off */
+FIXTURE_VARIANT_ADD(layout1_no_inherit, rw_parent_ro_leaf) {
+ /* clang-format on */
+ .ni_path = TMP_DIR "/s1d1/s1d2/s1d3",
+ .ni_access = ACCESS_RO,
+ .ni_file = TMP_DIR "/s1d1/s1d2/s1d3/f1",
+ .desc_file = TMP_DIR "/s1d1/s1d2/s1d3/f2",
+ .expected_ni_write = EACCES,
+ .expected_ni_read = 0,
+ .expected_desc_write = EACCES,
+ .expected_desc_read = 0,
+};
+
+/* NO_INHERIT on middle directory: blocks parent's RW for all descendants. */
+/* clang-format off */
+FIXTURE_VARIANT_ADD(layout1_no_inherit, rw_parent_ro_middle) {
+ /* clang-format on */
+ .ni_path = TMP_DIR "/s1d1/s1d2",
+ .ni_access = ACCESS_RO,
+ .ni_file = TMP_DIR "/s1d1/s1d2/f1",
+ .desc_file = TMP_DIR "/s1d1/s1d2/s1d3/f1",
+ .expected_ni_write = EACCES,
+ .expected_ni_read = 0,
+ .expected_desc_write = EACCES,
+ .expected_desc_read = 0,
+};
+
+/* NO_INHERIT on root directory: blocks parent's RW for entire subtree. */
+/* clang-format off */
+FIXTURE_VARIANT_ADD(layout1_no_inherit, rw_parent_ro_root) {
+ /* clang-format on */
+ .ni_path = TMP_DIR "/s1d1",
+ .ni_access = ACCESS_RO,
+ .ni_file = TMP_DIR "/s1d1/f1",
+ .desc_file = TMP_DIR "/s1d1/s1d2/s1d3/f1",
+ .expected_ni_write = EACCES,
+ .expected_ni_read = 0,
+ .expected_desc_write = EACCES,
+ .expected_desc_read = 0,
+};
+
+/* NO_INHERIT with RW access expands parent's RO to RW. */
+/* clang-format off */
+FIXTURE_VARIANT_ADD(layout1_no_inherit, ro_parent_rw_middle) {
+ /* clang-format on */
+ .ni_path = TMP_DIR "/s1d1/s1d2",
+ .ni_access = ACCESS_RW,
+ .ni_file = TMP_DIR "/s1d1/s1d2/f1",
+ .desc_file = TMP_DIR "/s1d1/s1d2/s1d3/f1",
+ .expected_ni_write = 0,
+ .expected_ni_read = 0,
+ .expected_desc_write = 0,
+ .expected_desc_read = 0,
+};
+
+/* NO_INHERIT on a file: file gets only its explicit READ_FILE access. */
+/* clang-format off */
+FIXTURE_VARIANT_ADD(layout1_no_inherit, rw_parent_read_file) {
+ /* clang-format on */
+ .ni_path = TMP_DIR "/s1d1/s1d2/f1",
+ .ni_access = LANDLOCK_ACCESS_FS_READ_FILE,
+ .ni_file = TMP_DIR "/s1d1/s1d2/f1",
+ .desc_file = TMP_DIR "/s1d1/s1d2/f2",
+ .expected_ni_write = EACCES,
+ .expected_ni_read = 0,
+ .expected_desc_write = 0,
+ .expected_desc_read = 0,
+};
+
+TEST_F_FORK(layout1_no_inherit, blocks_inheritance)
+{
+ struct landlock_ruleset_attr ruleset_attr = {
+ .handled_access_fs = ACCESS_RW,
+ };
+ int ruleset_fd;
+
+ /* RO variants: TMP_DIR gets RO instead of RW. */
+ if (variant->ni_access == ACCESS_RW)
+ ruleset_attr.handled_access_fs |= LANDLOCK_ACCESS_FS_READ_DIR;
+
+ ruleset_fd =
+ landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
+ ASSERT_LE(0, ruleset_fd);
+
+ if (variant->ni_access == ACCESS_RW)
+ add_path_beneath(_metadata, ruleset_fd, ACCESS_RO, TMP_DIR, 0);
+ else
+ add_path_beneath(_metadata, ruleset_fd, ACCESS_RW, TMP_DIR, 0);
+
+ add_path_beneath(_metadata, ruleset_fd, variant->ni_access,
+ variant->ni_path, LANDLOCK_ADD_RULE_NO_INHERIT);
+
+ enforce_ruleset(_metadata, ruleset_fd);
+ ASSERT_EQ(0, close(ruleset_fd));
+
+ EXPECT_EQ(variant->expected_ni_write,
+ test_open(variant->ni_file, O_WRONLY));
+ EXPECT_EQ(variant->expected_ni_read,
+ test_open(variant->ni_file, O_RDONLY));
+
+ if (variant->desc_file != variant->ni_file) {
+ EXPECT_EQ(variant->expected_desc_write,
+ test_open(variant->desc_file, O_WRONLY));
+ EXPECT_EQ(variant->expected_desc_read,
+ test_open(variant->desc_file, O_RDONLY));
+ }
+}
+
+TEST_F_FORK(layout1_no_inherit, seals_topology)
+{
+ int ruleset_fd;
+ struct landlock_ruleset_attr ruleset_attr = {
+ .handled_access_fs = ACCESS_RW | LANDLOCK_ACCESS_FS_REFER |
+ LANDLOCK_ACCESS_FS_REMOVE_FILE |
+ LANDLOCK_ACCESS_FS_REMOVE_DIR,
+ };
+
+ ruleset_fd =
+ landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
+ ASSERT_LE(0, ruleset_fd);
+
+ add_path_beneath(_metadata, ruleset_fd,
+ ACCESS_RW | LANDLOCK_ACCESS_FS_REFER |
+ LANDLOCK_ACCESS_FS_REMOVE_FILE |
+ LANDLOCK_ACCESS_FS_REMOVE_DIR,
+ TMP_DIR, 0);
+ add_path_beneath(_metadata, ruleset_fd, variant->ni_access,
+ variant->ni_path, LANDLOCK_ADD_RULE_NO_INHERIT);
+
+ enforce_ruleset(_metadata, ruleset_fd);
+ ASSERT_EQ(0, close(ruleset_fd));
+
+ /* The directory bearing NO_INHERIT cannot be renamed or removed. */
+ ASSERT_EQ(-1, rename(variant->ni_path, TMP_DIR "/ni_renamed"));
+ ASSERT_EQ(EACCES, errno);
+
+ /*
+ * Content inside the NO_INHERIT directory is still mutable
+ * (if the access rights permit it).
+ */
+ if (variant->ni_access & LANDLOCK_ACCESS_FS_REMOVE_FILE) {
+ ASSERT_EQ(0, unlink(variant->ni_file));
+ } else {
+ ASSERT_EQ(-1, unlink(variant->ni_file));
+ }
+
+ /* Unrelated operations outside the sealed branch still work. */
+ ASSERT_EQ(0, unlink(file1_s2d1));
+ ASSERT_EQ(0, mknod(file1_s2d1, S_IFREG | 0700, 0));
+}
+
+TEST_F_FORK(layout1_no_inherit, layered_no_inherit)
+{
+ const struct rule layer_rules[] = {
+ {
+ .path = TMP_DIR,
+ .access = ACCESS_RW | LANDLOCK_ACCESS_FS_REMOVE_FILE,
+ },
+ {},
+ };
+ int ruleset_fd;
+
+ /* Layer 1: RW on TMP_DIR. */
+ ruleset_fd = create_ruleset(_metadata,
+ ACCESS_RW | LANDLOCK_ACCESS_FS_REMOVE_FILE,
+ layer_rules);
+ ASSERT_LE(0, ruleset_fd);
+ enforce_ruleset(_metadata, ruleset_fd);
+ ASSERT_EQ(0, close(ruleset_fd));
+
+ /* Layer 2: NO_INHERIT on the target. */
+ ruleset_fd = create_ruleset(_metadata,
+ ACCESS_RW | LANDLOCK_ACCESS_FS_REMOVE_FILE,
+ layer_rules);
+ ASSERT_LE(0, ruleset_fd);
+ add_path_beneath(_metadata, ruleset_fd, variant->ni_access,
+ variant->ni_path, LANDLOCK_ADD_RULE_NO_INHERIT);
+ enforce_ruleset(_metadata, ruleset_fd);
+ ASSERT_EQ(0, close(ruleset_fd));
+
+ /* The target path cannot be renamed. */
+ ASSERT_EQ(-1, rename(variant->ni_path, TMP_DIR "/ni_renamed_layered"));
+ ASSERT_EQ(EACCES, errno);
+
+ /* Content at NI path respects the NO_INHERIT access from layer 2. */
+ EXPECT_EQ(variant->expected_ni_write,
+ test_open(variant->ni_file, O_WRONLY));
+ EXPECT_EQ(variant->expected_ni_read,
+ test_open(variant->ni_file, O_RDONLY));
+}
+
TEST_F_FORK(layout0, max_layers)
{
int i, err;
@@ -5571,6 +5789,25 @@ FIXTURE_VARIANT(layout4_disconnected_leafs)
const int expected_exchange_result;
/* Expected result of the call to renameat([fd:s1d42]/f4, [fd:s1d42]/f5). */
const int expected_same_dir_rename_result;
+
+ /*
+ * If true, a NO_INHERIT rule is set on s1d41 (via the bind mount
+ * at s2d2). Used by the no_inherit_mount test.
+ */
+ bool no_inherit_on_s1d41;
+ /*
+ * Access rights used for the optional NO_INHERIT rule on s1d41.
+ */
+ const __u64 no_inherit_access;
+ /*
+ * Expected result of renaming s1d31 (parent of s1d41 within the
+ * mount) when no_inherit_on_s1d41 is set.
+ */
+ const int expected_parent_rename;
+ /*
+ * Expected result of rmdir on s1d31, when no_inherit_on_s1d41 is set.
+ */
+ const int expected_parent_rmdir;
};
/* clang-format off */
@@ -5823,6 +6060,26 @@ FIXTURE_VARIANT_ADD(layout4_disconnected_leafs, f1_f2_f3) {
.expected_exchange_result = EACCES,
};
+/*
+ * NO_INHERIT variant: s1d41 is protected with ACCESS_RO via the bind mount.
+ * Parents within the mount are sealed against topology changes.
+ */
+/* clang-format off */
+FIXTURE_VARIANT_ADD(layout4_disconnected_leafs, no_inherit_mount) {
+ /* clang-format on */
+ .allowed_f1 = LANDLOCK_ACCESS_FS_READ_FILE,
+ .allowed_f2 = LANDLOCK_ACCESS_FS_READ_FILE,
+ .allowed_f3 = LANDLOCK_ACCESS_FS_READ_FILE,
+ .expected_read_result = 0,
+ .expected_rename_result = EACCES,
+ .expected_exchange_result = EACCES,
+ .expected_same_dir_rename_result = EACCES,
+ .no_inherit_on_s1d41 = true,
+ .no_inherit_access = ACCESS_RO,
+ .expected_parent_rename = EACCES,
+ .expected_parent_rmdir = EACCES,
+};
+
TEST_F_FORK(layout4_disconnected_leafs, read_rename_exchange)
{
const __u64 handled_access =
@@ -5931,6 +6188,70 @@ TEST_F_FORK(layout4_disconnected_leafs, read_rename_exchange)
test_renameat(s1d42_bind_fd, "f4", s1d42_bind_fd, "f5"));
}
+/*
+ * When s1d41 (accessed via the bind mount at s2d2) is protected with
+ * NO_INHERIT, its parent directories within the mount are sealed from
+ * topology changes. Other variants do not exercise NO_INHERIT and skip
+ * this test.
+ */
+TEST_F_FORK(layout4_disconnected_leafs, no_inherit_seals_mount)
+{
+ struct landlock_ruleset_attr ruleset_attr = {
+ .handled_access_fs = ACCESS_RW | LANDLOCK_ACCESS_FS_REFER |
+ LANDLOCK_ACCESS_FS_REMOVE_FILE |
+ LANDLOCK_ACCESS_FS_REMOVE_DIR,
+ };
+ int ruleset_fd, s1d41_bind_fd;
+
+ if (!variant->no_inherit_on_s1d41)
+ SKIP(return, "variant does not set NO_INHERIT on s1d41");
+
+ ruleset_fd =
+ landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
+ ASSERT_LE(0, ruleset_fd);
+
+ add_path_beneath(_metadata, ruleset_fd,
+ ACCESS_RW | LANDLOCK_ACCESS_FS_REFER |
+ LANDLOCK_ACCESS_FS_REMOVE_FILE |
+ LANDLOCK_ACCESS_FS_REMOVE_DIR,
+ TMP_DIR, 0);
+
+ s1d41_bind_fd = open(TMP_DIR "/s2d1/s2d2/s1d31/s1d41",
+ O_DIRECTORY | O_PATH | O_CLOEXEC);
+ ASSERT_LE(0, s1d41_bind_fd);
+
+ ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
+ &(struct landlock_path_beneath_attr){
+ .parent_fd = s1d41_bind_fd,
+ .allowed_access =
+ variant->no_inherit_access,
+ },
+ LANDLOCK_ADD_RULE_NO_INHERIT));
+ EXPECT_EQ(0, close(s1d41_bind_fd));
+
+ enforce_ruleset(_metadata, ruleset_fd);
+ ASSERT_EQ(0, close(ruleset_fd));
+
+ /* Parent of s1d41 within the mount is sealed. */
+ ASSERT_EQ(-1, rmdir(TMP_DIR "/s2d1/s2d2/s1d31"));
+ ASSERT_EQ(variant->expected_parent_rmdir, errno);
+
+ ASSERT_EQ(-1, rename(TMP_DIR "/s2d1/s2d2/s1d31",
+ TMP_DIR "/s2d1/s2d2/s1d31_renamed"));
+ ASSERT_EQ(variant->expected_parent_rename, errno);
+
+ /* Sibling directories outside the sealed chain are free. */
+ ASSERT_EQ(0, rename(TMP_DIR "/s2d1/s2d2/s1d32",
+ TMP_DIR "/s2d1/s2d2/s1d32_renamed"));
+ ASSERT_EQ(0, rename(TMP_DIR "/s2d1/s2d2/s1d32_renamed",
+ TMP_DIR "/s2d1/s2d2/s1d32"));
+
+ /* The mount source parent hierarchy is also sealed. */
+ ASSERT_EQ(-1, rename(TMP_DIR "/s1d1/s1d2/s1d31",
+ TMP_DIR "/s1d1/s1d2/s1d31_renamed"));
+ ASSERT_EQ(variant->expected_parent_rename, errno);
+}
+
/*
* layout5_disconnected_branch before rename:
*
@@ -7358,6 +7679,104 @@ TEST_F(audit_layout1, write_file)
EXPECT_EQ(1, records.domain);
}
+FIXTURE(audit_no_inherit)
+{
+ struct audit_filter audit_filter;
+ int audit_fd;
+};
+
+FIXTURE_SETUP(audit_no_inherit)
+{
+ prepare_layout(_metadata);
+ create_layout1(_metadata);
+
+ set_cap(_metadata, CAP_AUDIT_CONTROL);
+ self->audit_fd = audit_init_with_exe_filter(&self->audit_filter);
+ EXPECT_LE(0, self->audit_fd);
+ clear_cap(_metadata, CAP_AUDIT_CONTROL);
+}
+
+FIXTURE_TEARDOWN_PARENT(audit_no_inherit)
+{
+ remove_layout1(_metadata);
+ cleanup_layout(_metadata);
+
+ EXPECT_EQ(0, audit_cleanup(-1, NULL));
+}
+
+FIXTURE_VARIANT(audit_no_inherit)
+{
+ bool parent_quiet;
+ const char *test_path;
+ bool expect_audit_log;
+};
+
+/* clang-format off */
+FIXTURE_VARIANT_ADD(audit_no_inherit, parent_is_logged) {
+ /* clang-format on */
+ .parent_quiet = false,
+ .test_path = TMP_DIR "/s1d1/s1d2/f1",
+ .expect_audit_log = true,
+};
+
+/* clang-format off */
+FIXTURE_VARIANT_ADD(audit_no_inherit, blocks_quiet_inheritance) {
+ /* clang-format on */
+ .parent_quiet = true,
+ .test_path = TMP_DIR "/s1d1/s1d2/s1d3/f1",
+ .expect_audit_log = true,
+};
+
+/* clang-format off */
+FIXTURE_VARIANT_ADD(audit_no_inherit, quiet_parent) {
+ /* clang-format on */
+ .parent_quiet = true,
+ .test_path = TMP_DIR "/s1d1/f1",
+ .expect_audit_log = false,
+};
+
+TEST_F(audit_no_inherit, no_inherit_audit)
+{
+ struct audit_records records;
+ struct landlock_ruleset_attr ruleset_attr = {
+ .handled_access_fs = ACCESS_RW,
+ .quiet_access_fs = variant->parent_quiet ? ACCESS_RW : 0,
+ };
+ int ruleset_fd;
+
+ ruleset_fd = landlock_create_ruleset(&ruleset_attr,
+ sizeof(ruleset_attr), 0);
+ ASSERT_LE(0, ruleset_fd);
+
+ if (variant->parent_quiet)
+ add_path_beneath(_metadata, ruleset_fd, ACCESS_RO, dir_s1d1,
+ LANDLOCK_ADD_RULE_QUIET);
+ else
+ add_path_beneath(_metadata, ruleset_fd, ACCESS_RO, dir_s1d1, 0);
+
+ add_path_beneath(_metadata, ruleset_fd, ACCESS_RO, dir_s1d3,
+ LANDLOCK_ADD_RULE_NO_INHERIT);
+
+ enforce_ruleset(_metadata, ruleset_fd);
+
+ EXPECT_EQ(EACCES, test_open(variant->test_path, O_WRONLY));
+ if (variant->expect_audit_log) {
+ EXPECT_EQ(0, matches_log_fs(_metadata, self->audit_fd,
+ "fs\\.write_file",
+ variant->test_path));
+ } else {
+ EXPECT_NE(0, matches_log_fs(_metadata, self->audit_fd,
+ "fs\\.write_file",
+ variant->test_path));
+ }
+
+ EXPECT_EQ(0, audit_count_records(self->audit_fd, &records));
+ EXPECT_EQ(0, records.access);
+ EXPECT_EQ(variant->expect_audit_log ? 1 : 0, records.domain);
+
+ EXPECT_EQ(0, close(ruleset_fd));
+}
+
TEST_F(audit_layout1, read_file)
{
struct audit_records records;
--
2.53.0
next prev parent reply other threads:[~2026-05-29 1:52 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-29 1:51 [PATCH v8 00/10] Implement LANDLOCK_ADD_RULE_NO_INHERIT Justin Suess
2026-05-29 1:52 ` [PATCH v8 01/10] landlock: Add landlock_walk_path_up() helper Justin Suess
2026-05-29 1:52 ` [PATCH v8 02/10] landlock: Use landlock_walk_path_up() in is_access_to_paths_allowed() Justin Suess
2026-05-29 1:52 ` [PATCH v8 03/10] landlock: Use landlock_walk_path_up() in collect_domain_accesses() Justin Suess
2026-05-29 1:52 ` [PATCH v8 04/10] landlock: Add LANDLOCK_ADD_RULE_NO_INHERIT user API Justin Suess
2026-05-29 1:52 ` [PATCH v8 05/10] landlock: Return inserted rule from landlock_insert_rule() Justin Suess
2026-05-29 1:52 ` [PATCH v8 06/10] landlock: Implement LANDLOCK_ADD_RULE_NO_INHERIT Justin Suess
2026-05-29 1:52 ` [PATCH v8 07/10] landlock: Add documentation for LANDLOCK_ADD_RULE_NO_INHERIT Justin Suess
2026-05-29 1:52 ` [PATCH v8 08/10] samples/landlock: Add LANDLOCK_ADD_RULE_NO_INHERIT to landlock-sandboxer Justin Suess
2026-05-29 1:52 ` Justin Suess [this message]
2026-05-29 1:52 ` [PATCH v8 10/10] landlock: Add KUnit tests for LANDLOCK_ADD_RULE_NO_INHERIT Justin Suess
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260529015210.500291-10-utilityemal77@gmail.com \
--to=utilityemal77@gmail.com \
--cc=gnoack3000@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-security-module@vger.kernel.org \
--cc=mic@digikod.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox