From 2c3aaeae1e599e3b81f7dcc70846d8a34ef38bd2 Mon Sep 17 00:00:00 2001 From: Dan Walsh Date: May 25 2011 18:25:56 +0000 Subject: Move /selinux to /sys/fs/selinux Add selinuxexeccon Add realpath to matchpathcon to handle matchpathcon * type queries. --- diff --git a/libselinux-rhat.patch b/libselinux-rhat.patch index 3051b12..52ceb43 100644 --- a/libselinux-rhat.patch +++ b/libselinux-rhat.patch @@ -1,3 +1,33 @@ +diff --git a/libselinux/man/man8/selinuxexeccon.8 b/libselinux/man/man8/selinuxexeccon.8 +new file mode 100644 +index 0000000..6482d74 +--- /dev/null ++++ b/libselinux/man/man8/selinuxexeccon.8 +@@ -0,0 +1,24 @@ ++.TH "selinuxexeccon" "1" "14 May 2011" "dwalsh@redhat.com" "SELinux Command Line documentation" ++.SH "NAME" ++selinuxexeccon \- report SELinux context used for this executable ++ ++.SH "SYNOPSIS" ++.B selinuxexeccon command [ fromcon] o ++ ++.SH "DESCRIPTION" ++.B selinuxexeccon ++reports the SELinux process context for the specified command from the specified context or the current context. ++ ++.SH EXAMPLE ++# selinuxexeccon /usr/bin/passwd ++staff_u:staff_r:passwd_t:s0-s0:c0.c1023 ++ ++.br ++# selinuxexeccon /usr/sbin/sendmail system_u:system_r:httpd_t:s0 ++system_u:system_r:system_mail_t:s0 ++ ++.SH AUTHOR ++This manual page was written by Dan Walsh . ++ ++.SH "SEE ALSO" ++secon(8) diff --git a/libselinux/src/Makefile b/libselinux/src/Makefile index bf665ab..ccd08ae 100644 --- a/libselinux/src/Makefile @@ -174,6 +204,204 @@ index b245364..7c47222 100644 va_start(ap, fmt); rc = vfprintf(stderr, fmt, ap); va_end(ap); +diff --git a/libselinux/src/enabled.c b/libselinux/src/enabled.c +index b3c8c47..018c787 100644 +--- a/libselinux/src/enabled.c ++++ b/libselinux/src/enabled.c +@@ -11,10 +11,6 @@ + + int is_selinux_enabled(void) + { +- char *buf=NULL; +- FILE *fp; +- ssize_t num; +- size_t len; + int enabled = 0; + security_context_t con; + +@@ -32,37 +28,8 @@ int is_selinux_enabled(void) + enabled = 0; + freecon(con); + } +- return enabled; + } + +- /* Drop back to detecting it the long way. */ +- fp = fopen("/proc/filesystems", "r"); +- if (!fp) +- return -1; +- +- __fsetlocking(fp, FSETLOCKING_BYCALLER); +- while ((num = getline(&buf, &len, fp)) != -1) { +- if (strstr(buf, "selinuxfs")) { +- enabled = 1; +- break; +- } +- } +- +- if (num < 0) +- goto out; +- +- /* Since an selinux file system is available, we consider +- * selinux enabled. If getcon_raw fails, selinux is still +- * enabled. We only consider it disabled if no policy is loaded. */ +- if (getcon_raw(&con) == 0) { +- if (!strcmp(con, "kernel")) +- enabled = 0; +- freecon(con); +- } +- +- out: +- free(buf); +- fclose(fp); + return enabled; + } + +diff --git a/libselinux/src/init.c b/libselinux/src/init.c +index a948920..dd03559 100644 +--- a/libselinux/src/init.c ++++ b/libselinux/src/init.c +@@ -7,6 +7,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -20,12 +21,41 @@ char *selinux_mnt = NULL; + int selinux_page_size = 0; + int obj_class_compat = 1; + ++/* Verify the mount point for selinux file system has a selinuxfs. ++ If the file system: ++ * Exist, ++ * Is mounted with an selinux file system, ++ * The file system is read/write ++ * then set this as the default file system. ++*/ ++static int verify_selinuxmnt(char *mnt) ++{ ++ struct statfs sfbuf; ++ int rc; ++ ++ do { ++ rc = statfs(mnt, &sfbuf); ++ } while (rc < 0 && errno == EINTR); ++ if (rc == 0) { ++ if ((uint32_t)sfbuf.f_type == (uint32_t)SELINUX_MAGIC) { ++ struct statvfs vfsbuf; ++ rc = statvfs(mnt, &vfsbuf); ++ if (rc == 0) { ++ if (!(vfsbuf.f_flag & ST_RDONLY)) { ++ set_selinuxmnt(mnt); ++ } ++ return 0; ++ } ++ } ++ } ++ ++ return -1; ++} ++ + static void init_selinuxmnt(void) + { + char *buf=NULL, *p; + FILE *fp=NULL; +- struct statfs sfbuf; +- int rc; + size_t len; + ssize_t num; + int exists = 0; +@@ -33,17 +63,9 @@ static void init_selinuxmnt(void) + if (selinux_mnt) + return; + +- /* We check to see if the preferred mount point for selinux file +- * system has a selinuxfs. */ +- do { +- rc = statfs(SELINUXMNT, &sfbuf); +- } while (rc < 0 && errno == EINTR); +- if (rc == 0) { +- if ((uint32_t)sfbuf.f_type == (uint32_t)SELINUX_MAGIC) { +- selinux_mnt = strdup(SELINUXMNT); +- return; +- } +- } ++ if (verify_selinuxmnt(SELINUXMNT) == 0) return; ++ ++ if (verify_selinuxmnt(OLDSELINUXMNT) == 0) return; + + /* Drop back to detecting it the long way. */ + fp = fopen("/proc/filesystems", "r"); +@@ -52,7 +74,7 @@ static void init_selinuxmnt(void) + + __fsetlocking(fp, FSETLOCKING_BYCALLER); + while ((num = getline(&buf, &len, fp)) != -1) { +- if (strstr(buf, "selinuxfs")) { ++ if (strstr(buf, SELINUXFS)) { + exists = 1; + break; + } +@@ -79,7 +101,7 @@ static void init_selinuxmnt(void) + tmp = strchr(p, ' '); + if (!tmp) + goto out; +- if (!strncmp(tmp + 1, "selinuxfs ", 10)) { ++ if (!strncmp(tmp + 1, SELINUXFS" ", strlen(SELINUXFS)+1)) { + *tmp = '\0'; + break; + } +@@ -87,7 +109,7 @@ static void init_selinuxmnt(void) + + /* If we found something, dup it */ + if (num > 0) +- selinux_mnt = strdup(p); ++ verify_selinuxmnt(p); + + out: + free(buf); +diff --git a/libselinux/src/load_policy.c b/libselinux/src/load_policy.c +index 83d2143..0961912 100644 +--- a/libselinux/src/load_policy.c ++++ b/libselinux/src/load_policy.c +@@ -369,7 +369,17 @@ int selinux_init_load_policy(int *enforce) + * Check for the existence of SELinux via selinuxfs, and + * mount it if present for use in the calls below. + */ +- if (mount("selinuxfs", SELINUXMNT, "selinuxfs", 0, 0) < 0 && errno != EBUSY) { ++ char *mntpoint = NULL; ++ if (mount(SELINUXFS, SELINUXMNT, SELINUXFS, 0, 0) == 0 || errno == EBUSY) { ++ mntpoint = SELINUXMNT; ++ } else { ++ /* check old mountpoint */ ++ if (mount(SELINUXFS, OLDSELINUXMNT, SELINUXFS, 0, 0) == 0 || errno == EBUSY) { ++ mntpoint = OLDSELINUXMNT; ++ } ++ } ++ ++ if (! mntpoint ) { + if (errno == ENODEV) { + /* + * SELinux was disabled in the kernel, either +@@ -385,7 +395,7 @@ int selinux_init_load_policy(int *enforce) + + goto noload; + } +- set_selinuxmnt(SELINUXMNT); ++ set_selinuxmnt(mntpoint); + + /* + * Note: The following code depends on having selinuxfs +@@ -397,7 +407,7 @@ int selinux_init_load_policy(int *enforce) + rc = security_disable(); + if (rc == 0) { + /* Successfully disabled, so umount selinuxfs too. */ +- umount(SELINUXMNT); ++ umount(selinux_mnt); + fini_selinuxmnt(); + } + /* diff --git a/libselinux/src/matchpathcon.c b/libselinux/src/matchpathcon.c index 5fd8fe4..da5cab9 100644 --- a/libselinux/src/matchpathcon.c @@ -195,6 +423,27 @@ index 5fd8fe4..da5cab9 100644 va_end(ap); } +diff --git a/libselinux/src/policy.h b/libselinux/src/policy.h +index 10e8712..bf270b5 100644 +--- a/libselinux/src/policy.h ++++ b/libselinux/src/policy.h +@@ -9,11 +9,15 @@ + /* Initial length guess for getting contexts. */ + #define INITCONTEXTLEN 255 + ++/* selinux file system type */ ++#define SELINUXFS "selinuxfs" ++ + /* selinuxfs magic number */ + #define SELINUX_MAGIC 0xf97cff8c + + /* Preferred selinux mount location */ +-#define SELINUXMNT "/selinux" ++#define SELINUXMNT "/sys/fs/selinux" ++#define OLDSELINUXMNT "/selinux" + + /* selinuxfs mount point */ + extern char *selinux_mnt; diff --git a/libselinux/src/selinux.py b/libselinux/src/selinux.py index fd63a4f..248048a 100644 --- a/libselinux/src/selinux.py @@ -1375,3 +1624,199 @@ index e0884f6..b131d2e 100644 SWIG_Python_SetConstant(d, "SELINUX_AVD_FLAGS_PERMISSIVE",SWIG_From_int((int)(0x0001))); SWIG_Python_SetConstant(d, "SELINUX_CB_LOG",SWIG_From_int((int)(0))); SWIG_Python_SetConstant(d, "SELINUX_CB_AUDIT",SWIG_From_int((int)(1))); +diff --git a/libselinux/utils/matchpathcon.c b/libselinux/utils/matchpathcon.c +index 4453a88..f1fe506 100644 +--- a/libselinux/utils/matchpathcon.c ++++ b/libselinux/utils/matchpathcon.c +@@ -8,6 +8,49 @@ + #include + #include + #include ++#include ++#include ++ ++ ++static int symlink_realpath(char *name, char *path) ++{ ++ char *p = NULL, *file_sep; ++ char *tmp_path = strdupa(name); ++ size_t len = 0; ++ ++ if (!tmp_path) { ++ fprintf(stderr, "strdupa on %s failed: %s\n", name, ++ strerror(errno)); ++ return -1; ++ } ++ file_sep = strrchr(tmp_path, '/'); ++ if (file_sep == tmp_path) { ++ file_sep++; ++ p = strcpy(path, ""); ++ } else if (file_sep) { ++ *file_sep = 0; ++ file_sep++; ++ p = realpath(tmp_path, path); ++ } else { ++ file_sep = tmp_path; ++ p = realpath("./", path); ++ } ++ if (p) ++ len = strlen(p); ++ if (!p || len + strlen(file_sep) + 2 > PATH_MAX) { ++ fprintf(stderr, "symlink_realpath(%s) failed %s\n", name, ++ strerror(errno)); ++ return -1; ++ } ++ p += len; ++ /* ensure trailing slash of directory name */ ++ if (len == 0 || *(p - 1) != '/') { ++ *p = '/'; ++ p++; ++ } ++ strcpy(p, file_sep); ++ return 0; ++} + + void usage(const char *progname) + { +@@ -103,49 +146,66 @@ int main(int argc, char **argv) + } + } + for (i = optind; i < argc; i++) { ++ char lnkpath[PATH_MAX + 1]; + int mode = 0; + struct stat buf; ++ char *newpath = NULL; ++ char *path; + int len = strlen(argv[i]); + if (len > 1 && argv[i][len - 1 ] == '/') { + argv[i][len - 1 ] = '\0'; + } + +- if (lstat(argv[i], &buf) == 0) ++ if (lstat(argv[i], &buf) == 0) { + mode = buf.st_mode; ++ } ++ ++ path = argv[i]; ++ if (S_ISLNK(mode)) { ++ int rc = symlink_realpath(argv[i], lnkpath); ++ if (rc >= 0) { ++ path = lnkpath; ++ } ++ } else { ++ if ((newpath = realpath(argv[i], NULL))) { ++ path = newpath; ++ } ++ } + + if (verify) { + if (quiet) { +- if (selinux_file_context_verify(argv[i], mode)) ++ if (selinux_file_context_verify(path, mode)) + continue; + else + exit(1); + } +- if (selinux_file_context_verify(argv[i], mode)) { +- printf("%s verified.\n", argv[i]); ++ if (selinux_file_context_verify(path, mode)) { ++ printf("%s verified.\n", path); + } else { + security_context_t con; + int rc; + error = 1; + if (notrans) +- rc = lgetfilecon_raw(argv[i], &con); ++ rc = lgetfilecon_raw(path, &con); + else +- rc = lgetfilecon(argv[i], &con); ++ rc = lgetfilecon(path, &con); + + if (rc >= 0) { + printf("%s has context %s, should be ", + argv[i], con); +- printmatchpathcon(argv[i], 0, mode); ++ printmatchpathcon(path, 0, mode); + freecon(con); + } else { + printf + ("actual context unknown: %s, should be ", + strerror(errno)); +- printmatchpathcon(argv[i], 0, mode); ++ printmatchpathcon(path, 0, mode); + } + } + } else { +- error |= printmatchpathcon(argv[i], header, mode); ++ error |= printmatchpathcon(path, header, mode); + } ++ free(newpath); newpath = NULL; + } + matchpathcon_fini(); + return error; +diff --git a/libselinux/utils/selinuxexeccon.c b/libselinux/utils/selinuxexeccon.c +new file mode 100644 +index 0000000..c55fde9 +--- /dev/null ++++ b/libselinux/utils/selinuxexeccon.c +@@ -0,0 +1,60 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++void usage(char *name, char *detail, int rc) ++{ ++ fprintf(stderr, "usage: %s command [ fromcon ]\n", name); ++ if (detail) ++ fprintf(stderr, "%s: %s\n", name, detail); ++ exit(rc); ++} ++ ++static security_context_t get_selinux_proc_context(const char *command, security_context_t execcon) { ++ security_context_t fcon = NULL, newcon = NULL; ++ ++ int ret = getfilecon(command, &fcon); ++ if (ret < 0) goto err; ++ ret = security_compute_create(execcon, fcon, SECCLASS_PROCESS, &newcon); ++ if (ret < 0) goto err; ++ ++err: ++ freecon(fcon); ++ return newcon; ++} ++ ++int main(int argc, char **argv) ++{ ++ int ret = -1; ++ security_context_t proccon = NULL, con = NULL; ++ if (argc < 2 || argc > 3) ++ usage(argv[0], "Invalid number of arguments", -1); ++ ++ if (argc == 2) { ++ if (getcon(&con) < 0) { ++ perror(argv[0]); ++ return -1; ++ } ++ } else { ++ con = strdup(argv[2]); ++ } ++ ++ proccon = get_selinux_proc_context(argv[1], con); ++ if (proccon) { ++ printf("%s\n", proccon); ++ ret = 0; ++ } else { ++ perror(argv[0]); ++ } ++ ++ free(proccon); ++ free(con); ++ return ret; ++} diff --git a/libselinux.spec b/libselinux.spec index 9d49eda..65df21a 100644 --- a/libselinux.spec +++ b/libselinux.spec @@ -7,7 +7,7 @@ Summary: SELinux library and simple utilities Name: libselinux Version: 2.0.102 -Release: 4%{?dist} +Release: 5%{?dist} License: Public Domain Group: System Environment/Libraries Source: http://www.nsa.gov/research/selinux/%{name}-%{version}.tgz @@ -198,6 +198,7 @@ exit 0 %{_sbindir}/matchpathcon %{_sbindir}/selinuxconlist %{_sbindir}/selinuxdefcon +%{_sbindir}/selinuxexeccon %{_sbindir}/selinuxenabled %{_sbindir}/setenforce %{_sbindir}/togglesebool @@ -236,6 +237,11 @@ exit 0 %{ruby_sitearch}/selinux.so %changelog +* Fri Apr 29 2011 Dan Walsh - 2.0.102-5 +- Move /selinux to /sys/fs/selinux +- Add selinuxexeccon +- Add realpath to matchpathcon to handle matchpathcon * type queries. + * Thu Apr 21 2011 Dan Walsh - 2.0.102-4 - Update for latest libsepol