diff options
| author | Tobias Geerinckx-Rice <me@tobias.gr> | 2022-10-23 02:00:01 +0200 |
|---|---|---|
| committer | Tobias Geerinckx-Rice <me@tobias.gr> | 2024-08-11 02:00:00 +0200 |
| commit | 4e58dfee6c7456d1e662f66041b8a157efe8710a (patch) | |
| tree | dfe3b18e5feb938490108b9da3078e1aad220ade | |
| parent | beb37ea4ad9999c28cfb60aca5d021851f9a1176 (diff) | |
system: Add privileged-programs to <operating-system>.
* gnu/system.scm (<operating-system>): Add new privileged-programs
field, that defaults to…
(%default-privileged-programs): …this new variable, renamed from…
(%setuid-programs): …this, which is now defined as the empty list.
* doc/guix.texi (Setuid Programs): Rename this…
(Privileged Programs): …to this. Adjust all refs. Update all mentions
of ‘setuid’ (whether in prose, variable names, or code samples) to use
the new ‘privilege[d]’ terminology instead.
(operating-system Reference, X Window, Invoking guix system)
(Service Reference): Adjust likewise.
| -rw-r--r-- | doc/guix.texi | 81 | ||||
| -rw-r--r-- | gnu/packages/crypto.scm | 2 | ||||
| -rw-r--r-- | gnu/services.scm | 1 | ||||
| -rw-r--r-- | gnu/system.scm | 21 |
4 files changed, 60 insertions, 45 deletions
diff --git a/doc/guix.texi b/doc/guix.texi index 03a8c13d0cf..f882eb70e49 100644 --- a/doc/guix.texi +++ b/doc/guix.texi | |||
| @@ -370,7 +370,7 @@ System Configuration | |||
| 370 | * Keyboard Layout:: How the system interprets key strokes. | 370 | * Keyboard Layout:: How the system interprets key strokes. |
| 371 | * Locales:: Language and cultural convention settings. | 371 | * Locales:: Language and cultural convention settings. |
| 372 | * Services:: Specifying system services. | 372 | * Services:: Specifying system services. |
| 373 | * Setuid Programs:: Programs running with elevated privileges. | 373 | * Privileged Programs:: Programs running with elevated privileges. |
| 374 | * X.509 Certificates:: Authenticating HTTPS servers. | 374 | * X.509 Certificates:: Authenticating HTTPS servers. |
| 375 | * Name Service Switch:: Configuring libc's name service switch. | 375 | * Name Service Switch:: Configuring libc's name service switch. |
| 376 | * Initial RAM Disk:: Linux-Libre bootstrapping. | 376 | * Initial RAM Disk:: Linux-Libre bootstrapping. |
| @@ -16965,7 +16965,7 @@ instance to support new system services. | |||
| 16965 | * Keyboard Layout:: How the system interprets key strokes. | 16965 | * Keyboard Layout:: How the system interprets key strokes. |
| 16966 | * Locales:: Language and cultural convention settings. | 16966 | * Locales:: Language and cultural convention settings. |
| 16967 | * Services:: Specifying system services. | 16967 | * Services:: Specifying system services. |
| 16968 | * Setuid Programs:: Programs running with elevated privileges. | 16968 | * Privileged Programs:: Programs running with elevated privileges. |
| 16969 | * X.509 Certificates:: Authenticating HTTPS servers. | 16969 | * X.509 Certificates:: Authenticating HTTPS servers. |
| 16970 | * Name Service Switch:: Configuring libc's name service switch. | 16970 | * Name Service Switch:: Configuring libc's name service switch. |
| 16971 | * Initial RAM Disk:: Linux-Libre bootstrapping. | 16971 | * Initial RAM Disk:: Linux-Libre bootstrapping. |
| @@ -17689,9 +17689,9 @@ touch this field. | |||
| 17689 | Linux @dfn{pluggable authentication module} (PAM) services. | 17689 | Linux @dfn{pluggable authentication module} (PAM) services. |
| 17690 | @c FIXME: Add xref to PAM services section. | 17690 | @c FIXME: Add xref to PAM services section. |
| 17691 | 17691 | ||
| 17692 | @item @code{setuid-programs} (default: @code{%setuid-programs}) | 17692 | @item @code{privileged-programs} (default: @code{%default-privileged-programs}) |
| 17693 | List of @code{<setuid-program>}. @xref{Setuid Programs}, for more | 17693 | List of @code{<privileged-program>}. @xref{Privileged Programs}, for |
| 17694 | information. | 17694 | more information. |
| 17695 | 17695 | ||
| 17696 | @item @code{sudoers-file} (default: @code{%sudoers-specification}) | 17696 | @item @code{sudoers-file} (default: @code{%sudoers-specification}) |
| 17697 | @cindex sudoers file | 17697 | @cindex sudoers file |
| @@ -23700,10 +23700,10 @@ environment, you are unlikely to need this procedure. | |||
| 23700 | 23700 | ||
| 23701 | @defvar screen-locker-service-type | 23701 | @defvar screen-locker-service-type |
| 23702 | Type for a service that adds a package for a screen locker or screen | 23702 | Type for a service that adds a package for a screen locker or screen |
| 23703 | saver to the set of setuid programs and/or add a PAM entry for it. The | 23703 | saver to the set of privileged programs and/or add a PAM entry for it. The |
| 23704 | value for this service is a @code{<screen-locker-configuration>} object. | 23704 | value for this service is a @code{<screen-locker-configuration>} object. |
| 23705 | 23705 | ||
| 23706 | While the default behavior is to setup both a setuid program and PAM | 23706 | While the default behavior is to setup both a privileged program and PAM |
| 23707 | entry, these two methods are redundant. Screen locker programs may not | 23707 | entry, these two methods are redundant. Screen locker programs may not |
| 23708 | execute when PAM is configured and @code{setuid} is set on their | 23708 | execute when PAM is configured and @code{setuid} is set on their |
| 23709 | executable. In this case, @code{using-setuid?} can be set to @code{#f}. | 23709 | executable. In this case, @code{using-setuid?} can be set to @code{#f}. |
| @@ -27877,7 +27877,7 @@ remote servers. Run @command{man smtpd.conf} for more information. | |||
| 27877 | Make the following commands setgid to @code{smtpq} so they can be | 27877 | Make the following commands setgid to @code{smtpq} so they can be |
| 27878 | executed: @command{smtpctl}, @command{sendmail}, @command{send-mail}, | 27878 | executed: @command{smtpctl}, @command{sendmail}, @command{send-mail}, |
| 27879 | @command{makemap}, @command{mailq}, and @command{newaliases}. | 27879 | @command{makemap}, @command{mailq}, and @command{newaliases}. |
| 27880 | @xref{Setuid Programs}, for more information on setgid programs. | 27880 | @xref{Privileged Programs}, for more information on setgid programs. |
| 27881 | @end table | 27881 | @end table |
| 27882 | @end deftp | 27882 | @end deftp |
| 27883 | 27883 | ||
| @@ -40848,8 +40848,8 @@ create and run application bundles (aka. ``containers''). The value for this | |||
| 40848 | service is the Singularity package to use. | 40848 | service is the Singularity package to use. |
| 40849 | 40849 | ||
| 40850 | The service does not install a daemon; instead, it installs helper programs as | 40850 | The service does not install a daemon; instead, it installs helper programs as |
| 40851 | setuid-root (@pxref{Setuid Programs}) such that unprivileged users can invoke | 40851 | setuid-root (@pxref{Privileged Programs}) such that unprivileged users can |
| 40852 | @command{singularity run} and similar commands. | 40852 | invoke @command{singularity run} and similar commands. |
| 40853 | @end defvar | 40853 | @end defvar |
| 40854 | 40854 | ||
| 40855 | @cindex OCI-backed, Shepherd services | 40855 | @cindex OCI-backed, Shepherd services |
| @@ -41649,9 +41649,10 @@ invokation. | |||
| 41649 | 41649 | ||
| 41650 | @c %end of fragment | 41650 | @c %end of fragment |
| 41651 | 41651 | ||
| 41652 | @node Setuid Programs | 41652 | @node Privileged Programs |
| 41653 | @section Setuid Programs | 41653 | @section Privileged Programs |
| 41654 | 41654 | ||
| 41655 | @cindex privileged programs | ||
| 41655 | @cindex setuid programs | 41656 | @cindex setuid programs |
| 41656 | @cindex setgid programs | 41657 | @cindex setgid programs |
| 41657 | Some programs need to run with elevated privileges, even when they are | 41658 | Some programs need to run with elevated privileges, even when they are |
| @@ -41664,46 +41665,48 @@ obvious security reasons. To address that, @command{passwd} should be | |||
| 41664 | (@pxref{How Change Persona,,, libc, The GNU C Library Reference Manual}, | 41665 | (@pxref{How Change Persona,,, libc, The GNU C Library Reference Manual}, |
| 41665 | for more info about the setuid mechanism). | 41666 | for more info about the setuid mechanism). |
| 41666 | 41667 | ||
| 41667 | The store itself @emph{cannot} contain setuid programs: that would be a | 41668 | The store itself @emph{cannot} contain privileged programs: that would be |
| 41668 | security issue since any user on the system can write derivations that | 41669 | a security issue since any user on the system can write derivations that |
| 41669 | populate the store (@pxref{The Store}). Thus, a different mechanism is | 41670 | populate the store (@pxref{The Store}). Thus, a different mechanism is |
| 41670 | used: instead of changing the setuid or setgid bits directly on files that | 41671 | used: instead of directly granting permissions to files that are in |
| 41671 | are in the store, we let the system administrator @emph{declare} which | 41672 | the store, we let the system administrator @emph{declare} which |
| 41672 | programs should be entrusted with these additional privileges. | 41673 | programs should be entrusted with these additional privileges. |
| 41673 | 41674 | ||
| 41674 | The @code{setuid-programs} field of an @code{operating-system} | 41675 | The @code{privileged-programs} field of an @code{operating-system} |
| 41675 | declaration contains a list of @code{<setuid-program>} denoting the | 41676 | declaration contains a list of @code{<privileged-program>} denoting the |
| 41676 | names of programs to have a setuid or setgid bit set (@pxref{Using the | 41677 | names of programs to have a setuid or setgid bit set (@pxref{Using the |
| 41677 | Configuration System}). For instance, the @command{mount.nfs} program, | 41678 | Configuration System}). For instance, the @command{mount.nfs} program, |
| 41678 | which is part of the nfs-utils package, with a setuid root can be | 41679 | which is part of the nfs-utils package, with a setuid root can be |
| 41679 | designated like this: | 41680 | designated like this: |
| 41680 | 41681 | ||
| 41681 | @lisp | 41682 | @lisp |
| 41682 | (setuid-program | 41683 | (privileged-program |
| 41683 | (program (file-append nfs-utils "/sbin/mount.nfs"))) | 41684 | (program (file-append nfs-utils "/sbin/mount.nfs")) |
| 41685 | (setuid? #t)) | ||
| 41684 | @end lisp | 41686 | @end lisp |
| 41685 | 41687 | ||
| 41686 | And then, to make @command{mount.nfs} setuid on your system, add the | 41688 | And then, to make @command{mount.nfs} setuid on your system, add the |
| 41687 | previous example to your operating system declaration by appending it to | 41689 | previous example to your operating system declaration by appending it to |
| 41688 | @code{%setuid-programs} like this: | 41690 | @code{%default-privileged-programs} like this: |
| 41689 | 41691 | ||
| 41690 | @lisp | 41692 | @lisp |
| 41691 | (operating-system | 41693 | (operating-system |
| 41692 | ;; Some fields omitted... | 41694 | ;; Some fields omitted... |
| 41693 | (setuid-programs | 41695 | (privileged-programs |
| 41694 | (append (list (setuid-program | 41696 | (append (list (privileged-program |
| 41695 | (program (file-append nfs-utils "/sbin/mount.nfs")))) | 41697 | (program (file-append nfs-utils "/sbin/mount.nfs")) |
| 41696 | %setuid-programs))) | 41698 | (setuid? #t)) |
| 41699 | %default-privileged-programs))) | ||
| 41697 | @end lisp | 41700 | @end lisp |
| 41698 | 41701 | ||
| 41699 | @deftp {Data Type} setuid-program | 41702 | @deftp {Data Type} privileged-program |
| 41700 | This data type represents a program with a setuid or setgid bit set. | 41703 | This data type represents a program with special privileges, such as setuid |
| 41701 | 41704 | ||
| 41702 | @table @asis | 41705 | @table @asis |
| 41703 | @item @code{program} | 41706 | @item @code{program} |
| 41704 | A file-like object having its setuid and/or setgid bit set. | 41707 | A file-like object to which all given privileges should apply. |
| 41705 | 41708 | ||
| 41706 | @item @code{setuid?} (default: @code{#t}) | 41709 | @item @code{setuid?} (default: @code{#f}) |
| 41707 | Whether to set user setuid bit. | 41710 | Whether to set user setuid bit. |
| 41708 | 41711 | ||
| 41709 | @item @code{setgid?} (default: @code{#f}) | 41712 | @item @code{setgid?} (default: @code{#f}) |
| @@ -41720,18 +41723,18 @@ defaults to root. | |||
| 41720 | @end table | 41723 | @end table |
| 41721 | @end deftp | 41724 | @end deftp |
| 41722 | 41725 | ||
| 41723 | A default set of setuid programs is defined by the | 41726 | A default set of privileged programs is defined by the |
| 41724 | @code{%setuid-programs} variable of the @code{(gnu system)} module. | 41727 | @code{%default-privileged-programs} variable of the @code{(gnu system)} module. |
| 41725 | 41728 | ||
| 41726 | @defvar %setuid-programs | 41729 | @defvar {Scheme Variable} %default-privileged-programs |
| 41727 | A list of @code{<setuid-program>} denoting common programs that are | 41730 | A list of @code{<privileged-program>} denoting common programs with |
| 41728 | setuid-root. | 41731 | elevated privileges. |
| 41729 | 41732 | ||
| 41730 | The list includes commands such as @command{passwd}, @command{ping}, | 41733 | The list includes commands such as @command{passwd}, @command{ping}, |
| 41731 | @command{su}, and @command{sudo}. | 41734 | @command{su}, and @command{sudo}. |
| 41732 | @end defvar | 41735 | @end defvar |
| 41733 | 41736 | ||
| 41734 | Under the hood, the actual setuid programs are created in the | 41737 | Under the hood, the actual privileged programs are created in the |
| 41735 | @file{/run/privileged/bin} directory at system activation time. The | 41738 | @file{/run/privileged/bin} directory at system activation time. The |
| 41736 | files in this directory refer to the ``real'' binaries, which are in the | 41739 | files in this directory refer to the ``real'' binaries, which are in the |
| 41737 | store. | 41740 | store. |
| @@ -42674,7 +42677,7 @@ once @command{reconfigure} has completed. | |||
| 42674 | @end quotation | 42677 | @end quotation |
| 42675 | 42678 | ||
| 42676 | This effects all the configuration specified in @var{file}: user | 42679 | This effects all the configuration specified in @var{file}: user |
| 42677 | accounts, system services, global package list, setuid programs, etc. | 42680 | accounts, system services, global package list, privileged programs, etc. |
| 42678 | The command starts system services specified in @var{file} that are not | 42681 | The command starts system services specified in @var{file} that are not |
| 42679 | currently running; if a service is currently running this command will | 42682 | currently running; if a service is currently running this command will |
| 42680 | arrange for it to be upgraded the next time it is stopped (e.g.@: by | 42683 | arrange for it to be upgraded the next time it is stopped (e.g.@: by |
| @@ -44047,10 +44050,10 @@ In this example, the effect would be to add an @file{/etc/issue} file | |||
| 44047 | pointing to the given file. | 44050 | pointing to the given file. |
| 44048 | @end defvar | 44051 | @end defvar |
| 44049 | 44052 | ||
| 44050 | @defvar setuid-program-service-type | 44053 | @defvar privileged-program-service-type |
| 44051 | Type for the ``setuid-program service''. This service collects lists of | 44054 | Type for the ``privileged-program service''. This service collects lists of |
| 44052 | executable file names, passed as gexps, and adds them to the set of | 44055 | executable file names, passed as gexps, and adds them to the set of |
| 44053 | setuid and setgid programs on the system (@pxref{Setuid Programs}). | 44056 | privileged programs on the system (@pxref{Privileged Programs}). |
| 44054 | @end defvar | 44057 | @end defvar |
| 44055 | 44058 | ||
| 44056 | @defvar profile-service-type | 44059 | @defvar profile-service-type |
diff --git a/gnu/packages/crypto.scm b/gnu/packages/crypto.scm index d5d32d72fb4..b00dc8aa4ca 100644 --- a/gnu/packages/crypto.scm +++ b/gnu/packages/crypto.scm | |||
| @@ -504,7 +504,7 @@ total number of shares generated.") | |||
| 504 | `(#:make-flags (list (string-append "PREFIX=" (assoc-ref %outputs "out"))) | 504 | `(#:make-flags (list (string-append "PREFIX=" (assoc-ref %outputs "out"))) |
| 505 | ;; The "sudo" input is needed only to satisfy dependency checks in the | 505 | ;; The "sudo" input is needed only to satisfy dependency checks in the |
| 506 | ;; 'check' phase. The "sudo" used at runtime should come from the | 506 | ;; 'check' phase. The "sudo" used at runtime should come from the |
| 507 | ;; system's setuid-programs, so ensure no reference is kept. | 507 | ;; system's privileged-programs, so ensure no reference is kept. |
| 508 | #:disallowed-references (,sudo) | 508 | #:disallowed-references (,sudo) |
| 509 | ;; TODO: Build and install gtk and qt trays | 509 | ;; TODO: Build and install gtk and qt trays |
| 510 | #:phases | 510 | #:phases |
diff --git a/gnu/services.scm b/gnu/services.scm index 38692b36661..553ec93a6c7 100644 --- a/gnu/services.scm +++ b/gnu/services.scm | |||
| @@ -47,7 +47,6 @@ | |||
| 47 | #:use-module (gnu packages bash) | 47 | #:use-module (gnu packages bash) |
| 48 | #:use-module (gnu packages hurd) | 48 | #:use-module (gnu packages hurd) |
| 49 | #:use-module (gnu system privilege) | 49 | #:use-module (gnu system privilege) |
| 50 | #:use-module (gnu system setuid) | ||
| 51 | #:use-module (srfi srfi-1) | 50 | #:use-module (srfi srfi-1) |
| 52 | #:use-module (srfi srfi-9) | 51 | #:use-module (srfi srfi-9) |
| 53 | #:use-module (srfi srfi-9 gnu) | 52 | #:use-module (srfi srfi-9 gnu) |
diff --git a/gnu/system.scm b/gnu/system.scm index 4ac619d4eca..44f93f91d17 100644 --- a/gnu/system.scm +++ b/gnu/system.scm | |||
| @@ -77,6 +77,7 @@ | |||
| 77 | #:use-module (gnu system locale) | 77 | #:use-module (gnu system locale) |
| 78 | #:use-module (gnu system pam) | 78 | #:use-module (gnu system pam) |
| 79 | #:use-module (gnu system linux-initrd) | 79 | #:use-module (gnu system linux-initrd) |
| 80 | #:use-module (gnu system privilege) | ||
| 80 | #:use-module (gnu system setuid) | 81 | #:use-module (gnu system setuid) |
| 81 | #:use-module (gnu system uuid) | 82 | #:use-module (gnu system uuid) |
| 82 | #:use-module (gnu system file-systems) | 83 | #:use-module (gnu system file-systems) |
| @@ -130,6 +131,7 @@ | |||
| 130 | operating-system-keyboard-layout | 131 | operating-system-keyboard-layout |
| 131 | operating-system-name-service-switch | 132 | operating-system-name-service-switch |
| 132 | operating-system-pam-services | 133 | operating-system-pam-services |
| 134 | operating-system-privileged-programs | ||
| 133 | operating-system-setuid-programs | 135 | operating-system-setuid-programs |
| 134 | operating-system-skeletons | 136 | operating-system-skeletons |
| 135 | operating-system-sudoers-file | 137 | operating-system-sudoers-file |
| @@ -174,6 +176,7 @@ | |||
| 174 | 176 | ||
| 175 | local-host-aliases ;deprecated | 177 | local-host-aliases ;deprecated |
| 176 | %root-account | 178 | %root-account |
| 179 | %default-privileged-programs | ||
| 177 | %setuid-programs | 180 | %setuid-programs |
| 178 | %sudoers-specification | 181 | %sudoers-specification |
| 179 | %base-packages | 182 | %base-packages |
| @@ -301,7 +304,10 @@ VERSION is the target version of the boot-parameters record." | |||
| 301 | 304 | ||
| 302 | (pam-services operating-system-pam-services ; list of PAM services | 305 | (pam-services operating-system-pam-services ; list of PAM services |
| 303 | (default (base-pam-services))) | 306 | (default (base-pam-services))) |
| 307 | (privileged-programs operating-system-privileged-programs ; list of <privileged-program> | ||
| 308 | (default %default-privileged-programs)) | ||
| 304 | (setuid-programs operating-system-setuid-programs | 309 | (setuid-programs operating-system-setuid-programs |
| 310 | ;; For backwards compatibility; will be removed. | ||
| 305 | (default %setuid-programs)) ; list of <setuid-program> | 311 | (default %setuid-programs)) ; list of <setuid-program> |
| 306 | 312 | ||
| 307 | (sudoers-file operating-system-sudoers-file ; file-like | 313 | (sudoers-file operating-system-sudoers-file ; file-like |
| @@ -821,7 +827,8 @@ bookkeeping." | |||
| 821 | (service host-name-service-type host-name) | 827 | (service host-name-service-type host-name) |
| 822 | procs root-fs | 828 | procs root-fs |
| 823 | (service privileged-program-service-type | 829 | (service privileged-program-service-type |
| 824 | (operating-system-setuid-programs os)) | 830 | (append (operating-system-privileged-programs os) |
| 831 | (operating-system-setuid-programs os))) | ||
| 825 | (service profile-service-type | 832 | (service profile-service-type |
| 826 | (operating-system-packages os)) | 833 | (operating-system-packages os)) |
| 827 | boot-fs non-boot-fs | 834 | boot-fs non-boot-fs |
| @@ -860,7 +867,8 @@ bookkeeping." | |||
| 860 | (service hosts-service-type | 867 | (service hosts-service-type |
| 861 | (local-host-entries host-name))) | 868 | (local-host-entries host-name))) |
| 862 | (service privileged-program-service-type | 869 | (service privileged-program-service-type |
| 863 | (operating-system-setuid-programs os)) | 870 | (append (operating-system-privileged-programs os) |
| 871 | (operating-system-setuid-programs os))) | ||
| 864 | (service profile-service-type (operating-system-packages os))))) | 872 | (service profile-service-type (operating-system-packages os))))) |
| 865 | 873 | ||
| 866 | (define* (operating-system-services os) | 874 | (define* (operating-system-services os) |
| @@ -1239,8 +1247,7 @@ use 'plain-file' instead~%") | |||
| 1239 | ;; when /etc/machine-id is missing. Make sure these warnings are non-fatal. | 1247 | ;; when /etc/machine-id is missing. Make sure these warnings are non-fatal. |
| 1240 | ("DBUS_FATAL_WARNINGS" . "0"))) | 1248 | ("DBUS_FATAL_WARNINGS" . "0"))) |
| 1241 | 1249 | ||
| 1242 | (define %setuid-programs | 1250 | (define %default-privileged-programs |
| 1243 | ;; Default set of setuid-root programs. | ||
| 1244 | (let ((shadow (@ (gnu packages admin) shadow))) | 1251 | (let ((shadow (@ (gnu packages admin) shadow))) |
| 1245 | (map file-like->setuid-program | 1252 | (map file-like->setuid-program |
| 1246 | (list (file-append shadow "/bin/passwd") | 1253 | (list (file-append shadow "/bin/passwd") |
| @@ -1262,6 +1269,12 @@ use 'plain-file' instead~%") | |||
| 1262 | (file-append util-linux "/bin/mount") | 1269 | (file-append util-linux "/bin/mount") |
| 1263 | (file-append util-linux "/bin/umount"))))) | 1270 | (file-append util-linux "/bin/umount"))))) |
| 1264 | 1271 | ||
| 1272 | (define %setuid-programs | ||
| 1273 | ;; Do not add to this list or use it in new code! It's defined only to ease | ||
| 1274 | ;; transition to %default-privileged-programs and will be removed. Some rare | ||
| 1275 | ;; use cases already break, such as the obvious (remove … %setuid-programs). | ||
| 1276 | '()) | ||
| 1277 | |||
| 1265 | (define %sudoers-specification | 1278 | (define %sudoers-specification |
| 1266 | ;; Default /etc/sudoers contents: 'root' and all members of the 'wheel' | 1279 | ;; Default /etc/sudoers contents: 'root' and all members of the 'wheel' |
| 1267 | ;; group can do anything. See | 1280 | ;; group can do anything. See |
