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);
 }
        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;
        }
 public VBinderThreadState(Thread current)
 {
     Contract.Ensures(Owner == current);
     Capabilities = new CapabilityRef(current, 0, Globals.CapabilityManager.NullCapability);
     MessageQueue = new VBinderMessageBuffer(Capacity, current);
     this.Owner = current;
 }
Exemple #4
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;
            }
        }
Exemple #5
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;
        }
 public VBinderMessage(Thread from, Thread target, int label, ByteBufferRef payload, int length)
 {
     Contract.Ensures(GhostTarget == target);
     this.from = from;
     this.label = label;
     this.payload = payload;
     this.GhostTarget = target;
     this.Length = length;
 }
        internal VBinderMessageBuffer(uint capacity, Thread owner)
        {
            Contract.Requires(capacity > 0);
            Contract.Ensures(GhostOwner == owner);

            this.data = new VBinderMessage[capacity];
            this.first = 0;
            this.len = 0;
            this.GhostOwner = owner;
        }
Exemple #8
0
        private static int AcquireChannel(Thread current, int tid, int label)
        {
            var cap = Globals.CapabilityManager.Find(current, tid, label);

            if (cap == null)
                return -ErrorCode.EPERM;

            var id = current.VBinderState.MapInCapability(current, cap);

            return id;
        }
        internal BinderIPCMarshaler(Thread current, ByteBufferRef buf)
        {
            Contract.Requires(buf.Length >= kPatchTableSize * sizeof(int));

            this.buf = buf;
            this.ReadCursor = 0;
            this.WriteCursor = 0;
            this.current = current;
            this.patchTable = new int[kPatchTableSize];
            this.CurrentPatchEntry = 0;
        }
Exemple #10
0
        public static bool IsSecureFS(Thread current, byte[] filename)
        {
            if (Util.ByteStringCompare(current.Parent.SFSFilePrefix, filename) != 0)
                return false;

            Globals.LinuxIPCBuffer.CopyFrom(0, filename);
            var ret = Arch.IPCStubs.linux_sys_stat64(current.Parent.helperPid);
            if (ret == 0 && FileSystem.StatIsDir(Globals.LinuxIPCBuffer))
                return false;

            return true;
        }
Exemple #11
0
        private static void HandleAsyncCall(Thread target, VBinderMessage msg)
        {
            var entry = target.VBinderState.Completion;

            var length = msg.Length;
            entry.ptr_label.Write(target.Parent, msg.label);
            entry.userBuf.Write(target, new Pointer(msg.payload.Location), length);
            msg.Recycle();

            target.VBinderState.Completion = null;
            target.ReturnFromCompletion(length);
        }
        public CapabilityRef Find(Thread current, int cap_idx)
        {
            var ref_chain = current.VBinderState.Capabilities.Next;
            while (ref_chain != null)
            {

                if (ref_chain.id == cap_idx)
                    return ref_chain;

                ref_chain = ref_chain.Next;
            }
            return null;
        }
Exemple #13
0
        public static int Close(Thread current, int fd)
        {
            var proc = current.Parent;
            var file = proc.LookupFile(fd);

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

            // post-condition of LookupFile
            Contract.Assume(proc.IsValidFd(fd));
            proc.UninstallFd(fd);

            int ret = file.Close();
            return ret;
        }
Exemple #14
0
        private static int CreateChannel(Thread current, int label, int permission)
        {
            Contract.Requires(current != null && current.VBinderState.Owner == current);

            var has_permission = Globals.SecurityManager.CanCreateVBinderChannel(current, label, permission);
            if (!has_permission)
                return -ErrorCode.EPERM;

            var cap = Globals.CapabilityManager.Create(current, label, permission);

            Contract.Assert(has_permission);

            var id = current.VBinderState.MapInCapability(current, cap);

            return id;
        }
Exemple #15
0
        internal static OpenFileCompletion OpenAndReadPagesAsync(Thread current, byte[] filename, int flags, int mode)
        {
            Contract.Requires(filename.Length < READ_AHEAD_PAGES * Arch.ArchDefinition.PageSize);
            Utils.Assert(filename[filename.Length - 1] == 0);

            var size = READ_AHEAD_PAGES * Arch.ArchDefinition.PageSize;

            var buf = Globals.AllocateAlignedCompletionBuffer(size);
            if (!buf.isValid)
                return null;

            buf.CopyFrom(0, filename);

            var completion = new OpenFileCompletion(current, GenericINode.INodeKind.SecureFSINodeKind, buf, flags, mode);
            Arch.IPCStubs.OpenAndReadPagesAsync(current.Parent.helperPid, current.impl._value.thread._value, new Pointer(completion.buf.Location), buf.Length / Arch.ArchDefinition.PageSize, flags, mode);
            return completion;
        }
Exemple #16
0
        public static int Dispatch(Thread current, ref Arch.ExceptionRegisters regs, int cmd, int arg1, int arg2, int arg3)
        {
            Contract.Requires(current != null && current.VBinderState.Owner == current);
            switch (cmd)
            {
                case VBINDER_REGISTER_CHANNEL:
                    return CreateChannel(current, arg1, arg2);
                case VBINDER_ACQUIRE_CHANNEL:
                    return AcquireChannel(current, arg1, arg2);
                case VBINDER_SEND:
                    return Send(current, arg1, new UserPtr(arg2), (uint)arg3);
                case VBINDER_RECV:
                    return Recv(current, ref regs, new UserPtr(arg1), new UserPtr(arg2), (uint)arg3);
            }

            return -ErrorCode.ENOSYS;
        }
        public int MapInCapability(Thread current, Capability cap)
        {
            int id;
            if (cap.parent == current)
            {
                id = cap.Uses.id;
                cap.Uses.InsertAfter(Capabilities);
            }
            else
            {
                id = NewCapAllocId();
                var cap_ref = new CapabilityRef(current, id, cap);
                cap_ref.InsertAfter(Capabilities);
            }

            return id;
        }
        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;
        }
Exemple #19
0
        internal int Lseek(Thread current, int offset, int origin)
        {
            Contract.Requires(GhostOwner == current.Parent);
            long new_pos = 0;
            switch (origin)
            {
                case FileSystem.SEEK_CUR:
                    new_pos = position + offset;
                    break;

                case FileSystem.SEEK_SET:
                    new_pos = offset;
                    break;

                case FileSystem.SEEK_END:
                    new_pos = inode.Size + offset;
                    break;

                default:
                    return -ErrorCode.EINVAL;
            }

            if (new_pos > inode.Size)
            {
                if (origin == FileSystem.SEEK_SET)
                {
                    inode.Size = (uint)new_pos;
                }
                new_pos = inode.Size;
            }
            else
            if (new_pos < 0)
            {
                new_pos = 0;
            }
            position = (uint)new_pos;
            return (int)new_pos;
        }
        /*
         * Testing whether the current process is getting the focus.
         *
         * See frameworks/base/core/java/android/view/IWindow.aidl and
         * frameworks/base/services/java/com/android/server/WindowManagerService.java
         * for more details.
         */
        private static bool GainingWindowFocus(Thread current, binder_transaction_data tr)
        {
            const int OP_windowFocusChanged = 5;
            if (tr.code != OP_windowFocusChanged || tr.data_size != 0x3c)
                return false;

            var buf = InspectionBuffer;
            tr.data_buffer.Read(current, buf, buf.Length);

            bool header_matched = true;
            for (var i = 0; i < WindowFocusChangedHeader.Length && header_matched; ++i)
            {
                if (buf[i] != WindowFocusChangedHeader[i])
                    header_matched = false;
            }

            if (!header_matched)
                return false;

            int get_focus;
            (tr.data_buffer + WindowFocusChangedHeader.Length).Read(current, out get_focus);
            return get_focus == 1;
        }
Exemple #21
0
 public static int Stat64(Thread current, UserPtr filenamePtr, UserPtr buf)
 {
     return StatAt64(current, filenamePtr, buf, true);
 }
Exemple #22
0
        public static int Dup(Thread current, int old_fd)
        {
            var proc = current.Parent;
            var file = proc.LookupFile(old_fd);
            if (file == null)
                return -ErrorCode.EBADF;

            int new_fd = proc.GetUnusedFd();
            proc.InstallFd(new_fd, file);
            file.inode.IncreaseRefCount();

            return new_fd;
        }
Exemple #23
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;
        }
Exemple #24
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;
        }
Exemple #25
0
        public static int Write(Thread current, ref Arch.ExceptionRegisters regs, int fd, UserPtr userBuf, int len)
        {
            if (len == 0)
                return 0;

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

            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;

            int ret = file.Write(current, ref regs, userBuf, len);
            return ret;
        }
Exemple #26
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;
        }
Exemple #27
0
        public static int Open(Thread current, ref Arch.ExceptionRegisters regs, UserPtr filenamePtr, int flags, int mode)
        {
            // TODO: Deal with current path
            var filenameBuf = new byte[PATH_MAX];
            var ret = filenamePtr.ReadString(current, filenameBuf);

            var proc = current.Parent;
            int fd = 0;
            GenericINode inode = null;

            var startTime = Arch.NativeMethods.l4api_get_system_clock();

            if (Util.ByteStringCompare(filenameBuf, IPCFilename.GetByteString()) == 0)
            {
                fd = proc.GetUnusedFd();
                inode = BinderINode.Instance;
            }
            else if (Util.ByteStringCompare(filenameBuf, AshmemFileName.GetByteString()) == 0)
            {
                var linux_fd = Arch.ArchFS.OpenAndReturnLinuxFd(current.Parent.helperPid, new ASCIIString(filenameBuf), flags, mode);
                if (linux_fd < 0)
                    return linux_fd;

                inode = new AshmemINode(linux_fd, current.Parent.helperPid);
                fd = proc.GetUnusedFd();
            }
            else if (SecureFS.IsSecureFS(current, filenameBuf))
            {
                var completion = SecureFS.OpenAndReadPagesAsync(current, filenameBuf, flags, mode);
                if (completion == null)
                    return -ErrorCode.ENOMEM;

                Globals.CompletionQueue.Enqueue(completion);
                current.SaveState(ref regs);
                current.AsyncReturn = true;
                return 0;
            }
            else
            {
                var filename_len = ret;

                var completion = Arch.ArchFS.OpenAndGetSizeAsync(current, filenameBuf, flags, mode);
                if (completion == null)
                    return -ErrorCode.ENOMEM;

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

            if (fd > 0)
            {
                var file = new File(proc, inode, flags, mode);
                proc.InstallFd(fd, file);
            }

            if (SyscallProfiler.Enable)
            {
                var endTime = Arch.NativeMethods.l4api_get_system_clock();
                SyscallProfiler.AccountOpen((int)inode.kind, (long)(endTime - startTime));
            }

            return fd;
        }
Exemple #28
0
        public static int Lseek(Thread current, int fd, int offset, int origin)
        {
            var proc = current.Parent;
            var file = proc.LookupFile(fd);
            if (file == null)
                return -ErrorCode.EINVAL;

            int ret = file.Lseek(current, offset, origin);
            return ret;
        }
Exemple #29
0
 public static int Mkdir(Thread current, UserPtr pathname, int mode)
 {
     pathname.ReadString(current, Globals.LinuxIPCBuffer);
     return Arch.IPCStubs.Mkdir(current.Parent.helperPid, mode);
 }
Exemple #30
0
 public static int Unlink(Thread current, UserPtr pathname)
 {
     pathname.ReadString(current, Globals.LinuxIPCBuffer);
     return Arch.IPCStubs.Unlink(current.Parent.helperPid);
 }