trim: Added is_called_via_syscall() function.

* And use it in get_trim_data_from_user(), formerly known as copy_*().
* This fixes differentiating between user and kernel buffers.
This commit is contained in:
Axel Dörfler
2013-11-07 19:06:13 +01:00
parent 79cb543ae0
commit 547cd462f8
5 changed files with 42 additions and 13 deletions
+15 -1
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2008-2011, Haiku Inc. All rights reserved. * Copyright 2008-2013, Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#ifndef _KERNEL_SYSCALL_RESTART_H #ifndef _KERNEL_SYSCALL_RESTART_H
@@ -100,6 +100,20 @@ syscall_restart_is_restarted()
} }
/*! Returns whether or not a function has been called via a syscall. The flag
to determine this is currently only used where actually needed, such as
ioctl().
TODO: this function is actually needed as part of the public API for ioctl()
*/
static inline bool
is_called_via_syscall(void)
{
Thread* thread = thread_get_current_thread();
return (thread->flags & THREAD_FLAGS_SYSCALL) != 0;
}
struct SyscallFlagUnsetter { struct SyscallFlagUnsetter {
SyscallFlagUnsetter() SyscallFlagUnsetter()
{ {
+20 -3
View File
@@ -6,14 +6,23 @@
#define _FS_TRIM_SUPPORT_H #define _FS_TRIM_SUPPORT_H
#include <Drivers.h> #include <KernelExport.h>
#include <kernel.h> #include <kernel.h>
#include <syscall_restart.h>
static inline status_t static inline status_t
copy_trim_data_from_user(void* buffer, size_t size, fs_trim_data*& _trimData) get_trim_data_from_user(void* buffer, size_t size, MemoryDeleter& deleter,
fs_trim_data*& _trimData)
{ {
if (!is_called_via_syscall() && !IS_USER_ADDRESS(buffer)) {
// Called from kernel
_trimData = (fs_trim_data*)buffer;
return B_OK;
}
// Called from userland
if (!IS_USER_ADDRESS(buffer)) if (!IS_USER_ADDRESS(buffer))
return B_BAD_ADDRESS; return B_BAD_ADDRESS;
@@ -29,8 +38,10 @@ copy_trim_data_from_user(void* buffer, size_t size, fs_trim_data*& _trimData)
if (trimBuffer == NULL) if (trimBuffer == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
if (user_memcpy(trimBuffer, buffer, bytes) != B_OK) if (user_memcpy(trimBuffer, buffer, bytes) != B_OK) {
free(trimBuffer);
return B_BAD_ADDRESS; return B_BAD_ADDRESS;
}
_trimData = (fs_trim_data*)trimBuffer; _trimData = (fs_trim_data*)trimBuffer;
return B_OK; return B_OK;
@@ -40,6 +51,12 @@ copy_trim_data_from_user(void* buffer, size_t size, fs_trim_data*& _trimData)
static inline status_t static inline status_t
copy_trim_data_to_user(void* buffer, fs_trim_data* trimData) copy_trim_data_to_user(void* buffer, fs_trim_data* trimData)
{ {
if (!is_called_via_syscall() && !IS_USER_ADDRESS(buffer))
return B_OK;
if (!IS_USER_ADDRESS(buffer))
return B_BAD_ADDRESS;
// Do not copy any ranges // Do not copy any ranges
return user_memcpy(buffer, trimData, sizeof(uint64) * 2); return user_memcpy(buffer, trimData, sizeof(uint64) * 2);
} }
@@ -416,13 +416,12 @@ das_ioctl(void* cookie, uint32 op, void* buffer, size_t length)
case B_TRIM_DEVICE: case B_TRIM_DEVICE:
{ {
fs_trim_data* trimData; fs_trim_data* trimData;
status_t status = copy_trim_data_from_user(buffer, length, MemoryDeleter deleter;
status_t status = get_trim_data_from_user(buffer, length, deleter,
trimData); trimData);
if (status != B_OK) if (status != B_OK)
return status; return status;
MemoryDeleter deleter(trimData);
status = trim_device(info, trimData); status = trim_device(info, trimData);
if (status != B_OK) if (status != B_OK)
return status; return status;
@@ -629,12 +629,12 @@ bfs_ioctl(fs_volume* _volume, fs_vnode* _node, void* _cookie, uint32 cmd,
case B_TRIM_DEVICE: case B_TRIM_DEVICE:
{ {
fs_trim_data* trimData; fs_trim_data* trimData;
status_t status = copy_trim_data_from_user(buffer, bufferLength, MemoryDeleter deleter;
trimData); status_t status = get_trim_data_from_user(buffer, bufferLength,
deleter, trimData);
if (status != B_OK) if (status != B_OK)
return status; return status;
MemoryDeleter deleter(trimData);
trimData->trimmed_size = 0; trimData->trimmed_size = 0;
for (uint32 i = 0; i < trimData->range_count; i++) { for (uint32 i = 0; i < trimData->range_count; i++) {
+2 -3
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2006-2011, Haiku, Inc. All Rights Reserved. * Copyright 2006-2013, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
@@ -699,8 +699,7 @@ uninit_timers(void)
bool bool
is_syscall(void) is_syscall(void)
{ {
Thread* thread = thread_get_current_thread(); return is_called_via_syscall();
return (thread->flags & THREAD_FLAGS_SYSCALL) != 0;
} }