Merge pull request #348 from cgzones/monolithic
Improve monolithic policy build support
This commit is contained in:
commit
072f850e23
5
.gitignore
vendored
5
.gitignore
vendored
@ -22,3 +22,8 @@
|
||||
/tmp/
|
||||
|
||||
.vagrant/
|
||||
|
||||
# monolithic generated files
|
||||
/file_contexts
|
||||
/homedir_template
|
||||
/policy.conf
|
||||
|
@ -13,6 +13,11 @@ ifeq "$(kv)" ""
|
||||
kv := $(pv)
|
||||
endif
|
||||
|
||||
# dont print version warnings if we specified a lower version than the kernel supports
|
||||
ifneq "$(OUTPUT_POLICY)" ""
|
||||
kv := $(shell if test $(kv) -gt $(pv); then echo $(pv); else echo $(kv); fi)
|
||||
endif
|
||||
|
||||
# load_policy(8) loads policy from /etc/selinux/<SELINUXTYPE>/policy/policy.$(pv)
|
||||
# It does this by reading the /etc/selinux/config file SELINUXTYPE entry to
|
||||
# form the full path. $(polbinpath) will contain this evaluated path for use as
|
||||
@ -73,10 +78,10 @@ $(polver): $(policy_conf)
|
||||
@echo "Compiling $(NAME) $(polver)"
|
||||
ifneq ($(pv),$(kv))
|
||||
@echo
|
||||
@echo "WARNING: Policy version mismatch! Is your OUTPUT_POLICY set correctly?"
|
||||
@echo "WARNING: Policy version mismatch (policy:$(pv) kernel:$(kv))! Is your OUTPUT_POLICY set correctly?"
|
||||
@echo
|
||||
endif
|
||||
$(verbose) $(CHECKPOLICY) -U $(UNK_PERMS) $^ -o $@
|
||||
$(verbose) $(CHECKPOLICY) -U $(UNK_PERMS) -S -O -E $^ -o $@
|
||||
|
||||
########################################
|
||||
#
|
||||
@ -86,11 +91,11 @@ $(loadpath): $(policy_conf)
|
||||
@echo "Compiling and installing $(NAME) $(loadpath)"
|
||||
ifneq ($(pv),$(kv))
|
||||
@echo
|
||||
@echo "WARNING: Policy version mismatch! Is your OUTPUT_POLICY set correctly?"
|
||||
@echo "WARNING: Policy version mismatch (policy:$(pv) kernel:$(kv))! Is your OUTPUT_POLICY set correctly?"
|
||||
@echo
|
||||
endif
|
||||
@$(INSTALL) -d -m 0755 $(@D)
|
||||
$(verbose) $(CHECKPOLICY) -U $(UNK_PERMS) $^ -o $@
|
||||
$(verbose) $(CHECKPOLICY) -U $(UNK_PERMS) -S -O -E $^ -o $@
|
||||
|
||||
########################################
|
||||
#
|
||||
@ -106,7 +111,7 @@ ifneq ($(polbinpath).$(pv),$(loadpath))
|
||||
Check $(topdir)/config file entry is: "SELINUXTYPE=$(NAME)")
|
||||
endif
|
||||
@echo "Loading $(NAME) $(loadpath)"
|
||||
$(verbose) $(LOADPOLICY) -q $(loadpath)
|
||||
$(verbose) $(LOADPOLICY)
|
||||
|
||||
########################################
|
||||
#
|
||||
@ -212,7 +217,7 @@ $(fcpath): $(fc) $(loadpath) $(userpath)/system.users
|
||||
@$(INSTALL) -d -m 0755 $(@D)
|
||||
$(verbose) $(INSTALL) -m 0644 $(fc) $(fcpath)
|
||||
$(verbose) $(INSTALL) -m 0644 $(homedir_template) $(homedirpath)
|
||||
$(verbose) $(UMASK) 022 ; $(genhomedircon) -d $(topdir) -t $(NAME) $(USEPWD)
|
||||
$(verbose) $(UMASK) 022 ; $(genhomedircon) -d $(topdir) -t $(NAME)
|
||||
|
||||
########################################
|
||||
#
|
||||
@ -262,4 +267,4 @@ clean:
|
||||
$(verbose) rm -f *.res
|
||||
$(verbose) rm -fR $(tmpdir)
|
||||
|
||||
.PHONY: default policy install load reload enableaudit checklabels restorelabels relabel check longcheck clean
|
||||
.PHONY: default policy install load reload enableaudit checklabels restorelabels relabel resetlabels validate check longcheck clean
|
||||
|
@ -8,7 +8,7 @@
|
||||
# version policy it supports. Setting this will
|
||||
# override the version. This only has an
|
||||
# effect for monolithic policies.
|
||||
#OUTPUT_POLICY = 18
|
||||
#OUTPUT_POLICY = 32
|
||||
|
||||
# Policy Type
|
||||
# standard, mls, mcs
|
||||
|
@ -40,7 +40,7 @@
|
||||
# are always "real" (including root, in the default configuration).
|
||||
#
|
||||
|
||||
import sys, os, pwd, getopt, re
|
||||
import sys, pwd, getopt, re, os
|
||||
from subprocess import getstatusoutput
|
||||
|
||||
EXCLUDE_LOGINS=["/sbin/nologin", "/bin/false"]
|
||||
@ -69,190 +69,36 @@ def getStartingUID():
|
||||
starting_uid = 500
|
||||
return starting_uid
|
||||
|
||||
#############################################################################
|
||||
#
|
||||
# This section is just for backwards compatibility
|
||||
#
|
||||
#############################################################################
|
||||
def getPrefixes():
|
||||
ulist = pwd.getpwall()
|
||||
STARTING_UID=getStartingUID()
|
||||
prefixes = {}
|
||||
for u in ulist:
|
||||
if u[2] >= STARTING_UID and \
|
||||
not u[6] in EXCLUDE_LOGINS and \
|
||||
u[5] != "/" and \
|
||||
u[5].count("/") > 1:
|
||||
prefix = u[5][:u[5].rfind("/")]
|
||||
if not prefix in prefixes:
|
||||
prefixes[prefix] = ""
|
||||
return prefixes
|
||||
|
||||
def getUsers(filecontextdir):
|
||||
rc = getstatusoutput("grep ^user %s/users" % filecontextdir)
|
||||
udict = {}
|
||||
if rc[0] == 0:
|
||||
ulist = rc[1].strip().split("\n")
|
||||
for u in ulist:
|
||||
user = u.split()
|
||||
try:
|
||||
if user[1] == "user_u" or user[1] == "system_u":
|
||||
continue
|
||||
# !!! chooses first role in the list to use in the file context !!!
|
||||
role = user[3]
|
||||
if role == "{":
|
||||
role = user[4]
|
||||
role = role.split("_r")[0]
|
||||
home = pwd.getpwnam(user[1])[5]
|
||||
if home == "/":
|
||||
continue
|
||||
prefs = {}
|
||||
prefs["role"] = role
|
||||
prefs["home"] = home
|
||||
udict[user[1]] = prefs
|
||||
except KeyError:
|
||||
sys.stderr.write("The user \"%s\" is not present in the passwd file, skipping...\n" % user[1])
|
||||
return udict
|
||||
|
||||
def update(filecontext, user, prefs):
|
||||
rc=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])
|
||||
else:
|
||||
errorExit("grep/sed error " + rc[1])
|
||||
return rc
|
||||
|
||||
def oldgenhomedircon(filecontextdir, filecontext):
|
||||
sys.stderr.flush()
|
||||
|
||||
if os.path.isdir(filecontextdir) == 0:
|
||||
sys.stderr.write("New usage is the following\n")
|
||||
usage()
|
||||
#We are going to define home directory used by libuser and show-utils as a home directory root
|
||||
prefixes = {}
|
||||
rc=getstatusoutput("grep -h '^HOME' /etc/default/useradd")
|
||||
if rc[0] == 0:
|
||||
homedir = rc[1].split("=")[1]
|
||||
homedir = homedir.split("#")[0]
|
||||
homedir = homedir.strip()
|
||||
if not homedir in prefixes:
|
||||
prefixes[homedir] = ""
|
||||
else:
|
||||
#rc[0] == 256 means the file was there, we read it, but the grep didn't match
|
||||
if rc[0] != 256:
|
||||
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=getstatusoutput("grep -h '^LU_HOMEDIRECTORY' /etc/libuser.conf")
|
||||
if rc[0] == 0:
|
||||
homedir = rc[1].split("=")[1]
|
||||
homedir = homedir.split("#")[0]
|
||||
homedir = homedir.strip()
|
||||
homedir = re.sub(r"[^/a-zA-Z0-9].*$", "", homedir)
|
||||
if not homedir in prefixes:
|
||||
prefixes[homedir] = ""
|
||||
|
||||
#the idea is that we need to find all of the home_root_t directories we do this by just accepting
|
||||
#any default home directory defined by either /etc/libuser.conf or /etc/default/useradd
|
||||
#we then get the potential home directory roots from /etc/passwd or nis or wherever and look at
|
||||
#the defined homedir for all users with UID > STARTING_UID. This list of possible root homedirs
|
||||
#is then checked to see if it has an explicit context defined in the file_contexts. Explicit
|
||||
#is any regex that would match it which does not end with .*$ or .+$ since those are general
|
||||
#recursive matches. We then take any regex which ends with [pattern](/.*)?$ and just check against
|
||||
#[pattern]
|
||||
potential_prefixes = getPrefixes()
|
||||
prefix_regex = {}
|
||||
#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=getstatusoutput("grep \"^/\" %s | cut -f 1 | cut -f 1 -d \" \" " % (sys.argv[2]) )
|
||||
if rc[0] == 0:
|
||||
prefix_regex = rc[1].split("\n")
|
||||
else:
|
||||
sys.stderr.write("%s\n" % rc[1])
|
||||
sys.stderr.write("You do not have access to grep/cut/the file contexts\n")
|
||||
sys.stderr.flush()
|
||||
for potential in potential_prefixes.keys():
|
||||
addme = 1
|
||||
for regex in prefix_regex:
|
||||
#match a trailing (/*)? which is actually a bug in rpc_pipefs
|
||||
regex = re.sub(r"\(/\*\)\?$", "", regex)
|
||||
#match a trailing .+
|
||||
regex = re.sub(r"\.+$", "", regex)
|
||||
#match a trailing .*
|
||||
regex = re.sub(r"\.\*$", "", regex)
|
||||
#strip a (/.*)? which matches anything trailing to a /*$ which matches trailing /'s
|
||||
regex = re.sub(r"\(\/\.\*\)\?", "", regex)
|
||||
regex = regex + "/*$"
|
||||
if re.search(regex, potential, 0):
|
||||
addme = 0
|
||||
if addme == 1:
|
||||
if not potential in prefixes:
|
||||
prefixes[potential] = ""
|
||||
|
||||
|
||||
if prefixes.__eq__({}):
|
||||
sys.stderr.write("LU_HOMEDIRECTORY not set in /etc/libuser.conf\n")
|
||||
sys.stderr.write("HOME= not set in /etc/default/useradd\n")
|
||||
sys.stderr.write("And no users with a reasonable homedir found in passwd/nis/ldap/etc...\n")
|
||||
sys.stderr.write("Assuming /home is the root of home directories\n")
|
||||
sys.stderr.flush()
|
||||
prefixes["/home"] = ""
|
||||
|
||||
# There may be a more elegant sed script to expand a macro to multiple lines, but this works
|
||||
sed_root = "h; s|^HOME_ROOT|%s|" % (prefixes.keys() + "|; p; g; s|^HOME_ROOT|")
|
||||
sed_dir = "h; s|^HOME_DIR|%s/[^/]+|; s|ROLE_|user_|" % (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=getstatusoutput("sed -e \"/^HOME_ROOT/{%s}\" -e \"/^HOME_DIR/{%s}\" %s" % (sed_root, sed_dir, filecontext))
|
||||
if rc[0] == 0:
|
||||
print(rc[1])
|
||||
else:
|
||||
errorExit("sed error " + rc[1])
|
||||
|
||||
users = getUsers(filecontextdir)
|
||||
print("\n#\n# User-specific file contexts\n#\n")
|
||||
|
||||
# Fill in HOME and ROLE for users that are defined
|
||||
for u in users.keys():
|
||||
update(filecontext, u, users[u])
|
||||
|
||||
#############################################################################
|
||||
#
|
||||
# End of backwards compatibility section
|
||||
#
|
||||
#############################################################################
|
||||
|
||||
def getDefaultHomeDir():
|
||||
ret = []
|
||||
rc=getstatusoutput("grep -h '^HOME' /etc/default/useradd")
|
||||
if rc[0] == 0:
|
||||
homedir = rc[1].split("=")[1]
|
||||
homedir = homedir.split("#")[0]
|
||||
homedir = homedir.strip()
|
||||
if not homedir in ret:
|
||||
ret.append(homedir)
|
||||
else:
|
||||
#rc[0] == 256 means the file was there, we read it, but the grep didn't match
|
||||
if rc[0] != 256:
|
||||
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=getstatusoutput("grep -h '^LU_HOMEDIRECTORY' /etc/libuser.conf")
|
||||
if rc[0] == 0:
|
||||
homedir = rc[1].split("=")[1]
|
||||
homedir = homedir.split("#")[0]
|
||||
homedir = homedir.strip()
|
||||
if not homedir in ret:
|
||||
ret.append(homedir)
|
||||
else:
|
||||
#rc[0] == 256 means the file was there, we read it, but the grep didn't match
|
||||
if rc[0] != 256:
|
||||
sys.stderr.write("%s\n" % rc[1])
|
||||
sys.stderr.write("You do not have access to /etc/libuser.conf LU_HOMEDIRECTORY=\n")
|
||||
sys.stderr.flush()
|
||||
if os.path.isfile('/etc/default/useradd'):
|
||||
rc=getstatusoutput("grep -h '^HOME' /etc/default/useradd")
|
||||
if rc[0] == 0:
|
||||
homedir = rc[1].split("=")[1]
|
||||
homedir = homedir.split("#")[0]
|
||||
homedir = homedir.strip()
|
||||
if not homedir in ret:
|
||||
ret.append(homedir)
|
||||
else:
|
||||
#rc[0] == 1 means the file was there, we read it, but the grep didn't match
|
||||
if rc[0] != 1:
|
||||
sys.stderr.write("(%d): %s\n" % (rc[0], rc[1]))
|
||||
sys.stderr.write("You do not have access to /etc/default/useradd HOME=\n")
|
||||
sys.stderr.flush()
|
||||
if os.path.isfile('/etc/libuser.conf'):
|
||||
rc=getstatusoutput("grep -h '^LU_HOMEDIRECTORY' /etc/libuser.conf")
|
||||
if rc[0] == 0:
|
||||
homedir = rc[1].split("=")[1]
|
||||
homedir = homedir.split("#")[0]
|
||||
homedir = homedir.strip()
|
||||
if not homedir in ret:
|
||||
ret.append(homedir)
|
||||
else:
|
||||
#rc[0] == 1 means the file was there, we read it, but the grep didn't match
|
||||
if rc[0] != 1:
|
||||
sys.stderr.write("(%d): %s\n" % (rc[0], rc[1]))
|
||||
sys.stderr.write("You do not have access to /etc/libuser.conf LU_HOMEDIRECTORY=\n")
|
||||
sys.stderr.flush()
|
||||
if ret == []:
|
||||
ret.append("/home")
|
||||
return ret
|
||||
@ -294,18 +140,14 @@ class selinuxConfig:
|
||||
def getFileContextFile(self):
|
||||
return self.getFileContextDir()+"/file_contexts"
|
||||
|
||||
def getContextDir(self):
|
||||
return self.selinuxdir+self.setype+self.contextdir
|
||||
|
||||
def getHomeDirTemplate(self):
|
||||
return self.getFileContextDir()+"/homedir_template"
|
||||
|
||||
def getHomeRootContext(self, homedir):
|
||||
rc=getstatusoutput("grep HOME_ROOT %s | sed -e \"s|^HOME_ROOT|%s|\"" % ( self.getHomeDirTemplate(), homedir))
|
||||
if rc[0] == 0:
|
||||
return rc[1]+"\n"
|
||||
else:
|
||||
errorExit("sed error " + rc[1])
|
||||
if rc[0] != 0:
|
||||
errorExit("sed error (" + str(rc[0]) + "): " + rc[1])
|
||||
return rc[1]+"\n"
|
||||
|
||||
def getUsersFile(self):
|
||||
return self.selinuxdir+self.setype+"/users/local.users"
|
||||
@ -327,7 +169,6 @@ class selinuxConfig:
|
||||
if rc[0] == 0:
|
||||
users+=rc[1]
|
||||
udict = {}
|
||||
prefs = {}
|
||||
if users != "":
|
||||
ulist = users.split("\n")
|
||||
for u in ulist:
|
||||
@ -340,28 +181,39 @@ class selinuxConfig:
|
||||
if role == "{":
|
||||
role = user[4]
|
||||
role = role.split("_r")[0]
|
||||
home = pwd.getpwnam(user[1])[5]
|
||||
pwdentry = pwd.getpwnam(user[1])
|
||||
home = pwdentry[5]
|
||||
if home == "/":
|
||||
continue
|
||||
prefs = {}
|
||||
prefs["role"] = role
|
||||
prefs["home"] = home
|
||||
prefs["name"] = pwdentry[0]
|
||||
prefs["uid"] = pwdentry[2]
|
||||
udict[user[1]] = prefs
|
||||
except KeyError:
|
||||
sys.stderr.write("The user \"%s\" is not present in the passwd file, skipping...\n" % user[1])
|
||||
return udict
|
||||
|
||||
def getHomeDirContext(self, user, home, role):
|
||||
ret="\n\n#\n# Context for user %s\n#\n\n" % user
|
||||
rc=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))
|
||||
def getHomeDirContext(self, seuser, home, role, username, userid):
|
||||
ret = "\n\n#\n# Context for user %s\n#\n\n" % seuser
|
||||
rc = getstatusoutput("grep -E '^HOME_DIR|%%{USERID}|%%{USERNAME}' %s | sed"
|
||||
" -e 's|HOME_DIR|%s|'"
|
||||
" -e 's|ROLE|%s|'"
|
||||
" -e 's|system_u|%s|'"
|
||||
" -e 's|%%{USERID}|%s|'"
|
||||
" -e 's|%%{USERNAME}|%s|'"
|
||||
% (self.getHomeDirTemplate(), home, role, seuser, userid, username))
|
||||
if rc[0] != 0:
|
||||
errorExit("sed error (" + str(rc[0]) + "): " + rc[1])
|
||||
return ret + rc[1] + "\n"
|
||||
|
||||
def genHomeDirContext(self):
|
||||
users = self.getUsers()
|
||||
ret=""
|
||||
# Fill in HOME and ROLE for users that are defined
|
||||
for u in users.keys():
|
||||
ret += self.getHomeDirContext (u, users[u]["home"], users[u]["role"])
|
||||
for u in users:
|
||||
ret += self.getHomeDirContext (u, users[u]["home"], users[u]["role"], users[u]["name"], users[u]["uid"])
|
||||
return ret+"\n"
|
||||
|
||||
def checkExists(self, home):
|
||||
@ -393,8 +245,7 @@ class selinuxConfig:
|
||||
break
|
||||
if exists == 1:
|
||||
return 1
|
||||
else:
|
||||
return 0
|
||||
return 0
|
||||
|
||||
|
||||
def getHomeDirs(self):
|
||||
@ -422,14 +273,11 @@ class selinuxConfig:
|
||||
def genoutput(self):
|
||||
ret= self.heading()
|
||||
for h in self.getHomeDirs():
|
||||
ret += self.getHomeDirContext ("user_u" , h+'/[^/]*', "user")
|
||||
ret += self.getHomeDirContext ("user_u" , h+'/[^/]+', "user", "[^/]+", "[0-9]+")
|
||||
ret += self.getHomeRootContext(h)
|
||||
ret += self.genHomeDirContext()
|
||||
return ret
|
||||
|
||||
def printout(self):
|
||||
print(self.genoutput())
|
||||
|
||||
def write(self):
|
||||
try:
|
||||
fd = open(self.getFileContextDir()+"/file_contexts.homedirs", "w")
|
||||
@ -453,11 +301,11 @@ try:
|
||||
'nopasswd',
|
||||
'dir='])
|
||||
for o,a in gopts:
|
||||
if o == '--type' or o == "-t":
|
||||
if o in ('--type', '-t'):
|
||||
setype=a
|
||||
if o == '--nopasswd' or o == "-n":
|
||||
if o in ('--nopasswd', '-n'):
|
||||
usepwd=0
|
||||
if o == '--dir' or o == "-d":
|
||||
if o in ('--dir', '-d'):
|
||||
directory=a
|
||||
if o == '--help':
|
||||
usage()
|
||||
@ -466,10 +314,6 @@ try:
|
||||
if setype is None:
|
||||
setype=getSELinuxType(directory)
|
||||
|
||||
if len(cmds) == 2:
|
||||
oldgenhomedircon(cmds[0], cmds[1])
|
||||
sys.exit(0)
|
||||
|
||||
if len(cmds) != 0:
|
||||
usage()
|
||||
selconf=selinuxConfig(directory, setype, usepwd)
|
||||
|
Loading…
Reference in New Issue
Block a user