SUPER.TAB(5)
π super.tab β welcome to the SUPER.TAB(5) glow-up π
okay so this is the File Formats Manual page for super.tab, and it's literally the blueprint for how super(1) decides who gets to do what. grab a snack, we're doing this together π«Ά
β¨ NAME β¨
super.tab β the database of restricted commands for super(1) π
πΈ DESCRIPTION πΈ
so the super.tab file holds the restrictions on who can execute commands with super(1). but wait, there's more β it can also hold options that change the uid and/or gid that a command runs under, plus the list of environment variables that get yeeted before a command executes, and honestly a bunch of other stuff. and like, you're expected to already know the super(1) man page, bestie. that's the prerequisite, no cap. π
π the "i'm not reading all that" speedrun π
okay if you're trying to dodge this entire lengthy man page (valid, honestly), here's the minimum you need:
Rule one. for a user to successfully run a command by typing super commandName, the absolute minimum entry in super.tab looks something like:
commandName FullPathToCommand userName
for example, this entry:
cdmount /usr/local/bin/cdmount wally,dolly
is saying that users wally and dolly may execute the /usr/local/bin/cdmount program by typing super cdmount. iconic. that's it, that's the whole vibe. β¨
Rule two. when you're defining options in the super.tab file, remember that all options are orthogonal to each other, and it genuinely does not matter what order they show up in on a control line. order? irrelevant. we love a chill queen. π
Rule three. global options β the ones defined on a :global or :global_options line β take effect immediately after the defining line. they're valid until the end of the input, or until there's a countermanding global option or pattern, and they get overridden by local (per-command) options, which are defined on a regular control line. so like, global is the main character until local walks in and steals the scene. π
π the options situation π
ngl, super has a great many options you can set inside the super.tab file, but here's the thing: none of them are required for security, so you do NOT have to be intimately familiar with this entire document just to use super securely. breathe. you're fine. π§
the most important options you'll probably want are:
- (a) a logging option, like
logfile=xxxorsyslog=y; and - (b)
patterns=shell, so that the default regular-expression interpretation of wildcards gets changed to the much more convenient shell-style glob patterns. lowkey a game changer fr fr.
π what super does by default π
unless you modify things with options in the super.tab file, super executes commands using:
- effective uid root π
- unchanged real uid and gid
- no supplementary groups
- no open file descriptors save
0,1, and2 - no environment variables except a few with safe values (see
super(1)) - signal handling reset to the default
that's the default package, no add-ons. π
π¦ the .supertab plot twist π¦
when super uses a command from a user-supplied super file β that's .supertab in the user's home directory β these rules get modified, and it's giving different rules, same energy:
- the real and effective uid and gid are set to the owner of the
.supertabfile - the supplementary groups are set to the user's login groups
π super.init enters the chat π
if the special supplementary file named super.init exists, it is implicitly included at the start of super.tab and every .supertab file. β¨
here's the tea on it:
- it lives in the same directory as
super.tab - it must be owned by
root - it should be world-readable
- it provides a uniform configuration file applied to every super-executed command
heads up bestie: the configuration file should contain entries that are appropriate for use in both thesuper.tabfile and any per-user supertab file. and it is not a good idea to include commands in thesuper.initfile. just... don't. π«
the variable IS_USERTAB is defined to be yes if super is processing a per-user .supertab file, and no otherwise. so this pair of entries could be used in a super.init file to allow different initialization for regular use and per-user use:
:if $IS_USERTAB == yes :include /etc/super.init.per-user
:if $IS_USERTAB != yes :include /etc/super.init.as-root
(and the use of variables and conditional expressions is explained further down, in the Variables and Conditionally-included Control Lines sections respectively. we'll get there, i promise. π«Ά)
π the format, aka how control lines work π
the super.tab file is formatted as a series of control lines of the form:
CmdPat FullPath \
Options PermittedUsers PermittedTimes
or
CmdPat1::FullPath1 CmdPat2::FullPath2 ... \
Options PermittedUsers PermittedTimes
or
:BuiltinCmd arguments
the Options, PermittedUsers, and PermittedTimes may be mixed together in any order. at least one PermittedUsers field is required, but neither Options nor PermittedTimes are required. so like, PermittedUsers is the non-negotiable friend in the group chat. π
for each control line, Super matches the following:
- the user-entered command to a
CmdPat; - the
{user,group,host}triplet to aPermittedUsersentry; and - the current time to a
PermittedTimesentry (the default permits any time).
if these conditions are not satisfied, super "falls through" and tries the next control line. no hard feelings, just moving on. π¦
π a lil example, as a treat π
for example, the entry:
renice /etc/renice jack@hill jill@bucket time~8-17
specifies that between hours 8:00 and 17:00, user Jack can renice any process on host hill, and user Jill can do so on host bucket, by simply typing:
super renice <args>
periodt. β¨
π quoting, comments, and whitespace π
control lines begin in column 1, and the fields are whitespace-separated.
note that you can either use a single CmdPat and FullPath, separated by whitespace, or you can use a series of them in one control line by putting :: between each CmdPat and FullPath pair.
whitespace may be included in a field by enclosing text in single- or double-quotes. the quoting is shell-like, in the sense that quotemarks don't have to surround the entire field, and you can switch between quotemark types in a single entry. for instance:
X"a b"Y'd e'
is equivalent to:
"Xa bYd e"
comments begin with a # and continue to the end of a line. π¬
there can also be blank or comment lines without any control data. we love a lil breathing room. πΈ
π line continuation (the backslash era) π
a control line may be continued by preceding the newline with a backslash, and indenting the continuation line with whitespace.
when the multiple-line entry is read:
- the text just before the backslash-newline is not modified (any whitespace before the backslash will be kept)
- the backslash-newline-whitespace sequence is either eliminated entirely or treated as whitespace
the rule is simple, bestie: following a letter, digit, or underscore, it is treated as whitespace. otherwise, it is eliminated.
this means that:
Cmd File user1\
user2\
user3
is equivalent to:
Cmd File user1 user2 user3
on the other hand:
Cmd File {user1,\
user2,\
user3}
is equivalent to:
Cmd File {user1,user2,user3}
that is, the sensible interpretation is done in both cases. β¨ we love an intuitive queen.
π«Ά why the indentation tho π«Ά
the indentation requirement for continuation lines helps super catch typos. π΅οΈββοΈ
and β important β comments may be placed before each backslash-newline pair, not just at the end of a continued control line. so you can sprinkle your lil notes everywhere, you absolute icon. π¬π
(more of this page coming, bestie β don't go anywhere) π
π¦ The CmdPat Field π¦
okay so bestie, when a user types:
super cmd [ args ]
the cmd gets searched for in the super.tab file. Then that cmd is matched against each pattern CmdPat. it's giving matchmaker energy, fr fr. π
β¨ Basic Use: Simple Command Patterns without Wildcards β¨
Typically, a CmdPat just uses plain characters without any special pattern-matching characters, so a cmd must be the same as the CmdPat string. For example:
skill /usr/local/bin/skill user1 user2 user3
Here, any user in the list {user1, user2, user3} may type super skill to execute /usr/local/bin/skill. slay. π
π₯ Advanced Use: Command Patterns with Wildcards π₯
More generally, a CmdPat can be either an ed-style pattern (regex β the BSD 4.x syntax used in the re_comp()/re_exec() routines), POSIX regular expressions, or a Bourne-shell-style pattern. You can set the pattern style using the global option patterns (see below). The default is regex for historical reasons; however, shell-style patterns are easier to use without errors, and most sites should use shell-style patterns. In all cases the patterns are extended to support csh-style brace expansion. For instance, a{x,y,z}b stands for the set of patterns axb ayb azb. Don't put any whitespace inside the braces! no cap, that's a trap. π©
For convenience, there is always an implied set of braces around an entire pattern. This means that any comma-separated list a,b,c is interpreted as {a,b,c}, and is very helpful so that you don't have to worry about getting braces just right when you build complex lists of out of (say) variables containing other lists of users. the way that saves you from brace-induced meltdowns. π
All pattern matching is anchored: patterns are forced to match the entire cmd string. periodt.
If the CmdPat is matched and the other conditions are met (such as the user being in the PermittedUser list to execute this command), FullPath gives the name of the actual command that will be executed with execve(). If FullPath contains an asterisk, the asterisk is first replaced by the user's cmd. iconic behavior.
If you put special pattern-matching characters into the CmdPat, but don't put an asterisk into FullPath, you have simply given more ways a user can execute the same FullPath. This isn't useful, and in fact isn't a good idea at all. The power of using patterns in the CmdPat comes when FullPath includes an asterisk. For instance, a SysV-based host might have an entry in the super.tab file that looks like:
/usr/bin/{lp,lpstat,disable,enable,cancel} * \
:operators uid=0
This would allow anybody in the "operators" group to have root access to the line printer commands (the uid=0 tells super to set the real uid to 0, not just the effective uid). For instance, if the user typed:
super /usr/bin/disable some_printer
then the FullPath (*) would be replaced by /usr/bin/disable, which would be the command to exec. big brain. π§
More conveniently, the super.tab file could have a line like:
{lp,lpstat,disable,enable,cancel} /usr/bin/* \
:operators uid=0
In this case, the user can type
super disable some_printer
The asterisk-replacement ability also lets a user execute any of an entire directory of commands, using a super.tab entry like the following:
op/* /usr/local/super/scripts/* :operators uid=0
In this case, the user can type
super op/xyz
and super will execute /usr/local/super/scripts/op/xyz. okay that's kinda iconic.
The asterisk-replacement capability is useful but potentially dangerous, because it may unintentionally open the door to programs you hadn't intended to give away. It is a sensible precaution to restrict asterisk-replacement to entries where the valid-user list includes trusted users only. > β οΈ bestie, do NOT hand out asterisks like candy. that's how you get got.
If you completely trust some users, but want logging of all actions executed as root, you could use:
/* * ReallyReallyTrustedUsers
or
/.* * ReallyReallyTrustedUsers
(depending on whether patterns=shell, patterns=regex, or patterns=posix).
The trusted users can now execute any command. Note that the pattern begins with a slash, to ensure that the cmd must be an absolute path β this helps avoid accidental execs of the wrong program. safety first, bestie. π«Ά
If you were really going to give everything away as shown above, you'd probably want to exclude any public-area workstations, require the trusted users to periodically give their passwords, and set the real uid=root (instead of just the effective uid), so the entry might be modified to read something like:
/* * TrustedUsers \
!{PatternsOfPublicWorkstations} \
password=y timeout=5 uid=0
πΈ The FullPath Field πΈ
The FullPath field gives the name of the actual command that will be executed, and if it contains an asterisk, the asterisk is first replaced by the user's cmd string. The FullPath can optionally contain a list of initial arguments that precede any arguments passed by the user. For example,
xyz "/usr/local/bin/blah -o1 -o2 -xrm 'a b c'" ...
specifies that when a valid user types super xyz, the command to execute is /usr/local/bin/blah and its arguments will be
argv[1]: -o1
argv[2]: -o2
argv[3]: -xrm
argv[4]: a b c
followed by any arguments that the user put on the super command line. Note: asterisk replacement is only done on the filename part of the FullPath, not on the arguments. You can safely include asterisks in the argument list. For security, the user's cmd may not contain any whitespace or backslashes. no whitespace, no backslashes, no exceptions. π
The FullPath string is parsed using rules similar to the Bourne shell rules for backslashes in quoted strings, namely:
(a) backslash-newline is discarded;
(b) Otherwise, if outside a quoted substring, \x β plain x, which
will not be treated as a delimiter, quotemark, or comment
character;
(c) Otherwise, inside a quoted substring of FullPath:
\\ β \;
\q β q, where q is the quote character that encloses the
FullPath string;
other backslashes are preserved: \x β \x.
After writing a command with such backslash escapes, you should certainly use super -d cmd to check that your args are being parsed as expected before you offer this command to your users. literally test it, bestie. π
The same cmd can be listed several times in the super.tab file, in which case the first entry that allows the user to execute the command is chosen. The EXAMPLES section shows how this can be useful.
π Permitted Users π
Permitted users are those who may execute the specified Cmd's. Entries for any number of permitted users are given after the CmdPat and FullPath fields. Local options β options that apply to this command only β may also appear anywhere after the FullPath. Options are distinguished from permitted users because options all have the form key=value, whereas permitted-user entries may not contain unescaped equal signs. Each whitespace-separated word is a pattern in one of the formats
[user~]user[:][@host][user~]:group[@host][user~]user[:group][@host]
Note that the user~ part is optional. The user's login name must match the user pattern; the user must belong to a group whose name matches the group pattern; and the hostname must match the host pattern. If the user, group, or host part is not given, there are no corresponding restrictions.
If the user is root, super acts as if all permitted-user patterns are preceded by the pattern user~root β that is, root's rule is default-allow, instead of the default-deny rule that applies to all ordinary users. root really said "main character energy". π
By default, the group field is first matched against named groups to which the user belongs, and then against the user's decimal gid β this allows the user to be put in a group in the /etc/passwd file that isn't given a name in the /etc/group file. (If you want to change the rules for using decimal gid, see the use of MATCH_DECIMAL_UID and MATCH_DECIMAL_GID in super.c for details.)
Since you can restrict users to particular hosts, a single super.tab file can be shared among many different machines. If the host part is of the form +xyz, then xyz is interpreted as a netgroup name and any host in netgroup xyz is matched. In that case, xyz is taken literally, and not interpreted as a pattern to be matched. Note: netgroup lookup is only implemented if the function innetgr() is available.
If the host part doesn't match the hostname, it might be because the pattern and actual hostnames contain two different (but both valid) incomplete versions of the fully-qualified domain name (FQDN). By default, if the host part fails to match the hostname, the FQDN is looked up and all of the ways of naming the host are matched against the pattern. For example, if the FQDN is spacely.sprockets.com, super will first try spacely.sprockets.com, then spacely.sprockets, and finally spacely. This can be turned off; see option gethostbyname. (You might want to turn it off because using nameserver lookup can reduce security a bit β your host may query a nameserver on another host to obtain the FQDN, and (a) that nameserver or an intermediate host along the way could have been subverted, or (b) another host could impersonate the nameserver. In either case your computer could receive incorrect hostnames.) > β οΈ security tea: nameserver lookups can be sketchy. turn it off if you're paranoid.
The patterns for valid users, groups, and hosts follow the same rules for the CmdPats, described above: they can be entered with either ed-style or Bourne-shell-style patterns (depending on the setting of the patterns global option); csh-style brace expansion is allowed; and all pattern matching is anchored: patterns are forced to match the entire username, groupname, or hostname.
To make it easy to exclude some users/groups/hosts, any of these patterns can be negated by prefixing the pattern with !. If a negated pattern is matched, the user may not execute the command, even if there was a previous non-negated pattern that the user matched. All patterns are read left-to-right, and the last matched pattern wins. Thus if the user/group/host list is
j.* !jo
or
user~j.* !user~jo
then the first entry allows any username beginning with j to execute the command, but the second entry disallows user jo. If entered in the reverse order,
!jo j.*
then the second entry, j.*, allows all users beginning j, and therefore the first entry has no effect. last one wins, so order matters bestie. π
β° Permitted Times
ok so the time condition is the vibe check for when a command is allowed to match. If the execution time isn't acceptable, super just ignores the control line and "falls through" to peek at the next entry β same energy as when the user/group/host isn't acceptable. A time condition looks like:
time~pattern
and the patterns look like:
hh[:mm]-hh[:mm][/dayname]β e.g.13:30-17/monday{<,>,<=,>=}hh[:mm][/dayname]β e.g.<17/tuesdaynameβ e.g.Friday
The first form straight up names an interval during which the command may be used. Times may not go past midnight β so to specify the night between Monday and Tuesday you gotta do something like:
time~{17:30-24:00/mon,0-8/tues}
The second form lets you use logical operators, and the Monday-night example could equally have been rendered as:
time~{>17:30/mon,<8/tues}
(There is a tiny difference in the two examples above: in the first example, the time range includes 17:30 and 8:00; in the second example, the time range is 17:31-07:59. Use time~{>=17:30/mon,<=8/tues} to make the interpretation identical to the first example.) β¨
If there are a series of time patterns, they are evaluated left-to-right, and the rightmost matching pattern is used. To permit execution between 17:30 Monday and 8:00 Tuesday, but exclude 0:00 to 1:00 Tuesday, use:
time~{>=17:30/mon,<=8/tues} !time~{0-1/tues}
By default, valid daynames are English, but if your system supports the setlocale(3) function, the global option lang=zzz will set the valid names to those of locale zzz. Valid daynames are either (a) the full names of the chosen language; (b) an official abbreviated day name for that language; (c) a 3-or-more character abbreviation of the full weekday; or (d) *, meaning any day. (You can check on super's valid daynames by executing super -d, which will show the default names of the weekdays at or near the top of its debugging output, and show the new weekday names that take effect when the lang=zzz option is encountered.)
Time patterns have a special defaulting rule when the execution time is not in one of the intervals in the time list:
- if all time patterns are negated, super permits execution at any time not in one of the listed intervals;
- otherwise, there is at least one non-negated pattern, and super defaults to deny execution at times outside the specified acceptable intervals.
The reason is that the natural interpretation of a series of negated conditions, such as
!time~{0-8,17-24} !time~{sat,sun}
is to infer that all other times are acceptable for execution. On the other hand, if there are any ordinary, non-negated times, such as
time~8-17/{mon,tues,wed,thu,fri}
the natural interpretation is that any times not explicitly mentioned are not acceptable. π€
Note that explicit braces are important in the above list. If they were missing, the implied braces around the entire pattern would render this equivalent to time~8-17/mon time~tues time~wed time~thu time~fri That is, the permitted times are 8-17h on Monday, and any time on Tuesday through Friday. π
π Global Conditions
Global options and conditions affect the overall super processing. To set them, you must use a line like
:global Global Options And Patterns
or
:global_options Global Options And Patterns
For backwards compatibility, you can alternatively use
/ / GlobalOptionsAndPatterns
but this use is discouraged. π ββοΈ
These so-called "global" options and conditions actually take effect immediately after the line on which they appear, and are valid until the end of the input or until there is a countermanding global option or pattern. To have a global option or pattern affect the entire file, you must place it as the first non-comment line of the super.tab file.
If there are any PermittedUser or PermittedTime conditions on the global settings line, they are applied to each following command in the super.tab file. The conditions look like
:global cond cond ... <> cond cond ...
PermittedUser and PermittedTime conditions to the left of <> are processed before the local (per-command) conditions; conditions to the right of <> are processed after the per-command conditions. If <> is missing, all conditions are processed after the local conditions. Example 1:
:global jan <> !@+badhosts
says that user jan can usually execute any command, but under no circumstances will a user on any host in netgroup badhosts be allowed to execute any command. (User jan will not be allowed to execute a command if the per-command conditions disallow it, or if jan is on one of the badhosts computers).
Example 2:
:global !root <>
changes root's default setting from default-allow to default-deny, just like ordinary users. Root will only be given execute permission for entries that explicitly allow root on the per-entry line. π
Global PermittedUser (PermittedTime) conditions take effect on the line on which they are defined, and are good until another set of global PermittedUser (PermittedTime) conditions is entered on another :global_option line. That is, a new global condition line replaces any previous global conditions.
One sensible approach to using global conditions is to put conditions that allow users to execute commands before the per-command conditions are processed, and to put negating patterns (for users/groups/hosts that are never to be allowed to execute anything) after the per-command conditions.
(Global options are discussed below, together with local options).
π§ Conditionally-included Control Lines
Control lines can be conditionally included by using the :if control line. This can be helpful when using a single super.tab file for hosts with different architectures, or hosts in different NIS domains, etc. The syntax is:
:if left op right moreText
The expression left op right is evaluated, and if true, moreText is evaluated as an ordinary control line. The valid comparison operators are:
==β string equality!=β string inequality~β glob match stringleftagainst patternright!~β negated glob-match.
For example, you could include a file of commands only valid on Sun4-type machines as follows:
:if $UNAME_MACHINE ~ sun* \
:include /Path/To/Sun4/File
(UNAME_MACHINE is a variable automatically defined by super; see the following section on variables.)
If you wanted to exclude Sun4c-type machines from using the file, you could modify this to be:
:if $UNAME_MACHINE ~ sun* \
:if $UNAME_MACHINE != sun4c \
:include /Path/To/Sun4/File
There are no boolean operators provided, but note that there is an implicit boolean and available by concatenating :if commands, as shown in the second example above. π¦
β¨ Variables β¨
Super is like, so into variables, bestie β they make it easy to handle entries that are duplicated or built out of other entries. You define them by typing
:define VariableName VariableDefinition
or you can import them from the environment with
:getenv [EnvVarName...]
If you use :getenv, then the values of any imported environment variables may only contain these "safe" characters: -/:+._a-zA-Z0-9. If "bad" characters show up in a value, the whole value gets replaced with an empty string. And note: these imported variables do not enter the environment of any executed command; they just become part of the super.tab variable set.
The VariableName should be made up only of letters, digits, and/or underscore. (You can actually use any characters you want, but super doesn't pinky-promise to work correctly if you use characters outside the standard set.)
The VariableDefinition begins at the first non-whitespace character after the VariableName and continues up to but not including the final newline. Comments embedded on the variable definition line(s) are deleted before the variable definition is stored. A variable definition can be continued across multiple lines by putting a backslash before each newline, and indenting the continuation line with whitespace. Just like for regular control lines, the backslash-newline-whitespace sequence is treated as whitespace if it follows a letter, digit, or underscore; otherwise, it's eliminated. For example,
:define Users user1,\
user2,\
user3
and
:define Users user1,user2,user3
are equivalent definitions.
Unlike Makefiles, the variable definitions are not scanned first and then the file re-scanned. Instead, variables take effect at the point they are defined, and stay in effect until they're re-defined or end of file β so variable definitions must come before their first use in the file. Periodt.
Variables can contain other variables (which must already be defined). Variable substitution happens when a line is first read. A line is never re-scanned after variable substitution.
You use variables in a file by typing
$VariableName
or
$(VariableName)
The special variable $$ is replaced by a single $. Any other name $X (where X is not a letter, digit, or underscore) is an error. Not cute.
Because a line is never re-scanned after variable substitution, this sequence:
:define A $$
:define B A
:define C $B $$B
$C
defines C to be simply A $B.
Variables can be super helpful for grouping users or hosts together. For example, you might restrict access to a command so it can't be run from a public-access workstation:
:define Room103_WS hosta,hostb,hostc,hostd
:define Room105_WS hoste,hostf,hostg,hosth
:define Room106_WS +nonprivate
:define PublicWorkstations $Room103_WS,$Room105_WS,$Room106_WS
SomeCmd FullPathHere !@$(PublicWorkstations)
In that example, we've taken advantage of the implied braces that are always placed around any pattern, so the comma-separated list of workstations gets brace-expanded into !@hosta !@hostb ... !@hoste !@hostf ... !@+nonprivate. Slay.
Some variables are automatically defined by super.
After super figures out whether it's processing a per-user .supertab (see super(1)), it defines IS_USERTAB to be yes if super is processing a per-user .supertab file, and no otherwise. This lets super.init act differently depending on how it's being invoked.
When the top-level super.tab file is opened, SUPER_OWNER is set to the login name of the owner, and SUPER_HOME is set to the home directory of the owner. This can be useful in per-user .supertab files, especially when they include files shared among several accounts. For example, each person's .supertab file could be simply
:include /opt/proj/common.supertab owner=cristy
Then, the /opt/proj/common.supertab file can use entries like:
:global logfile=$SUPER_HOME/.superlog
* /project/tools/$SUPER_OWNER/* :toolgroup
Because the SUPER_HOME and SUPER_OWNER variables apply to the top-level per-user files, they always refer to per-user locations.
Super defines the built-in variable CALLER to be the login name of the account invoking super, and CALLER_HOME is the home directory of $CALLER. Sample use:
sam /usr/sbin/sam group~operator uid=0 \
env=DISPLAY \
setenv=XAUTHORITY=$CALLER_HOME/.Xauthority
Here, the operator group can execute sam as root, and the GUI will display at the caller's display (because of env=DISPLAY). Since the XAUTHORITY environment variable is set to the caller's .Xauthority file, this gives the caller access to the same display(s) to which s/he already has access.
The following variables are defined when super starts up. They can be useful in conditionally-included lines (:if lines). If your host doesn't supply these functions, or doesn't support some of the values that super tries to fetch, the corresponding variable will be initialized to an empty string. (Use super -b to print the names and values of all builtin variables. This makes it simple to see what variable values to check in :if lines.)
From the gethostname() or sysinfo() function:
HOSTNAMEβ Hostname, possibly canonicalized.HOSTβ Hostname, short (unqualified).
From the getdomainname() function:
NIS_DOMAINβ domain set for NIS purposes.
From the sysinfo() function:
SI_SYSNAMEβ Name of operating system.SI_HOSTNAMEβ Name of node.SI_RELEASEβ Release of operating system.SI_VERSIONβ Version field ofutsname.SI_MACHINEβ Kind of machine.SI_ARCHITECTUREβ Instruction set arch.SI_HW_SERIALβ Hardware serial number.SI_HW_PROVIDERβ Hardware manufacturer.SI_SRPC_DOMAINβ Secure RPC domain.
From the uname() function:
UNAME_SYSNAMEβ Operating system name.UNAME_NODENAMEβ The nodename.UNAME_RELEASEβ Operating system release.UNAME_VERSIONβ Operating system version.UNAME_MACHINEβ Machine hardware name (class).
π Options π
The config file can specify a whole buffet of options, like requiring the user's password before executing some commands, or restricting the command-line arguments to match certain patterns.
Options are handled very differently from conditions (conditions include user, group, host, and time). If a control line's conditions aren't met, super falls through and tries the next control line in the file. After finding an acceptable control line, super will execute the command if the options are satisfied; otherwise, it stops and doesn't search the super.tab file any further. No take-backs.
Options can be divided into (a) local options, which are defined on a regular control line and apply only to that control line; and (b) global options, which are defined on a :global or :global_options line, take effect immediately after the line, and are valid until the end of the input or until there's a countermanding global option or pattern.
All options are orthogonal to each other. It doesn't matter what order they appear on a control line.
Some options can be given as either local or global options. If both are used, the local setting overrides the global one.
Two special names can be used with any of the options that take user or group ids as arguments: owner=xxx, uid=xxx, euid=xxx, gid=xxx, egid=xxx, u+g=xxx, groups=xxx, addgroups=xxx. These names are <owner>, meaning the owner of the file to be executed (or the owner's group, whichever is appropriate in the context); and <caller>, meaning the owner or group of the user calling super. The angle brackets are literally part of the name. These have the same values as the built-in variables CALLER and OWNER (see the Variables section, above). For example, the options
gid=Foo uid=<caller>
would change the group to Foo, but leave the uid unchanged.
The recognized options are:
πΈ Group 1. Options Affecting How Superfiles Are Read and Processed πΈ
patterns=xxxβ (Global) Specifies the pattern-matching type for conditions and options. The stringxxxmust be one of:posixβ patterns are POSIX regular expressions. You can useposix/extendedfor extended regular expressions;posix/icasefor case-insensitive regular expressions; orposix/extended/icasefor both. See your regular-expression man pages for details.regexβ patterns are ed-style regular expressions, using the rules embodied in the BSD 4.x routinesre_comp()/re_exec(), with the addition of csh-style brace expansion. This is the default for historical reasons, but most people prefer to use shell-style patterns here, and it's recommended that you putpatterns=shell(see below) in your global options list.shellβ patterns are approximately Bourne-shell style, with the addition of csh-style brace expansion and the special[[chars]]pattern. The patterns are formed from:\xβ forcexto be a plain character;?β matches any single character;*β matches any sequence of 0 or more chars;[chars]β matches any single character in the set;[^chars]β matches any single char NOT in the set;[[chars]]β When the pattern begins with[[, and ends with]], then each and every character in the string must match the ordinary square-bracket pattern[chars](or[^chars]).^patβ inverts the sense of the match β the string must NOT match the pattern.
lang=zzzβ (Global) This option sets the language used for weekdays (in time conditions). Here,zzzmay be any locale available on your host. For example,lang=dewould typically cause super to use German names. The default is the C locale, hence English names.relative_path=y|nβ (Global) Ify,FullPathNamescan be relative instead of absolute. By default this is disallowed, because it is almost always a very foolish (unsafe) thing to do. Like, don't.group_slash=y|nβ (Global) Say y and group names are allowed to have a slash in them π©·. By default this is NOT allowed, and that's on purpose, bestie β it's howsupercatches a whole class of typos in thesuper.tabfile. Specifically, it catches the oopsie where somebody writes an entry likeCmd:Fileinstead of the requiredCmd::File. The whole problem is thatCmd:Filelooks syntactically likeuser:group, so it can totally get mistaken for a legit piece of a control line π. But the filename is gonna contain a slash β unless you went and enabled therelative_pathoption, which, respectfully, was unwise π β so disallowing slashes letssuperflag that line as syntactically invalid. Slay. β¨gethostbyname=y|nβ (Global) Turns the use ofgethostbyname()on or off for finding the fully-qualified domain name π¦. (Go read the discussion in the Permitted Users section, it talks about the security issues that come with enabling this.) Default: enabled (if your host supportsgethostbyname()).
π Group 2. Logging Options. π
logfile=fnameβ (Global) Enables logging to a local file πΎ. Every single invocation ofsuper(except the ones for help) drops an entry into the filefname. Every. Single. One.loguid=xxxβ (Global) If logging is turned on withlogfile=fname, then the logfile gets opened for writing usinguid=xxx(andxxxcan be a username or a numeric uid) π. This option exists so you can have the file created/opened under some other uid that actually has cross-host access, like the uid of a system manager. (Seetimestampuid=xxxfor extra comments on this.) Default:loguid=0.mail="mail-command"β (Local|Global) Notices aboutsuperfailures get piped to the shell commandmail-commandπ§. This is totally independent of whatever you set for thelogfileandsyslogoptions. For example,mail="mail -s Super joeblow"will cause error messages to be mailed to userjoeblow(on some systems you might need to swap inmailxformail). Note: themail-commandgets executed by handing it as an argument topopen(3). This is safe to execute because of the clean environment thatsuperguarantees π«Ά.mailany="mail-command"β (Local|Global) Exactly the same as themailoption, except thatmailanyalso sends notification of successful invocations, not just the errors π.rlog_host=hostnameβ (Global) Tellssuperwhich host's syslog daemon is supposed to receive log messages when thesyslog=yoption is enabled π‘. Heads up: this option has no effect if you use it after the first message has already been logged β once the logger has been opened, it does not get re-opened ifrlog_hostchanges. Default: the local host. Note: alternatively, you could configure thesyslog.conffile to forward the messages to a central machine instead. Your call, bestie π .syslog=y|nβ (Global) Logging info gets passed to the logs that thesyslogddaemon maintains πͺ΅. This is independent of whatever you set for thelogfileoption above. Error messages are by default logged at priorityLOG_ERR, and successful attempts to run programs get logged at priorityLOG_INFO. (Peep thesyslog_errorandsyslog_successoptions if you wanna change those levels.)syslog_error=xxxβ (Global) Ifsyslogis enabled (see thesyslogoption), then by defaultsuperlogs error messages using thesyslog(3)codeLOG_ERR. This option changes that code toxxx, wherexxxis any of the usualsyslog(3)priority and/or facility codes β stuff likeLOG_WARNINGorLOG_LOCAL7|LOG_ERRπ. TheLOG_xxxwords can be separated by whitespace, dot, and/or ``|'', but of course you must use quotes if whitespace is in there. The leading"LOG_"is optional, and the value is case-insensitive. For example,LOG_LOCAL7|LOG_ERRcan alternatively be written aslocal7.err. Real talk:superdoesn't know what sensible codes are β it's up to thesuper.tabwriter to pick meaningful values π . For instance, if you put
syslog_error="LOG_INFO | LOG_ERR" (bad!)
then you'll get both of those values or'd together and passed to syslog(). Not it. π
syslog_success=xxxβ (Global) This option is just likesyslog_error, except it applies to successful-execution messages instead of error messages π. Default:LOG_INFO.
πΈ Group 3. Extra Help Information for Users. πΈ
info=xxxβ (Local) The stringxxxgets printed when giving help to users π«Ά. You should set it to a helpful one-line description of the command. Give the people what they need, bestie.
π Group 4. Password and Other Restrictions Before Approval. π
maxlen=[mmm,]nnnβ (Local|Global) Every argument has to be no more thanmmmcharacters long (and yes, that count includes the terminating null), and the total length of all the arguments combined must not go overnnncharacters π. A negative value means no limit gets applied at all. The defaults formmmandnnncome from the compile-time manifest constantsMAXLEN1ARGandMAXLENARGS, which are usually1000and10,000characters, respectively.nargs=[mmm-]nnnβ (Local|Global) The user is required to entermmm-nnnarguments to the command π’. If you give justnnn, then the user must enter exactlynnnarguments. And these arguments are in addition to any arguments entered in the command part of thesuper.tabfile. The default is to let the user enter any number of arguments they want.arg[mmm-]nnn=sssβ (Local|Global) This means thennn'th ormmm-nnn'th arguments have to match the patternsssπ§©. (Arguments are numbered starting from1.) The pattern must be wrapped in quotes if it contains whitespace. Note that this option does not require there to bemmm-nnnarguments β it only says what those arguments must look like, if they get entered. You can use this option several times on one line, with differentmmm-nnnvalues each time, to apply different patterns to different arguments. If more than one pattern applies to a given argument, then all of those patterns have to be matched. An empty pattern ("") is special: it has the effect of unsetting (removing) any previous patterns for the matching[mmm-]nnnπ§Ό. This is useful when you wanna change:globalsettings instead of just adding to them. And if there are localarg[mmm-]nnnoption(s), they completely replace all the globalarg[mmm-]nnnvalues β even if the localmmm-nnnvalues don't overlap with the global ones. Periodt.owner=xxxβ (Local|Global) This option says that theFullPath(after asterisk-substitution, iykyk) must be owned by user (or uid)xxxβ otherwise it won't get executed π«.auth=y|nβ (Local|Global) Ify, the user has to authenticate before the command gets executed π. The default authentication method is Unix password authentication. Also go see the optionsauthprompt,authtype,authuser,timeout, andrenewtime, and please be sure to read the warning undertimestampbyhost.authprompt=messageβ (Local|Global) Sets the prompt used when authenticating the user (usually the default prompt is fine, bestie) π¬. Variable substitution gets done on the prompt before it's printed.authtype=typeβ (Local|Global) Sets the type of authentication used whenauth=yπ. The type can bepasswordorpam(if PAM is supported on your system). The default ispassword. If PAM authentication is used,superuses the service name ``super'' when looking for authentication in your system PAM configuration files.authuser=usernameβ (Local|Global) Sets the user whose authentication is required whenauth=yπ€. The default is the password (or other authentication) for the user who invokedsuper.password=y|nβ (Local|Global) This one is a deprecated option, bestie β it's been replaced by theauthandauthtypeoptions π.Password=yis equivalent toauth=y authtype=password; andPassword=nis equivalent toauth=n.renewtime=y|nβ (Global) Ify, the user's timestamp file gets updated to the current time whenever an authentication-requiring command is executed β°. The result: a user who frequently runs authentication-requiring commands won't need to re-authenticate until more thantimeoutminutes have elapsed since the last such command. Otherwise, the user will need to re-authenticatetimeoutminutes after last entering the password. The default isn.timeout=mβ (Local|Global) User authentication is good formminutes π; meaning the command may be executed without re-authenticating formminutes after the previous authentication (for any command). Aftermminutes, user authentication will be required again before the command can be executed. Iftimeoutis zero or negative, then authentication is required every single time the command is used. The timestamp for userusris recorded in theTIMESTAMP_DIRdirectory (seetimestampbyhostand the FILES section, below).timestampbyhost=y|nβ (Global) Ify(the default), the timestamp files get names that are unique on each host π¦. For instance,jouser@somehostwill be given a timestamp file namedTIMESTAMP_DIR/somehost/jouser, whereTIMESTAMP_DIRis defined in the FILES section. Iftimestmapbyhost=n, the timestamp files get names that are unique to each user, but not unique per host. For instance,jouseron any host will be given a timestamp file namedTIMESTAMP_DIR/jouser.
β οΈ WARNING: The hostname used here is the one from gethostname(). Note that this is not necessarily unique across internet domains, since it's frequently not a fully-qualified domain name. So you should not share timestamp directories with hosts outside the local domain. (Generally such connections don't exist, but one could crossmount the timestamp directory disk... π so like, don't.)
timestampuid=xxxβ okay so when a password is needed, the moment it was typed gets stored as the mtime of a timestamp file πΎ. Normally that file is made withowner=root, but this option makes it get created/modified usinguid=xxxinstead (xxxcan be a username or a numeric uid). Why would you want that? Because if you've got a whole network of hosts sharing a cross-mounted timestamp directory, this is your moment. See, networks are usually set up so root on one host does not get root access to files on another host β which means root over there can't create that timestamp file unless it's world-writable. This option lets the file be created/opened under a different uid that does have cross-host access, like the uid of a system manager. Default:timestampuid=0.checkvar=name[,...]β (Local) Eachnamein that comma-separated list is asuper.tabvariable the user has to actually type in at a prompt fromsuper. Picture this: you've got asuper shutdowncommand that halts the machine. Run that on the wrong host and you have some very annoyed users, no cap π. So you throw incheckvar=HOST, and the user has to type the correct hostname into the prompt before anything happens. Vibe check passed or it's not happening.
π§ Group 5. Modifications to Environment Before Executing Command π§
uid=xxxβ (Local) Sets the real uid toxxxright before executing the command. If theeuidoption isn't used, it also sets the effective uid toxxx. The uidxxxis tried first as a login name, then as a number. Heads up: if you useuid=xxxandu+g=yyytogether (see below), then theu+goption only sets the group id, not the user id. Teamwork β¨euid=xxxβ (Local) Sets the effective uid toxxxjust before executing the command. Same deal as above:xxxis tried as a login name first, then as a number.gid=yyyβ (Local) Sets the real gid toyyyjust before executing the command. Ifegidisn't used, it also sets the effective gid toyyy. Andyyy? Tried first as a group name, then as a number. πegid=yyyβ (Local) Sets the effective gid toyyyjust before executing the command. Again: group name first, then number.u+g=zzzβ (Local) Sets the real uid tozzz, the real gid tozzz's login gid, and the supplementary groups list tozzz's supplementary groups, all right before executing the command. Ifeuidand/oregidaren't given, the effective uid and/or gid get set too. But βu+gandgid=yyyconflict with each other and may not be used together. Pick a lane bestie π«groups=name[,...]β (Local|Global) By default the user's supplementary groups list gets yeeted before executing a command (unless you're usingu+g). This option instead sets the group list toname[,...].addgroups=name[,...]β (Local|Global) This one adds the listed groups to the supplementary groups list. Since the default gives you an empty supplementary groups list, this usually does the same thing as the plaingroupsoption. However β if you dou+g=foo addgroups=a,b,c, then the supplementary groups list becomes userfoo's supplementary groups plusa,b, andc. Stacking, we love to see it π«Άargv0=nameβ (Local) The command will execute with its first argument (the one we conventionally callargv[0]) set toname. As a handy shorthand, the value<path>β angle brackets literally part of the name β means use theFullPathspecified in thesuper.tabfile. By defaultargv[0]is set toCmd, the name of the super command the user invoked, regardless of the actual path being invoked. But some programs just won't run right unlessargv[0]has a specific value. Example time: say you want to let users safely mount zip disks, and you use something like:
zipmount "/etc/mount -o nosuid /dev/xz10 /zip"
This command will fail if /etc/mount requires being invoked with argv[0] set to [.../]mount, because super is gonna use the name zipmount. The fix? Put argv0=<path> in your super.tab file, and then the mount command works properly. Iconic problem-solving, honestly β
env=name[,...]β (Global|Local) Eachnamein the comma-separated list is an environment variable that should not be deleted before executing theCmd. These are in addition to the normal variables created or passed bysuper(TERM,IFS,PATH,USER,LOGNAME,HOME,ORIG_USER,ORIG_LOGNAME,ORIG_HOME,LINES,COLUMNS,SUPERCMD).
β οΈ Be careful here β environment variables can sometimes be abused to create security holes. Stay safe out there.
Also: if you use this option more than once, the later instance overrides the earlier one instead of adding to it. Same energy with local vs global β using it as a local option completely overrides any global setting.
maxenvlen=nnnβ (Global|Local) Specifies the maximum length of an environment variable definition (that's name + equal sign + value + the trailing null character, all counted). The default comes from the compile-time manifest constantMAXENVLEN, usually1000characters. A negative value means no limit π¦cd=dirβ (Local|Global) Just before executing the command,superchanges the working directory todir.setenv=var=xxxβ (Local|Global) The environment variablevargets defined with the valuexxx, and it's passed on when executing theCmd. You can stack several environment variable definitions by using this option more than once. Love a repeatable option πfd=n[,...]β (Local) Each file descriptornin the comma-separated list should not be closed before executing theCmd. These get added to the usual set of descriptors kept open, namely0,1,2.nice=nβ (Local|Global) Changes the "nice" value of the executed command by an amountnfrom the default level. (Positive increments reduce the command's priority; negative increments increase it.) Note it, because that's lowkey backwards from what you'd guess πumask=nnnβ (Local|Global) Sets the umask of any executed command ton. A leading0xor0Xinnnnmeans a hexadecimal value; otherwise a leading0means octal; otherwise it's decimal. Read your number formats, bestie π’
πΈ Group 6. Other Options πΈ
print=messageβ (Local) If the rest of the line is matched, thensuperprints the specified message just before executing the command.die=messageβ (Local) If the rest of the line is matched, thensuperdoes variable-substitution on the specifiedmessage, prints it, and exits. This is how you conveniently set up some "stop" conditions, then use thedieoption to keepsuperfrom looking at any line past those stop conditions. Otherwise you'd have to individually attach the stop conditions to every single control line β exhausting, no thank you π
π Include Files π
A super.tab file can pull in other files with an entry like:
:include filename [ owner=xxx ] [ group=yyy ]
or
:optinclude file [ owner=xxx ] [ group=yyy ]
If the file isn't an absolute path, it's taken relative to the directory containing the super.tab file. Include files may be nested up to the system limit on the number of simultaneously-open file descriptors. Recursion go brrr π
The owner=xxx option says the file must be owned by user xxx; the group=yyy option says the file must belong to group yyy. If group=yyy is specified, then the file can be group-writable; by default, the file must be writable only by owner. This is useful for a collection of accounts operated together as part of a single project β the several accounts can share .supertab files by :include-ing files belonging to the trusted user xxx and/or group yyy. Notes, bestie:
- The regular root-owned
super.tabfile can also use theowner=orgroup=constructs, but it's not a good idea. Don't do it. Periodt. - Beware of the transitive nature of this trust: the file owned by
xxxcan in turn include a file owned by yet another user. You might wind up trusting a user you didn't intend to trust! π
The difference between :include and :optinclude is that the former generates an error if the named file doesn't exist, whereas the latter (optional-include) silently ignores files that don't exist.
β οΈ WARNING: You should use:optincludewith great caution, and be sure not to depend on that file being present. It is easy to imagine a scenario in which an administrator carelessly changes an entry so that the wrong permission is granted if an:optinclude'd file was missing. Fr fr, be careful with this one.
ποΈ FILES ποΈ
/etc/super.tabβ The location of thesuper.tabfile on your system./etc/super.initβ The location of thesuper.initfile on your system./run/superstamps/usernameβ Default location of the file whose mtime is used as the timestamp for the last time the user entered his or her password for password-requiring commands. Check your installation for the directory used on your system. π
π EXAMPLES π
Bestie. This is the part where it all clicks. Sit down, sip your lil drink, we're doing examples. π
β¨ Example 1. The control line β¨
doit /usr/local/bin/doit \
me \
you@{h1,h32} \
ja.*:ok_j \
:goodguys
okay so this one control line lets /usr/local/bin/doit be run setuid-root by:
- user
meon any host, no questions asked π - user
youon hostsh1andh32specifically - any users named
ja.*who are in groupok_j - and literally anybody at all in group
goodguys
that's four whole permission grants in one line. iconic. π
π Example 2. The pair of control lines π
doit /usr/local/bin/doit \
u+g=smith env=TZ,TAPE \
password=y timeout=0 \
jo@PublicWorkstation
doit /usr/local/bin/doit \
u+g=smith env=TZ,TAPE \
jo
so what's happening here? user jo gets to run /usr/local/bin/doit with uid = smith, gid = smith's login gid, and keeps the environment variables TZ and TAPE on top of the standard set. β¨
now the spicy part: if user jo is sitting at PublicWorkstation, the first entry matches, and that one demands jo's password every single time the command is used. no skipping, no vibes-based bypass, we are being careful at the public machine. π
otherwise (not at PublicWorkstation), super matches at the second entry, and no password is needed to run the command at all. easy peasy. π¦
π Example 3. π
here's an entry that restricts CD-ROM mounting differently across different hosts:
tasis the only user who may mount CD's onelgar- anybody in group
xyzmay mount CD's onalphaordelta - and anybody on a host in the netgroup
indiamay mount a CD on theindiahosts
However β and this is the dramatic part β user jo may never run cdmount, regardless of his or her group or host. periodt. π«
that's assuming there is no overriding global pattern that permits jo to use the command, bestie. global patterns are out here overruling things, so check those too. π
Also note: these are shell-style patterns, not regex-style patterns. do not come in here with regex energy, it will not work. π
cdmount /usr/local/bin/cdmount \
tas@elgar \
:xyz@{alpha,delta} \
*@+india \
!jo
look at that !jo at the end. one lil exclamation mark and jo is out. the power. π₯
π SEE ALSO π
okay bestie that's the whole page, you made it to the end, I'm so proud of you fr fr π₯Ήπ
this one came from the local source, it's the SUPER.TAB(5) page, and yeah β that's a wrap. go forth and write your control lines with main character energy. slay. π
β¨π«Ά
π¦ where this page comes from
- debian bookworm: super 3.30.3-2+b1 Β· GPL-1.0-or-later OR Artistic-1.0-Perl
- debian trixie: super 3.30.3-2+b2 Β· GPL-1.0-or-later OR Artistic-1.0-Perl
- ubuntu jammy: super 3.30.3-2 Β· GPL-1.0-or-later OR Artistic-1.0-Perl
- ubuntu noble: super 3.30.3-2 Β· GPL-1.0-or-later OR Artistic-1.0-Perl
- ubuntu questing: super 3.30.3-2.1
- ubuntu resolute: super 3.30.3-2.2 Β· GPL-1.0-or-later OR Artistic-1.0-Perl
- ubuntu stonking: super 3.30.3-2.2 Β· GPL-1.0-or-later OR Artistic-1.0-Perl
- Copyright (c) 1993 by California Institute of Technology
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms