guest - flak

experiments with prepledge

MP3 is officially dead, so I figure I should listen to my collection one last time before it vanishes entirely. The provenance of some of these files is a little suspect however, and since I know one shouldn’t open files from strangers, I’d like to take some precautions against malicious malarkey. This would be a good use for pledge, perhaps, if we can get it working.

At the same time, an occasional feature request for pledge is the ability to specify restrictions before running a program. Given some untrusted program, wrap its execution in a pledge like environment. There are other system call sandbox mechanisms that can do this (systrace was one), but pledge is quite deliberately designed not to support this. But maybe we can bend it to our will.

Continue reading experiments with prepledge...

Posted 2017-05-20 16:28:36 by tedu Updated: 2017-05-20 16:28:36
Tagged: c openbsd programming

time scrolling

The hovertext for Friday’s xkcd Borrow Your Laptop asks for scrolling mapped to undo and redo. How hard can it be? There’s more than one way to do this, but the other ways are boring. What if we’re using a program that doesn’t allow rebinding keys or buttons?

First we need to grab the scroll events. To avoid too much mischief, we’ll only bind to scroll events with the control key down. XGrabButton sure does take a lot of arguments, but only the first few are interesting.

Continue reading time scrolling...

Posted 2017-03-05 07:51:26 by tedu Updated: 2017-03-05 07:51:26
Tagged: c programming x11

to errno or to error

Unlike other languages which have one preferred means of signalling an error, C is a multi error paradigm language. Error handling styles in C can be organized into one of several distinct styles, such as popular or correct. Some examples of each.

in band sentinel

One very popular option is the classic unix style. -1 is returned to indicate an error.

Continue reading to errno or to error...

Posted 2017-01-24 20:52:42 by tedu Updated: 2017-01-24 20:52:42
Tagged: c programming

exfiltration via receive timing

Another similar way to create a backchannel but without transmitting anything is to introduce delays in the receiver and measure throughput as observed by the sender. All we need is a protocol with transmission control. Hmmm.

Actually, it’s easier (and more reliable) to code this up using a plain pipe, but the same principle applies to networked transmissions.

First the reader code. We’ll assume an input string of decimal digits, 1-9.

Continue reading exfiltration via receive timing...

Posted 2016-12-22 15:20:19 by tedu Updated: 2016-12-22 15:20:39
Tagged: c network programming security

exfiltration via request timing

There are any number of ways to exfiltrate data via covert channels. For example, a popular technique is to make DNS lookups for a series of hostnames like “attack.example.com”, “atdawn.example.com”, etc. which will be passed through most firewalls. For a long time DNS requests weren’t monitored, but savvy network operators have grown wise. So if we wanted to beam some data off a device surreptitiously, what else can we do?

There are some even lower level techniques, like varying IP packet size or options, but this too may trigger alarms. Instead, let’s move up the stack and try to make our tunnel look as normal as possible. Consider the scenario where we’re Apple or Google and we want to extract Signal private keys off a device. It’s a small amount of data, and we already have an established channel: update checks. The trick is to piggyback our channel onto update requests. (This is not an entirely original idea, I just wanted to explore it.)

Continue reading exfiltration via request timing...

Posted 2016-12-19 17:30:45 by tedu Updated: 2016-12-19 17:30:45
Tagged: c network programming security

process listing consistency

POSIX specifies that there is a ps utility to list processes, although it doesn’t describe how the command is implemented. In fact, it’s not possible to implement ps using only POSIX interfaces. However it’s implemented, it’s unlikely to use double buffering, which means on a sufficiently busy system, the results may be inconsistent. If lots of processes are being created and exited while ps runs, some of the output may be “before” and some “after”. Much like a game without vsync.

In order to test for inconsistency, we need to create lots of processes, but in a predictable way. Then we run ps over and over, looking for discrepancies. Enter the chicken and the egg.

Continue reading process listing consistency...

Posted 2016-10-06 12:26:37 by tedu Updated: 2016-10-06 12:26:37
Tagged: c openbsd programming

backlight battery indicator

The last few models of Thinkpads are sadly devoid of indicators. How do you tell if caps lock is on? Type something and see if it matches expectations. If it happens to be the lock screen, loltastic. More importantly, how do you know if AC power has accidentally been disconnected and the battery is running low? The red dot on the opposite side of the lid isn’t much use.

It’s possible to use some sort of desktop environment status bar, but I prefer a low thrills environment. I don’t need a big honking battery icon distracting me. Accordingly, I have only a small (text) battery display in the corner. It’s there when I need it, but unobtrusive. The only problem is if I think I’m plugged into the wall, but I’m not, I won’t be checking battery and may not notice even as the situation grows dire.

Continue reading backlight battery indicator...

Posted 2016-08-28 02:43:19 by tedu Updated: 2016-09-09 21:02:52
Tagged: c computers openbsd programming

connect doesn’t restart

There was an interesting bug where pkg_add failed when resizing the terminal. The bug was actually in ftp, specifically the way it calls connect. When the terminal is resized, SIGWINCH is sent, which interrupts the connect system call. Sometimes syscalls restart, but connect is not among those that do. This may be a little surprising, because the previous bug involved the server side counterpart to connect, accept. On the server, accept restarts, but on the client, connect does not.

Behind the scenes, what’s happening? As the man page says, connect “initiates a connection on a socket”. It doesn’t say much about finishing the connection, though, which may be a bit surprising. Depending on whether the socket is blocking or nonblocking, there are two ways that may happen. This all assumes TCP, which involves some interplay of SYNs and ACKs that does not take place instantaneously. (Which explains why accept behaves differently. It is never in a half connected state.)

Continue reading connect doesn’t restart...

Posted 2016-08-15 21:00:54 by tedu Updated: 2016-08-15 21:00:54
Tagged: c openbsd programming

it’s hard work printing nothing

It all starts with a bug report to LibreSSL that the openssl tool crashes when it tries to print NULL. This bug doesn’t manifest on OpenBSD because libc will convert NULL strings to ”(null)” when printing. However, this behavior is not required, and as observed, it’s not universal. When snprintf silently accepts NULL, that simply leads to propagating the error.

There’s an argument to be made that silly error messages are better than crashing browsers, but stacking layers of sand seems like a poor means of building robust software in the long term.

As soon as development for the next release of OpenBSD restarted, some developers began testing a patch that would remove this crutch from printf.

Continue reading it’s hard work printing nothing...

Posted 2016-08-08 17:00:03 by tedu Updated: 2016-10-10 19:46:11
Tagged: c openbsd programming

one reason to hate openbsd

The gcc-local man page, which documents local changes to the compiler has this to say.

The -O2 option does not include -fstrict-aliasing, as this option causes issues on some legacy code. -fstrict-aliasing is very unsafe with code that plays tricks with casts, bypassing the already weak type system of C.

What does this mean and why should you care? The first part is easy to answer. Long ago, in the dark ages when legacy code was written, people used to write functions like this:

float superbad(float f) { int *x = (int *)&f; *x = 0x5f3759df - ( *x >> 1 ); return f; }

The C standard clearly says that objects are not to be accessed through incompatible pointers, but people did it anyway. Fucking idiots.

As for why one should care about the default setting of the compiler, the best answer I can give is that if you’re in a position to care, you probably know more than enough to form your own opinion and don’t need me to explain it to you. Otherwise, nobody cares except to the extent it confirms one’s own biases.

The strict aliasing optimization is disabled in gcc 4.2 because it was disabled in gcc 3.3. It was disabled in gcc 3.3 because it was disabled in gcc 2.95. It was disabled in gcc 2.95 because it was the year 1999.

The gcc-local man page continues with even more stupid options.

The -O2 option does not include -fstrict-overflow, as this option causes issues on some legacy code. -fstrict-overflow can cause surprising optimizations to occur, possibly deleting security critical overflow checks.

Lame.

The Strict Aliasing Situation Is Pretty Bad.

Posted 2016-07-25 12:52:07 by tedu Updated: 2016-09-08 13:06:33
Tagged: c openbsd rants

my int is too big

Lots of kernel patches yesterday. Several of them, as reported by NCC, involved similar integer truncation issues. Actually, they involved very similar modern 64 bit code meeting classic 32 bit code. The NCC Group report describes the bugs, but not the history of the code. (Some of the other bugs like usermount aren’t interesting. The unp bug is kind of interesting, but not part of the NCC set. Also doesn’t involve integers. Another time.)

ticks

The thrsleep system call is a part of the kernel code that supports threads. As the name implies, it gives userland a measure of control over scheduling and lets a thread sleep until something happens. As such, it takes a timeout in the form of a timespec. The kernel, however, internally implements time keeping using ticks (there are HZ, 100, ticks per second). The tsleep function (t is for timed) takes an int number of ticks and performs basic validation by checking that it’s not negative. A negative timeout would indicate that the caller has miscalculated. The kernel panics so you can fix the bug, instead of stalling forever.

Continue reading my int is too big...

Posted 2016-07-15 15:47:35 by tedu Updated: 2016-07-15 18:33:44
Tagged: c openbsd

true string indices

The other day cperciva answered why strchr returns a pointer. Many other languages do return an offset, but of course many of those lanuages don’t have pointers. Poor things. I happened to be writing a bunch of code using strchr recently, and needed both pointers and offsets.

Let’s imagine we have two similar functions, strchr and index.

Continue reading true string indices...

Posted 2016-06-24 13:42:27 by tedu Updated: 2016-06-25 17:03:49
Tagged: c programming

select works poorly

At the bottom of the OpenBSD man page for select is a little note. “Internally to the kernel, select() and pselect() work poorly if multiple processes wait on the same file descriptor.” There’s a similar warning in the poll man page. Where does this warning come from and what does it mean?

The code to implement these system calls lives in src/sys/kern/sys_generic.c. Despite differences in interface, the internal implementation is mostly shared, which is why they both have the same affliction. select and poll both scan a set of file descriptors for readiness, then if none are ready we sleep and wait.

The primary function for sleeping is tsleep, which requires a wait channel. Conceptually similar to a condition variable. At some later point, when something changes, another process or interrupt will call wakeup on the same wait channel and we’ll resume running. For example, if we’re trying to read from a pipe, but there’s no data, we’ll sleep using the address of the pipe data structure. When data is written to the pipe, it will call wakeup with the same address. We only wake up the reader(s) of this pipe, and don’t disturb the slumber of all the readers blocked waiting on other pipes.

Continue reading select works poorly...

Posted 2016-06-07 13:59:14 by tedu Updated: 2016-06-07 13:59:14
Tagged: c openbsd programming

accidentally nonblocking

A continuation, perhaps culmination, of a series that includes rough idling, firefox vs rthreads, and browser ktrace browsing.

I really like using ktrace to inspect programs. It’s somewhat primitive, to be sure, and unlike source review, it can be difficult to understand the programmer’s intentions. However, my CPU doesn’t execute intentions; it executes instructions.

poll

Browser source code can be nearly impenetrable due to size, but some other programs share similar behaviors. Perhaps they will prove a tractable target for further investigation. xterm contains some code that looks about like this. (Despite the “Abandon All Hope” warning at the entrance to this ifdef maze, I still found it quite navigable.)

Continue reading accidentally nonblocking...

Posted 2016-06-06 05:41:09 by tedu Updated: 2016-06-06 12:57:18
Tagged: c network openbsd programming

a prog by any other name

What is a name, really?

Sometimes two similar programs are really the same program with two names. For example, grep and egrep are two commands that perform very similar functions and are therefore implemented as a single program. Running ls -i and observing the inode number of each file will reveal that there is only one file. Calling the program egrep is a shorthand for -E and does the same thing.

names

In fact, every program has three names: its name in the filesystem, the name it has been invoked with, and whatever it believes its own name to be. Under normal circumstances the first two will be the same, but it is possible to call execve with a path and argv[0] not in alignment. Sometimes by accident, as in mv.

Continue reading a prog by any other name...

Posted 2016-04-28 12:26:04 by tedu Updated: 2016-04-29 02:22:50
Tagged: c openbsd programming

more input validation unnecessary

There’s a widespread belief that validating user input prevents security vulnerabilities. This is true as far as it goes, but doesn’t tell the whole story. Consider the following example, distilled from any number of real world examples.

if (!valid_input(buffer)) { free(buffer); error = BADSTUFF; goto ungood; } error = process_input(buffer); ungood: free(buffer); return error;

A not uncommon mistake. A vulnerability report may, quite accurately, say something like “Invalid inputs may result in remote code execution.” However, further input validation won’t fix this bug, nor will tweeting “This is why you always validate your inputs!” prevent future occurrences.

Lots of problems may share similar or even identical descriptions without sharing fixes. It’s a small point, really, but no less important. And of course, hardly limited to the field of security.

Posted 2016-04-25 18:14:33 by tedu Updated: 2016-04-25 18:14:33
Tagged: c programming security

outrageous roaming fees

Unexpected roaming fees are the worst. You’re just cruising along, having a jolly old time, and then boom. $20 per megabyte??? Should have read the fine print. Of course, if you had known to read the fine print, you probably would have already known about the roaming fees, and therefore not needed to read the fine print. And so it goes, in life and in ssh.

What, ssh has roaming??? Should have read the fine print. The Qualys Security Advisory is more than thorough. Now that we’ve read the fine print, what can we do differently?

The main bug (ignoring the second overflow for now) is that some sensitive memory was recycled and leaked. The possibility of this happening has been known for some time, and there’s some countermeasures in place, but they’re not foolproof.

Continue reading outrageous roaming fees...

Posted 2016-01-15 14:55:50 by tedu Updated: 2016-01-19 04:17:28
Tagged: c openbsd programming security thoughts

sometimes syscalls restart

Yesterday Reyk fixed a tiny bug in vmd. It wasn’t possible to kill the process by pressing ^C. As explained in the commit, the accept4 system call was being restarted after the signal.

By default, most signal handlers that a program establishes have the SA_RESTART flag set, which causes an interrupted system call to be restarted. Actually, by default signals are either ignored or cause the program to terminate, so this isn’t a problem at all, but any handler installed by calling signal sets this flag. More control over signal actions is possible using the appropriately named sigaction function.

On the kernel side, system calls that need to block call tsleep which usually waits for a corresponding wakeup or a timeout to expire. However, it may also return an error (ERESTART) if it’s interrupted by a signal. Most system calls don’t inspect the error code, they simply pass it along. But when the kernel is about to return to userland, it will notice this error code and run the syscall again.

Among the system calls that handle ERESTART specially are poll, select, and kevent. All of them check for ERESTART and immediately map it to EINTR so it gets returned to userland.

Back in vmd, it had installed a SIGTERM handler that set a quit flag variable to true, but was getting stuck in accept. The code looking at quit never had a chance to run. The fix was to add a call to poll before accept.

Most of the time the default behaviors make sense. Restarting system calls prevents a lot of spurious failures from propagating. Applications that install signal handlers usually use one of the interruptible functions in the core of their event loop. vmd happened to be an exception, that only needed to handle one event and tried to take a shortcut.

Posted 2015-11-24 17:52:49 by tedu Updated: 2015-11-24 17:52:49
Tagged: c openbsd programming

starting from scratch bugs

Or everything I didn’t know about unix. The OpenBSD source tree has lots of example code for solving any number of problems, but I like to do things my own way. Occasionally this means something gets overlooked. A few examples. Previous thoughts on rewrites and reuse: out with the old, in with the less and hoarding and reuse.

Quite a few programs contain variations of the same parse.y file. This file originated in pfctl (649 revisions!) but spread to bgpd, relayd, and smtpd, among many other places. The grammar changes every time of course, but the lexer that drives it stays mostly the same. parse.y also implements a few other grammar niceties, like including other files and setting macros (variables). This gives a consistent feel to each config file.

Continue reading starting from scratch bugs...

Posted 2015-11-04 06:11:05 by tedu Updated: 2015-11-04 06:11:05
Tagged: c openbsd programming