예제 #1
0
        private int HandleWriteRead(Thread current, UserPtr userBwr, ref Arch.ExceptionRegisters pt_regs)
        {
            var bwr = new binder_write_read();

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

            if (bwr.write_size > 0 || bwr.read_size > 0)
            {
                var ret = HandleWriteRead(current, ref pt_regs, userBwr, bwr);
                if (ret < 0)
                {
                    bwr.read_consumed = 0;
                    if (userBwr.Write(current, ref bwr) != 0)
                    {
                        return(-ErrorCode.EFAULT);
                    }
                }
            }

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

            return(0);
        }
예제 #2
0
 public VBinderCompletion(Thread current, UserPtr ptr_label, UserPtr userBuf, uint size)
     : base(current, Kind.VBinderCompletionKind)
 {
     this.ptr_label = ptr_label;
     this.userBuf = userBuf;
     this.size = size;
 }
예제 #3
0
 public FutexCompletionEntry(Thread current, UserPtr uaddr, uint bitset)
     : base(current, Kind.FutexCompletionKind)
 {
     this.uaddr       = uaddr;
     this.bitset      = bitset;
     this.timeoutNode = null;
 }
예제 #4
0
 public VBinderCompletion(Thread current, UserPtr ptr_label, UserPtr userBuf, uint size)
     : base(current, Kind.VBinderCompletionKind)
 {
     this.ptr_label = ptr_label;
     this.userBuf   = userBuf;
     this.size      = size;
 }
예제 #5
0
        public void Remove(AddressSpace parent, UserPtr startPage, UserPtr endPage)
        {
            Utils.Assert(Arch.ArchDefinition.PageOffset(startPage.Value.ToUInt32()) == 0);
            Utils.Assert(Arch.ArchDefinition.PageOffset(endPage.Value.ToUInt32()) == 0);

            for (var page = startPage; page < endPage; page += Arch.ArchDefinition.PageSize)
            {
                var directory_index = DirectoryIndex(page);
                var table_index     = TableIndex(page);
                var table           = Directory[directory_index];
                if (table == null)
                {
                    continue;
                }

                if (table[table_index] == Pointer.Zero)
                {
                    continue;
                }

                FreePhysicalPage(table[table_index]);
                table[table_index] = Pointer.Zero;
            }

            Arch.NativeMethods.l4api_flush_regions(parent.impl._value, startPage.Value, endPage.Value, (int)MemoryRegion.FAULT_MASK);
        }
예제 #6
0
 public FutexCompletionEntry(Thread current, UserPtr uaddr, uint bitset)
     : base(current, Kind.FutexCompletionKind)
 {
     this.uaddr = uaddr;
     this.bitset = bitset;
     this.timeoutNode = null;
 }
예제 #7
0
 public IOCompletion(Thread current, Type type, UserPtr userBuf, int len, File file, ByteBufferRef buf)
     : base(current, Kind.IOCompletionKind, buf)
 {
     this.type = type;
     this.userBuf = userBuf;
     this.len = len;
     this.posToUpdate = file;
 }
예제 #8
0
 public IOCompletion(Thread current, Type type, UserPtr userBuf, int len, File file, ByteBufferRef buf)
     : base(current, Kind.IOCompletionKind, buf)
 {
     this.type        = type;
     this.userBuf     = userBuf;
     this.len         = len;
     this.posToUpdate = file;
 }
예제 #9
0
        public void Add(UserPtr userAddress, Pointer virtualAddr)
        {
            Utils.Assert(virtualAddr != Pointer.Zero);
            var directory_index = DirectoryIndex(userAddress);
            var table_index = TableIndex(userAddress);

            var table = GetOrCreateTable(directory_index);

            Utils.Assert(table[table_index] == Pointer.Zero);
            table[table_index] = virtualAddr;
        }
예제 #10
0
        public int ArchFStat64(Thread current, UserPtr buf)
        {
            var ret = IPCStubs.linux_sys_fstat64(current.Parent.helperPid, Fd);
            if (ret < 0)
                return ret;

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

            return 0;
        }
예제 #11
0
        public void Add(UserPtr userAddress, Pointer virtualAddr)
        {
            Utils.Assert(virtualAddr != Pointer.Zero);
            var directory_index = DirectoryIndex(userAddress);
            var table_index     = TableIndex(userAddress);

            var table = GetOrCreateTable(directory_index);

            Utils.Assert(table[table_index] == Pointer.Zero);
            table[table_index] = virtualAddr;
        }
예제 #12
0
        public int ArchFStat64(Thread current, UserPtr buf)
        {
            var ret = IPCStubs.linux_sys_fstat64(current.Parent.helperPid, Fd);

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

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

            return(0);
        }
예제 #13
0
        public Pointer UserToVirt(UserPtr addr)
        {
            var directory_index = DirectoryIndex(addr);

            if (Directory[directory_index] == null)
            {
                return(Pointer.Zero);
            }

            var table_index = TableIndex(addr);
            var virtualAddr = Directory[directory_index][table_index];

            if (virtualAddr == Pointer.Zero)
            {
                return(Pointer.Zero);
            }

            virtualAddr += Arch.ArchDefinition.PageOffset(addr.Value.ToInt32());

            return(virtualAddr);
        }
예제 #14
0
        public void Remove(AddressSpace parent, UserPtr startPage, UserPtr endPage)
        {
            Utils.Assert(Arch.ArchDefinition.PageOffset(startPage.Value.ToUInt32()) == 0);
            Utils.Assert(Arch.ArchDefinition.PageOffset(endPage.Value.ToUInt32()) == 0);

            for (var page = startPage; page < endPage; page += Arch.ArchDefinition.PageSize)
            {
                var directory_index = DirectoryIndex(page);
                var table_index = TableIndex(page);
                var table = Directory[directory_index];
                if (table == null)
                    continue;

                if (table[table_index] == Pointer.Zero)
                    continue;

                FreePhysicalPage(table[table_index]);
                table[table_index] = Pointer.Zero;
            }

            Arch.NativeMethods.l4api_flush_regions(parent.impl._value, startPage.Value, endPage.Value, (int)MemoryRegion.FAULT_MASK);
        }
예제 #15
0
        internal int ArchRead(Thread current, ref ExceptionRegisters regs, UserPtr userBuf, int len, uint pos, File file)
        {
            var buf = Globals.AllocateAlignedCompletionBuffer(len);

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

            var iocp = IOCompletion.CreateReadIOCP(current, userBuf, len, file, buf);

            var r = IPCStubs.ReadAsync(current.Parent.helperPid, current.impl._value.thread._value, new Pointer(buf.Location), fd, len, pos);

            if (r < 0)
            {
                iocp.Dispose();
                return(r);
            }

            Globals.CompletionQueue.Enqueue(iocp);
            current.SaveState(ref regs);
            current.AsyncReturn = true;
            return(0);
        }
예제 #16
0
 internal BinderCompletion(Thread current, UserPtr userBwrBuf, sys_binder_write_desc desc, ByteBufferRef buf)
     : base(current, Kind.BinderCompletionKind, buf)
 {
     this.userBwrBuf = userBwrBuf;
     this.desc = desc;
 }
예제 #17
0
        private int HandleWriteRead(Thread current, ref Arch.ExceptionRegisters regs, UserPtr userBwr, binder_write_read bwr)
        {
            var writeBuf  = bwr.write_buffer;
            var writeSize = bwr.write_size;
            var buf       = Globals.AllocateAlignedCompletionBuffer(MARSHAL_BUF_PAGES * Arch.ArchDefinition.PageSize);

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

            var marshaler = new BinderIPCMarshaler(current, buf);

            if (bwr.write_consumed != 0)
            {
                Arch.Console.WriteLine("BinderINode::HandleWriteRead: write_consumed != 0");
                Utils.Panic();
            }

            var r = marshaler.Marshal(writeBuf, writeSize);

            if (r < 0)
            {
                Arch.Console.WriteLine("Marshaling error");
                Globals.CompletionQueueAllocator.FreePages(new Pointer(buf.Location), MARSHAL_BUF_PAGES);
                return(-1);
            }

            sys_binder_write_desc desc;

            desc.buffer_size         = marshaler.WriteCursor;
            desc.bwr_write_size      = writeSize;
            desc.write_buffer        = new Pointer(buf.Location);
            desc.patch_table_entries = marshaler.CurrentPatchEntry;
            desc.patch_table_offset  = marshaler.PatchTableOffset;
            desc.read_consumed       = 0;
            desc.write_consumed      = 0;

            var binder_cp = new BinderCompletion(current, userBwr, desc, buf);

            r = Arch.IPCStubs.linux_sys_binder_write_read_async(current.Parent.helperPid, current.impl._value.thread._value, desc);

            if (r < 0)
            {
                binder_cp.Dispose();
                return(r);
            }

            Globals.CompletionQueue.Enqueue(binder_cp);
            current.SaveState(ref regs);
            current.AsyncReturn = true;
            return(0);
        }
예제 #18
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;
        }
예제 #19
0
        internal int Ioctl(Thread current, ref Arch.ExceptionRegisters pt_regs, uint cmd, UserPtr userBuf)
        {
            switch (cmd)
            {
            case BINDER_WRITE_READ:
                return(HandleWriteRead(current, userBuf, ref pt_regs));

            case BINDER_VERSION:
                if (userBuf.Write(current, BINDER_CURRENT_PROTOCOL_VERSION) != 0)
                {
                    return(-ErrorCode.EINVAL);
                }

                return(0);

            case BINDER_SET_IDLE_TIMEOUT:
            case BINDER_SET_MAX_THREADS:
            case BINDER_SET_IDLE_PRIORITY:
            case BINDER_SET_CONTEXT_MGR:
            case BINDER_THREAD_EXIT:
                // skipping
                return(0);

            default:
                return(-ErrorCode.EINVAL);
            }
        }
예제 #20
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;
            }
        }
예제 #21
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;
        }
예제 #22
0
 internal static IOCompletion CreateReadIOCP(Thread current, UserPtr userBuf, int len, File file, ByteBufferRef buf)
 {
     return(new IOCompletion(current, Type.Read, userBuf, len, file, buf));
 }
예제 #23
0
 private static int TableIndex(UserPtr addr)
 {
     return (int)((addr.Value.ToUInt32() & PGT_IDX_MASK) >> Arch.ArchDefinition.PageShift);
 }
예제 #24
0
 private static int TableIndex(UserPtr addr)
 {
     return((int)((addr.Value.ToUInt32() & PGT_IDX_MASK) >> Arch.ArchDefinition.PageShift));
 }
예제 #25
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;
        }
예제 #26
0
        private int HandleWriteRead(Thread current, ref Arch.ExceptionRegisters regs, UserPtr userBwr, binder_write_read bwr)
        {
            var writeBuf = bwr.write_buffer;
            var writeSize = bwr.write_size;
            var buf = Globals.AllocateAlignedCompletionBuffer(MARSHAL_BUF_PAGES * Arch.ArchDefinition.PageSize);
            if (!buf.isValid)
                return -ErrorCode.ENOMEM;

            var marshaler = new BinderIPCMarshaler(current, buf);

            if (bwr.write_consumed != 0)
            {
                Arch.Console.WriteLine("BinderINode::HandleWriteRead: write_consumed != 0");
                Utils.Panic();
            }

            var r = marshaler.Marshal(writeBuf, writeSize);
            if (r < 0)
            {
                Arch.Console.WriteLine("Marshaling error");
                Globals.CompletionQueueAllocator.FreePages(new Pointer(buf.Location), MARSHAL_BUF_PAGES);
                return -1;
            }

            sys_binder_write_desc desc;
            desc.buffer_size = marshaler.WriteCursor;
            desc.bwr_write_size = writeSize;
            desc.write_buffer = new Pointer(buf.Location);
            desc.patch_table_entries = marshaler.CurrentPatchEntry;
            desc.patch_table_offset = marshaler.PatchTableOffset;
            desc.read_consumed = 0;
            desc.write_consumed = 0;

            var binder_cp = new BinderCompletion(current, userBwr, desc, buf);

            r = Arch.IPCStubs.linux_sys_binder_write_read_async(current.Parent.helperPid, current.impl._value.thread._value, desc);

            if (r < 0)
            {
                binder_cp.Dispose();
                return r;
            }

            Globals.CompletionQueue.Enqueue(binder_cp);
            current.SaveState(ref regs);
            current.AsyncReturn = true;
            return 0;
        }
예제 #27
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;
 }
예제 #28
0
        internal int ArchRead(Thread current, ref ExceptionRegisters regs, UserPtr userBuf, int len, uint pos, File file)
        {
            var buf = Globals.AllocateAlignedCompletionBuffer(len);

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

            var iocp = IOCompletion.CreateReadIOCP(current, userBuf, len, file, buf);

            var r = IPCStubs.ReadAsync(current.Parent.helperPid, current.impl._value.thread._value, new Pointer(buf.Location), fd, len, pos);

            if (r < 0)
            {
                iocp.Dispose();
                return r;
            }

            Globals.CompletionQueue.Enqueue(iocp);
            current.SaveState(ref regs);
            current.AsyncReturn = true;
            return 0;
        }
예제 #29
0
 internal BinderCompletion(Thread current, UserPtr userBwrBuf, sys_binder_write_desc desc, ByteBufferRef buf)
     : base(current, Kind.BinderCompletionKind, buf)
 {
     this.userBwrBuf = userBwrBuf;
     this.desc       = desc;
 }
예제 #30
0
 private static int DirectoryIndex(UserPtr addr)
 {
     return (int)(addr.Value.ToUInt32() >> (Arch.ArchDefinition.PageShift + PGT_SHIFT));
 }
예제 #31
0
 internal static IOCompletion CreateReadIOCP(Thread current, UserPtr userBuf, int len, File file, ByteBufferRef buf)
 {
     return new IOCompletion(current, Type.Read, userBuf, len, file, buf);
 }
예제 #32
0
        internal int Ioctl(Thread current, ref Arch.ExceptionRegisters pt_regs, uint cmd, UserPtr userBuf)
        {
            switch (cmd)
            {
                case BINDER_WRITE_READ:
                    return HandleWriteRead(current, userBuf, ref pt_regs);

                case BINDER_VERSION:
                    if (userBuf.Write(current, BINDER_CURRENT_PROTOCOL_VERSION) != 0)
                        return -ErrorCode.EINVAL;

                    return 0;

                case BINDER_SET_IDLE_TIMEOUT:
                case BINDER_SET_MAX_THREADS:
                case BINDER_SET_IDLE_PRIORITY:
                case BINDER_SET_CONTEXT_MGR:
                case BINDER_THREAD_EXIT:
                    // skipping
                    return 0;

                default:
                    return -ErrorCode.EINVAL;
            }
        }
예제 #33
0
 private static int DirectoryIndex(UserPtr addr)
 {
     return((int)(addr.Value.ToUInt32() >> (Arch.ArchDefinition.PageShift + PGT_SHIFT)));
 }
예제 #34
0
        public Pointer UserToVirt(UserPtr addr)
        {
            var directory_index = DirectoryIndex(addr);

            if (Directory[directory_index] == null)
                return Pointer.Zero;

            var table_index = TableIndex(addr);
            var virtualAddr = Directory[directory_index][table_index];

            if (virtualAddr == Pointer.Zero)
                return Pointer.Zero;

            virtualAddr += Arch.ArchDefinition.PageOffset(addr.Value.ToInt32());

            return virtualAddr;
        }
예제 #35
0
        private int HandleWriteRead(Thread current, UserPtr userBwr, ref Arch.ExceptionRegisters pt_regs)
        {
            var bwr = new binder_write_read();

            if (userBwr.Read(current, out bwr) != 0)
                return -ErrorCode.EFAULT;

            if (bwr.write_size > 0 || bwr.read_size > 0)
            {
                var ret = HandleWriteRead(current, ref pt_regs, userBwr, bwr);
                if (ret < 0)
                {
                    bwr.read_consumed = 0;
                    if (userBwr.Write(current, ref bwr) != 0)
                        return -ErrorCode.EFAULT;
                }
            }

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

            return 0;
        }