Is OS X's SecRandomCopyBytes fork safe? - ios

Many userspace CSPRNG's have an issue where after fork(2), it's possible for the two different processes to return the same stream of random bytes.
From looking at dtruss, it's clear that SecRandomCopyBytes is, at a minimum, seeding from /dev/random, but is it doing so in a way that's safe for use after fork()?
With the following source code:
#include <Security/Security.h>
int main() {
uint8_t data[8];
SecRandomCopyBytes(kSecRandomDefault, 8, data);
SecRandomCopyBytes(kSecRandomDefault, 8, data);
printf("%llu\n", *(uint64_t *)data);
}
I get the following from dtruss (with irrelevant stuff removed):
open("/dev/random\0", 0x0, 0x7FFF900D76F5) = 3 0
read(0x3, "\b\2029a6\020+\254\356\256\017\3171\222\376T\300\212\017\213\002\034w\3608\203-\214\373\244\177K\177Y\371\033\243Y\020\030*M\3264\265\027\216r\220\002\361\006\262\326\234\336\357F\035\036o\306\216\227\0", 0x40) = 64 0
read(0x3, "\223??3\263\324\3604\314:+\362c\311\274\326\a_Ga\331\261\022\023\265C\na\211]\356)\0", 0x20) = 32 0

The implementation is actually CCRandomCopyBytes():
http://www.opensource.apple.com/source/Security/Security-55471/libsecurity_keychain/lib/SecRandom.c
int SecRandomCopyBytes(SecRandomRef rnd, size_t count, uint8_t *bytes) {
if (rnd != kSecRandomDefault)
return errSecParam;
return CCRandomCopyBytes(kCCRandomDefault, bytes, count);
}
So the actual code is here:
http://www.opensource.apple.com/source/CommonCrypto/CommonCrypto-60049/lib/CommonRandom.c
The comments in the include for CCRandomCopyBytes state that it is fork() safe:
It is inconvenient to call system random number generators
directly. In the simple case of calling /dev/random, the caller
has to open the device and close it in addition to managing it
while it's open. This module has as its immediate raison d'être
the inconvenience of doing this. It manages a file descriptor to
/dev/random including the exception processing of what happens
in a fork() and exec(). Call CCRandomCopyBytes() and all the
fiddly bits are managed for you. Just get on with whatever you
were really trying to do.
[...]
In my own quick test, the child gets killed when it invokes SecRandomCopyBytes()

Related

vkGetMemoryFdKHR is return the same fd?

In WIN32:
I'm sure that if the handle is the same, the memory may not be the same, and the same handle will be returned no matter how many times getMemoryWin32HandleKHR is executed.
This is consistent with vulkan's official explanation: Vulkan shares memory.
It doesn't seem to work properly in Linux.
In my program,
getMemoryWin32HandleKHR works normally and can return a different handle for each different memory.
The same memory returns the same handle.
But in getMemoryFdKHR, different memories return the same fd.
Or the same memory executes getMemoryFdKHR twice, it can return two different handles.
This causes me to fail the device memory allocation during subsequent imports.
I don't understand why this is?
Thanks!
#ifdef WIN32
texGl.handle = device.getMemoryWin32HandleKHR({ info.memory, vk::ExternalMemoryHandleTypeFlagBits::eOpaqueWin32 });
#else
VkDeviceMemory memory=VkDeviceMemory(info.memory);
int file_descriptor=-1;
VkMemoryGetFdInfoKHR get_fd_info{
VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR, nullptr, memory,
VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT
};
VkResult result= vkGetMemoryFdKHR(device,&get_fd_info,&file_descriptor);
assert(result==VK_SUCCESS);
texGl.handle=file_descriptor;
// texGl.handle = device.getMemoryFdKHR({ info.memory, vk::ExternalMemoryHandleTypeFlagBits::eOpaqueFd });
Win32 is nomal.
Linux is bad.
It will return VK_ERROR_OUT_OF_DEVICE_MEMORY.
#ifdef _WIN32
VkImportMemoryWin32HandleInfoKHR import_allocate_info{
VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR, nullptr,
VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT, sharedHandle, nullptr };
#elif __linux__
VkImportMemoryFdInfoKHR import_allocate_info{
VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR, nullptr,
VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT,
sharedHandle};
#endif
VkMemoryAllocateInfo allocate_info{
VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // sType
&import_allocate_info, // pNext
aligned_data_size_, // allocationSize
memory_index };
VkDeviceMemory device_memory=VK_NULL_HANDLE;
VkResult result = vkAllocateMemory(m_device, &allocate_info, nullptr, &device_memory);
NVVK_CHECK(result);
I think it has something to do with fd.
In my some test: if I try to get fd twice. use the next fd that vkAllocateMemory is work current......but I think is error .
The fd obtained in this way is different from the previous one.
Because each acquisition will be a different fd.
This makes it impossible for me to distinguish, and the following fd does vkAllocateMemory.
Still get an error.
So this test cannot be used.
I still think it should have the same process as win32. When the fd is obtained for the first time, vkAllocateMemory can be performed correctly.
thanks very much!
The Vulkan specifications for the Win32 handle and POSIX file descriptor interfaces explicitly state different things about their importing behavior.
For HANDLEs:
Importing memory object payloads from Windows handles does not transfer ownership of the handle to the Vulkan implementation. For handle types defined as NT handles, the application must release handle ownership using the CloseHandle system call when the handle is no longer needed.
For FDs:
Importing memory from a file descriptor transfers ownership of the file descriptor from the application to the Vulkan implementation. The application must not perform any operations on the file descriptor after a successful import.
So HANDLE importation leaves the HANLDE in a valid state, still referencing the memory object. File descriptor importation claims ownership of the FD, leaving it in a place where you cannot use it.
What this means is that the FD may have been released by the internal implementation. If that is the case, later calls to create a new FD may use the same FD index as a previous call.
The safest way to use both of these APIs is to have the Win32 version emulate the functionality of the FD version. Don't try to do any kinds of comparisons of handles. If you need some kind of comparison logic, then you'll have to implement it yourself. When you import a HANDLE, close it immediately afterwards.

Pthreads create argument passing

I am trying to pass 2 arguments using a struct in the pthread_create method. One argument is for the total amount of threads active and the other one is for the id of the thread, which is the number it receives from theloop (i). The problem i have right now is that the argument_struct.id value has the same value when i use the run the for loop.
struct argument_struct {
int total_threads;
int id;
} argument_struct;
void * body(void *args)
{
struct argument_struct *arguments = args;
printf("Hello World! %i, %i \n", argument_struct.total_threads, argument_struct.id);
return NULL;
}
int main()
{
const num_threads = 20;
pthread_t thread[num_threads];
pthread_attr_t attr;
int i;
/* Initiate the thread attributes */
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
argument_struct.total_threads = num_threads;
for (i=0; i<num_threads; i++)
{
argument_struct.id = i;
pthread_create(&thread[i], &attr, &body, (void *)&argument_struct);
}
output
Hello world! 20, 19
Hello world! 20, 19
Hello world! 20, 19
etc
You have a race condition - by the time a thread gets to look at the structure it has been passed, the main thread has already reused that structure to pass to the next created thread.
There are several ways you could solve this:
1) have an array of struct argument_struct items (the array at least large enough for the number of threads), and use a separate element to pass to each newly created thread
2) store the total_threads value in a global that the threads can read. There's no data race here, since the value isn't updated after it is initialized and the threads will only read it. On the other hand you have a shared global which isn't a great idea to use as an interface, but might be OK for small programs. To avoid the problem with sharing the id element, just pass it directly by casting it to a (void*).
3) dynamically allocate a new struct argument_struct to pass to each thread. The thread will become the owner of the struct and will be responsible for freeing it. This is probably the best solution generally (ie., the technique will work well even if you start passing in a large number or complex set of arguments).
4) Use something like a semaphore or condition variable to let the thread signal when it has finished using the passed in structure. The main thread should wait on that synchronization object before reusing the structure to create the next thread. This might be overkill for your simple example, but again it'll work in situations of greater complexity (though I still think that passing in a dynamically allocated structure is simpler).
You are passing each thread the same argument, which is why they all see the same value.

Queues in FreeRTOS

I'm using Freescale FRDM-KL25Z board with Codewarrior 10.6 software. My goal is to make small program in FreeRTOS, which reads voltage from thermistor by analog/digital converter (0-3,3v) and depends on this voltage I'd like turn on/off led diodes. It worked for me till the moment, when I added second task and queues. I'm thinking that problem might be in stack size, but I have no idea how to configure it.
Code is below:
xQueueHandle queue_led;
void TaskLed (void *p)
{
uint16_t temp_val;
xQueueReceive(queue_led, &temp_val, 1);
if (temp_val<60000)
{
LED_1_Neg();
}
}
void TaskTemp (void *p)
{
uint16_t temp_val;
(void)AD1_Measure(TRUE);
(void)AD1_GetValue16(&temp_val);
xQueueSendToBack(queue_led, &temp_val, 1000);
FRTOS1_vTaskDelay(1000);
}
Code in main():
xTaskCreate(TaskLed, (signed char *)"tl", 200, NULL, 1, NULL);
xTaskCreate(TaskTemp, (signed char *)"tt", 200, NULL, 1, NULL);
vTaskStartScheduler();
return(0);
A task is normally a continuous thread of execution - that is - it is implemented as an infinite loop that runs forever. It is very rare for a task to exit its loop - and in FreeRTOS you cannot run off the bottom of a function that implements a task without deleting the task (in more recent versions of FreeRTOS you will trigger an assert if you try). Therefore the functions that implement your tasks are not valid.
FreeRTOS has excellent documentation (and an excellent support forum, for that matter, which would be a more appropriate place to post this question). You can see how a task should be written here: http://www.freertos.org/implementing-a-FreeRTOS-task.html
In the code you post I can't see that you are creating the queue that you are trying to use. That is also documented on the FreeRTOS.org website, and the download has hundreds of examples of how to do it.
If it were a stack issue then Google would show you to go here:
http://www.freertos.org/Stacks-and-stack-overflow-checking.html
You should create the queue and then check that the returned value is not zero (the queue is successfully created)

is there a substitute malloc and free library on solaris?

I am trying to find memory leaks in a very complicated legacy system that is written in C++/C on the Solaris operating system. the idea is to log every malloc and free and then postproccess the log.
i was able to write a stub malloc and free function that gets called correctly. the problem is that they dont do anyhing other than log. As a result the sytem crashes
My question is: is they a substitute malloc library that works on solaris that is can call from my stub malloc& free functions?
Why don't you just do an LD_PRELOAD of libumem and use UMEM_DEBUG? The manpage for umem_debug should give you more information.
Ideally, You should some memory profiling tool but in the absence of the same you can try to implement your own leak detector as you plan to.
You can just call malloc and free library versions through your wrapper.
Here is a scheme that you may try to implement:
Your wrapper function should implement a functionality wherein your wrapper for malloc stores the line number, file name, size requested & address being returned by malloc in a linked list.
How to get filename and line number?
Hint: Use __FILE__, __LINE__
The free wrapper should check the address being sent for freeing against the list and remove the entry from the linked list.
At the end of the program you should print contents of this linked list which gives you leaking memory size, file name and line number from where the buffer was allocated.
Update:
How do you map program malloc calls to own wrapper calls without infinite recurssion?
Through clever Use of Macros!
#define malloc(X) my_malloc( X, __FILE__, __LINE__, __FUNCTION__)
void* my_malloc(size_t size, const char *file, int line, const char *func)
{
void *p = malloc(size);
printf ("Allocated = %s, %i, %s, %p[%li]\n", file, line, func, p, size);
/*Link List functionality goes in here*/
return p;
}
In addition to libumem, I would recommend using Solaris Studio dbx which includes with RTC, a memory leak detector.

Odd behavior when creating and cancelling a thread in close succession

I'm using g++ version 4.4.3 (Ubuntu 4.4.3-4ubuntu5) and libpthread v. 2-11-1. The following code simply creates a thread running Foo(), and immediately cancels it:
void* Foo(void*){
printf("Foo\n");
/* wait 1 second, e.g. using nanosleep() */
return NULL;
}
int main(){
pthread_t thread;
int res_create, res_cancel;
printf("creating thread\n);
res_create = pthread_create(&thread, NULL, &Foo, NULL);
res_cancel = pthread_cancel(thread);
printf("cancelled thread\n);
printf("create: %d, cancel: %d\n", res_create, res_cancel);
return 0;
}
The output I get is:
creating thread
Foo
Foo
cancelled thread
create: 0, cancel: 0
Why the second Foo output? Am I abusing the pthread API by calling pthread_cancel right after pthread_create? If so, how can I know when it's safe to touch the thread? If I so much as stick a printf() between the two, I don't have this problem.
I cannot reproduce this on a slightly newer Ubuntu. Sometimes I get one Foo and sometimes none. I had to fix a few things to get your code to compile (missing headers, missing call to some sleep function implied by a comment and string literals not closed), which indicate you did not paste the actual code which reproduced the problem.
If the problem is indeed real, it might indicate some thread cancellation problem in glibc's IO library. It looks a lot like two threads doing a flush(stdout) on the same buffer contents. Now that should never happen normally because the IO library is thread safe. But what if there is some cancellation scenario like: the thread has the mutex on stdout, and has just done a flush, but has not updated the buffer yet to clear the output. Then it is canceled before it can do that, and the main thread flushes the same data again.

Resources