setuid


Rev.1を表示中。最新版はこちら

ファイルオープン時、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);
}

補足

sgidの処理がif ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP))と、S_IXGRPとでチェックしているのは、強制ロックでの、xが設定されていなく、sgidが設定を考慮したものです。


最終更新 2012/11/29 18:30:46 - north
(2012/11/29 18:30:46 作成)


検索

アクセス数
3585495
最近のコメント
コアダンプファイル - sakaia
list_head構造体 - yocto_no_yomikata
勧告ロックと強制ロック - wataash
LKMからのファイル出力 - 重松 宏昌
kprobe - ななし
ksetの実装 - スーパーコピー
カーネルスレッドとは - ノース
カーネルスレッドとは - nbyst
asmlinkageってなに? - ノース
asmlinkageってなに? - よろしく
Adsense
広告情報が設定されていません。