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; }
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; } }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
public static int Stat64(Thread current, UserPtr filenamePtr, UserPtr buf) { return StatAt64(current, filenamePtr, buf, true); }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
public static int Mkdir(Thread current, UserPtr pathname, int mode) { pathname.ReadString(current, Globals.LinuxIPCBuffer); return Arch.IPCStubs.Mkdir(current.Parent.helperPid, mode); }
public static int Unlink(Thread current, UserPtr pathname) { pathname.ReadString(current, Globals.LinuxIPCBuffer); return Arch.IPCStubs.Unlink(current.Parent.helperPid); }