⛏️ index : haiku.git

author Augustin Cavalier <waddlesplash@gmail.com> 2018-09-23 14:45:01.0 -04:00:00
committer Augustin Cavalier <waddlesplash@gmail.com> 2018-09-25 23:29:18.0 -04:00:00
commit
aef2ee83bafb0d05329b7fd2a1df2845585d2fff [patch]
tree
8212ffddfd171f55448f6571d81ca7507cc612ee
parent
807ad0cf46760ec0660cbcfc9c8629ce8cf4d3b1
download
aef2ee83bafb0d05329b7fd2a1df2845585d2fff.tar.gz

kernel: Handle the user buffers properly in _user_xsi_semctl.

Should fix #14512.

Diff

 src/system/kernel/posix/xsi_semaphore.cpp | 45 +++++++++++++++++++++++----------------------
 1 file changed, 23 insertions(+), 22 deletions(-)

diff --git a/src/system/kernel/posix/xsi_semaphore.cpp b/src/system/kernel/posix/xsi_semaphore.cpp
index 8938cfa..f4f4a2e 100644
--- a/src/system/kernel/posix/xsi_semaphore.cpp
+++ b/src/system/kernel/posix/xsi_semaphore.cpp
@@ -832,10 +832,18 @@

int
_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",
		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 setHashLocker(sXsiSemaphoreSetLock);
	XsiSemaphoreSet *semaphoreSet = sSemaphoreHashTable.Lookup(semaphoreID);
@@ -849,10 +857,6 @@
		TRACE_ERROR(("xsi_semctl: semaphore number %d not valid for "
			"semaphore %d\n", semaphoreNumber, semaphoreID));
		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
@@ -865,11 +869,12 @@
		setLocker.SetTo(&semaphoreSet->Lock(), false);
		setHashLocker.Unlock();
		ipcHashLocker.Unlock();
	} else
	} else {
		// We are about to delete the set along with its mutex, so
		// we can't use the MutexLocker class, as the mutex itself
		// won't exist on function exit
		mutex_lock(&semaphoreSet->Lock());
	}

	int result = 0;
	XsiSemaphore *semaphore = semaphoreSet->Semaphore(semaphoreNumber);
@@ -892,15 +897,11 @@
					(int)semaphoreSet->IpcKey()));
				result = EACCES;
			} else {
				int value;
				if (user_memcpy(&value, &args->val, sizeof(int)) < B_OK) {
					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));
				if (args.val > USHRT_MAX) {
					TRACE_ERROR(("xsi_semctl: value %d out of range\n", args.val));
					result = ERANGE;
				} else {
					semaphore->SetValue(value);
					semaphore->SetValue(args.val);
					semaphoreSet->ClearUndo(semaphoreNumber);
				}
			}
@@ -950,8 +951,8 @@
				for (int i = 0; i < semaphoreSet->NumberOfSemaphores(); i++) {
					semaphore = semaphoreSet->Semaphore(i);
					unsigned short value = semaphore->Value();
					if (user_memcpy(&args->array[i], &value,
						sizeof(unsigned short)) < B_OK) {
					if (user_memcpy(args.array + i, &value,
							sizeof(unsigned short)) != B_OK) {
						TRACE_ERROR(("xsi_semctl: user_memcpy failed\n"));
						result = B_BAD_ADDRESS;
						break;
@@ -971,8 +972,8 @@
				for (int i = 0; i < semaphoreSet->NumberOfSemaphores(); i++) {
					semaphore = semaphoreSet->Semaphore(i);
					unsigned short value;
					if (user_memcpy(&value, &args->array[i], sizeof(unsigned short))
						< B_OK) {
					if (user_memcpy(&value, args.array + i,
							sizeof(unsigned short)) != B_OK) {
						TRACE_ERROR(("xsi_semctl: user_memcpy failed\n"));
						result = B_BAD_ADDRESS;
						doClear = false;
@@ -998,8 +999,8 @@
				sem.sem_nsems = semaphoreSet->NumberOfSemaphores();
				sem.sem_otime = semaphoreSet->LastSemopTime();
				sem.sem_ctime = semaphoreSet->LastSemctlTime();
				if (user_memcpy(args->buf, &sem, sizeof(struct semid_ds))
					< B_OK) {
				if (user_memcpy(args.buf, &sem, sizeof(struct semid_ds))
						< B_OK) {
					TRACE_ERROR(("xsi_semctl: user_memcpy failed\n"));
					result = B_BAD_ADDRESS;
				}
@@ -1015,8 +1016,8 @@
				result = EACCES;
			} else {
				struct semid_ds sem;
				if (user_memcpy(&sem, args->buf, sizeof(struct semid_ds))
					< B_OK) {
				if (user_memcpy(&sem, args.buf, sizeof(struct semid_ds))
						!= B_OK) {
					TRACE_ERROR(("xsi_semctl: user_memcpy failed\n"));
					result = B_BAD_ADDRESS;
				} else
@@ -1105,7 +1106,7 @@
	MemoryDeleter operationsDeleter(operations);

	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"));
		return B_BAD_ADDRESS;
	}