Arquivo para categoria Linux

Chrooting from a 32bit userland into a 64bit jail

Before you start

Although this work on any linux distribution, this text will talk specifically about gentoo linux. The motivation for this writing is that I run an hybrid gentoo installation (32bit userland running a 64bit kernel) and now I want to migrate to a full 64bit installation.

As a great opportunity to learn a bit more I decided to try to install the new system while still running the old one.

An alternative way to run ELF binaries

Chrooting into a different userland, in this case from 32bit into 64bit, is not trivial. This happens because a 32bit shell cannot directly run a 64bit binary. Here is an example:

> file `which bzip2`
/bin/bzip2: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), 
dynamically linked (uses shared libs), for GNU/Linux 2.6.9, stripped

> file /usr/x86_64-pc-linux-gnu/bin/bzip2
/usr/x86_64-pc-linux-gnu/bin/bzip2: ELF 64-bit LSB executable, x86-64, 
version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.16, stripped

 > /bin/bzip2
 bzip2: I won't write compressed data to a terminal.
 bzip2: For help, type: `bzip2 --help'.

 > /usr/x86_64-pc-linux-gnu/bin/bzip2
 zsh: no such file or directory: /usr/x86_64-pc-linux-gnu/bin/bzip2

as you can see, the 64bit binary could not be directly executed and the error message is everything but helpful.  We need an alternative way to execute an ELF binary. Luckly the linux dynamic linker/loader (,*) can also be used to run any ELF binary. All you have to do is invoke it directly passing as the only argument the final binary you need to run. So this is essentially the same:

 > bzip2
 bzip2: I won't write compressed data to a terminal.
 bzip2: For help, type: `bzip2 --help'.

 > /lib/ /bin/bzip2
 bzip2: I won't write compressed data to a terminal.
 bzip2: For help, type: `bzip2 --help'.

We could try to use our current /lib/ to run na 64bit binay but unfortunately this does not work as you can see:

> /lib/ /usr/x86_64-pc-linux-gnu/bin/bzip2 
/usr/x86_64-pc-linux-gnu/bin/bzip2: error while loading shared libraries: /usr/x86_64-pc-linux-gnu/bin/bzip2: wrong ELF class: ELFCLASS64

What do we need is a 64bit dynamic linker/loader and for this we must install a basic cross-compile environment.

Installing a cross-compiler

To have a cross-compile environment on gentoo you need to install the crossdev package. This is simple as:

emerge crossdev

Now you use the crossdev script to build the essential tools for the desired target. In this case we need 64bit target:

crossdev -t x86_64-pc-linux-gnu

This will build the essential tools so you can generate 64bit ELF binaries even being in a host 32bit system. After this we have a 64bit dynamic loader/linker that we use to run any 64bit ELF binary:

> file /usr/x86_64-pc-linux-gnu/lib/
/usr/x86_64-pc-linux-gnu/lib/ symbolic link to `'

> file /usr/x86_64-pc-linux-gnu/lib/ 
/usr/x86_64-pc-linux-gnu/lib/ ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, stripped

> /usr/x86_64-pc-linux-gnu/lib/ 
You have invoked `', the helper program for shared library executables.
This program usually lives in the file `/lib/', and special directives
in executable files using ELF shared libraries tell the system's program
loader to load the helper program from this file. This helper program loads
the shared libraries needed by the program executable, prepares the program
to run, and runs it. You may invoke this helper program directly from the
command line to load and run an ELF executable file; this is like executing
that file itself, but always uses this helper program from the file you
specified, instead of the helper program file specified in the executable
file you run. This is mostly of use for maintainers to test new versions
of this helper program; chances are you did not intend to run this program.
--list list all dependencies and how they are resolved
 --verify verify that given object really is a dynamically linked
 object we can handle
 --inhibit-cache Do not use /etc/
 --library-path PATH use given PATH instead of content of the environment
 --inhibit-rpath LIST ignore RUNPATH and RPATH information in object names
 in LIST
 --audit LIST use objects named in LIST as auditors

This means that now we have a way to run an arbitrary 64bit binary. Let’s test it with the first example we saw earlier.

> file /usr/x86_64-pc-linux-gnu/bin/bzip2 
/usr/x86_64-pc-linux-gnu/bin/bzip2: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.16, stripped

> /usr/x86_64-pc-linux-gnu/lib/ /usr/x86_64-pc-linux-gnu/bin/bzip2 
/usr/x86_64-pc-linux-gnu/bin/bzip2: error while loading shared libraries: wrong ELF class: ELFCLASS32

Not so easy! This error means that the wrong shared library was chosen by the dynamic loader/linker. Now we have a new problem, we cannot run an 64bit binary using 32bit libraries. Fortunately there is an easy fix for this.

Solving shared libraries problems

What we need is to change the directories where the dynamic loader/linker will search for shared libraries when resolving the dependencies. This can be done using the LD_LIBRARY_PATH environment variable.

> LD_LIBRARY_PATH=/usr/x86_64-pc-linux-gnu/lib /usr/x86_64-pc-linux-gnu/lib/ /usr/x86_64-pc-linux-gnu/bin/bzip2 
bzip2: I won't write compressed data to a terminal.
bzip2: For help, type: `bzip2 --help'.

That’s much better! The crossdev script puts the target shared libraries inside lib/ and usr/lib directories, so it’s advisable to add both to the LD_LIBRARY_PATH variable.

Putting all the pieces together

Now that we know how to run a 64bit binary being in a 32bit userland we need to run the main point of all this, the chroot binary.

> LD_LIBRARY_PATH=/usr/x86_64-pc-linux-gnu/lib:/usr/x86_64-pc-linux-gnu/usr/lib/ /usr/x86_64-pc-linux-gnu/lib/ /usr/x86_64-pc-linux-gnu/bin/chroot 
/usr/x86_64-pc-linux-gnu/bin/chroot: missing operand
Try '/usr/x86_64-pc-linux-gnu/bin/chroot --help' for more information.

Awesome! Now that we can run the chroot binary, let’s do the chroot.

> sudo LD_LIBRARY_PATH=/usr/x86_64-pc-linux-gnu/lib:/usr/x86_64-pc-linux-gnu/usr/lib/ /usr/x86_64-pc-linux-gnu/lib/ /usr/x86_64-pc-linux-gnu/bin/chroot /mnt/gentoo64 /bin/bash
jetta / #

Here we are already inside the 64bit jail, let’s check.

jetta / # which bzip2
jetta / # file /bin/bzip2 
/bin/bzip2: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.9, stripped
jetta / # /bin/bzip2 
bzip2: I won't write compressed data to a terminal.
bzip2: For help, type: `bzip2 --help'.
jetta / #

And that’s it! We are now in a full 64bit jail, ready to install a new gentoo system while running an hybrid (32bit userland, 64bit kernel) system, that is, a brand new gentoo with no downtime!

Thanks for reading!

Deixe um comentário

Running 64bit binaries on 32bit userland with 64bit kernel

The problem

Some time ago I wrote about how my Gentoo Linux is installed (blogpost in pt_BR) on my laptop. Long story short: I have a hybrid system, 32bit userland running on a 64bit kernel. I opted to do this type of install because I still have an impression that a full 64bit system still has some key problems (in my past adventures flash was one of them). Anyway, this setup works very well. I can use all 8GB (not by one same process) for example. But not long after the installation I discovered one thing that got me confused.

How come even with a 64bit kernel I still coudn’t run any 64bit ELF binary?

I thought that just having a 64bit kernel was enough to run 32 and 64bit binaries, in fact it is! But is not so trivial do run a 64bit binary in a 32bit userland.

The first attempt, no luck

The first thing I tried was obviously call the binary directly on the command line:

daltonmatos@jetta ~/src [158]$ ./m64
-bash: ./m64: No such file or directory
daltonmatos@jetta ~/src [159]$

This is, indeed, a very cryptic error message.

Enter the dynamic loader

All binaries (at least the massive majority) on your system is a dynamically linked ELF. And you can check this with the file command.

daltonmatos@jetta ~/src [179]$ file /bin/ls
/bin/ls: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), 
for GNU/Linux 2.6.9, stripped
daltonmatos@jetta ~/src [180]$

Remember, 32bit userland. A bit further and we will see this for 64 bit binaries.

By dynamic linked you can understand that all libraries that the binary depends on are loaded at runtime. You can check which are these libraries with the ldd command.

daltonmatos@jetta ~/src [180]$ ldd /bin/ls => (0xffffe000) => /lib/ (0xf776c000) => /lib/ (0xf7763000) => /lib/ (0xf7605000) => /lib/ (0xf75eb000)
 /lib/ (0xf7796000) => /lib/ (0xf75e4000)
daltonmatos@jetta ~/src [181]$

Note: Thee ldd command is just a wrapper around the real dynamic loader, usually /lib/ or /lib/ld-<version>.so. I’m running glibc-2.13 so here I have /lib/ Running ldd <some-binary> is the same as running /lib/ --list <some-binary>. So for now on we will be using the second.

Here begins the differencies. The 32 bit (or the ldd wrapper) tool does not know how to handle a 64 bit binary, as we can see:

daltonmatos@jetta ~/src [229]$ /lib/ --list ./m64
./m64: error while loading shared libraries: ./m64: wrong ELF class: ELFCLASS64
daltonmatos@jetta ~/src [230]$

And the ldd command:

daltonmatos@jetta ~/src [190]$ ldd ./m64
 not a dynamic executable

which is clearly not true, since I compiled m64 myself using a regular gcc that outputs 64bit binaries. So we need a 64bit-capable Since I have two compilers (one that generates 32bit binaries and another that generates 64bit) I need to have two complete tool chains (basically: binutils, gcc, gdb, glibc). So my second tool chain has what I need.

Specifically on Gentoo Linux, the cross compiling infrastructure creates /usr/<arch>-pc-linux-gnu folder and stores all files under it so I have a /usr/x86_64-pc-linux-gnu/lib/, that is, the dynamic loader for 64bit binaries. Yes, I have a different version of the glibc for 64bit (2.14.1).

So let’s re-check our binaries, but now with this new tool:

daltonmatos@jetta ~/src [191]$ file ./m64 
./m64: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), 
for GNU/Linux 2.6.9, not stripped
daltonmatos@jetta ~/src [192]$

Alright, our brand new 64bit program. Now, the shared libraries:

daltonmatos@jetta ~/src [194]$ /usr/x86_64-pc-linux-gnu/lib/ --list ./m64 => (0x00007fffa90fb000) => /usr/x86_64-pc-linux-gnu/lib/ (0x00007f103f367000)
 /lib64/ => /usr/x86_64-pc-linux-gnu/lib/ (0x00007f103f6f7000)
daltonmatos@jetta ~/src [195]$

That’s awesome! You maybe asking yourself: “How is it possible to run the binary directly but not other 64bit binaries?” And you’re right, because the itself is a 64bit binary:

daltonmatos@jetta ~/src [197]$ file /usr/x86_64-pc-linux-gnu/lib/ 
/usr/x86_64-pc-linux-gnu/lib/ ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), 
dynamically linked, stripped
daltonmatos@jetta ~/src [198]$

If you know this, let me know because I don’t! =) I just discovered that the dynamic loader itself is runnable directly from the command line and can be used to run other binaries.

daltonmatos@jetta ~/src [200]$ file ./m64
./m64: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), 
for GNU/Linux 2.6.9, not stripped
daltonmatos@jetta ~/src [201]$ /usr/x86_64-pc-linux-gnu/lib/ ./m64 
Hello World
daltonmatos@jetta ~/src [202]$

Like magic! =)

If you tried these exact steps I  just described you probably got an error like this one:

daltonmatos@jetta ~/src [202]$ /usr/x86_64-pc-linux-gnu/lib/ ./m64 
./m64: error while loading shared libraries: wrong ELF class: ELFCLASS32
daltonmatos@jetta ~/src [203]$

What does this mean? Remember that we have two glibc’s installed? Both binaries depend on a shared library with the name So shouldn’t the SO handle this automatically? Yes, but it doesn’t and now I have to tell you that I’ve been hiding one piece of important information from you. Is the second key to be able to run 64bit binaries, being the first the discovery of as a generic binary runner.

Go back in the output of the --list command and see how the‘s path is resolved in both cases. See that they have different paths? 32 bit resloves to /lib/ and 64bit resolves to /usr/x86_64-pc-linux-gnu/lib/ So how do we handle this?

It turns out that we can change where the dynamic loader looks for shared objects with the LD_LIBRARY_PATH environment variable. So all commands using the 64bit loader need to be prepended with LD_LIBRARY_PATH=<new-path>, like this:

daltonmatos@jetta ~/src [203]$ LD_LIBRARY_PATH=/usr/x86_64-pc-linux-gnu/lib /usr/x86_64-pc-linux-gnu/lib/ ./m64 
Hello World
daltonmatos@jetta ~/src [204]$

One of the key advantages of having the ability to do this is that you can compile some programs to 64bit code and this program will be able to use more that 4GB of RAM, if needed.

An easier, but not optimal way

There is another way to do this that will not require tweaking the library loading path or anythin. You can compile all your 64bit binaries as statically linked ELF’s, like this:

daltonmatos@jetta ~/src [218]$ x86_64-pc-linux-gnu-gcc -static -o m64s main.c
daltonmatos@jetta ~/src [219]$ file m64s 
m64s: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, for GNU/Linux 2.6.9, not stripped
daltonmatos@jetta ~/src [220]$

This way you won’t need the dynamic loader and then you can run your binary directly from the command line:

daltonmatos@jetta ~/src [220]$ ./m64s
Hello World
daltonmatos@jetta ~/src [221]$

But this comes with a cost. Extra disk space:

daltonmatos@jetta ~/src [222]$ file m64*
m64: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.9, not stripped
m64s: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, for GNU/Linux 2.6.9, not stripped
daltonmatos@jetta ~/src [223]$ ls -lh m64*
-rwxr-xr-x 1 daltonmatos daltonmatos 7,7K Abr 8 17:15 m64
-rwxr-xr-x 1 daltonmatos daltonmatos 771K Abr 10 20:32 m64s
daltonmatos@jetta ~/src [224]$

The statically linked binary is 100 times bigger than the dynamic one. This is because you have all that’s needed bundled into the static binary. You can reduce the final size using the strip command but you won’t get a significant reduction.

That’s it! Thanks for reading!

, , , ,

6 Comentários

SSH bruteforce break attempts made to my personal server

This is just a quick post to show you why you must at least try to configure properly you ssh servers. Today, reading my server logs I realized a big number of login failures into my server and I thought about collecting some numbers about these attempts.

All login attempts have the same signature on the logs, it’s something like this:

Apr 19 23:33:20 li292-237 sshd[25190]: Invalid user <username> from <IP Address>

Each entry with a different username and possibly a different origin IP. A quick wc -l on the string Invalid user returns 197243 lines.

daltonmatos@jetta ~/ [10]$ grep -i "invalid user" messages | wc -l
daltonmatos@jetta ~/ [11]$

From all these, there are 32175 unique username

daltonmatos@jetta ~/ [13]$ grep -i "invalid user" messages | awk '{print $8}' | sort | uniq | wc -l
daltonmatos@jetta ~/ [14]$

and 669 unique IP Addresses.

daltonmatos@jetta ~/ [16]$ grep -i "invalid user" messages | awk '{print $10}' | sort | uniq | wc -l
daltonmatos@jetta ~/ [17]$

The 10 most common usernames were:

daltonmatos@jetta ~/ [25]$ grep -i "invalid user" messages | awk '{print $8}' | ./ | sort -k 2 -n -r | head -10
test 3099
oracle 2901
admin 2869
guest 1596
nagios 1459
postgres 1229
user 1174
mysql 1030
ftp 754
temp 592
daltonmatos@jetta ~/ [26]$

p.s. Here is the code for, if you are curious. =)

The same approach cane be applied to know the IP’s involved in the attacks and here are the top 10 (just the number of hits from each IP):

daltonmatos@jetta ~/ [27]$ grep -i "invalid user" messages | awk '{print $10}' | ./ | sort -k 2 -n -r | head -10
daltonmatos@jetta ~/ [28]$

Running a whois on the IP’s show me that the attacks comes from many different places including: China, Japan, Nigeria and US.

All attempts were made between April 2011 and April 2012. What I want to show you is that you need to take care of your ssh server configuration because one of these attempts could be successful. The first thing I do with any new ssh server is to disable login/password authentication and only accept ssh keys authentication. This is already a good start. =)

Thanks for reading.

Update: My great friend Denilson just pointed out that has the very same effect of uniq -c. Thanks for the tip!

, , , , ,

1 comentário

How to configure wsgid and mongrel2 to handle arbitrary sized requests


Wsgid is a generic handler for the mongrel2 web server. It acts as a bridge between WSGI and mongrel2 and makes it possible to run any WSGI python application using mongrel2 as the front end. To know more about both projects visit their official websites at: and

In this post we will see how to configure mongrel2 and wsgid so your application will be able to handle arbitrary sized requests very easily and with a low memory usage.


The problem of receiving big requests is that depending on how your front end server deals with it, you can easily become out of resources and in a worst case scenario your application can stop responding for a while. If your application exposes any POST endpoint, then you should be prepared to handle some big requests along the way.

The big picture

Mongrel2 has a very clever way to handle big requests without consuming all your server’s resources, in fact without consuming almost nothing, only bandwidth. Basically what it does is to dump the entire request to disk, using almost none additional memory. Here is how it works:

When the request comes in, mongrel2 sends a special message to the back-end handler containing only the original headers. This message notifies the start of this request. It’s up to the handler to accept or deny it. To accept the request, your handler just do nothing. If you want to deny the request, your handler must send a 0-length message back to mongrel2. Due to mongrel2 async model, you can send this deny message at any time, does not need to be imediatelly after receiving the request start message.

If you happen to be using wsgid (I hope you are!) this happens without your WSGI application ever knowing. All your application will see (if at all) is the wsgi.input attribute of the WSGI environ (if you happen to write a WSGI framework) or just request.POST (or something similar depending on what framework you’re using). It’s all transparent.

After the request is completely dumped, mongrel2 sends another message notifying the end of the upload and that’s when wsgid will actually call your application. During all the upload process, your application does not even know that a new request has come and was being handled.

All this happens while mongrel2 is already dumping the request content to disk. If your handler happen to deny the request, mongrel2 will close the connection and remove the temporary file. To know more about how mongrel2 notifies the handlers, you can read the on-line manual:

Configuring mongrel2 to handle big requests

The configuration of the server is extremely simple. All you have to do is tell it where to dump any big request that may arrive. You may ask: How big a request must be to be dumped to disk? The truth is that you decide this and tell mongrel2 about it.

To tell it where to dump the request you must set the option upload.temp_store to the correct path. This path must include the filename template. An example could be: /uploads/m2.XXXXXX. This must be a mkstemp(3) compatible template. See the manpage for more details.

The size of the request is set with the limits.content_length. This sets the biggest request mongrel2 will handle without dumping to disk. This size is set in bytes.

Configuring wsgid to understand what mongrel2 is saying

Since mongrel is saving requests on disk wsgid must be able to open these files and pass its contents to the application being run. It’s important to note that the path chosen on the upload.temp_store is always relative to where your mongrel2 is chrooted, so somehow we must tell wsgid where this is.

Fortunately this new release of wsgid comes with a new command line option: --mongrel2-chroot. You just have to pass this to your wsgid instance to be able to handle big requests.

Alternatively you can add this options to your wsgid.json configuration file if you want. This can be complished with a simple command:

$ wsgid config --app-path=/path/to/your/wsgid-app --mongrel2-chroot=/path/to/mongrel2/chroot

This will save this new option on your config file. Just restart your wsgid instance and it will re-read the config file.

Working without knowing where mongrel2 is chrooted

There is another way to handle these big requests. In this approach your don’t need to pass --mongrel2-chroot to all your wsgid instances. The trick here is to mount the same device on many different places. The easiest way to do this is to have mongrel2’s temp_store in a separated partition (or logical volume if you are using LVM). Let’s see an example:

Suppose we have mongrel2 chrooted at /var/mongrel2/ and configured this way:

upload.temp_store = '/uploads/m2.XXXXXX'

Since mongrel2 assumes /uploads is relative to its chroot we must mount this device ate the right place.

# mount /dev/vg01/uploads /var/mongrel2/uploads

Now our logical volume is mounted at /var/mongrel2/uploads. There is one last setp so we can start serving big requests with wsgid. When mongrel2 sends the upload started message to wsgid, which contains the path of the temporary file, the path received by wsgid is the same we put on mongrel2’s config. So wsgid will try to read /uploads/m2.384Tdg (for example) and obviously will fail. So we need a way to make /uploas/ also available to wsgid (that normally is not chrooted anywhere) and the trick to do this is to re-mount the same device at a different place. And this is how we do it:

# mount /dev/vg01/uploads /uploads

So now we have the same device mongrel2 writes the temporary files available to all wsgid processes that need to read them. Remember that mongrel2 does not remove any of these file because obviously it does not know when your app is done. So it’s up to you to clean them.

If your /upload directory is part of a bigger volume or is not on a separated one, you still can accomplish this multi-mount approach. Just use the --bind. This way you can re-mount any directory at another place. Read the mount man page for more details.


This is another cool mongrel2 feature that the latest wsgid release (0.5.0) already supports. So now wsgid supports all major features mongrel2 provides and is starting to be more mature, trying to find its way into a production-ready tool.

This release complete changelog is available at and you can grab your wsgid copy at

Thanks for reading and enjoy!

, , ,

Deixe um comentário

Deploying your django application with mongrel2 and wsgid

Some time ago when people talked about webapp deployment they were probably talking about the LAMP stack. Since the appearance of the nginx webserver this has changed quite a bit. In this post you will know another stack, that does not use neither apache nor nginx but that is equally interesting and quite scalable too. We will be talking about mongrel2 for the frontend and wsgid for the backend worker processes.


In this post you will learn how to configure mongrel2 and wsgid to run your WSGI appalication. If you are interested in web servers, web application deployment and system administration, read on!

Leia o resto deste post »

, , ,

Deixe um comentário

Gentoo com kernel land 64 bits e user land 32 bits

O problema

Recentemente comprei um novo  notebook e por isso tive a oportunidade de instalar um novo S.O do zero, afinal já estava com uma mesma instalação desde 2008 (quando comprei meu primeiro notebook). Até poderia transferir uma instalação de um notebook para o outro, mas daria um trabalho parecido (ou maior) do que instalar novamente.

Nesse momento surgiu a mesma dúvida de sempre: Instalar a versão 64 bits ou 32 bits? Em 2008 tentei instalar uma versão totalmente 64 bits e tive problemas com plugin do flash, cheguei a ter um firefox 32 bits só para poder ver vídeos usando flash. Pouco tempo depois desisti do sistema 64 bits por esses e outros motivos e acabei instalando 32 bits mesmo.

Dessa vez a mesma dúvida. Achei que 3 anos depois as coisas estariam melhores, mas já de cara tive problemas com o driver de vídeo. A tela simplesmente não dava refresh corretamente. Um ls no terminal não retornava nenhum resultado, a não ser que a janela do terminal fosse movida de lugar, aí sim acontecia o refresh e o resultado do ls (já executado) aparecia. Isso significa que estava simplesmente impossível de usar o sistema.

Percebi que no live-DVD que estava usando, o driver de vídeo funcionava perfeitamente, então comecei a estudar o que o sistema do live-DVD tinha de diferente. Percebi que ele era userland 32 bits, apesar de reconhecer os 4GB do novo notebook. Nesse momento tive a idéia de tentar uma instalação mista: Kernel 64 bits e userland 32 bits.


O termo crosscompiling é usado quando temos um compilador rodando em um sistema e gerando código para outro. Por exemplo, você tem um notebook (intel x86) e consegue compilar um código em C que roda no seu celular (processador ARM, por exemplo). Mas o crosscompiling não serve apenas para gerar código entre máquinas diferentes, pode ser usado também para gerar código para a mesma máquinas, apenas escolhendo se o resultado será um binário de 32 bits ou 64 bits.

Foi exatamente isso que fiz nesse caso. Para fazer o que estava querendo precisava ter dois compiladores. Primeiro usei o gcc que é instalado no gentoo para compilar um outro gcc, esse último gerando código 64 bits. Ou seja, tenho agora um compilador que roda em um ambiente 32 bits mas que gera código 64 bits. E esse compilador foi gerado por um outro compilador que roda em 32 bits e também gera código 32 bits, entendeu? Ainda comigo? Ok, vamos lá.

Toda a mágica desse processo é feita pelo pacote sys-devel/crossdev, que faz parte da árvore principal do Gentoo. O que esse script faz é construir todo o toolkit necessário para gerar o cross compiler que precisamos. O que precisamos fazer é muito simples:

# emerge crosdevv
# crossdev -t x86_64-pc-linux-gnu

E isso é suficiente. Quando vi que realmente funcionava lembrei de 2004, quando ainda estava usando slackware e tive que fazer isso “na unha. Cheguei até a postar no twitter um agradecimento a quem quer que tenha escrito esse script. Merecido!

Compilando o novo kernel

Agora, com tudo pronto, temos dois compiladores: O que gera código 32 bits, que podemos chamar apenas digitando gcc, e o que gera código 64 bits que podemos chamar com o comando x86_64-pc-linux-gnu-gcc. O que temos que fazer agora é configurar nosso kernel para que use o compilador correto. Felizmente alguém já precisou fazer o que estou fazendo e existe uma maneira fácil de escolher o compilador que vai gerar nosso kernel.

Escolhendo compilador customizado para nosso kernel

Para isso basta irmos ao menu General setup/ e escolher o valor correto para a opção Cross-compiler tool prefix. Isso fará com que nosso novo compilador seja usado no momento de compilar nosso kernel. Agora o que temos que fazer é compilar nosso kernel como fazemos normalmente, o de sempre:

# make
# make modules
# make modules_install

Agora é só copiar nosso novo 64 bit kernel para o lugar certo, adicionar uma nova entrada no boot loader e bootar nosso novo kernel. E isso é o que temos depois de um boot com sucesso:

Kernel 64 bits com userland 32 bits

Exatamente o que queríamos:

  • Kernel 64 bits (X86_64)
  • Userland 32 bits (todos os binários são ELF 32-bit)
  • Os 4 GB RAM corretamente sendo usados
Agora tenho o driver de vídeo funcionando perfeitamente, com aceleração 3D e o novo gnome3 rodando sem nenhum problema! Perfeito!

, ,

1 comentário

Gentoo com partição raiz encriptada

A idéia desse post é apenas mostrar o caminho para instalar um Gentoo tendo a partição raiz (e todas as outras) encriptadas. Não é um texto muito detalhado, é para quem já tem costume com a instalação de gentoo. Mas mesmo que você não tenha familiaridade com esta distribuição, pode ler mesmo assim, apenas por curiosidade. =)

Um ponto negativo da abordagem que vou apresentar é que fica praticamente impossível recuperar seu laptop com programas como preyproject. A idéia nesse caso é proteger seus dados, não o aparelho. Esse último, bem ou mal, pode-se juntar dinheiro (mesmo que por muito tempo) e comprar outro, mas seus dados pessoais em mãos erradas, pode ser fatal. Lembrem-se sempre de manter seus backups atualizados. Bem, chega de papo e vamos ao que interessa.

Preparando as partições

Antes de começar a instalação, precisamos particionar nosso disco de forma correta. Repare que o que teremos encriptado será somente a partição raiz onde o S.O estará inslatado, tudo bem que isso corresponderá a quase 100% do disco, mas precisamos dexar claro que uma pequena parte do disco permanecerá sem encriptação, e você entenderá porque mais a frente.

Essas são as partções originais do notebook onde fiz essa instalação:

Particoes originais

Preciasmos, basciamente, criar duas partições:

  • Uma onde guardaremos as imagens dos kernels que vamos usar (/boot, 256MB)
  • Outra contendo o restande do disco, onde o S.O estará instalado

O motivo pelo qual temos que ter essa partição não encriptada é que nosso boot loader (grub) não é capaz de ler uma partição que esteja encriptada, se isso fosse possível poderíamos encriptar 100% do disco, inclusive a partição onde estão os kernels. Feito isso, nosso disco agora tem apenas duas partições:

Novas particoes criadas

Encriptando a partição principal

Agora o que precisamos fazer é efetivamente encriptar a partição onde vamos instalar o gentoo, para isso usaremos o cryptsetup:

Formatando com cryptsetup luksformat

Agora temos que fazer com que essa partição encriptada fique disponível como um block device.

Destravando crypt root

A partir desse momento já poderíamos formatar esse block device (mke2fs -j), mas como vamos usar LVM2 em cima da encriptação, precisamos fazer mais algumas coisas antes de começar a instalação. O comando acima cria um block device em /dev/mapper/crypt-root.

Configurando o LVM2

Agora que já temos toda a partição encripada é hora de configurar o LVM2. Vamos criar apenas um volume físico (physical volume) que ocupará toda a partição que acabamos de encriptar. Depois criaremos um Volume Group e dois Logical Volumes.

Criando volumes lvm2

Agora é hora de formatar os volumes que acabamos de criar:

Formatando volume lógico que será a partição raiz do S.O

Formatando o volume lógico que será o /home

Agora que temos dois volumes prontos, podemos começar a instalar o gentoo. Basta montar o block device /dev/vg01/root em /mnt/gentoo (como recomenda o gentoo handbook) e podemos continuar a partir do passo 5.

Configurando o kernel

No momento de configurar o kernel (handbook, passo 7) que usaremos, precisamos adicionar opções especiais para que tudo dê certo. Basicamente essas opções são:

  • Suporte a Device mapper, com suporte a encripatação
  • Suporte ao algoritmo de encriptação usado

Kernel option: device mapper

Kernel Option: Algoritmo de encriptação

Kernel Option: Sha 256 support

Essa última opção só foi necessária pois usamos –cipher twofish-cbc-essiv:sha256 no momento de encriptar a partição /dev/sda2.

Para podermos compilar esse kernel, o melhor é usarmos o utilitário genkernel. Basta instalar usando emerge normal. Antes de efetivamente compilar esse kernel, precisamos instalar dois pacotes. Atenção para as USE flags específicas de cada um deles:

  • sys-fs/lvm2 USE: +static
  • sys-fs/cryptsetup USE: +static-libs

Isso é necessário pois o ramdisk que será criado daqui a pouco precisará deles. O genkernel é uma mão na roda e é quem fará o trabalho duro de adicionar suporte para que seja possível bootar esse sistema com do disco encriptado. Como o genkernel já salva automaticamente os arquivos em /boot, temos que montar nossa partição (aquela que não é encriptada) no lugar certo:

# mount /dev/sda1 /boot

Agora poderemos usar o genkernel para preparar tudo:

# genkernel --menuconfig --luks --lvm all

Isso vai fazer com que o menu de configuração do kernel seja chamado (onde teremos que adicionar as opções citadas acima) e depois que salvarmos a configuração já começará a compilar nosso novo kernel. No final da compilação, teremos em /boot dois arquivos: O kernel e o initramfs criados pelo genkernel.

Configurando o boot loader

Nesse momento, o que falta é configurar o boot loader, nesse caso o Grub.

# emerge grub
# grub
grub> root (hd0,0)
gurb> setup (hd0)

Repare que estamos instalando o grub no MBR, isso é válido pois nesse caso temos apenas um S.O instalado. Se estivéssemos fazendo dual-boot e já tivéssemos um outro S.O rodando, teríamos que instalar o grub na partição sda1, nesse caso em (hd0,0).

Como estamos preparando um sistema e um kernel especiais, precisamos passar opções especiais para o Grub, só assim ele poderá carregar nosso novo S.O. As linhas do /boot/grub/menu.lst ficam assim:

title Gentoo Linux 2.6.38-gentoo-r6
root (hd0,0)
kernel /boot/kernel-genkernel-x86_64-2.6.38-gentoo-r6 dolvm root=/dev/ram0 crypt_root=/dev/sda2 real_root=/dev/vg01/root
initrd /boot/initramfs-genkernel-x86_64-2.6.38-gentoo-r6

Ajustando o /etc/fstab

O último passo é ajustar o arquivo /etc/fstab para que as partições corretas sejam montadas. Temos que adicionar o /boot e o /, ficando assim:

Como fica o /etc/fstab

Nesse arquivo temos o /home, que no meu caso foi necessário pois sempre deixo a home separada. Não esqueça de retirar a linha do SWAP, pois não criamos uma.

Agora é dar reboot e curtir o novo sistema com os dados totalmente encriptados. Como estamos usando LVM2, qualquer partição adicional que você criar no futuro, já estará encriptada.

Considerações finais

É bem verdade que pelo fato de ter seu disco encriptado você terá uma perda de performance. Eu sei disso. A questão é que já uso essa configuração há 3 anos (usei desde o primeiro notebook) e como nunca tive um notebook sem ter o disco encriptado acabo não sabendo qual é a real perda de performance.

Usei o primeiro notebook durante todo o tempo, sem achar que ele estava lento por qualquer motivo. O notebook novo já é naturalmente mais rápido (Processador melhor, disco melhor, etc) então mesmo tendo novamente o disco encriptado, já percebi uma melhoria considerável na performance do novo aparelho. Então, diante disso, tá tudo bem! =)

1 comentário

Rodando sua aplicação WSGI como um *nix daemon

For english readers, pease see post below.

Quase sempre quando pensamos em aplicações web (eu inclusive), pensamos na apache stack. Esse post apresenta uma forma diferente de fazer o deploy de sua aplicação, começando pelo fato de usarmos o servidor web apache.

Primeiro de tudo, precisamos conhecer uma peça chave diso tudo:


Mongrel2 é um servidor web escrito por Zed A. Shaw. Esse é um servidor que simplismente não se importa em que linguagem sua aplicação foi escrita, tudo que você precisa fazer é seguir algumas regras bem simples para conseguir juntar mongrel2 e sua aplicação.

A primeira regra é que sua aplicação precisa saber se comunicar através de uma fila, nesse caso ØMQ ( e a segunda regra é que sua aplicação precisa entender o protocolo definido pelo mongrel2. Você pode (e deve!) saber mais sobre o mongrel2 no site oficial:

A grande sacada do mongrel2 é que, o fato dele usar uma fila para se comunicar com sua aplicação faz com que sua aplicação possa rodar de forma desacoplada do servidor, isso significa que sua aplicação não roda com a ajuda de um mod_algumacoisa ou como um processo filho do servidor web. Uma outra vantagem é que o ØMQ permite enviar mensagem por TCP, isso significa que sua aplicação pode estar rodando em uma máquina diferente de onde o mongrel2 está rodando.

Poder rodar sua aplicação em máquinas diferentes é fantástico pois sempre que necessário você pode adicionar mais uma máquina ao seu cluster e startar mais instâncias da sua apliação, todas as instâncias vão se comunicar com o mesmo mongrel2, que vai balancear as requisições entre todas as instâncias conectadas, usando uma politica round-robin.


wsgid é o projeto que desenvolvi para tornar possível rodar suas aplicações WSGI usando como servidor web o mongrel2. O wsgid é a ponte entre o mongrel2 e a especificação WSGI (PEP-333), isso significa que basta a sua aplicação obedecer à especificação WSGI para já estar pronta para rodar com o mongrel2.

O wsgid entende tanto a língua do mongrel2 (zeromq + protocolo) quanto a especificação WSGI. Além disso, sua aplicação agora é um processo separado, com PID e tudo mais. Isso te traz algumas vantagens, como:

  • Pode rodar com permissões de qualquer usuário, a sua escolha;
  • Por ser um processo do sistema operacional, está automaticamente sujeito a quaisquer configurações que o S.O possa oferecer, como por exemplo: limite de banda, memória, CPU e etc;
  • Pode ser rodado dentro de um chroot, caso você precise rodar código não confiável;
  • Entre outras.

Iniciar uma nova instância de sua aplicação é tão fácil quanto:

   $ wsgid --app-path=/path/to/wsgid-app-folder/ --recv=tcp:// --send=tcp://

Nesse exemplo simples estamos conectando ao endpoint 0MQ que está na mesma máquna em que nossa aplicação, mas nada impede de usarmos –recv=tcp://, sendo esse IP o de uma máquina qualquer em seu cluster. Ainda nesse exemplo a opção –workers=4 cria 4 processos que vão ser responsáveis por atender requisições de sua aplicação.

wsgid, principais funcionalidades

Além de facilitar o deploy de aplicações WSGI com o mongrel2, o wsgid possui ainda outras funcionalidades importantes:


Com a opção workers você pode iniciar quantos processos desejar, de uma só vez. Isso significa que você não precisa rodar o comando 4 vezes caso queira 4 instâncias, apesar de você poder fazer isso, sem problema nenhum. Mas essa opção te dá a possibilidade de fazer –workers=4, que te dará o mesmo resultado.

keep alive

Com a opção keep-alive o wsgid reinicia automaticamente qualquer processo que tenha terminado sua execução. Isso significa que uma chamada ao wsgid com –workers=4 –keep-alive manterá sempre 4 workers trabalhando para sua aplicação.

hot deploy

Sempre que o wsgid restarta um dos processos, o código de sua aplicação é recarregado, afinal é um novo processo que está sendo criado. Isso significa que você pode atualizar o código-fonte de sua aplicação e apenas mandar um SIGTERM para todos os seus workers, isso fará com que o wsgid restarte cada um deles, mas dessa vez já rodando o novo código-fonte.


O wsgid já pode, automaticamente, fazer o chroot para uma localidade onde a aplicação está. Isso faz com que essa aplicação possa rodar de forma isolada, criando assim um ambiente um pouco mais seguro (não totalmente) caso você esteja rodando códigos não confiáveis.

Sistema plugável para carregar diferentes aplicações

O wsgid conta com um sistema de plugins muito simples porém bem poderoso. Com ele você pode escrever seu próprio Application Loader, caso o wsgid não consiga carregar sua aplicação. Com isso será muito simples adicionar suporte a outros frameworks WSGI para que mais aplicações possam fazer uso desse projeto.

Espero que tenha gostado do projeto, qualquer feedback é bem vindo. Para saber mais sobre o projeto visite o site oficial: e saiba mais.

Mas lembre-se, use o que for melhor para você, use o que te atende melhor. Não estou dizendo que a solução mongrel2+wsgid é a melhor sempre, estou apenas dizendo que essa combinação é fantástica, e deve ser considerada no momento de publicar uma nova aplicação WSGI.

Apenas por curiosidade, o site é uma aplicação django e está rodado usando o próprio wsgid.

Running your WSGI app as a *nix daemon

Almost every time we think about web apps (at least me) we think about the apache stack. This post will show you a different method to deploy your aps, starting by not using apache as the web server.

First of all, we need to know a key piece of all this:


Mongrel2 is a webserver written by Zed A. Shaw. The server is language agnostic, which means that it just doesn’t care which language you wrote you app, all you have to do is follow some very simple rules and you will be able to plug mongrel2 and your app together.

The first rule is that your app must know how to communicate through a queue, in this case ØMQ ( and the second one is that you must follow the very simple protocol specified by mongrel2. You can (and must!) know more about mongre2 on the official website:

The key feature of mongrel2 is that, that fact of using a queue to communicate with the applications makes it possible to run the apps decoupled from the server, this means that your app doesn’t run with a mod_something or as a child process of the webserver. Another advantage is that ØMQ allows you to communicate over TCP, that’s how you can run your app on a machine other than where mongrel2 is running.

The ability to run your app this way, that is, on different machines is fantastic, because whenever needed you can add a new node to your cluster and start new instances of your app. All these instances will connect to the same mongrel2, and the requests will be load-balanced among all instances in a round-robin policy.


wsgid is a project I developed to make possible to run your WSGI apps with mongrel2 webserver. wsgid is the brifge between mongrel2 and the WSGI specification (PEP-333), this means that just by conforming with the WSGI spec your app is ready to run with mongrel2+wsgid.

wsgid talks both mongrel2 and WSGI, also from now on your app will be a separated process, with it’s own PID and everything a process has. This brings you some advantages:

  • Can run as any user on your operating system;
  • As being a O.S process, is automatically submitted to all characteristcs and O.S process has, eg: bandwith limit, memory limits, CPU scheduling, etc;
  • Can run inside a chroot, in caso you are running untrusted code;
  • Many others.

Start new instances of your app is as easy as:

   $ wsgid --app-path=/path/to/wsgid-app-folder/ --recv=tcp:// --send=tcp://

I this very simple example we are connecting to a ØMQ endponit in same machine that the app will be running, but nothing prevents us from using –recv=tcp://, being this IP the address of another node on the cluster. Still in this example, the option –worker=4 starts 4 processes that will respond to requests for your app.

wsgid, key features

Besides facilitating the deployment of WSGI applications with mongrel2, wsgid also has other important features:


With this option you will be able to start any number of processes you want at once. That means you don’t need to run the same wsgid command 4 times if you want four instances, although you can do this without any problem. But this option gives you the possibility to do –workers=4, which gives you the same result.

keep alive

With the keep-alive option wsgid automatically restarts any process which has finished its execution. This means that with a call to wsgid with –workers=4 –keep-alive, wsgid will always keep 4 processes working for your application.

hot deploy

Whenever wsgid re-starts one of the processes, the code of your application is reloaded, after all is a new process being created. That means you can update the source code of your application and just SIGTERM all its workers, it will make  wsgid restart all workers, but this time already running the new source code.


wsgid can chroot to the location where the application is. This makes such application run in isolated, thus creating an environment a little safer (not entirely) if you are running untrusted code.

Plugable system for Application Loading

wsgid has a very simple but very powerful plugin sub-system . With it you can write your own application loader, in case wsgid is not able to load your WSGI app. With such a sub-system, it will be very simple to add support for other WSGI frameworks so that more applications can make use of this project.

That’s it! Hope you enjoyed the project, any feedback is more than welcome. To learn more about the project visit the official website:

But remember, use what works best for you, use what best serves you. I’m not saying that the solution mongrel2+wsgid is the best ever, I’m just saying that this combination is fantastic and should be considered whenever you are thinking of publishing a new WSGI application.

Just out of curiosity, the website is a django application and runs with wsgid.


2 Comentários

Acessando os sites que você quiser no trabalho

Esse post mostra uma (dentre várias) formas de burlar os diversos bloqueios impostos por algumas empresas no que diz respeito a acesso à internet. Veremos uma forma bem simples e eficiente de navegar em sites que supostamente não poderíamos estar vendo. =)

Leia o resto deste post »

, ,

14 Comentários

A Importância de programas que sabem usar a entrada/saída padrão: Solução do desafio

No último post deixei um desafio (que foi rapidamente resolvido já nos comentários) que era fazer uma cópia de um arquivo (que tinha sido compactado e depois dividido) para um disco com espaço suficiente para apenas uma cópia desse arquivo, ou seja, não poderíamos juntar as partes para só depois descompactar.

Nesse post vamos apresentar uma solução para o problema proposto.

Leia o resto deste post »

Deixe um comentário

O poder do pipe e a importância de programas de linha de comando que sabem usar entrada/saída padrão

A interface de linha de comando, na marioria daz vezes, causa medo nas pessoas. Não sei se é pela aparência meio bruta ou se é pelo fato de raramente você usar o mouse (sim, tem gente que não consegue imaginar um computador útil sem um mouse!!). O fato é que apesar da aparência a linha de comando possui um poder quase infinito.

O grande poder dessa interface está na possibilidade de combinar quaisquer comandos para que seja possível executar uma tarefa maior. Nesse post proponho um desafio para um problema que parece complicado. Imagine um arquivo de 10GB compactado e dividido em 5 partes de 2GB. Como gravar esse arquivo, já descompactado, em um disco que só tem exatos 10GB de espaço? Com a linha de comando é possível!

Leia o resto deste post »


6 Comentários

Como burlar limitações de conectividade impostas por hoteis e afins

Muitas vezes estamos em locais públicos e que oferecem conexão com a internet. Em alguns locais essa conexão é paga, em outros é de graça mas possui limite de tempo de conexão e em outros é paga e limita o tempo de conexão. Veremos nesse post uma forma de extender nosso tempo de conexão quando necessário.

Leia o resto deste post »

, ,

10 Comentários

Descobrindo o destino de um link malicioso sem se arriscar

Esse post passou pela minha cabeça quando recebi um email dizendo que eu havia recebido um convite para o novo orkut.

Olhando isso lembrei que existem provavelmente muitas pessoas que acabam acreditando nas promessas desses emails e acabam caindo na armadilha. Outras pessoas, mesmo tendo conhecimento para julgar que aquela seria uma mensagem falsa, acabam clicando nos links contidos nessas mensagens apenas por estarem usando um sistema operacional livre de vírus, mas se esquecem de que algumas páginas podem conter códigos maliciosos que afetam o navegador que estão usando, e esse sendo multi-plataforma pode acabar expondo o sistema operacional.

Nesse post veremos como saber o destino de um link contindo em uma dessas mensagens sem nos expor aos riscos de clicar e fazer com que o navegador faça o acesso e interprete a resposta.

Leia o resto deste post »

2 Comentários

Assembly vs. [coloque-sua-linguagem-de-programacao-favorita-aqui]

O termo versus dá uma idéia de briga. Parece que estou prestes a defender Assembly com unhas e dentes e dizer que é melhor do que qualquer outra coisa. Antes que você pense, isso não vai acontecer! =D O que vou mostrar aqui é apenas um comparativo que fiz há uns 4~5 anos atrás e que por algum motivo que eu ainda não sei qual, passou pela minha cabeça denovo recentemente.

Nessa época eu estava no quinto período e era monitor de Assembly na faculdade. Sim, eu fui monitor de assembly! E tem mais, nessa mesma época, empolgado com a monitoria, reescrevi o clássico snakeinteiramente em Assembly.

A idéia de fazer essa comparação (naquela época) veio porque eu estava aprendendo sobre linguagens compiladas e interpretadas. E todo mundo sabe que, na teoria um código implementado em uma linguagem interpretada não pode ser mais rápido do que esse mesmo código implementado em uma linguagem compilada.

Leia o resto deste post »

, ,

2 Comentários

Como aplicar formatação nos textos que você escreve no google talk

Update: Apenas mudança na formação. Texto justificado.

Nem todo mundo sabe, mas é possível aplicar efeitos aos textos enviados pelo google talk. Esses efeitos são:

  • Itálico
  • Negrito
  • Strike through

O que menos gente ainda sabe é como aplicar esses efeitos. =) Eu descobri como fazer por acaso (e não foi lendo o manual do google talk). Por várias vezes, lendo emails de listas de discussão de projetos vi emails usando caracteres especias para dar algum destaque às palavras do texto. Um caractere clássico é o *, usado quando queremos dar alguma ênfase ao termo escrito.

Leia o resto deste post »

Deixe um comentário

xargs: A ponte entre entrada padrão e a lista de parâmetros

Update: Apenas mudança na formatação. Texto justificado. Mudança no formato das figuras (jpg)

O xargs é um programa de linha de comando que transforma o conteúdo de sua entrada padrão na lista de parâmetros de um segundo comando, à sua escolha. Muito útil quando você tem um texto qualquer e, com cada parte desse texto, deseja executar um comando. Um exemplo clássico é o redimensionamento de uma quantidade muito grande imagens, ou a necessidade de baixar da rede uma lista de arquivos.

Leia o resto deste post »

, , ,

1 comentário