kernel: Handle the user buffers properly in _user_xsi_semctl.

Should fix #14512.
This commit is contained in:
Augustin Cavalier
2018-09-23 14:45:01 -04:00
parent c609f04f86
commit 80be7d09c5
+23 -22
View File
@@ -832,10 +832,18 @@ _user_xsi_semget(key_t key, int numberOfSemaphores, int flags)
int int
_user_xsi_semctl(int semaphoreID, int semaphoreNumber, int command, _user_xsi_semctl(int semaphoreID, int semaphoreNumber, int command,
union semun *args) union semun *_args)
{ {
TRACE(("xsi_semctl: semaphoreID = %d, semaphoreNumber = %d, command = %d\n", TRACE(("xsi_semctl: semaphoreID = %d, semaphoreNumber = %d, command = %d\n",
semaphoreID, semaphoreNumber, command)); semaphoreID, semaphoreNumber, command));
union semun args = {0};
if (_args != NULL) {
if (!IS_USER_ADDRESS(_args)
|| user_memcpy(&args, _args, sizeof(union semun)) != B_OK)
return B_BAD_ADDRESS;
}
MutexLocker ipcHashLocker(sIpcLock); MutexLocker ipcHashLocker(sIpcLock);
MutexLocker setHashLocker(sXsiSemaphoreSetLock); MutexLocker setHashLocker(sXsiSemaphoreSetLock);
XsiSemaphoreSet *semaphoreSet = sSemaphoreHashTable.Lookup(semaphoreID); XsiSemaphoreSet *semaphoreSet = sSemaphoreHashTable.Lookup(semaphoreID);
@@ -850,10 +858,6 @@ _user_xsi_semctl(int semaphoreID, int semaphoreNumber, int command,
"semaphore %d\n", semaphoreNumber, semaphoreID)); "semaphore %d\n", semaphoreNumber, semaphoreID));
return EINVAL; return EINVAL;
} }
if (args != 0 && !IS_USER_ADDRESS(args)) {
TRACE_ERROR(("xsi_semctl: semun address is not valid\n"));
return B_BAD_ADDRESS;
}
// Lock the semaphore set itself and release both the semaphore // Lock the semaphore set itself and release both the semaphore
// set hash table lock and the ipc hash table lock _only_ if // set hash table lock and the ipc hash table lock _only_ if
@@ -865,11 +869,12 @@ _user_xsi_semctl(int semaphoreID, int semaphoreNumber, int command,
setLocker.SetTo(&semaphoreSet->Lock(), false); setLocker.SetTo(&semaphoreSet->Lock(), false);
setHashLocker.Unlock(); setHashLocker.Unlock();
ipcHashLocker.Unlock(); ipcHashLocker.Unlock();
} else } else {
// We are about to delete the set along with its mutex, so // We are about to delete the set along with its mutex, so
// we can't use the MutexLocker class, as the mutex itself // we can't use the MutexLocker class, as the mutex itself
// won't exist on function exit // won't exist on function exit
mutex_lock(&semaphoreSet->Lock()); mutex_lock(&semaphoreSet->Lock());
}
int result = 0; int result = 0;
XsiSemaphore *semaphore = semaphoreSet->Semaphore(semaphoreNumber); XsiSemaphore *semaphore = semaphoreSet->Semaphore(semaphoreNumber);
@@ -892,15 +897,11 @@ _user_xsi_semctl(int semaphoreID, int semaphoreNumber, int command,
(int)semaphoreSet->IpcKey())); (int)semaphoreSet->IpcKey()));
result = EACCES; result = EACCES;
} else { } else {
int value; if (args.val > USHRT_MAX) {
if (user_memcpy(&value, &args->val, sizeof(int)) < B_OK) { TRACE_ERROR(("xsi_semctl: value %d out of range\n", args.val));
TRACE_ERROR(("xsi_semctl: user_memcpy failed\n"));
result = B_BAD_ADDRESS;
} else if (value > USHRT_MAX) {
TRACE_ERROR(("xsi_semctl: value %d out of range\n", value));
result = ERANGE; result = ERANGE;
} else { } else {
semaphore->SetValue(value); semaphore->SetValue(args.val);
semaphoreSet->ClearUndo(semaphoreNumber); semaphoreSet->ClearUndo(semaphoreNumber);
} }
} }
@@ -950,8 +951,8 @@ _user_xsi_semctl(int semaphoreID, int semaphoreNumber, int command,
for (int i = 0; i < semaphoreSet->NumberOfSemaphores(); i++) { for (int i = 0; i < semaphoreSet->NumberOfSemaphores(); i++) {
semaphore = semaphoreSet->Semaphore(i); semaphore = semaphoreSet->Semaphore(i);
unsigned short value = semaphore->Value(); unsigned short value = semaphore->Value();
if (user_memcpy(&args->array[i], &value, if (user_memcpy(args.array + i, &value,
sizeof(unsigned short)) < B_OK) { sizeof(unsigned short)) != B_OK) {
TRACE_ERROR(("xsi_semctl: user_memcpy failed\n")); TRACE_ERROR(("xsi_semctl: user_memcpy failed\n"));
result = B_BAD_ADDRESS; result = B_BAD_ADDRESS;
break; break;
@@ -971,8 +972,8 @@ _user_xsi_semctl(int semaphoreID, int semaphoreNumber, int command,
for (int i = 0; i < semaphoreSet->NumberOfSemaphores(); i++) { for (int i = 0; i < semaphoreSet->NumberOfSemaphores(); i++) {
semaphore = semaphoreSet->Semaphore(i); semaphore = semaphoreSet->Semaphore(i);
unsigned short value; unsigned short value;
if (user_memcpy(&value, &args->array[i], sizeof(unsigned short)) if (user_memcpy(&value, args.array + i,
< B_OK) { sizeof(unsigned short)) != B_OK) {
TRACE_ERROR(("xsi_semctl: user_memcpy failed\n")); TRACE_ERROR(("xsi_semctl: user_memcpy failed\n"));
result = B_BAD_ADDRESS; result = B_BAD_ADDRESS;
doClear = false; doClear = false;
@@ -998,8 +999,8 @@ _user_xsi_semctl(int semaphoreID, int semaphoreNumber, int command,
sem.sem_nsems = semaphoreSet->NumberOfSemaphores(); sem.sem_nsems = semaphoreSet->NumberOfSemaphores();
sem.sem_otime = semaphoreSet->LastSemopTime(); sem.sem_otime = semaphoreSet->LastSemopTime();
sem.sem_ctime = semaphoreSet->LastSemctlTime(); sem.sem_ctime = semaphoreSet->LastSemctlTime();
if (user_memcpy(args->buf, &sem, sizeof(struct semid_ds)) if (user_memcpy(args.buf, &sem, sizeof(struct semid_ds))
< B_OK) { < B_OK) {
TRACE_ERROR(("xsi_semctl: user_memcpy failed\n")); TRACE_ERROR(("xsi_semctl: user_memcpy failed\n"));
result = B_BAD_ADDRESS; result = B_BAD_ADDRESS;
} }
@@ -1015,8 +1016,8 @@ _user_xsi_semctl(int semaphoreID, int semaphoreNumber, int command,
result = EACCES; result = EACCES;
} else { } else {
struct semid_ds sem; struct semid_ds sem;
if (user_memcpy(&sem, args->buf, sizeof(struct semid_ds)) if (user_memcpy(&sem, args.buf, sizeof(struct semid_ds))
< B_OK) { != B_OK) {
TRACE_ERROR(("xsi_semctl: user_memcpy failed\n")); TRACE_ERROR(("xsi_semctl: user_memcpy failed\n"));
result = B_BAD_ADDRESS; result = B_BAD_ADDRESS;
} else } else
@@ -1105,7 +1106,7 @@ _user_xsi_semop(int semaphoreID, struct sembuf *ops, size_t numOps)
MemoryDeleter operationsDeleter(operations); MemoryDeleter operationsDeleter(operations);
if (user_memcpy(operations, ops, if (user_memcpy(operations, ops,
(sizeof(struct sembuf) * numOps)) < B_OK) { (sizeof(struct sembuf) * numOps)) != B_OK) {
TRACE_ERROR(("xsi_semop: user_memcpy failed\n")); TRACE_ERROR(("xsi_semop: user_memcpy failed\n"));
return B_BAD_ADDRESS; return B_BAD_ADDRESS;
} }