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_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; }
int user_port_get_next_port_info(proc_id uproc, uint32 *ucookie, struct port_info *uinfo) { int res; struct port_info info; uint32 cookie; int rc; if (ucookie == NULL) return ERR_INVALID_ARGS; if (uinfo == NULL) return ERR_INVALID_ARGS; if(is_kernel_address(ucookie)) return ERR_VM_BAD_USER_MEMORY; if(is_kernel_address(uinfo)) return ERR_VM_BAD_USER_MEMORY; // copy from userspace rc = user_memcpy(&cookie, ucookie, sizeof(uint32)); if(rc < 0) return rc; res = port_get_next_port_info(uproc, &cookie, &info); // copy to userspace rc = user_memcpy(ucookie, &info, sizeof(uint32)); if(rc < 0) return rc; rc = user_memcpy(uinfo, &info, sizeof(struct port_info)); if(rc < 0) return rc; return res; }
status_t get_route_information(struct net_domain* _domain, void* value, size_t length) { struct net_domain_private* domain = (net_domain_private*)_domain; if (length < sizeof(route_entry)) return B_BAD_VALUE; route_entry entry; if (user_memcpy(&entry, value, sizeof(route_entry)) < B_OK) return B_BAD_ADDRESS; sockaddr_storage destination; status_t status = user_copy_address(entry.destination, &destination); if (status != B_OK) return status; RecursiveLocker locker(domain->lock); net_route_private* route = find_route(domain, (sockaddr*)&destination); if (route == NULL) return B_ENTRY_NOT_FOUND; status = fill_route_entry(&entry, value, length, route); if (status != B_OK) return status; return user_memcpy(value, &entry, sizeof(route_entry)); }
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; }
status_t ice1712_buffer_exchange(ice1712 *card, multi_buffer_info *data) { int cpu_status; multi_buffer_info buffer_info; #ifdef __HAIKU__ if (user_memcpy(&buffer_info, data, sizeof(buffer_info)) < B_OK) return B_BAD_ADDRESS; #else memcpy(&buffer_info, data, sizeof(buffer_info)); #endif buffer_info.flags = B_MULTI_BUFFER_PLAYBACK | B_MULTI_BUFFER_RECORD; if (acquire_sem_etc(card->buffer_ready_sem, 1, B_RELATIVE_TIMEOUT | B_CAN_INTERRUPT, 50000) == B_TIMED_OUT) { TRACE("buffer_exchange timeout\n"); }; cpu_status = lock(); // Playback buffers info buffer_info.played_real_time = card->played_time; buffer_info.played_frames_count = card->frames_count; buffer_info.playback_buffer_cycle = (card->buffer - 1) % SWAPPING_BUFFERS; //Buffer played // Record buffers info buffer_info.recorded_real_time = card->played_time; buffer_info.recorded_frames_count = card->frames_count; buffer_info.record_buffer_cycle = (card->buffer - 1) % SWAPPING_BUFFERS; //Buffer filled unlock(cpu_status); /* if ((card->buffer % 1500) == 0) { uint8 reg8, reg8_dir; reg8 = read_gpio(card); reg8_dir = read_cci_uint8(card, CCI_GPIO_DIRECTION_CONTROL); TRACE("DEBUG === GPIO = %d (dir %d)\n", reg8, reg8_dir); reg8 = spdif_read(card, CS84xx_VERSION_AND_CHIP_ID); TRACE("DEBUG === S/PDif Version : 0x%x\n", reg8); }*/ #ifdef __HAIKU__ if (user_memcpy(data, &buffer_info, sizeof(buffer_info)) < B_OK) return B_BAD_ADDRESS; #else memcpy(data, &buffer_info, sizeof(buffer_info)); #endif 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 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 read_cdda_data(int fd, off_t endFrame, off_t offset, void *data, size_t length, off_t bufferOffset, void *buffer, size_t bufferSize) { if (bufferOffset >= 0 && bufferOffset <= offset + length && bufferOffset + bufferSize > offset) { if (offset >= bufferOffset) { // buffer reaches into the beginning of the request off_t dataOffset = offset - bufferOffset; size_t bytes = min_c(bufferSize - dataOffset, length); if (user_memcpy(data, (uint8 *)buffer + dataOffset, bytes) < B_OK) return B_BAD_ADDRESS; data = (void *)((uint8 *)data + bytes); length -= bytes; offset += bytes; } else if (offset < bufferOffset && offset + length < bufferOffset + bufferSize) { // buffer overlaps at the end of the request off_t dataOffset = bufferOffset - offset; size_t bytes = length - dataOffset; if (user_memcpy((uint8 *)data + dataOffset, buffer, bytes) < B_OK) return B_BAD_ADDRESS; length -= bytes; } // we don't handle the case where we would need to split the request } while (length > 0) { off_t frame = offset / kFrameSize; uint32 count = bufferSize / kFrameSize; if (frame + count > endFrame) count = endFrame - frame; status_t status = read_frames(fd, frame, (uint8 *)buffer, count); if (status < B_OK) return status; off_t dataOffset = offset % kFrameSize; size_t bytes = bufferSize - dataOffset; if (bytes > length) bytes = length; if (user_memcpy(data, (uint8 *)buffer + dataOffset, bytes) < B_OK) return B_BAD_ADDRESS; data = (void *)((uint8 *)data + bytes); length -= bytes; offset += bytes; } 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_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; }
static status_t acpi_battery_control(void* _cookie, uint32 op, void* arg, size_t len) { battery_device_cookie* device = (battery_device_cookie*)_cookie; status_t err; switch (op) { case IDENTIFY_DEVICE: { if (len < sizeof(uint32)) return B_BAD_VALUE; uint32 magicId = kMagicACPIBatteryID; return user_memcpy(arg, &magicId, sizeof(magicId)); } case GET_BATTERY_INFO: { if (len < sizeof(acpi_battery_info)) return B_BAD_VALUE; acpi_battery_info batteryInfo; err = ReadBatteryStatus(device->driver_cookie, &batteryInfo); if (err != B_OK) return err; return user_memcpy(arg, &batteryInfo, sizeof(batteryInfo)); } case GET_EXTENDED_BATTERY_INFO: { if (len < sizeof(acpi_extended_battery_info)) return B_BAD_VALUE; acpi_extended_battery_info extBatteryInfo; err = ReadBatteryInfo(device->driver_cookie, &extBatteryInfo); if (err != B_OK) return err; return user_memcpy(arg, &extBatteryInfo, sizeof(extBatteryInfo)); } case WATCH_BATTERY: sBatteryCondition.Wait(); if (atomic_get(&(device->stop_watching))) { atomic_set(&(device->stop_watching), 0); return B_ERROR; } return B_OK; case STOP_WATCHING_BATTERY: atomic_set(&(device->stop_watching), 1); sBatteryCondition.NotifyAll(); return B_OK; } return B_DEV_INVALID_IOCTL; }
static int vesa_ioctl(dev_cookie cookie, int op, void *buf, size_t len) { int err = 0; if(!vesa.enabled) return ERR_NOT_FOUND; switch(op) { case IOCTL_DEVFS_GET_FRAMEBUFFER_INFO: if(is_kernel_address(buf)) err = ERR_VM_BAD_USER_MEMORY; else err = user_memcpy(buf, &vesa.fb_info, sizeof(vesa.fb_info)); break; case IOCTL_DEVFS_MAP_FRAMEBUFFER: { aspace_id aid = vm_get_current_user_aspace_id(); region_id rid; void *address; if(is_kernel_address(buf)) { err = ERR_VM_BAD_USER_MEMORY; goto out; } // map the framebuffer into the user's address space rid = vm_map_physical_memory(aid, "vesa_fb", &address, REGION_ADDR_ANY_ADDRESS, vesa.phys_memory.size, LOCK_RW, vesa.phys_memory.start); if(rid < 0) { err = rid; goto out; } // copy the new pointer back to the user err = user_memcpy(buf, &address, sizeof(address)); if(err < 0) { vm_delete_region(aid, rid); goto out; } // return the region id as the return code err = rid; break; } default: err = ERR_INVALID_ARGS; } out: return err; }
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_sendmsg(int socket, const 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; // copy the address from userland if (userAddress != NULL && user_memcpy(address, userAddress, message.msg_namelen) != B_OK) { return B_BAD_ADDRESS; } // copy ancillary data from userland MemoryDeleter ancillaryDeleter; void* userAncillary = message.msg_control; if (userAncillary != NULL) { if (!IS_USER_ADDRESS(userAncillary)) return B_BAD_ADDRESS; if (message.msg_controllen < 0 || message.msg_controllen > MAX_ANCILLARY_DATA_LENGTH) { return B_BAD_VALUE; } message.msg_control = malloc(message.msg_controllen); if (message.msg_control == NULL) return B_NO_MEMORY; ancillaryDeleter.SetTo(message.msg_control); if (user_memcpy(message.msg_control, userAncillary, message.msg_controllen) != B_OK) { return B_BAD_ADDRESS; } } // sendmsg() SyscallRestartWrapper<ssize_t> result; return result = common_sendmsg(socket, &message, flags, false); }
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_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; }
static status_t copy_address_to_userland(const void* address, socklen_t addressLength, sockaddr* userAddress, socklen_t userAddressBufferSize, socklen_t* userAddressLength) { // copy address size and address back to userland if (user_memcpy(userAddressLength, &addressLength, sizeof(socklen_t)) != B_OK || (userAddress != NULL && user_memcpy(userAddress, address, min_c(addressLength, userAddressBufferSize)) != B_OK)) { 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); }
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 mem_write(void* cookie, off_t position, const void* buffer, size_t* numBytes) { void *virtualAddress; area_id area; status_t status = B_OK; /* check permissions */ if (getuid() != 0 && geteuid() != 0) { *numBytes = 0; return EPERM; } area = mem_map_target(position, *numBytes, B_WRITE_AREA, &virtualAddress); if (area < 0) { *numBytes = 0; return area; } if (user_memcpy(virtualAddress, buffer, *numBytes) != B_OK) status = B_BAD_ADDRESS; delete_area(area); return status; }
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 device_ioctl(void* cookie, uint32 msg, void* buf, size_t len) { TRACE("device_ioctl\n"); DeviceInfo* dev = (DeviceInfo*)cookie; switch (msg) { case B_GET_ACCELERANT_SIGNATURE: strcpy((char*)buf, "vboxvideo.accelerant"); return B_OK; case VBOXVIDEO_GET_PRIVATE_DATA: return user_memcpy(buf, &dev->sharedArea, sizeof(area_id)); case VBOXVIDEO_GET_DEVICE_NAME: if (user_strlcpy((char*)buf, gDeviceInfo.name, len) < B_OK) return B_BAD_ADDRESS; else return B_OK; case VBOXVIDEO_SET_DISPLAY_MODE: { display_mode* mode = (display_mode*)buf; VBoxVideoSetModeRegisters(mode->timing.h_display, mode->timing.v_display, mode->timing.h_display, get_depth_for_color_space(mode->space), 0, 0, 0); gDeviceInfo.sharedInfo->currentMode = *mode; return B_OK; } default: return B_BAD_VALUE; } }
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; }
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); }
ssize_t user_port_read_etc(port_id uport, int32 *umsg_code, void *umsg_buffer, size_t ubuffer_size, uint32 uflags, bigtime_t utimeout) { ssize_t res; int32 msg_code; int rc; if (umsg_code == NULL) return ERR_INVALID_ARGS; if (umsg_buffer == NULL) return ERR_INVALID_ARGS; if(is_kernel_address(umsg_code)) return ERR_VM_BAD_USER_MEMORY; if(is_kernel_address(umsg_buffer)) return ERR_VM_BAD_USER_MEMORY; res = port_read_etc(uport, &msg_code, umsg_buffer, ubuffer_size, uflags | PORT_FLAG_USE_USER_MEMCPY | SEM_FLAG_INTERRUPTABLE, utimeout); rc = user_memcpy(umsg_code, &msg_code, sizeof(int32)); if(rc < 0) return rc; return res; }
status_t device_ioctl(void *data, uint32 msg, void *buffer, size_t bufferLength) { struct sis_info *info; if (checkDeviceInfo(info = data) != B_OK) return EINVAL; switch (msg) { case ETHER_GETADDR: TRACE(("ioctl: get MAC address\n")); memcpy(buffer, &info->address, 6); return B_OK; case ETHER_INIT: TRACE(("ioctl: init\n")); return B_OK; case ETHER_GETFRAMESIZE: TRACE(("ioctl: get frame size\n")); *(uint32*)buffer = MAX_FRAME_SIZE; return B_OK; case ETHER_SETPROMISC: TRACE(("ioctl: set promisc\n")); sis900_setPromiscuous(info, *(uint32 *)buffer != 0); return B_OK; case ETHER_NONBLOCK: info->blockFlag = *(int32 *)buffer ? B_TIMEOUT : 0; TRACE(("ioctl: non blocking ? %s\n", info->blockFlag ? "yes" : "no")); return B_OK; case ETHER_ADDMULTI: TRACE(("ioctl: add multicast\n")); /* not yet implemented */ break; #ifdef HAIKU_TARGET_PLATFORM_HAIKU case ETHER_GET_LINK_STATE: { ether_link_state_t state; state.media = (info->link ? IFM_ACTIVE : 0) | IFM_ETHER | (info->full_duplex ? IFM_FULL_DUPLEX : IFM_HALF_DUPLEX) | (info->speed == LINK_SPEED_100_MBIT ? IFM_100_TX : IFM_10_T); state.speed = info->speed == LINK_SPEED_100_MBIT ? 100000 : 10000; state.quality = 1000; return user_memcpy(buffer, &state, sizeof(ether_link_state_t)); } #endif default: TRACE(("ioctl: unknown message %lu (length = %ld)\n", msg, bufferLength)); break; } return B_ERROR; }
status_t _user_sigwait(const sigset_t *userSet, int *_userSignal) { if (userSet == NULL || _userSignal == NULL) return B_BAD_VALUE; sigset_t set; if (user_memcpy(&set, userSet, sizeof(sigset_t)) < B_OK) return B_BAD_ADDRESS; int signal; status_t status = sigwait(&set, &signal); if (status < B_OK) return syscall_restart_handle_post(status); return user_memcpy(_userSignal, &signal, sizeof(int)); }
static status_t get_int_option(void* target, size_t length, int value) { if (length != sizeof(int)) return B_BAD_VALUE; return user_memcpy(target, &value, sizeof(int)); }
static status_t device_ioctl(void* dev, uint32 msg, void* buffer, size_t bufferLength) { DeviceInfo& di = *((DeviceInfo*)dev); // TRACE("device_ioctl(); ioctl: %lu, buffer: 0x%08lx, bufLen: %lu\n", msg, // (uint32)buffer, bufferLength); switch (msg) { case B_GET_ACCELERANT_SIGNATURE: strcpy((char*)buffer, ATI_ACCELERANT_NAME); return B_OK; case ATI_DEVICE_NAME: strncpy((char*)buffer, di.name, B_OS_NAME_LENGTH); ((char*)buffer)[B_OS_NAME_LENGTH -1] = '\0'; return B_OK; case ATI_GET_SHARED_DATA: if (bufferLength != sizeof(area_id)) return B_BAD_DATA; *((area_id*)buffer) = di.sharedArea; return B_OK; case ATI_GET_EDID: { if (bufferLength != sizeof(edid1_raw)) return B_BAD_DATA; edid1_raw rawEdid; status_t status = GetEdidFromBIOS(rawEdid); if (status == B_OK) user_memcpy((edid1_raw*)buffer, &rawEdid, sizeof(rawEdid)); return status; } case ATI_SET_VESA_DISPLAY_MODE: if (bufferLength != sizeof(uint16)) return B_BAD_DATA; return SetVesaDisplayMode(*((uint16*)buffer)); case ATI_RUN_INTERRUPTS: if (bufferLength != sizeof(bool)) return B_BAD_DATA; if (*((bool*)buffer)) EnableVBI(); else DisableVBI(); return B_OK; } return B_DEV_INVALID_IOCTL; }