Skip to content

Commit 493f038

Browse files
committed
Implement IPC hooks in OS memory provider
Signed-off-by: Lukasz Dorau <[email protected]>
1 parent 449133c commit 493f038

File tree

4 files changed

+150
-5
lines changed

4 files changed

+150
-5
lines changed

src/provider/provider_os_memory.c

Lines changed: 105 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -669,6 +669,106 @@ static umf_result_t os_allocation_merge(void *provider, void *lowPtr,
669669
return UMF_RESULT_SUCCESS;
670670
}
671671

672+
typedef struct os_ipc_data_t {
673+
int pid;
674+
int fd;
675+
size_t fd_offset;
676+
size_t size;
677+
} os_ipc_data_t;
678+
679+
static umf_result_t os_get_ipc_handle_size(void *provider, size_t *size) {
680+
if (provider == NULL || size == NULL) {
681+
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
682+
}
683+
684+
*size = sizeof(os_ipc_data_t);
685+
return UMF_RESULT_SUCCESS;
686+
}
687+
688+
static umf_result_t os_get_ipc_handle(void *provider, const void *ptr,
689+
size_t size, void *providerIpcData) {
690+
if (provider == NULL || providerIpcData == NULL) {
691+
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
692+
}
693+
694+
os_memory_provider_t *os_provider = (os_memory_provider_t *)provider;
695+
696+
void *value = critnib_get(os_provider->ptr_off, (uintptr_t)ptr);
697+
if (value == NULL) {
698+
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
699+
}
700+
701+
os_ipc_data_t *os_ipc_data = (os_ipc_data_t *)providerIpcData;
702+
os_ipc_data->pid = os_getpid();
703+
os_ipc_data->fd = os_provider->fd;
704+
os_ipc_data->fd_offset = (size_t)value;
705+
os_ipc_data->size = size;
706+
707+
return UMF_RESULT_SUCCESS;
708+
}
709+
710+
static umf_result_t os_put_ipc_handle(void *provider, void *providerIpcData) {
711+
if (provider == NULL || providerIpcData == NULL) {
712+
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
713+
}
714+
715+
os_memory_provider_t *os_provider = (os_memory_provider_t *)provider;
716+
os_ipc_data_t *os_ipc_data = (os_ipc_data_t *)providerIpcData;
717+
718+
if (os_ipc_data->fd != os_provider->fd || os_ipc_data->pid != os_getpid()) {
719+
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
720+
}
721+
722+
return UMF_RESULT_SUCCESS;
723+
}
724+
725+
static umf_result_t os_open_ipc_handle(void *provider, void *providerIpcData,
726+
void **ptr) {
727+
if (provider == NULL || providerIpcData == NULL || ptr == NULL) {
728+
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
729+
}
730+
731+
os_memory_provider_t *os_provider = (os_memory_provider_t *)provider;
732+
os_ipc_data_t *os_ipc_data = (os_ipc_data_t *)providerIpcData;
733+
734+
int fd;
735+
umf_result_t umf_result =
736+
os_duplicate_fd(os_ipc_data->pid, os_ipc_data->fd, &fd);
737+
if (umf_result != UMF_RESULT_SUCCESS) {
738+
LOG_PERR("duplicating file descriptor failed");
739+
return umf_result;
740+
}
741+
742+
*ptr = os_mmap(NULL, os_ipc_data->size, os_provider->protection,
743+
os_provider->flag, fd, os_ipc_data->fd_offset);
744+
if (*ptr == NULL) {
745+
os_store_last_native_error(UMF_OS_RESULT_ERROR_ALLOC_FAILED, errno);
746+
LOG_PERR("memory mapping failed");
747+
return UMF_RESULT_ERROR_MEMORY_PROVIDER_SPECIFIC;
748+
}
749+
750+
return UMF_RESULT_SUCCESS;
751+
}
752+
753+
static umf_result_t os_close_ipc_handle(void *provider, void *ptr,
754+
size_t size) {
755+
if (provider == NULL || ptr == NULL) {
756+
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
757+
}
758+
759+
errno = 0;
760+
int ret = os_munmap(ptr, size);
761+
// ignore error when size == 0
762+
if (ret && (size > 0)) {
763+
os_store_last_native_error(UMF_OS_RESULT_ERROR_FREE_FAILED, errno);
764+
LOG_PERR("memory unmapping failed");
765+
766+
return UMF_RESULT_ERROR_MEMORY_PROVIDER_SPECIFIC;
767+
}
768+
769+
return UMF_RESULT_SUCCESS;
770+
}
771+
672772
static umf_memory_provider_ops_t UMF_OS_MEMORY_PROVIDER_OPS = {
673773
.version = UMF_VERSION_CURRENT,
674774
.initialize = os_initialize,
@@ -683,11 +783,11 @@ static umf_memory_provider_ops_t UMF_OS_MEMORY_PROVIDER_OPS = {
683783
.ext.purge_force = os_purge_force,
684784
.ext.allocation_merge = os_allocation_merge,
685785
.ext.allocation_split = os_allocation_split,
686-
.ipc.get_ipc_handle_size = NULL,
687-
.ipc.get_ipc_handle = NULL,
688-
.ipc.put_ipc_handle = NULL,
689-
.ipc.open_ipc_handle = NULL,
690-
.ipc.close_ipc_handle = NULL};
786+
.ipc.get_ipc_handle_size = os_get_ipc_handle_size,
787+
.ipc.get_ipc_handle = os_get_ipc_handle,
788+
.ipc.put_ipc_handle = os_put_ipc_handle,
789+
.ipc.open_ipc_handle = os_open_ipc_handle,
790+
.ipc.close_ipc_handle = os_close_ipc_handle};
691791

692792
umf_memory_provider_ops_t *umfOsMemoryProviderOps(void) {
693793
return &UMF_OS_MEMORY_PROVIDER_OPS;

src/provider/provider_os_memory_internal.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ size_t os_get_page_size(void);
4545

4646
void os_strerror(int errnum, char *buf, size_t buflen);
4747

48+
int os_getpid(void);
49+
50+
umf_result_t os_duplicate_fd(int pid, int fd_in, int *fd_out);
51+
4852
#ifdef __cplusplus
4953
}
5054
#endif

src/provider/provider_os_memory_linux.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,3 +150,35 @@ int os_purge(void *addr, size_t length, int advice) {
150150
void os_strerror(int errnum, char *buf, size_t buflen) {
151151
strerror_r(errnum, buf, buflen);
152152
}
153+
154+
int os_getpid(void) { return getpid(); }
155+
156+
umf_result_t os_duplicate_fd(int pid, int fd_in, int *fd_out) {
157+
errno = 0;
158+
// SYS_pidfd_open is supported since Linux 5.3
159+
// SYS_pidfd_getfd is supported since Linux 5.6
160+
#if defined(__NR_pidfd_open) && defined(__NR_pidfd_getfd)
161+
int pid_fd = syscall(SYS_pidfd_open, pid, 0);
162+
if (pid_fd == -1) {
163+
LOG_PDEBUG("SYS_pidfd_open");
164+
return UMF_RESULT_ERROR_UNKNOWN;
165+
}
166+
167+
int fd_dup = syscall(SYS_pidfd_getfd, pid_fd, fd_in, 0);
168+
close(pid_fd);
169+
if (fd_dup == -1) {
170+
LOG_PDEBUG("SYS_pidfd_getfd");
171+
return UMF_RESULT_ERROR_UNKNOWN;
172+
}
173+
174+
*fd_out = fd_dup;
175+
176+
return UMF_RESULT_SUCCESS;
177+
#else
178+
(void)pid; // unused
179+
(void)fd_in; // unused
180+
(void)fd_out; // unused
181+
return UMF_RESULT_ERROR_NOT_SUPPORTED; // unsupported
182+
// TODO: find another way
183+
#endif /* defined(__NR_pidfd_open) && defined(__NR_pidfd_getfd) */
184+
}

src/provider/provider_os_memory_windows.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,3 +112,12 @@ size_t os_get_page_size(void) {
112112
void os_strerror(int errnum, char *buf, size_t buflen) {
113113
strerror_s(buf, buflen, errnum);
114114
}
115+
116+
int os_getpid(void) { return GetCurrentProcessId(); }
117+
118+
umf_result_t os_duplicate_fd(int pid, int fd_in, int *fd_out) {
119+
(void)pid; // unused
120+
(void)fd_in; // unused
121+
(void)fd_out; // unused
122+
return UMF_RESULT_ERROR_NOT_SUPPORTED; // unsupported
123+
}

0 commit comments

Comments
 (0)