Thu, 24 Dec 2009

CFT: Sudo Update

If you use Sudo on FreeBSD and want to test out an update for it please apply the patch from here and rebuild/reinstall the port. I'm especially interested in environments using ldap, kerberos and newer releases of FreeBSD (specifically 8.0). I'll take reports of success or failure for anything though. Since this is such a heavily used port I want to make sure I get it correct and cause as little headache for myself and others as possible.

posted at: 14:02 | tags: , , | path: /entries/freebsd | 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

Fri, 14 Aug 2009

Soekris net4501 Acquisition

Thanks Jordan!

I've been quiet because I bought a house. Things have been hectic, to say the least, with that and are only going to get more hectic as we prepare to move in and finally move in. I'm hoping that by the end of September I'll be settled in and can get back to doing more than just updating ports.

The picture above will be one of my first projects. It's a net4501 donated to me by Jordan. He said he was having network performance issues with it and I said I would take it off his hands to replace my dying Linksys. Along with that piece of hardware to work on I've had another donation (which is currently in Northern Virginia pending my arrival to pick it up and bring it home) which will make a fine addition to my house. I'll give details once I have them in picture form. It supposedly doesn't work with -CURRENT so my first task with that will be to figure out why and fix it.

Things will likely continue to be quiet around here until my life settles back to normal.

posted at: 20:35 | tags: | path: /entries/freebsd | permanent link to this entry

Fri, 17 Jul 2009

My, How They Grow...

I just made the commit to note that my mentee, Steven Kreuzer, is flying solo. He's been a pleasure to work with and I know will go forth and do great things. Keep up the good work Steven!

posted at: 09:30 | tags: | path: /entries/freebsd | permanent link to this entry

Sat, 20 Jun 2009

What is really meant by "STABLE" branches in FreeBSD.

A question I am routinely asked by people is what is the latest stable FreeBSD release. People are often tripped up by the fact that there are usually two releases listed on the front page of FreeBSD.org. The best way to answer that question is to explain how branches are done in FreeBSD. The question almost always comes from people who don't understand the details so I'll do my best to explain them here.

Perhaps it's best explained in picture form (somewhat simplified for explanation purposes):

---V-------------------------------V----------------------> CURRENT
    \-V------V----V-----------------\---> RELENG_6
       \------\----\--> RELENG_6_0   \
               \----\--> RELENG_6_1   \
                     \----> RELENG_6_2 \---V---V-------> RELENG_7
                                            \---\---> RELENG_7_0
                                                 \------> RELENG_7_1

Tag:       | Meaning:
.          | CURRENT
RELENG_6   | 6-STABLE (at the time of fetching)
RELENG_6_0 | 6.0-RELEASE-WITH-PATCHES-FOR-SECURITY-AND-MAJOR-ERRATA
RELENG_6_1 | 6.1-RELEASE-WITH-PATCHES-FOR-SECURITY-AND-MAJOR-ERRATA
RELENG_6_2 | 6.2-RELEASE-WITH-PATCHES-FOR-SECURITY-AND-MAJOR-ERRATA
RELENG_7   | 7-STABLE (at the time of fetching)
RELENG_7_0 | 7.0-RELEASE-WITH-PATCHES-FOR-SECURITY-AND-MAJOR-ERRATA
RELENG_7_1 | 7.1-RELEASE-WITH-PATCHES-FOR-SECURITY-AND-MAJOR-ERRATA

There is a lot going on here so we'll start with the terminology. In FreeBSD, "CURRENT" is the very tip of the tree, "STABLE" is a branch off of that tree, and "RELEASE" are branches off of the STABLE line. In FreeBSD there are multiple STABLE branches and each one has multiple RELEASE branches off of it. With that picture and terminology in mind it's best to next explain what gets committed into each branch.

All new commits go into head (CURRENT) first - there are very few exceptions to this. Simply leaving things in head would make for a pretty hectic process for consumers of the FreeBSD source code as people/companies often use FreeBSD as a base for a product. Only having CURRENT to develop a product with is never a good idea. After some settling time in head a commit can possibly be merged to a STABLE branch.

STABLE branches provide a point in the tree where the team has decided that data structures look good and are not going to change. I'll provide more details on what this means later. The most important factor in determining what can be merged from CURRENT (MFC, sometimes called merge from head (MFH)) to a STABLE branch is something called ABI stability. I'll explain what this means later but for now the commit is generally not allowed if it breaks the ABI. It's important to note that not all commits in head get merged to a STABLE branch. It really depends upon what it is and if it is deemed important enough to make it into the next release off that particular STABLE branch. Something that often trips up users of FreeBSD is that a STABLE branch is still a development branch. Due to the way commits are done in CURRENT first and merged into a STABLE branch later it's usually the case that a STABLE branch is more stable (in the "least likely to crash" sense) but it's important to note that it is still an active development effort.

RELEASE branches are branched off of a STABLE line and are the most tightly controlled of them all. These only get security and major errata updates. In the "least likely to crash" sense, a RELEASE branch is the right choice.

If all that makes sense then it's time to explain what ABI stability is and why it is so important to the FreeBSD development model. Imagine a situation where a company is building a something with FreeBSD. If they were using CURRENT they would be subject to any of the data structure changes going on. If any of these changes were to affect their code they would have to adjust their code. By picking STABLE branch they are not subject to any data structure changes (which is probably the biggest worry as other parts of the ABI are so rarely changed), nor any of the other things which could possibly break ABI. Beyond providing a slightly more tested area for users and consumers a STABLE branch allows for code to be built on FreeBSD that is guaranteed to work across the lifetime of the STABLE branch. This allows for resources to be better utilized. Compare that to other development efforts where not only is the ABI constantly broken but entire subsystems are ripped out and replaced between releases. Imagine having to keep track of what changed and what that means to your product. By picking a STABLE branch that worry is lessened (you should still pay attention to the commits to see if they provide new features or bug fixes that interest you) because you know the underlying binary interface you are using will not change.

So what does this mean to you? If you're an average user who just wants things to work I would recommend a RELEASE branch and upgrading between them when a new one is made. If you're a company building something using FreeBSD I would recommend following a STABLE branch. If you have the resources and are looking to the future I would also recommend that as a new STABLE branch nears you focus on moving your code to CURRENT for testing. This gives you the ability to maintain releases based upon code in a STABLE branch while making sure that you have an upgrade path to the next STABLE branch in the future, because the last thing you want to do is get stuck maintaining a EoL (End of Life) STABLE branch on your own (it's probably a waste of your resources). If you're an enthusiast, developer or just plain looking to get the most cutting edge features you can run CURRENT.

Hopefully this made sense to people not very familiar with how the development in FreeBSD works at a high level. If you're looking for more reading I would recommend at least this page in the handbook.

posted at: 15:18 | tags: | path: /entries/freebsd | permanent link to this entry

Tue, 16 Jun 2009

Package List (plist) Details

For the most part plists (in FreeBSD ports) are simply a listing of files installed by the port relative to ${PREFIX}. The contents of the plist get put into the +CONTENTS file in the package. Failure to get the plist correct in the port causes the package and the port to not properly clean up after itself, which leads to stray files on your machine. Not only is it a tidy problem it can potentially cause problems later on down the road. It's not hard to imagine a scenario where a binary is left laying around with a vulnerability in it. It is important to get plists correct to ensure a happy user experience.

Probably the most common thing you will see done in plists besides listing files is handling configuration files during (de)installation. This is well documented in the handbook (and don't forget to put the corresponding part in the Makefile as the plist is not processed when using the port). You can actually do a lot more with the plist if you need to, though it is not often the case.

I've had a few people ask me recently how plists work so I thought I would document what I consider to be a good resource regarding plists. When in doubt I always take a look at pkg_create(1) - specifically the PACKING LIST DETAILS section. If you're working on a port and get yourself confused when dealing with the plist I would look through that and it will most likely clear up any issue you have.

posted at: 17:10 | tags: , | path: /entries/freebsd | permanent link to this entry

Wed, 10 Jun 2009

Upgrading Python with Portmaster

If you are upgrading python on FreeBSD to 2.6 the steps as they stand now require portupgrade to be installed. This is based purely on the usage of pkg_which when walking /usr/local/lib/python$ver to determine what ports to rebuild.

Last night I came up with a patch that allows one to use portmaster instead of portupgrade. It's slower because it uses pkg_info. My guess is that pkg_which is using the pkgdb used by the portupgrade suite, which makes it significantly faster then how pkg_info works. We try to parallelize the processing but it's still slow - IMO we could greatly increase the amount of parallelism going on but I'm not going to push it too far.

The patch is available at my FreeBSD space and will apply cleanly to the latest lang/python port. I intend to commit it tomorrow morning while I'm eating breakfast but if you want to test it out now just do the following:

cd /usr/ports/lang/python
fetch - http://people.freebsd.org/~wxs/python26-portmaster.diff | patch
portmaster -o lang/python26 lang/python25
make upgrade-site-packages -DUSE_PORTMASTER

posted at: 12:45 | tags: , , | path: /entries/freebsd | 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