tag:blogger.com,1999:blog-35976177900380016742024-02-07T12:36:26.908-08:00Mud SlideUseful things to know if you are a software engineerUnknownnoreply@blogger.comBlogger27125tag:blogger.com,1999:blog-3597617790038001674.post-61255824417702773462014-01-19T15:00:00.000-08:002014-01-20T14:30:11.616-08:00Installing Linux on ZyXel NSA-320 - Part 3 - Boot and install OS from USB<div style="text-align: center;">
<span style="background-color: red; color: white; font-size: large;">Warning: This process will erase data on your primary hard disk!</span></div>
<br />
You may be wondering why you needed to get a telnet back door in Part 1. Well, when I did this previously, I didn't have a serial cable and it was easier (but extremely risky) just to reflash the nand with uboot by writing a file over the flash device in /dev. However, the NSA320 already has u-boot in flash so nothing needs modifying there. Plus, with the serial cable, you get access to the system via the serial console. I am using a modified Nokia serial cable, plugged into the serial connector on the NSA320.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-e8t9Zt_TD-Q/UpvBcYaLUvI/AAAAAAAAPQk/XfaIF3aIBl8/s1600/20131201_222641.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/-e8t9Zt_TD-Q/UpvBcYaLUvI/AAAAAAAAPQk/XfaIF3aIBl8/s640/20131201_222641.jpg" height="386" width="640" /></a></div>
<br />
I have also used an SD card reader as a USB host device, since I didn't have a USB drive to hand. You can see the serial cable plugged into the serial connector on the NSA320 motherboard.<br />
<br />
To get started, download the following tarball:<br />
<br />
<a href="http://os.archlinuxarm.org/os/nsa3x0/nsa320-alarm.tar.gz">nsa320-alarm.tar.gz</a><br />
<br />
You need to unpack the contents of this tarball to a FAT formatted USB drive. In my case, this is the SD card I have connected via the card reader on the USB port in the picture. You should find four files in the tarball, used by u-boot to boot into the ArchLinux distro. But before you can do that, you need to get the root file system tarball and place that on the USB drive as well. You can download the ArchLinux root fs here:<br />
<br />
<a href="http://us.mirror.archlinuxarm.org/os/ArchLinuxARM-armv5te-latest.tar.gz">ArchLinuxARM-armv5te-latest.tar.gz</a><br />
<br />
When you copy to the USB drive, you need to rename it to just <b>rootfs.tgz</b>. Once copying has finished, sync disks a couple of times and unmount the USB drive. Connect it up to the front USB port on the NSA-320 and connect up your serial cable. Run up minicom as root:<br />
<br />
<span style="color: #6aa84f;"># minicom -D /dev/ttyUSB0</span><br />
<span style="color: #6aa84f;"><br /></span>
Now when you power on the NSA-320, you can monitor the install process. Essentially, the stock OS on the NSA320 looks for files and scripts on the USB drive if attached. If a certain script is present, it will execute the script. The script on the USB drive is the ArchLinux installer that unpacks the rootfs.tgz to the primary hard drive, after repartitioning it and formatting it with an EXT file system. It takes a while dependent on the size of the hard drive, but once complete it will reboot and boot the kernel from the primary hard disk's boot partition. The boot partition doesn't get mounted automatically in fstab, so just remember to mount it before you install a new kernel. Otherwise, your new kernel will be installed to the boot directory on the root file system and will never be booted by u-boot.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/uPbq5JHgEm8?feature=player_embedded' frameborder='0'></iframe></div>
<br />
In order to get the DHCP client to obtain an address dynamically, some extra work is needed to ensure a hardware flag is set that prevents this. There is a script I created post install that fixes this and requires a subsequent reboot. The script is installed as a systemd script, to ensure the flag is set on each boot, in case the device is powered off for a prolonged period and the capacitor loses its state. I have made the following guide on creating the script and installing it as a systemd script.<br />
<br />
The script can be downloaded from: <a href="https://github.com/iwonbigbro/tools/blob/master/bin/power_resume">power_resume</a><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/lh8w7SCx-zQ?feature=player_embedded' frameborder='0'></iframe></div>
<h2>
Follow-up for power_resume</h2>
I initially had some trouble configuring netctl to reliably bring up the eth0 interface and noticed it was already up before having enabled it. After creating the video above, I did some further reading. It seems that there is a "roaming" network daemon that is started to handle network connections for certain interfaces - netctl-ifplugd. This handles cables being connected/disconnected and wireless connections coming in and going out of range. With this enabled and enabling the netctl@eth0 profile, conflicts occur with shutting down and starting up the DHCP client daemon. The solution is not to enable the netctl@eth0 profile and stick with the netctl-ifplugd profile that is configured by default. In order to make the power_resume script work, you just need to modify the dependency line in the systemd configuration script:<br />
<br />
[Install]<br />
WantedBy=netctl-ifplugd@eth0.service<br />
<br />
Changing that and then enabling and disabling the power_resume service (to reinstall it) should fix it.<br />
<h2>
Follow-up number two...</h2>
Well, second thing I learnt today is that you don't place your systemd configuration files in the /etc/systemd directory. This is the location of enabled services, so systemd is likely to get confused if you drop something in here without it being enabled. The actual location for system configuration is in /usr/lib/systemd. From this directory, any service can be enabled or disabled using the systemctl command.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-3597617790038001674.post-60497975254158884612013-12-23T12:57:00.001-08:002014-01-20T04:28:44.231-08:00Installing Linux on ZyXel NSA-320 - Part 2 - Making a USB serial cableYou can fly blind with this project, but it's so much easier and faster to fly with your eyes open, so making a serial cable to connect to the serial interface on the ZyXel is a no-brainer; especially since you can make a cable for less than £5. If you are willing to partake in some risky business, then skip the cable guide and proceed to part 3, where you can try installing Arch-Linux on your NSA-320.<br />
<br />
<h3>
<b>The Cable</b></h3>
I used the <a href="http://buffalo.nas-central.org/wiki/Use_a_Nokia_Serial_Cable_on_an_ARM9_Linkstation">NAS Central guide to using a Nokia serial cable for a Buffalo LinkStation</a> to construct a USB serial cable from a Nokia CA-42 cable. The guide describes how to attach/solder the cable to the motherboard of the Buffalo LinkStation, because the LinkStation doesn't have a serial connector attached to the board. However, the NSA-320 does have a serial connector, in the form of a set of four jumper pins. The reason for using this cable in particular, is it has a micro-controller built into the USB connector that acts as a transceiver for the high USB voltages, into the 3V signals present on serial interfaces. This is important, since it will prevent you from sending 5 volts from your USB port into the serial interface of the SoC on your NSA-320, potentially frying it. This is the cable I used, that I purchased from Amazon:<br />
<br />
<a href="http://www.amazon.co.uk/Nokia-CA-42-Connectivity-Adapter-Cable/dp/B0006N2DJC/">Nokia-CA-42-Connectivity-Adapter-Cable</a><br />
<br />
<h3>
<b>The Connector</b></h3>
So following the guide, you cut the Nokia attachment off the end of the cable, since that is the bit you won't be needing. In place of the connector, you need to attach four female jumper pins or jumper wires. I used wires and just soldered the wires together, wrapping insulating table between each wire. Be sure to use coloured wires that match the original Nokia wire colours. This will help you make sense of the wires later on. I used something like this:<br />
<br />
<a href="http://www.amazon.co.uk/Solderless-Flexible-Breadboard-Jumper-Cable/dp/B00D7SCT6A/">Solderless-Flexible-Breadboard-Jumper-Cable</a><br />
<br />
Obviously, you get a lot of wires and there are connectors at both ends. You just need to pick the four most appropriate wires, by colour. Then cut them in half and remove some of the insulation to expose the copper wire that you will solder to the wires on your Nokia cable.<br />
<br />
<h3>
<b>Finding TX, RX and GND</b></h3>
This is supposed to be a fairly trivial task. The guide above tells you to use a voltage meter to work out what wires are what, but this didn't help me at all, since I got a signal on only one wire and the ground. Instead, I went for pot luck and used minicom to work out what my GND, TX, and RX wires were. You will notice a spare wire, which is not required for a serial connection, so you just leave it disconnected from the NSA-320. You can put a jumper on it or tape it off with insulation tape once you have worked out what it is.<br />
<br />
So if like me, you aren't having much luck with the voltage meter, or you don't have a voltage meter. Fear not, you can quite safely short out some pins on the connector to work out what's what. Worst case scenario, you will short out the transceiver and need to buy another cable. Good news, the transceiver will prevent you from shorting out your USB port, so will protect your PC from any such short comings. Saying that, I've never managed to damage the transceiver, given that the serial connection end is only operating at 3 volts. Before you get trigger happy shorting out wires though, think about the cable colours. Even though cable colours are different for each cable (mine most certainly didn't match the guide on NAS central), they will definitely follow the basic wiring paradigm. Usually reds/browns indicate positive charge, green is most certainly a receiver (RX) while black/blue is generally GND. If you can establish that you have a black or blue wire with a green wire and two others your are not quite so sure of, you can find the TX wire by shorting each of the remaining wires with the RX wire one at a time, using minicom to check whether you have found the right one.<br />
<br />
So hook up your USB cable to your PC/laptop and run minicom from a terminal, attaching it to the USB device your just connected. If you're not sure, run dmesg to look for messages about a TTY device. My device appeared as /dev/ttyUSB0. Run it as root. It's worth noting that this is just my really hacky, lazy, CBA method for finding the TX and RX connectors and does require a lot of guess work and a little common-sense. However, you can be far more professional about it and use a voltage meter as I mentioned before. The guide on NAS Central covers this already and will assist you, should you wish to do things properly. If however, you want to take a more cowboy like approach, follow my lead :-)<br />
<br />
The general idea is that by shorting out the TX/RX pins, your will create a loop-back serial cable. This means that what you type will be echoed back to the terminal should you find the right TX wire and short it with your RX wire. At this point you don't need GND.<br />
<br />
You may find that you also get other characters printed out, mostly non-printable characters. But as long as you get back the characters that your type as well, you can be sure you have found the right ones. The extra characters are the result of interference coming from the lack of resistance between the RX and TX wires. You can add a resistor if you like, but it really isn't that important, especially not for a £5 cable.<br />
<br />
This is how mine looks, with the pin configuration and the coloured wires matching the original Nokia wiring. The unlabelled red wire is not required and can be considered redundant. You need only connect the GND, RX and TX connectors to the NSA-320.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKepL8EJoxs8j3J43jdbGNYotD1tIhM5U8arF9kWfVlQ9eZpmVbPQay4VsXIjWJ92vLS3vsfVkeSbDOTnJQUUJgOSH6rdIkB7y1KJWjLmADmI_yuFE3fRjrNxY7nY27c4c-FHeO5yuwQHd/s1600/20131223_190505.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKepL8EJoxs8j3J43jdbGNYotD1tIhM5U8arF9kWfVlQ9eZpmVbPQay4VsXIjWJ92vLS3vsfVkeSbDOTnJQUUJgOSH6rdIkB7y1KJWjLmADmI_yuFE3fRjrNxY7nY27c4c-FHeO5yuwQHd/s640/20131223_190505.jpg" height="386" width="640" /></a></div>
<br />
Here is a video demonstration of the lazy approach to finding TX and RX on your connector, before you potentially fry the serial interface on your NSA-320.<br />
<br />
<div style="text-align: center;">
<span style="background-color: red;"><span style="color: white;">You have every opportunity to do it properly, so you can still turn back. If you're feeling lucky...</span></span></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/nfUoKfsxkjU?feature=player_embedded' frameborder='0'></iframe></div>
<b><br /></b>
<br />
<h3>
<b>Connecting it all together</b></h3>
Once you know what wires are what, make a note of the colours and you can safely power off your NSA-320 and connect the serial cable to the serial interface. Disconnect it from your PC first, then once everything is connected, connect it back up to your PC. Here is the pin configuration on the NSA-320. Note that the VCC connection is not required, since USB serial cables are powered by the USB port of the PC. Also notice that there is a blank between the TX/RX pins and the GND. This helps identify which is which. Just remember that the GND is on its own.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9cjT3ONNvfJ1PrnK3aP-4TUDE-kg42hxp6vxTvpoieV0Cpp7E-px9iRZ460QWfLOTweFKpwmNo2BV3DZgSwbMol9PWKvH2vjcCvXig8G-05hXcooiB-GSzvYokWpCuuQoWIO-tRBVVcB7/s1600/20131223_193043.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9cjT3ONNvfJ1PrnK3aP-4TUDE-kg42hxp6vxTvpoieV0Cpp7E-px9iRZ460QWfLOTweFKpwmNo2BV3DZgSwbMol9PWKvH2vjcCvXig8G-05hXcooiB-GSzvYokWpCuuQoWIO-tRBVVcB7/s640/20131223_193043.jpg" height="386" width="640" /></a></div>
<br />
<br />
Once you've hooked it up, run minicom as described above and power on your NSA-320; you should immediately see the boot sequence being output in the minicom terminal. It should also now accept input from your terminal and respond to key-presses.<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
I will be following up soon with how to get ArchLinux installed and set up, and how to overcome some of the common issues with ArchLinux straight out of the box.<br />
<br />Unknownnoreply@blogger.com8tag:blogger.com,1999:blog-3597617790038001674.post-5686072934718498772013-12-01T09:59:00.002-08:002014-01-20T04:28:20.733-08:00Installing Linux on ZyXel NSA-320 - Part 1 - Telnet back doorMy MK802 finally gave up on me. It lasted a while, with the modifications I made to provide it with adequate cooling in order to operate around the clock. But a few weeks ago it went down and never came back. There seems to be some issue with power, where it will only last for about 10 or so seconds before it fills the syslog with spurious errors and then dies. Booting the OS on another device shows there is nothing wrong with the OS or SD card image, so it must be hardware. Anyway, on to matters at hand. So now I have just picked up a brand new ZyXel NSA-320 for £60. It is actually a very nice piece of kit on its own, with lots of features. But I want NIS and NFS, with support for EXT journalling file systems, so will be going back down the path of my old Buffalo NAS and flashing it.<br />
<br />
Here is the ZyXel NSA-320 in all its glory. To give you a feel for its size, that's a 3.5 HDD with an external 2.5 HDD. The ZyXel supports two internal 3.5 SATA HDD, has 512 MB ram, 128 MB of flash and a 1.2 GHz ARM926EJ-S CPU. So only 300 MB less on RAM than the MK802, but makes up for it in lots of other ways. For £60 this thing is a beast!<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-9fCeo-v4Lpg/Uptb7B2pSZI/AAAAAAAAPPU/pnB71fSDB2w/s1600/20131201_155355.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-9fCeo-v4Lpg/Uptb7B2pSZI/AAAAAAAAPPU/pnB71fSDB2w/s320/20131201_155355.jpg" height="320" width="193" /></a></div>
<br />
<br />
First off, in order to flash it, we need to get a root telnet session on the box. This is actually really simple, taking advantage of the development telnet back door. Typically, everything like this sort of device will have a back door of some description, since there needs to be a way of debugging devices in test harnesses when they go wrong. Test harnesses typically have to run the releasable software/hardware, otherwise it's not really a valid test. If something goes wrong and it's not reproducible and you have no way of logging on to investigate the failure, you have a potential PR disaster on your hands. So, pave the way to the inevitable back doors!<br />
<br />
The back door on this can be enabled by logging onto the device web interface in administrator mode. Make a note of the path element I have highlighted with a red circle; you will need this to enable the telnet back door.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-FE8UhKBST4Q/Upt0qcApWaI/AAAAAAAAPQA/YfMYnQHOb3E/s1600/ZyXEL+NSA320+-+Google+Chrome_001.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://2.bp.blogspot.com/-FE8UhKBST4Q/Upt0qcApWaI/AAAAAAAAPQA/YfMYnQHOb3E/s320/ZyXEL+NSA320+-+Google+Chrome_001.png" height="180" width="320" /></a></div>
<br />
<br />
Having just logged in and using that part of the path, access the following URL (substituting accordingly): <a href="http://10.42.0.48/r38571,/adv,/cgi-bin/remote_help-cgi?type=backdoor">http://10.42.0.48/r38571,/adv,/cgi-bin/remote_help-cgi?type=backdoor</a><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-0q_l7nipJy8/UpthMKebBgI/AAAAAAAAPPo/C_k0hrcdXbI/s1600/10.42.0.48-r38571,-adv,-cgi-bin-remote_help-cgi%3ftype=backdoor+-+Google+Chrome_002.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://3.bp.blogspot.com/-0q_l7nipJy8/UpthMKebBgI/AAAAAAAAPPo/C_k0hrcdXbI/s320/10.42.0.48-r38571,-adv,-cgi-bin-remote_help-cgi%3ftype=backdoor+-+Google+Chrome_002.png" height="180" width="320" /></a></div>
<br />
After this, you will get a blank screen and the back door will be accessible for a limited time:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-gvAeI-hFkIk/Upthb_89MeI/AAAAAAAAPPw/5UHn05pYv5o/s1600/Terminal_003.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-gvAeI-hFkIk/Upthb_89MeI/AAAAAAAAPPw/5UHn05pYv5o/s320/Terminal_003.png" height="221" width="320" /></a></div>
<br />
Now for the fun part. The login is not simply the login you used for the web interface, it is a hash of the device's MAC address, but using a special ARM binary found on the NSA-320 itself. So catch 22, you need to get access to the NSA-320 in order to get access to the NSA-320. Fortunately, I have a work around, since you can download the utility and run it with qemu-arm. You just need your device's MAC address, which is on the system status page of the administration web interface. Ensure you use a capitalised MAC address, since anything else will result in a different hash.<br />
<br />
Download the makekey utility here: <a href="http://downloads.zyxel.nas-central.org/Users/Mijzelf/makekey">makekey utility</a><br />
<br />
Install qemu and libc6-dev-armel-cross, then ensure you have qemu-arm available at your disposal. To get the "root" password, run the makekey like so:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-BFutZHtxH6A/Upt3pq1Gg4I/AAAAAAAAPQM/qoBSaMvX8jc/s1600/Terminal_004.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/-BFutZHtxH6A/Upt3pq1Gg4I/AAAAAAAAPQM/qoBSaMvX8jc/s320/Terminal_004.png" height="82" width="320" /></a></div>
<br />
Armed with your privileged user's password, you can log into the telnet back door. Repeat the process above and get the telnet session open, then login with the user: NsaRescueAngel<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-UbzDSlNU2sg/Upt4a6ss-4I/AAAAAAAAPQU/zKRJOhwJTUs/s1600/Terminal_005.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://3.bp.blogspot.com/-UbzDSlNU2sg/Upt4a6ss-4I/AAAAAAAAPQU/zKRJOhwJTUs/s320/Terminal_005.png" height="178" width="320" /></a></div>
<br />
And there you have it, a privileged BusyBox shell on your NSA320. I will post a follow up demonstrating how to use the boot loader to boot your preferred ARM Linux distribution.Unknownnoreply@blogger.com12tag:blogger.com,1999:blog-3597617790038001674.post-1145926513332557632013-09-26T13:22:00.000-07:002013-09-26T13:22:58.994-07:00TP-WN822N AP/Master Mode - SummaryIf you have been following my previous threads on this topic, you will know the pains I have been through with this, both involving the ARM architecture and the Atheros ath9k driver for the TP-WN822N adapter. The goals were simple enough:<br />
<div>
<ul>
<li>Incorporate Wi-Fi access point into NAS driver.</li>
<li>Eliminate requirement for attaching ADSL / Wi-Fi switch.</li>
<li>Eliminate requirement for attaching secondary USB Ethernet port.</li>
<li>Upgrade kernel from 2.6 to 3.X.</li>
<li>Setup PPPoE on primary Ethernet port to also eliminate the need for an ADSL modem.</li>
</ul>
The end goal was really about reducing the number of things plugged into the mains. Previously, there were roughly three devices drawing power through transformers. The NAS itself, the ADSL / Wi-Fi switch and a EOP (Ethernet over Power) home plug. The Wi-Fi was G rated, so was no good for use as the primary form of network connectivity. However, upgrading to N rated adapters throughout the house and being able to relocate the NAS drive makes for there being no real requirement for physical network connectivity; wireless seems to be the way to go. So ditching everything and upgrading to BT Infinity leaves me with the NAS drive and the Infinity modem plugged in. The Infinity modem is a necessity unfortunately but BT kindly mounted it on the wall next to the phone socket. What I don't have is the BT home hub or any other form of wireless switch / infinity / ADSL modem. Instead, PPPoE on eth0 and a USB wireless adapter running in AP mode is all that is required.</div>
<div>
<br /></div>
<div>
<b>How to summary:</b></div>
<div>
<b><br /></b></div>
<div>
Let me summarize the three previous posts and fill in the gaps on how I eventually got this all to work. So firstly, let's mention that I couldn't get this working using the 3.2 kernel, though I am yet to identify the reason, given my TTL cable has only just arrived. So a 3.4 kernel is a minimum requirement. Building is fairly simple, you can do it on box (NAS) or cross compile it. The choice is yours, but it could be the difference between 7 hours or 5 minutes. Cross compiling on my i7 running parallel make processes up to a load average of 15, utilises all the memory and finishes the entire kernel build, including modules, in around four and a half minutes. Great if you need keep changing it in experimentation mode! I have a script that can be downloaded for making cross compilation a simple one-liner. It will ask for permission to install the necessary modules for cross compilation against ARM architecture and will auto create base kernel configuration. It has a usage '--help' option, so if you choose to use it, check out the options: --menuconfig is a good one to note, since you will need that for selecting the appropriate kernel modules.</div>
<div>
<br /></div>
<div>
<b>Building the kernel:</b><br />
<br />
Building is fairly straight forward. Depending on the platform, be it, armel or armhf, you can use the gnueabi cross compiler. To get started, install the following packages:<br />
<br />
<ul>
<li>g++-arm-linux-gnueabi</li>
<li>dpkg-cross</li>
<li>devio</li>
<li>fakeroot</li>
<li>uboot-mkimage</li>
<li>u-boot-tools</li>
</ul>
<div>
If you want to use the graphical menu configuration tool, then also install:</div>
<div>
<ul>
<li>libcurses5</li>
<li>libcurses5-dev</li>
</ul>
</div>
<br />
Next you need to be aware that all make invocations need to run with the architecture and cross compiler options set. The simplest way to make sure you get this right is to run the following:<br />
<br />
alias make='make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi-'<br />
<br />
This way, you can't forget! I actually went to the extent of creating a new user with this set in the .bashrc file.<br />
<br />
So to build the kernel, clean it out first:<br />
<br />
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- mrproper<br />
<br />
Now copy in your existing configuration. This will be the configuration you have on the target machine, not the one you are building on. The easiest way to obtain it, is to use the following command:<br />
<br />
ssh you@yourmachine "zcat /proc/config.gz" > ~/linux-3.4.X/.config<br />
<br />
The output file is within the root of the kernel source you will build.<br />
<br />
Now you have that in place, you will need to upgrade the configuration. Run:<br />
<br />
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- oldconfig<br />
<br />
That will prompt you for some details about what modules to build. For this, you may choose to accept the defaults. You should then change the following settings in the file:<br />
<br />
<br />
CONFIG_ARCH="arm"<br />
CONFIG_CROSS_COMPILE="arm-linux-gnueabi-"<br />
CONFIG_LOCALVERSION="-2012-12-12-1212"<br />
CONFIG_LOCALVERSION_AUTO=n<br />
<div>
<br /></div>
<div>
Set the LOCALVERSION to the date in the form of YYYY-MM-DD-HHMM. This makes it easier to identify when you built it, as opposed to some sequential value. Alternatively, set it to some unique name that you would prefer to use.</div>
<br />
<br />
Once you have been through the setup, you then just need to setup the Atheros modules.<br />
<br />
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- menuconfig<br />
<br />
This will start the graphical menu configuration. To build the Atheros drivers for the TP-LINK device, you need to locate them under:<br />
<br />
<div style="text-align: center;">
<span style="background-color: #cccccc; color: #0b5394;"> Device Drivers ---> Network Device Support ---> Wireless LAN ---> Atheros Wireless Cards </span></div>
<div style="text-align: center;">
<br /></div>
Before you can select what Atheros drivers to build, you must first select this category using the space bar. Once selected, you can hit enter to expand the category and enable the following modules:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDVcVo8ZBwUBNBAkDm5BNyGCkkdK3a63_-D2MfQvwxEFwDidqeBuvGjfC66q4YDjTXkypzdZLFCgttPNSU3UmXSc2NHRRr4gdp3QP0W9kIiAgloBm-jeZ3Ya4g-TNTioelS5bNZK2GLUZG/s1600/kernel-modules.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDVcVo8ZBwUBNBAkDm5BNyGCkkdK3a63_-D2MfQvwxEFwDidqeBuvGjfC66q4YDjTXkypzdZLFCgttPNSU3UmXSc2NHRRr4gdp3QP0W9kIiAgloBm-jeZ3Ya4g-TNTioelS5bNZK2GLUZG/s400/kernel-modules.png" width="400" /></a></div>
<br />
Once you have selected these modules and any others you desire, you can exit the menu and build the kernel. Now, the target you need to build with depends on whether you need the uboot hack. If you are installing this kernel on your hacked Buffalo LinkStation NAS, you will need to build the zImage and perform the necessary hacks to create your uImage. However, if you are using a standard uboot configuration, then just get cracking by using the uImage target:<br />
<br />
make -j -l 15 ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- uImage modules<br />
<br />
For the uImage hack:<br />
<br />
make -j -l 15 ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- zImage modules<br />
<br />
( devio 'wl 0xe3a01c06,4' 'wl 0xe3811031,4' ; cat arch/arm/boot/zImage ) > /tmp/zImage<br />
mkimage -A arm -O linux -T kernel -C none -a 0x00008000 -e 0x00008000 -n linux -d /tmp/zImage arch/arm/boot/uImage<br />
<br />
Next, setup the modules install package, by installing them into a temporary directory.<br />
<br />
<br />
make -j -l 15 ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- modules_install INSTALL_MOD_PATH=/some/temporary/path<br />
<br />
<br />
You will now have a uImage that you can copy into your boot partition on your ARM device. You will also have modules setup and ready to install. To install them, use ssh to transfer them across:<br />
<br />
( cd /some/temporary/path ; tar Jcf - lib ) | ssh you@yourmachine "cd / && sudo tar Jxvf && sudo chown -R root:root /lib/modules/linux-3.4.X-2012-12-12-1212"<br />
<br />
You get the idea. But you can get the modules and firmware on however you choose.</div>
<div>
<b><br /></b></div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-3597617790038001674.post-72783899668523383002013-09-24T13:20:00.003-07:002013-09-24T13:20:52.455-07:00MK802 - Linux (Debian) how toInstalling Linux is fairly straight forward providing you have an appropriately sized SD card. Rather than go into too much detail, the images and a guide to installing can be found here:<br />
<br />
<a href="https://www.miniand.com/forums/forums/development/topics/debian-wheezy-lxde-armhf-build">https://www.miniand.com/forums/forums/development/topics/debian-wheezy-lxde-armhf-build</a><br />
<br />
After installing however, it's extremely advisable that you lock it down before attaching it to your network. I've never met the author of the image, don't know him and therefore can not trust the image entirely. My first port call was to build my own kernel. You are best using cross tools for this, which I have explained in detail in another post. Ensure the kernel is built with the appropriate configuration. You can use the existing kernel configuration as follows:<br />
<br />
<span style="color: orange; font-family: Courier New, Courier, monospace; font-size: x-small;">$ cat /proc/config > ~/mk802-kernel-config</span><br />
<br />
Next, lock down the firewall and update the rules. Go for a block everything and open what is required approach. If you accidentally lock yourself out, just power off the device, remove the SD card, mount on your computer and revert whatever changes necessary to allow you access again.<br />
<br />
Go through running processes with a fine tooth comb. Make sure you are only running what you need. If you don't need the GUI, make sure you change the default runlevel in /etc/inittab. A runlevel of 3 will disable the GUI normal (unless it is a fluffy distro like Ubuntu).<br />
<br />
Make sure you change the access point passphrase if you intend to create an access point. Also make sure the network interfaces configuration isn't defining soft MAC addresses for your network devices.<br />
<br />
There are many more ways to harden the system. Take a look at some of the many Linux hardening guides on the net.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-3597617790038001674.post-90773818639973082922013-09-03T05:26:00.004-07:002013-09-24T14:03:32.971-07:00RSync for Google Drive is here...I have been working on an implementation of RSync specifically for Google Drive. I now have it synchronizing between client and server using many of the basic rsync options. I am limited on the time I have with which to develop it and test it, so am looking to find volunteers willing to use the software and identify issues. The project is hosted on git hub here:<br />
<br />
<a href="https://github.com/iwonbigbro/gsync">GSync on Github</a><br />
<br />
Update: I have published the GSync application to pypi.python.org.<br />
<br />
<a href="https://pypi.python.org/pypi/gsync/0.1.0">https://pypi.python.org/pypi/gsync/0.1.0</a><br />
<br />
To install using pypi, you just need to execute the following command:<br />
<br />
$ sudo pypi-install gsync<br />
<br />
It will autoresolve dependencies and install require packages. To install the pypi-install utility on debian, execute the following command:<br />
<br />
$ sudo apt-get install python-stdeb<br />
<br />
Thanks.Unknownnoreply@blogger.com59tag:blogger.com,1999:blog-3597617790038001674.post-3018364640853562622013-08-30T01:38:00.002-07:002013-08-30T01:38:39.658-07:00Linux Mint - Upgrading from Maya(13) to Olivia(15)I thought I'd give this unsupported upgrade a go to see if it would actually work. Wow, just as I thought, it totally nose dived! I love you Debian, for all your flaws. Anyway, all was not lost. The failure occurred as a result of glibc6 being uninstalled without being replaced by the upgraded glibc6. Something went horribly wrong after uninstall, when something couldn't be restarted as a result of not having glibc6 available; yet another argument that suggests package managers should queue post install scripts until the end of installing all packages rather than trying to do a half arsed install and messing it up.<br />
<br />
Anyway, since aptititude kindly caches all the downloaded packages in /var/cache/apt/archive, it was easy to reinstate a working glibc6, providing I didn't reboot!<br />
<br />
<blockquote class="tr_bq">
<span style="color: orange; font-family: Courier New, Courier, monospace; font-size: x-small;">$ dpkg -i $(ls -t1 /var/cache/apt/archive/*glibc6*.deb | head -1)</span></blockquote>
After that, just running the dist-upgrade again managed to get the upgrade merrily on its way. So my tip of the day:<br />
<i><br /></i>
<i>No matter how bad you think the situation is, you can make it worse by hitting the reset button!</i>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-3597617790038001674.post-90919498877700624132013-07-25T05:31:00.006-07:002013-07-25T05:31:56.961-07:00Fanotify NFS root_squash woesThis just plainly doesn't work for root_squash file systems. Here's my bug report:<br />
<br />
<a href="https://bugzilla.kernel.org/show_bug.cgi?id=60563">https://bugzilla.kernel.org/show_bug.cgi?id=60563</a>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-3597617790038001674.post-52686451987402653942012-12-04T14:56:00.001-08:002012-12-04T14:59:24.025-08:00MK802 Project - NAS AssemblyUsing some parts I had lying around, namely an external USB SATA HDD caddy, the HDD from my existing NAS and a few USB cables, I was able to assemble the MK802 NAS - Phase One:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzDvoE68OEP4uMsXYzxc_AkYX8JOtfyVriyh-fCobZ1FCqTzg3UJu-RNTQ0ARRpZijSVKHnPWG3tKSvA1q4sFBPlD5T9_d4QR3HJS15YT_Fx20DKUsxvY065Ihlf4oHzezWVgWsiPT_Ztp/s1600/20121202_194425.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzDvoE68OEP4uMsXYzxc_AkYX8JOtfyVriyh-fCobZ1FCqTzg3UJu-RNTQ0ARRpZijSVKHnPWG3tKSvA1q4sFBPlD5T9_d4QR3HJS15YT_Fx20DKUsxvY065Ihlf4oHzezWVgWsiPT_Ztp/s640/20121202_194425.jpg" width="385" /></a></div>
<br />
This all runs using the single DC adapter for the external HDD caddy. I am powering the MK802 using the first USB port on the HDD. The second port has a second WiFi adapter plugged in, to allow me to bridge the WiFi interface that will run in AP mode on the MK802, with the existing WiFi router. This will allow me to set up the device with access to the local network and internet (required for updating / downloading packages). All of this is hooked up to the second USB port on the MK802, via the USB input on the HDD caddy, thus allowing the HDD caddy to act as a four port hub too.<br />
<br />
The HDD caddy was purchased a few years back on Amazon for around £15 including delivery. It has served me well and makes for a good hot-pluggable HDD caddy.<br />
<br />
I have Debian running on the MK802 with a sunxi 3.0.36 kernel. I will provide details on how to set up the MK802 with Debian using an SD card.<br />
<br />
Related: <a href="http://www.blogger.com/blogger.g?blogID=3597617790038001674#editor/target=post;postID=6585435735542541018;onPublishedMenu=overview;onClosedMenu=overview;postNum=2;src=postname">MK802 Project - Heat sinks</a>Unknownnoreply@blogger.com9tag:blogger.com,1999:blog-3597617790038001674.post-65854357355425410182012-12-01T12:48:00.000-08:002012-12-01T12:48:08.428-08:00MK802 Project - Adding heat sinksI have just bought an MK802 Mini Android PC. My intention is to use this powerful but small piece of kit to create a replacement for my dated NAS. It will serve as a router, wireless AP, firewall, NAS, NIS and NFS server. It is some 6 times more powerful than it's predecessor, with 10 times more memory. It cost just over £30 including delivery and runs at 3 watts; some 8 watts less than the current NAS. It also has USB 2.0, replacing the previously poor USB 1.1 from the predecessor.<br />
<br />
Phase one will involve using my existing 3.5" HDD, running in an external USB caddy. This will server as the NAS storage, while the OS is run directly from the 8GB UHS Micro SD card. Using u-boot, it is possible to boot a custom linux kernel from the SD card and boot an entirely different OS. I will be sticking with Debian ARM, since it has served me so well. I will be restricted to the 3.0.36 kernel for a while, downgrading from 3.4, since the Allwinner A10 SOC drivers have not yet been ported to 3.4. However, 3.4 is currently in WIP status, so I should be able to return to this version very soon.<br />
<br />
Phase two will see the introduction of the 2.5" external USB HDD, powered by USB and thus losing the need to power the drive separately. I'm not sure how the MK802 will cope with providing this power throughput, though you have to wonder how affordable a 500GB SSD will be by that point...<br />
<br />
Before doing anything though, I have read a few reviews that suggest the MK802 gets hot when operational. This is understandable given it's running a 1.6 GHz CPU and a dual core 500 MHz GPU and 2 x 512 MB DDR3 memory modules. The solution is quite brutal, but simple: add heat sinks! Since the whole design is based on it being minimalistic, some surgery is required. If you care to follow it, I have prepared step by step instructions:<br />
<br />
<b>Step 1: Dismantling the MK802</b><br />
<br />
You will notice a thin layer of plastic attached to the thicker base layer. This thin layer is just clipped in place and can be removed by carefully inserting a Stanley blade into the end with the HDMI connector, and carefully twisting until the two elements separate.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPCyWSYxphIZWy0_9uXlobS0rfkTW_53pNPLR80CIUKoCvCAmZzbyCfZ8TKcJk2lALhjH7pZf94ssiASZzoX6xrEi3YA1zUjdc_3ImIN0qSz938iHNaaFXZfBsXDcGTecHoVNRbIZH1X0N/s1600/20121130_185337.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="241" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPCyWSYxphIZWy0_9uXlobS0rfkTW_53pNPLR80CIUKoCvCAmZzbyCfZ8TKcJk2lALhjH7pZf94ssiASZzoX6xrEi3YA1zUjdc_3ImIN0qSz938iHNaaFXZfBsXDcGTecHoVNRbIZH1X0N/s400/20121130_185337.jpg" width="400" /></a></div>
<br />
Before getting dirty and hacking a whole in your casing, you should try to work out an area that will provide the maximum coverage, while not shorting anything; remember, the heat sinks are metal, so have the potential to short something if carelessly placed. Once you know where that will go, line up your four heat sinks<br />
in single file on the inside of the lid part of the casing, precisely where they will protrude. Now carefully mark an outline using your Stanley knife. Don't press hard, you are only making a guide for when you will cut, so just a light scratch in the surface will suffice.<br />
<br />
<b>Step 3: Modification of the casing</b><br />
<br />
With the template engraved in the lid, you can remove the heat sinks and begin cutting. Be patient and gentle with this, since trying to press too hard and cut all the way through will result in cracking the plastic or slicing a finger. Just gently score the surface, one edge at a time, repeating the same pattern until you notice the knife begin to make it's way through. This part took me about 20 minutes to complete, but it's worth taking your time. I have seen some people use electric hand tools and make a complete mess of the casing, so it pays to be patient here.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEivWvlB03NK9WJ51gdstASJjsYT6XoAjoSOrhyWUXkeFwnf2YeZ34-KwL324LxsefS8zpmc_LLNNXh8tvIpglvHtgUCE92KvWFqo108RnQ3kwuG4eaBaZDGb-TUn53mTmKfaNQUotYefSM5/s1600/20121130_185415.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="241" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEivWvlB03NK9WJ51gdstASJjsYT6XoAjoSOrhyWUXkeFwnf2YeZ34-KwL324LxsefS8zpmc_LLNNXh8tvIpglvHtgUCE92KvWFqo108RnQ3kwuG4eaBaZDGb-TUn53mTmKfaNQUotYefSM5/s400/20121130_185415.jpg" width="400" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhwRPQmvh1saXDphBeBCMUHjyyM0AlyCHOQtQcGrhzzSrpOxhuL1WA6MZu3NT0iNM3Nr3Z1MbxubZAIY6myoQHKUFJwdswDeGbhZGGkmK1_IYUvTW14Eja4R9SUCe28GY1UlZDV0jiXgjw/s1600/20121130_185941.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="241" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhwRPQmvh1saXDphBeBCMUHjyyM0AlyCHOQtQcGrhzzSrpOxhuL1WA6MZu3NT0iNM3Nr3Z1MbxubZAIY6myoQHKUFJwdswDeGbhZGGkmK1_IYUvTW14Eja4R9SUCe28GY1UlZDV0jiXgjw/s400/20121130_185941.jpg" width="400" /></a></div>
<br />
If you want to improve the finish even further, then you can also use a nail file to get rid of any burrs. <br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4iDi45CreSBCSEGv8fIp0W3MivfgB7I4T2MTwSXCQFJZh2L1XKvvuWf3nfMlI4YzSacu0lHrfpkOnYMHbtvRDt-2YmZVuBBcqjdBTLmN8Mx6CpIJYuqJwhgYp64X9YsKlbwfJBF5i-d5u/s1600/20121130_185958.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="241" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4iDi45CreSBCSEGv8fIp0W3MivfgB7I4T2MTwSXCQFJZh2L1XKvvuWf3nfMlI4YzSacu0lHrfpkOnYMHbtvRDt-2YmZVuBBcqjdBTLmN8Mx6CpIJYuqJwhgYp64X9YsKlbwfJBF5i-d5u/s400/20121130_185958.jpg" width="400" /></a></div>
<br />
<b>Step 4: Assembly and adhesion of the heat sinks </b><br />
<br />
It is better to assemble the casing first, before adhering the heat sinks, since it will be easier to get them in the right place. You can use the hole in the case as a guide for alignment.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnSHLokGX8sgTAiEKCb17PVb6x9ZCHg5qPttV228LVq51M3nNVMyFA24pQFSf0PEH8vgbQ6KQOtgVMg-FzS9bY0TZ_NHtw7s9786EcLif0ToASrrdHnbPBJvUngeEx5owW9sDavleCc6qc/s1600/20121130_190429.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="241" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnSHLokGX8sgTAiEKCb17PVb6x9ZCHg5qPttV228LVq51M3nNVMyFA24pQFSf0PEH8vgbQ6KQOtgVMg-FzS9bY0TZ_NHtw7s9786EcLif0ToASrrdHnbPBJvUngeEx5owW9sDavleCc6qc/s400/20121130_190429.jpg" width="400" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7Zj84Pgj0ELPZpaKTmoK-iI06krRRWmdO1dcg2mnyqqpLQ9czMfDFPmkjRaA-PuWMhbjSQyG4huGpLzzenK3wFAhXLdw0D8TAoTbk_1r-yHyeYx6F3KpqRo9bz35wEL1k08GPqp2QQJrl/s1600/20121130_190501.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="241" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7Zj84Pgj0ELPZpaKTmoK-iI06krRRWmdO1dcg2mnyqqpLQ9czMfDFPmkjRaA-PuWMhbjSQyG4huGpLzzenK3wFAhXLdw0D8TAoTbk_1r-yHyeYx6F3KpqRo9bz35wEL1k08GPqp2QQJrl/s400/20121130_190501.jpg" width="400" /></a></div>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhScrmSiJ70L5Pl98LAqq0Y1CiqUEtpZpe0wO9cVp6N0fF-SvcgPbA0qAttieMCa_DwfGyPgZBi3TxmUzoy40q5FIM9ke19JIpqjyXuzuYJzxaWvcW5NWt3k_3eLfjSNOTw1jyHIQiqVe2r/s1600/20121130_190642.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="241" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhScrmSiJ70L5Pl98LAqq0Y1CiqUEtpZpe0wO9cVp6N0fF-SvcgPbA0qAttieMCa_DwfGyPgZBi3TxmUzoy40q5FIM9ke19JIpqjyXuzuYJzxaWvcW5NWt3k_3eLfjSNOTw1jyHIQiqVe2r/s400/20121130_190642.jpg" width="400" /></a></div>
<br />
After adhering all the heat sinks, you should have something that looks a little like this: <br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6c4hJCQLF7tt_-feKQUxfUuCMycAzxW1k-RLnf5DM43m02fTdo2k7hKA6h0_qhN009wlHnMEXXajmUpt70KUGyGSMgerlp3id6hW_wcmaE9KM8BiGCF9KfZ9Yr067ZT25G1_iWfj2rFJo/s1600/20121130_190719.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="241" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6c4hJCQLF7tt_-feKQUxfUuCMycAzxW1k-RLnf5DM43m02fTdo2k7hKA6h0_qhN009wlHnMEXXajmUpt70KUGyGSMgerlp3id6hW_wcmaE9KM8BiGCF9KfZ9Yr067ZT25G1_iWfj2rFJo/s400/20121130_190719.jpg" width="400" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhrGO2c4NCJn7zx4_DkoTk2VFQuZuLxszGQzVqAjPZTwga-6jBBQ9p95B4o9rC80yjuwzMAbF-wTr8wg8cD8bN40mhLQI72I94rOK3TwCw-J6Lx1KWqQSd59tmgbi2GYUyvOO1D2M4oqyFv/s1600/20121130_190734.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="241" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhrGO2c4NCJn7zx4_DkoTk2VFQuZuLxszGQzVqAjPZTwga-6jBBQ9p95B4o9rC80yjuwzMAbF-wTr8wg8cD8bN40mhLQI72I94rOK3TwCw-J6Lx1KWqQSd59tmgbi2GYUyvOO1D2M4oqyFv/s400/20121130_190734.jpg" width="400" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiio4i_fgli7alLCzelTZ6VbwiZPkxXdh0YgFy1R4KKKTVZmdolY0tkhW-C6u5A1RO198V_MaU5usmHwj-pR_yN5YrNtCIwt_Yo2SATWjSbGNWdObb3-1nTzm9-36Easzd_Ch1GSSYRP-uU/s1600/20121130_190742.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="241" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiio4i_fgli7alLCzelTZ6VbwiZPkxXdh0YgFy1R4KKKTVZmdolY0tkhW-C6u5A1RO198V_MaU5usmHwj-pR_yN5YrNtCIwt_Yo2SATWjSbGNWdObb3-1nTzm9-36Easzd_Ch1GSSYRP-uU/s400/20121130_190742.jpg" width="400" /></a></div>
<br />
I have seen some other articles where holes are drilled in the surface to allow more ventilation. This really isn't at all necessary, since the heat sinks are fairly efficient at radiating heat on their own, thus drawing cooler air through other cavities such as the USB ports, SD slot or HDMI slot.<br />
<br />
Remember, when operating, keep the heat sinks on the top most surface, since they will not function correctly if they cannot radiate heat upwards. It is okay if the heat sinks are on the side, providing the assembly is kept horizontal. Vertical positioning will result in radiated heat preventing either the GPU or DDR memory from getting sufficient cooling.<br />
<br />
To test that they are working adequately, turn on your device and wait a minute or two. If working correctly, the heat sinks will be hot to the touch.<br />
<br />Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-3597617790038001674.post-85213743607177088982012-10-13T16:59:00.001-07:002012-10-13T16:59:58.874-07:00PPPoE and obscure packet dropping (some websites not working)...I have been having a mare with packets just disappearing or packets being marked as invalid and dropped, then resulting in established and related packets being dropped in response to mangled requests. I spent ages trying to debug this, logging anything and everything with iptables log rules. I couldn't determine what on earth was going on, until I started reading about MSS exceeding the MTU of 1500 set by the ISP. This is only apparent with large amounts of data and even more apparent on devices connecting from behind the firewall, with mangling going on. Essentially, it boils down to packets being mangled, increasing the segment size, which eventually leads to a packet that exceeds the MTU when the ISP reroutes it. At the firwall level, the packet is fine and fits just within the 1500 limit. Proposed solutions seem to be centred around adjusting the PPPoE interface MTU to something that would not exceed the limit of 1500 when mangled. This is a good idea to have set. For me, I modified my PPP configuration and changed the MTU:<br />
<br />
<span style="font-family: Courier New, Courier, monospace; font-size: xx-small;">$ sed -i.bak 's/^mtu [0-9]\+$/mtu 1454/' /etc/ppp/peers/dsl-provider</span><br />
<br />
This is not always guaranteed to work alone though, as I found out. This is because you don't know what additional mangling is going on at the ISP's end. In the end, I started reading the iptables man page for the 3.4 kernel I am running. I found something very interesting...<br />
<br />
<br />
<span style="font-family: Courier New, Courier, monospace; font-size: xx-small;">TCPMSS</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: xx-small;"> This target allows to alter the MSS value of TCP SYN packets, to control the maximum size for that connection (usually limiting it to your outgoing inter-</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: xx-small;"> face's MTU minus 40 for IPv4 or 60 for IPv6, respectively). Of course, it can only be used in conjunction with -p tcp.</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: xx-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: xx-small;"> This target is used to overcome criminally braindead ISPs or servers which block "ICMP Fragmentation Needed" or "ICMPv6 Packet Too Big" packets. The symp-</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: xx-small;"> toms of this problem are that everything works fine from your Linux firewall/router, but machines behind it can never exchange large packets:</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: xx-small;"> 1) Web browsers connect, then hang with no data received.</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: xx-small;"> 2) Small mail works fine, but large emails hang.</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: xx-small;"> 3) ssh works fine, but scp hangs after initial handshaking.</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: xx-small;"> Workaround: activate this option and add a rule to your firewall configuration like:</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: xx-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: xx-small;"> iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: xx-small;"> -j TCPMSS --clamp-mss-to-pmtu</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: xx-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: xx-small;"> --set-mss value</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: xx-small;"> Explicitly sets MSS option to specified value. If the MSS of the packet is already lower than value, it will not be increased (from Linux 2.6.25</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: xx-small;"> onwards) to avoid more problems with hosts relying on a proper MSS.</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: xx-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: xx-small;"> --clamp-mss-to-pmtu</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: xx-small;"> Automatically clamp MSS value to (path_MTU - 40 for IPv4; -60 for IPv6). This may not function as desired where asymmetric routes with differing</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: xx-small;"> path MTU exist -- the kernel uses the path MTU which it would use to send packets from itself to the source and destination IP addresses. Prior to</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: xx-small;"> Linux 2.6.25, only the path MTU to the destination IP address was considered by this option; subsequent kernels also consider the path MTU to the</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: xx-small;"> source IP address.</span><br />
<span style="font-family: Courier New, Courier, monospace; font-size: xx-small;"><br /></span>
<span style="font-family: Courier New, Courier, monospace; font-size: xx-small;"> These options are mutually exclusive.</span><br />
<div>
<br /></div>
<div>
So I wasn't going mad after all and it does appear to be a widely known issue. So I gave it a try...</div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: xx-small;">-A FORWARD -p tcp --tcp-flags SYN,RST SYN -j LOG --log-prefix "CLAMP-MSS-TO-PMTU" --log-tcp-options --log-ip-options --log-level 7</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: xx-small;">-A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu</span></div>
</div>
<div>
<br /></div>
<div>
I am only specifying the LOG action here to ensure that it works. Indeed it does. After enabling it, I instantly started seeing entries appear in the logs and all the websites that weren't previously accessible suddenly started working. I don't need to explain why this works, since it's explained enough in the above manual excerpt. But if you share my blight, then hopefully this helps you too!</div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-3597617790038001674.post-58563152142629409102012-10-12T14:20:00.000-07:002012-10-12T14:20:23.928-07:00Broadcast ping for host discoveryI saw a question posted on an exchange website today that took me back a few years. Often, people assume that broadcast ping can be used for host discovery on a network. But these days, broadcast ICMP requests are dropped silently to avoid stimulating springboard style DoS attacks. This is essentially where you ping a number of hosts, as many as possible across a multitude of subnets, but have all the responses returned to the machine you want to attack. This overloads the machine's network interface with ICMP traffic, obstructing real network traffic. It also poses as a threat to ADSL connections, when you consider that most people have caps on their broadband. It would be quite easy to render someone's internet connection useless through this attack mechanism. For this reason, the default response for any machine, is to not respond to broadcast ICMP requests. Most routers also filter these out, to prevent ICMP broadcast packets spreading across different subnets.<br />
<br />
Anyway, host discovery can actually be obtained through a much simpler mechanism, given that you can ping specific hosts for a reply; again, providing that those hosts reply to ICMP requests. The solution is to ping each possible permutation of addresses on a given subnet, looking for a response from any of them. This sounds like a really heavyweight process, but it's actually very easy and very fast. The following command demonstrates this, which can be incorporated into a script if you wish (brackets are important).<br />
<br />
<br />
<span style="color: #b45f06; font-family: Courier New, Courier, monospace;">$ time ( s=192.168.0 ; for i in $(seq 1 254) ; do ( ping -n -c 1 -w 1 $s.$i 1>/dev/null 2>&1 && printf "%-16s %s\n" $s.$i responded ) & done ; wait ; echo )</span><br />
<span style="color: #b45f06; font-family: Courier New, Courier, monospace;">192.168.0.5 responded</span><br />
<span style="color: #b45f06; font-family: Courier New, Courier, monospace;">192.168.0.11 responded</span><br />
<span style="color: #b45f06; font-family: Courier New, Courier, monospace;">192.168.0.2 responded</span><br />
<span style="color: #b45f06; font-family: Courier New, Courier, monospace;">192.168.0.254 responded</span><br />
<span style="color: #b45f06; font-family: Courier New, Courier, monospace;">192.168.0.4 responded</span><br />
<span style="color: #b45f06; font-family: Courier New, Courier, monospace;"><br /></span>
<span style="color: #b45f06; font-family: Courier New, Courier, monospace;">real 0m1.317s</span><br />
<span style="color: #b45f06; font-family: Courier New, Courier, monospace;">user 0m0.004s</span><br />
<span style="color: #b45f06; font-family: Courier New, Courier, monospace;">sys 0m0.084s</span><br />
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-3597617790038001674.post-87861295088325797782012-10-12T13:52:00.001-07:002012-10-12T13:52:49.656-07:00TP-WN822N AP/Master Mode - Part 3The new kernel worked, at least for a little while. I had to radically rework the network configuration in order to get it functioning with minimal firewall changes. So initially I had 1 Gb on board Ethernet wired to the internal network, 100 Mb USB Ethernet on the ADSL line with the wifi provided by a bridge on the switch. Now, the 1 GB provides the PPPoE interface and WiFi supplies the network. I use the USB Ethernet adapter on it's own subnet, connected directly to my laptop, as a management port.<br />
<br />
The best way to avoid changing the firewall, other than a simple bit of 'sedding', was to create a bridge interface between what is now regarded as the physical interface and the wireless interface. The physical interface doesn't actually exist any more, but it's there just in case; call it future proofing against my own change of mind. So let's look at the network/interfaces configuration...<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">allow-hotplug eth4</span><br />
<span style="font-family: Courier New, Courier, monospace;">iface eth4 inet manual</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">allow-hotplug wlan0</span><br />
<span style="font-family: Courier New, Courier, monospace;">iface wlan0 inet manual</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">auto br0</span><br />
<span style="font-family: Courier New, Courier, monospace;">iface br0 inet static</span><br />
<span style="font-family: Courier New, Courier, monospace;"> bridge_ports eth4 wlan0</span><br />
<span style="font-family: Courier New, Courier, monospace;"> address ...</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: inherit;">The rest is pretty straight forward. This creates the bridge interface. Actually, nothing happens on boot, because there is no eth4 device and no wlan0 device, therefore no bridge device is created. But once udevd detects the ath9k driver, a udev rule takes care of starting the hostapd daemon, and thus creates the bridge. The script also sets up extra iptables rules to allow traffic on br0, since everything is implicitly dropped. Having hostapd start on system boot is no good, even though it's the recommended route. With USB devices, they have to wait until the USB hub driver has loaded before plugged devices can be found. By this point, the hostapd will have failed because the devices weren't present. Instead, I completely rewrote my own version of the hostapd ifupdown.sh script, to ensure that the right thing is done when a device comes online and goes of line. I have tested this, by </span>repeatedly<span style="font-family: inherit;"> unplugging the USB </span>adapter<span style="font-family: inherit;"> and plugging it back in. Each time, udev unloads and loads the ath9k module, runs my script, thus installs firewall rules and runs hostapd.</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;"><b>Dilema! (another one)</b></span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">The 3.2 kernel I am using seems to have a bug in the Atheros driver. After a period of the driver being loaded and the adapter being connected, sending and receiving traffic, the kernel crashes. There are a few problems with this. One is that the kernel crashes!! Two is that the kernel panic doesn't make it to syslog, so I have no idea what happens. Three, I need to create serial connector for the hidden serial port on the NAS drive. Hassle!</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">So next steps... I have purchased a Nokia CA 42 lead from Amazon. This has an inbuilt TTL, and considering it's only £4, it is far cheaper than the £30 for a proper USB TTL lead. When it arrives, I will set to work on getting the serial console up and running so I can debug the driver crash.</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">In the meantime, I am going to build the 3.4 kernel using my scripts and investigate what changes have been made to the ath9k modules between 3.2, 3.4 and 3.6 kernels. It's quite possible that I can backport a change that provides a solution, to my 3.2 kernel.</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">Stay tuned for more progress...</span>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-3597617790038001674.post-65801254299806343732012-10-08T11:45:00.003-07:002012-10-08T11:45:48.572-07:00TP-WN822N AP/Master Mode - Part 2<b>Kernel Building!</b><br />
<br />
Okay, building the kernels did eventually become a bit tedious given the problems I was having. Initially the 3.5.5 kernel I built worked, but was shortly followed by intermittent kernel crashes; no panics, no core dumps (disabled). So I immediately looked to the 3.4.X kernel, which would appear to be more stable. At this point I had opted for the cross compiling approach, given 7 hours to wait for a build was a bit tedious. To hopefully make the process of building kernels for the NAS more portable and easier, I created a script to do the job for me. It automates the job of installing the appropriate build tools (cross compilers, utilities and libraries) as well as keeping these up-to-date by running through the install process on each invocation.<br />
<br />
After some playing, I found a base configuration that worked well, based on my 2.6 kernel config. At this point, I snap shot it and placed it with the script. The script now snap shots according to kernel versions built out of the same directory. I have the compilation time on my i7 down to 4 minutes. That's incredible given it took 7 hours on a 200 MHz ARM CPU. I supposed the biggest difference is the amount of memory available to me on the i7 and how many processes can be spawned. I am running make with unlimited parallel processes, limited only by the system load. I have this set to a load average of around 5. So initially, there is a surge in memory usage and CPU usage, before it all settles down, with all 8 cores working at an average capacity of about 80%. But to get an image and modules out in under 5 minutes is still astonishing!<br />
<br />
Download the <a href="http://code.google.com/p/build-ukernel/source/browse/trunk/bin/build-ukernel">build-ukernel script</a><br />
<br />
Stay tuned for more...Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-3597617790038001674.post-32663827605871872042012-10-05T11:54:00.000-07:002012-10-05T11:54:16.571-07:00TP-WN822N AP/Master ModeI have been running Debian on a hacked Buffalo LS500GL NAS for at least the past four years now and this little beast is still going strong. I've since upgraded the HDD to a 1TB disk and use it for various things, such as Firewall, NIS server, NFS server, DLNA server, Web server and just about any other kind of server you can cram into the 128 MB of RAM. It only has a 200 MHz ARM CPU, so it's no good for use as a transcoder, but for general services, it serves me well.<br />
<br />
However, having just upgrades to a fibre connection, I thought I'd take advantage of the PPPoE availability and run a wireless access point, instead of having the switch plugged in. The NAS uses some 11 watts, so is really economic. Having the switch plugged in as well, draws an extra 8 or 9 watts; which, when you consider it is not really necessary, I may as well ditch it in favour of a USB access point.<br />
<br />
<b>Dilemma!</b><br />
<b><br /></b>
There is of course a dilemma. Most wireless drivers on Linux don't support access point mode. The simple work around is to use NDIS wrapper to wrap native Windows kernel drivers, providing the Windows kernel API, whilst interfacing with the Linux kernel. However, this is not possible when you are not running a supported Windows architecture, or at least one that you can finder drivers for. In this case, there are no Windows drivers for ARM.<br />
<br />
<b>Solution!</b><br />
<br />
The solution is simple, so it would seem. Find a device that has a Linux driver that supports AP mode. These are few and far between and figuring out which of the devices will be suitable before you buy is a tough one. Luckily I was able to find a few resources that indicated that the TP-WN822N USB adapter supports AP mode using the Atheros drivers (ath9k variant). This driver is available in the 3.X.X kernels and onwards, so first port of call is to upgrade my 2.6.X kernel.<br />
<br />
Cross compiling means running up a computer for hours on end while it builds, so I opt for building them on the NAS. It takes a lot longer, given the memory restrictions and slow CPU, but you can log in, run up '/usr/bin/screen' and leave it running, while you go off and do something else as equally constructive for 7 hours, like sleep!<br />
<br />
So here is my procedure:<br />
<br />
<span style="color: #783f04; font-family: Courier New, Courier, monospace;">ssh root@nasdrive</span><br />
<span style="color: #783f04; font-family: Courier New, Courier, monospace;">exec screen</span><br />
<span style="color: #783f04; font-family: Courier New, Courier, monospace;">cd /usr/src/linux-3.X.X</span><br />
<span style="color: #783f04; font-family: Courier New, Courier, monospace;">make menuconfig</span><br />
<span style="color: #783f04; font-family: Courier New, Courier, monospace;">make</span><br />
<br />
Installation is slightly different given the U-Boot loader that runs out of the NAS flash. For the NAS, you need to build the zImage and modify it slightly:<br />
<br />
<span style="color: #783f04; font-family: Courier New, Courier, monospace;">make zImage</span><br />
<span style="color: #783f04; font-family: Courier New, Courier, monospace;">mkimage -O linux -T kernel -C none -a 0x00008000 -e 0x00008000 -n 'linux' -d <( devio 'wl 0xe3a01c06,4' 'wl 0xe3811031,4'; cat arch/arm/boot/zImage ) uImage.new</span><br />
<span style="color: #783f04; font-family: Courier New, Courier, monospace;">mv uImage.new uImage-3.X.X</span><br />
<span style="color: #783f04; font-family: Courier New, Courier, monospace;">mv System.map System.map-3.X.X</span><br />
<span style="color: #783f04; font-family: Courier New, Courier, monospace;">mv .config config-3.X.X</span><br />
<br />
Once all this has been built, it can be copied to the /boot partition and the default links updated appropriately. It's no big deal if the NAS doesn't come up on reboot. You can dismantle it, remove the HDD, relink the old kernel and start over. This doesn't happen often, but when it does, is usually the result of not having built the uImage with the correct devio header.<br />
<br />
So, let's leave it there for now. I am going to set my kernel building and will come back and report the next stages of getting the ath9k driver loaded and getting the wlan interface up for the TP-LINK adapter. Stay tuned...Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-3597617790038001674.post-45191447250257259512012-06-13T14:57:00.000-07:002012-06-13T14:57:47.026-07:00Debian, NIS, Headaches, Wi-Fi and AutoFSFor quite some time now, there has been a lot of hoo-har surrounding startup ordering, dependencies and chain loading of autofs, ypbind and networking. Historically, it had been solved post-installation by manually modifying insserv directives in the headers of sysinit scripts then recalculating the dependency start order. Well, that or just simply modifying the rc.d start sequence. However, with the introduction and adoption of upstart, the dependencies have been fine tuned somewhat, allowing a virtual "start-ypbind.conf" script to be provided as a blocking event, blocking the start up of things that depend on ypbind. This works exactly as everyone that uses NIS and AutoFS require it to, providing the binding takes less than five seconds. Historically, binding time-out before ypbind startup was backgrounded, was around a minute. However, since the upstart edition, this time-out has been reduced to five seconds. After which, ypbind is backgrounded and upstart startup events are emitted for autofs and other NIS dependent services. When connecting to a network via a wi-fi connection, connecting to wi-fi alone can take that long. So obviously, since AutoFS is extremely sensitive to the presence of YP binding, automount fails to start and you are presented with a system in the same age old unusable state. The simple solution would be to increase the time-out and prey it makes its way into mainstream. However, wouldn't it be nice if YP could bind in less time, perhaps without there even being a presence of any networking at all?<br />
<br />
Well, the answer is "yes". And the answer to "how we achieve it" is actually quite simple, although it does uncover another little bug with yphelper.<br />
<br />
<b>Solution</b><br />
So how do we bind faster and without any networking? The answer is that we need to bind locally. In order to bind locally, it means running a local NIS server, but one intended as a NIS slave. This is extremely simple to set up, using the /usr/lib/yp/ypinit utility. Providing the -s option and the fully qualified hostname of the master NIS server, the NIS server will be replicated locally. Synchronisation with the master will be maintained by ypfxrd on the master NIS server, so no need to setup any nasty cron tasks to update the NIS records periodically. There are a few configuration settings to ensure the NIS server is only made available locally, but once done, a restart of NIS and autofs will see the system switched to using the local NIS server; ypwhich will confirm this.<br />
<br />
Modify the yp.conf file to include your original entry below a duplicate of itself, with the IP or hostname of the NIS server swapped for localhost (127.0.0.1). It should look somewhat like this:<br />
<br />
domain some.domain.com server 127.0.0.1<br />
domain some.domain.com server 10.0.0.1<br />
<br />
The host on 10.0.0.1 will be the master, used only as a secondary to the local server. Effectively, this is a null op, but it serves as a reminder to the real NIS server.<br />
<br />
Make sure the only entry that is permitted in ypserv.securenets is the link local address range. Comment anything else out to ignore all other authentication requests.<br />
<br />
That's it! Configuring NIS in this way will have YP binding completing almost instantaneously, while the networking is able to come online and autofs is able to start.<br />
<br />
<b>Issues</b><br />
There is a bug with ypinit, in that on some NIS master configurations, it is unable to obtain a list of maps for that server. This can be remedied by modifying the script and replacing the call to yphelper with a call to ypwhich as follows:<br />
<br />
maps=`ypwhich -m | awk '($2 == "'$MASTER'") { printf("%s ", $1) }'`<br />
<br />
This is a variation of the original method for obtaining maps, and one that works reliably.Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-3597617790038001674.post-56100993546289731742012-05-30T00:44:00.001-07:002012-05-30T00:45:16.457-07:00Tech: Leap MotionI want one of these!! Well, providing it works as shown and there is a Linux driver for it. :-)<br />
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<object class="BLOGGER-youtube-video" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" data-thumbnail-src="http://0.gvt0.com/vi/_d6KuiuteIA/0.jpg" height="266" width="320"><param name="movie" value="http://www.youtube.com/v/_d6KuiuteIA&fs=1&source=uds" />
<param name="bgcolor" value="#FFFFFF" />
<embed width="320" height="266" src="http://www.youtube.com/v/_d6KuiuteIA&fs=1&source=uds" type="application/x-shockwave-flash"></embed></object></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<a href="http://www.leapmotion.com/">Leap Motion</a></div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-3597617790038001674.post-40026047774524842112012-04-11T01:35:00.004-07:002012-04-11T01:46:02.002-07:00xsltproc: exslt functions, and SEGVThis has a habit of coming back to bite me when I have forgotten about it, but essentially there is an issue with performing XSLT within a <func:result> block. If the XSLT within the result block is too extensive and results in a large return block or node-set, then it causes xsltproc to SEGV. There is a simple way to defend against this from ever happening, but it requires a little concious thought and consistency.<br />
<br />
To prevent the func:result from throwing a wobbly, you must ensure you encapsulate your return value in a variable where you would otherwise return the result. Thus func:result:</func:result><br />
<br />
<span style="color: #7f6000; font-family: 'Courier New', Courier, monospace; font-size: x-small;"><func:result></span><br />
<span style="color: #7f6000; font-family: 'Courier New', Courier, monospace; font-size: x-small;"> <xsl:for-each select="myns:isInteresting(exsl:node-set($nodes)/Thing)"></span><br />
<span style="color: #7f6000; font-family: 'Courier New', Courier, monospace; font-size: x-small;"> <xsl:value-of select="@name"/></span><br />
<span style="color: #7f6000; font-family: 'Courier New', Courier, monospace; font-size: x-small;"> </xsl:for-each></span><br />
<span style="color: #7f6000; font-family: 'Courier New', Courier, monospace; font-size: x-small;"></func:result></span><br />
<br />
Becomes:<br />
<br />
<span style="color: #7f6000; font-family: 'Courier New', Courier, monospace; font-size: x-small;"><xsl:variable name="ret"></span><br />
<span style="color: #7f6000; font-family: 'Courier New', Courier, monospace; font-size: x-small;"> <xsl:for-each select="myns:isInteresting(exsl:node-set($nodes)/Thing)"></span><br />
<span style="color: #7f6000; font-family: 'Courier New', Courier, monospace; font-size: x-small;"> <xsl:value-of select="@name"/></span><br />
<span style="color: #7f6000; font-family: 'Courier New', Courier, monospace; font-size: x-small;"> </xsl:for-each></span><br />
<span style="color: #7f6000; font-family: 'Courier New', Courier, monospace; font-size: x-small;"></xsl:variable></span><br />
<span style="color: #7f6000; font-family: 'Courier New', Courier, monospace; font-size: x-small;"><func:result select="$ret"/></span>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-3597617790038001674.post-66154704257285751412011-11-22T01:35:00.000-08:002011-11-22T01:38:56.575-08:00ECMAScript ES6 - The future of JavaScript......or is it just:<br />
<span class="Apple-style-span" style="color: #b45f06; font-family: 'Courier New', Courier, monospace;"><br />
<script type="text/python"><br />
<br />
import YUI from "yui.py"<br />
<br />
</script><br />
</span>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-3597617790038001674.post-14951543067130008632011-10-23T02:17:00.000-07:002011-10-23T02:17:00.058-07:00Modifying Gnome3 Login BackgroundI recently started using Gnome3 and found that it is seriously lacking in configuration utilities. While this is a problem for simplicity, you can still achieve most customisations through brute force. One of the most common customisations I have seen many requests for on Google, is that of customising the GDM3 login screen background.<br />
<br />
The easiest way to understand how the login background can be modified, is to think of the login screen as a Gnome session, but with a different interface to that of the gnome-shell. The active user for the Gnome login screen is the GDM user. On Debian this user is Debian-gdm. So in order to modify the login screen background, you in fact need to modify the Debian-gdm user's gconf settings, updating the path to the desired wallpaper.<br />
<br />
Its a fairly straight forward task, but is made complicated by the fact that the Debian-gdm user does not have a login shell defined in /etc/passwd and cannot be used as a valid user from the GDM login screen. So in order to access and modify the Debian-gdm user's gconf settings, you must switch to this user using the su command from a root login shell.<br />
<br />
<span class="Apple-style-span" style="color: #b45f06; font-family: 'Courier New', Courier, monospace; font-size: x-small;">root# su - Debian-gdm -s /bin/bash</span><br />
<span class="Apple-style-span" style="color: #b45f06; font-family: 'Courier New', Courier, monospace; font-size: x-small;">Debian-gdm$ </span><br />
<br />
Now, gconf settings are modified through the dconf subsystem using DBus. So to enable access to the DBus interface, you need to launch a DBus daemon for the Debian-gdm user and import it into the environment:<br />
<br />
<span class="Apple-style-span" style="color: #b45f06; font-family: 'Courier New', Courier, monospace; font-size: x-small;">Debian-gdm$ $(dbus-launch | sed 's/^/export /g')</span><br />
<br />
Next you need to start the dconf-service that interfaces with DBus and provides the backend for gconf.<br />
<br />
<span class="Apple-style-span" style="color: #b45f06; font-family: 'Courier New', Courier, monospace; font-size: x-small;">Debian-gdm$ ps -eao user,command | awk '("'${USER:-$LOGNAME}'" == $1 && $NF ~ /^\/usr\/lib\/d-?conf\/dconf-service/) { print $NF }'</span><br />
<br />
Running the above command will print the username and command line of the running dconf-service if there is one. If the dconf-service isn't running, then start it.<br />
<br />
<span class="Apple-style-span" style="color: #b45f06; font-family: 'Courier New', Courier, monospace; font-size: x-small;">Debian-gdm$ /usr/lib/d*conf/dconf-service &</span><br />
<br />
Now you can access the gconf settings for Debian-gdm through the gsettings utility.<br />
<br />
<span class="Apple-style-span" style="color: #b45f06; font-family: 'Courier New', Courier, monospace; font-size: x-small;">Debian-gdm$ gsettings get org.gnome.desktop.background picture-uri</span><br />
<br />
Don't forget picture-uri is a URI, so be sure to prefix it with file:// or http://. For all of this wrapped up into a script you can run as root, see my Google code project:<br />
<br />
<a href="http://code.google.com/p/set-gnome3-background">http://code.google.com/p/set-gnome3-background</a>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-3597617790038001674.post-44871467674283944572010-12-22T06:04:00.000-08:002010-12-22T06:04:37.106-08:00resolv.conf and DynDNSSo, in order to save a few pennies on my broadband service, I have downgraded my package which means I lose my static IP address. Now the issue is that I have bridge mode setup on the router so I can manage my own internal network, placing different security policies onto different subnets and changing what services are listening on each network, like UPnP for example. Since game consoles typically require UPnP and most other things don't, games consoles are locked down onto their own private subnet, connected to the outside world via a different interface on the server.<br />
<br />
So back to the bridge mode issue. Why is it an issue? Well, when switching from static, it means your interfaces configuration must change from static to dhcp as well:<br />
<br />
<span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #b45f06;">auto eth0</span></span></span><br />
<span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #b45f06;">iface eth0 inet dhcp</span></span></span><br />
<br />
What this means is, that dhclient will handle setting up routes and designating the IP address etc, to the interface, when it receives a DHCP response from the ISP's DHCP server. This usually entails losing everything you have setup in resolv.conf when dhclient decides to overwrite it. To prevent it being overwritten, you need to use the hooks provided in dhclient-script. See dhclient-script man page.<br />
<br />
Essentially, what is required is an enter hook that declares a function called 'make_resolv_conf'. This function will replace the function defined in dhclient-script at the point the enter hook gets included, and thus, if the body of the function does nothing, resolv.conf doesn't get modified. For me, this is good since DNS is managed by dnsmasqd and I forward DNS requests to OpenDNS.org to provide simple security on things like typos:<br />
<br />
www.bcarlays.com -> Hmm, nice place to setup a spoof / phishing site I would imagine. OpenDNS resolve addresses like these to one of your choosing. For me, I have it resolve back to the address of my internal gateway, where I host a 404 page.<br />
<br />
What next? Well, there is the issue that this dynamic IP address being assigned to my bridged interface, is... well... dynamic. So when the lease runs out, it could mean it will change to a new address, making my network inaccessible from the WAN. To counter this, ddclient needs to be run whenever the lease runs out or a new address is assigned to the interface, as well as the periodic calls to ddclient in order to keep the DynDNS hostname alive. I lost a host to DynDNS once before because I didn't force update it every so often, so I want to avoid that painful experience again.<br />
<br />
So how on earth do you go about executing ddclient whenever the lease is renewed or the interface is bound to the DHCP server? Well, lets use the dhclient-script hooks again. I created an exit hook script this time, to listen for the dhclient-script being called with the reason of BOUND, RENEW or REBIND. These three reasons will get triggered whenever the interface address is likely to change and often when the interface address hasn't changed. But importantly, it will ensure ddclient can be called when the lease expires. Here is the script:<br />
<br />
<br />
<span class="Apple-style-span" style="color: #b45f06;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"># dhclient-script exit hook to ensure that the DYNDNS address is updated</span></span></span><br />
<span class="Apple-style-span" style="color: #b45f06;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"># through the ddclient, whenever the address changes.</span></span></span><br />
<span class="Apple-style-span" style="color: #b45f06;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><br />
</span></span></span><br />
<span class="Apple-style-span" style="color: #b45f06;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">function ddclient_exithook() {</span></span></span><br />
<span class="Apple-style-span" style="color: #b45f06;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> local prog="${0##*/}::ddclient_exithook()"</span></span></span><br />
<span class="Apple-style-span" style="color: #b45f06;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> logger -t "$prog" "Reason: $reason"</span></span></span><br />
<span class="Apple-style-span" style="color: #b45f06;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><br />
</span></span></span><br />
<span class="Apple-style-span" style="color: #b45f06;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> case $reason in</span></span></span><br />
<span class="Apple-style-span" style="color: #b45f06;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> (BOUND|RENEW|REBIND)</span></span></span><br />
<span class="Apple-style-span" style="color: #b45f06;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> # Run the ddclient script to rebind the address to the DYNDNS hostname</span></span></span><br />
<span class="Apple-style-span" style="color: #b45f06;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> cat <<ddclient $prog"="" -t="" logger="" |=""></ddclient></span></span></span><br />
<span class="Apple-style-span" style="color: #b45f06;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">Executing ddclient to renew DynDNS hostname...</span></span></span><br />
<span class="Apple-style-span" style="color: #b45f06;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><br />
</span></span></span><br />
<span class="Apple-style-span" style="color: #b45f06;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">$(/usr/sbin/ddclient -force -verbose 2>&1)</span></span></span><br />
<span class="Apple-style-span" style="color: #b45f06;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><br />
</span></span></span><br />
<span class="Apple-style-span" style="color: #b45f06;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">Executing ddclient returned exitcode: $?</span></span></span><br />
<span class="Apple-style-span" style="color: #b45f06;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">DDCLIENT</span></span></span><br />
<span class="Apple-style-span" style="color: #b45f06;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> ;;</span></span></span><br />
<span class="Apple-style-span" style="color: #b45f06;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> (*)</span></span></span><br />
<span class="Apple-style-span" style="color: #b45f06;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> # No need to renew the DYNDNS address</span></span></span><br />
<span class="Apple-style-span" style="color: #b45f06;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> logger -t "$prog" "Nothing to be done for $reason"</span></span></span><br />
<span class="Apple-style-span" style="color: #b45f06;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> ;;</span></span></span><br />
<span class="Apple-style-span" style="color: #b45f06;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> esac</span></span></span><br />
<span class="Apple-style-span" style="color: #b45f06;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">}</span></span></span><br />
<span class="Apple-style-span" style="color: #b45f06;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><br />
</span></span></span><br />
<span class="Apple-style-span" style="color: #b45f06;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">ddclient_exithook</span></span></span><br />
<br />
Test the script works by taking down the interface and bringing it back up. This will force the interface to bind to the DHCP server when it comes back up, causing dhclient-script to be invoked with the BOUND reason.<br />
<br />
See also:<br />
<br />
<span class="Apple-style-span" style="color: #b45f06;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">/etc/dhcp3/dhclient-enter-hooks.d</span></span></span><br />
<span class="Apple-style-span" style="color: #b45f06;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">/etc/dhcp3/dhclient-exit-hooks.d</span></span></span><br />
<span class="Apple-style-span" style="color: #b45f06;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">/etc/ddclient.conf</span></span></span><br />
<br />
Man pages:<br />
<br />
<span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #b45f06;">ddclient</span></span></span><br />
<span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #b45f06;">dhclient-script</span></span></span><br />
<span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #b45f06;">dhclient</span></span></span>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-3597617790038001674.post-58316090345817236792010-12-15T06:14:00.000-08:002010-12-15T06:14:12.302-08:00Subversion and Gnome KeyringThe problem:<br />
<br />
You want to run an svn command in a cron task as a user that is already logged in and authenticated against a running gnome-keyring-daemon and the svn repository in question, but DBus prevents a user acquiring the privilege to access his own daemon without an associated x-session-manager.<br />
<br />
The solution:<br />
<br />
Attach to the Gnome session artificially, in order to be granted access to the gnome-keyring-daemon through DBus.<br />
<br />
Details:<br />
<br />
So how do you do that?<br />
<br />
Well, there are three things required here. Firstly, the DBus session bus address. This will be something along the lines of:<br />
<br />
<span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;">unix:abstract=/tmp/dbus-abcdefghijk,guid=1234567890abcdef09878654321</span></span></span><br />
<br />
It essentially enables applications that use DBus, to actually use it. It's the flag that notifies the applications that DBus is available. However, this alone will not solve the problem, since this will just allow the authentication request to take place but not actually be authenticated. So, svn will see the environment variable and request authentication through DBus to the authentication agent (gnome-keyring), but there is nothing to tell DBus what the authentication agent is and where it is. Next step...<br />
<br />
Get the authentication agent.<br />
<br />
This will be the gnome-keyring daemon pretending to be an ssh-agent, since it assumes the responsibility of the SSH agent when users use the gnome-keyring-manager, authentication for SSH keys is done through the gnome-keyring-daemon SSH authentication socket. So how do you attach to this?<br />
<br />
The Auth socket lives in the tmp directory, but it's no use hunting for it, since there could be lots of dead instances or instances owned by other users. The easiest way is to hijack your own x-session-manager's environment and politely steel the socket and PID from the environment. Let's see how we do that...<br />
<br />
<span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;">$ export pid=$(ps -C x-session-manager -o pid --no-heading)</span></span></span><br />
<span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;">$ cat /proc/${pid//[^0-9]/}/environ | sed 's/\x00/\n/g' | grep SSH</span></span></span><br />
<br />
This will give you the path to the socket and the PID of the SSH agent in use by the x-session-manager; the one you want to pretend launched your shell. The best way to be doing this however, is from one of the getty terminals that aren't running within your x-session, or by locally ssh'ing onto your machine to detach yourself from your x-session. This way, you can be sure it is all working.<br />
<br />
So is that it? Not quite, keep reading...<br />
<br />
So, you have the DBus address, the agent socket and PID, what more could you possibly need? Well, anything X related must be authenticated against the X server, otherwise all authentication through DBus and essentially the gnome-keyring-daemon, will fail due to X authentication issues. So finally, we must hijack our own X session, by associating ourselves with our own X authentication cookie. This is in the form of some UUID. This simplest way to obtain it is exactly the same as obtaining the SSH agent information. You politely ask the kernel for it:<br />
<br />
<br />
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;">$ export pid=$(ps -C x-session-manager -o pid --no-heading)</span></span></span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;">$ cat /proc/${pid//[^0-9]/}/environ | sed 's/\x00/\n/g' | grep XDG_SESSION_COOKIE</span></span></span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><br />
</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">So with this arsenal of environment variables, you can effectively mimic a process created by the x-session-manager, and start having friendly conversations with the x-session-manager and gnome-keyring-daemon. However, it's all a bit dirty at the moment, so we can clean it up quite easily. Create a file to include in your .bashrc file. This will ensure that any processes created by "you" will attempt to associate themselves with an x-session. I always opt for something like .bash_functions:</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><br />
</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;">#!/bin/bash</span></span></span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;"><br />
</span></span></span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;">################################################################################</span></span></span></div><div><div><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;">#</span></span></span></div><div><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;"># Attaches the current BASH session to a GNOME keyring daemon</span></span></span></div><div><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;">#</span></span></span></div><div><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;"># Returns 0 on success 1 on failure.</span></span></span></div><div><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;">#</span></span></span></div><div><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;">function gnome-keyring-attach() {</span></span></span></div><div><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;"> local -a vars=( \</span></span></span></div><div><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;"> DBUS_SESSION_BUS_ADDRESS \</span></span></span></div><div><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;"> SSH_AUTH_SOCK \</span></span></span></div><div><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;"> SSH_AGENT_PID \</span></span></span></div><div><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;"> XDG_SESSION_COOKIE \</span></span></span></div><div><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;"> )</span></span></span></div><div><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;"> local pid=$(ps -C x-session-manager -o pid --no-heading)</span></span></span></div><div><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;"> eval "unset ${vars[@]}; $(printf "export %s;" $(sed 's/\x00/\n/g' /proc/${pid//[^0-9]/}/environ | grep $(printf -- "-e ^%s= " "${vars[@]}")) )"</span></span></span></div><div><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;">}</span></span></span></div></div><div><br />
</div><br />
<br />
The reason it is a function, is because calling a script would run as a child process, so setting anything up in the environment there will have no affect on the calling environment. Instead, calling a bash function allows the function to modify the calling environment. You could of course write a function that prints the shell environment settings to the screen, where they can be imported into the current environment, but I find this is tidier. Alternative method:<br />
<br />
<span class="Apple-style-span" style="color: #38761d;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">eval "$(gnome-keyring-attach)"</span></span></span><br />
<br />
All you need to do now, is invoke this function when required. Either in your cron task or in every session if you so wish to grant yourself access to your X session remotely, for example.Unknownnoreply@blogger.com4tag:blogger.com,1999:blog-3597617790038001674.post-80795346928570756172010-12-15T03:07:00.000-08:002012-10-12T16:14:34.074-07:00Not impossible: setuid shell scriptingI often come across the age old question of "why can't I setuid a Bash script?". Well the simple one word answer is "security". Plain and simple, having a script that is potentially modifiable or susceptible to script injection, either through parameters or through the environment, is a major security flaw. However, there are ways of making a script root executable in a controlled manner, that ensures a clean environment.<br />
<br />
Since the introduction of 'sudo', it is possible to execute any script as root by simply replacing the shebang with the following:<br />
<br />
<span class="Apple-style-span" style="color: #38761d;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">#!/usr/bin/sudo /bin/bash</span></span></span><br />
<br />
However, this is extremely insecure since you would be handing root privileges to /bin/bash from within the sudoers to anybody with access rights to run bash through sudo. Thus this would be innevitable:<br />
<br />
<span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span"><span class="Apple-style-span" style="color: #38761d;">[blee@dragon:~]$ sudo /bin/bash --login</span></span></span></span><br />
<span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span"><span class="Apple-style-span" style="color: #38761d;">[root@dragon:~]# id</span></span></span></span><br />
<span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span"><span class="Apple-style-span" style="color: #38761d;">uid=0(root) gid=0(root) groups=0(root)</span></span></span></span><br />
<br />
So how do you permit bash to be executed as root from the shebang, whilst maintaining control over what can actually be executed? The answer is to write a more intricate sudo rules to enable us to execute these setuid scripts. First a User_Alias is required to provide a list of all the users permitted to execute certain scripts:<br />
<br />
<span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;">User_Alias ROOT_SUID_USERS = blee, cnorris</span></span></span><br />
<br />
Next we need to know what scripts can be run as root.<br />
<br />
<span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;">Cmd_Alias ROOT_SUID_SCRIPTS = /usr/bin/myscript</span></span></span><br />
<br />
Next we want to ensure that the environment is reset when invoking these commands:<br />
<br />
<span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;">Defaults!ROOT_SUID_SCRIPTS env_reset</span></span></span><br />
<br />
Next we put the two together:<br />
<br />
<span class="Apple-style-span" style="color: #38761d;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">ROOT_SUID_USERS ALL = (root) NOPASSWD: ROOT_SUID_SCRIPTS</span></span></span><br />
<br />
Now, /usr/bin/myscript is permissibly executable as root by the users blee and cnorris. However, since sudo is invoked from the calling script's shebang, we need to somehow invoke bash in a safe way, otherwise we would just end up in a loop, with sudo being invoked by itself from /usr/bin/myscript. So what we do is prefix each of the scripts in the /bin/bash invocation, which is safe, since we are saying that /bin/bash can be invoked by sudo providing it is immediately followed by the /usr/bin/myscript argument:<br />
<br />
<span class="Apple-style-span" style="color: #38761d;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">Cmd_Alias ROOT_SUID_SCRIPTS = \</span></span></span><br />
<span class="Apple-style-span" style="color: #38761d;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> /bin/bash /usr/bin/myscript, \</span></span></span><br />
<span class="Apple-style-span" style="color: #38761d;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> /bin/bash /usr/bin/myotherscript</span></span></span><br />
<br />
In /usr/bin/myscript, we replace the shebang as follows:<br />
<br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="color: #38761d;">#!/usr/bin/sudo /bin/bash</span></span></span><br />
<br />
Now, sudo will invoke /bin/bash as root given the rule, providing cnorris or blee are the users executing the script. Here are the test results:<br />
<br />
Before we add anything to the sudoers file, but with our shebang in place:<br />
<br />
<span class="Apple-style-span" style="color: #38761d;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">[blee@dragon:~]$ myscript</span></span></span><br />
<span class="Apple-style-span" style="color: #38761d;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><br />
</span></span></span><br />
<span class="Apple-style-span" style="color: #38761d;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">We trust you have received the usual lecture from the local System</span></span></span><br />
<span class="Apple-style-span" style="color: #38761d;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">Administrator. It usually boils down to these three things:</span></span></span><br />
<span class="Apple-style-span" style="color: #38761d;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><br />
</span></span></span><br />
<span class="Apple-style-span" style="color: #38761d;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> #1) Respect the privacy of others.</span></span></span><br />
<span class="Apple-style-span" style="color: #38761d;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> #2) Think before you type.</span></span></span><br />
<span class="Apple-style-span" style="color: #38761d;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"> #3) With great power comes great responsibility.</span></span></span><br />
<span class="Apple-style-span" style="color: #38761d;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><br />
</span></span></span><br />
<span class="Apple-style-span" style="color: #38761d;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">[sudo] password for blee:</span></span></span><br />
<span class="Apple-style-span" style="color: #38761d;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;">Sorry, user blee is not allowed to execute '/bin/bash /usr/bin/myscript' as root on dragon.</span></span></span><br />
<br />
So lets add the sudoers configuration and try again:<br />
<br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="color: #38761d;">[blee@dragon:~]$ myscript</span></span></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="color: #38761d;">myscript: Demonstrating setuid shell scripting:</span></span></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="color: #38761d;">uid=0(root) gid=0(root) groups=0(root)</span></span></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="color: #38761d;"><br />
</span></span></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="color: #38761d;">[tjones@dragon:~]$ myscript</span></span></span><br />
<br />
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="color: #38761d;"><br class="Apple-interchange-newline" />We trust you have received the usual lecture from the local System</span></span></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="color: #38761d;">Administrator. It usually boils down to these three things:</span></span></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="color: #38761d;"><br />
</span></span></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="color: #38761d;"> #1) Respect the privacy of others.</span></span></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="color: #38761d;"> #2) Think before you type.</span></span></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="color: #38761d;"> #3) With great power comes great responsibility.</span></span></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="color: #38761d;"><br />
</span></span></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="color: #38761d;">[sudo] password for tjones:</span></span></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="color: #38761d;">Sorry, user tjones is not allowed to execute '/bin/bash /usr/bin/myscript' as root on dragon.</span></span></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<br /></div>
<br />
Just to prove that /bin/bash cannot be exploited through this sudo rule:<br />
<br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="color: #38761d;">[blee@dragon:~]$ sudo /bin/bash --login</span></span></span><br />
<br />
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="color: #38761d;"><br class="Apple-interchange-newline" />We trust you have received the usual lecture from the local System</span></span></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="color: #38761d;">Administrator. It usually boils down to these three things:</span></span></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="color: #38761d;"><br />
</span></span></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="color: #38761d;"> #1) Respect the privacy of others.</span></span></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="color: #38761d;"> #2) Think before you type.</span></span></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="color: #38761d;"> #3) With great power comes great responsibility.</span></span></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="color: #38761d;"><br />
</span></span></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="color: #38761d;">[sudo] password for blee:</span></span></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="color: #38761d;">Sorry, user blee is not allowed to execute '/bin/bash --login' as root on dragon.</span></span></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="color: #38761d;"><br />
</span></span></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
</div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="color: #38761d;">[blee@dragon:~]$ sudo /bin/bash</span></span></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
</div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="color: #38761d;"><br class="Apple-interchange-newline" />We trust you have received the usual lecture from the local System</span></span></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="color: #38761d;">Administrator. It usually boils down to these three things:</span></span></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="color: #38761d;"><br />
</span></span></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="color: #38761d;"> #1) Respect the privacy of others.</span></span></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="color: #38761d;"> #2) Think before you type.</span></span></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="color: #38761d;"> #3) With great power comes great responsibility.</span></span></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="color: #38761d;"><br />
</span></span></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="color: #38761d;">[sudo] password for blee:</span></span></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="color: #38761d;">Sorry, user blee is not allowed to execute '/bin/bash' as root on dragon.</span></span></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<br /></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
But, executing myscript the by bypassing the shebang is fine:</div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<br /></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="color: #38761d;">[blee@dragon:~]$ sudo /bin/bash /usr/bin/myscript</span></span></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="color: #38761d;">myscript: Demonstrating setuid shell scripting:</span></span></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="color: #38761d;">uid=0(root) gid=0(root) groups=0(root)</span></span></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<br /></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
</div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
To summarise, there we have blee running myscript and assuming root privileges for the life of the script. Obviously, it does rely on the author of the scripts being run as root, to write the scripts securely, so there will possibly be an opportunity for exploitation if scripts are written sloppily. Also, the permissions of these scripts must be as such that they are owned and writeable only by root! Any modification to the file permissions that would allow anybody else write access creates a window of opportunity for someone to modify the contents as such it would grant them a root shell, providing they have permission to execute it and be granted root privileges from sudo.</div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<br /></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
As sudo suggests:</div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<br /></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
</div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="color: #38761d;">It usually boils down to these three things:</span></span></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="color: #38761d;"><br />
</span></span></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="color: #38761d;"> #1) Respect the privacy of others.</span></span></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="color: #38761d;"> #2) Think before you type.</span></span></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="color: #38761d;"> #3) With great power comes great responsibility.</span></span></span></div>
<br />
<br />
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<br /></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<br /></div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-3597617790038001674.post-75655961969174669452010-11-12T06:37:00.000-08:002010-11-12T06:47:54.531-08:00More Perl eval DESTROY woes!Something now seemingly obvious, is the scope issues associated with the $@ variable, eval and an object's destructor. Consider the scenario, that like in a C++ program, you want to use well defined exceptions to determine the flow of the program under erroneous circumstances, rather than arbitrarily passing parameters around or relying on return value checking:<br />
<br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;">my $success = 0;</span></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;">if (open(my $fh, ">", "/dev/null")) {</span></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;"> if (myFunction("some parameter")) {</span></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;"> my $obj = My::Something->new();</span></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;"><br />
</span> </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;"> if ($obj->method1()) {</span></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;"> if ($obj->method2()) {</span></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;"> $success = 1;</span></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;"> }</span></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;"> }</span></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;"> }</span></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;">}</span></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;">if (! $success) {</span></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;"> warn("Oh dear, something went wrong");</span></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;"> return 0;</span></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;">}</span></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;">return 1;</span></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: inherit;">Levels of nesting can start to look ugly, and with lots of return value checking going on, it can start to become hard to follow or sustain. So instead, I often look to simplify things like this:</span><br />
<span class="Apple-style-span" style="font-family: inherit;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;">eval {</span></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;"> open(my $fh, ">", "/dev/null") or do {</span></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;"> die(My::Exception->new($!));</span></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;"> };</span></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;"> </span></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;"> myFunction("some parameter");</span></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;"><br />
</span> </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;"> my $obj = My::Something->new();</span></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;"> $obj->method1();</span></span><br />
<span class="Apple-style-span" style="color: #38761d;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"></span></span><br />
<span class="Apple-style-span" style="color: #38761d;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"></span></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><div style="font-family: 'Times New Roman'; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;"> $obj->method2();</span></span></div><div style="font-family: 'Times New Roman'; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;">};</span></span></div><div style="font-family: 'Times New Roman'; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;">if ($@) {</span></span></div><div style="font-family: 'Times New Roman'; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;"> my $ref = ref($@);</span></span></div><div style="font-family: 'Times New Roman'; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;"> if ("My::Exception" eq $ref) {</span></span></div><div style="font-family: 'Times New Roman'; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;"> $@->warn();</span></span></div><div style="font-family: 'Times New Roman'; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;"> } else {</span></span></div><div style="font-family: 'Times New Roman'; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;"> warn("Oh dear, something went wrong: $@");</span></span></div><div style="font-family: 'Times New Roman'; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;"> }</span></span></div><div style="font-family: 'Times New Roman'; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;"> return 0;</span></span></div><div style="font-family: 'Times New Roman'; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;">}</span></span></div><div style="font-family: 'Times New Roman'; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><span class="Apple-style-span" style="color: #38761d;">return 1;</span></span></div><div style="font-family: 'Times New Roman'; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br />
</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: Times, 'Times New Roman', serif;">Ensuring that all packages and functions you create throw some exception object, makes error reporting easy to localise and self contained. It's also easy to disable if you haven't warnings plastered throughout your code.</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: Times, 'Times New Roman', serif;"><br />
</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: Times, 'Times New Roman', serif;">Well all be it nice, in Perl there is one caveat that caught me out. Consider the scenario above, where in the instance of My::Something, it's destructor calls some method or function that contains an eval block. With that in mind, also consider what would happen if method1 was to throw an exception. Here is what happens:</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: Times, 'Times New Roman', serif;"><br />
</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #38761d;"># My::Something constructor is executed.</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #38761d;">my $obj = My::Something->new();</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #38761d;"><br />
</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #38761d;"># When method2 throws an exception, the eval </span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #38761d;"># block is exited and $@ is set to the appropriate </span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #38761d;"># exception object by 'die'.</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #38761d;">$obj->method2();</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #38761d;"><br />
</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #38761d;"># After setting $@ but before executing the next </span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #38761d;"># statement after the eval block, Perl executes </span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #38761d;"># the destructor on $obj. Within the destructor, </span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #38761d;"># some method calls 'eval', which on instantiation,</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #38761d;"># resets the $@ variable.</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #38761d;">eval { die("Ignore this error"); };</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #38761d;"><br />
</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #38761d;"># Now when the destructor has finished, Perl executes </span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #38761d;"># the next statement where it evaluates whether the 'eval' </span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #38761d;"># block was successful or not.</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #38761d;">if ($@) { ...</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #38761d;"><br />
</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #38761d;"># Because of the 'eval' instance resetting $@, the </span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #38761d;"># code skips the error reporting and returns a </span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #38761d;"># successful return value.</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #38761d;">return 1;</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><br />
</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: Times, 'Times New Roman', serif;">This is a complete disaster and will easily go unnoticed until something much further down the line identifies something that should have happened, hasn't or vice-versa. However, there is an extremely simple way to secure the destructor of an object against such an event, by simply declaring $@ in local scope within the destructor:</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: Times, 'Times New Roman', serif;"><br />
</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #38761d;">sub DESTROY {</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #38761d;"> my $this = shift;</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #38761d;"> local $@;</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #38761d;"><br />
</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #38761d;"> eval {</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #38761d;"> die("Now this error will truly be ignored");</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #38761d;"> };</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #38761d;">}</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><br />
</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: Times, 'Times New Roman', serif;">For such a simple solution, it's worth making habit to always instantiate a local copy of $@ within a destructor unless you want to explicitly propagate a destructor exception up to some other handler. But since there is a danger you will always overwrite some other more important exception that quite possibly caused the exception in the destructor in the first place, it's probably worth implementing some global variable for destructor exceptions:</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: Times, 'Times New Roman', serif;"><br />
</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #38761d;">package My::Something;</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #38761d;"><br />
</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #38761d;">my $destruct_except;</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #38761d;"><br />
</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #38761d;">sub DESTROY {</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #38761d;"> my $this = shift;</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #38761d;"> local $@;</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #38761d;"> </span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #38761d;"> $My::Something::destruct_except = undef;</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #38761d;"> eval {</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #38761d;"> die("Oh dear, that's not supposed to happen!");</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #38761d;"> };</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #38761d;"> if ($@) {</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #38761d;"> $My::Something::destruct_except = $@;</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #38761d;"> }</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #38761d;">}</span></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><br />
</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: Times, 'Times New Roman', serif;">Obviously, if there are multiple instances of the same object type in a single eval block, it would be very difficult to track which destructor threw or which ones didn't. Then you would have to become more cunning, using some sort of hash or list to stack up the exceptions that occurred with each destructor. For the most part though, usually you are not interested in what fails within a destructor, since it's primary purpose is to clean up. If what it wants to clean doesn't exist, as far as you are concerned, it's job is done and you don't need to know about what couldn't be cleaned, because the lack of existence implies it is clean.</span></div></span>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-3597617790038001674.post-76212272077933590712010-08-09T05:56:00.000-07:002010-08-09T05:56:16.947-07:00FOLLOW UP: Perl: eval {...}, DESTROY and fork()Just following up on a previous entry. I have read something interesting on the destructors of Perl modules in a threaded environment. This doesn't work for forked processes, since the kernel is responsible for duplicating forked processes, but it does provide a mechanism for making threads with cloned objects thread-safe.<br />
<br />
<a href="http://perldoc.perl.org/perlmod.html#BEGIN%2c-UNITCHECK%2c-CHECK%2c-INIT-and-END">CLONE_SKIP</a>Unknownnoreply@blogger.com0