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