예제 #1
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;
        }
예제 #2
0
파일: File.cs 프로젝트: terry2012/expressos
        public File(Process owner, GenericINode inode, int flags, int mode)
        {
            Contract.Ensures(GhostOwner == owner);

            this.inode      = inode;
            this.flags      = flags;
            this.mode       = mode;
            this.position   = 0;
            this.GhostOwner = owner;
            inode.IncreaseRefCount();
        }
예제 #3
0
파일: File.cs 프로젝트: xiaohe27/Tasks
        public File(Process owner, GenericINode inode, int flags, int mode)
        {
            Contract.Ensures(GhostOwner == owner);

            this.inode = inode;
            this.flags = flags;
            this.mode = mode;
            this.position = 0;
            this.GhostOwner = owner;
            inode.IncreaseRefCount();
        }
예제 #4
0
        internal static void HandleOpenFileCompletion(OpenFileCompletion c, int linux_fd, int size)
        {
            var current = c.thr;
            var proc    = current.Parent;

            GenericINode inode = null;
            int          ret   = linux_fd;

            if (ret < 0)
            {
                c.Dispose();
                current.ReturnFromCompletion(ret);
                return;
            }

            switch (c.fileKind)
            {
            case GenericINode.INodeKind.ArchINodeKind:
                inode = new Arch.ArchINode(linux_fd, (uint)size, proc.helperPid);
                break;

            case GenericINode.INodeKind.SecureFSINodeKind:
                inode = SecureFS.HandleOpenFileCompletion(c, linux_fd, size, ref ret);
                break;

            default:
                break;
            }

            if (inode != null)
            {
                var file = new File(proc, inode, c.flags, c.mode);
                ret = proc.GetUnusedFd();
                proc.InstallFd(ret, file);
            }

            c.Dispose();
            current.ReturnFromCompletion(ret);
            return;
        }
예제 #5
0
 private static bool SharedWithLinux(GenericINode inode)
 {
     return inode.kind == GenericINode.INodeKind.BinderSharedINodeKind
         || inode.kind == GenericINode.INodeKind.AshmemINodeKind
         || inode.kind == GenericINode.INodeKind.ScreenBufferINodeKind;
 }
예제 #6
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);
        }
예제 #7
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);
        }
예제 #8
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());
        }
예제 #9
0
 private static bool SharedWithLinux(GenericINode inode)
 {
     return(inode.kind == GenericINode.INodeKind.BinderSharedINodeKind ||
            inode.kind == GenericINode.INodeKind.AshmemINodeKind ||
            inode.kind == GenericINode.INodeKind.ScreenBufferINodeKind);
 }