I am reviewing that for the MIPS part, and I am not really used to the
linux-user code, so a review from someone familiar with it would be
appreciated.

I added Richard Henderson and Blue Swirl in Cc: as alpha and sparc are 
also affected by this issue.

On Mon, Mar 18, 2013 at 11:47:05PM +0100, Petar Jovanovic wrote:
> From: Petar Jovanovic <petar.jovano...@imgtec.com>
> 
> Previous implementation has failed to take into account different value of
> SOCK_NONBLOCK on target (MIPS) and host, and existence of SOCK_CLOEXEC.
> The same conversion has to be applied both for do_socket and do_socketpair,
> so the code has been isolated in a static inline function.
> It is defined for MIPS target only.
> 
> enum sock_type in linux-user/socket.h has been extended to include
> TARGET_SOCK_CLOEXEC and TARGET_SOCK_NONBLOCK, similar to definition in libc.
> The patch also includes necessary code style changes (tab to spaces) in the
> header file in the MIPS #ifdef block touched by the change.
> 
> Signed-off-by: Petar Jovanovic <petar.jovano...@imgtec.com>
> ---
>  linux-user/socket.h  |  172 
> ++++++++++++++++++++++++++------------------------
>  linux-user/syscall.c |   45 ++++++++-----
>  2 files changed, 119 insertions(+), 98 deletions(-)
> 
> diff --git a/linux-user/socket.h b/linux-user/socket.h
> index 339cae5..e4dfe56 100644
> --- a/linux-user/socket.h
> +++ b/linux-user/socket.h
> @@ -1,91 +1,101 @@
>  
>  #if defined(TARGET_MIPS)
> -     // MIPS special values for constants
> -
> -     /*
> -      * For setsockopt(2)
> -      *
> -      * This defines are ABI conformant as far as Linux supports these ...
> -      */
> -     #define TARGET_SOL_SOCKET      0xffff
> -
> -     #define TARGET_SO_DEBUG        0x0001  /* Record debugging information. 
>  */
> -     #define TARGET_SO_REUSEADDR    0x0004  /* Allow reuse of local 
> addresses.  */
> -     #define TARGET_SO_KEEPALIVE    0x0008  /* Keep connections alive and 
> send
> -                                       SIGPIPE when they die.  */
> -     #define TARGET_SO_DONTROUTE    0x0010  /* Don't do local routing.  */
> -     #define TARGET_SO_BROADCAST    0x0020  /* Allow transmission of
> -                                       broadcast messages.  */
> -     #define TARGET_SO_LINGER       0x0080  /* Block on close of a reliable
> -                                       socket to transmit pending data.  */
> -     #define TARGET_SO_OOBINLINE 0x0100     /* Receive out-of-band data 
> in-band.  */
> -     #if 0
> -     To add: #define TARGET_SO_REUSEPORT 0x0200     /* Allow local address 
> and port reuse.  */
> -     #endif
> -
> -     #define TARGET_SO_TYPE         0x1008  /* Compatible name for SO_STYLE. 
>  */
> -     #define TARGET_SO_STYLE        SO_TYPE /* Synonym */
> -     #define TARGET_SO_ERROR        0x1007  /* get error status and clear */
> -     #define TARGET_SO_SNDBUF       0x1001  /* Send buffer size. */
> -     #define TARGET_SO_RCVBUF       0x1002  /* Receive buffer. */
> -     #define TARGET_SO_SNDLOWAT     0x1003  /* send low-water mark */
> -     #define TARGET_SO_RCVLOWAT     0x1004  /* receive low-water mark */
> -     #define TARGET_SO_SNDTIMEO     0x1005  /* send timeout */
> -     #define TARGET_SO_RCVTIMEO     0x1006  /* receive timeout */
> -     #define TARGET_SO_ACCEPTCONN   0x1009
> -
> -     /* linux-specific, might as well be the same as on i386 */
> -     #define TARGET_SO_NO_CHECK     11
> -     #define TARGET_SO_PRIORITY     12
> -     #define TARGET_SO_BSDCOMPAT    14
> +    /* MIPS special values for constants */
> +
> +    /*
> +     * For setsockopt(2)
> +     *
> +     * This defines are ABI conformant as far as Linux supports these ...
> +     */
> +    #define TARGET_SOL_SOCKET      0xffff
> +
> +    #define TARGET_SO_DEBUG        0x0001  /* Record debugging information. 
> */
> +    #define TARGET_SO_REUSEADDR    0x0004  /* Allow reuse of local 
> addresses. */
> +    #define TARGET_SO_KEEPALIVE    0x0008  /* Keep connections alive and send
> +                                              SIGPIPE when they die. */
> +    #define TARGET_SO_DONTROUTE    0x0010  /* Don't do local routing. */
> +    #define TARGET_SO_BROADCAST    0x0020  /* Allow transmission of
> +                                              broadcast messages. */
> +    #define TARGET_SO_LINGER       0x0080  /* Block on close of a reliable
> +                                            * socket to transmit pending 
> data.
> +                                            */
> +    #define TARGET_SO_OOBINLINE 0x0100     /* Receive out-of-band data 
> in-band.
> +                                            */
> +    #if 0
> +    /* To add: Allow local address and port reuse. */
> +    #define TARGET_SO_REUSEPORT 0x0200
> +    #endif
> +
> +    #define TARGET_SO_TYPE         0x1008  /* Compatible name for SO_STYLE. 
> */
> +    #define TARGET_SO_STYLE        SO_TYPE /* Synonym */
> +    #define TARGET_SO_ERROR        0x1007  /* get error status and clear */
> +    #define TARGET_SO_SNDBUF       0x1001  /* Send buffer size. */
> +    #define TARGET_SO_RCVBUF       0x1002  /* Receive buffer. */
> +    #define TARGET_SO_SNDLOWAT     0x1003  /* send low-water mark */
> +    #define TARGET_SO_RCVLOWAT     0x1004  /* receive low-water mark */
> +    #define TARGET_SO_SNDTIMEO     0x1005  /* send timeout */
> +    #define TARGET_SO_RCVTIMEO     0x1006  /* receive timeout */
> +    #define TARGET_SO_ACCEPTCONN   0x1009
>  
> -     #define TARGET_SO_PASSCRED     17
> -     #define TARGET_SO_PEERCRED     18
> +    /* linux-specific, might as well be the same as on i386 */
> +    #define TARGET_SO_NO_CHECK     11
> +    #define TARGET_SO_PRIORITY     12
> +    #define TARGET_SO_BSDCOMPAT    14
>  
> -     /* Security levels - as per NRL IPv6 - don't actually do anything */
> -     #define TARGET_SO_SECURITY_AUTHENTICATION              22
> -     #define TARGET_SO_SECURITY_ENCRYPTION_TRANSPORT        23
> -     #define TARGET_SO_SECURITY_ENCRYPTION_NETWORK          24
> +    #define TARGET_SO_PASSCRED     17
> +    #define TARGET_SO_PEERCRED     18
> +
> +    /* Security levels - as per NRL IPv6 - don't actually do anything */
> +    #define TARGET_SO_SECURITY_AUTHENTICATION              22
> +    #define TARGET_SO_SECURITY_ENCRYPTION_TRANSPORT        23
> +    #define TARGET_SO_SECURITY_ENCRYPTION_NETWORK          24
>  
> -     #define TARGET_SO_BINDTODEVICE         25
> +    #define TARGET_SO_BINDTODEVICE         25
>  
> -     /* Socket filtering */
> -     #define TARGET_SO_ATTACH_FILTER        26
> -     #define TARGET_SO_DETACH_FILTER        27
> +    /* Socket filtering */
> +    #define TARGET_SO_ATTACH_FILTER        26
> +    #define TARGET_SO_DETACH_FILTER        27
>  
> -     #define TARGET_SO_PEERNAME             28
> -     #define TARGET_SO_TIMESTAMP            29
> -     #define SCM_TIMESTAMP          SO_TIMESTAMP
> -
> -     #define TARGET_SO_PEERSEC              30
> -     #define TARGET_SO_SNDBUFFORCE          31
> -     #define TARGET_SO_RCVBUFFORCE          33
> -
> -     /** sock_type - Socket types
> -      *
> -      * Please notice that for binary compat reasons MIPS has to
> -      * override the enum sock_type in include/linux/net.h, so
> -      * we define ARCH_HAS_SOCKET_TYPES here.
> -      *
> -      * @SOCK_DGRAM - datagram (conn.less) socket
> -      * @SOCK_STREAM - stream (connection) socket
> -      * @SOCK_RAW - raw socket
> -      * @SOCK_RDM - reliably-delivered message
> -      * @SOCK_SEQPACKET - sequential packet socket
> -      * @SOCK_PACKET - linux specific way of getting packets at the dev 
> level.
> -      *               For writing rarp and other similar things on the user 
> level.
> -      */
> -     enum sock_type {
> -            TARGET_SOCK_DGRAM       = 1,
> -            TARGET_SOCK_STREAM      = 2,
> -            TARGET_SOCK_RAW = 3,
> -            TARGET_SOCK_RDM = 4,
> -            TARGET_SOCK_SEQPACKET   = 5,
> -            TARGET_SOCK_DCCP        = 6,
> -            TARGET_SOCK_PACKET      = 10,
> -     };
> -
> -     #define TARGET_SOCK_MAX (SOCK_PACKET + 1)
> +    #define TARGET_SO_PEERNAME             28
> +    #define TARGET_SO_TIMESTAMP            29
> +    #define SCM_TIMESTAMP          SO_TIMESTAMP
> +
> +    #define TARGET_SO_PEERSEC              30
> +    #define TARGET_SO_SNDBUFFORCE          31
> +    #define TARGET_SO_RCVBUFFORCE          33
> +
> +    /** sock_type - Socket types
> +     *
> +     * Please notice that for binary compat reasons MIPS has to
> +     * override the enum sock_type in include/linux/net.h, so
> +     * we define ARCH_HAS_SOCKET_TYPES here.
> +     *

Not related to your changes, but note that ARCH_HAS_SOCKET_TYPES is not
defined anywhere contrary to what is said in the comment. It might be a
good idea to revive it, as at least alpha and sparc also have the issue.

> +     * @SOCK_DGRAM - datagram (conn.less) socket
> +     * @SOCK_STREAM - stream (connection) socket
> +     * @SOCK_RAW - raw socket
> +     * @SOCK_RDM - reliably-delivered message
> +     * @SOCK_SEQPACKET - sequential packet socket
> +     * @SOCK_DCCP - Datagram Congestion Control Protocol socket
> +     * @SOCK_PACKET - linux specific way of getting packets at the dev level.
> +     *                For writing rarp and other similar things on the user
> +     *                level.
> +     * @SOCK_CLOEXEC - sets the close-on-exec (FD_CLOEXEC) flag.
> +     * @SOCK_NONBLOCK - sets the O_NONBLOCK file status flag.
> +     */
> +    enum sock_type {
> +           TARGET_SOCK_DGRAM       = 1,
> +           TARGET_SOCK_STREAM      = 2,
> +           TARGET_SOCK_RAW         = 3,
> +           TARGET_SOCK_RDM         = 4,
> +           TARGET_SOCK_SEQPACKET   = 5,
> +           TARGET_SOCK_DCCP        = 6,
> +           TARGET_SOCK_PACKET      = 10,
> +           TARGET_SOCK_CLOEXEC     = 02000000,
> +           TARGET_SOCK_NONBLOCK    = 0200,
> +    };
> +
> +    #define TARGET_SOCK_MAX (TARGET_SOCK_PACKET + 1)
> +    #define TARGET_SOCK_TYPE_MASK    0xf  /* Covers up to TARGET_SOCK_MAX-1. 
> */
>  
>  #elif defined(TARGET_ALPHA)
>  
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index ee82a2d..0a9e6db 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -1859,30 +1859,38 @@ static void unlock_iovec(struct iovec *vec, abi_ulong 
> target_addr,
>      free(vec);
>  }
>  
> -/* do_socket() Must return target values and target errnos. */
> -static abi_long do_socket(int domain, int type, int protocol)
> -{
>  #if defined(TARGET_MIPS)
> -    switch(type) {
> +static inline void target_to_host_sock_type(int *type)
> +{
> +    int host_type = 0;
> +    int target_type = *type;
> +
> +    switch (target_type & TARGET_SOCK_TYPE_MASK) {
>      case TARGET_SOCK_DGRAM:
> -        type = SOCK_DGRAM;
> +        host_type = SOCK_DGRAM;
>          break;
>      case TARGET_SOCK_STREAM:
> -        type = SOCK_STREAM;
> +        host_type = SOCK_STREAM;
>          break;
> -    case TARGET_SOCK_RAW:
> -        type = SOCK_RAW;
> -        break;
> -    case TARGET_SOCK_RDM:
> -        type = SOCK_RDM;
> -        break;
> -    case TARGET_SOCK_SEQPACKET:
> -        type = SOCK_SEQPACKET;
> -        break;
> -    case TARGET_SOCK_PACKET:
> -        type = SOCK_PACKET;
> +    default:
> +        host_type = target_type & TARGET_SOCK_TYPE_MASK;
>          break;
>      }

I am not sure we want to really copy the type without more checking than
the mask: a new value still within the mask limit could be added
differently depending on the architecture.

> +    if (target_type & TARGET_SOCK_CLOEXEC) {
> +        host_type |= SOCK_CLOEXEC;
> +    }
> +    if (target_type & TARGET_SOCK_NONBLOCK) {
> +        host_type |= SOCK_NONBLOCK;
> +    }
> +    *type = host_type;

Also I think the values should be checked in all cases returning -EINVAL
if not supported. On other architecture where no translation is done,
this is done by the host kernel. With the code above, unsupported
arguments are simply ignored.

> +}
> +#endif
> +
> +/* do_socket() Must return target values and target errnos. */
> +static abi_long do_socket(int domain, int type, int protocol)
> +{
> +#if defined(TARGET_MIPS)
> +    target_to_host_sock_type(&type);
>  #endif

As said above this could probably be conditional on
ARCH_HAS_SOCKET_TYPES to make it more generic.

>      if (domain == PF_NETLINK)
>          return -EAFNOSUPPORT; /* do not NETLINK socket connections possible 
> */
> @@ -2116,6 +2124,9 @@ static abi_long do_socketpair(int domain, int type, int 
> protocol,
>      int tab[2];
>      abi_long ret;
>  
> +#if defined(TARGET_MIPS)
> +    target_to_host_sock_type(&type);
> +#endif
>      ret = get_errno(socketpair(domain, type, protocol, tab));
>      if (!is_error(ret)) {
>          if (put_user_s32(tab[0], target_tab_addr)
> -- 
> 1.7.9.5
> 
> 

-- 
Aurelien Jarno                          GPG: 1024D/F1BCDB73
aurel...@aurel32.net                 http://www.aurel32.net

Reply via email to