Sun, 15 Aug 2010

Review of Droid X

Yesterday I bought a Droid X because my iPhone 3G has serious battery issues when I am using data. It's to the point where I spent most of Defcon with my phone plugged into my laptop in my bag. When I first bought my iPhone there was no decent competition in the market so I went with it. Times have changed and there is now a couple of phones that are worth looking at.

I picked the Droid X. There's no definitive functionality that I liked in it over the other Droid phones. I simply liked the form factor and did not require a physical keyboard. So far I do not regret my decision from a hardware perspective.

My biggest complaint is that the UI feels completely unpolished when compared to iOS' UI. The default UI from Motorola takes the idea of a smartphone to it's painful extreme. There is simply too much going on in the default UI. And on top of all of that the visual effect is very painful: there are a lot of obtrusive icons everywhere making it very cumbersome.

As I take the time to turn 99% of the worthless crap Motorola ships with the phone off I find that the UI is nice and easy to follow. It's a drastic difference from the "built for idiots" UI that the iPhone has. This one feels like a real OS and not some bastardized single-tasking joke. I can do so much more with this phone than with my iPhone and I haven't even scratched the surface.

It may seem like the previous two paragraphs are in direct contradiction to each other. The beauty of the iPhone is it's UI. It is very easy to use and navigate around in. The downside of the iPhone is that unless you want to jailbreak it and jump through a crap ton of hoops it's very limited it what you can do with it. Even once you jailbreak it you have to deal with some fundamental problems with the OS. The beauty of the Droid X is that you are not as easily limited. Sure, you can jump through the same hoops and have even more freedom but generally speaking it just feels like a proper OS. The downside of the Droid X is that Motorola crams it so full of things that it's a pain in the ass to use and navigate around in by default.

My biggest wish at this point is that Motorola needs to hire some UI people who can build something that makes me believe I'm using a well polished product and not a bunch of shitty software built upon a nice OS.

I also have a couple of friends who are quite smart in the area of Droid hacking. I fully intend to pick their brains on ways I can drop some of this crap from my phone and get to a decent UI that doesn't make me cringe every time I use it.

posted at: 09:20 | tags: | path: /entries/geek | permanent link to this entry

Thu, 29 Apr 2010

GELI + ZFS. Easy.

Someone recently asked me how I would run ZFS on top of GELI devices. It's not that hard. Here's how I did it using two vnode backed md(4) devices since I didn't have any spare drives or slices laying around.

wxs@ack wxs % truncate -s 10G a b  
wxs@ack wxs % sudo mdconfig -a -t vnode -f a
Password:
md0
wxs@ack wxs % sudo mdconfig -a -t vnode -f b
md1
wxs@ack wxs % dd if=/dev/random of=key bs=64 count=1
1+0 records in
1+0 records out
64 bytes transferred in 0.000145 secs (441506 bytes/sec)
wxs@ack wxs % sudo geli init -s 4096 -K key -P /dev/md0 

Metadata backup can be found in /var/backups/md0.eli and
can be restored with the following command:

	# geli restore /var/backups/md0.eli /dev/md0

wxs@ack wxs % sudo geli init -s 4096 -K key -P /dev/md1

Metadata backup can be found in /var/backups/md1.eli and
can be restored with the following command:

	# geli restore /var/backups/md1.eli /dev/md1

wxs@ack wxs % sudo geli attach -k key -p /dev/md0 
wxs@ack wxs % sudo geli attach -k key -p /dev/md1
wxs@ack wxs % sudo zpool create foo mirror /dev/md0.eli /dev/md1.eli
wxs@ack wxs % zpool list foo
NAME   SIZE   USED  AVAIL    CAP  HEALTH  ALTROOT
foo   9.94G   364K  9.94G     0%  ONLINE  -
wxs@ack wxs % zpool status foo
  pool: foo
 state: ONLINE
 scrub: none requested
config:

	NAME         STATE     READ WRITE CKSUM
	foo          ONLINE       0     0     0
	  mirror     ONLINE       0     0     0
	    md0.eli  ONLINE       0     0     0
	    md1.eli  ONLINE       0     0     0

errors: No known data errors
wxs@ack wxs %

posted at: 13:56 | tags: , , | path: /entries/geek | permanent link to this entry

Mon, 22 Mar 2010

On Distributed SCM and Somewhat-Misleading Statements...

One thing I've heard mentioned over and over the past couple of days is how a distributed SCM saved the day when the owner of the domain took the master copy off-line. What people keep saying is that the fact that it was a distributed SCM was great because they all had a copy of the code and they were able to host it elsewhere. What they really mean is that they had a copy of the repository (code + history) and were able to host that elsewhere.

If a centralized SCM is taken off-line I can take the latest copy I have of the source, dump it into a new SCM and host that. I will lose the history, which is almost as important as the source in a long-running project, but I will still be able to continue. This, obviously, assumes that the source was checked out somewhere.

I know it's nit-picking but from a "the source is never lost" standpoint there is no difference between a distributed SCM and a centralized SCM. As long as someone has checked it out you can always keep going from that point forward if the main repository is taken off-line.

posted at: 16:39 | tags: , | path: /entries/geek | permanent link to this entry

CarolinaCon 6 - Best One Yet.

So CarolinaCon 6 happened this past weekend. It was, in my opinion, the best one yet. I was given the opportunity to rant for an hour and as far as I can tell I didn't get in any fights over it. Next year I promise to actually have something interesting to talk about. ;)

If you were at the conference and I got a chance to meet you for the first time, or if you are someone I've known from before and I got to see you again, thank you for making it another memorable experience for me. One thing I love about CarolinaCon is the small, intimate nature of it. It really emphasizes the human aspect of the scene (or industry in some cases), which is something the bigger conferences simply can not do.

So if you were there and are reading this I'd like to say thank you. If you were there, and are reading this and I got a chance to speak with you, even for a short time, I'd like to say thank you. If you were not there then you should have been, and I hope to see you there next year.

posted at: 06:55 | tags: | path: /entries/geek | permanent link to this entry

Fri, 12 Mar 2010

I was looking over the release notes for OpenSSH 5.4. Among the list of nice things (key revocation, better passphrase protection, and certificates - though not X.509) in there I noticed support for a new -W option. The manual has this to say about it:

-W host:port
        Requests that standard input and output on the client be for-
        warded to host on port over the secure channel.  Implies -N, -T,
        ExitOnForwardFailure and ClearAllForwardings and works with Pro-
        tocol version 2 only.

The release notes specifically state:

 * Added a 'netcat mode' to ssh(1): "ssh -W host:port ..." This connects
   stdio on the client to a single port forward on the server. This
   allows, for example, using ssh as a ProxyCommand to route connections
   via intermediate servers. bz#1618

That sounds nice and like it will save me from having to do things in a two step process. Normally I have to do ssh -L 7272:gmail-smtp-in.l.google.com:25 syn and use nc localhost -p 7272 or something else in another terminal to get data out through the tunnel. Now with -W it's combined into one simple step.

wxs@ack wxs % ssh -W gmail-smtp-in.l.google.com:25 syn     
220 mx.google.com ESMTP 14si5094846qyk.3
EHLO PANTS!
250-mx.google.com at your service, [129.21.50.215]
250-SIZE 35651584
250-8BITMIME
250-ENHANCEDSTATUSCODES
250 PIPELINING

I like things that make my life easier.

posted at: 09:19 | tags: | path: /entries/geek | permanent link to this entry

Mon, 16 Nov 2009

This Can't Be Right.

        if (eocd[i  ] == 0x50 && eocd[i+1] == 0x4b &&
            eocd[i+2] == 0x05 && eocd[i+1] == 0x06) {
            // if the sequence $50 $4b $05 $06 appears anywhere after
            // the real one, minzip will find the later (wrong) one,
            // which could be exploitable.  Fail verification if
            // this sequence occurs anywhere after the real one.

A friend who is poking around at Android code came across that and pointed it out to me. I took a look at the git repository and it's still there (git://android.git.kernel.org/platform/bootable/recovery). I don't know any reality where that will ever be true.

posted at: 15:42 | tags: , | path: /entries/geek | permanent link to this entry

Fri, 18 Sep 2009

Adventures in Soekris Land - Part I

As I've mentioned before I was recently given a net4501 by Jordan. Now that I'm moved into my new house I'm in the process of getting FreeBSD up and running on it. Since Jordan said he was seeing performance issues with it I figured it couldn't hurt to update the BIOS on the device first before I boot FreeBSD on it. It's actually a pretty simple process. All you need is lrzsz (ports/comms/lrzsz) and a serial cable.

Connect your serial cable and power on the board. You'll see the inital POST and then you have 5 seconds to hit Ctrl-P to break out of the boot sequence and into the "Monitor" which is basically a firmware prompt. Once you've got there issue the "download" command. Once you do that you have 30 seconds to start a file transfer of the image you want to flash. Using cu(1) to connect to the board you can use the ~C sequence to fork a child process where file descriptor 0 is the remote tty input, file descriptor 1 is the remote tty output and file descriptor 2 is the local tty stderr. The command you want to run is lsz -X <img.bin>. This will send the image over the serial port to the board which is waiting for it (and stores it at a special location in memory). Once the download is finished you can flash the freshly downloaded image onto the board using the "flashupdate" command.

Soekris has a great manual and a wiki which are both great sources of information.

Now that my board has the newest BIOS I'll be working on getting a FreeBSD image running on it. I think I'll start off with a simple PXE booting environment and eventually move to using the compact flash card as a boot environment. You can expect more updates as my Adventures in Soekris Land continues but for now I need to go to bed - my lawn needs to be cut in the morning (oh, the joys of being a home owner =b).

posted at: 22:27 | tags: | path: /entries/geek | permanent link to this entry

Wed, 09 Sep 2009

Way to respect TTL, VMware.

Here's something fun. Here's a DNS query that looks right:

wxs@ack wxs % dig @4.2.2.1 +nocmd +nocomments +noquestion +nostats syn.atarininja.org
syn.atarininja.org.     1771    IN      A       129.21.60.158
wxs@ack wxs % 

Here's the same query but from a NAT'ed VM (VMware Workstation) using the NAT device as a DNS server:

wxs@rst wxs % dig @192.168.2.2 +nocmd +nocomments +noquestion +nostats syn.atarininja.org
syn.atarininja.org. 5       IN      A       129.21.60.158
wxs@rst wxs % 

The TTL is always 5. It's not like it starts at 5 and counts down. It's always 5. The NAT device acts as a DNS proxy, forwarding requests to whatever DNS server the host machine uses. I checked these requests and the response coming back has the real TTL. Why does VMware feel the need to manipulate TTL values on DNS responses?

posted at: 12:33 | tags: | path: /entries/geek | permanent link to this entry

Mon, 08 Jun 2009

ZFS + NFS = Crash :(

I started to experience a crash recently that was triggered when building something in my tinderbox setup. This particular tinderbox is running on ZFS and uses NFS mounts on localhost. The panic and backtrace look like this:

Fatal trap 12: page fault while in kernel mode
cpuid = 0; apic id = 00
fault virtual address   = 0x6dc
fault code              = supervisor read data, page not present
instruction pointer     = 0x20:0xffffffff80572e7f
stack pointer           = 0x28:0xffffff803e722530
frame pointer           = 0x28:0xffffff803e722550
code segment            = base 0x0, limit 0xfffff, type 0x1b
                        = DPL 0, pres 1, long 1, def32 0, gran 1
processor eflags        = interrupt enabled, resume, IOPL = 0
current process         = 1030 (nfsd: service)
[thread pid 1030 tid 100140 ]
Stopped at      prison_priv_check+0xff: movl    0x6dc(%rsi),%eax
db> bt
Tracing pid 1030 tid 100140 td 0xffffff00029ea000
prison_priv_check() at prison_priv_check+0xff
priv_check_cred() at priv_check_cred+0x4c
secpolicy_vnode_access() at secpolicy_vnode_access+0x28
zfs_zaccess() at zfs_zaccess+0x1d5
zfs_freebsd_access() at zfs_freebsd_access+0xd0
VOP_ACCESS_APV() at VOP_ACCESS_APV+0x44
nfsrv_access() at nfsrv_access+0xf3
nfsrv3_access() at nfsrv3_access+0x386
nfssvc_program() at nfssvc_program+0x1fb
svc_run_internal() at svc_run_internal+0x6d2
svc_thread_start() at svc_thread_start+0xb
fork_exit() at fork_exit+0x118
fork_trampoline() at fork_trampoline+0xe
--- trap 0xc, rip = 0x8006a0e1c, rsp = 0x7fffffffe6d8, rbp = 0x5 ---
db> 

Here's the relevant pieces of prison_priv_check():

/*
 * Check with permission for a specific privilege is granted within jail.  We
 * have a specific list of accepted privileges; the rest are denied.
 */
int
prison_priv_check(struct ucred *cred, int priv)
{

        if (!jailed(cred))
                return (0);

        switch (priv) {

...

               /*
                 * Depending on the global setting, allow privilege of
                 * mounting/unmounting file systems.
                 */
        case PRIV_VFS_MOUNT:
        case PRIV_VFS_UNMOUNT:
        case PRIV_VFS_MOUNT_NONUSER:
        case PRIV_VFS_MOUNT_OWNER:
                if (cred->cr_prison->pr_allow & PR_ALLOW_MOUNT)
                        return (0);
                else
                        return (EPERM);

...

Loading up the core in kgdb for analysis it becomes very clear what is going on.

(kgdb) frame 12
#12 0xffffffff80572e7f in prison_priv_check (cred=0xffffff00168f5900, priv=334) at /usr/home/wxs/freebsd/src/head/sys/kern/kern_jail.c:3315
3315            switch (priv) {
(kgdb) p/x *cred
$7 = {cr_ref = 0x1, cr_uid = 0x0, cr_ruid = 0x0, cr_svuid = 0x0, 
  cr_ngroups = 0x1, cr_groups = {0x0 }, cr_rgid = 0x0, 
  cr_svgid = 0x0, cr_uidinfo = 0x0, cr_ruidinfo = 0x0, cr_prison = 0x0, 
  cr_vimage = 0x0, cr_flags = 0x0, cr_pspare = {0x0, 0x0}, cr_label = 0x0, 
  cr_audit = {ai_auid = 0x0, ai_mask = {am_success = 0x0, am_failure = 0x0}, 
    ai_termid = {at_port = 0x0, at_type = 0x0, at_addr = {0x0, 0x0, 0x0, 
        0x0}}, ai_asid = 0x0, ai_flags = 0x0}}
(kgdb) 

It's clear that cred->cr_prison is bad. But this isn't the real meat of the problem. The first check in prison_priv_check() is to see if we are jailed, and that looks something like this:

/*
 * Return 1 if the passed credential is in a jail, otherwise 0.
 */
int
jailed(struct ucred *cred)
{

        return (cred->cr_prison != &prison0);
}

Up until fairly recently this function used to contain:

        return (cred->cr_prison != NULL);

So, because cred->cr_prison is NULL in our case the check in prison_check_cred() is evaluating to false, when it should be evaluating to true. So now we know why we are crashing (NULL ptr dereference) we still don't know what is causing cr_cred to be NULL.

Credentials like this are derived from a very small number of places. The reason these are wrong is that the RPC code in the kernel doesn't know which credentials to assign when it handles the request. Luckily a workaround has been put in place while a more proper solution is being worked on.

posted at: 12:48 | tags: , , | path: /entries/geek | permanent link to this entry

Mon, 06 Apr 2009

getrusage() and another example of Linux failure.

So I'm writing some code for work and I need to know the current stack usage. One would think getrusage() would be nice to use. Think again. To quote the manual page on Ubuntu:

           struct rusage {
               struct timeval ru_utime; /* user time used */
               struct timeval ru_stime; /* system time used */
               long   ru_maxrss;        /* maximum resident set size */
               long   ru_ixrss;         /* integral shared memory size */
               long   ru_idrss;         /* integral unshared data size */
               long   ru_isrss;         /* integral unshared stack size */
               long   ru_minflt;        /* page reclaims */
               long   ru_majflt;        /* page faults */
               long   ru_nswap;         /* swaps */
               long   ru_inblock;       /* block input operations */
               long   ru_oublock;       /* block output operations */
               long   ru_msgsnd;        /* messages sent */
               long   ru_msgrcv;        /* messages received */
               long   ru_nsignals;      /* signals received */
               long   ru_nvcsw;         /* voluntary context switches */
               long   ru_nivcsw;        /* involuntary context switches */
           };

[...]

       The  above struct was taken from 4.3BSD Reno.  Not all fields are mean-
       ingful under Linux.  In linux 2.4 only the fields  ru_utime,  ru_stime,
       ru_minflt, and ru_majflt are maintained.  Since Linux 2.6, ru_nvcsw and
       ru_nivcsw are also maintained.

I can understand having the same struct for portability reasons. It's nice that code can be portable between the two at compile time but this is opening itself up to run-time problems if code assumes all the members of the struct will be populated.

I'm not sure why it's only barely implemented but it's quite annoying. The same function call on FreeBSD gives all the information, and the manual page under FreeBSD has useful information on what each of the members of the struct means. Linux fails, again.

gdb output on Linux:

(gdb) p/x *usage
$1 = {ru_utime = {tv_sec = 0x0, tv_usec = 0xfa0}, ru_stime = {tv_sec = 0x0,
    tv_usec = 0xbb83}, ru_maxrss = 0x0, ru_ixrss = 0x0, ru_idrss = 0x0,
  ru_isrss = 0x0, ru_minflt = 0x2fe, ru_majflt = 0x0, ru_nswap = 0x0,
  ru_inblock = 0x0, ru_oublock = 0x0, ru_msgsnd = 0x0, ru_msgrcv = 0x0,
  ru_nsignals = 0x0, ru_nvcsw = 0x7b, ru_nivcsw = 0x1}
(gdb)

gdb output on FreeBSD:

(gdb) p/x *usage
$3 = {ru_utime = {tv_sec = 0x0, tv_usec = 0x0}, ru_stime = {tv_sec = 0x0,
    tv_usec = 0x3ac7}, ru_maxrss = 0x8e8, ru_ixrss = 0x3f8, ru_idrss = 0xec,
  ru_isrss = 0x100, ru_minflt = 0xeb, ru_majflt = 0x0, ru_nswap = 0x0,
  ru_inblock = 0x0, ru_oublock = 0x0, ru_msgsnd = 0x0, ru_msgrcv = 0x0,
  ru_nsignals = 0x0, ru_nvcsw = 0xc, ru_nivcsw = 0x1}
(gdb)

posted at: 16:46 | tags: , , | path: /entries/geek | permanent link to this entry