Re: [PATCH] Add SELinux support to run jobs in the proper domain

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 07/09/2015 07:42 AM, Laurent Bigonville wrote:
> From: Marcela Mašláňová <mmaslano@xxxxxxxxxx>
> 
> 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 <bigon@xxxxxxxx>
> ---
>  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) ],
> 

_______________________________________________
Selinux mailing list
Selinux@xxxxxxxxxxxxx
To unsubscribe, send email to Selinux-leave@xxxxxxxxxxxxx.
To get help, send an email containing "help" to Selinux-request@xxxxxxxxxxxxx.




[Index of Archives]     [Selinux Refpolicy]     [Linux SGX]     [Fedora Users]     [Fedora Desktop]     [Yosemite Photos]     [Yosemite Camping]     [Yosemite Campsites]     [KDE Users]     [Gnome Users]

  Powered by Linux