diff options
| author | chs <chs@NetBSD.org> | 2010-11-02 18:02:59 +0000 |
|---|---|---|
| committer | chs <chs@NetBSD.org> | 2010-11-02 18:02:59 +0000 |
| commit | 3c3115da20f482fe845ae6f40a003e1e386bdb6c (patch) | |
| tree | 3c44ab368ede64def322a23830998e9cfbba3532 /sys/compat/linux/common/linux_socket.c | |
| parent | 069ef5a4d01ff6a0f390ee6837cb4b20f5f2c32a (diff) | |
update linux_sys_socket() to understand the flags that are now
included in the "type" parameter. in linux_sys_sendmsg(),
if we see an SCM_CREDENTIALS control message, just drop it
instead of giving an error. the linux and native versions of
the cred-passing operation are very different and some apps
(eg. linux pulseaudio library talking to a native server)
will work without the control data.
Diffstat (limited to 'sys/compat/linux/common/linux_socket.c')
| -rw-r--r-- | sys/compat/linux/common/linux_socket.c | 54 |
1 files changed, 48 insertions, 6 deletions
diff --git a/sys/compat/linux/common/linux_socket.c b/sys/compat/linux/common/linux_socket.c index 721a0682e65..0defc0c94e1 100644 --- a/sys/compat/linux/common/linux_socket.c +++ b/sys/compat/linux/common/linux_socket.c @@ -1,4 +1,4 @@ -/* $NetBSD: linux_socket.c,v 1.107 2009/11/28 22:11:42 dsl Exp $ */ +/* $NetBSD: linux_socket.c,v 1.108 2010/11/02 18:02:59 chs Exp $ */ /*- * Copyright (c) 1995, 1998, 2008 The NetBSD Foundation, Inc. @@ -35,7 +35,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: linux_socket.c,v 1.107 2009/11/28 22:11:42 dsl Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux_socket.c,v 1.108 2010/11/02 18:02:59 chs Exp $"); #if defined(_KERNEL_OPT) #include "opt_inet.h" @@ -70,6 +70,7 @@ __KERNEL_RCSID(0, "$NetBSD: linux_socket.c,v 1.107 2009/11/28 22:11:42 dsl Exp $ #include <sys/kauth.h> #include <sys/syscallargs.h> #include <sys/ktrace.h> +#include <sys/fcntl.h> #include <lib/libkern/libkern.h> @@ -84,6 +85,7 @@ __KERNEL_RCSID(0, "$NetBSD: linux_socket.c,v 1.107 2009/11/28 22:11:42 dsl Exp $ #include <compat/linux/common/linux_signal.h> #include <compat/linux/common/linux_ioctl.h> #include <compat/linux/common/linux_socket.h> +#include <compat/linux/common/linux_fcntl.h> #if !defined(__alpha__) && !defined(__amd64__) #include <compat/linux/common/linux_socketcall.h> #endif @@ -200,13 +202,13 @@ static const struct { {MSG_DONTWAIT, LINUX_MSG_DONTWAIT}, {MSG_BCAST, 0}, /* not supported, clear */ {MSG_MCAST, 0}, /* not supported, clear */ + {MSG_NOSIGNAL, LINUX_MSG_NOSIGNAL}, {-1, /* not supp */ LINUX_MSG_PROBE}, {-1, /* not supp */ LINUX_MSG_FIN}, {-1, /* not supp */ LINUX_MSG_SYN}, {-1, /* not supp */ LINUX_MSG_CONFIRM}, {-1, /* not supp */ LINUX_MSG_RST}, {-1, /* not supp */ LINUX_MSG_ERRQUEUE}, - {-1, /* not supp */ LINUX_MSG_NOSIGNAL}, {-1, /* not supp */ LINUX_MSG_MORE}, }; @@ -297,15 +299,46 @@ linux_sys_socket(struct lwp *l, const struct linux_sys_socket_args *uap, registe syscallarg(int) protocol; } */ struct sys___socket30_args bsa; - int error; + struct sys_fcntl_args fsa; + register_t fretval[2]; + int error, flags; + SCARG(&bsa, protocol) = SCARG(uap, protocol); - SCARG(&bsa, type) = SCARG(uap, type); + SCARG(&bsa, type) = SCARG(uap, type) & LINUX_SOCK_TYPE_MASK; SCARG(&bsa, domain) = linux_to_bsd_domain(SCARG(uap, domain)); if (SCARG(&bsa, domain) == -1) return EINVAL; + flags = SCARG(uap, type) & ~LINUX_SOCK_TYPE_MASK; + if (flags & ~(LINUX_SOCK_CLOEXEC | LINUX_SOCK_NONBLOCK)) + return EINVAL; error = sys___socket30(l, &bsa, retval); + /* + * Linux overloads the "type" parameter to include some + * fcntl flags to be set on the file descriptor. + * Process those if creating the socket succeeded. + */ + + if (!error && flags & LINUX_SOCK_CLOEXEC) { + SCARG(&fsa, fd) = *retval; + SCARG(&fsa, cmd) = F_SETFD; + SCARG(&fsa, arg) = (void *)(uintptr_t)FD_CLOEXEC; + (void) sys_fcntl(l, &fsa, fretval); + } + if (!error && flags & LINUX_SOCK_NONBLOCK) { + SCARG(&fsa, fd) = *retval; + SCARG(&fsa, cmd) = F_SETFL; + SCARG(&fsa, arg) = (void *)(uintptr_t)O_NONBLOCK; + error = sys_fcntl(l, &fsa, fretval); + if (error) { + struct sys_close_args csa; + + SCARG(&csa, fd) = *retval; + (void) sys_close(l, &csa, fretval); + } + } + #ifdef INET6 /* * Linux AF_INET6 socket has IPV6_V6ONLY setsockopt set to 0 by @@ -505,6 +538,14 @@ linux_sys_sendmsg(struct lwp *l, const struct linux_sys_sendmsg_args *uap, regis /* Linux SCM_RIGHTS is same as NetBSD */ break; + case LINUX_SCM_CREDENTIALS: + /* no native equivalent, just drop it */ + m_free(ctl_mbuf); + ctl_mbuf = NULL; + msg.msg_control = NULL; + msg.msg_controllen = 0; + goto skipcmsg; + default: /* other types not supported */ error = EINVAL; @@ -545,7 +586,7 @@ linux_sys_sendmsg(struct lwp *l, const struct linux_sys_sendmsg_args *uap, regis cmsg->cmsg_level = l_cmsg.cmsg_level; cmsg->cmsg_type = l_cmsg.cmsg_type; - /* Zero are between header and data */ + /* Zero area between header and data */ memset(cmsg + 1, 0, CMSG_ALIGN(sizeof(cmsg)) - sizeof(cmsg)); @@ -575,6 +616,7 @@ linux_sys_sendmsg(struct lwp *l, const struct linux_sys_sendmsg_args *uap, regis msg.msg_controllen); } +skipcmsg: error = do_sys_sendmsg(l, SCARG(uap, s), &msg, bflags, retval); /* Freed internally */ ctl_mbuf = NULL; |
