Esempio n. 1
0
int
sys_shmget(struct proc *p, void *v, register_t *retval)
{
	struct sys_shmget_args /* {
		syscallarg(key_t) key;
		syscallarg(size_t) size;
		syscallarg(int) shmflg;
	} */ *uap = v;
	int segnum, mode, error;

	mode = SCARG(uap, shmflg) & ACCESSPERMS;

	if (SCARG(uap, key) != IPC_PRIVATE) {
	again:
		segnum = shm_find_segment_by_key(SCARG(uap, key));
		if (segnum >= 0)
			return (shmget_existing(p, uap, mode, segnum, retval));
		if ((SCARG(uap, shmflg) & IPC_CREAT) == 0) 
			return (ENOENT);
	}
	error = shmget_allocate_segment(p, uap, mode, retval);
	if (error == EAGAIN)
		goto again;
	return (error);
}
Esempio n. 2
0
/* Handle a shmget() request. */
int
handle_shmget(pid_t pid, struct shmget_msg *shmget_msg,
		struct cmsgcred *cred ) {
	int segnum, mode, error;
	struct shmid_ds *shmseg;
	struct shm_handle *handle;

	//if (!jail_sysvipc_allowed && td->td_cmsgcred->cr_prison != NULL)
	//	return (ENOSYS);
	mode = shmget_msg->shmflg & ACCESSPERMS;

	sysvd_print("ask for key = %ld\n", shmget_msg->key);
	shmget_msg->key = (shmget_msg->key & 0x3FFF) |
		(shmget_msg->type << 30);
	sysvd_print("ask for key = %ld\n", shmget_msg->key);

	if (shmget_msg->key != IPC_PRIVATE) {
		//again:
		segnum = shm_find_segment_by_key(shmget_msg->key);
		if (segnum >= 0) {
			error = shmget_existing(shmget_msg, mode, segnum, cred);
			//TODO if daemon is multithreading
			//if (error == EAGAIN)
			//	goto again;
			goto done;
		}
		if ((shmget_msg->shmflg & IPC_CREAT) == 0) {
			error = -ENOENT;
			goto done_err;
		}
	}
	error = shmget_allocate_segment(pid, shmget_msg, mode, cred);
	sysvd_print("allocate segment = %d\n", error);
done:
	/*
	 * Install to th client the file corresponding to the
	 * shared memory segment.
	 * client_fd is the file descriptor added in the client
	 * files table.
	 */
	shmseg = shm_find_segment_by_shmid(error);
	if (shmseg == NULL) {
		sysvd_print_err("can not find segment by shmid\n");
		return (-1);
	}

	handle = (struct shm_handle *)shmseg->shm_internal;
	if (install_fd_client(pid, handle->fd) != 0)
		error = errno;
done_err:
	return (error);

}
Esempio n. 3
0
int
shmget_allocate_segment(struct proc *p,
	struct sys_shmget_args /* {
		syscallarg(key_t) key;
		syscallarg(size_t) size;
		syscallarg(int) shmflg;
	} */ *uap,
	int mode, register_t *retval)
{
	size_t size;
	key_t key;
	int segnum;
	struct ucred *cred = p->p_ucred;
	struct shmid_ds *shmseg;
	struct shm_handle *shm_handle;
	int error = 0;
	
	if (SCARG(uap, size) < shminfo.shmmin ||
	    SCARG(uap, size) > shminfo.shmmax)
		return (EINVAL);
	if (shm_nused >= shminfo.shmmni) /* any shmids left? */
		return (ENOSPC);
	size = round_page(SCARG(uap, size));
	if (shm_committed + atop(size) > shminfo.shmall)
		return (ENOMEM);
	shm_nused++;
	shm_committed += atop(size);

	/*
	 * If a key has been specified and we had to wait for memory
	 * to be freed up we need to verify that no one has allocated
	 * the key we want in the meantime.  Yes, this is ugly.
	 */
	key = SCARG(uap, key);
	shmseg = pool_get(&shm_pool, key == IPC_PRIVATE ? PR_WAITOK :
	    PR_NOWAIT);
	if (shmseg == NULL) {
		shmseg = pool_get(&shm_pool, PR_WAITOK);
		if (shm_find_segment_by_key(key) != -1) {
			pool_put(&shm_pool, shmseg);
			shm_nused--;
			shm_committed -= atop(size);
			return (EAGAIN);
		}
	}

	/* XXX - hash shmids instead */
	if (shm_last_free < 0) {
		for (segnum = 0; segnum < shminfo.shmmni && shmsegs[segnum];
		    segnum++)
			;
		if (segnum == shminfo.shmmni)
			panic("shmseg free count inconsistent");
	} else {
		segnum = shm_last_free;
		if (++shm_last_free >= shminfo.shmmni || shmsegs[shm_last_free])
			shm_last_free = -1;
	}
	shmsegs[segnum] = shmseg;

	shm_handle = (struct shm_handle *)((caddr_t)shmseg + sizeof(*shmseg));
	shm_handle->shm_object = uao_create(size, 0);

	shmseg->shm_perm.cuid = shmseg->shm_perm.uid = cred->cr_uid;
	shmseg->shm_perm.cgid = shmseg->shm_perm.gid = cred->cr_gid;
	shmseg->shm_perm.mode = (mode & ACCESSPERMS);
	shmseg->shm_perm.seq = shmseqs[segnum] = (shmseqs[segnum] + 1) & 0x7fff;
	shmseg->shm_perm.key = key;
	shmseg->shm_segsz = SCARG(uap, size);
	shmseg->shm_cpid = p->p_p->ps_pid;
	shmseg->shm_lpid = shmseg->shm_nattch = 0;
	shmseg->shm_atime = shmseg->shm_dtime = 0;
	shmseg->shm_ctime = time_second;
	shmseg->shm_internal = shm_handle;

	*retval = IXSEQ_TO_IPCID(segnum, shmseg->shm_perm);
	return (error);
}