mishimaの日記: Debian lenny/sid libc6 patch for problem with RHEL4/5 ABI
RHEL4 and 5 has a problem in those kernels. glibc-2.7 and programs linking with it does not work in these RHEL. Of course, the programs include not only VPS but also chroot jail.
If you install Debian etch chroot-jail to RHEL5, it works fine because it's linking with glibc-2.3.
If you install Debian lenny/sid chroot-jail to RHEL5, it does not work.
Some daemons would output error like this:
Becoming sub class of "Net::Server::PreFork"
2007/12/14-19:45:07 main (type MySmtpProxyServer) starting! pid(32338)
Binding to TCP port 10025 on host akatsuki
2007/12/14-19:45:07 Can't connect to TCP port 10025 on akatsuki [Unknown error 530]
at line 88 in file /usr/share/perl5/Net/Server/Proto/TCP.pm
2007/12/14-19:45:07 Server closing!
.
To solve this problem, you could apply following patch to libc6 of Debian lenny/sid.
--- 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)
+
save above patch in another Debian machine running under Debian-supported kernel, and build libc6-*.deb in there.
% 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
Let's enjoy.
Debian lenny/sid libc6 patch for problem with RHEL4/5 ABI More ログイン