#!/bin/bash

function checkdate()
{
	y=$1
	m=$2
	d=$3
	
	fixed="platform (`uname -v`) post-dates fix"
	year=`uname -v | cut -c 8-11`

	if [[ $year -lt 2010 ]]; then
		echo $fixed
		exit 0
	fi

	if [[ $year -gt 2020 ]]; then
		echo $fixed
		exit 0
	fi

	if [[ $year -gt $y ]]; then
		echo $fixed
		exit 0
	fi

	if [[ $year -eq $y ]]; then
		month=`uname -v | cut -c 12-13`

		if [[ $month -gt $m ]]; then
			echo $fixed
			exit 0
		fi

		if [[ $month -eq $m ]]; then
			day=`uname -v | cut -c 14-15`
		
			if [[ $day -gt $d ]]; then
				echo $fixed
				exit 0
			fi
		fi
	fi
}

checkdate 2015 9 29

variant1=/tmp/ZDI-CAN-3263-check.variant1
variant2=/tmp/ZDI-CAN-3263-check.variant2
out=/tmp/ZDI-CAN-3263-check.out

cat > $variant1 <<EOF
dtrace_dstate_init:             pushq  %rbp
dtrace_dstate_init+1:           movq   %rsp,%rbp
dtrace_dstate_init+4:           subq   \$0x30,%rsp
dtrace_dstate_init+8:           movq   %rbx,-0x30(%rbp)
dtrace_dstate_init+0xc:         movq   %r12,-0x28(%rbp)
dtrace_dstate_init+0x10:        movq   %rsi,%r12
dtrace_dstate_init+0x13:        movq   %rsi,-0x10(%rbp)
dtrace_dstate_init+0x17:        movq   %r13,-0x20(%rbp)
dtrace_dstate_init+0x1b:        movl   \$0x38,%esi
dtrace_dstate_init+0x20:        movq   %r14,-0x18(%rbp)
dtrace_dstate_init+0x24:        movq   %rdi,-0x8(%rbp)
dtrace_dstate_init+0x28:        movq   %rdi,%rbx
dtrace_dstate_init+0x2b:        movq   0x18(%rdi),%r13
dtrace_dstate_init+0x34:        testq  %r13,%r13
dtrace_dstate_init+0x37:        movq   %r13,0x18(%rbx)
dtrace_dstate_init+0x3b:        je     +0x183   <dtrace_dstate_init+0x1c4>
dtrace_dstate_init+0x41:        addq   \$0x40,%r13
EOF

cat > $variant2 <<EOF
dtrace_dstate_init:             pushq  %rbp
dtrace_dstate_init+1:           movq   %rsp,%rbp
dtrace_dstate_init+4:           subq   \$0x10,%rsp
dtrace_dstate_init+8:           movq   %rdi,-0x8(%rbp)
dtrace_dstate_init+0xc:         movq   %rsi,-0x10(%rbp)
dtrace_dstate_init+0x10:        pushq  %r12
dtrace_dstate_init+0x12:        pushq  %r13
dtrace_dstate_init+0x14:        pushq  %r14
dtrace_dstate_init+0x16:        subq   \$0x8,%rsp
dtrace_dstate_init+0x1a:        movq   %rdi,%r13
dtrace_dstate_init+0x1d:        movq   %rsi,%r14
dtrace_dstate_init+0x20:        movq   0x18(%r13),%r12
dtrace_dstate_init+0x24:        movq   %r13,%rdi
dtrace_dstate_init+0x27:        movq   \$0x38,%rsi
dtrace_dstate_init+0x33:        movq   %r12,0x18(%r13)
dtrace_dstate_init+0x37:        testq  %r12,%r12
dtrace_dstate_init+0x3a:        jne    +0xf     <dtrace_dstate_init+0x4b>
EOF

echo "dtrace_dstate_init::dis" | mdb -k 2> /dev/null | \
    head -18 | grep -v bzero > $out

if cmp $out $variant1 > /dev/null ; then
        echo "variant 1 found; hot-patching jump at dtrace_dstate_init+0x3b"
        echo "dtrace_dstate_init+0x3c/v 8e" | mdb -kw
        exit 0
fi

if cmp $out $variant2 > /dev/null ; then
        echo "variant 2 found; hot-patching jump at dtrace_dstate_init+0x3a"
        echo "dtrace_dstate_init+0x3a/v 7f" | mdb -kw
        exit 0
fi

#
# Check against the patched variants.
#
cat > $variant1 <<EOF
dtrace_dstate_init:             pushq  %rbp
dtrace_dstate_init+1:           movq   %rsp,%rbp
dtrace_dstate_init+4:           subq   \$0x30,%rsp
dtrace_dstate_init+8:           movq   %rbx,-0x30(%rbp)
dtrace_dstate_init+0xc:         movq   %r12,-0x28(%rbp)
dtrace_dstate_init+0x10:        movq   %rsi,%r12
dtrace_dstate_init+0x13:        movq   %rsi,-0x10(%rbp)
dtrace_dstate_init+0x17:        movq   %r13,-0x20(%rbp)
dtrace_dstate_init+0x1b:        movl   \$0x38,%esi
dtrace_dstate_init+0x20:        movq   %r14,-0x18(%rbp)
dtrace_dstate_init+0x24:        movq   %rdi,-0x8(%rbp)
dtrace_dstate_init+0x28:        movq   %rdi,%rbx
dtrace_dstate_init+0x2b:        movq   0x18(%rdi),%r13
dtrace_dstate_init+0x34:        testq  %r13,%r13
dtrace_dstate_init+0x37:        movq   %r13,0x18(%rbx)
dtrace_dstate_init+0x3b:        jle    +0x183   <dtrace_dstate_init+0x1c4>
dtrace_dstate_init+0x41:        addq   \$0x40,%r13
EOF

cat > $variant2 <<EOF
dtrace_dstate_init:             pushq  %rbp
dtrace_dstate_init+1:           movq   %rsp,%rbp
dtrace_dstate_init+4:           subq   \$0x10,%rsp
dtrace_dstate_init+8:           movq   %rdi,-0x8(%rbp)
dtrace_dstate_init+0xc:         movq   %rsi,-0x10(%rbp)
dtrace_dstate_init+0x10:        pushq  %r12
dtrace_dstate_init+0x12:        pushq  %r13
dtrace_dstate_init+0x14:        pushq  %r14
dtrace_dstate_init+0x16:        subq   \$0x8,%rsp
dtrace_dstate_init+0x1a:        movq   %rdi,%r13
dtrace_dstate_init+0x1d:        movq   %rsi,%r14
dtrace_dstate_init+0x20:        movq   0x18(%r13),%r12
dtrace_dstate_init+0x24:        movq   %r13,%rdi
dtrace_dstate_init+0x27:        movq   \$0x38,%rsi
dtrace_dstate_init+0x33:        movq   %r12,0x18(%r13)
dtrace_dstate_init+0x37:        testq  %r12,%r12
dtrace_dstate_init+0x3a:        jg     +0xf     <dtrace_dstate_init+0x4b>
EOF

if cmp $out $variant1 > /dev/null ; then
        echo "found variant 1, but dtrace_dstate_init+0x3b is already patched"
        exit 0
fi

if cmp $out $variant2 > /dev/null ; then
        echo "found variant 2, but dtrace_dstate_init+0x3a is already patched"
        exit 0
fi

echo "did not find either variant"
exit 1

