Finding bugs in Tarsnap
tedunangst.com
tedunangst.com
I bumped into Ted again three weeks ago at BSDCan 2015 and he must have had memory leaks on his mind, because the day after the conference ended he sent me an email pointing out a memory leak in Tarsnap. (Harmless, since it's in a we're-about-to-exit error path, but worth $10 anyway.)
If a function is very project-specific and has no purpose to being used independently it may be worth considering declaring it static, right?
For example, doing a strcpy(dest, dest + 1) will work in most cases, but if done on 64-bit Linux with a CPU that has sse4 optimizations, you will get random corruption on certain string lengths. (The C standard says that the behavior in this case is undefined). I'd like to see a list of items such as this to watch out for when auditing code.
Has a lot of rules of the form "Do Not ..."
[0] http://blog.llvm.org/2013/04/testing-libc-with-fsanitizeunde...
Maybe you took some notes.
Could you share some more info if you are free to disclose how you poked with the connection pool. I haven't look at OpenERP sources, but I think the database in use is PostgreSQL.
> "for a user of one database to access other database"
Were OpenERP using a database for each tenant or 1 database with multiple schemas ? In case it was the former case, were all databases accessed with the same credentials ? Which connection pool was it ? Pgpool / Pgbouncer ? Where was the vulnerability, code, db, pool, config setup ?
Sorry for all this questions, I'm indeed very interested and involved in this topic.
OpenERP, at least back then, was using a single PostgreSQL cluster for a given OpenERP server. Each tenant has its own PostgreSQL database. In multiple places, OpenERP offers the administrator role of a tenant to customize OpenERP with Python code. Basically you can inject Python code for execution, and it is run in the same processes used for every tenant. OpenERP tries to limit what the Python expressions can do.
The idea of what I did was, starting from the objects I had access to, to find a way to get a database cursor to another database than mine.
The connection pool in OpenERP is custom and part of the Python code base.
To get the cursor, I poked at some object, took its class and reinstanciated (this is all straightforward to do in Python) it with the name of another database (listing other databases was another longstanding issue of OpenERP).
So I imagine, given their specifications, they had to give each tenant its own full PG database. I understand they have strong business logics but it does not seem very efficient. Salesforce is known to use a single oracle instance for all its tenants and I don't think their business logics is less demanding.
Giving an administrator or elevated role to the tenant connection looks like a really bad idea from the start, especially if the tenant instance is not sandboxed in a container or virtual server.
But this things are hard and a small mistake can have big consequences.
In particular, I remember, while writing an ASN.1 library, commenting to a friend that "most ASN.1 implementations are probably full of dangerous bugs" (since mine certainly was), and about a year or two later all those ASN.1-related vulnerabilities came out.
I guess that in general, bugs appear in patterns that recur again and again in independent code, as people try to solve the same problems with the same tools and make the same assumptions.
An references to the standard (I assume he is referring to POSIX) where this is disallowed?
The relevant quote is:
the behavior is undefined if the signal handler refers to any object
other than errno with static storage duration other than by assigning
a value to an object declared as volatile sig_atomic_t, or if the
signal handler calls any function defined in this standard other than
one of the functions listed in the following table.