パスワードを忘れた? アカウント作成
402417 journal

mishimaの日記: 先日の困ったなぁ…の解決策

日記 by mishima

libc にパッチを当ててみた。とりあえずうまく動いてはいるようだ。こんな感じの内容だ。

--- sysdeps/unix/sysv/linux/openat.c.orig       2008-02-14 16:43:27.000000000 +0900
+++ sysdeps/unix/sysv/linux/openat.c    2008-02-14 16:45:38.000000000 +0900
@@ -87,13 +87,17 @@
 
   INTERNAL_SYSCALL_DECL (err);
   int res;
+  int o_cloexec;
 
  #ifdef __NR_openat
  # ifndef __ASSUME_ATFCTS
   if (__have_atfcts >= 0)
  # endif
     {
+      o_cloexec = oflag & O_CLOEXEC;
+      oflag &= ~O_CLOEXEC;
       res = INLINE_SYSCALL (openat, 4, fd, file, oflag, mode);
+      if( res >= 0 && o_cloexec ) fcntl(res, F_SETFD, FD_CLOEXEC);
 
  # ifndef __ASSUME_ATFCTS
       if (res == -1 && errno == ENOSYS)
@@ -126,6 +130,8 @@
       file = buf;
     }
 
+  o_cloexec = oflag & O_CLOEXEC;
+  oflag &= ~O_CLOEXEC;
   res = INTERNAL_SYSCALL (open, err, 3, file, oflag, mode);
 
   if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (res, err), 0))
@@ -133,6 +139,7 @@
       __atfct_seterrno (INTERNAL_SYSCALL_ERRNO (res, err), fd, buf);
       res = -1;
     }
+  if( res >= 0 && o_cloexec ) fcntl(res, F_SETFD, FD_CLOEXEC);
 
   return res;
  #endif
--- sysdeps/unix/sysv/linux/not-cancel.h.orig    2008-02-15 13:33:39.000000000 +0900
+++ sysdeps/unix/sysv/linux/not-cancel.h    2008-02-15 13:39:31.000000000 +0900
@@ -22,10 +22,21 @@
  #include <sysdep.h>
 
  /* Uncancelable open.  */
+static int __internal_open_not_cancel( const char* name, int flags, mode_t mode ){
+    int r = INLINE_SYSCALL ( open, 3, name, flags&~O_CLOEXEC, mode );
+    if( r >= 0 && flags&O_CLOEXEC ) fcntl( res, F_SETFD, FD_CLOEXEC );
+    return r;
+}
+static int __internal_open_not_cancel_2( const char* name, int flags ){
+    int r = INLINE_SYSCALL ( open, 2, name, flags&~O_CLOEXEC );
+    if( r >= 0 && flags&O_CLOEXEC ) fcntl( res, F_SETFD, FD_CLOEXEC );
+    return r;
+}
+
  #define open_not_cancel(name, flags, mode) \
-   INLINE_SYSCALL (open, 3, (const char *) (name), (flags), (mode))
+   __internal_open_not_cancel ( (name), (flags), (mode) )
  #define open_not_cancel_2(name, flags) \
-   INLINE_SYSCALL (open, 2, (const char *) (name), (flags))
+   __internal_open_not_cancel_2 ( (name), (flags) )
 
  /* Uncancelable openat.  */
  #if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
--- sysdeps/unix/sysv/linux/open64.c.orig    2008-02-15 13:36:54.000000000 +0900
+++ sysdeps/unix/sysv/linux/open64.c    2008-02-15 13:45:59.000000000 +0900
@@ -38,12 +38,16 @@
       va_end (arg);
     }
 
-  if (SINGLE_THREAD_P)
-    return INLINE_SYSCALL (open, 3, file, oflag | O_LARGEFILE, mode);
+  if (SINGLE_THREAD_P){
+    int r = INLINE_SYSCALL (open, 3, file, (oflag&~O_CLOEXEC)|O_LARGEFILE, mode);
+    if( r >= 0 && oflag&O_CLOEXEC ) fcntl( r, F_SETFD, FD_CLOEXEC );
+    return r;
+  }
 
   int oldtype = LIBC_CANCEL_ASYNC ();
 
-  int result = INLINE_SYSCALL (open, 3, file, oflag | O_LARGEFILE, mode);
+  int result = INLINE_SYSCALL (open, 3, file, (oflag&~O_CLOEXEC)|O_LARGEFILE, mode);
+  if( result >= 0 && oflag&O_CLOEXEC ) fcntl( result, F_SETFD, FD_CLOEXEC );
 
   LIBC_CANCEL_RESET (oldtype);
 
@@ -63,12 +67,16 @@
   if (oflag & O_CREAT)
     __fortify_fail ("invalid open64 call: O_CREAT without mode");
 
-  if (SINGLE_THREAD_P)
-    return INLINE_SYSCALL (open, 2, file, oflag | O_LARGEFILE);
+  if (SINGLE_THREAD_P){
+    int r = INLINE_SYSCALL (open, 2, file, (oflag&~O_CLOEXEC)|O_LARGEFILE);
+    if( r >= 0 && oflag&O_CLOEXEC ) fcntl( r, F_SETFD, FD_CLOEXEC );
+    return r;
+  }
 
   int oldtype = LIBC_CANCEL_ASYNC ();
 
-  int result = INLINE_SYSCALL (open, 2, file, oflag | O_LARGEFILE);
+  int result = INLINE_SYSCALL (open, 2, file, (oflag&~O_CLOEXEC)|O_LARGEFILE);
+  if( result >= 0 && oflag&O_CLOEXEC ) fcntl( result, F_SETFD, FD_CLOEXEC );
 
   LIBC_CANCEL_RESET (oldtype);
 
--- sysdeps/unix/sysv/linux/open.c.orig    2008-02-15 21:26:30.000000000 +0900
+++ sysdeps/unix/sysv/linux/open.c    2008-02-15 20:03:54.000000000 +0900
@@ -0,0 +1,57 @@
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <sysdep-cancel.h>
+
+int __open_nocancel (const char *file, int oflag, ...)
+{
+  int mode = 0;
+
+  if (oflag & O_CREAT)
+    {
+      va_list arg;
+      va_start (arg, oflag);
+      mode = va_arg (arg, int);
+      va_end (arg);
+    }
+
+  int result = INLINE_SYSCALL (open, 3, file, oflag&~O_CLOEXEC, mode);
+  if( result >= 0 && oflag&O_CLOEXEC ) fcntl( result, F_SETFD, FD_CLOEXEC );
+
+  return result;
+}
+
+int __libc_open (const char *file, int oflag, ...)
+{
+  int mode = 0;
+
+  if (oflag & O_CREAT)
+    {
+      va_list arg;
+      va_start (arg, oflag);
+      mode = va_arg (arg, int);
+      va_end (arg);
+    }
+
+  if (SINGLE_THREAD_P){
+    int r = INLINE_SYSCALL (open, 3, file, oflag&~O_CLOEXEC, mode);
+    if( r >= 0 && oflag&O_CLOEXEC ) fcntl( r, F_SETFD, FD_CLOEXEC );
+    return r;
+  }
+
+  int oldtype = LIBC_CANCEL_ASYNC ();
+
+  int result = INLINE_SYSCALL (open, 3, file, oflag&~O_CLOEXEC, mode);
+  if( result >= 0 && oflag&O_CLOEXEC ) fcntl( result, F_SETFD, FD_CLOEXEC );
+
+  LIBC_CANCEL_RESET (oldtype);
+
+  return result;
+}
+libc_hidden_def (__libc_open)
+
+weak_alias (__libc_open, __open)
+libc_hidden_weak (__open)
+weak_alias (__libc_open, open)
+

で、これをこんな風に適用してみた。

% apt-get source libc6
% cd glibc-2.7
% cp ABOVE_PATCH_FILE debian/patches/i386/local-O_CLOEXEC.diff
% echo "i386/local-O_CLOEXEC.diff -p0" >> debian/patches/series
% dpkg-buildpackage

debuild だとうまくいかないので dpkg-buildpackage で。ちゃんとパッケージの形にすればいいんだろうが、面倒くさいので今のところは放置しときます。

英語圏の人のために別エントリを立ててみたが、不得意なのはわかっているので気にしないように。

この議論は賞味期限が切れたので、アーカイブ化されています。 新たにコメントを付けることはできません。
typodupeerror

吾輩はリファレンスである。名前はまだ無い -- perlの中の人

読み込み中...