2014-03-23 21:05:45

by Nicolas Iooss

[permalink] [raw]
Subject: [refpolicy] [PATCH] Make scripts compatible with Python 3

Here are all the changes which are needed to make the scripts compatible with
Python 3 while keeping compatibility with Python 2.6 and 2.7:

* use subprocess module instead of commands,
* use sys.maxsize instead of sys.maxint,
* use print as a function,
* use "as" keyword in except statements.
---
support/genhomedircon | 56 ++++++++++++++++++++++++-------------------------
support/gennetfilter.py | 54 +++++++++++++++++++++++------------------------
support/policyvers.py | 2 +-
support/pyplate.py | 4 ++--
4 files changed, 58 insertions(+), 58 deletions(-)

diff --git a/support/genhomedircon b/support/genhomedircon
index 33dbcc1..ca296f9 100644
--- a/support/genhomedircon
+++ b/support/genhomedircon
@@ -40,13 +40,13 @@
# are always "real" (including root, in the default configuration).
#

-import commands, sys, os, pwd, string, getopt, re
+import subprocess, sys, os, pwd, string, getopt, re

EXCLUDE_LOGINS=["/sbin/nologin", "/bin/false"]

def getStartingUID():
- starting_uid = sys.maxint
- rc=commands.getstatusoutput("grep -h '^UID_MIN' /etc/login.defs")
+ starting_uid = sys.maxsize
+ rc=subprocess.getstatusoutput("grep -h '^UID_MIN' /etc/login.defs")
if rc[0] == 0:
uid_min = re.sub("^UID_MIN[^0-9]*", "", rc[1])
#stip any comment from the end of the line
@@ -54,7 +54,7 @@ def getStartingUID():
uid_min = uid_min.strip()
if int(uid_min) < starting_uid:
starting_uid = int(uid_min)
- rc=commands.getstatusoutput("grep -h '^LU_UIDNUMBER' /etc/libuser.conf")
+ rc=subprocess.getstatusoutput("grep -h '^LU_UIDNUMBER' /etc/libuser.conf")
if rc[0] == 0:
lu_uidnumber = re.sub("^LU_UIDNUMBER[^0-9]*", "", rc[1])
#stip any comment from the end of the line
@@ -63,7 +63,7 @@ def getStartingUID():
lu_uidnumber = lu_uidnumber.strip()
if int(lu_uidnumber) < starting_uid:
starting_uid = int(lu_uidnumber)
- if starting_uid == sys.maxint:
+ if starting_uid == sys.maxsize:
starting_uid = 500
return starting_uid

@@ -87,7 +87,7 @@ def getPrefixes():
return prefixes

def getUsers(filecontextdir):
- rc = commands.getstatusoutput("grep ^user %s/users" % filecontextdir)
+ rc = subprocess.getstatusoutput("grep ^user %s/users" % filecontextdir)
udict = {}
if rc[0] == 0:
ulist = rc[1].strip().split("\n")
@@ -113,9 +113,9 @@ def getUsers(filecontextdir):
return udict

def update(filecontext, user, prefs):
- rc=commands.getstatusoutput("grep -h '^HOME_DIR' %s | grep -v vmware | sed -e 's|HOME_DIR|%s|' -e 's/ROLE/%s/' -e 's/system_u/%s/'" % (filecontext, prefs["home"], prefs["role"], user))
+ rc=subprocess.getstatusoutput("grep -h '^HOME_DIR' %s | grep -v vmware | sed -e 's|HOME_DIR|%s|' -e 's/ROLE/%s/' -e 's/system_u/%s/'" % (filecontext, prefs["home"], prefs["role"], user))
if rc[0] == 0:
- print rc[1]
+ print(rc[1])
else:
errorExit(string.join("grep/sed error ", rc[1]))
return rc
@@ -128,7 +128,7 @@ def oldgenhomedircon(filecontextdir, filecontext):
usage()
#We are going to define home directory used by libuser and show-utils as a home directory root
prefixes = {}
- rc=commands.getstatusoutput("grep -h '^HOME' /etc/default/useradd")
+ rc=subprocess.getstatusoutput("grep -h '^HOME' /etc/default/useradd")
if rc[0] == 0:
homedir = rc[1].split("=")[1]
homedir = homedir.split("#")[0]
@@ -143,7 +143,7 @@ def oldgenhomedircon(filecontextdir, filecontext):
sys.stderr.flush()


- rc=commands.getstatusoutput("grep -h '^LU_HOMEDIRECTORY' /etc/libuser.conf")
+ rc=subprocess.getstatusoutput("grep -h '^LU_HOMEDIRECTORY' /etc/libuser.conf")
if rc[0] == 0:
homedir = rc[1].split("=")[1]
homedir = homedir.split("#")[0]
@@ -165,7 +165,7 @@ def oldgenhomedircon(filecontextdir, filecontext):
#this works by grepping the file_contexts for
# 1. ^/ makes sure this is not a comment
# 2. prints only the regex in the first column first cut on \t then on space
- rc=commands.getstatusoutput("grep \"^/\" %s | cut -f 1 | cut -f 1 -d \" \" " % (sys.argv[2]) )
+ rc=subprocess.getstatusoutput("grep \"^/\" %s | cut -f 1 | cut -f 1 -d \" \" " % (sys.argv[2]) )
if rc[0] == 0:
prefix_regex = rc[1].split("\n")
else:
@@ -204,14 +204,14 @@ def oldgenhomedircon(filecontextdir, filecontext):
sed_dir = "h; s|^HOME_DIR|%s/[^/]+|; s|ROLE_|user_|" % (string.join(prefixes.keys(), "/[^/]+|; s|ROLE_|user_|; p; g; s|^HOME_DIR|"),)

# Fill in HOME_ROOT, HOME_DIR, and ROLE for users not explicitly defined in /etc/security/selinux/src/policy/users
- rc=commands.getstatusoutput("sed -e \"/^HOME_ROOT/{%s}\" -e \"/^HOME_DIR/{%s}\" %s" % (sed_root, sed_dir, filecontext))
+ rc=subprocess.getstatusoutput("sed -e \"/^HOME_ROOT/{%s}\" -e \"/^HOME_DIR/{%s}\" %s" % (sed_root, sed_dir, filecontext))
if rc[0] == 0:
- print rc[1]
+ print(rc[1])
else:
errorExit(string.join("sed error ", rc[1]))

users = getUsers(filecontextdir)
- print "\n#\n# User-specific file contexts\n#\n"
+ print("\n#\n# User-specific file contexts\n#\n")

# Fill in HOME and ROLE for users that are defined
for u in users.keys():
@@ -225,7 +225,7 @@ def oldgenhomedircon(filecontextdir, filecontext):

def getDefaultHomeDir():
ret = []
- rc=commands.getstatusoutput("grep -h '^HOME' /etc/default/useradd")
+ rc=subprocess.getstatusoutput("grep -h '^HOME' /etc/default/useradd")
if rc[0] == 0:
homedir = rc[1].split("=")[1]
homedir = homedir.split("#")[0]
@@ -238,7 +238,7 @@ def getDefaultHomeDir():
sys.stderr.write("%s\n" % rc[1])
sys.stderr.write("You do not have access to /etc/default/useradd HOME=\n")
sys.stderr.flush()
- rc=commands.getstatusoutput("grep -h '^LU_HOMEDIRECTORY' /etc/libuser.conf")
+ rc=subprocess.getstatusoutput("grep -h '^LU_HOMEDIRECTORY' /etc/libuser.conf")
if rc[0] == 0:
homedir = rc[1].split("=")[1]
homedir = homedir.split("#")[0]
@@ -256,7 +256,7 @@ def getDefaultHomeDir():
return ret

def getSELinuxType(directory):
- rc=commands.getstatusoutput("grep ^SELINUXTYPE= %s/config" % directory)
+ rc=subprocess.getstatusoutput("grep ^SELINUXTYPE= %s/config" % directory)
if rc[0]==0:
return rc[1].split("=")[-1].strip()
return "targeted"
@@ -299,7 +299,7 @@ class selinuxConfig:
return self.getFileContextDir()+"/homedir_template"

def getHomeRootContext(self, homedir):
- rc=commands.getstatusoutput("grep HOME_ROOT %s | sed -e \"s|^HOME_ROOT|%s|\"" % ( self.getHomeDirTemplate(), homedir))
+ rc=subprocess.getstatusoutput("grep HOME_ROOT %s | sed -e \"s|^HOME_ROOT|%s|\"" % ( self.getHomeDirTemplate(), homedir))
if rc[0] == 0:
return rc[1]+"\n"
else:
@@ -318,10 +318,10 @@ class selinuxConfig:

def getUsers(self):
users=""
- rc = commands.getstatusoutput('grep "^user" %s' % self.getSystemUsersFile())
+ rc = subprocess.getstatusoutput('grep "^user" %s' % self.getSystemUsersFile())
if rc[0] == 0:
users+=rc[1]+"\n"
- rc = commands.getstatusoutput("grep ^user %s" % self.getUsersFile())
+ rc = subprocess.getstatusoutput("grep ^user %s" % self.getUsersFile())
if rc[0] == 0:
users+=rc[1]
udict = {}
@@ -351,7 +351,7 @@ class selinuxConfig:

def getHomeDirContext(self, user, home, role):
ret="\n\n#\n# Context for user %s\n#\n\n" % user
- rc=commands.getstatusoutput("grep '^HOME_DIR' %s | sed -e 's|HOME_DIR|%s|' -e 's/ROLE/%s/' -e 's/system_u/%s/'" % (self.getHomeDirTemplate(), home, role, user))
+ rc=subprocess.getstatusoutput("grep '^HOME_DIR' %s | sed -e 's|HOME_DIR|%s|' -e 's/ROLE/%s/' -e 's/system_u/%s/'" % (self.getHomeDirTemplate(), home, role, user))
return ret + rc[1] + "\n"

def genHomeDirContext(self):
@@ -363,12 +363,12 @@ class selinuxConfig:
return ret+"\n"

def checkExists(self, home):
- if commands.getstatusoutput("grep -E '^%s[^[:alnum:]_-]' %s" % (home, self.getFileContextFile()))[0] == 0:
+ if subprocess.getstatusoutput("grep -E '^%s[^[:alnum:]_-]' %s" % (home, self.getFileContextFile()))[0] == 0:
return 0
#this works by grepping the file_contexts for
# 1. ^/ makes sure this is not a comment
# 2. prints only the regex in the first column first cut on \t then on space
- rc=commands.getstatusoutput("grep \"^/\" %s | cut -f 1 | cut -f 1 -d \" \" " % self.getFileContextFile() )
+ rc=subprocess.getstatusoutput("grep \"^/\" %s | cut -f 1 | cut -f 1 -d \" \" " % self.getFileContextFile() )
if rc[0] == 0:
prefix_regex = rc[1].split("\n")
else:
@@ -426,14 +426,14 @@ class selinuxConfig:
return ret

def printout(self):
- print self.genoutput()
+ print(self.genoutput())

def write(self):
try:
fd = open(self.getFileContextDir()+"/file_contexts.homedirs", "w")
fd.write(self.genoutput())
fd.close()
- except IOError, error:
+ except IOError as error:
sys.stderr.write("%s: %s\n" % ( sys.argv[0], error ))


@@ -473,9 +473,9 @@ try:
selconf=selinuxConfig(directory, type, usepwd)
selconf.write()

-except getopt.error, error:
+except getopt.error as error:
errorExit(string.join("Options Error ", error))
-except ValueError, error:
+except ValueError as error:
errorExit(string.join("ValueError ", error))
-except IndexError, error:
+except IndexError as error:
errorExit("IndexError")
diff --git a/support/gennetfilter.py b/support/gennetfilter.py
index 866db91..c35fadd 100644
--- a/support/gennetfilter.py
+++ b/support/gennetfilter.py
@@ -49,7 +49,7 @@ def print_input_rules(packets,mls,mcs):
elif mcs:
line += ":"+DEFAULT_MCS

- print line
+ print(line)

for i in packets:
for j in i.ports:
@@ -58,10 +58,10 @@ def print_input_rules(packets,mls,mcs):
line += ":"+j.mls_sens
elif mcs:
line += ":"+j.mcs_cats
- print line
+ print(line)

- print "post -A selinux_new_input -j CONNSECMARK --save"
- print "post -A selinux_new_input -j RETURN"
+ print("post -A selinux_new_input -j CONNSECMARK --save")
+ print("post -A selinux_new_input -j RETURN")

def print_output_rules(packets,mls,mcs):
line = "base -A selinux_new_output -j SECMARK --selctx system_u:object_r:"+DEFAULT_OUTPUT_PACKET
@@ -69,7 +69,7 @@ def print_output_rules(packets,mls,mcs):
line += ":"+DEFAULT_MLS
elif mcs:
line += ":"+DEFAULT_MCS
- print line
+ print(line)

for i in packets:
for j in i.ports:
@@ -78,10 +78,10 @@ def print_output_rules(packets,mls,mcs):
line += ":"+j.mls_sens
elif mcs:
line += ":"+j.mcs_cats
- print line
+ print(line)

- print "post -A selinux_new_output -j CONNSECMARK --save"
- print "post -A selinux_new_output -j RETURN"
+ print("post -A selinux_new_output -j CONNSECMARK --save")
+ print("post -A selinux_new_output -j RETURN")

def parse_corenet(file_name):
packets = []
@@ -118,33 +118,33 @@ def parse_corenet(file_name):
return packets

def print_netfilter_config(packets,mls,mcs):
- print "pre *mangle"
- print "pre :PREROUTING ACCEPT [0:0]"
- print "pre :INPUT ACCEPT [0:0]"
- print "pre :FORWARD ACCEPT [0:0]"
- print "pre :OUTPUT ACCEPT [0:0]"
- print "pre :POSTROUTING ACCEPT [0:0]"
- print "pre :selinux_input - [0:0]"
- print "pre :selinux_output - [0:0]"
- print "pre :selinux_new_input - [0:0]"
- print "pre :selinux_new_output - [0:0]"
- print "pre -A INPUT -j selinux_input"
- print "pre -A OUTPUT -j selinux_output"
- print "pre -A selinux_input -m state --state NEW -j selinux_new_input"
- print "pre -A selinux_input -m state --state RELATED,ESTABLISHED -j CONNSECMARK --restore"
- print "pre -A selinux_output -m state --state NEW -j selinux_new_output"
- print "pre -A selinux_output -m state --state RELATED,ESTABLISHED -j CONNSECMARK --restore"
+ print("pre *mangle")
+ print("pre :PREROUTING ACCEPT [0:0]")
+ print("pre :INPUT ACCEPT [0:0]")
+ print("pre :FORWARD ACCEPT [0:0]")
+ print("pre :OUTPUT ACCEPT [0:0]")
+ print("pre :POSTROUTING ACCEPT [0:0]")
+ print("pre :selinux_input - [0:0]")
+ print("pre :selinux_output - [0:0]")
+ print("pre :selinux_new_input - [0:0]")
+ print("pre :selinux_new_output - [0:0]")
+ print("pre -A INPUT -j selinux_input")
+ print("pre -A OUTPUT -j selinux_output")
+ print("pre -A selinux_input -m state --state NEW -j selinux_new_input")
+ print("pre -A selinux_input -m state --state RELATED,ESTABLISHED -j CONNSECMARK --restore")
+ print("pre -A selinux_output -m state --state NEW -j selinux_new_output")
+ print("pre -A selinux_output -m state --state RELATED,ESTABLISHED -j CONNSECMARK --restore")
print_input_rules(packets,mls,mcs)
print_output_rules(packets,mls,mcs)
- print "post COMMIT"
+ print("post COMMIT")

mls = False
mcs = False

try:
opts, paths = getopt.getopt(sys.argv[1:],'mc',['mls','mcs'])
-except getopt.GetoptError, error:
- print "Invalid options."
+except getopt.GetoptError as error:
+ print("Invalid options.")
sys.exit(1)

for o, a in opts:
diff --git a/support/policyvers.py b/support/policyvers.py
index 0d969a4..a367ef1 100644
--- a/support/policyvers.py
+++ b/support/policyvers.py
@@ -1,4 +1,4 @@
#!/usr/bin/python
import selinux
if selinux.is_selinux_enabled():
- print selinux.security_policyvers()
+ print(selinux.security_policyvers())
diff --git a/support/pyplate.py b/support/pyplate.py
index 44b662a..96f057b 100644
--- a/support/pyplate.py
+++ b/support/pyplate.py
@@ -182,7 +182,7 @@ class ForTemplateNode(TemplateNode):
self.vars = []
for v in self.vars_temp:
self.vars.append(v.strip())
- #print self.vars
+ #print(self.vars)
self.expression = match.group(2)

def execute(self, stream, data):
@@ -258,7 +258,7 @@ class FunctionTemplateNode(TemplateNode):
self.vars = []
for v in self.vars_temp:
self.vars.append(v.strip())
- #print self.vars
+ #print(self.vars)
self.parent.functions[self.function_name] = self

def execute(self, stream, data):
--
1.9.0


2014-03-27 13:40:22

by Nicolas Iooss

[permalink] [raw]
Subject: [refpolicy] [PATCH] Make scripts compatible with Python 3

2014-03-23 22:05 GMT+01:00 Nicolas Iooss <[email protected]>:
> Here are all the changes which are needed to make the scripts compatible with
> Python 3 while keeping compatibility with Python 2.6 and 2.7:
>
> * use subprocess module instead of commands,

I've learnt today that Python 2 doesn't have
subprocess.getstatusoutput function even though the commands module is
deprecated [1] and Python 3 provides it without documenting "New in
python 3" [2] :( I haven't tested building the monolithic policy with
Python 2 after my patch so it didn't occurred to me that this specific
config is broken. I think it's best to cancel at least the
support/genhomedircon part of this patch for now.

Looking at that, is there any reason why support/genhomedircon uses
lines like this instead of opening the file with open() and parsing
the file with Python code?

rc=commands.getstatusoutput("grep \"^/\" %s | cut -f 1 | cut -f 1
-d \" \" " % (sys.argv[2]) )

I believe that every "commands.getstatusoutput" call can be replaced
by pure Python code. I'll send a patch soon (maybe a few days) which
does exactly this, if it's possible and if nobody tells me I'm wrong
in doing that.

Regards,

Nicolas

[1] http://docs.python.org/2/library/commands.html
[2] http://docs.python.org/3.0/library/subprocess.html#subprocess.getstatusoutput

2014-03-27 16:44:17

by cpebenito

[permalink] [raw]
Subject: [refpolicy] [PATCH] Make scripts compatible with Python 3

On 03/27/2014 09:40 AM, Nicolas Iooss wrote:
> 2014-03-23 22:05 GMT+01:00 Nicolas Iooss <[email protected]>:
>> Here are all the changes which are needed to make the scripts compatible with
>> Python 3 while keeping compatibility with Python 2.6 and 2.7:
>>
>> * use subprocess module instead of commands,
>
> I've learnt today that Python 2 doesn't have
> subprocess.getstatusoutput function even though the commands module is
> deprecated [1] and Python 3 provides it without documenting "New in
> python 3" [2] :( I haven't tested building the monolithic policy with
> Python 2 after my patch so it didn't occurred to me that this specific
> config is broken. I think it's best to cancel at least the
> support/genhomedircon part of this patch for now.
>
> Looking at that, is there any reason why support/genhomedircon uses
> lines like this instead of opening the file with open() and parsing
> the file with Python code?
>
> rc=commands.getstatusoutput("grep \"^/\" %s | cut -f 1 | cut -f 1
> -d \" \" " % (sys.argv[2]) )
>
> I believe that every "commands.getstatusoutput" call can be replaced
> by pure Python code. I'll send a patch soon (maybe a few days) which
> does exactly this, if it's possible and if nobody tells me I'm wrong
> in doing that.

I wouldn't worry about that script. We kept it around to work on RHEL4 systems. That OS has been end of life for a while, so I'll probably remove the RHEL4 refpolicy stuff very soon.


--
Chris PeBenito
Tresys Technology, LLC
http://www.tresys.com | oss.tresys.com