( ) . I- - struct inode - <sys/inode.h>, - struct dinode - <sys/ino.h>. . , 1992-95 - 237 - UNIX exec ruid -->----------------->---> ruid uid -->--------*-------->---> uid (new) | i_uid (st_uid) , . - , : (i_mode) S_ISUID (set-uid bit), u_uid i_uid : /* ... exec ... */ p_suid = u_uid; /* */ if( i_mode & S_ISUID ) u_uid = i_uid; if( i_mode & S_ISGID ) u_gid = i_gid; .. . gid - -   ( , - - ). ? - , -  . .. , mode = i_mode & 0777; /* rwx rwx rwx */ i_uid, , , "" : if( u_uid == 0 ) /* super user */ ; else if( u_uid == i_uid ) (mode & 0700); else if( u_gid == i_gid ) (mode & 0070); else (mode & 0007); : unsigned short uid = geteuid(); /* u_uid */ unsigned short ruid = getuid(); /* u_ruid */ unsigned short gid = getegid(); /* u_gid */ unsigned short rgid = getuid(); /* u_rgid */ : setuid(newuid); setgid(newgid); setuid. (u_uid - , ): if( u_uid == 0 /* superuser */ ) u_uid = u_ruid = p_suid = newuid; else if( u_ruid == newuid || p_suid == newuid ) u_uid = newuid; else ; p_suid set-uid- , exec-. . , 1992-95 - 238 - UNIX -, : BASE . 0600 (  ). , , . , BASE, , .. , , , - . PROG, , , 0711 (rwx--x--x) - . , BASE ( ) PROG? ! - PROG, -  ,   BASE. , , PROG, - . chmod chmod u+s PROG PROG S_ISUID. , PROG, - ,  , BASE. getuid , ( , ). - UNIX, ( ) . , - S_ISUID   - , . - , . ps, . - /dev/mem, - /dev/kmem.  , - " ", , set-uid. uid ruid ( gid rgid) - ? : /etc/getty. , (u_uid==0). : #include <stdio.h> /* cc -lc_s */ #include <pwd.h> #include <signal.h> struct passwd *p; char userName[80], *pass, *crpass; extern char *getpass(), *crypt(); ... /* */ signal (SIGINT, SIG_IGN); for(;;){ /* : */ printf("Login: "); gets(userName); /* ( ): */ pass = getpass("Password: "); /* : */ if(p = getpwnam(userName)){ /* */ crpass = (p->pw_passwd[0]) ? /* */ crypt(pass, p->pw_passwd) : pass; if( !strcmp( crpass, p->pw_passwd)) break; /* */ } printf("Login incorrect.\a\n"); } signal (SIGINT, SIG_DFL); . , 1992-95 - 239 - UNIX : // ... // /etc/utmp ( ) // /etc/wtmp (  ) ... setuid( p->pw_uid ); setgid( p->pw_gid ); chdir ( p->pw_dir ); /* GO HOME! */ // // . ... // envp: // HOME = p->pw_dir // SHELL = p->pw_shell // PATH = , :/bin:/usr/bin // LOGNAME (USER) = p->pw_name // TERM = // /etc/ttytype av[1] // - // char *envp[MAXENV], buffer[512]; int envc = 0; // ... // sprintf(buffer, "HOME=%s", p->pw_dir); // envp[envc++] = strdup(buffer); // ... // envp[envc] = NULL; ... // . // av[1] main. chown (av[1], p->pw_uid, p->pw_gid); chmod (av[1], 0600 ); /* -rw------- */ // // . // , // getty, init // wait() // chown ( _, 2 /*bin*/, 15 /*terminal*/ ); // chmod ( _, 0600 ); // , // /etc/inittab  ( respawn), // init _ // getty fork() exec(). ... // : execle( *p->pw_shell ? p->pw_shell : "/bin/sh", "-", NULL, envp ); , . exec-, getty, p->pw_shell ( /bin/sh /bin/csh) . , , - . , , getty,  : /etc/getty /bin/login. getty (.. - ) /etc/gettydefs.  ( exec) login, . login , , ..., , . . , , , - getty, . , 1992-95 - 240 - UNIX login. , - , . , - getty. , , char *getlogin(); uid , /etc/utmp. ,  ( creat mknod), - . di_uid = u_uid; di_gid = u_gid; 6.8.4. , : , , , ( TERM). 6.9. . . , , . - , A , B . , B . - , A , C . ( - A, - C). , , () / . - UNIX : . . , UNIX  . , , . . , , ,  - - : " ". 6.9.1. flock_t lock; fcntl(fd, operation, &lock); operation : F_SETLK , lock. flock_t : short l_type; short l_whence; off_t l_start; size_t l_len; long l_sysid; pid_t l_pid; l_type : . , 1992-95 - 241 - UNIX F_RDLCK - ; F_WRLCK - ; F_UNLCK - . l_whence, l_start, l_len , : lseek(fd,l_start,l_whence); l_len . l_whence : SEEK_SET, SEEK_CUR, SEEK_END. l_len " ". 0, . F_SETLKW , lock. , , - , . | | | READ WRITE -----------|--------------------------------------------------------------- READ | ;; WRITE | ;; ;; UNLOCK | - - , , . - - - . - - , () , . - ,  - , , ( ). - - . F_GETLK , lock. - ( ), lock l_type F_UNLCK l_whence SEEK_SET. - - ( F_SETLKW , ), lock. l_pid , , l_sysid - ( - ). . - fork. #include <stdio.h> #include <sys/types.h> #include <fcntl.h> #include <unistd.h> #include <time.h> #include <signal.h> char DataFile [] = "data.xxx"; char info [] = "abcdefghijklmnopqrstuvwxyz"; #define OFFSET 5 #define SIZE 12 #define PAUSE 2 int trial = 1; int fd, pid; char buffer[120], myname[20]; void writeAccess(), readAccess(); . , 1992-95 - 242 - UNIX void fcleanup(int nsig){ unlink(DataFile); printf("cleanup:%s\n", myname); if(nsig) exit(0); } int main(){ int i; fd = creat(DataFile, 0644); write(fd, info, strlen(info)); close(fd); signal(SIGINT, fcleanup); sprintf(myname, fork() ? "B-%06d" : "A-%06d", pid = getpid()); srand(time(NULL)+pid); printf("%s:started\n", myname); fd = open(DataFile, O_RDWR|O_EXCL); printf("%s:opened %s\n", myname, DataFile); for(i=0; i < 30; i++){ if(rand()%2) readAccess(); else writeAccess(); } close(fd); printf("%s:finished\n", myname); wait(NULL); fcleanup(0); return 0; } . , 1992-95 - 243 - UNIX void writeAccess(){ flock_t lock; printf("Write:%s #%d\n", myname, trial); lock.l_type = F_WRLCK; lock.l_whence = SEEK_SET; lock.l_start = (off_t) OFFSET; lock.l_len = (size_t) SIZE; if(fcntl(fd, F_SETLKW, &lock) <0) perror("F_SETLKW"); printf("\twrite:%s locked\n", myname); sprintf(buffer, "%s #%02d", myname, trial); printf ("\twrite:%s \"%s\"\n", myname, buffer); lseek (fd, (off_t) OFFSET, SEEK_SET); write (fd, buffer, SIZE); sleep (PAUSE); lock.l_type = F_UNLCK; if(fcntl(fd, F_SETLKW, &lock) <0) perror("F_SETLKW"); printf("\twrite:%s unlocked\n", myname); trial++; } void readAccess(){ flock_t lock; printf("Read:%s #%d\n", myname, trial); lock.l_type = F_RDLCK; lock.l_whence = SEEK_SET; lock.l_start = (off_t) OFFSET; lock.l_len = (size_t) SIZE; if(fcntl(fd, F_SETLKW, &lock) <0) perror("F_SETLKW"); printf("\tread:%s locked\n", myname); lseek(fd, (off_t) OFFSET, SEEK_SET); read (fd, buffer, SIZE); printf("\tcontents:%s \"%*.*s\"\n", myname, SIZE, SIZE, buffer); sleep (PAUSE); lock.l_type = F_UNLCK; if(fcntl(fd, F_SETLKW, &lock) <0) perror("F_SETLKW"); printf("\tread:%s unlocked\n", myname); trial++; } . , 1992-95 - 244 - UNIX , , READ- - ; READ WRITE . A - B A ( - ). A - B B A. 6.9.2. UNIX SVR4 : lockf. #include <unistd.h> int lockf(int fd, int operation, size_t size); operation: F_ULOCK ( ). F_LOCK F_TLOCK . , , F_LOCK , F_TLOCK - ( - -1, errno EAGAIN). - / . - : - fd ( fcntl, - ); size. size . - " ". " " , . , ( ). - , , - . F_TEST . 0, ; -1 (). , , - . : ___________#######____######__________ :______________##########______________ : ___________#################__________ , , . : ___________#################__________ :______________XXXXXXXXXX______________ : ___________###__________####__________ 6.10. .   ( FS), .. / . (, )  . FS I- 1. FS : . , 1992-95 - 245 - UNIX - - , (- /boot, - /unix); -  - , ( ), (512, 1024, ...), I-, - , FS; - I- - "I-".  - - -"" FS. : - , : /usr/abs/bin/hackIt bin/hackIt ./../../bin/vi ( , , - ); - , - . FS  I-, : - () , , : dev_t i_dev; - I- : ino_t i_number;     namei ( - ): struct inode *ip = namei(...); I- i_dev i_number ( !). .  . ( ) - , ;  . , file inode, - I- - , . . ( ): #include <sys/types.h> #include <sys/inode.h> #include <sys/file.h> int fd_read = open(ߔ, O_RDONLY){ int fd; struct inode *ip; struct file *fp; dev_t dev; u_error = 0; /* errno */ // . I- : ip = namei(ߔ, LOOKUP); // namei , if(u_error) return(-1); // // " ": fp = falloc(ip, FREAD); // fp->f_flag = FREAD; . , 1992-95 - 246 - UNIX // fp->f_offset = 0; RWptr // fp->f_inode = ip; I- // for(fd=0; fd < NOFILE; fd++) if(u_ofile[fd] == NULL ) // goto done; u_error = EMFILE; return (-1); done: u_ofile[fd] = fp; // - . // openi(ip, fp->f_flag); dev = ip->i_rdev; if((ip->i_mode & IFMT) == IFCHR) (*cdevsw[major(dev)].d_open)(minor(dev),fp->f_flag); else if((ip->i_mode & IFMT) == IFBLK) (*bdevsw[major(dev)].d_open)(minor(dev),fp->f_flag); return fd; // u_rval1 } close(fd){ struct file *fp = u_ofile[fd]; struct inode *ip = fp->f_inode; dev_t dev = ip->i_rdev; if((ip->i_mode & IFMT) == IFCHR) (*cdevsw[major(dev)].d_close)(minor(dev),fp->f_flag); else if((ip->i_mode & IFMT) == IFBLK) (*bdevsw[major(dev)].d_close)(minor(dev),fp->f_flag); u_ofile[fd] = NULL; // . } . I- . - , - - ( " " ). , i_addr[], n- bno- : bno = ip->i_addr[n]; , - . . , i_addr[0]  , . i_rdev, .. #define i_rdev i_addr[0] ( union). -, ( - ); -, - ( - ). , ,   ip->i_mode & IFMT . , 1992-95 - 247 - UNIX : IFCHR - ; IFBLK - . : ushort u_pboff; // ushort u_pbsize; // // ushort - unsigned short, <sys/types.h> // daddr_t - long (disk address) daddr_t bmap(struct inode *ip, off_t offset, unsigned count){ int sz, rem; // RWptr. // BSIZE - , // <sys/param.h> daddr_t bno = offset / BSIZE; // BSIZE == 1 , offset >> 10 u_pboff = offset % BSIZE; // offset & 01777 sz = BSIZE - u_pboff; // , // u_pboff. if(count < sz) sz = count; u_pbsize = sz; , - "" , .. : if((ip->i_mode & IFMT) == IFBLK) // block device return bno; // raw disk // : rem = ip->i_size /* */ - offset; // . if( rem < 0 ) rem = 0; // , : if( rem < sz ) sz = rem; if((u_pbsize = sz) == 0) return (-1); // EOF // , , . . return ip->i_addr[bno]; } read. , u_..., - u-area . read(int fd, char *u_base, unsigned u_count){ unsigned srccount = u_count; struct file *fp = u_ofile[fd]; struct inode *ip = fp->f_inode; struct buf *bp; daddr_t bno; // // dev - , //  -, //   . dev_t dev = (ip->i_mode & (IFCHR|IFBLK)) ? . , 1992-95 - 248 - UNIX ip->i_rdev : ip->i_dev; switch( ip->i_mode & IFMT ){ case IFCHR: // - (*cdevsw[major(dev)].d_read)(minor(dev)); // u-area break; case IFREG: // case IFDIR: // case IFBLK: // - do{ bno = bmap(ip, fp->f_offset /*RWptr*/, u_count); if(u_pbsize==0 || (long)bno < 0) break; // EOF bp = bread(dev, bno); // block read iomove(bp->b_addr + u_pboff, u_pbsize, B_READ); iomove bp->b_addr[ u_pboff..u_pboff+u_pbsize-1 ] ( ) u_base[ 0..u_pbsize-1 ] u_pbsize (u_base iomove ). write(), iomove B_WRITE - . : // : u_count -= u_pbsize; u_base += u_pbsize; fp->f_offset += u_pbsize; // RWptr } while( u_count != 0 ); break; ... return( srccount - u_count ); } // end read . , . i_rdev. UNIX ( dev_t) , -  , : #define major(dev) ((dev >> 8) & 0x7F) #define minor(dev) ( dev & 0xFF)    (, , ...) - ( 8 , );    (... 0..7). . . - - bdevsw[], - - - cdevsw[] (. <sys/conf.h>; block/character device switch). , , . .  , . . , 1992-95 - 249 - UNIX  - ; ( , , , ... ) .  ( ). , - open, close, read, write, ioctl, select. open - (++ip->i_count==1) - , ; close - (--ip->i_count==0). - read write strategy, B_READ B_WRITE. ioctl - . select - : (- , clist- ? . " "). select (socket-). , (, read ), nodev; , ( write /dev/null) - nulldev. - "": {}. - . UNIX  |-. bp=bread(dev,bno); bno dev. : - (cache, ""). - (struct buf) (. <sys/buf.h>): b_dev , ; b_blkno , ; b_flags (. ); b_addr ( ), . . - bread() (dev,bno) -. , , . -, , b_dev b_blkno, bp->b_flags |= B_READ; // : (*bdevsw[major(dev)].d_startegy)(bp); // bno - *bp . - write(), - , . : b_flags |= B_DELWRI; // ____________________ |- stdio. , . . , 1992-95 - 250 - UNIX . : - sync(); - - ( ). ( ) . - umount; ,   (.. ). close, - sync. , "" - , , : - . "" -. : , . "" - . "" , .. , . /, , . , ( - ), - . - "" - sync(); // synchronize sync 30 /etc/update, . ,