diff --git a/.gitignore b/.gitignore index 3f320d399..4e4f2e3fb 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,8 @@ /tmp/ .vagrant/ + +# monolithic generated files +/file_contexts +/homedir_template +/policy.conf diff --git a/Rules.monolithic b/Rules.monolithic index 7dbc2e1cf..87edd2d36 100644 --- a/Rules.monolithic +++ b/Rules.monolithic @@ -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//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 diff --git a/build.conf b/build.conf index 2ab0b2f22..3f2a2fdb2 100644 --- a/build.conf +++ b/build.conf @@ -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 diff --git a/support/genhomedircon.py b/support/genhomedircon.py index bb4e50617..2721bd7df 100644 --- a/support/genhomedircon.py +++ b/support/genhomedircon.py @@ -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)