Пример #1
0
int
linux_sysctl(struct thread *td, struct linux_sysctl_args *args)
{
	struct l___sysctl_args la;
	struct sbuf *sb;
	l_int *mib;
	int error, i;

	error = copyin(args->args, &la, sizeof(la));
	if (error)
		return (error);

	if (la.nlen <= 0 || la.nlen > LINUX_CTL_MAXNAME)
		return (ENOTDIR);

	mib = malloc(la.nlen * sizeof(l_int), M_TEMP, M_WAITOK);
	error = copyin(PTRIN(la.name), mib, la.nlen * sizeof(l_int));
	if (error) {
		free(mib, M_TEMP);
		return (error);
	}

	switch (mib[0]) {
	case LINUX_CTL_KERN:
		if (la.nlen < 2)
			break;

		switch (mib[1]) {
		case LINUX_KERN_VERSION:
			error = handle_string(&la, version);
			free(mib, M_TEMP);
			return (error);
		default:
			break;
		}
		break;
	default:
		break;
	}

	sb = sbuf_new(NULL, NULL, 20 + la.nlen * 5, SBUF_AUTOEXTEND);
	if (sb == NULL) {
		linux_msg(td, "sysctl is not implemented");
	} else {
		sbuf_printf(sb, "sysctl ");
		for (i = 0; i < la.nlen; i++)
			sbuf_printf(sb, "%c%d", (i) ? ',' : '{', mib[i]);
		sbuf_printf(sb, "} is not implemented");
		sbuf_finish(sb);
		linux_msg(td, "%s", sbuf_data(sb));
		sbuf_delete(sb);
	}

	free(mib, M_TEMP);
	return (ENOTDIR);
}
Пример #2
0
void
linux_thread_detach(struct thread *td)
{
	struct linux_sys_futex_args cup;
	struct linux_emuldata *em;
	int *child_clear_tid;
	int error;

	em = em_find(td);
	KASSERT(em != NULL, ("thread_detach: emuldata not found.\n"));

	LINUX_CTR1(thread_detach, "thread(%d)", em->em_tid);

	release_futexes(td, em);

	child_clear_tid = em->child_clear_tid;

	if (child_clear_tid != NULL) {

		LINUX_CTR2(thread_detach, "thread(%d) %p",
		    em->em_tid, child_clear_tid);
	
		error = suword32(child_clear_tid, 0);
		if (error != 0)
			return;

		cup.uaddr = child_clear_tid;
		cup.op = LINUX_FUTEX_WAKE;
		cup.val = 1;		/* wake one */
		cup.timeout = NULL;
		cup.uaddr2 = NULL;
		cup.val3 = 0;
		error = linux_sys_futex(td, &cup);
		/*
		 * this cannot happen at the moment and if this happens it
		 * probably means there is a user space bug
		 */
		if (error != 0)
			linux_msg(td, "futex stuff in thread_detach failed.");
	}
}
Пример #3
0
int
linux_shmctl(struct thread *td, struct linux_shmctl_args *args)
{
    struct l_shmid_ds linux_shmid;
	struct l_shminfo linux_shminfo;
	struct l_shm_info linux_shm_info;
	struct shmid_ds bsd_shmid;
    int error;

    switch (args->cmd & ~LINUX_IPC_64) {

	case LINUX_IPC_INFO: {
	    struct shminfo bsd_shminfo;

	    /* Perform shmctl wanting removed segments lookup */
	    error = kern_shmctl(td, args->shmid, IPC_INFO,
	        (void *)&bsd_shminfo, NULL);
	    if (error)
		return error;
	
	    bsd_to_linux_shminfo(&bsd_shminfo, &linux_shminfo);

	    return (linux_shminfo_pushdown(args->cmd & LINUX_IPC_64,
	       &linux_shminfo, PTRIN(args->buf)));
	}

	case LINUX_SHM_INFO: {
	    struct shm_info bsd_shm_info;

	    /* Perform shmctl wanting removed segments lookup */
	    error = kern_shmctl(td, args->shmid, SHM_INFO,
	        (void *)&bsd_shm_info, NULL);
	    if (error)
		return error;

	    bsd_to_linux_shm_info(&bsd_shm_info, &linux_shm_info);

	    return copyout(&linux_shm_info, PTRIN(args->buf),
	        sizeof(struct l_shm_info));
	}

	case LINUX_IPC_STAT:
	    /* Perform shmctl wanting removed segments lookup */
	    error = kern_shmctl(td, args->shmid, IPC_STAT,
	        (void *)&bsd_shmid, NULL);
	    if (error)
		return error;
		
	    bsd_to_linux_shmid_ds(&bsd_shmid, &linux_shmid);

	    return (linux_shmid_pushdown(args->cmd & LINUX_IPC_64,
	  &linux_shmid, PTRIN(args->buf)));

    case LINUX_SHM_STAT:
	/* Perform shmctl wanting removed segments lookup */
	error = kern_shmctl(td, args->shmid, IPC_STAT,
	    (void *)&bsd_shmid, NULL);
	if (error)
		return error;
		
	bsd_to_linux_shmid_ds(&bsd_shmid, &linux_shmid);
	
	return (linux_shmid_pushdown(args->cmd & LINUX_IPC_64,
	   &linux_shmid, PTRIN(args->buf)));

    case LINUX_IPC_SET:
	error = linux_shmid_pullup(args->cmd & LINUX_IPC_64,
	  &linux_shmid, PTRIN(args->buf));
	if (error)
    		return error;

	linux_to_bsd_shmid_ds(&linux_shmid, &bsd_shmid);

	/* Perform shmctl wanting removed segments lookup */
	return kern_shmctl(td, args->shmid, IPC_SET,
	    (void *)&bsd_shmid, NULL);

    case LINUX_IPC_RMID: {
	void *buf;
		
	if (args->buf == 0)
    		buf = NULL;
	else {
    		error = linux_shmid_pullup(args->cmd & LINUX_IPC_64,
		    &linux_shmid, PTRIN(args->buf));
		if (error)
			return error;
		linux_to_bsd_shmid_ds(&linux_shmid, &bsd_shmid);
		buf = (void *)&bsd_shmid;
	}
	return kern_shmctl(td, args->shmid, IPC_RMID, buf, NULL);
    }

    case LINUX_SHM_LOCK:
    case LINUX_SHM_UNLOCK:
    default:
	linux_msg(td, "ipc typ=%d not implemented", args->cmd & ~LINUX_IPC_64);
	return EINVAL;
    }
}
Пример #4
0
int
linux_semctl(struct thread *td, struct linux_semctl_args *args)
{
	struct l_semid_ds linux_semid;
	struct l_seminfo linux_seminfo;
	struct semid_ds semid;
	union semun semun;
	register_t rval;
	int cmd, error;

	switch (args->cmd & ~LINUX_IPC_64) {
	case LINUX_IPC_RMID:
		cmd = IPC_RMID;
		break;
	case LINUX_GETNCNT:
		cmd = GETNCNT;
		break;
	case LINUX_GETPID:
		cmd = GETPID;
		break;
	case LINUX_GETVAL:
		cmd = GETVAL;
		break;
	case LINUX_GETZCNT:
		cmd = GETZCNT;
		break;
	case LINUX_SETVAL:
		cmd = SETVAL;
		semun.val = args->arg.val;
		break;
	case LINUX_IPC_SET:
		cmd = IPC_SET;
		error = linux_semid_pullup(args->cmd & LINUX_IPC_64,
		    &linux_semid, PTRIN(args->arg.buf));
		if (error)
			return (error);
		linux_to_bsd_semid_ds(&linux_semid, &semid);
		semun.buf = &semid;
		return (kern_semctl(td, args->semid, args->semnum, cmd, &semun,
		    td->td_retval));
	case LINUX_IPC_STAT:
	case LINUX_SEM_STAT:
		if ((args->cmd & ~LINUX_IPC_64) == LINUX_IPC_STAT)
			cmd = IPC_STAT;
		else
			cmd = SEM_STAT;
		semun.buf = &semid;
		error = kern_semctl(td, args->semid, args->semnum, cmd, &semun,
		    &rval);
		if (error)
			return (error);
		bsd_to_linux_semid_ds(&semid, &linux_semid);
		error = linux_semid_pushdown(args->cmd & LINUX_IPC_64,
		    &linux_semid, PTRIN(args->arg.buf));
		if (error == 0)
			td->td_retval[0] = (cmd == SEM_STAT) ? rval : 0;
		return (error);
	case LINUX_IPC_INFO:
	case LINUX_SEM_INFO:
		bcopy(&seminfo, &linux_seminfo, sizeof(linux_seminfo) );
/* XXX BSD equivalent?
#define used_semids 10
#define used_sems 10
		linux_seminfo.semusz = used_semids;
		linux_seminfo.semaem = used_sems;
*/
		error = copyout(&linux_seminfo,
		    PTRIN(args->arg.buf), sizeof(linux_seminfo));
		if (error)
			return error;
		td->td_retval[0] = seminfo.semmni;
		return 0;			/* No need for __semctl call */
	case LINUX_GETALL:
		cmd = GETALL;
		semun.val = args->arg.val;
		break;
	case LINUX_SETALL:
		cmd = SETALL;
		semun.val = args->arg.val;
		break;
	default:
		linux_msg(td, "ipc type %d is not implemented",
		  args->cmd & ~LINUX_IPC_64);
		return EINVAL;
	}
	return (kern_semctl(td, args->semid, args->semnum, cmd, &semun,
	    td->td_retval));
}
Пример #5
0
int
linux_semctl(struct thread *td, struct linux_semctl_args *args)
{
    struct l_semid_ds linux_semid;
    struct l_seminfo linux_seminfo;
    struct semid_ds semid;
    union semun semun;
    register_t rval;
    int cmd, error;

    switch (args->cmd & ~LINUX_IPC_64) {
    case LINUX_IPC_RMID:
        cmd = IPC_RMID;
        break;
    case LINUX_GETNCNT:
        cmd = GETNCNT;
        break;
    case LINUX_GETPID:
        cmd = GETPID;
        break;
    case LINUX_GETVAL:
        cmd = GETVAL;
        break;
    case LINUX_GETZCNT:
        cmd = GETZCNT;
        break;
    case LINUX_SETVAL:
        cmd = SETVAL;
        semun.val = args->arg.val;
        break;
    case LINUX_IPC_SET:
        cmd = IPC_SET;
        error = linux_semid_pullup(args->cmd & LINUX_IPC_64,
                                   &linux_semid, PTRIN(args->arg.buf));
        if (error)
            return (error);
        linux_to_bsd_semid_ds(&linux_semid, &semid);
        semun.buf = &semid;
        return (kern_semctl(td, args->semid, args->semnum, cmd, &semun,
                            td->td_retval));
    case LINUX_IPC_STAT:
    case LINUX_SEM_STAT:
        if ((args->cmd & ~LINUX_IPC_64) == LINUX_IPC_STAT)
            cmd = IPC_STAT;
        else
            cmd = SEM_STAT;
        semun.buf = &semid;
        error = kern_semctl(td, args->semid, args->semnum, cmd, &semun,
                            &rval);
        if (error)
            return (error);
        bsd_to_linux_semid_ds(&semid, &linux_semid);
        error = linux_semid_pushdown(args->cmd & LINUX_IPC_64,
                                     &linux_semid, PTRIN(args->arg.buf));
        if (error == 0)
            td->td_retval[0] = (cmd == SEM_STAT) ? rval : 0;
        return (error);
    case LINUX_IPC_INFO:
    case LINUX_SEM_INFO:
        bcopy(&seminfo, &linux_seminfo.semmni, sizeof(linux_seminfo) -
              sizeof(linux_seminfo.semmap) );
        /*
         * Linux does not use the semmap field but populates it with
         * the defined value from SEMMAP, which really is redefined to
         * SEMMNS, which they define as SEMMNI * SEMMSL.  Try to
         * simulate this returning our dynamic semmns value.
         */
        linux_seminfo.semmap = linux_seminfo.semmns;
        /* XXX BSD equivalent?
        #define used_semids 10
        #define used_sems 10
        		linux_seminfo.semusz = used_semids;
        		linux_seminfo.semaem = used_sems;
        */
        error = copyout(&linux_seminfo,
                        PTRIN(args->arg.buf), sizeof(linux_seminfo));
        if (error)
            return (error);
        td->td_retval[0] = seminfo.semmni;
        return (0);			/* No need for __semctl call */
    case LINUX_GETALL:
        cmd = GETALL;
        semun.val = args->arg.val;
        break;
    case LINUX_SETALL:
        cmd = SETALL;
        semun.val = args->arg.val;
        break;
    default:
        linux_msg(td, "ipc type %d is not implemented",
                  args->cmd & ~LINUX_IPC_64);
        return (EINVAL);
    }
    return (kern_semctl(td, args->semid, args->semnum, cmd, &semun,
                        td->td_retval));
}