void print_ksemptr(int i, int option, struct semid_kernel *ksemaptr) { char ctime_buf[100], otime_buf[100]; cvt_time(ksemaptr->u.sem_otime, otime_buf); cvt_time(ksemaptr->u.sem_ctime, ctime_buf); printf("s %12d %12d %s %-8s %-8s", IXSEQ_TO_IPCID(i, ksemaptr->u.sem_perm), (int)ksemaptr->u.sem_perm.key, fmt_perm(ksemaptr->u.sem_perm.mode), user_from_uid(ksemaptr->u.sem_perm.uid, 0), group_from_gid(ksemaptr->u.sem_perm.gid, 0)); if (option & CREATOR) printf(" %-8s %-8s", user_from_uid(ksemaptr->u.sem_perm.cuid, 0), group_from_gid(ksemaptr->u.sem_perm.cgid, 0)); if (option & BIGGEST) printf(" %12d", ksemaptr->u.sem_nsems); if (option & TIME) printf(" %s %s", otime_buf, ctime_buf); printf("\n"); }
/* Get the id of an existing shared memory segment. */ static int shmget_existing(struct shmget_msg *shmget_msg, int mode, int segnum, struct cmsgcred *cred) { struct shmid_ds *shmseg; int error; shmseg = &shmsegs[segnum]; if (shmseg->shm_perm.mode & SHMSEG_REMOVED) { /* * This segment is in the process of being allocated. Wait * until it's done, and look the key up again (in case the * allocation failed or it was freed). */ //TODO Maybe it will be necessary if the daemon is multithreading /*shmseg->shm_perm.mode |= SHMSEG_WANTED; error = tsleep((caddr_t)shmseg, PCATCH, "shmget", 0); if (error) return error; return EAGAIN;*/ } if ((shmget_msg->shmflg & (IPC_CREAT | IPC_EXCL)) == (IPC_CREAT | IPC_EXCL)) return (-EEXIST); error = ipcperm(cred, &shmseg->shm_perm, mode); if (error) return (-error); if (shmget_msg->size && (shmget_msg->size > shmseg->shm_segsz)) return (-EINVAL); return (IXSEQ_TO_IPCID(segnum, shmseg->shm_perm)); }
static int semrmall(void) { int mib[4]; struct sem_sysctl_info *semsi; size_t len; int32_t i; int result = 0; mib[0] = CTL_KERN; mib[1] = KERN_SYSVIPC; mib[2] = KERN_SYSVIPC_INFO; mib[3] = KERN_SYSVIPC_SEM_INFO; if (sysctl(mib, 4, NULL, &len, NULL, 0) == -1) err(1, "sysctl(KERN_SYSVIPC_SEM_INFO)"); if ((semsi = malloc(len)) == NULL) err(1, "malloc"); if (sysctl(mib, 4, semsi, &len, NULL, 0) == -1) { free(semsi); err(1, "sysctl(KERN_SYSVIPC_SEM_INFO)"); } for (i = 0; i < semsi->seminfo.semmni; i++) { struct semid_ds_sysctl *semptr = &semsi->semids[i]; if ((semptr->sem_perm.mode & SEM_ALLOC) != 0) result -= semrm((key_t)0, (int)IXSEQ_TO_IPCID(i, semptr->sem_perm)); } free(semsi); return result; }
static int msgrmall(void) { int mib[4]; struct msg_sysctl_info *msgsi; int32_t i; size_t len; int result = 0; mib[0] = CTL_KERN; mib[1] = KERN_SYSVIPC; mib[2] = KERN_SYSVIPC_INFO; mib[3] = KERN_SYSVIPC_MSG_INFO; if (sysctl(mib, 4, NULL, &len, NULL, 0) == -1) err(1, "sysctl(KERN_SYSVIPC_MSG_INFO)"); if ((msgsi = malloc(len)) == NULL) err(1, "malloc"); if (sysctl(mib, 4, msgsi, &len, NULL, 0) == -1) { free(msgsi); err(1, "sysctl(KERN_SYSVIPC_MSG_INFO)"); } for (i = 0; i < msgsi->msginfo.msgmni; i++) { struct msgid_ds_sysctl *msgptr = &msgsi->msgids[i]; if (msgptr->msg_qbytes != 0) result -= msgrm((key_t)0, (int)IXSEQ_TO_IPCID(i, msgptr->msg_perm)); } free(msgsi); return result; }
void print_kshmptr(int i, int option, struct shmid_kernel *kshmptr) { char atime_buf[100], dtime_buf[100], ctime_buf[100]; cvt_time(kshmptr->u.shm_atime, atime_buf); cvt_time(kshmptr->u.shm_dtime, dtime_buf); cvt_time(kshmptr->u.shm_ctime, ctime_buf); printf("m %12d %12d %s %-8s %-8s", IXSEQ_TO_IPCID(i, kshmptr->u.shm_perm), (int)kshmptr->u.shm_perm.key, fmt_perm(kshmptr->u.shm_perm.mode), user_from_uid(kshmptr->u.shm_perm.uid, 0), group_from_gid(kshmptr->u.shm_perm.gid, 0)); if (option & CREATOR) printf(" %-8s %-8s", user_from_uid(kshmptr->u.shm_perm.cuid, 0), group_from_gid(kshmptr->u.shm_perm.cgid, 0)); if (option & OUTSTANDING) printf(" %12d", kshmptr->u.shm_nattch); if (option & BIGGEST) printf(" %12zu", kshmptr->u.shm_segsz); if (option & PID) printf(" %12d %12d", kshmptr->u.shm_cpid, kshmptr->u.shm_lpid); if (option & TIME) printf(" %s %s %s", atime_buf, dtime_buf, ctime_buf); printf("\n"); }
void print_kmsqptr(int i, int option, struct msqid_kernel *kmsqptr) { char stime_buf[100], rtime_buf[100], ctime_buf[100]; cvt_time(kmsqptr->u.msg_stime, stime_buf); cvt_time(kmsqptr->u.msg_rtime, rtime_buf); cvt_time(kmsqptr->u.msg_ctime, ctime_buf); printf("q %12d %12d %s %-8s %-8s", IXSEQ_TO_IPCID(i, kmsqptr->u.msg_perm), (int)kmsqptr->u.msg_perm.key, fmt_perm(kmsqptr->u.msg_perm.mode), user_from_uid(kmsqptr->u.msg_perm.uid, 0), group_from_gid(kmsqptr->u.msg_perm.gid, 0)); if (option & CREATOR) printf(" %-8s %-8s", user_from_uid(kmsqptr->u.msg_perm.cuid, 0), group_from_gid(kmsqptr->u.msg_perm.cgid, 0)); if (option & OUTSTANDING) printf(" %12lu %12lu", kmsqptr->u.msg_cbytes, kmsqptr->u.msg_qnum); if (option & BIGGEST) printf(" %20lu", kmsqptr->u.msg_qbytes); if (option & PID) printf(" %12d %12d", kmsqptr->u.msg_lspid, kmsqptr->u.msg_lrpid); if (option & TIME) printf(" %s %s %s", stime_buf, rtime_buf, ctime_buf); printf("\n"); }
int semrm(key_t key, int id) { union semun arg; if (key == -1 || id == -1) { struct semid_kernel *kxsema; size_t kxsema_len; int num; kget(X_SEMINFO, &seminfo, sizeof(seminfo)); kxsema_len = sizeof(struct semid_kernel) * seminfo.semmni; kxsema = malloc(kxsema_len); kget(X_SEMA, kxsema, kxsema_len); num = seminfo.semmni; while (num-- && !signaled) if ((kxsema[num].u.sem_perm.mode & SEM_ALLOC) != 0) { id = IXSEQ_TO_IPCID(num, kxsema[num].u.sem_perm); if (semctl(id, IPC_RMID, NULL) < 0) { if (rmverbose > 1) warn("semid(%d): ", id); errflg++; } else if (rmverbose) printf( "Removed %s %d\n", IPC_TO_STRING('S'), id); } return signaled ? -1 : 0; /* errors maybe handled above */ } if (key) { id = semget(key, 0, 0); if (id == -1) return -1; } return semctl(id, 0, IPC_RMID, arg); }
int msgrm(key_t key, int id) { if (key == -1 || id == -1) { struct msqid_kernel *kxmsqids; size_t kxmsqids_len; int num; kget(X_MSGINFO, &msginfo, sizeof(msginfo)); kxmsqids_len = sizeof(struct msqid_kernel) * msginfo.msgmni; kxmsqids = malloc(kxmsqids_len); kget(X_MSQIDS, kxmsqids, kxmsqids_len); num = msginfo.msgmni; while (num-- && !signaled) if (kxmsqids[num].u.msg_qbytes != 0) { id = IXSEQ_TO_IPCID(num, kxmsqids[num].u.msg_perm); if (msgctl(id, IPC_RMID, NULL) < 0) { if (rmverbose > 1) warn("msqid(%d): ", id); errflg++; } else if (rmverbose) printf( "Removed %s %d\n", IPC_TO_STRING('Q'), id); } return signaled ? -1 : 0; /* errors maybe handled above */ } if (key) { id = msgget(key, 0); if (id == -1) return -1; } return msgctl(id, IPC_RMID, NULL); }
int shmrm(key_t key, int id) { if (key == -1 || id == -1) { struct shmid_kernel *kxshmids; size_t kxshmids_len; int num; kget(X_SHMINFO, &shminfo, sizeof(shminfo)); kxshmids_len = sizeof(struct shmid_kernel) * shminfo.shmmni; kxshmids = malloc(kxshmids_len); kget(X_SHMSEGS, kxshmids, kxshmids_len); num = shminfo.shmmni; while (num-- && !signaled) if (kxshmids[num].u.shm_perm.mode & 0x0800) { id = IXSEQ_TO_IPCID(num, kxshmids[num].u.shm_perm); if (shmctl(id, IPC_RMID, NULL) < 0) { if (rmverbose > 1) warn("shmid(%d): ", id); errflg++; } else if (rmverbose) printf( "Removed %s %d\n", IPC_TO_STRING('M'), id); } return signaled ? -1 : 0; /* errors maybe handled above */ } if (key) { id = shmget(key, 0, 0); if (id == -1) return -1; } return shmctl(id, IPC_RMID, NULL); }
int shmget_existing(struct proc *p, struct sys_shmget_args /* { syscallarg(key_t) key; syscallarg(size_t) size; syscallarg(int) shmflg; } */ *uap, int mode, int segnum, register_t *retval) { struct shmid_ds *shmseg; struct ucred *cred = p->p_ucred; int error; shmseg = shmsegs[segnum]; /* We assume the segnum is valid */ if ((error = ipcperm(cred, &shmseg->shm_perm, mode)) != 0) return (error); if (SCARG(uap, size) && SCARG(uap, size) > shmseg->shm_segsz) return (EINVAL); if ((SCARG(uap, shmflg) & (IPC_CREAT | IPC_EXCL)) == (IPC_CREAT | IPC_EXCL)) return (EEXIST); *retval = IXSEQ_TO_IPCID(segnum, shmseg->shm_perm); return (0); }
/* * MPALMOSTSAFE */ int sys_msgget(struct msgget_args *uap) { struct thread *td = curthread; int msqid, eval; int key = uap->key; int msgflg = uap->msgflg; struct ucred *cred = td->td_ucred; struct msqid_ds *msqptr = NULL; #ifdef MSG_DEBUG_OK kprintf("msgget(0x%x, 0%o)\n", key, msgflg); #endif if (!jail_sysvipc_allowed && cred->cr_prison != NULL) return (ENOSYS); eval = 0; get_mplock(); if (key != IPC_PRIVATE) { for (msqid = 0; msqid < msginfo.msgmni; msqid++) { msqptr = &msqids[msqid]; if (msqptr->msg_qbytes != 0 && msqptr->msg_perm.key == key) break; } if (msqid < msginfo.msgmni) { #ifdef MSG_DEBUG_OK kprintf("found public key\n"); #endif if ((msgflg & IPC_CREAT) && (msgflg & IPC_EXCL)) { #ifdef MSG_DEBUG_OK kprintf("not exclusive\n"); #endif eval = EEXIST; goto done; } if ((eval = ipcperm(td->td_proc, &msqptr->msg_perm, msgflg & 0700 ))) { #ifdef MSG_DEBUG_OK kprintf("requester doesn't have 0%o access\n", msgflg & 0700); #endif goto done; } goto done; } } #ifdef MSG_DEBUG_OK kprintf("need to allocate the msqid_ds\n"); #endif if (key == IPC_PRIVATE || (msgflg & IPC_CREAT)) { for (msqid = 0; msqid < msginfo.msgmni; msqid++) { /* * Look for an unallocated and unlocked msqid_ds. * msqid_ds's can be locked by msgsnd or msgrcv while * they are copying the message in/out. We can't * re-use the entry until they release it. */ msqptr = &msqids[msqid]; if (msqptr->msg_qbytes == 0 && (msqptr->msg_perm.mode & MSG_LOCKED) == 0) break; } if (msqid == msginfo.msgmni) { #ifdef MSG_DEBUG_OK kprintf("no more msqid_ds's available\n"); #endif eval = ENOSPC; goto done; } #ifdef MSG_DEBUG_OK kprintf("msqid %d is available\n", msqid); #endif msqptr->msg_perm.key = key; msqptr->msg_perm.cuid = cred->cr_uid; msqptr->msg_perm.uid = cred->cr_uid; msqptr->msg_perm.cgid = cred->cr_gid; msqptr->msg_perm.gid = cred->cr_gid; msqptr->msg_perm.mode = (msgflg & 0777); /* Make sure that the returned msqid is unique */ msqptr->msg_perm.seq = (msqptr->msg_perm.seq + 1) & 0x7fff; msqptr->msg_first = NULL; msqptr->msg_last = NULL; msqptr->msg_cbytes = 0; msqptr->msg_qnum = 0; msqptr->msg_qbytes = msginfo.msgmnb; msqptr->msg_lspid = 0; msqptr->msg_lrpid = 0; msqptr->msg_stime = 0; msqptr->msg_rtime = 0; msqptr->msg_ctime = time_second; } else { #ifdef MSG_DEBUG_OK kprintf("didn't find it and wasn't asked to create it\n"); #endif eval = ENOENT; } done: rel_mplock(); /* Construct the unique msqid */ if (eval == 0) uap->sysmsg_result = IXSEQ_TO_IPCID(msqid, msqptr->msg_perm); return(eval); }
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); }
/* Create a shared memory segment and return the id. */ static int shmget_allocate_segment(pid_t pid, struct shmget_msg *shmget_msg, int mode, struct cmsgcred *cred) { int i, segnum, shmid; size_t size; struct shmid_ds *shmseg; struct shm_handle *handle; #if 0 /* It is possible after a process calls exec(). * We don't create another segment but return the old one * with all information. * This segment is destroyed only when process dies. * */ if (shmget_msg->type == UNDOGET) { struct client *cl= _hash_lookup(clientshash, pid); if (cl->undoid != -1) return cl->undoid; } #endif if ((long)shmget_msg->size < shminfo.shmmin) //|| (long)shmget_msg->size > shminfo.shmmax) /* There is no need to check the max limit, * the operating system do this for us. */ return (-EINVAL); if (shm_nused >= shminfo.shmmni) /* any shmids left? */ return (-ENOSPC); /* Compute the size of the segment. */ size = round_page(shmget_msg->size); /* Find a free entry in the shmsegs vector. */ if (shm_last_free < 0) { // shmrealloc(); /* maybe expand the shmsegs[] array */ for (i = 0; i < shmalloced; i++) { if (shmsegs[i].shm_perm.mode & SHMSEG_FREE) break; } if (i == shmalloced) { sysvd_print("i == shmalloced\n"); return (-ENOSPC); } segnum = i; } else { segnum = shm_last_free; shm_last_free = -1; } shmseg = &shmsegs[segnum]; /* * In case we sleep in malloc(), mark the segment present but deleted * so that noone else tries to create the same key. */ shmseg->shm_perm.mode = SHMSEG_ALLOCATED | SHMSEG_REMOVED; shmseg->shm_perm.key = shmget_msg->key; shmseg->shm_perm.seq = (shmseg->shm_perm.seq + 1) & 0x7fff; /* Create the file for the shared memory segment. */ handle = shmseg->shm_internal = malloc(sizeof(struct shm_handle)); handle->type = shmget_msg->type; handle->fd = create_sysv_file(shmget_msg, size, shmseg); if (handle->fd == -1) { free(handle); handle = NULL; shmseg->shm_perm.mode = SHMSEG_FREE; shm_last_free = segnum; errno = -ENFILE; return (-1); } LIST_INIT(&handle->attached_list); if (handle->fd < 0) { free(shmseg->shm_internal); shmseg->shm_internal = NULL; shm_last_free = segnum; shmseg->shm_perm.mode = SHMSEG_FREE; return (-errno); } /* Get the id. */ shmid = IXSEQ_TO_IPCID(segnum, shmseg->shm_perm); shmseg->shm_perm.cuid = shmseg->shm_perm.uid = cred->cmcred_euid; shmseg->shm_perm.cgid = shmseg->shm_perm.gid = cred->cmcred_gid; shmseg->shm_perm.mode = (shmseg->shm_perm.mode & SHMSEG_WANTED) | (mode & ACCESSPERMS) | SHMSEG_ALLOCATED; shmseg->shm_cpid = pid; shmseg->shm_lpid = shmseg->shm_nattch = 0; shmseg->shm_atime = shmseg->shm_dtime = 0; shmseg->shm_ctime = time(NULL); shmseg->shm_segsz = shmget_msg->size; shm_committed += btoc(size); shm_nused++; if (shmseg->shm_perm.mode & SHMSEG_WANTED) { /* * Somebody else wanted this key while we were asleep. Wake * them up now. */ shmseg->shm_perm.mode &= ~SHMSEG_WANTED; //TODO multithreading //wakeup((caddr_t)shmseg); } shmseg->shm_perm.mode &= ~SHMSEG_REMOVED; if (shmget_msg->type == UNDOGET) { /* The file is used by daemon when clients terminates * and sem_undo resources must be cleaned. */ struct client *cl= _hash_lookup(clientshash, pid); cl->undoid = shmid; } return (shmid); }
int sys_msgget(struct proc *p, void *v, register_t *retval) { struct sys_msgget_args /* { syscallarg(key_t) key; syscallarg(int) msgflg; } */ *uap = v; int msqid, eval; int key = SCARG(uap, key); int msgflg = SCARG(uap, msgflg); struct ucred *cred = p->p_ucred; struct msqid_kernel *msqkptr = NULL; DPRINTF(("msgget(0x%x, 0%o)\n", key, msgflg)); if (key != IPC_PRIVATE) { for (msqid = 0; msqid < msginfo.msgmni; msqid++) { msqkptr = &msqids[msqid]; if (msqkptr->u.msg_qbytes != 0 && msqkptr->u.msg_perm.key == key) break; } if (msqid < msginfo.msgmni) { DPRINTF(("found public key\n")); if ((msgflg & IPC_CREAT) && (msgflg & IPC_EXCL)) { DPRINTF(("not exclusive\n")); return (EEXIST); } if ((eval = ipcperm(cred, &msqkptr->u.msg_perm, msgflg & 0700 ))) { DPRINTF(("requester doesn't have 0%o access\n", msgflg & 0700)); return (eval); } #ifdef MAC eval = mac_sysvmsq_check_msqget(cred, msqkptr); if (eval) return (eval); #endif goto found; } } DPRINTF(("need to allocate the msqid_ds\n")); if (key == IPC_PRIVATE || (msgflg & IPC_CREAT)) { for (msqid = 0; msqid < msginfo.msgmni; msqid++) { /* * Look for an unallocated and unlocked msqid_ds. * msqid_ds's can be locked by msgsnd or msgrcv while * they are copying the message in/out. We can't * re-use the entry until they release it. */ msqkptr = &msqids[msqid]; if (msqkptr->u.msg_qbytes == 0 && (msqkptr->u.msg_perm.mode & MSG_LOCKED) == 0) break; } if (msqid == msginfo.msgmni) { DPRINTF(("no more msqid_ds's available\n")); return (ENOSPC); } DPRINTF(("msqid %d is available\n", msqid)); msqkptr->u.msg_perm.key = key; msqkptr->u.msg_perm.cuid = cred->cr_uid; msqkptr->u.msg_perm.uid = cred->cr_uid; msqkptr->u.msg_perm.cgid = cred->cr_gid; msqkptr->u.msg_perm.gid = cred->cr_gid; msqkptr->u.msg_perm.mode = (msgflg & 0777); /* Make sure that the returned msqid is unique */ msqkptr->u.msg_perm.seq = (msqkptr->u.msg_perm.seq + 1) & 0x7fff; msqkptr->u.msg_first = NULL; msqkptr->u.msg_last = NULL; msqkptr->u.msg_cbytes = 0; msqkptr->u.msg_qnum = 0; msqkptr->u.msg_qbytes = msginfo.msgmnb; msqkptr->u.msg_lspid = 0; msqkptr->u.msg_lrpid = 0; msqkptr->u.msg_stime = 0; msqkptr->u.msg_rtime = 0; msqkptr->u.msg_ctime = time_second; #ifdef MAC mac_sysvmsq_create(cred, msqkptr); #endif } else { DPRINTF(("didn't find it and wasn't asked to create it\n")); return (ENOENT); } found: /* Construct the unique msqid */ *retval = IXSEQ_TO_IPCID(msqid, msqkptr->u.msg_perm); return (0); }
int msgget(__unused struct proc *p, struct msgget_args *uap, int32_t *retval) { int msqid, eval; int key = uap->key; int msgflg = uap->msgflg; kauth_cred_t cred = kauth_cred_get(); struct msqid_kernel *msqptr = NULL; SYSV_MSG_SUBSYS_LOCK(); if (!msginit(0)) { eval = ENOMEM; goto msggetout; } #ifdef MSG_DEBUG_OK printf("msgget(0x%x, 0%o)\n", key, msgflg); #endif if (key != IPC_PRIVATE) { for (msqid = 0; msqid < msginfo.msgmni; msqid++) { msqptr = &msqids[msqid]; if (msqptr->u.msg_qbytes != 0 && msqptr->u.msg_perm._key == key) break; } if (msqid < msginfo.msgmni) { #ifdef MSG_DEBUG_OK printf("found public key\n"); #endif if ((msgflg & IPC_CREAT) && (msgflg & IPC_EXCL)) { #ifdef MSG_DEBUG_OK printf("not exclusive\n"); #endif eval = EEXIST; goto msggetout; } if ((eval = ipcperm(cred, &msqptr->u.msg_perm, msgflg & 0700 ))) { #ifdef MSG_DEBUG_OK printf("requester doesn't have 0%o access\n", msgflg & 0700); #endif goto msggetout; } #if CONFIG_MACF eval = mac_sysvmsq_check_msqget(cred, msqptr); if (eval) goto msggetout; #endif goto found; } } #ifdef MSG_DEBUG_OK printf("need to allocate the user_msqid_ds\n"); #endif if (key == IPC_PRIVATE || (msgflg & IPC_CREAT)) { for (msqid = 0; msqid < msginfo.msgmni; msqid++) { /* * Look for an unallocated and unlocked user_msqid_ds. * user_msqid_ds's can be locked by msgsnd or msgrcv * while they are copying the message in/out. We * can't re-use the entry until they release it. */ msqptr = &msqids[msqid]; if (msqptr->u.msg_qbytes == 0 && (msqptr->u.msg_perm.mode & MSG_LOCKED) == 0) break; } if (msqid == msginfo.msgmni) { #ifdef MSG_DEBUG_OK printf("no more user_msqid_ds's available\n"); #endif eval = ENOSPC; goto msggetout; } #ifdef MSG_DEBUG_OK printf("msqid %d is available\n", msqid); #endif msqptr->u.msg_perm._key = key; msqptr->u.msg_perm.cuid = kauth_cred_getuid(cred); msqptr->u.msg_perm.uid = kauth_cred_getuid(cred); msqptr->u.msg_perm.cgid = kauth_cred_getgid(cred); msqptr->u.msg_perm.gid = kauth_cred_getgid(cred); msqptr->u.msg_perm.mode = (msgflg & 0777); /* Make sure that the returned msqid is unique */ msqptr->u.msg_perm._seq++; msqptr->u.msg_first = NULL; msqptr->u.msg_last = NULL; msqptr->u.msg_cbytes = 0; msqptr->u.msg_qnum = 0; msqptr->u.msg_qbytes = msginfo.msgmnb; msqptr->u.msg_lspid = 0; msqptr->u.msg_lrpid = 0; msqptr->u.msg_stime = 0; msqptr->u.msg_rtime = 0; msqptr->u.msg_ctime = sysv_msgtime(); #if CONFIG_MACF mac_sysvmsq_label_associate(cred, msqptr); #endif } else { #ifdef MSG_DEBUG_OK printf("didn't find it and wasn't asked to create it\n"); #endif eval = ENOENT; goto msggetout; } found: /* Construct the unique msqid */ *retval = IXSEQ_TO_IPCID(msqid, msqptr->u.msg_perm); AUDIT_ARG(svipc_id, *retval); eval = 0; msggetout: SYSV_MSG_SUBSYS_UNLOCK(); return(eval); }
int sys_semget(struct lwp *l, const struct sys_semget_args *uap, register_t *retval) { /* { syscallarg(key_t) key; syscallarg(int) nsems; syscallarg(int) semflg; } */ int semid, error = 0; int key = SCARG(uap, key); int nsems = SCARG(uap, nsems); int semflg = SCARG(uap, semflg); kauth_cred_t cred = l->l_cred; SEM_PRINTF(("semget(0x%x, %d, 0%o)\n", key, nsems, semflg)); mutex_enter(&semlock); if (key != IPC_PRIVATE) { for (semid = 0; semid < seminfo.semmni; semid++) { if ((sema[semid].sem_perm.mode & SEM_ALLOC) && sema[semid].sem_perm._key == key) break; } if (semid < seminfo.semmni) { SEM_PRINTF(("found public key\n")); if ((error = ipcperm(cred, &sema[semid].sem_perm, semflg & 0700))) goto out; if (nsems > 0 && sema[semid].sem_nsems < nsems) { SEM_PRINTF(("too small\n")); error = EINVAL; goto out; } if ((semflg & IPC_CREAT) && (semflg & IPC_EXCL)) { SEM_PRINTF(("not exclusive\n")); error = EEXIST; goto out; } goto found; } } SEM_PRINTF(("need to allocate the semid_ds\n")); if (key == IPC_PRIVATE || (semflg & IPC_CREAT)) { if (nsems <= 0 || nsems > seminfo.semmsl) { SEM_PRINTF(("nsems out of range (0<%d<=%d)\n", nsems, seminfo.semmsl)); error = EINVAL; goto out; } if (nsems > seminfo.semmns - semtot) { SEM_PRINTF(("not enough semaphores left " "(need %d, got %d)\n", nsems, seminfo.semmns - semtot)); error = ENOSPC; goto out; } for (semid = 0; semid < seminfo.semmni; semid++) { if ((sema[semid].sem_perm.mode & SEM_ALLOC) == 0) break; } if (semid == seminfo.semmni) { SEM_PRINTF(("no more semid_ds's available\n")); error = ENOSPC; goto out; } SEM_PRINTF(("semid %d is available\n", semid)); sema[semid].sem_perm._key = key; sema[semid].sem_perm.cuid = kauth_cred_geteuid(cred); sema[semid].sem_perm.uid = kauth_cred_geteuid(cred); sema[semid].sem_perm.cgid = kauth_cred_getegid(cred); sema[semid].sem_perm.gid = kauth_cred_getegid(cred); sema[semid].sem_perm.mode = (semflg & 0777) | SEM_ALLOC; sema[semid].sem_perm._seq = (sema[semid].sem_perm._seq + 1) & 0x7fff; sema[semid].sem_nsems = nsems; sema[semid].sem_otime = 0; sema[semid].sem_ctime = time_second; sema[semid]._sem_base = &sem[semtot]; semtot += nsems; memset(sema[semid]._sem_base, 0, sizeof(sema[semid]._sem_base[0]) * nsems); SEM_PRINTF(("sembase = %p, next = %p\n", sema[semid]._sem_base, &sem[semtot])); } else { SEM_PRINTF(("didn't find it and wasn't asked to create it\n")); error = ENOENT; goto out; } found: *retval = IXSEQ_TO_IPCID(semid, sema[semid].sem_perm); out: mutex_exit(&semlock); return (error); }
int sys_msgget(struct lwp *l, const struct sys_msgget_args *uap, register_t *retval) { /* { syscallarg(key_t) key; syscallarg(int) msgflg; } */ int msqid, error = 0; int key = SCARG(uap, key); int msgflg = SCARG(uap, msgflg); kauth_cred_t cred = l->l_cred; struct msqid_ds *msqptr = NULL; kmsq_t *msq; mutex_enter(&msgmutex); MSG_PRINTF(("msgget(0x%x, 0%o)\n", key, msgflg)); if (key != IPC_PRIVATE) { for (msqid = 0; msqid < msginfo.msgmni; msqid++) { msq = &msqs[msqid]; msqptr = &msq->msq_u; if (msqptr->msg_qbytes != 0 && msqptr->msg_perm._key == key) break; } if (msqid < msginfo.msgmni) { MSG_PRINTF(("found public key\n")); if ((msgflg & IPC_CREAT) && (msgflg & IPC_EXCL)) { MSG_PRINTF(("not exclusive\n")); error = EEXIST; goto unlock; } if ((error = ipcperm(cred, &msqptr->msg_perm, msgflg & 0700 ))) { MSG_PRINTF(("requester doesn't have 0%o access\n", msgflg & 0700)); goto unlock; } goto found; } } MSG_PRINTF(("need to allocate the msqid_ds\n")); if (key == IPC_PRIVATE || (msgflg & IPC_CREAT)) { for (msqid = 0; msqid < msginfo.msgmni; msqid++) { /* * Look for an unallocated and unlocked msqid_ds. * msqid_ds's can be locked by msgsnd or msgrcv while * they are copying the message in/out. We can't * re-use the entry until they release it. */ msq = &msqs[msqid]; msqptr = &msq->msq_u; if (msqptr->msg_qbytes == 0 && (msqptr->msg_perm.mode & MSG_LOCKED) == 0) break; } if (msqid == msginfo.msgmni) { MSG_PRINTF(("no more msqid_ds's available\n")); error = ENOSPC; goto unlock; } MSG_PRINTF(("msqid %d is available\n", msqid)); msqptr->msg_perm._key = key; msqptr->msg_perm.cuid = kauth_cred_geteuid(cred); msqptr->msg_perm.uid = kauth_cred_geteuid(cred); msqptr->msg_perm.cgid = kauth_cred_getegid(cred); msqptr->msg_perm.gid = kauth_cred_getegid(cred); msqptr->msg_perm.mode = (msgflg & 0777); /* Make sure that the returned msqid is unique */ msqptr->msg_perm._seq++; msqptr->_msg_first = NULL; msqptr->_msg_last = NULL; msqptr->_msg_cbytes = 0; msqptr->msg_qnum = 0; msqptr->msg_qbytes = msginfo.msgmnb; msqptr->msg_lspid = 0; msqptr->msg_lrpid = 0; msqptr->msg_stime = 0; msqptr->msg_rtime = 0; msqptr->msg_ctime = time_second; } else { MSG_PRINTF(("didn't find it and wasn't asked to create it\n")); error = ENOENT; goto unlock; } found: /* Construct the unique msqid */ *retval = IXSEQ_TO_IPCID(msqid, msqptr->msg_perm); unlock: mutex_exit(&msgmutex); return (error); }