linux-user: add pselect6 syscall support
Some architectures (like Blackfin) only implement pselect6 (and skip select/newselect). So add support for it. Signed-off-by: Mike Frysinger <vapier@gentoo.org> Signed-off-by: Riku Voipio <riku.voipio@iki.fi>
This commit is contained in:
		
							parent
							
								
									4d1de87c75
								
							
						
					
					
						commit
						055e090687
					
				@ -550,6 +550,15 @@ _syscall5(int, sys_ppoll, struct pollfd *, fds, nfds_t, nfds,
 | 
				
			|||||||
          size_t, sigsetsize)
 | 
					          size_t, sigsetsize)
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(TARGET_NR_pselect6)
 | 
				
			||||||
 | 
					#ifndef __NR_pselect6
 | 
				
			||||||
 | 
					# define __NR_pselect6 -1
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#define __NR_sys_pselect6 __NR_pselect6
 | 
				
			||||||
 | 
					_syscall6(int, sys_pselect6, int, nfds, fd_set *, readfds, fd_set *, writefds,
 | 
				
			||||||
 | 
					          fd_set *, exceptfds, struct timespec *, timeout, void *, sig);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern int personality(int);
 | 
					extern int personality(int);
 | 
				
			||||||
extern int flock(int, int);
 | 
					extern int flock(int, int);
 | 
				
			||||||
extern int setfsuid(int);
 | 
					extern int setfsuid(int);
 | 
				
			||||||
@ -819,6 +828,20 @@ static inline abi_long copy_from_user_fdset(fd_set *fds,
 | 
				
			|||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline abi_ulong copy_from_user_fdset_ptr(fd_set *fds, fd_set **fds_ptr,
 | 
				
			||||||
 | 
					                                                 abi_ulong target_fds_addr,
 | 
				
			||||||
 | 
					                                                 int n)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (target_fds_addr) {
 | 
				
			||||||
 | 
					        if (copy_from_user_fdset(fds, target_fds_addr, n))
 | 
				
			||||||
 | 
					            return -TARGET_EFAULT;
 | 
				
			||||||
 | 
					        *fds_ptr = fds;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        *fds_ptr = NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline abi_long copy_to_user_fdset(abi_ulong target_fds_addr,
 | 
					static inline abi_long copy_to_user_fdset(abi_ulong target_fds_addr,
 | 
				
			||||||
                                          const fd_set *fds,
 | 
					                                          const fd_set *fds,
 | 
				
			||||||
                                          int n)
 | 
					                                          int n)
 | 
				
			||||||
@ -984,6 +1007,7 @@ static inline abi_long copy_to_user_mq_attr(abi_ulong target_mq_attr_addr,
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(TARGET_NR_select) || defined(TARGET_NR__newselect)
 | 
				
			||||||
/* do_select() must return target values and target errnos. */
 | 
					/* do_select() must return target values and target errnos. */
 | 
				
			||||||
static abi_long do_select(int n,
 | 
					static abi_long do_select(int n,
 | 
				
			||||||
                          abi_ulong rfd_addr, abi_ulong wfd_addr,
 | 
					                          abi_ulong rfd_addr, abi_ulong wfd_addr,
 | 
				
			||||||
@ -994,26 +1018,17 @@ static abi_long do_select(int n,
 | 
				
			|||||||
    struct timeval tv, *tv_ptr;
 | 
					    struct timeval tv, *tv_ptr;
 | 
				
			||||||
    abi_long ret;
 | 
					    abi_long ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (rfd_addr) {
 | 
					    ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n);
 | 
				
			||||||
        if (copy_from_user_fdset(&rfds, rfd_addr, n))
 | 
					    if (ret) {
 | 
				
			||||||
            return -TARGET_EFAULT;
 | 
					        return ret;
 | 
				
			||||||
        rfds_ptr = &rfds;
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
        rfds_ptr = NULL;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (wfd_addr) {
 | 
					    ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n);
 | 
				
			||||||
        if (copy_from_user_fdset(&wfds, wfd_addr, n))
 | 
					    if (ret) {
 | 
				
			||||||
            return -TARGET_EFAULT;
 | 
					        return ret;
 | 
				
			||||||
        wfds_ptr = &wfds;
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
        wfds_ptr = NULL;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (efd_addr) {
 | 
					    ret = copy_from_user_fdset_ptr(&efds, &efds_ptr, efd_addr, n);
 | 
				
			||||||
        if (copy_from_user_fdset(&efds, efd_addr, n))
 | 
					    if (ret) {
 | 
				
			||||||
            return -TARGET_EFAULT;
 | 
					        return ret;
 | 
				
			||||||
        efds_ptr = &efds;
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
        efds_ptr = NULL;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (target_tv_addr) {
 | 
					    if (target_tv_addr) {
 | 
				
			||||||
@ -1040,6 +1055,7 @@ static abi_long do_select(int n,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static abi_long do_pipe2(int host_pipe[], int flags)
 | 
					static abi_long do_pipe2(int host_pipe[], int flags)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -5601,7 +5617,102 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
#ifdef TARGET_NR_pselect6
 | 
					#ifdef TARGET_NR_pselect6
 | 
				
			||||||
    case TARGET_NR_pselect6:
 | 
					    case TARGET_NR_pselect6:
 | 
				
			||||||
	    goto unimplemented_nowarn;
 | 
					        {
 | 
				
			||||||
 | 
					            abi_long rfd_addr, wfd_addr, efd_addr, n, ts_addr;
 | 
				
			||||||
 | 
					            fd_set rfds, wfds, efds;
 | 
				
			||||||
 | 
					            fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
 | 
				
			||||||
 | 
					            struct timespec ts, *ts_ptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            /*
 | 
				
			||||||
 | 
					             * The 6th arg is actually two args smashed together,
 | 
				
			||||||
 | 
					             * so we cannot use the C library.
 | 
				
			||||||
 | 
					             */
 | 
				
			||||||
 | 
					            sigset_t set;
 | 
				
			||||||
 | 
					            struct {
 | 
				
			||||||
 | 
					                sigset_t *set;
 | 
				
			||||||
 | 
					                size_t size;
 | 
				
			||||||
 | 
					            } sig, *sig_ptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            abi_ulong arg_sigset, arg_sigsize, *arg7;
 | 
				
			||||||
 | 
					            target_sigset_t *target_sigset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            n = arg1;
 | 
				
			||||||
 | 
					            rfd_addr = arg2;
 | 
				
			||||||
 | 
					            wfd_addr = arg3;
 | 
				
			||||||
 | 
					            efd_addr = arg4;
 | 
				
			||||||
 | 
					            ts_addr = arg5;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n);
 | 
				
			||||||
 | 
					            if (ret) {
 | 
				
			||||||
 | 
					                goto fail;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n);
 | 
				
			||||||
 | 
					            if (ret) {
 | 
				
			||||||
 | 
					                goto fail;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            ret = copy_from_user_fdset_ptr(&efds, &efds_ptr, efd_addr, n);
 | 
				
			||||||
 | 
					            if (ret) {
 | 
				
			||||||
 | 
					                goto fail;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            /*
 | 
				
			||||||
 | 
					             * This takes a timespec, and not a timeval, so we cannot
 | 
				
			||||||
 | 
					             * use the do_select() helper ...
 | 
				
			||||||
 | 
					             */
 | 
				
			||||||
 | 
					            if (ts_addr) {
 | 
				
			||||||
 | 
					                if (target_to_host_timespec(&ts, ts_addr)) {
 | 
				
			||||||
 | 
					                    goto efault;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                ts_ptr = &ts;
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                ts_ptr = NULL;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            /* Extract the two packed args for the sigset */
 | 
				
			||||||
 | 
					            if (arg6) {
 | 
				
			||||||
 | 
					                sig_ptr = &sig;
 | 
				
			||||||
 | 
					                sig.size = _NSIG / 8;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                arg7 = lock_user(VERIFY_READ, arg6, sizeof(*arg7) * 2, 1);
 | 
				
			||||||
 | 
					                if (!arg7) {
 | 
				
			||||||
 | 
					                    goto efault;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                arg_sigset = tswapl(arg7[0]);
 | 
				
			||||||
 | 
					                arg_sigsize = tswapl(arg7[1]);
 | 
				
			||||||
 | 
					                unlock_user(arg7, arg6, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (arg_sigset) {
 | 
				
			||||||
 | 
					                    sig.set = &set;
 | 
				
			||||||
 | 
					                    target_sigset = lock_user(VERIFY_READ, arg_sigset,
 | 
				
			||||||
 | 
					                                              sizeof(*target_sigset), 1);
 | 
				
			||||||
 | 
					                    if (!target_sigset) {
 | 
				
			||||||
 | 
					                        goto efault;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    target_to_host_sigset(&set, target_sigset);
 | 
				
			||||||
 | 
					                    unlock_user(target_sigset, arg_sigset, 0);
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    sig.set = NULL;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                sig_ptr = NULL;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            ret = get_errno(sys_pselect6(n, rfds_ptr, wfds_ptr, efds_ptr,
 | 
				
			||||||
 | 
					                                         ts_ptr, sig_ptr));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (!is_error(ret)) {
 | 
				
			||||||
 | 
					                if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n))
 | 
				
			||||||
 | 
					                    goto efault;
 | 
				
			||||||
 | 
					                if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n))
 | 
				
			||||||
 | 
					                    goto efault;
 | 
				
			||||||
 | 
					                if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n))
 | 
				
			||||||
 | 
					                    goto efault;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (ts_addr && host_to_target_timespec(ts_addr, &ts))
 | 
				
			||||||
 | 
					                    goto efault;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
    case TARGET_NR_symlink:
 | 
					    case TARGET_NR_symlink:
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user