Showing posts with label FreeBSD. Show all posts
Showing posts with label FreeBSD. Show all posts

Sunday, March 29, 2015

FreeBSD SMB Client under OSX Host

I recently purchased a new Macbook Pro and wanted to get a FreeBSD Virtual Machine set up in order to continue doing development work on it. Unfortunately, FreeBSD as a guest does not support native folder sharing so I decided to try using a samba mounted.

I decided to set up my VM to have two network interfaces: a NATed interface for internet access and a host-only interface for access to SMB and ssh.

The NAT networking configuration looks like:

NetworkName:    FreeBSDNatNetwork
IP:             10.0.2.1
Network:        10.0.2.0/24
IPv6 Enabled:   Yes
IPv6 Prefix:
DHCP Enabled:   Yes
Enabled:        Yes
Port-forwarding (ipv4)
        SSH IPv4:tcp:[]:5022:[10.0.2.4]:22
Port-forwarding (ipv6)
        FreeBSD ssh:tcp:[]:6022:[fd17:625c:f037:2:a00:27ff:fefc:9dab]:22
loopback mappings (ipv4)

The Host-Only networking configuration looks like:

Name:            vboxnet0
GUID:            786f6276-656e-4074-8000-0a0027000000
DHCP:            Disabled
IPAddress:       192.168.56.1
NetworkMask:     255.255.255.0
IPV6Address:     
IPV6NetworkMaskPrefixLength: 0
HardwareAddress: 0a:00:27:00:00:00
MediumType:      Ethernet
Status:          Up
VBoxNetworkName: HostInterfaceNetworking-vboxnet0
The FreeBSD configuration looks like this: The OSX sharing configuration looks like:

Unfortunately, when attempting to actually mount the SMB filesystem with: mount_smbfs -I 192.168.56.1 //eax@192.168.56.1/shared_vbox I get the error mount_smbfs: can't get server address: syserr = Operation timed out

I tried installing the package net/samba36 and found that I needed the --signing=off flag to let it work:

It seems based on this setup and research that FreeBSD can not natively mount an OSX samba share. It might be possible to use sysutils/fusefs-smbnetfs. Other people have recommended NFS or sshfs.

Tuesday, October 9, 2012

Reduced Entropy in rand() and random()

TL;DR: Don't rely on undefined behavior, even when you think it should work.

I recently reported a minor issue to the FreeBSD security team.

The libc random functions had code1,2 designed to run when /dev/random is not available. This can easily occur in a chroot or jail environment.

if (!done) {
        struct timeval tv;
        unsigned long junk;

        gettimeofday(&tv, NULL);
        srandom((getpid() << 16) ^ tv.tv_sec ^ tv.tv_usec ^ junk);
        return;
}

This code is designed provide a minimal amount of entropy in the "failure" case. Unfortunately, it doesn't even provide the entropy it claims to. This is a minor issue because getpid, getimeday, and a single long variable don't provide a lot of entropy in the first place: (only $log_2{sizeof(long)}$ bits).

The point of the junk value is to add entropy by using uninitialized memory. This relies on the compiler being "stupid" enough not optimize it away.

Unfortunately clang and newer versions of gcc are smart enough to use the undefined behavior in undesired ways.

clang 3 removes any computation which relies on the undefined behavior and so produces the following object code:

 af0:   e8 5f fc ff ff          callq  754 <gettimeofday@plt>
 af5:   e8 7a fc ff ff          callq  774 <getpid@plt>
 afa:   e8 65 fc ff ff          callq  764 <srandom@plt>

Note that the junk variable is entirely unused and that the xor operation between gettimeofday and getpid is non-existent.

gcc 4.6 4 outputs:

 ce8:   e8 03 fa ff ff          callq  6f0 <gettimeofday@plt>
 ced:   e8 4e fa ff ff          callq  740 <getpid@plt>
 cf2:   48 8b 7c 24 08          mov    0x8(%rsp),%rdi
 cf7:   48 33 3c 24             xor    (%rsp),%rdi
 cfb:   c1 e0 10                shl    $0x10,%eax
 cfe:   48 98                   cltq
 d00:   48 31 c7                xor    %rax,%rdi
 d03:   e8 28 fa ff ff          callq  730 <srandom@plt>
Note that in this case the junk value appears to be (%rsp) which isn't all that random.

gcc 4.25 produces the following code

with the junk variable
 d9f:   e8 18 fa ff ff          callq  7bc <gettimeofday@plt>
 da4:   e8 43 fa ff ff          callq  7ec <getpid@plt>
 da9:   48 8b 3c 24             mov    (%rsp),%rdi
 dad:   48 33 7c 24 08          xor    0x8(%rsp),%rdi
 db2:   c1 e0 10                shl    $0x10,%eax
 db5:   48 98                   cltq
 db7:   48 31 c7                xor    %rax,%rdi
 dba:   48 31 df                xor    %rbx,%rdi
 dbd:   e8 1a fa ff ff          callq  <srandom@plt>
and without:
 d9f:   e8 18 fa ff ff          callq  7bc <gettimeofday@plt>
 da4:   e8 43 fa ff ff          callq  7ec <getpid@plt>
 da9:   48 8b 3c 24             mov    (%rsp),%rdi
 dad:   48 33 7c 24 08          xor    0x8(%rsp),%rdi
 db2:   c1 e0 10                shl    $0x10,%eax
 db5:   48 98                   cltq
 db7:   48 31 c7                xor    %rax,%rdi
 dba:   e8 1d fa ff ff          callq  7dc <srandom@plt>

The base version of gcc isn't vulnerable. However, with the upcoming switch to the clang compiler the FreeBSD does become vulnerable.

The first proposed fix was to add the volatile type qualifier to the junk variable. While this seemed to fix the code generation issue I didn't believe this to be a valid fix as the behavior is still undefined6 (I misread text of the standard). Additionally, the value is likely have be very predictable. A preference was expressed to remove the junk variable as using it may leak a small amount of stack data.

I proposed the simple and obvious fix of removing the use of the junk variable7

In a brief survey of other libraries I noticed similar issues. I will attempt to notify the vendors

It should be obvious, but undefined behavior is undefined and can't be relied on to ever to give a sensible result.

  1. random.c r165903 (line 316)
  2. rand.c r241046 (line 131)
  3. FreeBSD clang version 3.1 (branches/release_31 156863) 20120523 compiled with -O2 or -O3
  4. gcc46 (FreeBSD Ports Collection) 4.6.4 20120608 (prerelease) compiled with -O2
  5. gcc (GCC) 4.2.1 20070831 patched [FreeBSD] compiled with -O3
  6. sections 5.1.2.2.3 and 6.7.2.4 of ISO9899
  7. svn commit r241373
Edit 2010-10-10: update the paragraph referring to undefined behavior of volatile.

Monday, October 8, 2012

NFS Mount Network Booting VirtualBox

In order to test modifications to the FreeBSD kernel, I would like to boot a diskless virtual machine. The goal is to be able to quickly test changed I make without needing to recreate the VM each time, or run the installation procedure inside of the VM.

You can elect to put the root anywhere you want. For this example, I will be using /home/vm as the root of the virtual machine.

There are a few aspects to this:

  • The filesystem that will be booted.
  • VirtualBox setup
  • Virtual machine setup
  • DHCP server
  • Host setup

Filesystem Installation

  1. Create the distribution:
    cd /usr/src 
    make installworld installkernel distribution DESTDIR=/home/vm
    
  2. Create the /conf directory used for diskless boot. See /etc/rc.initdiskless for details.
    # cd /home/vm/
    # mkdir -p conf/base/etc
    # cd conf/base/etc
    # cat diskless_remount 
    /etc
    # cat fstab 
    md    /tmp    mfs    -s=30m,rw    0 0
    md    /var    mfs    -s=30m,rw    0 0
    # cat md_size 
    256m
    

VirtualBox Setup

Create a "host-only" interface with DHCP disabled. To do this:

  1. Open up the preferences screen and go the "network" tab.
    screenshot of the preferences screen
  2. Create a new host-only network (the green plus on the right).
    screenshot of the network preferences screen
  3. Disable the DHCP Server.
    screenshot of the host only network DHCP screen
  4. Select an IP Address in the range your VM will have.
    screenshot of the host only network preferences screen
  5. Note that the DHCP server will continue to run until killed or the machine rebooted:
    ## Note that you may kill too much here. Be careful.
    # pgrep -fl DHCP
    # pkill -15 DHCP
    

Create the Virtual Machine

  1. Create a new virtual machine. Make sure to select "FreeBSD - 64 bit". Note that you should create this machine without any disk (and ignore the warning at the end).
    filled in machine name and type screenshot
  2. Open up the virtual machine's settings
    default settings screenshot
  3. Select only the "Network" option under boot order (System->Motherboard->Boot Order). Also check "Hardware clock in UTC time."
    changed setting screen screenshot
  4. Under network select the Host Only Adapter created before. Under advanced options, change the adapter type to "PCNet-PCI II." Also make a note of the mac address of the virtual machine. It will be needed later.
    changed network setting screen screenshot

DHCP Server

For simplicity I opted to use a really simple DHCP server dnsmasq:
  1. Install dnsmasq
    $ make -C /usr/ports/dns/dnsmasq install clean
    
  2. Configure dnsmasq to server as a tftp and DHCP server for the virtual machine interface. Modify /usr/local/etc/dnsmasq.conf (I've bolded the parts that are configuration specific):
    interface=vboxnet0
    dhcp-range=172.16.100.100,172.16.100.200,48h[1]
    #Note that this mac address is the mac address of the vm noted earlier.
    dhcp-host=01:02:03:04:05:06,vm-testing,172.16.100.100,set:diskless
    dhcp-boot=tag:diskless,/home/vm/boot/pxeboot
    dhcp-option=tag:diskless,option:root-path,"/home/vm/"
    enable-tftp
    
  3. Add this to /etc/dhclient.conf so that you can reference your virtual machine by name:
    precede domain-name-servers 127.0.0.1;
    

Host Setup

  1. Add the following to /etc/rc.conf:
    # Required for VirtualBox
    devfs_system_ruleset="system" 
    
    # Required for diskless boot
    dnsmasq_enable="YES"
    
    # NFS Exports
    rpcbind_enable="YES"
    nfs_server_enable="YES"
    mountd_enable="YES"
    mountd_flags="-r"
    nfs_client_enable="YES"
    weak_mountd_authentication="YES"
    
  2. Add the directory to /etc/exports:
    /home/vm -ro -alldirs -network 172.16.0.0 -maproot=root
    

Now you are all set. Just boot the virtual machine from VirtualBox and watch it go!


  1. Note that the 172.16.0.0/20 network is RFC 1918 private address space.

Monday, September 20, 2010

Proccess Kernel States (wchan in ps)

FreeBSD has a nice feature that will signal a process with SIG-INFO when you press Ctrl-T and will tell you some other interesting data about the process such as the load of the CPU, current command that is being run, and the kernel state the process is in (the wchan keyword in ps(1)).
This state is set by the msleep function and is a syscall or lock that the proccess is waiting on

I know of no other list explaining each of these states so here it goes:

biord: block on io read.
futex: [Linux emulation] process is waiting until a futex is released (see fast userspace mutex)
getblk: get block (seems to be generated often by tar)
nanoslp: process is sleeping for some number of nanoseconds (see nanosleep(2))
pause: process is waiting for a signal (see pause(3))
pcmwrv: waiting for audio samples to be played
piperd: read(2) from a pipe
pipewr: write(2) to a pipe
physrd: reading from a HDD
runnable: process is ready to run on the CPU
running: currently on CPU
sbwait: wait for socket to return data (see uipc_sockbuf.c) 
swread: read in from swap
stopev: process is stopped because of a debugging event (see sys_process.c; relates to ptrace(2))
tttout: write(2) to a tty
ttyin: read(2) from a tty
ucond: a proccess is blocked until a pthreads mutex is released
vnread: part of the pager (see vnode_pager.c)
wait: wait(2) for a child process
wdrain: write drain. On a device mounted with the async option (or soft-updates) wait until all the previous writes have been completed. (see vfs_bio.c)
zombie: a process died but its parent did not wait(2) for it.

There are other syscalls that are similar to the ones mentioned above (such as readv(2) instead of read(2), and waitpid(2) instead of wait(2)) which will end up with the same wchans.

Thank you irc://irc.efnet.org/nox--- for helping me figure out what all of these mean.

I will try to keep this list up-to-date as I find out about more of them.

Update 9/21/10: removed "CPU0" state - it doesn't show up in the siginfo output - only in the top output.
Update 9/22/10: added getblk entry without link to syscall
Update 10/7/10: added wdrain, swread - I have a /lot/ more to add. 
I need to add all the following - and more: sfbufa, umtxqb, psleep, qsleep, bo_wwait, bwunpin, sigwait, pause, suspkp suspkp ktsusp  mntref, "mount drain", roothold, rootwait, failpt, exithold, exit1, ritwait , kqflxwt, kqclose, kqclo1, kqclo2, kqkclr, kqflxwt, ithread, iev_rmh , purgelocks, conifhk, aioprn, aiordy, aiospn, aiowc vlruwt vlruwk targrd tgabrt cgticb cgticb  sgread simfree ccb_scanq crydev  crypto_destroy crypto_destroy crypto_ret_wait

Monday, November 30, 2009

Setting up wpa2

I've been trying to set up wpa2 for a while now. Unfortunately whenever I tried to run wpa_supplicant I got "No compatible AP found". Adding a reference to WPA in rc.conf solved the problem even though I set it up not to start automatically.

# This is because I usually use wlan0 not DHCP
wlans_ndis0="wlan0";
ifconfig_wlan0="DHCP"
# I manually destroy wlan0 and create wlan1. This lets me use wpa_supplicant manually.
ifconfig_wlan1="WPA DHCP"