[haiku-commits] haiku: hrev52006 - headers/private/kernel/compat src/system/kernel headers/private/kernel/util

  • From: Jérôme Duval <jerome.duval@xxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Tue, 12 Jun 2018 11:55:58 -0400 (EDT)

hrev52006 adds 1 changeset to branch 'master'
old head: 2ffbe7aaca8668c5a68ac7488459bace7a0700f2
new head: c70cba914aa79c01bbc2da38085936f589899c8c
overview: 
https://git.haiku-os.org/haiku/log/?qt=range&q=c70cba914aa7+%5E2ffbe7aaca86

----------------------------------------------------------------------------

c70cba914aa7: kernel/x86_64: compatibility syscalls for image.cpp.
  
  * define compat_image_info, compat_extended_image_info
  to be used for respective 32-bit types of syscalls in compatibility mode.
  * handle 32-bit types in _user_register_image, _user_get_image_info,
  _user_get_next_image_info, other syscalls are compatible as is.
  
  Change-Id: Ibbd33e6796208dfa70d869e36bf745bc3e18d330

                                   [ Jérôme Duval <jerome.duval@xxxxxxxxx> ]

----------------------------------------------------------------------------

Revision:    hrev52006
Commit:      c70cba914aa79c01bbc2da38085936f589899c8c
URL:         https://git.haiku-os.org/haiku/commit/?id=c70cba914aa7
Author:      Jérôme Duval <jerome.duval@xxxxxxxxx>
Date:        Fri May 18 16:43:22 2018 UTC

----------------------------------------------------------------------------

3 files changed, 169 insertions(+), 15 deletions(-)
headers/private/kernel/compat/image_compat.h | 129 +++++++++++++++++++++++
headers/private/kernel/util/syscall_args.h   |  25 +++++
src/system/kernel/image.cpp                  |  30 +++---

----------------------------------------------------------------------------

diff --git a/headers/private/kernel/compat/image_compat.h 
b/headers/private/kernel/compat/image_compat.h
new file mode 100644
index 0000000000..eb52f03698
--- /dev/null
+++ b/headers/private/kernel/compat/image_compat.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2018, Haiku Inc. All rights reserved.
+ *
+ * Distributed under the terms of the MIT License.
+ */
+#ifndef _KERNEL_COMPAT_IMAGE_H
+#define _KERNEL_COMPAT_IMAGE_H
+
+
+#include <image.h>
+
+
+#define compat_uintptr_t uint32
+typedef struct {
+       image_id        id;
+       image_type      type;
+       int32           sequence;
+       int32           init_order;
+       compat_uintptr_t        init_routine;
+       compat_uintptr_t        term_routine;
+       dev_t           device;
+       ino_t           node;
+       char            name[MAXPATHLEN];
+       compat_uintptr_t        text;
+       compat_uintptr_t        data;
+       int32           text_size;
+       int32           data_size;
+
+       /* Haiku R1 extensions */
+       int32           api_version;    /* the Haiku API version used by the 
image */
+       int32           abi;                    /* the Haiku ABI used by the 
image */
+} _PACKED compat_image_info;
+
+
+typedef struct {
+       compat_image_info       basic_info;
+       int32                           text_delta;
+       compat_uintptr_t        symbol_table;
+       compat_uintptr_t        symbol_hash;
+       compat_uintptr_t        string_table;
+} _PACKED compat_extended_image_info;
+
+
+static_assert(sizeof(compat_image_info) == 1084,
+       "size of compat_image_info mismatch");
+static_assert(sizeof(compat_extended_image_info) == 1100,
+       "size of compat_extended_image_info mismatch");
+
+
+inline status_t
+copy_ref_var_to_user(image_info &info, image_info* userInfo, size_t size)
+{
+       if (!IS_USER_ADDRESS(userInfo))
+               return B_BAD_ADDRESS;
+       Thread* thread = thread_get_current_thread();
+       bool compatMode = (thread->flags & THREAD_FLAGS_COMPAT_MODE) != 0;
+       if (compatMode) {
+               if (size > sizeof(compat_image_info))
+                       return B_BAD_VALUE;
+               compat_image_info compat_info;
+               compat_info.id = info.id;
+               compat_info.type = info.type;
+               compat_info.sequence = info.sequence;
+               compat_info.init_order = info.init_order;
+               compat_info.init_routine = (uint32)(addr_t)info.init_routine;
+               compat_info.term_routine = (uint32)(addr_t)info.term_routine;
+               compat_info.device = info.device;
+               compat_info.node = info.node;
+               strlcpy(compat_info.name, info.name, MAXPATHLEN);
+               compat_info.text = (uint32)(addr_t)info.text;
+               compat_info.data = (uint32)(addr_t)info.data;
+               compat_info.text_size = info.text_size;
+               compat_info.data_size = info.data_size;
+               if (user_memcpy(userInfo, &compat_info, size) < B_OK)
+                       return B_BAD_ADDRESS;
+       } else {
+               if (size > sizeof(image_info))
+                       return B_BAD_VALUE;
+
+               if (user_memcpy(userInfo, &info, size) < B_OK)
+                       return B_BAD_ADDRESS;
+       }
+       return B_OK;
+}
+
+
+inline status_t
+copy_ref_var_from_user(extended_image_info* userInfo,
+       extended_image_info &info, size_t size)
+{
+       if (!IS_USER_ADDRESS(userInfo))
+               return B_BAD_ADDRESS;
+       Thread* thread = thread_get_current_thread();
+       bool compatMode = (thread->flags & THREAD_FLAGS_COMPAT_MODE) != 0;
+       if (compatMode) {
+               compat_extended_image_info compat_info;
+               if (size != sizeof(compat_info))
+                       return B_BAD_VALUE;
+               if (user_memcpy(&compat_info, userInfo, size) < B_OK)
+                       return B_BAD_ADDRESS;
+               info.basic_info.id = compat_info.basic_info.id;
+               info.basic_info.type = compat_info.basic_info.type;
+               info.basic_info.sequence = compat_info.basic_info.sequence;
+               info.basic_info.init_order = compat_info.basic_info.init_order;
+               info.basic_info.init_routine = 
(void(*)())(addr_t)compat_info.basic_info.init_routine;
+               info.basic_info.term_routine = 
(void(*)())(addr_t)compat_info.basic_info.term_routine;
+               info.basic_info.device = compat_info.basic_info.device;
+               info.basic_info.node = compat_info.basic_info.node;
+               strlcpy(info.basic_info.name, compat_info.basic_info.name, 
MAXPATHLEN);
+               info.basic_info.text = 
(void*)(addr_t)compat_info.basic_info.text;
+               info.basic_info.data = 
(void*)(addr_t)compat_info.basic_info.data;
+               info.basic_info.text_size = compat_info.basic_info.text_size;
+               info.basic_info.data_size = compat_info.basic_info.data_size;
+               info.text_delta = compat_info.text_delta;
+               info.symbol_table = (void*)(addr_t)compat_info.symbol_table;
+               info.symbol_hash = (void*)(addr_t)compat_info.symbol_hash;
+               info.string_table = (void*)(addr_t)compat_info.string_table;
+       } else {
+               if (size != sizeof(info))
+                       return B_BAD_VALUE;
+
+               if (user_memcpy(&info, userInfo, size) < B_OK)
+                       return B_BAD_ADDRESS;
+       }
+       return B_OK;
+}
+
+
+#endif // _KERNEL_COMPAT_IMAGE_H
diff --git a/headers/private/kernel/util/syscall_args.h 
b/headers/private/kernel/util/syscall_args.h
index 46eab7342c..c6d1d6166d 100644
--- a/headers/private/kernel/util/syscall_args.h
+++ b/headers/private/kernel/util/syscall_args.h
@@ -23,6 +23,18 @@ copy_ref_var_from_user(T *user, T &kernel)
        return user_memcpy(&kernel, user, sizeof(T));
 }
 
+
+template<typename T>
+inline
+status_t
+copy_ref_var_from_user(T *user, T &kernel, size_t size)
+{
+       if (size != sizeof(T))
+               return B_BAD_VALUE;
+       return copy_ref_var_from_user(user, kernel);
+}
+
+
 // copy_ref_var_to_user
 template<typename T>
 inline
@@ -35,4 +47,17 @@ copy_ref_var_to_user(T &kernel, T *user)
 }
 
 
+template<typename T>
+inline
+status_t
+copy_ref_var_to_user(T &kernel, T *user, size_t size)
+{
+       if (size > sizeof(T))
+               return B_BAD_VALUE;
+       if (!IS_USER_ADDRESS(user))
+               return B_BAD_ADDRESS;
+       return user_memcpy(user, &kernel, size);
+}
+
+
 #endif // _SYSCALL_ARGS_H
diff --git a/src/system/kernel/image.cpp b/src/system/kernel/image.cpp
index 30c4b293b0..41b79899f4 100644
--- a/src/system/kernel/image.cpp
+++ b/src/system/kernel/image.cpp
@@ -18,6 +18,11 @@
 #include <thread_types.h>
 #include <user_debugger.h>
 #include <util/AutoLock.h>
+#include <util/syscall_args.h>
+
+#ifdef _COMPAT_MODE
+#      include <image_compat.h>
+#endif
 
 #include <stdlib.h>
 #include <string.h>
@@ -464,12 +469,9 @@ _user_register_image(extended_image_info *userInfo, size_t 
size)
 {
        extended_image_info info;
 
-       if (size != sizeof(info))
-               return B_BAD_VALUE;
-
-       if (!IS_USER_ADDRESS(userInfo)
-               || user_memcpy(&info, userInfo, size) < B_OK)
-               return B_BAD_ADDRESS;
+       status_t status = copy_ref_var_from_user(userInfo, info, size);
+       if (status != B_OK)
+               return status;
 
        return register_image(thread_get_current_thread()->team, &info, size);
 }
@@ -525,9 +527,9 @@ _user_get_image_info(image_id id, image_info *userInfo, 
size_t size)
 
        status = _get_image_info(id, &info, sizeof(image_info));
 
-       if (user_memcpy(userInfo, &info, size) < B_OK)
-               return B_BAD_ADDRESS;
-
+       status_t err = copy_ref_var_to_user(info, userInfo, size);
+       if (err != B_OK)
+               return err;
        return status;
 }
 
@@ -540,9 +542,6 @@ _user_get_next_image_info(team_id team, int32 *_cookie, 
image_info *userInfo,
        status_t status;
        int32 cookie;
 
-       if (size > sizeof(image_info))
-               return B_BAD_VALUE;
-
        if (!IS_USER_ADDRESS(userInfo) || !IS_USER_ADDRESS(_cookie)
                || user_memcpy(&cookie, _cookie, sizeof(int32)) < B_OK) {
                return B_BAD_ADDRESS;
@@ -550,10 +549,11 @@ _user_get_next_image_info(team_id team, int32 *_cookie, 
image_info *userInfo,
 
        status = _get_next_image_info(team, &cookie, &info, sizeof(image_info));
 
-       if (user_memcpy(userInfo, &info, size) < B_OK
-               || user_memcpy(_cookie, &cookie, sizeof(int32)) < B_OK) {
+       status_t err = copy_ref_var_to_user(info, userInfo, size);
+       if (err != B_OK)
+               return err;
+       if (user_memcpy(_cookie, &cookie, sizeof(int32)) < B_OK)
                return B_BAD_ADDRESS;
-       }
 
        return status;
 }


Other related posts:

  • » [haiku-commits] haiku: hrev52006 - headers/private/kernel/compat src/system/kernel headers/private/kernel/util - Jérôme Duval