2012-04-26 13 views
16

मेरा xinetd डिमन अचानक कर्नेल अपग्रेड के बाद काम करना बंद कर दिया (2.6.24 से 2.6.33 तक)। मैं एक strace चलाने के लिए और पाया है कि यह:बंद करें() x86_64 सिस्टम कॉल अजीब वापसी मूल्य

[...] 
close(3)        = 0 
munmap(0x7f1a93b43000, 4096)   = 0 
getrlimit(RLIMIT_NOFILE, {rlim_cur=8*1024, rlim_max=16*1024}) = 0 
setrlimit(RLIMIT_NOFILE, {rlim_cur=1024, rlim_max=1024}) = 0 
close(3)        = 4294967287 
exit_group(1)       = ? 

तो बुनियादी तौर पर, यह करीब सिस्टम कॉल की तरह कुछ अलग लौटे 0 से या -1 लग रहा है

मैं कई परीक्षण किया था और ऐसा लगता है कि ऐसा होता है

$ file closetest32 
closetest32: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, not stripped 
$ strace closetest32 
execve("./closetest32", ["closetest32"], [/* 286 vars */]) = 0 
[ Process PID=4731 runs in 32 bit mode. ] 
open("/proc/mounts", O_RDONLY)   = 3 
close(3)        = 0 
close(3)        = -1 EBADF (Bad file descriptor) 
_exit(0)        = ? 


$ file closetest64 
closetest64: ELF 64-bit LSB executable, AMD x86-64, version 1 (SYSV), statically linked, not stripped 
$ strace closetest64 
execve("./closetest64", ["closetest64"], [/* 286 vars */]) = 0 
open("/proc/mounts", O_RDONLY)   = 3 
close(3)        = 0 
close(3)        = 4294967287 
_exit(0)        = ? 

मैं निम्नलिखित कर्नेल चल रहा हूँ:

Linux foobar01 2.6.33.9-rt31.64.el5rt #1 SMP PREEMPT RT Wed May 4 10:34:12 EDT 2011 x86_64 x86_64 x86_64 GNU/Linux 
केवल 64 बिट निष्पादनयोग्य के साथ

सबसे बुरा हिस्सा यह है कि मैं उसी कर्नेल के साथ किसी अन्य मशीन पर बग को पुन: उत्पन्न नहीं कर सकता।

कोई विचार?

संपादित करें: अनुरोध के रूप में: यहाँ closetest32 के लिए इस्तेमाल किया कोड और closetest64 है

closetest32.asm:

as test32.asm -o test32.o --32 
ld -m elf_i386 test32.o -o closetest32 

closetest64.asm:

.section .data 

filename: 
    .ascii "/proc/mounts" 

.section .text 
.globl _start 
_start: 
    xorq %rdi, %rdi 
    movq $2, %rax # open() system call 
    leaq filename, %rdi # %rdi ---> filename 
    movq $0, %rsi # O_RDONLY flag into rsi 
    syscall 

    xorq %rdi, %rdi 
    movq $3, %rax # close() system call 
    movq $3, %rdi # fd 3 
    syscall 

    xorq %rdi, %rdi 
    movq $3, %rax # close() system call 
    movq $3, %rdi # fd 3 
    syscall 

    ## terminate program via _exit() system call 
    movq $60, %rax # %rax = _exit() system call 
    xorq %rdi, %rdi # %rdi = 0 normal program return code 
    syscall 

.section .data 

filename: 
    .ascii "/proc/mounts" 

.section .text 
.globl _start 
_start: 
    xorl %edi, %edi 
    movl $5, %eax # open() i386 system call 
    leal filename, %ebx # %ebx ---> filename 
    movl $0, %esi # O_RDONLY flag into esi 
    int $0x80 

    xorl %edi, %edi 
    movl $6, %eax # close() i386 system call 
    movl $3, %ebx # fd 3 
    int $0x80 

    xorl %edi, %edi 
    movl $6, %eax # close() i386 system call 
    movl $3, %ebx # fd 3 
    int $0x80 

    ## terminate program via _exit() system call 
    movl $1, %eax # %eax = _exit() i386 system call 
    xorl %ebx, %ebx # %ebx = 0 normal program return code 
    int $0x80 

के रूप में संकलित

संकलन:

as test64.asm -o test64.o 
ld test64.o -o closetest64 
+6

यह सुनिश्चित नहीं है कि यह संबंधित है, लेकिन संभवतः संयोग से, लौटा मूल्य 0xFFFFFFF7 = -9। और ईबीएडीएफ = + 9। जिज्ञासु। –

+0

क्या आप closetest64/32 का स्रोत कोड दिखा सकते हैं? – JeremyP

+0

दोनों मशीनों पर स्ट्रेस बाइनरी और ग्लिबैक क्या संस्करण है? मैंने अभी 32/64 दोनों के लिए एक साधारण परीक्षण और 4.5.20 प्रिंट -1 ईबीएडीएफ को चिपकाया है। libc - 2.13 – strkol

उत्तर

1

जैसा कि अपेक्षित था, पिछले कर्नेल संस्करण के रोलबैक ने समस्या हल की। मैं वास्तव में एक कर्नेल विशेषज्ञ नहीं हूँ लेकिन जहां तक ​​मैं समझता हूँ, जवाब @R द्वारा दिए गए .. बनाता है भावना:

यह एक 64-बिट मशीन है, इसलिए 1 < < 32-9 नहीं दिखना चाहिए । समस्या यह है कि कर्नेल आंतरिक रूप से इन कार्यों में से कुछ के रिटर्न वैल्यू के लिए इंटिनेटेड का उपयोग कर आंतरिक रूप से उपयोग कर रहा है, फिर -ईबीएडीएफ लौटाता है जो मॉड्यूलो 2^64

की बजाय मॉड्यूलो 2^32 को कम करता है समस्या यह है कि जेनेरिक syccall त्रुटि रिटर्न को संभालने वाले libc syscall wrappers में कोड को रिटर्न वैल्यू को लंबे समय तक इलाज करना पड़ता है (क्योंकि यह एक संकेतक हो सकता है या कुछ सिस्कोल के लिए लंबा हो सकता है) जब यह देखने के लिए तुलना की जाती है कि यह एक छोटा नकारात्मक मान है जो त्रुटि का संकेत देगा । लेकिन कर्नेल लौटा (लंबा) (हस्ताक्षरित) -9 जो कि (लंबे) -9 से बहुत अलग है। या (हस्ताक्षर किए गए लंबे समय -9 (जिनमें से कोई भी काम करता)।

संबंधित मुद्दे