<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-7977789709139913287</id><updated>2012-02-17T04:54:48.584+01:00</updated><category term='linux'/><category term='apache'/><category term='console'/><category term='eee'/><category term='huawei'/><category term='Propolice'/><category term='wifi'/><category term='unix'/><category term='script'/><category term='mod_rewrite'/><category term='debian'/><category term='elf'/><category term='gcc'/><category term='FreeBSD'/><category term='rtld'/><category term='kvm'/><category term='bash'/><category term='xen'/><category term='svn'/><category term='ZFS'/><category term='asm'/><title type='text'>Technicals writings from JLH</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://bsdjlh.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7977789709139913287/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://bsdjlh.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Jeremie Le Hen</name><uri>http://www.blogger.com/profile/07863111280211011857</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_sP33YFnaRDk/R3BLYSjJ6_I/AAAAAAAAAAs/FMP6tQxYHHw/S220/DSC05747.JPG'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>17</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-7977789709139913287.post-4643462762278981577</id><published>2011-11-09T17:24:00.009+01:00</published><updated>2011-11-10T11:46:51.299+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mod_rewrite'/><category scheme='http://www.blogger.com/atom/ns#' term='apache'/><title type='text'>Apache mod_rewrite evilness (with dynamic vhosts and .htaccess rewrite rules)</title><content type='html'>At my new $job, we have a SVN repository for the websites we are maintaining.  We devised a workflow to work with it: each developer has one or more branches for himself.  The merge of their features is done in the trunk.  Once everything seems to work, we merge into the "preproduction" branch and finally in the "production" branch.&lt;br /&gt;&lt;br /&gt;On the developement web server, I wanted them to be able access every branch with their web browser.  Initially, there was a "svn.mywebsite.com" virtual host and each branch was accessible through an URL-path within it.  Unfortuntaly, for "historical" reason, the web site doesn't work correctly if set in an URL sub-directory (and we are currently writing a new version of this website, so we actually don't want to spend time fixing it).  I am therefore doomed to create a virtual host for each SVN trunk/tag/branch.&lt;br /&gt;&lt;br /&gt;Here is the relevant part of the initial configuration I wrote:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;VirtualHost *:80&amp;gt;&lt;br /&gt;    ServerName   svn.mywebsite.com&lt;br /&gt;    ServerAlias *.svn.mywebsite.com&lt;br /&gt;&lt;br /&gt;    DocumentRoot /var/empty&lt;br /&gt;&lt;br /&gt;    RewriteEngine on&lt;br /&gt;&lt;br /&gt;    RewriteCond %{HTTP_HOST} ^trunk\.svn\.mywebsite\.com$&lt;br /&gt;    RewriteRule $(.*)        /home/www-data/svn/project/trunk$1       [L]&lt;br /&gt;&lt;br /&gt;    RewriteCond %{HTTP_HOST} ^([^.]+).branches\.svn\.mywebsite\.com$&lt;br /&gt;    RewriteRule $(.*)        /home/www-data/svn/project/branches%1$1  [L]&lt;br /&gt;&lt;br /&gt;    RewriteCond %{HTTP_HOST} ^([^.]+).tags\.svn\.mywebsite\.com$&lt;br /&gt;    RewriteRule $(.*)        /home/www-data/svn/project/tags%1$1      [L]&lt;br /&gt;&lt;br /&gt;&amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;So far it's easy and it would have worked if there wasn't the following RewriteRule in the .htaccess at the root of the project:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;RewriteCond %{REQUEST_FILENAME} !-f&lt;br /&gt;RewriteCond %{REQUEST_FILENAME} !-d&lt;br /&gt;RewriteCond %{REQUEST_URI} !=/favicon.ico&lt;br /&gt;RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The problem with this rule is that if we request a "virtual URL" (which does not match a physical file in the hierarchy), index.php is called with the original URL in the query string, which results in an internal redirect within Apache.&lt;br /&gt;&lt;br /&gt;I save you from the RewriteLog, but let's say you try: &lt;tt&gt;http://trunk.svn.mywebsite.com/virtual-url&lt;/tt&gt;.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Initially the &lt;tt&gt;${REQUEST_URI}&lt;/tt&gt; is "/virtual-url".  The vhost rewrite rules are applied, which redirect to the filesystem path: &lt;tt&gt;/home/www-data/svn/project/trunk/virtual-url&lt;/tt&gt;.&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;Then we reach the per-directory (.htaccess) rewrite rules which, given the file doesn't exist, redirect to &lt;tt&gt;/home/www-data/svn/project/trunk/index.php&lt;/tt&gt; with the following query string &lt;tt&gt;q=virtual-url&lt;/tt&gt;.&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;Here is the first trap: an internal redirect is done within Apache, which restarts the rewrite rules evaluation from the beginning, with &lt;tt&gt;${REQUEST_URI}&lt;/tt&gt; set to &lt;tt&gt;/home/www-data/svn/project/trunk/index.php&lt;/tt&gt;, while the &lt;tt&gt;${HTTP_HOST}&lt;/tt&gt; is still the same.  So the directory will be prepended twice if we do not put a safeguard: basically checking that &lt;tt&gt;$REQUEST_URI&lt;/tt&gt; doesn't contain &lt;tt&gt;/home/www-data/svn/project/&lt;/tt&gt;.&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;But the true evilness is here: &lt;b&gt;we cannot rewrite to a full filesystem path in a per-directory rewrite rule&lt;/b&gt;.  The subsequent internal redirect will invariably think that this is an URL path, that is it will try to serve a page as if you had requested: &lt;tt&gt;http://trunk.svn.mywebsite.com/home/www-data/svn/project/trunk/index.php&lt;/tt&gt;.  Because of the safeguard above, the dynamic vhost magic will not apply, and Apache will try to reach this file from the vhost's DocumentRoot and you will get a 404.&lt;br /&gt;&lt;br /&gt;The workaround for this is trick Apache into thinking the content of &lt;tt&gt;${REQUEST_URI}&lt;/tt&gt; is a full filesystem path if the latter looks like a filesystem path :-).  Contrary to the per-directory rewrite rules, the vhost rewrite rules are able to redirect to a full filesystem path.  So just match the whole content and redirect to it.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;VirtualHost *:80&amp;gt;&lt;br /&gt;    ServerName   svn.mywebsite.com&lt;br /&gt;    ServerAlias *.svn.mywebsite.com&lt;br /&gt;&lt;br /&gt;    DocumentRoot /var/empty&lt;br /&gt;&lt;br /&gt;    RewriteEngine on&lt;br /&gt;&lt;br /&gt;    RewriteRule ^(/home/www-data/svn/project/.*)       $1             [L]&lt;br /&gt;&lt;br /&gt;    RewriteCond %{HTTP_HOST} ^trunk\.svn\.mywebsite\.com$&lt;br /&gt;    RewriteRule $(.*)        /home/www-data/svn/project/trunk$1       [L]&lt;br /&gt;&lt;br /&gt;    RewriteCond %{HTTP_HOST} ^([^.]+).branches\.svn\.mywebsite\.com$&lt;br /&gt;    RewriteRule $(.*)        /home/www-data/svn/project/branches%1$1  [L]&lt;br /&gt;&lt;br /&gt;    RewriteCond %{HTTP_HOST} ^([^.]+).tags\.svn\.mywebsite\.com$&lt;br /&gt;    RewriteRule $(.*)        /home/www-data/svn/project/tags%1$1      [L]&lt;br /&gt;&lt;br /&gt;&amp;lt;/VirtualHost&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The first rewrite rule matches a &lt;tt&gt;${REQUEST_URI}&lt;/tt&gt; containing the a filesystem path.  This is not exactly a rewrite, this is just a trick to trigger the mod_rewrite evaluation of the substitution.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7977789709139913287-4643462762278981577?l=bsdjlh.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bsdjlh.blogspot.com/feeds/4643462762278981577/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7977789709139913287&amp;postID=4643462762278981577' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7977789709139913287/posts/default/4643462762278981577'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7977789709139913287/posts/default/4643462762278981577'/><link rel='alternate' type='text/html' href='http://bsdjlh.blogspot.com/2011/11/apache-modrewrite-evilness.html' title='Apache mod_rewrite evilness (with dynamic vhosts and .htaccess rewrite rules)'/><author><name>Jeremie Le Hen</name><uri>http://www.blogger.com/profile/07863111280211011857</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_sP33YFnaRDk/R3BLYSjJ6_I/AAAAAAAAAAs/FMP6tQxYHHw/S220/DSC05747.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7977789709139913287.post-8692107752825834949</id><published>2011-10-08T17:32:00.008+02:00</published><updated>2011-10-09T20:08:35.936+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ZFS'/><category scheme='http://www.blogger.com/atom/ns#' term='FreeBSD'/><title type='text'>Installing full-ZFS server at OVH</title><content type='html'>OVH is a french web hosting service in France, that provides dedicated servers (and many other things).  It is great because they offer an infrastructure which brings you low-cost but yet professional facilities for less than 20 euros a month.  They provide Linux, FreeBSD and even Solaris: you can of course ask for your server to be installed with this but the real great thing is the netboot feature that will boot the same OS as the one which is installed on your server.&lt;br /&gt;&lt;br /&gt;The FreeBSD installation is UFS based.  It is nonetheless possible to migrate in on ZFS with little wizardry.  It is best the do this with a fresh installation, but is should be possible to do so as long as you use less than the half of you hard drive.  However, you have to move everything into the first physical half of the hard drive (it is easier when the server has just been installed, as you just have to keep the root partition).&lt;br /&gt;&lt;br /&gt;The procedure is the following: You move all your data in a (small) transient partition at the end of the disk.  Then a ZFS partition is created at the beginning of the disk, and again move your data there.  You can then destroy the transient partition and create a physical swap partition in its stead.  Indeed, although FreeBSD can use a ZFS vdev as swap, it cannot dump to it.  Therefore this procedure creates a real partition for swap.&lt;br /&gt;&lt;br /&gt;Your FreeBSD is booted.  Go to the OVH manager and in the "Netboot" page and select "rescue-pro".  Then reboot you server, wait for a while, you should receive a mail with the root password of your netbooted server.&lt;br /&gt;&lt;br /&gt;Once connected on it, create a partition large enough to hold all your data at the end of the hard drive.  We will copy them here in order to be able to install the ZFS partition at the beginning of the disk.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;rescue-bsd# fdisk /dev/ad0&lt;br /&gt;******* Working on device /dev/ad0 *******&lt;br /&gt;[...]&lt;br /&gt;&lt;br /&gt;Media sector size is 512&lt;br /&gt;Warning: BIOS sector numbering starts with sector 1&lt;br /&gt;Information from DOS bootblock is:&lt;br /&gt;The data for partition 1 is:&lt;br /&gt;sysid 165 (0xa5),(FreeBSD/NetBSD/386BSD)&lt;br /&gt;    start 63, size 488397105 (238475 Meg), flag 80 (active)&lt;br /&gt;        beg: cyl 1/ head 0/ sector 1;&lt;br /&gt;        end: cyl 655/ head 0/ sector 63&lt;br /&gt;The data for partition 2 is:&lt;br /&gt;&lt;UNUSED&gt;&lt;br /&gt;The data for partition 3 is:&lt;br /&gt;&lt;UNUSED&gt;&lt;br /&gt;The data for partition 4 is:&lt;br /&gt;&lt;UNUSED&gt;&lt;br /&gt;&lt;br /&gt;rescue-bsd# bsdlabel /dev/ad0s1&lt;br /&gt;# /dev/ad0s1:&lt;br /&gt;8 partitions:&lt;br /&gt;#        size   offset    fstype   [fsize bsize bps/cpg]&lt;br /&gt;  a: 20971520        0    4.2BSD     4096 16384    64 &lt;br /&gt;  b:  2097152 20971520      swap                    &lt;br /&gt;  c: 488397105        0    unused        0     0         # "raw" part, don't edit&lt;br /&gt;  d: 465328433 23068672    4.2BSD        0     0     0 &lt;br /&gt;&lt;br /&gt;rescue-bsd# mount /dev/ad0s1a /mnt/&lt;br /&gt;rescue-bsd# df -k /mnt/&lt;br /&gt;Filesystem 1024-blocks   Used   Avail Capacity  Mounted on&lt;br /&gt;/dev/ad0s1a    10154158 495960 8845866     5%    /mnt&lt;br /&gt;rescue-bsd# umount /mnt/&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;We have a swap partition on /dev/ad0s1b and an empty filesystem on /dev/ad0s1d.  The root partition only uses 500 MB.  We are going to create a partition at the end of the disk to copy the content of it.  Thus this partition must be large enough.  But this partition should also large enough to hold the swap partition you want on your system eventually.  In this example I want 1 GB of swap.&lt;br /&gt;&lt;br /&gt;So let's create a 1 GB partition at the end of the disk.  1 GB is 1024*1024*1024/512 = 2097152 sectors.  The disk is 488397105 sectors wide, so the partition would start at 488397105 - 2097152 = 486299953.  A good practice is to align the partition to a 4 KB boundary: 486299953 % 4096 = 2353, so we will use 486299953 - 2353 = 486297600 for first sector of the partition.  Given the end of the disk is 488397105, the partition size will be 488397105 - 486297600 = 2099505 sectors.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;rescue-bsd# bsdlabel /dev/ad0s1 &gt; /tmp/ad0.label&lt;br /&gt;rescue-bsd# vi /tmp/ad0.label&lt;br /&gt;[...]&lt;br /&gt;&lt;br /&gt;rescue-bsd# cat /tmp/ad0.label&lt;br /&gt;# /dev/ad0s1:&lt;br /&gt;8 partitions:&lt;br /&gt;#        size   offset    fstype   [fsize bsize bps/cpg]&lt;br /&gt;  a: 20971520         0    4.2BSD     4096 16384    64 &lt;br /&gt;  b: 2099505  486297600    4.2BSD     4096 16384    64              &lt;br /&gt;  c: 488397105        0    unused        0     0         # "raw" part, don't edit&lt;br /&gt;&lt;br /&gt;rescue-bsd# bsdlabel -R /dev/ad0s1 /tmp/ad0.label&lt;br /&gt;rescue-bsd# newfs /dev/ad0s1b &lt;br /&gt;/dev/ad0s1b: 1025.1MB (2099504 sectors) block size 16384, fragment size 2048&lt;br /&gt;        using 6 cylinder groups of 183.77MB, 11761 blks, 23552 inodes.&lt;br /&gt;super-block backups (for fsck -b #) at:&lt;br /&gt; 160, 376512, 752864, 1129216, 1505568, 1881920&lt;br /&gt;&lt;br /&gt;rescue-bsd# mount /dev/ad0s1b /mnt&lt;br /&gt;rescue-bsd# cd /mnt&lt;br /&gt;rescue-bsd# dump -0af - /dev/ad0s1a | restore -rf -&lt;br /&gt;  DUMP: Date of this level 0 dump: Sat Oct  8 10:07:58 2011&lt;br /&gt;  DUMP: Date of last level 0 dump: the epoch&lt;br /&gt;  DUMP: Dumping /dev/ad0s1a to standard output&lt;br /&gt;  DUMP: mapping (Pass I) [regular files]&lt;br /&gt;  DUMP: mapping (Pass II) [directories]&lt;br /&gt;  DUMP: estimated 499089 tape blocks.&lt;br /&gt;  DUMP: dumping (Pass III) [directories]&lt;br /&gt;  DUMP: dumping (Pass IV) [regular files]&lt;br /&gt;[...]&lt;br /&gt;  DUMP: finished in 131 seconds, throughput 3816 KBytes/sec&lt;br /&gt;  DUMP: DUMP IS DONE&lt;br /&gt;rescue-bsd# cd&lt;br /&gt;rescue-bsd# umount /mnt&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now we can remove the first partition and create a big ZFS partition spanning from the beginning of the disk to the beginning of the second partition we have just created.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;rescue-bsd# gpart show ad0s1&lt;br /&gt;=&gt;        0  488397105  ad0s1  BSD  (233G)&lt;br /&gt;          0   20971520      1  freebsd-ufs  (10G)&lt;br /&gt;   20971520  465326080         - free -  (222G)&lt;br /&gt;  486297600    2099505      2  freebsd-ufs  (1.0G)&lt;br /&gt;&lt;br /&gt;rescue-bsd# gpart delete -i 1 ad0s1&lt;br /&gt;ad0s1a deleted&lt;br /&gt;rescue-bsd# gpart show ad0s1&lt;br /&gt;=&gt;        0  488397105  ad0s1  BSD  (233G)&lt;br /&gt;          0  486297600         - free -  (232G)&lt;br /&gt;  486297600    2099505      2  freebsd-ufs  (1.0G)&lt;br /&gt;&lt;br /&gt;rescue-bsd# gpart add -s 486297600 -t freebsd-zfs ad0s1&lt;br /&gt;ad0s1a added&lt;br /&gt;rescue-bsd# gpart show ad0s1&lt;br /&gt;=&gt;        0  488397105  ad0s1  BSD  (233G)&lt;br /&gt;          0  486297600      1  freebsd-zfs  (232G)&lt;br /&gt;  486297600    2099505      2  freebsd-ufs  (1.0G)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now let's create the ZFS pool.  But the OVH netboot only provides a read-only root filesystem, so we have to tell zpool(8) to put the cache file into /tmp (this file will be needed to import the pool at boot time).  We must also to tell the ZFS layer to temporary mount the pool into /mnt, so it won't try to mount the root of the pool as /.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;rescue-bsd# kldload opensolaris&lt;br /&gt;rescue-bsd# kldload zfs&lt;br /&gt;rescue-bsd# zpool create -o cachefile=/tmp/zpool.cache -o altroot=/mnt zroot /dev/ad0s1a&lt;br /&gt;rescue-bsd# zpool export zroot&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Install the various bootcodes.  The MBR bootcode should already be there anyway.  The ZFS bootcode is somewhat strange because it consists actually of two parts that must be written at different places (note that the first dd(1) uses /dev/ad0s1 while the second one uses /dev/ad0s1a):&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;rescue-bsd# gpart bootcode -b /boot/boot0 ad0&lt;br /&gt;bootcode written to ad0&lt;br /&gt;rescue-bsd# dd if=/boot/zfsboot of=/dev/ad0s1 count=1 bs=512&lt;br /&gt;rescue-bsd# dd if=/boot/zfsboot of=/dev/ad0s1b skip=1 seek=1024 bs=512&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Then re-import the pool with the same options used during its creation and create the datasets for the base filesystem (I'm using the same layout as described on the FreeBSD wiki):&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;rescue-bsd# zpool import -o cachefile=/tmp/zpool.cache -o altroot=/mnt zroot &lt;br /&gt;rescue-bsd# zfs set checksum=fletcher4 zroot&lt;br /&gt;rescue-bsd# zfs set mountpoint=none zroot&lt;br /&gt;rescue-bsd# zfs create -o mountpoint=/ zroot/rootfs&lt;br /&gt;rescue-bsd# zpool set bootfs=zroot/rootfs zroot&lt;br /&gt;rescue-bsd# zfs create -o compression=on -o exec=on -o setuid=off zroot/rootfs/tmp&lt;br /&gt;rescue-bsd# chmod 1777 /mnt/tmp/&lt;br /&gt;rescue-bsd# zfs create zroot/rootfs/usr&lt;br /&gt;rescue-bsd# zfs create zroot/rootfs/usr/home&lt;br /&gt;rescue-bsd# ln -s /usr/home /mnt/home&lt;br /&gt;rescue-bsd# zfs create -o compression=lzjb -o setuid=off zroot/rootfs/usr/ports&lt;br /&gt;rescue-bsd# zfs create -o compression=off -o exec=off -o setuid=off zroot/rootfs/usr/ports/distfiles&lt;br /&gt;rescue-bsd# zfs create -o compression=off -o exec=off -o setuid=off zroot/rootfs/usr/ports/packages&lt;br /&gt;rescue-bsd# zfs create -o compression=lzjb -o exec=off -o setuid=off zroot/rootfs/usr/src&lt;br /&gt;rescue-bsd# zfs create zroot/rootfs/var&lt;br /&gt;rescue-bsd# zfs create -o compression=lzjb -o exec=off -o setuid=off zroot/rootfs/var/crash&lt;br /&gt;rescue-bsd# zfs create -o exec=off -o setuid=off zroot/rootfs/var/db&lt;br /&gt;rescue-bsd# zfs create -o compression=lzjb -o exec=on -o setuid=off zroot/rootfs/var/db/pkg&lt;br /&gt;rescue-bsd# zfs create -o exec=off -o setuid=off zroot/rootfs/var/empty&lt;br /&gt;rescue-bsd# zfs create -o compression=lzjb -o exec=off -o setuid=off zroot/rootfs/var/log&lt;br /&gt;rescue-bsd# zfs create -o compression=gzip -o exec=off -o setuid=off zroot/rootfs/var/mail&lt;br /&gt;rescue-bsd# zfs create -o exec=off -o setuid=off zroot/rootfs/var/run&lt;br /&gt;rescue-bsd# zfs create -o compression=lzjb -o exec=on -o setuid=off zroot/rootfs/var/tmp&lt;br /&gt;rescue-bsd# chmod 1777 /mnt/var/tmp&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Note that I've activated compression on some datasets as in the FreeBSD wiki, but on a low-end box with little CPU power, I advise to turn it off.&lt;br /&gt;&lt;br /&gt;Now let's copy our data to the ZFS partition.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;rescue-bsd# mount /dev/ad0s1b /media&lt;br /&gt;rescue-bsd# cd /media&lt;br /&gt;rescue-bsd# find . | cpio -dump /mnt/&lt;br /&gt;rescue-bsd# cd&lt;br /&gt;rescue-bsd# umount /media&lt;br /&gt;rescue-bsd# zfs set readonly=on zroot/rootfs/var/empty&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Note that cpio(1) does not handle file flags set by chflags(8).  Your system will be able to boot, but some security seatbelt won't be here until you perform an installworld.&lt;br /&gt;&lt;br /&gt;Let's create the swap partition instead of the transient UFS filesystem:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;rescue-bsd# gpart show ad0s1&lt;br /&gt;=&gt;        0  488397105  ad0s1  BSD  (233G)&lt;br /&gt;          0  486297600      1  freebsd-zfs  (232G)&lt;br /&gt;  486297600    2099505      2  freebsd-ufs  (1.0G)&lt;br /&gt;&lt;br /&gt;rescue-bsd# gpart delete -i 2 ad0s1&lt;br /&gt;ad0s1b deleted&lt;br /&gt;rescue-bsd# gpart add -t freebsd-swap ad0s1&lt;br /&gt;ad0s1b added&lt;br /&gt;rescue-bsd# gpart show ad0s1&lt;br /&gt;=&gt;        0  488397105  ad0s1  BSD  (233G)&lt;br /&gt;          0  486297600      1  freebsd-zfs  (232G)&lt;br /&gt;  486297600    2099505      2  freebsd-swap  (1.0G)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now we need to configure the system to be able to boot from ZFS:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;rescue-bsd# echo 'zfs_load="YES"' &gt; /mnt/boot/loader.conf&lt;br /&gt;rescue-bsd# echo 'vfs.root.mountfrom="zfs:zroot/rootfs"' &gt;&gt; /mnt/boot/loader.conf&lt;br /&gt;rescue-bsd# cp /tmp/zpool.cache /mnt/boot/zfs/&lt;br /&gt;rescue-bsd# vi /mnt/etc/fstab&lt;br /&gt;[...]&lt;br /&gt;rescue-bsd# cat /mnt/etc/fstab&lt;br /&gt;# Device                Mountpoint      FStype  Options         Dump    Pass#&lt;br /&gt;/dev/ad0s1b             none            swap            sw      0       0&lt;br /&gt;proc                    /proc           procfs  rw              0       0&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Et voilà!  You can reboot your server (don't forget to deactivate netbooting from the OVH web interface).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7977789709139913287-8692107752825834949?l=bsdjlh.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bsdjlh.blogspot.com/feeds/8692107752825834949/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7977789709139913287&amp;postID=8692107752825834949' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7977789709139913287/posts/default/8692107752825834949'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7977789709139913287/posts/default/8692107752825834949'/><link rel='alternate' type='text/html' href='http://bsdjlh.blogspot.com/2011/10/installing-full-zfs-server-at-ovh.html' title='Installing full-ZFS server at OVH'/><author><name>Jeremie Le Hen</name><uri>http://www.blogger.com/profile/07863111280211011857</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_sP33YFnaRDk/R3BLYSjJ6_I/AAAAAAAAAAs/FMP6tQxYHHw/S220/DSC05747.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7977789709139913287.post-942800935176990938</id><published>2011-06-30T12:18:00.012+02:00</published><updated>2011-07-01T17:54:02.453+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='FreeBSD'/><category scheme='http://www.blogger.com/atom/ns#' term='console'/><title type='text'>Configuring FreeBSD with dual console</title><content type='html'>This post is short as I intend to use it more as a reminder than a full-fledged article.&lt;br /&gt;&lt;br /&gt;As an introduction for the un-educated reader, here is a simple paste of the &lt;tt&gt;boot(8)&lt;/tt&gt; manpage:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;   By default, a three-stage bootstrap is employed, and control is automati-&lt;br /&gt;   cally passed from the boot blocks (bootstrap stages one and two) to a&lt;br /&gt;   separate third-stage bootstrap program, loader(8).  This third stage pro-&lt;br /&gt;   vides more sophisticated control over the booting process than it is pos-&lt;br /&gt;   sible to achieve in the boot blocks, which are constrained by occupying&lt;br /&gt;   limited fixed space on a given disk or slice.&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;In summary: boot0 -&gt; boot2 -&gt; loader -&gt; kernel&lt;br /&gt;&lt;br /&gt;The first stage (boot0) cannot be configured, as the code as to fit in 512 bytes.  It will simply use the default system console (the screen).&lt;br /&gt;&lt;br /&gt;However the following things can be configured more or less independently:&lt;br /&gt;- boot2 (stage 2);&lt;br /&gt;- &lt;tt&gt;loader(8)&lt;/tt&gt; (stage 3);&lt;br /&gt;- the kernel;&lt;br /&gt;- &lt;tt&gt;login(8)&lt;/tt&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Configuring boot2&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;boot2 is configured through &lt;tt&gt;/boot.config&lt;/tt&gt;.  This file contains the flags documented in &lt;tt&gt;boot(8)&lt;/tt&gt;, as though they were given on the boot2 prompt.  Therefore if you want to see boot2 output on both your screen and the serial console, you have to put "-D" in it.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;shell# cat /boot.config&lt;br /&gt;-D&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Configuring &lt;tt&gt;loader(8)&lt;/tt&gt;&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;&lt;tt&gt;loader(8)&lt;/tt&gt; is configured through &lt;tt&gt;/boot/loader.conf&lt;/tt&gt;.  The &lt;tt&gt;console&lt;/tt&gt; variable can be set either "vidconsole", "comconsole" or "vidconsole,comconsole" to have both "comconsole,vidconsole" works too, we will see the difference later)&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;shell# grep ^console /boot/loader.conf&lt;br /&gt;console="vidconsole,comconsole"&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Configuring the kernel&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;&lt;tt&gt;/boot/loader.conf&lt;/tt&gt; also contains variables that will set kenv variables, which will define the kernel behaviour.  See this comment in &lt;tt&gt;/boot/defaults/loader.conf&lt;/tt&gt;:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;##############################################################&lt;br /&gt;###  Kernel settings  ########################################&lt;br /&gt;##############################################################&lt;br /&gt;&lt;br /&gt;# The following boot_ variables are enabled by setting them to any value.&lt;br /&gt;# Their presence in the kernel environment (see kenv(1)) has the same&lt;br /&gt;# effect as setting the given boot flag (see boot(8)).&lt;br /&gt;&lt;br /&gt;#boot_askname=""        # -a: Prompt the user for the name of the root device&lt;br /&gt;#boot_cdrom=""          # -C: Attempt to mount root file system from CD-ROM&lt;br /&gt;#boot_ddb=""            # -d: Instructs the kernel to start in the DDB debugger&lt;br /&gt;#boot_dfltroot=""       # -r: Use the statically configured root file system&lt;br /&gt;#boot_gdb=""            # -g: Selects gdb-remote mode for the kernel debugger&lt;br /&gt;#boot_multicons=""      # -D: Use multiple consoles&lt;br /&gt;#boot_mute=""           # -m: Mute the console&lt;br /&gt;#boot_pause=""          # -p: Pause after each line during device probing&lt;br /&gt;#boot_serial=""         # -h: Use serial console&lt;br /&gt;#boot_single=""         # -s: Start system in single-user mode&lt;br /&gt;#boot_verbose=""        # -v: Causes extra debugging information to be printed&lt;br /&gt;#init_path="/sbin/init:/sbin/oinit:/sbin/init.bak:/rescue/init:/stand/sysinstall"&lt;br /&gt;                      # Sets the list of init candidates&lt;br /&gt;#init_shell="/bin/sh"   # The shell binary used by init(8).&lt;br /&gt;#init_script=""         # Initial script to run by init(8) before chrooting.&lt;br /&gt;#init_chroot=""         # Directory for init(8) to chroot into.&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;So basically, the kernel defaults to use the screen only, but you can override this by setting the &lt;tt&gt;boot_multicons&lt;/tt&gt; variable:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;shell# grep ^boot_multicons /boot/loader.conf&lt;br /&gt;boot_multicons="YES"&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;How the whole stuff works&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;Actually when you configure one stage, subsequent stages will use the same settings unless configured to do differently.  So in the end you just have to configure boot2.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Userland output&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;Contrary to the other parts, userland boot output can only be sent to one device at time.  Even when configured with the above settings, the userland boot output will only appear on screen.&lt;br /&gt;&lt;br /&gt;Actually, the kernel will pick the first entry from the &lt;tt&gt;console&lt;/tt&gt; kenv variable to sent userland output to.  So if you are not often behind the screen and you prefer to see the userland boot output on the serial console:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;shell# grep ^console /boot/loader.conf&lt;br /&gt;console="comconsole,vidconsole"&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Configuring &lt;tt&gt;login(8)&lt;/tt&gt;&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;Not seeing the userland boot output on one console or the other doesn't mean it is unusable.  FreeBSD is configured by default to spawn a login: prompt on the screen.  You can easily configure it to spawn another one one the serial console, as explained in &lt;a href="http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/serialconsole-setup.html"&gt;this chapter on the handbook&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;shell# grep ttyu0 /etc/ttys&lt;br /&gt;ttyu0   "/usr/libexec/getty std.9600"   dialup  on secure&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;That's all.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7977789709139913287-942800935176990938?l=bsdjlh.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bsdjlh.blogspot.com/feeds/942800935176990938/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7977789709139913287&amp;postID=942800935176990938' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7977789709139913287/posts/default/942800935176990938'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7977789709139913287/posts/default/942800935176990938'/><link rel='alternate' type='text/html' href='http://bsdjlh.blogspot.com/2011/06/configuring-freebsd-with-dual-console.html' title='Configuring FreeBSD with dual console'/><author><name>Jeremie Le Hen</name><uri>http://www.blogger.com/profile/07863111280211011857</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_sP33YFnaRDk/R3BLYSjJ6_I/AAAAAAAAAAs/FMP6tQxYHHw/S220/DSC05747.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7977789709139913287.post-1350706051950470077</id><published>2010-06-02T18:03:00.019+02:00</published><updated>2011-07-01T17:54:29.574+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='debian'/><category scheme='http://www.blogger.com/atom/ns#' term='kvm'/><category scheme='http://www.blogger.com/atom/ns#' term='console'/><title type='text'>Debian KVM console on a headless server</title><content type='html'>At work I use a Debian KVM with an encrypted root filesystem as a workstation (our physical workstations run Windows) running on a headless server.  This means that I have to use the QEMU' VNC console to enter the password for the root filesystem very early in the boot process.&lt;br /&gt;&lt;br /&gt;Unfortunately VNC is unsecure and anyway QEMU only binds VNC on 127.0.0.1.  It would be easy to create an SSH tunnel, but this is administratively prohibited here and it is cumbersome to temporarily modify &lt;code&gt;sshd_config(5)&lt;/code&gt; each time.  So I tried a Netfilter DNAT rule as a workaround but Linux' network stack contains a very annoying line of code which checks that packets destined 127.0.0.1 comes from 127.0.0.1 as well.  If you see some logs like this, you have probably been biten by it too:&lt;br /&gt;&lt;pre&gt;Jun  2 18:14:20 srv kernel: martian destination 127.0.0.1 from 10.1.2.2, dev br0&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;So I gave up VNC and configured the KVM domain to use the serial port like any other headless server.&lt;br /&gt;&lt;br /&gt;Supposedly your VM is already running so we will make the changes here first.  There are three things to be told to use the serial console, which are in time-order:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;the bootloader (GRUB here);&lt;/li&gt;&lt;br /&gt;&lt;li&gt;the kernel;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;init(8)&lt;/code&gt; for the login prompt.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;On Debian, the first two things can be done easily through &lt;code&gt;/etc/default/grub&lt;/code&gt;.&lt;br /&gt;&lt;pre&gt;# Bootloader part.&lt;br /&gt;GRUB_TERMINAL=serial&lt;br /&gt;GRUB_SERIAL_COMMAND="serial --speed=9600 --unit=0 --word=8 --parity=no --stop=1"&lt;br /&gt;&lt;br /&gt;# Kernel command-line ("quiet" has no matter in our business):&lt;br /&gt;GRUB_CMDLINE_LINUX_DEFAULT="console=tty0 console=ttyS0,9600n8 quiet"&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Then regen the &lt;code&gt;grub.cfg&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;# upgrade-grub&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;If you do not use Debian, here is the relevant part of the generated &lt;code&gt;/boot/grub/grub.cfg&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;serial --speed=9600 --unit=0 --word=8 --parity=no --stop=1&lt;br /&gt;if terminal_input serial ; then true ; else&lt;br /&gt;  # For backward compatibility with versions of terminal.mod that don't&lt;br /&gt;  # understand terminal_input&lt;br /&gt;  terminal serial&lt;br /&gt;fi&lt;br /&gt;if terminal_output serial ; then true ; else&lt;br /&gt;  # For backward compatibility with versions of terminal.mod that don't&lt;br /&gt;  # understand terminal_output&lt;br /&gt;  terminal serial&lt;br /&gt;fi&lt;br /&gt;&lt;br /&gt;menuentry "Linux 2.6.32-trunk-amd64" {&lt;br /&gt;        insmod ext2&lt;br /&gt;        set root='(hd0,1)'&lt;br /&gt;        search --no-floppy --fs-uuid --set 9245a9e3-8ea5-4170-a19b-17d10051c107&lt;br /&gt;        echo    Loading Linux 2.6.32-trunk-amd64 ...&lt;br /&gt;        linux   /vmlinuz-2.6.32-trunk-amd64 root=/dev/mapper/vg0-root ro  console=tty0 console=ttyS0,9600n8 quiet&lt;br /&gt;        echo    Loading initial ramdisk ...&lt;br /&gt;        initrd  /initrd.img-2.6.32-trunk-amd64&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Regarding the login prompt on serial console, edit &lt;code&gt;/etc/inittab&lt;/code&gt;:&lt;br /&gt;&lt;pre&gt;T0:23:respawn:/sbin/getty -L ttyS0 9600 vt100&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Now your VM is configured, let's configure your KVM domain.  Dump the configuration of your vm, and change the &lt;code&gt;&amp;lt;serial&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;console&amp;gt;&lt;/code&gt; part to use a PTY (you can choose an arbitrary PTY, &lt;code&gt;/dev/pts/24&lt;/code&gt; here, as it seems to be redefined each time the VM is started).  Other interfaces are possible, like TCP, pipe, stdio... (see the &lt;a href="http://www.libvirt.org/formatdomain.html#elementsCharHostInterface"&gt;libvirt domain XML format&lt;/a&gt;) but I chose PTY because it can be easily attached using &lt;code&gt;screen(1)&lt;/code&gt; and cannot be easily snooped:&lt;br /&gt;&lt;pre&gt;# virsh dumpxml mykvm &gt; mykvm.xml&lt;br /&gt;# vi mykvm.xml&lt;br /&gt;   &amp;lt;serial type='pty'&amp;gt;&lt;br /&gt;     &amp;lt;source path='/dev/pts/24'/&amp;gt;&lt;br /&gt;     &amp;lt;target port='0'/&amp;gt;&lt;br /&gt;   &amp;lt;/serial&amp;gt;&lt;br /&gt;   &amp;lt;console type='pty' tty='/dev/pts/24'&amp;gt;&lt;br /&gt;     &amp;lt;source path='/dev/pts/24'/&amp;gt;&lt;br /&gt;     &amp;lt;target port='0'/&amp;gt;&lt;br /&gt;   &amp;lt;/console&amp;gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Then stop your VM, redefine your KVM domain and restart it:&lt;br /&gt;&lt;pre&gt;# virsh shutdown mykvm      # or run shutdown(8) inside the VM&lt;br /&gt;# virsh undefine mykvm&lt;br /&gt;# virsh define mykvm.xml&lt;br /&gt;# virsh start mykvm&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;You can attach the console using:&lt;br /&gt;&lt;pre&gt;# virsh console mykvm&lt;/pre&gt;&lt;br /&gt;To detach, use &lt;code&gt;Ctrl + $&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;If you attach quickly enough after starting it, you will even see the Grub menu!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7977789709139913287-1350706051950470077?l=bsdjlh.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bsdjlh.blogspot.com/feeds/1350706051950470077/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7977789709139913287&amp;postID=1350706051950470077' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7977789709139913287/posts/default/1350706051950470077'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7977789709139913287/posts/default/1350706051950470077'/><link rel='alternate' type='text/html' href='http://bsdjlh.blogspot.com/2010/06/debian-kvm-console-on-headless-server.html' title='Debian KVM console on a headless server'/><author><name>Jeremie Le Hen</name><uri>http://www.blogger.com/profile/07863111280211011857</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_sP33YFnaRDk/R3BLYSjJ6_I/AAAAAAAAAAs/FMP6tQxYHHw/S220/DSC05747.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7977789709139913287.post-1407990278571056543</id><published>2010-05-24T23:19:00.007+02:00</published><updated>2010-05-24T23:57:41.179+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='wifi'/><title type='text'>Quick n' Dirty Linux WPA-PSK Wireless AP</title><content type='html'>On saturday evening, there was a party at home.  One of the guests poured her glass of champagne on the ADSL modem lended by my ISP.  Undoubtly it wasn't champagne-proof.  I have about a week to wait before getting a new one.  Fortunately I have my 3G connection but only one person can use it at a given time... and we are two at home.  So I have created a very quick and dirty access-point to share my 3G connection.  This post has two purpose: record how I did it and show how it eventually turned out to be really easy.  Ironically, it was more difficult to configure a new wireless connection on Windows XP than creating the AP.&lt;br /&gt;&lt;br /&gt;I am assuming you are running mac80211 wireless stack, which is standard from recent kernels 2.6.30+).  You will need &lt;a href="http://hostap.epitest.fi/hostapd/"&gt;hostapd&lt;/a&gt; and &lt;a href="http://www.isc.org/software/dhcp"&gt;ISC's DHCPd&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;First set up your wireless interface as you would with any other wired interface:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;# ifconfig wlan0 inet 192.168.10.1 netmask 0xffffff00 up&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Next, configure &lt;tt&gt;/etc/hostapd/hostapd.conf&lt;/tt&gt;:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;driver=nl80211&lt;br /&gt;interface=wlan0&lt;br /&gt;channel=13&lt;br /&gt;ssid=3g2wifi&lt;br /&gt;auth_algs=1&lt;br /&gt;wpa=1&lt;br /&gt;wpa_passphrase=XXXXXXXX&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;And run it:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;# hostapd /etc/hostapd/hostapd.conf&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;From now on, you can configure a smartphone or another computer with this wireless network and see DHCP traffic when using &lt;tt&gt;tcpdump -ni wlan0&lt;/tt&gt;.  You may enable debugging with hostapd's &lt;tt&gt;-d&lt;/tt&gt; flag if it doesn't work.&lt;br /&gt;&lt;br /&gt;Next step is to provide connectivity to the Internet through 3G (interface ppp0).  We have to masquerade the computers behind the access-point (I assume there are no filtering rules):&lt;br /&gt;&lt;code&gt;&lt;br /&gt;# iptables -t nat -A POSTROUTING -s 192.168.10.0/24 -o ppp0 -j MASQUERADE&lt;br /&gt;# sysctl net.ipv4.conf.all.forwarding=1&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Here you can manually configure the IPv4 layer on another computer, setting the DNS servers to the ones provided by you 3G provider, and it should work.&lt;br /&gt;&lt;br /&gt;But the sugar on the cake would be to have a DHCP server, to minimize manual configuration.  This is straightforward.  Here is my &lt;tt&gt;/etc/dhcp3/dhcpd.conf&lt;/tt&gt; (note that I used Google's open DNS resolvers for example purpose):&lt;br /&gt;&lt;code&gt;&lt;br /&gt;subnet 192.168.10.0 netmask 255.255.255.0 {&lt;br /&gt;  range 192.168.10.20 192.168.10.30;&lt;br /&gt;  option routers 192.168.10.1;&lt;br /&gt;  option domain-name-servers 4.4.4.4, 4.4.8.8;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Start the DHCP server:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;# dhcpd3 -cf /etc/dhcp3/dhcpd.conf wlan0&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;And voila!  Now good luck if you have to configure a Windows 7 computer to use this connection :).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7977789709139913287-1407990278571056543?l=bsdjlh.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bsdjlh.blogspot.com/feeds/1407990278571056543/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7977789709139913287&amp;postID=1407990278571056543' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7977789709139913287/posts/default/1407990278571056543'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7977789709139913287/posts/default/1407990278571056543'/><link rel='alternate' type='text/html' href='http://bsdjlh.blogspot.com/2010/05/quick-n-dirty-linux-wpa-psk-wireless-ap.html' title='Quick n&apos; Dirty Linux WPA-PSK Wireless AP'/><author><name>Jeremie Le Hen</name><uri>http://www.blogger.com/profile/07863111280211011857</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_sP33YFnaRDk/R3BLYSjJ6_I/AAAAAAAAAAs/FMP6tQxYHHw/S220/DSC05747.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7977789709139913287.post-4106009660797447591</id><published>2010-05-20T18:45:00.011+02:00</published><updated>2010-08-10T23:25:15.486+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='unix'/><category scheme='http://www.blogger.com/atom/ns#' term='script'/><title type='text'>column.sh - columizator</title><content type='html'>It has been a long time since I've last written on this blog.  I am indeed very busy by my work so I don't have much time to write.  Nonetheless a positive aspect of this is that I happen to write some tools for me to alleviate some tasks.&lt;br /&gt;&lt;br /&gt;I am pretty sure that many if not all of you have already been annoyed by the output format such as vmstat(8), iostat(8), ...  They are great commands because they produce very valuable information but they are often very difficult to read, especially on busy servers when you need them most, because of the misalignment.  We cannot blame them because it is the Unix way of doing thing: do one thing and do it well.  It's not their job to pretty print the output.  The "&lt;tt&gt;column&lt;/tt&gt;" script exposed here will realign the output for you.&lt;br /&gt;&lt;br /&gt;This command acts like a standard Unix command: it may be used alone or as a filter.  It takes one mandatory argument, namely a keyword that will be used to recognize the &amp;laquo;caption&amp;raquo; line.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;jlehen@warg:~$ ./column -h&lt;br /&gt;Pretty-print columns, for iostat or vmstat.&lt;br /&gt;OS: All.&lt;br /&gt;&lt;br /&gt;Usage: column [-g] &lt;keyword&gt;&lt;br /&gt;&lt;br /&gt;Keyword is used to identify the caption line.  This may be an&lt;br /&gt;awk/nawk regex (thus don't forget to escape "/").&lt;br /&gt;Options:&lt;br /&gt; -g     Change the output to what I called "giant mode".&lt;br /&gt;        This is useful for iostat with an awful lot of disks.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Let's take an example.  Here is a classical vmstat(8) output on a busy Solaris server:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;05:26:32   kthr      memory            page            disk          faults      cpu&lt;br /&gt;05:26:32   r b w   swap  free  re  mf pi po fr de sr m0 m1 m2 m1   in   sy   cs us sy id&lt;br /&gt;05:26:32   0 29 0 139019936 26258128 4776 17739 38816 8 0 0 0 4 4 4 0 29969 129465 33184 21 25 54&lt;br /&gt;05:26:33   0 40 0 138993232 26235120 5240 19492 47250 39 31 0 0 7 7 7 0 30665 133160 34489 23 25 51&lt;br /&gt;05:26:34   0 28 0 139002648 26230848 4878 18717 36828 16 16 0 0 3 3 3 0 31368 144148 35850 22 24 54&lt;br /&gt;05:26:35   1 26 0 138978136 26211456 4046 14760 30778 8 8 0 0 4 4 4 0 26295 158433 27845 20 20 61&lt;br /&gt;05:26:36   0 29 0 138980472 26212968 4469 15525 33361 23 16 0 0 4 4 4 0 25826 118810 27653 21 19 60&lt;br /&gt;05:26:37   0 22 0 139004424 26227824 4208 16734 29367 8 8 0 0 4 4 4 0 24879 122903 28154 23 19 58&lt;br /&gt;05:26:38   0 18 0 139010608 26232864 3958 15324 27984 0 0 0 0 2 2 2 0 22422 105347 23563 17 17 66&lt;br /&gt;05:26:39   0 25 0 139022192 26237584 4076 15124 27770 31 31 0 0 2 2 2 0 25046 115101 26467 17 17 65&lt;br /&gt;05:26:40   0 21 0 139035416 26248720 5205 15215 38873 0 0 0 0 1 1 1 0 26961 131668 28818 22 18 60&lt;br /&gt;05:26:41   0 17 0 139014056 26239552 5132 17257 31959 0 0 0 0 0 0 0 0 23780 116586 25043 18 19 63&lt;br /&gt;05:26:42   0 13 0 139028280 26250352 3661 17215 17719 23 16 0 0 3 3 3 0 22048 110885 23717 15 17 67&lt;br /&gt;05:26:43   0 11 0 138993472 26220968 3796 19241 16468 0 0 0 0 0 0 0 0 21640 115744 23173 18 15 66&lt;br /&gt;05:26:44   0 12 0 138972904 26199192 2607 14008 15327 8 8 0 0 2 2 2 0 20428 120489 21064 18 15 67&lt;br /&gt;05:26:45   0 11 0 138973008 26194376 2122 9228 21017 23 23 0 0 5 5 5 0 24543 123981 25423 20 16 64&lt;br /&gt;05:26:46   2 12 0 138977112 26194960 1929 12010 23333 0 0 0 0 1 1 1 0 32145 144927 34596 26 16 59&lt;br /&gt;05:26:47   1 21 0 139032632 26240256 2361 11192 32759 16 16 0 0 2 2 2 0 36018 204602 39325 27 21 51&lt;br /&gt;05:26:49   1 25 0 139043840 26245952 2628 9895 35478 24 24 0 0 3 3 3 0 32645 136756 34903 26 20 54&lt;br /&gt;05:26:50   0 23 0 139043552 26246304 1942 9952 21395 0 0 0 0 0 0 0 0 24948 121252 25918 21 14 66&lt;br /&gt;05:26:51   0 19 0 139053752 26249176 1949 7929 26141 0 0 0 0 6 7 7 0 24490 113321 26220 19 14 67&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This is difficult to read because of the large amount of memory and swap.  Let's look at the same output now filtered through &lt;tt&gt;column&lt;/tt&gt; (keyword used to match caption line is "swap"):&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;05:26:32   kthr      memory            page            disk          faults      cpu&lt;br /&gt;05:26:32 r b  w swap      free     re   mf    pi    po  fr  de sr m0   m1  m2  m1 in    sy     cs    us sy id&lt;br /&gt;05:26:32 0 29 0 139019936 26258128 4776 17739 38816 8   0   0  0  4    4   4   0  29969 129465 33184 21 25 54&lt;br /&gt;05:26:33 0 40 0 138993232 26235120 5240 19492 47250 39  31  0  0  7    7   7   0  30665 133160 34489 23 25 51&lt;br /&gt;05:26:34 0 28 0 139002648 26230848 4878 18717 36828 16  16  0  0  3    3   3   0  31368 144148 35850 22 24 54&lt;br /&gt;05:26:35 1 26 0 138978136 26211456 4046 14760 30778 8   8   0  0  4    4   4   0  26295 158433 27845 20 20 61&lt;br /&gt;05:26:36 0 29 0 138980472 26212968 4469 15525 33361 23  16  0  0  4    4   4   0  25826 118810 27653 21 19 60&lt;br /&gt;05:26:37 0 22 0 139004424 26227824 4208 16734 29367 8   8   0  0  4    4   4   0  24879 122903 28154 23 19 58&lt;br /&gt;05:26:38 0 18 0 139010608 26232864 3958 15324 27984 0   0   0  0  2    2   2   0  22422 105347 23563 17 17 66&lt;br /&gt;05:26:39 0 25 0 139022192 26237584 4076 15124 27770 31  31  0  0  2    2   2   0  25046 115101 26467 17 17 65&lt;br /&gt;05:26:40 0 21 0 139035416 26248720 5205 15215 38873 0   0   0  0  1    1   1   0  26961 131668 28818 22 18 60&lt;br /&gt;05:26:41 0 17 0 139014056 26239552 5132 17257 31959 0   0   0  0  0    0   0   0  23780 116586 25043 18 19 63&lt;br /&gt;05:26:42 0 13 0 139028280 26250352 3661 17215 17719 23  16  0  0  3    3   3   0  22048 110885 23717 15 17 67&lt;br /&gt;05:26:43 0 11 0 138993472 26220968 3796 19241 16468 0   0   0  0  0    0   0   0  21640 115744 23173 18 15 66&lt;br /&gt;05:26:44 0 12 0 138972904 26199192 2607 14008 15327 8   8   0  0  2    2   2   0  20428 120489 21064 18 15 67&lt;br /&gt;05:26:45 0 11 0 138973008 26194376 2122 9228  21017 23  23  0  0  5    5   5   0  24543 123981 25423 20 16 64&lt;br /&gt;05:26:46 2 12 0 138977112 26194960 1929 12010 23333 0   0   0  0  1    1   1   0  32145 144927 34596 26 16 59&lt;br /&gt;05:26:47 1 21 0 139032632 26240256 2361 11192 32759 16  16  0  0  2    2   2   0  36018 204602 39325 27 21 51&lt;br /&gt;05:26:49 1 25 0 139043840 26245952 2628 9895  35478 24  24  0  0  3    3   3   0  32645 136756 34903 26 20 54&lt;br /&gt;05:26:50 0 23 0 139043552 26246304 1942 9952  21395 0   0   0  0  0    0   0   0  24948 121252 25918 21 14 66&lt;br /&gt;05:26:51 0 19 0 139053752 26249176 1949 7929  26141 0   0   0  0  6    7   7   0  24490 113321 26220 19 14 67&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The &lt;tt&gt;-g&lt;/tt&gt; option is meant to be used when the output is giant. For instance, when a system has a lot of disks, the iostat(8) command prints so much lines that the caption line is swept out of your terminal immediately..&lt;br /&gt;&lt;br /&gt;Let's take a sample output of iostat(8).  I won't show a lot of disks because it is worthless, but keep in mind than when there are tenths or hundreds of disks, the caption line no longer appear on the screen:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;                  extended device statistics&lt;br /&gt;device      r/s    w/s   kr/s   kw/s wait actv  svc_t  %w  %b&lt;br /&gt;md0         5.0    8.1   36.3  155.5  0.0  0.1    6.7   0   6&lt;br /&gt;md1         3.0    8.1   20.2  155.5  0.0  0.1    7.3   0   6&lt;br /&gt;md2         2.0    8.1   16.2  155.5  0.0  0.1    5.1   0   4&lt;br /&gt;md10        0.0    0.0    0.0    0.0  0.0  0.0    0.0   0   0&lt;br /&gt;md11        0.0    0.0    0.0    0.0  0.0  0.0    0.0   0   0&lt;br /&gt;md12        0.0    0.0    0.0    0.0  0.0  0.0    0.0   0   0&lt;br /&gt;md50        0.0    0.0    0.0    0.0  0.0  0.0    0.0   0   0&lt;br /&gt;md51        0.0    0.0    0.0    0.0  0.0  0.0    0.0   0   0&lt;br /&gt;md52        0.0    0.0    0.0    0.0  0.0  0.0    0.0   0   0&lt;br /&gt;md60        0.0    0.0    0.0    0.0  0.0  0.0    0.0   0   0&lt;br /&gt;md61        0.0    0.0    0.0    0.0  0.0  0.0    0.0   0   0&lt;br /&gt;md62        0.0    0.0    0.0    0.0  0.0  0.0    0.0   0   0&lt;br /&gt;ramdisk1    0.0    0.0    0.0    0.0  0.0  0.0    0.0   0   0&lt;br /&gt;sd0         0.0    0.0    0.0    0.0  0.0  0.0    0.0   0   0&lt;br /&gt;[...]&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Filtering with &lt;tt&gt;column -g actv&lt;/tt&gt; (using "device" would be useless as the very first line also contains it):&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;                  extended device statistics&lt;br /&gt;device:md0      r/s:5.0  w/s:8.1 kr/s:36.3  kw/s:155.5 wait:0.0 actv:0.1 svc_t:6.7   %w:0 %b:6&lt;br /&gt;device:md1      r/s:3.0  w/s:8.1 kr/s:20.2  kw/s:155.5 wait:0.0 actv:0.1 svc_t:7.3   %w:0 %b:6&lt;br /&gt;device:md2      r/s:2.0  w/s:8.1 kr/s:16.2  kw/s:155.5 wait:0.0 actv:0.1 svc_t:5.1   %w:0 %b:4&lt;br /&gt;device:md10     r/s:0.0  w/s:0.0 kr/s:0.0   kw/s:0.0   wait:0.0 actv:0.0 svc_t:0.0   %w:0 %b:0&lt;br /&gt;device:md11     r/s:0.0  w/s:0.0 kr/s:0.0   kw/s:0.0   wait:0.0 actv:0.0 svc_t:0.0   %w:0 %b:0&lt;br /&gt;device:md12     r/s:0.0  w/s:0.0 kr/s:0.0   kw/s:0.0   wait:0.0 actv:0.0 svc_t:0.0   %w:0 %b:0&lt;br /&gt;device:md50     r/s:0.0  w/s:0.0 kr/s:0.0   kw/s:0.0   wait:0.0 actv:0.0 svc_t:0.0   %w:0 %b:0&lt;br /&gt;device:md51     r/s:0.0  w/s:0.0 kr/s:0.0   kw/s:0.0   wait:0.0 actv:0.0 svc_t:0.0   %w:0 %b:0&lt;br /&gt;device:md52     r/s:0.0  w/s:0.0 kr/s:0.0   kw/s:0.0   wait:0.0 actv:0.0 svc_t:0.0   %w:0 %b:0&lt;br /&gt;device:md60     r/s:0.0  w/s:0.0 kr/s:0.0   kw/s:0.0   wait:0.0 actv:0.0 svc_t:0.0   %w:0 %b:0&lt;br /&gt;device:md61     r/s:0.0  w/s:0.0 kr/s:0.0   kw/s:0.0   wait:0.0 actv:0.0 svc_t:0.0   %w:0 %b:0&lt;br /&gt;device:md62     r/s:0.0  w/s:0.0 kr/s:0.0   kw/s:0.0   wait:0.0 actv:0.0 svc_t:0.0   %w:0 %b:0&lt;br /&gt;device:ramdisk1 r/s:0.0  w/s:0.0 kr/s:0.0   kw/s:0.0   wait:0.0 actv:0.0 svc_t:0.0   %w:0 %b:0&lt;br /&gt;device:sd0      r/s:0.0  w/s:0.0 kr/s:0.0   kw/s:0.0   wait:0.0 actv:0.0 svc_t:0.0   %w:0 %b:0&lt;br /&gt;[...]&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This nice script is available &lt;a href="http://jlh.chchile.org/column.sh"&gt;here&lt;/a&gt;.&lt;br /&gt;Beware that is used &lt;tt&gt;/bin/sh&lt;/tt&gt;.  If you want to use it on Solaris, use &lt;tt&gt;/bin/ksh&lt;/tt&gt; instead.  I have yet to find a shebang line that will work on *BSD, Linux and Solaris.  If you know one, contact me on &amp;lt; jeremie le-hen org &amp;gt; (up to you to but the "@" and "." where you think it best fits...).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7977789709139913287-4106009660797447591?l=bsdjlh.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bsdjlh.blogspot.com/feeds/4106009660797447591/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7977789709139913287&amp;postID=4106009660797447591' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7977789709139913287/posts/default/4106009660797447591'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7977789709139913287/posts/default/4106009660797447591'/><link rel='alternate' type='text/html' href='http://bsdjlh.blogspot.com/2010/05/columnsh-columizator.html' title='column.sh - columizator'/><author><name>Jeremie Le Hen</name><uri>http://www.blogger.com/profile/07863111280211011857</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_sP33YFnaRDk/R3BLYSjJ6_I/AAAAAAAAAAs/FMP6tQxYHHw/S220/DSC05747.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7977789709139913287.post-4204936594289039698</id><published>2009-02-18T12:40:00.016+01:00</published><updated>2009-06-22T16:43:52.595+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='bash'/><title type='text'>Bash prompt trick: cheap emulation of tcsh's pwd trailing component</title><content type='html'>I started Unix with Linux where Bash has always been the default shell, at least in my own reckoning.   Hence I've always been using Bash as I never found the necessity nor the motivation to really switch to another shell.&lt;br /&gt;&lt;br /&gt;When FreeBSD turned to be my favorite operating system, I had a chance to fiddle with tcsh.  One thing I really liked was the "%c" prompt sequence, a.k.a. "trailing component of the current working directory".  Basically, "%c02" in "/home/jlh/a/b" expands to something like "/&lt;2&gt;/a/b".  Since then, I've always missed this sequence in Bash, as "\w" often expands to something far too long and "\W" is often not enough.&lt;br /&gt;&lt;br /&gt;Therefore I implemented a function to mimic this behaviour in tcsh.  I devised it to only use builtins so as to be cheap (read inexpensive, not lousy).  Indeed, I think it would be really stupid to spawn many processes each time Enter is hit in my shell.  Here it is:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;traildir() {&lt;br /&gt;    local n=$1 dir=$2&lt;br /&gt;    local sl tildedir homelen shifted  traildir&lt;br /&gt;&lt;br /&gt;    sl=/&lt;br /&gt;    tildedir=${dir#$HOME}&lt;br /&gt;    if ! [[ "$tildedir" == "$dir" ]]; then&lt;br /&gt;            tildedir="~$tildedir"&lt;br /&gt;            sl=&lt;br /&gt;    fi&lt;br /&gt;&lt;br /&gt;    set -- ${HOME//\// }&lt;br /&gt;    homelen=$#&lt;br /&gt;&lt;br /&gt;    shifted=0&lt;br /&gt;    set -- ${tildedir//\// }&lt;br /&gt;    if [[ $# -gt $n ]]; then&lt;br /&gt;            shifted=$(($# - $n))&lt;br /&gt;            shift $shifted&lt;br /&gt;            [[ -z "$sl" ]] &amp;amp;&amp;amp; shifted=$(($shifted + $homelen - 1))&lt;br /&gt;            traildir="&lt;$shifted&gt;/$@"&lt;br /&gt;    else&lt;br /&gt;            traildir="$sl$@"&lt;br /&gt;    fi&lt;br /&gt;&lt;br /&gt;    echo ${traildir// /\/}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Then, you just have to set, for example:&lt;br /&gt;&lt;tt&gt;&lt;br /&gt;TRAILPWD=2&lt;br /&gt;export PS1='\u@\h:$(traildir $TRAILPWD $PWD) \#\$'&lt;br /&gt;&lt;/tt&gt;&lt;br /&gt;&lt;br /&gt;And that's it!  Ok it still forks a process each time you hit enter, but it's not possible to achieve it less expensively with Bash anyway.  Note that the example above uses a neat trick: if you need more trailing components in your prompt for your current task, just set TRAILPWD to the desired value.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Addendum on 2009/06/22&lt;/h3&gt;&lt;br /&gt;A smaller but less resilient version of this prompt is:&lt;br /&gt;&lt;tt&gt;&lt;br /&gt;export PS1='\u@\h:$(set -- ${PWD//\// }; n=$(($# - $TRAILPWD)); s=; [[ $n -le 0 ]] &amp;amp;&amp;amp; s=/ || shift $n; d="$@"; echo $s${d// /\/}) \#\$'&lt;br /&gt;&lt;/tt&gt;&lt;br /&gt;&lt;br /&gt;One advantage of this one is that is only relies on an environment variable, thus is inherited across forks.  This is useful for instance if you call bash through sudo(8) and you wish to use the same prompt.  This is impossible with the function-based prompt.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7977789709139913287-4204936594289039698?l=bsdjlh.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bsdjlh.blogspot.com/feeds/4204936594289039698/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7977789709139913287&amp;postID=4204936594289039698' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7977789709139913287/posts/default/4204936594289039698'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7977789709139913287/posts/default/4204936594289039698'/><link rel='alternate' type='text/html' href='http://bsdjlh.blogspot.com/2009/02/bash-prompt-trick-cheap-emulation-of.html' title='Bash prompt trick: cheap emulation of tcsh&apos;s pwd trailing component'/><author><name>Jeremie Le Hen</name><uri>http://www.blogger.com/profile/07863111280211011857</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_sP33YFnaRDk/R3BLYSjJ6_I/AAAAAAAAAAs/FMP6tQxYHHw/S220/DSC05747.JPG'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7977789709139913287.post-6816374174490433076</id><published>2008-12-10T14:52:00.004+01:00</published><updated>2008-12-10T16:34:25.614+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='huawei'/><category scheme='http://www.blogger.com/atom/ns#' term='eee'/><title type='text'>Get rid of Vodafone Mobile Connect Card driver for Linux</title><content type='html'>Back in August, &lt;a href="http://bsdjlh.blogspot.com/2008/08/debian-on-asus-eeepc-701-with-huawei.html"&gt;I explained&lt;/a&gt; why I switched from shipped Xandros to the Debian Eee blend.  I bought my EeePC with a 3G USB modem from Huawei:&lt;br /&gt;&lt;tt&gt;&lt;br /&gt;Bus 001 Device 003: ID 12d1:1003 Huawei Technologies Co., Ltd. E220 HSDPA Modem / E270 HSDPA/HSUPA Modem&lt;br /&gt;&lt;/tt&gt;&lt;br /&gt;Thanks to &lt;a href="https://forge.betavine.net/projects/vodafonemobilec/"&gt;Vodafone Mobile Connect Card driver for Linux&lt;/a&gt;, I could use it very easily.  But compared to the Asus dialer, it is way slow!  Between the time I click on the icon and the time I am connected, there is nearly two minutes because EeePC is not powerful enough to process quickly this bloated Python software.&lt;br /&gt;&lt;br /&gt;While inspecting this program, you will notice that it uses wvdial behind the scene:&lt;br /&gt;&lt;tt&gt;&lt;br /&gt;jlh      11626 11579  0 15:22 pts/5    00:00:00 /opt/vmc/bin/wvdial --config /tmp/VMC_uJJ0r/VMCYy5LXzwvdial.conf connect&lt;br /&gt;&lt;/tt&gt;&lt;br /&gt;Just copy the configuration file to wvdial.conf:&lt;br /&gt;&lt;tt&gt;&lt;br /&gt;[Dialer Defaults]&lt;br /&gt;&lt;br /&gt;Phone = *99***1#&lt;br /&gt;Username = slsfr&lt;br /&gt;Password = slsfr&lt;br /&gt;Stupid Mode = 1&lt;br /&gt;Dial Command = ATDT&lt;br /&gt;Check Def Route = on&lt;br /&gt;Dial Attempts = 3&lt;br /&gt;&lt;br /&gt;[Dialer connect]&lt;br /&gt;&lt;br /&gt;Modem = /dev/ttyUSB0&lt;br /&gt;Baud = 460800&lt;br /&gt;Init2 = ATZ&lt;br /&gt;Init3 = ATQ0 V1 E0 S0=0 &amp;amp;C1 &amp;amp;D2 +FCLASS=0&lt;br /&gt;Init4 = AT+CGDCONT=1,"IP","slsfr"&lt;br /&gt;ISDN = 0&lt;br /&gt;Modem Type = Analog Modem&lt;br /&gt;&lt;/tt&gt;&lt;br /&gt;&lt;br /&gt;But running wvdial with this configuration will only work if you have already entered the PIN code with Vodafone Mobile Connect Card driver for Linux.  I needed to find a way to automate this.  I quickly googled for a solution without luck, so I devised a way to do it myself.&lt;br /&gt;&lt;br /&gt;What I basically did was to use strace(1) on Vodafone Mobile Connect Card driver for Linux just when I entered my PIN code.  Then I looked for the PIN code itself in the output file and watched about so I could figure out the dialog with the USB modem to unlock it.&lt;br /&gt;&lt;br /&gt;Let's say my PIN code is 5678.  First check where my PIN code is used:&lt;br /&gt;&lt;tt&gt;&lt;br /&gt;jlh@r2d2:~$ grep -n 5678 strace.vodafone&lt;br /&gt;68172:12333 write(29, "AT+CPIN=5678\r\n"..., 14) = 14&lt;br /&gt;&lt;/tt&gt;&lt;br /&gt;&lt;br /&gt;Line 68172.  The line is sent on file descriptor 29.  Let's find where this file descriptor is opened before line 68172.  It may be recycled during the execution of the program, so only take the last one:&lt;br /&gt;&lt;tt&gt;&lt;br /&gt;jlh@r2d2:~$ cat -n strace.vodafone | head -n 68172  | grep 'open.*= 29' | tail -n 1&lt;br /&gt;66643 12333 open("/dev/ttyUSB1", O_RDWR|O_NOCTTY|O_NONBLOCK|O_LARGEFILE) = 29&lt;br /&gt;&lt;/tt&gt;&lt;br /&gt;&lt;br /&gt;And where it's closed:&lt;br /&gt;&lt;tt&gt;&lt;br /&gt;jlh@r2d2:~$ cat -n strace.vodafone | tail -n +66643  | grep 'close(29'&lt;br /&gt;74856 12333 close(29)                         = 0&lt;br /&gt;&lt;/tt&gt;&lt;br /&gt;&lt;br /&gt;We just have to get read(2) and write(2) calls on file descriptor 29 between line 66643 and line 74856:&lt;br /&gt;&lt;tt&gt;&lt;br /&gt;jlh@r2d2:~$ sed -n '66643,74856{ /\(read\|write\)(29/p }' strace.vodafone&lt;br /&gt;12333 write(29, "AT+CSQ\r\n"..., 8)     = 8&lt;br /&gt;12333 read(29, "AT+CSQ\r\r\n+CME ERROR: SIM PIN requ"..., 8192) = 39&lt;br /&gt;12333 write(29, "ATZ\r\n"..., 5)        = 5&lt;br /&gt;12333 read(29, "ATZ\r"..., 8192)        = 4&lt;br /&gt;12333 read(29, "\r\nOK\r\n"..., 8192)   = 6&lt;br /&gt;12333 write(29, "ATE0\r\n"..., 6)       = 6&lt;br /&gt;12333 read(29, "ATE0\r\r\nOK\r\n"..., 8192) = 11&lt;br /&gt;12333 write(29, "AT+CPIN?\r\n"..., 10)  = 10&lt;br /&gt;12333 read(29, "\r\n+CPIN: SIM PIN\r\n\r\nOK\r\n"..., 8192) = 24&lt;br /&gt;12333 read(29, "\r\n^BOOT:12633134,0,0,0,64\r\n"..., 8192) = 27&lt;br /&gt;12333 write(29, "AT+CPIN=5678\r\n"..., 14) = 14&lt;br /&gt;12333 read(29, "\r\nOK\r\n"..., 8192)   = 6&lt;br /&gt;12333 read(29, "\r\n^SIMST:1\r\n"..., 8192) = 12&lt;br /&gt;12333 read(29, "\r\n^SRVST:2\r\n"..., 8192) = 12&lt;br /&gt;12333 read(29, "\r\n^RSSI:13\r\n"..., 8192) = 12&lt;br /&gt;12333 read(29, "\r\n^BOOT:12633134,0,0,0,64\r\n"..., 8192) = 27&lt;br /&gt;...&lt;br /&gt;&lt;/tt&gt;&lt;br /&gt;&lt;br /&gt;The important thing is to send the PIN, so we will just stop after sending the PIN (if it doesn't work, you can still try to add a few lines).  Let's translate this to a chat(8) script:&lt;br /&gt;&lt;tt&gt;&lt;br /&gt;ECHO ON&lt;br /&gt;TIMEOUT 1&lt;br /&gt;'' AT+CSQ&lt;br /&gt;'SIM PIN required' ATZ&lt;br /&gt;OK ATE0&lt;br /&gt;OK AT+CPIN?&lt;br /&gt;OK AT+CGSN&lt;br /&gt;OK AT+CPIN=5678&lt;br /&gt;&lt;/tt&gt;&lt;br /&gt;&lt;br /&gt;Then, just before running wvdial with the stolen configuration file, just use:&lt;br /&gt;&lt;tt&gt;&lt;br /&gt;jlh@r2d2:~$ /usr/sbin/chat -f pin.chat &lt; /dev/ttyUSB0 &gt; /dev/ttyUSB0&lt;br /&gt;[...]&lt;br /&gt;&lt;/tt&gt;&lt;br /&gt;&lt;br /&gt;Note that if you try to rerun this chat(8) script, it won't work because the modem won't return what is expected.  Given there is no way to implement branches in chat(8), I used a very small timeout so it will exit very quickly if the modem is already unlocked.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7977789709139913287-6816374174490433076?l=bsdjlh.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bsdjlh.blogspot.com/feeds/6816374174490433076/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7977789709139913287&amp;postID=6816374174490433076' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7977789709139913287/posts/default/6816374174490433076'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7977789709139913287/posts/default/6816374174490433076'/><link rel='alternate' type='text/html' href='http://bsdjlh.blogspot.com/2008/12/get-rid-of-vodafone-mobile-connect-card.html' title='Get rid of Vodafone Mobile Connect Card driver for Linux'/><author><name>Jeremie Le Hen</name><uri>http://www.blogger.com/profile/07863111280211011857</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_sP33YFnaRDk/R3BLYSjJ6_I/AAAAAAAAAAs/FMP6tQxYHHw/S220/DSC05747.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7977789709139913287.post-264382213739417934</id><published>2008-09-26T12:33:00.005+02:00</published><updated>2008-10-29T18:16:18.292+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='elf'/><title type='text'>Global Offset Table, why is it needed?</title><content type='html'>In ELF land, GOT stands for Global Offset Table.  It is a very important component of Position Independant Code (PIC), used in shared libraries.  In this article, we try to understand why it is needed.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Preface&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;Understanding linking and loading is difficult.  At least it was for me because I mainly read documentation, without writing source which usually helps to stick things in mind.  If you are really interested in linking and loading, I can only advice you to read the following documentation:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;John R Levine's "&lt;a href="http://linker.iecc.com/"&gt;Linkers and Loaders&lt;/a&gt;" book (ISBN 1-55860-496-0).  This is the best documentation you can find on this topic.  You can find the &lt;a href="http://www.cse.iitb.ac.in/%7Ekrithi/courses/431/linker.html"&gt;first chapter&lt;/a&gt; here which is a very good reading to understand the history of linkers.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Ian Lance Taylor's &lt;a href="http://www.google.fr/search?q=site%3Awww.airs.com%2Fblog%2Farchives+%22linkers+part%22"&gt;"Linkers" blog entries&lt;/a&gt; contains a overall explanation of the linking process.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Also, have a look in the bookmarks on my website there are a couple of interesting pointers too in "Code"/"Linkers/Loaders".&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;So, why GOT?&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;Quote from Wikipedia in the &lt;a href="http://www.blogger.com/=%22http://en.wikipedia.org/wiki/Linker%22"&gt;Linker&lt;/a&gt; article:&lt;br /&gt;&lt;blockquote&gt;In computer science, a linker or link editor is a program that takes one or more objects generated by a compiler and assembles them into a single executable program.&lt;/blockquote&gt;&lt;br /&gt;As you may already know when linking binary objects together into a program, the linker has to handle &lt;a href="http://en.wikipedia.org/wiki/Relocation_%28computer_science%29"&gt;relocations&lt;/a&gt;.  Relocations are basically hints left by the assembler so the linker knows where there are addresses to fix once everything has been put together.  Let's take a simple example to illustrate the need of relocations.  Imagine that &lt;code&gt;i&lt;/code&gt; is a global variable defined in a source file and you assign it a value in another source file: &lt;code&gt;i = 1&lt;/code&gt;.  On i386, the compiler translates this in &lt;code&gt;movl $1, i&lt;/code&gt;.  When the assembler processes this, it doesn't know the actual address of &lt;code&gt;i&lt;/code&gt; since it can see only one file at time, so it just set the address to zero; on the other hand the linker sees all files at once and can figure out the final value of a symbol (or, address of a variable).  So in this case, the assembler generates a relocation informing the linker to put the value of symbol "i" at such or such offset in the code section, once every binary objects have been combined and the final address of all symbols is known.  I won't go futher into the details about relocations, this deserves another blog article I think.  Just keep in mind that most types of relocation are used to "fix" the code of the library.  And this is not a problem when linking multiple objects files (including static libraries) together into a program.&lt;br /&gt;&lt;br /&gt;Contrariwise to static libraries, shared libraries are dynamically linked, which means that the linker's job is defered to runtime and is handled by the so-called dynamic linker.  By definition, shared libraries code is shared among multiple processes: thanks to virtual memory, the same physical memory pages holding the library code are mapped into the address space of every processes that need it.  The benefit is savings of physical memory.  Thus the shared code must obviously stay the same and should not be fixed directly to suit one particular process memory layout or the other.&lt;br /&gt;&lt;br /&gt;The difficulty comes from the fact we don't know where the dynamic linker will decide to load the library in the process memory as it depends on a number of factors such as executable size, number and size of libraries loaded previously, not to mention that actual load address might randomized for security reasons on recent systems.  Still when the library code refers to a global variable, its address has to be stashed somewhere so the code can access it.&lt;br /&gt;&lt;br /&gt;As we saw in the relocation example, this is normally done directly by fixing the code.  In order to avoid modifying shared libraries code at runtime and losing memory sharing, we have to make the runtime relocations point to the process private data.   This is done by asking the compiler to generate Position-Independant Code (PIC).  The idea is simple: instead of having the final absolute address of a symbol in the code, the code refers to a particular entry of a private array containing this address.  At runtime, the dynamic linker will stuff this array with the actual symbols value so the same code will access addresses proper to each process.  The sharp minded reader may have noticed that this only moves the problem on step further because the address of the private array itself is still unknown.  This is resolved by a small calculation.  Given that the library is loaded as a single unit in the memory, the distance between the code and the private array is known by the compiler.  The code just have to get the address of the current instruction and the address of the private array can be figured out.&lt;br /&gt;&lt;br /&gt;Ladies and gentlemen, this private array of addresses is what we call the Global Offset Table, or GOT.&lt;br /&gt;&lt;br /&gt;It is actually perfectly valid to create a non-PIC shared library.  It will work.  But under the hood, the dynamic linker will probably patch most of the code pages of the library which will be duplicated by the &lt;a href="http://en.wikipedia.org/wiki/Copy-on-write"&gt;copy-on-write&lt;/a&gt; mechanism of the virtual memory.  Besides wasting memory, it may take more time to start because if a symbol is used thousands time along the code, the dynamic linker will have thousands relocations pointing into the code section to process at startup.  On the other hand, with PIC there is one GOT entry per symbol so there is only one relocation to perform.  But to be honest this is more a tradeoff than a pure win because using GOT implies using a more expensive function prologue to compute the GOT address and an additional indirection for access through the GOT.&lt;br /&gt;&lt;br /&gt;Shared libraries all have their own GOT, and the program would have his if it was compiled with PIC as well (this is called Position Independant Executable by the way).  Actually in any shared library, the GOT is used for every data accessed with an absolute address in the code, which includes static variables and global variables defined in the library itself.&lt;br /&gt;&lt;br /&gt;For static variables there is no need for a GOT entry: getting the address is straightforward because the distance between the GOT and the variable itself is known, being in the same loadable unit, so the code can directly access it.&lt;br /&gt;&lt;br /&gt;One might think this is the same for global variables defined within the library itself.  But this is without counting that ELF allows the executable or a previously shared library to redefine a global variable of a shared library.  For example, you can perfectly define a &lt;code&gt;stdout&lt;/code&gt; variable in your program despite it is already defined in libc, but keep in mind that your variable will also be used by the libc functions referring to &lt;code&gt;stdout&lt;/code&gt; such as &lt;code&gt;printf(3)&lt;/code&gt; so be careful that it points to a valid &lt;code&gt;FILE&lt;/code&gt; object.  In short, all global variables used by the shared library unconditionally have a GOT entry.&lt;br /&gt;&lt;br /&gt;I hope you better understand what is GOT now :).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7977789709139913287-264382213739417934?l=bsdjlh.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bsdjlh.blogspot.com/feeds/264382213739417934/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7977789709139913287&amp;postID=264382213739417934' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7977789709139913287/posts/default/264382213739417934'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7977789709139913287/posts/default/264382213739417934'/><link rel='alternate' type='text/html' href='http://bsdjlh.blogspot.com/2008/09/global-offset-table-why-is-it-needed.html' title='Global Offset Table, why is it needed?'/><author><name>Jeremie Le Hen</name><uri>http://www.blogger.com/profile/07863111280211011857</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_sP33YFnaRDk/R3BLYSjJ6_I/AAAAAAAAAAs/FMP6tQxYHHw/S220/DSC05747.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7977789709139913287.post-7522878614678810303</id><published>2008-08-19T18:46:00.014+02:00</published><updated>2008-08-21T11:48:52.850+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='debian'/><category scheme='http://www.blogger.com/atom/ns#' term='eee'/><title type='text'>Debian on Asus EeePC 701 with Huawei USB modem from SFR or Vodafone</title><content type='html'>A few month ago, I bought a neat bundle from SFR, a french mobile operator, containing Asus EeePC 701 and a subscription to Internet through 2G/3G/3G+.  The connection is achieved thanks to an "E220 HSDPA Modem" USB key from Huawei Technologies.  All this stuff has been working very well out of the box with the pre-installed Xandros-based distribution (based on Debian).&lt;br /&gt;&lt;br /&gt;All I wanted from this netbook was to be able to surf the web and open terminals without wasting time administer the beast.  And well, standard EeePC distribution achieves this very well, and use OpenOffice as a bonus.  Of course, I was lacking some stuff like gcc, mplayer, screen...  That's why I harvested a few unofficial package repositories to cram my sources.list(5).  There was obviously some conflicts between the repositories, but I really didn't care (although usually I'm very keen to make my package manager happy): I had a handful of configuration files backup'd on a USB key and in case of unrecoverable failure within the package system, I just had to restore the original state by pressing F9 at startup (EeePC is shipped with a cunning disk setup: two partitions, the first one containing the original system and the second empty one being mounted on top of the former using unionfs, so restoring the system basically means blanking the second partition).&lt;br /&gt;&lt;br /&gt;But as time went on, one thing was more and more upsetting me: no package updates from Asus.  As you may already know, this EeePC is also shipped out-of-the-box with remote root exploit (through Samba)...  This was very annoying for me because I sometimes connect to other boxes using SSH, so one could hack my EeePC to steal my passwords or perform even more subtle things.  So I turned off everything I could because the kernel provided by Xandros doesn't contain IPTables.  But honestly, I was still worry about security.&lt;br /&gt;&lt;br /&gt;I finally decided to spare some time to install an other, more up to date, distribution when I noticed that I couldn't use Firefox 3 because most of the required libraries were not available.  A friend of mine had tried Ubuntu EEE or EEE Ubuntu, whatever.  At first, I thought it was a good choice because it could fit both the low administration and up-to-date-ness requirements.  But he quickly told me that Ubuntu was far more too memory hungry.  Moreover, I don't like these kind of bloated distributions; they somewhat remind me Windows where everything is done behind the scene without giving me any choice unless I really dig deep to understand how things work together.  So I forgot Ubuntu and kept on with Xandros&lt;br /&gt;&lt;br /&gt;Then I read that &lt;a href="http://lists.alioth.debian.org/pipermail/debian-eeepc-devel/2008-June/000449.html"&gt;Asus was working with Debian&lt;/a&gt; in order to maybe replace Xandros on EeePC some day.  This caught all my attention as this implied that Debian EeePC support should be very good.  What finally decided me to give Debian Eee a shot, despite my disappointing experience with Debian on my girlfriend's laptop last year, was &lt;a href="http://lists.debian.org/debian-devel-announce/2008/08/msg00002.html"&gt;this post from the Debian Eee PC Team&lt;/a&gt;, which looked quite encouraging.  Additionally, Debian is one of the cleanest distribution; or rather I should say this is one of the less messy  ;-) (hey, it's Linux!).&lt;br /&gt;&lt;br /&gt;I fetched the Debian Eee's &lt;a href="http://wiki.debian.org/DebianEeePC/HowTo/WPAInstaller-Beta"&gt;WPA Installer&lt;/a&gt; and spread it on a USB key.  I could install Debian flawlessly through my WPA/TKIP router.  I went for a 256 MB swap partition and all the remaining space as one big partition, and asked for a desktop installation, hoping to find again the regretted Xandros' usability.&lt;br /&gt;&lt;br /&gt;And I am very happy.  Given this is based on Debian testing, all packages are fairly up to date: Firefox 3 is here!  This is a great improvement because it can achieve true full screen like Opera; it's damn important because EeePC 701's screen is really small for web surfing.  All devices seems to be supported, although I haven't tested all of them; some shortcut keys are working (contrast keys for example), but volume keys don't.  But honestly it's not a big deal compared to what I won and hopefully it will be resolved soon.&lt;br /&gt;&lt;br /&gt;The "hardest" task was to make the Huawey modem USB key work.  The current kernel (2.6.25...something) is supposed to support it, but anyway you have to somehow manage to enter the PIN code because there is a SIM card in it.  Fortunately, the &lt;a href="https://forge.betavine.net/projects/vodafonemobilec/"&gt;Vodafone Mobile Connect Card driver for Linux&lt;/a&gt; (wow, what a name!) handle it perfectly: just beware to download the &lt;a href="https://forge.betavine.net/frs/download.php/269/vodafone-mobile-connect-card-driver-for-linux-2.0.beta3-ALL-i386-installer.run"&gt;i386 installer&lt;/a&gt;, which is not available as a package at time of writing.  You just have run it and tell that your user must belong to the "vmc" group.  Then don't forget to logout so as to be in the "vmc" group effectively and run the "vodaphone-mobile-connect-card-driver-for-linux" (I'm not kidding).  Edit the profile, and change username, password and APN host to "slsfr" and the DNS servers to "172.20.2.10" and "172.20.2.39" as noted in &lt;a href="http://forum.eee-pc.fr/sujet-2023-logiciel-gerer-cle"&gt;this french forum post&lt;/a&gt;.  And voila!  You can connect to Internet over 3G+ and even read the SMS and directory stored on the SIM card!&lt;br /&gt;&lt;br /&gt;Ok, it's not a package and it spreads some files but... it works!  And if you ever want to remove it, you could still follow the installation script to know what as been copied (/etc/udev/rules/ and /usr/bin mainly if I recall correctly).  The graphical interface is heavy and I would have preferred a neat command-line tool, but I won't complain more.  In open-source, if you want it, just code it! :-)&lt;br /&gt;&lt;br /&gt;In summary, if you're fed up with your Xandros, go for &lt;a href="http://wiki.debian.org/DebianEeePC"&gt;Debian/Eee&lt;/a&gt;!  (It's hard to say when you are a BSD guy ;p.)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7977789709139913287-7522878614678810303?l=bsdjlh.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bsdjlh.blogspot.com/feeds/7522878614678810303/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7977789709139913287&amp;postID=7522878614678810303' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7977789709139913287/posts/default/7522878614678810303'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7977789709139913287/posts/default/7522878614678810303'/><link rel='alternate' type='text/html' href='http://bsdjlh.blogspot.com/2008/08/debian-on-asus-eeepc-701-with-huawei.html' title='Debian on Asus EeePC 701 with Huawei USB modem from SFR or Vodafone'/><author><name>Jeremie Le Hen</name><uri>http://www.blogger.com/profile/07863111280211011857</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_sP33YFnaRDk/R3BLYSjJ6_I/AAAAAAAAAAs/FMP6tQxYHHw/S220/DSC05747.JPG'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7977789709139913287.post-5172562190238997846</id><published>2008-06-23T10:48:00.016+02:00</published><updated>2008-06-23T18:55:49.552+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='FreeBSD'/><category scheme='http://www.blogger.com/atom/ns#' term='rtld'/><category scheme='http://www.blogger.com/atom/ns#' term='Propolice'/><title type='text'>Chicken and egg problem with Propolice in runtime linker/loader</title><content type='html'>Some background first: Back in 2006, I was frustrated because FreeBSD was somewhat lagging behind other open-source operating systems in term of integrated security features.  One of them is a GCC extension originally named Propolice or SSP for Stack Smashing Protection.  As its name lets sound, it protects (very efficiently) against stack based buffer overflows.  Historically &lt;a href="http://www.trl.ibm.com/projects/security/ssp/"&gt;Propolice&lt;/a&gt; has been developed by Hiroaki Etoh at IBM for gcc-2.95.3 and then gcc-3.4.4 as an external patch, but it has now been included in the mainstream, starting at gcc-4.1.  The patch to integrate Propolice in FreeBSD has been existing for more than two years on my &lt;a href="http://tataz.chchile.org/%7Etataz/FreeBSD/SSP/"&gt;website&lt;/a&gt;, but then FreeBSD only provided gcc-3.4.4 and heavily patching a contributed software is ruled out by policy, so it couldn't be committed in FreeBSD-6.  I missed the FreeBSD-7 window for various reasons, and now I'm working to get it committed to FreeBSD-8 (aka CURRENT).&lt;br /&gt;&lt;br /&gt;How does Propolice work?  The compiler identifies functions that might be vulnerable (containing a stack based buffer) and during their prologue, pushes a one-word &lt;i&gt;canary&lt;/i&gt; between the return address stored in the stack and the local variables.  In the function's epilogue, the canary is checked against its original value and if it has changed then a buffer overflow occurred and the program is aborted.  The canary is initially in the BSS segment but is initialized to a random value by a function called during the program startup (namely, a constructor).  Both the canary and the initializer function are provided in FreeBSD's libc.&lt;br /&gt;&lt;br /&gt;When I sent the patch for review back in april, Antoine Brodin noticed that when build world is performed with &lt;tt&gt;-fstack-protector-all&lt;/tt&gt; (which makes GCC to protect &lt;u&gt;all&lt;/u&gt; functions instead of only those containing a local buffer), it breaks the whole system.  There were actually various problems, such as the&lt;br /&gt;initializer function being protected itself: during its prologue the canary was equal to zero but during the epilogue its value had been set to a random value meanwhile so obviously the saved value did't match...  This problem has been resolved quickly.  The nasty problem lay in the runtime loader (aka rtld-elf): once it was installed, all programs would fail with SIGSEGV.&lt;br /&gt;&lt;br /&gt;When a dynamically-linked program is run, the kernel always transfers control to rtld behing the scene, instead of the actual program.  The purpose is to do runtime linking of libraries needed by the program, which includes resolving symbols and performing relocations, before actually transfering control to it.  So I've recompiled rtld without SSP, but it was still crashing.  I've narrowed down the segfault to a call mmap(2) which turned out to be the first call into libc, against which rtld was statically linked.  One of the very first thing rtld has to do is to relocate itself, mainly to be able to access global data which are addressed through GOT (Global Offset Table).  This was the very problem.  Given that all libc functions were protected with Propolice, mmap(2)'s prologue tried to push the canary, which is accessed through the &amp;laquo;__stack_chk_guard&amp;raquo; global symbol.  This means it used a pointer from the GOT, which had not been initialized at this point.&lt;br /&gt;&lt;br /&gt;As an additional note (and a reminder for me ;p), I came to thinking that the problem could also arise in the canary initializer which stands in rtld's .init section.  After some thinking, I realized that usual .init and .fini sections were handled by rtld itself, so rtld's ones are actually never run I think.&lt;br /&gt;&lt;br /&gt;Obviously rtld must been compiled without SSP.  As a temporary solution, libc is not allowed to be compiled with &lt;tt&gt;-fstack-protector-all&lt;/tt&gt;.  I think a better solution would be to create a librtld containing symbols required by rtld and compiled without SSP.&lt;br /&gt;&lt;br /&gt;Sharp minds have certainly understood that if the original patch worked without &lt;tt&gt;-fstack-protector-all&lt;/tt&gt; it was just a matter of chance because no functions during relocation of rtld's GOT entries had been elected by GCC to be protected.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7977789709139913287-5172562190238997846?l=bsdjlh.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bsdjlh.blogspot.com/feeds/5172562190238997846/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7977789709139913287&amp;postID=5172562190238997846' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7977789709139913287/posts/default/5172562190238997846'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7977789709139913287/posts/default/5172562190238997846'/><link rel='alternate' type='text/html' href='http://bsdjlh.blogspot.com/2008/06/chicken-and-egg-problem-with-propolice.html' title='Chicken and egg problem with Propolice in runtime linker/loader'/><author><name>Jeremie Le Hen</name><uri>http://www.blogger.com/profile/07863111280211011857</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_sP33YFnaRDk/R3BLYSjJ6_I/AAAAAAAAAAs/FMP6tQxYHHw/S220/DSC05747.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7977789709139913287.post-6542422616522192594</id><published>2008-03-12T16:15:00.007+01:00</published><updated>2008-03-18T15:18:48.245+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='svn'/><title type='text'>Sketching Subversion</title><content type='html'>Subversion is easy to grasp for long-time CVS users, since it is conceptually very similar.  The intent when creating Subversion was simply to create "a better CVS" as they state on their frontpage.  I think they succeeded with regard to this.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Revisions&lt;/span&gt;&lt;br /&gt;First, each commit is atomic and revision numbers are incremented for each commit &lt;u&gt;repository-wise&lt;/u&gt;, whereas in CVS revision numbers are incremented for each commit &lt;u&gt;file-wise&lt;/u&gt;.  This means each revision number represent a state of the filesystem tree.  With CVS, if you want to get the diff of a commit, you could only approximate it with dates.  In SVN, you simply ask for the diff between two revisions.&lt;br /&gt;&lt;br /&gt;The puzzling side of this is that two successive revisions of a file may not have successive revision number.  For example, I've recently worked on a script stored in a repository shared by multiple developpers, and here are the successive revision number:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    r558&lt;br /&gt;    r580&lt;br /&gt;    r595&lt;br /&gt;    r596&lt;br /&gt;    r597&lt;br /&gt;    ...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Externals&lt;/span&gt;&lt;br /&gt;Another feature worth noting is called "externals".  Each repository entry, file or directory, may carry metadatas as name/value pairs, so-called "properties".  Their name may be whatever you want, such as a copyright or even the full license text, but a few have special meaning.  I've only used the one named "svn:externals", which it is extremely useful.  I've once work on a CVS repository containing multiple projects and a couple home-grown libs shared among them.  In order to build the project, we had to write some shell script glue that checked out the required libs automatically into the project directory before building.  As far as I know, there is no other way to circumvent this problem (let me know if there is one).  This is the exact problem that externals can resolve.  By adding a couple of svn:externals properties to your project directory, you compel Subversion to pull down the required libraries along your project.  Supposing your repository is laid out like this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    myproject/&lt;br /&gt;    lib/mylib/&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;You can add a "svn:externals" property to the "myproject" directory containing:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    mylib /path/to/your/repository/lib/mylib&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt; &lt;br /&gt;And the next time you'll check out or update your project, the mylib/ subdirectory will automatically created.  You could even use it as a working copy of lib/mylib/ and perform commits in it!&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Branches and all&lt;/span&gt;&lt;br /&gt;Subversion only knows about "cheap copies" of a directory or file somewhere else in the repository, no tag, no branch.  Let me explain.  Newly copied entries share their history with their ancestor, therefrom the &lt;u&gt;cheap&lt;/u&gt; copy.  From here onward, all commits on one or the other copy won't be shared...  I'm sure the concept of branch is already looming in your mind :-).  You may also have already figured that branches are addressed through the repository namespace: you don't need an extra information as in CVS ("-r BRANCH").  This is why Subversion repositories are commonly laid out like this (this is the advised way in SVN documentation to design your repository, though this is really a matter of &lt;u&gt;policy&lt;/u&gt;):&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    myproject/&lt;br /&gt;        trunk/&lt;br /&gt;        branches/&lt;br /&gt;            1.0/&lt;br /&gt;            1.1/&lt;br /&gt;            2.0/&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;You may now wonder how to create a simple tag (i.e. not a branch tag, to use CVS terminology), unless you are especially keen and you have already grasped the whole thing.  Actually, there is no difference between a branch and a mere tag, except you haven't performed any commits in the latter.  A good practice when using CVS when you want to create a new branch for a given release is to first tag and then branch, so you can address the exact branching point using the tag.  In Subversion, a cheap copy creates a new revision number, so you only have to dig the log up to for it and ask for the diff.&lt;br /&gt;&lt;br /&gt;This also mean you can easily move a file in the repository without losing its history, by copying and then deleting the ancestor.  With CVS, this required a so-called "repo-copy", i.e. duplicating the RCS file on the repository side, which somehow is a waste of space.&lt;br /&gt;&lt;br /&gt;To sum up the whole thing, you have a namespace in which you can do cheap copies which will share their history up to the copy revision.  Everything else is just a matter of policy.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Conclusion&lt;/span&gt;&lt;br /&gt;I really like SVN, for all those aforementioned things above.&lt;br /&gt;But I won't ever blame CVS for its weaknesses.  It has been designed more than twenty years ago and relies on the RCS format which was designed in the early eighties.  It works so well that numerous projects are still using it, notably the FreeBSD project which is known to have the biggest open-source repository ever.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7977789709139913287-6542422616522192594?l=bsdjlh.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bsdjlh.blogspot.com/feeds/6542422616522192594/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7977789709139913287&amp;postID=6542422616522192594' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7977789709139913287/posts/default/6542422616522192594'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7977789709139913287/posts/default/6542422616522192594'/><link rel='alternate' type='text/html' href='http://bsdjlh.blogspot.com/2008/03/sketching-subversion.html' title='Sketching Subversion'/><author><name>Jeremie Le Hen</name><uri>http://www.blogger.com/profile/07863111280211011857</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_sP33YFnaRDk/R3BLYSjJ6_I/AAAAAAAAAAs/FMP6tQxYHHw/S220/DSC05747.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7977789709139913287.post-2945525373228649019</id><published>2008-02-21T20:11:00.009+01:00</published><updated>2008-03-18T15:18:17.040+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='FreeBSD'/><title type='text'>FreeBSD textdump(4) is awesome</title><content type='html'>FreeBSD has had the reputation of being rock solid for a long time.  One of the reason for this is that FreeBSD provides a great number powerful debugging tools.&lt;br /&gt;&lt;br /&gt;Especially, when your kernel panics, you have three options:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Live debug with &lt;a href="http://www.freebsd.org/cgi/man.cgi?query=ddb"&gt;ddb(4)&lt;/a&gt;, but this is not always possible if the box has to be up back quickly.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Dump the memory to perform post-mortem analysis.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Do nothing and pray that the panic won't happen again too soon.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Memory dumps use the swap device.  This is perfectly legal because once your OS has crashed, you won't do anything with the data in the swap anyway.  On the next reboot, &lt;a href="http://www.freebsd.org/cgi/man.cgi?query=savecore"&gt;savecore(8)&lt;/a&gt; checks if the swap partition contains a memory dump and copies it into a file in &lt;tt&gt;/var/crash&lt;/tt&gt;.&lt;br /&gt;&lt;br /&gt;In the beginning, only full memory dumps were possible.  In this case if you have 1 GB of RAM, you  need a swap partition of at least 1 GB too.  So is the file in &lt;tt&gt;/var/crash&lt;/tt&gt;.  This worked well but given that most of users are not kernel developpers, kernel dumps are usually useless unless they are transmitted to the right folk.  But a 1-GB file is cumbersome.&lt;br /&gt;&lt;br /&gt;In April 2006, Peter Wemm introduced minidumps.  They are very similar to full dumps except that, from what I've understood, only the kernel memory is dumped.  Typically, on my laptop with 1 GB of RAM, minidumps took about 150 MB.  The problem, while lessened, was still there though.&lt;br /&gt;&lt;br /&gt;A couple of weeks ago, Robert Watson commited a new feature called textdump(4) in FreeBSD 8.0-CURRENT.  Basically, this is  possible because of two new features of ddb(4):&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;It is possible to define "scripts" (no loop or condition, only a sequence of commands), certain special names corresponding to events.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;ddb(4) output can be captured in an internal buffer and dumped in place of the memory.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;In &lt;a href="http://lists.freebsd.org/pipermail/freebsd-current/2007-December/081626.html"&gt;this post&lt;/a&gt;, Robert Watson gives numerous informations about textdumps.  I strongly advice you to read this.  The very important thing is that most of panics reported by users can be solved by a backtrace and a couple of DDB commands.  This is precisely what this feature achieves.  Moreover, textdumps rarely exceed one megabyte, which is far more convenient than dumps or minidumps and can be easily sent by e-mail.&lt;br /&gt;&lt;br /&gt;Moreover, users using FreeBSD as desktop obviously run X.org.  When a panic arise, it is not possible to go back to console mode, so ddb(4) is not accessible.  If you've asked your kernel to drop to ddb(4) on panic as I did, the kernel dump is not performed automatically and you're screwed.  Textdumps removes this needle from your foot.&lt;br /&gt;&lt;br /&gt;Now let's see how to use them.  FreeBSD will automatically configures (mini)dumps for you.  This is possible to do in a single command:&lt;br /&gt;&lt;br /&gt;root# ddb script kdb.enter.panic="textdump set; capture on; show pcpu;trace;show locks;ps;alltrace;show alllocks;show lockedvnods; call doadump"&lt;br /&gt;&lt;br /&gt;"kdb.enter.panic" is a script name with a special meaning: as its name lets sound, it will be automatically executed on panic.  The first command "textdump set", forces the next dump to be the captured ddb(4) output instead of the traditional memory dump.  The second one "capture on"... enables the capture of commands output.  Next comes a bunch of ddb(4) commands commonly.  The final command "call doadump" performs the actual dump.  If you want to reboot automatically, you can add the "reset" command afterward.&lt;br /&gt;&lt;br /&gt;As far as I know, there is no configuration sugar to enable this automatically at boot time, so for now I stuck it in &lt;tt&gt;/etc/rc.local&lt;/tt&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7977789709139913287-2945525373228649019?l=bsdjlh.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bsdjlh.blogspot.com/feeds/2945525373228649019/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7977789709139913287&amp;postID=2945525373228649019' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7977789709139913287/posts/default/2945525373228649019'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7977789709139913287/posts/default/2945525373228649019'/><link rel='alternate' type='text/html' href='http://bsdjlh.blogspot.com/2008/02/freebsd-textdump4-is-awesome.html' title='FreeBSD textdump(4) is awesome'/><author><name>Jeremie Le Hen</name><uri>http://www.blogger.com/profile/07863111280211011857</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_sP33YFnaRDk/R3BLYSjJ6_I/AAAAAAAAAAs/FMP6tQxYHHw/S220/DSC05747.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7977789709139913287.post-2695607494609914926</id><published>2008-01-27T23:14:00.001+01:00</published><updated>2008-01-29T15:43:15.373+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='xen'/><title type='text'>Quick HOWTO for building Xen 3.2 on Debian/Ubuntu</title><content type='html'>I finally carried out "make world" with Xen 3.2 on Debian/sid after much struggle.&lt;br /&gt;&lt;br /&gt;First, contrary to xen-3.1.0-src.tgz, xen-3.2.0.tar.gz doesn't come along with the linux-2.6-xen-sparse/ and patches/ directories which allow to build a &amp;laquo;xen-infied&amp;raquo; kernel from a vanilla kernel source.  Thus it is impossible to use &lt;tt&gt;make world XEN_LINUX_SOURCE=tarball&lt;/tt&gt;.&lt;br /&gt;&lt;br /&gt;By default, &lt;tt&gt;make world&lt;/tt&gt; will use Mercurial to pull down (or &amp;laquo;clone&amp;raquo; in Mercurial vocabulary) the xenified kernel from Xensource's Mercurial repository.  Unfortunately, it seems that the current Mercurial version shipped with Debian/Ubuntu is outdated and cannot be used out-of-the-box.  Nonetheless, it is possible to fetch the xenified kernel manually.&lt;br /&gt;&lt;br /&gt;From my understanding, it is necessary to "make prep-kernels" in order to create the &lt;i&gt;kernel build directory&lt;/i&gt;.  Indeed if you put your &lt;i&gt;.config&lt;/i&gt; file directory into the kernel tree itself, the kernel's build system will complain about the lack of cleanliness and will ask you to run "make mrproper".  This is baffling but it appears that whenever the kernel is asked to store the object files in a separate directory (namely &lt;i&gt;build-linux-2.6.18-xen_x86_32/&lt;/i&gt;), it makes sure you didn't create your .config file in the wrong directory.  I suppose this is a safeguard.&lt;br /&gt;&lt;br /&gt;So I devised with the following process to build Xen 3.2.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;root# mkdir build&lt;br /&gt;root# wget http://bits.xensource.com/oss-xen/release/3.2.0/xen-3.2.0.tar.gz&lt;br /&gt;root# tar xzf xen-3.2.0.tar.gz&lt;br /&gt;# Download the xenifid kernel tree manually, but NOT in xen-3.2.0/&lt;br /&gt;# because the buildconfig/select-repository script would skip it.&lt;br /&gt;# ! xen-3.2.0/ and linux-2.6.18-xen.hg/ must be at the same level !&lt;br /&gt;root# hg clone http://xenbits.xensource.com/linux-2.6.18-xen.hg&lt;br /&gt;root# cd xen-3.2.0&lt;br /&gt;root# make prep-kernels&lt;br /&gt;root# cp /boot/config-2.6.18-my build-linux-2.6.18-xen_x86_32/.config&lt;br /&gt;# Using the world target will clean everything first.  Don't use it here.&lt;br /&gt;root# make dist&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7977789709139913287-2695607494609914926?l=bsdjlh.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://lists.xensource.com/archives/html/xen-users/2008-01/msg00699.html' title='Quick HOWTO for building Xen 3.2 on Debian/Ubuntu'/><link rel='replies' type='application/atom+xml' href='http://bsdjlh.blogspot.com/feeds/2695607494609914926/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7977789709139913287&amp;postID=2695607494609914926' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7977789709139913287/posts/default/2695607494609914926'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7977789709139913287/posts/default/2695607494609914926'/><link rel='alternate' type='text/html' href='http://bsdjlh.blogspot.com/2008/01/quick-howto-for-building-xen-32-on_27.html' title='Quick HOWTO for building Xen 3.2 on Debian/Ubuntu'/><author><name>Jeremie Le Hen</name><uri>http://www.blogger.com/profile/07863111280211011857</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_sP33YFnaRDk/R3BLYSjJ6_I/AAAAAAAAAAs/FMP6tQxYHHw/S220/DSC05747.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7977789709139913287.post-4643023718538524512</id><published>2008-01-22T11:07:00.000+01:00</published><updated>2008-01-28T23:08:20.686+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='kvm'/><title type='text'>Quick HOWTO for building Qumranet's KVM</title><content type='html'>This post really deserves the name scrawl, but I thought sharing my experience in building a Qumranet's KVM snapshot on Linux could helpful for others.  Indeed it was not as straightforward as it seemed at first glance and it required some grope and wandering on Google.&lt;br /&gt;&lt;br /&gt;You will need KVM (surprising, isn't it?) and Linux kernel sources corresponding to your kernel.&lt;br /&gt;&lt;br /&gt;FWIW, KVM snapshots can be downloaded &lt;a href="http://people.qumranet.com:8888/avi/snapshots"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;First, let's prepare the kernel tree.  This step is only important for people who use packaged kernel (or IOW who don't build their kernel themselves and have extracted the kernel source tree for the sole purpose of building KVM).  For others, this step could be avoided because the targets we will use are performed implicitely when building the kernel.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;root# tar xzf linux-2.6.23.tar.gz&lt;br /&gt;root# cd linux-2.6.23.tar.gz&lt;br /&gt;root# cp /boot/config-2.6.23 .config&lt;br /&gt;root# make oldconfig prepare scripts&lt;br /&gt;root# cd -&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Next we will build KVM.  Beware your GCC version!  The current major branch is GCC 4 and it is shipped with almost if not all recent Linux distributions.  Unfortunately, QEMU (on which KVM's userland is heavily based, not to say they've reused QEMU with little modifications) doesn't build with GCC 4.  It requires GCC 3.2 or GCC 3.4 (a thorough explanation is provided in Fabrice Bellard's paper, "QEMU, a fast and portable dynamic translator", USENIX 2005).  So you need to install this version of GCC as well.  If you are running Debian for instance, this is pretty straightforward :&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;root# aptitude install gcc-3.4&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And you will have a new compiler named &lt;tt&gt;gcc-3.4&lt;/tt&gt;.  On other distros, you will have to either find a package of GCC 3 or build it manually as described on &lt;a href="http://gentoo-wiki.com/HOWTO:_Qemu_with_gcc_4"&gt;Gentoo Wiki&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Finally you will simply have to build KVM with a few special arguments to the configure script:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;root# tar xzf kvm-snapshot-20080117.tar.gz&lt;br /&gt;root# cd kvm-snapshot-20080117&lt;br /&gt;root# ./configure --qemu-cc=gcc-3.4 --kerneldir=$OLDPWD/linux-2.6.23 --prefix=/opt/kvm-snapshot-20080117&lt;br /&gt;root# make all install&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And this should work. :-)&lt;br /&gt;&lt;br /&gt;As you may have noticed, I installed KVM in /opt in order to avoid messing with your tidy package management system.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7977789709139913287-4643023718538524512?l=bsdjlh.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bsdjlh.blogspot.com/feeds/4643023718538524512/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7977789709139913287&amp;postID=4643023718538524512' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7977789709139913287/posts/default/4643023718538524512'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7977789709139913287/posts/default/4643023718538524512'/><link rel='alternate' type='text/html' href='http://bsdjlh.blogspot.com/2008/01/quick-howto-for-building-qumranets-kvm.html' title='Quick HOWTO for building Qumranet&apos;s KVM'/><author><name>Jeremie Le Hen</name><uri>http://www.blogger.com/profile/07863111280211011857</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_sP33YFnaRDk/R3BLYSjJ6_I/AAAAAAAAAAs/FMP6tQxYHHw/S220/DSC05747.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7977789709139913287.post-5947876183395043904</id><published>2008-01-05T00:05:00.000+01:00</published><updated>2008-01-09T23:17:30.577+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='gcc'/><category scheme='http://www.blogger.com/atom/ns#' term='asm'/><title type='text'>x86 assembly generated by various GCC releases for a classic function</title><content type='html'>In this new article, I will have a look at the same C source as in my previous article, except that it will be in its own function instead of being inlined in main().  We will see that some oddities spotted out previously only occured because we were in the main() function.&lt;br /&gt;&lt;br /&gt;All tests are compiled with the following GCC command-line:&lt;br /&gt;&lt;pre&gt;gcc -S -O test.c&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The C source file is:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;int     &lt;br /&gt;function(int ac, char *av[])&lt;br /&gt;{&lt;br /&gt;        char buf[16];&lt;br /&gt;        &lt;br /&gt;        if (ac &lt; 2)&lt;br /&gt;                return 0;&lt;br /&gt;        strcpy(buf, av[1]);&lt;br /&gt;        return 1; &lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;int     &lt;br /&gt;main(int ac, char *av[])&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;        function(ac, av);&lt;br /&gt;        return 0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;h3&gt;Expectation, GCC 2.8.1 and GCC 2.95.3&lt;/h3&gt;&lt;br /&gt;The expectation, GCC 2.8.1 and GCC 2.95.3 assembly versions are the same as in the previous article.  The stack frames are therefore identical too.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;GCC 3.4.6&lt;/h3&gt;&lt;br /&gt;Fortunately, the assembly code generated by GCC 3.4.6 is far less puzzling when the C source code stands in a mere function instead of main().  Actually, the code is nearly identical to the one generated by GCC 2.95.3.  The stack pointer has been aligned in the main() function on 16 bytes boundary.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;function:&lt;br /&gt;        pushl   %ebp&lt;br /&gt;        movl    %esp, %ebp&lt;br /&gt;        subl    $24, %esp        /* Alloc a 24 bytes buffer */&lt;br /&gt;        movl    $0, %eax&lt;br /&gt;        cmpl    $1, 8(%ebp)&lt;br /&gt;        jle     .L1&lt;br /&gt;        subl    $8, %esp         /* Alloc an unused 8 bytes */&lt;br /&gt;                                 /* buffer */&lt;br /&gt;        movl    12(%ebp), %eax&lt;br /&gt;        pushl   4(%eax)&lt;br /&gt;        leal    -24(%ebp), %eax  /* The 24 bytes buffer is */&lt;br /&gt;                                 /* used for strcpy() */&lt;br /&gt;        pushl   %eax&lt;br /&gt;        call    strcpy&lt;br /&gt;        movl    $1, %eax&lt;br /&gt;.L1:    &lt;br /&gt;        leave&lt;br /&gt;        ret&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The corresponding stack frame, similar to the GCC 2.95.3 one but the entire 24 bytes buffer is provided to strcpy().&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;       |   av   |&lt;br /&gt;       |   ac   |&lt;br /&gt;       |   ret  |&lt;br /&gt; ebp-&gt; |  sebp  |&lt;br /&gt;       |/ / / / | ^&lt;br /&gt;       | / / / /| |&lt;br /&gt;       |/ / / / | |&lt;br /&gt;       | / / / /| | buf, 24 bytes wide&lt;br /&gt;       |/ / / / | |&lt;br /&gt;       | / / / /| v&lt;br /&gt;       |\\\\\\\\| ^&lt;br /&gt;       |\\\\\\\\| v 8 unused bytes&lt;br /&gt;       |  av[1] |&lt;br /&gt; esp-&gt; |  &amp;buf  |&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;GCC 4.2.1&lt;/h3&gt;&lt;br /&gt;Astonishingly, GCC 4.2.1 does not keep with 16 bytes alignment, although it seemed to do so in the main() function.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;function:&lt;br /&gt;        pushl   %ebp&lt;br /&gt;        movl    %esp, %ebp&lt;br /&gt;        subl    $24, %esp        /* Alloc a 24 bytes buffer */&lt;br /&gt;        movl    $0, %eax&lt;br /&gt;        cmpl    $1, 8(%ebp)&lt;br /&gt;        jle     .L4&lt;br /&gt;        movl    12(%ebp), %edx&lt;br /&gt;        movl    4(%edx), %eax&lt;br /&gt;        movl    %eax, 4(%esp)    /* Fake push */&lt;br /&gt;        leal    -16(%ebp), %eax  /* A 16 bytes buffer is */&lt;br /&gt;                                 /* used for strcpy() */&lt;br /&gt;        movl    %eax, (%esp)     /* Fake push */&lt;br /&gt;        call    strcpy&lt;br /&gt;        movl    $1, %eax&lt;br /&gt;.L4:&lt;br /&gt;        leave&lt;br /&gt;        ret&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And now the stack frame:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;       |   av   |&lt;br /&gt;       |   ac   |&lt;br /&gt;       |   ret  |&lt;br /&gt; ebp-&gt; |  sebp  |&lt;br /&gt;       |/ / / / | ^ ^&lt;br /&gt;       | / / / /| | |&lt;br /&gt;       |/ / / / | | | buf, 16 bytes wide&lt;br /&gt;       | / / / /| | v&lt;br /&gt;       |  av[1] | |&lt;br /&gt; esp-&gt; |  &amp;buf  | v&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The stack frame looks exactly like the expectation.  One thing worth noting however is that GCC 4.2.1 always uses peculiar code for arguments storage.  Instead of using the push instruction, it reserves space for arguments of further function calls in the same time as local variables are allocated.  Arguments are the stored relative to %esp.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7977789709139913287-5947876183395043904?l=bsdjlh.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bsdjlh.blogspot.com/feeds/5947876183395043904/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7977789709139913287&amp;postID=5947876183395043904' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7977789709139913287/posts/default/5947876183395043904'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7977789709139913287/posts/default/5947876183395043904'/><link rel='alternate' type='text/html' href='http://bsdjlh.blogspot.com/2008/01/x86-assembly-generated-by-various-gcc.html' title='x86 assembly generated by various GCC releases for a classic function'/><author><name>Jeremie Le Hen</name><uri>http://www.blogger.com/profile/07863111280211011857</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_sP33YFnaRDk/R3BLYSjJ6_I/AAAAAAAAAAs/FMP6tQxYHHw/S220/DSC05747.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7977789709139913287.post-1071145366634117258</id><published>2007-12-23T23:53:00.000+01:00</published><updated>2008-01-08T22:44:01.281+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='gcc'/><category scheme='http://www.blogger.com/atom/ns#' term='asm'/><title type='text'>x86 assembly generated by various GCC releases for the main() function</title><content type='html'>In this article, I will look at the assembly code generated from it by various releases of GCC on FreeBSD and I will try to explain what it does and why (though a couple of things are still mysterious).  Moreover I will illustrate each assembly with a snapshot of the &lt;a href="http://en.wikipedia.org/wiki/Call_stack"&gt;call stack&lt;/a&gt; right before calling strcpy.  This shouldn't change much on other operating systems (such as Linux).&lt;br /&gt;&lt;br /&gt;All tests are compiled with the following GCC command-line:&lt;br /&gt;&lt;pre&gt;gcc -S -O test.c&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Here is the very simple (vulnerable) C program I will use:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;int&lt;br /&gt;main(int ac, char *av[])&lt;br /&gt;{&lt;br /&gt;        char buf[16];&lt;br /&gt;&lt;br /&gt;        if (ac &lt; 2)&lt;br /&gt;                return 0;&lt;br /&gt;        strcpy(buf, av[1]);&lt;br /&gt;        return 1;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;h3&gt;Expectation&lt;/h3&gt;&lt;br /&gt;First let's see what I would expect.  This first assembly code comes along with verbose comments.  Later ones won't be&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;main:&lt;br /&gt;  enter                 /* Create a new stack frame */&lt;br /&gt;  sub $16, %esp         /* Allocate buf */&lt;br /&gt;  cmp $1, 8(%ebp)       /* Compare ac to 1... */&lt;br /&gt;  jle .byebye0          /* And set the return value to */&lt;br /&gt;                        /* 0 if lower or equal */&lt;br /&gt;  mov 12(%ebp), %eax    /* Load av */&lt;br /&gt;  push 4(%eax)          /* Push av[1] */&lt;br /&gt;  push -16(%ebp)        /* Push &amp;buf */&lt;br /&gt;  call strcpy&lt;br /&gt;  mov $1, %eax          /* Set the return value to 1 */&lt;br /&gt;  jmp .byebye&lt;br /&gt;byebye0:&lt;br /&gt;  mov $0, %eax&lt;br /&gt;byebye:&lt;br /&gt;  leave                 /* Restore the old stack frame */&lt;br /&gt;  ret                   /* Return to the caller */&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now let's look at the stack frame:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;       |   av   |&lt;br /&gt;       |   ac   |&lt;br /&gt;       |   ret  |&lt;br /&gt; ebp-&gt; |  sebp  | saved ebp from the previous stack frame&lt;br /&gt;       |/ / / / | ^&lt;br /&gt;       | / / / /| |&lt;br /&gt;       |/ / / / | | buf, 16 bytes wide&lt;br /&gt;       | / / / /| v&lt;br /&gt;       |  av[1] |&lt;br /&gt; esp-&gt; |  &amp;buf  |&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;GCC 2.8.1&lt;/h3&gt;&lt;br /&gt;With GCC 2.8.1, the assembly is pretty close to what I expected:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;main:&lt;br /&gt;  pushl %ebp            /* Don't know why enter isn't */&lt;br /&gt;  movl %esp,%ebp        /* but this is semantically */&lt;br /&gt;                        /* equivalent */&lt;br /&gt;  subl $16,%esp&lt;br /&gt;  cmpl $1,8(%ebp)&lt;br /&gt;  jle .L2&lt;br /&gt;  movl 12(%ebp),%eax&lt;br /&gt;  pushl 4(%eax)&lt;br /&gt;  leal -16(%ebp),%eax&lt;br /&gt;  pushl %eax&lt;br /&gt;  call strcpy&lt;br /&gt;  movl $1,%eax&lt;br /&gt;  jmp .L3&lt;br /&gt;  .align 4&lt;br /&gt;.L2:&lt;br /&gt;  xorl %eax,%eax&lt;br /&gt;.L3:&lt;br /&gt;  leave&lt;br /&gt;  ret&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The stack right before calling strcpy() is identical to the expectation.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;GCC 2.95.3&lt;/h3&gt;&lt;br /&gt;Here, the generated assembly is very close to above, but the size allocated on the stack is a little larger (8 bytes).  Moreover, 8 additional bytes are allocated on the stack before pushing the arguments.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;main:&lt;br /&gt;   pushl %ebp&lt;br /&gt;   movl %esp,%ebp&lt;br /&gt;   subl $24,%esp        /* 24 bytes are allocated */&lt;br /&gt;                        /* instead of 16 */&lt;br /&gt;   cmpl $1,8(%ebp)&lt;br /&gt;   jle .L3&lt;br /&gt;   addl $-8,%esp&lt;br /&gt;   movl 12(%ebp),%eax&lt;br /&gt;   pushl 4(%eax)&lt;br /&gt;   leal -16(%ebp),%eax  /* surprisingly, a 16 bytes */&lt;br /&gt;                        /* buffer is still provided */&lt;br /&gt;                        /* to strcpy() */&lt;br /&gt;   pushl %eax&lt;br /&gt;   call strcpy&lt;br /&gt;   movl $1,%eax&lt;br /&gt;   jmp .L4&lt;br /&gt;   .p2align 4,,7&lt;br /&gt;.L3:&lt;br /&gt;   xorl %eax,%eax&lt;br /&gt;.L4:&lt;br /&gt;   leave&lt;br /&gt;   ret&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And the corresponding stack frame:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;       |   av   |&lt;br /&gt;       |   ac   |&lt;br /&gt;       |   ret  |&lt;br /&gt; ebp-&gt; |  sebp  |&lt;br /&gt;       |/ / / / | ^ ^&lt;br /&gt;       | / / / /| | |&lt;br /&gt;       |/ / / / | | | buf, 16 bytes wide&lt;br /&gt;       | / / / /| | v&lt;br /&gt;       |////////| | ^&lt;br /&gt;       |////////| v v 8 unused bytes&lt;br /&gt;       |\\\\\\\\| ^&lt;br /&gt;       |\\\\\\\\| v 8 unused bytes&lt;br /&gt;       |  av[1] |&lt;br /&gt; esp-&gt; |  &amp;buf  |&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;In order to understand what kind of optimization GCC tried to perform, I compile the test program with multiple buffer sizes:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;sizeof(buf)       stack alloc&lt;br /&gt;0                 8              (= 16 * 1 - 8)&lt;br /&gt;1-16              24             (= 16 * 2 - 8)&lt;br /&gt;17-32             40             (= 16 * 3 - 8)&lt;br /&gt;33-48             56             (= 16 * 4 - 8)&lt;br /&gt;49-64             72             (= 16 * 5 - 8)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Given that GCC 2.95.3 allocates an additional 8 bytes buffer afterward, it is undoubtly doing 16-bytes alignment here.  The intent is good but in my opinion it lacks an initial alignment of the stack frame pointer that later GCC releases do, as we are going to see.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;GCC 3.4.6&lt;/h3&gt;&lt;br /&gt;This release is the greediest among the ones we are looking at with regard to the stack management.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;main:&lt;br /&gt;   pushl %ebp&lt;br /&gt;   movl  %esp, %ebp&lt;br /&gt;   subl  $24, %esp      /* Alloc a 24 bytes buffer */&lt;br /&gt;   andl  $-16, %esp     /* Stack alignment on 16 */&lt;br /&gt;                        /* bytes boundary */&lt;br /&gt;   subl  $16, %esp      /* Allocates another 16 */&lt;br /&gt;                        /* bytes buffer */&lt;br /&gt;   movl  $0, %eax&lt;br /&gt;   cmpl  $1, 8(%ebp)&lt;br /&gt;   jle   .L1&lt;br /&gt;   subl  $8, %esp       /* And yet another 8 bytes one */&lt;br /&gt;   movl  12(%ebp), %eax&lt;br /&gt;   pushl 4(%eax)&lt;br /&gt;   leal  -24(%ebp), %eax /* The 24 bytes buffer is */&lt;br /&gt;                         /* used for strcpy() */&lt;br /&gt;   pushl %eax&lt;br /&gt;   call  strcpy&lt;br /&gt;   movl  $1, %eax&lt;br /&gt;.L1&lt;br /&gt;   leave&lt;br /&gt;   ret&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Looking at the stack, we can see it is greedily stuffed:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;       |   av   |&lt;br /&gt;       |   ac   |&lt;br /&gt;       |   ret  |&lt;br /&gt; ebp-&gt; |  sebp  |&lt;br /&gt;       |/ / / / | ^&lt;br /&gt;       | / / / /| |&lt;br /&gt;       |/ / / / | |&lt;br /&gt;       | / / / /| | buf, 24 bytes wide&lt;br /&gt;       |/ / / / | |&lt;br /&gt;       | / / / /| v&lt;br /&gt;       |\\\\\\\\| ^&lt;br /&gt;       |\\\\\\\\| | stack alignment on 16 bytes boundary&lt;br /&gt;       |\\\\\\\\| v (runtime-dependent size)&lt;br /&gt;       |/ / / / | ^&lt;br /&gt;       | / / / /| |&lt;br /&gt;       |/ / / / | | 16 unused bytes&lt;br /&gt;       | / / / /| v&lt;br /&gt;       |\ \ \ \ | ^&lt;br /&gt;       | \ \ \ \| v 8 unused bytes&lt;br /&gt;       |  av[1] |&lt;br /&gt; esp-&gt; |  &amp;buf  |&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;I performed the same test as above by varying buf size and I get the very same result as GCC 2.95.3.  It is however difficult to argue this is to maintain alignment since strcpy() arguments are pushed far below and the stack is aligned explicitely right after anyway.  This question stays opened.&lt;br /&gt;&lt;br /&gt;Interestingly, while GCC 2.95.3 allocates 24 bytes but only provides an address with 16 available bytes, GCC 3.4.6 allocates 24 bytes too but provides the whole buffer to strcpy().  My feeling is that instead of wasting 8 bytes, GCC developpers prefered to include them in the buffer in order to mitigate off-by-one/two exploitations.&lt;br /&gt;&lt;br /&gt;The 8 bytes buffer is certainly here to create a 16 byte block with the two arguments of strcpy().  Nonetheless, I don't understand the purpose of the 16 bytes buffer at all.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;GCC 4.2.1&lt;/h3&gt;&lt;br /&gt;This release generates assembly that seems quite odd at first glance but after thinking a bit about it, everything is (quite) understandable, contrary to GCC 3.4.6 :-).&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;main:&lt;br /&gt;  leal 4(%esp), %ecx    /* Load &amp;ac in %ecx */&lt;br /&gt;  andl $-16, %esp       /* Stack alignment on 16 */&lt;br /&gt;                        /* bytes boundary */&lt;br /&gt;  pushl -4(%ecx)        /* Push the ret again */&lt;br /&gt;  pushl %ebp            /* Creates a new stack frame */&lt;br /&gt;  movl %esp, %ebp&lt;br /&gt;  pushl %ecx            /* Push &amp;ac */&lt;br /&gt;  subl $36, %esp        /* Create a 36 bytes buffer */&lt;br /&gt;  movl 4(%ecx), %edx    /* Load av in %edx */&lt;br /&gt;  movl $0, %eax         /* Return value will be 0 if */&lt;br /&gt;                        /* the comparison fails */&lt;br /&gt;  cmpl $1, (%ecx)&lt;br /&gt;  jle .L4&lt;br /&gt;  movl 4(%edx), %eax    /* Load av[1] in %eax */&lt;br /&gt;  movl %eax, 4(%esp)    /* Fake push */&lt;br /&gt;  leal -20(%ebp), %eax  /* Load the 16 bytes buffer */&lt;br /&gt;                        /* (jump over &amp;ac, thus 20) */&lt;br /&gt;  movl %eax, (%esp)     /* Fake push */&lt;br /&gt;  call strcpy&lt;br /&gt;  movl $1, %eax&lt;br /&gt;.L4:&lt;br /&gt;  addl $36, %esp        /* Cleanup the stack  */&lt;br /&gt;  popl %ecx             /* Pop &amp;ac in %ecx */&lt;br /&gt;  popl %ebp             /* Restore %ebp */&lt;br /&gt;  leal -4(%ecx), %esp   /* Restore %esp thanks to &amp;ac */&lt;br /&gt;  ret&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Evil, isn't it? :-)  Let's look at the stack snapshot right before strcpy is called().  You will see that actually the stack is handled very neatly.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;      |   av   |&lt;br /&gt;      |   ac   |&lt;br /&gt;      |   ret  |&lt;br /&gt;      |\\\\\\\\| ^&lt;br /&gt;      |\\\\\\\\| | stack alignment on 16 bytes boundary&lt;br /&gt;      |\\\\\\\\| v (runtime-dependent size)&lt;br /&gt;      |   ret  |&lt;br /&gt;ebp-&gt; |  sebp  |&lt;br /&gt;      |   &amp;ac  |&lt;br /&gt;      |/ / / / | ^ ^&lt;br /&gt;      | / / / /| | |&lt;br /&gt;      |/ / / / | | | buf, 16 bytes wide&lt;br /&gt;      | / / / /| | v&lt;br /&gt;      |////////| | ^&lt;br /&gt;      |////////| | | 12 unused bytes&lt;br /&gt;      |////////| | v&lt;br /&gt;      |  av[1] | |&lt;br /&gt;esp-&gt; |  &amp;buf  | v&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;As you may have already notice, stack alignment is performed before creating a new stack frame.  Therefore, contrary to the previous assembly we have seen, it is not possible to get &lt;i&gt;ac&lt;/i&gt; or &lt;i&gt;av&lt;/i&gt; with simple indexing from %ebp since the gap created by the alignment cannot be known at compile time.  So the very first instruction stores the address of &lt;i&gt;ac&lt;/i&gt; in %ecx; it is then possible to access main()'s arguments: (%ecx) for ac and 4(%ecx) for av.  Note that -4(%ecx) is the address where ret is stored.&lt;br /&gt;&lt;br /&gt;Still before creating the new stack frame, ret is pushed once again.  I'm not sure about the purpose of this, but my feeling is that it is meant to create an authentic-looking stack frame, in case the program performs nasty things with it.  Only then the new stack frame is created.  &lt;i&gt;&amp;ac&lt;/i&gt; is pushed afterward so we won't lose its track if %ecx is used for something else.&lt;br /&gt;&lt;br /&gt;A 36 bytes buffer is allocated on the stack which will hold buf in its end (top) and strcpy() arguments at its beginning (bottom).  Indeed you can see that before calling strcpy(), instead of using "push" to set arguments on the stack, it simply stores values using indexation from %esp.  Ok that's fine but we only need 16 + 8 = 24 bytes to hold all this, not 36, so there are 12 superfluous bytes.  Yes, but GCC wants to keep its 16 bytes alignment!   Look:  After the explicit stack alignment, 12 bytes have been pushed (3 words); 16 bytes are needed for buf and 8 bytes (2 words) are needed for the arguments of strcpy().  12 + 16 + 8 = 36; the next multiple of 16 is 48, so it allocates 48 - 36 = 12 "superfluous" bytes.  Neat, eh?&lt;br /&gt;&lt;br /&gt;Upon return, &lt;i&gt;&amp;ac&lt;/i&gt; is popped up in %ecx, %ebp is popped as well and %esp is restored to its initial value.&lt;br /&gt;&lt;br /&gt;One thing I'm not sure to understand is why GCC stores &lt;i&gt;&amp;ac&lt;/i&gt; in %ecx.  Why not simply perform "mov %ebp, %ecx" at the beginning.  One could argue this is because &lt;i&gt;ac&lt;/i&gt; is used later in a comparison but I tried to remove the test from the C source and this does change anything.  So I think this is merely a convention.&lt;br /&gt;&lt;br /&gt;Without wanting to be too picky, I also wonder why &lt;i&gt;av&lt;/i&gt; is loaded into %edx before the test, while it is only useful after it.  I don't have any idea about this :-).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7977789709139913287-1071145366634117258?l=bsdjlh.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bsdjlh.blogspot.com/feeds/1071145366634117258/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7977789709139913287&amp;postID=1071145366634117258' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7977789709139913287/posts/default/1071145366634117258'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7977789709139913287/posts/default/1071145366634117258'/><link rel='alternate' type='text/html' href='http://bsdjlh.blogspot.com/2007/12/x86-assembly-generated-by-various.html' title='x86 assembly generated by various GCC releases for the main() function'/><author><name>Jeremie Le Hen</name><uri>http://www.blogger.com/profile/07863111280211011857</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_sP33YFnaRDk/R3BLYSjJ6_I/AAAAAAAAAAs/FMP6tQxYHHw/S220/DSC05747.JPG'/></author><thr:total>0</thr:total></entry></feed>
