Beispiel #1
0
/*
 * This is the generic front-end to uuid_generate_random and
 * uuid_generate_time.  It uses uuid_generate_random only if
 * /dev/urandom is available, since otherwise we won't have
 * high-quality randomness.
 */
void uuid_generate(uuid_t out)
{
	if (get_random_fd() >= 0)
		uuid_generate_random(out);
	else
		uuid_generate_time(out);
}
Beispiel #2
0
/*
 * Generate a series of random bytes.  Use /dev/urandom if possible,
 * and if not, use srandom/random.
 */
static void get_random_bytes(void *buf, int nbytes)
{
	int i, n = nbytes, fd = get_random_fd();
	int lose_counter = 0;
	unsigned char *cp = (unsigned char *) buf;

	if (fd >= 0) {
		while (n > 0) {
			i = read(fd, cp, n);
			if (i <= 0) {
				if (lose_counter++ > 16)
					break;
				continue;
			}
			n -= i;
			cp += i;
			lose_counter = 0;
		}
	}
	
	/*
	 * We do this all the time, but this is the only source of
	 * randomness if /dev/random/urandom is out to lunch.
	 */
	for (cp = buf, i = 0; i < nbytes; i++)
		*cp++ ^= (rand() >> 7) & 0xFF;
	return;
}
Beispiel #3
0
static void pppox_PX_PROTO_OL2TP_PPPoL2TPin6(struct sockaddr **addr, socklen_t *addrlen)
{
#ifdef USE_PPPOL2TPIN6
	struct sockaddr_pppol2tpin6 *pppol2tpin6;

	pppol2tpin6 = zmalloc(sizeof(struct sockaddr_pppol2tpin6));

	pppol2tpin6->sa_family = PF_PPPOX;
	pppol2tpin6->sa_protocol = rnd() % 3;
	pppol2tpin6->pppol2tp.pid = get_pid();
	pppol2tpin6->pppol2tp.fd = get_random_fd();
	pppol2tpin6->pppol2tp.s_tunnel = rnd();
	pppol2tpin6->pppol2tp.s_session = rnd();
	pppol2tpin6->pppol2tp.d_tunnel = rnd();
	pppol2tpin6->pppol2tp.d_session = rnd();
	pppol2tpin6->pppol2tp.addr.sin6_family = AF_INET6;
	pppol2tpin6->pppol2tp.addr.sin6_port = rnd();
	pppol2tpin6->pppol2tp.addr.sin6_flowinfo = rnd();
	pppol2tpin6->pppol2tp.addr.sin6_addr.s6_addr32[0] = 0;
	pppol2tpin6->pppol2tp.addr.sin6_addr.s6_addr32[1] = 0;
	pppol2tpin6->pppol2tp.addr.sin6_addr.s6_addr32[2] = 0;
	pppol2tpin6->pppol2tp.addr.sin6_addr.s6_addr32[3] = htonl(1);
	pppol2tpin6->pppol2tp.addr.sin6_scope_id = rnd();
	*addr = (struct sockaddr *) pppol2tpin6;
	*addrlen = sizeof(struct sockaddr_pppol2tpin6);
#endif
}
Beispiel #4
0
/*
 * Generate a series of random bytes.  Use /dev/urandom if possible,
 * and if not, use srandom/random.
 */
static void get_random_bytes(void *buf, int nbytes)
{
	int i, fd = get_random_fd();
	int lose_counter = 0;
	char *cp = (char *) buf;

	if (fd >= 0) {
		while (nbytes > 0) {
			i = read(fd, cp, nbytes);
			if ((i < 0) &&
			    ((errno == EINTR) || (errno == EAGAIN)))
				continue;
			if (i <= 0) {
				if (lose_counter++ == 8)
					break;
				continue;
			}
			nbytes -= i;
			cp += i;
			lose_counter = 0;
		}
	}

	/* XXX put something better here if no /dev/random! */
	for (i = 0; i < nbytes; i++)
		*cp++ = rand() & 0xFF;
	return;
}
Beispiel #5
0
static void sanitise_epoll_ctl(struct syscallrecord *rec)
{
	struct epoll_event *ep;

	ep = zmalloc(sizeof(struct epoll_event));
	ep->data.fd = get_random_fd();
	ep->events = set_rand_bitmask(ARRAY_SIZE(epoll_flags), epoll_flags);
	rec->a4 = (unsigned long) ep;
}
Beispiel #6
0
static void autofs_sanitise(const struct ioctl_group *grp, struct syscallrecord *rec)
{
	struct autofs_dev_ioctl *arg;

	pick_random_ioctl(grp, rec);

	rec->a3 = (unsigned long) get_address();

	switch (rec->a2) {
	case AUTOFS_DEV_IOCTL_VERSION:
	case AUTOFS_DEV_IOCTL_PROTOVER:
	case AUTOFS_DEV_IOCTL_PROTOSUBVER:
	case AUTOFS_DEV_IOCTL_OPENMOUNT:
	case AUTOFS_DEV_IOCTL_CLOSEMOUNT:
	case AUTOFS_DEV_IOCTL_READY:
	case AUTOFS_DEV_IOCTL_FAIL:
	case AUTOFS_DEV_IOCTL_SETPIPEFD:
	case AUTOFS_DEV_IOCTL_CATATONIC:
	case AUTOFS_DEV_IOCTL_TIMEOUT:
	case AUTOFS_DEV_IOCTL_REQUESTER:
	case AUTOFS_DEV_IOCTL_EXPIRE:
	case AUTOFS_DEV_IOCTL_ASKUMOUNT:
	case AUTOFS_DEV_IOCTL_ISMOUNTPOINT:
		arg = (struct autofs_dev_ioctl *) rec->a3;
		init_autofs_dev_ioctl(arg);
		arg->ioctlfd = get_random_fd();
		arg->fail.token = rand();
		arg->fail.status = rand();
		if (RAND_BOOL()) {
			arg->size += 5;
			arg->path[0] = '/';
			arg->path[1] = rand();
			arg->path[2] = rand();
			arg->path[3] = rand();
			arg->path[4] = 0;
		} else {
			int i;

			arg->size += rand();
			for (i=0; i < 10; ++i)
				arg->path[i] = rand();
		}
		break;
	default:
		break;
	}
}
Beispiel #7
0
static void autofs_sanitise(const struct ioctl_group *grp, int childno)
{
    int i;
    struct autofs_dev_ioctl *arg;

    pick_random_ioctl(grp, childno);

    shm->a3[childno] = (unsigned long) page_rand;

    switch (shm->a2[childno]) {
    case AUTOFS_DEV_IOCTL_VERSION:
    case AUTOFS_DEV_IOCTL_PROTOVER:
    case AUTOFS_DEV_IOCTL_PROTOSUBVER:
    case AUTOFS_DEV_IOCTL_OPENMOUNT:
    case AUTOFS_DEV_IOCTL_CLOSEMOUNT:
    case AUTOFS_DEV_IOCTL_READY:
    case AUTOFS_DEV_IOCTL_FAIL:
    case AUTOFS_DEV_IOCTL_SETPIPEFD:
    case AUTOFS_DEV_IOCTL_CATATONIC:
    case AUTOFS_DEV_IOCTL_TIMEOUT:
    case AUTOFS_DEV_IOCTL_REQUESTER:
    case AUTOFS_DEV_IOCTL_EXPIRE:
    case AUTOFS_DEV_IOCTL_ASKUMOUNT:
    case AUTOFS_DEV_IOCTL_ISMOUNTPOINT:
        arg = (struct autofs_dev_ioctl *)shm->a3[childno];
        init_autofs_dev_ioctl(arg);
        arg->ioctlfd = get_random_fd();
        arg->fail.token = rand();
        arg->fail.status = rand();
        if (rand_bool()) {
            arg->size += 5;
            arg->path[0] = '/';
            arg->path[1] = rand();
            arg->path[2] = rand();
            arg->path[3] = rand();
            arg->path[4] = 0;
        } else {
            arg->size += rand();
            for (i=0; i < 10; ++i)
                arg->path[i] = rand();
        }
        break;
    default:
        break;
    }
}
Beispiel #8
0
static void pppox_PX_PROTO_OL2TP_PPPoL2TP(struct sockaddr **addr, socklen_t *addrlen)
{
	struct sockaddr_pppol2tp *pppol2tp;

	pppol2tp = zmalloc(sizeof(struct sockaddr_pppol2tp));

	pppol2tp->sa_family = PF_PPPOX;
	pppol2tp->sa_protocol = rnd() % 3;
	pppol2tp->pppol2tp.pid = get_pid();
	pppol2tp->pppol2tp.fd = get_random_fd();
	pppol2tp->pppol2tp.addr.sin_addr.s_addr = random_ipv4_address();
	pppol2tp->pppol2tp.s_tunnel = rnd();
	pppol2tp->pppol2tp.s_session = rnd();
	pppol2tp->pppol2tp.d_tunnel = rnd();
	pppol2tp->pppol2tp.d_session = rnd();
	*addr = (struct sockaddr *) pppol2tp;
	*addrlen = sizeof(struct sockaddr_pppol2tp);
}
Beispiel #9
0
static void pppox_PX_PROTO_OL2TP_PPPoL2TPv3(struct sockaddr **addr, socklen_t *addrlen)
{
#ifdef USE_PPPOL2TPV3
	struct sockaddr_pppol2tpv3 *pppol2tpv3;

	pppol2tpv3 = zmalloc(sizeof(struct sockaddr_pppol2tpv3));

	pppol2tpv3->sa_family = PF_PPPOX;
	pppol2tpv3->sa_protocol = rnd() % 3;
	pppol2tpv3->pppol2tp.pid = get_pid();
	pppol2tpv3->pppol2tp.fd = get_random_fd();
	pppol2tpv3->pppol2tp.addr.sin_addr.s_addr = random_ipv4_address();
	pppol2tpv3->pppol2tp.s_tunnel = rnd();
	pppol2tpv3->pppol2tp.s_session = rnd();
	pppol2tpv3->pppol2tp.d_tunnel = rnd();
	pppol2tpv3->pppol2tp.d_session = rnd();
	*addr = (struct sockaddr *) pppol2tpv3;
	*addrlen = sizeof(struct sockaddr_pppol2tpv3);
#endif
}
Beispiel #10
0
static void sanitise_poll(struct syscallrecord *rec)
{
	struct pollfd *pollfd;
	unsigned int i;
	unsigned int num_fds = rand() % 10;
	unsigned long flags[] = {
		POLLIN, POLLPRI, POLLOUT, POLLRDHUP,
		POLLERR, POLLHUP, POLLNVAL, POLLRDNORM,
		POLLRDBAND, POLLWRNORM, POLLWRBAND, POLLMSG
	};

	pollfd = zmalloc(num_fds * sizeof(struct pollfd));

	for (i = 0; i < num_fds; i++) {
		pollfd[i].fd = get_random_fd();
		pollfd[i].events = set_rand_bitmask(ARRAY_SIZE(flags), flags);
	}

	rec->a1 = (unsigned long) pollfd;
	rec->a2 = num_fds;
}
Beispiel #11
0
static unsigned long fill_arg(struct syscallrecord *rec, unsigned int argnum)
{
	struct syscallentry *entry;
	unsigned int call;
	enum argtype argtype;

	call = rec->nr;
	entry = syscalls[call].entry;

	if (argnum > entry->num_args)
		return 0;

	argtype = get_argtype(entry, argnum);

	switch (argtype) {
	case ARG_UNDEFINED:
		if (RAND_BOOL())
			return (unsigned long) rand64();
		return (unsigned long) get_writable_address(page_size);

	case ARG_FD:
		if (RAND_BOOL()) {
			unsigned int i;
			/* If this is the 2nd or more ARG_FD, make it unique */
			for (i = 0; i < argnum; i++) {
				enum argtype arg;
				arg = get_argtype(entry, i);
				if (arg == ARG_FD)
					return get_new_random_fd();
			}
		}
		return get_random_fd();

	case ARG_LEN:
		return (unsigned long) get_len();

	case ARG_ADDRESS:
		return handle_arg_address(rec, argnum);

	case ARG_NON_NULL_ADDRESS:
		return (unsigned long) get_non_null_address();

	case ARG_MMAP:
		return (unsigned long) get_map();

	case ARG_PID:
		return (unsigned long) get_pid();

	case ARG_RANGE:
		return handle_arg_range(entry, argnum);

	case ARG_OP:	/* Like ARG_LIST, but just a single value. */
		return handle_arg_op(entry, argnum);

	case ARG_LIST:
		return handle_arg_list(entry, argnum);

	case ARG_CPU:
		return (unsigned long) get_cpu();

	case ARG_PATHNAME:
		return (unsigned long) generate_pathname();

	case ARG_IOVEC:
		return handle_arg_iovec(entry, rec, argnum);

	case ARG_IOVECLEN:
	case ARG_SOCKADDRLEN:
		/* We already set the len in the ARG_IOVEC/ARG_SOCKADDR case
		 * So here we just return what we had set there. */
		return get_argval(rec, argnum);

	case ARG_SOCKADDR:
		return handle_arg_sockaddr(entry, rec, argnum);

	case ARG_MODE_T:
		return handle_arg_mode_t();

	case ARG_SOCKETINFO:
		return (unsigned long) get_rand_socketinfo();
	}

	BUG("unreachable!\n");
}
Beispiel #12
0
static unsigned long fill_arg(struct syscallrecord *rec, unsigned int argnum)
{
	struct syscallentry *entry;
	unsigned int call;
	enum argtype argtype;

	call = rec->nr;
	entry = syscalls[call].entry;

	if (argnum > entry->num_args)
		return 0;

	argtype = get_argtype(entry, argnum);

	switch (argtype) {
	case ARG_UNDEFINED:
		return (unsigned long) rand64();

	case ARG_FD:
		return get_random_fd();

	case ARG_LEN:
		return (unsigned long) get_len();

	case ARG_ADDRESS:
		return handle_arg_address(rec, argnum);

	case ARG_NON_NULL_ADDRESS:
		return (unsigned long) get_non_null_address();

	case ARG_MMAP:
		return (unsigned long) get_map();

	case ARG_PID:
		return (unsigned long) get_pid();

	case ARG_RANGE:
		return handle_arg_range(entry, argnum);

	case ARG_OP:	/* Like ARG_LIST, but just a single value. */
		return handle_arg_op(entry, argnum);

	case ARG_LIST:
		return handle_arg_list(entry, argnum);

	case ARG_RANDPAGE:
		return handle_arg_randpage();

	case ARG_CPU:
		return (unsigned long) get_cpu();

	case ARG_PATHNAME:
		return (unsigned long) generate_pathname();

	case ARG_IOVEC:
		return handle_arg_iovec(entry, rec, argnum);

	case ARG_IOVECLEN:
	case ARG_SOCKADDRLEN:
		/* We already set the len in the ARG_IOVEC/ARG_SOCKADDR case
		 * So here we just return what we had set there. */
		return get_argval(rec, argnum);

	case ARG_SOCKADDR:
		return handle_arg_sockaddr(entry, rec, argnum);

	case ARG_MODE_T:
		return handle_arg_mode_t();
	}

	BUG("unreachable!\n");
}
Beispiel #13
0
void sanitise_fcntl(int childno)
{
	switch (shm->a2[childno]) {
	/* arg = fd */
	case F_DUPFD:
	case F_DUPFD_CLOEXEC:
	case F_SETLEASE:
		shm->a3[childno] = (unsigned long) get_random_fd();
		break;
		break;

	/* no arg */
	case F_GETFD:
	case F_GETFL:
	case F_GETOWN:
	case F_GETSIG:
	case F_GETLEASE:
	case F_GETPIPE_SZ:
		break;

	case F_SETFD:	/* arg = flags */
		shm->a3[childno] = (unsigned int) rand32();
		break;

	case F_SETFL:
		shm->a3[childno] = 0L;
		if (rand_bool())
			shm->a3[childno] |= O_APPEND;
		if (rand_bool())
			shm->a3[childno] |= O_ASYNC;
		if (rand_bool())
			shm->a3[childno] |= O_DIRECT;
		if (rand_bool())
			shm->a3[childno] |= O_NOATIME;
		if (rand_bool())
			shm->a3[childno] |= O_NONBLOCK;
		break;

	/* arg = (struct flock *) */
	case F_GETLK:
	case F_SETLK:
	case F_SETLKW:
		break;
#ifdef HAVE_LK64
	case F_GETLK64:
		break;
	case F_SETLK64:
		break;
	case F_SETLKW64:
		break;
#endif

	case F_SETOWN:
		shm->a3[childno] = (unsigned long) get_pid();
		break;

	/* arg = struct f_owner_ex *) */
	case F_GETOWN_EX:
	case F_SETOWN_EX:
		break;

	case F_SETSIG:
		shm->a3[childno] = (unsigned long) rand32();
		if (shm->a3[childno] == SIGINT)
			shm->a3[childno] = 0; /* restore default (SIGIO) */
		break;

	case F_NOTIFY:
		shm->a3[childno] = 0L;
		if (rand_bool())
			shm->a3[childno] |= DN_ACCESS;
		if (rand_bool())
			shm->a3[childno] |= DN_MODIFY;
		if (rand_bool())
			shm->a3[childno] |= DN_CREATE;
		if (rand_bool())
			shm->a3[childno] |= DN_DELETE;
		if (rand_bool())
			shm->a3[childno] |= DN_RENAME;
		if (rand_bool())
			shm->a3[childno] |= DN_ATTRIB;
		break;

	case F_SETPIPE_SZ:
		shm->a3[childno] = rand32();
		break;

	default:
		break;
	}

}
Beispiel #14
0
static void sanitise_fcntl(struct syscallrecord *rec)
{
	switch (rec->a2) {
	/* arg = fd */
	case F_DUPFD:
	case F_DUPFD_CLOEXEC:
	case F_SETLEASE:
		rec->a3 = (unsigned long) get_random_fd();
		break;

	/* no arg */
	case F_GETFD:
	case F_GETFL:
	case F_GETOWN:
	case F_GETSIG:
	case F_GETLEASE:
	case F_GETPIPE_SZ:
	case F_GETOWNER_UIDS:
		break;

	case F_SETFD:	/* arg = flags */
		rec->a3 = (unsigned int) rand32();
		break;

	case F_SETFL:
		rec->a3 = (unsigned long) random_fcntl_setfl_flags();
		break;

	/* arg = (struct flock *) */
	case F_GETLK:
	case F_SETLK:
	case F_SETLKW:
		break;
#ifdef HAVE_LK64
	case F_GETLK64:
		break;
	case F_SETLK64:
		break;
	case F_SETLKW64:
		break;
#endif

	case F_SETOWN:
		rec->a3 = (unsigned long) get_pid();
		break;

	/* arg = struct f_owner_ex *) */
	case F_GETOWN_EX:
	case F_SETOWN_EX:
		break;

	case F_SETSIG:
		rec->a3 = (unsigned long) rand32();
		if (rec->a3 == SIGINT)
			rec->a3 = 0; /* restore default (SIGIO) */
		break;

	case F_NOTIFY:
		rec->a3 = 0L;
		if (rand_bool())
			rec->a3 |= DN_ACCESS;
		if (rand_bool())
			rec->a3 |= DN_MODIFY;
		if (rand_bool())
			rec->a3 |= DN_CREATE;
		if (rand_bool())
			rec->a3 |= DN_DELETE;
		if (rand_bool())
			rec->a3 |= DN_RENAME;
		if (rand_bool())
			rec->a3 |= DN_ATTRIB;
		break;

	case F_SETPIPE_SZ:
		rec->a3 = rand32();
		break;

	default:
		break;
	}

}
Beispiel #15
0
static void socket_destructor(struct object *obj)
{
	struct socketinfo *si = &obj->sockinfo;
	struct linger ling = { .l_onoff = FALSE, .l_linger = 0 };
	int fd;

	//FIXME: This is a workaround for a weird bug where we hang forevre
	// waiting for bluetooth sockets when we setsockopt.
	// Hopefully at some point we can remove this when someone figures out what's going on.
	if (si->triplet.family == PF_BLUETOOTH)
		return;

	/* Grab an fd, and nuke it before someone else uses it. */
	fd = si->fd;
	si->fd = 0;

	/* disable linger */
	(void) setsockopt(fd, SOL_SOCKET, SO_LINGER, &ling, sizeof(struct linger));

	(void) shutdown(fd, SHUT_RDWR);

	if (close(fd) != 0)
		output(1, "failed to close socket [%d:%d:%d].(%s)\n",
			si->triplet.family,
			si->triplet.type,
			si->triplet.protocol,
			strerror(errno));
}

static void socket_dump(struct object *obj, bool global)
{
	struct socketinfo *si = &obj->sockinfo;
	struct msg_objcreatedsocket objmsg;

	output(2, "socket fd:%d domain:%u (%s) type:0x%u protocol:%u\n",
		si->fd, si->triplet.family, get_domain_name(si->triplet.family),
		si->triplet.type, si->triplet.protocol);

	init_msgobjhdr(&objmsg.hdr, OBJ_CREATED_SOCKET, global, obj);
	objmsg.si.fd = si->fd;
	objmsg.si.triplet.family = si->triplet.family;
	objmsg.si.triplet.type = si->triplet.type;
	objmsg.si.triplet.protocol = si->triplet.protocol;
	sendudp((char *) &objmsg, sizeof(objmsg));
}

static int open_sockets(void)
{
	struct objhead *head;
	int bytesread = -1;
	int ret;

	head = get_objhead(OBJ_GLOBAL, OBJ_FD_SOCKET);
	head->destroy = &socket_destructor;
	head->dump = &socket_dump;

	cachefile = open(cachefilename, O_RDONLY);
	if (cachefile < 0) {
		output(1, "Couldn't find socket cachefile. Regenerating.\n");
		ret = generate_sockets();
		output(1, "created %d sockets\n", nr_sockets);
		return ret;
	}

	lock_cachefile(F_RDLCK);

	while (bytesread != 0) {
		unsigned int domain, type, protocol;
		unsigned int buffer[3];
		int fd;

		bytesread = read(cachefile, buffer, sizeof(int) * 3);
		if (bytesread == 0) {
			if (nr_sockets == 0)
				goto regenerate;
			break;
		}

		domain = buffer[0];
		type = buffer[1];
		protocol = buffer[2];

		if (domain >= TRINITY_PF_MAX) {
			output(1, "cachefile contained invalid domain %u\n", domain);
			goto regenerate;
		}

		if ((do_specific_domain == TRUE && domain != specific_domain) ||
		    (no_domains[domain] == TRUE)) {
			output(1, "ignoring socket cachefile due to specific "
			       "protocol request (or protocol disabled), "
			       "and stale data in cachefile.\n");
regenerate:
				unlock_cachefile();	/* drop the reader lock. */
				close(cachefile);
				unlink(cachefilename);

				ret = generate_sockets();
				return ret;
		}

		fd = open_socket(domain, type, protocol);
		if (fd < 0) {
			output(1, "Cachefile is stale. Need to regenerate.\n");
			goto regenerate;
		}

		/* check for ctrl-c */
		if (shm->exit_reason != STILL_RUNNING) {
			close(cachefile);
			return FALSE;
		}
	}

	output(1, "%d sockets created based on info from socket cachefile.\n", nr_sockets);

	unlock_cachefile();
	close(cachefile);

	return TRUE;
}

struct socketinfo * get_rand_socketinfo(void)
{
	struct object *obj;

	/* When using victim files, sockets can be 0. */
	if (objects_empty(OBJ_FD_SOCKET) == TRUE)
		return NULL;

	obj = get_random_object(OBJ_FD_SOCKET, OBJ_GLOBAL);
	return &obj->sockinfo;
}

static int get_rand_socket_fd(void)
{
	struct socketinfo *sockinfo;

	sockinfo = get_rand_socketinfo();
	if (sockinfo == NULL)
		return -1;

	return sockinfo->fd;
}

int fd_from_socketinfo(struct socketinfo *si)
{
	if (si != NULL) {
		if (!(ONE_IN(1000)))
			return si->fd;
	}
	return get_random_fd();
}

static const struct fd_provider socket_fd_provider = {
	.name = "sockets",
	.enabled = TRUE,
	.open = &open_sockets,
	.get = &get_rand_socket_fd,
};

REG_FD_PROV(socket_fd_provider);