Move /selinux to /sys/fs/selinux

Add selinuxexeccon
Add realpath to matchpathcon to handle matchpathcon * type queries.
This commit is contained in:
Dan Walsh 2011-05-25 14:25:56 -04:00
parent 71e7978d45
commit 2c3aaeae1e
2 changed files with 452 additions and 1 deletions

View File

@ -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 <dwalsh@redhat.com>.
+
+.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 <stdio.h>
#include <stdio_ext.h>
#include <dlfcn.h>
+#include <sys/statvfs.h>
#include <sys/vfs.h>
#include <stdint.h>
#include <limits.h>
@@ -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 <sys/stat.h>
#include <sys/errno.h>
#include <selinux/selinux.h>
+#include <limits.h>
+#include <stdlib.h>
+
+
+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 <unistd.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <ctype.h>
+#include <selinux/flask.h>
+#include <selinux/selinux.h>
+
+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;
+}

View File

@ -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 <dwalsh@redhat.com> - 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 <dwalsh@redhat.com> - 2.0.102-4
- Update for latest libsepol