← Back to team overview

yahoo-eng-team team mailing list archive

[Bug 1839899] [NEW] When running on an SELinux enforcing system, cloud-init will not run user-data scripts

 

Public bug reported:

Cloud Vendor: Amazon AWS
Platform:     RHEL7.6
Cloud-Init:   cloud-init-18.5-3.el7.x86_64
Kernel:       3.10.0-1062.el7.x86_64
SELinux:      selinux-policy-targeted-3.13.1-252.el7.1.noarch

--

We have identified an issue where SELinux labeling appears to be
conflicting with the operation of Cloud-Init's user-data execution
process.

In the file: /usr/lib/python2.7/site-packages/cloudinit/util.py
Under the function: runparts()

The system checks for access to the executable using the following line:

        if os.path.isfile(exe_path) and os.access(exe_path, os.X_OK):
                                    ##  ^^^^^^^^^

On an SELinux system in Enforcing mode, os.access() returns false on
this check, even though the file is set to be executable by the root
account, because the SELinux context for the file is
system_u:object_r:cloud_var_lib_t:s0.

Disabling the os.access() check on the line above will cause cloud-init
to throw an error indicating that the execution of the script failed,
and debugging the function underneath that reveals that the root cause
is (oserr 13: Permission Denied).

Adding the following line to the program will work around this problem,
but may cause problems for cloud-init users that use other script
formats:

def runparts(dirp, skip_no_exist=True, exe_prefix=None):
    exe_prefix = "/bin/bash"     ## <<<<-----------------------------<<<<
    if skip_no_exist and not os.path.isdir(dirp):
        return

    failed = []
    attempted = []

It may be necessary to either change the context with which these files
are created to either cloud_init_exec_t or cloud_init_unit_file_t, but
we were unable to put together a working scenario that would enable us
to test this.

Alternately, runparts() or the calling function can check the first line
of the script and if the executable marker (#!) is found, this string
can be extracted from the rest of the line and supplied to the
runparts() function as exe_prefix.

Please advise what the recommended approach should be, and we can
attempt to submit a fix.

** Affects: cloud-init
     Importance: Undecided
         Status: New


** Tags: aws rhel selinux

** Tags added: selinux

** Tags added: aws rhel

-- 
You received this bug notification because you are a member of Yahoo!
Engineering Team, which is subscribed to cloud-init.
https://bugs.launchpad.net/bugs/1839899

Title:
  When running on an SELinux enforcing system, cloud-init will not run
  user-data scripts

Status in cloud-init:
  New

Bug description:
  Cloud Vendor: Amazon AWS
  Platform:     RHEL7.6
  Cloud-Init:   cloud-init-18.5-3.el7.x86_64
  Kernel:       3.10.0-1062.el7.x86_64
  SELinux:      selinux-policy-targeted-3.13.1-252.el7.1.noarch

  --

  We have identified an issue where SELinux labeling appears to be
  conflicting with the operation of Cloud-Init's user-data execution
  process.

  In the file: /usr/lib/python2.7/site-packages/cloudinit/util.py
  Under the function: runparts()

  The system checks for access to the executable using the following
  line:

          if os.path.isfile(exe_path) and os.access(exe_path, os.X_OK):
                                      ##  ^^^^^^^^^

  On an SELinux system in Enforcing mode, os.access() returns false on
  this check, even though the file is set to be executable by the root
  account, because the SELinux context for the file is
  system_u:object_r:cloud_var_lib_t:s0.

  Disabling the os.access() check on the line above will cause cloud-
  init to throw an error indicating that the execution of the script
  failed, and debugging the function underneath that reveals that the
  root cause is (oserr 13: Permission Denied).

  Adding the following line to the program will work around this
  problem, but may cause problems for cloud-init users that use other
  script formats:

  def runparts(dirp, skip_no_exist=True, exe_prefix=None):
      exe_prefix = "/bin/bash"     ## <<<<-----------------------------<<<<
      if skip_no_exist and not os.path.isdir(dirp):
          return

      failed = []
      attempted = []

  It may be necessary to either change the context with which these
  files are created to either cloud_init_exec_t or
  cloud_init_unit_file_t, but we were unable to put together a working
  scenario that would enable us to test this.

  Alternately, runparts() or the calling function can check the first
  line of the script and if the executable marker (#!) is found, this
  string can be extracted from the rest of the line and supplied to the
  runparts() function as exe_prefix.

  Please advise what the recommended approach should be, and we can
  attempt to submit a fix.

To manage notifications about this bug go to:
https://bugs.launchpad.net/cloud-init/+bug/1839899/+subscriptions


Follow ups