1 / 29

System Programming

System Programming. Chapter 8.11. Fun Stuff. Touch-based Communication. Changing User/Group ID ’ s. This part is confusing … (when I read it) Why changes user id in the middle of a program execution?

sawyer
Download Presentation

System Programming

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. System Programming Chapter 8.11

  2. Fun Stuff • Touch-based Communication

  3. 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

  4. 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)

  5. 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

  6. 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).

  7. 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

  8. Example of using setuid() • Step 1: exec tip program: • 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.

  9. 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

  10. 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)

  11. User/Group ID’s superuser setreuid(ruid, euid) superuser setuid(uid) superuser seteuid(uid) • The supplementary guid’s are not affected by the setgid function. uid euid uid uid uid ruid nonsuperuser setreuid real uid effective uid saved suid nonsuperuser setreuid exec of suid nonsuperuser setuid or seteuid nonsuperuser setuid or seteuid

  12. 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()

  13. #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_06/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/echoarg foo linux1:~/sys_prog_06/test> fig8.20.exe argv[0]: /mnt/professor/hchu/sys_prog_06/test/echoarg argv[1]: foo argv[2]: /home/professor/hchu/sys_prog_06/test/testinterp argv[3]: myarg1 argv[4]: MY ARG2 what is the pathname of the interpreter? shifting off the argument list Examples of Interpreter & Interprted file

  14. “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? Interpreter Files

  15. 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

  16. 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?

  17. 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

  18. 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; } } } return(status); }

  19. 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.

  20. #include "apue.h" #include <sys/wait.h> int main(void) { int status; if ((status = system("date")) < 0) err_sys("system() error"); pr_exit(status); 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); } 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

  21. 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.

  22. // tsys #include "apue.h" int main(int argc, char *argv[]) { int status; if (argc < 2) err_quit("command-line argument required"); if ((status = system(argv[1])) < 0) err_sys("system() error"); pr_exit(status); exit(0); } // printuids #include "apue.h" int main(void) { printf("real uid = %d, effective uid = %d\n", getuid(), geteuid()); 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 = ?

  23. 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?

  24. 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 */ • };

  25. 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 first child second child third child fourth child parent sleep(2) exit(2) sleep(4) abort() sleep(8) exit(0) sleep(6) kill() fork fork fork fork etime=128 execl etime=360 etime=274 stat=9 /usr/bin/dd stat=128+6 Remark: 60 ticks/sec flag=AFORK

  26. F = result of a fork, X = killed by a signal, D = process dumped core

  27. 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

  28. 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

  29. int main(int argc, char *argv[]) { int i; setbuf(stdout, NULL); for (i = 1; i < argc; i++) do_cmd(argv[i]); /* once for each command-line arg */ exit(0); } static void do_cmd(char *cmd) /* execute and time the "cmd" */ { struct tms tmsstart, tmsend; clock_t start, end; int status; printf("\ncommand: %s\n", cmd); if ((start = times(&tmsstart)) == -1) /* starting values */ err_sys("times error"); if ((status = system(cmd)) < 0) /* execute command */ err_sys("system() error"); if ((end = times(&tmsend)) == -1) /* ending values */ err_sys("times error"); pr_times(end-start, &tmsstart, &tmsend); pr_exit(status); } static void pr_times(clock_t real, struct tms *tmsstart, struct tms *tmsend) { static long clktck = 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); } linux1:~/sys_prog_06/test> fig8.30.exe "sleep 5" "date" 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 command: date ¤G 5¤ë 23 18:37:08 CST 2006 real: 0.01 user: 0.00 sys: 0.00 child user: 0.01 child sys: 0.00 normal termination, exit status = 0

More Related