Beispiel #1
0
        public int Read(Thread current, ref Arch.ExceptionRegisters regs, UserPtr userBuf, int len, uint pos)
        {
            Contract.Requires(GhostOwner == current.Parent);
            var ret = inode.Read(current, ref regs, userBuf, len, pos, null);

            return(ret);
        }
Beispiel #2
0
        private int Ioctl(Thread current, uint cmd, UserPtr arg1)
        {
            //Arch.Console.Write("ioctl:, cmd=");
            //Arch.Console.Write(cmd);
            //Arch.Console.WriteLine();
            // marshal arguments
            switch (cmd)
            {
            case AshmemINode.ASHMEM_SET_NAME:
            case AshmemINode.ASHMEM_PIN:
            case AshmemINode.ASHMEM_UNPIN:
            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:
                return(AshmemINode.AshmemIoctl(this, current, cmd, arg1));

            case FileSystem.FIONREAD:
                return(LinuxIoctl(current, cmd, arg1));

            default:
                return(-1);
            }
        }
Beispiel #3
0
        private static int Recv(Thread current, ref Arch.ExceptionRegisters regs, UserPtr ptr_label, UserPtr userBuf, uint size)
        {
            Contract.Requires(current.VBinderState.Owner == current);

            if (!current.Parent.Space.VerifyWrite(userBuf, size) || !current.Parent.Space.VerifyWrite(ptr_label, sizeof(int)))
            {
                return(-ErrorCode.EFAULT);
            }

            var b = current.VBinderState.NoPendingMessages();

            if (b)
            {
                var entry = new VBinderCompletion(current, ptr_label, userBuf, size);
                current.VBinderState.Completion = entry;

                current.SaveState(ref regs);
                current.AsyncReturn = true;
                return(0);
            }
            else
            {
                var msg = current.VBinderState.TakeMessage();

                Contract.Assert(msg.GhostTarget == current);

                var length = msg.Length;
                ptr_label.Write(current.Parent, msg.label);
                userBuf.Write(current, new Pointer(msg.payload.Location), length);
                msg.Recycle();
                return(length);
            }
        }
Beispiel #4
0
        private int LinuxIoctl(Thread current, uint cmd, UserPtr arg1)
        {
            var msg_buf = Globals.LinuxIPCBuffer;
            int ret     = 0;

            // marshal arguments
            switch (cmd)
            {
            case FileSystem.FIONREAD:
                break;

            default:
                return(-ErrorCode.ENOTTY);
            }

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

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

            // unmarshal if necessary
            if (cmd == FileSystem.FIONREAD)
            {
                if (arg1.Write(current, new Pointer(msg_buf.Location), sizeof(int)) != 0)
                {
                    return(-ErrorCode.EFAULT);
                }
            }

            return(ret);
        }
Beispiel #5
0
        internal int Write(Thread current, ref Arch.ExceptionRegisters regs, UserPtr userBuf, int len)
        {
            Contract.Requires(GhostOwner == current.Parent);
            var ret = inode.Write(current, ref regs, userBuf, len, position, this);

            return(ret);
        }
        private static int StatAt64(Thread current, UserPtr filenamePtr, UserPtr buf, bool followSymlink)
        {
            var proc = current.Parent;
            int err;

            filenamePtr.ReadString(current, Globals.LinuxIPCBuffer);
            if (followSymlink)
            {
                err = Arch.IPCStubs.linux_sys_stat64(proc.helperPid);
            }
            else
            {
                err = Arch.IPCStubs.linux_sys_lstat64(proc.helperPid);
            }
            if (err != 0)
            {
                return(err);
            }

            if (buf.Write(current, new Pointer(Globals.LinuxIPCBuffer.Location), SIZE_OF_STAT64) != 0)
            {
                return(-ErrorCode.EFAULT);
            }

            return(0);
        }
Beispiel #7
0
        public static int ClockGetTime(Thread current, int clock_id, UserPtr tp)
        {
            timespec res;

            res.tv_nsec = res.tv_sec = 0;
            switch (clock_id)
            {
            case CLOCK_REALTIME:
            case CLOCK_PROCESS_CPUTIME_ID:
            case CLOCK_THREAD_CPUTIME_ID:
                res = GetTime(UptimeTimeSpec);
                break;

            case CLOCK_MONOTONIC:
                res = GetTime(MonotonicTimeSpec);
                break;

            default:
                Arch.Console.Write("Unimplemented ClockGetTime:");
                Arch.Console.Write(clock_id);
                Arch.Console.WriteLine();
                return(-ErrorCode.ENOSYS);
            }

            if (tp.Write(current, ref res) != 0)
            {
                return(-ErrorCode.EFAULT);
            }

            return(0);
        }
Beispiel #8
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;
        }
Beispiel #9
0
        internal int TranslateToUserFdlist(Thread current, ByteBufferRef buf, int poll_ret, int maxfds, UserPtr userPtr, short event_type)
        {
            Contract.Requires(poll_ret * pollfd.Size < buf.Length);

            if (userPtr == UserPtr.Zero)
                return 0;

            var res = 0;
            var len = (maxfds + 7) / 8;
            var vec = new FixedSizeBitVector(maxfds);

            for (int i = 0; i < poll_ret; i++)
            {
                var poll_struct = pollfd.Deserialize(buf, i * pollfd.Size);
                var linux_fd = poll_struct.fd;
                var node = Lookup(linux_fd);
                if (node == null)
                    return -ErrorCode.EBADF;

                if ((poll_struct.revents & event_type & node.event_type) != 0)
                {
                    vec.Set(node.expressos_fd);
                    ++res;
                }
            }

            if (userPtr.Write(current, vec.Buffer) != 0)
                return -ErrorCode.EFAULT;

            return res;
        }
Beispiel #10
0
        public static int ClockGetTime(Thread current, int clock_id, UserPtr tp)
        {
            timespec res;
            res.tv_nsec = res.tv_sec = 0;
            switch (clock_id)
            {
                case CLOCK_REALTIME:
                case CLOCK_PROCESS_CPUTIME_ID:
                case CLOCK_THREAD_CPUTIME_ID:
                    res = GetTime(UptimeTimeSpec);
                    break;

                case CLOCK_MONOTONIC:
                    res = GetTime(MonotonicTimeSpec);
                    break;

                default:
                    Arch.Console.Write("Unimplemented ClockGetTime:");
                    Arch.Console.Write(clock_id);
                    Arch.Console.WriteLine();
                    return -ErrorCode.ENOSYS;
            }

            if (tp.Write(current, ref res) != 0)
                return -ErrorCode.EFAULT;

            return 0;
        }
Beispiel #11
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);
 }
Beispiel #12
0
        private static int Recv(Thread current, ref Arch.ExceptionRegisters regs, UserPtr ptr_label, UserPtr userBuf, uint size)
        {
            Contract.Requires(current.VBinderState.Owner == current);

            if (!current.Parent.Space.VerifyWrite(userBuf, size) || !current.Parent.Space.VerifyWrite(ptr_label, sizeof(int)))
                return -ErrorCode.EFAULT;

            var b = current.VBinderState.NoPendingMessages();
            if (b)
            {
                var entry = new VBinderCompletion(current, ptr_label, userBuf, size);
                current.VBinderState.Completion = entry;

                current.SaveState(ref regs);
                current.AsyncReturn = true;
                return 0;
            }
            else
            {
                var msg = current.VBinderState.TakeMessage();

                Contract.Assert(msg.GhostTarget == current);

                var length = msg.Length;
                ptr_label.Write(current.Parent, msg.label);
                userBuf.Write(current, new Pointer(msg.payload.Location), length);
                msg.Recycle();
                return length;
            }
        }
Beispiel #13
0
        public static int Clone(Thread current, uint flags, UserPtr newsp, UserPtr parent_tidptr, UserPtr child_tidptr, ref Arch.ExceptionRegisters pt_regs)
        {
            // Only support pthread_create right now
            if (flags != (CLONE_FILES | CLONE_FS | CLONE_VM | CLONE_SIGHAND
                          | CLONE_THREAD | CLONE_SYSVSEM | CLONE_DETACHED))
            {
                return(-ErrorCode.EINVAL);
            }

            var proc = current.Parent;
            var thr  = Thread.Create(proc);

            if (thr == null)
            {
                Arch.Console.WriteLine("Failed to create thread");
                return(-ErrorCode.EINVAL);
            }

            // Start the main thread
            // Skipping the int $0x80
            thr.Start(new Pointer(pt_regs.ip + 2), newsp.Value);

            // There's no need to set eax for thr as they are zero by default..

            return(thr.Tid);
        }
        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);
        }
Beispiel #15
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;
            }
        }
Beispiel #16
0
 public SelectCompletion(Thread current, int maxfds, UserPtr inp, UserPtr outp, UserPtr exp, SelectHelper helper, ByteBufferRef buf)
     : base(current, Kind.SelectCompletionKind, buf)
 {
     this.fds    = maxfds;
     this.inp    = inp;
     this.outp   = outp;
     this.exp    = exp;
     this.helper = helper;
 }
Beispiel #17
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;
        }
Beispiel #18
0
        private static int PushInt(Process proc, int v, ref UserPtr stack_top)
        {
            stack_top -= sizeof(int);
            if (stack_top.Write(proc, v) != 0)
            {
                return(-1);
            }

            return(0);
        }
Beispiel #19
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);
        }
Beispiel #20
0
        public PollCompletion(Thread current, UserPtr fds, int nfds, ByteBufferRef buf)
            : base(current, Kind.PollCompletionKind, buf)
        {
            Contract.Requires(nfds >= 0);
            Contract.Requires(buf.Length >= nfds * pollfd.Size);
            Contract.Ensures(fdMaps.Length == nfds);
            Contract.Ensures(this.buf.Length >= fdMaps.Length * pollfd.Size);

            this.userFdBuf = fds;
            this.fdMaps    = new int[nfds];
        }
Beispiel #21
0
        internal int FStat64(Thread current, UserPtr buf)
        {
            switch (kind)
            {
            case INodeKind.ArchINodeKind:
                return(ArchINode.ArchFStat64(current, buf));

            case INodeKind.SecureFSINodeKind:
                return(SFSINode.SFSFStat64(current, buf));
            }
            return(-ErrorCode.EINVAL);
        }
Beispiel #22
0
        public static int Parse(int helperPid, File file, Process proc, ref UserPtr stackTop)
        {
            Contract.Requires(file.GhostOwner == proc);
            Contract.Requires(proc.Space.GhostOwner == proc);

            var buf = new byte[Size];
            uint pos = 0;
            if (file.Read(buf, ref pos) != buf.Length)
                return -ErrorCode.EINVAL;

            var eh = Read(buf);
            if (eh.type != ELF32Header.ELF_TYPE_EXECUTABLE || eh.ProgramHeaderOffest == 0)
                return -ErrorCode.ENOEXEC;

            proc.EntryPoint = eh.EntryPoint;

            ELF32ProgramHeader ph = new ELF32ProgramHeader();
            var ret = FindInterpreter(file, eh, ref ph);
            if (ret == -ErrorCode.EINVAL)
            {
                Arch.Console.WriteLine("Malformed ELF file");
                return ret;
            }
            else if (ret == 0)
            {
                var interpreterBuf = new byte[ph.FileSize];
                pos = ph.offset;
                if (file.Read(interpreterBuf, ref pos) != interpreterBuf.Length)
                    return -ErrorCode.EINVAL;

                var interpreterName = new ASCIIString(interpreterBuf);
                ErrorCode ec;
                var interpreter_inode = Arch.ArchFS.Open(helperPid, interpreterName, 0, 0, out ec);
                if (interpreter_inode == null)
                    return -ErrorCode.ENOENT;

                var interpreter = new File(proc, interpreter_inode, FileFlags.ReadOnly, 0);

                /*
                 * Parse the information of linker.
                 *
                 * This function will also override the entry point.
                 */
                if (Parse(helperPid, interpreter, proc, ref stackTop) != 0)
                    return -ErrorCode.EINVAL;

                // So now let's copy the program header to the top of the stack, and push auxlirary vectors
                PushProgramHeaderAndAuxliraryVectors(proc, file, eh, ref stackTop);
            }

            return MapInSegments(file, proc, eh);
        }
Beispiel #23
0
        internal int Read(Thread current, ref Arch.ExceptionRegisters regs, UserPtr userBuf, int len, uint pos, File file)
        {
            switch (kind)
            {
            case INodeKind.ArchINodeKind:
            case INodeKind.SocketINodeKind:
                return(ArchINode.ArchRead(current, ref regs, userBuf, len, pos, file));

            case INodeKind.SecureFSINodeKind:
                return(SFSINode.SFSRead(current, ref regs, userBuf, len, pos, file));
            }
            return(-ErrorCode.EINVAL);
        }
Beispiel #24
0
        //* return values:
        //*  zero    - success
        //*  -EINVAL - start + len < 0, start is not page-aligned,
        //*              "behavior" is not a valid value, or application
        //*              is attempting to release locked or shared pages.
        //*  -ENOMEM - addresses in the specified range are not currently
        //*              mapped, or are outside the AS of the process.
        //*  -EIO    - an I/O error occurred while paging in data.
        //*  -EBADF  - map exists, but area maps something that isn't a file.
        //*  -EAGAIN - a kernel resource was temporarily unavailable.
        private static int madviseDontNeed(Thread current, uint start, int len)
        {
            if (Arch.ArchDefinition.PageOffset(start) != 0 || len < 0)
            {
                return(-ErrorCode.EINVAL);
            }

            var alignedLength = Arch.ArchDefinition.PageAlign((uint)len);
            var endPage       = new UserPtr(start + alignedLength);

            current.Parent.Space.workingSet.Remove(current.Parent.Space, new UserPtr(start), endPage);
            return(0);
        }
        public static int Pipe(Thread current, UserPtr pipeFd)
        {
            var proc = current.Parent;
            var helperPid = proc.helperPid;
            int fd0, fd1;

            var ret = Arch.IPCStubs.Pipe(helperPid, out fd0, out fd1);

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

            var inode1 = new Arch.ArchINode(fd0, 0, helperPid);
            var inode2 = new Arch.ArchINode(fd1, 0, helperPid);

            // XXX: are the permission settings correct?
            var file1 = new File(proc, inode1, FileFlags.ReadWrite, 0);

            var rfd0 = proc.GetUnusedFd();

            proc.InstallFd(rfd0, file1);

            var file2 = new File(proc, inode2, FileFlags.ReadWrite, 0);

            var rfd1 = proc.GetUnusedFd();

            proc.InstallFd(rfd1, file2);

            //Arch.Console.Write("pipe: linux_fd [");
            //Arch.Console.Write(fd0);
            //Arch.Console.Write(",");
            //Arch.Console.Write(fd1);
            //Arch.Console.Write("] => [");
            //Arch.Console.Write(rfd0);
            //Arch.Console.Write(",");
            //Arch.Console.Write(rfd1);
            //Arch.Console.Write("], ret=");
            //Arch.Console.Write(ret);
            //Arch.Console.WriteLine();

            if (pipeFd.Write(current, rfd0) != 0 || (pipeFd + sizeof(int)).Write(current, rfd1) != 0)
            {
                Arch.IPCStubs.Close(helperPid, fd0);
                Arch.IPCStubs.Close(helperPid, fd1);

                return(-ErrorCode.EFAULT);
            }

            return(ret);
        }
Beispiel #26
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;
        }
Beispiel #27
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));
        }
Beispiel #28
0
        public static int Gettimeofday(Thread current, UserPtr timeval)
        {
            timespec res = GetTime(UptimeTimeSpec);
            timeval  r;

            r.tv_sec  = res.tv_sec;
            r.tv_usec = res.tv_nsec / 1000;

            if (timeval.Write(current, ref r) != 0)
            {
                return(-ErrorCode.EFAULT);
            }

            return(0);
        }
Beispiel #29
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);
     }
 }
Beispiel #30
0
        private static UserPtr[] PushCharArray(Process proc, ASCIIString[] arr, ref UserPtr stack_top)
        {
            var res = new UserPtr[arr.Length];

            for (int i = 0; i < arr.Length; ++i)
            {
                // Include the terminator
                stack_top -= arr[i].Length + 1;
                res[i]     = stack_top;
                if (stack_top.Write(proc, arr[i].GetByteString()) != 0)
                {
                    return(null);
                }
            }
            return(res);
        }
Beispiel #31
0
        internal int SFSRead(Thread current, ref Arch.ExceptionRegisters regs, UserPtr userBuf, int len, uint pos, File file)
        {
            var readBytes = Read(current, userBuf, len, pos);

            if (readBytes <= 0)
            {
                return(readBytes);
            }

            if (file != null)
            {
                file.position = (uint)(pos + readBytes);
            }

            return(readBytes);
        }
Beispiel #32
0
        private static int PushArgumentPointers(Process proc, UserPtr[] arr, ref UserPtr stack_top)
        {
            if (PushInt(proc, 0, ref stack_top) != 0)
            {
                return(-1);
            }

            for (int i = arr.Length - 1; i >= 0; --i)
            {
                var p = arr[i];
                if (PushInt(proc, p.Value.ToInt32(), ref stack_top) != 0)
                {
                    return(-1);
                }
            }
            return(0);
        }
Beispiel #33
0
        internal int SFSFStat64(Thread current, UserPtr buf)
        {
            var ret = Arch.IPCStubs.linux_sys_fstat64(helperPid, Fd);

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

            FileSystem.SetSizeFromStat64(Globals.LinuxIPCBuffer, FileSize);

            if (buf.Write(current, new Pointer(Globals.LinuxIPCBuffer.Location), GenericINode.SIZE_OF_STAT64) != 0)
            {
                return(-ErrorCode.EFAULT);
            }

            return(0);
        }
Beispiel #34
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);
        }
Beispiel #35
0
        private static int PushProgramHeaderAndAuxliraryVectors(Process proc, File file, ELF32Header eh, ref UserPtr stackTop)
        {
            var  programHeaderLength = eh.NumOfProgramHeader * eh.ProgramHeaderSize;
            var  buf = new byte[programHeaderLength];
            uint pos = eh.ProgramHeaderOffest;

            if (file.Read(buf, ref pos) != programHeaderLength)
            {
                return(-ErrorCode.ENOMEM);
            }

            stackTop -= programHeaderLength;
            UserPtr ph_ptr = stackTop;

            if (ph_ptr.Write(proc, buf) != 0)
            {
                return(-ErrorCode.ENOMEM);
            }

            // align
            stackTop = UserPtr.RoundDown(stackTop);

            var aux_vector = new uint[LengthOfAuxVector];

            aux_vector[0] = AT_PHDR;
            aux_vector[1] = ph_ptr.Value.ToUInt32();
            aux_vector[2] = AT_ENTRY;
            aux_vector[3] = eh.EntryPoint;
            aux_vector[4] = AT_PHNUM;
            aux_vector[5] = eh.NumOfProgramHeader;
            aux_vector[6] = 0;
            aux_vector[7] = 0;

            var auxVectorSize = sizeof(uint) * LengthOfAuxVector;

            stackTop -= auxVectorSize;

            if (stackTop.Write(proc, aux_vector) != 0)
            {
                return(-ErrorCode.ENOMEM);
            }

            return(0);
        }
Beispiel #36
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);
        }
Beispiel #37
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);
        }
        public static int FStat64(Thread current, int fd, UserPtr buf)
        {
            var proc = current.Parent;
            var file = proc.LookupFile(fd);

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

            int ret = file.FStat64(current, buf);

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

            return(0);
        }
Beispiel #39
0
        private int Read(Thread current, UserPtr userBuf, int len, uint pos)
        {
            int readBytes     = 0;
            int remainedBytes = len;

            if (FileSize - pos < remainedBytes)
            {
                remainedBytes = (int)(FileSize - pos);
            }
            int currentPageIndex = (int)Arch.ArchDefinition.PageIndex(pos);
            var page             = Pages.Lookup(currentPageIndex / Arch.ArchDefinition.PageSize);

            while (remainedBytes > 0)
            {
                if (page == null)
                {
                    page = CachePage.Allocate(current.Parent, currentPageIndex / Arch.ArchDefinition.PageSize);
                    var succeed = page.Load(this);
                    if (!succeed)
                    {
                        return(-ErrorCode.EIO);
                    }

                    Contract.Assert(page != null && (page.CurrentState == CachePage.State.Empty || page.CurrentState == CachePage.State.Decrypted));
                    Pages.Add(page);
                }

                var pageCursor = (int)((pos + readBytes) % Arch.ArchDefinition.PageSize);
                var chunkLen   = Arch.ArchDefinition.PageSize - pageCursor < remainedBytes ? Arch.ArchDefinition.PageSize - pageCursor : remainedBytes;
                var left       = WriteUserBuffer(current, userBuf, readBytes, page, pageCursor, chunkLen);

                readBytes += chunkLen - left;
                if (left != 0)
                {
                    return(-ErrorCode.EFAULT);
                }

                remainedBytes    = remainedBytes - chunkLen;
                currentPageIndex = currentPageIndex + Arch.ArchDefinition.PageSize;
                page             = Pages.Lookup(currentPageIndex / Arch.ArchDefinition.PageSize);
            }
            return(readBytes);
        }
        public static int UnmarshalReadBuffer(Thread thr, ByteBufferRef completionBuf, ref sys_binder_write_desc desc, UserPtr readBuffer, int readBufferSize)
        {
            var proc = thr.Parent;
            var marshaledPtr = new Pointer(completionBuf.Location);

            //Arch.Console.Write("read_consumed:");
            //Arch.Console.Write(desc.read_consumed);
            //BinderIPCMarshaler.DumpBuf(new Pointer(completionBuf.Location), (int)desc.read_consumed);

            if (proc.binderVMStart == UserPtr.Zero)
            {
                Arch.Console.WriteLine("proc.binderVMStart == UserPtr.Zero");
                return -ErrorCode.EFAULT;
            }

            if (UnmarshalDataEntries(thr, completionBuf, ref desc) != 0)
            {
                Arch.Console.WriteLine("UnmarshalDataEntries failed");
                return -ErrorCode.ENOMEM;
            }

            if (desc.read_consumed > completionBuf.Length)
            {
                Arch.Console.WriteLine("UnmarshalReadBuffer: bad input");
                return -ErrorCode.ENOMEM;
            }

            // Patch pointers and convert file descriptors
            var b = completionBuf.Slice(0, desc.read_consumed);
            if (PatchReadBuffer(thr, b) != 0)
            {
                Arch.Console.WriteLine("Failed to patch read buffer");
                return -ErrorCode.EINVAL;
            }

            if (readBuffer.Write(thr, marshaledPtr, desc.read_consumed) != 0)
            {
                Arch.Console.WriteLine("readBuffer.Write failed");
                return -ErrorCode.ENOMEM;
            }

            return 0;
        }
Beispiel #41
0
        private static int Wake(Thread current, UserPtr uaddr, int flags, int nr_wake, uint bitset)
        {
            if (bitset == 0)
            {
                return(-ErrorCode.EINVAL);
            }

            var space = current.Parent.Space;

            int ret = 0;

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

            FutexCompletionEntry q;

            // XXX: For simplicity (right now), we scan through the whole completion queue
            for (var p = Globals.FutexLists.nextFutex; p != Globals.FutexLists && ret < nr_wake; p = q)
            {
                q = p.nextFutex;

                //Arch.Console.Write("wake_loop: uaddr=");
                //Arch.Console.Write(p.uaddr.Value.ToUInt32());
                //Arch.Console.Write(" tid=");
                //Arch.Console.Write(p.thr.Tid);
                //Arch.Console.WriteLine();

                if (!(p.Space == space && p.uaddr == uaddr && (p.bitset & bitset) != 0))
                {
                    continue;
                }

                ++ret;
                WakeUp(p, true, 0);
            }

            return(ret);
        }
Beispiel #42
0
        public static int Clone(Thread current, uint flags, UserPtr newsp, UserPtr parent_tidptr, UserPtr child_tidptr, ref Arch.ExceptionRegisters pt_regs)
        {
            // Only support pthread_create right now
            if (flags != (CLONE_FILES | CLONE_FS | CLONE_VM | CLONE_SIGHAND
                | CLONE_THREAD | CLONE_SYSVSEM | CLONE_DETACHED))
                return -ErrorCode.EINVAL;

            var proc = current.Parent;
            var thr = Thread.Create(proc);

            if (thr == null)
            {
                Arch.Console.WriteLine("Failed to create thread");
                return -ErrorCode.EINVAL;
            }

            // Start the main thread
            // Skipping the int $0x80
            thr.Start(new Pointer(pt_regs.ip + 2), newsp.Value);

            // There's no need to set eax for thr as they are zero by default..

            return thr.Tid;
        }
        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;
        }
Beispiel #44
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;
        }
Beispiel #45
0
 public static UserPtr RoundDown(UserPtr stack_top)
 {
     return new UserPtr(stack_top.Value.ToUInt32() & ~3U);
 }
Beispiel #46
0
 private static UserPtr[] PushCharArray(Process proc, ASCIIString[] arr, ref UserPtr stack_top)
 {
     var res = new UserPtr[arr.Length];
     for (int i = 0; i < arr.Length; ++i)
     {
         // Include the terminator
         stack_top -= arr[i].Length + 1;
         res[i] = stack_top;
         if (stack_top.Write(proc, arr[i].GetByteString()) != 0)
             return null;
     }
     return res;
 }
Beispiel #47
0
        private static int PushArgumentPointers(Process proc, UserPtr[] arr, ref UserPtr stack_top)
        {
            if (PushInt(proc, 0, ref stack_top) != 0)
                return -1;

            for (int i = arr.Length - 1; i >= 0; --i)
            {
                var p = arr[i];
                if (PushInt(proc, p.Value.ToInt32(), ref stack_top) != 0)
                    return -1;
            }
            return 0;
        }
Beispiel #48
0
        //* return values:
        //*  zero    - success
        //*  -EINVAL - start + len < 0, start is not page-aligned,
        //*              "behavior" is not a valid value, or application
        //*              is attempting to release locked or shared pages.
        //*  -ENOMEM - addresses in the specified range are not currently
        //*              mapped, or are outside the AS of the process.
        //*  -EIO    - an I/O error occurred while paging in data.
        //*  -EBADF  - map exists, but area maps something that isn't a file.
        //*  -EAGAIN - a kernel resource was temporarily unavailable.
        private static int madviseDontNeed(Thread current, uint start, int len)
        {
            if (Arch.ArchDefinition.PageOffset(start) != 0 || len < 0)
                return -ErrorCode.EINVAL;

            var alignedLength = Arch.ArchDefinition.PageAlign((uint)len);
            var endPage = new UserPtr(start + alignedLength);
            current.Parent.Space.workingSet.Remove(current.Parent.Space, new UserPtr(start), endPage);
            return 0;
        }
Beispiel #49
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;
        }
Beispiel #50
0
        public static int mprotect(Thread current, UserPtr addr, int len, int prot)
        {
            if (len < 0)
                return -ErrorCode.EINVAL;

            if (Arch.ArchDefinition.PageOffset(addr.Value.ToUInt32()) != 0)
                return -ErrorCode.EINVAL;

            var space = current.Parent.Space;

            var nextAddr = addr.Value;

            var aligned_len = (int)Arch.ArchDefinition.PageAlign((uint)len);

            var r = space.UpdateAccessRightRange(addr.Value, aligned_len, ProtToAccessFlag(prot));
            if (!r)
            {
                return -ErrorCode.EINVAL;
            }

            if (!space.SanityCheck())
            {
                Arch.Console.Write("Sanity Check failed, after mprotect vaddr=");
                Arch.Console.Write(addr.Value.ToUInt32());
                Arch.Console.Write(", len=");
                Arch.Console.Write(len);
                space.DumpAll();
                Utils.Panic();
            }

            return 0;
        }
Beispiel #51
0
        public static int munmap(Thread current, UserPtr addr, int length)
        {
            if (length <= 0)
                return -ErrorCode.EINVAL;

            var space = current.Parent.Space;
            var alignedLength = Arch.ArchDefinition.PageAlign(length);

            //Arch.Console.Write("munmap:");
            //Arch.Console.Write(addr.Value.ToInt32());
            //Arch.Console.Write(" sz=");
            //Arch.Console.Write(length);
            //Arch.Console.WriteLine();

            if (alignedLength <= 0)
                return -ErrorCode.EINVAL;

            return space.RemoveMapping(addr.Value, alignedLength);
        }
Beispiel #52
0
        private static int PushInt(Process proc, int v, ref UserPtr stack_top)
        {
            stack_top -= sizeof(int);
            if (stack_top.Write(proc, v) != 0)
                return -1;

            return 0;
        }
Beispiel #53
0
        public static int mmap2(Thread current, UserPtr addr, int length, int prot, int flags, int fd, int pgoffset)
        {
            Contract.Requires(current.Parent == current.Parent.Space.GhostOwner);

            Pointer targetAddr = new Pointer(Arch.ArchDefinition.PageAlign(addr.Value.ToUInt32()));

            //Arch.Console.Write("mmap2:");
            //Arch.Console.Write(addr.Value.ToInt32());
            //Arch.Console.Write(" sz=");
            //Arch.Console.Write(length);
            //Arch.Console.Write(" prot=");
            //Arch.Console.Write(prot);
            //Arch.Console.WriteLine();

            var proc = current.Parent;
            var space = proc.Space;
            Contract.Assert(proc == space.GhostOwner);

            if ((flags & MAP_FIXED) == 0)
            {
                if (targetAddr == Pointer.Zero || space.ContainRegion(targetAddr, length))
                    targetAddr = space.FindFreeRegion(length);
            }
            else if (Arch.ArchDefinition.PageOffset(addr.Value.ToInt32()) != 0)
            {
                return -ErrorCode.EINVAL;
            }

            targetAddr = new Pointer(Arch.ArchDefinition.PageIndex(targetAddr.ToUInt32()));

            if (targetAddr == Pointer.Zero || length == 0)
                return -ErrorCode.EINVAL;

            File file = null;
            GenericINode inode = null;

            if ((flags & MAP_ANONYMOUS) == 0)
            {
                file = proc.LookupFile(fd);
                if (file == null)
                    return -ErrorCode.EBADF;

                inode = file.inode;
            }

            int memorySize = Arch.ArchDefinition.PageAlign(length);

            // fix for code contract
            if (length > memorySize)
                length = memorySize;

            if ((file != null && length == 0) || length < 0)
                return -ErrorCode.EINVAL;

            if (file == null)
            {
                pgoffset = 0;
                length = 0;
            }

            //
            // Be careful for shared mapping -- which could be a shared memory region coming from Linux.
            // In this case we'll need to (1) call mmap() in the shadow process to obtain a valid mapping
            // (2) when a page fault happens, grabs the physical page from linux.
            //
            if ((flags & MAP_SHARED) != 0 && SharedWithLinux(inode))
            {
                // Don't know how to deal with it...
                if (addr != UserPtr.Zero)
                   return -ErrorCode.EINVAL;

                var vaddr = Arch.IPCStubs.linux_sys_alien_mmap2(current.Parent.helperPid, addr.Value, length,
                    prot, flags, inode.LinuxFd, pgoffset);

                if (vaddr > AddressSpace.KERNEL_OFFSET)
                    return -ErrorCode.EINVAL;

                switch (inode.kind)
                {
                    case GenericINode.INodeKind.BinderSharedINodeKind:
                    case GenericINode.INodeKind.AshmemINodeKind:
                    case GenericINode.INodeKind.ScreenBufferINodeKind:
                        inode.AlienSharedMemoryINode.vaddrInShadowProcess = new Pointer(vaddr);
                        break;

                    default:
                        // UNIMPLEMENTED... let's return EINVAL to make sure we can catch it.
                        return -ErrorCode.EINVAL;
                }
            }

            var r = space.AddMapping(ProtToAccessFlag(prot), flags, file,
                (uint)pgoffset * Arch.ArchDefinition.PageSize, length, targetAddr, memorySize);

            if (r < 0)
                return r;

            //
            // HACK for binder IPC
            //
            if (inode != null && inode.kind == GenericINode.INodeKind.BinderINodeKind)
            {
                proc.binderVMStart = new UserPtr(targetAddr);
                proc.binderVMSize = length;
            }

            return targetAddr.ToInt32();
        }
Beispiel #54
0
        private static int PushProgramHeaderAndAuxliraryVectors(Process proc, File file, ELF32Header eh, ref UserPtr stackTop)
        {
            var programHeaderLength = eh.NumOfProgramHeader * eh.ProgramHeaderSize;
            var buf = new byte[programHeaderLength];
            uint pos = eh.ProgramHeaderOffest;

            if (file.Read(buf, ref pos) != programHeaderLength)
                return -ErrorCode.ENOMEM;

            stackTop -= programHeaderLength;
            UserPtr ph_ptr = stackTop;

            if (ph_ptr.Write(proc, buf) != 0)
                return -ErrorCode.ENOMEM;

            // align
            stackTop = UserPtr.RoundDown(stackTop);

            var aux_vector = new uint[LengthOfAuxVector];
            aux_vector[0] = AT_PHDR;
            aux_vector[1] = ph_ptr.Value.ToUInt32();
            aux_vector[2] = AT_ENTRY;
            aux_vector[3] = eh.EntryPoint;
            aux_vector[4] = AT_PHNUM;
            aux_vector[5] = eh.NumOfProgramHeader;
            aux_vector[6] = 0;
            aux_vector[7] = 0;

            var auxVectorSize = sizeof(uint) * LengthOfAuxVector;
            stackTop -= auxVectorSize;

            if (stackTop.Write(proc, aux_vector) != 0)
                return -ErrorCode.ENOMEM;

            return 0;
        }
Beispiel #55
0
        private static int StatAt64(Thread current, UserPtr filenamePtr, UserPtr buf, bool followSymlink)
        {
            var proc = current.Parent;
            int err;
            filenamePtr.ReadString(current, Globals.LinuxIPCBuffer);
            if (followSymlink)
            {
                err = Arch.IPCStubs.linux_sys_stat64(proc.helperPid);
            }
            else
            {
                err = Arch.IPCStubs.linux_sys_lstat64(proc.helperPid);
            }
            if (err != 0)
                return err;

            if (buf.Write(current, new Pointer(Globals.LinuxIPCBuffer.Location), SIZE_OF_STAT64) != 0)
                return -ErrorCode.EFAULT;

            return 0;
        }
Beispiel #56
0
        private static Pointer FindShadowAddr(Thread current, UserPtr uaddr)
        {
            var r = current.Parent.Space.Find(uaddr.Value);
            if (r == null)
                return Pointer.Zero;

            var f = r.BackingFile;

            var shm_inode = f.inode.AlienSharedMemoryINode;
            if (shm_inode != null)
                return shm_inode.vaddrInShadowProcess + (uaddr.Value - r.StartAddress);
            else
                return Pointer.Zero;
        }
Beispiel #57
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;
        }
Beispiel #58
0
        //
        // We do sync read for this one, since it's simpler..
        //
        public static Process CreateProcess(ASCIIString path, ASCIIString[] argv, ASCIIString[] envp, AndroidApplicationInfo appInfo)
        {
            var proc = new Process(path, appInfo);
            Utils.Assert(!proc.Space.impl._value.isInvalid);

            uint addr;
            int workspace_fd;
            uint workspace_size;
            proc.helperPid = Arch.IPCStubs.linux_sys_take_helper(out addr, out workspace_fd, out workspace_size);

            if (proc.helperPid < 0)
            {
                Arch.Console.WriteLine("CreateProcess: cannot get helper");
                return null;
            }

            proc.ShadowBinderVMStart = addr;

            ErrorCode ec;
            var inode = Arch.ArchFS.Open(proc.helperPid, path, 0, 0, out ec);
            if (inode == null)
            {
                Arch.Console.WriteLine("CreateProcess: cannot open file");
                return null;
            }

            var stack_top = new UserPtr(INITIAL_STACK_LOCATION);

            // 4M Initial stack
            var stack_size = 4096 * Arch.ArchDefinition.PageSize;
            proc.Space.AddStackMapping(stack_top, stack_size);
            stack_top += stack_size;

            var augmented_envp = CreateEnvpArrayWithWorkspace(envp, proc, workspace_fd, workspace_size);

            var envp_ptr = PushCharArray(proc, augmented_envp, ref stack_top);
            if (envp_ptr == null)
            {
                Arch.Console.WriteLine("CreateProcess: Push envp failed");
                return null;
            }

            var argv_ptr = PushCharArray(proc, argv, ref stack_top);
            if (argv_ptr == null)
            {
                Arch.Console.WriteLine("CreateProcess: Push argv failed");
                return null;
            }

            stack_top = UserPtr.RoundDown(stack_top);

            // Parse the ELF file, which might push additional info on to the stack
            // (i.e., aux vectors when the ELF is dynamically linked)
            var file = new File(proc, inode, FileFlags.ReadWrite, 0);

            int ret = ELF32Header.Parse(proc.helperPid, file, proc, ref stack_top);

            if (ret != 0)
            {
                Arch.Console.WriteLine("CreateProcess: Parse ELF file failed");
                return null;
            }

            //%esp         The stack contains the arguments and environment:
            //     0(%esp)                 argc
            //     4(%esp)                 argv[0]
            //     ...
            //     (4*argc)(%esp)          NULL
            //     (4*(argc+1))(%esp)      envp[0]
            //     ...
            //                             NULL
            if (PushArgumentPointers(proc, envp_ptr, ref stack_top) != 0)
                return null;

            if (PushArgumentPointers(proc, argv_ptr, ref stack_top) != 0)
                return null;

            if (PushInt(proc, argv_ptr.Length, ref stack_top) != 0)
                return null;

            // Stdio
            var file_stdout = File.CreateStdout(proc);
            Contract.Assume(proc.Files.IsAvailableFd(Process.STDOUT_FD));
            proc.InstallFd(Process.STDOUT_FD, file_stdout);

            var file_stderr = File.CreateStdout(proc);
            Contract.Assume(proc.Files.IsAvailableFd(Process.STDERR_FD));
            proc.InstallFd(Process.STDERR_FD, file_stderr);

            var mainThread = Thread.Create(proc);

            if (appInfo != null)
            {
                var p = appInfo.ToParcel();
                Globals.LinuxIPCBuffer.CopyFrom(0, p);
                Arch.IPCStubs.WriteAppInfo(proc.helperPid, p.Length);
            }

            // Start the main thread
            mainThread.Start(new Pointer(proc.EntryPoint), stack_top.Value);
            return proc;
        }
        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;
        }
Beispiel #60
0
        private static int Wake(Thread current, UserPtr uaddr, int flags, int nr_wake, uint bitset)
        {
            if (bitset == 0)
                return -ErrorCode.EINVAL;

            var space = current.Parent.Space;

            int ret = 0;

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

            FutexCompletionEntry q;
            // XXX: For simplicity (right now), we scan through the whole completion queue
            for (var p = Globals.FutexLists.nextFutex; p != Globals.FutexLists && ret < nr_wake; p = q)
            {
                q = p.nextFutex;

                //Arch.Console.Write("wake_loop: uaddr=");
                //Arch.Console.Write(p.uaddr.Value.ToUInt32());
                //Arch.Console.Write(" tid=");
                //Arch.Console.Write(p.thr.Tid);
                //Arch.Console.WriteLine();

                if (!(p.Space == space && p.uaddr == uaddr && (p.bitset & bitset) != 0))
                    continue;

                ++ret;
                WakeUp(p, true, 0);
            }

            return ret;
        }