]> git.ipfire.org Git - thirdparty/e2fsprogs.git/commitdiff
mke2fs: add root_selinux option for root inode label
authorRalph Siemsen <ralph.siemsen@linaro.org>
Wed, 10 Sep 2025 13:51:47 +0000 (09:51 -0400)
committerTheodore Ts'o <tytso@mit.edu>
Tue, 11 Nov 2025 19:37:16 +0000 (14:37 -0500)
This option allows setting the SELinux security context (label) for the
root directory. A common value would be system_u:object_r:root_t
possibly with a level/range such as :s0 suffix (for MCS/MLS policy).

Signed-off-by: Ralph Siemsen <ralph.siemsen@linaro.org>
Reviewed-by: Andreas Dilger <adilger@dilger.ca>
Message-ID: <20250910-mke2fs-small-fixes-v2-3-55c9842494e0@linaro.org>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
misc/mke2fs.8.in
misc/mke2fs.c
tests/m_root_selinux/expect.1 [new file with mode: 0644]
tests/m_root_selinux/script [new file with mode: 0644]

index 99ecc64b6e0f9cfdfa8148eadb30e44d10d17e72..ffe02eb0e5e912cd2fe38df0323a478793a0189c 100644 (file)
@@ -428,6 +428,16 @@ Specify the root directory permissions in octal format. If no permissions
 are specified then the root directory permissions would be set in accordance with
 the default filesystem umask.
 .TP
+.BI root_selinux= label
+Specify the root directory SELinux security context as
+.IR label ,
+typically
+.nh
+.B system_u:object_r:root_t
+with an optional level/range suffix such as
+.B :s0
+for MCS/MLS policy types.
+.TP
 .BI stride= stride-size
 Configure the file system for a RAID array with
 .I stride-size
index a54f83ad6e46b85c56b219ce9cb10d6b105a31c6..6eca46a43facd93a82f952cff960871826f8aa99 100644 (file)
@@ -95,6 +95,7 @@ static int    num_backups = 2; /* number of backup bg's for sparse_super2 */
 static uid_t   root_uid;
 static mode_t  root_perms = (mode_t)-1;
 static gid_t   root_gid;
+static char    *root_selinux = NULL;
 int    journal_size;
 int    journal_flags;
 int    journal_fc_size;
@@ -515,6 +516,35 @@ static void create_root_dir(ext2_filsys fs)
                        exit(1);
                }
        }
+
+       if (root_selinux) {
+               struct ext2_xattr_handle *handle;
+               retval = ext2fs_xattrs_open(fs, EXT2_ROOT_INO, &handle);
+               if (retval) {
+                       com_err("ext2fs_xattrs_open", retval,
+                               _("while setting root inode label"));
+                       exit(1);
+               }
+               retval = ext2fs_xattrs_read(handle);
+               if (retval) {
+                       com_err("ext2fs_xattrs_read", retval,
+                               _("while setting root inode label"));
+                       exit(1);
+               }
+               retval = ext2fs_xattr_set(handle, "security.selinux",
+                                         root_selinux, strlen(root_selinux));
+               if (retval) {
+                       com_err("ext2fs_xattr_set", retval,
+                               _("while setting root inode label"));
+                       exit(1);
+               }
+               retval = ext2fs_xattrs_close(&handle);
+               if (retval) {
+                       com_err("ext2fs_xattrs_close", retval,
+                               _("while setting root inode label"));
+                       exit(1);
+               }
+       }
 }
 
 static void create_lost_and_found(ext2_filsys fs)
@@ -1089,6 +1119,21 @@ static void parse_extended_opts(struct ext2_super_block *param,
                        if (arg) {
                                root_perms = strtoul(arg, &p, 8);
                        }
+               } else if (!strcmp(token, "root_selinux")) {
+                       if (arg) {
+                               root_selinux = realloc(root_selinux,
+                                                      strlen(arg) + 1);
+                               if (!root_selinux) {
+                                       com_err(program_name, ENOMEM, "%s",
+                                               _("in malloc for root_selinux"));
+                                       exit(1);
+                               }
+                               strcpy(root_selinux, arg);
+                       } else {
+                               r_usage++;
+                               badopt = token;
+                               continue;
+                       }
                } else if (!strcmp(token, "discard")) {
                        discard = 1;
                } else if (!strcmp(token, "nodiscard")) {
@@ -1174,6 +1219,7 @@ static void parse_extended_opts(struct ext2_super_block *param,
                        "\tlazy_journal_init=<0 to disable, 1 to enable>\n"
                        "\troot_owner=<uid of root dir>:<gid of root dir>\n"
                        "\troot_perms=<octal root directory permissions>\n"
+                       "\troot_selinux=<selinux root directory label>\n"
                        "\ttest_fs\n"
                        "\tdiscard\n"
                        "\tnodiscard\n"
diff --git a/tests/m_root_selinux/expect.1 b/tests/m_root_selinux/expect.1
new file mode 100644 (file)
index 0000000..19a3d6e
--- /dev/null
@@ -0,0 +1,57 @@
+Creating filesystem with 1024 1k blocks and 128 inodes
+
+Allocating group tables:    \b\b\bdone                            
+Writing inode tables:    \b\b\bdone                            
+Writing superblocks and filesystem accounting information:    \b\b\bdone
+
+Filesystem features: ext_attr resize_inode dir_index filetype sparse_super
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+test_filesys: 11/128 files (0.0% non-contiguous), 54/1024 blocks
+Exit status is 0
+Filesystem volume name:   <none>
+Last mounted on:          <not available>
+Filesystem magic number:  0xEF53
+Filesystem revision #:    1 (dynamic)
+Filesystem features:      ext_attr resize_inode dir_index filetype sparse_super
+Default mount options:    (none)
+Filesystem state:         clean
+Errors behavior:          Continue
+Filesystem OS type:       Linux
+Inode count:              128
+Block count:              1024
+Reserved block count:     51
+Overhead clusters:        40
+Free blocks:              970
+Free inodes:              117
+First block:              1
+Block size:               1024
+Fragment size:            1024
+Reserved GDT blocks:      3
+Blocks per group:         8192
+Fragments per group:      8192
+Inodes per group:         128
+Inode blocks per group:   32
+Mount count:              0
+Check interval:           15552000 (6 months)
+Reserved blocks uid:      0
+Reserved blocks gid:      0
+First inode:              11
+Inode size:               256
+Required extra isize:     32
+Desired extra isize:      32
+Default directory hash:   half_md4
+
+
+Group 0: (Blocks 1-1023)
+  Primary superblock at 1, Group descriptors at 2-2
+  Reserved GDT blocks at 3-5
+  Block bitmap at 6 (+5)
+  Inode bitmap at 7 (+6)
+  Inode table at 8-39 (+7)
+  970 free blocks, 117 free inodes, 2 directories
+  Free blocks: 54-1023
+  Free inodes: 12-128
diff --git a/tests/m_root_selinux/script b/tests/m_root_selinux/script
new file mode 100644 (file)
index 0000000..4ac8291
--- /dev/null
@@ -0,0 +1,4 @@
+DESCRIPTION="root directory SELinux security context"
+FS_SIZE=1024
+MKE2FS_OPTS="-E root_selinux=system_u:object_r:root_t"
+. $cmd_dir/run_mke2fs