]> granicus.if.org Git - cronie/commitdiff
Add first selinux patch. Loading users through selinux scontext.
authormmaslano <mmaslano@redhat.com>
Fri, 17 Aug 2007 12:52:08 +0000 (14:52 +0200)
committermmaslano <mmaslano@redhat.com>
Fri, 17 Aug 2007 12:52:08 +0000 (14:52 +0200)
cron.h
database.c
do_command.c
funcs.h
structs.h
user.c

diff --git a/cron.h b/cron.h
index da6c850556fbfd37de5f5897b90186837a4e740d..f1b3671abed54c07827a19d6aaf51eae1a52aaf7 100644 (file)
--- a/cron.h
+++ b/cron.h
  */
 
 #define CRON_VERSION "V5.0"
+
+#ifdef WITH_SELINUX
+#include <selinux/selinux.h>
+#endif
+
 #include "config.h"
 #include "externs.h"
 #include "pathnames.h"
@@ -36,3 +41,4 @@
 #include "structs.h"
 #include "funcs.h"
 #include "globals.h"
+
index 828ef529bb01efa3b3c157a5960665b7bec46ff6..a920f1ca2064def656a9a464e706689c91a90ccd 100644 (file)
@@ -245,7 +245,7 @@ process_crontab(const char *uname, const char *fname, const char *tabname,
                free_user(u);
                log_it(fname, getpid(), "RELOAD", tabname);
        }
-       u = load_user(crontab_fd, pw, fname);
+       u = load_user(crontab_fd, pw, uname, fname, tabname);
        if (u != NULL) {
                u->mtime = statbuf->st_mtime;
                link_user(new_db, u);
index ed378fea907daf8b606b5cd5e13873b79d3da053..e24e0190611a60f480f2dee3744d2d47cd064c09 100644 (file)
@@ -265,6 +265,20 @@ child_process(entry *e, user *u) {
                                _exit(OK_EXIT);
                        }
 # endif /*DEBUGGING*/
+
+#ifdef WITH_SELINUX
+                       if (is_selinux_enabled() >0 ) {
+                               if (setexeccon(u->scontext) < 0) {
+                                       if (security_getenforce() > 0) {
+                                               fprintf(stderr, 
+                                                       "Could not set exec context to %s for user  %s\n", 
+                                                       u->scontext,u->name);
+                                               _exit(ERROR_EXIT);
+                                       }
+                               }
+                       }
+#endif
+
                        execle(shell, shell, "-c", e->cmd, (char *)0, e->envp);
                        fprintf(stderr, "execl: couldn't exec `%s'\n", shell);
                        perror("execl");
diff --git a/funcs.h b/funcs.h
index 06392810a9de905a725b5305e76e093369c5bdca..5d900c664e61bbef6bf37923b8e34e87ab99d91a 100644 (file)
--- a/funcs.h
+++ b/funcs.h
@@ -65,7 +65,7 @@ char          *env_get(char *, char **),
                **env_copy(char **),
                **env_set(char **, char *);
 
-user           *load_user(int, struct passwd *, const char *),
+user           *load_user(int, struct passwd *, const char *, const char *, const char *),
                *find_user(cron_db *, const char *);
 
 entry          *load_entry(FILE *, void (*)(), struct passwd *, char **);
index 47fc23816bf186772276b06e8704e6ea8a3d006b..fc09cd57e33af451ad09b9fc3499e92a6604ea7b 100644 (file)
--- a/structs.h
+++ b/structs.h
@@ -50,6 +50,9 @@ typedef       struct _user {
        char            *name;
        time_t          mtime;          /* last modtime of crontab */
        entry           *crontab;       /* this person's crontab */
+#ifdef WITH_SELINUX
+        security_context_t scontext;    /* SELinux security context */
+#endif
 } user;
 
 typedef        struct _cron_db {
diff --git a/user.c b/user.c
index 5221f8472a3b812af4cacaf1dfda22cba9f4439e..af89f8920135420c3a8a1437148599c6a4f1222d 100644 (file)
--- a/user.c
+++ b/user.c
@@ -26,8 +26,72 @@ static char rcsid[] = "$Id: user.c,v 1.5 2004/01/23 18:56:43 vixie Exp $";
 /* vix 26jan87 [log is in RCS file]
  */
 
+#ifdef WITH_SELINUX
+#include <selinux/selinux.h>
+#include <selinux/flask.h>
+#include <selinux/av_permissions.h>
+#endif
+
 #include "cron.h"
 
+#ifdef WITH_SELINUX
+static int get_security_context(char *name, 
+                                int crontab_fd, 
+                                security_context_t *rcontext, 
+                                char *tabname) {
+       security_context_t scontext;
+       security_context_t  file_context=NULL;
+       struct av_decision avd;
+       int retval=0;
+       *rcontext = NULL;
+       if (get_default_context(name, NULL, &scontext)) {
+               if (security_getenforce() > 0) {
+                       log_it(name, getpid(), "No SELinux security context",tabname);
+                       return -1;
+               } else {
+                       log_it(name, getpid(), "No security context but SELinux in permissive mode, continuing",tabname);
+               }
+       }
+       
+       if (fgetfilecon(crontab_fd, &file_context) < OK) {
+               if (security_getenforce() > 0) {
+                       log_it(name, getpid(), "getfilecon FAILED", tabname);
+                       freecon(scontext);
+                       return -1;
+               } else {
+                       log_it(name, getpid(), "getfilecon FAILED but SELinux in permissive mode, continuing", tabname);
+                       *rcontext=scontext;
+                       return 0;
+               }
+       }
+    
+       /*
+        * 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.
+        */
+       retval = security_compute_av(scontext,
+                                    file_context,
+                                    SECCLASS_FILE,
+                                    FILE__ENTRYPOINT,
+                                    &avd);
+       freecon(file_context);
+       if (retval || ((FILE__ENTRYPOINT & avd.allowed) != FILE__ENTRYPOINT)) {
+               if (security_getenforce() > 0) {
+                       log_it(name, getpid(), "ENTRYPOINT FAILED", tabname);
+                       freecon(scontext);
+                       return -1;
+               } else {
+                       log_it(name, getpid(), "ENTRYPOINT FAILED but SELinux in permissive mode, continuing", tabname);
+               }
+       }
+       *rcontext=scontext;
+       return 0;
+}
+#endif
+
 void
 free_user(user *u) {
        entry *e, *ne;
@@ -37,11 +101,14 @@ free_user(user *u) {
                ne = e->next;
                free_entry(e);
        }
+#ifdef WITH_SELINUX
+       freecon(u->scontext);
+#endif 
        free(u);
 }
 
 user *
-load_user(int crontab_fd, struct passwd        *pw, const char *name) {
+load_user(int crontab_fd, struct passwd        *pw, const char *uname, const char *fname, const char *tabname) {
        char envstr[MAX_ENVSTR];
        FILE *file;
        user *u;
@@ -60,7 +127,7 @@ load_user(int crontab_fd, struct passwd      *pw, const char *name) {
         */
        if ((u = (user *) malloc(sizeof(user))) == NULL)
                return (NULL);
-       if ((u->name = strdup(name)) == NULL) {
+       if ((u->name = strdup(fname)) == NULL) {
                save_errno = errno;
                free(u);
                errno = save_errno;
@@ -78,6 +145,22 @@ load_user(int crontab_fd, struct passwd     *pw, const char *name) {
                return (NULL);
        }
 
+#ifdef WITH_SELINUX
+       if (is_selinux_enabled() > 0) {
+               char *sname=uname;
+               if (pw==NULL) {
+                       sname="system_u";
+               }
+
+               if (get_security_context(sname, crontab_fd, 
+                                        &u->scontext, tabname) != 0) {
+                       free_user(u);
+                       u = NULL;
+                       goto done;
+               }
+       }
+#endif
+
        /* load the crontab
         */
        while ((status = load_env(envstr, file)) >= OK) {