On 07/09/2015 07:42 AM, Laurent Bigonville wrote:
> From: Marcela Mašláňová <[email protected]>
>
> Currently, jobs run by at are run in the crond_t domain and not
> transitioned outside of it.
>
> 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.
>
> Tested-by: Laurent Bigonville <[email protected]>
> ---
> Makefile.in | 3 ++-
> atd.c | 81
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> config.h.in | 3 +++
> configure.ac | 8 ++++++
> 4 files changed, 94 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..55f6f8d 100644
> --- a/atd.c
> +++ b/atd.c
> @@ -83,6 +83,14 @@
> #include "getloadavg.h"
> #endif
>
> +#ifdef WITH_SELINUX
> +#include <selinux/selinux.h>
> +#include <selinux/get_context_list.h>
> +int selinux_enabled=0;
> +#include <selinux/flask.h>
> +#include <selinux/av_permissions.h>
Use of these headers (flask.h and av_permissions.h) is deprecated.
See below.
> +#endif
> +
> /* Macros */
>
> #define BATCH_INTERVAL_DEFAULT 60
> @@ -195,6 +203,68 @@ 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;
> + struct av_decision avd;
> + int retval=-1;
> + 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) {
> + if (security_getenforce()==1) {
> + perr("execle: couldn't get security context
> for user %s\n", name);
> + } else {
> + syslog(LOG_ERR, "execle: couldn't get
> security context for user %s\n", name);
> + return -1;
> + }
> + }
> + }
> +
> + /*
> + * 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)
> + perr("fgetfilecon FAILED %s", filename);
> +
> + retval = security_compute_av(user_context,
> + file_context,
> + SECCLASS_FILE,
> + FILE__ENTRYPOINT,
> + &avd);
> + freecon(file_context);
> + if (retval || ((FILE__ENTRYPOINT & avd.allowed) != FILE__ENTRYPOINT))
> {
> + if (security_getenforce()==1) {
> + perr("Not allowed to set exec context to %s for user
> %s\n", user_context,name);
> + } else {
> + syslog(LOG_ERR, "Not allowed to set exec context to
> %s for user %s\n", user_context,name);
> + retval = -1;
> + goto err;
> + }
> + }
Please switch to using selinux_check_access() rather than
security_compute_av() in new code. This handles dynamically looking up
the "file" class and "entrypoint" permission values, checks and uses
security_deny_unknown() to handle unknown classes/permissions, uses the
AVC, checks enforcing mode (both global and per-domain), and ensures
that denials are audited/logged in a standardized format. You will also
want to use selinux_set_callback(SELINUX_CB_LOG, ...) and possibly
selinux_set_callback(SELINUX_CB_AUDIT, ...) to redirect the logging to
your preferred destination and to supply any auxiliary audit data in the
message.
> + if (setexeccon(user_context) < 0) {
> + if (security_getenforce()==1) {
> + perr("Could not set exec context to %s for user
> %s\n", user_context,name);
> + retval = -1;
> + } else {
> + syslog(LOG_ERR, "Could not set exec context to %s for
> user %s\n", user_context,name);
> + }
> + }
> + err:
> + freecon(user_context);
> + return 0;
> +}
> +#endif
> +
> static void
> run_file(const char *filename, uid_t uid, gid_t gid)
> {
> @@ -424,6 +494,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 +784,10 @@ main(int argc, char *argv[])
> struct passwd *pwe;
> struct group *ge;
>
> +#ifdef WITH_SELINUX
> + selinux_enabled=is_selinux_enabled();
> +#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) ],
>
--
To UNSUBSCRIBE, email to [email protected]
with a subject of "unsubscribe". Trouble? Contact [email protected]