1

I use dd a lot day to day for writing Raspberry Pi SD card images.

However every now and then I slip and by accident dd the wrong partition and thus killing my other drives.

I was wondering if there was a way to be able to block writing using dd to say /dev/sdb and /dev/sdc.

  • 1
    Close voters: Ubuntu runs on the Raspberry Pi as of RasPi 2. Ryanteck: We assume you are using a Pi 2 with real Ubuntu. If not then you're better of asking on Unix & Linux if the answer below does not work for you. – Seth Aug 22 '15 at 23:46
  • 1
    also you could be writing images for raspberry Pi on an ubuntu machine – mchid Aug 22 '15 at 23:48
  • mchid is right, I run full ubuntu on my Laptop & Desktops. – Ryan Walmsley Aug 23 '15 at 6:35
3

This is Linux, so it's easy. Type echo $PATH and find a directory that 1) you have write access to; and 2) it is earlier in the list than the directory you get from type -p dd. Put this file in that directory, called dd, and make it executable via chmod +x.

Here is the file:

----------------------------- cut here ---------------------------
#!/bin/bash
# try to prevent foot-shooting via dd - complain if if= or of= is mounted
debugmode=1
#
# either abort with a message or pass everything to the real dd
realdd="/usr/bin/dd"
if [ $debugmode = 1 ] ; then
    realdd="/bin/echo"
fi
if [ ! -x "$realdd" ] ; then
    echo "$0 cannot find the real dd at $realdd" >&2
    exit 255
fi

errors=0

function diskok () {
    # passed a parameter, if=... or of=... 
    # if the argument to if= or of= is "WRONG", pull the plug
    param=$1;
    device="${param##?f=}"

# replace this with checks of your choice. I'm simply excluding any word in /etc/fstab 

    if [[ $( grep -q "$device" /etc/fstab;echo $? ) = 0 ]]; then
    echo "Trying to dd a mounted device $param" >&2
    (( errors++ ))
    fi
}

laundry=""

# Re: Those tests for if and of. You can just do if [[ $1 = if=* ]] and if [[ $1 = of=* ]]. Or, better yet, use a case statement. –  muru 7 mins ago
while [[ $# -gt 0 ]] ; do
    case "$1" in
    if=*)
            diskok "$1" ;;
    of=*)
            diskok "$1" ;;
    esac
    laundry="$laundry $1"
    shift
done
if [ 0 -eq $errors ] ; then
    eval "$realdd $laundry"
else
    echo "Saved"
fi
----------------------------- cut here ---------------------------

When you have tested it sufficiently, change debugmode=1 to debugmode=0.

Here are my tests:

w3@aardvark:~(254)$ df
Filesystem        1K-blocks      Used Available Use% Mounted on
/dev/sda5         170416096  29962928 131773488  19% /
none                      4         0         4   0% /sys/fs/cgroup
udev                1938252        12   1938240   1% /dev
tmpfs                390632      1104    389528   1% /run
none                   5120         0      5120   0% /run/lock
none                1953148       444   1952704   1% /run/shm
none                 102400        24    102376   1% /run/user
/dev/sda6         302248384 247234972  39637036  87% /home
/home/w3/.Private 302248384 247234972  39637036  87% /home/w3
/dev/sdb            3840544   1229408   2611136  33% /home/w3/mnt/CLIPZIP
w3@aardvark:~(0)$ dd bs=8293 if=/dev/sda of=/dev/sda5 of=/home
Trying to dd a mounted device if=/dev/sda
Trying to dd a mounted device of=/dev/sda5
Trying to dd a mounted device of=/home
Saved
w3@aardvark:~(254)$ dd bs=8293 if=/dev/sdaa of=/dev/sdaa5 of=/homae
bs=8293 if=/dev/sdaa of=/dev/sdaa5 of=/homae

Remember to change the test to the test you want.

Thanks to @muru for [[ and case

  • Re: Those tests for if and of. You can just do if [[ $1 = if=* ]] and if [[ $1 = of=* ]]. Or, better yet, use a case statement. – muru Aug 22 '15 at 23:31
2

Sure, you could write a wrapper script to prevent yourself from making misatkes, but having such a false sense of security established, you're going to have risky behaviour on other systems because you're used to a level of comfort that only exists in your system.

Therefore my answer is:

Think before root and no, there is no way to block other devices. When the block device is accessible to root, then dd can also access it. dd does only what you tell it to do.

dd is also known as Disk Destroyer ;-)

  • WRONG! dd is $(type -p dd) = /bin/dd. My $PATH is /home/w3/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:... which means that any of /home/w3/bin/dd, /usr/local/sbin/dd, /usr/local/bin/dd,/usr/sbin/dd,/usr/bin/dd, and /sbin/dd, IF THEY EXISTED, would be executed instead of /bin/dd. – waltinator Aug 22 '15 at 21:31
  • @waltinator Why is your PATH so weird? – Kaz Wolfe Aug 23 '15 at 8:09
  • Also, +1 for best practices. – Kaz Wolfe Aug 23 '15 at 8:13
  • My PATH contains directories containing programs I might want to run. I got tired of having to type the whole path to them. What is weird about it? – waltinator Aug 23 '15 at 16:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.