All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2] Currently, jobs run by at are run in the crond_t domain and not transitioned outside of it.
@ 2015-07-15 23:06 Laurent Bigonville
  0 siblings, 0 replies; only message in thread
From: Laurent Bigonville @ 2015-07-15 23:06 UTC (permalink / raw)
  To: selinux; +Cc: 510466

From: Laurent Bigonville <bigon@bigon.be>

With this patch, the jobs are transitioned in the same domain as the
jobs that are run by the cron daemon:

- When cron_userdomain_transition is set to off, a process for an
  unconfined user will transition to unconfined_cronjob_t. For confined
  user, the job is run as cronjob_t.

- When cron_userdomain_transition is set to on, the processes are run
  under the user default context.

This patch is based on Marcela Mašláňová <mmaslano@redhat.com> work
---
 Makefile.in  |  3 ++-
 atd.c        | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 config.h.in  |  3 +++
 configure.ac |  8 ++++++
 daemon.c     | 16 +++++++++++
 daemon.h     |  3 +++
 6 files changed, 119 insertions(+), 1 deletion(-)

diff --git a/Makefile.in b/Makefile.in
index 5dd2767..2bddc13 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -40,6 +40,7 @@ LIBS		= @LIBS@
 LIBOBJS		= @LIBOBJS@
 INSTALL		= @INSTALL@
 PAMLIB          = @PAMLIB@
+SELINUXLIB      = @SELINUXLIB@
 
 CLONES		= atq atrm
 ATOBJECTS	= at.o panic.o perm.o posixtm.o y.tab.o lex.yy.o
@@ -73,7 +74,7 @@ at: $(ATOBJECTS)
 	$(LN_S) -f at atrm
 
 atd: $(RUNOBJECTS)
-	$(CC) $(LDFLAGS) -o atd $(RUNOBJECTS) $(LIBS) $(PAMLIB)
+	$(CC) $(LDFLAGS) -o atd $(RUNOBJECTS) $(LIBS) $(PAMLIB) $(SELINUXLIB)
 
 y.tab.c y.tab.h: parsetime.y
 	$(YACC) -d parsetime.y
diff --git a/atd.c b/atd.c
index d0b422e..e70caf0 100644
--- a/atd.c
+++ b/atd.c
@@ -83,6 +83,12 @@
 #include "getloadavg.h"
 #endif
 
+#ifdef WITH_SELINUX
+#include <selinux/selinux.h>
+#include <selinux/get_context_list.h>
+int selinux_enabled = 0;
+#endif
+
 /* Macros */
 
 #define BATCH_INTERVAL_DEFAULT 60
@@ -195,6 +201,72 @@ myfork()
 #define fork myfork
 #endif
 
+#ifdef WITH_SELINUX
+static int
+set_selinux_context(const char *name, const char *filename) {
+    security_context_t user_context = NULL;
+    security_context_t file_context = NULL;
+    int retval = 0;
+    char *seuser = NULL;
+    char *level = NULL;
+
+    if (getseuserbyname(name, &seuser, &level) == 0) {
+        retval = get_default_context_with_level(seuser, level, NULL, &user_context);
+        free(seuser);
+        free(level);
+        if (retval < 0) {
+            lerr("execle: couldn't get security context for user %s\n", name);
+            retval = -1;
+            goto err;
+        }
+    }
+
+    /*
+     * Since crontab files are not directly executed,
+     * crond must ensure that the crontab file has
+     * a context that is appropriate for the context of
+     * the user cron job.  It performs an entrypoint
+     * permission check for this purpose.
+     */
+    if (fgetfilecon(STDIN_FILENO, &file_context) < 0) {
+        lerr("fgetfilecon FAILED %s", filename);
+        retval = -1;
+        goto err;
+    }
+
+    retval = selinux_check_access(user_context, file_context, "file", "entrypoint", NULL);
+    freecon(file_context);
+    if (retval < 0) {
+        lerr("Not allowed to set exec context to %s for user  %s\n", user_context, name);
+        retval = -1;
+        goto err;
+    }
+    if (setexeccon(user_context) < 0) {
+        lerr("Could not set exec context to %s for user  %s\n", user_context, name);
+        retval = -1;
+        goto err;
+    }
+err:
+    if (retval < 0 && security_getenforce() != 1)
+        retval = 0;
+    if (user_context)
+        freecon(user_context);
+    return retval;
+}
+
+static int
+selinux_log_callback (int type, const char *fmt, ...)
+{
+    va_list ap;
+
+    va_start(ap, fmt);
+    vsyslog (LOG_ERR, fmt, ap);
+    va_end(ap);
+    return 0;
+}
+
+#endif
+
 static void
 run_file(const char *filename, uid_t uid, gid_t gid)
 {
@@ -424,6 +496,13 @@ run_file(const char *filename, uid_t uid, gid_t gid)
 
 	    nice((tolower((int) queue) - 'a' + 1) * 2);
 
+#ifdef WITH_SELINUX
+	    if (selinux_enabled > 0) {
+	        if (set_selinux_context(pentry->pw_name, filename) < 0)
+	            perr("SELinux Failed to set context\n");
+	    }
+#endif
+
 	    if (initgroups(pentry->pw_name, pentry->pw_gid))
 		perr("Cannot initialize the supplementary group access list");
 
@@ -707,6 +786,14 @@ main(int argc, char *argv[])
     struct passwd *pwe;
     struct group *ge;
 
+#ifdef WITH_SELINUX
+    selinux_enabled=is_selinux_enabled();
+
+    if (selinux_enabled) {
+        selinux_set_callback(SELINUX_CB_LOG, (union selinux_callback) selinux_log_callback);
+    }
+#endif
+
 /* We don't need root privileges all the time; running under uid and gid
  * daemon is fine.
  */
diff --git a/config.h.in b/config.h.in
index 4d7dc91..681d68e 100644
--- a/config.h.in
+++ b/config.h.in
@@ -192,6 +192,9 @@
    <sys/cpustats.h>. */
 #undef UMAX4_3
 
+/* Define if you are building with_selinux */
+#undef WITH_SELINUX
+
 /* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a
    `char[]'. */
 #undef YYTEXT_POINTER
diff --git a/configure.ac b/configure.ac
index f3d2e35..1f6494a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -239,6 +239,14 @@ AC_ARG_WITH(daemon_username,
 )
 AC_SUBST(DAEMON_USERNAME)
 
+AC_ARG_WITH(selinux,
+[ --with-selinux       Define to run with selinux],
+AC_DEFINE(WITH_SELINUX, 1, [Define if you are building with_selinux]),
+)
+AC_CHECK_LIB(selinux, is_selinux_enabled, SELINUXLIB=-lselinux)
+AC_SUBST(SELINUXLIB)
+AC_SUBST(WITH_SELINUX)
+
 AC_MSG_CHECKING(groupname to run under)
 AC_ARG_WITH(daemon_groupname,
 [ --with-daemon_groupname=DAEMON_GROUPNAME	Groupname to run under (default daemon) ],
diff --git a/daemon.c b/daemon.c
index 8be40d4..f9d25e7 100644
--- a/daemon.c
+++ b/daemon.c
@@ -83,6 +83,22 @@ perr(const char *fmt,...)
 }
 
 void
+lerr(const char *fmt,...)
+{
+    char buf[1024];
+    va_list args;
+
+    va_start(args, fmt);
+    vsnprintf(buf, sizeof(buf), fmt, args);
+    va_end(args);
+
+    if (daemon_debug) {
+	perror(buf);
+    } else
+	syslog(LOG_ERR, "%s: %m", buf);
+}
+
+void
 pabort(const char *fmt,...)
 {
     char buf[1024];
diff --git a/daemon.h b/daemon.h
index c4507ae..f44ccd1 100644
--- a/daemon.h
+++ b/daemon.h
@@ -13,5 +13,8 @@ __attribute__((noreturn))
 #endif
 perr (const char *fmt, ...);
 
+void
+lerr (const char *fmt, ...);
+
 extern int daemon_debug;
 extern int daemon_foreground;
-- 
2.1.4

^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2015-07-15 23:06 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-07-15 23:06 [PATCH v2] Currently, jobs run by at are run in the crond_t domain and not transitioned outside of it Laurent Bigonville

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.