示例#1
0
文件: scenario.c 项目: coyizumi/cs111
/*
 * Enact a scenario by looping through the four test cases for the scenario,
 * spawning off pairs of processes with the desired credentials, and
 * reporting results to stdout.
 */
static int
enact_scenario(int scenario)
{
    pid_t pid1, pid2;
    char *name, *tracefile;
    int error, desirederror, loop;

    for (loop = 0; loop < LOOP_MAX+1; loop++) {
        /*
         * Spawn the first child, target of the operation.
         */
        pid1 = fork();
        switch (pid1) {
        case -1:
            return (-1);
        case 0:
            /* child */
            error = cred_set(scenarios[scenario].sc_cred2);
            if (error) {
                perror("cred_set");
                return (error);
            }
            /* 200 seconds should be plenty of time. */
            sleep(200);
            exit(0);
        default:
            /* parent */
            break;
        }

        /*
         * XXX
         * This really isn't ideal -- give proc 1 a chance to set
         * its credentials, or we may get spurious errors.  Really,
         * some for of IPC should be used to allow the parent to
         * wait for the first child to be ready before spawning
         * the second child.
         */
        sleep(1);

        /*
         * Spawn the second child, source of the operation.
         */
        pid2 = fork();
        switch (pid2) {
        case -1:
            return (-1);

        case 0:
            /* child */
            error = cred_set(scenarios[scenario].sc_cred1);
            if (error) {
                perror("cred_set");
                return (error);
            }

            /*
             * Initialize errno to zero so as to catch any
             * generated errors.  In each case, perform the
             * operation.  Preserve the error number for later
             * use so it doesn't get stomped on by any I/O.
             * Determine the desired error for the given case
             * by extracting it from the scenario table.
             * Initialize a function name string for output
             * prettiness.
             */
            errno = 0;
            switch (loop) {
            case LOOP_PTRACE:
                error = ptrace(PT_ATTACH, pid1, NULL, 0);
                error = errno;
                name = "ptrace";
                desirederror =
                    scenarios[scenario].sc_canptrace_errno;
                break;
            case LOOP_KTRACE:
                tracefile = mktemp("/tmp/testuid_ktrace.XXXXXX");
                if (tracefile == NULL) {
                    error = errno;
                    perror("mktemp");
                    break;
                }
                error = ktrace(tracefile, KTROP_SET,
                               KTRFAC_SYSCALL, pid1);
                error = errno;
                name = "ktrace";
                desirederror =
                    scenarios[scenario].sc_canktrace_errno;
                unlink(tracefile);
                break;
            case LOOP_SIGHUP:
                error = kill(pid1, SIGHUP);
                error = errno;
                name = "sighup";
                desirederror =
                    scenarios[scenario].sc_cansighup_errno;
                break;
            case LOOP_SIGSEGV:
                error = kill(pid1, SIGSEGV);
                error = errno;
                name = "sigsegv";
                desirederror =
                    scenarios[scenario].sc_cansigsegv_errno;
                break;
            case LOOP_SEE:
                getpriority(PRIO_PROCESS, pid1);
                error = errno;
                name = "see";
                desirederror =
                    scenarios[scenario].sc_cansee_errno;
                break;
            case LOOP_SCHED:
                error = setpriority(PRIO_PROCESS, pid1,
                                    0);
                error = errno;
                name = "sched";
                desirederror =
                    scenarios[scenario].sc_cansched_errno;
                break;
            default:
                name = "broken";
            }

            if (error != desirederror) {
                fprintf(stdout,
                        "[%s].%s: expected %s, got %s\n  ",
                        scenarios[scenario].sc_name, name,
                        errno_to_string(desirederror),
                        errno_to_string(error));
                cred_print(stdout,
                           scenarios[scenario].sc_cred1);
                cred_print(stdout,
                           scenarios[scenario].sc_cred2);
                fprintf(stdout, "\n");
            }

            exit(0);

        default:
            /* parent */
            break;
        }

        error = waitpid(pid2, NULL, 0);
        /*
         * Once pid2 has died, it's safe to kill pid1, if it's still
         * alive.  Mask signal failure in case the test actually
         * killed pid1 (not unlikely: can occur in both signal and
         * ptrace cases).
         */
        kill(pid1, SIGKILL);
        error = waitpid(pid2, NULL, 0);
    }

    return (0);
}
示例#2
0
void KernelStartup::ProcessCommandLine(LPSTR lpCmdLine)
{
	ktrace("Processing arguments\n");

	//some yucky code to process the command line

	list<string> args;
	ParseCommandLine(lpCmdLine, args);

	//default init is /bin/init
	s_InitArguments[0] = "/bin/init";
	for(int i=1; i<s_InitMaxArgs; ++i) {
		s_InitArguments[i] = NULL;
	}
	s_InitCurrentArgs = 1;

	//process the found args
	list<string>::iterator it;
	for(it=args.begin(); it!=args.end(); ++it)
	{
		string a = *it;
		string name,val;

		ktrace("processing: %s\n", a.c_str());

		//split name=value?
		int eq = a.find('=');
		if(eq<0)
		{
			name = a;
			val  = a;
		}
		else
		{
			name = a.substr(0,eq);
			val  = a.substr(eq+1);
		}
		

		//find handler for arg
		int h=0;
		bool handled=false;
		for(; s_ArgumentHandlers[h].arg_name!=NULL; ++h)
		{
			if(name == s_ArgumentHandlers[h].arg_name)
			{
				(*s_ArgumentHandlers[h].handler)(val.c_str());
				handled=true;
				break;
			}
		}
		if(!handled) {
			//Unknown arguments are passed as arguments to init (same as linux kernel does)
			if(s_InitCurrentArgs < s_InitMaxArgs) {
				s_InitArguments[s_InitCurrentArgs] = _strdup(val.c_str());
				s_InitCurrentArgs++;
			}
		}

	}
	ktrace("Finished argument processing\n");


	//we started with debug on
	//turn off now unless a log file was specified
	if(g_pKernelTable->m_hLogFile==NULL)
		g_pKernelTable->m_DebugLevel=0;
}
示例#3
0
/*
 * open a mutex object, creating if non-existent
 */
NTSTATUS
SERVICECALL
NtCreateMutant(OUT PHANDLE MutantHandle,
               IN ACCESS_MASK DesiredAccess,
               IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
               IN BOOLEAN InitialOwner)
{
	HANDLE hMutant;
	struct kmutant* Mutant;
	NTSTATUS Status = STATUS_SUCCESS;
	POBJECT_ATTRIBUTES	obj_attr = NULL;

	ktrace("\n");
	if (ObjectAttributes) {
		if ((ULONG)ObjectAttributes < TASK_SIZE) {
			if (copy_object_attr_from_user(ObjectAttributes, &obj_attr))
				return STATUS_NO_MEMORY;
		}
		else {
			obj_attr = ObjectAttributes;
		}
	}
	
	if (obj_attr) {
		if (obj_attr->RootDirectory)
			obj_attr->RootDirectory = base_dir_handle;
	}

	Status = create_object(KernelMode,
			mutant_object_type,
			obj_attr,
			KernelMode,
			NULL,
			sizeof(struct kmutant),
			0,
			0,
			(PVOID *)&Mutant);

	if (ObjectAttributes && (ULONG)ObjectAttributes < TASK_SIZE)
		kfree(obj_attr);

	if (!NT_SUCCESS(Status))
		return Status;

	mutant_init(Mutant, InitialOwner);

	Status = insert_object((PVOID)Mutant,
			NULL,
			DesiredAccess,
			0,
			NULL,
			&hMutant);

	if (Status == STATUS_OBJECT_NAME_EXISTS) {
		goto mutant_exists;
	}

	if (!NT_SUCCESS(Status))
		return Status;

mutant_exists:
	deref_object(Mutant);

	if (MutantHandle) {
		if ((ULONG)MutantHandle < TASK_SIZE) {
			if (copy_to_user(MutantHandle, &hMutant, sizeof(HANDLE)))
				Status = STATUS_NO_MEMORY;
		}
		else
			*MutantHandle = hMutant;
	}

	return Status;
} /* end NtCreateMutant() */
示例#4
0
void KernelStartup::arg_automount(const char *arg)
{
	s_pszAutoMount = _strdup(arg);
	ktrace("AutoMount: %s\n", s_pszAutoMount);
}
示例#5
0
void KernelStartup::arg_log(const char *arg)
{
	g_pKernelTable->m_hLogFile = CreateFile(arg, GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, 0);
	ktrace("Log File: %s\n", arg);
}
示例#6
0
void KernelStartup::arg_debug(const char *arg)
{
	g_pKernelTable->m_DebugLevel = atoi(arg);
	ktrace("Kernel Debug Level: %d\n", g_pKernelTable->m_DebugLevel);
}
示例#7
0
void KernelStartup::arg_init(const char *arg)
{
	s_InitArguments[0] = _strdup(arg);
	ktrace("Using %s as 'init'\n", arg);
}
示例#8
0
//AutoMount windows drive letters
//make mounts and generate initial /etc/mtab
void KernelStartup::AutoMountDrives()
{
	if(s_pszAutoMount==0)
		s_pszAutoMount = "CDEFGHIJKLMNOPRSTUVWXYZ";

	Path p;

	//files may no exist, if so don't create them
	FILE * fMtab = NULL;
	p.SetUnixPath("/etc/mtab");
	if(GetFileAttributes(p.GetWin32Path())!=INVALID_FILE_ATTRIBUTES)
		fMtab = fopen(p.GetWin32Path(), "wb");

	char drive[] = "X:\\";
	char mnt[] = "/mnt/X";
	char *pMntLetter = &mnt[5]; //the 'X'

	const char *letter = s_pszAutoMount;
	while(*letter)
	{
		drive[0] = *pMntLetter = toupper(*letter);

		//is the drive valid to mount?
		if(GetFileAttributes(drive)!=INVALID_FILE_ATTRIBUTES)
		{
			//try to make the mount directory /mnt/X
			p.SetUnixPath(mnt);
			CreateDirectory(p.GetWin32Path(), NULL);
			if(GetFileAttributes(p.GetWin32Path())&FILE_ATTRIBUTE_DIRECTORY)
			{
				ktrace("automatic drive mount: %s on /mnt/%c\n", drive, *pMntLetter);

				//record the mount
				MountPoint * pMp = MountPoint::Mount(p, drive, new FilesystemKeow(), 0, NULL, 0);

				//update /etc/mtab (because we're not using unix 'mount' which normally does it)
				if(fMtab!=NULL)
				{
					//eg: c:/ /mnt/c keow rw 0 0
					fprintf(fMtab, "%c:\\  /mnt/%c  keow rw 0 0 \x0a", *pMntLetter, *pMntLetter);
				}
			}
		}

		++letter;
	}

	//also want /proc and /dev mounted
	p.SetUnixPath("/proc");
	CreateDirectory(p.GetWin32Path(), NULL);
	if(GetFileAttributes(p.GetWin32Path())&FILE_ATTRIBUTE_DIRECTORY)
	{
		//record the mount
		MountPoint * pMp = MountPoint::Mount(p, "", new FilesystemProc(), 0, NULL, 0);

		//update /etc/mtab
		if(fMtab)
			fprintf(fMtab, "/proc /proc proc rw 0 0 \x0a");
	}
	p.SetUnixPath("/dev");
	CreateDirectory(p.GetWin32Path(), NULL);
	if(GetFileAttributes(p.GetWin32Path())&FILE_ATTRIBUTE_DIRECTORY)
	{
		//record the mount
		MountPoint * pMp = MountPoint::Mount(p, "", new FilesystemDev(), 0, NULL, 0);

		//update /etc/mtab
		if(fMtab)
			fprintf(fMtab, "/dev /dev dev rw 0 0 \x0a");
	}

	//close mtab
	if(fMtab)
		fclose(fMtab);
}
示例#9
0
文件: wait.c 项目: amir9/longene
NTSTATUS SERVICECALL
NtSignalAndWaitForSingleObject(IN HANDLE ObjectHandleToSignal,
		IN HANDLE WaitableObjectHandle,
		IN BOOLEAN Alertable,
		IN PLARGE_INTEGER TimeOut OPTIONAL)
{
	PVOID signal_obj, wait_obj;
	struct dispatcher_header *signal_header;
	LARGE_INTEGER _timeout;
	MODE previous_mode;
	NTSTATUS status;

	ktrace("ObjectHandleToSignal %p, WaitableObjectHandle %p, Alertable %d\n",
			ObjectHandleToSignal, WaitableObjectHandle, Alertable);
	previous_mode = (unsigned long)TimeOut > TASK_SIZE ? KernelMode : UserMode;
	if(TimeOut){
		if (previous_mode == UserMode) {
			if (copy_from_user(&_timeout, TimeOut, sizeof(_timeout)))
				return STATUS_NO_MEMORY;
		} else
			_timeout = *TimeOut;
	}

	status = ref_object_by_handle(ObjectHandleToSignal, 0,
			NULL, KernelMode, &signal_obj, NULL);
	if (!NT_SUCCESS(status))
		return status;

	status = ref_object_by_handle(WaitableObjectHandle, SYNCHRONIZE,
			NULL, KernelMode, &wait_obj, NULL);
	if (!NT_SUCCESS(status)) {
		deref_object(signal_obj);
		return status;
	}

	signal_header = (struct dispatcher_header *)signal_obj;

	if (is_wine_object(signal_header->type)) {
		struct object *obj = (struct object*)signal_obj;
		unsigned int access = get_handle_access(process2eprocess(current_thread->process), WaitableObjectHandle);
		if (BODY_TO_HEADER(obj)->ops->signal)
			BODY_TO_HEADER(obj)->ops->signal(obj, access);
	}
	else
		switch (signal_header->type) {
			case EventNotificationObject:
			case EventSynchronizationObject:
				set_event(signal_obj, EVENT_INCREMENT, TRUE);
				break;

			case MutantObject:
				release_mutant(signal_obj, IO_NO_INCREMENT, FALSE, TRUE);
				break;

			case SemaphoreObject:
				release_semaphore(signal_obj, SEMAPHORE_INCREMENT, 1, TRUE);
				break;

			default:
				deref_object(signal_obj);
				deref_object(wait_obj);
				return STATUS_OBJECT_TYPE_MISMATCH;
		}

	if(TimeOut){
		status = wait_for_single_object(wait_obj,
				UserRequest, KernelMode, Alertable, &_timeout);
	} else {
		status = wait_for_single_object(wait_obj,
				UserRequest, KernelMode, Alertable, NULL);
	}	

	if (!NT_SUCCESS(status))
		goto out;

	if (TimeOut) {
		if (previous_mode == UserMode) {
			if (copy_to_user(TimeOut, &_timeout, sizeof(_timeout))) {
				status = STATUS_NO_MEMORY;
				goto out;
			}
		} else
			*TimeOut = _timeout;
	}

out:
	deref_object(signal_obj);
	deref_object(wait_obj);

	return status;
} /* end NtSignalAndWaitForSingleObject */
示例#10
0
文件: wait.c 项目: amir9/longene
NTSTATUS SERVICECALL
NtWaitForMultipleObjects(IN ULONG ObjectCount,
		IN PHANDLE ObjectsArray,
		IN WAIT_TYPE WaitType,
		IN BOOLEAN Alertable,
		IN PLARGE_INTEGER TimeOut  OPTIONAL)
{
	int i;
	struct kwait_block *wait_block;
	LARGE_INTEGER _timeout;
	NTSTATUS status;
	PVOID object[ObjectCount];
	HANDLE hobj[ObjectCount];
	MODE previous_mode;

	ktrace("%d, %p\n", ObjectCount, *ObjectsArray);
	previous_mode = (unsigned long)ObjectsArray > TASK_SIZE ? KernelMode : UserMode;
	if(TimeOut){
		if (previous_mode == UserMode) {
			if (copy_from_user(&_timeout, TimeOut, sizeof(_timeout)))
				return STATUS_NO_MEMORY;
		} else
			_timeout = *TimeOut;
	}
	if(previous_mode == UserMode) {
		if(copy_from_user(hobj, ObjectsArray, sizeof(HANDLE)*ObjectCount))
			return STATUS_NO_MEMORY;
	} else {
		memcpy(ObjectsArray, hobj, sizeof(HANDLE)*ObjectCount);
	}

	if (ObjectCount == 0) {
		wait_block = (struct kwait_block *)kmalloc(MAXIMUM_WAIT_OBJECTS * sizeof(struct kwait_block), GFP_KERNEL);
		if (!wait_block) {
			status = STATUS_NO_MEMORY;
			goto out;
		}

		status = wait_for_multi_objs(0,
				NULL,
				WaitType,
				UserRequest,
				KernelMode,
				Alertable,
				TimeOut ? &_timeout : NULL,
				wait_block);

		kfree(wait_block);
		return status;
	}

	for (i = 0; i < ObjectCount; i++) {
		status = ref_object_by_handle(hobj[i],
					SYNCHRONIZE,
					NULL,
					KernelMode,
					&object[i],
					NULL);
		if (!NT_SUCCESS(status)) {
			ObjectCount = i;
			goto out;
		}
		if (BODY_TO_HEADER(object[i])->Type == thread_object_type
				&& object[i] == get_current_ethread()) {
			status = STATUS_INVALID_PARAMETER;
			ObjectCount = i + 1;
			goto out;
		}
	}

	wait_block = (struct kwait_block *)kmalloc(MAXIMUM_WAIT_OBJECTS * sizeof(struct kwait_block), GFP_KERNEL);
	if (!wait_block) {
		status = STATUS_NO_MEMORY;
		goto out;
	}

	status = wait_for_multi_objs(ObjectCount,
			object,
			WaitType,
			UserRequest,
			KernelMode,
			Alertable,
			TimeOut ? &_timeout : NULL,
			wait_block);

	kfree(wait_block);

out:
	for (i = 0; i < ObjectCount; i++)
		deref_object(object[i]);

	ktrace("%x\n", status);
	return status;
} /* end NtWaitForMultipleObjects */