summaryrefslogtreecommitdiff
path: root/libc/sysdeps/unix/sysv/linux
diff options
context:
space:
mode:
Diffstat (limited to 'libc/sysdeps/unix/sysv/linux')
-rw-r--r--libc/sysdeps/unix/sysv/linux/Makefile4
-rw-r--r--libc/sysdeps/unix/sysv/linux/accept4.c49
-rw-r--r--libc/sysdeps/unix/sysv/linux/i386/accept4.S4
-rw-r--r--libc/sysdeps/unix/sysv/linux/ia64/____longjmp_chk.S48
-rw-r--r--libc/sysdeps/unix/sysv/linux/ia64/__longjmp.S10
-rw-r--r--libc/sysdeps/unix/sysv/linux/internal_accept4.S14
-rw-r--r--libc/sysdeps/unix/sysv/linux/kernel-features.h2
-rw-r--r--libc/sysdeps/unix/sysv/linux/socketcall.h4
8 files changed, 124 insertions, 11 deletions
diff --git a/libc/sysdeps/unix/sysv/linux/Makefile b/libc/sysdeps/unix/sysv/linux/Makefile
index 0c1dcee0c..a41624e37 100644
--- a/libc/sysdeps/unix/sysv/linux/Makefile
+++ b/libc/sysdeps/unix/sysv/linux/Makefile
@@ -11,6 +11,10 @@ ifeq ($(subdir),malloc)
CFLAGS-malloc.c += -DMORECORE_CLEARS=2
endif
+ifeq ($(subdir),socket)
+sysdep_routines += internal_accept4
+endif
+
ifeq ($(subdir),misc)
sysdep_routines += sysctl clone llseek umount umount2 readahead \
setfsuid setfsgid makedev epoll_pwait signalfd \
diff --git a/libc/sysdeps/unix/sysv/linux/accept4.c b/libc/sysdeps/unix/sysv/linux/accept4.c
index 97f7b8ce6..9ef9f479b 100644
--- a/libc/sysdeps/unix/sysv/linux/accept4.c
+++ b/libc/sysdeps/unix/sysv/linux/accept4.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2008 Free Software Foundation, Inc.
+/* Copyright (C) 2008, 2009 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2008.
@@ -23,8 +23,7 @@
#include <sysdep-cancel.h>
#include <sys/syscall.h>
-
-#define __NR_accept4 288
+#include <kernel-features.h>
#ifdef __NR_accept4
@@ -43,6 +42,50 @@ accept4 (int fd, __SOCKADDR_ARG addr, socklen_t *addr_len, int flags)
return result;
}
+#elif defined __NR_socketcall
+# ifndef __ASSUME_ACCEPT4
+extern int __internal_accept4 (int fd, __SOCKADDR_ARG addr,
+ socklen_t *addr_len, int flags)
+ attribute_hidden;
+
+static int have_accept4;
+
+int
+accept4 (int fd, __SOCKADDR_ARG addr, socklen_t *addr_len, int flags)
+{
+ if (__builtin_expect (have_accept4 >= 0, 1))
+ {
+ int ret = __internal_accept4 (fd, addr, addr_len, flags);
+ /* The kernel returns -EINVAL for unknown socket operations.
+ We need to convert that error to an ENOSYS error. */
+ if (__builtin_expect (ret < 0, 0)
+ && have_accept4 == 0
+ && errno == EINVAL)
+ {
+ /* Try another call, this time with the FLAGS parameter
+ cleared and an invalid file descriptor. This call will not
+ cause any harm and it will return immediately. */
+ ret = __internal_accept4 (-1, addr, addr_len, 0);
+ if (errno == EINVAL)
+ {
+ have_accept4 = -1;
+ __set_errno (ENOSYS);
+ }
+ else
+ {
+ have_accept4 = 1;
+ __set_errno (EINVAL);
+ }
+ return -1;
+ }
+ return ret;
+ }
+ __set_errno (ENOSYS);
+ return -1;
+}
+# else
+/* When __ASSUME_ACCEPT4 accept4 is defined in internal_accept4.S. */
+# endif
#else
int
accept4 (int fd, __SOCKADDR_ARG addr, socklen_t *addr_len, int flags)
diff --git a/libc/sysdeps/unix/sysv/linux/i386/accept4.S b/libc/sysdeps/unix/sysv/linux/i386/accept4.S
index 087ccc456..1d05eff7f 100644
--- a/libc/sysdeps/unix/sysv/linux/i386/accept4.S
+++ b/libc/sysdeps/unix/sysv/linux/i386/accept4.S
@@ -24,10 +24,6 @@
#define EINVAL 22
#define ENOSYS 38
-#ifndef SOCKOP_accept4
-# define SOCKOP_accept4 18
-#endif
-
#ifdef __ASSUME_ACCEPT4
# define errlabel SYSCALL_ERROR_LABEL
#else
diff --git a/libc/sysdeps/unix/sysv/linux/ia64/____longjmp_chk.S b/libc/sysdeps/unix/sysv/linux/ia64/____longjmp_chk.S
new file mode 100644
index 000000000..e097c2288
--- /dev/null
+++ b/libc/sysdeps/unix/sysv/linux/ia64/____longjmp_chk.S
@@ -0,0 +1,48 @@
+/* Copyright (C) 2009 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+ .section .rodata.str1.8,"aMS",@progbits,1
+ .align 8
+.LC0:
+ .string "longjmp causes uninitialized stack frame"
+
+ .section .sdata,"aws",@progbits
+ .align 8
+ .type longjmp_msg,@object
+longjmp_msg:
+ data8 .LC0
+ .size longjmp_msg, .-longjmp_msg
+
+#define __longjmp ____longjmp_chk
+
+#ifdef PIC
+# define CALL_FAIL __GI___fortify_fail
+#else
+# define CALL_FAIL __fortify_fail
+#endif
+
+#define CHECK_RSP(reg) \
+ cmp.ltu p0, p8 = reg, r12; \
+(p8) br.cond.dpnt .Lok;; \
+ addl r28 = @ltoffx(longjmp_msg#), r1;; \
+ ld8.mov r28 = [r28], longjmp_msg#;; \
+ ld8 out0 = [r28]; \
+ br.call.sptk.many b0 = CALL_FAIL#;; \
+.Lok:
+
+#include "__longjmp.S"
diff --git a/libc/sysdeps/unix/sysv/linux/ia64/__longjmp.S b/libc/sysdeps/unix/sysv/linux/ia64/__longjmp.S
index aa18fadf9..2e7490438 100644
--- a/libc/sysdeps/unix/sysv/linux/ia64/__longjmp.S
+++ b/libc/sysdeps/unix/sysv/linux/ia64/__longjmp.S
@@ -42,7 +42,11 @@
/* __longjmp(__jmp_buf buf, int val) */
LEAF(__longjmp)
+#ifdef CHECK_RSP
+ alloc r8=ar.pfs,2,1,1,0
+#else
alloc r8=ar.pfs,2,1,0,0
+#endif
mov r27=ar.rsc
add r2=0x98,in0 // r2 <- &jmpbuf.orig_jmp_buf_addr
;;
@@ -70,14 +74,18 @@ LEAF(__longjmp)
add r3=8,in0 // r3 <- &jmpbuf.r1
shl r9=r25,r17
;;
+ ld8.fill.nta r28=[r2],16 // r28 <- jmpbuf.sp
or r25=r8,r9
;;
mov r26=ar.rnat
mov ar.unat=r25 // setup ar.unat (NaT bits for r1, r4-r7, and r12)
;;
- ld8.fill.nta sp=[r2],16 // r12 (sp)
+#ifdef CHECK_RSP
+ CHECK_RSP (r28)
+#endif
ld8.fill.nta gp=[r3],16 // r1 (gp)
dep r11=-1,r23,3,6 // r11 <- ia64_rse_rnat_addr(jmpbuf.ar_bsp)
+ mov sp=r28 // r12 (sp)
;;
ld8.nta r16=[r2],16 // caller's unat
ld8.nta r17=[r3],16 // fpsr
diff --git a/libc/sysdeps/unix/sysv/linux/internal_accept4.S b/libc/sysdeps/unix/sysv/linux/internal_accept4.S
new file mode 100644
index 000000000..ffc553624
--- /dev/null
+++ b/libc/sysdeps/unix/sysv/linux/internal_accept4.S
@@ -0,0 +1,14 @@
+#include <kernel-features.h>
+#include <sys/syscall.h>
+#if !defined __NR_accept4 && defined __NR_socketcall
+# define socket accept4
+# ifdef __ASSUME_ACCEPT4
+# define __socket accept4
+# else
+# define __socket __internal_accept4
+# endif
+# define NARGS 4
+# define NEED_CANCELLATION
+# define NO_WEAK_ALIAS
+# include <socket.S>
+#endif
diff --git a/libc/sysdeps/unix/sysv/linux/kernel-features.h b/libc/sysdeps/unix/sysv/linux/kernel-features.h
index 473360a13..456251579 100644
--- a/libc/sysdeps/unix/sysv/linux/kernel-features.h
+++ b/libc/sysdeps/unix/sysv/linux/kernel-features.h
@@ -521,7 +521,7 @@
/* Support for the accept4 syscall was added in 2.6.28. */
#if __LINUX_KERNEL_VERSION >= 0x02061c \
&& (defined __i386__ || defined __x86_64__ || defined __powerpc__ \
- || defined __ia64__ || defined __sparc__ || defined __s390__)
+ || defined __sparc__ || defined __s390__)
# define __ASSUME_ACCEPT4 1
#endif
diff --git a/libc/sysdeps/unix/sysv/linux/socketcall.h b/libc/sysdeps/unix/sysv/linux/socketcall.h
index 24ec9ee2a..adf01b6e1 100644
--- a/libc/sysdeps/unix/sysv/linux/socketcall.h
+++ b/libc/sysdeps/unix/sysv/linux/socketcall.h
@@ -1,5 +1,5 @@
/* ID for functions called via socketcall system call.
- Copyright (C) 1995, 1996, 2008 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1996, 2008, 2009 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -43,6 +43,6 @@
#define SOCKOP_getsockopt 15
#define SOCKOP_sendmsg 16
#define SOCKOP_recvmsg 17
-#define SOCKOP_paccept 18
+#define SOCKOP_accept4 18
#endif /* sys/socketcall.h */