📄 users.texi
字号:
This function sets both the real and effective group ID of the processto @var{newgid}, provided that the process has appropriate privileges.@c !!! also sets saved-idIf the process is not privileged, then @var{newgid} must either be equalto the real group ID or the saved group ID. In this case, @code{setgid}sets only the effective group ID and not the real group ID.The return values and error conditions for @code{setgid} are the sameas those for @code{setuid}.@end deftypefun@comment unistd.h@comment BSD@deftypefun int setregid (gid_t @var{rgid}, fid_t @var{egid})This function sets the real group ID of the process to @var{rgid} andthe effective group ID to @var{egid}. If @var{rgid} is @code{-1}, itmeans not to change the real group ID; likewise if @var{egid} is@code{-1}, it means not to change the effective group ID.The @code{setregid} function is provided for compatibility with 4.3 BSDUnix, which does not support saved IDs. You can use this function toswap the effective and real group IDs of the process. (Privilegedprocesses are not limited to this usage.) If saved IDs are supported,you should use that feature instead of using this function.@xref{Enable/Disable Setuid}.The return values and error conditions for @code{setregid} are the sameas those for @code{setreuid}.@end deftypefunThe GNU system also lets privileged processes change their supplementary group IDs. To use @code{setgroups} or @code{initgroups}, your programsshould include the header file @file{grp.h}.@pindex grp.h@comment grp.h@comment BSD@deftypefun int setgroups (size_t @var{count}, gid_t *@var{groups})This function sets the process's supplementary group IDs. It can onlybe called from privileged processes. The @var{count} argument specifiesthe number of group IDs in the array @var{groups}.This function returns @code{0} if successful and @code{-1} on error.The following @code{errno} error conditions are defined for thisfunction:@table @code@item EPERMThe calling process is not privileged.@end table@end deftypefun@comment grp.h@comment BSD@deftypefun int initgroups (const char *@var{user}, gid_t @var{gid})The @code{initgroups} function effectively calls @code{setgroups} toset the process's supplementary group IDs to be the normal default forthe user name @var{user}. The group ID @var{gid} is also included.@c !!! explain that this works by reading the group file looking for@c groups USER is a member of.@end deftypefun@node Enable/Disable Setuid@section Enabling and Disabling Setuid AccessA typical setuid program does not need its special access all of thetime. It's a good idea to turn off this access when it isn't needed,so it can't possibly give unintended access.If the system supports the saved user ID feature, you can accomplishthis with @code{setuid}. When the game program starts, its real user IDis @code{jdoe}, its effective user ID is @code{games}, and its saveduser ID is also @code{games}. The program should record both user IDvalues once at the beginning, like this:@smallexampleuser_user_id = getuid ();game_user_id = geteuid ();@end smallexampleThen it can turn off game file access with @smallexamplesetuid (user_user_id);@end smallexample@noindentand turn it on with @smallexamplesetuid (game_user_id);@end smallexample@noindentThroughout this process, the real user ID remains @code{jdoe} and thesaved user ID remains @code{games}, so the program can always set itseffective user ID to either one.On other systems that don't support the saved user ID feature, you canturn setuid access on and off by using @code{setreuid} to swap the realand effective user IDs of the process, as follows:@smallexamplesetreuid (geteuid (), getuid ());@end smallexample@noindentThis special case is always allowed---it cannot fail.Why does this have the effect of toggling the setuid access? Suppose agame program has just started, and its real user ID is @code{jdoe} whileits effective user ID is @code{games}. In this state, the game canwrite the scores file. If it swaps the two uids, the real becomes@code{games} and the effective becomes @code{jdoe}; now the program hasonly @code{jdoe} access. Another swap brings @code{games} back tothe effective user ID and restores access to the scores file.In order to handle both kinds of systems, test for the saved user IDfeature with a preprocessor conditional, like this:@smallexample#ifdef _POSIX_SAVED_IDS setuid (user_user_id);#else setreuid (geteuid (), getuid ());#endif@end smallexample@node Setuid Program Example@section Setuid Program ExampleHere's an example showing how to set up a program that changes itseffective user ID.This is part of a game program called @code{caber-toss} thatmanipulates a file @file{scores} that should be writable only by the gameprogram itself. The program assumes that its executablefile will be installed with the set-user-ID bit set and owned by thesame user as the @file{scores} file. Typically, a systemadministrator will set up an account like @code{games} for this purpose.The executable file is given mode @code{4755}, so that doing an @samp{ls -l} on it produces output like:@smallexample-rwsr-xr-x 1 games 184422 Jul 30 15:17 caber-toss@end smallexample@noindentThe set-user-ID bit shows up in the file modes as the @samp{s}.The scores file is given mode @code{644}, and doing an @samp{ls -l} onit shows:@smallexample-rw-r--r-- 1 games 0 Jul 31 15:33 scores@end smallexampleHere are the parts of the program that show how to set up the changeduser ID. This program is conditionalized so that it makes use of thesaved IDs feature if it is supported, and otherwise uses @code{setreuid}to swap the effective and real user IDs.@smallexample#include <stdio.h>#include <sys/types.h>#include <unistd.h>#include <stdlib.h>/* @r{Save the effective and real UIDs.} */static uid_t euid, ruid;/* @r{Restore the effective UID to its original value.} */voiddo_setuid (void)@{ int status;#ifdef _POSIX_SAVED_IDS status = setuid (euid);#else status = setreuid (ruid, euid);#endif if (status < 0) @{ fprintf (stderr, "Couldn't set uid.\n"); exit (status); @}@}@group/* @r{Set the effective UID to the real UID.} */voidundo_setuid (void)@{ int status;#ifdef _POSIX_SAVED_IDS status = setuid (ruid);#else status = setreuid (euid, ruid);#endif if (status < 0) @{ fprintf (stderr, "Couldn't set uid.\n"); exit (status); @}@}@end group/* @r{Main program.} */intmain (void)@{ /* @r{Save the real and effective user IDs.} */ ruid = getuid (); euid = geteuid (); undo_setuid (); /* @r{Do the game and record the score.} */ @dots{}@}@end smallexampleNotice how the first thing the @code{main} function does is to set theeffective user ID back to the real user ID. This is so that any otherfile accesses that are performed while the user is playing the game usethe real user ID for determining permissions. Only when the programneeds to open the scores file does it switch back to the originaleffective user ID, like this:@smallexample/* @r{Record the score.} */intrecord_score (int score)@{ FILE *stream; char *myname; /* @r{Open the scores file.} */ do_setuid (); stream = fopen (SCORES_FILE, "a"); undo_setuid ();@group /* @r{Write the score to the file.} */ if (stream) @{ myname = cuserid (NULL); if (score < 0) fprintf (stream, "%10s: Couldn't lift the caber.\n", myname); else fprintf (stream, "%10s: %d feet.\n", myname, score); fclose (stream); return 0; @} else return -1;@}@end group@end smallexample@node Tips for Setuid@section Tips for Writing Setuid ProgramsIt is easy for setuid programs to give the user access that isn't intended---in fact, if you want to avoid this, you need to be careful.Here are some guidelines for preventing unintended access andminimizing its consequences when it does occur:@itemize @bullet@itemDon't have @code{setuid} programs with privileged user IDs such as@code{root} unless it is absolutely necessary. If the resource isspecific to your particular program, it's better to define a new,nonprivileged user ID or group ID just to manage that resource.@itemBe cautious about using the @code{system} and @code{exec} functions incombination with changing the effective user ID. Don't let users ofyour program execute arbitrary programs under a changed user ID.Executing a shell is especially bad news. Less obviously, the@code{execlp} and @code{execvp} functions are a potential risk (sincethe program they execute depends on the user's @code{PATH} environmentvariable).If you must @code{exec} another program under a changed ID, specify anabsolute file name (@pxref{File Name Resolution}) for the executable,and make sure that the protections on that executable and @emph{all}containing directories are such that ordinary users cannot replace itwith some other program.@itemOnly use the user ID controlling the resource in the part of the programthat actually uses that resource. When you're finished with it, restorethe effective user ID back to the actual user's user ID.@xref{Enable/Disable Setuid}.@itemIf the @code{setuid} part of your program needs to access other filesbesides the controlled resource, it should verify that the real userwould ordinarily have permission to access those files. You can use the@code{access} function (@pxref{Access Permission}) to check this; ituses the real user and group IDs, rather than the effective IDs.@end itemize@node Who Logged In@section Identifying Who Logged In@cindex login name, determining@cindex user ID, determiningYou can use the functions listed in this section to determine the loginname of the user who is running a process, and the name of the user whologged in the current session. See also the function @code{getuid} andfriends (@pxref{Reading Persona}).The @code{getlogin} function is declared in @file{unistd.h}, while@code{cuserid} and @code{L_cuserid} are declared in @file{stdio.h}.@pindex stdio.h@pindex unistd.h@comment unistd.h@comment POSIX.1@deftypefun {char *} getlogin (void)The @code{getlogin} function returns a pointer to a string containing thename of the user logged in on the controlling terminal of the process,or a null pointer if this information cannot be determined. The stringis statically allocated and might be overwritten on subsequent calls tothis function or to @code{cuserid}.@end deftypefun
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -