Example #1
0
/*===========================================================================*
 *				do_semget		     		     *
 *===========================================================================*/
PUBLIC int do_semget(message *m)
{
	key_t key;
	int nsems, flag, id;
	struct sem_struct *sem;

	key = m->SEMGET_KEY;
	nsems = m->SEMGET_NR;
	flag = m->SEMGET_FLAG;

	if ((sem = sem_find_key(key))) {
		if ((flag & IPC_CREAT) && (flag & IPC_EXCL))
			return EEXIST;
		if (!check_perm(&sem->semid_ds.sem_perm, who_e, flag))
			return EACCES;
		if (nsems > sem->semid_ds.sem_nsems)
			return EINVAL;
		id = sem->id;
	} else {
		if (!(flag & IPC_CREAT))
			return ENOENT;
		if (nsems < 0 || nsems >= SEMMSL)
			return EINVAL;
		if (sem_list_nr == SEMMNI)
			return ENOSPC;

		/* create a new semaphore set */
		sem = &sem_list[sem_list_nr];
		memset(sem, 0, sizeof(struct sem_struct));
		sem->semid_ds.sem_perm.cuid =
			sem->semid_ds.sem_perm.uid = getnuid(who_e);
		sem->semid_ds.sem_perm.cgid =
			sem->semid_ds.sem_perm.gid = getngid(who_e);
		sem->semid_ds.sem_perm.mode = flag & 0777;
		sem->semid_ds.sem_nsems = nsems;
		sem->semid_ds.sem_otime = 0;
		sem->semid_ds.sem_ctime = time(NULL);
		sem->id = id = identifier++;
		sem->key = key;

		sem_list_nr++;
	}

	m->SEMGET_RETID = id;
	return OK;
}
Example #2
0
int
main(int argc, char *argv[])
{
	int r, i;
	struct tm t;
	endpoint_t user, caller;
	message m;
	int ipc_status, reply_status;

	env_setargs(argc, argv);

	r = i2cdriver_env_parse(&bus, &addresses[0], valid_addrs);
	if (r < 0) {
		log_warn(&log, "Expecting -args 'bus=X address=0xYY'\n");
		log_warn(&log, "Example -args 'bus=1 address=0x48'\n");
		return EXIT_FAILURE;
	} else if (r > 0) {
		log_warn(&log,
		    "Invalid slave address for device, expecting 0x48\n");
		return EXIT_FAILURE;
	}

	sef_local_startup();

	while (TRUE) {

		/* Receive Message */
		r = sef_receive_status(ANY, &m, &ipc_status);
		if (r != OK) {
			log_warn(&log, "sef_receive_status() failed\n");
			continue;
		}

		if (is_ipc_notify(ipc_status)) {

			if (m.m_source == DS_PROC_NR) {
				for (i = 0; i < NADDRESSES; i++) {
					/* changed state, update endpoint */
					i2cdriver_handle_bus_update
					    (&bus_endpoint, bus, addresses[i]);
				}
			}

			/* Do not reply to notifications. */
			continue;
		}

		caller = m.m_source;

		log_debug(&log, "Got message 0x%x from 0x%x\n", m.m_type,
		    caller);

		switch (m.m_type) {
		case RTCDEV_GET_TIME_G:
			/* Any user can read the time */
			reply_status = rtc_get_time(&t, m.RTCDEV_FLAGS);
			if (reply_status != OK) {
				break;
			}

			/* write results back to calling process */
			reply_status =
			    store_t(caller, (cp_grant_id_t) m.RTCDEV_GRANT,
			    &t);
			break;

		case RTCDEV_SET_TIME_G:
			/* Only super user is allowed to set the time */
			if (getnuid(caller) == SUPER_USER) {
				/* read time from calling process */
				reply_status =
				    fetch_t(caller,
				    (cp_grant_id_t) m.RTCDEV_GRANT, &t);
				if (reply_status != OK) {
					break;
				}

				reply_status =
				    rtc_set_time(&t, m.RTCDEV_FLAGS);
			} else {
				reply_status = EPERM;
			}
			break;

		case RTCDEV_PWR_OFF:
			reply_status = ENOSYS;
			break;

		default:
			/* Unrecognized call */
			reply_status = EINVAL;
			break;
		}

		/* Send Reply */
		m.m_type = RTCDEV_REPLY;
		m.RTCDEV_STATUS = reply_status;

		log_debug(&log, "Sending Reply");

		r = sendnb(caller, &m);
		if (r != OK) {
			log_warn(&log, "sendnb() failed\n");
			continue;
		}
	}

	rtc_exit();

	return 0;
}
Example #3
0
/*===========================================================================*
 *				do_shmget		     		     *
 *===========================================================================*/
PUBLIC int do_shmget(message *m)
{
	struct shm_struct *shm;
	long key, size, old_size;
	int flag;
	int id;

	key = m->SHMGET_KEY;
	old_size = size = m->SHMGET_SIZE;
	flag = m->SHMGET_FLAG;

	if ((shm = shm_find_key(key))) {
		if (!check_perm(&shm->shmid_ds.shm_perm, who_e, flag))
			return EACCES;
		if ((flag & IPC_CREAT) && (flag & IPC_EXCL))
			return EEXIST;
		if (size && shm->shmid_ds.shm_segsz < size)
			return EINVAL;
		id = shm->id;
	} else { /* no key found */
		if (!(flag & IPC_CREAT))
			return ENOENT;
		if (size <= 0)
			return EINVAL;
		/* round up to a multiple of PAGE_SIZE */
		if (size % I386_PAGE_SIZE)
			size += I386_PAGE_SIZE - size % I386_PAGE_SIZE;
		if (size <= 0)
			return EINVAL;

		if (shm_list_nr == MAX_SHM_NR)
			return ENOMEM;
		/* TODO: shmmni should be changed... */
		if (identifier == SHMMNI)
			return ENOSPC;
		shm = &shm_list[shm_list_nr];
		memset(shm, 0, sizeof(struct shm_struct));
		shm->page = (vir_bytes) mmap(0, size,
					PROT_READ|PROT_WRITE,
					MAP_CONTIG|MAP_PREALLOC|MAP_ANON|MAP_SHARED,
					-1, 0);
		if (shm->page == (vir_bytes) MAP_FAILED)
			return ENOMEM;
		shm->phys = vm_getphys(SELF_E, (void *) shm->page);
		memset((void *)shm->page, 0, size);

		shm->shmid_ds.shm_perm.cuid =
			shm->shmid_ds.shm_perm.uid = getnuid(who_e);
		shm->shmid_ds.shm_perm.cgid =
			shm->shmid_ds.shm_perm.gid = getngid(who_e);
		shm->shmid_ds.shm_perm.mode = flag & 0777;
		shm->shmid_ds.shm_segsz = old_size;
		shm->shmid_ds.shm_atime = 0;
		shm->shmid_ds.shm_dtime = 0;
		shm->shmid_ds.shm_ctime = time(NULL);
		shm->shmid_ds.shm_cpid = getnpid(who_e);
		shm->shmid_ds.shm_lpid = 0;
		shm->shmid_ds.shm_nattch = 0;
		shm->id = id = identifier++;
		shm->key = key;

		shm_list_nr++;
	}

	m->SHMGET_RETID = id;
	return OK;
}
Example #4
0
/*===========================================================================*
 *				do_shmctl		     		     *
 *===========================================================================*/
PUBLIC int do_shmctl(message *m)
{
	int id = m->SHMCTL_ID;
	int cmd = m->SHMCTL_CMD;
	struct shmid_ds *ds = (struct shmid_ds *)m->SHMCTL_BUF;
	struct shmid_ds tmp_ds;
	struct shm_struct *shm;
	struct shminfo sinfo;
	struct shm_info s_info;
	uid_t uid;
	int r, i;

	if (cmd == IPC_STAT)
		update_refcount_and_destroy();

	if ((cmd == IPC_STAT ||
		cmd == IPC_SET ||
		cmd == IPC_RMID) &&
		!(shm = shm_find_id(id)))
		return EINVAL;

	switch (cmd) {
	case IPC_STAT:
		if (!ds)
			return EFAULT;
		/* check whether it has read permission */
		if (!check_perm(&shm->shmid_ds.shm_perm, who_e, 0444))
			return EACCES;
		r = sys_datacopy(SELF_E, (vir_bytes)&shm->shmid_ds,
			who_e, (vir_bytes)ds, sizeof(struct shmid_ds));
		if (r != OK)
			return EFAULT;
		break;
	case IPC_SET:
		uid = getnuid(who_e);
		if (uid != shm->shmid_ds.shm_perm.cuid &&
			uid != shm->shmid_ds.shm_perm.uid &&
			uid != 0)
			return EPERM;
		r = sys_datacopy(who_e, (vir_bytes)ds,
			SELF_E, (vir_bytes)&tmp_ds, sizeof(struct shmid_ds));
		if (r != OK)
			return EFAULT;
		shm->shmid_ds.shm_perm.uid = tmp_ds.shm_perm.uid;
		shm->shmid_ds.shm_perm.gid = tmp_ds.shm_perm.gid;
		shm->shmid_ds.shm_perm.mode &= ~0777;
		shm->shmid_ds.shm_perm.mode |= tmp_ds.shm_perm.mode & 0666;
		shm->shmid_ds.shm_ctime = time(NULL);
		break;
	case IPC_RMID:
		uid = getnuid(who_e);
		if (uid != shm->shmid_ds.shm_perm.cuid &&
			uid != shm->shmid_ds.shm_perm.uid &&
			uid != 0)
			return EPERM;
		shm->shmid_ds.shm_perm.mode |= SHM_DEST;
		/* destroy if possible */
		update_refcount_and_destroy();
		break;
	case IPC_INFO:
		if (!ds)
			return EFAULT;
		sinfo.shmmax = (unsigned long) -1;
		sinfo.shmmin = 1;
		sinfo.shmmni = MAX_SHM_NR;
		sinfo.shmseg = (unsigned long) -1;
		sinfo.shmall = (unsigned long) -1;
		r = sys_datacopy(SELF_E, (vir_bytes)&sinfo,
			who_e, (vir_bytes)ds, sizeof(struct shminfo));
		if (r != OK)
			return EFAULT;
		m->SHMCTL_RET = shm_list_nr - 1;
		if (m->SHMCTL_RET < 0)
			m->SHMCTL_RET = 0;
		break;
	case SHM_INFO:
		if (!ds)
			return EFAULT;
		s_info.used_ids = shm_list_nr;
		s_info.shm_tot = 0;
		for (i = 0; i < shm_list_nr; i++)
			s_info.shm_tot +=
				shm_list[i].shmid_ds.shm_segsz/I386_PAGE_SIZE;
		s_info.shm_rss = s_info.shm_tot;
		s_info.shm_swp = 0;
		s_info.swap_attempts = 0;
		s_info.swap_successes = 0;
		r = sys_datacopy(SELF_E, (vir_bytes)&s_info,
			who_e, (vir_bytes)ds, sizeof(struct shm_info));
		if (r != OK)
			return EFAULT;
		m->SHMCTL_RET = shm_list_nr - 1;
		if (m->SHMCTL_RET < 0)
			m->SHMCTL_RET = 0;
		break;
	case SHM_STAT:
		if (id < 0 || id >= shm_list_nr)
			return EINVAL;
		shm = &shm_list[id];
		r = sys_datacopy(SELF_E, (vir_bytes)&shm->shmid_ds,
			who_e, (vir_bytes)ds, sizeof(struct shmid_ds));
		if (r != OK)
			return EFAULT;
		m->SHMCTL_RET = shm->id;
		break;
	default:
		return EINVAL;
	}
	return OK;
}
Example #5
0
/*===========================================================================*
 *				do_semctl		     		     *
 *===========================================================================*/
PUBLIC int do_semctl(message *m)
{
	int r, i;
	long opt;
	uid_t uid;
	int id, num, cmd, val;
	unsigned short *buf;
	struct semid_ds *ds, tmp_ds;
	struct sem_struct *sem;

	id = m->SEMCTL_ID;
	num = m->SEMCTL_NUM;
	cmd = m->SEMCTL_CMD;

	if (cmd == IPC_STAT || cmd == IPC_SET || cmd == IPC_INFO ||
		cmd == SEM_INFO || cmd == SEM_STAT || cmd == GETALL ||
		cmd == SETALL || cmd == SETVAL)
		opt = m->SEMCTL_OPT;

	if (!(sem = sem_find_id(id))) {
		return EINVAL;
	}

	/* IPC_SET and IPC_RMID as its own permission check */
	if (cmd != IPC_SET && cmd != IPC_RMID) {
		/* check read permission */
		if (!check_perm(&sem->semid_ds.sem_perm, who_e, 0444))
			return EACCES;
	}

	switch (cmd) {
	case IPC_STAT:
		ds = (struct semid_ds *) opt;
		if (!ds)
			return EFAULT;
		r = sys_datacopy(SELF_E, (vir_bytes) &sem->semid_ds,
			who_e, (vir_bytes) ds, sizeof(struct semid_ds));
		if (r != OK)
			return EINVAL;
		break;
	case IPC_SET:
		uid = getnuid(who_e);
		if (uid != sem->semid_ds.sem_perm.cuid &&
			uid != sem->semid_ds.sem_perm.uid &&
			uid != 0)
			return EPERM;
		ds = (struct semid_ds *) opt;
		r = sys_datacopy(who_e, (vir_bytes) ds,
			SELF_E, (vir_bytes) &tmp_ds, sizeof(struct semid_ds));
		if (r != OK)
			return EINVAL;
		sem->semid_ds.sem_perm.uid = tmp_ds.sem_perm.uid;
		sem->semid_ds.sem_perm.gid = tmp_ds.sem_perm.gid;
		sem->semid_ds.sem_perm.mode &= ~0777;
		sem->semid_ds.sem_perm.mode |= tmp_ds.sem_perm.mode & 0666;
		sem->semid_ds.sem_ctime = time(NULL);
		break;
	case IPC_RMID:
		uid = getnuid(who_e);
		if (uid != sem->semid_ds.sem_perm.cuid &&
			uid != sem->semid_ds.sem_perm.uid &&
			uid != 0)
			return EPERM;
		/* awaken all processes block in semop
		 * and remove the semaphore set.
		 */
		update_one_semaphore(sem, 1);
		break;
	case IPC_INFO:
		break;
	case SEM_INFO:
		break;
	case SEM_STAT:
		break;
	case GETALL:
		buf = malloc(sizeof(unsigned short) * sem->semid_ds.sem_nsems);
		if (!buf)
			return ENOMEM;
		for (i = 0; i < sem->semid_ds.sem_nsems; i++)
			buf[i] = sem->sems[i].semval;
		r = sys_datacopy(SELF_E, (vir_bytes) buf,
			who_e, (vir_bytes) opt,
			sizeof(unsigned short) * sem->semid_ds.sem_nsems);
		if (r != OK)
			return EINVAL;
		free(buf);
		break;
	case GETNCNT:
		if (num < 0 || num >= sem->semid_ds.sem_nsems)
			return EINVAL;
		m->SHMCTL_RET = sem->sems[num].semncnt;
		break;
	case GETPID:
		if (num < 0 || num >= sem->semid_ds.sem_nsems)
			return EINVAL;
		m->SHMCTL_RET = sem->sems[num].sempid;
		break;
	case GETVAL:
		if (num < 0 || num >= sem->semid_ds.sem_nsems)
			return EINVAL;
		m->SHMCTL_RET = sem->sems[num].semval;
		break;
	case GETZCNT:
		if (num < 0 || num >= sem->semid_ds.sem_nsems)
			return EINVAL;
		m->SHMCTL_RET = sem->sems[num].semzcnt;
		break;
	case SETALL:
		buf = malloc(sizeof(unsigned short) * sem->semid_ds.sem_nsems);
		if (!buf)
			return ENOMEM;
		r = sys_datacopy(who_e, (vir_bytes) opt,
			SELF_E, (vir_bytes) buf,
			sizeof(unsigned short) * sem->semid_ds.sem_nsems);
		if (r != OK)
			return EINVAL;
#ifdef DEBUG_SEM
		printf("SEMCTL: SETALL: opt: %p\n");
		for (i = 0; i < sem->semid_ds.sem_nsems; i++)
			printf("SEMCTL: SETALL val: [%d] %d\n", i, buf[i]);
#endif
		for (i = 0; i < sem->semid_ds.sem_nsems; i++) {
			if (buf[i] < 0 || buf[i] > SEMVMX) {
				free(buf);
				update_semaphores();
				return ERANGE;
			}
			sem->sems[i].semval = buf[i];
		}
		free(buf);
		/* awaken if possible */
		update_semaphores();
		break;
	case SETVAL:
		val = (int) opt;
		/* check write permission */
		if (!check_perm(&sem->semid_ds.sem_perm, who_e, 0222))
			return EACCES;
		if (num < 0 || num >= sem->semid_ds.sem_nsems)
			return EINVAL;
		if (val < 0 || val > SEMVMX)
			return ERANGE;
		sem->sems[num].semval = val;
#ifdef DEBUG_SEM
		printf("SEMCTL: SETVAL: %d %d\n", num, val);
#endif
		sem->semid_ds.sem_ctime = time(NULL);
		/* awaken if possible */
		update_semaphores();
		break;
	default:
		return EINVAL;
	}

	return OK;
}
Example #6
0
int
main(int argc, char **argv)
{
	int r;
	endpoint_t caller;
	struct tm t;
	message m;
	int ipc_status, reply_status;

	env_setargs(argc, argv);
	sef_local_startup();

	while (TRUE) {

		/* Receive Message */
		r = sef_receive_status(ANY, &m, &ipc_status);
		if (r != OK) {
			log_warn(&log, "sef_receive_status() failed\n");
			continue;
		}

		if (is_ipc_notify(ipc_status)) {

			/* Do not reply to notifications. */
			continue;
		}

		caller = m.m_source;

		log_debug(&log, "Got message 0x%x from 0x%x\n", m.m_type,
		    caller);

		switch (m.m_type) {
		case RTCDEV_GET_TIME:
			/* Any user can read the time */
			reply_status = rtc.get_time(&t, m.m_lc_readclock_rtcdev.flags);
			if (reply_status != OK) {
				break;
			}

			/* write results back to calling process */
			reply_status =
			    store_t(caller, m.m_lc_readclock_rtcdev.tm, &t);
			break;

		case RTCDEV_SET_TIME:
			/* Only super user is allowed to set the time */
			if (getnuid(caller) == SUPER_USER) {
				/* read time from calling process */
				reply_status =
				    fetch_t(caller, m.m_lc_readclock_rtcdev.tm,
				    &t);
				if (reply_status != OK) {
					break;
				}

				reply_status =
				    rtc.set_time(&t, m.m_lc_readclock_rtcdev.flags);
			} else {
				reply_status = EPERM;
			}
			break;

		case RTCDEV_PWR_OFF:
			/* Only PM is allowed to set the power off time */
			if (caller == PM_PROC_NR) {
				reply_status = rtc.pwr_off();
			} else {
				reply_status = EPERM;
			}
			break;

		default:
			/* Unrecognized call */
			reply_status = EINVAL;
			break;
		}

		/* Send Reply */
		m.m_type = RTCDEV_REPLY;
		m.m_readclock_lc_rtcdev.status = reply_status;

		log_debug(&log, "Sending Reply");

		r = ipc_sendnb(caller, &m);
		if (r != OK) {
			log_warn(&log, "ipc_sendnb() failed\n");
			continue;
		}
	}

	rtc.exit();
	return 0;
}