status_t _user_get_next_image_info(team_id team, int32 *_cookie, image_info *userInfo, size_t size) { image_info info; 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; } 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) { return B_BAD_ADDRESS; } return status; }
ssize_t _user_sendto(int socket, const void *data, size_t length, int flags, const struct sockaddr *userAddress, socklen_t addressLength) { if (data == NULL || !IS_USER_ADDRESS(data)) return B_BAD_ADDRESS; // TODO: If this is a connection-mode socket, the address parameter is // supposed to be ignored. if (userAddress == NULL || addressLength <= 0 || addressLength > MAX_SOCKET_ADDRESS_LENGTH) { return B_BAD_VALUE; } // copy address from userland char address[MAX_SOCKET_ADDRESS_LENGTH]; if (!IS_USER_ADDRESS(userAddress) || user_memcpy(address, userAddress, addressLength) != B_OK) { return B_BAD_ADDRESS; } // sendto() SyscallRestartWrapper<ssize_t> result; return result = common_sendto(socket, data, length, flags, (sockaddr*)address, addressLength, false); }
static status_t prepare_userland_address_result(struct sockaddr* userAddress, socklen_t* _addressLength, socklen_t& addressLength, bool addressRequired) { // check parameters if (_addressLength == NULL) return B_BAD_VALUE; if (userAddress == NULL) { if (addressRequired) return B_BAD_VALUE; } else if (!IS_USER_ADDRESS(userAddress) || !IS_USER_ADDRESS(_addressLength)) { return B_BAD_ADDRESS; } // copy the buffer size from userland addressLength = 0; if (userAddress != NULL && user_memcpy(&addressLength, _addressLength, sizeof(socklen_t)) != B_OK) { return B_BAD_ADDRESS; } if (addressLength > MAX_SOCKET_ADDRESS_LENGTH) addressLength = MAX_SOCKET_ADDRESS_LENGTH; return B_OK; }
status_t _user_get_next_socket_stat(int family, uint32 *_cookie, struct net_stat *_stat) { // check parameters and copy cookie from userland if (_cookie == NULL || _stat == NULL) return B_BAD_VALUE; uint32 cookie; if (!IS_USER_ADDRESS(_stat) || !IS_USER_ADDRESS(_cookie) || user_memcpy(&cookie, _cookie, sizeof(cookie)) != B_OK) { return B_BAD_ADDRESS; } net_stat stat; SyscallRestartWrapper<status_t> error; error = common_get_next_socket_stat(family, &cookie, &stat); if (error != B_OK) return error; // copy cookie and data back to userland if (user_memcpy(_cookie, &cookie, sizeof(cookie)) != B_OK || user_memcpy(_stat, &stat, sizeof(net_stat)) != B_OK) { return B_BAD_ADDRESS; } return B_OK; }
status_t _user_getsockopt(int socket, int level, int option, void *userValue, socklen_t *_length) { // check params if (userValue == NULL || _length == NULL) return B_BAD_VALUE; if (!IS_USER_ADDRESS(userValue) || !IS_USER_ADDRESS(_length)) return B_BAD_ADDRESS; // copy length from userland socklen_t length; if (user_memcpy(&length, _length, sizeof(socklen_t)) != B_OK) return B_BAD_ADDRESS; if (length > MAX_SOCKET_OPTION_LENGTH) return B_BAD_VALUE; // getsockopt() char value[MAX_SOCKET_OPTION_LENGTH]; SyscallRestartWrapper<status_t> error; error = common_getsockopt(socket, level, option, value, &length, false); if (error != B_OK) return error; // copy value back to userland if (user_memcpy(userValue, value, length) != B_OK) return B_BAD_ADDRESS; return B_OK; }
static status_t prepare_userland_msghdr(const msghdr* userMessage, msghdr& message, iovec*& userVecs, MemoryDeleter& vecsDeleter, void*& userAddress, char* address) { if (userMessage == NULL) return B_BAD_VALUE; // copy message from userland if (!IS_USER_ADDRESS(userMessage) || user_memcpy(&message, userMessage, sizeof(msghdr)) != B_OK) { return B_BAD_ADDRESS; } userVecs = message.msg_iov; userAddress = message.msg_name; // copy iovecs from userland if (message.msg_iovlen < 0 || message.msg_iovlen > IOV_MAX) return EMSGSIZE; if (userVecs != NULL && message.msg_iovlen > 0) { iovec* vecs = (iovec*)malloc(sizeof(iovec) * message.msg_iovlen); if (vecs == NULL) return B_NO_MEMORY; vecsDeleter.SetTo(vecs); if (!IS_USER_ADDRESS(message.msg_iov) || user_memcpy(vecs, message.msg_iov, message.msg_iovlen * sizeof(iovec)) != B_OK) { return B_BAD_ADDRESS; } for (int i = 0; i < message.msg_iovlen; i++) { if (!IS_USER_ADDRESS(vecs[i].iov_base)) return B_BAD_ADDRESS; } message.msg_iov = vecs; } else { message.msg_iov = NULL; message.msg_iovlen = 0; } // prepare the address field userAddress = message.msg_name; if (userAddress != NULL) { if (!IS_USER_ADDRESS(message.msg_name)) return B_BAD_ADDRESS; if (message.msg_namelen > MAX_SOCKET_ADDRESS_LENGTH) message.msg_namelen = MAX_SOCKET_ADDRESS_LENGTH; message.msg_name = address; } return B_OK; }
status_t socket_control(net_socket* socket, int32 op, void* data, size_t length) { switch (op) { case FIONBIO: { if (data == NULL) return B_BAD_VALUE; int value; if (is_syscall()) { if (!IS_USER_ADDRESS(data) || user_memcpy(&value, data, sizeof(int)) != B_OK) { return B_BAD_ADDRESS; } } else value = *(int*)data; return socket_setsockopt(socket, SOL_SOCKET, SO_NONBLOCK, &value, sizeof(int)); } case FIONREAD: { if (data == NULL) return B_BAD_VALUE; ssize_t available = socket_read_avail(socket); if (available < B_OK) return available; if (is_syscall()) { if (!IS_USER_ADDRESS(data) || user_memcpy(data, &available, sizeof(ssize_t)) != B_OK) { return B_BAD_ADDRESS; } } else *(ssize_t *)data = available; return B_OK; } case B_SET_BLOCKING_IO: case B_SET_NONBLOCKING_IO: { int value = op == B_SET_NONBLOCKING_IO; return socket_setsockopt(socket, SOL_SOCKET, SO_NONBLOCK, &value, sizeof(int)); } } return socket->first_info->control(socket->first_protocol, LEVEL_DRIVER_IOCTL, op, data, &length); }
status_t _user_mutex_switch_lock(int32* fromMutex, int32* toMutex, const char* name, uint32 flags, bigtime_t timeout) { if (fromMutex == NULL || !IS_USER_ADDRESS(fromMutex) || (addr_t)fromMutex % 4 != 0 || toMutex == NULL || !IS_USER_ADDRESS(toMutex) || (addr_t)toMutex % 4 != 0) { return B_BAD_ADDRESS; } return user_mutex_switch_lock(fromMutex, toMutex, name, flags | B_CAN_INTERRUPT, timeout); }
status_t _user_get_timezone(time_t *_timezoneOffset, bool *_daylightSavingTime) { time_t offset = (time_t)(sTimezoneOffset / 1000000LL); if (!IS_USER_ADDRESS(_timezoneOffset) || !IS_USER_ADDRESS(_daylightSavingTime) || user_memcpy(_timezoneOffset, &offset, sizeof(time_t)) < B_OK || user_memcpy(_daylightSavingTime, &sDaylightSavingTime, sizeof(bool)) < B_OK) return B_BAD_ADDRESS; return B_OK; }
ssize_t _user_recvfrom(int socket, void *data, size_t length, int flags, struct sockaddr *userAddress, socklen_t *_addressLength) { if (data == NULL || !IS_USER_ADDRESS(data)) return B_BAD_ADDRESS; // check parameters socklen_t addressLength = 0; status_t error = prepare_userland_address_result(userAddress, _addressLength, addressLength, false); if (error != B_OK) return error; // recvfrom() SyscallRestartWrapper<ssize_t> result; char address[MAX_SOCKET_ADDRESS_LENGTH]; socklen_t userAddressBufferSize = addressLength; result = common_recvfrom(socket, data, length, flags, userAddress != NULL ? (sockaddr*)address : NULL, &addressLength, false); if (result < 0) return result; // copy address size and address back to userland if (copy_address_to_userland(address, addressLength, userAddress, userAddressBufferSize, _addressLength) != B_OK) { return B_BAD_ADDRESS; } return result; }
status_t _user_system_profiler_next_buffer(size_t bytesRead, uint64* _droppedEvents) { if (_droppedEvents != NULL && !IS_USER_ADDRESS(_droppedEvents)) return B_BAD_ADDRESS; team_id team = thread_get_current_thread()->team->id; InterruptsSpinLocker locker(sProfilerLock); if (sProfiler == NULL || sProfiler->TeamID() != team) return B_BAD_VALUE; // get a reference to the profiler SystemProfiler* profiler = sProfiler; BReference<SystemProfiler> reference(profiler); locker.Unlock(); uint64 droppedEvents; status_t error = profiler->NextBuffer(bytesRead, _droppedEvents != NULL ? &droppedEvents : NULL); if (error == B_OK && _droppedEvents != NULL) user_memcpy(_droppedEvents, &droppedEvents, sizeof(droppedEvents)); return error; }
status_t _user_get_timer(int32 timerID, thread_id threadID, struct user_timer_info* userInfo) { // get the timer TimerLocker timerLocker; UserTimer* timer; status_t error = timerLocker.LockAndGetTimer(threadID, timerID, timer); if (error != B_OK) return error; // get the info user_timer_info info; timer->GetInfo(info.remaining_time, info.interval, info.overrun_count); // Sanitize remaining_time. If it's <= 0, we set it to 1, the least valid // value. if (info.remaining_time <= 0) info.remaining_time = 1; timerLocker.Unlock(); // copy it back to userland if (userInfo != NULL && (!IS_USER_ADDRESS(userInfo) || user_memcpy(userInfo, &info, sizeof(info)) != B_OK)) { return B_BAD_ADDRESS; } return B_OK; }
status_t _user_socketpair(int family, int type, int protocol, int *userSocketVector) { // check parameters if (userSocketVector == NULL) return B_BAD_VALUE; if (!IS_USER_ADDRESS(userSocketVector)) return B_BAD_ADDRESS; // socketpair() int socketVector[2]; SyscallRestartWrapper<status_t> error; error = common_socketpair(family, type, protocol, socketVector, false); if (error != B_OK) return error; // copy FDs back to userland if (user_memcpy(userSocketVector, socketVector, sizeof(socketVector)) != B_OK) { _user_close(socketVector[0]); _user_close(socketVector[1]); return B_BAD_ADDRESS; } return B_OK; }
status_t _user_writev_port_etc(port_id port, int32 messageCode, const iovec *userVecs, size_t vecCount, size_t bufferSize, uint32 flags, bigtime_t timeout) { syscall_restart_handle_timeout_pre(flags, timeout); if (userVecs == NULL && bufferSize != 0) return B_BAD_VALUE; if (userVecs != NULL && !IS_USER_ADDRESS(userVecs)) return B_BAD_ADDRESS; iovec *vecs = NULL; if (userVecs && vecCount != 0) { vecs = (iovec*)malloc(sizeof(iovec) * vecCount); if (vecs == NULL) return B_NO_MEMORY; if (user_memcpy(vecs, userVecs, sizeof(iovec) * vecCount) < B_OK) { free(vecs); return B_BAD_ADDRESS; } } status_t status = writev_port_etc(port, messageCode, vecs, vecCount, bufferSize, flags | PORT_FLAG_USE_USER_MEMCPY | B_CAN_INTERRUPT, timeout); free(vecs); return syscall_restart_handle_timeout_post(status, timeout); }
status_t _user_system_profiler_recorded(struct system_profiler_parameters* userParameters) { if (userParameters == NULL || !IS_USER_ADDRESS(userParameters)) return B_BAD_ADDRESS; if (sRecordedParameters == NULL) return B_ERROR; // Transfer the area to the userland process void* address; area_id newArea = transfer_area(sRecordedParameters->buffer_area, &address, B_ANY_ADDRESS, team_get_current_team_id(), true); if (newArea < 0) return newArea; status_t status = set_area_protection(newArea, B_READ_AREA); if (status == B_OK) { sRecordedParameters->buffer_area = newArea; status = user_memcpy(userParameters, sRecordedParameters, sizeof(system_profiler_parameters)); } if (status != B_OK) delete_area(newArea); delete sRecordedParameters; sRecordedParameters = NULL; return status; }
status_t _user_set_timezone(time_t timezoneOffset, const char *name, size_t nameLength) { bigtime_t offset = (bigtime_t)timezoneOffset * 1000000LL; if (geteuid() != 0) return B_NOT_ALLOWED; TRACE(("old system_time_offset %Ld old %Ld new %Ld gmt %d\n", arch_rtc_get_system_time_offset(sRealTimeData), sTimezoneOffset, offset, sIsGMT)); if (name != NULL && nameLength > 0) { if (!IS_USER_ADDRESS(name) || user_strlcpy(sTimezoneName, name, sizeof(sTimezoneName)) < 0) return B_BAD_ADDRESS; } // We only need to update our time offset if the hardware clock // does not run in the local timezone. // Since this is shared data, we need to update it atomically. if (!sIsGMT) { arch_rtc_set_system_time_offset(sRealTimeData, arch_rtc_get_system_time_offset(sRealTimeData) + sTimezoneOffset - offset); real_time_clock_changed(); } sTimezoneOffset = offset; TRACE(("new system_time_offset %Ld\n", arch_rtc_get_system_time_offset(sRealTimeData))); return B_OK; }
char* alloc_tracing_buffer_strcpy(const char* source, size_t maxSize, bool user) { if (source == NULL || maxSize == 0) return NULL; if (user && !IS_USER_ADDRESS(source)) return NULL; // limit maxSize to the actual source string len if (user) { ssize_t size = user_strlcpy(NULL, source, 0); // there's no user_strnlen() if (size < 0) return 0; maxSize = min_c(maxSize, (size_t)size + 1); } else maxSize = strnlen(source, maxSize - 1) + 1; char* buffer = (char*)alloc_tracing_buffer(maxSize); if (buffer == NULL) return NULL; if (user) { if (user_strlcpy(buffer, source, maxSize) < B_OK) return NULL; } else strlcpy(buffer, source, maxSize); return buffer; }
status_t _user_get_timezone(time_t *_timezoneOffset, char *userName, size_t nameLength) { time_t offset = (time_t)(sTimezoneOffset / 1000000LL); if (_timezoneOffset != NULL && (!IS_USER_ADDRESS(_timezoneOffset) || user_memcpy(_timezoneOffset, &offset, sizeof(time_t)) < B_OK)) return B_BAD_ADDRESS; if (userName != NULL && (!IS_USER_ADDRESS(userName) || user_strlcpy(userName, sTimezoneName, nameLength) < 0)) return B_BAD_ADDRESS; return B_OK; }
ssize_t _user_recv(int socket, void *data, size_t length, int flags) { if (data == NULL || !IS_USER_ADDRESS(data)) return B_BAD_ADDRESS; SyscallRestartWrapper<ssize_t> result; return result = common_recv(socket, data, length, flags, false); }
status_t _user_get_tzfilename(char *userFilename, size_t length, bool *_userIsGMT) { if ((userFilename == NULL || length == 0) && _userIsGMT == NULL) return B_BAD_VALUE; if (userFilename != NULL && (!IS_USER_ADDRESS(userFilename) || user_strlcpy(userFilename, sTimezoneFilename, length) < 0)) return B_BAD_ADDRESS; if (_userIsGMT != NULL && (!IS_USER_ADDRESS(_userIsGMT) || user_memcpy(_userIsGMT, &sIsGMT, sizeof(bool)) != B_OK)) return B_BAD_ADDRESS; return B_OK; }
ssize_t _user_recvmsg(int socket, struct msghdr *userMessage, int flags) { // copy message from userland msghdr message; iovec* userVecs; MemoryDeleter vecsDeleter; void* userAddress; char address[MAX_SOCKET_ADDRESS_LENGTH]; status_t error = prepare_userland_msghdr(userMessage, message, userVecs, vecsDeleter, userAddress, address); if (error != B_OK) return error; // prepare a buffer for ancillary data MemoryDeleter ancillaryDeleter; void* ancillary = NULL; void* userAncillary = message.msg_control; if (userAncillary != NULL) { if (!IS_USER_ADDRESS(userAncillary)) return B_BAD_ADDRESS; if (message.msg_controllen < 0) return B_BAD_VALUE; if (message.msg_controllen > MAX_ANCILLARY_DATA_LENGTH) message.msg_controllen = MAX_ANCILLARY_DATA_LENGTH; message.msg_control = ancillary = malloc(message.msg_controllen); if (message.msg_control == NULL) return B_NO_MEMORY; ancillaryDeleter.SetTo(ancillary); } // recvmsg() SyscallRestartWrapper<ssize_t> result; result = common_recvmsg(socket, &message, flags, false); if (result < 0) return result; // copy the address, the ancillary data, and the message header back to // userland message.msg_name = userAddress; message.msg_iov = userVecs; message.msg_control = userAncillary; if ((userAddress != NULL && user_memcpy(userAddress, address, message.msg_namelen) != B_OK) || (userAncillary != NULL && user_memcpy(userAncillary, ancillary, message.msg_controllen) != B_OK) || user_memcpy(userMessage, &message, sizeof(msghdr)) != B_OK) { return B_BAD_ADDRESS; } return result; }
static status_t launch_speedup_control(const char *subsystem, uint32 function, void *buffer, size_t bufferSize) { switch (function) { case LAUNCH_SPEEDUP_START_SESSION: { char name[B_OS_NAME_LENGTH]; if (!IS_USER_ADDRESS(buffer) || user_strlcpy(name, (const char *)buffer, B_OS_NAME_LENGTH) < B_OK) return B_BAD_ADDRESS; if (isdigit(name[0]) || name[0] == '.') return B_BAD_VALUE; sMainSession = start_session(-1, -1, -1, name, 60); sMainSession->Unlock(); return B_OK; } case LAUNCH_SPEEDUP_STOP_SESSION: { char name[B_OS_NAME_LENGTH]; if (!IS_USER_ADDRESS(buffer) || user_strlcpy(name, (const char *)buffer, B_OS_NAME_LENGTH) < B_OK) return B_BAD_ADDRESS; // ToDo: this check is not thread-safe if (sMainSession == NULL || strcmp(sMainSession->Name(), name)) return B_BAD_VALUE; if (!strcmp(name, "system boot")) dprintf("STOP BOOT %Ld\n", system_time()); sMainSession->Lock(); stop_session(sMainSession); sMainSession = NULL; return B_OK; } } return B_BAD_VALUE; }
status_t _user_get_cpu_topology_info(cpu_topology_node_info* topologyInfos, uint32* topologyInfoCount) { if (topologyInfoCount == NULL || !IS_USER_ADDRESS(topologyInfoCount)) return B_BAD_ADDRESS; const cpu_topology_node* node = get_cpu_topology(); uint32 count = 0; count_topology_nodes(node, count); if (topologyInfos == NULL) return user_memcpy(topologyInfoCount, &count, sizeof(uint32)); else if (!IS_USER_ADDRESS(topologyInfoCount)) return B_BAD_ADDRESS; uint32 userCount; status_t error = user_memcpy(&userCount, topologyInfoCount, sizeof(uint32)); if (error != B_OK) return error; if (userCount == 0) return B_OK; count = std::min(count, userCount); cpu_topology_node_info* topology = new(std::nothrow) cpu_topology_node_info[count]; if (topology == NULL) return B_NO_MEMORY; ArrayDeleter<cpu_topology_node_info> _(topology); memset(topology, 0, sizeof(cpu_topology_node_info) * count); uint32 nodesLeft = count; generate_topology_array(topology, node, nodesLeft); ASSERT(nodesLeft == 0); error = user_memcpy(topologyInfos, topology, sizeof(cpu_topology_node_info) * count); if (error != B_OK) return error; return user_memcpy(topologyInfoCount, &count, sizeof(uint32)); }
status_t _user_set_signal_stack(const stack_t *newUserStack, stack_t *oldUserStack) { struct thread *thread = thread_get_current_thread(); struct stack_t newStack, oldStack; bool onStack = false; if ((newUserStack != NULL && user_memcpy(&newStack, newUserStack, sizeof(stack_t)) < B_OK) || (oldUserStack != NULL && user_memcpy(&oldStack, oldUserStack, sizeof(stack_t)) < B_OK)) return B_BAD_ADDRESS; if (thread->signal_stack_enabled) { // determine wether or not the user thread is currently // on the active signal stack onStack = arch_on_signal_stack(thread); } if (oldUserStack != NULL) { oldStack.ss_sp = (void *)thread->signal_stack_base; oldStack.ss_size = thread->signal_stack_size; oldStack.ss_flags = (thread->signal_stack_enabled ? 0 : SS_DISABLE) | (onStack ? SS_ONSTACK : 0); } if (newUserStack != NULL) { // no flags other than SS_DISABLE are allowed if ((newStack.ss_flags & ~SS_DISABLE) != 0) return B_BAD_VALUE; if ((newStack.ss_flags & SS_DISABLE) == 0) { // check if the size is valid if (newStack.ss_size < MINSIGSTKSZ) return B_NO_MEMORY; if (onStack) return B_NOT_ALLOWED; if (!IS_USER_ADDRESS(newStack.ss_sp)) return B_BAD_VALUE; thread->signal_stack_base = (addr_t)newStack.ss_sp; thread->signal_stack_size = newStack.ss_size; thread->signal_stack_enabled = true; } else thread->signal_stack_enabled = false; } // only copy the old stack info if a pointer has been given if (oldUserStack != NULL && user_memcpy(oldUserStack, &oldStack, sizeof(stack_t)) < B_OK) return B_BAD_ADDRESS; return B_OK; }
status_t _user_ioctl(int fd, uint32 op, void* buffer, size_t length) { if (!IS_USER_ADDRESS(buffer)) return B_BAD_ADDRESS; TRACE(("user_ioctl: fd %d\n", fd)); SyscallRestartWrapper<status_t> status; return status = fd_ioctl(false, fd, op, buffer, length); }
inline ssize_t RingBuffer::Read(void* buffer, size_t length, bool isUser) { if (fBuffer == NULL) return B_NO_MEMORY; if (isUser && !IS_USER_ADDRESS(buffer)) return B_BAD_ADDRESS; return isUser ? ring_buffer_user_read(fBuffer, (uint8*)buffer, length) : ring_buffer_read(fBuffer, (uint8*)buffer, length); }
ssize_t _user_read_dir(int fd, struct dirent* userBuffer, size_t bufferSize, uint32 maxCount) { TRACE(("user_read_dir(fd = %d, userBuffer = %p, bufferSize = %ld, count = " "%lu)\n", fd, userBuffer, bufferSize, maxCount)); if (maxCount == 0) return 0; if (userBuffer == NULL || !IS_USER_ADDRESS(userBuffer)) return B_BAD_ADDRESS; // get I/O context and FD io_context* ioContext = get_current_io_context(false); FDGetter fdGetter; struct file_descriptor* descriptor = fdGetter.SetTo(ioContext, fd, false); if (descriptor == NULL || (descriptor->open_mode & O_DISCONNECTED) != 0) return B_FILE_ERROR; if (descriptor->ops->fd_read_dir == NULL) return B_UNSUPPORTED; // restrict buffer size and allocate a heap buffer if (bufferSize > kMaxReadDirBufferSize) bufferSize = kMaxReadDirBufferSize; struct dirent* buffer = (struct dirent*)malloc(bufferSize); if (buffer == NULL) return B_NO_MEMORY; MemoryDeleter bufferDeleter(buffer); // read the directory uint32 count = maxCount; status_t status = descriptor->ops->fd_read_dir(ioContext, descriptor, buffer, bufferSize, &count); if (status != B_OK) return status; // copy the buffer back -- determine the total buffer size first size_t sizeToCopy = 0; struct dirent* entry = buffer; for (uint32 i = 0; i < count; i++) { size_t length = entry->d_reclen; sizeToCopy += length; entry = (struct dirent*)((uint8*)entry + length); } if (user_memcpy(userBuffer, buffer, sizeToCopy) != B_OK) return B_BAD_ADDRESS; return count; }
port_id _user_find_port(const char *userName) { char name[B_OS_NAME_LENGTH]; if (userName == NULL) return B_BAD_VALUE; if (!IS_USER_ADDRESS(userName) || user_strlcpy(name, userName, B_OS_NAME_LENGTH) < B_OK) return B_BAD_ADDRESS; return find_port(name); }
status_t _user_get_real_time_clock_is_gmt(bool *_userIsGMT) { if (_userIsGMT == NULL) return B_BAD_VALUE; if (_userIsGMT != NULL && (!IS_USER_ADDRESS(_userIsGMT) || user_memcpy(_userIsGMT, &sIsGMT, sizeof(bool)) != B_OK)) return B_BAD_ADDRESS; return B_OK; }
image_id _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; return register_image(thread_get_current_thread()->team, &info, size); }