Exemple #1
0
/* initialize ethread */
void ethread_init(struct ethread *thread, struct eprocess *process, struct task_struct *tsk)
{
	ktrace("\n");

	/* attach to the containing process */
	ref_object((PVOID)process);
	write_lock(&process->ep_lock);
	thread->threads_process = process;
	write_unlock(&process->ep_lock);

	/* FIXME create a thread object and hook in to the Linux task */
	thread->et_task = tsk;

	atomic_set(&thread->et_count, 0);

	/* FIXME */
	thread->et_ops = (struct ethread_operations *)&ethread_ops;

	INIT_LIST_HEAD(&thread->lpc_reply_chain);
	INIT_LIST_HEAD(&thread->irp_list);
	INIT_LIST_HEAD(&thread->active_timer_list_head);
	thread->active_timer_list_lock = SPIN_LOCK_UNLOCKED;
	thread->thread_lock = SPIN_LOCK_UNLOCKED;

	/* FIXME: semaphore_init */

	thread->cid.unique_process = process->unique_processid;

	thread->win32_start_address = 0;        /* context->Eax, default is 0 */
	lock_process(process);
	list_add_tail(&thread->thread_list_entry, &process->thread_list_head);
	unlock_process(process);

	add_ethread(thread->et_task, thread);
	if (atomic_read(&thread->et_count) == 1)	/* FIXME: add this to win32_thread.c */
		ref_object(thread);

	kthread_init(&thread->tcb, process);
} /* end ethread_init */
Exemple #2
0
PACCESS_TOKEN
ref_impersonation_token(IN struct ethread *Thread,
		OUT PBOOLEAN CopyOnOpen,
		OUT PBOOLEAN EffectiveOnly,
		OUT PSECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
{

	if (Thread->active_impersonation_info == FALSE) 
		return NULL;

	*ImpersonationLevel = Thread->impersonation_info->impersonation_level;
	*CopyOnOpen = Thread->impersonation_info->copy_on_open;
	*EffectiveOnly = Thread->impersonation_info->effective_only;

	ref_object(Thread->impersonation_info->token);

	return Thread->impersonation_info->token;
}
Exemple #3
0
NTSTATUS
open_process_token(HANDLE ProcessHandle, 
		PACCESS_TOKEN *Token)
{
	struct eprocess *process;
	NTSTATUS status;

	status = ref_object_by_handle(ProcessHandle, 
			PROCESS_QUERY_INFORMATION, /* TODO */
			process_object_type,
			get_pre_mode(), 
			(PVOID *)&process, 
			NULL);

	if (NT_SUCCESS(status)) {
		ref_object(&process->token);
		*Token = process->token.object;
		deref_object(process);
	}
	return status;
}
Exemple #4
0
/*-------------------------------------------------------------------------*/
svalue_t *
v_tls_init_connection (svalue_t *sp, int num_arg)

/* EFUN tls_init_connection()
 *
 *   int tls_init_connection(object ob)
 *   int tls_init_connection(object ob, string fun, string|object fob, mixed extra...)
 *   int tls_init_connection(object ob, closure fun, mixed extra...)
 *
 * tls_init_connection() tries to start a TLS secured connection to the
 * interactive object <ob> (or this_object() if <ob> is not given).
 * Result:
 *   errorcode < 0: unsuccessful, use tls_error() to get an useful
 *                  description of the error
 *      number > 0: the secure connection is still being set up in the
 *                   background
 *     number == 0: the secure connection is active.
 *
 * If the callback <fun>/<fun>:<fob> is specified, it will be called once
 * the fate of the secure connection has been determined. The first argument
 * will be the return code from the handshake (errorcode < 0 on failure,
 * or 0 on success), followed by the interactive object <ob> and any <extra>
 * arguments.
 */

{
    svalue_t * argp = sp - num_arg + 1;
    long ret;
    object_t * obj;
    interactive_t *ip;

    if (!tls_available())
        errorf("tls_init_connection(): TLS layer hasn't been initialized.\n");

    if (num_arg > 0)
    {
        obj = argp->u.ob;
        put_number(argp, 0); /* remove obj reference from the stack */
    }
    else
    {
        obj = ref_object(current_object, "tls_init_connection");
    }

    if (!O_SET_INTERACTIVE(ip, obj))
    {
        free_object(obj, "tls_init_connection");
        errorf("Bad arg 1 to tls_init_connection(): "
              "object not interactive.\n");
    }

    free_object(obj, "tls_init_connection");
      /* ip has another reference to obj, so this is safe to do */

    if (ip->tls_status != TLS_INACTIVE)
        errorf("tls_init_connection(): Interactive already has a secure "
              "connection.\n");

    /* Extract the callback information from the stack */
    if (num_arg > 1)
    {
        /* Extract the callback information from the stack */
        int error_index;
        callback_t * cb;

        inter_sp = sp;

        memsafe(cb = xalloc(sizeof *cb) , sizeof *cb , "callback structure");

        assign_eval_cost();

        error_index = setup_efun_callback(cb, argp+1, num_arg-1);

        if (error_index >= 0)
        {
            /* The callback values have already been removed. */
            
            xfree(cb);
            inter_sp = sp = argp;
            vefun_bad_arg(error_index+2, argp);
            /* NOTREACHED */
            return argp;
        }

        /* Callback creation successful */
        ip->tls_cb = cb;

    }

    inter_sp = sp = argp - 1;

    /* Flush the connection */

    {
        object_t * save_c_g = command_giver;
        command_giver = obj;
        add_message(message_flush);
        command_giver = save_c_g;
    }

    ret = tls_init_connection(ip);
    if (ret >= 0)
    {
        ip->tls_status = TLS_HANDSHAKING;
        ret = tls_continue_handshake(ip);

        /* Adjust the return value of tls_continue_handshake() */
        if (ret >= 0)
            ret = !ret;
    }

    push_number(sp, ret);
    return sp;
} /* f_tls_init_connection() */
Exemple #5
0
/*
 * open a section object, maybe creating if non-existent
 */
NTSTATUS SERVICECALL
NtCreateSection(
		OUT PHANDLE  SectionHandle,
		IN ACCESS_MASK  DesiredAccess,
		IN POBJECT_ATTRIBUTES  ObjectAttributes OPTIONAL,
		IN PLARGE_INTEGER  MaximumSize OPTIONAL,
		IN ULONG  Protect,
		IN ULONG  AllocationAttributes,
		IN HANDLE  FileHandle OPTIONAL
		)
{
	HANDLE	hSection;
	size_t	size = 0;
	struct win32_file	*wfile = NULL;
	struct win32_section	*section;
	struct ethread	*thread;
	POBJECT_ATTRIBUTES	obj_attr = NULL;
	LARGE_INTEGER	max_size;
	NTSTATUS	Status;
	MODE	previous_mode;

	ktrace("()\n");
	if (!(thread = get_current_ethread()))
		return STATUS_UNSUCCESSFUL;

	/* FIXME */
	previous_mode = (unsigned long)ObjectAttributes > TASK_SIZE ? KernelMode : UserMode;

	if (ObjectAttributes) {
		if (previous_mode == UserMode) {
			if (copy_object_attr_from_user(ObjectAttributes, &obj_attr))
				return STATUS_NO_MEMORY;
		}
		else
			obj_attr = ObjectAttributes;
	}
	
	if (obj_attr && obj_attr->RootDirectory)
		obj_attr->RootDirectory = base_dir_handle;

	if (MaximumSize) {
		if (previous_mode == UserMode) {
			Status = STATUS_NO_MEMORY;
			if (copy_from_user(&max_size, MaximumSize, sizeof(max_size)))
				goto cleanup_object_attr;
			MaximumSize = &max_size;
		}
		Status = STATUS_INVALID_PARAMETER;
		if (MaximumSize->u.HighPart)
			goto cleanup_object_attr;
		size = MaximumSize->u.LowPart;
	}

	/* gain access to the file */
	if (FileHandle) {
		Status = ref_object_by_handle(
				FileHandle,
				DesiredAccess,
				file_object_type,
				KernelMode,
				(PVOID *)&wfile,
				NULL
				);
		if (!NT_SUCCESS(Status))
			goto cleanup_object_attr;
	}
	
	/* create a section object */
	Status = create_object(
			KernelMode,
			section_object_type,
			obj_attr,
			KernelMode,
			NULL,
			sizeof(struct win32_section),
			0,
			0,
			(PVOID *)&section
		      );
	if (Status)
		goto cleanup_wfile;

	Status = insert_object(
			(PVOID)section,
			NULL,
			0,
			0,
			NULL,
			&hSection
			);
	if (Status == STATUS_OBJECT_NAME_EXISTS) {
		deref_object(section);
		goto section_exists;
	}

	deref_object(section);
	if (Status)
		goto cleanup_wfile;

	/* setup section */
	if (wfile)
		ref_object(wfile);
	section->ws_wfile = wfile;	/* attach file */
	section->ws_len = size;

	section->ws_flags = 0;
	section->ws_alloctype = AllocationAttributes;
	if (AllocationAttributes & _SEC_IMAGE) {
		if (!wfile || image_section_setup(section) < 0) {
			Status = STATUS_NO_SUCH_FILE;
			goto cleanup_handle;
		}
	}
	else {
		if ((Protect & PAGE_PROT_MASK) != Protect || !(Protect & PAGE_PROT_MASK)) {
			Status = STATUS_INVALID_PAGE_PROTECTION;
			kdebug("FIXME: some protect not implemention! Protect %x\n", Protect);
			goto cleanup_handle;
		}

		section->ws_protect = prot_to_linux(Protect);

		/* anonymous map, map len is need */
		if (!wfile && !section->ws_len) {
			Status = STATUS_NOT_MAPPED_VIEW;
			goto cleanup_handle;
		}
		if (!wfile && (!obj_attr->ObjectName || !obj_attr->ObjectName->Length)) {
			Status = STATUS_OBJECT_NAME_INVALID;
			goto cleanup_handle;
		}

		if (!wfile && (AllocationAttributes & _SEC_RESERVE))
			section->ws_flags |= MAP_RESERVE;

		if ((Protect & _PAGE_WRITECOPY) || (Protect & _PAGE_EXECUTE_WRITECOPY))
			/* copy on write */
			section->ws_flags |= MAP_PRIVATE;
		else
			/* shared map */
			section->ws_flags |= MAP_SHARED;

		/* get the file size, when paramter len is 0 */
		if (!section->ws_len && wfile)
			section->ws_len = wfile->wf_file->f_dentry->d_inode->i_size;
		section->ws_pagelen = PAGE_ALIGN(section->ws_len);

		/* TODO
		if (section->ws_len < wfile->wf_file->f_dentry->d_inode->i_size)
			grow_file(wfile);
		*/

		if (data_section_setup(section) < 0) {
			Status = STATUS_NOT_MAPPED_VIEW;
			goto cleanup_handle;
		}
	}

	Status = STATUS_SUCCESS;

section_exists:
	if (previous_mode == UserMode) {
		if (copy_to_user(SectionHandle, &hSection, sizeof(hSection))) {
			Status = STATUS_INVALID_ADDRESS;
			goto cleanup_handle;
		}
	}
	else
		*SectionHandle = hSection;

	goto cleanup_wfile;

cleanup_handle:
	NtClose(hSection);
cleanup_wfile:
	if (wfile)
		deref_object((PVOID)wfile);
cleanup_object_attr:
	if (obj_attr && previous_mode == UserMode)
		kfree(obj_attr);

	return Status;
} /* end NtCreateSection() */
Exemple #6
0
/*
 * map a view of the section to the process's address space
 */
NTSTATUS
SERVICECALL
NtMapViewOfSection(
		IN HANDLE  SectionHandle,
		IN HANDLE  ProcessHandle,
		IN OUT PVOID  *BaseAddress,
		IN ULONG  ZeroBits,
		IN ULONG  CommitSize,
		IN OUT PLARGE_INTEGER  SectionOffset  OPTIONAL,
		IN OUT PSIZE_T  ViewSize,
		IN SECTION_INHERIT  InheritDisposition,
		IN ULONG  AllocationType,
		IN ULONG  Protect
		)
{
	NTSTATUS	Status;
	size_t		size = 0;
	MODE		previous_mode;
	unsigned long	addr = 0L;
	struct win32_section	*section;
	struct ethread	*thread;
	struct eprocess *process;
	LARGE_INTEGER	sec_off = { .QuadPart = 0LL };

	ktrace("\n");
	if (!(thread = get_current_ethread()))
		return STATUS_UNSUCCESSFUL;

	/* FIXME */
	previous_mode = (unsigned long)BaseAddress > TASK_SIZE ? KernelMode : UserMode;

	if (!BaseAddress)
		return STATUS_INVALID_PARAMETER;
	if (!ViewSize)
		return STATUS_INVALID_PARAMETER;

	if (previous_mode == UserMode) {
		if (copy_from_user(&addr, BaseAddress, sizeof(PVOID)))
			return STATUS_INVALID_ADDRESS;
		if (copy_from_user(&size, ViewSize, sizeof(size)))
			return STATUS_INVALID_ADDRESS;
		if (SectionOffset && copy_from_user(&sec_off, SectionOffset, sizeof(sec_off)))
			return STATUS_INVALID_ADDRESS;
	}
	else {
		addr = (unsigned long)*BaseAddress;
		size = (size_t)*ViewSize;
		if (SectionOffset)
			sec_off = *SectionOffset;
	}

	if (addr > WIN32_TASK_SIZE || size > WIN32_TASK_SIZE)
		return STATUS_INVALID_PARAMETER;

	/* TODO: not support 64bit offset */
	if (sec_off.u.HighPart)
		return STATUS_INVALID_PARAMETER;

	/* access the section object */
	Status = ref_object_by_handle(
			SectionHandle,
			SECTION_ALL_ACCESS,
			section_object_type,
			KernelMode,
			(PVOID *)&section,
			NULL
			);
	if (Status)
		return Status;
	
	if (!ProcessHandle || ProcessHandle == NtCurrentProcess()) {
		process = thread->threads_process;
		ref_object((PVOID)process);
	}
	else {
		Status = ref_object_by_handle(
				ProcessHandle,
				PROCESS_ALL_ACCESS,
				process_object_type,
				KernelMode,
				(PVOID *)&process,
				NULL
				);
		if (Status)
			goto cleanup_section;
	}
	
	Status = map_section_view(
			(PVOID)section,
			process,
			(PVOID *)&addr,
			ZeroBits,
			CommitSize,
			SectionOffset ? (PLARGE_INTEGER)&sec_off : NULL,
			(PSIZE_T)&size,
			InheritDisposition,
			AllocationType,
			Protect
			);

	if (!NT_SUCCESS(Status))
		goto cleanup_process;

	Status = STATUS_INVALID_ADDRESS;
	if (previous_mode == UserMode) {
		if (copy_to_user(BaseAddress, &addr, sizeof(PVOID)))
			goto cleanup_process;
		if (copy_to_user(ViewSize, &size, sizeof(PVOID)))
			goto cleanup_process;
	}
	else {
		*BaseAddress = (PVOID)addr;
		*ViewSize = size;
	}

	Status = STATUS_SUCCESS;

cleanup_process:
	deref_object(process);

cleanup_section:
	deref_object(section);

	return Status;
} /* end NtMapViewOfSection() */
EXPORT_SYMBOL(NtMapViewOfSection);

/*
 * unmap a mapped view of the file
 * - the view must start _exactly_ on the address
 */
NTSTATUS SERVICECALL
NtUnmapViewOfSection(
		IN HANDLE  ProcessHandle,
		IN PVOID  BaseAddress
		)
{
	struct mm_struct	*mm;
	struct eprocess	*process;
	struct ethread	*thread;
	NTSTATUS	ret;

	ktrace("\n");
	if (!ProcessHandle || ProcessHandle == NtCurrentProcess()) {
		mm = current->mm;
		process = get_current_eprocess();
		ref_object((PVOID)process);
	} else {
		ret = ref_object_by_handle(
				ProcessHandle,
				PROCESS_ALL_ACCESS,
				process_object_type,
				KernelMode,
				(PVOID *)&process,
				NULL
				);
		if (!NT_SUCCESS(ret))
			return ret;
		thread = get_first_thread(process);
		if (!thread) {
			ret = STATUS_THREAD_NOT_IN_PROCESS;
			goto out;
		}
		mm = thread->et_task->mm;
	}

	ret = unmap_section_view(process, mm, (unsigned long)BaseAddress);

out:
	deref_object(process);
	return ret;
} /* NtUnmapViewOfSection() */
EXPORT_SYMBOL(NtUnmapViewOfSection);

NTSTATUS SERVICECALL
NtOpenSection(PHANDLE   SectionHandle,
		ACCESS_MASK  DesiredAccess,
		POBJECT_ATTRIBUTES ObjectAttributes)
{
	HANDLE hSection;
	POBJECT_ATTRIBUTES obj_attr = NULL;
	MODE previous_mode;
	NTSTATUS Status = STATUS_SUCCESS;

	ktrace("\n");
	previous_mode = (unsigned long)ObjectAttributes > TASK_SIZE ? KernelMode : UserMode;
	if (ObjectAttributes) {
		if (previous_mode == UserMode) {
			if (copy_object_attr_from_user(ObjectAttributes, &obj_attr))
				return STATUS_NO_MEMORY;
		}
		else 
			obj_attr = ObjectAttributes;
	}

	if (obj_attr && obj_attr->RootDirectory)
		obj_attr->RootDirectory = base_dir_handle;

	Status = open_object_by_name(obj_attr,
			section_object_type,
			NULL,
			KernelMode,
			DesiredAccess,
			NULL,
			&hSection);

	if (!NT_SUCCESS(Status))
		goto cleanup;

	if (previous_mode == UserMode) {
		if (copy_to_user(SectionHandle, &hSection, sizeof(HANDLE))) {
			Status = STATUS_INVALID_ADDRESS;
			goto cleanup;
		}
	}
	else 
		*SectionHandle = hSection;

cleanup:
	if (obj_attr && previous_mode == UserMode)
		kfree(obj_attr);
	return Status;
} /* end NtOpenSection */ 
Exemple #7
0
NTSTATUS
STDCALL
create_thread(OUT PHANDLE ThreadHandle,
		IN ACCESS_MASK DesiredAccess,
		IN POBJECT_ATTRIBUTES ObjectAttributes  OPTIONAL,
		IN HANDLE ProcessHandle,
		IN struct eprocess* TargetProcess,   			/* FIXME */
		OUT PCLIENT_ID ClientId,
		IN PCONTEXT ThreadContext,
		IN PINITIAL_TEB InitialTeb,
		IN BOOLEAN CreateSuspended,
		IN PKSTART_ROUTINE StartRoutine OPTIONAL,   	/* FIXME */
		IN PVOID StartContext OPTIONAL)            	/* FIXME */
{
	struct eprocess * process;
	struct ethread * thread, *first_thread, *cur_thread;
	struct task_struct *new_tsk = NULL;
	unsigned clone_flags = 0;
	PTEB teb_base;
	long   cpid;
	HANDLE hthread;
	NTSTATUS status = STATUS_SUCCESS;

	ktrace("\n");

	if (!(cur_thread = get_current_ethread())) {
		return STATUS_INVALID_PARAMETER;
	}

	/* current still be regarded */
	if (ProcessHandle && ProcessHandle != NtCurrentProcess()) {
		status = ref_object_by_handle(ProcessHandle,
				PROCESS_ALL_ACCESS,
				process_object_type,
				KernelMode,
				(PVOID *)&process,
				NULL);
		if (!NT_SUCCESS(status))
			return status;
	} else {
		if (TargetProcess)
			process = (struct eprocess *)TargetProcess;
		else
			process = cur_thread->threads_process;
		ref_object(process);
	}

	if (!process->fork_in_progress) {
		/* second and after */
		if (!ProcessHandle || ProcessHandle == NtCurrentProcess())
			first_thread = cur_thread;
		else
			first_thread = get_first_thread(process);
		if (!first_thread) {
			status = STATUS_INVALID_PARAMETER;
			goto cleanup_process;
		}
		
		clone_flags = SIGCHLD | CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_PARENT | CLONE_THREAD;

		cpid = do_fork_from_task(first_thread->et_task, CREATE_THREAD, clone_flags,
				first_thread->tcb.trap_frame->esp, (struct pt_regs *)first_thread->tcb.trap_frame,
			       	0, NULL, NULL);
		if (cpid < 0) {
			status = STATUS_INVALID_PARAMETER;
			goto cleanup_process;
		}

		new_tsk = find_task_by_vpid(cpid);
		
		memset(&new_tsk->thread.tls_array, 0, sizeof(new_tsk->thread.tls_array));
		set_tls_array(&new_tsk->thread, first_thread->et_task->thread.gs >> 3, 
				(unsigned long)InitialTeb->StackBase + 0x800, 0xfffff);

		/* allocate a Win32 thread object */
		status = create_object(KernelMode,
				thread_object_type,
				ObjectAttributes,
				KernelMode,
				NULL,
				sizeof(struct ethread),
				0,
				0,
				(PVOID *)&thread);
		if (!NT_SUCCESS(status))
			goto cleanup_tsk;

		ethread_init(thread, process, new_tsk);
		deref_object(thread);

	} else {