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); }
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); } }
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); }