PATCH selinux for udev
Daniel Walsh's working selinux patch
selinux.h new file +131 -0
@@ -0,0 +1,131 @@ +#ifndef SELINUX_H +#define SELINUX_H + +#ifndef USE_SELINUX + +static inline void selinux_setfilecon (char *file,unsigned int mode) { } +static inline void selinux_setfscreatecon (char *file,unsigned int mode) {} +static inline void selinux_init (void ) {} +static inline void selinux_restore (void ) {} + +#else + +#include <selinux/selinux.h> +#include <stdio.h> +#include <limits.h> +#include <ctype.h> + + +static int selinux_enabled=-1 ; +static security_context_t prev_scontext=NULL ; + +static inline int is_selinux_running (void ) { +if ( selinux_enabled==-1 ) +return selinux_enabled=is_selinux_enabled ()>0 ; +return selinux_enabled; +} + +static inline int selinux_get_media (char *path,int mode,char **media) +{ +FILE *fp; +char buf[PATH_MAX ]; +char mediabuf[PATH_MAX ]; + *media=NULL ; +if (!( mode &&S_IFBLK )) { +return -1 ; + } +snprintf (buf,sizeof (buf),"/proc/ide/%s/media" ,basename (path)); + fp=fopen (buf,"r" ); +if (fp) { +if (fgets (mediabuf,sizeof (mediabuf), fp)) { +int size=strlen (mediabuf); +while (size-- >0 ) { +if (isspace (mediabuf[size])) { + mediabuf[size]='\0' ; + }else { +break ; + } + } + *media=strdup (mediabuf); +info ("selinux_get_media(%s)->%s \n" , path, *media); + } +fclose (fp); +return 0 ; + }else { +return -1 ; + } +} + +static inline void selinux_setfilecon (char *file,unsigned int mode) { +if (is_selinux_running ()) { +security_context_t scontext=NULL ; +char *media; +int ret=selinux_get_media (file, mode, &media); +if ( ret==0 ) { + ret =matchmediacon (media, &scontext); +free (media); + } +if (ret==-1 ) +if (matchpathcon (file, mode, &scontext) <0 ) { +dbg ("matchpathcon(%s) failed\n" , file); +return ; + } +if (setfilecon (file, scontext) <0 ) +dbg ("setfiles %s failed with error '%s'" , + file,strerror (errno)); +freecon (scontext); + } +} + +static inline void selinux_setfscreatecon (char *file,unsigned int mode) { +int retval =0 ; +security_context_t scontext=NULL ; + +if (is_selinux_running ()) { +char *media; +int ret=selinux_get_media (file, mode, &media); +if ( ret==0 ) { + ret =matchmediacon (media, &scontext); +free (media); + } + +if (ret==-1 ) +if (matchpathcon (file, mode, &scontext) <0 ) { +dbg ("matchpathcon(%s) failed\n" , file); +return ; + } + + retval=setfscreatecon (scontext); +if (retval <0 ) +dbg ("setfiles %s failed with error '%s'" , + file,strerror (errno)); +freecon (scontext); + } +} +static inline void selinux_init (void ) { +/* record the present security context, for file-creation +* restoration creation purposes. +* +*/ + +if (is_selinux_running ()) + { +if (getfscreatecon (&prev_scontext) <0 ) { +dbg ("getfscreatecon failed\n" ); + } + prev_scontext=NULL ; + } +} +static inline void selinux_restore (void ) { +if (is_selinux_running ()) { +/* reset the file create context to its former glory */ +if (setfscreatecon (prev_scontext) <0 ) +dbg ("setfscreatecon failed\n" ); +if (prev_scontext) { +freecon (prev_scontext); + prev_scontext=NULL ; + } + } +} +#endif /* USE_SELINUX */ +#endif /* SELINUX_H */
Makefile renamed from Makefile.selinux +8 -0
@@ -25,6 +25,8 @@ # Leave this set to `false' for production use. DEBUG = false +# Set this to compile with Security-Enhanced Linux support. +USE_SELINUX = true ROOT = udev DAEMON = udevd
@@ -172,6 +174,11 @@ CFLAGS += -I$(PWD)/libsysfs +ifeq ($(strip $(USE_SELINUX)),true) + CFLAGS += -DUSE_SELINUX + LIB_OBJS += -lselinux +endif + all: $(ROOT) $(SENDER) $(DAEMON) $(INFO) $(TESTER) @extras="$(EXTRAS)" ; for target in $$extras ; do \ echo $$target ; \
@@ -216,6 +223,7 @@ udevdb.h \ klibc_fixups.h \ logging.h \ + selinux.h \ list.h ifeq ($(strip $(USE_KLIBC)),true)
udev-add.c renamed from udev-add.c.selinux +10 -0
@@ -50,6 +50,8 @@#define LOCAL_USER "$local" +#include "selinux.h" +/* * Right now the major/minor of a device is stored in a file called * "dev" in sysfs.
@@ -92,6 +94,7 @@break ; *pos =0x00 ;if (stat (p, &stats)) { +selinux_setfscreatecon (p,S_IFDIR ); retval =mkdir (p,0755 );if (retval !=0 ) { dbg("mkdir(%s) failed with error '%s'",
@@ -99,6 +102,8 @@return retval; }dbg ("created '%s'" , p); + }else { +selinux_setfilecon (p,S_IFDIR ); } *pos ='/' ; }
@@ -117,6 +122,7 @@if (((stats.st_mode &S_IFMT ) ==S_IFBLK || (stats.st_mode &S_IFMT ) ==S_IFCHR ) && (stats.st_rdev ==makedev (major, minor))) {dbg ("preserve file '%s', cause it has correct dev_t" , file); +selinux_setfilecon (file,stats.st_mode); goto perms; }
@@ -126,6 +132,7 @@dbg ("already present file '%s' unlinked" , file); create: +selinux_setfscreatecon (file, mode); retval =mknod (file, mode,makedev (major, minor));if (retval !=0 ) { dbg("mknod(%s, %#o, %u, %u) failed with error '%s'",
@@ -304,6 +311,7 @@dbg ("symlink(%s, %s)" , linktarget, filename);if (!fake) { +selinux_setfscreatecon (filename,S_IFLNK );unlink (filename);if (symlink (linktarget, filename) !=0 ) dbg("symlink(%s, %s) failed with error '%s'",
@@ -438,6 +446,7 @@dbg ("name='%s'" , dev.name); +selinux_init ();switch (dev.type) {case 'b' :case 'c' :
@@ -475,6 +484,7 @@ } exit: +selinux_restore ();sysfs_close_class_device (class_dev);return retval;