162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * mdp - make dummy policy
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * When pointed at a kernel tree, builds a dummy policy for that kernel
762306a36Sopenharmony_ci * with exactly one type with full rights to itself.
862306a36Sopenharmony_ci *
962306a36Sopenharmony_ci * Copyright (C) IBM Corporation, 2006
1062306a36Sopenharmony_ci *
1162306a36Sopenharmony_ci * Authors: Serge E. Hallyn <serue@us.ibm.com>
1262306a36Sopenharmony_ci */
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci/* NOTE: we really do want to use the kernel headers here */
1662306a36Sopenharmony_ci#define __EXPORTED_HEADERS__
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci#include <stdio.h>
1962306a36Sopenharmony_ci#include <stdlib.h>
2062306a36Sopenharmony_ci#include <unistd.h>
2162306a36Sopenharmony_ci#include <string.h>
2262306a36Sopenharmony_ci#include <linux/kconfig.h>
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_cistatic void usage(char *name)
2562306a36Sopenharmony_ci{
2662306a36Sopenharmony_ci	printf("usage: %s [-m] policy_file context_file\n", name);
2762306a36Sopenharmony_ci	exit(1);
2862306a36Sopenharmony_ci}
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci/* Class/perm mapping support */
3162306a36Sopenharmony_cistruct security_class_mapping {
3262306a36Sopenharmony_ci	const char *name;
3362306a36Sopenharmony_ci	const char *perms[sizeof(unsigned) * 8 + 1];
3462306a36Sopenharmony_ci};
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci#include "classmap.h"
3762306a36Sopenharmony_ci#include "initial_sid_to_string.h"
3862306a36Sopenharmony_ci#include "policycap_names.h"
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ciint main(int argc, char *argv[])
4362306a36Sopenharmony_ci{
4462306a36Sopenharmony_ci	int i, j, mls = 0;
4562306a36Sopenharmony_ci	int initial_sid_to_string_len;
4662306a36Sopenharmony_ci	char **arg, *polout, *ctxout;
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci	FILE *fout;
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci	if (argc < 3)
5162306a36Sopenharmony_ci		usage(argv[0]);
5262306a36Sopenharmony_ci	arg = argv+1;
5362306a36Sopenharmony_ci	if (argc==4 && strcmp(argv[1], "-m") == 0) {
5462306a36Sopenharmony_ci		mls = 1;
5562306a36Sopenharmony_ci		arg++;
5662306a36Sopenharmony_ci	}
5762306a36Sopenharmony_ci	polout = *arg++;
5862306a36Sopenharmony_ci	ctxout = *arg;
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci	fout = fopen(polout, "w");
6162306a36Sopenharmony_ci	if (!fout) {
6262306a36Sopenharmony_ci		printf("Could not open %s for writing\n", polout);
6362306a36Sopenharmony_ci		usage(argv[0]);
6462306a36Sopenharmony_ci	}
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci	/* print out the classes */
6762306a36Sopenharmony_ci	for (i = 0; secclass_map[i].name; i++)
6862306a36Sopenharmony_ci		fprintf(fout, "class %s\n", secclass_map[i].name);
6962306a36Sopenharmony_ci	fprintf(fout, "\n");
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci	initial_sid_to_string_len = sizeof(initial_sid_to_string) / sizeof (char *);
7262306a36Sopenharmony_ci	/* print out the sids */
7362306a36Sopenharmony_ci	for (i = 1; i < initial_sid_to_string_len; i++) {
7462306a36Sopenharmony_ci		const char *name = initial_sid_to_string[i];
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci		if (name)
7762306a36Sopenharmony_ci			fprintf(fout, "sid %s\n", name);
7862306a36Sopenharmony_ci		else
7962306a36Sopenharmony_ci			fprintf(fout, "sid unused%d\n", i);
8062306a36Sopenharmony_ci	}
8162306a36Sopenharmony_ci	fprintf(fout, "\n");
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci	/* print out the class permissions */
8462306a36Sopenharmony_ci	for (i = 0; secclass_map[i].name; i++) {
8562306a36Sopenharmony_ci		const struct security_class_mapping *map = &secclass_map[i];
8662306a36Sopenharmony_ci		fprintf(fout, "class %s\n", map->name);
8762306a36Sopenharmony_ci		fprintf(fout, "{\n");
8862306a36Sopenharmony_ci		for (j = 0; map->perms[j]; j++)
8962306a36Sopenharmony_ci			fprintf(fout, "\t%s\n", map->perms[j]);
9062306a36Sopenharmony_ci		fprintf(fout, "}\n\n");
9162306a36Sopenharmony_ci	}
9262306a36Sopenharmony_ci	fprintf(fout, "\n");
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci	/* print out mls declarations and constraints */
9562306a36Sopenharmony_ci	if (mls) {
9662306a36Sopenharmony_ci		fprintf(fout, "sensitivity s0;\n");
9762306a36Sopenharmony_ci		fprintf(fout, "sensitivity s1;\n");
9862306a36Sopenharmony_ci		fprintf(fout, "dominance { s0 s1 }\n");
9962306a36Sopenharmony_ci		fprintf(fout, "category c0;\n");
10062306a36Sopenharmony_ci		fprintf(fout, "category c1;\n");
10162306a36Sopenharmony_ci		fprintf(fout, "level s0:c0.c1;\n");
10262306a36Sopenharmony_ci		fprintf(fout, "level s1:c0.c1;\n");
10362306a36Sopenharmony_ci#define SYSTEMLOW "s0"
10462306a36Sopenharmony_ci#define SYSTEMHIGH "s1:c0.c1"
10562306a36Sopenharmony_ci		for (i = 0; secclass_map[i].name; i++) {
10662306a36Sopenharmony_ci			const struct security_class_mapping *map = &secclass_map[i];
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci			fprintf(fout, "mlsconstrain %s {\n", map->name);
10962306a36Sopenharmony_ci			for (j = 0; map->perms[j]; j++)
11062306a36Sopenharmony_ci				fprintf(fout, "\t%s\n", map->perms[j]);
11162306a36Sopenharmony_ci			/*
11262306a36Sopenharmony_ci			 * This requires all subjects and objects to be
11362306a36Sopenharmony_ci			 * single-level (l2 eq h2), and that the subject
11462306a36Sopenharmony_ci			 * level dominate the object level (h1 dom h2)
11562306a36Sopenharmony_ci			 * in order to have any permissions to it.
11662306a36Sopenharmony_ci			 */
11762306a36Sopenharmony_ci			fprintf(fout, "} (l2 eq h2 and h1 dom h2);\n\n");
11862306a36Sopenharmony_ci		}
11962306a36Sopenharmony_ci	}
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci	/* enable all policy capabilities */
12262306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(selinux_policycap_names); i++)
12362306a36Sopenharmony_ci		fprintf(fout, "policycap %s;\n", selinux_policycap_names[i]);
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci	/* types, roles, and allows */
12662306a36Sopenharmony_ci	fprintf(fout, "type base_t;\n");
12762306a36Sopenharmony_ci	fprintf(fout, "role base_r;\n");
12862306a36Sopenharmony_ci	fprintf(fout, "role base_r types { base_t };\n");
12962306a36Sopenharmony_ci	for (i = 0; secclass_map[i].name; i++)
13062306a36Sopenharmony_ci		fprintf(fout, "allow base_t base_t:%s *;\n",
13162306a36Sopenharmony_ci			secclass_map[i].name);
13262306a36Sopenharmony_ci	fprintf(fout, "user user_u roles { base_r }");
13362306a36Sopenharmony_ci	if (mls)
13462306a36Sopenharmony_ci		fprintf(fout, " level %s range %s - %s", SYSTEMLOW,
13562306a36Sopenharmony_ci			SYSTEMLOW, SYSTEMHIGH);
13662306a36Sopenharmony_ci	fprintf(fout, ";\n");
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci#define SUBJUSERROLETYPE "user_u:base_r:base_t"
13962306a36Sopenharmony_ci#define OBJUSERROLETYPE "user_u:object_r:base_t"
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci	/* default sids */
14262306a36Sopenharmony_ci	for (i = 1; i < initial_sid_to_string_len; i++) {
14362306a36Sopenharmony_ci		const char *name = initial_sid_to_string[i];
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci		if (name)
14662306a36Sopenharmony_ci			fprintf(fout, "sid %s ", name);
14762306a36Sopenharmony_ci		else
14862306a36Sopenharmony_ci			fprintf(fout, "sid unused%d\n", i);
14962306a36Sopenharmony_ci		fprintf(fout, SUBJUSERROLETYPE "%s\n",
15062306a36Sopenharmony_ci			mls ? ":" SYSTEMLOW : "");
15162306a36Sopenharmony_ci	}
15262306a36Sopenharmony_ci	fprintf(fout, "\n");
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_ci#define FS_USE(behavior, fstype)			    \
15562306a36Sopenharmony_ci	fprintf(fout, "fs_use_%s %s " OBJUSERROLETYPE "%s;\n", \
15662306a36Sopenharmony_ci		behavior, fstype, mls ? ":" SYSTEMLOW : "")
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_ci	/*
15962306a36Sopenharmony_ci	 * Filesystems whose inode labels can be fetched via getxattr.
16062306a36Sopenharmony_ci	 */
16162306a36Sopenharmony_ci#ifdef CONFIG_EXT2_FS_SECURITY
16262306a36Sopenharmony_ci	FS_USE("xattr", "ext2");
16362306a36Sopenharmony_ci#endif
16462306a36Sopenharmony_ci#ifdef CONFIG_EXT4_FS_SECURITY
16562306a36Sopenharmony_ci#ifdef CONFIG_EXT4_USE_FOR_EXT2
16662306a36Sopenharmony_ci	FS_USE("xattr", "ext2");
16762306a36Sopenharmony_ci#endif
16862306a36Sopenharmony_ci	FS_USE("xattr", "ext3");
16962306a36Sopenharmony_ci	FS_USE("xattr", "ext4");
17062306a36Sopenharmony_ci#endif
17162306a36Sopenharmony_ci#ifdef CONFIG_JFS_SECURITY
17262306a36Sopenharmony_ci	FS_USE("xattr", "jfs");
17362306a36Sopenharmony_ci#endif
17462306a36Sopenharmony_ci#ifdef CONFIG_REISERFS_FS_SECURITY
17562306a36Sopenharmony_ci	FS_USE("xattr", "reiserfs");
17662306a36Sopenharmony_ci#endif
17762306a36Sopenharmony_ci#ifdef CONFIG_JFFS2_FS_SECURITY
17862306a36Sopenharmony_ci	FS_USE("xattr", "jffs2");
17962306a36Sopenharmony_ci#endif
18062306a36Sopenharmony_ci#ifdef CONFIG_XFS_FS
18162306a36Sopenharmony_ci	FS_USE("xattr", "xfs");
18262306a36Sopenharmony_ci#endif
18362306a36Sopenharmony_ci#ifdef CONFIG_GFS2_FS
18462306a36Sopenharmony_ci	FS_USE("xattr", "gfs2");
18562306a36Sopenharmony_ci#endif
18662306a36Sopenharmony_ci#ifdef CONFIG_BTRFS_FS
18762306a36Sopenharmony_ci	FS_USE("xattr", "btrfs");
18862306a36Sopenharmony_ci#endif
18962306a36Sopenharmony_ci#ifdef CONFIG_F2FS_FS_SECURITY
19062306a36Sopenharmony_ci	FS_USE("xattr", "f2fs");
19162306a36Sopenharmony_ci#endif
19262306a36Sopenharmony_ci#ifdef CONFIG_OCFS2_FS
19362306a36Sopenharmony_ci	FS_USE("xattr", "ocsfs2");
19462306a36Sopenharmony_ci#endif
19562306a36Sopenharmony_ci#ifdef CONFIG_OVERLAY_FS
19662306a36Sopenharmony_ci	FS_USE("xattr", "overlay");
19762306a36Sopenharmony_ci#endif
19862306a36Sopenharmony_ci#ifdef CONFIG_SQUASHFS_XATTR
19962306a36Sopenharmony_ci	FS_USE("xattr", "squashfs");
20062306a36Sopenharmony_ci#endif
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci	/*
20362306a36Sopenharmony_ci	 * Filesystems whose inodes are labeled from allocating task.
20462306a36Sopenharmony_ci	 */
20562306a36Sopenharmony_ci	FS_USE("task", "pipefs");
20662306a36Sopenharmony_ci	FS_USE("task", "sockfs");
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_ci	/*
20962306a36Sopenharmony_ci	 * Filesystems whose inode labels are computed from both
21062306a36Sopenharmony_ci	 * the allocating task and the superblock label.
21162306a36Sopenharmony_ci	 */
21262306a36Sopenharmony_ci#ifdef CONFIG_UNIX98_PTYS
21362306a36Sopenharmony_ci	FS_USE("trans", "devpts");
21462306a36Sopenharmony_ci#endif
21562306a36Sopenharmony_ci#ifdef CONFIG_HUGETLBFS
21662306a36Sopenharmony_ci	FS_USE("trans", "hugetlbfs");
21762306a36Sopenharmony_ci#endif
21862306a36Sopenharmony_ci#ifdef CONFIG_TMPFS
21962306a36Sopenharmony_ci	FS_USE("trans", "tmpfs");
22062306a36Sopenharmony_ci#endif
22162306a36Sopenharmony_ci#ifdef CONFIG_DEVTMPFS
22262306a36Sopenharmony_ci	FS_USE("trans", "devtmpfs");
22362306a36Sopenharmony_ci#endif
22462306a36Sopenharmony_ci#ifdef CONFIG_POSIX_MQUEUE
22562306a36Sopenharmony_ci	FS_USE("trans", "mqueue");
22662306a36Sopenharmony_ci#endif
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_ci#define GENFSCON(fstype, prefix)			     \
22962306a36Sopenharmony_ci	fprintf(fout, "genfscon %s %s " OBJUSERROLETYPE "%s\n", \
23062306a36Sopenharmony_ci		fstype, prefix, mls ? ":" SYSTEMLOW : "")
23162306a36Sopenharmony_ci
23262306a36Sopenharmony_ci	/*
23362306a36Sopenharmony_ci	 * Filesystems whose inodes are labeled from path prefix match
23462306a36Sopenharmony_ci	 * relative to the filesystem root.  Depending on the filesystem,
23562306a36Sopenharmony_ci	 * only a single label for all inodes may be supported.  Here
23662306a36Sopenharmony_ci	 * we list the filesystem types for which per-file labeling is
23762306a36Sopenharmony_ci	 * supported using genfscon; any other filesystem type can also
23862306a36Sopenharmony_ci	 * be added by only with a single entry for all of its inodes.
23962306a36Sopenharmony_ci	 */
24062306a36Sopenharmony_ci#ifdef CONFIG_PROC_FS
24162306a36Sopenharmony_ci	GENFSCON("proc", "/");
24262306a36Sopenharmony_ci#endif
24362306a36Sopenharmony_ci#ifdef CONFIG_SECURITY_SELINUX
24462306a36Sopenharmony_ci	GENFSCON("selinuxfs", "/");
24562306a36Sopenharmony_ci#endif
24662306a36Sopenharmony_ci#ifdef CONFIG_SYSFS
24762306a36Sopenharmony_ci	GENFSCON("sysfs", "/");
24862306a36Sopenharmony_ci#endif
24962306a36Sopenharmony_ci#ifdef CONFIG_DEBUG_FS
25062306a36Sopenharmony_ci	GENFSCON("debugfs", "/");
25162306a36Sopenharmony_ci#endif
25262306a36Sopenharmony_ci#ifdef CONFIG_TRACING
25362306a36Sopenharmony_ci	GENFSCON("tracefs", "/");
25462306a36Sopenharmony_ci#endif
25562306a36Sopenharmony_ci#ifdef CONFIG_PSTORE
25662306a36Sopenharmony_ci	GENFSCON("pstore", "/");
25762306a36Sopenharmony_ci#endif
25862306a36Sopenharmony_ci	GENFSCON("cgroup", "/");
25962306a36Sopenharmony_ci	GENFSCON("cgroup2", "/");
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_ci	fclose(fout);
26262306a36Sopenharmony_ci
26362306a36Sopenharmony_ci	fout = fopen(ctxout, "w");
26462306a36Sopenharmony_ci	if (!fout) {
26562306a36Sopenharmony_ci		printf("Wrote policy, but cannot open %s for writing\n", ctxout);
26662306a36Sopenharmony_ci		usage(argv[0]);
26762306a36Sopenharmony_ci	}
26862306a36Sopenharmony_ci	fprintf(fout, "/ " OBJUSERROLETYPE "%s\n", mls ? ":" SYSTEMLOW : "");
26962306a36Sopenharmony_ci	fprintf(fout, "/.* " OBJUSERROLETYPE "%s\n", mls ? ":" SYSTEMLOW : "");
27062306a36Sopenharmony_ci	fclose(fout);
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_ci	return 0;
27362306a36Sopenharmony_ci}
274