| 1096 | }; |
| 1097 | #endif |
| 1098 | int |
| 1099 | sys_semop(struct thread *td, struct semop_args *uap) |
| 1100 | { |
| 1101 | #define SMALL_SOPS 8 |
| 1102 | struct sembuf small_sops[SMALL_SOPS]; |
| 1103 | int semid = uap->semid; |
| 1104 | size_t nsops = uap->nsops; |
| 1105 | struct prison *rpr; |
| 1106 | struct sembuf *sops; |
| 1107 | struct semid_kernel *semakptr; |
| 1108 | struct sembuf *sopptr = NULL; |
| 1109 | struct sem *semptr = NULL; |
| 1110 | struct sem_undo *suptr; |
| 1111 | struct mtx *sema_mtxp; |
| 1112 | size_t i, j, k; |
| 1113 | int error; |
| 1114 | int do_wakeup, do_undos; |
| 1115 | unsigned short seq; |
| 1116 | |
| 1117 | #ifdef SEM_DEBUG |
| 1118 | sops = NULL; |
| 1119 | #endif |
| 1120 | DPRINTF(("call to semop(%d, %p, %u)\n", semid, sops, nsops)); |
| 1121 | |
| 1122 | AUDIT_ARG_SVIPC_ID(semid); |
| 1123 | |
| 1124 | rpr = sem_find_prison(td->td_ucred); |
| 1125 | if (sem == NULL) |
| 1126 | return (ENOSYS); |
| 1127 | |
| 1128 | semid = IPCID_TO_IX(semid); /* Convert back to zero origin */ |
| 1129 | |
| 1130 | if (semid < 0 || semid >= seminfo.semmni) |
| 1131 | return (EINVAL); |
| 1132 | |
| 1133 | /* Allocate memory for sem_ops */ |
| 1134 | if (nsops <= SMALL_SOPS) |
| 1135 | sops = small_sops; |
| 1136 | else if (nsops > seminfo.semopm) { |
| 1137 | DPRINTF(("too many sops (max=%d, nsops=%d)\n", seminfo.semopm, |
| 1138 | nsops)); |
| 1139 | return (E2BIG); |
| 1140 | } else { |
| 1141 | #ifdef RACCT |
| 1142 | if (racct_enable) { |
| 1143 | PROC_LOCK(td->td_proc); |
| 1144 | if (nsops > |
| 1145 | racct_get_available(td->td_proc, RACCT_NSEMOP)) { |
| 1146 | PROC_UNLOCK(td->td_proc); |
| 1147 | return (E2BIG); |
| 1148 | } |
| 1149 | PROC_UNLOCK(td->td_proc); |
| 1150 | } |
| 1151 | #endif |
| 1152 | |
| 1153 | sops = malloc(nsops * sizeof(*sops), M_TEMP, M_WAITOK); |
| 1154 | } |
| 1155 | if ((error = copyin(uap->sops, sops, nsops * sizeof(sops[0]))) != 0) { |
nothing calls this directly
no test coverage detected