cbuildbot: disable yama kernel hardlink security checks

Yama will disallow hardlinking files that a user does not have write
access to.  This breaks the cros_setup_toolchains logic which creates
packages by hardlinking root owned files into a directory.

Otherise the builds fail like so:
Traceback (most recent call last):
  File "/home/chrome-bot/trunk/chromite/buildbot/cbuildbot_background.py", line 237, in _TaskRunner
    task(*x)
  File "/home/chrome-bot/trunk/chromite/scripts/cros_setup_toolchains.py", line 914, in CreatePackagableRoot
    _BuildInitialPackageRoot(output_dir, paths, elfs, ldpaths, root=root)
  File "/home/chrome-bot/trunk/chromite/scripts/cros_setup_toolchains.py", line 785, in _BuildInitialPackageRoot
    os.link(path, dst)
OSError: [Errno 1] Operation not permitted

BUG=chromium-os:36453
TEST=hand ran this func on a bot and it tried to set yama to 0 when it was enabled, and returned when it was disabled
TEST=`cbuildbot chromiumos-sdk` no longer errors out when run on our buildbots

Change-Id: Ifb2cc466b0e49b158e73f3a964d1a47c6be1c906
Reviewed-on: https://gerrit.chromium.org/gerrit/39160
Commit-Ready: Mike Frysinger <vapier@chromium.org>
Reviewed-by: Mike Frysinger <vapier@chromium.org>
Tested-by: Mike Frysinger <vapier@chromium.org>
diff --git a/scripts/cbuildbot.py b/scripts/cbuildbot.py
index 4985702..321975b 100644
--- a/scripts/cbuildbot.py
+++ b/scripts/cbuildbot.py
@@ -11,6 +11,7 @@
 """
 
 import distutils.version
+import errno
 import glob
 import logging
 import multiprocessing
@@ -528,6 +529,34 @@
   return buildroot
 
 
+def _DisableYamaHardLinkChecks():
+  """Disable Yama kernel hardlink security checks.
+
+  The security module disables hardlinking to files you do not have
+  write access to which causes some of our build scripts problems.
+  Disable it so we don't have to worry about it.
+  """
+  PROC_PATH = '/proc/sys/kernel/yama/protected_nonaccess_hardlinks'
+  SYSCTL_PATH = PROC_PATH[len('/proc/sys/'):].replace('/', '.')
+
+  # Yama not available in this system -- nothing to do.
+  if not os.path.exists(PROC_PATH):
+    return
+
+  # Already disabled -- nothing to do.
+  if osutils.ReadFile(PROC_PATH).strip() == '0':
+    return
+
+  # Create a hardlink in a tempdir and see if we get back EPERM.
+  with osutils.TempDirContextManager() as tempdir:
+    try:
+      os.link('/bin/sh', os.path.join(tempdir, 'sh'))
+    except OSError as e:
+      if e.errno == errno.EPERM:
+        cros_build_lib.Warning('Disabling Yama hardlink security')
+        cros_build_lib.SudoRunCommand(['sysctl', '%s=0' % SYSCTL_PATH])
+
+
 def _BackupPreviousLog(log_file, backup_limit=25):
   """Rename previous log.
 
@@ -1177,7 +1206,7 @@
 
   if not options.buildroot:
     if options.buildbot:
-      parser.error('Please specify a buildroot with the --buildroot option.')
+      parser.error('Please specify a buildroot with the --buildbot option.')
 
     options.buildroot = _DetermineDefaultBuildRoot(options.sourceroot,
                                                    build_config['internal'])
@@ -1238,4 +1267,7 @@
           build_config,
           options.remote_trybot)
 
+    if options.buildbot or options.remote_trybot:
+      _DisableYamaHardLinkChecks()
+
     _RunBuildStagesWrapper(options, build_config)