Funkcja chown - kod zrodlowy.
Ta funkcja pochodzi z pliku fs/open.c.
asmlinkage int sys_chown(const char * filename, uid_t user, gid_t group)
{
struct inode * inode;
int error;
struct iattr newattrs;
error = lnamei(filename,&inode);
if (error)
return error;
if (IS_RDONLY(inode)) {
/* to znaczy, ze fs jest read-only */
iput(inode);
return -EROFS;
}
if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) {
iput(inode);
return -EPERM;
}
/*******************
(uid_t) -1 oznacza rzutowanie -1 na typ uid_t,
wiec gdy user == -1, to nie zmieniaj wlasciciela pliku.
Tak samo dla grupy.
********************/
if (user == (uid_t) -1)
user = inode->i_uid;
/* jesli argumentem user jest -1, to wez tego z pliku */
if (group == (gid_t) -1)
/* to samo dla grupy */
group = inode->i_gid;
newattrs.ia_mode = inode->i_mode;
/* podstawiamy sobie te rzeczy to struktury iattr */
/********************
struct inode { umode_t i_mode; ... }
types.h:typedef unsigned short umode_t;
********************/
newattrs.ia_uid = user;
newattrs.ia_gid = group;
newattrs.ia_valid = ATTR_UID | ATTR_GID | ATTR_CTIME;
/******************************* 2 ******** 4 ******** 64 *********/
/*** tzn. ze traci waznosc atrybut wlasciciela, grupy i change-time ***/
(tzn. czas ostatniej
modyfikacji i-wezla )
if (user != inode->i_uid && (inode->i_mode & S_ISUID)) {
/* jesli ustawiony jest bit setuid, ... */
newattrs.ia_mode &= ~S_ISUID; /*** ~ ozn. bitowa negacja ***/
/* to usun ten bit */
newattrs.ia_valid |= ATTR_MODE; /*** 1 ***/
/* traca waznosc stare prawa dostepu do pliku */
}
/*********** stat.h: #define S_ISUID 0004000 (osemkowo),
oznacza setuid bit, czyli ustawienie przy wykonywaniu efektywnego euid
procesu na ten, co ma plik.
***********/
/* Jesli grupa sie zmienila, usun bit setgid.
*
* Nie usuwaj bitu setgid, jesli nie ma bitu wykonywania dla grupy.
*/
if (group != inode->i_gid &&
((inode->i_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP))) {
/********************* 0002000 00010
/********************* prawo wyk. dla grupy ****************/
newattrs.ia_mode &= ~S_ISGID;
newattrs.ia_valid |= ATTR_MODE;
}
inode->i_dirt = 1;
if (inode->i_sb->dq_op) {
inode->i_sb->dq_op->initialize(inode, -1);
/* Initialize pointer in a inode to the right dquots. */
if (inode->i_sb->dq_op->transfer(inode, &newattrs, 0))
/* Transfer the number of inode and blocks from one
diskquota to an other. */
return -EDQUOT;
error = notify_change(inode, &newattrs);
if (error)
inode->i_sb->dq_op->transfer(inode, &newattrs, 1);
/* transfer quoty z powrotem */
} else
error = notify_change(inode, &newattrs);
iput(inode); /*** zwolnij i-wezel ***/
return(error);
}
Funkcja notify_change - kod zrodlowy.
int notify_change(struct inode * inode, struct iattr *attr)
{
/* algorytm dokladnie opisalem w HTML'u (M.H.) */
int retval;
attr->ia_ctime = CURRENT_TIME;
if (attr->ia_valid & (ATTR_ATIME | ATTR_MTIME)) {
if (!(attr->ia_valid & ATTR_ATIME_SET))
attr->ia_atime = attr->ia_ctime;
if (!(attr->ia_valid & ATTR_MTIME_SET))
attr->ia_mtime = attr->ia_ctime;
}
if (inode->i_sb && inode->i_sb->s_op &&
inode->i_sb->s_op->notify_change)
/*** ext2 ma dla notify_change NULL'a,
s_op to super_operations ***/
return inode->i_sb->s_op->notify_change(inode, attr);
if ((retval = inode_change_ok(inode, attr)) != 0)
return retval;
inode_setattr(inode, attr);
return 0;
}
Funkcja inode_change_ok.
/* weryfikacja typu POSIX UID/GID dla ustalania atrbutow i-wezla */
int inode_change_ok(struct inode *inode, struct iattr *attr)
/* po wnikliwej analizie wyprodukowalem to, co jest pod Wordem o tej
funkcji. Sa tam wg. mnie wszystkie przypadki */
{
/*
* Jesli ustawione jest FORCE, to nic nie sprawdzaj.
*/
if (attr->ia_valid & ATTR_FORCE)
return 0;
/* Upewnij sie, ze proces moze zmieniac wlasciciela pliku: */
if ((attr->ia_valid & ATTR_UID) &&
(current->fsuid != inode->i_uid ||
attr->ia_uid != inode->i_uid) && !fsuser())
return -EPERM;
/* Upewnij sie, ze proces moze zmienic grupe plikowi: */
if ((attr->ia_valid & ATTR_GID) &&
(!in_group_p(attr->ia_gid) && attr->ia_gid != inode->i_gid) &&
!fsuser())
return -EPERM;
/* in_group_p sprawdza, czy proces jest w podanej grupie */
/* Upewnij sie, ze proces moze zmieniac tryb dostepu: */
if (attr->ia_valid & ATTR_MODE) {
if ((current->fsuid != inode->i_uid) && !fsuser())
return -EPERM;
/* Also check the setgid bit! */
if (!fsuser() && !in_group_p((attr->ia_valid & ATTR_GID) ? attr->ia_gid :
inode->i_gid))
attr->ia_mode &= ~S_ISGID;
}
/* Sprawdz, czy proces moze zmieniac czas: */
if ((attr->ia_valid & ATTR_ATIME_SET) &&
((current->fsuid != inode->i_uid) && !fsuser()))
return -EPERM;
if ((attr->ia_valid & ATTR_MTIME_SET) &&
((current->fsuid != inode->i_uid) && !fsuser()))
return -EPERM;
return 0;
}
Odnosniki:
kernel.h:
#define fsuser() (current->fsuid == 0)
fs.h: /* To jest struktura Atrybuty I-wezla, uzywana do notify_change().
Zasadniczo, to sa atrybuty, ktorych warstwa wirtualnego file-systemu (VFS) moze
zadac (ang. request) zmiany przez rzeczywisty system plikow. */
struct iattr {
unsigned int ia_valid;
umode_t ia_mode;
uid_t ia_uid;
gid_t ia_gid;
off_t ia_size;
time_t ia_atime;
time_t ia_mtime;
time_t ia_ctime;
};
fs.h:
#define IS_IMMUTABLE(inode) ((inode)->i_flags & S_IMMUTABLE) #define S_IMMUTABLE 512 /* Immutable file */
#define IS_APPEND(inode) ((inode)->i_flags & S_APPEND) #define S_APPEND 256 /* Append-only file */
fs.h:
Czesc struktury super_block to: struct dquot_operations *dq_op;
struct dquot_operations {
void (*initialize) (struct inode *, short);
void (*drop) (struct inode *);
int (*alloc_block) (const struct inode *, unsigned long);
int (*alloc_inode) (const struct inode *, unsigned long);
void (*free_block) (const struct inode *, unsigned long);
void (*free_inode) (const struct inode *, unsigned long);
int (*transfer) (struct inode *, struct iattr *, char);
};