Example #1
0
 public static void DumpUserBuf(Thread current, UserPtr writeBuf, int size)
 {
     var buf = new byte[(size + 3) / 4];
     var buf_ref = new ByteBufferRef(buf);
     writeBuf.Read(current, buf, size);
     DumpBuf(new Pointer(buf_ref.Location), size);
 }
Example #2
0
        public static int DoFutex(Thread current, ref Arch.ExceptionRegisters regs, UserPtr uaddr, int op, int val, UserPtr timeoutPtr, UserPtr uaddr2, uint val3)
        {
            var cmd = op & FUTEX_CMD_MASK;
            var flags = ToFlags(op, cmd);
            timespec ts;
            ts.tv_sec = ts.tv_nsec = 0;

            // Don't care about shared mutex
            if ((flags & FLAGS_SHARED) != 0)
            {
                return DoFutexShared(current, ref regs, uaddr, op, val, timeoutPtr, uaddr2, val3);
            }

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

            switch (cmd)
            {
                case FUTEX_WAIT:
                    return Wait(current, ref regs, uaddr, flags, val, hasTimeout, ts, FUTEX_BITSET_MATCH_ANY);
                case FUTEX_WAIT_BITSET:
                    return Wait(current, ref regs, uaddr, flags, val, hasTimeout, ts, val3);
                case FUTEX_WAKE:
                    return Wake(current, uaddr, flags, val, FUTEX_BITSET_MATCH_ANY);
                case FUTEX_WAKE_BITSET:
                    return Wake(current, uaddr, flags, val, val3);
                default:
                    Arch.Console.Write("futex: unknown primitives ");
                    Arch.Console.Write(cmd);
                    Arch.Console.WriteLine();
                    return -ErrorCode.ENOSYS;
            }
        }
Example #3
0
        internal static int AshmemIoctl(GenericINode generic_inode, Thread current, uint cmd, UserPtr arg1)
        {
            Contract.Requires(Globals.LinuxIPCBuffer.Length >= AshmemINode.ASHMEM_PIN_SIZE);

            int ret = 0;

            switch (cmd)
            {
                case AshmemINode.ASHMEM_SET_NAME:
                    arg1.ReadString(current, Globals.LinuxIPCBuffer);
                    break;

                case AshmemINode.ASHMEM_PIN:
                case AshmemINode.ASHMEM_UNPIN:
                    if (arg1.Read(current, Globals.LinuxIPCBuffer, AshmemINode.ASHMEM_PIN_SIZE) != 0)
                        ret = -ErrorCode.EFAULT;
                    break;

                case AshmemINode.ASHMEM_GET_NAME:
                case AshmemINode.ASHMEM_SET_SIZE:
                case AshmemINode.ASHMEM_GET_SIZE:
                case AshmemINode.ASHMEM_SET_PROT_MASK:
                case AshmemINode.ASHMEM_GET_PROT_MASK:
                case AshmemINode.ASHMEM_GET_PIN_STATUS:
                case AshmemINode.ASHMEM_PURGE_ALL_CACHES:
                    break;

                default:
                    ret = -ErrorCode.ENOSYS;
                    break;
            }

            if (ret < 0)
                return ret;

            var linux_fd = generic_inode.LinuxFd;

            ret = Arch.IPCStubs.linux_sys_vfs_ashmem_ioctl(current.Parent.helperPid, linux_fd, cmd, arg1.Value.ToInt32());

            if (ret < 0)
                  return ret;

            // unmarshal if necessary
            if (cmd == AshmemINode.ASHMEM_GET_NAME)
            {
                var length = Util.Strnlen(Globals.LinuxIPCBuffer, AshmemINode.ASHMEM_NAME_LEN);
                // include terminator
                if (length < AshmemINode.ASHMEM_NAME_LEN)
                    length++;

                var buf = Globals.LinuxIPCBuffer.Slice(0, length);
                if (arg1.Write(current, Globals.LinuxIPCBuffer) != 0)
                    return -ErrorCode.EFAULT;
            }

            return ret;
        }
Example #4
0
        private static void DumpUserBuf(Thread current, UserPtr writeBuf, int size)
        {
            var buf = new byte[(size + 3) / 4];

            writeBuf.Read(current, buf, size);

            var buf_ref = new ByteBufferRef(buf);

            DumpBuf(new Pointer(buf_ref.Location), size);
        }
Example #5
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);
        }
Example #6
0
        private static int Sendto(Thread current, int sockfd, UserPtr userBuf, int len, int flags, UserPtr sockaddr, int addrlen)
        {
            var proc = current.Parent;
            var file = proc.LookupFile(sockfd);

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

            var buf = Globals.LinuxIPCBuffer;

            if (len < 0 || addrlen < 0)
            {
                return(-ErrorCode.EINVAL);
            }

            if (len + addrlen > buf.Length)
            {
                return(-ErrorCode.ENOMEM);
            }

            if (sockaddr == UserPtr.Zero && addrlen != 0)
            {
                return(-ErrorCode.EINVAL);
            }

            Contract.Assert(buf.Length >= len + addrlen);

            if (userBuf.Read(current, buf, len) != 0)
            {
                return(-ErrorCode.EFAULT);
            }

            var old_buf_len  = buf.Length;
            var sockaddr_buf = buf.Slice(len, buf.Length - len);

            // Post-condition of ByteBufferRef#ctor and slice
            Contract.Assume(buf.Length == old_buf_len);
            Contract.Assume(sockaddr_buf.Length == buf.Length - len);

            Contract.Assert(buf.Length - len >= addrlen);

            if (sockaddr != UserPtr.Zero && sockaddr.Read(current, sockaddr_buf, addrlen) != 0)
            {
                return(-ErrorCode.EFAULT);
            }

            return(Arch.IPCStubs.Sendto(proc.helperPid, file.inode.LinuxFd, len, flags, addrlen));
        }
Example #7
0
        internal int AddUserFdList(Thread current, UserPtr fdlist, int maxfds, short event_type)
        {
            if (fdlist == UserPtr.Zero)
                return 0;

            var buf = new byte[(maxfds + 7) / 8];
            if (fdlist.Read(current, buf) != 0)
                return -ErrorCode.EFAULT;

            var vec = new FixedSizeBitVector(maxfds, buf);

            var ret = AddFdList(current, vec, event_type);
            return ret;
        }
Example #8
0
 // XXX: Move to some places
 public static void DumpStackTrace(Thread current, UserPtr ebp)
 {
     int eip;
     int new_ebp;
     while (ebp != UserPtr.Zero)
     {
         Arch.Console.Write("EIP:");
         if ((ebp + sizeof(int)).Read(current, out eip) != 0)
             return;
         Arch.Console.Write(eip);
         Arch.Console.WriteLine();
         if (ebp.Read(current, out new_ebp) != 0)
             return;
         ebp = new UserPtr(new_ebp);
     }
 }
Example #9
0
        public static int SetThreadArea(Thread current, UserPtr userDescriptor)
        {
            var info = new userdesc();

            if (userDescriptor.Read(current, out info) != 0)
            {
                return(-ErrorCode.EFAULT);
            }

            var ret = NativeMethods.l4api_set_thread_area(current.impl._value.thread, current.TLSArray, -1, ref info, 1);

            if (userDescriptor.Write(current, info) != 0)
            {
                return(-ErrorCode.EFAULT);
            }

            return(ret);
        }
Example #10
0
        private static int Send(Thread current, int cap_idx, UserPtr userBuf, uint size)
        {
            if (!current.Parent.Space.VerifyRead(userBuf, size))
            {
                return(-ErrorCode.EFAULT);
            }

            var cap_ref = current.VBinderState.Find(current, cap_idx);

            if (cap_ref == null)
            {
                return(-ErrorCode.EINVAL);
            }

            var blob = Globals.AllocateAlignedCompletionBuffer((int)size);

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

            if (userBuf.Read(current, blob, (int)size) != 0)
            {
                return(-ErrorCode.EFAULT);
            }

            var targetThread = cap_ref.def.parent;

            // Object invariant of thread
            Contract.Assume(targetThread.VBinderState.Owner == targetThread);

            var msg = new VBinderMessage(current, targetThread, cap_ref.def.label, blob, (int)size);

            if (targetThread.VBinderState.Completion != null)
            {
                HandleAsyncCall(targetThread, msg);
            }
            else
            {
                Contract.Assert(msg.GhostTarget == targetThread);
                targetThread.VBinderState.Enqueue(msg);
            }
            return((int)size);
        }
Example #11
0
        public const int SYS_SENDMMSG    = 20; /* sys_sendmmsg(2)              */

        public static int Poll(Thread current, ref Arch.ExceptionRegisters regs, UserPtr fds, int nfds, int timeout)
        {
            if (nfds < 0)
            {
                return(-ErrorCode.EINVAL);
            }

            var pollfd_size = pollfd.Size * nfds;

            var buf = Globals.AllocateAlignedCompletionBuffer(pollfd_size);

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

            var poll_entry = new PollCompletion(current, fds, nfds, buf);

            if (fds.Read(current, buf, pollfd_size) != 0)
            {
                poll_entry.Dispose();
                return(-ErrorCode.EFAULT);
            }

            Contract.Assert(buf.Length >= pollfd_size);
            if (!TranslateToLinuxFd(current, poll_entry, buf))
            {
                poll_entry.Dispose();
                return(-ErrorCode.EBADF);
            }

            var ret = Arch.IPCStubs.PollAsync(current.Parent.helperPid, current.impl._value.thread._value, new Pointer(buf.Location), nfds, timeout);

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

            Globals.CompletionQueue.Enqueue(poll_entry);
            current.SaveState(ref regs);
            current.AsyncReturn = true;
            return(0);
        }
Example #12
0
        private static int Getsockopt(Thread current, ref Arch.ExceptionRegisters regs, int sockfd, int level, int optname, UserPtr optval, UserPtr p_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);
            }

            uint optlen = 0;

            if (p_optlen.Read(current, out optlen) != 0)
            {
                return(-ErrorCode.EFAULT);
            }

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

            var buf = Globals.AllocateAlignedCompletionBuffer((int)optlen);

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

            var completion = new GetSockParamCompletion(current, optval, p_optlen, buf);

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

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

            return(0);
        }
Example #13
0
        public static int DoFutex(Thread current, ref Arch.ExceptionRegisters regs, UserPtr uaddr, int op, int val, UserPtr timeoutPtr, UserPtr uaddr2, uint val3)
        {
            var      cmd   = op & FUTEX_CMD_MASK;
            var      flags = ToFlags(op, cmd);
            timespec ts;

            ts.tv_sec = ts.tv_nsec = 0;

            // Don't care about shared mutex
            if ((flags & FLAGS_SHARED) != 0)
            {
                return(DoFutexShared(current, ref regs, uaddr, op, val, timeoutPtr, uaddr2, val3));
            }

            bool hasTimeout = timeoutPtr != UserPtr.Zero;

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

            switch (cmd)
            {
            case FUTEX_WAIT:
                return(Wait(current, ref regs, uaddr, flags, val, hasTimeout, ts, FUTEX_BITSET_MATCH_ANY));

            case FUTEX_WAIT_BITSET:
                return(Wait(current, ref regs, uaddr, flags, val, hasTimeout, ts, val3));

            case FUTEX_WAKE:
                return(Wake(current, uaddr, flags, val, FUTEX_BITSET_MATCH_ANY));

            case FUTEX_WAKE_BITSET:
                return(Wake(current, uaddr, flags, val, val3));

            default:
                Arch.Console.Write("futex: unknown primitives ");
                Arch.Console.Write(cmd);
                Arch.Console.WriteLine();
                return(-ErrorCode.ENOSYS);
            }
        }
Example #14
0
        internal int AddUserFdList(Thread current, UserPtr fdlist, int maxfds, short event_type)
        {
            if (fdlist == UserPtr.Zero)
            {
                return(0);
            }

            var buf = new byte[(maxfds + 7) / 8];

            if (fdlist.Read(current, buf) != 0)
            {
                return(-ErrorCode.EFAULT);
            }

            var vec = new FixedSizeBitVector(maxfds, buf);

            var ret = AddFdList(current, vec, event_type);

            return(ret);
        }
Example #15
0
        public static int Nanosleep(Thread current, ref Arch.ExceptionRegisters regs, UserPtr rqtp, UserPtr rmtp)
        {
            timespec ts;
            timespec trem;

            trem.tv_sec  = 0;
            trem.tv_nsec = 0;

            if (rqtp.Read(current, out ts) != 0 || rmtp.Write(current, ref trem) != 0)
            {
                return(-ErrorCode.EFAULT);
            }

            Globals.TimeoutQueue.Enqueue(ts.ToMilliseconds(), current);
            var c = new SleepCompletion(current);

            Globals.CompletionQueue.Enqueue(c);
            current.SaveState(ref regs);
            current.AsyncReturn = true;
            return(0);
        }
Example #16
0
        // XXX: Move to some places
        public static void DumpStackTrace(Thread current, UserPtr ebp)
        {
            int eip;
            int new_ebp;

            while (ebp != UserPtr.Zero)
            {
                Arch.Console.Write("EIP:");
                if ((ebp + sizeof(int)).Read(current, out eip) != 0)
                {
                    return;
                }
                Arch.Console.Write(eip);
                Arch.Console.WriteLine();
                if (ebp.Read(current, out new_ebp) != 0)
                {
                    return;
                }
                ebp = new UserPtr(new_ebp);
            }
        }
Example #17
0
        private static int RecvFrom(Thread current, int sockfd, UserPtr userBuf, int len, int flags, UserPtr sockaddr, UserPtr p_addrlen)
        {
            var proc = current.Parent;
            var file = proc.LookupFile(sockfd);

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

            int addrlen;

            if (p_addrlen.Read(current, out addrlen) != 0)
            {
                return(-ErrorCode.EFAULT);
            }

            var buf = Globals.LinuxIPCBuffer;

            if (len + addrlen > buf.Length)
            {
                return(-ErrorCode.ENOMEM);
            }

            var ret = Arch.IPCStubs.Recvfrom(proc.helperPid, file.inode.LinuxFd, len, flags, ref addrlen);

            if (ret < 0)
            {
                return(ret);
            }

            var left = userBuf.Write(current, new Pointer(buf.Location), ret);

            if (sockaddr.Write(current, new Pointer(buf.Location + ret - left), addrlen) != 0)
            {
                return(-ErrorCode.EFAULT);
            }

            return(ret - left);
        }
Example #18
0
        private int MarshalDataSegments(int size, ref UserPtr data, int offset)
        {
            Contract.Requires(size >= 0);
            Contract.Ensures(ReadCursor == Contract.OldValue(ReadCursor));

            if (size == 0)
            {
                return(0);
            }

            if (size > buf.Length - WriteCursor)
            {
                return(-ErrorCode.ENOMEM);
            }

            var b = buf.Slice(WriteCursor, size);

            // Post condition for ByteBufferRef
            Contract.Assume(b.Length == size);
            var r = data.Read(current, b, size);

            if (r != 0)
            {
                return(-ErrorCode.EFAULT);
            }

            data         = new UserPtr((uint)WriteCursor);
            WriteCursor += size;

            // Add patch entry
            if (CurrentPatchEntry >= kPatchTableSize)
            {
                return(-ErrorCode.ENOMEM);
            }

            patchTable[CurrentPatchEntry++] = ReadCursor + offset;

            return(0);
        }
Example #19
0
        internal int Write(Thread current, ref Arch.ExceptionRegisters regs, UserPtr userBuf, int len, uint pos, File file)
        {
            var buf = Globals.AllocateAlignedCompletionBuffer(len);

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

            var l = userBuf.Read(current, buf, len);
            var bytesToBeWritten = len - l;

            var ret = Write(current, ref regs, ref buf, bytesToBeWritten, pos, file);

            // Buffer hasn't been taken by write(), free it here
            if (buf.isValid)
            {
                Globals.CompletionQueueAllocator.FreePages(new Pointer(buf.Location), buf.Length >> Arch.ArchDefinition.PageShift);
            }

            return(ret);
        }
Example #20
0
        private static int Wait(Thread current, ref Arch.ExceptionRegisters regs, UserPtr uaddr, int flags, int val, bool hasTimeout, timespec ts, uint bitset)
        {
            int old_val;

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

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

            //Arch.Console.Write("wait: addr=");
            //Arch.Console.Write(uaddr.Value.ToUInt32());
            //Arch.Console.Write(" thr=");
            //Arch.Console.Write(current.Tid);
            //Arch.Console.WriteLine();

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

            Globals.FutexLists.InsertAtTail(futex_entry);

            if (hasTimeout)
            {
                node = Globals.TimeoutQueue.Enqueue(ts.ToMilliseconds(), current);
                futex_entry.timeoutNode = node;
            }

            Globals.CompletionQueue.Enqueue(futex_entry);
            current.SaveState(ref regs);
            current.AsyncReturn = true;
            return(0);
        }
Example #21
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;
        }
Example #22
0
        private static int Wait(Thread current, ref Arch.ExceptionRegisters regs, UserPtr uaddr, int flags, int val, bool hasTimeout, timespec ts, uint bitset)
        {
            int old_val;
            if (uaddr.Read(current, out old_val) != 0)
                return -ErrorCode.EFAULT;

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

            //Arch.Console.Write("wait: addr=");
            //Arch.Console.Write(uaddr.Value.ToUInt32());
            //Arch.Console.Write(" thr=");
            //Arch.Console.Write(current.Tid);
            //Arch.Console.WriteLine();

            TimerQueueNode node;
            var futex_entry = new FutexCompletionEntry(current, uaddr, bitset);
            Globals.FutexLists.InsertAtTail(futex_entry);

            if (hasTimeout)
            {
                node = Globals.TimeoutQueue.Enqueue(ts.ToMilliseconds(), current);
                futex_entry.timeoutNode = node;
            }

            Globals.CompletionQueue.Enqueue(futex_entry);
            current.SaveState(ref regs);
            current.AsyncReturn = true;
            return 0;
        }
Example #23
0
        public static int Poll(Thread current, ref Arch.ExceptionRegisters regs, UserPtr fds, int nfds, int timeout)
        {
            if (nfds < 0)
                return -ErrorCode.EINVAL;

            var pollfd_size = pollfd.Size * nfds;

            var buf = Globals.AllocateAlignedCompletionBuffer(pollfd_size);
            if (!buf.isValid)
                return -ErrorCode.ENOMEM;

            var poll_entry = new PollCompletion(current, fds, nfds, buf);

            if (fds.Read(current, buf, pollfd_size) != 0)
            {
                poll_entry.Dispose();
                return -ErrorCode.EFAULT;
            }

            Contract.Assert(buf.Length >= pollfd_size);
            if (!TranslateToLinuxFd(current, poll_entry, buf))
            {
                poll_entry.Dispose();
                return -ErrorCode.EBADF;
            }

            var ret = Arch.IPCStubs.PollAsync(current.Parent.helperPid, current.impl._value.thread._value, new Pointer(buf.Location), nfds, timeout);

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

            Globals.CompletionQueue.Enqueue(poll_entry);
            current.SaveState(ref regs);
            current.AsyncReturn = true;
            return 0;
        }
Example #24
0
        internal int Write(Thread current, ref Arch.ExceptionRegisters regs, UserPtr userBuf, int len, uint pos, File file)
        {
            var buf = Globals.AllocateAlignedCompletionBuffer(len);

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

            var l = userBuf.Read(current, buf, len);
            var bytesToBeWritten = len - l;

            var ret = Write(current, ref regs, ref buf, bytesToBeWritten, pos, file);

            // Buffer hasn't been taken by write(), free it here
            if (buf.isValid)
                Globals.CompletionQueueAllocator.FreePages(new Pointer(buf.Location), buf.Length >> Arch.ArchDefinition.PageShift);

            return ret;
        }
Example #25
0
        public static int Writev(Thread current, ref Arch.ExceptionRegisters regs, int fd, UserPtr iovPtr, int iovcnt)
        {
            if (iovcnt < 0)
                return -ErrorCode.EINVAL;

            if (iovcnt == 0)
                return 0;

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

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

            var mode = file.flags & FileFlags.ReadWriteMask;

            if (mode == FileFlags.ReadOnly)
                return -ErrorCode.EPERM;

            var iovec_buf = new byte[IOVector.Size * iovcnt];

            if (iovPtr.Read(current, iovec_buf, iovec_buf.Length) != 0)
            {
                Arch.Console.WriteLine("Cannot read iovec");
                return -ErrorCode.EFAULT;
            }

            int totalLength = 0;
            for (int i = 0; i < iovcnt; ++i)
            {
                Contract.Assert((i + 1) * IOVector.Size <= iovec_buf.Length);
                var iovec = IOVector.Deserialize(iovec_buf, i * IOVector.Size);
                totalLength += iovec.iov_len;
            }

            var buf = Globals.AllocateAlignedCompletionBuffer(totalLength);
            if (!buf.isValid)
                return -ErrorCode.ENOMEM;

            int cursor = 0;
            for (int i = 0; i < iovcnt; ++i)
            {
                Contract.Assert((i + 1) * IOVector.Size <= iovec_buf.Length);
                var iovec = IOVector.Deserialize(iovec_buf, i * IOVector.Size);

                var chunk = buf.Slice(cursor, iovec.iov_len);

                // Post condition of Slice
                Contract.Assume(chunk.Length >= iovec.iov_len);
                if (iovec.iov_base.Read(current, chunk, iovec.iov_len) != 0)
                {
                    Globals.CompletionQueueAllocator.FreePages(new Pointer(buf.Location), buf.Length >> Arch.ArchDefinition.PageShift);
                    return -ErrorCode.EFAULT;
                }

                cursor += iovec.iov_len;
            }

            int ret = file.Write(current, ref regs, ref buf, totalLength);

            if (buf.isValid)
                Globals.CompletionQueueAllocator.FreePages(new Pointer(buf.Location), buf.Length >> Arch.ArchDefinition.PageShift);
            return ret;
        }
Example #26
0
        public static int Writev(Thread current, ref Arch.ExceptionRegisters regs, int fd, UserPtr iovPtr, int iovcnt)
        {
            if (iovcnt < 0)
            {
                return(-ErrorCode.EINVAL);
            }

            if (iovcnt == 0)
            {
                return(0);
            }

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

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

            var mode = file.flags & FileFlags.ReadWriteMask;

            if (mode == FileFlags.ReadOnly)
            {
                return(-ErrorCode.EPERM);
            }

            var iovec_buf = new byte[IOVector.Size * iovcnt];

            if (iovPtr.Read(current, iovec_buf) != 0)
            {
                Arch.Console.WriteLine("Cannot read iovec");
                return(-ErrorCode.EFAULT);
            }

            int totalLength = 0;

            for (int i = 0; i < iovcnt; ++i)
            {
                Contract.Assert((i + 1) * IOVector.Size <= iovec_buf.Length);
                var iovec = IOVector.Deserialize(iovec_buf, i * IOVector.Size);
                totalLength += iovec.iov_len;
            }

            var buf = Globals.AllocateAlignedCompletionBuffer(totalLength);

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

            int cursor = 0;

            for (int i = 0; i < iovcnt; ++i)
            {
                Contract.Assert((i + 1) * IOVector.Size <= iovec_buf.Length);
                var iovec = IOVector.Deserialize(iovec_buf, i * IOVector.Size);

                var chunk = buf.Slice(cursor, iovec.iov_len);

                // Post condition of Slice
                Contract.Assume(chunk.Length >= iovec.iov_len);
                if (iovec.iov_base.Read(current, chunk, iovec.iov_len) != 0)
                {
                    Globals.CompletionQueueAllocator.FreePages(new Pointer(buf.Location), buf.Length >> Arch.ArchDefinition.PageShift);
                    return(-ErrorCode.EFAULT);
                }

                cursor += iovec.iov_len;
            }

            int ret = file.Write(current, ref regs, ref buf, totalLength);

            if (buf.isValid)
            {
                Globals.CompletionQueueAllocator.FreePages(new Pointer(buf.Location), buf.Length >> Arch.ArchDefinition.PageShift);
            }
            return(ret);
        }
Example #27
0
        internal static int AshmemIoctl(GenericINode generic_inode, Thread current, uint cmd, UserPtr arg1)
        {
            Contract.Requires(Globals.LinuxIPCBuffer.Length >= AshmemINode.ASHMEM_PIN_SIZE);

            int ret = 0;

            switch (cmd)
            {
            case AshmemINode.ASHMEM_SET_NAME:
                arg1.ReadString(current, Globals.LinuxIPCBuffer);
                break;

            case AshmemINode.ASHMEM_PIN:
            case AshmemINode.ASHMEM_UNPIN:
                if (arg1.Read(current, Globals.LinuxIPCBuffer, AshmemINode.ASHMEM_PIN_SIZE) != 0)
                {
                    ret = -ErrorCode.EFAULT;
                }
                break;

            case AshmemINode.ASHMEM_GET_NAME:
            case AshmemINode.ASHMEM_SET_SIZE:
            case AshmemINode.ASHMEM_GET_SIZE:
            case AshmemINode.ASHMEM_SET_PROT_MASK:
            case AshmemINode.ASHMEM_GET_PROT_MASK:
            case AshmemINode.ASHMEM_GET_PIN_STATUS:
            case AshmemINode.ASHMEM_PURGE_ALL_CACHES:
                break;

            default:
                ret = -ErrorCode.ENOSYS;
                break;
            }

            if (ret < 0)
            {
                return(ret);
            }

            var linux_fd = generic_inode.LinuxFd;

            ret = Arch.IPCStubs.linux_sys_vfs_ashmem_ioctl(current.Parent.helperPid, linux_fd, cmd, arg1.Value.ToInt32());

            if (ret < 0)
            {
                return(ret);
            }

            // unmarshal if necessary
            if (cmd == AshmemINode.ASHMEM_GET_NAME)
            {
                var length = Util.Strnlen(Globals.LinuxIPCBuffer, AshmemINode.ASHMEM_NAME_LEN);
                // include terminator
                if (length < AshmemINode.ASHMEM_NAME_LEN)
                {
                    length++;
                }

                var buf = Globals.LinuxIPCBuffer.Slice(0, length);
                if (arg1.Write(current, Globals.LinuxIPCBuffer) != 0)
                {
                    return(-ErrorCode.EFAULT);
                }
            }

            return(ret);
        }
Example #28
0
        private static int Getsockname(Thread current, ref Arch.ExceptionRegisters regs, int sockfd, UserPtr sockaddr, UserPtr p_addrlen)
        {
            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;

            int addrlen;
            if (p_addrlen.Read(current, out addrlen) != 0)
                return -ErrorCode.EFAULT;

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

            var buf = Globals.AllocateAlignedCompletionBuffer((int)addrlen);

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

            var completion = new GetSockParamCompletion(current, sockaddr, p_addrlen, buf);

            Arch.IPCStubs.GetsockNameAsync(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;
        }
Example #29
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;
        }
Example #30
0
        public static int socketcall(Thread current, ref Arch.ExceptionRegisters regs, int call, UserPtr argPtr)
        {
            int err = 0;
            int a0, a1, a2, a3, a4, a5;

            SyscallProfiler.EnterSocketcall(call);
            switch (call)
            {
            case SYS_SOCKET:
                if (argPtr.Read(current, out a0) != 0 || (argPtr + sizeof(int)).Read(current, out a1) != 0 ||
                    (argPtr + sizeof(int) * 2).Read(current, out a2) != 0)
                {
                    return(-ErrorCode.EFAULT);
                }

                err = Socket(current, ref regs, a0, a1, a2);
                break;

            case SYS_BIND:
                if (argPtr.Read(current, out a0) != 0 || (argPtr + sizeof(int)).Read(current, out a1) != 0 ||
                    (argPtr + sizeof(int) * 2).Read(current, out a2) != 0)
                {
                    return(-ErrorCode.EFAULT);
                }

                err = Bind(current, ref regs, a0, new UserPtr(a1), a2);
                break;

            case SYS_CONNECT:
                if (argPtr.Read(current, out a0) != 0 || (argPtr + sizeof(int)).Read(current, out a1) != 0 ||
                    (argPtr + sizeof(int) * 2).Read(current, out a2) != 0)
                {
                    return(-ErrorCode.EFAULT);
                }

                err = Connect(current, ref regs, a0, new UserPtr(a1), a2);
                break;

            case SYS_GETSOCKNAME:
                if (argPtr.Read(current, out a0) != 0 || (argPtr + sizeof(int)).Read(current, out a1) != 0 ||
                    (argPtr + sizeof(int) * 2).Read(current, out a2) != 0)
                {
                    return(-ErrorCode.EFAULT);
                }

                err = Getsockname(current, ref regs, a0, new UserPtr(a1), new UserPtr(a2));
                break;

            case SYS_SENDTO:
                if (argPtr.Read(current, out a0) != 0 || (argPtr + sizeof(int)).Read(current, out a1) != 0 ||
                    (argPtr + sizeof(int) * 2).Read(current, out a2) != 0 || (argPtr + sizeof(int) * 3).Read(current, out a3) != 0 ||
                    (argPtr + sizeof(int) * 4).Read(current, out a4) != 0 || (argPtr + sizeof(int) * 5).Read(current, out a5) != 0)
                {
                    return(-ErrorCode.EFAULT);
                }

                err = Sendto(current, a0, new UserPtr(a1), a2, a3, new UserPtr(a4), a5);
                break;

            case SYS_RECVFROM:
                if (argPtr.Read(current, out a0) != 0 || (argPtr + sizeof(int)).Read(current, out a1) != 0 ||
                    (argPtr + sizeof(int) * 2).Read(current, out a2) != 0 || (argPtr + sizeof(int) * 3).Read(current, out a3) != 0 ||
                    (argPtr + sizeof(int) * 4).Read(current, out a4) != 0 || (argPtr + sizeof(int) * 5).Read(current, out a5) != 0)
                {
                    return(-ErrorCode.EFAULT);
                }

                err = RecvFrom(current, a0, new UserPtr(a1), a2, a3, new UserPtr(a4), new UserPtr(a5));
                break;

            case SYS_SHUTDOWN:
                if (argPtr.Read(current, out a0) != 0 || (argPtr + sizeof(int)).Read(current, out a1) != 0)
                {
                    return(-ErrorCode.EFAULT);
                }

                err = Shutdown(current, a0, a1);
                break;

            case SYS_SETSOCKOPT:
                if (argPtr.Read(current, out a0) != 0 || (argPtr + sizeof(int)).Read(current, out a1) != 0 ||
                    (argPtr + sizeof(int) * 2).Read(current, out a2) != 0 || (argPtr + sizeof(int) * 3).Read(current, out a3) != 0 ||
                    (argPtr + sizeof(int) * 4).Read(current, out a4) != 0)
                {
                    return(-ErrorCode.EFAULT);
                }

                err = Setsockopt(current, ref regs, a0, a1, a2, new UserPtr(a3), a4);
                break;

            case SYS_GETSOCKOPT:
                if (argPtr.Read(current, out a0) != 0 || (argPtr + sizeof(int)).Read(current, out a1) != 0 ||
                    (argPtr + sizeof(int) * 2).Read(current, out a2) != 0 || (argPtr + sizeof(int) * 3).Read(current, out a3) != 0 ||
                    (argPtr + sizeof(int) * 4).Read(current, out a4) != 0)
                {
                    return(-ErrorCode.EFAULT);
                }

                err = Getsockopt(current, ref regs, a0, a1, a2, new UserPtr(a3), new UserPtr(a4));
                break;

            default:
                Arch.Console.Write("Unimplemented socketcall ");
                Arch.Console.Write(call);
                Arch.Console.WriteLine();
                err = -1;
                break;
            }
            SyscallProfiler.ExitSocketcall(call);

            return(err);
        }
Example #31
0
        private static int RecvFrom(Thread current, int sockfd, UserPtr userBuf, int len, int flags, UserPtr sockaddr, UserPtr p_addrlen)
        {
            var proc = current.Parent;
            var file = proc.LookupFile(sockfd);
            if (file == null)
                return -ErrorCode.EBADF;

            int addrlen;
            if (p_addrlen.Read(current, out addrlen) != 0)
                return -ErrorCode.EFAULT;

            var buf = Globals.LinuxIPCBuffer;
            if (len + addrlen > buf.Length)
            {
                return -ErrorCode.ENOMEM;
            }

            var ret = Arch.IPCStubs.Recvfrom(proc.helperPid, file.inode.LinuxFd, len, flags, ref addrlen);
            if (ret < 0)
                return ret;

            var left = userBuf.Write(current, new Pointer(buf.Location), ret);

            if (sockaddr.Write(current, new Pointer(buf.Location + ret - left), addrlen) != 0)
                return -ErrorCode.EFAULT;

            return ret - left;
        }
Example #32
0
        public static int Select(Thread current, ref Arch.ExceptionRegisters regs, int maxfds, UserPtr inp, UserPtr outp, UserPtr exp, UserPtr tvp)
        {
            var helper = new SelectHelper();
            int ret    = 0;

            ret = helper.AddUserFdList(current, inp, maxfds, POLLIN);
            if (ret < 0)
            {
                return(ret);
            }

            ret = helper.AddUserFdList(current, outp, maxfds, POLLOUT);
            if (ret < 0)
            {
                return(ret);
            }

            ret = helper.AddUserFdList(current, exp, maxfds, POLLERR);
            if (ret < 0)
            {
                return(ret);
            }

            int     timeout = 0;
            timeval tv;

            if (tvp == UserPtr.Zero)
            {
                timeout = -1;
            }
            else if (tvp.Read(current, out tv) != 0)
            {
                return(-ErrorCode.EFAULT);
            }
            else
            {
                timeout = (int)(tv.tv_sec * 1000 + tv.tv_usec / 1000);
            }

            var nfds        = helper.TotalFds;
            var pollfd_size = pollfd.Size * nfds;
            var buf         = Globals.AllocateAlignedCompletionBuffer(pollfd_size);

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

            helper.WritePollFds(buf);

            var select_entry = new SelectCompletion(current, maxfds, inp, outp, exp, helper, buf);

            ret = Arch.IPCStubs.PollAsync(current.Parent.helperPid, current.impl._value.thread._value, new Pointer(buf.Location), nfds, timeout);

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

            Globals.CompletionQueue.Enqueue(select_entry);
            current.SaveState(ref regs);
            current.AsyncReturn = true;
            return(0);
        }
Example #33
0
        private static int Sendto(Thread current, int sockfd, UserPtr userBuf, int len, int flags, UserPtr sockaddr, int addrlen)
        {
            var proc = current.Parent;
            var file = proc.LookupFile(sockfd);
            if (file == null)
                return -ErrorCode.EBADF;

            var buf = Globals.LinuxIPCBuffer;

            if (len < 0 || addrlen < 0)
                return -ErrorCode.EINVAL;

            if (len + addrlen > buf.Length)
                return -ErrorCode.ENOMEM;

            if (sockaddr == UserPtr.Zero && addrlen != 0)
                return -ErrorCode.EINVAL;

            Contract.Assert(buf.Length >= len + addrlen);

            if (userBuf.Read(current, buf, len) != 0)
                return -ErrorCode.EFAULT;

            var old_buf_len = buf.Length;
            var sockaddr_buf = buf.Slice(len, buf.Length - len);

            // Post-condition of ByteBufferRef#ctor and slice
            Contract.Assume(buf.Length == old_buf_len);
            Contract.Assume(sockaddr_buf.Length == buf.Length - len);

            Contract.Assert(buf.Length - len >= addrlen);

            if (sockaddr != UserPtr.Zero && sockaddr.Read(current, sockaddr_buf, addrlen) != 0)
                return -ErrorCode.EFAULT;

            return Arch.IPCStubs.Sendto(proc.helperPid, file.inode.LinuxFd, len, flags, addrlen);
        }
Example #34
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;
        }
        private int MarshalDataSegments(int size, ref UserPtr data, int offset)
        {
            Contract.Requires(size >= 0);
            Contract.Ensures(ReadCursor == Contract.OldValue(ReadCursor));

            if (size == 0)
                return 0;

            if (size > buf.Length - WriteCursor)
                return -ErrorCode.ENOMEM;

            var b = buf.Slice(WriteCursor, size);

            // Post condition for ByteBufferRef
            Contract.Assume(b.Length == size);
            var r = data.Read(current, b, size);
            if (r != 0)
                return -ErrorCode.EFAULT;

            data = new UserPtr((uint)WriteCursor);
            WriteCursor += size;

            // Add patch entry
            if (CurrentPatchEntry >= kPatchTableSize)
                return -ErrorCode.ENOMEM;

            patchTable[CurrentPatchEntry++] = ReadCursor + offset;

            return 0;
        }
Example #36
0
        public static int socketcall(Thread current, ref Arch.ExceptionRegisters regs, int call, UserPtr argPtr)
        {
            int err = 0;
            int a0, a1, a2, a3, a4, a5;

            SyscallProfiler.EnterSocketcall(call);
            switch (call)
            {
                case SYS_SOCKET:
                    if (argPtr.Read(current, out a0) != 0 || (argPtr + sizeof(int)).Read(current, out a1) != 0
                        || (argPtr + sizeof(int) * 2).Read(current, out a2) != 0)
                        return -ErrorCode.EFAULT;

                    err = Socket(current, ref regs, a0, a1, a2);
                    break;

                case SYS_BIND:
                    if (argPtr.Read(current, out a0) != 0 || (argPtr + sizeof(int)).Read(current, out a1) != 0
                        || (argPtr + sizeof(int) * 2).Read(current, out a2) != 0)
                        return -ErrorCode.EFAULT;

                    err = Bind(current, ref regs, a0, new UserPtr(a1), a2);
                    break;

                case SYS_CONNECT:
                    if (argPtr.Read(current, out a0) != 0 || (argPtr + sizeof(int)).Read(current, out a1) != 0
                        || (argPtr + sizeof(int) * 2).Read(current, out a2) != 0)
                        return -ErrorCode.EFAULT;

                    err = Connect(current, ref regs, a0, new UserPtr(a1), a2);
                    break;

                case SYS_GETSOCKNAME:
                    if (argPtr.Read(current, out a0) != 0 || (argPtr + sizeof(int)).Read(current, out a1) != 0
                        || (argPtr + sizeof(int) * 2).Read(current, out a2) != 0)
                        return -ErrorCode.EFAULT;

                    err = Getsockname(current, ref regs, a0, new UserPtr(a1), new UserPtr(a2));
                    break;

                case SYS_SENDTO:
                    if (argPtr.Read(current, out a0) != 0 || (argPtr + sizeof(int)).Read(current, out a1) != 0
                        || (argPtr + sizeof(int) * 2).Read(current, out a2) != 0 || (argPtr + sizeof(int) * 3).Read(current, out a3) != 0
                        || (argPtr + sizeof(int) * 4).Read(current, out a4) != 0 || (argPtr + sizeof(int) * 5).Read(current, out a5) != 0)
                        return -ErrorCode.EFAULT;

                    err = Sendto(current, a0, new UserPtr(a1), a2, a3, new UserPtr(a4), a5);
                    break;

                case SYS_RECVFROM:
                    if (argPtr.Read(current, out a0) != 0 || (argPtr + sizeof(int)).Read(current, out a1) != 0
                        || (argPtr + sizeof(int) * 2).Read(current, out a2) != 0 || (argPtr + sizeof(int) * 3).Read(current, out a3) != 0
                        || (argPtr + sizeof(int) * 4).Read(current, out a4) != 0 || (argPtr + sizeof(int) * 5).Read(current, out a5) != 0)
                        return -ErrorCode.EFAULT;

                    err = RecvFrom(current, a0, new UserPtr(a1), a2, a3, new UserPtr(a4), new UserPtr(a5));
                    break;

                case SYS_SHUTDOWN:
                    if (argPtr.Read(current, out a0) != 0 || (argPtr + sizeof(int)).Read(current, out a1) != 0)
                        return -ErrorCode.EFAULT;

                    err = Shutdown(current, a0, a1);
                    break;

                case SYS_SETSOCKOPT:
                    if (argPtr.Read(current, out a0) != 0 || (argPtr + sizeof(int)).Read(current, out a1) != 0
                        || (argPtr + sizeof(int) * 2).Read(current, out a2) != 0 || (argPtr + sizeof(int) * 3).Read(current, out a3) != 0
                        || (argPtr + sizeof(int) * 4).Read(current, out a4) != 0)
                        return -ErrorCode.EFAULT;

                    err = Setsockopt(current, ref regs, a0, a1, a2, new UserPtr(a3), a4);
                    break;

                case SYS_GETSOCKOPT:
                    if (argPtr.Read(current, out a0) != 0 || (argPtr + sizeof(int)).Read(current, out a1) != 0
                      || (argPtr + sizeof(int) * 2).Read(current, out a2) != 0 || (argPtr + sizeof(int) * 3).Read(current, out a3) != 0
                      || (argPtr + sizeof(int) * 4).Read(current, out a4) != 0)
                        return -ErrorCode.EFAULT;

                    err = Getsockopt(current, ref regs, a0, a1, a2, new UserPtr(a3), new UserPtr(a4));
                    break;

                default:
                    Arch.Console.Write("Unimplemented socketcall ");
                    Arch.Console.Write(call);
                    Arch.Console.WriteLine();
                    err = -1;
                    break;
            }
            SyscallProfiler.ExitSocketcall(call);

            return err;
        }
        internal int Marshal(UserPtr writeBuf, int size)
        {
            if (size < 0 || size > buf.Length)
                return -ErrorCode.EINVAL;

            ReadCursor = 0;

            // Copy the full data into the buffer, but don't increment the read pointer yet.
            var r = writeBuf.Read(current, buf, size);
            if (r != 0)
                return -1;

            // Advance the cursor
            WriteCursor = size;
            // parse the command
            while (ReadCursor < size)
            {
                if (ReadCursor + sizeof(uint) > buf.Length)
                    return -ErrorCode.ENOMEM;

                var cmd = Deserializer.ReadUInt(buf, ReadCursor);
                ReadCursor += sizeof(uint);

                switch (cmd)
                {
                    case BinderINode.BC_INCREFS:
                    case BinderINode.BC_ACQUIRE:
                    case BinderINode.BC_RELEASE:
                    case BinderINode.BC_DECREFS:
                        ReadCursor += sizeof(int);
                        break;

                    case BinderINode.BC_INCREFS_DONE:
                    case BinderINode.BC_ACQUIRE_DONE:
                    case BinderINode.BC_REQUEST_DEATH_NOTIFICATION:
                    case BinderINode.BC_CLEAR_DEATH_NOTIFICATION:
                        ReadCursor += Pointer.Size * 2;
                        break;

                    case BinderINode.BC_ATTEMPT_ACQUIRE:
                    case BinderINode.BC_ACQUIRE_RESULT:
                        // Unimplemented in Android IPC
                        return -ErrorCode.EINVAL;

                    case BinderINode.BC_FREE_BUFFER:
                        {
                            if (ReadCursor + sizeof(uint) > buf.Length)
                                return -ErrorCode.ENOMEM;

                            var addr = Deserializer.ReadUInt(buf, ReadCursor);
                            var new_val = addr - current.Parent.binderVMStart.Value.ToUInt32() + current.Parent.ShadowBinderVMStart;
                            Deserializer.WriteUInt(new_val, buf, ReadCursor);
                            ReadCursor += Pointer.Size;
                            break;
                        }

                    case BinderINode.BC_TRANSACTION:
                    case BinderINode.BC_REPLY:
                        {
                            var ret = MarshalTransaction();
                            if (ret < 0)
                                return ret;

                            break;
                        }

                    case BinderINode.BC_REGISTER_LOOPER:
                    case BinderINode.BC_ENTER_LOOPER:
                    case BinderINode.BC_EXIT_LOOPER:
                        break;

                    default:
                        Arch.Console.Write("binder: unsupported IPC primitive ");
                        Arch.Console.Write(cmd);
                        Arch.Console.WriteLine();
                        return -1;
                }
            }

            r = AppendPatchTable();
            if (r != 0)
                return -1;

            //Arch.Console.Write("Dump write buffer ");
            //Arch.Console.Write(current.Tid);
            //Arch.Console.WriteLine();
            //DumpBuf(new Pointer(buf.Location), size);
            return 0;
        }
Example #38
0
        public static int Select(Thread current, ref Arch.ExceptionRegisters regs, int maxfds, UserPtr inp, UserPtr outp, UserPtr exp, UserPtr tvp)
        {
            var helper = new SelectHelper();
            int ret = 0;

            ret = helper.AddUserFdList(current, inp, maxfds, POLLIN);
            if (ret < 0)
                return ret;

            ret = helper.AddUserFdList(current, outp, maxfds, POLLOUT);
            if (ret < 0)
                return ret;

            ret = helper.AddUserFdList(current, exp, maxfds, POLLERR);
            if (ret < 0)
                return ret;

            int timeout = 0;
            timeval tv;
            if (tvp == UserPtr.Zero)
            {
                timeout = -1;
            }
            else if (tvp.Read(current, out tv) != 0)
            {
                return -ErrorCode.EFAULT;
            }
            else
            {
                timeout = (int)(tv.tv_sec * 1000 + tv.tv_usec / 1000);
            }

            var nfds = helper.TotalFds;
            var pollfd_size = pollfd.Size * nfds;
            var buf = Globals.AllocateAlignedCompletionBuffer(pollfd_size);
            if (!buf.isValid)
                return -ErrorCode.ENOMEM;

            helper.WritePollFds(buf);

            var select_entry = new SelectCompletion(current, maxfds, inp, outp, exp, helper, buf);
            ret = Arch.IPCStubs.PollAsync(current.Parent.helperPid, current.impl._value.thread._value, new Pointer(buf.Location), nfds, timeout);

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

            Globals.CompletionQueue.Enqueue(select_entry);
            current.SaveState(ref regs);
            current.AsyncReturn = true;
            return 0;
        }
Example #39
0
        private static int Send(Thread current, int cap_idx, UserPtr userBuf, uint size)
        {
            if (!current.Parent.Space.VerifyRead(userBuf, size))
                return -ErrorCode.EFAULT;

            var cap_ref = current.VBinderState.Find(current, cap_idx);
            if (cap_ref == null)
                return -ErrorCode.EINVAL;

            var blob = Globals.AllocateAlignedCompletionBuffer((int)size);
            if (!blob.isValid)
                return -ErrorCode.ENOMEM;

            if (userBuf.Read(current, blob, (int)size) != 0)
                return -ErrorCode.EFAULT;

            var targetThread = cap_ref.def.parent;

            // Object invariant of thread
            Contract.Assume(targetThread.VBinderState.Owner == targetThread);

            var msg = new VBinderMessage(current, targetThread, cap_ref.def.label, blob, (int)size);

            if (targetThread.VBinderState.Completion != null)
            {
                HandleAsyncCall(targetThread, msg);
            }
            else
            {
                Contract.Assert(msg.GhostTarget == targetThread);
                targetThread.VBinderState.Enqueue(msg);
            }
            return (int)size;
        }
Example #40
0
        internal int Marshal(UserPtr writeBuf, int size)
        {
            if (size < 0 || size > buf.Length)
            {
                return(-ErrorCode.EINVAL);
            }

            ReadCursor = 0;

            // Copy the full data into the buffer, but don't increment the read pointer yet.
            var r = writeBuf.Read(current, buf, size);

            if (r != 0)
            {
                return(-1);
            }

            // Advance the cursor
            WriteCursor = size;
            // parse the command
            while (ReadCursor < size)
            {
                if (ReadCursor + sizeof(uint) > buf.Length)
                {
                    return(-ErrorCode.ENOMEM);
                }

                var cmd = Deserializer.ReadUInt(buf, ReadCursor);
                ReadCursor += sizeof(uint);

                switch (cmd)
                {
                case BinderINode.BC_INCREFS:
                case BinderINode.BC_ACQUIRE:
                case BinderINode.BC_RELEASE:
                case BinderINode.BC_DECREFS:
                    ReadCursor += sizeof(int);
                    break;

                case BinderINode.BC_INCREFS_DONE:
                case BinderINode.BC_ACQUIRE_DONE:
                case BinderINode.BC_REQUEST_DEATH_NOTIFICATION:
                case BinderINode.BC_CLEAR_DEATH_NOTIFICATION:
                    ReadCursor += Pointer.Size * 2;
                    break;

                case BinderINode.BC_ATTEMPT_ACQUIRE:
                case BinderINode.BC_ACQUIRE_RESULT:
                    // Unimplemented in Android IPC
                    return(-ErrorCode.EINVAL);

                case BinderINode.BC_FREE_BUFFER:
                {
                    if (ReadCursor + sizeof(uint) > buf.Length)
                    {
                        return(-ErrorCode.ENOMEM);
                    }

                    var addr    = Deserializer.ReadUInt(buf, ReadCursor);
                    var new_val = addr - current.Parent.binderVMStart.Value.ToUInt32() + current.Parent.ShadowBinderVMStart;
                    Deserializer.WriteUInt(new_val, buf, ReadCursor);
                    ReadCursor += Pointer.Size;
                    break;
                }

                case BinderINode.BC_TRANSACTION:
                case BinderINode.BC_REPLY:
                {
                    var ret = MarshalTransaction();
                    if (ret < 0)
                    {
                        return(ret);
                    }

                    break;
                }

                case BinderINode.BC_REGISTER_LOOPER:
                case BinderINode.BC_ENTER_LOOPER:
                case BinderINode.BC_EXIT_LOOPER:
                    break;

                default:
                    Arch.Console.Write("binder: unsupported IPC primitive ");
                    Arch.Console.Write(cmd);
                    Arch.Console.WriteLine();
                    return(-1);
                }
            }

            r = AppendPatchTable();
            if (r != 0)
            {
                return(-1);
            }

            //Arch.Console.Write("Dump write buffer ");
            //Arch.Console.Write(current.Tid);
            //Arch.Console.WriteLine();
            //DumpBuf(new Pointer(buf.Location), size);
            return(0);
        }
Example #41
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);
        }
Example #42
0
        public static int Nanosleep(Thread current, ref Arch.ExceptionRegisters regs, UserPtr rqtp, UserPtr rmtp)
        {
            timespec ts;
            timespec trem;

            trem.tv_sec = 0;
            trem.tv_nsec = 0;

            if (rqtp.Read(current, out ts) != 0 || rmtp.Write(current, ref trem) != 0)
                return -ErrorCode.EFAULT;

            Globals.TimeoutQueue.Enqueue(ts.ToMilliseconds(), current);
            var c = new SleepCompletion(current);

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