diff --git a/.gitignore b/.gitignore index 12b57f3..ae56fa1 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/libselinux-2.2.2.tgz +SOURCES/libselinux-2.5.tar.gz diff --git a/.libselinux.metadata b/.libselinux.metadata index 80ee7c4..c799213 100644 --- a/.libselinux.metadata +++ b/.libselinux.metadata @@ -1 +1 @@ -722254a10c1156d15588c24752f56461a62d71df SOURCES/libselinux-2.2.2.tgz +03a561762d7496cc756f1a6985ff63f8b4a7852d SOURCES/libselinux-2.5.tar.gz diff --git a/SOURCES/libselinux-rhat.patch b/SOURCES/libselinux-rhat.patch deleted file mode 100644 index 9c2b6e7..0000000 --- a/SOURCES/libselinux-rhat.patch +++ /dev/null @@ -1,883 +0,0 @@ -diff --git a/libselinux/Makefile b/libselinux/Makefile -index fd4f0b1..51469bc 100644 ---- a/libselinux/Makefile -+++ b/libselinux/Makefile -@@ -1,4 +1,4 @@ --SUBDIRS = src include utils man -+SUBDIRS = src include utils man golang - - DISABLE_AVC ?= n - DISABLE_SETRANS ?= n -diff --git a/libselinux/golang/Makefile b/libselinux/golang/Makefile -new file mode 100644 -index 0000000..b75677b ---- /dev/null -+++ b/libselinux/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 a/libselinux/golang/selinux.go b/libselinux/golang/selinux.go -new file mode 100644 -index 0000000..6cee26a ---- /dev/null -+++ b/libselinux/golang/selinux.go -@@ -0,0 +1,378 @@ -+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 ( -+ "encoding/binary" -+ "crypto/rand" -+ "unsafe" -+ "fmt" -+ "bufio" -+ "regexp" -+ "io" -+ "os" -+ "strings" -+) -+ -+var ( -+ assignRegex = regexp.MustCompile(`^([^=]+)=(.*)$`) -+ mcs_list = make(map[string]bool) -+) -+ -+func Matchpathcon(path string, mode int) (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) (int, error) { -+ var val *C.char -+ if ! Selinux_enabled() { -+ return 0, nil -+ } -+ if scon != "" { -+ val = C.CString(scon) -+ } else { -+ val = nil -+ } -+ rc, err := C.setexeccon(val) -+ return int(rc), err -+} -+ -+type Context struct { -+ con []string -+} -+func (c *Context) Set_user(user string) { -+ c.con[0]=user -+} -+func (c *Context) Get_user() string { -+ return c.con[0] -+} -+func (c *Context) Set_role(role string) { -+ c.con[1]=role -+} -+func (c *Context) Get_role() string { -+ return c.con[1] -+} -+func (c *Context) Set_type(setype string) { -+ c.con[2]=setype -+} -+func (c *Context) Get_type() string { -+ return c.con[2] -+} -+func (c *Context) Set_level(mls string) { -+ c.con[3]=mls -+} -+func (c *Context) Get_level() 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 New_context(scon string) Context { -+ var con Context -+ con.Set(scon) -+ return con -+} -+ -+func Is_selinux_enabled() bool { -+ b := C.is_selinux_enabled() -+ if b > 0 { -+ return true; -+ } -+ return false -+} -+ -+func Selinux_enabled() bool { -+ b := C.is_selinux_enabled() -+ if b > 0 { -+ return true; -+ } -+ return false -+} -+ -+const ( -+ Enforcing = 1 -+ Permissive = 0 -+ Disabled = -1 -+) -+ -+func Selinux_getenforce() int { -+ return int(C.security_getenforce()) -+} -+ -+func Selinux_getenforcemode() (int) { -+ var enforce C.int -+ C.selinux_getenforcemode(&enforce) -+ return int(enforce) -+} -+ -+func mcs_add(mcs string) { -+ mcs_list[mcs] = true -+} -+ -+func mcs_delete(mcs string) { -+ mcs_list[mcs] = false -+} -+ -+func mcs_exists(mcs string) bool { -+ return mcs_list[mcs] -+} -+ -+func Int_to_mcs(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 uniq_mcs(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 mcs_exists(mcs) { -+ continue -+ } -+ mcs_add(mcs) -+ break -+ } -+ return mcs -+} -+func free_context(process_label string) { -+ var scon Context -+ scon = New_context(process_label) -+ mcs_delete(scon.Get_level()) -+} -+ -+func Get_lxc_contexts() (process_label string, file_label string) { -+ var val, key string -+ var bufin *bufio.Reader -+ if ! Selinux_enabled() { -+ return -+ } -+ lxc_path := C.GoString(C.selinux_lxc_contexts_path()) -+ file_label = "system_u:object_r:svirt_sandbox_file_t:s0" -+ process_label = "system_u:system_r:svirt_lxc_net_t:s0" -+ -+ in, err := os.Open(lxc_path) -+ 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" { -+ process_label = strings.Trim(val,"\"") -+ } -+ if key == "file" { -+ file_label = strings.Trim(val,"\"") -+ } -+ } -+ } -+exit: -+ var scon Context -+ mcs := Int_to_mcs(os.Getpid(), 1024) -+ scon = New_context(process_label) -+ scon.Set_level(mcs) -+ process_label = scon.Get() -+ scon = New_context(file_label) -+ scon.Set_level(mcs) -+ file_label = scon.Get() -+ return process_label, file_label -+} -+ -+func CopyLevel (src, dest string) (string, error) { -+ if ! Selinux_enabled() { -+ 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 := New_context(src) -+ tcon := New_context(dest) -+ tcon.Set_level(scon.Get_level()) -+ return tcon.Get(), nil -+} -+ -+func Test() { -+ var plabel,flabel string -+ if ! Selinux_enabled() { -+ return -+ } -+ -+ plabel, flabel = Get_lxc_contexts() -+ fmt.Println(plabel) -+ fmt.Println(flabel) -+ free_context(plabel) -+ plabel, flabel = Get_lxc_contexts() -+ fmt.Println(plabel) -+ fmt.Println(flabel) -+ free_context(plabel) -+ if Selinux_enabled() { -+ fmt.Println("Enabled") -+ } else { -+ fmt.Println("Disabled") -+ } -+ fmt.Println("getenforce ", Selinux_getenforce()) -+ fmt.Println("getenforcemode ", Selinux_getenforcemode()) -+ flabel,_ = Matchpathcon("/home/dwalsh/.emacs", 0) -+ fmt.Println(flabel) -+ pid := os.Getpid() -+ fmt.Printf("PID:%d MCS:%s\n", pid, Int_to_mcs(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 a/libselinux/golang/test.go b/libselinux/golang/test.go -new file mode 100644 -index 0000000..fed6de8 ---- /dev/null -+++ b/libselinux/golang/test.go -@@ -0,0 +1,9 @@ -+package main -+ -+import ( -+ "./selinux" -+) -+ -+func main() { -+ selinux.Test() -+} -diff --git a/libselinux/man/man3/getfscreatecon.3 b/libselinux/man/man3/getfscreatecon.3 -index c7675be..677ece4 100644 ---- a/libselinux/man/man3/getfscreatecon.3 -+++ b/libselinux/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 a/libselinux/man/man3/getkeycreatecon.3 b/libselinux/man/man3/getkeycreatecon.3 -index d6a118c..b503535 100644 ---- a/libselinux/man/man3/getkeycreatecon.3 -+++ b/libselinux/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 a/libselinux/man/man3/getsockcreatecon.3 b/libselinux/man/man3/getsockcreatecon.3 -index 99e9436..673738c 100644 ---- a/libselinux/man/man3/getsockcreatecon.3 -+++ b/libselinux/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 a/libselinux/src/Makefile b/libselinux/src/Makefile -index 02dd829..6dfdb46 100644 ---- a/libselinux/src/Makefile -+++ b/libselinux/src/Makefile -@@ -114,7 +114,7 @@ $(LIBA): $(OBJS) - $(RANLIB) $@ - - $(LIBSO): $(LOBJS) -- $(CC) $(CFLAGS) -shared -o $@ $^ -lpcre -ldl $(LDFLAGS) -L$(LIBDIR) -Wl,-soname,$(LIBSO),-z,defs,-z,relro -+ $(CC) $(CFLAGS) -shared -o $@ $^ -lpcre -llzma -ldl $(LDFLAGS) -L$(LIBDIR) -Wl,-soname,$(LIBSO),-z,defs,-z,relro - ln -sf $@ $(TARGET) - - $(LIBPC): $(LIBPC).in ../VERSION -diff --git a/libselinux/src/avc_sidtab.c b/libselinux/src/avc_sidtab.c -index 0b696bb..506e236 100644 ---- a/libselinux/src/avc_sidtab.c -+++ b/libselinux/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 a/libselinux/src/canonicalize_context.c b/libselinux/src/canonicalize_context.c -index 176c45a..6075025 100644 ---- a/libselinux/src/canonicalize_context.c -+++ b/libselinux/src/canonicalize_context.c -@@ -17,6 +17,11 @@ int security_canonicalize_context_raw(const security_context_t con, - size_t size; - int fd, ret; - -+ if (! con) { -+ errno=EINVAL; -+ return -1; -+ } -+ - if (!selinux_mnt) { - errno = ENOENT; - return -1; -diff --git a/libselinux/src/check_context.c b/libselinux/src/check_context.c -index 33ab5e3..1277bdd 100644 ---- a/libselinux/src/check_context.c -+++ b/libselinux/src/check_context.c -@@ -14,6 +14,11 @@ int security_check_context_raw(const security_context_t con) - char path[PATH_MAX]; - int fd, ret; - -+ if (! con) { -+ errno=EINVAL; -+ return -1; -+ } -+ - if (!selinux_mnt) { - errno = ENOENT; - return -1; -diff --git a/libselinux/src/compute_av.c b/libselinux/src/compute_av.c -index 5962c0b..61ea454 100644 ---- a/libselinux/src/compute_av.c -+++ b/libselinux/src/compute_av.c -@@ -26,6 +26,11 @@ int security_compute_av_flags_raw(const security_context_t 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 a/libselinux/src/compute_create.c b/libselinux/src/compute_create.c -index 3c05be3..34a1ccd 100644 ---- a/libselinux/src/compute_create.c -+++ b/libselinux/src/compute_create.c -@@ -64,6 +64,11 @@ int security_compute_create_name_raw(const security_context_t 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 a/libselinux/src/compute_member.c b/libselinux/src/compute_member.c -index dad0a77..7850986 100644 ---- a/libselinux/src/compute_member.c -+++ b/libselinux/src/compute_member.c -@@ -25,6 +25,11 @@ int security_compute_member_raw(const security_context_t 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 a/libselinux/src/compute_relabel.c b/libselinux/src/compute_relabel.c -index 656f00a..2560e78 100644 ---- a/libselinux/src/compute_relabel.c -+++ b/libselinux/src/compute_relabel.c -@@ -25,6 +25,11 @@ int security_compute_relabel_raw(const security_context_t 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 a/libselinux/src/compute_user.c b/libselinux/src/compute_user.c -index 3b39ddd..af20735 100644 ---- a/libselinux/src/compute_user.c -+++ b/libselinux/src/compute_user.c -@@ -24,6 +24,11 @@ int security_compute_user_raw(const security_context_t 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 a/libselinux/src/fsetfilecon.c b/libselinux/src/fsetfilecon.c -index 9963f7a..37f9d74 100644 ---- a/libselinux/src/fsetfilecon.c -+++ b/libselinux/src/fsetfilecon.c -@@ -9,8 +9,12 @@ - - int fsetfilecon_raw(int fd, const security_context_t 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) { - security_context_t ccontext = NULL; - int err = errno; -diff --git a/libselinux/src/load_policy.c b/libselinux/src/load_policy.c -index e419f1a..275672d 100644 ---- a/libselinux/src/load_policy.c -+++ b/libselinux/src/load_policy.c -@@ -16,6 +16,82 @@ - #include - #include "policy.h" - #include -+#include -+ -+static char *lzmaread(int fd, size_t *rsize) { -+ int capacity = 64*1024; -+ char *buf = NULL; -+ int tmpsize = 8 * 1024; -+ unsigned char tmp[tmpsize]; -+ unsigned char tmp_out[tmpsize]; -+ size_t size = 0; -+ lzma_stream strm = LZMA_STREAM_INIT; -+ lzma_action action = LZMA_RUN; -+ lzma_ret ret; -+ -+ FILE *stream = fdopen (fd, "r"); -+ if (!stream) { -+ return NULL; -+ } -+ ret = lzma_stream_decoder(&strm, UINT64_MAX, -+ LZMA_CONCATENATED); -+ -+ strm.avail_in = 0; -+ strm.next_out = tmp_out; -+ strm.avail_out = tmpsize; -+ -+ buf = (char *) malloc (capacity); -+ if (!buf) -+ goto err; -+ -+ while (1) { -+ if (strm.avail_in == 0) { -+ strm.next_in = tmp; -+ strm.avail_in = fread(tmp, 1, tmpsize, stream); -+ -+ if (ferror(stream)) { -+ // POSIX says that fread() sets errno if -+ // an error occurred. ferror() doesn't -+ // touch errno. -+ goto err; -+ } -+ if (feof(stream)) action = LZMA_FINISH; -+ } -+ -+ ret = lzma_code(&strm, action); -+ -+ // Write and check write error before checking decoder error. -+ // This way as much data as possible gets written to output -+ // even if decoder detected an error. -+ if (strm.avail_out == 0 || ret != LZMA_OK) { -+ const size_t num = tmpsize - strm.avail_out; -+ if (num > capacity) { -+ buf = (char*) realloc (buf, size*2); -+ capacity = size; -+ } -+ memcpy (buf+size, tmp_out, num); -+ capacity -= num; -+ size += num; -+ strm.next_out = tmp_out; -+ strm.avail_out = tmpsize; -+ } -+ if (ret != LZMA_OK) { -+ if (ret == LZMA_STREAM_END) { -+ break; -+ } else { -+ goto err; -+ } -+ } -+ } -+ *rsize = size; -+ -+ goto exit; -+err: -+ free(buf); buf = NULL; -+exit: -+ lzma_end(&strm); -+ return buf; -+} - - int security_load_policy(void *data, size_t len) - { -@@ -55,7 +131,7 @@ int selinux_mkload_policy(int preservebools) - struct stat sb; - struct utsname uts; - size_t size; -- void *map, *data; -+ void *map = NULL, *data=NULL; - int fd, rc = -1, prot; - sepol_policydb_t *policydb; - sepol_policy_file_t *pf; -@@ -181,24 +257,28 @@ checkbool: - goto dlclose; - } - -- if (fstat(fd, &sb) < 0) { -- fprintf(stderr, -- "SELinux: Could not stat policy file %s: %s\n", -- path, strerror(errno)); -- goto close; -- } -- -- prot = PROT_READ; -- if (setlocaldefs || preservebools) -- prot |= PROT_WRITE; -+ data = lzmaread(fd,&size); - -- size = sb.st_size; -- data = map = mmap(NULL, size, prot, MAP_PRIVATE, fd, 0); -- if (map == MAP_FAILED) { -- fprintf(stderr, -- "SELinux: Could not map policy file %s: %s\n", -+ if (!data) { -+ if (fstat(fd, &sb) < 0) { -+ fprintf(stderr, -+ "SELinux: Could not stat policy file %s: %s\n", - path, strerror(errno)); -- goto close; -+ goto close; -+ } -+ -+ prot = PROT_READ; -+ if (setlocaldefs || preservebools) -+ prot |= PROT_WRITE; -+ -+ size = sb.st_size; -+ data = map = mmap(NULL, size, prot, MAP_PRIVATE, fd, 0); -+ if (map == MAP_FAILED) { -+ fprintf(stderr, -+ "SELinux: Could not map policy file %s: %s\n", -+ path, strerror(errno)); -+ goto close; -+ } - } - - if (vers > kernvers && usesepol) { -@@ -210,6 +290,8 @@ checkbool: - goto unmap; - } - policy_file_set_mem(pf, data, size); -+ if (!map) -+ free(data); - if (policydb_read(policydb, pf)) { - policy_file_free(pf); - policydb_free(policydb); -@@ -223,7 +305,8 @@ checkbool: - path); - policy_file_free(pf); - policydb_free(policydb); -- munmap(map, sb.st_size); -+ if (map) -+ munmap(map, sb.st_size); - close(fd); - vers--; - goto search; -@@ -275,7 +358,7 @@ checkbool: - #endif - } - -- -+ - rc = security_load_policy(data, size); - - if (rc) -@@ -286,7 +369,8 @@ checkbool: - unmap: - if (data != map) - free(data); -- munmap(map, sb.st_size); -+ if (map) -+ munmap(map, sb.st_size); - close: - close(fd); - dlclose: -diff --git a/libselinux/src/lsetfilecon.c b/libselinux/src/lsetfilecon.c -index fd9bb26..af2d88c 100644 ---- a/libselinux/src/lsetfilecon.c -+++ b/libselinux/src/lsetfilecon.c -@@ -9,8 +9,13 @@ - - int lsetfilecon_raw(const char *path, const security_context_t 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) { - security_context_t ccontext = NULL; - int err = errno; -diff --git a/libselinux/src/matchpathcon.c b/libselinux/src/matchpathcon.c -index 2d7369e..2a00807 100644 ---- a/libselinux/src/matchpathcon.c -+++ b/libselinux/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 a/libselinux/src/setfilecon.c b/libselinux/src/setfilecon.c -index 50cb228..e617039 100644 ---- a/libselinux/src/setfilecon.c -+++ b/libselinux/src/setfilecon.c -@@ -9,8 +9,12 @@ - - int setfilecon_raw(const char *path, const security_context_t 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) { - security_context_t ccontext = NULL; - int err = errno; diff --git a/SOURCES/libselinux-rhel.patch b/SOURCES/libselinux-rhel.patch new file mode 100644 index 0000000..5a06f64 --- /dev/null +++ b/SOURCES/libselinux-rhel.patch @@ -0,0 +1,1315 @@ +diff --git libselinux-2.5/ChangeLog libselinux-2.5/ChangeLog +index 24673dd..41507e4 100644 +--- libselinux-2.5/ChangeLog ++++ libselinux-2.5/ChangeLog +@@ -1,3 +1,20 @@ ++ * Handle NULL pcre study data, from Stephen Smalley. ++ * Fix in tree compilation of utils that depend on libsepol, from Laurent Bigonville. ++ * Clarify is_selinux_mls_enabled() description, from David King. ++ * Explain how to free policy type from selinux_getpolicytype(), from David King. ++ * Compare absolute pathname in matchpathcon -V, from Petr Lautrbach. ++ * Add selinux_snapperd_contexts_path(), from Petr Lautrbach. ++ * Modify audit2why analyze function to use loaded policy, from Joshua Brindle. ++ * Sort object files for deterministic linking order, from Laurent Bigonville. ++ * Respect CC and PKG_CONFIG environment variable, from Julien Pivotto. ++ * Avoid mounting /proc outside of selinux_init_load_policy(), from Stephen Smalley. ++ * Fix multiple spelling errors, from Laurent Bigonville. ++ * Fix typo in sefcontext_compile.8, from Petr Lautrbach and Milos Malik ++ * Fix location of selinuxfs mount point, from Dan Walsh. ++ * Only mount /proc if necessary, from Stephen Smalley. ++ * procattr: return einval for <= 0 pid args, from Daniel Cashman. ++ * procattr: return error on invalid pid_t input, from Daniel Cashman. ++ + 2.5 2016-02-23 + * selinux_restorecon.3 man page corrections, from Richard Haines. + * Add selinux_restorecon function, from Richard Haines. +diff --git libselinux-2.5/Makefile libselinux-2.5/Makefile +index 6142b60..bdf9de8 100644 +--- libselinux-2.5/Makefile ++++ libselinux-2.5/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/golang/Makefile libselinux-2.5/golang/Makefile +new file mode 100644 +index 0000000..b75677b +--- /dev/null ++++ libselinux-2.5/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/golang/selinux.go libselinux-2.5/golang/selinux.go +new file mode 100644 +index 0000000..34bf6bb +--- /dev/null ++++ libselinux-2.5/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/golang/test.go libselinux-2.5/golang/test.go +new file mode 100644 +index 0000000..fed6de8 +--- /dev/null ++++ libselinux-2.5/golang/test.go +@@ -0,0 +1,9 @@ ++package main ++ ++import ( ++ "./selinux" ++) ++ ++func main() { ++ selinux.Test() ++} +diff --git libselinux-2.5/include/selinux/selinux.h libselinux-2.5/include/selinux/selinux.h +index 2262086..3d8673f 100644 +--- libselinux-2.5/include/selinux/selinux.h ++++ libselinux-2.5/include/selinux/selinux.h +@@ -544,6 +544,7 @@ 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_snapperd_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.5/man/man3/avc_add_callback.3 libselinux-2.5/man/man3/avc_add_callback.3 +index dbfe72d..bdbbadf 100644 +--- libselinux-2.5/man/man3/avc_add_callback.3 ++++ libselinux-2.5/man/man3/avc_add_callback.3 +@@ -57,7 +57,7 @@ and will cause any SID to match. + .I callback + is the callback function provided by the userspace object manager. The + .I event +-argument indicates the security event which occured; the remaining arguments ++argument indicates the security event which occurred; the remaining arguments + are interpreted according to the event as described below. The return value + of the callback should be zero on success, \-1 on error with + .I errno +@@ -175,7 +175,7 @@ If the userspace AVC is running in threaded mode, callbacks registered via + may be executed in the context of the netlink handler thread. This will likely introduce synchronization issues requiring the use of locks. See + .BR avc_init (3). + +-Support for dynamic revocation and retained permissions is mostly unimplemented in the SELinux kernel module. The only security event that currently gets excercised is ++Support for dynamic revocation and retained permissions is mostly unimplemented in the SELinux kernel module. The only security event that currently gets exercised is + .BR AVC_CALLBACK_RESET . + . + .SH "AUTHOR" +diff --git libselinux-2.5/man/man3/avc_has_perm.3 libselinux-2.5/man/man3/avc_has_perm.3 +index 7353952..3e9fca8 100644 +--- libselinux-2.5/man/man3/avc_has_perm.3 ++++ libselinux-2.5/man/man3/avc_has_perm.3 +@@ -108,7 +108,7 @@ for the first time. + Using an uninitialized structure will produce undefined behavior. + . + .SH "RETURN VALUE" +-If requested permissions are granted, zero is returned. If requested permissions are denied or an error occured, \-1 is returned and ++If requested permissions are granted, zero is returned. If requested permissions are denied or an error occurred, \-1 is returned and + .I errno + is set appropriately. + +diff --git libselinux-2.5/man/man3/is_selinux_enabled.3 libselinux-2.5/man/man3/is_selinux_enabled.3 +index f02052c..df62c22 100644 +--- libselinux-2.5/man/man3/is_selinux_enabled.3 ++++ libselinux-2.5/man/man3/is_selinux_enabled.3 +@@ -3,7 +3,7 @@ + is_selinux_enabled \- check whether SELinux is enabled + . + .SH "NAME" +-is_selinux_mls_enabled \- check whether SELinux is enabled for (Multi Level Securty) MLS ++is_selinux_mls_enabled \- check whether SELinux is enabled for (Multi Level Security) MLS + . + .SH "SYNOPSIS" + .B #include +@@ -18,7 +18,9 @@ returns 1 if SELinux is running or 0 if it is not. + On error, \-1 is returned. + + .BR is_selinux_mls_enabled () +-returns 1 if SELinux is running in MLS mode or 0 if it is not. ++returns 1 if SELinux is capable of running in MLS mode or 0 if it is not. To ++determine the policy in use on the system, use ++.BR selinux_getpolicytype (3). + . + .SH "SEE ALSO" + .BR selinux "(8)" +diff --git libselinux-2.5/man/man3/security_disable.3 libselinux-2.5/man/man3/security_disable.3 +index c75ce0d..072923c 100644 +--- libselinux-2.5/man/man3/security_disable.3 ++++ libselinux-2.5/man/man3/security_disable.3 +@@ -12,7 +12,7 @@ security_disable \- disable the SELinux kernel code at runtime + disables the SELinux kernel code, unregisters selinuxfs from + .IR /proc/filesystems , + and then unmounts +-.IR /selinux . ++.IR /sys/fs/selinux . + .sp + This function can only be called at runtime and prior to the initial policy + load. After the initial policy load, the SELinux kernel code cannot be disabled, +diff --git libselinux-2.5/man/man3/selinux_getpolicytype.3 libselinux-2.5/man/man3/selinux_getpolicytype.3 +index c947e2c..b219d42 100644 +--- libselinux-2.5/man/man3/selinux_getpolicytype.3 ++++ libselinux-2.5/man/man3/selinux_getpolicytype.3 +@@ -13,7 +13,10 @@ Reads the contents of the + .I /etc/selinux/config + file to determine the SELinux policy used on the system, and sets + .I \%policytype +-accordinly. ++accordingly. Free ++.I \%policytype ++with ++.BR free (3). + . + .SH "RETURN VALUE" + On success, zero is returned. +diff --git libselinux-2.5/man/man3/selinux_status_open.3 libselinux-2.5/man/man3/selinux_status_open.3 +index f779dd9..2d44be5 100644 +--- libselinux-2.5/man/man3/selinux_status_open.3 ++++ libselinux-2.5/man/man3/selinux_status_open.3 +@@ -23,7 +23,7 @@ without invocation of system calls + .SH "DESCRIPTION" + Linux 2.6.37 or later provides a SELinux kernel status page; being mostly + placed on +-.I /selinux/status ++.I /sys/fs/selinux/status + entry. It enables userspace applications to mmap this page with read-only + mode, then it informs some status without system call invocations. + .sp +@@ -38,7 +38,7 @@ without system-call invocation or worker thread for monitoring. + .BR selinux_status_open () + tries to + .BR open (2) +-.I /selinux/status ++.I /sys/fs/selinux/status + and + .BR mmap (2) + it in read-only mode. The file-descriptor and pointer to the page shall +diff --git libselinux-2.5/man/man8/avcstat.8 libselinux-2.5/man/man8/avcstat.8 +index 204687d..2c4bce1 100644 +--- libselinux-2.5/man/man8/avcstat.8 ++++ libselinux-2.5/man/man8/avcstat.8 +@@ -25,7 +25,7 @@ Display the cumulative values. + .TP + .B \-f + Specifies the location of the AVC statistics file, defaulting to +-.IR /selinux/avc/cache_stats . ++.IR /sys/fs/selinux/avc/cache_stats . + . + .SH AUTHOR + This manual page was written by Dan Walsh . +diff --git libselinux-2.5/man/man8/sefcontext_compile.8 libselinux-2.5/man/man8/sefcontext_compile.8 +index b77ff3a..4eae173 100644 +--- libselinux-2.5/man/man8/sefcontext_compile.8 ++++ libselinux-2.5/man/man8/sefcontext_compile.8 +@@ -13,14 +13,14 @@ sefcontext_compile \- compile file context regular expression files + .SH "DESCRIPTION" + .B sefcontext_compile + is used to compile file context regular expressions into +-.BR prce (3) ++.BR pcre (3) + format. + .sp + The compiled file is used by libselinux file labeling functions. + .sp + By default + .B sefcontext_compile +-writes the compiled prce file with the ++writes the compiled pcre file with the + .B .bin + suffix appended (e.g. \fIinputfile\fB.bin\fR). + .SH OPTIONS +diff --git libselinux-2.5/man/man8/selinux.8 libselinux-2.5/man/man8/selinux.8 +index 6f1034b..c9f188c 100644 +--- libselinux-2.5/man/man8/selinux.8 ++++ libselinux-2.5/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/src/Makefile libselinux-2.5/src/Makefile +index d0021ae..d94163e 100644 +--- libselinux-2.5/src/Makefile ++++ libselinux-2.5/src/Makefile +@@ -5,6 +5,7 @@ PYTHON ?= python + PYPREFIX ?= $(notdir $(PYTHON)) + RUBY ?= ruby + RUBYPREFIX ?= $(notdir $(RUBY)) ++PKG_CONFIG ?= pkg-config + + # Installation directories. + PREFIX ?= $(DESTDIR)/usr +@@ -12,11 +13,11 @@ LIBDIR ?= $(PREFIX)/lib + SHLIBDIR ?= $(DESTDIR)/lib + INCLUDEDIR ?= $(PREFIX)/include + PYLIBVER ?= $(shell $(PYTHON) -c 'import sys;print("python%d.%d" % sys.version_info[0:2])') +-PYINC ?= $(shell pkg-config --cflags $(PYPREFIX)) ++PYINC ?= $(shell $(PKG_CONFIG) --cflags $(PYPREFIX)) + PYLIBDIR ?= $(LIBDIR)/$(PYLIBVER) + RUBYLIBVER ?= $(shell $(RUBY) -e 'print RUBY_VERSION.split(".")[0..1].join(".")') + RUBYPLATFORM ?= $(shell $(RUBY) -e 'print RUBY_PLATFORM') +-RUBYINC ?= $(shell pkg-config --cflags ruby) ++RUBYINC ?= $(shell $(PKG_CONFIG) --cflags ruby) + RUBYINSTALL ?= $(LIBDIR)/ruby/site_ruby/$(RUBYLIBVER)/$(RUBYPLATFORM) + LIBBASE ?= $(shell basename $(LIBDIR)) + +@@ -48,7 +49,7 @@ ifeq ($(DISABLE_BOOL),y) + endif + + GENERATED=$(SWIGCOUT) $(SWIGRUBYCOUT) selinuxswig_python_exception.i +-SRCS= $(filter-out $(UNUSED_SRCS) $(GENERATED) audit2why.c, $(wildcard *.c)) ++SRCS= $(filter-out $(UNUSED_SRCS) $(GENERATED) audit2why.c, $(sort $(wildcard *.c))) + + MAX_STACK_SIZE=32768 + +diff --git libselinux-2.5/src/audit2why.c libselinux-2.5/src/audit2why.c +index 12745b3..abe1701 100644 +--- libselinux-2.5/src/audit2why.c ++++ libselinux-2.5/src/audit2why.c +@@ -343,8 +343,8 @@ static PyObject *analyze(PyObject *self __attribute__((unused)) , PyObject *args + if (rc < 0) + RETURN(BADTCON) + +- tclass = string_to_security_class(tclassstr); +- if (!tclass) ++ rc = sepol_string_to_security_class(tclassstr, &tclass); ++ if (rc < 0) + RETURN(BADTCLASS) + + /* Convert the permission list to an AV. */ +@@ -365,8 +365,8 @@ static PyObject *analyze(PyObject *self __attribute__((unused)) , PyObject *args + permstr = PyString_AsString( strObj ); + #endif + +- perm = string_to_av_perm(tclass, permstr); +- if (!perm) ++ rc = sepol_string_to_av_perm(tclass, permstr, &perm); ++ if (rc < 0) + RETURN(BADPERM) + + av |= perm; +diff --git libselinux-2.5/src/avc_sidtab.c libselinux-2.5/src/avc_sidtab.c +index 9669264..c775430 100644 +--- libselinux-2.5/src/avc_sidtab.c ++++ libselinux-2.5/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/src/canonicalize_context.c libselinux-2.5/src/canonicalize_context.c +index 7cf3139..364a746 100644 +--- libselinux-2.5/src/canonicalize_context.c ++++ libselinux-2.5/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/src/check_context.c libselinux-2.5/src/check_context.c +index 52063fa..234749c 100644 +--- libselinux-2.5/src/check_context.c ++++ libselinux-2.5/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/src/compute_av.c libselinux-2.5/src/compute_av.c +index 937e5c3..35ace7f 100644 +--- libselinux-2.5/src/compute_av.c ++++ libselinux-2.5/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/src/compute_create.c libselinux-2.5/src/compute_create.c +index 9559d42..14a65d1 100644 +--- libselinux-2.5/src/compute_create.c ++++ libselinux-2.5/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/src/compute_member.c libselinux-2.5/src/compute_member.c +index 1fc7e41..065d996 100644 +--- libselinux-2.5/src/compute_member.c ++++ libselinux-2.5/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/src/compute_relabel.c libselinux-2.5/src/compute_relabel.c +index 4615aee..cc77f36 100644 +--- libselinux-2.5/src/compute_relabel.c ++++ libselinux-2.5/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/src/compute_user.c libselinux-2.5/src/compute_user.c +index b37c5d3..7703c26 100644 +--- libselinux-2.5/src/compute_user.c ++++ libselinux-2.5/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/src/exception.sh libselinux-2.5/src/exception.sh +index b7cff7e..a58bf3f 100755 +--- libselinux-2.5/src/exception.sh ++++ libselinux-2.5/src/exception.sh +@@ -15,6 +15,6 @@ echo " + ;; + esac + } +-gcc -x c -c -I../include - -aux-info temp.aux < ../include/selinux/selinux.h ++${CC:-gcc} -x c -c -I../include - -aux-info temp.aux < ../include/selinux/selinux.h + for i in `awk '/.*extern int/ { print $6 }' temp.aux`; do except $i ; done + rm -f -- temp.aux -.o +diff --git libselinux-2.5/src/file_path_suffixes.h libselinux-2.5/src/file_path_suffixes.h +index d1f9b48..95b228b 100644 +--- libselinux-2.5/src/file_path_suffixes.h ++++ libselinux-2.5/src/file_path_suffixes.h +@@ -24,6 +24,7 @@ S_(BINPOLICY, "/policy/policy") + S_(VIRTUAL_IMAGE, "/contexts/virtual_image_context") + S_(LXC_CONTEXTS, "/contexts/lxc_contexts") + S_(OPENSSH_CONTEXTS, "/contexts/openssh_contexts") ++ S_(SNAPPERD_CONTEXTS, "/contexts/snapperd_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.5/src/fsetfilecon.c libselinux-2.5/src/fsetfilecon.c +index 52707d0..0cbe12d 100644 +--- libselinux-2.5/src/fsetfilecon.c ++++ libselinux-2.5/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/src/init.c libselinux-2.5/src/init.c +index 3db4de0..3c687a2 100644 +--- libselinux-2.5/src/init.c ++++ libselinux-2.5/src/init.c +@@ -11,7 +11,6 @@ + #include + #include + #include +-#include + + #include "dso.h" + #include "policy.h" +@@ -57,20 +56,15 @@ static int verify_selinuxmnt(const char *mnt) + + int selinuxfs_exists(void) + { +- int exists = 0, mnt_rc = 0; ++ int exists = 0; + FILE *fp = NULL; + char *buf = NULL; + size_t len; + ssize_t num; + +- mnt_rc = mount("proc", "/proc", "proc", 0, 0); +- + fp = fopen("/proc/filesystems", "r"); +- if (!fp) { +- exists = 1; /* Fail as if it exists */ +- goto out; +- } +- ++ if (!fp) ++ return 1; /* Fail as if it exists */ + __fsetlocking(fp, FSETLOCKING_BYCALLER); + + num = getline(&buf, &len, fp); +@@ -84,14 +78,6 @@ int selinuxfs_exists(void) + + free(buf); + fclose(fp); +- +-out: +-#ifndef MNT_DETACH +-#define MNT_DETACH 2 +-#endif +- if (mnt_rc == 0) +- umount2("/proc", MNT_DETACH); +- + return exists; + } + hidden_def(selinuxfs_exists) +diff --git libselinux-2.5/src/label_file.c libselinux-2.5/src/label_file.c +index 071d902..c89bb35 100644 +--- libselinux-2.5/src/label_file.c ++++ libselinux-2.5/src/label_file.c +@@ -388,18 +388,21 @@ static int load_mmap(struct selabel_handle *rec, const char *path, + rc = -1; + goto err; + } +- spec->lsd.study_data = (void *)mmap_area->next_addr; +- spec->lsd.flags |= PCRE_EXTRA_STUDY_DATA; +- rc = next_entry(NULL, mmap_area, entry_len); +- if (rc < 0) +- goto err; + +- /* Check that study data lengths match. */ +- rc = pcre_fullinfo(spec->regex, &spec->lsd, +- PCRE_INFO_STUDYSIZE, &len); +- if (rc < 0 || len != entry_len) { +- rc = -1; +- goto err; ++ if (entry_len) { ++ spec->lsd.study_data = (void *)mmap_area->next_addr; ++ spec->lsd.flags |= PCRE_EXTRA_STUDY_DATA; ++ rc = next_entry(NULL, mmap_area, entry_len); ++ if (rc < 0) ++ goto err; ++ ++ /* Check that study data lengths match. */ ++ rc = pcre_fullinfo(spec->regex, &spec->lsd, ++ PCRE_INFO_STUDYSIZE, &len); ++ if (rc < 0 || len != entry_len) { ++ rc = -1; ++ goto err; ++ } + } + + data->nspec++; +diff --git libselinux-2.5/src/label_file.h libselinux-2.5/src/label_file.h +index 72fed1f..6d1e890 100644 +--- libselinux-2.5/src/label_file.h ++++ libselinux-2.5/src/label_file.h +@@ -80,9 +80,12 @@ struct saved_data { + + static inline pcre_extra *get_pcre_extra(struct spec *spec) + { +- if (spec->from_mmap) +- return &spec->lsd; +- else ++ if (spec->from_mmap) { ++ if (spec->lsd.study_data) ++ return &spec->lsd; ++ else ++ return NULL; ++ } else + return spec->sd; + } + +diff --git libselinux-2.5/src/load_policy.c libselinux-2.5/src/load_policy.c +index 21ee58b..4f39fc7 100644 +--- libselinux-2.5/src/load_policy.c ++++ libselinux-2.5/src/load_policy.c +@@ -17,6 +17,10 @@ + #include "policy.h" + #include + ++#ifndef MNT_DETACH ++#define MNT_DETACH 2 ++#endif ++ + int security_load_policy(void *data, size_t len) + { + char path[PATH_MAX]; +@@ -348,11 +352,6 @@ int selinux_init_load_policy(int *enforce) + fclose(cfg); + free(buf); + } +-#ifndef MNT_DETACH +-#define MNT_DETACH 2 +-#endif +- if (rc == 0) +- umount2("/proc", MNT_DETACH); + + /* + * Determine the final desired mode. +@@ -400,11 +399,17 @@ int selinux_init_load_policy(int *enforce) + /* Only emit this error if selinux was not disabled */ + fprintf(stderr, "Mount failed for selinuxfs on %s: %s\n", SELINUXMNT, strerror(errno)); + } ++ ++ if (rc == 0) ++ umount2("/proc", MNT_DETACH); + + goto noload; + } + set_selinuxmnt(mntpoint); + ++ if (rc == 0) ++ umount2("/proc", MNT_DETACH); ++ + /* + * Note: The following code depends on having selinuxfs + * already mounted and selinuxmnt set above. +diff --git libselinux-2.5/src/lsetfilecon.c libselinux-2.5/src/lsetfilecon.c +index 1d3b28a..ea6d70b 100644 +--- libselinux-2.5/src/lsetfilecon.c ++++ libselinux-2.5/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/src/matchpathcon.c libselinux-2.5/src/matchpathcon.c +index 5b495a0..a2f2c3e 100644 +--- libselinux-2.5/src/matchpathcon.c ++++ libselinux-2.5/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); + } + +@@ -470,6 +471,17 @@ int selinux_file_context_verify(const char *path, mode_t mode) + char * con = NULL; + char * fcontext = NULL; + int rc = 0; ++ char stackpath[PATH_MAX + 1]; ++ char *p = NULL; ++ ++ if (S_ISLNK(mode)) { ++ if (!realpath_not_final(path, stackpath)) ++ path = stackpath; ++ } else { ++ p = realpath(path, stackpath); ++ if (p) ++ path = p; ++ } + + rc = lgetfilecon_raw(path, &con); + if (rc == -1) { +diff --git libselinux-2.5/src/procattr.c libselinux-2.5/src/procattr.c +index 527a0a5..eee4612 100644 +--- libselinux-2.5/src/procattr.c ++++ libselinux-2.5/src/procattr.c +@@ -70,9 +70,9 @@ static int openattr(pid_t pid, const char *attr, int flags) + char *path; + pid_t tid; + +- if (pid > 0) ++ if (pid > 0) { + rc = asprintf(&path, "/proc/%d/attr/%s", pid, attr); +- else { ++ } else if (pid == 0) { + rc = asprintf(&path, "/proc/thread-self/attr/%s", attr); + if (rc < 0) + return -1; +@@ -82,6 +82,9 @@ static int openattr(pid_t pid, const char *attr, int flags) + free(path); + tid = gettid(); + rc = asprintf(&path, "/proc/self/task/%d/attr/%s", tid, attr); ++ } else { ++ errno = EINVAL; ++ return -1; + } + if (rc < 0) + return -1; +@@ -303,11 +306,21 @@ static int setprocattrcon(const char * context, + #define getpidattr_def(fn, attr) \ + int get##fn##_raw(pid_t pid, char **c) \ + { \ +- return getprocattrcon_raw(c, pid, #attr); \ ++ if (pid <= 0) { \ ++ errno = EINVAL; \ ++ return -1; \ ++ } else { \ ++ return getprocattrcon_raw(c, pid, #attr); \ ++ } \ + } \ + int get##fn(pid_t pid, char **c) \ + { \ +- return getprocattrcon(c, pid, #attr); \ ++ if (pid <= 0) { \ ++ errno = EINVAL; \ ++ return -1; \ ++ } else { \ ++ return getprocattrcon(c, pid, #attr); \ ++ } \ + } + + all_selfattr_def(con, current) +diff --git libselinux-2.5/src/selinux_config.c libselinux-2.5/src/selinux_config.c +index bec5f3b..c519a77 100644 +--- libselinux-2.5/src/selinux_config.c ++++ libselinux-2.5/src/selinux_config.c +@@ -50,7 +50,8 @@ + #define BOOLEAN_SUBS 27 + #define OPENSSH_CONTEXTS 28 + #define SYSTEMD_CONTEXTS 29 +-#define NEL 30 ++#define SNAPPERD_CONTEXTS 30 ++#define NEL 31 + + /* Part of one-time lazy init */ + static pthread_once_t once = PTHREAD_ONCE_INIT; +@@ -499,6 +500,13 @@ const char *selinux_openssh_contexts_path(void) + + hidden_def(selinux_openssh_contexts_path) + ++const char *selinux_snapperd_contexts_path(void) ++{ ++ return get_path(SNAPPERD_CONTEXTS); ++} ++ ++hidden_def(selinux_snapperd_contexts_path) ++ + const char *selinux_systemd_contexts_path(void) + { + return get_path(SYSTEMD_CONTEXTS); +diff --git libselinux-2.5/src/selinux_internal.h libselinux-2.5/src/selinux_internal.h +index 46566f6..9b9145c 100644 +--- libselinux-2.5/src/selinux_internal.h ++++ libselinux-2.5/src/selinux_internal.h +@@ -84,6 +84,7 @@ hidden_proto(selinux_mkload_policy) + hidden_proto(selinux_x_context_path) + hidden_proto(selinux_sepgsql_context_path) + hidden_proto(selinux_openssh_contexts_path) ++ hidden_proto(selinux_snapperd_contexts_path) + hidden_proto(selinux_systemd_contexts_path) + hidden_proto(selinux_path) + hidden_proto(selinux_check_passwd_access) +diff --git libselinux-2.5/src/setexecfilecon.c libselinux-2.5/src/setexecfilecon.c +index e72ba0d..9c821f8 100644 +--- libselinux-2.5/src/setexecfilecon.c ++++ libselinux-2.5/src/setexecfilecon.c +@@ -45,7 +45,7 @@ int setexecfilecon(const char *filename, const char *fallback_type) + goto out; + out: + +- if (rc < 0 && security_getenforce() == 0) ++ if (rc < 0 && security_getenforce() < 1) + rc = 0; + + context_free(con); +diff --git libselinux-2.5/src/setfilecon.c libselinux-2.5/src/setfilecon.c +index d05969c..3f0200e 100644 +--- libselinux-2.5/src/setfilecon.c ++++ libselinux-2.5/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/utils/.gitignore libselinux-2.5/utils/.gitignore +index 060eaab..ed3bf0b 100644 +--- libselinux-2.5/utils/.gitignore ++++ libselinux-2.5/utils/.gitignore +@@ -14,7 +14,12 @@ getseuser + matchpathcon + policyvers + sefcontext_compile ++selabel_digest ++selabel_lookup ++selabel_lookup_best_match ++selabel_partial_match + selinux_check_securetty_context ++selinux_restorecon + selinuxenabled + selinuxexeccon + setenforce +diff --git libselinux-2.5/utils/Makefile libselinux-2.5/utils/Makefile +index cf7af52..8497cb4 100644 +--- libselinux-2.5/utils/Makefile ++++ libselinux-2.5/utils/Makefile +@@ -3,6 +3,7 @@ PREFIX ?= $(DESTDIR)/usr + LIBDIR ?= $(PREFIX)/lib + USRBINDIR ?= $(PREFIX)/sbin + SBINDIR ?= $(DESTDIR)/sbin ++INCLUDEDIR ?= $(PREFIX)/include + + MAX_STACK_SIZE=8192 + CFLAGS ?= -O -Wall -W -Wundef -Wformat-y2k -Wformat-security -Winit-self -Wmissing-include-dirs \ +@@ -23,7 +24,7 @@ CFLAGS ?= -O -Wall -W -Wundef -Wformat-y2k -Wformat-security -Winit-self -Wmissi + -fasynchronous-unwind-tables -fdiagnostics-show-option -funit-at-a-time \ + -fipa-pure-const -Wno-suggest-attribute=pure -Wno-suggest-attribute=const \ + -Werror -Wno-aggregate-return -Wno-redundant-decls +-override CFLAGS += -I../include -D_GNU_SOURCE $(EMFLAGS) ++override CFLAGS += -I../include -I$(INCLUDEDIR) -D_GNU_SOURCE $(EMFLAGS) + LDLIBS += -L../src -lselinux -L$(LIBDIR) + + TARGETS=$(patsubst %.c,%,$(wildcard *.c)) +diff --git libselinux-2.5/utils/sefcontext_compile.c libselinux-2.5/utils/sefcontext_compile.c +index d2578b6..fd6fb78 100644 +--- libselinux-2.5/utils/sefcontext_compile.c ++++ libselinux-2.5/utils/sefcontext_compile.c +@@ -228,10 +228,13 @@ static int write_binary_file(struct saved_data *data, int fd) + if (len != to_write) + goto err; + +- /* determine the size of the pcre study info */ +- rc = pcre_fullinfo(re, sd, PCRE_INFO_STUDYSIZE, &size); +- if (rc < 0) +- goto err; ++ if (sd) { ++ /* determine the size of the pcre study info */ ++ rc = pcre_fullinfo(re, sd, PCRE_INFO_STUDYSIZE, &size); ++ if (rc < 0) ++ goto err; ++ } else ++ size = 0; + + /* write the number of bytes in the pcre study data */ + to_write = size; +@@ -239,10 +242,12 @@ static int write_binary_file(struct saved_data *data, int fd) + if (len != 1) + goto err; + +- /* write the actual pcre study data as a char array */ +- len = fwrite(sd->study_data, 1, to_write, bin_file); +- if (len != to_write) +- goto err; ++ if (sd) { ++ /* write the actual pcre study data as a char array */ ++ len = fwrite(sd->study_data, 1, to_write, bin_file); ++ if (len != to_write) ++ goto err; ++ } + } + + rc = 0; diff --git a/SPECS/libselinux.spec b/SPECS/libselinux.spec index 0e659c1..1821e96 100644 --- a/SPECS/libselinux.spec +++ b/SPECS/libselinux.spec @@ -1,27 +1,31 @@ -%global with_python3 0 +%if 0%{?fedora} > 12 +%global with_python3 1 +%endif %define ruby_inc %(pkg-config --cflags ruby) %define ruby_sitearch %(ruby -rrbconfig -e "puts RbConfig::CONFIG['vendorarchdir']") -%define libsepolver 2.1.9-1 +%define libsepolver 2.5-6 %{!?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.2.2 +Version: 2.5 Release: 6%{?dist} License: Public Domain Group: System Environment/Libraries -Source: %{name}-%{version}.tgz +# https://github.com/SELinuxProject/selinux/wiki/Releases +Source: https://raw.githubusercontent.com/wiki/SELinuxProject/selinux/files/releases/20160223/libselinux-2.5.tar.gz Source1: selinuxconlist.8 Source2: selinuxdefcon.8 -Url: http://oss.tresys.com/git/selinux.git -Patch1: libselinux-rhat.patch -BuildRequires: pkgconfig python-devel ruby-devel ruby libsepol-static >= %{libsepolver} swig pcre-devel xz-devel +Url: https://github.com/SELinuxProject/selinux/wiki +# HEAD 95ce251a24e80e884c69771a497589323be2223c +Patch1: libselinux-rhel.patch +BuildRequires: pkgconfig python python-devel ruby-devel ruby libsepol-static >= %{libsepolver} swig pcre-devel xz-devel %if 0%{?with_python3} -BuildRequires: python3-devel +BuildRequires: python3 python3-devel %endif # if with_python3 -Requires: libsepol >= %{libsepolver} pcre -Conflicts: filesystem < 3 +Requires: libsepol%{?_isa} >= %{libsepolver} pcre +Conflicts: filesystem < 3 systemd < 219-20 BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) %description @@ -42,7 +46,7 @@ decisions. Required for any applications that use the SELinux API. %package utils Summary: SELinux libselinux utilies Group: Development/Libraries -Requires: libselinux = %{version}-%{release} +Requires: libselinux%{?_isa} = %{version}-%{release} %description utils The libselinux-utils package contains the utilities @@ -50,7 +54,7 @@ The libselinux-utils package contains the utilities %package python Summary: SELinux python bindings for libselinux Group: Development/Libraries -Requires: libselinux = %{version}-%{release} +Requires: libselinux%{?_isa} = %{version}-%{release} %description python The libselinux-python package contains the python bindings for developing @@ -60,7 +64,7 @@ SELinux applications. %package python3 Summary: SELinux python 3 bindings for libselinux Group: Development/Libraries -Requires: libselinux = %{version}-%{release} +Requires: libselinux%{?_isa} = %{version}-%{release} %description python3 The libselinux-python3 package contains python 3 bindings for developing @@ -70,7 +74,7 @@ SELinux applications. %package ruby Summary: SELinux ruby bindings for libselinux Group: Development/Libraries -Requires: libselinux = %{version}-%{release} +Requires: libselinux%{?_isa} = %{version}-%{release} Provides: ruby(selinux) %description ruby @@ -80,8 +84,8 @@ SELinux applications. %package devel Summary: Header files and libraries used to build SELinux Group: Development/Libraries -Requires: libselinux = %{version}-%{release} -Requires: libsepol-devel >= %{libsepolver} +Requires: libselinux%{?_isa} = %{version}-%{release} +Requires: libsepol-devel%{?_isa} >= %{libsepolver} %description devel The libselinux-devel package contains the libraries and header files @@ -90,17 +94,20 @@ needed for developing SELinux applications. %package static Summary: Static libraries used to build SELinux Group: Development/Libraries -Requires: libselinux-devel = %{version}-%{release} +Requires: libselinux-devel%{?_isa} = %{version}-%{release} %description static The libselinux-static package contains the static libraries needed for developing SELinux applications. %prep -%setup -q -%patch1 -p2 -b .rhat +%setup -q -n libselinux-2.5 +%patch1 -p1 -b .rhel %build +export LDFLAGS="%{?__global_ldflags}" +# FIXME: export DISABLE_RPM="y" + # To support building the Python wrapper against multiple Python runtimes # Define a function, for how to perform a "build" of the python wrapper against # a specific runtime: @@ -155,7 +162,7 @@ InstallPythonWrapper %{__python} InstallPythonWrapper %{__python3} %endif # with_python3 -make DESTDIR="%{buildroot}" LIBDIR="%{buildroot}%{_libdir}" SHLIBDIR="%{buildroot}%{_libdir}" BINDIR="%{buildroot}%{_bindir}" SBINDIR="%{buildroot}%{_sbindir}" RUBYINSTALL=%{buildroot}%{ruby_sitearch} install install-rubywrap +make DESTDIR="%{buildroot}" LIBDIR="%{buildroot}%{_libdir}" SHLIBDIR="%{buildroot}%{_libdir}" BINDIR="%{buildroot}%{_bindir}" SBINDIR="%{buildroot}%{_sbindir}" RUBYINSTALL=%{buildroot}%{ruby_vendorarchdir} install install-rubywrap # Nuke the files we don't want to distribute rm -f %{buildroot}%{_sbindir}/compute_* @@ -204,6 +211,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/* @@ -211,9 +223,9 @@ rm -rf %{buildroot} %defattr(-,root,root,-) %{_libdir}/libselinux.so %{_libdir}/pkgconfig/libselinux.pc -%dir %{_includedir}/selinux %dir %{_libdir}/golang/src/pkg/github.com/selinux %{_libdir}/golang/src/pkg/github.com/selinux/selinux.go +%dir %{_includedir}/selinux %{_includedir}/selinux/* %{_mandir}/man3/* @@ -238,9 +250,39 @@ rm -rf %{buildroot} %files ruby %defattr(-,root,root,-) -%{ruby_sitearch}/selinux.so +%{ruby_vendorarchdir}/selinux.so %changelog +* Fri Aug 26 2016 Petr Lautrbach 2.5-6 +- Handle NULL pcre study data + +* Wed Aug 10 2016 Petr Lautrbach 2.5-5 +- Fix in tree compilation of utils that depend on libsepol + +* Mon Jun 27 2016 Petr Lautrbach - 2.5-4 +- Clarify is_selinux_mls_enabled() description +- Explain how to free policy type from selinux_getpolicytype() +- Compare absolute pathname in matchpathcon -V +- Add selinux_snapperd_contexts_path() +- Modify audit2why analyze function to use loaded policy +- Sort object files for deterministic linking order +- Respect CC and PKG_CONFIG environment variable +- Avoid mounting /proc outside of selinux_init_load_policy() +- Fix multiple spelling errors + +* Wed Apr 27 2016 Petr Lautrbach - 2.5-3 +- Fix setexecfilecon() to work better in a chroot (#1329931) +- Fix typo in sefcontext_compile.8 (#1320062) + +* Mon Apr 11 2016 Petr Lautrbach - 2.5-2 +- Fix location of selinuxfs mount point (#1321086) +- Only mount /proc if necessary +- procattr: return einval for <= 0 pid args +- procattr: return error on invalid pid_t inpu + +* Tue Feb 23 2016 Petr Lautrbach 2.5-1 +- Update to upstream release 2016-02-23 + * Fri Feb 14 2014 Dan Walsh - 2.2.2-6 - Add additional go bindings for get*con calls - Add go bindings test command