Пример #1
0
/*
 * Mark a selector as available for future reuse.
 */
void NaClLdtDeleteSelector(uint16_t selector) {
  struct user_desc ud;
  ud.entry_number = selector >> 3;
  ud.seg_not_present = 1;
  ud.base_addr = 0;
  ud.limit = 0;
  ud.limit_in_pages = 0;
  ud.read_exec_only = 0;
  ud.seg_32bit = 0;
  ud.useable = 0;
  ud.contents = MODIFY_LDT_CONTENTS_DATA;
  NaClXMutexLock(&nacl_ldt_mutex);
  modify_ldt(1, &ud, sizeof ud);
  NaClXMutexUnlock(&nacl_ldt_mutex);
}
Пример #2
0
/*
 * create_segment() -
 */
int create_segment(void *seg, size_t size)
{
	modify_ldt_s entry;

	entry.entry_number = 0;
	entry.base_addr = (unsigned long)seg;
	entry.limit = size;
	entry.seg_32bit = 1;
	entry.contents = 0;
	entry.read_exec_only = 0;
	entry.limit_in_pages = 0;
	entry.seg_not_present = 0;

	return modify_ldt(1, &entry, sizeof(entry));
}
Пример #3
0
void NaClLdtPrintSelector(uint16_t selector) {
  /* type_name converts the segment type into print name */
  static const char* type_name[] = {
    "data read only",
    "data read_only accessed",
    "data read write",
    "data read write accessed",
    "data read expand",
    "data read expand accessed",
    "data read write expand",
    "data read write expand accessed",
    "code execute",
    "code execute accessed",
    "code execute read",
    "code execute read accessed",
    "code execute conforming",
    "code execute conforming accessed",
    "code execute read conforming",
    "code execute read conforming accessed"
  };

  struct LdtEntry entries[LDT_ENTRIES];
  struct LdtEntry entry;
  int retval = modify_ldt(0, entries, sizeof(entries));
  if (-1 == retval) {
    return;
  }
  entry = entries[selector >> 3];
  printf("DESCRIPTOR for selector %04x\n", selector);
  /* create functions to do base, limit, and type */
  printf("  base        %08x\n", (entry.base_24to31 << 24)
         | (entry.base_16to23 << 16) | entry.base_00to15);
  printf("  limit       %08x%s\n",
         (((entry.limit_16to19 << 16) | entry.limit_00to15)
          << (entry.granularity ? 12 : 0)),
         (entry.granularity ? " (page granularity)" : ""));
  printf("  type        %s, %s\n", ((entry.type & 0x10) ? "user" : "system"),
         type_name[entry.type & 0xf]);
  printf("  privilege   %d\n", entry.descriptor_privilege);
  printf("  present %s\n", (entry.present ? "yes" : "no"));
  printf("  available %s\n", (entry.available ? "yes" : "no"));
  printf("  64-bit code %s\n", (entry.code_64_bit ? "yes" : "no"));
  printf("  op size %s\n", (entry.op_size_32 ? "32" : "16"));
}
Пример #4
0
/*
 * Find a free selector.  Always invoked while holding nacl_ldt_mutex.
 */
static int NaClFindUnusedEntryNumber(void) {
  int size = sizeof(struct LdtEntry) * LDT_ENTRIES;
  struct LdtEntry *entries = malloc(size);
  int i;

  int retval = modify_ldt(0, entries, size);

  if (-1 != retval) {
    retval = -1;  /* In case we don't find any free entry */
    for (i = 0; i < LDT_ENTRIES; ++i) {
      if (!entries[i].present) {
        retval = i;
        break;
      }
    }
  }

  free(entries);
  return retval;
}
Пример #5
0
/*
 * Find and allocate an available selector, inserting an LDT entry with the
 * appropriate permissions.
 */
uint16_t NaClLdtAllocateSelector(int32_t entry_number,
                                 int size_is_in_pages,
                                 NaClLdtDescriptorType type,
                                 int read_exec_only,
                                 void* base_addr,
                                 uint32_t size_minus_one) {
  struct user_desc ud;
  int retval;

  NaClXMutexLock(&nacl_ldt_mutex);

  if (-1 == entry_number) {
    /* -1 means caller did not specify -- allocate */
    entry_number = NaClFindUnusedEntryNumber();

    if (-1 == entry_number) {
      /*
       * No free entries were available.
       */
      goto alloc_error;
    }
  }
  ud.entry_number = entry_number;

  switch (type) {
    case NACL_LDT_DESCRIPTOR_DATA:
      ud.contents = MODIFY_LDT_CONTENTS_DATA;
      break;
    case NACL_LDT_DESCRIPTOR_CODE:
      ud.contents = MODIFY_LDT_CONTENTS_CODE;
      break;
    default:
      goto alloc_error;
  }
  ud.read_exec_only = read_exec_only;
  ud.seg_32bit = 1;
  ud.seg_not_present = 0;
  ud.useable = 1;

  if (size_is_in_pages && ((unsigned long) base_addr & 0xfff)) {
    /*
     * The base address needs to be page aligned.
     */
    goto alloc_error;
  };
  ud.base_addr = (unsigned long) base_addr;

  if (size_minus_one > 0xfffff) {
    /*
     * If size is in pages, no more than 2**20 pages can be protected.
     * If size is in bytes, no more than 2**20 bytes can be protected.
     */
    goto alloc_error;
  }
  ud.limit = size_minus_one;
  ud.limit_in_pages = size_is_in_pages;

  /*
   * Install the LDT entry.
   */
  retval = modify_ldt(1, &ud, sizeof ud);
  if (-1 == retval) {
    goto alloc_error;
  }

  /*
   * Return an LDT selector with a requested privilege level of 3.
   */
  NaClXMutexUnlock(&nacl_ldt_mutex);
  return (ud.entry_number << 3) | 0x7;

  /*
   * All error returns go through this epilog.
   */
 alloc_error:
  NaClXMutexUnlock(&nacl_ldt_mutex);
  return 0;
}
Пример #6
0
int main(int ac, char **av)
{
	int lc;
	const char *msg;

	void *ptr;
	int retval, func;

	int flag;
	int seg[4];

	if ((msg = parse_opts(ac, av, NULL, NULL)) != NULL) {
		tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
	}

	setup();		/* global setup */

	/* The following loop checks looping state if -i option given */
	for (lc = 0; TEST_LOOPING(lc); lc++) {

		/* reset tst_count in case we are looping */
		tst_count = 0;

//block1:
		/*
		 * Check for ENOSYS.
		 */
		tst_resm(TINFO, "Enter block 1");
		flag = 0;
		ptr = (void *)malloc(10);
		func = 100;
		retval = modify_ldt(func, ptr, sizeof(ptr));
		if (retval < 0) {
			if (errno != ENOSYS) {
				tst_resm(TFAIL, "modify_ldt() set invalid "
					 "errno, expected ENOSYS, got: %d",
					 errno);
				flag = FAILED;
			}
		} else {
			tst_resm(TFAIL, "modify_ldt error: "
				 "unexpected return value %d", retval);
			flag = FAILED;
		}

		if (flag) {
			tst_resm(TINFO, "block 1 FAILED");
		} else {
			tst_resm(TINFO, "block 1 PASSED");
		}
		tst_resm(TINFO, "Exit block 1");
		free(ptr);

//block2:
		/*
		 * Check for EINVAL
		 */
		tst_resm(TINFO, "Enter block 2");
		flag = 0;

		ptr = 0;

		retval = modify_ldt(1, ptr, sizeof(ptr));
		if (retval < 0) {
			if (errno != EINVAL) {
				tst_resm(TFAIL, "modify_ldt() set invalid "
					 "errno, expected EINVAL, got: %d",
					 errno);
				flag = FAILED;
			}
		} else {
			tst_resm(TFAIL, "modify_ldt error: "
				 "unexpected return value %d", retval);
			flag = FAILED;
		}

		if (flag) {
			tst_resm(TINFO, "block 2 FAILED");
		} else {
			tst_resm(TINFO, "block 2 PASSED");
		}
		tst_resm(TINFO, "Exit block 2");

//block3:

		/*
		 * Create a new LDT segment.
		 */
		if (create_segment(seg, sizeof(seg)) == -1) {
			tst_brkm(TINFO, cleanup, "Creation of segment failed");
		}

		/*
		 * Check for EFAULT
		 */
		ptr = sbrk(0);

		retval = modify_ldt(0, ptr + 0xFFF, sizeof(ptr));
		if (retval < 0) {
			if (errno != EFAULT) {
				tst_resm(TFAIL, "modify_ldt() set invalid "
					 "errno, expected EFAULT, got: %d",
					 errno);
				flag = FAILED;
			}
		} else {
			tst_resm(TFAIL, "modify_ldt error: "
				 "unexpected return value %d", retval);
			flag = FAILED;
		}

		if (flag) {
			tst_resm(TINFO, "block 3 FAILED");
		} else {
			tst_resm(TINFO, "block 3 PASSED");
		}
		tst_resm(TINFO, "Exit block 3");

	}
	cleanup();
	tst_exit();

}
Пример #7
0
int main(int argc, char **argv)
{	int	x = 0;
	char	*args[10];

	setuid(2);

	signal(SIGCHLD, sigchld);
	do_signals();

	x += getpid();
	x += getppid();
	x += getuid();
	x += getgid();
	x += setsid();
	x += seteuid();
	x += setegid();
	lseek(0, 0, -1);
	kill(0, 0);
	signal(99, 0);
	signal(SIGINT, int_handler);
	signal(SIGSEGV, segv_handler);
//	*(int *) 0 = 0;
	pipe(0);
	munmap(0, 0);
	mincore(0, 0);
	shmget(0);
	shmat(0);

	line = __LINE__;
	poll(-1, 0, 0);
	signal(SIGSEGV, SIG_IGN);
//	ppoll(-1, -1, -1, 0);
	signal(SIGSEGV, SIG_DFL);
	sched_yield();
	readv(-1, 0, 0, 0);
	writev(-1, 0, 0, 0);
	msync(0, 0, 0);
	fsync(-1);
	fdatasync(-1);
	semget(0, 0, 0);
	semctl(0, 0, 0);
	uselib(NULL);
	pivot_root(0, 0);
	personality(-1);
	setfsuid(-1);
	flock(-1, 0);
	shmdt(0, 0, 0);
	times(0);
	mremap(0, 0, 0, 0, 0);
	madvise(0, 0, 0);
	fchown(-1, 0, 0);
	lchown(0, 0, 0);
	setreuid();
	setregid();
	link("/nonexistant", "/also-nonexistant");

	do_slow();

	symlink("/nothing", "/");
	rename("/", "/");
	mkdir("/junk/stuff////0", 0777);
	geteuid();
	getsid();
	getpgid();
	getresuid();
	getresgid();
	getpgid();
	ptrace(-1, 0, 0, 0);
	semop(0, 0, 0);
	capget(0, 0);

	line = __LINE__;
	gettimeofday(0, 0);
	settimeofday(0, 0);
	dup(-1);
	dup2(-1, -1);
	shmctl(0, 0, 0, 0);
	execve("/bin/nothing", "/bin/nothing", 0);
	alarm(9999);
	bind(0, 0, 0);
	socket(0, 0, 0);
	accept(0, 0, 0);
	listen(0);
	shutdown(0);
	getsockname(0, 0, 0);
	getpeername(0, 0, 0);
	truncate(0, 0);
	ftruncate(0, 0);
	line = __LINE__;
	if (vfork() == 0)
		exit(0);
	line = __LINE__;
	x = opendir("/", 0, 0);
	line = __LINE__;
	readdir(x, 0, 0);
	line = __LINE__;
	closedir(x);
	line = __LINE__;
	chroot("/");
	line = __LINE__;
	sigaction(0, 0, 0);
	line = __LINE__;
	sigprocmask(0, 0, 0);
	x += open("/nothing", 0);
	x += chdir("/nothing");
	x += mknod("/nothing/nothing", 0);
	x += ioctl();
	execve("/nothing", NULL, NULL);
	line = __LINE__;
	x += close(-2);
	line = __LINE__;
	if (fork() == 0)
		exit(0);
	line = __LINE__;
	clone(clone_func, 0, 0, 0);
	line = __LINE__;
	brk(0);
	sbrk(0);
	line = __LINE__;
	mmap(0, 0, 0, 0, 0);
	line = __LINE__;
	uname(0);
	line = __LINE__;
	getcwd(0, 0);
	line = __LINE__;
	iopl(3);
	ioperm(0, 0, 0);
	mount(0, 0, 0, 0, 0);
	umount(0, 0);
	umount(0, 0, 0);
	swapon(0, 0);
	swapoff(0);
	sethostname(0);
	line = __LINE__;
	time(NULL);
	unlink("/nothing");
	line = __LINE__;
	rmdir("/nothing");
	chmod(0, 0);
	line = __LINE__;
# if defined(__i386) || defined(__amd64)
	modify_ldt(0);
# endif

	stat("/doing-nice", 0);
	nice(0);

	args[0] = "/bin/df";
	args[1] = "-l";
	args[2] = NULL;
	close(1);
	open("/dev/null", O_WRONLY);
	/***********************************************/
	/*   Some  syscalls  arent  available  direct  */
	/*   from  libc,  so get them here. We mostly  */
	/*   care  about  the  ones which have caused  */
	/*   implementation   difficulty  and  kernel  */
	/*   crashes - eventually we can be complete.  */
	/***********************************************/
	line = __LINE__;
	open("/system-dependent-syscalls-follow", 0);
	line = __LINE__;
	if (fork() == 0)
		exit(0);

	{int status;
	while (wait(&status) >= 0)
		;
	}

	sigaltstack(0, 0);

	/*vm86(0, 0);*/

	/***********************************************/
	/*   Some syscalls arent directly accessible,  */
	/*   e.g. legacy.			       */
	/***********************************************/
#if defined(__x86_64__)
	trace(__LINE__, "x64 syscalls");
	syscall(174, 0, 0, 0); // create_module
	syscall(176, 0, 0, 0); // delete_module
	syscall(178, 0, 0, 0); // query_module
#else
	trace(__LINE__, "x32 syscalls");
	syscall(0, 0, 0, 0); // restart_syscall
	syscall(34, 0, 0, 0); // nice
	syscall(59, 0, 0, 0); // oldolduname	
	syscall(109, 0, 0, 0); // olduname	
	if (fork() == 0)
		syscall(1, 0, 0, 0); // exit
#endif
	line = __LINE__;
	execve("/bin/df", args, NULL);

	fprintf(stderr, "Error: should not get here -- %s\n", strerror(errno));

	exit(1);
}