無料Wikiサービス | デモページ
検索

アクセス数
最近のコメント
kprobe - ななし
ksetの実装 - スーパーコピー
カーネルスレッドとは - ノース
カーネルスレッドとは - nbyst
asmlinkageってなに? - ノース
asmlinkageってなに? - よろしく
はじめ - ノース
はじめ - ノース
はじめ - 楽打連動ユーザー
はじめ - 楽打連動ユーザー
Adsense
広告情報が設定されていません。

O_CLOEXEC


ファイルモードがO_CLOEXECなら、exec(外部コマンド)によるプロセスでは、そのファイルを参照する事はできません。
[root@localhost c]# cat closeexec1.c
#include <stdio.h>
#include <fcntl.h>

void main(int argc, char* argv[])
{
       int     pfd1[2], pfd2[2];

       pipe2(pfd1, 0);
       dup3(pfd1[0], 253, 0);

       pipe2(pfd2, 0);
       dup3(pfd2[0], 254, O_CLOEXEC);

       write(pfd1[1], "01234", 5);
       write(pfd2[1], "56789", 5);
       system("./closeexec2.o");
}

[root@localhost c]# cat closeexec2.c
#include <stdio.h>
#include <string.h>

void main(int argc, char* argv[])
{
       int     ret;
       char    buff[6];

       printf("read from NO_O_CLOEXEC\n");
       memset(buff, 0, 6);
       ret = read(253,buff, 5);
       printf("%2d:%s\n", ret, buff);

       printf("read from O_CLOEXEC\n");
       memset(buff, 0, 6);
       ret = read(254,buff, 5);
       printf("%2d:%s\n", ret, buff);

}

[root@localhost c]# ./closeexec1.o
read from NO_O_CLOEXEC
 5:01234
read from O_CLOEXEC
-1:
alloc_fd()でcurrent->file[file ID] = struct file *file;としファイルIDを取得します。flagsがO_CLOEXECなら、そのファイルIDをcurrent->files->fdt->close_on_execのビット位置として設定され、forkで継承した子プロセスのclose_on_execのビット位置の掛かるファイルをexecでcloseされます。
#define FD_SET(fd,fdsetp)       __FD_SET(fd,fdsetp)

int alloc_fd(unsigned start, unsigned flags)
{
       struct files_struct *files = current->files;
       unsigned int fd;
       int error;
       struct fdtable *fdt;

       spin_lock(&files->file_lock);
repeat:
       fdt = files_fdtable(files);
       fd = start;
       if (fd < files->next_fd)
               fd = files->next_fd;

       if (fd < fdt->max_fds)
               fd = find_next_zero_bit(fdt->open_fds->fds_bits,
                                          fdt->max_fds, fd);

       error = expand_files(files, fd);
       if (error < 0)
               goto out;

       if (error)
               goto repeat;

       if (start <= files->next_fd)
               files->next_fd = fd + 1;

       FD_SET(fd, fdt->open_fds);
       if (flags & O_CLOEXEC)
               FD_SET(fd, fdt->close_on_exec);
       else
               FD_CLR(fd, fdt->close_on_exec);
       error = fd;
#if 1
       if (rcu_dereference_raw(fdt->fd[fd]) != NULL) {
               printk(KERN_WARNING "alloc_fd: slot %d not NULL!\n", fd);
               rcu_assign_pointer(fdt->fd[fd], NULL);
       }
#endif

out:
       spin_unlock(&files->file_lock);
       return error;
}
O_CLOEXECできるファイルIDの最大は1024で、longサイズが4バイト時fds_bits[32]です。
#define __NFDBITS       (8 * sizeof(unsigned long))
#define __FD_SETSIZE    1024
#define __FDSET_LONGS   (__FD_SETSIZE/__NFDBITS)

typedef struct {
       unsigned long fds_bits [__FDSET_LONGS];
} __kernel_fd_set;

static inline void __FD_SET(unsigned long __fd, __kernel_fd_set *__fdsetp)
{
       unsigned long __tmp = __fd / __NFDBITS;
       unsigned long __rem = __fd % __NFDBITS;
       __fdsetp->fds_bits[__tmp] |= (1UL<<__rem);
}
execはsearch_binary_handler()でコマンドファイルのファイルシステムのstruct linux_binfmtを取得し、load_elf_binaryコールバックでコマンドイメージをロードします。この時、flush_old_files()でfdt->close_on_exec->fds_bits[]毎のセットされているビット位置をファイルIDとするファイルをクローズします。
static void flush_old_files(struct files_struct * files)
{
       long j = -1;
       struct fdtable *fdt;

       spin_lock(&files->file_lock);
       for (;;) {
               unsigned long set, i;

               j++;
               i = j * __NFDBITS;
               fdt = files_fdtable(files);
               if (i >= fdt->max_fds)
                       break;
               set = fdt->close_on_exec->fds_bits[j];
               if (!set)
                       continue;
               fdt->close_on_exec->fds_bits[j] = 0;
               spin_unlock(&files->file_lock);
               for ( ; set ; i++,set >>= 1) {
                       if (set & 1) {
                               sys_close(i);
                       }
               }
               spin_lock(&files->file_lock);
       }
       spin_unlock(&files->file_lock);
}

追記

pipe作成でのpipe2()でO_CLOEXECを設定する事はできません。又fctrlでの設定もできません。dup3()で複写したpipeにしかO_CLOEXECを設定できません。

最終更新 2016/12/01 15:56:37 - north
(2015/01/10 19:39:14 作成)