Ejemplo n.º 1
0
        public static int Access(Thread current, ref Arch.ExceptionRegisters regs, UserPtr filenamePtr, int mode)
        {
            // XXX: This is vfs related, now let's assume that we're dealing with pass through fs.

            var buf = Globals.AllocateAlignedCompletionBuffer(PATH_MAX);

            if (!buf.isValid)
                return -ErrorCode.ENOMEM;

            var ret = filenamePtr.ReadString(current, buf);

            var accessCompletion = new BridgeCompletion(current, buf);

            ret = Arch.IPCStubs.AccessAsync(current.Parent.helperPid, current.impl._value.thread._value, new Pointer(buf.Location), mode);

            if (ret < 0)
            {
                accessCompletion.Dispose();
                return ret;
            }

            Globals.CompletionQueue.Enqueue(accessCompletion);
            current.SaveState(ref regs);
            current.AsyncReturn = true;
            return 0;
        }
Ejemplo n.º 2
0
        private static void HandleBridgeCompletion(BridgeCompletion c, int ret)
        {
            var current = c.thr;

            c.Dispose();
            current.ReturnFromCompletion(ret);
        }
Ejemplo n.º 3
0
        public static int Access(Thread current, ref Arch.ExceptionRegisters regs, UserPtr filenamePtr, int mode)
        {
            // XXX: This is vfs related, now let's assume that we're dealing with pass through fs.

            var buf = Globals.AllocateAlignedCompletionBuffer(PATH_MAX);

            if (!buf.isValid)
            {
                return(-ErrorCode.ENOMEM);
            }

            var ret = filenamePtr.ReadString(current, buf);

            var accessCompletion = new BridgeCompletion(current, buf);

            ret = Arch.IPCStubs.AccessAsync(current.Parent.helperPid, current.impl._value.thread._value, new Pointer(buf.Location), mode);

            if (ret < 0)
            {
                accessCompletion.Dispose();
                return(ret);
            }

            Globals.CompletionQueue.Enqueue(accessCompletion);
            current.SaveState(ref regs);
            current.AsyncReturn = true;
            return(0);
        }
Ejemplo n.º 4
0
        private static int BindOrConnect(int type, Thread current, ref Arch.ExceptionRegisters regs, int sockfd, UserPtr sockaddr, int addrlen)
        {
            Contract.Requires(type == SYS_BIND || type == SYS_CONNECT);

            var proc = current.Parent;
            var file = proc.LookupFile(sockfd);

            if (file == null)
            {
                return(-ErrorCode.EBADF);
            }

            if (file.inode.kind != GenericINode.INodeKind.SocketINodeKind)
            {
                return(-ErrorCode.ENOTSOCK);
            }

            if (addrlen > Globals.LinuxIPCBuffer.Length)
            {
                return(-ErrorCode.EINVAL);
            }

            var buf = Globals.AllocateAlignedCompletionBuffer(addrlen);

            if (!buf.isValid)
            {
                return(-ErrorCode.ENOMEM);
            }

            var completion = new BridgeCompletion(current, buf);

            if (sockaddr.Read(current, buf, addrlen) != 0)
            {
                completion.Dispose();
                return(-ErrorCode.EFAULT);
            }

            if (type == SYS_BIND)
            {
                Arch.IPCStubs.BindAsync(proc.helperPid, current.impl._value.thread._value, new Pointer(buf.Location), file.inode.LinuxFd, addrlen);
            }
            else if (type == SYS_CONNECT)
            {
                Arch.IPCStubs.ConnectAsync(proc.helperPid, current.impl._value.thread._value, new Pointer(buf.Location), file.inode.LinuxFd, addrlen);
            }

            Globals.CompletionQueue.Enqueue(completion);
            current.SaveState(ref regs);
            current.AsyncReturn = true;
            return(0);
        }
Ejemplo n.º 5
0
        private static int Setsockopt(Thread current, ref Arch.ExceptionRegisters regs, int sockfd, int level, int optname, UserPtr optval, int optlen)
        {
            var proc = current.Parent;
            var file = proc.LookupFile(sockfd);

            if (file == null)
            {
                return(-ErrorCode.EBADF);
            }

            if (file.inode.kind != GenericINode.INodeKind.SocketINodeKind)
            {
                return(-ErrorCode.ENOTSOCK);
            }

            if (optlen > Globals.LinuxIPCBuffer.Length)
            {
                return(-ErrorCode.EINVAL);
            }

            var buf = Globals.AllocateAlignedCompletionBuffer(optlen);

            if (!buf.isValid)
            {
                return(-ErrorCode.ENOMEM);
            }

            var completion = new BridgeCompletion(current, buf);

            if (optval.Read(current, buf, optlen) != 0)
            {
                completion.Dispose();
                return(-ErrorCode.EFAULT);
            }

            Arch.IPCStubs.SetSockoptAsync(proc.helperPid, current.impl._value.thread._value, new Pointer(buf.Location), file.inode.LinuxFd, level, optname, optlen);

            Globals.CompletionQueue.Enqueue(completion);
            current.SaveState(ref regs);
            current.AsyncReturn = true;
            return(0);
        }
Ejemplo n.º 6
0
        // Forward the futex request to Linux helper
        private static int DoFutexShared(Thread current, ref Arch.ExceptionRegisters regs, UserPtr uaddr, int op, int val, UserPtr timeoutPtr, UserPtr uaddr2, uint val3)
        {
            // Some local test
            var      cmd = op & FUTEX_CMD_MASK;
            timespec ts  = new timespec();

            bool hasTimeout = timeoutPtr != UserPtr.Zero;

            if (hasTimeout && timeoutPtr.Read(current, out ts) != 0)
            {
                return(-ErrorCode.EFAULT);
            }

            if (cmd == FUTEX_WAIT || cmd == FUTEX_WAIT_BITSET)
            {
                int old_val;
                if (uaddr.Read(current, out old_val) != 0)
                {
                    return(-ErrorCode.EFAULT);
                }

                if (old_val != val)
                {
                    return(-ErrorCode.EWOULDBLOCK);
                }

                var bitset     = cmd == FUTEX_WAIT ? FUTEX_BITSET_MATCH_ANY : val3;
                var shadowAddr = FindShadowAddr(current, uaddr);

                if (shadowAddr == Pointer.Zero)
                {
                    Arch.Console.WriteLine("FutexShared: Don't know how to deal with shared_wait");
                    return(0);
                }

                var futex_entry = new FutexCompletionEntry(current, uaddr, bitset);

                Arch.IPCStubs.linux_sys_futex_wait(current.Parent.helperPid, current.impl._value.thread._value, op, shadowAddr, val, ts, bitset);

                Globals.CompletionQueue.Enqueue(futex_entry);
                current.SaveState(ref regs);
                current.AsyncReturn = true;
                return(0);
            }
            else if (cmd == FUTEX_WAKE || cmd == FUTEX_WAKE_BITSET)
            {
                var bitset = cmd == FUTEX_WAKE ? FUTEX_BITSET_MATCH_ANY : val3;
                if (bitset == 0)
                {
                    return(-ErrorCode.EINVAL);
                }

                var shadowAddr = FindShadowAddr(current, uaddr);
                if (shadowAddr == Pointer.Zero)
                {
                    Arch.Console.WriteLine("FutexShared: Don't know how to deal with shared_wake");
                    return(0);
                }

                var c = new BridgeCompletion(current, new ByteBufferRef());

                Arch.IPCStubs.linux_sys_futex_wake(current.Parent.helperPid, current.impl._value.thread._value, op, shadowAddr, bitset);

                Globals.CompletionQueue.Enqueue(c);
                current.SaveState(ref regs);
                current.AsyncReturn = true;

                return(0);
            }

            return(0);
        }
Ejemplo n.º 7
0
        // Forward the futex request to Linux helper
        private static int DoFutexShared(Thread current, ref Arch.ExceptionRegisters regs, UserPtr uaddr, int op, int val, UserPtr timeoutPtr, UserPtr uaddr2, uint val3)
        {
            // Some local test
            var cmd = op & FUTEX_CMD_MASK;
            timespec ts = new timespec();

            bool hasTimeout = timeoutPtr != UserPtr.Zero;
            if (hasTimeout && timeoutPtr.Read(current, out ts) != 0)
                return -ErrorCode.EFAULT;

            if (cmd == FUTEX_WAIT || cmd == FUTEX_WAIT_BITSET)
            {
                int old_val;
                if (uaddr.Read(current, out old_val) != 0)
                    return -ErrorCode.EFAULT;

                if (old_val != val)
                    return -ErrorCode.EWOULDBLOCK;

                var bitset = cmd == FUTEX_WAIT ? FUTEX_BITSET_MATCH_ANY : val3;
                var shadowAddr = FindShadowAddr(current, uaddr);

                if (shadowAddr == Pointer.Zero)
                {
                    Arch.Console.WriteLine("FutexShared: Don't know how to deal with shared_wait");
                    return 0;
                }

                var futex_entry = new FutexCompletionEntry(current, uaddr, bitset);

                Arch.IPCStubs.linux_sys_futex_wait(current.Parent.helperPid, current.impl._value.thread._value, op, shadowAddr, val, ts, bitset);

                Globals.CompletionQueue.Enqueue(futex_entry);
                current.SaveState(ref regs);
                current.AsyncReturn = true;
                return 0;
            }
            else if (cmd == FUTEX_WAKE || cmd == FUTEX_WAKE_BITSET)
            {
                var bitset = cmd == FUTEX_WAKE ? FUTEX_BITSET_MATCH_ANY : val3;
                if (bitset == 0)
                    return -ErrorCode.EINVAL;

                var shadowAddr = FindShadowAddr(current, uaddr);
                if (shadowAddr == Pointer.Zero)
                {
                    Arch.Console.WriteLine("FutexShared: Don't know how to deal with shared_wake");
                    return 0;
                }

                var c = new BridgeCompletion(current, new ByteBufferRef());

                Arch.IPCStubs.linux_sys_futex_wake(current.Parent.helperPid, current.impl._value.thread._value, op, shadowAddr, bitset);

                Globals.CompletionQueue.Enqueue(c);
                current.SaveState(ref regs);
                current.AsyncReturn = true;

                return 0;
            }

            return 0;
        }
Ejemplo n.º 8
0
        private static int Setsockopt(Thread current, ref Arch.ExceptionRegisters regs, int sockfd, int level, int optname, UserPtr optval, int optlen)
        {
            var proc = current.Parent;
            var file = proc.LookupFile(sockfd);
            if (file == null)
                return -ErrorCode.EBADF;

            if (file.inode.kind != GenericINode.INodeKind.SocketINodeKind)
                return -ErrorCode.ENOTSOCK;

            if (optlen > Globals.LinuxIPCBuffer.Length)
                return -ErrorCode.EINVAL;

            var buf = Globals.AllocateAlignedCompletionBuffer(optlen);

            if (!buf.isValid)
                return -ErrorCode.ENOMEM;

            var completion = new BridgeCompletion(current, buf);

            if (optval.Read(current, buf, optlen) != 0)
            {
                completion.Dispose();
                return -ErrorCode.EFAULT;
            }

            Arch.IPCStubs.SetSockoptAsync(proc.helperPid, current.impl._value.thread._value, new Pointer(buf.Location), file.inode.LinuxFd, level, optname, optlen);

            Globals.CompletionQueue.Enqueue(completion);
            current.SaveState(ref regs);
            current.AsyncReturn = true;
            return 0;
        }
Ejemplo n.º 9
0
        private static int BindOrConnect(int type, Thread current, ref Arch.ExceptionRegisters regs, int sockfd, UserPtr sockaddr, int addrlen)
        {
            Contract.Requires(type == SYS_BIND || type == SYS_CONNECT);

            var proc = current.Parent;
            var file = proc.LookupFile(sockfd);
            if (file == null)
                return -ErrorCode.EBADF;

            if (file.inode.kind != GenericINode.INodeKind.SocketINodeKind)
                return -ErrorCode.ENOTSOCK;

            if (addrlen > Globals.LinuxIPCBuffer.Length)
                return -ErrorCode.EINVAL;

            var buf = Globals.AllocateAlignedCompletionBuffer(addrlen);

            if (!buf.isValid)
                return -ErrorCode.ENOMEM;

            var completion = new BridgeCompletion(current, buf);

            if (sockaddr.Read(current, buf, addrlen) != 0)
            {
                completion.Dispose();
                return -ErrorCode.EFAULT;
            }

            if (type == SYS_BIND)
            {
                Arch.IPCStubs.BindAsync(proc.helperPid, current.impl._value.thread._value, new Pointer(buf.Location), file.inode.LinuxFd, addrlen);
            }
            else if (type == SYS_CONNECT)
            {
                Arch.IPCStubs.ConnectAsync(proc.helperPid, current.impl._value.thread._value, new Pointer(buf.Location), file.inode.LinuxFd, addrlen);
            }

            Globals.CompletionQueue.Enqueue(completion);
            current.SaveState(ref regs);
            current.AsyncReturn = true;
            return 0;
        }
Ejemplo n.º 10
0
 private static void HandleBridgeCompletion(BridgeCompletion c, int ret)
 {
     var current = c.thr;
     c.Dispose();
     current.ReturnFromCompletion(ret);
 }