Links

Ben Laurie blathering

3 Apr 2011

Improving SSL Certificate Security

Filed under: Crypto,DNSSEC,Security — Ben @ 19:47

Given how often I say on this blog that I am not speaking for my employer, I am amused to be able to say for once that I am. Over here.

28 Mar 2011

Census FAIL

Filed under: Rants — Ben @ 13:19

Once every ten years, every household in the UK gets to fill in a census form. This year, for the first time ever, I think, you can do it online. So, imagine how delighted we are that I am the only person in my household whose name actually fits in the box. Yes, really, there’s a 50 character limit.

Why? Suppose they’d splashed out and allowed 500 characters instead. What would that cost? Well, let’s assume 100M names. That’s an extra 450 x 100 = 45,000 MB of data, assuming they’re still using databases with fixed width fields. 45 GB. That would’ve cost them nearly an extra £5 at today’s prices. Not £5 per person, or £5 per household. £5 total.

Thank god for government savings, eh?

BTW, my wife rang and asked what to do. Amazingly, they opt for the least useful possible answer: start at the beginning of your name and keep going ’til you run out of space. I’m sure future generations will be very happy to have complete middle names and no surname. Not.

27 Mar 2011

ZFS Part 3: Replacing Dead Disks

Filed under: Open Source — Ben @ 16:39

As discussed in my previous article, if a disk fails then a ZFS system will just carry on as if nothing has happened. Of course, we’d like to restore the system to its former redundant glory, so here’s how…

Once more, we simulate a failure by removing the primary disk, but this time replace it with a new unformatted disk (I guess if the new disk was already bootable you’d need to fix that first).

Let’s assume we’re several years down the line and no longer have any documentation at all. First off, find your disks by inspecting dmesg. As before we have ad4 and ad8. ad4 is the new disk.

# diskinfo -v ad4 ad8
ad4
        512             # sectorsize
        500107862016    # mediasize in bytes (466G)
        976773168       # mediasize in sectors
        0               # stripesize
        0               # stripeoffset
        969021          # Cylinders according to firmware.
        16              # Heads according to firmware.
        63              # Sectors according to firmware.
        S20BJ9AB212006  # Disk ident.

ad8
        512             # sectorsize
        500107862016    # mediasize in bytes (466G)
        976773168       # mediasize in sectors
        0               # stripesize
        0               # stripeoffset
        969021          # Cylinders according to firmware.
        16              # Heads according to firmware.
        63              # Sectors according to firmware.
        9VMYLC5V        # Disk ident.

This time they are conveniently exactly the same size, despite having diffferent manufacturers (Samsung and Seagate respectively). We already know from the first article in this series that we can deal with disks that don’t look the same, and in any case only 250GB is currently replicated. So, let’s partition the new disk as the old one…

# gpart show ad8
=>       34  976773101  ad8  GPT  (466G)
         34        128    1  freebsd-boot  (64K)
        162    4194304    2  freebsd-swap  (2.0G)
    4194466  484202669    3  freebsd-zfs  (231G)
  488397135  488376000    4  freebsd-zfs  (233G)

# gpart show -l ad8
=>       34  976773101  ad8  GPT  (466G)
         34        128    1  (null)  (64K)
        162    4194304    2  swap8  (2.0G)
    4194466  484202669    3  system8  (231G)
  488397135  488376000    4  scratch8  (233G)

# gpart create -s gpt ad4
ad4 created
# gpart add -b 34 -s 128 -t freebsd-boot ad4
ad4p1 added
# gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 ad4
bootcode written to ad4
# gpart add -s 4194304 -t freebsd-swap -l swap4 ad4
ad4p2 added
# gpart add -s 484202669 -t freebsd-zfs -l system4 ad4
ad4p3 added
# gpart add -t freebsd-zfs -l scratch4 ad4
ad4p4 added
# gpart show ad4
=>       34  976773101  ad4  GPT  (466G)
         34        128    1  freebsd-boot  (64K)
        162    4194304    2  freebsd-swap  (2.0G)
    4194466  484202669    3  freebsd-zfs  (231G)
  488397135  488376000    4  freebsd-zfs  (233G)

Now we’re ready to reattach the disk to the various filesystems.

First the swap. Since we can’t remove the dead disk from the gmirror setup, first we forget then add the new swap partition back in.

# gmirror forget swap
# gmirror insert -h -p 1 swap /dev/gpt/swap4
# gmirror status
       Name    Status  Components
mirror/swap  DEGRADED  gpt/swap8
                       gpt/swap4 (29%)

and after a while

# gmirror status
       Name    Status  Components
mirror/swap  COMPLETE  gpt/swap8
                       gpt/swap4

Next the main filesystem. In this case, since the new device has the same name as the old one, we can just write

# zpool replace system /dev/gpt/system4
If you boot from pool 'system', you may need to update
boot code on newly attached disk '/dev/gpt/system4'.

Assuming you use GPT partitioning and 'da0' is your new boot disk
you may use the following command:

        gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 da0

Once more we’ve already done this step, so no need to do it again. Note, this command took a little while, don’t be alarmed!

# zpool status
  pool: scratch
 state: ONLINE
 scrub: none requested
config:

        NAME            STATE     READ WRITE CKSUM
        scratch         ONLINE       0     0     0
          gpt/scratch8  ONLINE       0     0     0

errors: No known data errors

  pool: system
 state: DEGRADED
status: One or more devices is currently being resilvered.  The pool will
        continue to function, possibly in a degraded state.
action: Wait for the resilver to complete.
 scrub: resilver in progress for 0h0m, 9.77% done, 0h2m to go
config:

        NAME                   STATE     READ WRITE CKSUM
        system                 DEGRADED     0     0     0
          mirror               DEGRADED     0     0     0
            gpt/system8        ONLINE       0     0     0
            replacing          DEGRADED     0     0     0
              gpt/system4/old  UNAVAIL      0     0     0  cannot open
              gpt/system4      ONLINE       0     0     0  221M resilvered

errors: No known data errors

and after not very long

# zpool status
  pool: scratch
 state: ONLINE
 scrub: none requested
config:

        NAME            STATE     READ WRITE CKSUM
        scratch         ONLINE       0     0     0
          gpt/scratch8  ONLINE       0     0     0

errors: No known data errors

  pool: system
 state: ONLINE
 scrub: resilver completed after 0h1m with 0 errors on Sun Mar 27 13:04:02 2011
config:

        NAME             STATE     READ WRITE CKSUM
        system           ONLINE       0     0     0
          mirror         ONLINE       0     0     0
            gpt/system8  ONLINE       0     0     0
            gpt/system4  ONLINE       0     0     0  2.21G resilvered

errors: No known data errors

And we’re all good, back to where we were before. Reboot to check everything is fine.

Note, by the way, that all of this was done on a live system in multi-user mode. Apart from the occasional reboot there was no loss of service whatsoever.

Also, because the primary disk didn’t really fail, if I wanted I could put it in my other machine and end up with a working replicated system there without any need for setup.

There is one niggling question remaining: I started off with one 250 GB and one 500 GB disk. I now have two 500 GBs, which means the non-redundant scratch file system I had before could now become redundant. Or they could become part of the system pool. Or they could become a bigger non-redundant scratch filesystem.

In the end I decided to do the simplest thing, which is to make the scratch partitions part of the larger system partition. If I ever need to rearrange that is always possible either with the help of an additional disk or, even, with less safety, by taking one of the disks out of the pools and rearranging onto that (see a description of doing this kind of thing on freenas).

So, to make them part of the existing pool, first destroy the scratch filesystem (if I’d already used it I’d have to copy it before I started, but since I haven’t I can just blow it away). Since we mounted the pool direct, we destroy it with zpool:

# zpool destroy scratch

(and we can confirm it has gone with zpool list and zfs list). Just
for naming sanity, I rename the two scratch partitions:

# gpart modify -i 4 -l system8.p2 ad8
ad8p2 modified
# gpart modify -i 4 -l system4.p2 ad4
ad4p2 modified

and since those aren’t reflected in /dev/gpt, reboot. Then finally

# zpool add system mirror /dev/gpt/system4.p2 /dev/gpt/system8.p2

and presto

# zpool list
NAME SIZE USED AVAIL CAP HEALTH ALTROOT
system 463G 2.21G 461G 0% ONLINE -

ZFS Part 2: Disk Failure

Filed under: Open Source — Ben @ 16:12

Before I’m ready to trust ZFS I need to make sure I can replace a disk when it dies. With the setup described here, as a first experiment I removed the primary disk.

So, power down and remove the primary disk (ad4). Note that if you’re doing this on the Proliant system I mentioned, then you really should replace the drive mount (it is needed for cooling). Luckily I have a spare system so I just borrowed one.

Reboot. Comes up fine on the secondary disk without further intervention.

$ zpool status
  pool: scratch
 state: ONLINE
 scrub: none requested
config:

        NAME            STATE     READ WRITE CKSUM
        scratch         ONLINE       0     0     0
          gpt/scratch8  ONLINE       0     0     0

errors: No known data errors

  pool: system
 state: DEGRADED
status: One or more devices could not be opened.  Sufficient replicas exist for
        the pool to continue functioning in a degraded state.
action: Attach the missing device and online it using 'zpool online'.
   see: http://www.sun.com/msg/ZFS-8000-2Q
 scrub: none requested
config:

        NAME             STATE     READ WRITE CKSUM
        system           DEGRADED     0     0     0
          mirror         DEGRADED     0     0     0
            gpt/system8  ONLINE       0     0     0
            gpt/system4  UNAVAIL      0     0     0  cannot open

errors: No known data errors

Note that the system pool is now degraded. How would we have known if we hadn’t checked? Well, turns out we missed something from the previous setup.

We should have put

daily_status_zfs_enable="YES"
daily_status_gmirror_enable="YES"

in /etc/periodic.conf. Then in the daily mail we’d see:

Checking status of zfs pools:
  pool: system
 state: DEGRADED
status: One or more devices could not be opened.  Sufficient replicas exist for
	the pool to continue functioning in a degraded state.
action: Attach the missing device and online it using 'zpool online'.
   see: http://www.sun.com/msg/ZFS-8000-2Q
 scrub: none requested
config:

	NAME             STATE     READ WRITE CKSUM
	system           DEGRADED     0     0     0
	  mirror         DEGRADED     0     0     0
	    gpt/system8  ONLINE       0     0     0
	    gpt/system4  UNAVAIL      0     0     0  cannot open

errors: No known data errors

Checking status of gmirror(8) devices:
       Name    Status  Components
mirror/swap  DEGRADED  gpt/swap8

So remember, boys and girls, read your daily mails!

So far, so good. One disk failed, the system came back up without intervention, and would have alerted us in daily mails had we configured it correctly (of course it now is). So what happens if we put the disk back in? Since we’ve modified the other disk in the meantime, we’d hope that would get reconciled. Let’s see…

Power down and replace the missing disk, reboot.

Now we see

$ zpool status
  pool: scratch
 state: ONLINE
 scrub: none requested
config:

        NAME            STATE     READ WRITE CKSUM
        scratch         ONLINE       0     0     0
          gpt/scratch8  ONLINE       0     0     0

errors: No known data errors

  pool: system
 state: ONLINE
 scrub: resilver completed after 0h0m with 0 errors on Sat Mar 26 10:48:56 2011
config:

        NAME             STATE     READ WRITE CKSUM
        system           ONLINE       0     0     0
          mirror         ONLINE       0     0     0
            gpt/system8  ONLINE       0     0     0
            gpt/system4  ONLINE       0     0     0  345K resilvered

errors: No known data errors

$ gmirror status
       Name    Status  Components
mirror/swap  COMPLETE  gpt/swap4
                       gpt/swap8

and there we are, back to where we started. But suppose the disk had really failed, then what? See the next exciting installment!

18 Mar 2011

Completely Redundant Disks with ZFS and FreeBSD

Filed under: General,Open Source — Ben @ 15:00

A while back, I bought a ReadyNAS device for my network, attracted by the idea of RAID I can grow over time and mirrored disks.

Today I just finished building the same thing “by hand”, using FreeBSD and ZFS. At a fraction of the cost. Here’s how.

First off, I bought this amazing bargain: an HP ProLiant MicroServer. These would be cheap even at list price, but with the current £100 cashback offer, they’re just stupidly cheap. And rather nice.

Since I want to cater for a realistic future, I am assuming by the time I need to replace a drive I will no longer be able to buy a matching device, so I started from day one with a different second drive (the primary is 250 GB, secondary is 500 GB – both Seagate, which was not the plan, but I’ll remedy that in the next episode). I also added an extra 1GB of RAM to the machine (this is important for ZFS which is apparently not happy with less than 2GB of system RAM).

I then followed, more or less, Pawel’s excellent instructions for creating a fully mirrored setup. However, I had to deviate from them somewhat, so here’s my version.

The broad overview of the process is as follows

  1. Install FreeBSD on the primary disk, using a standard sysinstall.
  2. Create and populate gmirror and ZFS partitions on the secondary disk.
  3. Boot from the primary disk, but mount the secondary.
  4. Create and populate gmirror and ZFS partitions on the primary disk.
  5. Use excess secondary disk as scratch.

In my case the two disks are ad4 (primary, 250 GB) and ad8 (secondary, 500 GB). Stuff I typed is in italic.

Since we need identical size partitions for the mirror, we need to simulate the first disk (since it happens to be smaller). Get the disk’s size

# diskinfo -v /dev/ad4
/dev/ad4
        512             # sectorsize
        250059350016    # mediasize in bytes (233G)
        488397168       # mediasize in sectors
        0               # stripesize
        0               # stripeoffset
        484521          # Cylinders according to firmware.
        16              # Heads according to firmware.
        63              # Sectors according to firmware.
        9VMQN8T5        # Disk ident.

Create a memory disk the same size. Note that the sector sizes must match!

# mdconfig -a -t swap -s 488397168
md0

Verify they are the same.

# diskinfo -v /dev/ad4 /dev/md0
/dev/ad4
        512             # sectorsize
        250059350016    # mediasize in bytes (233G)
        488397168       # mediasize in sectors
        0               # stripesize
        0               # stripeoffset
        484521          # Cylinders according to firmware.
        16              # Heads according to firmware.
        63              # Sectors according to firmware.
        9VMQN8T5        # Disk ident.

/dev/md0
        512             # sectorsize
        250059350016    # mediasize in bytes (233G)
        488397168       # mediasize in sectors
        0               # stripesize
        0               # stripeoffset

Now partition the memory disk as we will the first disk later on.

# gpart create -s gpt md0
md0 created
# gpart add -b 34 -s 128 -t freebsd-boot md0
md0p1 added
# gpart add -s 2g -t freebsd-swap -l swap1 md0
md0p2 added
# gpart add -t freebsd-zfs -l systemx md0
md0p3 added

and show the resulting sizes

# gpart show md0
=>       34  488397101  md0  GPT  (233G)
         34        128    1  freebsd-boot  (64K)
        162    4194304    2  freebsd-swap  (2.0G)
    4194466  484202669    3  freebsd-zfs  (231G)

Now blow away the memory disk, we don’t need it any more.

# mdconfig -d -u 0

Create the partitions on the second disk.

# gpart create -s gpt ad8
ad8 created
# gpart add -b 34 -s 128 -t freebsd-boot ad8
ad8p1 added
# gpart add -s 2g -t freebsd-swap -l swap1 ad8
ad8p2 added
# gpart add -s 484202669 -t freebsd-zfs -l system8 ad8
ad8p3 added

And eat the rest of the disk as a scratch area (this area will not be mirrored, and so should only be used for disposable stuff).

# gpart add -t freebsd-zfs -l scratch8 ad8
ad8p4 added

Check it matches the md0 simulation

# gpart show ad8
=>       34  976773101  ad8  GPT  (466G)
         34        128    1  freebsd-boot  (64K)
        162    4194304    2  freebsd-swap  (2.0G)
    4194466  484202669    3  freebsd-zfs  (231G)
  488397135  488376000    4  freebsd-zfs  (233G)

And don’t forget to set up the bootloader

# gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 ad8
bootcode written to ad8

I realised as this point I had intended to label everything with an 8, to match the unit number, and had not done so for swap, so for completeness, here’s how you fix it

# gpart modify -i 2 -l swap8 ad8
ad8p2 modified
# gpart show -l ad8
=>       34  976773101  ad8  GPT  (466G)
         34        128    1  (null)  (64K)
        162    4194304    2  swap8  (2.0G)
    4194466  484202669    3  system8  (231G)
  488397135  488376000    4  scratch8  (233G)

Note that the label change is not reflected by the device names in /dev/gpt, which is needed for the next step, so at this point I rebooted.

Now set up the swap mirror.

# gmirror label -F -h -b round-robin swap /dev/gpt/swap8

Create the ZFS storage pool called system, consisting only of our system8 partition.

# zpool create -O mountpoint=/mnt -O atime=off -O setuid=off -O canmount=off system /dev/gpt/system8

And create a dataset – “mountpoint=legacy” stops ZFS from managing it.

# zfs create -o mountpoint=legacy -o setuid=on system/root

Mark it as the default bootable dataset.

# zpool set bootfs=system/root system

Mount it

# mount -t zfs system/root /mnt
# mount
/dev/ad4s1a on / (ufs, local)
devfs on /dev (devfs, local, multilabel)
system/root on /mnt (zfs, local, noatime)

And create the remaining mountpoints according to Pawel’s suggested layout…

# zfs create -o compress=lzjb system/tmp
# chmod 1777 /mnt/tmp
# zfs create -o canmount=off system/usr
# zfs create -o setuid=on system/usr/local
# zfs create -o compress=gzip system/usr/src
# zfs create -o compress=lzjb system/usr/obj
# zfs create -o compress=gzip system/usr/ports
# zfs create -o compress=off system/usr/ports/distfiles
# zfs create -o canmount=off system/var
# zfs create -o compress=gzip system/var/log
# zfs create -o compress=lzjb system/var/audit
# zfs create -o compress=lzjb system/var/tmp
# chmod 1777 /mnt/var/tmp
# zfs create -o canmount=off system/usr/home

And create one for each user:

# zfs create system/usr/home/ben

Now, at a slightly different point from Pawel, I edit the various config files. First /boot/loader.conf. Note that some of these are commented out: this is because, although they appear in Pawel’s version, they are already built into the kernel (this is because I use a GENERIC kernel and he uses a stripped-down one). Including them seems to cause problems (particularly geom_part_gpt, which causes a hang during boot if present).

geom_eli_load=YES
#geom_label_load=YES
geom_mirror_load=YES
#geom_part_gpt_load=YES
zfs_load=YES
vm.kmem_size=3G # This should be 150% of your RAM.

Enable ZFS

# echo zfs_enable=YES >> /etc/rc.conf

Change fstab for the new layout (note, you might want to edit these in – for example, my system had an entry for cd drives).

# cat > /etc/fstab
system/root / zfs rw,noatime 0 0
/dev/mirror/swap.eli none swap sw 0 0
^D

The .eli extension here is magic: geom_eli finds it at startup and automatically encrypts it.

Set the work directory for ports (so that it uses the faster compression scheme during builds).

# echo WRKDIRPREFIX=/usr/obj >> /etc/make.conf

These need to be done now because the next step is to copy the entire install to the new ZFS filesystem. Note that this particular command pastes completely incorrectly from Pawel’s blog post so be careful!

# tar -c --one-file-system -f - . | tar xpf - -C /mnt/

Tar can’t copy some types of file, so expect an error or two at this point:

tar: ./var/run/devd.pipe: tar format cannot archive socket
tar: ./var/run/log: tar format cannot archive socket
tar: ./var/run/logpriv: tar format cannot archive socket

Just for fun, take a look at the ZFS we’ve created so far…

# zfs list
NAME USED AVAIL REFER MOUNTPOINT
system 1.12G 225G 21K /mnt
system/root 495M 225G 495M legacy
system/tmp 30K 225G 30K /mnt/tmp
system/usr 652M 225G 21K /mnt/usr
system/usr/home 50K 225G 21K /mnt/usr/home
system/usr/home/ben 29K 225G 29K /mnt/usr/home/ben
system/usr/local 297M 225G 297M /mnt/usr/local
system/usr/obj 21K 225G 21K /mnt/usr/obj
system/usr/ports 190M 225G 159M /mnt/usr/ports
system/usr/ports/distfiles 30.8M 225G 30.8M /mnt/usr/ports/distfiles
system/usr/src 165M 225G 165M /mnt/usr/src
system/var 100K 225G 21K /mnt/var
system/var/audit 21K 225G 21K /mnt/var/audit
system/var/log 35K 225G 35K /mnt/var/log
system/var/tmp 23K 225G 23K /mnt/var/tmp

Unmount ZFS

# zfs umount -a

And the one we mounted by hand

# umount /mnt

And set the new ZFS-based system to be mounted on /

# zfs set mountpoint=/ system

And … reboot! (this is the moment of truth)

After the reboot, you should see

$ mount
system/root on / (zfs, local, noatime)
devfs on /dev (devfs, local, multilabel)
system/tmp on /tmp (zfs, local, noatime, nosuid)
system/usr/home/ben on /usr/home/ben (zfs, local, noatime, nosuid)
system/usr/local on /usr/local (zfs, local, noatime)
system/usr/obj on /usr/obj (zfs, local, noatime, nosuid)
system/usr/ports on /usr/ports (zfs, local, noatime, nosuid)
system/usr/ports/distfiles on /usr/ports/distfiles (zfs, local, noatime, nosuid)
system/usr/src on /usr/src (zfs, local, noatime, nosuid)
system/var/audit on /var/audit (zfs, local, noatime, nosuid)
system/var/log on /var/log (zfs, local, noatime, nosuid)
system/var/tmp on /var/tmp (zfs, local, noatime, nosuid)
$ zfs list
NAME USED AVAIL REFER MOUNTPOINT
system 1.79G 225G 21K /
system/root 763M 225G 763M legacy
system/tmp 43K 225G 43K /tmp
system/usr 1.04G 225G 21K /usr
system/usr/home 50.5K 225G 21K /usr/home
system/usr/home/ben 29.5K 225G 29.5K /usr/home/ben
system/usr/local 297M 225G 297M /usr/local
system/usr/obj 416M 225G 416M /usr/obj
system/usr/ports 190M 225G 159M /usr/ports
system/usr/ports/distfiles 30.8M 225G 30.8M /usr/ports/distfiles
system/usr/src 165M 225G 165M /usr/src
system/var 106K 225G 21K /var
system/var/audit 21K 225G 21K /var/audit
system/var/log 41.5K 225G 41.5K /var/log
system/var/tmp 23K 225G 23K /var/tmp
$ swapinfo
Device 1K-blocks Used Avail Capacity
/dev/mirror/swap.eli 2097148 0 2097148 0%

Note that system is not actually mounted (it has canmount=off) – it is used to allow all the other filesystems to inherit the / mountpoint. The one that is actually mounted on / is system/root, which is marked as legacy because it is mounted before zfs is up.

Now we’re up on the second disk, time to get the first disk back in the picture (we’re using it for boot but nothing else right now).

First blow away the MBR

# dd if=/dev/zero of=/dev/ad4 count=79
79+0 records in
79+0 records out
40448 bytes transferred in 0.008059 secs (5018970 bytes/sec)

and create the GPT partitions:

# gpart create -s GPT ad4
ad4 created
# gpart add -b 34 -s 128 -t freebsd-boot ad4
ad4p1 added
# gpart add -s 2g -t freebsd-swap -l swap4 ad4
ad4p2 added
# gpart add -t freebsd-zfs -l system4 ad4
ad4p3 added
# gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 ad4
bootcode written to ad4

No scratch partition on this one, there’s no room. Now the two disks should match

# gpart show
=>       34  976773101  ad8  GPT  (466G)
         34        128    1  freebsd-boot  (64K)
        162    4194304    2  freebsd-swap  (2.0G)
    4194466  484202669    3  freebsd-zfs  (231G)
  488397135  488376000    4  freebsd-zfs  (233G)

=>       34  488397101  ad4  GPT  (233G)
         34        128    1  freebsd-boot  (64K)
        162    4194304    2  freebsd-swap  (2.0G)
    4194466  484202669    3  freebsd-zfs  (231G)

apart from the scratch partition, of course.

Add the mirrored swap

# gmirror insert -h -p 1 swap /dev/gpt/swap4

And when rebuilding is finished, you should see

# gmirror status
       Name    Status  Components
mirror/swap  COMPLETE  gpt/swap8
                       gpt/swap4

Now add the second disk’s zfs partition

# zpool attach system /dev/gpt/system8 /dev/gpt/system4
If you boot from pool 'system', you may need to update
boot code on newly attached disk '/dev/gpt/system4'.

Assuming you use GPT partitioning and 'da0' is your new boot disk
you may use the following command:

        gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 da0

We already did this part, so no need to do anything. Wait for it to finish. Here it is partway through

# zpool status
  pool: system
 state: ONLINE
status: One or more devices is currently being resilvered.  The pool will
        continue to function, possibly in a degraded state.
action: Wait for the resilver to complete.
 scrub: resilver in progress for 0h0m, 39.20% done, 0h0m to go
config:

        NAME             STATE     READ WRITE CKSUM
        system           ONLINE       0     0     0
          mirror         ONLINE       0     0     0
            gpt/system8  ONLINE       0     0     0
            gpt/system4  ONLINE       0     0     0  718M resilvered

errors: No known data errors

and now done

# zpool status
  pool: system
 state: ONLINE
 scrub: resilver completed after 0h2m with 0 errors on Fri Mar 18 12:13:19 2011
config:

        NAME             STATE     READ WRITE CKSUM
        system           ONLINE       0     0     0
          mirror         ONLINE       0     0     0
            gpt/system8  ONLINE       0     0     0
            gpt/system4  ONLINE       0     0     0  1.79G resilvered

errors: No known data errors

And we’re done. Reboot one last time to check everything worked.

One final task not relevant to the mirroring is to mount the scratch disk area.

Create a mountpoint

# mkdir /scratch

And a pool

# zpool create -O mountpoint=/scratch -O atime=off -O setuid=off scratch /dev/gpt/scratch8

This filesystem has no redundancy, as previously mentioned. (edit: I am told that the mkdir and mountpoint are both redundant – zfs will create the directory as needed, and uses the pool name as the mount point by default)

In the next installment I will fail and replace one of the disks.

Edit:

daily_status_zfs_enable="YES"
daily_status_gmirror_enable="YES"

should be added to /etc/periodic.conf so checks are added to the daily mails.

9 Mar 2011

Capsicum Wins Cambridge Ring Award

Filed under: Capabilities,Security — Ben @ 19:28

Of course, I know that capabilities are really important, and that the work we (I say we as if I did much – the hard graft is down to Robert Watson and Jon Anderson) have done on adding capabilities to FreeBSD is particularly awesome. But I continue to be amazed at the community reaction to it.

The latest accolade is the rather unwieldy Cambridge Ring Hall of Fame Award for Best Publication of the Year.

You know, I’m beginning to think we might actually make some serious progress with capabilities in the next year or two. Watch this space, there’s a lot going on in this field!

5 Mar 2011

Chicken and Lentils

Filed under: Recipes — Ben @ 15:56

chicken thighs/drumsticks/whatever – skin on
green lentils (I doubt it matters much, but this is what I used)
cardamom pods
cloves
coriander
cumin
dried red chillies
diced ginger
sliced onion
chicken stock
tinned tomatoes

Grind the spices (I use a coffee grinder, but pestle and mortar is fine). Fry with the ginger in whatever oil takes your fancy (or even ghee) for a minute or so, then add the chicken pieces. Fry pretty vigorously until nicely browned, but try not to burn the spices. I try to have enough spice so the chicken all gets nicely coated and there’s some left over for the next stage…

Once the chicken is browned (but not cooked through), set aside, leaving whatever oil and spices aren’t sticking to them in the pan. Add the onions and fry until clear, then add the lentils and some water.

Some, but not all, lentils need to be cooked carefully (they contain an enzyme that ain’t so good for you) so make sure you incorporate the cooking instructions into this recipe. The green lentils I used don’t need soaking (in fact, in my experience you can generally substitute more boiling for soaking anyway), but they do need boiling hard for ten minutes, so … do that now.

Once any hard cooking needed by the lentils is over, return the chicken to the pan, add the tinned tomatoes and chicken stock – smash the tomatoes up, bring to the boil, then simmer until the lentils are done (varies according to type). Note that lentils can soak up a lot of water, so stir occasionally and add more if needed. Season to taste and serve with rice and whatever.

I expect a raita would be nice with this.

I don’t usually do quantities, but since I was asked nicely, here’s some guidance: for eight chicken thighs (enough for four people, if they’re not too greedy) I used around 200g of lentils, one tin of tomatoes and probably around a third of a cup (or more) of spices, after they’d been ground. Mostly cumin and coriander. I know it sounds like a lot, but you need a lot – and its hard to overdo them. Stock should be enough to cook the lentils, bearing in mind the liquid from the tomatoes – the aim is for a thick lentil sauce, not a soup.

24 Feb 2011

Who the Hell are 2o7?

Filed under: Privacy,Security — Ben @ 13:38

My friend Adriana pointed me to this cool track-blocking extension for Chrome.

Back in the day, I used to do this kind of blocking “by hand” – i.e. by manually deciding which cookies to block and which to allow. This is far from an exact science – it’s fairly easy to block some sites into uselessness – so I’m pleased to see an automated alternative.

In any case, it all came to an end when Chrome decided (without any explanation I ever saw) to drop the ability to control cookies, so extensions are probably the only way now.

Anyway, it reminded me of something I kept meaning to look into but never really got very far, which is 2o7.net. This domain crops up all the time if you start monitoring cookies, and clearly is some massive tracking operation. But I’ve never heard of it, and nor has anyone else I know.

So … who the hell are 2o7? (And yes, I can do whois, which leads me to Omniture. Not much the wiser. Except they now seem to be owned by Adobe – mmm – looking forward to mixing all that tracking data with Adobe’s careful attention to security).

Note, btw, the cool track-blocking extension doesn’t appear to have heard of 2o7 either. From my experience you can just block all their cookies without harm.

16 Feb 2011

Two Cool Caja Things

Filed under: Caja — Ben @ 14:01

Firstly, Paypal are using Caja to protect their customers from errors or evilness in gadgets. There are also some performance hints here.

Secondly, my esteemed colleague, Jasvir Nagra, has put together a really nice playground for Caja. Have a go, it’s pretty.

That is all.

22 Jan 2011

Salmon with Sticky Ginger Sauce

Filed under: Recipes — Ben @ 5:22

Salmon fillets (with skin)
Sugar
Vinegar
Ginger
Spring onions

Finely chop ginger and spring onions. Mix a lot of sugar with a roughly equal quantity of vinegar. Add the ginger and reduce (I always overdo this which means the sauce solidifies when it cools – try not to copy me, it’s a pain to have to keep warming it). Add the chopped spring onions at the end. You could also add chilli, but I didn’t. I expect cubed cucumber might be nice, too.

While it is reducing, fry the salmon in olive oil, quite hot so the skin browns (do the skin side first). Serve with sauce generously drizzled on it.

We had it with rice and leeks with cream (roll-cut leeks, fry gently in butter/salt/pepper, add double cream at the end).

21 Dec 2010

Is Openleaks The Next Haystack?

As everyone who’s even half-awake knows by now, a bunch of people who used to work on Wikileaks have got together to work on Openleaks. From what I hear, Openleaks is going to be so much better than Wikileaks – it will have no editorial role, it will strongly protect people who submit leaks, it’s not about the people who run it, it’ll be distributed and encrypted.

But where’s the design to back up this rhetoric? Where are the security reviews from well-known authorities? They seem to be missing. Instead we have excited articles in mainstream media about how wonderful it is going to be, and how many hours the main man has spent on it.

This sounds very familiar indeed. And we all know what happened last time round.

Of course, Openleaks may be fine, but I strongly suggest that those who are working on it publish their plan and subject it to scrutiny before they put contributors at risk.

As always, I offer my services in this regard. I am sure I am not alone.

18 Dec 2010

ƃuıʇsılʞɔɐlq uʍop-ǝpısd∩

Filed under: Anonymity,Crypto,Identity Management,Lazyweb,Privacy — Ben @ 14:54

A well-known problem with anonymity is that it allows trolls to ply their unwelcome trade. So, pretty much every decent cryptographic anonymity scheme proposed has some mechanism for blacklisting. Basically these work by some kind of zero-knowledge proof that you aren’t on the blacklist – and once you’ve done that you can proceed.

However, this scheme suffers from the usual problem with trolls: as soon as they’re blacklisted, they create a new account and carry on. Solving this problem ultimately leads to a need for strong identification for everyone so you can block the underlying identity. Obviously this isn’t going to happen any time soon, and ideally never, so blacklists appear to be fundamentally and fatally flawed, except perhaps in closed user groups (where you can, presumably, find a way to do strong-enough identification, at least sometimes) – for example, members of a club, or employees of a company.

So lately I’ve been thinking about using “blacklists” for reputation. That is, rather than complain about someone’s behaviour and get them blacklisted, instead when you see someone do something you like, add them to a “good behaviour blacklist”. Membership of the “blacklist” then proves the (anonymous) user has a good reputation, which could then be used, for example, to allow them to moderate posts, or could be shown to other users of the system (e.g. “the poster has a +1 reputation”), or all sorts of other things, depending on what the system in question does.

The advantage of doing it this way is that misbehaviour can then be used to remove reputation, and the traditional fallback of trolls no longer works: a new account is just as useless as the one they already have.

There is one snag that I can see, though, which is at least some anonymity systems with blacklisting (e.g. Nymble, which I’ve somehow only recently become aware of) have the side-effect of making every login by a blacklisted person linkable. This is not good, of course. I wonder if there are systems immune to this problem?

Given that Jan Camenisch et al have a presentation on upside-down blacklisting (predating my thinking by quite a long way – one day I’ll get there first!), I assume there are – however, according to Henry, Henry and Goldberg, Camenisch’s scheme is not very efficient compared to Nymble or Nymbler.

14 Dec 2010

Grown-up Arduino Programming

Filed under: Arduino/Freeduino,Programming — Ben @ 13:38

As I mentioned in a previous post, I am not a big a fan of the Arduino IDE. Since writing that, I’ve discovered I like it even less, because it does some ad-hoc mangling of what you write to turn it from a nearly-C language into genuine C. As a result, it is possible to write some C++ and get away with it, but whether C++ stuff works or not seems entirely random.

It may sound nuts to want to write C++ for a processor so small. But read on – it turns out you can do some nice things at essentially zero cost. But first you need a proper C++ toolchain. One way to get hold of it would be to install the Arduino IDE, in fact, since it uses it under the hood. But I did it from scratch on my FreeBSD system. This turns out to be mostly easy, but there were a couple of wrinkles worth writing down for the greater good.

Firstly, on FreeBSD the compiler is available as a port, so I just installed it with my favourite ports tool

portmaster devel/avr-gcc

(note that there are several variants based on different versions of the compiler available – this is the default variant which, at the time of writing, is based on gcc 4.2.4).

Sadly, although the libc part of the toolchain is available as a port, too, at the time of writing both versions (devel/avr-libc and devel/avr-libc-devel) are broken because they depend on defunct source code. So, I had to build this one by hand, starting with avr-libc-1.6.8.tar.bz2 from http://download.savannah.gnu.org/releases/avr-libc/. This is not too hard, just a slightly customised configuration followed by the usual make commands:

./configure --prefix=/usr/local/avr --host=avr
make
make install

Setting the prefix to /usr/local/avr is advisable as some things get installed immediately below the prefix and so could conflict with native compilers and libraries. However, it does cause some things to end up in /usr/local/avr/avr. Oh, well.

Next up, a test program is a good idea. avr-glibc comes with demo code, which can be found in /usr/local/avr/share/doc/avr-libc-1.6.8/examples/, but none of it is particularly well suited to an Arduino. So, I stole the Makefile from the demo sample and used this code instead of demo.c

#include <avr/interrupt.h>
#include <avr/io.h>

#define FLASH		PB5  // "Pin 13" (Arduino pin) - ATmega168 pin 19
#define CONTROL_PORT	PORTB
#define CONTROL_DDR	DDRB

static void ioinit(void)
    {
    CONTROL_DDR = _BV(FLASH);
    }

int main(void)
    {
    long n;

    ioinit();

    for( ; ; )
	{
	CONTROL_PORT &= ~_BV(FLASH);
	for(n=0; n < 300000; ++n)
	    ;
	CONTROL_PORT |= _BV(FLASH);
	for(n=0; n < 300000; ++n)
	    ;
	}
    }

and modified the Makefile to remove optimisation (essential, otherwise the delay loops get optimised away), select the right CPU (atmega168) and to modify these two lines

DEFS = -I /usr/local/avr/avr/include
LIBS = -B /usr/local/avr/avr/lib

-B is a new flag to me: it specifies where binaries and the crt0 files are found. The last ingredient is a way to upload to the Arduino. The utility avrdude can do this for you

avrdude -p m168 -P /dev/cuaU0 -c arduino -b 19200 -U flash:w:yourstuff.hex

Of course, delay loops are horrible, so my second attempt does this properly, using a timer interrupt. And this is where the C++ comes in: the “standard” way to set up the CPU is to write code like

#define FLASH		PB5  // "Pin 13" (Arduino pin) - ATmega168 pin 19
#define CONTROL_PORT	PORTB
#define CONTROL_DDR	DDRB

static void ioinit(void)
    {
    // PWM, 10-bit, phase-correct
    TCCR1A = _BV(WGM10) | _BV(WGM11);
    // Pre-scaler set to 1024
    TCCR1B = _BV(CS12) | _BV(CS10);
    // Set flash pin to output
    CONTROL_DDR = _BV(FLASH);
    // Enable timer 1 overflow interrupt
    TIMSK1 = _BV(TOIE1);
    sei();
    }

which is pretty revolting and involves a lot of manual-reading to understand. So, as is my habit when dealing with hardware, I tried wrapping it up in nice C++ classes to see what the run-time cost is. I won’t show the C++ classes here as they’re quite verbose and are a work in progress, but the net effect on the setup code is that it now looks like this

#define FLASH		PortB5  // "Pin 13" (Arduino pin) - ATmega168 pin 19

static void ioinit(void)
    {
    Control c;

    c.tc1.OC1ADisconnected();
    c.tc1.OC1BDisconnected();
    c.tc1.PWMPhaseCorrect10Bit();
    c.tc1.Prescaler1024();
    c.tc1.OverflowInterruptEnable();

    FLASH::Out(&c);

    c.Set();

    sei();
    }

which I hope you’ll agree is much more readable. The amazing thing is that, despite the increased verbosity, there’s no cost at all: this produces almost exactly the same assembler as the original code (it is in a slightly different order, though even that could be fixed if needed). The wonders of optimisation.

Note, by the way, the use of a PWM mode is simply because the demo code I borrowed from actually did use PWM – but pin 19 (where the LED is on a standard Ardunio/Freeduino) isn’t a PWM pin, so my code just uses the timer interrupt to time when to turn the LED on or off. The PWM is not really needed but the timer has to be in some mode, so I haven’t yet bothered to figure out a more appropriate one.

When I’ve got more stuff encapsulated in C++ I’ll start sharing the code.

2 Dec 2010

P2P DNS

Filed under: DNSSEC — Ben @ 14:10

Apparently the Pirate Bay are tired of ICANN and want to start their own peer-to-peer DNS. I think their chances of wide adoption are pretty near zero, but it’s an interesting area that’s needed serious exploration for quite some time. Obviously if you’re doing P2P DNS you need to use DNSSEC or attacks become trivial. Since they also want to have multiple registrars who can nominate themselves, it seems a proposal I made to the DNS working group many years ago could be handy. Basically, the idea is to distribute keys for “islands of security” by having bilateral agreements between them, so each island signs some set of other island’s keys, if they want to. The user then bootstraps their set of keys by starting from an island or islands they trust.

When ferreting this out I found that the -01 version is already on my server, and I just uploaded -02 – not sure what the differences are, when I have some time I’ll make a diff. Probably.

27 Nov 2010

Fun With Freeduino

Filed under: Arduino/Freeduino,Sustainable Energy — Ben @ 16:43

As I may have mentioned before, I have a place in Wales. That place is pretty primitive, we have a solid fuel heating system, otherwise known as a Rayburn, and until recently the extent of the control systems in the whole house was a thermostat strapped to the hot water tank. When the temperature hits the set point, a pump switches on, which pumps the hot water round the radiators instead.

I did consider adding a second thermostat for a while: if you let the Rayburn get overexcited it can boil the water in the convection system before the hot water tank is up to temperature. This is pretty exciting to be in amongst, the whole place vibrates and clanks. So, I mused about putting in a second thermostat that monitored the temperature of the pipes and switched on the pump if they got too hot. But then I learnt to control the Rayburn better and it has become a non-issue.

But anyway, the prospect of a house with basically no control systems in it has me thinking about building my own: something I’ve long wanted to play with. So, I started looking at the Arduino. I have read that Arduinos are not actually completely open (I believe their PCB design is not, even though everything else is), but in any case, Freeduinos seem to be cheaper, and completely compatible, so I got one from an outfit called nueletronics.

It turns out that there’s a package based on Processing which lets you very easily write and upload C/C++ code for the board, available from the Arduino site, so step one is obviously to write some code to do stuff with the LEDs on the Arduino board. I won’t bore you with that, since the source comes with the Arduino software.

Of course, that’s only fun for a short while, so I had to move on to something relevant to Wales. My first thought was to measure temperature, and perhaps do something about avoiding freezing when we’re not there. In a past life I played with 1-wire devices from Dallas[1] so the natural choice for the thermometer was a Dallas 18B20, also available from nueletronics, as it happens. It turns out that you need a 4.7 kOhm pull-up resistor for the parasitic power, so I bought some of those from eBay (amusingly buying 100 costs the same as buying 10, it seems, so of course I bought 100 – the cost was something like 1p each). Then I needed something to connect it to the Arduino, so I also bought a prototyping shield (shields are what they call daughter boards for the Arduino) and a breadboard, also from eBay.

Then I realised I’d need to communicate the temperature to some more serious machine, for recording/monitoring purposes. So I also bought an Ethernet shield, again from nuelectronics (note that this is not a “standard” Arduino ethernet shield). While I was browsing I realised I could be both lazy and a little tidier by buying yet more stuff from nuelectronics, namely a real-time datalog and I/O shield and a DS18B20 module. Ultimately I’ll probably connect the thermometer directly, but for now the I/O shield provides wiring (the rest of the board is unused in this little project) and the DS18B20 module saves me having a breadboard floating around – the software is exactly the same as it would be if I’d wired it direct.

So, now I’ve got all the hardware, my plan was to read the 1-wire temperature over Ethernet. Simples. Turns out that this was pretty easy once you have all the info (which is not so easy to find!) and cobble together the various bits of software. But since it was actually pretty painful to figure out all the bits, let me explain a step at a time.

  1. Connect the Freeduino to your PC/Mac/whatever with a USB cable.
  2. Fire up the Arduino software and configure it for the right USB port (sorry, no great advice on how to do this in general – in my case I had to install drivers on XP to do it).
  3. Convince yourself that you’ve got this working by running a sketch (this is what the Arduino software calls a program) that blinks the LED.
  4. Once you’ve done that, then disconnect the USB (which disconnects the power) and stack the I/O board and the Ethernet board on top of the Freeduino, in that order (the Ethernet has to go on top because the connector is too tall to fit between two boards).
  5. Connect the DS18B20 module to P7 on the I/O board (the centre connector).
  6. Plug the USB back in.
  7. Unzip the Ethernet shield drivers into the libraries directory of the Arduino software. They should end up in a directory called etherShield.
  8. Load up this sketch[2].
  9. Set an appropriate IP address[3] in the myip array at the top of the code. Also set the same address in baseurl.
  10. Build and install the sketch.
  11. Point your web browser at the IP address you configured. You should see the current temperature and a button to refresh.
  12. If you want to monitor temperature over time (and you are on Unix), run a script like this:

    while true
    do
            wget -q -O - 'http://193.133.15.111/?cmd=2'
            echo -n ' '
            date +%s
            sleep 60
    done
    

And that’s all folks. My first Arduino thermometer 🙂

What next? Well, firstly, the Arduino software environment is actually pretty annoying if you’re a professional coder like me, so I plan to figure out how to do this “properly” with the avr-gcc compiler suite (the Arduino software uses this under the hood, so it can’t be that hard). Secondly it seems to be quite hard to find out what pins are actually used by shields and what they connect to, so I’m probably going to start trying to gather that info in a useful format (does it already exist somewhere?), at least for components I have. I’m also planning to actually control some heating using the Arduino – for that purpose I’ll almost certainly use this relay module with the I/O board, at least for the prototype.

I’ll blog about these when I get round to them.

[1] 1-Wire is a really cute technology that allows you to control and power multiple devices over a single wire (+ ground).
[2] This is the demo code from nuelectronics, tidied up a bit and with some extra functionality added.
[3] If you don’t know what “appropriate” means, you should probably ask someone. It’s hard to give general advice.

Why Identity Is Still Just Login

Filed under: Identity Management,Privacy — Ben @ 15:14

It seems everyone now agrees that Internet identity is about a collection of assertions relating to a person (or thing, if you want to go there). Some of these assertions are assertions one makes about oneself, for example “I like brussels sprouts”, and assertions others make about you, for instance “Ben is a UK citizen, signed the UK Government”. These assertions are essentially invariant, or slowly varying, for the most part. So what makes an identity, we agree, is some collection of these assertions.

But we also agree that people need to assert different identities: there’s Ben at work, Ben as a member of the OpenSSL team, Ben at home and so on. Each of these identities, we like to think, corresponds to a different collection of assertions.

All we need to do, we think, to map these identities onto collections of electronic assertions and we’ll have solved The Internet Identity Problem. People will no longer be required to type in their credit card number five times a day, endlessly write down their address (and correct it when it changes) and so on. The ‘net will become one lovely, seamless experience of auto-communicated factoids about me that are just right for every circumstance and I’ll never fill in a form again.

You can probably see where I’m going. The more I think about it, the more I realise that every situation is different. My “identity” is contextual, and different for each context. We know this from endless studies of human behaviour.

So, what was the point of doing what every electronic identity system wants me to do, namely aggregating various assertions about me into various identities, and then choosing the right identity to reveal? To match this to what I do in the real world, I will need a different identity for each context.

So, what was the point of even talking about identities? Why not simply talk about assertions, and find better ways for me to quickly make the assertions I want to make. Cut out the middleman and do away with the notion of identity.

In practice, of course, this is exactly what has happened. The only vestige of this electronic identity that makes any sense is the ability to log in as some particular “person”. After that all my decisions are entirely contextual, and “identity” doesn’t help me at all. And so what we see is that “identity” has simply become “login”. And will always be so.

In a sense this is exactly what my Belay research project is all about – allowing me to decide exactly what I reveal in each individual context. In Belay, the ability to log in to a particular site will become the same kind of thing as any other assertion – a fine-grained permission I can grant or not grant.

Note: I am not against bundles of assertions – for example, I think lines one and two of my address clearly belong together (though for some purposes the first half of my postcode, or just my country, should suffice) or, less facetiously, when I use my credit card I almost always need to send a bunch of other stuff along with the credit card number. What I doubt is that the notion of a bundle that corresponds to an “identity” is a useful one. This implies that UIs where you pick “an identity” are doomed to failure – some other approach is needed.

16 Nov 2010

Apache vs. Oracle

Filed under: Open Source,Open Standards,Rants — Ben @ 11:49

As a founder of the Apache Software Foundation I have long been frustrated by the ASF’s reluctance to confront Sun and now Oracle head-on over their continued refusal to allow Apache Harmony to proceed as an open source Java implementation.

So I am very pleased to see the board finally draw a line in the sand, basically saying “honour the agreements or we block the next version of Java”. Oracle’s response is just ridiculous, including the blatant

Oracle provides TCK licenses under fair, reasonable, and non-discriminatory terms consistent with its obligations under the JSPA.

why even bother to say that in response to ASF’s charges? Do they think the ASF are suddenly going to say “oops, we see the light now, how wrong we were to expect a TCK licence under fair, reasonable and non-discriminatory terms consistent with your obligations under the JSPA, we see it all clearly now and humbly withdraw our unwarranted request”?

Well, whatever Oracle expected, the ASF’s response was short and sweet

Oracle statement regarding Java: “Now is the time for positive action (and) to move Java forward.”

The ball is in your court. Honor the agreement.

How this will play out is very uncertain, at least to me, but one thing is sure: delay and vacillation are over, at least from the ASF. Expect plenty of delay from Oracle, though.

13 Nov 2010

Chicken and Cashew

Filed under: Recipes — Ben @ 12:22

When I fancy a stirfry my thoughts often turn to this dish. I first learnt to cook this from Ken Hom’s excellent book, but it doesn’t bear much resemblance to his version any more. Quick and easy and delicious cold.

Chicken breast
Cashews
Ginger
Dark soy
Spring onions
Sesame oil

Chop the chicken. I believe the Chinese like things to all be roughly the same size, so in theory you should try and chop into cashew-nut-sized pieces. However, I typically do thin slices across the breast (by the way, if you want really thin slices then leaving frozen meat not quite defrosted is a great way to achieve it – no need to complete the defrosting after, it’ll happen in the wok). Marinade the chicken slices for 30 mins at least in diced ginger, dark soy and spring onion, finely chopped. Around here we like to use a lot of ginger but it is up to you.

While its marinading, stirfry the cashews in a little oil over a very gentle heat – burnt nut is very bitter, so keep the heat low and stir continuously – until lightly browned. Sometimes I use roasted and salted cashews, in which case there is no need to fry them, but you do need to rinse the salt off.

Then a little more oil (I use groundnut, by the way) on a high heat. Once it is smoking, throw in the chicken, which should’ve absorbed most of the marinade by now. Stirfry quickly and not for too long; the secret to really tender chicken is to stop as soon as all the meat is coloured – the pieces should be small enough that they’ll be cooked through by the time you’re done. Add the cashews and a little more dark soy and bring up to heat. Then take it off the heat, add yet more finely chopped spring onion and a generous dash of sesame oil give a final stir, and serve with plain boiled rice and a vegetable of your choice. Or a salad, even.

Nom nom. I think there might be some of this calling me from the fridge right now.

6 Nov 2010

Radical Copyright Thinking … at the European Commission!

Filed under: Civil Liberties,Digital Rights,Open Data — Ben @ 12:27

I criticise policy makers a lot. So it’s really nice when they say something sensible – or even inspirational. The summary does not do this speech justice. It’s quite short, I suggest you read it.

“We must ensure that copyright serves as a building block, not a stumbling block – we need action to promote a legal digital Single Market in Europe” European Commission Vice President for the Digital Agenda Neelie Kroes said today at the prestigious Forum D’Avignon, on the subject of how digital technology represents an opportunity rather than a threat to culture. Kroes underlined the need to modernise the copyright system so that it helps rather than hinders artists within the EU’s Single Market. “My goal, in promoting cultural diversity and content adapted to the digital age, is for European creativity to be even stronger”, Kroes said. “Today our fragmented copyright system is ill-adapted to the real essence of art, which has no frontiers. Instead that system has ended up giving a more prominent role to intermediaries than to artists. It irritates the public, who often cannot access what artists want to offer and leaves a vacuum which is served by illegal content, depriving artists of their well-deserved remuneration. It may suit some vested interests to avoid a debate, or to frame the debate in moralistic terms that merely demonise millions of citizens. But that is not a sustainable approach. Time alone will not solve the problems that have emerged.

25 Oct 2010

Firesheep: Session Hijacking for Morons

Filed under: Crypto,Privacy,Security — Ben @ 13:35

OK, we’ve all known forever that using any kind of credential over an unencrypted connection is a Bad Idea(tm). However, we also know that pretty much every website does an Obi-wan over session cookies, which typically travel over HTTP. “These are not the credentials you are looking for” they tell us.

Firesheep proves that comprehensively wrong. Surf your favourite login-requiring site on an open network, and *BANG*, you’re pwned. Awesome piece of work. Eric Butler, the author, says

Websites have a responsibility to protect the people who depend on their services. They’ve been ignoring this responsibility for too long, and it’s time for everyone to demand a more secure web. My hope is that Firesheep will help the users win.

« Previous PageNext Page »

Powered by WordPress