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); };