From 99051fe5b3e551f70ea7db7898b6f37f4f284770 Mon Sep 17 00:00:00 2001 From: Vit Mojzis Date: Mon, 12 Feb 2024 20:04:04 +0100 Subject: [PATCH] udica-0.2.8-4 - confined: make "-l" non optional - confined: allow asynchronous I/O operations Resolves: RHEL-29760 --- ...nerate-custom-policy-for-a-confined-.patch | 98 ++++++++++++++++--- ...ring-confined-user-policy-generation.patch | 4 +- 0003-confined-make-l-non-optional.patch | 57 +++++++++++ ...ed-allow-asynchronous-I-O-operations.patch | 31 ++++++ udica.spec | 8 +- 5 files changed, 182 insertions(+), 16 deletions(-) create mode 100644 0003-confined-make-l-non-optional.patch create mode 100644 0004-confined-allow-asynchronous-I-O-operations.patch diff --git a/0001-Add-option-to-generate-custom-policy-for-a-confined-.patch b/0001-Add-option-to-generate-custom-policy-for-a-confined-.patch index d18dbbc..a0acf2a 100644 --- a/0001-Add-option-to-generate-custom-policy-for-a-confined-.patch +++ b/0001-Add-option-to-generate-custom-policy-for-a-confined-.patch @@ -1,4 +1,4 @@ -From 21aa1fb602540d26e3ccad46ab59922da1810dd8 Mon Sep 17 00:00:00 2001 +From 3cda61f9a576315e9889821faf495663ad8257ef Mon Sep 17 00:00:00 2001 From: Vit Mojzis Date: Wed, 29 Nov 2023 10:38:48 +0100 Subject: [PATCH] Add option to generate custom policy for a confined user @@ -13,14 +13,76 @@ https://github.com/Koncpa/confined-users-policy Signed-off-by: Vit Mojzis --- + README.md | 50 + setup.py | 1 + - udica/__main__.py | 332 +- + udica/__main__.py | 342 +- udica/confined_user.py | 134 + udica/macros/confined_user_macros.cil | 4367 +++++++++++++++++++++++++ - 4 files changed, 4719 insertions(+), 115 deletions(-) + 5 files changed, 4779 insertions(+), 115 deletions(-) create mode 100644 udica/confined_user.py create mode 100644 udica/macros/confined_user_macros.cil +diff --git a/README.md b/README.md +index b37b885..37f68b1 100644 +--- a/README.md ++++ b/README.md +@@ -170,6 +170,56 @@ SELinux now allows binding to tcp/udp port *21*, but not to *80*: + Ncat: SHA-1 fingerprint: 6EEC 102E 6666 5F96 CC4F E5FA A1BE 4A5E 6C76 B6DC + Ncat: bind to :::80: Permission denied. QUITTING. + ++## Creating SELinux policy for confined user ++ ++Each Linux user on an SELinux-enabled system is mapped to an SELinux user. By default administrators can choose between the following SELinux users when confining a user account: root, staff_u, sysadm_u, user_u, xguest_u, guest_u (and unconfined_u which does not limit the user's actions). ++ ++To give administrators more options in confining users, *udica* now provides a way to generate a custom SELinux user (and corresponding roles and types) based on the specified parameters. The new user policy is assembled using a set of predefined policy macros based on use-cases (managing network, administrative tasks, etc.). ++ ++To generate a confined user, use the "confined_user" keyword followed by a list of options: ++ ++| Option | Use case | ++| ------------- | ------------- | ++| -a, --admin_commands | Use administrative commands (vipw, passwd, ...) | ++| -g, --graphical_login | Use graphical login environment | ++| -m, --mozilla_usage | Use mozilla firefox | ++| -n, --networking | Manage basic networking (ip, ifconfig, traceroute, tcpdump, ...) | ++| -d, --security_advanced | Manage SELinux settings (semanage, semodule, sepolicy, ...) | ++| -i, --security_basic | Use read-only security-related tools (seinfo, getsebool, sesearch, ...) | ++| -s, --sudo | Run commands as root using sudo | ++| -l, --user_login | Basic rules common to all users (tty, pty, ...) | ++| -c, --ssh_connect | Connect over SSH | ++| -b, --basic_commands | Use basic commands (date, ls, ps, man, systemctl -user, journalctl -user, passwd, ...) | ++ ++The new user also needs to be assigned an MLS/MCS level and range. These are set to `s0` and `s0:c0.c1023` respectively by default to work well in *targeted* policy mode. ++For more details see [Red Hat Multi-Level Security documentation](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9/html-single/using_selinux/index#using-multi-level-security-mls_using-selinux). ++ ++``` ++$ udica confined_user -abcdgilmns --level s0 --range "s0:c0" custom_user ++ ++Created custom_user.cil ++Run the following commands to apply the new policy: ++Install the new policy module ++# semodule -i custom_user.cil /usr/share/udica/macros/confined_user_macros.cil ++Create a default context file for the new user ++# sed -e ’s|user|custom_user|g’ /etc/selinux/targeted/contexts/users/user_u > /etc/selinux/targeted/contexts/users/custom_user_u ++Map the new selinux user to an existing user account ++# semanage login -a -s custom_user_u custom_user ++Fix labels in the user's home directory ++# restorecon -RvF /home/custom_user ++``` ++ ++As prompted by *udica*, the new user policy needs to be installed into the system along with the *confined_user_macros* file and a *default context* file needs to be created before the policy is ready to be used. ++ ++Last step is either assignment to an existing linux user (using `semanage login`), or specifying the new SELinux user when creating a new linux user account (no need to run `restorecon` for a new user home directory). ++``` ++useradd -Z custom_user_u ++``` ++ ++The created policy defines a new SELinux user `_u`, a corresponding role `_r` and a list of types (varies based on selected options) `_t, _sudo_t, _ssh_agent_t, ...` ++ ++See [Red Hat Confined User documentation](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9/html/using_selinux/managing-confined-and-unconfined-users_using-selinux#doc-wrapper) for more details about confined users, their assignment, available roles and access they allow. ++ + ## SELinux labels vs. objects they represent + + Policies generated by *udica* work with **SELinux labels** as opposed to filesystem paths, port numbers etc. This means that allowing access to given path (e.g. path to a directory mounted to your container), port number, or any other resource may also allow access to other resources you didn't specify, since the same SELinux label can be assigned to multiple resources. diff --git a/setup.py b/setup.py index deb6457..d3f20f4 100644 --- a/setup.py @@ -34,7 +96,7 @@ index deb6457..d3f20f4 100644 # scripts=["bin/udica"], entry_points={"console_scripts": ["udica=udica.__main__:main"]}, diff --git a/udica/__main__.py b/udica/__main__.py -index 43d2e43..2bbd401 100644 +index 43d2e43..1ba8515 100644 --- a/udica/__main__.py +++ b/udica/__main__.py @@ -13,8 +13,9 @@ @@ -48,7 +110,7 @@ index 43d2e43..2bbd401 100644 # import udica from udica.parse import parse_avc_file -@@ -25,116 +26,214 @@ from udica.policy import create_policy, load_policy, generate_playbook +@@ -25,116 +26,224 @@ from udica.policy import create_policy, load_policy, generate_playbook def get_args(): @@ -248,9 +310,19 @@ index 43d2e43..2bbd401 100644 + dest="basic_commands", + help="Use basic commands (date, ls, ps, man, systemctl -user, journalctl -user, passwd, ...)", + ) -+ parser.add_argument("--level", nargs="?", default="s0", dest="level") + parser.add_argument( -+ "--range", nargs="?", default="s0-s0:c0.c1023", dest="range" ++ "--level", ++ nargs="?", ++ default="s0", ++ dest="level", ++ help='MLS/MCS level, defaults to "s0"', ++ ) ++ parser.add_argument( ++ "--range", ++ nargs="?", ++ default="s0-s0:c0.c1023", ++ dest="range", ++ help='MLS/MCS range, defaults to "s0-s0:c0.c1023"', + ) + parser.add_argument("uname") + else: @@ -373,7 +445,7 @@ index 43d2e43..2bbd401 100644 args = parser.parse_args() return vars(args) -@@ -142,6 +241,13 @@ def get_args(): +@@ -142,6 +251,13 @@ def get_args(): def main(): opts = get_args() @@ -387,7 +459,7 @@ index 43d2e43..2bbd401 100644 if opts["ContainerID"]: container_inspect_raw = None for backend in [ENGINE_PODMAN, ENGINE_DOCKER]: -@@ -167,8 +273,6 @@ def main(): +@@ -167,8 +283,6 @@ def main(): if opts["JsonFile"]: if opts["JsonFile"] == "-": @@ -396,7 +468,7 @@ index 43d2e43..2bbd401 100644 container_inspect_raw = sys.stdin.read() else: import os.path -@@ -182,8 +286,6 @@ def main(): +@@ -182,8 +296,6 @@ def main(): if (not opts["JsonFile"]) and (not opts["ContainerID"]): try: @@ -407,7 +479,7 @@ index 43d2e43..2bbd401 100644 print("Couldn't parse inspect data from stdin:", e) diff --git a/udica/confined_user.py b/udica/confined_user.py new file mode 100644 -index 0000000..796f543 +index 0000000..bd92378 --- /dev/null +++ b/udica/confined_user.py @@ -0,0 +1,134 @@ @@ -543,7 +615,7 @@ index 0000000..796f543 + ) + print("Map the new selinux user to an existing user account") + print("# semanage login -a -s {}_u {}".format(opts["uname"], opts["uname"])) -+ print("Fix labels in the user's home direcotry") ++ print("Fix labels in the user's home directory") + print("# restorecon -RvF /home/{}".format(opts["uname"])) diff --git a/udica/macros/confined_user_macros.cil b/udica/macros/confined_user_macros.cil new file mode 100644 @@ -4919,5 +4991,5 @@ index 0000000..ddb5689 +;(call confined_ssh_connect_macro (u_t u_r u_ssh_agent_t)) +;(call confined_use_basic_commands_macro (u_t u_r)) -- -2.41.0 +2.43.0 diff --git a/0002-Add-tests-covering-confined-user-policy-generation.patch b/0002-Add-tests-covering-confined-user-policy-generation.patch index 280257b..ef435f5 100644 --- a/0002-Add-tests-covering-confined-user-policy-generation.patch +++ b/0002-Add-tests-covering-confined-user-policy-generation.patch @@ -1,4 +1,4 @@ -From bf1c8b2491b6f3eca2e519fb18d7d2143acc54fc Mon Sep 17 00:00:00 2001 +From d444e67ead27266d57184ab8bc032c5528f7e26c Mon Sep 17 00:00:00 2001 From: Vit Mojzis Date: Wed, 20 Dec 2023 14:33:27 +0100 Subject: [PATCH] Add tests covering confined user policy generation @@ -166,5 +166,5 @@ index fb6a9ab..0c73861 100644 return mock_out.output -- -2.41.0 +2.43.0 diff --git a/0003-confined-make-l-non-optional.patch b/0003-confined-make-l-non-optional.patch new file mode 100644 index 0000000..938a20f --- /dev/null +++ b/0003-confined-make-l-non-optional.patch @@ -0,0 +1,57 @@ +From f411c146986fabe7375724528b2d4ba8cf78b904 Mon Sep 17 00:00:00 2001 +From: Vit Mojzis +Date: Mon, 12 Feb 2024 19:38:14 +0100 +Subject: [PATCH] confined: make "-l" non optional + +The confinedom_user_login_macro is needed for all custom users. + +Also, allow the new user type to be accessed via remote login. + +Signed-off-by: Vit Mojzis +--- + udica/__main__.py | 2 +- + udica/macros/confined_user_macros.cil | 8 +++++++- + 2 files changed, 8 insertions(+), 2 deletions(-) + +diff --git a/udica/__main__.py b/udica/__main__.py +index 1ba8515..801499c 100644 +--- a/udica/__main__.py ++++ b/udica/__main__.py +@@ -92,7 +92,7 @@ def get_args(): + "-l", + "--user_login", + action="store_true", +- default=False, ++ default=True, + dest="user_login", + help="Basic rules common to all users (tty, pty, ...)", + ) +diff --git a/udica/macros/confined_user_macros.cil b/udica/macros/confined_user_macros.cil +index ddb5689..06c4c56 100644 +--- a/udica/macros/confined_user_macros.cil ++++ b/udica/macros/confined_user_macros.cil +@@ -2411,7 +2411,7 @@ + (typetransition utype sudo_exec_t process sudo_type) + (allow sudo_type utype (fd (use))) + (allow sudo_type utype (fifo_file (ioctl read write getattr lock append))) +- (allow sudo_type utype (process (sigchld))) ++ (allow sudo_type utype (process (getpgid sigchld))) + (allow sudo_type bin_t (dir (getattr open search))) + (allow sudo_type bin_t (dir (ioctl read getattr lock open search))) + (allow sudo_type bin_t (dir (getattr open search))) +@@ -4006,6 +4006,12 @@ + ) + ) + ) ++ ; Telnet login ++ (optional confinedom_user_login_optional_3 ++ (typeattributeset cil_gen_require remote_login_t) ++ (allow remote_login_t utype (process (signal transition))) ++ (allow utype self (bpf (prog_load))) ++ ) + ) + + (macro confined_ssh_connect_macro ((type utype) (role urole) (type ssh_agent_type)) +-- +2.43.0 + diff --git a/0004-confined-allow-asynchronous-I-O-operations.patch b/0004-confined-allow-asynchronous-I-O-operations.patch new file mode 100644 index 0000000..00241b6 --- /dev/null +++ b/0004-confined-allow-asynchronous-I-O-operations.patch @@ -0,0 +1,31 @@ +From 131d228c6a91eaaeccc1d000821beeccba69d134 Mon Sep 17 00:00:00 2001 +From: Vit Mojzis +Date: Mon, 4 Mar 2024 12:59:53 +0100 +Subject: [PATCH] confined: allow asynchronous I/O operations + +Signed-off-by: Vit Mojzis +--- + udica/macros/confined_user_macros.cil | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/udica/macros/confined_user_macros.cil b/udica/macros/confined_user_macros.cil +index 06c4c56..dcb5198 100644 +--- a/udica/macros/confined_user_macros.cil ++++ b/udica/macros/confined_user_macros.cil +@@ -4012,6 +4012,13 @@ + (allow remote_login_t utype (process (signal transition))) + (allow utype self (bpf (prog_load))) + ) ++ ; asynchronous I/O operations RHEL 10 ++ (optional confinedom_user_login_optional_4 ++ (typeattributeset cil_gen_require io_uring_t) ++ (allow utype self (io_uring (sqpoll))) ++ (allow utype io_uring_t (anon_inode (create))) ++ (allow utype io_uring_t (anon_inode (read write getattr map))) ++ ) + ) + + (macro confined_ssh_connect_macro ((type utype) (role urole) (type ssh_agent_type)) +-- +2.43.0 + diff --git a/udica.spec b/udica.spec index ae5dfe8..dbd564a 100644 --- a/udica.spec +++ b/udica.spec @@ -1,11 +1,13 @@ Summary: A tool for generating SELinux security policies for containers Name: udica Version: 0.2.8 -Release: 3%{?dist} +Release: 4%{?dist} Source0: https://github.com/containers/udica/archive/v%{version}.tar.gz #git format-patch -N v0.2.8 -- . ':!.cirrus.yml' ':!.github' Patch0001: 0001-Add-option-to-generate-custom-policy-for-a-confined-.patch Patch0002: 0002-Add-tests-covering-confined-user-policy-generation.patch +Patch0003: 0003-confined-make-l-non-optional.patch +Patch0004: 0004-confined-allow-asynchronous-I-O-operations.patch License: GPL-3.0-or-later BuildArch: noarch Url: https://github.com/containers/udica @@ -64,6 +66,10 @@ install -m 0644 udica/man/man8/udica.8 %{buildroot}%{_mandir}/man8/udica.8 %endif %changelog +* Mon Feb 12 2024 Vit Mojzis - 0.2.8-4 +- confined: make "-l" non optional +- confined: allow asynchronous I/O operations + * Sat Jan 27 2024 Fedora Release Engineering - 0.2.8-3 - Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild