mountのMS_NOSUID


MS_NOSUIDオプションでmountすると、setuid/setgidが無効になります。MS_NOSUIDオプションでmountシステムコールを呼び出すと、マウントフラグとして MNT_NOSUIDでファイルシステムをマウントします。
long do_mount(char *dev_name, char *dir_name, char *type_page,
                 unsigned long flags, void *data_page)
{

       if (flags & MS_NOSUID)
               mnt_flags |= MNT_NOSUID;
       if (flags & MS_NODEV)
               mnt_flags |= MNT_NODEV;
       if (flags & MS_NOEXEC)
               mnt_flags |= MNT_NOEXEC;
       if (flags & MS_NOATIME)
               mnt_flags |= MNT_NOATIME;
       if (flags & MS_NODIRATIME)
               mnt_flags |= MNT_NODIRATIME;
       if (flags & MS_STRICTATIME)
               mnt_flags &= ~(MNT_RELATIME | MNT_NOATIME);
       if (flags & MS_RDONLY)
               mnt_flags |= MNT_READONLY;

       flags &= ~(MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_ACTIVE | MS_BORN |
                  MS_NOATIME | MS_NODIRATIME | MS_RELATIME| MS_KERNMOUNT |
                  MS_STRICTATIME);

       if (flags & MS_REMOUNT)
               retval = do_remount(&path, flags & ~MS_REMOUNT, mnt_flags,
                                   data_page);
       else if (flags & MS_BIND)
               retval = do_loopback(&path, dev_name, flags & MS_REC);
       else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE))
               retval = do_change_type(&path, flags);
       else if (flags & MS_MOVE)
               retval = do_move_mount(&path, dev_name);
       else
               retval = do_new_mount(&path, type_page, flags, mnt_flags,
                                     dev_name, data_page);
dput_out:
       path_put(&path);
       return retval;
}
ファイルを実行すると、do_exec()からprepare_binprm()がコールされ、bprm->cred->euid = current_euid()/bprm->cred->egid = current_egid()で親プロセスで初期化し、実行しようとしているファイルのファイルシステムのマウントフラグが、MNT_NOSUIDでないなら、bprm->cred->euid = inode->i_uid/bprm->cred->egid = inode->i_gidで更新して、kernel_read()をコールすることになります。
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;

       /* clear any previous set[ug]id data from a previous binary */
       bprm->cred->euid = current_euid();
       bprm->cred->egid = current_egid();

       if (!(bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)) {
               /* Set-uid? */
               if (mode & S_ISUID) {
                       bprm->per_clear |= PER_CLEAR_ON_SETID;
                       bprm->cred->euid = inode->i_uid;
               }

               /* Set-gid? */
               if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
                       bprm->per_clear |= PER_CLEAR_ON_SETID;
                       bprm->cred->egid = inode->i_gid;
               }
       }

       /* fill in binprm security blob */
       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);
}
proc_fill_super()は、procfsのスーパブロック取得のコールバック関数です。この時s->s_flags |= MS_NODIRATIME | MS_NOSUID | MS_NOEXECとしています。procfsではスーパブロックオプションの位置づけで設定されています。従って再マウントする事で、setuid/setgidを有効にできないようになっています。
int proc_fill_super(struct super_block *s)
{
       struct inode * root_inode;

       s->s_flags |= MS_NODIRATIME | MS_NOSUID | MS_NOEXEC;
       s->s_blocksize = 1024;
       s->s_blocksize_bits = 10;
       s->s_magic = PROC_SUPER_MAGIC;
       s->s_op = &proc_sops;
       s->s_time_gran = 1;
       
       pde_get(&proc_root);
       root_inode = proc_get_inode(s, &proc_root);
       if (!root_inode)
               goto out_no_root;
       root_inode->i_uid = 0;
       root_inode->i_gid = 0;
       s->s_root = d_alloc_root(root_inode);
       if (!s->s_root)
               goto out_no_root;
       return 0;

out_no_root:
       printk("proc_read_super: get root inode failed\n");
       iput(root_inode);
       pde_put(&proc_root);
       return -ENOMEM;
}


最終更新 2013/12/30 15:47:46 - north
(2013/12/30 15:47:46 作成)


検索

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