shbuf.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright notice, this
  9. * list of conditions and the following disclaimer.
  10. *
  11. * 2. Redistributions in binary form must reproduce the above copyright notice,
  12. * this list of conditions and the following disclaimer in the documentation
  13. * and/or other materials provided with the distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  16. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  18. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  19. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  20. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  21. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  22. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  23. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  24. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. #include <Kernel/Process.h>
  27. #include <Kernel/SharedBuffer.h>
  28. //#define SHARED_BUFFER_DEBUG
  29. namespace Kernel {
  30. void Process::disown_all_shared_buffers()
  31. {
  32. LOCKER(shared_buffers().lock());
  33. Vector<SharedBuffer*, 32> buffers_to_disown;
  34. for (auto& it : shared_buffers().resource())
  35. buffers_to_disown.append(it.value.ptr());
  36. for (auto* shared_buffer : buffers_to_disown) {
  37. if (shared_buffer->disown(m_pid)) {
  38. shared_buffers().resource().remove(shared_buffer->id());
  39. delete shared_buffer;
  40. }
  41. }
  42. }
  43. int Process::sys$shbuf_create(int size, void** buffer)
  44. {
  45. REQUIRE_PROMISE(shared_buffer);
  46. if (!size || size < 0)
  47. return -EINVAL;
  48. size = PAGE_ROUND_UP(size);
  49. auto vmobject = AnonymousVMObject::create_with_size(size, AllocationStrategy::Reserve);
  50. if (!vmobject)
  51. return -ENOMEM;
  52. LOCKER(shared_buffers().lock());
  53. static int s_next_shbuf_id;
  54. int shbuf_id = ++s_next_shbuf_id;
  55. auto shared_buffer = make<SharedBuffer>(shbuf_id, vmobject.release_nonnull());
  56. shared_buffer->share_with(m_pid);
  57. void* address = shared_buffer->ref_for_process_and_get_address(*this);
  58. if (!copy_to_user(buffer, &address))
  59. return -EFAULT;
  60. ASSERT((int)shared_buffer->size() >= size);
  61. #ifdef SHARED_BUFFER_DEBUG
  62. klog() << "Created shared buffer " << shbuf_id << " @ " << buffer << " (" << size << " bytes, vmobject is " << shared_buffer->size() << ")";
  63. #endif
  64. shared_buffers().resource().set(shbuf_id, move(shared_buffer));
  65. return shbuf_id;
  66. }
  67. int Process::sys$shbuf_allow_pid(int shbuf_id, pid_t peer_pid)
  68. {
  69. REQUIRE_PROMISE(shared_buffer);
  70. if (!peer_pid || peer_pid < 0 || ProcessID(peer_pid) == m_pid)
  71. return -EINVAL;
  72. LOCKER(shared_buffers().lock());
  73. auto it = shared_buffers().resource().find(shbuf_id);
  74. if (it == shared_buffers().resource().end())
  75. return -EINVAL;
  76. auto& shared_buffer = *(*it).value;
  77. if (!shared_buffer.is_shared_with(m_pid))
  78. return -EPERM;
  79. {
  80. ScopedSpinLock lock(g_processes_lock);
  81. auto peer = Process::from_pid(peer_pid);
  82. if (!peer)
  83. return -ESRCH;
  84. }
  85. shared_buffer.share_with(peer_pid);
  86. return 0;
  87. }
  88. int Process::sys$shbuf_release(int shbuf_id)
  89. {
  90. REQUIRE_PROMISE(shared_buffer);
  91. LOCKER(shared_buffers().lock());
  92. auto it = shared_buffers().resource().find(shbuf_id);
  93. if (it == shared_buffers().resource().end())
  94. return -EINVAL;
  95. auto& shared_buffer = *(*it).value;
  96. if (!shared_buffer.is_shared_with(m_pid))
  97. return -EPERM;
  98. #ifdef SHARED_BUFFER_DEBUG
  99. klog() << "Releasing shared buffer " << shbuf_id << ", buffer count: " << shared_buffers().resource().size();
  100. #endif
  101. shared_buffer.deref_for_process(*this);
  102. return 0;
  103. }
  104. void* Process::sys$shbuf_get(int shbuf_id, Userspace<size_t*> user_size)
  105. {
  106. REQUIRE_PROMISE(shared_buffer);
  107. LOCKER(shared_buffers().lock());
  108. auto it = shared_buffers().resource().find(shbuf_id);
  109. if (it == shared_buffers().resource().end())
  110. return (void*)-EINVAL;
  111. auto& shared_buffer = *(*it).value;
  112. if (!shared_buffer.is_shared_with(m_pid))
  113. return (void*)-EPERM;
  114. #ifdef SHARED_BUFFER_DEBUG
  115. klog() << "Retaining shared buffer " << shbuf_id << ", buffer count: " << shared_buffers().resource().size();
  116. #endif
  117. if (user_size) {
  118. size_t size = shared_buffer.size();
  119. if (!copy_to_user(user_size, &size))
  120. return (void*)-EFAULT;
  121. }
  122. return shared_buffer.ref_for_process_and_get_address(*this);
  123. }
  124. int Process::sys$shbuf_seal(int shbuf_id)
  125. {
  126. REQUIRE_PROMISE(shared_buffer);
  127. LOCKER(shared_buffers().lock());
  128. auto it = shared_buffers().resource().find(shbuf_id);
  129. if (it == shared_buffers().resource().end())
  130. return -EINVAL;
  131. auto& shared_buffer = *(*it).value;
  132. if (!shared_buffer.is_shared_with(m_pid))
  133. return -EPERM;
  134. #ifdef SHARED_BUFFER_DEBUG
  135. klog() << "Sealing shared buffer " << shbuf_id;
  136. #endif
  137. shared_buffer.seal();
  138. return 0;
  139. }
  140. }