diff --git a/.gitignore b/.gitignore index bfada18..9e8c171 100644 --- a/.gitignore +++ b/.gitignore @@ -201,3 +201,4 @@ libselinux-2.0.96.tgz /libselinux-2.3.tgz /libselinux-2.3.tar.gz /libselinux-2.4.tar.gz +/libselinux-2.5-rc1.tar.gz diff --git a/libselinux-fedora.patch b/libselinux-fedora.patch new file mode 100644 index 0000000..1ddb3df --- /dev/null +++ b/libselinux-fedora.patch @@ -0,0 +1,2091 @@ +diff --git libselinux-2.5-rc1/ChangeLog libselinux-2.5-rc1/ChangeLog +index 993158f..2994ded 100644 +--- libselinux-2.5-rc1/ChangeLog ++++ libselinux-2.5-rc1/ChangeLog +@@ -1,4 +1,6 @@ + 2.5-rc1 2016-01-07 ++ * Add selinux_restorecon function, from Richard Haines. ++ * read_spec_entry: fail on non-ascii, from William Roberts. + * Add man information about thread specific functions, from Dan Waslh. + * Don't wrap rpm_execcon with DISABLE_RPM with SWIG, from Petr Lautrbach. + * Correct line count for property and service context files, from Richard Haines. +diff --git libselinux-2.5-rc1/Makefile libselinux-2.5-rc1/Makefile +index 6142b60..bdf9de8 100644 +--- libselinux-2.5-rc1/Makefile ++++ libselinux-2.5-rc1/Makefile +@@ -1,4 +1,4 @@ +-SUBDIRS = src include utils man ++SUBDIRS = src include utils man golang + + DISABLE_AVC ?= n + DISABLE_SETRANS ?= n +diff --git libselinux-2.5-rc1/golang/Makefile libselinux-2.5-rc1/golang/Makefile +new file mode 100644 +index 0000000..b75677b +--- /dev/null ++++ libselinux-2.5-rc1/golang/Makefile +@@ -0,0 +1,22 @@ ++# Installation directories. ++PREFIX ?= $(DESTDIR)/usr ++LIBDIR ?= $(DESTDIR)/usr/lib ++GODIR ?= $(LIBDIR)/golang/src/pkg/github.com/selinux ++all: ++ ++install: ++ [ -d $(GODIR) ] || mkdir -p $(GODIR) ++ install -m 644 selinux.go $(GODIR) ++ ++test: ++ @mkdir selinux ++ @cp selinux.go selinux ++ GOPATH=$(pwd) go run test.go ++ @rm -rf selinux ++ ++clean: ++ @rm -f *~ ++ @rm -rf selinux ++indent: ++ ++relabel: +diff --git libselinux-2.5-rc1/golang/selinux.go libselinux-2.5-rc1/golang/selinux.go +new file mode 100644 +index 0000000..34bf6bb +--- /dev/null ++++ libselinux-2.5-rc1/golang/selinux.go +@@ -0,0 +1,412 @@ ++package selinux ++ ++/* ++ The selinux package is a go bindings to libselinux required to add selinux ++ support to docker. ++ ++ Author Dan Walsh ++ ++ Used some ideas/code from the go-ini packages https://github.com/vaughan0 ++ By Vaughan Newton ++*/ ++ ++// #cgo pkg-config: libselinux ++// #include ++// #include ++import "C" ++import ( ++ "bufio" ++ "crypto/rand" ++ "encoding/binary" ++ "fmt" ++ "io" ++ "os" ++ "path" ++ "path/filepath" ++ "regexp" ++ "strings" ++ "unsafe" ++) ++ ++var ( ++ assignRegex = regexp.MustCompile(`^([^=]+)=(.*)$`) ++ mcsList = make(map[string]bool) ++) ++ ++func Matchpathcon(path string, mode os.FileMode) (string, error) { ++ var con C.security_context_t ++ var scon string ++ rc, err := C.matchpathcon(C.CString(path), C.mode_t(mode), &con) ++ if rc == 0 { ++ scon = C.GoString(con) ++ C.free(unsafe.Pointer(con)) ++ } ++ return scon, err ++} ++ ++func Setfilecon(path, scon string) (int, error) { ++ rc, err := C.lsetfilecon(C.CString(path), C.CString(scon)) ++ return int(rc), err ++} ++ ++func Getfilecon(path string) (string, error) { ++ var scon C.security_context_t ++ var fcon string ++ rc, err := C.lgetfilecon(C.CString(path), &scon) ++ if rc >= 0 { ++ fcon = C.GoString(scon) ++ err = nil ++ } ++ return fcon, err ++} ++ ++func Setfscreatecon(scon string) (int, error) { ++ var ( ++ rc C.int ++ err error ++ ) ++ if scon != "" { ++ rc, err = C.setfscreatecon(C.CString(scon)) ++ } else { ++ rc, err = C.setfscreatecon(nil) ++ } ++ return int(rc), err ++} ++ ++func Getfscreatecon() (string, error) { ++ var scon C.security_context_t ++ var fcon string ++ rc, err := C.getfscreatecon(&scon) ++ if rc >= 0 { ++ fcon = C.GoString(scon) ++ err = nil ++ C.freecon(scon) ++ } ++ return fcon, err ++} ++ ++func Getcon() string { ++ var pcon C.security_context_t ++ C.getcon(&pcon) ++ scon := C.GoString(pcon) ++ C.freecon(pcon) ++ return scon ++} ++ ++func Getpidcon(pid int) (string, error) { ++ var pcon C.security_context_t ++ var scon string ++ rc, err := C.getpidcon(C.pid_t(pid), &pcon) ++ if rc >= 0 { ++ scon = C.GoString(pcon) ++ C.freecon(pcon) ++ err = nil ++ } ++ return scon, err ++} ++ ++func Getpeercon(socket int) (string, error) { ++ var pcon C.security_context_t ++ var scon string ++ rc, err := C.getpeercon(C.int(socket), &pcon) ++ if rc >= 0 { ++ scon = C.GoString(pcon) ++ C.freecon(pcon) ++ err = nil ++ } ++ return scon, err ++} ++ ++func Setexeccon(scon string) error { ++ var val *C.char ++ if !SelinuxEnabled() { ++ return nil ++ } ++ if scon != "" { ++ val = C.CString(scon) ++ } else { ++ val = nil ++ } ++ _, err := C.setexeccon(val) ++ return err ++} ++ ++type Context struct { ++ con []string ++} ++ ++func (c *Context) SetUser(user string) { ++ c.con[0] = user ++} ++func (c *Context) GetUser() string { ++ return c.con[0] ++} ++func (c *Context) SetRole(role string) { ++ c.con[1] = role ++} ++func (c *Context) GetRole() string { ++ return c.con[1] ++} ++func (c *Context) SetType(setype string) { ++ c.con[2] = setype ++} ++func (c *Context) GetType() string { ++ return c.con[2] ++} ++func (c *Context) SetLevel(mls string) { ++ c.con[3] = mls ++} ++func (c *Context) GetLevel() string { ++ return c.con[3] ++} ++func (c *Context) Get() string { ++ return strings.Join(c.con, ":") ++} ++func (c *Context) Set(scon string) { ++ c.con = strings.SplitN(scon, ":", 4) ++} ++func NewContext(scon string) Context { ++ var con Context ++ con.Set(scon) ++ return con ++} ++ ++func SelinuxEnabled() bool { ++ b := C.is_selinux_enabled() ++ if b > 0 { ++ return true ++ } ++ return false ++} ++ ++const ( ++ Enforcing = 1 ++ Permissive = 0 ++ Disabled = -1 ++) ++ ++func SelinuxGetEnforce() int { ++ return int(C.security_getenforce()) ++} ++ ++func SelinuxGetEnforceMode() int { ++ var enforce C.int ++ C.selinux_getenforcemode(&enforce) ++ return int(enforce) ++} ++ ++func mcsAdd(mcs string) { ++ mcsList[mcs] = true ++} ++ ++func mcsDelete(mcs string) { ++ mcsList[mcs] = false ++} ++ ++func mcsExists(mcs string) bool { ++ return mcsList[mcs] ++} ++ ++func IntToMcs(id int, catRange uint32) string { ++ if (id < 1) || (id > 523776) { ++ return "" ++ } ++ ++ SETSIZE := int(catRange) ++ TIER := SETSIZE ++ ++ ORD := id ++ for ORD > TIER { ++ ORD = ORD - TIER ++ TIER -= 1 ++ } ++ TIER = SETSIZE - TIER ++ ORD = ORD + TIER ++ return fmt.Sprintf("s0:c%d,c%d", TIER, ORD) ++} ++ ++func uniqMcs(catRange uint32) string { ++ var n uint32 ++ var c1, c2 uint32 ++ var mcs string ++ for { ++ binary.Read(rand.Reader, binary.LittleEndian, &n) ++ c1 = n % catRange ++ binary.Read(rand.Reader, binary.LittleEndian, &n) ++ c2 = n % catRange ++ if c1 == c2 { ++ continue ++ } else { ++ if c1 > c2 { ++ t := c1 ++ c1 = c2 ++ c2 = t ++ } ++ } ++ mcs = fmt.Sprintf("s0:c%d,c%d", c1, c2) ++ if mcsExists(mcs) { ++ continue ++ } ++ mcsAdd(mcs) ++ break ++ } ++ return mcs ++} ++func freeContext(processLabel string) { ++ var scon Context ++ scon = NewContext(processLabel) ++ mcsDelete(scon.GetLevel()) ++} ++ ++func GetLxcContexts() (processLabel string, fileLabel string) { ++ var val, key string ++ var bufin *bufio.Reader ++ if !SelinuxEnabled() { ++ return ++ } ++ lxcPath := C.GoString(C.selinux_lxc_contexts_path()) ++ fileLabel = "system_u:object_r:svirt_sandbox_file_t:s0" ++ processLabel = "system_u:system_r:svirt_lxc_net_t:s0" ++ ++ in, err := os.Open(lxcPath) ++ if err != nil { ++ goto exit ++ } ++ ++ defer in.Close() ++ bufin = bufio.NewReader(in) ++ ++ for done := false; !done; { ++ var line string ++ if line, err = bufin.ReadString('\n'); err != nil { ++ if err == io.EOF { ++ done = true ++ } else { ++ goto exit ++ } ++ } ++ line = strings.TrimSpace(line) ++ if len(line) == 0 { ++ // Skip blank lines ++ continue ++ } ++ if line[0] == ';' || line[0] == '#' { ++ // Skip comments ++ continue ++ } ++ if groups := assignRegex.FindStringSubmatch(line); groups != nil { ++ key, val = strings.TrimSpace(groups[1]), strings.TrimSpace(groups[2]) ++ if key == "process" { ++ processLabel = strings.Trim(val, "\"") ++ } ++ if key == "file" { ++ fileLabel = strings.Trim(val, "\"") ++ } ++ } ++ } ++exit: ++ var scon Context ++ mcs := IntToMcs(os.Getpid(), 1024) ++ scon = NewContext(processLabel) ++ scon.SetLevel(mcs) ++ processLabel = scon.Get() ++ scon = NewContext(fileLabel) ++ scon.SetLevel(mcs) ++ fileLabel = scon.Get() ++ return processLabel, fileLabel ++} ++ ++func CopyLevel(src, dest string) (string, error) { ++ if !SelinuxEnabled() { ++ return "", nil ++ } ++ if src == "" { ++ return "", nil ++ } ++ rc, err := C.security_check_context(C.CString(src)) ++ if rc != 0 { ++ return "", err ++ } ++ rc, err = C.security_check_context(C.CString(dest)) ++ if rc != 0 { ++ return "", err ++ } ++ scon := NewContext(src) ++ tcon := NewContext(dest) ++ tcon.SetLevel(scon.GetLevel()) ++ return tcon.Get(), nil ++} ++ ++func RestoreCon(fpath string, recurse bool) error { ++ var flabel string ++ var err error ++ var fs os.FileInfo ++ ++ if !SelinuxEnabled() { ++ return nil ++ } ++ ++ if recurse { ++ var paths []string ++ var err error ++ ++ if paths, err = filepath.Glob(path.Join(fpath, "**", "*")); err != nil { ++ return fmt.Errorf("Unable to find directory %v: %v", fpath, err) ++ } ++ ++ for _, fpath := range paths { ++ if err = RestoreCon(fpath, false); err != nil { ++ return fmt.Errorf("Unable to restore selinux context for %v: %v", fpath, err) ++ } ++ } ++ return nil ++ } ++ if fs, err = os.Stat(fpath); err != nil { ++ return fmt.Errorf("Unable stat %v: %v", fpath, err) ++ } ++ ++ if flabel, err = Matchpathcon(fpath, fs.Mode()); flabel == "" { ++ return fmt.Errorf("Unable to get context for %v: %v", fpath, err) ++ } ++ ++ if rc, err := Setfilecon(fpath, flabel); rc != 0 { ++ return fmt.Errorf("Unable to set selinux context for %v: %v", fpath, err) ++ } ++ ++ return nil ++} ++ ++func Test() { ++ var plabel, flabel string ++ if !SelinuxEnabled() { ++ return ++ } ++ ++ plabel, flabel = GetLxcContexts() ++ fmt.Println(plabel) ++ fmt.Println(flabel) ++ freeContext(plabel) ++ plabel, flabel = GetLxcContexts() ++ fmt.Println(plabel) ++ fmt.Println(flabel) ++ freeContext(plabel) ++ if SelinuxEnabled() { ++ fmt.Println("Enabled") ++ } else { ++ fmt.Println("Disabled") ++ } ++ fmt.Println("getenforce ", SelinuxGetEnforce()) ++ fmt.Println("getenforcemode ", SelinuxGetEnforceMode()) ++ flabel, _ = Matchpathcon("/home/dwalsh/.emacs", 0) ++ fmt.Println(flabel) ++ pid := os.Getpid() ++ fmt.Printf("PID:%d MCS:%s\n", pid, IntToMcs(pid, 1023)) ++ fmt.Println(Getcon()) ++ fmt.Println(Getfilecon("/etc/passwd")) ++ fmt.Println(Getpidcon(1)) ++ Setfscreatecon("unconfined_u:unconfined_r:unconfined_t:s0") ++ fmt.Println(Getfscreatecon()) ++ Setfscreatecon("") ++ fmt.Println(Getfscreatecon()) ++ fmt.Println(Getpidcon(1)) ++} +diff --git libselinux-2.5-rc1/golang/test.go libselinux-2.5-rc1/golang/test.go +new file mode 100644 +index 0000000..fed6de8 +--- /dev/null ++++ libselinux-2.5-rc1/golang/test.go +@@ -0,0 +1,9 @@ ++package main ++ ++import ( ++ "./selinux" ++) ++ ++func main() { ++ selinux.Test() ++} +diff --git libselinux-2.5-rc1/include/selinux/restorecon.h libselinux-2.5-rc1/include/selinux/restorecon.h +new file mode 100644 +index 0000000..ba1232e +--- /dev/null ++++ libselinux-2.5-rc1/include/selinux/restorecon.h +@@ -0,0 +1,79 @@ ++#ifndef _RESTORECON_H_ ++#define _RESTORECON_H_ ++ ++#include ++#include ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/** ++ * selinux_restorecon - Relabel files. ++ * @pathname: specifies file/directory to relabel. ++ * @restorecon_flags: specifies the actions to be performed when relabeling. ++ * ++ * selinux_restorecon(3) will automatically call ++ * selinux_restorecon_default_handle(3) and selinux_restorecon_set_sehandle(3) ++ * first time through to set the selabel_open(3) parameters to use the ++ * currently loaded policy file_contexts and request their computed digest. ++ * ++ * Should other selabel_open(3) parameters be required see ++ * selinux_restorecon_set_sehandle(3). ++ */ ++extern int selinux_restorecon(const char *pathname, ++ unsigned int restorecon_flags); ++/* ++ * restorecon_flags options ++ */ ++/* Force the checking of labels even if the stored SHA1 ++ * digest matches the specfiles SHA1 digest. */ ++#define SELINUX_RESTORECON_IGNORE_DIGEST 1 ++/* Do not change file labels */ ++#define SELINUX_RESTORECON_NOCHANGE 2 ++/* If set set change file label to that in spec file. ++ * If not only change type component to that in spec file. */ ++#define SELINUX_RESTORECON_SET_SPECFILE_CTX 4 ++/* Recursively descend directories */ ++#define SELINUX_RESTORECON_RECURSE 8 ++/* Log changes to selinux log. Note that if VERBOSE and ++ * PROGRESS are set, then PROGRESS will take precedence. */ ++#define SELINUX_RESTORECON_VERBOSE 16 ++/* Show progress by printing * to stdout every 1000 files */ ++#define SELINUX_RESTORECON_PROGRESS 32 ++/* Convert passed-in pathname to canonical pathname */ ++#define SELINUX_RESTORECON_REALPATH 64 ++/* Prevent descending into directories that have a different ++ * device number than the pathname from which the descent began */ ++#define SELINUX_RESTORECON_XDEV 128 ++ ++/** ++ * selinux_restorecon_set_sehandle - Set the global fc handle. ++ * @handle: specifies handle to set as the global fc handle. ++ * ++ * Called by a process that has already called selabel_open(3) with it's ++ * required parameters, or if selinux_restorecon_default_handle(3) has been ++ * called to set the default selabel_open(3) parameters. ++ */ ++extern void selinux_restorecon_set_sehandle(struct selabel_handle *hndl); ++ ++/** ++ * selinux_restorecon_default_handle - Sets default selabel_open(3) parameters ++ * to use the currently loaded policy and ++ * file_contexts, also requests the digest. ++ */ ++extern struct selabel_handle *selinux_restorecon_default_handle(void); ++ ++/** ++ * selinux_restorecon_set_exclude_list - Add a list of files or ++ * directories that are to be excluded ++ * from relabeling. ++ * @exclude_list: containing a NULL terminated list of one or more ++ * directories or files not to be relabeled. ++ */ ++extern void selinux_restorecon_set_exclude_list(const char **exclude_list); ++ ++#ifdef __cplusplus ++} ++#endif ++#endif +diff --git libselinux-2.5-rc1/man/man3/selinux_restorecon.3 libselinux-2.5-rc1/man/man3/selinux_restorecon.3 +new file mode 100644 +index 0000000..152b29c +--- /dev/null ++++ libselinux-2.5-rc1/man/man3/selinux_restorecon.3 +@@ -0,0 +1,195 @@ ++.TH "selinux_restorecon" "3" "20 Oct 2015" "Security Enhanced Linux" "SELinux API documentation" ++ ++.SH "NAME" ++selinux_restorecon \- restore file(s) default SELinux security contexts ++. ++.SH "SYNOPSIS" ++.B #include ++.sp ++.BI "int selinux_restorecon(const char **" pathname , ++.in +\w'int selinux_restorecon('u ++.br ++.BI "unsigned int " restorecon_flags ");" ++.in ++. ++.SH "DESCRIPTION" ++.BR selinux_restorecon () ++restores file default security contexts based on: ++.sp ++.RS ++.IR pathname ++containing a directory or file to be relabeled. ++.br ++If this is a directory and the ++.IR restorecon_flags ++.B SELINUX_RESTORECON_RECURSE ++has been set (for decending through directories), then ++.BR selinux_restorecon () ++will write an SHA1 digest of the combined specfiles (see the ++.B NOTES ++section for details) to an extended attribute of ++.IR security.restorecon_last ++once the relabeling has been completed successfully. This digest will be ++checked should ++.BR selinux_restorecon () ++be rerun ++with the ++.IR restorecon_flags ++.B SELINUX_RESTORECON_RECURSE ++flag set. If any of the specfiles had been updated, the digest ++will also be updated. However if the digest is the same, no relabeling checks ++will take place (unless the ++.B SELINUX_RESTORECON_IGNORE_DIGEST ++is set). ++.sp ++.IR restorecon_flags ++contains the labeling option/rules as follows: ++.sp ++.RS ++.sp ++.B SELINUX_RESTORECON_IGNORE_DIGEST ++force the checking of labels even if the stored SHA1 digest matches the ++specfiles SHA1 digest. The specfiles digest will be written to the ++.IR security.restorecon_last ++extended attribute once relabeling has been completed successfully provided the ++.B SELINUX_RESTORECON_NOCHANGE ++has not been set. ++.sp ++.B SELINUX_RESTORECON_NOCHANGE ++don't change any file labels (passive check) or update the digest in the ++.IR security.restorecon_last ++extended attribute. ++.sp ++.B SELINUX_RESTORECON_SET_SPECFILE_CTX ++If set, reset the files label to match the default specfile context. ++if not set only reset the files "type" component of the context to match the ++default specfile context. ++.br ++ ++.sp ++.B SELINUX_RESTORECON_RECURSE ++change file and directory labels recursively (descend directories) ++and if successful write an SHA1 digest of the combined specfiles to an ++extended attribute as described in the ++.B NOTES ++section. ++.sp ++.B SELINUX_RESTORECON_VERBOSE ++log file label changes. ++.RS ++Note that if ++.B SELINUX_RESTORECON_VERBOSE ++and ++.B SELINUX_RESTORECON_PROGRESS ++are set, then ++.B SELINUX_RESTORECON_PROGRESS ++will take precedence. ++.RE ++.sp ++.B SELINUX_RESTORECON_PROGRESS ++show progress by printing * to stdout every 1000 files. ++.sp ++.B SELINUX_RESTORECON_REALPATH ++convert passed-in ++.I pathname ++to the canonical pathname using ++.BR realpath (3). ++.sp ++.B SELINUX_RESTORECON_XDEV ++prevent descending into directories that have a different device number than ++the ++.I pathname ++entry from which the descent began. ++.RE ++.sp ++The behavior regarding the checking and updating of the SHA1 digest described ++above is the default behavior. It is possible to change this by first calling ++.BR selabel_open (3) ++and not enabling the ++.B SELABEL_OPT_DIGEST ++option, then calling ++.BR selinux_restorecon_set_sehandle (3) ++to set the handle to be used by ++.BR selinux_restorecon (3). ++.sp ++If the ++.I pathname ++is a directory path, then it is possible to set files/directories to be exluded ++from the path by calling ++.BR selinux_restorecon_set_exclude_list (3) ++with a ++.B NULL ++terminated list before calling ++.BR selinux_restorecon (3). ++.RE ++. ++.SH "RETURN VALUE" ++On success, zero is returned. On error, \-1 is returned and ++.I errno ++is set appropriately. ++. ++.SH "NOTES" ++To improve performance when relabeling file systems recursively (e.g. the ++.IR restorecon_flags ++.B SELINUX_RESTORECON_RECURSE ++flag is set) ++.BR selinux_restorecon () ++will write an SHA1 digest of the specfiles that are processed by ++.BR selabel_open (3) ++to an extended attribute named ++.IR security.restorecon_last ++to the directory specified in the ++.IR pathname . ++.sp ++To check the extended attribute entry use ++.BR getfattr (1) , ++for example: ++.sp ++.RS ++getfattr -e hex -n security.restorecon_last / ++.RE ++.sp ++The SHA1 digest is calculated by ++.BR selabel_open (3) ++concatenating the specfiles it reads during initialisation with the ++resulting digest and list of specfiles being retrieved by ++.BR selabel_digest (3). ++.sp ++The specfiles consist of the mandatory ++.I file_contexts ++file plus any subs, subs_dist, local and homedir entries (text or binary versions) ++as determined by any ++.BR selabel_open (3) ++options e.g. ++.BR SELABEL_OPT_BASEONLY . ++.sp ++Should any of the specfiles have changed, then when ++.BR selinux_restorecon () ++is run again with the ++.B SELINUX_RESTORECON_RECURSE ++flag set, a new SHA1 digest will be calculated and all files will be automatically ++relabeled depending on the settings of the ++.B SELINUX_RESTORECON_SET_SPECFILE_CTX ++flag (provided ++.B SELINUX_RESTORECON_NOCHANGE ++is not set). ++.sp ++.B /sys ++and in-memory filesystems do not support the ++.IR security.restorecon_last ++extended attribute. ++.sp ++.BR selinux_restorecon () ++does not check whether the mounted filesystems support the ++.B seclabel ++option. These should be set by the caller by ++.BR selinux_restorecon_set_exclude_list (3) ++in the ++.IR exclude_list . ++. ++.SH "SEE ALSO" ++.BR selinux_restorecon_set_sehandle (3), ++.br ++.BR selinux_restorecon_default_handle (3), ++.br ++.BR selinux_restorecon_set_exclude_list (3), +diff --git libselinux-2.5-rc1/man/man3/selinux_restorecon_default_handle.3 libselinux-2.5-rc1/man/man3/selinux_restorecon_default_handle.3 +new file mode 100644 +index 0000000..0f1e737 +--- /dev/null ++++ libselinux-2.5-rc1/man/man3/selinux_restorecon_default_handle.3 +@@ -0,0 +1,59 @@ ++.TH "selinux_restorecon_default_handle" "3" "20 Oct 2015" "Security Enhanced Linux" "SELinux API documentation" ++ ++.SH "NAME" ++selinux_restorecon_default_handle \- sets default parameters for ++.BR selinux_restorecon (3) ++. ++.SH "SYNOPSIS" ++.B #include ++.br ++.B #include ++.sp ++.B "struct selabel_handle *selinux_restorecon_default_handle(void);" ++. ++.SH "DESCRIPTION" ++.BR selinux_restorecon_default_handle () ++sets default parameters for ++.BR selinux_restorecon (3) ++by calling ++.BR selabel_open (3) ++with the ++.B SELABEL_OPT_DIGEST ++option only. This will enable a digest to be calculated on the currently ++loaded policy ++.BR file_contexts (5) ++set of files as described in the ++.B NOTES ++section of ++.BR selinux_restorecon (3). ++.sp ++Calling ++.BR selinux_restorecon_default_handle () ++is optional, however if used then ++.BR selinux_restorecon_set_sehandle (3) ++should be called with the returned handle to set this for use by ++.BR selinux_restorecon (3). ++.sp ++.BR selinux_restorecon_default_handle () ++is optional as ++.BR selinux_restorecon (3) ++will automatically call this and ++.BR selinux_restorecon_set_sehandle (3) ++provided a handle has not already been set, for ++example by ++.BR selinux_restorecon_set_sehandle (3) ++to set customised ++.BR selabel_open (3) ++parameters. ++. ++.SH "RETURN VALUE" ++A non\-NULL handle value is returned on success. On error, NULL is returned and ++.I errno ++is set appropriately. ++. ++.SH "SEE ALSO" ++.BR selinux_restorecon (3), ++.br ++.BR selinux_restorecon_set_sehandle (3), ++.br ++.BR selinux_restorecon_set_exclude_list (3) +diff --git libselinux-2.5-rc1/man/man3/selinux_restorecon_set_exclude_list.3 libselinux-2.5-rc1/man/man3/selinux_restorecon_set_exclude_list.3 +new file mode 100644 +index 0000000..ea1fb78 +--- /dev/null ++++ libselinux-2.5-rc1/man/man3/selinux_restorecon_set_exclude_list.3 +@@ -0,0 +1,32 @@ ++.TH "selinux_restorecon_set_exclude_list" "3" "20 Oct 2015" "Security Enhanced Linux" "SELinux API documentation" ++ ++.SH "NAME" ++selinux_restorecon_set_exclude_list \- set list of files/directories to be ++excluded from relabeling. ++. ++.SH "SYNOPSIS" ++.B #include ++.sp ++.BI "void selinux_restorecon_set_exclude_list(const char **" exclude_list ");" ++.in +\w'void selinux_restorecon_set_exclude_list('u ++. ++.SH "DESCRIPTION" ++.BR selinux_restorecon_set_exclude_list () ++passes to ++.BR selinux_restorecon (3) ++a pointer containing a ++.B NULL ++terminated list of one or more directories or files that are not to be ++relabeled in ++.IR exclude_list . ++.sp ++.BR selinux_restorecon_set_exclude_list () ++must be called prior to ++.BR selinux_restorecon (3). ++. ++.SH "SEE ALSO" ++.BR selinux_restorecon (3), ++.br ++.BR selinux_restorecon_set_sehandle (3), ++.br ++.BR selinux_restorecon_default_handle (3) +diff --git libselinux-2.5-rc1/man/man3/selinux_restorecon_set_sehandle.3 libselinux-2.5-rc1/man/man3/selinux_restorecon_set_sehandle.3 +new file mode 100644 +index 0000000..6182f54 +--- /dev/null ++++ libselinux-2.5-rc1/man/man3/selinux_restorecon_set_sehandle.3 +@@ -0,0 +1,39 @@ ++.TH "selinux_restorecon_set_sehandle" "3" "20 Oct 2015" "Security Enhanced Linux" "SELinux API documentation" ++ ++.SH "NAME" ++selinux_restorecon_set_sehandle \- set a labeling handle for use by ++.BR selinux_restorecon (3) ++. ++.SH "SYNOPSIS" ++.B #include ++.br ++.B #include ++.sp ++.BI "void selinux_restorecon_set_sehandle(struct selabel_handle *" handle ");" ++.in +\w'void selinux_restorecon_set_sehandle('u ++. ++.SH "DESCRIPTION" ++.BR selinux_restorecon_set_sehandle () ++sets the ++.I handle ++to be use by ++.BR selinux_restorecon (3) ++when relabeling files. ++.sp ++.BR selinux_restorecon_set_sehandle () ++is generally used when customised ++.BR selabel_open (3) ++parameters are required to perform relabeling operations with ++.BR selinux_restorecon (3). ++.sp ++.BR selinux_restorecon_set_sehandle () ++will output to the default SELinux log information regarding whether a digest ++is available or not. If it were available, the message will contain the SHA1 ++digest and a list of specfiles used to compute the digest. ++. ++.SH "SEE ALSO" ++.BR selinux_restorecon (3), ++.br ++.BR selinux_restorecon_set_exclude_list (3), ++.br ++.BR selinux_restorecon_default_handle (3) +diff --git libselinux-2.5-rc1/man/man8/selinux.8 libselinux-2.5-rc1/man/man8/selinux.8 +index 6f1034b..c9f188c 100644 +--- libselinux-2.5-rc1/man/man8/selinux.8 ++++ libselinux-2.5-rc1/man/man8/selinux.8 +@@ -91,11 +91,13 @@ This manual page was written by Dan Walsh . + .BR sepolicy (8), + .BR system-config-selinux (8), + .BR togglesebool (8), +-.BR restorecon (8), + .BR fixfiles (8), ++.BR restorecon (8), + .BR setfiles (8), + .BR semanage (8), +-.BR sepolicy(8) ++.BR sepolicy(8), ++.BR seinfo(8), ++.BR sesearch(8) + + Every confined service on the system has a man page in the following format: + .br +diff --git libselinux-2.5-rc1/src/Makefile libselinux-2.5-rc1/src/Makefile +index 79d50d2..d0021ae 100644 +--- libselinux-2.5-rc1/src/Makefile ++++ libselinux-2.5-rc1/src/Makefile +@@ -73,7 +73,7 @@ CFLAGS ?= -O -Wall -W -Wundef -Wformat-y2k -Wformat-security -Winit-self -Wmissi + -fipa-pure-const -Wno-suggest-attribute=pure -Wno-suggest-attribute=const \ + -Werror -Wno-aggregate-return -Wno-redundant-decls + +-override CFLAGS += -I../include -I$(INCLUDEDIR) -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 $(EMFLAGS) ++override CFLAGS += -I../include -I$(INCLUDEDIR) -D_GNU_SOURCE $(EMFLAGS) + + SWIG_CFLAGS += -Wno-error -Wno-unused-variable -Wno-unused-but-set-variable -Wno-unused-parameter \ + -Wno-shadow -Wno-uninitialized -Wno-missing-prototypes -Wno-missing-declarations +diff --git libselinux-2.5-rc1/src/avc_sidtab.c libselinux-2.5-rc1/src/avc_sidtab.c +index 9669264..c775430 100644 +--- libselinux-2.5-rc1/src/avc_sidtab.c ++++ libselinux-2.5-rc1/src/avc_sidtab.c +@@ -81,6 +81,11 @@ sidtab_context_to_sid(struct sidtab *s, + int hvalue, rc = 0; + struct sidtab_node *cur; + ++ if (! ctx) { ++ errno=EINVAL; ++ return -1; ++ } ++ + *sid = NULL; + hvalue = sidtab_hash(ctx); + +diff --git libselinux-2.5-rc1/src/canonicalize_context.c libselinux-2.5-rc1/src/canonicalize_context.c +index 7cf3139..364a746 100644 +--- libselinux-2.5-rc1/src/canonicalize_context.c ++++ libselinux-2.5-rc1/src/canonicalize_context.c +@@ -17,6 +17,11 @@ int security_canonicalize_context_raw(const char * con, + size_t size; + int fd, ret; + ++ if (! con) { ++ errno=EINVAL; ++ return -1; ++ } ++ + if (!selinux_mnt) { + errno = ENOENT; + return -1; +diff --git libselinux-2.5-rc1/src/check_context.c libselinux-2.5-rc1/src/check_context.c +index 52063fa..234749c 100644 +--- libselinux-2.5-rc1/src/check_context.c ++++ libselinux-2.5-rc1/src/check_context.c +@@ -14,6 +14,11 @@ int security_check_context_raw(const char * con) + char path[PATH_MAX]; + int fd, ret; + ++ if (! con) { ++ errno=EINVAL; ++ return -1; ++ } ++ + if (!selinux_mnt) { + errno = ENOENT; + return -1; +diff --git libselinux-2.5-rc1/src/compute_av.c libselinux-2.5-rc1/src/compute_av.c +index 937e5c3..35ace7f 100644 +--- libselinux-2.5-rc1/src/compute_av.c ++++ libselinux-2.5-rc1/src/compute_av.c +@@ -26,6 +26,11 @@ int security_compute_av_flags_raw(const char * scon, + return -1; + } + ++ if ((! scon) || (! tcon)) { ++ errno=EINVAL; ++ return -1; ++ } ++ + snprintf(path, sizeof path, "%s/access", selinux_mnt); + fd = open(path, O_RDWR); + if (fd < 0) +diff --git libselinux-2.5-rc1/src/compute_create.c libselinux-2.5-rc1/src/compute_create.c +index 9559d42..14a65d1 100644 +--- libselinux-2.5-rc1/src/compute_create.c ++++ libselinux-2.5-rc1/src/compute_create.c +@@ -64,6 +64,11 @@ int security_compute_create_name_raw(const char * scon, + return -1; + } + ++ if ((! scon) || (! tcon)) { ++ errno=EINVAL; ++ return -1; ++ } ++ + snprintf(path, sizeof path, "%s/create", selinux_mnt); + fd = open(path, O_RDWR); + if (fd < 0) +diff --git libselinux-2.5-rc1/src/compute_member.c libselinux-2.5-rc1/src/compute_member.c +index 1fc7e41..065d996 100644 +--- libselinux-2.5-rc1/src/compute_member.c ++++ libselinux-2.5-rc1/src/compute_member.c +@@ -25,6 +25,11 @@ int security_compute_member_raw(const char * scon, + return -1; + } + ++ if ((! scon) || (! tcon)) { ++ errno=EINVAL; ++ return -1; ++ } ++ + snprintf(path, sizeof path, "%s/member", selinux_mnt); + fd = open(path, O_RDWR); + if (fd < 0) +diff --git libselinux-2.5-rc1/src/compute_relabel.c libselinux-2.5-rc1/src/compute_relabel.c +index 4615aee..cc77f36 100644 +--- libselinux-2.5-rc1/src/compute_relabel.c ++++ libselinux-2.5-rc1/src/compute_relabel.c +@@ -25,6 +25,11 @@ int security_compute_relabel_raw(const char * scon, + return -1; + } + ++ if ((! scon) || (! tcon)) { ++ errno=EINVAL; ++ return -1; ++ } ++ + snprintf(path, sizeof path, "%s/relabel", selinux_mnt); + fd = open(path, O_RDWR); + if (fd < 0) +diff --git libselinux-2.5-rc1/src/compute_user.c libselinux-2.5-rc1/src/compute_user.c +index b37c5d3..7703c26 100644 +--- libselinux-2.5-rc1/src/compute_user.c ++++ libselinux-2.5-rc1/src/compute_user.c +@@ -24,6 +24,11 @@ int security_compute_user_raw(const char * scon, + return -1; + } + ++ if (! scon) { ++ errno=EINVAL; ++ return -1; ++ } ++ + snprintf(path, sizeof path, "%s/user", selinux_mnt); + fd = open(path, O_RDWR); + if (fd < 0) +diff --git libselinux-2.5-rc1/src/fsetfilecon.c libselinux-2.5-rc1/src/fsetfilecon.c +index 52707d0..0cbe12d 100644 +--- libselinux-2.5-rc1/src/fsetfilecon.c ++++ libselinux-2.5-rc1/src/fsetfilecon.c +@@ -9,8 +9,12 @@ + + int fsetfilecon_raw(int fd, const char * context) + { +- int rc = fsetxattr(fd, XATTR_NAME_SELINUX, context, strlen(context) + 1, +- 0); ++ int rc; ++ if (! context) { ++ errno=EINVAL; ++ return -1; ++ } ++ rc = fsetxattr(fd, XATTR_NAME_SELINUX, context, strlen(context) + 1, 0); + if (rc < 0 && errno == ENOTSUP) { + char * ccontext = NULL; + int err = errno; +diff --git libselinux-2.5-rc1/src/label_android_property.c libselinux-2.5-rc1/src/label_android_property.c +index fea1f8f..290b438 100644 +--- libselinux-2.5-rc1/src/label_android_property.c ++++ libselinux-2.5-rc1/src/label_android_property.c +@@ -89,10 +89,21 @@ static int process_line(struct selabel_handle *rec, + struct saved_data *data = (struct saved_data *)rec->data; + spec_t *spec_arr = data->spec_arr; + unsigned int nspec = data->nspec; ++ const char *errbuf = NULL; + +- items = read_spec_entries(line_buf, 2, &prop, &context); +- if (items <= 0) ++ items = read_spec_entries(line_buf, &errbuf, 2, &prop, &context); ++ if (items < 0) { ++ items = errno; ++ selinux_log(SELINUX_ERROR, ++ "%s: line %u error due to: %s\n", path, ++ lineno, errbuf ?: strerror(errno)); ++ errno = items; ++ return -1; ++ } ++ ++ if (items == 0) + return items; ++ + if (items != 2) { + selinux_log(SELINUX_ERROR, + "%s: line %u is missing fields\n", path, +diff --git libselinux-2.5-rc1/src/label_file.h libselinux-2.5-rc1/src/label_file.h +index beb1fc2..72fed1f 100644 +--- libselinux-2.5-rc1/src/label_file.h ++++ libselinux-2.5-rc1/src/label_file.h +@@ -1,6 +1,9 @@ + #ifndef _SELABEL_FILE_H_ + #define _SELABEL_FILE_H_ + ++#include ++#include ++ + #include + + #include "callbacks.h" +@@ -390,8 +393,17 @@ static inline int process_line(struct selabel_handle *rec, + unsigned int nspec = data->nspec; + const char *errbuf = NULL; + +- items = read_spec_entries(line_buf, 3, ®ex, &type, &context); +- if (items <= 0) ++ items = read_spec_entries(line_buf, &errbuf, 3, ®ex, &type, &context); ++ if (items < 0) { ++ rc = errno; ++ selinux_log(SELINUX_ERROR, ++ "%s: line %u error due to: %s\n", path, ++ lineno, errbuf ?: strerror(errno)); ++ errno = rc; ++ return -1; ++ } ++ ++ if (items == 0) + return items; + + if (items < 2) { +diff --git libselinux-2.5-rc1/src/label_internal.h libselinux-2.5-rc1/src/label_internal.h +index cefa80b..aa48fff 100644 +--- libselinux-2.5-rc1/src/label_internal.h ++++ libselinux-2.5-rc1/src/label_internal.h +@@ -140,6 +140,6 @@ compat_validate(struct selabel_handle *rec, + * The read_spec_entries function may be used to + * replace sscanf to read entries from spec files. + */ +-extern int read_spec_entries(char *line_buf, int num_args, ...); ++extern int read_spec_entries(char *line_buf, const char **errbuf, int num_args, ...); + + #endif /* _SELABEL_INTERNAL_H_ */ +diff --git libselinux-2.5-rc1/src/label_support.c libselinux-2.5-rc1/src/label_support.c +index 324dc51..26f9ef1 100644 +--- libselinux-2.5-rc1/src/label_support.c ++++ libselinux-2.5-rc1/src/label_support.c +@@ -10,14 +10,19 @@ + #include + #include + #include ++#include + #include "label_internal.h" + + /* +- * The read_spec_entries and read_spec_entry functions may be used to +- * replace sscanf to read entries from spec files. The file and +- * property services now use these. ++ * Read an entry from a spec file (e.g. file_contexts) ++ * entry - Buffer to allocate for the entry. ++ * ptr - current location of the line to be processed. ++ * returns - 0 on success and *entry is set to be a null ++ * terminated value. On Error it returns -1 and ++ * errno will be set. ++ * + */ +-static inline int read_spec_entry(char **entry, char **ptr, int *len) ++static inline int read_spec_entry(char **entry, char **ptr, int *len, const char **errbuf) + { + *entry = NULL; + char *tmp_buf = NULL; +@@ -29,6 +34,11 @@ static inline int read_spec_entry(char **entry, char **ptr, int *len) + *len = 0; + + while (!isspace(**ptr) && **ptr != '\0') { ++ if (!isascii(**ptr)) { ++ errno = EINVAL; ++ *errbuf = "Non-ASCII characters found"; ++ return -1; ++ } + (*ptr)++; + (*len)++; + } +@@ -44,18 +54,23 @@ static inline int read_spec_entry(char **entry, char **ptr, int *len) + + /* + * line_buf - Buffer containing the spec entries . ++ * errbuf - Double pointer used for passing back specific error messages. + * num_args - The number of spec parameter entries to process. + * ... - A 'char **spec_entry' for each parameter. +- * returns - The number of items processed. ++ * returns - The number of items processed. On error, it returns -1 with errno ++ * set and may set errbuf to a specific error message. + * + * This function calls read_spec_entry() to do the actual string processing. ++ * As such, can return anything from that function as well. + */ +-int hidden read_spec_entries(char *line_buf, int num_args, ...) ++int hidden read_spec_entries(char *line_buf, const char **errbuf, int num_args, ...) + { + char **spec_entry, *buf_p; + int len, rc, items, entry_len = 0; + va_list ap; + ++ *errbuf = NULL; ++ + len = strlen(line_buf); + if (line_buf[len - 1] == '\n') + line_buf[len - 1] = '\0'; +@@ -85,7 +100,7 @@ int hidden read_spec_entries(char *line_buf, int num_args, ...) + return items; + } + +- rc = read_spec_entry(spec_entry, &buf_p, &entry_len); ++ rc = read_spec_entry(spec_entry, &buf_p, &entry_len, errbuf); + if (rc < 0) { + va_end(ap); + return rc; +diff --git libselinux-2.5-rc1/src/lsetfilecon.c libselinux-2.5-rc1/src/lsetfilecon.c +index 1d3b28a..ea6d70b 100644 +--- libselinux-2.5-rc1/src/lsetfilecon.c ++++ libselinux-2.5-rc1/src/lsetfilecon.c +@@ -9,8 +9,13 @@ + + int lsetfilecon_raw(const char *path, const char * context) + { +- int rc = lsetxattr(path, XATTR_NAME_SELINUX, context, strlen(context) + 1, +- 0); ++ int rc; ++ if (! context) { ++ errno=EINVAL; ++ return -1; ++ } ++ ++ rc = lsetxattr(path, XATTR_NAME_SELINUX, context, strlen(context) + 1, 0); + if (rc < 0 && errno == ENOTSUP) { + char * ccontext = NULL; + int err = errno; +diff --git libselinux-2.5-rc1/src/matchpathcon.c libselinux-2.5-rc1/src/matchpathcon.c +index 5b495a0..3868711 100644 +--- libselinux-2.5-rc1/src/matchpathcon.c ++++ libselinux-2.5-rc1/src/matchpathcon.c +@@ -2,6 +2,7 @@ + #include + #include + #include ++#include + #include "selinux_internal.h" + #include "label_internal.h" + #include "callbacks.h" +@@ -62,7 +63,7 @@ static void + { + va_list ap; + va_start(ap, fmt); +- vfprintf(stderr, fmt, ap); ++ vsyslog(LOG_ERR, fmt, ap); + va_end(ap); + } + +diff --git libselinux-2.5-rc1/src/selinux_internal.h libselinux-2.5-rc1/src/selinux_internal.h +index 46566f6..3d3fecf 100644 +--- libselinux-2.5-rc1/src/selinux_internal.h ++++ libselinux-2.5-rc1/src/selinux_internal.h +@@ -82,6 +82,7 @@ hidden_proto(selinux_mkload_policy) + hidden_proto(selinux_customizable_types_path) + hidden_proto(selinux_media_context_path) + hidden_proto(selinux_x_context_path) ++ hidden_proto(selinux_openssh_contexts_path) + hidden_proto(selinux_sepgsql_context_path) + hidden_proto(selinux_openssh_contexts_path) + hidden_proto(selinux_systemd_contexts_path) +diff --git libselinux-2.5-rc1/src/selinux_restorecon.c libselinux-2.5-rc1/src/selinux_restorecon.c +new file mode 100644 +index 0000000..17ed6fe +--- /dev/null ++++ libselinux-2.5-rc1/src/selinux_restorecon.c +@@ -0,0 +1,486 @@ ++/* ++ * The majority of this code is from Android's ++ * external/libselinux/src/android.c and upstream ++ * selinux/policycoreutils/setfiles/restorecon.c ++ * ++ * See selinux_restorecon(3) for details. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "callbacks.h" ++#include "selinux_internal.h" ++ ++#define RESTORECON_LAST "security.restorecon_last" ++ ++#define SYS_PATH "/sys" ++#define SYS_PREFIX SYS_PATH "/" ++ ++static struct selabel_handle *fc_sehandle = NULL; ++static unsigned char *fc_digest = NULL; ++static size_t fc_digest_len = 0; ++static const char **fc_exclude_list = NULL; ++static size_t fc_count = 0; ++#define STAR_COUNT 1000 ++ ++static void restorecon_init(void) ++{ ++ struct selabel_handle *sehandle = NULL; ++ ++ if (!fc_sehandle) { ++ sehandle = selinux_restorecon_default_handle(); ++ selinux_restorecon_set_sehandle(sehandle); ++ } ++} ++ ++static pthread_once_t fc_once = PTHREAD_ONCE_INIT; ++ ++ ++static int check_excluded(const char *file) ++{ ++ int i; ++ ++ for (i = 0; fc_exclude_list[i]; i++) { ++ if (strcmp(file, fc_exclude_list[i]) == 0) ++ return 1; ++ } ++ return 0; ++} ++ ++/* Called if SELINUX_RESTORECON_SET_SPECFILE_CTX is not set to check if ++ * the type components differ, updating newtypecon if so. */ ++static int compare_types(char *curcon, char *newcon, char **newtypecon) ++{ ++ int types_differ = 0; ++ context_t cona; ++ context_t conb; ++ int rc = 0; ++ ++ cona = context_new(curcon); ++ if (!cona) { ++ rc = -1; ++ goto out; ++ } ++ conb = context_new(newcon); ++ if (!conb) { ++ context_free(cona); ++ rc = -1; ++ goto out; ++ } ++ ++ types_differ = strcmp(context_type_get(cona), context_type_get(conb)); ++ if (types_differ) { ++ rc |= context_user_set(conb, context_user_get(cona)); ++ rc |= context_role_set(conb, context_role_get(cona)); ++ rc |= context_range_set(conb, context_range_get(cona)); ++ if (!rc) { ++ *newtypecon = strdup(context_str(conb)); ++ if (!*newtypecon) { ++ rc = -1; ++ goto err; ++ } ++ } ++ } ++ ++err: ++ context_free(cona); ++ context_free(conb); ++out: ++ return rc; ++} ++ ++static int restorecon_sb(const char *pathname, const struct stat *sb, ++ bool nochange, bool verbose, ++ bool progress, bool specctx) ++{ ++ char *newcon = NULL; ++ char *curcon = NULL; ++ char *newtypecon = NULL; ++ int rc = 0; ++ bool updated = false; ++ ++ if (selabel_lookup_raw(fc_sehandle, &newcon, pathname, sb->st_mode) < 0) ++ return 0; /* no match, but not an error */ ++ ++ if (lgetfilecon_raw(pathname, &curcon) < 0) { ++ if (errno != ENODATA) ++ goto err; ++ ++ curcon = NULL; ++ } ++ ++ if (progress) { ++ fc_count++; ++ if (fc_count % STAR_COUNT == 0) { ++ fprintf(stdout, "*"); ++ fflush(stdout); ++ } ++ } ++ ++ if (strcmp(curcon, newcon) != 0) { ++ if (!specctx && curcon && ++ (is_context_customizable(curcon) > 0)) { ++ if (verbose) { ++ selinux_log(SELINUX_INFO, ++ "%s not reset as customized by admin to %s\n", ++ pathname, curcon); ++ goto out; ++ } ++ } ++ ++ if (!specctx && curcon) { ++ /* If types different then update newcon. */ ++ rc = compare_types(curcon, newcon, &newtypecon); ++ if (rc) ++ goto err; ++ ++ if (newtypecon) { ++ freecon(newcon); ++ newcon = newtypecon; ++ } else { ++ goto out; ++ } ++ } ++ ++ if (!nochange) { ++ if (lsetfilecon(pathname, newcon) < 0) ++ goto err; ++ updated = true; ++ } ++ ++ if (verbose) ++ selinux_log(SELINUX_INFO, ++ "%s %s from %s to %s\n", ++ updated ? "Relabeled" : "Would relabel", ++ pathname, curcon, newcon); ++ } ++ ++out: ++ rc = 0; ++out1: ++ freecon(curcon); ++ freecon(newcon); ++ return rc; ++err: ++ selinux_log(SELINUX_ERROR, ++ "Could not set context for %s: %s\n", ++ pathname, strerror(errno)); ++ rc = -1; ++ goto out1; ++} ++ ++/* ++ * Public API ++ */ ++ ++/* selinux_restorecon(3) - Main function that is responsible for labeling */ ++int selinux_restorecon(const char *pathname_orig, ++ unsigned int restorecon_flags) ++{ ++ bool ignore = (restorecon_flags & ++ SELINUX_RESTORECON_IGNORE_DIGEST) ? true : false; ++ bool nochange = (restorecon_flags & ++ SELINUX_RESTORECON_NOCHANGE) ? true : false; ++ bool verbose = (restorecon_flags & ++ SELINUX_RESTORECON_VERBOSE) ? true : false; ++ bool progress = (restorecon_flags & ++ SELINUX_RESTORECON_PROGRESS) ? true : false; ++ bool recurse = (restorecon_flags & ++ SELINUX_RESTORECON_RECURSE) ? true : false; ++ bool specctx = (restorecon_flags & ++ SELINUX_RESTORECON_SET_SPECFILE_CTX) ? true : false; ++ bool userealpath = (restorecon_flags & ++ SELINUX_RESTORECON_REALPATH) ? true : false; ++ bool xdev = (restorecon_flags & ++ SELINUX_RESTORECON_XDEV) ? true : false; ++ bool issys; ++ bool setrestoreconlast = true; /* TRUE = set xattr RESTORECON_LAST ++ * FALSE = don't use xattr */ ++ struct stat sb; ++ struct statfs sfsb; ++ FTS *fts; ++ FTSENT *ftsent; ++ char *pathname = NULL, *pathdnamer = NULL, *pathdname, *pathbname; ++ char *paths[2] = { NULL , NULL }; ++ int fts_flags; ++ int error, sverrno; ++ char *xattr_value = NULL; ++ ssize_t size; ++ ++ if (verbose && progress) ++ verbose = false; ++ ++ __selinux_once(fc_once, restorecon_init); ++ ++ if (!fc_sehandle) ++ return -1; ++ ++ if (fc_digest_len) { ++ xattr_value = malloc(fc_digest_len); ++ if (!xattr_value) ++ return -1; ++ } ++ ++ /* ++ * Convert passed-in pathname to canonical pathname by resolving ++ * realpath of containing dir, then appending last component name. ++ */ ++ if (userealpath) { ++ pathbname = basename((char *)pathname_orig); ++ if (!strcmp(pathbname, "/") || !strcmp(pathbname, ".") || ++ !strcmp(pathbname, "..")) { ++ pathname = realpath(pathname_orig, NULL); ++ if (!pathname) ++ goto realpatherr; ++ } else { ++ pathdname = dirname((char *)pathname_orig); ++ pathdnamer = realpath(pathdname, NULL); ++ if (!pathdnamer) ++ goto realpatherr; ++ if (!strcmp(pathdnamer, "/")) ++ error = asprintf(&pathname, "/%s", pathbname); ++ else ++ error = asprintf(&pathname, "%s/%s", ++ pathdnamer, pathbname); ++ if (error < 0) ++ goto oom; ++ } ++ } else { ++ pathname = strdup(pathname_orig); ++ if (!pathname) ++ goto oom; ++ } ++ ++ paths[0] = pathname; ++ issys = (!strcmp(pathname, SYS_PATH) || ++ !strncmp(pathname, SYS_PREFIX, ++ sizeof(SYS_PREFIX) - 1)) ? true : false; ++ ++ if (lstat(pathname, &sb) < 0) { ++ error = -1; ++ goto cleanup; ++ } ++ ++ /* Ignore restoreconlast if not a directory */ ++ if ((sb.st_mode & S_IFDIR) != S_IFDIR) ++ setrestoreconlast = false; ++ ++ if (!recurse) { ++ error = restorecon_sb(pathname, &sb, nochange, verbose, ++ progress, specctx); ++ goto cleanup; ++ } ++ ++ /* Ignore restoreconlast on /sys */ ++ if (issys) ++ setrestoreconlast = false; ++ ++ /* Ignore restoreconlast on in-memory filesystems */ ++ if (statfs(pathname, &sfsb) == 0) { ++ if (sfsb.f_type == RAMFS_MAGIC || sfsb.f_type == TMPFS_MAGIC) ++ setrestoreconlast = false; ++ } ++ ++ if (setrestoreconlast) { ++ size = getxattr(pathname, RESTORECON_LAST, xattr_value, ++ fc_digest_len); ++ ++ if (!ignore && size == fc_digest_len && ++ memcmp(fc_digest, xattr_value, fc_digest_len) ++ == 0) { ++ selinux_log(SELINUX_INFO, ++ "Skipping restorecon as matching digest on: %s\n", ++ pathname); ++ error = 0; ++ goto cleanup; ++ } ++ } ++ ++ if (xdev) ++ fts_flags = FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV; ++ else ++ fts_flags = FTS_PHYSICAL | FTS_NOCHDIR; ++ ++ fts = fts_open(paths, fts_flags, NULL); ++ if (!fts) { ++ error = -1; ++ goto cleanup; ++ } ++ ++ error = 0; ++ while ((ftsent = fts_read(fts)) != NULL) { ++ switch (ftsent->fts_info) { ++ case FTS_DC: ++ selinux_log(SELINUX_ERROR, ++ "Directory cycle on %s.\n", ++ ftsent->fts_path); ++ errno = ELOOP; ++ error = -1; ++ goto out; ++ case FTS_DP: ++ continue; ++ case FTS_DNR: ++ selinux_log(SELINUX_ERROR, ++ "Could not read %s: %s.\n", ++ ftsent->fts_path, ++ strerror(ftsent->fts_errno)); ++ fts_set(fts, ftsent, FTS_SKIP); ++ continue; ++ case FTS_NS: ++ selinux_log(SELINUX_ERROR, ++ "Could not stat %s: %s.\n", ++ ftsent->fts_path, ++ strerror(ftsent->fts_errno)); ++ fts_set(fts, ftsent, FTS_SKIP); ++ continue; ++ case FTS_ERR: ++ selinux_log(SELINUX_ERROR, ++ "Error on %s: %s.\n", ++ ftsent->fts_path, ++ strerror(ftsent->fts_errno)); ++ fts_set(fts, ftsent, FTS_SKIP); ++ continue; ++ case FTS_D: ++ if (issys && !selabel_partial_match(fc_sehandle, ++ ftsent->fts_path)) { ++ fts_set(fts, ftsent, FTS_SKIP); ++ continue; ++ } ++ /* fall through */ ++ default: ++ if (fc_exclude_list) { ++ if (check_excluded(ftsent->fts_path)) { ++ fts_set(fts, ftsent, FTS_SKIP); ++ continue; ++ } ++ } ++ ++ error |= restorecon_sb(ftsent->fts_path, ++ ftsent->fts_statp, nochange, ++ verbose, progress, specctx); ++ break; ++ } ++ } ++ ++ /* Labeling successful. Mark the top level directory as completed. */ ++ if (setrestoreconlast && !nochange && !error) { ++ error = setxattr(pathname, RESTORECON_LAST, fc_digest, ++ fc_digest_len, 0); ++ if (!error && verbose) ++ selinux_log(SELINUX_INFO, ++ "Updated digest for: %s\n", pathname); ++ } ++ ++out: ++ sverrno = errno; ++ (void) fts_close(fts); ++ errno = sverrno; ++cleanup: ++ free(pathdnamer); ++ free(pathname); ++ free(xattr_value); ++ return error; ++oom: ++ sverrno = errno; ++ selinux_log(SELINUX_ERROR, "%s: Out of memory\n", __func__); ++ errno = sverrno; ++ error = -1; ++ goto cleanup; ++realpatherr: ++ sverrno = errno; ++ selinux_log(SELINUX_ERROR, ++ "SELinux: Could not get canonical path for %s restorecon: %s.\n", ++ pathname_orig, strerror(errno)); ++ errno = sverrno; ++ error = -1; ++ goto cleanup; ++} ++ ++/* selinux_restorecon_set_sehandle(3) is called to set the global fc handle */ ++void selinux_restorecon_set_sehandle(struct selabel_handle *hndl) ++{ ++ char **specfiles, *sha1_buf = NULL; ++ size_t num_specfiles, i; ++ ++ fc_sehandle = (struct selabel_handle *) hndl; ++ ++ /* Read digest if requested in selabel_open(3). ++ * If not the set global params. */ ++ if (selabel_digest(hndl, &fc_digest, &fc_digest_len, ++ &specfiles, &num_specfiles) < 0) { ++ fc_digest = NULL; ++ fc_digest_len = 0; ++ selinux_log(SELINUX_INFO, "Digest not requested.\n"); ++ return; ++ } ++ ++ sha1_buf = malloc(fc_digest_len * 2 + 1); ++ if (!sha1_buf) { ++ selinux_log(SELINUX_ERROR, ++ "Error allocating digest buffer: %s\n", ++ strerror(errno)); ++ return; ++ } ++ ++ for (i = 0; i < fc_digest_len; i++) ++ sprintf((&sha1_buf[i * 2]), "%02x", fc_digest[i]); ++ ++ selinux_log(SELINUX_INFO, ++ "specfiles SHA1 digest: %s\n", sha1_buf); ++ selinux_log(SELINUX_INFO, ++ "calculated using the following specfile(s):\n"); ++ if (specfiles) { ++ for (i = 0; i < num_specfiles; i++) ++ selinux_log(SELINUX_INFO, ++ "%s\n", specfiles[i]); ++ } ++ free(sha1_buf); ++} ++ ++/* selinux_restorecon_default_handle(3) is called to set the global restorecon ++ * handle by a process if the default params are required. */ ++struct selabel_handle *selinux_restorecon_default_handle(void) ++{ ++ struct selabel_handle *sehandle; ++ ++ struct selinux_opt fc_opts[] = { ++ { SELABEL_OPT_DIGEST, (char *)1 } ++ }; ++ ++ sehandle = selabel_open(SELABEL_CTX_FILE, fc_opts, 1); ++ ++ if (!sehandle) { ++ selinux_log(SELINUX_ERROR, ++ "Error obtaining file context handle: %s\n", ++ strerror(errno)); ++ return NULL; ++ } ++ ++ return sehandle; ++} ++ ++/* selinux_restorecon_set_exclude_list(3) is called to set a NULL terminated ++ * list of files/directories to exclude. */ ++void selinux_restorecon_set_exclude_list(const char **exclude_list) ++{ ++ fc_exclude_list = exclude_list; ++} +diff --git libselinux-2.5-rc1/src/setfilecon.c libselinux-2.5-rc1/src/setfilecon.c +index d05969c..3f0200e 100644 +--- libselinux-2.5-rc1/src/setfilecon.c ++++ libselinux-2.5-rc1/src/setfilecon.c +@@ -9,8 +9,12 @@ + + int setfilecon_raw(const char *path, const char * context) + { +- int rc = setxattr(path, XATTR_NAME_SELINUX, context, strlen(context) + 1, +- 0); ++ int rc; ++ if (! context) { ++ errno=EINVAL; ++ return -1; ++ } ++ rc = setxattr(path, XATTR_NAME_SELINUX, context, strlen(context) + 1, 0); + if (rc < 0 && errno == ENOTSUP) { + char * ccontext = NULL; + int err = errno; +diff --git libselinux-2.5-rc1/utils/Makefile libselinux-2.5-rc1/utils/Makefile +index cac85c7..cf7af52 100644 +--- libselinux-2.5-rc1/utils/Makefile ++++ libselinux-2.5-rc1/utils/Makefile +@@ -30,6 +30,8 @@ TARGETS=$(patsubst %.c,%,$(wildcard *.c)) + + sefcontext_compile: LDLIBS += -lpcre ../src/libselinux.a -lsepol + ++selinux_restorecon: LDLIBS += -lsepol ++ + ifeq ($(DISABLE_AVC),y) + UNUSED_TARGETS+=compute_av compute_create compute_member compute_relabel + endif +diff --git libselinux-2.5-rc1/utils/selinux_restorecon.c libselinux-2.5-rc1/utils/selinux_restorecon.c +new file mode 100644 +index 0000000..52352c5 +--- /dev/null ++++ libselinux-2.5-rc1/utils/selinux_restorecon.c +@@ -0,0 +1,263 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static char *policyfile; ++ ++static char **exclude_list; ++static int exclude_count; ++ ++static int validate_context(char **contextp) ++{ ++ char *context = *contextp, *tmpcon; ++ ++ if (policyfile) { ++ if (sepol_check_context(context) < 0) { ++ fprintf(stderr, "Invalid context %s\n", context); ++ exit(-1); ++ } ++ } else if (security_canonicalize_context_raw(context, &tmpcon) == 0) { ++ free(context); ++ *contextp = tmpcon; ++ } else if (errno != ENOENT) { ++ fprintf(stderr, "Validate context error: %s\n", ++ strerror(errno)); ++ exit(-1); ++ } ++ ++ return 0; ++} ++ ++static void usage(const char *progname) ++{ ++ fprintf(stderr, ++ "\nusage: %s [-FCnRrdei] [-v|-P] [-p policy] [-f specfile] " ++ "pathname ...\n" ++ "Where:\n\t" ++ "-F Set the label to that in specfile.\n\t" ++ " If not set then reset the \"type\" component of the " ++ "label to that\n\t in the specfile.\n\t" ++ "-C Check labels even if the stored SHA1 digest matches\n\t" ++ " the specfiles SHA1 digest.\n\t" ++ "-n Don't change any file labels (passive check).\n\t" ++ "-R Recursively change file and directory labels.\n\t" ++ "-v Show changes in file labels (-v and -P are mutually " ++ " exclusive).\n\t" ++ "-P Show progress by printing \"*\" to stdout every 1000 files.\n\t" ++ "-r Use realpath(3) to convert pathnames to canonical form.\n\t" ++ "-d Prevent descending into directories that have a " ++ "different\n\t device number than the pathname from which " ++ "the descent began.\n\t" ++ "-e Exclude this file/directory (add multiple -e entries).\n\t" ++ "-i Do not set SELABEL_OPT_VALIDATE option in selabel_open(3)" ++ " then call\n\t selinux_restorecon_set_sehandle(3).\n\t" ++ "-p Optional binary policy file (also sets validate context " ++ "option).\n\t" ++ "-f Optional file contexts file.\n\t" ++ "pathname One or more paths to relabel.\n\n", ++ progname); ++ exit(-1); ++} ++ ++static void add_exclude(const char *directory) ++{ ++ char **tmp_list; ++ ++ if (directory == NULL || directory[0] != '/') { ++ fprintf(stderr, "Full path required for exclude: %s.\n", ++ directory); ++ exit(-1); ++ } ++ ++ /* Add another two entries, one for directory, and the other to ++ * terminate the list */ ++ tmp_list = realloc(exclude_list, sizeof(char *) * (exclude_count + 2)); ++ if (!tmp_list) { ++ fprintf(stderr, "ERROR: realloc failed.\n"); ++ exit(-1); ++ } ++ exclude_list = tmp_list; ++ ++ exclude_list[exclude_count] = strdup(directory); ++ if (!exclude_list[exclude_count]) { ++ fprintf(stderr, "ERROR: strdup failed.\n"); ++ exit(-1); ++ } ++ exclude_count++; ++ exclude_list[exclude_count] = NULL; ++} ++ ++int main(int argc, char **argv) ++{ ++ int opt, i; ++ unsigned int restorecon_flags = 0; ++ char *path = NULL, *digest = NULL, *validate = NULL; ++ FILE *policystream; ++ bool ignore_digest = false, require_selinux = true; ++ bool verbose = false, progress = false; ++ ++ struct selabel_handle *hnd = NULL; ++ struct selinux_opt selabel_option[] = { ++ { SELABEL_OPT_PATH, path }, ++ { SELABEL_OPT_DIGEST, digest }, ++ { SELABEL_OPT_VALIDATE, validate } ++ }; ++ ++ if (argc < 2) ++ usage(argv[0]); ++ ++ exclude_list = NULL; ++ exclude_count = 0; ++ ++ while ((opt = getopt(argc, argv, "iFCnRvPrde:f:p:")) > 0) { ++ switch (opt) { ++ case 'F': ++ restorecon_flags |= ++ SELINUX_RESTORECON_SET_SPECFILE_CTX; ++ break; ++ case 'C': ++ restorecon_flags |= ++ SELINUX_RESTORECON_IGNORE_DIGEST; ++ break; ++ case 'n': ++ restorecon_flags |= SELINUX_RESTORECON_NOCHANGE; ++ break; ++ case 'R': ++ restorecon_flags |= SELINUX_RESTORECON_RECURSE; ++ break; ++ case 'v': ++ if (progress) { ++ fprintf(stderr, ++ "Progress and Verbose are mutually exclusive\n"); ++ exit(-1); ++ } ++ verbose = true; ++ restorecon_flags |= SELINUX_RESTORECON_VERBOSE; ++ break; ++ case 'P': ++ if (verbose) { ++ fprintf(stderr, ++ "Progress and Verbose are mutually exclusive\n"); ++ exit(-1); ++ } ++ progress = true; ++ restorecon_flags |= SELINUX_RESTORECON_PROGRESS; ++ break; ++ case 'r': ++ restorecon_flags |= SELINUX_RESTORECON_REALPATH; ++ break; ++ case 'd': ++ restorecon_flags |= SELINUX_RESTORECON_XDEV; ++ break; ++ case 'e': ++ add_exclude(optarg); ++ break; ++ case 'p': ++ policyfile = optarg; ++ ++ policystream = fopen(policyfile, "r"); ++ if (!policystream) { ++ fprintf(stderr, ++ "ERROR: opening %s: %s\n", ++ policyfile, strerror(errno)); ++ exit(-1); ++ } ++ ++ if (sepol_set_policydb_from_file(policystream) < 0) { ++ fprintf(stderr, ++ "ERROR: reading policy %s: %s\n", ++ policyfile, strerror(errno)); ++ exit(-1); ++ } ++ fclose(policystream); ++ ++ selinux_set_callback(SELINUX_CB_VALIDATE, ++ (union selinux_callback)&validate_context); ++ require_selinux = false; ++ break; ++ case 'f': ++ path = optarg; ++ break; ++ case 'i': ++ ignore_digest = true; ++ break; ++ default: ++ usage(argv[0]); ++ } ++ } ++ ++ if (require_selinux && (is_selinux_enabled() <= 0)) { ++ fprintf(stderr, ++ "SELinux must be enabled to perform this operation.\n"); ++ exit(-1); ++ } ++ ++ if (optind >= argc) { ++ fprintf(stderr, "No pathname specified\n"); ++ exit(-1); ++ } ++ ++ /* If any of these set then do our own selabel_open and pass ++ * handle to selinux_restorecon */ ++ if (ignore_digest || path || policyfile) { ++ if (path) ++ selabel_option[0].value = path; ++ else ++ selabel_option[0].value = NULL; ++ ++ if (ignore_digest) ++ selabel_option[1].value = NULL; ++ else ++ selabel_option[1].value = (char *)1; ++ ++ if (policyfile) /* Validate */ ++ selabel_option[2].value = (char *)1; ++ else ++ selabel_option[2].value = NULL; ++ ++ hnd = selabel_open(SELABEL_CTX_FILE, selabel_option, 3); ++ if (!hnd) { ++ switch (errno) { ++ case EOVERFLOW: ++ fprintf(stderr, "ERROR: Number of specfiles or" ++ " specfile buffer caused an overflow.\n"); ++ break; ++ default: ++ fprintf(stderr, "ERROR: selabel_open: %s\n", ++ strerror(errno)); ++ } ++ exit(-1); ++ } ++ selinux_restorecon_set_sehandle(hnd); ++ } ++ ++ if (exclude_list) ++ selinux_restorecon_set_exclude_list ++ ((const char **)exclude_list); ++ ++ /* Call restorecon for each path in list */ ++ for (i = optind; i < argc; i++) { ++ if (selinux_restorecon(argv[i], restorecon_flags) < 0) { ++ fprintf(stderr, "ERROR: selinux_restorecon: %s\n", ++ strerror(errno)); ++ exit(-1); ++ } ++ } ++ ++ if (exclude_list) { ++ for (i = 0; exclude_list[i]; i++) ++ free(exclude_list[i]); ++ free(exclude_list); ++ } ++ ++ if (hnd) ++ selabel_close(hnd); ++ ++ return 0; ++} diff --git a/libselinux-rhat.patch b/libselinux-rhat.patch deleted file mode 100644 index afbed40..0000000 --- a/libselinux-rhat.patch +++ /dev/null @@ -1,1492 +0,0 @@ -diff --git libselinux-2.4/Makefile libselinux-2.4/Makefile -index 6142b60..bdf9de8 100644 ---- libselinux-2.4/Makefile -+++ libselinux-2.4/Makefile -@@ -1,4 +1,4 @@ --SUBDIRS = src include utils man -+SUBDIRS = src include utils man golang - - DISABLE_AVC ?= n - DISABLE_SETRANS ?= n -diff --git libselinux-2.4/golang/Makefile libselinux-2.4/golang/Makefile -new file mode 100644 -index 0000000..b75677b ---- /dev/null -+++ libselinux-2.4/golang/Makefile -@@ -0,0 +1,22 @@ -+# Installation directories. -+PREFIX ?= $(DESTDIR)/usr -+LIBDIR ?= $(DESTDIR)/usr/lib -+GODIR ?= $(LIBDIR)/golang/src/pkg/github.com/selinux -+all: -+ -+install: -+ [ -d $(GODIR) ] || mkdir -p $(GODIR) -+ install -m 644 selinux.go $(GODIR) -+ -+test: -+ @mkdir selinux -+ @cp selinux.go selinux -+ GOPATH=$(pwd) go run test.go -+ @rm -rf selinux -+ -+clean: -+ @rm -f *~ -+ @rm -rf selinux -+indent: -+ -+relabel: -diff --git libselinux-2.4/golang/selinux.go libselinux-2.4/golang/selinux.go -new file mode 100644 -index 0000000..34bf6bb ---- /dev/null -+++ libselinux-2.4/golang/selinux.go -@@ -0,0 +1,412 @@ -+package selinux -+ -+/* -+ The selinux package is a go bindings to libselinux required to add selinux -+ support to docker. -+ -+ Author Dan Walsh -+ -+ Used some ideas/code from the go-ini packages https://github.com/vaughan0 -+ By Vaughan Newton -+*/ -+ -+// #cgo pkg-config: libselinux -+// #include -+// #include -+import "C" -+import ( -+ "bufio" -+ "crypto/rand" -+ "encoding/binary" -+ "fmt" -+ "io" -+ "os" -+ "path" -+ "path/filepath" -+ "regexp" -+ "strings" -+ "unsafe" -+) -+ -+var ( -+ assignRegex = regexp.MustCompile(`^([^=]+)=(.*)$`) -+ mcsList = make(map[string]bool) -+) -+ -+func Matchpathcon(path string, mode os.FileMode) (string, error) { -+ var con C.security_context_t -+ var scon string -+ rc, err := C.matchpathcon(C.CString(path), C.mode_t(mode), &con) -+ if rc == 0 { -+ scon = C.GoString(con) -+ C.free(unsafe.Pointer(con)) -+ } -+ return scon, err -+} -+ -+func Setfilecon(path, scon string) (int, error) { -+ rc, err := C.lsetfilecon(C.CString(path), C.CString(scon)) -+ return int(rc), err -+} -+ -+func Getfilecon(path string) (string, error) { -+ var scon C.security_context_t -+ var fcon string -+ rc, err := C.lgetfilecon(C.CString(path), &scon) -+ if rc >= 0 { -+ fcon = C.GoString(scon) -+ err = nil -+ } -+ return fcon, err -+} -+ -+func Setfscreatecon(scon string) (int, error) { -+ var ( -+ rc C.int -+ err error -+ ) -+ if scon != "" { -+ rc, err = C.setfscreatecon(C.CString(scon)) -+ } else { -+ rc, err = C.setfscreatecon(nil) -+ } -+ return int(rc), err -+} -+ -+func Getfscreatecon() (string, error) { -+ var scon C.security_context_t -+ var fcon string -+ rc, err := C.getfscreatecon(&scon) -+ if rc >= 0 { -+ fcon = C.GoString(scon) -+ err = nil -+ C.freecon(scon) -+ } -+ return fcon, err -+} -+ -+func Getcon() string { -+ var pcon C.security_context_t -+ C.getcon(&pcon) -+ scon := C.GoString(pcon) -+ C.freecon(pcon) -+ return scon -+} -+ -+func Getpidcon(pid int) (string, error) { -+ var pcon C.security_context_t -+ var scon string -+ rc, err := C.getpidcon(C.pid_t(pid), &pcon) -+ if rc >= 0 { -+ scon = C.GoString(pcon) -+ C.freecon(pcon) -+ err = nil -+ } -+ return scon, err -+} -+ -+func Getpeercon(socket int) (string, error) { -+ var pcon C.security_context_t -+ var scon string -+ rc, err := C.getpeercon(C.int(socket), &pcon) -+ if rc >= 0 { -+ scon = C.GoString(pcon) -+ C.freecon(pcon) -+ err = nil -+ } -+ return scon, err -+} -+ -+func Setexeccon(scon string) error { -+ var val *C.char -+ if !SelinuxEnabled() { -+ return nil -+ } -+ if scon != "" { -+ val = C.CString(scon) -+ } else { -+ val = nil -+ } -+ _, err := C.setexeccon(val) -+ return err -+} -+ -+type Context struct { -+ con []string -+} -+ -+func (c *Context) SetUser(user string) { -+ c.con[0] = user -+} -+func (c *Context) GetUser() string { -+ return c.con[0] -+} -+func (c *Context) SetRole(role string) { -+ c.con[1] = role -+} -+func (c *Context) GetRole() string { -+ return c.con[1] -+} -+func (c *Context) SetType(setype string) { -+ c.con[2] = setype -+} -+func (c *Context) GetType() string { -+ return c.con[2] -+} -+func (c *Context) SetLevel(mls string) { -+ c.con[3] = mls -+} -+func (c *Context) GetLevel() string { -+ return c.con[3] -+} -+func (c *Context) Get() string { -+ return strings.Join(c.con, ":") -+} -+func (c *Context) Set(scon string) { -+ c.con = strings.SplitN(scon, ":", 4) -+} -+func NewContext(scon string) Context { -+ var con Context -+ con.Set(scon) -+ return con -+} -+ -+func SelinuxEnabled() bool { -+ b := C.is_selinux_enabled() -+ if b > 0 { -+ return true -+ } -+ return false -+} -+ -+const ( -+ Enforcing = 1 -+ Permissive = 0 -+ Disabled = -1 -+) -+ -+func SelinuxGetEnforce() int { -+ return int(C.security_getenforce()) -+} -+ -+func SelinuxGetEnforceMode() int { -+ var enforce C.int -+ C.selinux_getenforcemode(&enforce) -+ return int(enforce) -+} -+ -+func mcsAdd(mcs string) { -+ mcsList[mcs] = true -+} -+ -+func mcsDelete(mcs string) { -+ mcsList[mcs] = false -+} -+ -+func mcsExists(mcs string) bool { -+ return mcsList[mcs] -+} -+ -+func IntToMcs(id int, catRange uint32) string { -+ if (id < 1) || (id > 523776) { -+ return "" -+ } -+ -+ SETSIZE := int(catRange) -+ TIER := SETSIZE -+ -+ ORD := id -+ for ORD > TIER { -+ ORD = ORD - TIER -+ TIER -= 1 -+ } -+ TIER = SETSIZE - TIER -+ ORD = ORD + TIER -+ return fmt.Sprintf("s0:c%d,c%d", TIER, ORD) -+} -+ -+func uniqMcs(catRange uint32) string { -+ var n uint32 -+ var c1, c2 uint32 -+ var mcs string -+ for { -+ binary.Read(rand.Reader, binary.LittleEndian, &n) -+ c1 = n % catRange -+ binary.Read(rand.Reader, binary.LittleEndian, &n) -+ c2 = n % catRange -+ if c1 == c2 { -+ continue -+ } else { -+ if c1 > c2 { -+ t := c1 -+ c1 = c2 -+ c2 = t -+ } -+ } -+ mcs = fmt.Sprintf("s0:c%d,c%d", c1, c2) -+ if mcsExists(mcs) { -+ continue -+ } -+ mcsAdd(mcs) -+ break -+ } -+ return mcs -+} -+func freeContext(processLabel string) { -+ var scon Context -+ scon = NewContext(processLabel) -+ mcsDelete(scon.GetLevel()) -+} -+ -+func GetLxcContexts() (processLabel string, fileLabel string) { -+ var val, key string -+ var bufin *bufio.Reader -+ if !SelinuxEnabled() { -+ return -+ } -+ lxcPath := C.GoString(C.selinux_lxc_contexts_path()) -+ fileLabel = "system_u:object_r:svirt_sandbox_file_t:s0" -+ processLabel = "system_u:system_r:svirt_lxc_net_t:s0" -+ -+ in, err := os.Open(lxcPath) -+ if err != nil { -+ goto exit -+ } -+ -+ defer in.Close() -+ bufin = bufio.NewReader(in) -+ -+ for done := false; !done; { -+ var line string -+ if line, err = bufin.ReadString('\n'); err != nil { -+ if err == io.EOF { -+ done = true -+ } else { -+ goto exit -+ } -+ } -+ line = strings.TrimSpace(line) -+ if len(line) == 0 { -+ // Skip blank lines -+ continue -+ } -+ if line[0] == ';' || line[0] == '#' { -+ // Skip comments -+ continue -+ } -+ if groups := assignRegex.FindStringSubmatch(line); groups != nil { -+ key, val = strings.TrimSpace(groups[1]), strings.TrimSpace(groups[2]) -+ if key == "process" { -+ processLabel = strings.Trim(val, "\"") -+ } -+ if key == "file" { -+ fileLabel = strings.Trim(val, "\"") -+ } -+ } -+ } -+exit: -+ var scon Context -+ mcs := IntToMcs(os.Getpid(), 1024) -+ scon = NewContext(processLabel) -+ scon.SetLevel(mcs) -+ processLabel = scon.Get() -+ scon = NewContext(fileLabel) -+ scon.SetLevel(mcs) -+ fileLabel = scon.Get() -+ return processLabel, fileLabel -+} -+ -+func CopyLevel(src, dest string) (string, error) { -+ if !SelinuxEnabled() { -+ return "", nil -+ } -+ if src == "" { -+ return "", nil -+ } -+ rc, err := C.security_check_context(C.CString(src)) -+ if rc != 0 { -+ return "", err -+ } -+ rc, err = C.security_check_context(C.CString(dest)) -+ if rc != 0 { -+ return "", err -+ } -+ scon := NewContext(src) -+ tcon := NewContext(dest) -+ tcon.SetLevel(scon.GetLevel()) -+ return tcon.Get(), nil -+} -+ -+func RestoreCon(fpath string, recurse bool) error { -+ var flabel string -+ var err error -+ var fs os.FileInfo -+ -+ if !SelinuxEnabled() { -+ return nil -+ } -+ -+ if recurse { -+ var paths []string -+ var err error -+ -+ if paths, err = filepath.Glob(path.Join(fpath, "**", "*")); err != nil { -+ return fmt.Errorf("Unable to find directory %v: %v", fpath, err) -+ } -+ -+ for _, fpath := range paths { -+ if err = RestoreCon(fpath, false); err != nil { -+ return fmt.Errorf("Unable to restore selinux context for %v: %v", fpath, err) -+ } -+ } -+ return nil -+ } -+ if fs, err = os.Stat(fpath); err != nil { -+ return fmt.Errorf("Unable stat %v: %v", fpath, err) -+ } -+ -+ if flabel, err = Matchpathcon(fpath, fs.Mode()); flabel == "" { -+ return fmt.Errorf("Unable to get context for %v: %v", fpath, err) -+ } -+ -+ if rc, err := Setfilecon(fpath, flabel); rc != 0 { -+ return fmt.Errorf("Unable to set selinux context for %v: %v", fpath, err) -+ } -+ -+ return nil -+} -+ -+func Test() { -+ var plabel, flabel string -+ if !SelinuxEnabled() { -+ return -+ } -+ -+ plabel, flabel = GetLxcContexts() -+ fmt.Println(plabel) -+ fmt.Println(flabel) -+ freeContext(plabel) -+ plabel, flabel = GetLxcContexts() -+ fmt.Println(plabel) -+ fmt.Println(flabel) -+ freeContext(plabel) -+ if SelinuxEnabled() { -+ fmt.Println("Enabled") -+ } else { -+ fmt.Println("Disabled") -+ } -+ fmt.Println("getenforce ", SelinuxGetEnforce()) -+ fmt.Println("getenforcemode ", SelinuxGetEnforceMode()) -+ flabel, _ = Matchpathcon("/home/dwalsh/.emacs", 0) -+ fmt.Println(flabel) -+ pid := os.Getpid() -+ fmt.Printf("PID:%d MCS:%s\n", pid, IntToMcs(pid, 1023)) -+ fmt.Println(Getcon()) -+ fmt.Println(Getfilecon("/etc/passwd")) -+ fmt.Println(Getpidcon(1)) -+ Setfscreatecon("unconfined_u:unconfined_r:unconfined_t:s0") -+ fmt.Println(Getfscreatecon()) -+ Setfscreatecon("") -+ fmt.Println(Getfscreatecon()) -+ fmt.Println(Getpidcon(1)) -+} -diff --git libselinux-2.4/golang/test.go libselinux-2.4/golang/test.go -new file mode 100644 -index 0000000..fed6de8 ---- /dev/null -+++ libselinux-2.4/golang/test.go -@@ -0,0 +1,9 @@ -+package main -+ -+import ( -+ "./selinux" -+) -+ -+func main() { -+ selinux.Test() -+} -diff --git libselinux-2.4/include/selinux/selinux.h libselinux-2.4/include/selinux/selinux.h -index d0eb5c6..4beb170 100644 ---- libselinux-2.4/include/selinux/selinux.h -+++ libselinux-2.4/include/selinux/selinux.h -@@ -543,6 +543,7 @@ extern const char *selinux_virtual_image_context_path(void); - extern const char *selinux_lxc_contexts_path(void); - extern const char *selinux_x_context_path(void); - extern const char *selinux_sepgsql_context_path(void); -+extern const char *selinux_openssh_contexts_path(void); - extern const char *selinux_systemd_contexts_path(void); - extern const char *selinux_contexts_path(void); - extern const char *selinux_securetty_types_path(void); -diff --git libselinux-2.4/man/man3/getfscreatecon.3 libselinux-2.4/man/man3/getfscreatecon.3 -index e348d3b..8cc4df5 100644 ---- libselinux-2.4/man/man3/getfscreatecon.3 -+++ libselinux-2.4/man/man3/getfscreatecon.3 -@@ -49,6 +49,11 @@ Signal handlers that perform a - must take care to - save, reset, and restore the fscreate context to avoid unexpected behavior. - . -+ -+.br -+.B Note: -+Contexts are thread specific. -+ - .SH "RETURN VALUE" - On error \-1 is returned. - On success 0 is returned. -diff --git libselinux-2.4/man/man3/getkeycreatecon.3 libselinux-2.4/man/man3/getkeycreatecon.3 -index 4d70f10..b51008d 100644 ---- libselinux-2.4/man/man3/getkeycreatecon.3 -+++ libselinux-2.4/man/man3/getkeycreatecon.3 -@@ -48,6 +48,10 @@ Signal handlers that perform a - .BR setkeycreatecon () - must take care to - save, reset, and restore the keycreate context to avoid unexpected behavior. -+ -+.br -+.B Note: -+Contexts are thread specific. - . - .SH "RETURN VALUE" - On error \-1 is returned. -diff --git libselinux-2.4/man/man3/getsockcreatecon.3 libselinux-2.4/man/man3/getsockcreatecon.3 -index 4dd8f30..26086d9 100644 ---- libselinux-2.4/man/man3/getsockcreatecon.3 -+++ libselinux-2.4/man/man3/getsockcreatecon.3 -@@ -49,6 +49,11 @@ Signal handlers that perform a - must take care to - save, reset, and restore the sockcreate context to avoid unexpected behavior. - . -+ -+.br -+.B Note: -+Contexts are thread specific. -+ - .SH "RETURN VALUE" - On error \-1 is returned. - On success 0 is returned. -diff --git libselinux-2.4/man/man3/matchpathcon.3 libselinux-2.4/man/man3/matchpathcon.3 -index 1bc7ba1..177f15d 100644 ---- libselinux-2.4/man/man3/matchpathcon.3 -+++ libselinux-2.4/man/man3/matchpathcon.3 -@@ -7,7 +7,7 @@ matchpathcon, matchpathcon_index \- get the default SELinux security context for - .sp - .BI "int matchpathcon_init(const char *" path ");" - .sp --.BI "int matchpathcon_init_prefix(const char *" path ", const char *" subset ");" -+.BI "int matchpathcon_init_prefix(const char *" path ", const char *" prefix ");" - .sp - .BI "int matchpathcon_fini(void);" - .sp -@@ -16,6 +16,24 @@ matchpathcon, matchpathcon_index \- get the default SELinux security context for - .BI "int matchpathcon_index(const char *" name ", mode_t " mode ", char **" con ");" - . - .SH "DESCRIPTION" -+ -+This family of functions is deprecated. For new code, please use -+.BR selabel_open (3) -+with the -+.B SELABEL_CTX_FILE -+backend in place of -+.BR matchpathcon_init (), -+use -+.BR selabel_close (3) -+in place of -+.BR matchpathcon_fini (), -+and use -+.BR selabel_lookup (3) -+in place of -+.BR matchpathcon (). -+ -+The remaining description below is for the legacy interface. -+ - .BR matchpathcon_init () - loads the file contexts configuration specified by - .I path -@@ -41,9 +59,16 @@ customizations. - .BR matchpathcon_init_prefix () - is the same as - .BR matchpathcon_init () --but only loads entries with regular expressions that have stems prefixed --by --.I \%prefix. -+but only loads entries with regular expressions whose first pathname -+component is a prefix of -+.I \%prefix -+, e.g. pass "/dev" if you only intend to call -+.BR matchpathcon () -+with pathnames beginning with /dev. -+However, this optimization is no longer necessary due to the use of -+.I file_contexts.bin -+files with precompiled regular expressions, so use of this interface -+is deprecated. - - .BR matchpathcon_fini () - frees the memory allocated by a prior call to -@@ -54,7 +79,17 @@ calls, or to free memory when finished using - .BR matchpathcon (). - - .BR matchpathcon () --matches the specified pathname and mode against the file contexts -+matches the specified -+.I pathname, -+after transformation via -+.BR realpath (3) -+excepting any final symbolic link component if S_IFLNK was -+specified as the -+.I mode, -+and -+.I mode -+against the -+.I file contexts - configuration and sets the security context - .I con - to refer to the -diff --git libselinux-2.4/man/man5/selabel_file.5 libselinux-2.4/man/man5/selabel_file.5 -index 79eca95..e738824 100644 ---- libselinux-2.4/man/man5/selabel_file.5 -+++ libselinux-2.4/man/man5/selabel_file.5 -@@ -55,7 +55,9 @@ A non-null value for this option specifies a path to a file that will be opened - A non-null value for this option indicates that any local customizations to the file contexts mapping should be ignored. - .TP - .B SELABEL_OPT_SUBSET --A non-null value for this option is interpreted as a path prefix, for example "/etc". Only file context specifications starting with the given prefix are loaded. This may increase lookup performance, however any attempt to look up a path not starting with the given prefix will fail. -+A non-null value for this option is interpreted as a path prefix, for example "/etc". Only file context specifications with starting with a first component that prefix matches the given prefix are loaded. This may increase lookup performance, however any attempt to look up a path not starting with the given prefix may fail. This optimization is no longer required due to the use of -+.I file_contexts.bin -+files and is deprecated. - .RE - . - .SH "FILES" -@@ -206,7 +208,7 @@ component with \fI/var/www\fR, therefore the path used is: - If contexts are to be validated, then the global option \fBSELABEL_OPT_VALIDATE\fR must be set before calling \fBselabel_open\fR(3). If this is not set, then it is possible for an invalid context to be returned. - .IP "2." 4 - If the size of file contexts series of files contain many entries, then \fBselabel_open\fR(3) may have a delay as it reads in the files, and if --requested validates the entries. If possible use the \fBSELABEL_OPT_SUBSET\fR option to reduce the number of entries processed. -+requested validates the entries. - .IP "3." 4 - Depending on the version of SELinux it is possible that a \fIfile_contexts.template\fR file may also be present, however this is now deprecated. - .br -diff --git libselinux-2.4/man/man8/selinux.8 libselinux-2.4/man/man8/selinux.8 -index 9e3bdc4..fd20363 100644 ---- libselinux-2.4/man/man8/selinux.8 -+++ libselinux-2.4/man/man8/selinux.8 -@@ -91,11 +91,13 @@ This manual page was written by Dan Walsh . - .BR sepolicy (8), - .BR system-config-selinux (8), - .BR togglesebool (8), --.BR restorecon (8), - .BR fixfiles (8), -+.BR restorecon (8), - .BR setfiles (8), - .BR semanage (8), --.BR sepolicy(8) -+.BR sepolicy(8), -+.BR seinfo(8), -+.BR sesearch(8) - - Every confined service on the system has a man page in the following format: - .br -diff --git libselinux-2.4/src/Makefile libselinux-2.4/src/Makefile -index 82cb6ed..ac25c1f 100644 ---- libselinux-2.4/src/Makefile -+++ libselinux-2.4/src/Makefile -@@ -59,7 +59,7 @@ CFLAGS ?= -O -Wall -W -Wundef -Wformat-y2k -Wformat-security -Winit-self -Wmissi - -Wstrict-prototypes -Wold-style-definition -Wmissing-prototypes \ - -Wmissing-declarations -Wmissing-noreturn -Wmissing-format-attribute \ - -Wredundant-decls -Wnested-externs -Winline -Winvalid-pch -Wvolatile-register-var \ -- -Wdisabled-optimization -Wbuiltin-macro-redefined -Wmudflap -Wpacked-bitfield-compat \ -+ -Wdisabled-optimization -Wbuiltin-macro-redefined -Wpacked-bitfield-compat \ - -Wsync-nand -Wattributes -Wcoverage-mismatch -Wmultichar -Wcpp \ - -Wdeprecated-declarations -Wdiv-by-zero -Wdouble-promotion -Wendif-labels -Wextra \ - -Wformat-contains-nul -Wformat-extra-args -Wformat-zero-length -Wformat=2 -Wmultichar \ -diff --git libselinux-2.4/src/avc.c libselinux-2.4/src/avc.c -index 2bd7d13..b1ec57f 100644 ---- libselinux-2.4/src/avc.c -+++ libselinux-2.4/src/avc.c -@@ -288,7 +288,7 @@ void avc_av_stats(void) - - avc_release_lock(avc_lock); - -- avc_log(SELINUX_INFO, "%s: %d AV entries and %d/%d buckets used, " -+ avc_log(SELINUX_INFO, "%s: %u AV entries and %d/%d buckets used, " - "longest chain length %d\n", avc_prefix, - avc_cache.active_nodes, - slots_used, AVC_CACHE_SLOTS, max_chain_len); -@@ -471,7 +471,7 @@ static int avc_insert(security_id_t ssid, security_id_t tsid, - - if (ae->avd.seqno < avc_cache.latest_notif) { - avc_log(SELINUX_WARNING, -- "%s: seqno %d < latest_notif %d\n", avc_prefix, -+ "%s: seqno %u < latest_notif %u\n", avc_prefix, - ae->avd.seqno, avc_cache.latest_notif); - errno = EAGAIN; - rc = -1; -diff --git libselinux-2.4/src/avc_internal.c libselinux-2.4/src/avc_internal.c -index f735e73..be94857 100644 ---- libselinux-2.4/src/avc_internal.c -+++ libselinux-2.4/src/avc_internal.c -@@ -125,14 +125,14 @@ static int avc_netlink_receive(char *buf, unsigned buflen, int blocking) - - if (nladdrlen != sizeof nladdr) { - avc_log(SELINUX_WARNING, -- "%s: warning: netlink address truncated, len %d?\n", -+ "%s: warning: netlink address truncated, len %u?\n", - avc_prefix, nladdrlen); - return -1; - } - - if (nladdr.nl_pid) { - avc_log(SELINUX_WARNING, -- "%s: warning: received spoofed netlink packet from: %d\n", -+ "%s: warning: received spoofed netlink packet from: %u\n", - avc_prefix, nladdr.nl_pid); - return -1; - } -@@ -197,7 +197,7 @@ static int avc_netlink_process(char *buf) - case SELNL_MSG_POLICYLOAD:{ - struct selnl_msg_policyload *msg = NLMSG_DATA(nlh); - avc_log(SELINUX_INFO, -- "%s: received policyload notice (seqno=%d)\n", -+ "%s: received policyload notice (seqno=%u)\n", - avc_prefix, msg->seqno); - rc = avc_ss_reset(msg->seqno); - if (rc < 0) { -diff --git libselinux-2.4/src/avc_sidtab.c libselinux-2.4/src/avc_sidtab.c -index 52f21df..c775430 100644 ---- libselinux-2.4/src/avc_sidtab.c -+++ libselinux-2.4/src/avc_sidtab.c -@@ -81,6 +81,11 @@ sidtab_context_to_sid(struct sidtab *s, - int hvalue, rc = 0; - struct sidtab_node *cur; - -+ if (! ctx) { -+ errno=EINVAL; -+ return -1; -+ } -+ - *sid = NULL; - hvalue = sidtab_hash(ctx); - -@@ -124,7 +129,7 @@ void sidtab_sid_stats(struct sidtab *h, char *buf, int buflen) - } - - snprintf(buf, buflen, -- "%s: %d SID entries and %d/%d buckets used, longest " -+ "%s: %u SID entries and %d/%d buckets used, longest " - "chain length %d\n", avc_prefix, h->nel, slots_used, - SIDTAB_SIZE, max_chain_len); - } -diff --git libselinux-2.4/src/canonicalize_context.c libselinux-2.4/src/canonicalize_context.c -index 7cf3139..364a746 100644 ---- libselinux-2.4/src/canonicalize_context.c -+++ libselinux-2.4/src/canonicalize_context.c -@@ -17,6 +17,11 @@ int security_canonicalize_context_raw(const char * con, - size_t size; - int fd, ret; - -+ if (! con) { -+ errno=EINVAL; -+ return -1; -+ } -+ - if (!selinux_mnt) { - errno = ENOENT; - return -1; -diff --git libselinux-2.4/src/checkAccess.c libselinux-2.4/src/checkAccess.c -index ee85ebc..8de5747 100644 ---- libselinux-2.4/src/checkAccess.c -+++ libselinux-2.4/src/checkAccess.c -@@ -8,10 +8,28 @@ - #include "avc_internal.h" - - static pthread_once_t once = PTHREAD_ONCE_INIT; -+static int selinux_enabled; -+ -+static int avc_reset_callback(uint32_t event __attribute__((unused)), -+ security_id_t ssid __attribute__((unused)), -+ security_id_t tsid __attribute__((unused)), -+ security_class_t tclass __attribute__((unused)), -+ access_vector_t perms __attribute__((unused)), -+ access_vector_t *out_retained __attribute__((unused))) -+{ -+ flush_class_cache(); -+ return 0; -+} - - static void avc_init_once(void) - { -- avc_open(NULL, 0); -+ selinux_enabled = is_selinux_enabled(); -+ if (selinux_enabled == 1) { -+ if (avc_open(NULL, 0)) -+ return; -+ avc_add_callback(avc_reset_callback, AVC_CALLBACK_RESET, -+ 0, 0, 0, 0); -+ } - } - - int selinux_check_access(const char *scon, const char *tcon, const char *class, const char *perm, void *aux) { -@@ -21,18 +39,20 @@ int selinux_check_access(const char *scon, const char *tcon, const char *class, - security_class_t sclass; - access_vector_t av; - -- if (is_selinux_enabled() == 0) -- return 0; -- - __selinux_once(once, avc_init_once); - -+ if (selinux_enabled != 1) -+ return 0; -+ - rc = avc_context_to_sid(scon, &scon_id); - if (rc < 0) - return rc; - -- rc = avc_context_to_sid(tcon, &tcon_id); -- if (rc < 0) -- return rc; -+ rc = avc_context_to_sid(tcon, &tcon_id); -+ if (rc < 0) -+ return rc; -+ -+ (void) avc_netlink_check_nb(); - - sclass = string_to_security_class(class); - if (sclass == 0) { -diff --git libselinux-2.4/src/check_context.c libselinux-2.4/src/check_context.c -index 52063fa..234749c 100644 ---- libselinux-2.4/src/check_context.c -+++ libselinux-2.4/src/check_context.c -@@ -14,6 +14,11 @@ int security_check_context_raw(const char * con) - char path[PATH_MAX]; - int fd, ret; - -+ if (! con) { -+ errno=EINVAL; -+ return -1; -+ } -+ - if (!selinux_mnt) { - errno = ENOENT; - return -1; -diff --git libselinux-2.4/src/compute_av.c libselinux-2.4/src/compute_av.c -index 937e5c3..35ace7f 100644 ---- libselinux-2.4/src/compute_av.c -+++ libselinux-2.4/src/compute_av.c -@@ -26,6 +26,11 @@ int security_compute_av_flags_raw(const char * scon, - return -1; - } - -+ if ((! scon) || (! tcon)) { -+ errno=EINVAL; -+ return -1; -+ } -+ - snprintf(path, sizeof path, "%s/access", selinux_mnt); - fd = open(path, O_RDWR); - if (fd < 0) -diff --git libselinux-2.4/src/compute_create.c libselinux-2.4/src/compute_create.c -index 9559d42..14a65d1 100644 ---- libselinux-2.4/src/compute_create.c -+++ libselinux-2.4/src/compute_create.c -@@ -64,6 +64,11 @@ int security_compute_create_name_raw(const char * scon, - return -1; - } - -+ if ((! scon) || (! tcon)) { -+ errno=EINVAL; -+ return -1; -+ } -+ - snprintf(path, sizeof path, "%s/create", selinux_mnt); - fd = open(path, O_RDWR); - if (fd < 0) -diff --git libselinux-2.4/src/compute_member.c libselinux-2.4/src/compute_member.c -index 1fc7e41..065d996 100644 ---- libselinux-2.4/src/compute_member.c -+++ libselinux-2.4/src/compute_member.c -@@ -25,6 +25,11 @@ int security_compute_member_raw(const char * scon, - return -1; - } - -+ if ((! scon) || (! tcon)) { -+ errno=EINVAL; -+ return -1; -+ } -+ - snprintf(path, sizeof path, "%s/member", selinux_mnt); - fd = open(path, O_RDWR); - if (fd < 0) -diff --git libselinux-2.4/src/compute_relabel.c libselinux-2.4/src/compute_relabel.c -index 4615aee..cc77f36 100644 ---- libselinux-2.4/src/compute_relabel.c -+++ libselinux-2.4/src/compute_relabel.c -@@ -25,6 +25,11 @@ int security_compute_relabel_raw(const char * scon, - return -1; - } - -+ if ((! scon) || (! tcon)) { -+ errno=EINVAL; -+ return -1; -+ } -+ - snprintf(path, sizeof path, "%s/relabel", selinux_mnt); - fd = open(path, O_RDWR); - if (fd < 0) -diff --git libselinux-2.4/src/compute_user.c libselinux-2.4/src/compute_user.c -index b37c5d3..7703c26 100644 ---- libselinux-2.4/src/compute_user.c -+++ libselinux-2.4/src/compute_user.c -@@ -24,6 +24,11 @@ int security_compute_user_raw(const char * scon, - return -1; - } - -+ if (! scon) { -+ errno=EINVAL; -+ return -1; -+ } -+ - snprintf(path, sizeof path, "%s/user", selinux_mnt); - fd = open(path, O_RDWR); - if (fd < 0) -diff --git libselinux-2.4/src/enabled.c libselinux-2.4/src/enabled.c -index 5c252dd..bb659a9 100644 ---- libselinux-2.4/src/enabled.c -+++ libselinux-2.4/src/enabled.c -@@ -11,26 +11,14 @@ - - int is_selinux_enabled(void) - { -- int enabled = 0; -- char * con; -- - /* init_selinuxmnt() gets called before this function. We - * will assume that if a selinux file system is mounted, then - * selinux is enabled. */ -- if (selinux_mnt) { -- -- /* Since a file system is mounted, we consider selinux -- * enabled. If getcon_raw fails, selinux is still enabled. -- * We only consider it disabled if no policy is loaded. */ -- enabled = 1; -- if (getcon_raw(&con) == 0) { -- if (!strcmp(con, "kernel")) -- enabled = 0; -- freecon(con); -- } -- } -- -- return enabled; -+#ifdef ANDROID -+ return (selinux_mnt ? 1 : 0); -+#else -+ return (selinux_mnt && has_selinux_config); -+#endif - } - - hidden_def(is_selinux_enabled) -diff --git libselinux-2.4/src/file_path_suffixes.h libselinux-2.4/src/file_path_suffixes.h -index 3c92424..d1f9b48 100644 ---- libselinux-2.4/src/file_path_suffixes.h -+++ libselinux-2.4/src/file_path_suffixes.h -@@ -23,6 +23,7 @@ S_(BINPOLICY, "/policy/policy") - S_(VIRTUAL_DOMAIN, "/contexts/virtual_domain_context") - S_(VIRTUAL_IMAGE, "/contexts/virtual_image_context") - S_(LXC_CONTEXTS, "/contexts/lxc_contexts") -+ S_(OPENSSH_CONTEXTS, "/contexts/openssh_contexts") - S_(SYSTEMD_CONTEXTS, "/contexts/systemd_contexts") - S_(FILE_CONTEXT_SUBS, "/contexts/files/file_contexts.subs") - S_(FILE_CONTEXT_SUBS_DIST, "/contexts/files/file_contexts.subs_dist") -diff --git libselinux-2.4/src/fsetfilecon.c libselinux-2.4/src/fsetfilecon.c -index 52707d0..0cbe12d 100644 ---- libselinux-2.4/src/fsetfilecon.c -+++ libselinux-2.4/src/fsetfilecon.c -@@ -9,8 +9,12 @@ - - int fsetfilecon_raw(int fd, const char * context) - { -- int rc = fsetxattr(fd, XATTR_NAME_SELINUX, context, strlen(context) + 1, -- 0); -+ int rc; -+ if (! context) { -+ errno=EINVAL; -+ return -1; -+ } -+ rc = fsetxattr(fd, XATTR_NAME_SELINUX, context, strlen(context) + 1, 0); - if (rc < 0 && errno == ENOTSUP) { - char * ccontext = NULL; - int err = errno; -diff --git libselinux-2.4/src/init.c libselinux-2.4/src/init.c -index 6d1ef33..3c687a2 100644 ---- libselinux-2.4/src/init.c -+++ libselinux-2.4/src/init.c -@@ -21,6 +21,8 @@ char *selinux_mnt = NULL; - int selinux_page_size = 0; - int obj_class_compat = 1; - -+int has_selinux_config = 0; -+ - /* Verify the mount point for selinux file system has a selinuxfs. - If the file system: - * Exist, -@@ -151,6 +153,9 @@ static void init_lib(void) - { - selinux_page_size = sysconf(_SC_PAGE_SIZE); - init_selinuxmnt(); -+#ifndef ANDROID -+ has_selinux_config = (access(SELINUXCONFIG, F_OK) == 0); -+#endif - } - - static void fini_lib(void) __attribute__ ((destructor)); -diff --git libselinux-2.4/src/label_android_property.c libselinux-2.4/src/label_android_property.c -index b00eb07..5e1b76e 100644 ---- libselinux-2.4/src/label_android_property.c -+++ libselinux-2.4/src/label_android_property.c -@@ -101,7 +101,7 @@ static int process_line(struct selabel_handle *rec, - items = sscanf(line_buf, "%255s %255s", prop, context); - if (items != 2) { - selinux_log(SELINUX_WARNING, -- "%s: line %d is missing fields, skipping\n", path, -+ "%s: line %u is missing fields, skipping\n", path, - lineno); - return 0; - } -@@ -111,7 +111,7 @@ static int process_line(struct selabel_handle *rec, - spec_arr[nspec].property_key = strdup(prop); - if (!spec_arr[nspec].property_key) { - selinux_log(SELINUX_WARNING, -- "%s: out of memory at line %d on prop %s\n", -+ "%s: out of memory at line %u on prop %s\n", - path, lineno, prop); - return -1; - -@@ -120,7 +120,7 @@ static int process_line(struct selabel_handle *rec, - spec_arr[nspec].lr.ctx_raw = strdup(context); - if (!spec_arr[nspec].lr.ctx_raw) { - selinux_log(SELINUX_WARNING, -- "%s: out of memory at line %d on context %s\n", -+ "%s: out of memory at line %u on context %s\n", - path, lineno, context); - return -1; - } -diff --git libselinux-2.4/src/label_db.c libselinux-2.4/src/label_db.c -index 999dd46..1b48735 100644 ---- libselinux-2.4/src/label_db.c -+++ libselinux-2.4/src/label_db.c -@@ -105,12 +105,12 @@ process_line(const char *path, char *line_buf, unsigned int line_num, - * - */ - type = key = context = temp = NULL; -- items = sscanf(line_buf, "%as %as %as %as", -+ items = sscanf(line_buf, "%ms %ms %ms %ms", - &type, &key, &context, &temp); - if (items != 3) { - if (items > 0) - selinux_log(SELINUX_WARNING, -- "%s: line %d has invalid format, skipped", -+ "%s: line %u has invalid format, skipped", - path, line_num); - goto skip; - } -@@ -146,7 +146,7 @@ process_line(const char *path, char *line_buf, unsigned int line_num, - spec->type = SELABEL_DB_DATATYPE; - else { - selinux_log(SELINUX_WARNING, -- "%s: line %d has invalid object type %s\n", -+ "%s: line %u has invalid object type %s\n", - path, line_num, type); - goto skip; - } -diff --git libselinux-2.4/src/label_file.c libselinux-2.4/src/label_file.c -index 8e7b288..2a43310 100644 ---- libselinux-2.4/src/label_file.c -+++ libselinux-2.4/src/label_file.c -@@ -170,10 +170,10 @@ static int process_line(struct selabel_handle *rec, - /* Skip comment lines and empty lines. */ - if (*buf_p == '#' || *buf_p == 0) - return 0; -- items = sscanf(line_buf, "%as %as %as", ®ex, &type, &context); -+ items = sscanf(line_buf, "%ms %ms %ms", ®ex, &type, &context); - if (items < 2) { - COMPAT_LOG(SELINUX_WARNING, -- "%s: line %d is missing fields, skipping\n", path, -+ "%s: line %u is missing fields, skipping\n", path, - lineno); - if (items == 1) - free(regex); -@@ -204,7 +204,7 @@ static int process_line(struct selabel_handle *rec, - spec_arr[nspec].stem_id = find_stem_from_spec(data, regex); - spec_arr[nspec].regex_str = regex; - if (rec->validating && compile_regex(data, &spec_arr[nspec], &errbuf)) { -- COMPAT_LOG(SELINUX_WARNING, "%s: line %d has invalid regex %s: %s\n", -+ COMPAT_LOG(SELINUX_WARNING, "%s: line %u has invalid regex %s: %s\n", - path, lineno, regex, (errbuf ? errbuf : "out of memory")); - } - -@@ -214,7 +214,7 @@ static int process_line(struct selabel_handle *rec, - if (type) { - mode_t mode = string_to_mode(type); - if (mode == (mode_t)-1) { -- COMPAT_LOG(SELINUX_WARNING, "%s: line %d has invalid file type %s\n", -+ COMPAT_LOG(SELINUX_WARNING, "%s: line %u has invalid file type %s\n", - path, lineno, type); - mode = 0; - } -diff --git libselinux-2.4/src/label_media.c libselinux-2.4/src/label_media.c -index 227785f..a09486b 100644 ---- libselinux-2.4/src/label_media.c -+++ libselinux-2.4/src/label_media.c -@@ -44,10 +44,10 @@ static int process_line(const char *path, char *line_buf, int pass, - /* Skip comment lines and empty lines. */ - if (*buf_p == '#' || *buf_p == 0) - return 0; -- items = sscanf(line_buf, "%as %as ", &key, &context); -+ items = sscanf(line_buf, "%ms %ms ", &key, &context); - if (items < 2) { - selinux_log(SELINUX_WARNING, -- "%s: line %d is missing fields, skipping\n", path, -+ "%s: line %u is missing fields, skipping\n", path, - lineno); - if (items == 1) - free(key); -diff --git libselinux-2.4/src/label_x.c libselinux-2.4/src/label_x.c -index 896ef02..8435b76 100644 ---- libselinux-2.4/src/label_x.c -+++ libselinux-2.4/src/label_x.c -@@ -46,10 +46,10 @@ static int process_line(const char *path, char *line_buf, int pass, - /* Skip comment lines and empty lines. */ - if (*buf_p == '#' || *buf_p == 0) - return 0; -- items = sscanf(line_buf, "%as %as %as ", &type, &key, &context); -+ items = sscanf(line_buf, "%ms %ms %ms ", &type, &key, &context); - if (items < 3) { - selinux_log(SELINUX_WARNING, -- "%s: line %d is missing fields, skipping\n", path, -+ "%s: line %u is missing fields, skipping\n", path, - lineno); - if (items > 0) - free(type); -@@ -76,7 +76,7 @@ static int process_line(const char *path, char *line_buf, int pass, - data->spec_arr[data->nspec].type = SELABEL_X_POLYSELN; - else { - selinux_log(SELINUX_WARNING, -- "%s: line %d has invalid object type %s\n", -+ "%s: line %u has invalid object type %s\n", - path, lineno, type); - return 0; - } -diff --git libselinux-2.4/src/lsetfilecon.c libselinux-2.4/src/lsetfilecon.c -index 1d3b28a..ea6d70b 100644 ---- libselinux-2.4/src/lsetfilecon.c -+++ libselinux-2.4/src/lsetfilecon.c -@@ -9,8 +9,13 @@ - - int lsetfilecon_raw(const char *path, const char * context) - { -- int rc = lsetxattr(path, XATTR_NAME_SELINUX, context, strlen(context) + 1, -- 0); -+ int rc; -+ if (! context) { -+ errno=EINVAL; -+ return -1; -+ } -+ -+ rc = lsetxattr(path, XATTR_NAME_SELINUX, context, strlen(context) + 1, 0); - if (rc < 0 && errno == ENOTSUP) { - char * ccontext = NULL; - int err = errno; -diff --git libselinux-2.4/src/matchpathcon.c libselinux-2.4/src/matchpathcon.c -index 3b96b1d..3868711 100644 ---- libselinux-2.4/src/matchpathcon.c -+++ libselinux-2.4/src/matchpathcon.c -@@ -2,6 +2,7 @@ - #include - #include - #include -+#include - #include "selinux_internal.h" - #include "label_internal.h" - #include "callbacks.h" -@@ -62,7 +63,7 @@ static void - { - va_list ap; - va_start(ap, fmt); -- vfprintf(stderr, fmt, ap); -+ vsyslog(LOG_ERR, fmt, ap); - va_end(ap); - } - -@@ -541,7 +542,7 @@ int compat_validate(struct selabel_handle *rec, - if (rc < 0) { - if (lineno) { - COMPAT_LOG(SELINUX_WARNING, -- "%s: line %d has invalid context %s\n", -+ "%s: line %u has invalid context %s\n", - path, lineno, *ctx); - } else { - COMPAT_LOG(SELINUX_WARNING, -diff --git libselinux-2.4/src/procattr.c libselinux-2.4/src/procattr.c -index f990350..527a0a5 100644 ---- libselinux-2.4/src/procattr.c -+++ libselinux-2.4/src/procattr.c -@@ -11,8 +11,6 @@ - - #define UNSET (char *) -1 - --static __thread pid_t cpid; --static __thread pid_t tid; - static __thread char *prev_current = UNSET; - static __thread char * prev_exec = UNSET; - static __thread char * prev_fscreate = UNSET; -@@ -24,15 +22,6 @@ static pthread_key_t destructor_key; - static int destructor_key_initialized = 0; - static __thread char destructor_initialized; - --extern void *__dso_handle __attribute__ ((__weak__, __visibility__ ("hidden"))); --extern int __register_atfork (void (*) (void), void (*) (void), void (*) (void), void *); -- --static int __selinux_atfork (void (*prepare) (void), void (*parent) (void), void (*child) (void)) --{ -- return __register_atfork (prepare, parent, child, -- &__dso_handle == NULL ? NULL : __dso_handle); --} -- - static pid_t gettid(void) - { - return syscall(__NR_gettid); -@@ -52,14 +41,6 @@ static void procattr_thread_destructor(void __attribute__((unused)) *unused) - free(prev_sockcreate); - } - --static void free_procattr(void) --{ -- procattr_thread_destructor(NULL); -- tid = 0; -- cpid = getpid(); -- prev_current = prev_exec = prev_fscreate = prev_keycreate = prev_sockcreate = UNSET; --} -- - void __attribute__((destructor)) procattr_destructor(void); - - void hidden __attribute__((destructor)) procattr_destructor(void) -@@ -79,7 +60,6 @@ static inline void init_thread_destructor(void) - static void init_procattr(void) - { - if (__selinux_key_create(&destructor_key, procattr_thread_destructor) == 0) { -- __selinux_atfork(NULL, NULL, free_procattr); - destructor_key_initialized = 1; - } - } -@@ -88,21 +68,26 @@ static int openattr(pid_t pid, const char *attr, int flags) - { - int fd, rc; - char *path; -- -- if (cpid != getpid()) -- free_procattr(); -+ pid_t tid; - - if (pid > 0) - rc = asprintf(&path, "/proc/%d/attr/%s", pid, attr); - else { -- if (!tid) -- tid = gettid(); -+ rc = asprintf(&path, "/proc/thread-self/attr/%s", attr); -+ if (rc < 0) -+ return -1; -+ fd = open(path, flags | O_CLOEXEC); -+ if (fd >= 0 || errno != ENOENT) -+ goto out; -+ free(path); -+ tid = gettid(); - rc = asprintf(&path, "/proc/self/task/%d/attr/%s", tid, attr); - } - if (rc < 0) - return -1; - - fd = open(path, flags | O_CLOEXEC); -+out: - free(path); - return fd; - } -@@ -120,9 +105,6 @@ static int getprocattrcon_raw(char ** context, - __selinux_once(once, init_procattr); - init_thread_destructor(); - -- if (cpid != getpid()) -- free_procattr(); -- - switch (attr[0]) { - case 'c': - prev_context = prev_current; -@@ -220,9 +202,6 @@ static int setprocattrcon_raw(const char * context, - __selinux_once(once, init_procattr); - init_thread_destructor(); - -- if (cpid != getpid()) -- free_procattr(); -- - switch (attr[0]) { - case 'c': - prev_context = &prev_current; -diff --git libselinux-2.4/src/selinux_config.c libselinux-2.4/src/selinux_config.c -index 30e9dc7..bec5f3b 100644 ---- libselinux-2.4/src/selinux_config.c -+++ libselinux-2.4/src/selinux_config.c -@@ -13,8 +13,6 @@ - #include "selinux_internal.h" - #include "get_default_type_internal.h" - --#define SELINUXDIR "/etc/selinux/" --#define SELINUXCONFIG SELINUXDIR "config" - #define SELINUXDEFAULT "targeted" - #define SELINUXTYPETAG "SELINUXTYPE=" - #define SELINUXTAG "SELINUX=" -@@ -50,8 +48,9 @@ - #define FILE_CONTEXT_SUBS_DIST 25 - #define LXC_CONTEXTS 26 - #define BOOLEAN_SUBS 27 --#define SYSTEMD_CONTEXTS 28 --#define NEL 29 -+#define OPENSSH_CONTEXTS 28 -+#define SYSTEMD_CONTEXTS 29 -+#define NEL 30 - - /* Part of one-time lazy init */ - static pthread_once_t once = PTHREAD_ONCE_INIT; -@@ -493,6 +492,13 @@ const char *selinux_lxc_contexts_path(void) - - hidden_def(selinux_lxc_contexts_path) - -+const char *selinux_openssh_contexts_path(void) -+{ -+ return get_path(OPENSSH_CONTEXTS); -+} -+ -+hidden_def(selinux_openssh_contexts_path) -+ - const char *selinux_systemd_contexts_path(void) - { - return get_path(SYSTEMD_CONTEXTS); -diff --git libselinux-2.4/src/selinux_internal.h libselinux-2.4/src/selinux_internal.h -index afb2170..16b5cdb 100644 ---- libselinux-2.4/src/selinux_internal.h -+++ libselinux-2.4/src/selinux_internal.h -@@ -82,6 +82,7 @@ hidden_proto(selinux_mkload_policy) - hidden_proto(selinux_customizable_types_path) - hidden_proto(selinux_media_context_path) - hidden_proto(selinux_x_context_path) -+ hidden_proto(selinux_openssh_contexts_path) - hidden_proto(selinux_sepgsql_context_path) - hidden_proto(selinux_systemd_contexts_path) - hidden_proto(selinux_path) -@@ -101,6 +102,8 @@ hidden_proto(security_get_initial_context); - hidden_proto(security_get_initial_context_raw); - hidden_proto(selinux_reset_config); - -+hidden void flush_class_cache(void); -+ - extern int load_setlocaldefs hidden; - extern int require_seusers hidden; - extern int selinux_page_size hidden; -@@ -137,3 +140,8 @@ extern int selinux_page_size hidden; - if (pthread_setspecific != NULL) \ - pthread_setspecific(KEY, VALUE); \ - } while (0) -+ -+#define SELINUXDIR "/etc/selinux/" -+#define SELINUXCONFIG SELINUXDIR "config" -+ -+extern int has_selinux_config hidden; -diff --git libselinux-2.4/src/selinuxswig_python.i libselinux-2.4/src/selinuxswig_python.i -index ae72246..8cea18d 100644 ---- libselinux-2.4/src/selinuxswig_python.i -+++ libselinux-2.4/src/selinuxswig_python.i -@@ -8,7 +8,7 @@ - - %pythoncode %{ - --import shutil, os, stat -+import shutil, os, errno, stat - - DISABLED = -1 - PERMISSIVE = 0 -@@ -26,14 +26,19 @@ def restorecon(path, recursive=False): - status, context = matchpathcon(path, mode) - - if status == 0: -- status, oldcontext = lgetfilecon(path) -+ try: -+ status, oldcontext = lgetfilecon(path) -+ except OSError as e: -+ if e.errno != errno.ENODATA: -+ raise -+ oldcontext = None - if context != oldcontext: - lsetfilecon(path, context) - - if recursive: -- os.path.walk(path, lambda arg, dirname, fnames: -- map(restorecon, [os.path.join(dirname, fname) -- for fname in fnames]), None) -+ for root, dirs, files in os.walk(path): -+ for name in files + dirs: -+ restorecon(os.path.join(root, name)) - - def chcon(path, context, recursive=False): - """ Set the SELinux context on a given path """ -diff --git libselinux-2.4/src/setfilecon.c libselinux-2.4/src/setfilecon.c -index d05969c..3f0200e 100644 ---- libselinux-2.4/src/setfilecon.c -+++ libselinux-2.4/src/setfilecon.c -@@ -9,8 +9,12 @@ - - int setfilecon_raw(const char *path, const char * context) - { -- int rc = setxattr(path, XATTR_NAME_SELINUX, context, strlen(context) + 1, -- 0); -+ int rc; -+ if (! context) { -+ errno=EINVAL; -+ return -1; -+ } -+ rc = setxattr(path, XATTR_NAME_SELINUX, context, strlen(context) + 1, 0); - if (rc < 0 && errno == ENOTSUP) { - char * ccontext = NULL; - int err = errno; -diff --git libselinux-2.4/src/stringrep.c libselinux-2.4/src/stringrep.c -index 9ae8248..2dbec2b 100644 ---- libselinux-2.4/src/stringrep.c -+++ libselinux-2.4/src/stringrep.c -@@ -158,6 +158,28 @@ err1: - return NULL; - } - -+hidden void flush_class_cache(void) -+{ -+ struct discover_class_node *cur = discover_class_cache, *prev = NULL; -+ size_t i; -+ -+ while (cur != NULL) { -+ free(cur->name); -+ -+ for (i = 0; i < MAXVECTORS; i++) -+ free(cur->perms[i]); -+ -+ free(cur->perms); -+ -+ prev = cur; -+ cur = cur->next; -+ -+ free(prev); -+ } -+ -+ discover_class_cache = NULL; -+} -+ - security_class_t string_to_security_class(const char *s) - { - struct discover_class_node *node; -diff --git libselinux-2.4/utils/Makefile libselinux-2.4/utils/Makefile -index f469924..5499538 100644 ---- libselinux-2.4/utils/Makefile -+++ libselinux-2.4/utils/Makefile -@@ -11,7 +11,7 @@ CFLAGS ?= -O -Wall -W -Wundef -Wformat-y2k -Wformat-security -Winit-self -Wmissi - -Wstrict-prototypes -Wold-style-definition -Wmissing-prototypes \ - -Wmissing-declarations -Wmissing-noreturn -Wmissing-format-attribute \ - -Wredundant-decls -Wnested-externs -Winline -Winvalid-pch -Wvolatile-register-var \ -- -Wdisabled-optimization -Wbuiltin-macro-redefined -Wmudflap -Wpacked-bitfield-compat \ -+ -Wdisabled-optimization -Wbuiltin-macro-redefined -Wpacked-bitfield-compat \ - -Wsync-nand -Wattributes -Wcoverage-mismatch -Wmultichar -Wcpp \ - -Wdeprecated-declarations -Wdiv-by-zero -Wdouble-promotion -Wendif-labels -Wextra \ - -Wformat-contains-nul -Wformat-extra-args -Wformat-zero-length -Wformat=2 -Wmultichar \ -diff --git libselinux-2.4/utils/sefcontext_compile.c libselinux-2.4/utils/sefcontext_compile.c -index 504699d..adb2b0c 100644 ---- libselinux-2.4/utils/sefcontext_compile.c -+++ libselinux-2.4/utils/sefcontext_compile.c -@@ -73,7 +73,7 @@ static int process_file(struct saved_data *data, const char *filename) - spec->lr.ctx_raw = context; - spec->mode = string_to_mode(mode); - if (spec->mode == (mode_t)-1) { -- fprintf(stderr, "%s: line %d has invalid file type %s\n", -+ fprintf(stderr, "%s: line %u has invalid file type %s\n", - regex, line_num + 1, mode); - spec->mode = 0; - } -diff --git libselinux-2.4/utils/togglesebool.c libselinux-2.4/utils/togglesebool.c -index ad0d2a2..309f83b 100644 ---- libselinux-2.4/utils/togglesebool.c -+++ libselinux-2.4/utils/togglesebool.c -@@ -86,7 +86,7 @@ int main(int argc, char **argv) - argv[i], pwd->pw_name); - else - syslog(LOG_NOTICE, -- "The %s policy boolean was toggled by uid:%d", -+ "The %s policy boolean was toggled by uid:%u", - argv[i], getuid()); - - } diff --git a/libselinux.spec b/libselinux.spec index 93f1562..0d03484 100644 --- a/libselinux.spec +++ b/libselinux.spec @@ -3,25 +3,25 @@ %endif %define ruby_inc %(pkg-config --cflags ruby) -%define libsepolver 2.4-1 +%define libsepolver 2.5-0 %{!?python_sitearch: %define python_sitearch %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib(1)")} Summary: SELinux library and simple utilities Name: libselinux -Version: 2.4 -Release: 8%{?dist} +Version: 2.5 +Release: 0.1.rc1%{?dist} License: Public Domain Group: System Environment/Libraries # https://github.com/SELinuxProject/selinux/wiki/Releases -Source: https://raw.githubusercontent.com/wiki/SELinuxProject/selinux/files/releases/20150202/%{name}-%{version}.tar.gz +Source: https://raw.githubusercontent.com/wiki/SELinuxProject/selinux/files/releases/20160107/libselinux-2.5-rc1.tar.gz Source1: selinuxconlist.8 Source2: selinuxdefcon.8 Url: https://github.com/SELinuxProject/selinux/wiki -# use make-rhat-patches.sh to create following patches from https://github.com/fedora-selinux/selinux/ -# HEAD https://github.com/fedora-selinux/selinux/commit/8c09d34e464e79a602fb9c9408554279aede3b6b -Patch1: libselinux-rhat.patch -# https://bugzilla.redhat.com/show_bug.cgi?id=1284019 -Patch10: libselinux-rpm_execcon.patch +# download https://raw.githubusercontent.com/fedora-selinux/scripts/master/selinux/make-fedora-selinux-patch.sh +# run: +# $ VERSION=2.5-rc1 ./make-fedora-selinux-patch.sh libselinux +# HEAD https://github.com/fedora-selinux/selinux/commit/fcbe30acc1ab728944f06ee9df9dc007053b5781 +Patch1: libselinux-fedora.patch BuildRequires: pkgconfig python-devel ruby-devel ruby libsepol-static >= %{libsepolver} swig pcre-devel xz-devel %if 0%{?with_python3} BuildRequires: python3-devel @@ -103,9 +103,8 @@ The libselinux-static package contains the static libraries needed for developing SELinux applications. %prep -%setup -q -%patch1 -p1 -b .rhat -%patch10 -p1 -b .rhat +%setup -q -n libselinux-2.5-rc1 +%patch1 -p1 -b .fedora %build export LDFLAGS="%{?__global_ldflags}" @@ -214,6 +213,11 @@ rm -rf %{buildroot} %{_sbindir}/selinuxexeccon %{_sbindir}/selinuxenabled %{_sbindir}/setenforce +%{_sbindir}/selabel_digest +%{_sbindir}/selabel_lookup +%{_sbindir}/selabel_lookup_best_match +%{_sbindir}/selabel_partial_match +%{_sbindir}/selinux_restorecon %{_mandir}/man5/* %{_mandir}/man8/* @@ -251,6 +255,9 @@ rm -rf %{buildroot} %{ruby_vendorarchdir}/selinux.so %changelog +* Sun Feb 21 2016 Petr Lautrbach 2.5-0.1.rc1 +- Update to upstream rc1 release 2016-01-07 + * Thu Feb 04 2016 Fedora Release Engineering - 2.4-8 - Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild diff --git a/make-rhat-patches.sh b/make-rhat-patches.sh index 9a47cda..9ab4513 100755 --- a/make-rhat-patches.sh +++ b/make-rhat-patches.sh @@ -1,12 +1,13 @@ #!/bin/bash -LIBSELINUX_VERSION=2.4 -BRANCH=master +LIBSELINUX_VERSION=2.5-rc1 +REPO=https://github.com/fedora-selinux/selinux +BRANCH=master-rc REBASEDIR=`mktemp -d rebase.XXXXXX` pushd $REBASEDIR -git clone https://github.com/fedora-selinux/selinux.git +git clone $REPO pushd selinux; git checkout $BRANCH; COMMIT=`git rev-parse --verify HEAD`; popd # prepare libselinux-rhat.patch @@ -24,4 +25,4 @@ popd popd # echo rm -rf $REBASEDIR -echo libselinux-rhat.patch created from https://github.com/fedora-selinux/selinux/commit/$COMMIT +echo libselinux-rhat.patch created from $REPO/commit/$COMMIT diff --git a/sources b/sources index 15159ba..edf2092 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -d19af2a367a81fb00bedc1b381694995 libselinux-2.4.tar.gz +8cacc33d9b5ff7bd64a36302d88a9243 libselinux-2.5-rc1.tar.gz