Fernando J. Pereda’s blag

May 25, 2010

iostreams are VERY thread-unsafe on Mac OS X

Filed under: blag — Tags: , , , — Fernando J. Pereda @ 8:19 am

This was both surprising and disgusting. Our in-house data acquisition software needs to convert lots of floats to ascii so that they can ve viewed in real time. This is very easy to do with a stringify-like function like the one found in paludis/paludis/util/stringify.hh.

stringify looks trivial, there’s no shared state nor there is any static data, so I thought that I could call stringify from several threads at the same time. I don’t think there’s any guarantee about thread safety of ostringstream’s operator<< but it looked like a safe assumption. Well, incorrect.

operator<< calls vsnprintf, which should be thread-safe by itself. However, OSX's vsnprintf ultimately calls localeconv_l, which is not thread-safe. And, you end up with something like this:

#0 0x96f734a9 in malloc_error_break ()
#1 0x96f6e497 in szone_error ()
#2 0x96e98503 in szone_free ()
#3 0x96e9836d in free ()
#4 0x96e97f24 in localeconv_l ()
#5 0x96e93335 in __vfprintf ()
#6 0x96ecb9b5 in vsnprintf ()
#7 0x0144615e in std::__convert_from_v ()
#8 0x01437d2a in std::num_put<char, std::ostreambuf_iterator<char, std::char_traits > >::_M_insert_float ()
#9 0x0143803d in std::num_put<char, std::ostreambuf_iterator<char, std::char_traits > >::do_put ()
#10 0x0144ab6a in std::ostream::_M_insert ()
#11 0x0000fb25 in std::basic_ostringstream<char, std::char_traits, std::allocator >::str () at sstream:217
...

Which means there’s no way of converting stuff to human readable in a thread-safe manner. I’m not sure whether I’m missing something or not… but this looks very fishy. I ended up adding a stupid big mutex around my stringify calls, but that looks more like a workaround that a final solution to the problem. Plus, this doesn’t protect ANY other uses of iostream’s operator<< such as loggers.

Ok… looks like that wasn’t a very accurate diagnostic. This is going to be more annoying than I thought.

— ferdy

April 27, 2009

Small C trivia

Filed under: blag — Tags: , , , — Fernando J. Pereda @ 8:50 am

This is somehow surprising the first time you see it and it is interesting to remind it to people from time to time. The question is easy, does this program always return 0? That is, are those summations the same?

If there’s a case when it doesn’t, provide a sample input and explain why it happens.

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
	float f[argc - 1];
	for (int i = 1; i < argc; i++)
		f[i - 1] = atof(argv[i]);
	float r1 = 0;
	for (int i = 0; i < argc - 1; i++)
		r1 += f[i];
	float r2 = 0;
	for (int i = argc - 2; i >= 0; i--)
		r2 += f[i];
	return r1 != r2;
}

As usual, I’ll post the solution in a couple of days or when someone gets it right (which is always the case :))

— fpereda

Update: correct typo spotted by Snaury.

September 8, 2008

GMandel meets Julia sets

Filed under: blag — Tags: , , , — Fernando J. Pereda @ 3:08 am

I was bored and decided to hack support for viewing Julia sets into GMandel. The code could be nicer, but that will come tomorrow. I should really stop slacking and make a proper hierarchy of widgets (GFractMandel and GFractJulia should inherit a common GFractWidget) to make the code more manageable but this will do for now.

These are some examples of Julia sets generated with GMandel:

I strongly recommend The Computational Beauty of Nature to those interested or curious about this kind of stuff. It is a nice book that can even be read without too much mathematical or computer science background. One of the nice things about fractals and chaos is that you can see most the stuff yourself through pretty pictures.

— ferdy

August 24, 2008

Security Trivia IV

Filed under: blag — Tags: , — Fernando J. Pereda @ 2:02 pm

This one is easy and sweet. Your goal is to make this program crash and explain why that happened, good luck:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
	if (argc != 4) {
		fprintf(stderr, "DIAF\n");
		return EXIT_FAILURE;
	}

	char c[3];
	unsigned i;
	for (i = 0; i < sizeof(c); i++)
		c[i] = atoi(argv[i + 1]);

	if (c[0] + c[1] + c[2] == 0) {
		fprintf(stderr, "No no\n");
		return EXIT_FAILURE;
	}

	c[1] += c[0] + c[2];
	printf("%d\n", c[0]/c[1]);

	return EXIT_SUCCESS;
}

Before spoling your own fun looking at the comments, try to do it yourself. Really, it is easy, and will make you understand C better.

— ferdy

June 1, 2008

Security trivia III

Filed under: blag — Tags: , — Fernando J. Pereda @ 6:03 pm

People seem to like this kind of stuff, so here it goes. Take a look at this code:

#define MAX(a, b) ((a) > (b) ? (a) : (b))

struct st *dst, *src;
int size /* = some number of bytes you can control so that size >= 0 */;

/* Some code that sets up src and dst to valid buffers.
 * Everything but the last structure of src fits into dst. */

memcpy(dst, src, MAX(0, size - sizeof(struct st)));

Again:

  • What’s wrong with this code?
  • What environment do you need to exploit it?
  • Given such an environment, how can you exploit it?
  • How would you fix the code?

Remember, someone might have solved it in the comments. That could spoil the fun. You have been warned.

— ferdy

May 26, 2008

Security trivia II

Filed under: blag — Tags: , — Fernando J. Pereda @ 6:25 pm

Suppose you have the following code:

char *start, *end, *ref;
/* Some code that process user input so that start and end
 * point to valid memory addresses and start + k < end.
 * Where k is some constant you can't control.
 * ref is made to point to some program-defined chunk,
 * but you can't control this one.
 */
int n = end - start;
if (memcmp(ref, start, n) != 0) {
    printf("Checksum mismatch. Access denied.\n");
    exit(EXIT_FAILURE);
}
printf("Checksum matches. Access granted.\n");

This one is probably easier than the first one, but anyway:

  • What’s wrong with this code?
  • What environment do you need to exploit it?
  • Given such an environment, how can you exploit it?
  • How would you fix the code?

If you’ve seen me ranting about this in #exherbo-dev, you are not allowed to answer :)

— ferdy

May 23, 2008

Security trivia

Filed under: blag — Tags: , — Fernando J. Pereda @ 2:37 pm

Apparently, this kind of issues are difficult to understand. Sometimes, you can pretend they don’t exist, but you want to get rid of them. Security is often about small mistakes here and there that lead to big holes when used together.

So:

  • What’s wrong with this code?
  • What environment do you need to exploit it?
  • Given such an environment, how can you exploit it?
  • How would you fix the code?
[...]
if(-l $statefile) {
        die("$statefile is a symbolic link, refusing to touch it.");
}                               
open (OUT, ">$statefile") or exit 4;
print OUT "$pos:$delivered\n";
[...]

A couple of days ago, I reported a similar issue (which I suspect it can be exploitable) and couldn’t get upstream to fix it (I can’t be bothered with a patch because I don’t use the software anyway). I’m not sure why they didn’t fix it, probably they don’t care about security, or they don’t understand the issue at hand.

I’ll post the answer in a couple of days or whenever someone gets it right.

— ferdy

May 22, 2008

Reading

Filed under: blag — Tags: , , — Fernando J. Pereda @ 1:29 am

Recently Read

  • Linux System Programming, Robert Love. This book disappointed me. I expected much deeper stuff and not only a mere listing of syscalls and some hints here and there.
  • Beyond Fear, Bruce Schneier. I liked it very much, really enlightening.

Currently Reading

Recommendation: Secure Coding in C and C++, Robert C. Seacord. Even if it is difficult to read at first, it is really enjoyable and interesting.

— ferdy

May 20, 2008

Gmandel, Gtk+ and Threads

Filed under: blag — Tags: , , , — Fernando J. Pereda @ 1:18 am

For gmandel (see Chaotic Stuff for more info) I had to add a little GtkProgressBar so that users have a rough estimate of the time it’ll take rendering the fractal.

I wanted to have a clean and easy to study code, so, to avoid threads (that are usually difficult to study for newcomers) I used the following hack to update the progress bar:

static inline void flush_events(void)
{
    while (gtk_events_pending())
        gtk_main_iteration();
}

And, with some code to save expose events and relaunch them once the image had been rendered, it worked fine. However, that’s a hack, and the real solution is to fire a new thread to do the rendering work and update the widget when it’s finished. Naïve I was.

Gtk+’s documentation states it very clearly: Make sure you protect all calls to Gtk with a gdk_threads_enter(), gdk_threads_leave() pair. With that, you can call Gtk functions from any thread you want and forget about implementing IPC mechanisms to make all the calls from one thread. One of the problems is that the default implementation of the Gdk lock is a non-reentrant mutex, which means you lock it while already holding it (otherwise, you deadlock).

It should be noted that gtk_main() should also be enclosed in an enter-leave which means that functions called by it, can’t try to lock Gdk’s mutex or they’ll deadlock. This is a problem if you are trying to share functions between event handlers and threads. The trick here is to replace that mutex with a couple of functions that lock a reentrant mutex using gtk_threads_set_lock_functions().

What isn’t clear is that gtk_events_pending() will try to acquire Gdk’s lock. For some reason, I forgot to remove the hack that events_flush() was, and had wasted lots of time trying to fix a small, difficult to reproduce, race condition because I was calling gtk_events_pending() while holding the Gdk lock.

So, really, working with threaded applications in Gtk+ is really easy. It is just a matter of protecting calls to Gtk with a critical section. I’m not sure why the documentation isn’t more clear, and the fact that some of the old information floating in the web still advises to only call Gtk from one thread doesn’t really help. Had I started with a threaded version instead of using events_flush() thing would’ve been far easier :)

Bottom line: If something is difficult, working it around won’t make it easier, quite the contrary.

— ferdy

May 18, 2008

Chaotic stuff

Filed under: blag — Tags: , , — Fernando J. Pereda @ 11:25 pm

I’ve been working on a couple of utilities to toy around with L-Systems and the Mandelbrot Set.

lsys is a simple utility that would take an axiom, generation rules and a depth. After some crunching (depends on the complexity of the fractal), it will show a window with the fractal. It has some examples bundled with it for further toying. The idea behind gmandel is a nice Mandelbrot Set explorator, reality is a bit far from that though :) . However, it offers something I haven’t seen in most fractal applications, Mandelbrot Orbits. Those are really nice to see to understand the set a bit more. It has facilities to load and save states and lets you save the image you are seeing (yay for fractal wallpapers).

Gmandel

It also has some dull color themes. All the code is really implementing a widget that draws the fractal, the idea is to inherit that widget to display Julia Sets too. But since I’m only spending a couple of hours every two months on this, it might take a while :)

I haven’t bothered with ebuilds for this yet, though the code is publicly available at: git://git.ferdyx.org/lsys.git and git://git.ferdyx.org/gmandel.git. The former needs copme (an option parsing library that doesn’t suck), which can be found at git://git.ferdyx.org/copme.git and for which there’s an ebuild at git://git.ferdyx.org/ferdy-overlay.git.

— ferdy

Blog at WordPress.com.