ia64/xen-unstable

changeset 11912:328606e0705f

Use the name of the title of the system to boot into (instead of the
kernel version) to determine where to make the entry into the grub
configuration file.

Signed-off-by: Reiner Sailer <sailer@us.ibm.com>
Signed-off-by: Stefan Berger <stefanb@us.ibm.com>
author kfraser@localhost.localdomain
date Fri Oct 20 09:32:16 2006 +0100 (2006-10-20)
parents 49d16162a585
children 02506a744315
files docs/man/xm.pod.1 tools/python/xen/util/security.py tools/python/xen/xm/cfgbootpolicy.py
line diff
     1.1 --- a/docs/man/xm.pod.1	Fri Oct 20 09:30:23 2006 +0100
     1.2 +++ b/docs/man/xm.pod.1	Fri Oct 20 09:32:16 2006 +0100
     1.3 @@ -810,13 +810,13 @@ global policy root directory.
     1.4  Loads the binary representation of the I<policy> into Xen. The binary
     1.5  representation can be created with the B<makepolicy> subcommand.
     1.6  
     1.7 -=item B<cfgbootpolicy> I<policy> [I<kernelversion>]
     1.8 +=item B<cfgbootpolicy> I<policy> [I<boot title>]
     1.9  
    1.10  Configures I<policy> as the boot policy for Xen. It copies the binary
    1.11  policy representation into the /boot directory and adds a module line
    1.12  specifying the binary policy to the /boot/grub/menu.lst file. If your
    1.13  boot configuration includes multiple Xen boot titles, then use the
    1.14 -I<kernelversion> parameter to select the proper title.
    1.15 +I<boot title> parameter to specify a unique part of the proper title.
    1.16  
    1.17  =item B<dumppolicy>
    1.18  
     2.1 --- a/tools/python/xen/util/security.py	Fri Oct 20 09:30:23 2006 +0100
     2.2 +++ b/tools/python/xen/util/security.py	Fri Oct 20 09:32:16 2006 +0100
     2.3 @@ -31,6 +31,7 @@ from xen.util import dictio
     2.4  policy_dir_prefix = "/etc/xen/acm-security/policies"
     2.5  res_label_filename = policy_dir_prefix + "/resource_labels"
     2.6  boot_filename = "/boot/grub/menu.lst"
     2.7 +altboot_filename = "/boot/grub/grub.conf"
     2.8  xensec_xml2bin = "/usr/sbin/xensec_xml2bin"
     2.9  xensec_tool = "/usr/sbin/xensec_tool"
    2.10  
     3.1 --- a/tools/python/xen/xm/cfgbootpolicy.py	Fri Oct 20 09:30:23 2006 +0100
     3.2 +++ b/tools/python/xen/xm/cfgbootpolicy.py	Fri Oct 20 09:32:16 2006 +0100
     3.3 @@ -14,6 +14,7 @@
     3.4  #============================================================================
     3.5  # Copyright (C) 2006 International Business Machines Corp.
     3.6  # Author: Reiner Sailer <sailer@us.ibm.com>
     3.7 +# Contributions: Stefan Berger <stefanb@us.ibm.com>
     3.8  #============================================================================
     3.9  """Configuring a security policy into the boot configuration
    3.10  """
    3.11 @@ -24,67 +25,60 @@ import tempfile
    3.12  import os, stat
    3.13  import shutil
    3.14  import string
    3.15 -from xen.util.security import ACMError, err
    3.16 -from xen.util.security import policy_dir_prefix, boot_filename, xen_title_re
    3.17 -from xen.util.security import any_title_re, xen_kernel_re, kernel_ver_re, any_module_re
    3.18 +import re
    3.19 +from xen.util.security import err
    3.20 +from xen.util.security import policy_dir_prefix, xen_title_re
    3.21 +from xen.util.security import boot_filename, altboot_filename
    3.22 +from xen.util.security import any_title_re, xen_kernel_re, any_module_re
    3.23  from xen.util.security import empty_line_re, binary_name_re, policy_name_re
    3.24  from xen.xm.opts import OptionError
    3.25  
    3.26  def help():
    3.27      return """
    3.28 -    Adds a 'module' line to the Xen grub.conf entry
    3.29 -    so that xen boots into a specific access control
    3.30 -    policy. If kernelversion is not given, then this
    3.31 -    script tries to determine it by looking for a grub
    3.32 -    entry with a line kernel xen.* If there are multiple
    3.33 -    Xen entries, then it must be called with an explicit
    3.34 -    version (it will fail otherwise).\n"""
    3.35 -
    3.36 -def determine_kernelversion(user_specified):
    3.37 -    within_xen_title = 0
    3.38 -    within_xen_entry = 0
    3.39 -    version_list = []
    3.40 -    guess_version = None
    3.41 +    Adds a 'module' line to the Xen grub configuration file entry
    3.42 +    so that Xen boots with a specific access control policy. If
    3.43 +    kernelversion is not given, then this script tries to determine
    3.44 +    it by looking for a title starting with \"XEN\". If there are
    3.45 +    multiple entries matching, then it must be called with the unique
    3.46 +    beginning of the title's name.\n"""
    3.47  
    3.48 -    grub_fd = open(boot_filename)
    3.49 -    for line in grub_fd:
    3.50 -        if xen_title_re.match(line):
    3.51 -            within_xen_title = 1
    3.52 -        elif within_xen_title and xen_kernel_re.match(line):
    3.53 -            within_xen_entry = 1
    3.54 -        elif within_xen_title and within_xen_entry and kernel_ver_re.match(line):
    3.55 -            for i in line.split():
    3.56 -                if (i.find("vmlinuz-") >= 0):
    3.57 -                    # skip start until "vmlinuz-"
    3.58 -                    guess_version = i[i.find("vmlinuz-") + len("vmlinuz-"):]
    3.59 -                    if user_specified:
    3.60 -                        if (guess_version == user_specified):
    3.61 -                            version_list.append(guess_version)
    3.62 -                    else:
    3.63 -                        version_list.append(guess_version)
    3.64 -        elif len(line.split()) > 0:
    3.65 -            if line.split()[0] == "title":
    3.66 -                within_xen_title = 0
    3.67 -                within_xen_entry = 0
    3.68 -    if len(version_list) > 1:
    3.69 -        err("Cannot decide between entries for kernels %s" % version_list)
    3.70 -    elif len(version_list) == 0:
    3.71 -        err("Cannot find a boot entry candidate (please create a Xen boot entry first).")
    3.72 +def strip_title(line):
    3.73 +    """
    3.74 +    strips whitespace left and right and cuts 'title'
    3.75 +    """
    3.76 +    s_title = string.strip(line)
    3.77 +    pos = string.index(s_title, "title")
    3.78 +    if pos >= 0:
    3.79 +        return s_title[pos+6:]
    3.80      else:
    3.81 -        return version_list[0]
    3.82 +        return s_title
    3.83  
    3.84  
    3.85 -
    3.86 -def insert_policy(boot_file, kernel_version, policy_name):
    3.87 +def insert_policy(boot_file, alt_boot_file, user_title, policy_name):
    3.88      """
    3.89      inserts policy binary file as last line of the grub entry
    3.90      matching the kernel_version version
    3.91      """
    3.92 +    if user_title:
    3.93 +        #replace "(" by "\(" and ")" by "\)" for matching
    3.94 +        user_title = string.replace(user_title, "(", "\(")
    3.95 +        user_title = string.replace(user_title, ")", "\)")
    3.96 +        user_title_re = re.compile("\s*title\s+.*%s" \
    3.97 +                                   % user_title, re.IGNORECASE)
    3.98 +    else:
    3.99 +        user_title_re = xen_title_re
   3.100 +
   3.101      within_xen_title = 0
   3.102      within_xen_entry = 0
   3.103      insert_at_end_of_entry = 0
   3.104      path_prefix = ''
   3.105 +    this_title = ''
   3.106 +    extended_titles = []
   3.107      (tmp_fd, tmp_grub) = tempfile.mkstemp()
   3.108 +    #First check whether menu.lst exists
   3.109 +    if not os.path.isfile(boot_file):
   3.110 +        #take alternate boot file (grub.conf) instead
   3.111 +        boot_file = alt_boot_file
   3.112      #follow symlink since menue.lst might be linked to grub.conf
   3.113      if stat.S_ISLNK(os.lstat(boot_file)[stat.ST_MODE]):
   3.114          new_name = os.readlink(boot_file)
   3.115 @@ -95,30 +89,33 @@ def insert_policy(boot_file, kernel_vers
   3.116              path[len(path)-1] = new_name
   3.117              boot_file = '/'.join(path)
   3.118          if not os.path.exists(boot_file):
   3.119 -            err("Boot file \'" + boot_file + "\' not found.")
   3.120 +            err("Boot file \'%s\' not found." % boot_file)
   3.121      grub_fd = open(boot_file)
   3.122      for line in grub_fd:
   3.123 -        if xen_title_re.match(line):
   3.124 +        if user_title_re.match(line):
   3.125 +            this_title = strip_title(line)
   3.126              within_xen_title = 1
   3.127          elif within_xen_title and xen_kernel_re.match(line):
   3.128 -            within_xen_entry = 1
   3.129 -        elif within_xen_title and within_xen_entry and kernel_ver_re.match(line):
   3.130 -            for i in line.split():
   3.131 -                if (i.find("vmlinuz-") >= 0):
   3.132 -                    if  kernel_version == i[i.find("vmlinuz-") + len("vmlinuz-"):]:
   3.133 -                        insert_at_end_of_entry = 1
   3.134 -                        path_prefix = i[0:i.find("vmlinuz-")]
   3.135 +            insert_at_end_of_entry = 1
   3.136 +            #use prefix from xen.gz path for policy
   3.137 +            path_prefix = line.split()[1]
   3.138 +            idx = path_prefix.rfind('/')
   3.139 +            if idx >= 0:
   3.140 +                path_prefix = path_prefix[0:idx+1]
   3.141 +            else:
   3.142 +                path_prefix = ''
   3.143          elif any_module_re.match(line) and insert_at_end_of_entry:
   3.144              if binary_name_re.match(line):
   3.145                  #delete existing policy module line
   3.146                  line=''
   3.147          elif any_title_re.match(line):
   3.148              within_xen_title = 0
   3.149 -            within_xen_entry = 0
   3.150  
   3.151 -        if (empty_line_re.match(line) or any_title_re.match(line)) and insert_at_end_of_entry:
   3.152 +        if (empty_line_re.match(line) or any_title_re.match(line)) and \
   3.153 +            insert_at_end_of_entry:
   3.154              #newline or new title: we insert the policy module line here
   3.155              os.write(tmp_fd, "\tmodule " + path_prefix + policy_name + ".bin\n")
   3.156 +            extended_titles.append(this_title)
   3.157              insert_at_end_of_entry = 0
   3.158          #write the line that was read (except potential existing policy entry)
   3.159          os.write(tmp_fd, line)
   3.160 @@ -126,27 +123,36 @@ def insert_policy(boot_file, kernel_vers
   3.161      if insert_at_end_of_entry:
   3.162          #last entry, no empty line at end of file
   3.163          os.write(tmp_fd, "\tmodule " + path_prefix + policy_name + ".bin\n")
   3.164 +        extended_titles.append(this_title)
   3.165  
   3.166 -    #temp file might be destroyed when closing it, first copy ...
   3.167 +    #if more than one entry was changed, abort
   3.168 +    if len(extended_titles) > 1:
   3.169 +        err("Following boot entries matched: %s. \nPlease specify "
   3.170 +            "unique part of the boot title." % extended_titles)
   3.171 +    if len(extended_titles) == 0:
   3.172 +        err("Boot entry not found. Please specify unique part "
   3.173 +            "of the boot title.")
   3.174 +
   3.175 +    #temp file might be destroyed when closing it, first copy it
   3.176      shutil.move(boot_file, boot_file+"_save")
   3.177      shutil.copyfile(tmp_grub, boot_file)
   3.178      os.close(tmp_fd)
   3.179 -    #temp file did not disappear on my system ...
   3.180 +    #sometimes the temp file does not disappear
   3.181      try:
   3.182          os.remove(tmp_grub)
   3.183      except:
   3.184          pass
   3.185 -
   3.186 +    return extended_titles[0]
   3.187  
   3.188  
   3.189  def main(argv):
   3.190      user_kver = None
   3.191 -    policy = None
   3.192 +    user_title = None
   3.193      if len(argv) == 2:
   3.194          policy = argv[1]
   3.195      elif len(argv) == 3:
   3.196          policy = argv[1]
   3.197 -        user_kver = argv[2]
   3.198 +        user_title = argv[2]
   3.199      else:
   3.200          raise OptionError('Invalid number of arguments')
   3.201      
   3.202 @@ -167,9 +173,10 @@ def main(argv):
   3.203      dst_binary_policy_file = "/boot/" + policy + ".bin"
   3.204      shutil.copyfile(src_binary_policy_file, dst_binary_policy_file)
   3.205      
   3.206 -    kernel_version = determine_kernelversion(user_kver)
   3.207 -    insert_policy(boot_filename, kernel_version, policy)
   3.208 -    print "Boot entry created and \'%s\' copied to /boot" % (policy + ".bin")
   3.209 +    entryname = insert_policy(boot_filename, altboot_filename,
   3.210 +                              user_title, policy)
   3.211 +    print "Boot entry '%s' extended and \'%s\' copied to /boot" \
   3.212 +          % (entryname, policy + ".bin")
   3.213  
   3.214  if __name__ == '__main__':
   3.215      try:
   3.216 @@ -177,4 +184,3 @@ if __name__ == '__main__':
   3.217      except Exception, e:
   3.218          sys.stderr.write('Error: ' + str(e) + '\n')    
   3.219          sys.exit(-1)
   3.220 -