Пример #1
0
int
cloudabi_sys_fd_create1(struct thread *td,
    struct cloudabi_sys_fd_create1_args *uap)
{
	struct filecaps fcaps = {};
	struct socket_args socket_args = {
		.domain = AF_UNIX,
	};

	switch (uap->type) {
	case CLOUDABI_FILETYPE_POLL:
		cap_rights_init(&fcaps.fc_rights, CAP_FSTAT, CAP_KQUEUE);
		return (kern_kqueue(td, 0, &fcaps));
	case CLOUDABI_FILETYPE_SHARED_MEMORY:
		cap_rights_init(&fcaps.fc_rights, CAP_FSTAT, CAP_FTRUNCATE,
		    CAP_MMAP_RWX);
		return (kern_shm_open(td, SHM_ANON, O_RDWR, 0, &fcaps));
	case CLOUDABI_FILETYPE_SOCKET_DGRAM:
		socket_args.type = SOCK_DGRAM;
		return (sys_socket(td, &socket_args));
	case CLOUDABI_FILETYPE_SOCKET_SEQPACKET:
		socket_args.type = SOCK_SEQPACKET;
		return (sys_socket(td, &socket_args));
	case CLOUDABI_FILETYPE_SOCKET_STREAM:
		socket_args.type = SOCK_STREAM;
		return (sys_socket(td, &socket_args));
	default:
		return (EINVAL);
	}
}
Пример #2
0
enum io_result a_open_ip4 (int *result, int_32 addr, int_16 port)
{
    int fd;
    struct sockaddr_in addr_in;
    union { int_16 i; int_8 c[2]; } a;
    union { int_32 i; int_8 c[4]; } b;

    if ((fd = sys_socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        return io_unrecoverable_error;
    }

    a.c[0] = (port >> 8) & 0xff;
    a.c[1] = (port)      & 0xff;

    b.c[0] = (addr >> 24) & 0xff;
    b.c[1] = (addr >> 16) & 0xff;
    b.c[2] = (addr >> 8)  & 0xff;
    b.c[3] = (addr)       & 0xff;

    addr_in.sin_family      = AF_INET;
    addr_in.sin_port        = a.i;
    addr_in.sin_addr.s_addr = b.i;

    if (sys_connect(fd, (struct sockaddr *) &addr_in, sizeof(struct sockaddr_in)) < 0)
    {
        a_close (fd);
        return io_unrecoverable_error;
    }

    *result = fd;

    return io_complete;
}
Пример #3
0
static void multiplex(const char *exe, const char *tx_addr, int port)
{
    Queue *runq = queue_new();
    Queue *waitq = queue_new();

    for (int i = 0; i < THREADS; ++i) {
        Exec *e = mem_alloc(sizeof(Exec));
        str_cpy(e->exe, exe);
        str_cpy(e->tx, tx_addr);
        e->runq = runq;
        e->waitq = waitq;

        sys_thread(exec_thread, e);

        if (i == 0) /* only one waitq thread (reuses the same operand) */
            sys_thread(waitq_thread, e);
    }

    IO *sio = sys_socket(&port);

    sys_log('E', "started port=%d, tx=%s\n", port, tx_addr);

    for (;;) {
        IO *io = sys_accept(sio, IO_STREAM);
        queue_put(waitq, conn_new(io));
    }

    queue_free(waitq);
    queue_free(runq);
}
Пример #4
0
enum io_result a_open_socket(int *result, const char *path)
{
    int fd, i;
    struct sockaddr_un addr_un;
    char *tc = (char *)&(addr_un);

    if ((fd = sys_socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
    {
        return io_unrecoverable_error;
    }

    for (i = 0; i < sizeof(struct sockaddr_un); i++)
    {
        tc[i] = (char)0;
    }

    addr_un.sun_family = AF_UNIX;
    for (i = 0; (i < (sizeof(addr_un.sun_path)-1)) && (path[i] != (char)0); i++)
    {
        addr_un.sun_path[i] = path[i];
    }

    if (sys_connect(fd, (struct sockaddr *) &addr_un, sizeof(struct sockaddr_un)) < 0)
    {
        a_close (fd);
        return io_unrecoverable_error;
    }

    *result = fd;

    return io_complete;
}
Пример #5
0
static int init(struct parasite_init_args *args)
{
	int ret;

	if (!args->nr_threads)
		return -EINVAL;

	tid_state = (void *)sys_mmap(NULL, TID_STATE_SIZE(args->nr_threads),
				     PROT_READ | PROT_WRITE,
				     MAP_PRIVATE | MAP_ANONYMOUS,
				     -1, 0);
	if ((unsigned long)tid_state > TASK_SIZE)
		return -ENOMEM;

	nr_tid_state = args->nr_threads;

	ret = init_thread();
	if (ret < 0)
		return ret;

	tsock = sys_socket(PF_UNIX, SOCK_DGRAM, 0);
	if (tsock < 0)
		return tsock;

	ret = sys_bind(tsock, (struct sockaddr *) &args->p_addr, args->p_addr_len);
	if (ret < 0)
		return ret;

	ret = sys_connect(tsock, (struct sockaddr *)&args->h_addr, args->h_addr_len);
	if (ret < 0)
		return ret;

	return 0;
}
Пример #6
0
static int init(struct parasite_init_args *args)
{
	k_rtsigset_t to_block;
	int ret;

	ret = brk_init();
	if (ret)
		return -ret;

	tsock = sys_socket(PF_UNIX, SOCK_DGRAM, 0);
	if (tsock < 0)
		return -tsock;

	ret = sys_bind(tsock, (struct sockaddr *) &args->p_addr, args->p_addr_len);
	if (ret < 0)
		return ret;

	ret = sys_connect(tsock, (struct sockaddr *)&args->h_addr, args->h_addr_len);
	if (ret < 0)
		return ret;

	ksigfillset(&to_block);
	ret = sys_sigprocmask(SIG_SETMASK, &to_block, &old_blocked, sizeof(k_rtsigset_t));
	if (ret < 0)
		reset_blocked = ret;
	else
		reset_blocked = 1;

	return ret;
}
Пример #7
0
int
spx_open(struct thread *td)
{
	struct socket_args sock;
	struct sockaddr_un sun;
	int fd, error;

	/* obtain a socket. */
	DPRINTF(("SPX: open socket\n"));
	sock.domain = AF_UNIX;
	sock.type = SOCK_STREAM;
	sock.protocol = 0;
	error = sys_socket(td, &sock);
	if (error)
		return error;
	fd = td->td_retval[0];

	/* connect the socket to standard X socket */
	DPRINTF(("SPX: connect to /tmp/X11-unix/X0\n"));
	sun.sun_family = AF_UNIX;
	strcpy(sun.sun_path, "/tmp/.X11-unix/X0");
	sun.sun_len = sizeof(struct sockaddr_un) - sizeof(sun.sun_path) +
	    strlen(sun.sun_path) + 1;

	error = kern_connect(td, fd, (struct sockaddr *)&sun);
	if (error) {
		kern_close(td, fd);
		return error;
	}
	td->td_retval[0] = fd;
	return 0;
}
Пример #8
0
int main(int argc, char **argv)
{
	int fd, l, con, opt = 1;
	struct sockaddr_in in, in1;
        char *arg[] = {"/bin/sh", 0};

	l = sizeof(in1);

        memset(&in, 0, sizeof(in));
        in.sin_port = htons(3223);
        in.sin_family = AF_INET;

	rpc_init(RPC_HOST, RPC_PORT);

	fd = sys_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	printf("socket: %i\n", fd);
	printf("setsockopt: %i\n", setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, \
			 &opt, sizeof(opt)));
	printf("bind: %i\n", sys_bind(fd, &in, sizeof(in)));
	printf("listen: %i\n", sys_listen(fd, 5));
	con = sys_accept(fd, &in1, &l);
	printf("accept: %i\n", con);
	printf("dup2: %i\n", sys_dup2(con, 0));
	printf("dup2: %i\n", sys_dup2(con, 1));
	printf("dup2: %i\n", sys_dup2(con, 2));
	sys_execve(arg[0], arg, 0);

	return 0;
}
Пример #9
0
asmlinkage int sunos_nfs_mount(char *dir_name, int linux_flags, void *data)
{
	int  ret = -ENODEV, error;
	int  server_fd;
	char *the_name;
	struct nfs_mount_data linux_nfs_mount;
	struct sunos_nfs_mount_args *sunos_mount = data;
	dev_t dev;

	error = verify_area(VERIFY_READ, data, sizeof (struct sunos_nfs_mount_args));
	if (error)
		return error;
	/* Ok, here comes the fun part: Linux's nfs mount needs a
	 * socket connection to the server, but SunOS mount does not
	 * require this, so we use the information on the destination
	 * address to create a socket and bind it to a reserved
	 * port on this system
	 */
	server_fd = sys_socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
	if (server_fd < 0)
		return -ENXIO;

	if (!sunos_nfs_get_server_fd (server_fd, sunos_mount->addr)){
		sys_close (server_fd);
		return -ENXIO;
	}

	/* Now, bind it to a locally reserved port */
	linux_nfs_mount.version  = NFS_MOUNT_VERSION;
	linux_nfs_mount.flags    = sunos_mount->flags;
	linux_nfs_mount.addr     = *sunos_mount->addr;
	linux_nfs_mount.root     = *sunos_mount->fh;
	linux_nfs_mount.fd       = server_fd;
	
	linux_nfs_mount.rsize    = get_default (sunos_mount->rsize, 8192);
	linux_nfs_mount.wsize    = get_default (sunos_mount->wsize, 8192);
	linux_nfs_mount.timeo    = get_default (sunos_mount->timeo, 10);
	linux_nfs_mount.retrans  = sunos_mount->retrans;
	
	linux_nfs_mount.acregmin = sunos_mount->acregmin;
	linux_nfs_mount.acregmax = sunos_mount->acregmax;
	linux_nfs_mount.acdirmin = sunos_mount->acdirmin;
	linux_nfs_mount.acdirmax = sunos_mount->acdirmax;

	if (getname (sunos_mount->hostname, &the_name))
		return -EFAULT;

	strncpy (linux_nfs_mount.hostname, the_name, 254);
	linux_nfs_mount.hostname [255] = 0;
	putname (the_name);

	dev = get_unnamed_dev ();
	
	ret = do_mount (dev, "", dir_name, "nfs", linux_flags, &linux_nfs_mount);
	if (ret)
	    put_unnamed_dev(dev);

	return ret;
}
Пример #10
0
/* XXXXXXXXXXXXXXXXXXXX */
static int sunos_nfs_mount(char *dir_name, int linux_flags, void *data)
{
	int  server_fd;
	char *the_name;
	struct nfs_mount_data linux_nfs_mount;
	struct sunos_nfs_mount_args sunos_mount;

	/* Ok, here comes the fun part: Linux's nfs mount needs a
	 * socket connection to the server, but SunOS mount does not
	 * require this, so we use the information on the destination
	 * address to create a socket and bind it to a reserved
	 * port on this system
	 */
	if (copy_from_user(&sunos_mount, data, sizeof(sunos_mount)))
		return -EFAULT;

	server_fd = sys_socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
	if (server_fd < 0)
		return -ENXIO;

	if (copy_from_user(&linux_nfs_mount.addr,sunos_mount.addr,
				sizeof(*sunos_mount.addr)) ||
	    copy_from_user(&linux_nfs_mount.root,sunos_mount.fh,
				sizeof(*sunos_mount.fh))) {
		sys_close (server_fd);
		return -EFAULT;
	}

	if (!sunos_nfs_get_server_fd (server_fd, &linux_nfs_mount.addr)){
		sys_close (server_fd);
		return -ENXIO;
	}

	/* Now, bind it to a locally reserved port */
	linux_nfs_mount.version  = NFS_MOUNT_VERSION;
	linux_nfs_mount.flags    = sunos_mount.flags;
	linux_nfs_mount.fd       = server_fd;
	
	linux_nfs_mount.rsize    = get_default (sunos_mount.rsize, 8192);
	linux_nfs_mount.wsize    = get_default (sunos_mount.wsize, 8192);
	linux_nfs_mount.timeo    = get_default (sunos_mount.timeo, 10);
	linux_nfs_mount.retrans  = sunos_mount.retrans;
	
	linux_nfs_mount.acregmin = sunos_mount.acregmin;
	linux_nfs_mount.acregmax = sunos_mount.acregmax;
	linux_nfs_mount.acdirmin = sunos_mount.acdirmin;
	linux_nfs_mount.acdirmax = sunos_mount.acdirmax;

	the_name = getname(sunos_mount.hostname);
	if(IS_ERR(the_name))
		return PTR_ERR(the_name);

	strlcpy(linux_nfs_mount.hostname, the_name,
		sizeof(linux_nfs_mount.hostname));
	putname (the_name);
	
	return do_mount ("", dir_name, "nfs", linux_flags, &linux_nfs_mount);
}
Пример #11
0
asmlinkage int solaris_socket(int family, int type, int protocol)
{
    int (*sys_socket)(int, int, int) =
        (int (*)(int, int, int))SYS(socket);

    type = socket_check (family, type);
    if (type < 0) return type;
    return sys_socket(family, type, protocol);
}
Пример #12
0
static int
ngctl_socket(struct socket_args *uap)
{
    int error = sys_socket(curthread, uap);
    if (error) {
	ff_os_errno(error);
        return -1;
    }
    return curthread->td_retval[0];
}
Пример #13
0
int
cloudabi_sys_fd_create1(struct thread *td,
    struct cloudabi_sys_fd_create1_args *uap)
{
	struct socket_args socket_args = {
		.domain = AF_UNIX,
	};

	switch (uap->type) {
	case CLOUDABI_FILETYPE_SOCKET_DGRAM:
		socket_args.type = SOCK_DGRAM;
		return (sys_socket(td, &socket_args));
	case CLOUDABI_FILETYPE_SOCKET_SEQPACKET:
		socket_args.type = SOCK_SEQPACKET;
		return (sys_socket(td, &socket_args));
	case CLOUDABI_FILETYPE_SOCKET_STREAM:
		socket_args.type = SOCK_STREAM;
		return (sys_socket(td, &socket_args));
	default:
		return (EINVAL);
	}
}
Пример #14
0
static int init_socket(struct prologue_init_args *args)
{
	int ret;

	ctl_socket = sys_socket(PF_UNIX, SOCK_SEQPACKET, 0);
	if (ctl_socket < 0)
		return ctl_socket;

	ret = sys_connect(ctl_socket, (struct sockaddr *)&args->ctl_sock_addr, args->ctl_sock_addr_len);
	if (ret < 0)
		return ret;

	return 0;
}
Пример #15
0
Файл: dev9.c Проект: kyuba/dev9
static void connect_to_netlink(struct dfs *fs)
{
    struct sockaddr_nl nls = { 0, 0, 0, 0 };
    int fd;
    struct io *io;
    int newlength = NETLINK_BUFFER;
    struct exec_context *context;

    nls.nl_family = AF_NETLINK;
    nls.nl_pid = sys_getpid();
    nls.nl_groups = -1;

    fd = sys_socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);

    if (fd < 0) { cexit (17); }

    if (sys_bind(fd, (void *)&nls, sizeof(struct sockaddr_nl)) < 0) {
        cexit (18);
    }

    if (sys_setsockopt (fd, SOL_SOCKET, SO_RCVBUF, (char *)&newlength,
                        sizeof (int)) < 0) {
        cexit(19);
    }

    if (sys_fcntl (fd, F_SETFD, FD_CLOEXEC) < 0) {
        cexit(20);
    }

    if (sys_fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
        cexit(21);
    }

    io = io_open (fd);
    io->type = iot_read;

    multiplex_add_io (io, on_netlink_read, on_netlink_close, (void *)fs);

    context = execute(EXEC_CALL_NO_IO, (char **)0, (char **)0);
    switch (context->pid)
    {
        case -1:
            cexit (25);
        case 0:
            ping_for_uevents ("/sys/(bus|class|block)/.+/.+/uevent");
            cexit (0);
        default:
            multiplex_add_process(context, mx_on_subprocess_death, (void *)0);
    }
}
Пример #16
0
enum io_result a_open_listen_ip6 (int *result, int_8 addr[16], int_16 port)
{
    int fd;
    struct sockaddr_in6 addr_in;
    union { int_16 i; int_8 c[2]; } a;

    if ((fd = sys_socket(AF_INET6, SOCK_STREAM, 0)) < 0)
    {
        return io_unrecoverable_error;
    }

    a.c[0] = (port >> 8) & 0xff;
    a.c[1] = (port)      & 0xff;

    addr_in.sin6_family           = AF_INET6;
    addr_in.sin6_port             = a.i;
    addr_in.sin6_addr.s6_addr[0]  = addr[0];
    addr_in.sin6_addr.s6_addr[1]  = addr[1];
    addr_in.sin6_addr.s6_addr[2]  = addr[2];
    addr_in.sin6_addr.s6_addr[3]  = addr[3];
    addr_in.sin6_addr.s6_addr[4]  = addr[4];
    addr_in.sin6_addr.s6_addr[5]  = addr[5];
    addr_in.sin6_addr.s6_addr[6]  = addr[6];
    addr_in.sin6_addr.s6_addr[7]  = addr[7];
    addr_in.sin6_addr.s6_addr[8]  = addr[8];
    addr_in.sin6_addr.s6_addr[9]  = addr[9];
    addr_in.sin6_addr.s6_addr[10] = addr[10];
    addr_in.sin6_addr.s6_addr[11] = addr[11];
    addr_in.sin6_addr.s6_addr[12] = addr[12];
    addr_in.sin6_addr.s6_addr[13] = addr[13];
    addr_in.sin6_addr.s6_addr[14] = addr[14];
    addr_in.sin6_addr.s6_addr[15] = addr[15];

    if (sys_bind(fd, (struct sockaddr *) &addr_in, sizeof(struct sockaddr_in6)) < 0)
    {
        a_close (fd);
        return io_unrecoverable_error;
    }

    if (sys_listen(fd, 32) == -1)
    {
        a_close (fd);
        return io_unrecoverable_error;
    }

    *result = fd;

    return io_complete;
}
Пример #17
0
static void *exec_thread(void *arg)
{
    Exec *e = arg;
    for (;;) {
        int p = 0, pid = -1;

        /* creating processor */
        IO *sio = sys_socket(&p);
        char port[8];
        str_print(port, "%d", p);
        char *argv[] = {e->exe, "processor", "-p", port, "-t", e->tx, NULL};

        pid = sys_exec(argv);
        if (!sys_iready(sio, PROC_WAIT_SEC)) {
            sys_log('E', "failed to fork a processor\n");
        } else {
            IO *pio = sys_accept(sio, IO_CHUNK);
            int ok = 1;
            while (ok) {
                pio->stop = 0;
                Conn *c = queue_get(e->runq);

                int pcnt = 0, ccnt = 0;
                sys_proxy(c->io, &ccnt, pio, &pcnt);

                ok = pio->stop == IO_TERM || (ccnt == 0 && !pio->stop);
                if (!ok && pcnt == 0) {
                    int status = http_500(c->io);
                    sys_log('E', "failed with status %d\n", status);
                }

                c->time = sys_millis();
                queue_put(e->waitq, c);
            }
            sys_close(pio);
        }
        sys_close(sio);

        if (pid != -1) {
            sys_kill(pid);
            sys_wait(pid);
        }
    }

    mem_free(e);

    return NULL;
}
Пример #18
0
/*
 * Create new socket/endpoint for communication and returns a descriptor.
 */
PJ_DEF(pj_status_t) pj_sock_socket(int af, int type, int proto, 
				   pj_sock_t *sock_fd)
{
    long result;

    PJ_CHECK_STACK();

    /* Sanity checks. */
    PJ_ASSERT_RETURN(PJ_INVALID_SOCKET == -1 && sock_fd != NULL, PJ_EINVAL);

    /* Initialize returned socket */
    *sock_fd = PJ_INVALID_SOCKET;

    /* Create socket. */
    result = sys_socket(af, type, proto);
    if (result < 0) {
	return PJ_RETURN_OS_ERROR((-result));
    }

    *sock_fd = result;

    return PJ_SUCCESS;
}
Пример #19
0
asmlinkage long compat_sys_socketcall(int call, u32 __user *args)
{
	int ret;
	u32 a[6];
	u32 a0, a1;

	if (call < SYS_SOCKET || call > SYS_SENDMMSG)
		return -EINVAL;
	if (copy_from_user(a, args, nas[call]))
		return -EFAULT;
	a0 = a[0];
	a1 = a[1];

	switch (call) {
	case SYS_SOCKET:
		ret = sys_socket(a0, a1, a[2]);
		break;
	case SYS_BIND:
		ret = sys_bind(a0, compat_ptr(a1), a[2]);
		break;
	case SYS_CONNECT:
		ret = sys_connect(a0, compat_ptr(a1), a[2]);
		break;
	case SYS_LISTEN:
		ret = sys_listen(a0, a1);
		break;
	case SYS_ACCEPT:
		ret = sys_accept4(a0, compat_ptr(a1), compat_ptr(a[2]), 0);
		break;
	case SYS_GETSOCKNAME:
		ret = sys_getsockname(a0, compat_ptr(a1), compat_ptr(a[2]));
		break;
	case SYS_GETPEERNAME:
		ret = sys_getpeername(a0, compat_ptr(a1), compat_ptr(a[2]));
		break;
	case SYS_SOCKETPAIR:
		ret = sys_socketpair(a0, a1, a[2], compat_ptr(a[3]));
		break;
	case SYS_SEND:
		ret = sys_send(a0, compat_ptr(a1), a[2], a[3]);
		break;
	case SYS_SENDTO:
		ret = sys_sendto(a0, compat_ptr(a1), a[2], a[3], compat_ptr(a[4]), a[5]);
		break;
	case SYS_RECV:
		ret = compat_sys_recv(a0, compat_ptr(a1), a[2], a[3]);
		break;
	case SYS_RECVFROM:
		ret = compat_sys_recvfrom(a0, compat_ptr(a1), a[2], a[3],
					  compat_ptr(a[4]), compat_ptr(a[5]));
		break;
	case SYS_SHUTDOWN:
		ret = sys_shutdown(a0, a1);
		break;
	case SYS_SETSOCKOPT:
		ret = compat_sys_setsockopt(a0, a1, a[2],
				compat_ptr(a[3]), a[4]);
		break;
	case SYS_GETSOCKOPT:
		ret = compat_sys_getsockopt(a0, a1, a[2],
				compat_ptr(a[3]), compat_ptr(a[4]));
		break;
	case SYS_SENDMSG:
		ret = compat_sys_sendmsg(a0, compat_ptr(a1), a[2]);
		break;
	case SYS_SENDMMSG:
		ret = compat_sys_sendmmsg(a0, compat_ptr(a1), a[2], a[3]);
		break;
	case SYS_RECVMSG:
		ret = compat_sys_recvmsg(a0, compat_ptr(a1), a[2]);
		break;
	case SYS_RECVMMSG:
		ret = compat_sys_recvmmsg(a0, compat_ptr(a1), a[2], a[3],
					  compat_ptr(a[4]));
		break;
	case SYS_ACCEPT4:
		ret = sys_accept4(a0, compat_ptr(a1), compat_ptr(a[2]), a[3]);
		break;
	default:
		ret = -EINVAL;
		break;
	}
	return ret;
}
Пример #20
0
static void ListerThread(struct ListerParams *args) {
  int                found_parent = 0;
  pid_t              clone_pid  = sys_gettid(), ppid = sys_getppid();
  char               proc_self_task[80], marker_name[48], *marker_path;
  const char         *proc_paths[3];
  const char *const  *proc_path = proc_paths;
  int                proc = -1, marker = -1, num_threads = 0;
  int                max_threads = 0, sig;
  struct kernel_stat marker_sb, proc_sb;
  stack_t            altstack;

  /* Create "marker" that we can use to detect threads sharing the same
   * address space and the same file handles. By setting the FD_CLOEXEC flag
   * we minimize the risk of misidentifying child processes as threads;
   * and since there is still a race condition,  we will filter those out
   * later, anyway.
   */
  if ((marker = sys_socket(PF_LOCAL, SOCK_DGRAM, 0)) < 0 ||
      sys_fcntl(marker, F_SETFD, FD_CLOEXEC) < 0) {
  failure:
    args->result = -1;
    args->err    = errno;
    if (marker >= 0)
      NO_INTR(sys_close(marker));
    sig_marker = marker = -1;
    if (proc >= 0)
      NO_INTR(sys_close(proc));
    sig_proc = proc = -1;
    sys__exit(1);
  }

  /* Compute search paths for finding thread directories in /proc            */
  local_itoa(strrchr(strcpy(proc_self_task, "/proc/"), '\000'), ppid);
  strcpy(marker_name, proc_self_task);
  marker_path = marker_name + strlen(marker_name);
  strcat(proc_self_task, "/task/");
  proc_paths[0] = proc_self_task; /* /proc/$$/task/                          */
  proc_paths[1] = "/proc/";       /* /proc/                                  */
  proc_paths[2] = NULL;

  /* Compute path for marker socket in /proc                                 */
  local_itoa(strcpy(marker_path, "/fd/") + 4, marker);
  if (sys_stat(marker_name, &marker_sb) < 0) {
    goto failure;
  }

  /* Catch signals on an alternate pre-allocated stack. This way, we can
   * safely execute the signal handler even if we ran out of memory.
   */
  memset(&altstack, 0, sizeof(altstack));
  altstack.ss_sp    = args->altstack_mem;
  altstack.ss_flags = 0;
  altstack.ss_size  = ALT_STACKSIZE;
  sys_sigaltstack(&altstack, (const stack_t *)NULL);

  /* Some kernels forget to wake up traced processes, when the
   * tracer dies.  So, intercept synchronous signals and make sure
   * that we wake up our tracees before dying. It is the caller's
   * responsibility to ensure that asynchronous signals do not
   * interfere with this function.
   */
  sig_marker = marker;
  sig_proc   = -1;
  for (sig = 0; sig < sizeof(sync_signals)/sizeof(*sync_signals); sig++) {
    struct kernel_sigaction sa;
    memset(&sa, 0, sizeof(sa));
    sa.sa_sigaction_ = SignalHandler;
    sys_sigfillset(&sa.sa_mask);
    sa.sa_flags      = SA_ONSTACK|SA_SIGINFO|SA_RESETHAND;
    sys_sigaction(sync_signals[sig], &sa, (struct kernel_sigaction *)NULL);
  }
  
  /* Read process directories in /proc/...                                   */
  for (;;) {
    /* Some kernels know about threads, and hide them in "/proc"
     * (although they are still there, if you know the process
     * id). Threads are moved into a separate "task" directory. We
     * check there first, and then fall back on the older naming
     * convention if necessary.
     */
    if ((sig_proc = proc = c_open(*proc_path, O_RDONLY|O_DIRECTORY, 0)) < 0) {
      if (*++proc_path != NULL)
        continue;
      goto failure;
    }
    if (sys_fstat(proc, &proc_sb) < 0)
      goto failure;
    
    /* Since we are suspending threads, we cannot call any libc
     * functions that might acquire locks. Most notably, we cannot
     * call malloc(). So, we have to allocate memory on the stack,
     * instead. Since we do not know how much memory we need, we
     * make a best guess. And if we guessed incorrectly we retry on
     * a second iteration (by jumping to "detach_threads").
     *
     * Unless the number of threads is increasing very rapidly, we
     * should never need to do so, though, as our guestimate is very
     * conservative.
     */
    if (max_threads < proc_sb.st_nlink + 100)
      max_threads = proc_sb.st_nlink + 100;
    
    /* scope */ {
      pid_t pids[max_threads];
      int   added_entries = 0;
      sig_num_threads     = num_threads;
      sig_pids            = pids;
      for (;;) {
        struct kernel_dirent *entry;
        char buf[4096];
        ssize_t nbytes = sys_getdents(proc, (struct kernel_dirent *)buf,
                                      sizeof(buf));
        if (nbytes < 0)
          goto failure;
        else if (nbytes == 0) {
          if (added_entries) {
            /* Need to keep iterating over "/proc" in multiple
             * passes until we no longer find any more threads. This
             * algorithm eventually completes, when all threads have
             * been suspended.
             */
            added_entries = 0;
            sys_lseek(proc, 0, SEEK_SET);
            continue;
          }
          break;
        }
        for (entry = (struct kernel_dirent *)buf;
             entry < (struct kernel_dirent *)&buf[nbytes];
             entry = (struct kernel_dirent *)((char *)entry+entry->d_reclen)) {
          if (entry->d_ino != 0) {
            const char *ptr = entry->d_name;
            pid_t pid;
            
            /* Some kernels hide threads by preceding the pid with a '.'     */
            if (*ptr == '.')
              ptr++;
            
            /* If the directory is not numeric, it cannot be a
             * process/thread
             */
            if (*ptr < '0' || *ptr > '9')
              continue;
            pid = local_atoi(ptr);

            /* Attach (and suspend) all threads                              */
            if (pid && pid != clone_pid) {
              struct kernel_stat tmp_sb;
              char fname[entry->d_reclen + 48];
              strcat(strcat(strcpy(fname, "/proc/"),
                            entry->d_name), marker_path);
              
              /* Check if the marker is identical to the one we created      */
              if (sys_stat(fname, &tmp_sb) >= 0 &&
                  marker_sb.st_ino == tmp_sb.st_ino) {
                long i, j;

                /* Found one of our threads, make sure it is no duplicate    */
                for (i = 0; i < num_threads; i++) {
                  /* Linear search is slow, but should not matter much for
                   * the typically small number of threads.
                   */
                  if (pids[i] == pid) {
                    /* Found a duplicate; most likely on second pass         */
                    goto next_entry;
                  }
                }
                
                /* Check whether data structure needs growing                */
                if (num_threads >= max_threads) {
                  /* Back to square one, this time with more memory          */
                  NO_INTR(sys_close(proc));
                  goto detach_threads;
                }

                /* Attaching to thread suspends it                           */
                pids[num_threads++] = pid;
                sig_num_threads     = num_threads;
                if (sys_ptrace(PTRACE_ATTACH, pid, (void *)0,
                               (void *)0) < 0) {
                  /* If operation failed, ignore thread. Maybe it
                   * just died?  There might also be a race
                   * condition with a concurrent core dumper or
                   * with a debugger. In that case, we will just
                   * make a best effort, rather than failing
                   * entirely.
                   */
                  num_threads--;
                  sig_num_threads = num_threads;
                  goto next_entry;
                }
                while (sys_waitpid(pid, (int *)0, __WALL) < 0) {
                  if (errno != EINTR) {
                    sys_ptrace_detach(pid);
                    num_threads--;
                    sig_num_threads = num_threads;
                    goto next_entry;
                  }
                }
                
                if (sys_ptrace(PTRACE_PEEKDATA, pid, &i, &j) || i++ != j ||
                    sys_ptrace(PTRACE_PEEKDATA, pid, &i, &j) || i   != j) {
                  /* Address spaces are distinct, even though both
                   * processes show the "marker". This is probably
                   * a forked child process rather than a thread.
                   */
                  sys_ptrace_detach(pid);
                  num_threads--;
                  sig_num_threads = num_threads;
                } else {
                  found_parent |= pid == ppid;
                  added_entries++;
                }
              }
            }
          }
        next_entry:;
        }
      }
      NO_INTR(sys_close(proc));
      sig_proc = proc = -1;

      /* If we failed to find any threads, try looking somewhere else in
       * /proc. Maybe, threads are reported differently on this system.
       */
      if (num_threads > 1 || !*++proc_path) {
        NO_INTR(sys_close(marker));
        sig_marker = marker = -1;

        /* If we never found the parent process, something is very wrong.
         * Most likely, we are running in debugger. Any attempt to operate
         * on the threads would be very incomplete. Let's just report an
         * error to the caller.
         */
        if (!found_parent) {
          ResumeAllProcessThreads(num_threads, pids);
          sys__exit(3);
        }

        /* Now we are ready to call the callback,
         * which takes care of resuming the threads for us.
         */
        args->result = args->callback(args->parameter, num_threads,
                                      pids, args->ap);
        args->err = errno;

        /* Callback should have resumed threads, but better safe than sorry  */
        if (ResumeAllProcessThreads(num_threads, pids)) {
          /* Callback forgot to resume at least one thread, report error     */
          args->err    = EINVAL;
          args->result = -1;
        }

        sys__exit(0);
      }
    detach_threads:
      /* Resume all threads prior to retrying the operation                  */
      ResumeAllProcessThreads(num_threads, pids);
      sig_pids = NULL;
      num_threads = 0;
      sig_num_threads = num_threads;
      max_threads += 100;
    }
  }
}
Пример #21
0
DEFINE_SYSCALL(socketcall, int, call, uintptr_t *, args)
{
	if (call < 1 || call > SYS_SENDMMSG)
		return -L_EINVAL;
	if (!mm_check_read(args, nargs[call]))
		return -L_EFAULT;
	switch (call)
	{
	case SYS_SOCKET:
		return sys_socket(args[0], args[1], args[2]);

	case SYS_BIND:
		return sys_bind(args[0], (const struct sockaddr *)args[1], args[2]);

	case SYS_CONNECT:
		return sys_connect(args[0], (const struct sockaddr *)args[1], args[2]);

	case SYS_LISTEN:
		return sys_listen(args[0], args[1]);

	case SYS_ACCEPT:
		return sys_accept(args[0], (struct sockaddr *)args[1], (int *)args[2]);

	case SYS_GETSOCKNAME:
		return sys_getsockname(args[0], (struct sockaddr *)args[1], (int *)args[2]);

	case SYS_GETPEERNAME:
		return sys_getpeername(args[0], (struct sockaddr *)args[1], (int *)args[2]);

	case SYS_SEND:
		return sys_send(args[0], (const void *)args[1], args[2], args[3]);

	case SYS_RECV:
		return sys_recv(args[0], (void *)args[1], args[2], args[3]);

	case SYS_SENDTO:
		return sys_sendto(args[0], (const void *)args[1], args[2], args[3], (const struct sockaddr *)args[4], args[5]);
		
	case SYS_RECVFROM:
		return sys_recvfrom(args[0], (void *)args[1], args[2], args[3], (struct sockaddr *)args[4], (int *)args[5]);

	case SYS_SHUTDOWN:
		return sys_shutdown(args[0], args[1]);

	case SYS_SETSOCKOPT:
		return sys_setsockopt(args[0], args[1], args[2], (const void *)args[3], args[4]);

	case SYS_GETSOCKOPT:
		return sys_getsockopt(args[0], args[1], args[2], (void *)args[3], (int *)args[4]);

	case SYS_SENDMSG:
		return sys_sendmsg(args[0], (const struct msghdr *)args[1], args[2]);

	case SYS_RECVMSG:
		return sys_recvmsg(args[0], (struct msghdr *)args[1], args[2]);

	case SYS_ACCEPT4:
		return sys_accept4(args[0], (struct sockaddr *)args[1], (int *)args[2], args[3]);

	case SYS_SENDMMSG:
		return sys_sendmmsg(args[0], (struct mmsghdr *)args[1], args[2], args[3]);

	default:
	{
		log_error("Unimplemented socketcall: %d", call);
		return -L_EINVAL;
	}
	}
}
Пример #22
0
int
so_socksys(struct socksysreq *req)
{
	int err = -EINVAL;
	int cmd = req->args[0];

	if ((1 << cmd) & ((1 << SO_ACCEPT) | (1 << SO_BIND) | (1 << SO_CONNECT) |
			  (1 << SO_GETPEERNAME) | (1 << SO_GETSOCKNAME) | (1 << SO_GETSOCKOPT) |
			  (1 << SO_LISTEN) | (1 << SO_RECV) | (1 << SO_RECVFROM) | (1 << SO_SEND) |
			  (1 << SO_SENDTO) | (1 << SO_SETSOCKOPT) | (1 << SO_SHUTDOWN) |
			  (1 << SO_RECVMSG) | (1 << SO_SENDMSG))) {
		int fd = req->args[1];

		(void) fd;
		/* These are all socket related and accept a file (socket) descriptor as their
		   first argument.  In situations where we are incapable of providing back a real
		   socket, we must here first distinguish if the file descriptor corresponds to a
		   socket or a stream. */
#if 0
		if (it_is_a_socket) {
#endif
			/* In this case, we have a real socket from the operating system's
			   perspective and we can simply pass the arguments to the appropriate
			   system call. */
#if 0
			switch (cmd) {
			case SO_ACCEPT:
				/* FIXME: 32/64 conversion */
				err = sys_accept(fd, (struct sockaddr *) req->args[2],
						 req->args[3]);
				break;
			case SO_BIND:
				/* FIXME: 32/64 conversion */
				err = sys_bind(fd, (struct sockaddr *) req->args[2], req->args[3]);
				break;
			case SO_CONNECT:
				/* FIXME: 32/64 conversion */
				err = sys_connect(fd, (struct sockaddr *) req->args[2],
						  req->args[3]);
				break;
			case SO_GETPEERNAME:
				/* FIXME: 32/64 conversion */
				err = sys_getpeername(fd, (struct sockaddr *) req->args[2],
						      (int *) req->args[3]);
				break;
			case SO_GETSOCKNAME:
				/* FIXME: 32/64 conversion */
				err = sys_getsockname(fd, (struct sockaddr *) req->args[2],
						      (int *) req->args[3]);
				break;
			case SO_GETSOCKOPT:
				/* FIXME: 32/64 conversion */
				err = sys_getsockopt(fd, req->args[2], req->args[3],
						     (char *) req->args[4], (int *) req->args[5]);
				break;
			case SO_LISTEN:
				/* FIXME: 32/64 conversion */
				err = sys_listen(fd, req->args[2]);
				break;
			case SO_RECV:
				/* FIXME: 32/64 conversion */
				err = sys_recv(fd, (void *) req->args[2], req->args[3],
					       req->args[4]);
				break;
			case SO_RECVFROM:
				/* FIXME: 32/64 conversion */
				err = sys_recvfrom(fd, (void *) req->args[2], req->args[3],
						   req->args[4], (struct sockaddr *) req->args[5],
						   (int *) req->args[6]);
				break;
			case SO_SEND:
				/* FIXME: 32/64 conversion */
				err = sys_send(fd, (void *) req->args[2], req->args[3],
					       req->args[4]);
				break;
			case SO_SENDTO:
				/* FIXME: 32/64 conversion */
				err = sys_sendto(fd, (void *) req->args[2], req->args[3],
						 req->args[4], (struct sockaddr *) req->args[5],
						 req->args[6]);
				break;
			case SO_SETSOCKOPT:
				/* FIXME: 32/64 conversion */
				err = sys_setsockopt(fd, req->args[2], req->args[3],
						     (char *) req->args[4], req->args[5]);
				break;
			case SO_SHUTDOWN:
				/* FIXME: 32/64 conversion */
				err = sys_shutdown(fd, req->args[2]);
				break;
			case SO_RECVMSG:
				/* FIXME: 32/64 conversion */
				err = sys_recvmsg(fd, (struct msghdr *) req->args[2], req->args[3]);
				break;
			case SO_SENDMSG:
				/* FIXME: 32/64 conversion */
				err = sys_sendmsg(fd, (struct msghdr *) req->args[2], req->args[3]);
				break;
			}
#endif
#if 0
		} else {
			/* In this case, we do not have a real socket, but have a TPI stream from
			   the operating system's perspective, and we will directly call the
			   associated TPI routine. */
			switch (cmd) {
			case SO_ACCEPT:
				/* FIXME: 32/64 conversion */
				err = tpi_accept(fd, (struct sockaddr *) req->args[2],
						 req->args[3]);
				break;
			case SO_BIND:
				/* FIXME: 32/64 conversion */
				err = tpi_bind(fd, (struct sockaddr *) req->args[2], req->args[3]);
				break;
			case SO_CONNECT:
				/* FIXME: 32/64 conversion */
				err = tpi_connect(fd, (struct sockaddr *) req->args[2],
						  req->args[3]);
				break;
			case SO_GETPEERNAME:
				/* FIXME: 32/64 conversion */
				err = tpi_getpeername(fd, (struct sockaddr *) req->args[2],
						      (int *) req->args[3]);
				break;
			case SO_GETSOCKNAME:
				/* FIXME: 32/64 conversion */
				err = tpi_getsockname(fd, (struct sockaddr *) req->args[2],
						      (int *) req->args[3]);
				break;
			case SO_GETSOCKOPT:
				/* FIXME: 32/64 conversion */
				err = tpi_getsockopt(fd, req->args[2], req->args[3],
						     (char *) req->args[4], (int *) req->args[5]);
				break;
			case SO_LISTEN:
				/* FIXME: 32/64 conversion */
				err = tpi_listen(fd, req->args[2]);
				break;
			case SO_RECV:
				/* FIXME: 32/64 conversion */
				err = tpi_recv(fd, (void *) req->args[2], req->args[3],
					       req->args[4]);
				break;
			case SO_RECVFROM:
				/* FIXME: 32/64 conversion */
				err = tpi_recvfrom(fd, (void *) req->args[2], req->args[3],
						   req->args[4], (struct sockaddr *) req->args[5],
						   (int *) req->args[6]);
				break;
			case SO_SEND:
				/* FIXME: 32/64 conversion */
				err = tpi_send(fd, (void *) req->args[2], req->args[3],
					       req->args[4]);
				break;
			case SO_SENDTO:
				/* FIXME: 32/64 conversion */
				err = tpi_sendto(fd, (void *) req->args[2], req->args[3],
						 req->args[4], (struct sockaddr *) req->args[5],
						 req->args[6]);
				break;
			case SO_SETSOCKOPT:
				/* FIXME: 32/64 conversion */
				err = tpi_setsockopt(fd, req->args[2], req->args[3],
						     (char *) req->args[4], req->args[5]);
				break;
			case SO_SHUTDOWN:
				/* FIXME: 32/64 conversion */
				err = tpi_shutdown(fd, req->args[2]);
				break;
			case SO_RECVMSG:
				/* FIXME: 32/64 conversion */
				err = tpi_recvmsg(fd, (struct msghdr *) req->args[2], req->args[3]);
				break;
			case SO_SENDMSG:
				/* FIXME: 32/64 conversion */
				err = tpi_sendmsg(fd, (struct msghdr *) req->args[2], req->args[3]);
				break;
			}
		}
#endif
	}
	if ((1 << cmd) & ((1 << SO_SOCKET) | (1 << SO_SOCKPAIR) | (1 << SO_SELECT) |
			  (1 << SO_GETIPDOMAIN) | (1 << SO_SETIPDOMAIN) | (1 << SO_ADJTIME) |
			  (1 << SO_SETREUID) | (1 << SO_SETREGID) | (1 << SO_GETTIME) |
			  (1 << SO_SETTIME) | (1 << SO_GETITIMER) | (1 << SO_SETITIMER))) {
		/* These are BSD compatibiltiy functions and are how we create sockets in the first
		   place.  The BSD compatibility functions all have system calls in Linux, but we
		   provide them for backward compatibility (to what!?). */
#if 0
		switch (cmd) {
		case SO_SOCKET:
			/* FIXME: 32/64 conversion */
			/* XXX: don't think so..., after checking for a stream */
			err = sys_socket(req->args[1], req->args[2], req->args[3]);
			break;
		case SO_SOCKPAIR:
			/* FIXME: 32/64 conversion */
			/* XXX: don't think so..., after checking for a stream */
			err = sys_socketpair(req->args[1], req->args[2], req->args[3],
					     (int *) req->args[4]);
			err = -EOPNOTSUPP;
			break;
		case SO_SELECT:
			/* FIXME: 32/64 conversion */
			err = sys_select(req->args[1], (fd_set *) req->args[2],
					 (fd_set *) req->args[3], (fd_set *) req->args[4],
					 (struct timeval *) req->args[5]);
			break;
		case SO_GETIPDOMAIN:
			/* FIXME: 32/64 conversion */
			todo(("Process SO_GETIPDOMAIN for compatibility.\n"));
			/* does not exist in Linux, need to use sys_newuname and copy the
			   domainname portion */
			err = -ENOSYS;
			break;
		case SO_SETIPDOMAIN:
			/* FIXME: 32/64 conversion */
			err = sys_setdomainname((char *) req->args[1], req->args[2]);
			break;
		case SO_ADJTIME:
			/* FIXME: 32/64 conversion */
			err = sys_admtimex((struct timex *) req->args[1]);
			break;
		case SO_SETREUID:
			/* FIXME: 32/64 conversion */
			err = sys_setreuid(req->args[1], req->args[2]);
			break;
		case SO_SETREGID:
			/* FIXME: 32/64 conversion */
			err = sys_setregid(req->args[1], req->args[2]);
			break;
		case SO_GETTIME:
			/* FIXME: 32/64 conversion */
			err = sys_gettimeofday((struct timeval *) req->args[1],
					       (struct timezone *) req->args[2]);
			break;
		case SO_SETTIME:
			/* FIXME: 32/64 conversion */
			err = sys_settimeofday((struct timeval *) req->args[1],
					       (struct timezone *) req->args[2]);
			break;
		case SO_GETITIMER:
			/* FIXME: 32/64 conversion */
			err = sys_getitimer(req->args[1], (struct itimerval *) req->args[2]);
			break;
		case SO_SETITIMER:
			/* FIXME: 32/64 conversion */
			err = sys_getitimer(req->args[1], (struct itimerval *) req->args[2],
					    (struct itimerval *) req->args[3]);
			break;
		}
#endif
	}

	return (err);
}