From: Kevin Day Date: Sat, 14 Sep 2024 21:02:06 +0000 (-0500) Subject: Update: Cgroup example controller script example to show running under a SystemD... X-Git-Url: https://git.kevux.org/?a=commitdiff_plain;h=refs%2Fheads%2Fdevelopment;p=controller Update: Cgroup example controller script example to show running under a SystemD system. This is not required, but it builds the structure to accommodate the over-engineered SystemD absurdity of an init system. This is now more dynamic. Also show different programs like browsers. Also show firewall being set to startup. --- diff --git a/data/data/controller/example/cgroup/entries/chromium.entry b/data/data/controller/example/cgroup/entries/chromium.entry index 8e41837..624d3a9 100644 --- a/data/data/controller/example/cgroup/entries/chromium.entry +++ b/data/data/controller/example/cgroup/entries/chromium.entry @@ -1,4 +1,7 @@ # fss-0005 +# +# Helper entry for starting chromium using a sub-user account rule. +# settings: mode helper diff --git a/data/data/controller/example/cgroup/entries/eclipse.entry b/data/data/controller/example/cgroup/entries/eclipse.entry deleted file mode 100644 index 7a3aedb..0000000 --- a/data/data/controller/example/cgroup/entries/eclipse.entry +++ /dev/null @@ -1,7 +0,0 @@ -# fss-0005 - -settings: - mode helper - -main: - start program eclipse asynchronous diff --git a/data/data/controller/example/cgroup/entries/falkon.entry b/data/data/controller/example/cgroup/entries/falkon.entry new file mode 100644 index 0000000..c899123 --- /dev/null +++ b/data/data/controller/example/cgroup/entries/falkon.entry @@ -0,0 +1,10 @@ +# fss-0005 +# +# Helper entry for starting falkon using a sub-user account rule. +# + +settings: + mode helper + +main: + start program falkon asynchronous diff --git a/data/data/controller/example/cgroup/entries/firefox.entry b/data/data/controller/example/cgroup/entries/firefox.entry index 5d5ff15..7cbb460 100644 --- a/data/data/controller/example/cgroup/entries/firefox.entry +++ b/data/data/controller/example/cgroup/entries/firefox.entry @@ -1,4 +1,7 @@ # fss-0005 +# +# Helper entry for starting firefox using a sub-user account rule. +# settings: mode helper diff --git a/data/data/controller/example/cgroup/entries/setup_cgroups.entry b/data/data/controller/example/cgroup/entries/setup_cgroups.entry deleted file mode 100644 index 7a59836..0000000 --- a/data/data/controller/example/cgroup/entries/setup_cgroups.entry +++ /dev/null @@ -1,7 +0,0 @@ -# fss-0005 - -settings: - mode program - -main: - start setup cgroups diff --git a/data/data/controller/example/cgroup/entries/startup.entry b/data/data/controller/example/cgroup/entries/startup.entry new file mode 100644 index 0000000..e02826e --- /dev/null +++ b/data/data/controller/example/cgroup/entries/startup.entry @@ -0,0 +1,26 @@ +# fss-0005 +# +# Entry file for system startup tasks, setting up cgroup for sub-users. +# +# A sub-user is a second user in which some other user can switch to without a password and run processes in a more controlled, or perhaps jailed, environment. +# +# The Rules that utilize the cgroup for sub-users functionality generally use sudo to perform this task and run in helper mode with asynchronous to allow for the controller program to exit while the program executes as a forked process. +# + +settings: + mode program + + control_user 0 + control_group 0 + control_mode ug+rwx,o-rwx + + session new + +main: + failsafe failure + + start network firewall asynchronous + start setup cgroups + +failure: + print Controller Startup Failed. diff --git a/data/data/controller/example/cgroup/entries/terminator.entry b/data/data/controller/example/cgroup/entries/terminator.entry new file mode 100644 index 0000000..298787e --- /dev/null +++ b/data/data/controller/example/cgroup/entries/terminator.entry @@ -0,0 +1,10 @@ +# fss-0005 +# +# Helper entry for starting terminator using a sub-user account rule. +# + +settings: + mode helper + +main: + start program terminator asynchronous diff --git a/data/data/controller/example/cgroup/rules/network/firewall.rule b/data/data/controller/example/cgroup/rules/network/firewall.rule new file mode 100644 index 0000000..c459248 --- /dev/null +++ b/data/data/controller/example/cgroup/rules/network/firewall.rule @@ -0,0 +1,10 @@ +# fss-000d +# +# Rule for loading the FLL firewall settings on system start. +# + +setting: + name "Load firewall settings." + +command: + start /usr/local/fll/programs/shared/firewall restart diff --git a/data/data/controller/example/cgroup/rules/program/chromium.rule b/data/data/controller/example/cgroup/rules/program/chromium.rule index 75d10f0..f332b70 100644 --- a/data/data/controller/example/cgroup/rules/program/chromium.rule +++ b/data/data/controller/example/cgroup/rules/program/chromium.rule @@ -1,8 +1,31 @@ # fss-000d +# +# Helper rule for starting chromium using a sub-user account. +# settings: - name "Run Chromium" - cgroup existing user.slice/user-1000.slice/user@1000.service/user_you/group/browser + name "Run Chromoum as some_user." + cgroup existing user.slice/user-1000.slice/section-1.scope/user_xmpme/group/browser + environment DISPLAY + #user some_user + #group some_group + nice 5 + +script: + start { + if [[ $(xhost | grep '^SI:localuser:some_user$') == "" ]] ; then + xhost SI:localuser:some_user + fi + + if [[ $DISPLAY == "" ]] ; then + export DISPLAY=:0.0 + fi + + export WEBKIT_DISABLE_COMPOSITING_MODE=1 + } command: - start chromium --disable-features=UserAgentClientHint + + # Run as a custom user in which the current user has passwordless sudo access to. + start sudo -n --preserve-env=WEBKIT_DISABLE_COMPOSITING_MODE,DISPLAY -u some_user chromium-browser --disable-features=UserAgentClientHint + #start sudo -n --preserve-env=WEBKIT_DISABLE_COMPOSITING_MODE,DISPLAY -u some_user chromium-browser --disable-features=UserAgentClientHint --disable-web-security diff --git a/data/data/controller/example/cgroup/rules/program/eclipse.rule b/data/data/controller/example/cgroup/rules/program/eclipse.rule deleted file mode 100644 index 8b1020a..0000000 --- a/data/data/controller/example/cgroup/rules/program/eclipse.rule +++ /dev/null @@ -1,8 +0,0 @@ -# fss-000d - -settings: - name "Run Eclipse" - cgroup existing user.slice/user-1000.slice/user@1000.service/user_you/group/eclipse - -command: - start eclipse diff --git a/data/data/controller/example/cgroup/rules/program/falkon.rule b/data/data/controller/example/cgroup/rules/program/falkon.rule new file mode 100644 index 0000000..f7458c5 --- /dev/null +++ b/data/data/controller/example/cgroup/rules/program/falkon.rule @@ -0,0 +1,28 @@ +# fss-000d +# +# Helper rule for starting falcon using a sub-user account. +# + +settings: + name "Run Falkon as some_user." + cgroup existing user.slice/user-1000.slice/section-1.scope/user_xmpme/group/browser + environment DISPLAY + #user some_user + #group some_group + nice 5 + +script: + start { + if [[ $(xhost | grep '^SI:localuser:some_user$') == "" ]] ; then + xhost SI:localuser:some_user + fi + + if [[ $DISPLAY == "" ]] ; then + export DISPLAY=:0.0 + fi + } + +command: + + # Run as a custom user in which the current user has passwordless sudo access to. + start sudo -n --preserve-env=DISPLAY -u some_user falkon diff --git a/data/data/controller/example/cgroup/rules/program/firefox.rule b/data/data/controller/example/cgroup/rules/program/firefox.rule index 79b19f9..196d6d0 100644 --- a/data/data/controller/example/cgroup/rules/program/firefox.rule +++ b/data/data/controller/example/cgroup/rules/program/firefox.rule @@ -1,8 +1,28 @@ # fss-000d +# +# Helper rule for starting firefox using a sub-user account. +# settings: - name "Run Firefox (ESR)" - cgroup existing user.slice/user-1000.slice/user@1000.service/user_you/group/browser + name "Run Firefox as some_user." + cgroup existing user.slice/user-1000.slice/section-1.scope/user_xmpme/group/browser + environment DISPLAY + #user some_user + #group some_group + nice 5 + +script: + start { + if [[ $(xhost | grep '^SI:localuser:some_user$') == "" ]] ; then + xhost SI:localuser:some_user + fi + + if [[ $DISPLAY == "" ]] ; then + export DISPLAY=:0.0 + fi + } command: - start firefox-esr + + # Run as a custom user in which the current user has passwordless sudo access to. + start sudo -n --preserve-env=DISPLAY -u some_user firefox diff --git a/data/data/controller/example/cgroup/rules/program/terminator.rule b/data/data/controller/example/cgroup/rules/program/terminator.rule new file mode 100644 index 0000000..79f373e --- /dev/null +++ b/data/data/controller/example/cgroup/rules/program/terminator.rule @@ -0,0 +1,28 @@ +# fss-000d +# +# Helper rule for starting terminator using a sub-user account. +# + +settings: + name "Run Terminator as some_user." + cgroup existing user.slice/user-1000.slice/section-1.scope/user_xmpme/group/browser + environment DISPLAY + #user some_user + #group some_group + nice 5 + +script: + start { + if [[ $(xhost | grep '^SI:localuser:some_user$') == "" ]] ; then + xhost SI:localuser:some_user + fi + + if [[ $DISPLAY == "" ]] ; then + export DISPLAY=:0.0 + fi + } + +command: + + # Run as a custom user in which the current user has passwordless sudo access to. + start sudo -n --preserve-env=DISPLAY -u some_user terminator diff --git a/data/data/controller/example/cgroup/rules/setup/cgroups.rule b/data/data/controller/example/cgroup/rules/setup/cgroups.rule index 87de765..b86e1ce 100644 --- a/data/data/controller/example/cgroup/rules/setup/cgroups.rule +++ b/data/data/controller/example/cgroup/rules/setup/cgroups.rule @@ -1,122 +1,152 @@ # fss-000d # -# A cgroups2 example for systemd-based system using example user with example subdirectories and example programs. +# Rule for auto-configuring specific CGroup settings for some users. # -# This uses a 12-core system as an example. -# -# This is intended to be run as the user rather than as root. -# -# Example sizes: -# For 2GB: 2 * 1024 * 1024 * 1024. +# This is setup to be run under a SystemD system and there is an example SystemD service file provided for this. +# This can be run without SystemD using controller or controller as init. +# In such cases, the cgroup paths could be further simplified as suggested in some commented out examples. # settings: - name "Setup Cgroups for User 1000, named "you"" + name "Setup CGroups for users." + + environment PATH script: start { main() { - local user="you" - local group="you" - local path_cgroup="/sys/fs/cgroup/" - local path_slice_1="${path_cgroup}user.slice/" - local path_slice_2="${path_slice_1}user-1000.slice/" - #local path_slice_3="${path_slice_2}" # Some systemd's might work without the service directory. - local path_slice_3="${path_slice_2}user@1000.service/" # Some systemd's only give access to this service directory (the '@' is a problem and requires quoting). - local path_user="${path_slice_3}user_${user}/" - local path_group="${path_user}group/" - local path_top_subtree="${path_cgroup}cgroup.subtree_control" # Modifying this likely requires root privileges. - local directories="browser eclipse untrusted" - local d= - local i= - local subtree="+cpu +cpuset +memory +pids" + # Example PATH containing the FLL programs at a custom isolated directory. + PATH=/usr/local/fll/programs/shared/:$PATH - # The user path is for restricting the user and should not grant permissions to user other than read and execute directory. - if [[ ! -d "${path_user}" ]] ; then - mkdir -p "${path_user}" + local settings=/etc/init/settings/cgroup.fss + local all_subtree=$(fss_extended_read -nl all_subtree 0 "${settings}") + local group_subtree=$(fss_extended_read -nl group_subtree 0 "${settings}") + local total=$(fss_extended_read -nt user "${settings}") + let -i i=0 - if [[ $? -ne 0 ]] ; then echo "Failed mkdir ${path_user}." ; return 1 ; fi + if [[ $total == "" ]] ; then + let total=0 fi - chmod -R u+rwX,g+rX-w,o-rwx "${path_user}" && - chgrp -R ${group} "${path_user}" + while [[ $i -lt $total ]] ; do - if [[ $? -ne 0 ]] ; then echo "Failed mkdir ${path_group}." ; return 1 ; fi + setup_cgroup $(fss_extended_read -nls user ${i} 0 "${settings}") $(fss_extended_read -nls user ${i} 1 "${settings}") $(fss_extended_read -nls user ${i} 2 "${settings}") - # The group path is for the user to restrict processes they run and must have ownership with write access. - if [[ ! -d "${path_group}" ]] ; then - mkdir -p "${path_group}" + let i++ + done + + return 0 + \} + + setup_cgroup() { + local user="${1}" + local user_id="user-${3}" + local group="${2}" + local path_cgroup="/sys/fs/cgroup/" + local path_group="group/" + local path_slice_1="user.slice/" + local path_slice_2="${path_slice_1}${user_id}.slice/" + local path_slice_3="${path_slice_2}section-1.scope/" + local path_user="${path_slice_3}user_${user}/" + #local path_user="user_${user}/" # Common SystemD designs prevent this cleaner path from being used. + #local path_systemd_control="/sys/fs/cgroup/user.slice/cgroup.subtree_control" + #local path_systemd_control_user="/sys/fs/cgroup/user.slice/${user_id}.slice/cgroup.subtree_control" + local path_systemd_procs_user="/sys/fs/cgroup/user.slice/${user_id}.slice/cgroup.procs" + local categories=$(fss_extended_read -nl categories 0 "${settings}") + local category= + local total= + local key= + local c= + local i= + local j= - if [[ $? -ne 0 ]] ; then echo "Failed mkdir ${path_group}." ; return 1 ; fi + # The user path is for restricting the user and should not grant permissions to user other than read and execute directory. + if [[ ! -d ${path_cgroup}${path_user} ]] ; then + mkdir -p ${path_cgroup}${path_user} || return 1 fi - # Must have common ancestor with write acces, so fix setup from systemd to work with this one. - chmod -R u+rw+X,g+rX-w,o-rwx "${path_group}" && - chown -R ${user}:${group} "${path_group}" + chmod u+rwX,g+rX-w,o-rwx ${path_cgroup}${path_slice_1} || return 1 + chgrp ${group} ${path_cgroup}${path_slice_1} || return 1 - if [[ $? -ne 0 ]] ; then echo "Failed change permission on ${path_group}." ; return 1 ; fi + chmod u+rwX,g+rX-w,o-rwx ${path_cgroup}${path_slice_2} || return 1 + chgrp ${group} ${path_cgroup}${path_slice_2} || return 1 - # Make sure the user can manipulate subtrees (May fail if any path outside of ${path_slice_1} lacks things wanted by ${subtree}). - echo ${subtree} >> "${path_slice_1}cgroup.subtree_control" - if [[ $? -ne 0 ]] ; then echo "Failed populate subtree of ${path_slice_1}cgroup.subtree_control." ; return 1 ; fi + chmod u+rwX,g+rX-w,o-rwx ${path_cgroup}${path_slice_3} || return 1 + chgrp ${group} ${path_cgroup}${path_slice_3} || return 1 - echo ${subtree} >> "${path_slice_2}cgroup.subtree_control" - if [[ $? -ne 0 ]] ; then echo "Failed populate subtree of ${path_slice_2}cgroup.subtree_control." ; return 1 ; fi + chmod -R u+rwX,g+rX-w,o-rwx ${path_cgroup}${path_user} || return 1 + chgrp -R ${group} ${path_cgroup}${path_user} || return 1 + + # The group path is for the user to restrict processes they run and must have ownership with write access. + if [[ ! -d ${path_cgroup}${path_user}${path_group} ]] ; then + mkdir -p ${path_cgroup}${path_user}${path_group} || return 1 + fi - echo ${subtree} >> "${path_slice_3}cgroup.subtree_control" - if [[ $? -ne 0 ]] ; then echo "Failed populate subtree of ${path_slice_3}cgroup.subtree_control." ; return 1 ; fi + chmod -R u+rw+X,g+rX-w,o-rwx ${path_cgroup}${path_user}${path_group} || return 1 + chown -R ${user}:${group} ${path_cgroup}${path_user}${path_group} || return 1 - echo ${subtree} >> "${path_slice_4}cgroup.subtree_control" - if [[ $? -ne 0 ]] ; then echo "Failed populate subtree of ${path_slice_4}cgroup.subtree_control." ; return 1 ; fi + find ${path_cgroup}${path_user} -type d -exec chmod g+s '{}' ';' || return 1 - echo ${subtree} >> "${path_user}cgroup.subtree_control" - if [[ $? -ne 0 ]] ; then echo "Failed populate subtree of ${path_user}cgroup.subtree_control." ; return 1 ; fi + # make sure the user can manipulate subtrees. + echo ${all_subtree} >> ${path_cgroup}cgroup.subtree_control || return 1 + #echo ${all_subtree} >> ${path_systemd_control} || return 1 + #echo ${all_subtree} >> ${path_systemd_control_user} || return 1 + echo ${group_subtree} >> ${path_cgroup}${path_slice_1}cgroup.subtree_control || return 1 + echo ${group_subtree} >> ${path_cgroup}${path_slice_2}cgroup.subtree_control || return 1 + echo ${group_subtree} >> ${path_cgroup}${path_slice_3}cgroup.subtree_control || return 1 + echo ${group_subtree} >> ${path_cgroup}${path_user}cgroup.subtree_control || return 1 + echo ${group_subtree} >> ${path_cgroup}${path_user}${path_group}cgroup.subtree_control || return 1 - echo ${subtree} >> "${path_group}cgroup.subtree_control" - if [[ $? -ne 0 ]] ; then echo "Failed populate subtree of ${path_group}cgroup.subtree_control." ; return 1 ; fi + # must have common ancestort write acces, so fix setup from systemd to work with this one. + chgrp ${group} ${path_systemd_procs_user} + chmod g+w ${path_systemd_procs_user} - for d in ${directories} ; do - i="${path_group}${d}/" + for c in ${categories} ; do + i="${path_cgroup}${path_user}${path_group}${c}/" if [[ ! -d ${i} ]] ; then echo "Creating cgroup directory '${i}'." - mkdir -p "${i}" && - chown -R ${user}:${group} "${i}" && - chmod -R u+rw+X,g+rX-w,o-rwx "${i}" && - chmod g+s "${i}" - - if [[ $? -ne 0 ]] ; then echo "Failed change permission on ${i}." ; return 1 ; fi + mkdir -p ${i} && + chown -R ${user}:${group} ${i} && + chmod -R u+rw+X,g+rX-w,o-rwx ${i} || exit 1 + chmod g+s ${i} || exit 1 fi - if [[ ${d} == "browser" ]] ; then - put_into "7516192768" "${i}memory.high" && - put_into "8589934592" "${i}memory.max" && - put_into "3-6" "${i}cpuset.cpus" - elif [[ ${d} == "eclipse" ]] ; then - put_into "3758096384" "${i}memory.high" && - put_into "4294967296" "${i}memory.max" && - put_into "5-8" "${i}cpuset.cpus" + if [[ $(fss_extended_read -nls "category_${c}" 0 0 "${settings}") != "" ]] ; then + category="category_${c}" else - put_into "858993459" "${i}memory.high" && - put_into "1073741824" "${i}memory.max" && - put_into "9-11" "${i}cpuset.cpus" + category="default" fi - if [[ $? -ne 0 ]] ; then echo "Failed to restrictions for ${d} at ${i}." ; return 1 ; fi + total=$(fss_extended_read -nt "${category}" "${settings}") + let j=0 + + if [[ $total == "" ]] ; then + let total=0 + fi + + while [[ $j -lt $total ]] ; do + + key=$(fss_extended_read -nls "${category}" ${j} 0 "${settings}") + + put_into $(fss_extended_read -nls "${category}" ${j} 1 "${settings}") "${i}${key}" || return 1 + + let j++ + done done return 0 \} - put_into() { - if [[ -e ${2} ]] ; then - echo ${1} > ${2} || return 1 - fi + put_into() { + if [[ -e ${2} ]] ; then + echo ${1} > ${2} || return 1 + fi - return 0 - \} + return 0 + \} - main + main } diff --git a/data/data/controller/example/cgroup/settings/cgroup.fss b/data/data/controller/example/cgroup/settings/cgroup.fss new file mode 100644 index 0000000..9b5c93e --- /dev/null +++ b/data/data/controller/example/cgroup/settings/cgroup.fss @@ -0,0 +1,18 @@ +# fss-0001 + +all_subtree +cpu +cpuset +memory +pids +group_subtree +cpu +cpuset +memory +pids + +# For 2GB: 2 * 1024 * 1024 * 1024 = 2147483648. +# For 1GB: 1024 * 1024 * 1024 = 1073741824 +# For 768MB: 1024 * 1024 * 768 = 805306368. +default memory.high 805306368 +default memory.max 1073741824 +default cpuset.cpus 1-2 + +categories browser untrusted + +category_browser memory.high 1073741824 +category_browser memory.max 1288490188 + +user some_user some_group 1000 diff --git a/data/data/controller/example/cgroup/systemd/setup_cgroup.service b/data/data/controller/example/cgroup/systemd/setup_cgroup.service new file mode 100644 index 0000000..1c1d221 --- /dev/null +++ b/data/data/controller/example/cgroup/systemd/setup_cgroup.service @@ -0,0 +1,12 @@ +[Unit] +Description=Controller: Setup CGroup + +[Service] +#Type=simple +Type=oneshot +User=0 +Group=0 +ExecStart=/usr/local/fll/programs/shared/controller -s /etc/init startup + +[Install] +WantedBy=default.target