diff --git a/src/kernel/core/sem.c b/src/kernel/core/sem.c index 47df6fa40f..07028fb0fa 100644 --- a/src/kernel/core/sem.c +++ b/src/kernel/core/sem.c @@ -429,7 +429,6 @@ status_t switch_sem_etc(sem_id semToBeReleased, sem_id id, int32 count, uint32 flags, bigtime_t timeout) { - // ToDo: add support for B_CHECK_PERMISSION int slot = id % sMaxSems; int state; status_t status = B_OK; @@ -449,13 +448,22 @@ switch_sem_etc(sem_id semToBeReleased, sem_id id, int32 count, state = disable_interrupts(); GRAB_SEM_LOCK(sSems[slot]); - + if (sSems[slot].id != id) { TRACE(("acquire_sem_etc: bad sem_id %ld\n", id)); status = B_BAD_SEM_ID; goto err; } + // ToDo: the B_CHECK_PERMISSION flag should be made private, as it + // doesn't have any use outside the kernel + if ((flags & B_CHECK_PERMISSION) != 0 + && sSems[slot].u.used.owner == team_get_kernel_team_id()) { + dprintf("thread %ld tried to acquire kernel semaphore.\n", thread_get_current_thread()->id); + status = B_NOT_ALLOWED; + goto err; + } + if (sSems[slot].u.used.count - count < 0 && (flags & B_RELATIVE_TIMEOUT) != 0 && timeout <= 0) { // immediate timeout @@ -574,7 +582,6 @@ release_sem(sem_id id) status_t release_sem_etc(sem_id id, int32 count, uint32 flags) { - // ToDo: add support for B_CHECK_PERMISSION struct thread_queue releaseQueue; int32 slot = id % sMaxSems; cpu_status state; @@ -596,6 +603,15 @@ release_sem_etc(sem_id id, int32 count, uint32 flags) goto err; } + // ToDo: the B_CHECK_PERMISSION flag should be made private, as it + // doesn't have any use outside the kernel + if ((flags & B_CHECK_PERMISSION) != 0 + && sSems[slot].u.used.owner == team_get_kernel_team_id()) { + dprintf("thread %ld tried to release kernel semaphore.\n", thread_get_current_thread()->id); + status = B_NOT_ALLOWED; + goto err; + } + // clear out a queue we will use to hold all of the threads that we will have to // put back into the run list. This is done so the thread lock wont be held // while this sems lock is held since the two locks are grabbed in the other