chapter8b

advertisement
System Programming
Chapter 8.11
1
Fun Stuff
• Touch-based Communication
2
Changing User/Group ID’s
• This part is confusing … (when I read it)
• Why changes user id in the middle of a program
execution?
– Least-privilege model: a program should use the least
privilege necessary to accomplish any task.
– Reduce window of security vulnerability
– Example: a process needs to gain a privilege to access a
privileged file
3
Recall …
• A process can have more than one ID.
– Real user/group ID: who you really are
– Effective user/group ID: determine file access
permission
– Supplementary group IDs
– Saved set-user/group-ID = owner of the program
with set-user-id bit set
• Why do you need saved set-user-id?
– cannot give up privilege temporarily (and get it back)
4
Recall …
#include <sys/types.h>
#include <unistd.h>
int setuid(uid_t uid);
–
–
–
–
The process == superuser  set real/effective/saved-suid = uid
Otherwise, euid=uid if uid == ruid or uid == saved-suid (suid = set-uid)
Return 0 upon success
Return -1 otherwise; errno=EPERM (_POSIX_SAVED_IDS)
int setgid(gid_t gid);
– The same as setuid
5
User/Group ID’s
• Only superuser process can change the real uid –
normally done by the login program.
• The euid is set by exec only if the setuid bit is set for
the program file. euid can only be set as its saved-suid
or ruid.
• exec copies the euid to the saved-suid (after the
setting of euid if setuid bit is on).
6
User/Group ID’s
• Example man program
– man is used for displaying manual pages
– The setuid bit is on for man (owner=man).
• For file locking
– man calls setuid(ruid) for privileged file access on
some configuration file
• Correct uid
– Switch the euid back to man after it is done with
them
7
Example of using setuid()
• Step 1: exec tip program:
Real user ID = Our user ID
Effective user ID = man
Saved-set-user ID = man
• Step 2: access the required locks
• Step 3: setuid(getuid()) to return to
normal permission
• Step 4: calling setuid(uucpuid) to
change the effective user ID
• Step 5: release the lock.
Real user ID = Our user ID
Effective user ID = Our user ID
Saved-set-user ID = man
Real user ID = Our user ID
Effective user ID = Man
Saved-set-user ID = man
8
User/Group ID’s
#include <sys/types.h>
#include <unistd.h>
int setreuid(uid_t ruid, uid_t euid);
int setregid(uid_t rgid, uid_t egid);
– Change both ruid/rgid and euid/egid.
– Swapping of real and effective uids.
• Good for even unprivileged users.
– BSD only or BSD-compatibility library
9
User/Group ID’s
#include <sys/types.h>
#include <unistd.h>
int seteuid(uid_t uid);
int setegid(uid_t gid);
– Change only euid/egid.
– Non-superusers can only set euid=ruid or saved-setuid.
– A privileged user only sets euid = uid.
• It is different from setuid(uid)
10
User/Group ID’s
superuser
setreuid(ruid, euid)
euid
ruid
real uid
nonsuperuser
setreuid
nonsuperuser
setuid or seteuid
superuser
setuid(uid)
uid
superuser
seteuid(uid)
uid
uid
effective uid
nonsuperuser
setreuid
uid
saved suid
exec of suid
nonsuperuser
setuid or seteuid
• The supplementary guid’s are not affected
by the setgid function.
11
Interpreter Files
• What is an interpreter?
– A program that executes other programs, e.g., java, lisp, python, etc.
• Def: a file begins with a line of the form: #! pathname
[optional-argument]
– E.g., “#! /bin/sh”
• Implementation:
– Recognition is done within the kernel
– Interpreter (normally an absolute pathname) vs the interpreter files
– Line-limit of the first line, e.g., 32 chars.
• Program 8.10 – Page 218
– Argument list, arg pathname of execl()
12
Examples of Interpreter & Interprted
file
#include "apue.h"
#include <sys/wait.h>
int main(void)
{
pid_t pid;
if ((pid = fork()) < 0) {
err_sys("fork error");
} else if (pid == 0) {
/* child */
if
(execl("/home/professor/hchu/sys_prog_0
6/test/testinterp",
"testinterp",
"myarg1", "MY ARG2", (char *)0) < 0)
err_sys("execl error");
}
if (waitpid(pid, NULL, 0) < 0) /* parent */
err_sys("waitpid error");
exit(0);
}
linux1:~/sys_prog_06/test> cat testinterp
#!/home/professor/hchu/sys_prog_06/test/ech
oarg foo
linux1:~/sys_prog_06/test> fig8.20.exe
argv[0]:
/mnt/professor/hchu/sys_prog_06/test/ech
oarg
argv[1]: foo
argv[2]:
/home/professor/hchu/sys_prog_06/test/t
estinterp
argv[3]: myarg1
argv[4]: MY ARG2
what is the pathname of the
interpreter?
shifting off the argument list
13
Interpreter Files
• “awk –f myfile” lets awk
read an awk program from
“myfile”.
• Argument list: awkexample file1
FILE2 f3 (at /usr/local/bin/)
#! /bin/awk –f
BEGIN {
for (i = 0; i < ARGC; i++)
printf “ARGV[%d] = %s\n”, i,
ARGV[i]
exit
}
linux1:~/sys_prog_06/test> awkexample file1
FILENAME2 f3
ARGV[0] = awk
ARGV[1] = file1
ARGV[2] = FILENAME2
ARGV[3] = f3
mapped to
awk -f /home/professor/../awkexample file1
FILENAME2 f3
what if awk is replaced by echoarg?
14
Interpreter Files
• Example: Removing of “-f”
$su
Passwd:
# mv /bin/awk /bin/awk.save
# cp /home/stevens/bin/echoarg /bin/awk
# suspend
[1] + Stopped su
$arkexample file1 FILE2 f3
argv[0]: /bin/awk
argv[1]: -f
argv[2]: /usr/local/bin/awkexample
argv[3]: file1
argv[4]: FILE2
argv[5]: f3
15
Interpreter Files
• Why interpreter files?
– Pro:
• Hide the fact that certain programs are scripts in other
languages.
– awkexample optional-arguments
• Provide efficiency gain (shell vs. awk scripts)
– What if awk script is turned into a shell script? exec twice
– awk ‘BEGIN { for (i=0); i<ARGC; i++) …. }’ $*
• Choices of shells -> specify in #! /bin/tcsh
– Against:
• Efficiency for users but at the cost of the kernel
– Executable files? /bin/sh? /bin/awk?
16
system
execute a command string from within a program
#include <stdlib.h>
int system(const char *cmdstring);
– If cmdstring = null, return nonzero only if a command
interpreter is available.
• Objective:
– Convenient in usage
• system(“date > file; ls”);
• Or write a program: call time, localtime, strftime, write, etc.
– ANSI C definition  system-dependent
• An interface to shells
17
system
• Implementation: fork-exec-waitpid
int system(const char *cmdstring) /* version without signal handling */
{
pid_t pid;
int
status;
if (cmdstring == NULL)
return(1);
/* always a command processor with UNIX */
if ((pid = fork()) < 0) {
status = -1; /* probably out of processes */
} else if (pid == 0) {
/* child */
execl("/bin/sh", "sh", "-c", cmdstring, (char *)0); // Why not execute the command directly?
_exit(127);
/* execl error */
} else {
/* parent */
while (waitpid(pid, &status, 0) < 0) {
if (errno != EINTR) {
status = -1; /* error other than EINTR from waitpid() */
break;
}
}
18
}
return(status);
system
• Program 8.23 – Page 224
– Calling system()
• Advantage
– system() does all the error handling & signal handling.
– Q: what will happen if you hits CTRL-C during the
execution?
• A security hole
– Call system from a setuid program
• Programs 8.14 & 8.15 – Page 225
• A set[ug]id program should change its uid’s back to the normal
after call fork.
– Not in current Linux distribution.
19
#include "apue.h"
#include <sys/wait.h>
int
main(void)
{
int
status;
if ((status = system("date")) < 0)
err_sys("system() error");
pr_exit(status);
linux1:~/sys_prog_06/test> fig8.23.exe
¤G 5¤ë 23 16:12:23 CST 2006
normal termination, exit status = 0
sh: nosuchcommand: command not found
normal termination, exit status = 127
p92007 pts/0
2006-05-23 14:22
(epson5.epson.com.tw)
r93007 pts/1
2006-05-22 17:30
(linux11.csie.ntu.edu.tw)
r93007 pts/2
2006-05-22 17:30
(linux11.csie.ntu.edu.tw)
normal termination, exit status = 44
if ((status = system("nosuchcommand"))
< 0)
err_sys("system() error");
pr_exit(status);
if ((status = system("who; exit 44")) < 0)
err_sys("system() error");
pr_exit(status);
exit(0);
}
20
system
• A security hole
– Call system from a setuid program
• Programs 8.24 & 8.25
• A set[ug]id program should change its uid’s back to the
normal after call fork.
– Not in current Linux distribution.
21
// tsys
// printuids
#include "apue.h"
#include "apue.h"
int
main(int argc, char *argv[])
{
int
status;
int
main(void)
{
printf("real uid = %d, effective uid =
%d\n", getuid(), geteuid());
exit(0);
}
if (argc < 2)
err_quit("command-line argument
required");
if ((status = system(argv[1])) < 0)
err_sys("system() error");
pr_exit(status);
exit(0);
}
what happens if you execute the following
command
$ tsys printuids
real uid = ?
effective uid = ?
$ su
$ chmod u+s tsys
$ tsys printuids
real uid = ?
effective uid = ?
22
Process Accounting
• Accounting Information
– Kept in the process table whenever a process terminates.
– No records for
• crashed processes and
• abnormal terminated processes
– Each accounting record is written into the accounting file
in the order of the termination order of processes.
• Q: Can we find the starting order from the accounting file?
23
Process Accounting
• Non-POSIX standards
– SVR4 & 4.3+BSD supported
• accton [filename]
• /var/adm/pacct or /usr/adm/acct
– Linux
• #include <unistd.h>
int acct(const char *filename);
typedef u_short comp_t;
struct acct {
char
ac_flag; /* Figure 8.26 – Page 251 */
char
ac_stat; /* termination status (core flag + signal #) */
uid_t ac_uid; gid_t
ac_gid; /* real [ug]id */
dev_t ac_tty; /* controlling terminal */
time_t ac_btime; /* staring calendar time (seconds) */
comp_t ac_utime; /* user CPU time (ticks) */
comp_t ac_stime; /* system CPU time (ticks) */
comp_t ac_etime; /* elapsed time (ticks) */
comp_t ac_mem; /* average memory usage */
comp_t ac_io; /* bytes transferred (by r/w) */
comp_t ac_rw; /* blocks read or written */
char
ac_comm[8]; /* command name: [8] for SVR4, [10] for
4.3 BSD */
24
};
Process Accounting
• A new record for each process (not each exec)
– E.g., A execs B, then B execs C
• ac_flag: AFORK is cleared. (cmd=C)
• Programs 8.28 & 8.29 – Page 253-254
parent
first child
sleep(2)
exit(2)
sleep(4)
abort()
fork
etime=128
Remark: 60 ticks/sec
second child
fork
third child
fork
etime=274
execl
stat=128+6
/usr/bin/dd
flag=AFORK
sleep(8)
exit(0)
fourth child
fork
sleep(6)
kill()
etime=360
stat=9
25
F = result of a fork, X = killed by a signal, D = process dumped core
elapsed
time
bytes transferred
termination
status
flags
accton
e=
7, chars =
64, stat =
0:
S
dd
e=
37, chars =
2218888, stat =
0:
second child
a.out
e=
128, chars =
0, stat =
0:
parent
a.out
e=
274, chars =
0, stat =
134: F
a.out
e=
360, chars =
0, stat =
9: F
a.out
e=
484, chars =
0, stat =
0: F
D X first child
X fourth child
third child
26
User Identification
• How to know the login name of the user who’s running the process?
#include <unistd.h>
char *getlogin(void);
• Fail if the process is not attached to a terminal – daemons
– init, …
• A user could have a multiple login names – login’s user name
with the same user ID.
– getpwuid, getpwnam
• Function ttyname – utmp
• Environment var LOGNAME (set by the login process in
4.3+BSD) – user-space data
27
Process Times
#include <sys/times.h>
clock_t times(struct tms *buf);
– Timestamps: returned value from some arbitrary point in
the past.
– Subtract two timestamps to compute elapsed time
struct tms {
clock_t tms_utime; /* user CPU time */
clock_t tms_stime; /* system CPU time */
clock_t tms_cutime; /* user CPU time, terminated child */
clock_t tms_cstime; /* system CPU time terminated child */
• Program 8.30 – Page 234
– clock_t: measurement in seconds or defined in
_SC_CLK_TCK
28
static void pr_times(clock_t real, struct tms *tmsstart, struct
tms *tmsend)
{
static long
clktck = 0;
int main(int argc, char *argv[])
{
int
i;
setbuf(stdout, NULL);
for (i = 1; i < argc; i++)
do_cmd(argv[i]);
line arg */
exit(0);
if (clktck == 0)
/* fetch clock ticks per second first
time */
if ((clktck = sysconf(_SC_CLK_TCK)) < 0)
err_sys("sysconf error");
printf(" real: %7.2f\n", real / (double) clktck);
printf(" user: %7.2f\n",
(tmsend->tms_utime - tmsstart->tms_utime) / (double)
clktck);
printf(" sys: %7.2f\n",
(tmsend->tms_stime - tmsstart->tms_stime) / (double)
clktck);
printf(" child user: %7.2f\n",
(tmsend->tms_cutime - tmsstart->tms_cutime) /
(double) clktck);
printf(" child sys: %7.2f\n",
(tmsend->tms_cstime - tmsstart->tms_cstime) /
(double) clktck);
/* once for each command-
}
static void do_cmd(char *cmd)
the "cmd" */
{
struct tms
tmsstart, tmsend;
clock_t
start, end;
int
status;
/* execute and time
printf("\ncommand: %s\n", cmd);
if ((start = times(&tmsstart)) == -1) /* starting values
*/
err_sys("times error");
}
if ((status = system(cmd)) < 0)
command */
err_sys("system() error");
command: sleep 5
real: 5.01
user: 0.00
sys:
0.00
child user: 0.00
child sys:
0.00
normal termination, exit status = 0
/* execute
if ((end = times(&tmsend)) == -1)
values */
err_sys("times error");
pr_times(end-start, &tmsstart, &tmsend);
pr_exit(status);
}
/* ending
linux1:~/sys_prog_06/test> fig8.30.exe "sleep 5" "date"
command: date
¤G 5¤ë 23 18:37:08 CST 2006
real: 0.01
user: 0.00
sys:
0.00
29
Download