setuid
Rev.3を表示中。最新版はこちら。
ファイルオープン時、rw等のチェックをした後、inode_owner_or_capable()で、current_fsuid() == inode->i_uidとし、ファイル所有者にかかるチェックを行います。current_fsuid()はカレントタスクディスクリプタ下のメンバーcredで、ここに実行uid等の情報が設定されています。
struct task_struct {
:
const struct cred __rcu *cred;
:
}
struct cred {
:
uid_t euid; /* effective UID of the task */
gid_t egid; /* effective GID of the task */
uid_t fsuid; /* UID for VFS ops */
gid_t fsgid; /* GID for VFS ops */
:
};
bool inode_owner_or_capable(const struct inode *inode)
{
struct user_namespace *ns = inode_userns(inode);
if (current_user_ns() == ns && current_fsuid() == inode->i_uid)
return true;
if (ns_capable(ns, CAP_FOWNER))
return true;
return false;
}
EXPORT_SYMBOL(inode_owner_or_capable);
inode_init_owner()はinode取得時にコールされ、inodeのuidは取得したカレントプロセスのファイル操作uidが設定されています。
void inode_init_owner(struct inode *inode, const struct inode *dir,
umode_t mode)
{
inode->i_uid = current_fsuid();
if (dir && dir->i_mode & S_ISGID) {
inode->i_gid = dir->i_gid;
if (S_ISDIR(mode))
mode |= S_ISGID;
} else
inode->i_gid = current_fsgid();
inode->i_mode = mode;
}
EXPORT_SYMBOL(inode_init_owner);
プログラムを起動すると言うのは、forkで作成されたプロセスに、ファイルから実行イメージを読み込んで差し替えるということです。その差し替えはdo_exeシステムコールで行うのですが、実行イメージの各種情報をstruct linux_binprm *bprmに設定して、起動ローダの引数として、この*bprmの情報がタスクデュスクリプタに反映されることになります。setuidの処理は、struct linux_binprm *bprmを設定するprepare_binprm()で行っています。デフォルトでは、カレントの実行uid/gidがstruct linux_binprm *bprmに設定されていますが、実行ファイルにsetuidが設定されていると、タスクデュスクリプタの実行uidは、ファイルのユーザidが設定されるようになっています。
int prepare_binprm(struct linux_binprm *bprm)
{
umode_t mode;
struct inode * inode = bprm->file->f_path.dentry->d_inode;
int retval;
mode = inode->i_mode;
if (bprm->file->f_op == NULL)
return -EACCES;
bprm->cred->euid = current_euid();
bprm->cred->egid = current_egid();
if (!(bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)) {
if (mode & S_ISUID) {
bprm->per_clear |= PER_CLEAR_ON_SETID;
bprm->cred->euid = inode->i_uid;
}
if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
bprm->per_clear |= PER_CLEAR_ON_SETID;
bprm->cred->egid = inode->i_gid;
}
}
retval = security_bprm_set_creds(bprm);
if (retval)
return retval;
bprm->cred_prepared = 1;
memset(bprm->buf, 0, BINPRM_BUF_SIZE);
return kernel_read(bprm->file, 0, bprm->buf, BINPRM_BUF_SIZE);
}






