Fedora and udev

Luke Kenneth Casson Leighton lkcl at lkcl.net
Sun Aug 22 14:40:16 UTC 2004


On Sun, Aug 22, 2004 at 09:25:38PM +1000, Russell Coker wrote:
> It seems that udev is now virtually mandatory as of the latest rawhide update.
> 
> udev uses ramfs for /tmp, ramfs (as of the latest Fedora kernel 2.6.8-1.525) 
> has no support for file labelling and breaks everything.
> 
> Can we get ramfs labelling working in the next few days or do we have to 
> change things to not depend on udev?
 
 chris pebenito of gentoo/hardened i believe has written a ramfs patch
 already (2.6.6)

 it was what i based the shmfs one off of.

 or maybe that's the other way round, i dunno.  can't remember.


 remember that just getting ramfs / tmpfs working is not enough, you
 must also:

 - patch selinux/hooks.c to allow mount -o fscontext=system_u:object_r:device_t
   on a tmpfs or shmfs or add an extra option to hooks.c _similar_ to
   fscontext but without the bit that says "stop if this filesystem
   supports xattrs".

 - modify /etc/init.d/udev to then mount /dev with the default context
   of device_t which whill FAIL if you DO NOT patch hooks.c as above:

    mount -n -o
	   fscontext=system_u:object_r:device_t,size=$tmpfs_size,mode=0755
	   -t tmpfs none /dev

 - add in an equivalent of my extra post-udev-and-hotplug duplicate of
   /etc/init.d/modutils that will load things like nvidia, ppp_generic
   and stuff that are not yet fully 2.6-compliant drivers (i.e. they
   don't grok /sys and consequently don't generate hotplug events) .

   i assume that rawhide, given that it is using udev already, is
   perfectly capable of doing a proper and far superior job to what
   i have hacked up.

 - run a restorecon on ALL DEVICE NODES CREATED PRIOR TO /etc/init.d/udev
   RUNNING.

   i got bored of doing this regularly and manually and so wrote a
   small script (/sbin/restoredevicefiles) which does this for me.
   badly.  it uses ls (really must use commands NOT from /usr and must
   use commands that DO NOT a require /dev/null or access to /dev/fd/*)

   i believe i had to copy cut from /usr/bin/cut to /bin/cut (!!) hey
   there are probably people out there who could do this as c-code
   or with sed or something more appropriate, to be honest i haven't
   got time to DoItRight(tm) so the ItWorksForMe(tm) approach is fine
   for me until _someone else_ does the DoItRight(tm) approach.

 - udev, udevd _and_ udevsend (_why_ is udev split into three separate
   programs??????) _all_ need to be hacked up to run setfiles -q -s on a
   pipe which udev(d?) will communicate the name of the inode to.

   russell advised me that using popen would be suitable for this:
   however i am not sure whether it should be put in udev or in
   udevd and i haven't the TimeRightNow(tm) to focus on
   MakingItNice(tm)

   alternatively, a patch (also attached) to add selinux "restorecon"
   stuff to udevsend is included which, although it still has a 1/4
   second delay per inode added, at least works.

   patch is against udev-0.030.  udev-0.030 has had the
   /etc/udev.d/default/selinux script removed which is a complete pain
   but hey, if linux-hotplug-devel say it don't work, it don't work.


 it's taken me about three maybe four weeks to get this hacked up to
 a working / reasonably acceptable (for me at least) point.

 i'm assuming that you would like the kernel patches: if you would like
 me to place a copy of my hacked-up policy files at hands.com/~lkcl/selinux
 please let me know because they are not very pretty but will save you a
 lot of time: because i don't know any better it has taken me somewhere
 in excess of 100 reboots to get a working udev-tmpfs-enabled policy
 plus initscripts hacks.

 if someone can inform me of the appropriate cvs-based diff
 command that will allow me to include fs/ramfs/xattr.c
 and fs/ramfs/xattr-security.c in the patch i would be most
 grateful, otherwise people will just have to manually blat
 those two files (attached) into the appropriate locations.

 i'd _really_ appreciate it if people _could_ say "hey, yes, we
 really need tmpfs-enabled udev in fc" because then i wouldn't
 have so much crap hanging around on my debian/selinux system:
 i'd far rather it had already been done and i could have
 copied or relied on the work of more experienced individuals.

 l.

-------------- next part --------------
Index: fs/Kconfig
===================================================================
RCS file: /cvsroot/selinux/nsa/linux-2.6/fs/Kconfig,v
retrieving revision 1.8
diff -u -u -r1.8 Kconfig
--- fs/Kconfig	18 Jun 2004 20:37:21 -0000	1.8
+++ fs/Kconfig	22 Aug 2004 14:06:10 -0000
@@ -925,6 +925,27 @@
 
 	  See <file:Documentation/filesystems/tmpfs.txt> for details.
 
+config TMPFS_FS_XATTR
+	bool "tmpfs Extended Attributes"
+	help
+	  Extended attributes are name:value pairs associated with inodes by
+	  the kernel or by users (see the attr(5) manual page, or visit
+	  <http://acl.bestbits.at/> for details).
+
+	  If unsure, say N.
+
+config TMPFS_FS_SECURITY
+	bool "tmpfs Security Labels"
+	depends on TMPFS_FS_XATTR
+	help
+	  Security labels support alternative access control models
+	  implemented by security modules like SELinux.  This option
+	  enables an extended attribute handler for file security
+	  labels in the tmpfs filesystem.
+
+	  If you are not using a security module that requires using
+	  extended attributes for file security labels, say N.
+
 config HUGETLBFS
 	bool "HugeTLB file system support"
 	depends X86 || IA64 || PPC64 || SPARC64 || SUPERH || X86_64 || BROKEN
Index: fs/ramfs/Makefile
===================================================================
RCS file: /cvsroot/selinux/nsa/linux-2.6/fs/ramfs/Makefile,v
retrieving revision 1.1.1.1
diff -u -u -r1.1.1.1 Makefile
--- fs/ramfs/Makefile	14 Aug 2003 12:08:40 -0000	1.1.1.1
+++ fs/ramfs/Makefile	22 Aug 2004 14:06:10 -0000
@@ -5,3 +5,6 @@
 obj-$(CONFIG_RAMFS) += ramfs.o
 
 ramfs-objs := inode.o
+ramfs-$(CONFIG_RAMFS_FS_XATTR)    += xattr.o
+ramfs-$(CONFIG_RAMFS_FS_SECURITY) += xattr_security.o
+
Index: fs/ramfs/inode.c
===================================================================
RCS file: /cvsroot/selinux/nsa/linux-2.6/fs/ramfs/inode.c,v
retrieving revision 1.1.1.4
diff -u -u -r1.1.1.4 inode.c
--- fs/ramfs/inode.c	18 Jun 2004 19:30:21 -0000	1.1.1.4
+++ fs/ramfs/inode.c	22 Aug 2004 14:06:11 -0000
@@ -31,6 +31,7 @@
 #include <linux/string.h>
 #include <linux/smp_lock.h>
 #include <linux/backing-dev.h>
+#include "xattr.h"
 
 #include <asm/uaccess.h>
 
@@ -157,6 +158,10 @@
 
 static struct inode_operations ramfs_file_inode_operations = {
 	.getattr	= simple_getattr,
+	.setxattr   = ramfs_setxattr,
+	.getxattr   = ramfs_getxattr,
+	.listxattr  = ramfs_listxattr,
+	.removexattr    = ramfs_removexattr,
 };
 
 static struct inode_operations ramfs_dir_inode_operations = {
@@ -169,6 +174,10 @@
 	.rmdir		= simple_rmdir,
 	.mknod		= ramfs_mknod,
 	.rename		= simple_rename,
+	.setxattr   = ramfs_setxattr,
+	.getxattr   = ramfs_getxattr,
+	.listxattr  = ramfs_listxattr,
+	.removexattr    = ramfs_removexattr,
 };
 
 static struct super_operations ramfs_ops = {
@@ -224,12 +233,17 @@
 
 static int __init init_ramfs_fs(void)
 {
+	int err = init_ramfs_xattr();
+	if (err)
+		return err;
+
 	return register_filesystem(&ramfs_fs_type);
 }
 
 static void __exit exit_ramfs_fs(void)
 {
 	unregister_filesystem(&ramfs_fs_type);
+	exit_ramfs_xattr();
 }
 
 module_init(init_ramfs_fs)
Index: mm/Makefile
===================================================================
RCS file: /cvsroot/selinux/nsa/linux-2.6/mm/Makefile,v
retrieving revision 1.1.1.4
diff -u -u -r1.1.1.4 Makefile
--- mm/Makefile	18 Jun 2004 19:31:02 -0000	1.1.1.4
+++ mm/Makefile	22 Aug 2004 14:06:12 -0000
@@ -15,3 +15,6 @@
 obj-$(CONFIG_SWAP)	+= page_io.o swap_state.o swapfile.o
 obj-$(CONFIG_HUGETLBFS)	+= hugetlb.o
 obj-$(CONFIG_NUMA) 	+= mempolicy.o
+
+obj-$(CONFIG_TMPFS_FS_XATTR)    += xattr.o
+obj-$(CONFIG_TMPFS_FS_SECURITY) += xattr_security.o
Index: mm/shmem.c
===================================================================
RCS file: /cvsroot/selinux/nsa/linux-2.6/mm/shmem.c,v
retrieving revision 1.1.1.8
diff -u -u -r1.1.1.8 shmem.c
--- mm/shmem.c	18 Jun 2004 19:31:03 -0000	1.1.1.8
+++ mm/shmem.c	22 Aug 2004 14:06:12 -0000
@@ -44,6 +44,8 @@
 #include <asm/div64.h>
 #include <asm/pgtable.h>
 
+#include "xattr.h"
+
 /* This magic number is used in glibc for posix shared memory */
 #define TMPFS_MAGIC	0x01021994
 
@@ -168,6 +170,8 @@
 static struct file_operations shmem_file_operations;
 static struct inode_operations shmem_inode_operations;
 static struct inode_operations shmem_dir_inode_operations;
+static struct inode_operations shmfs_special_inode_operations;
+static struct inode_operations shmem_symlink_inode_operations;
 static struct vm_operations_struct shmem_vm_ops;
 
 static struct backing_dev_info shmem_backing_dev_info = {
@@ -1212,6 +1216,7 @@
  		mpol_shared_policy_init(&info->policy);
 		switch (mode & S_IFMT) {
 		default:
+			inode->i_op = &shmfs_special_inode_operations;
 			init_special_inode(inode, mode, dev);
 			break;
 		case S_IFREG:
@@ -1229,6 +1234,7 @@
 			inode->i_fop = &simple_dir_operations;
 			break;
 		case S_IFLNK:
+			inode->i_op = &shmem_symlink_inode_operations;
 			break;
 		}
 	}
@@ -1261,7 +1267,6 @@
 
 #ifdef CONFIG_TMPFS
 
-static struct inode_operations shmem_symlink_inode_operations;
 static struct inode_operations shmem_symlink_inline_operations;
 
 /*
@@ -1715,12 +1720,33 @@
 static struct inode_operations shmem_symlink_inline_operations = {
 	.readlink	= shmem_readlink_inline,
 	.follow_link	= shmem_follow_link_inline,
+#ifdef CONFIG_TMPFS
+	.setxattr   = shmfs_setxattr,
+	.getxattr   = shmfs_getxattr,
+	.listxattr  = shmfs_listxattr,
+	.removexattr    = shmfs_removexattr,
+#endif
+};
+
+static struct inode_operations shmfs_special_inode_operations = {
+#ifdef CONFIG_TMPFS
+	.setxattr   = shmfs_setxattr,
+	.getxattr   = shmfs_getxattr,
+	.listxattr  = shmfs_listxattr,
+	.removexattr    = shmfs_removexattr,
+#endif
 };
 
 static struct inode_operations shmem_symlink_inode_operations = {
 	.truncate	= shmem_truncate,
 	.readlink	= shmem_readlink,
 	.follow_link	= shmem_follow_link,
+#ifdef CONFIG_TMPFS
+	.setxattr   = shmfs_setxattr,
+	.getxattr   = shmfs_getxattr,
+	.listxattr  = shmfs_listxattr,
+	.removexattr    = shmfs_removexattr,
+#endif
 };
 
 static int shmem_parse_options(char *options, int *mode, uid_t *uid, gid_t *gid, unsigned long *blocks, unsigned long *inodes)
@@ -1939,6 +1965,12 @@
 static struct inode_operations shmem_inode_operations = {
 	.truncate	= shmem_truncate,
 	.setattr	= shmem_notify_change,
+#ifdef CONFIG_TMPFS
+	.setxattr   = shmfs_setxattr,
+	.getxattr   = shmfs_getxattr,
+	.listxattr  = shmfs_listxattr,
+	.removexattr    = shmfs_removexattr,
+#endif
 };
 
 static struct inode_operations shmem_dir_inode_operations = {
@@ -1952,6 +1984,10 @@
 	.rmdir		= shmem_rmdir,
 	.mknod		= shmem_mknod,
 	.rename		= shmem_rename,
+	.setxattr   = shmfs_setxattr,
+	.getxattr   = shmfs_getxattr,
+	.listxattr  = shmfs_listxattr,
+	.removexattr    = shmfs_removexattr,
 #endif
 };
 
@@ -1993,6 +2029,9 @@
 static int __init init_tmpfs(void)
 {
 	int error;
+	int err = init_shmfs_xattr();
+	if (err)
+		return err;
 
 	error = init_inodecache();
 	if (error)
Index: security/selinux/hooks.c
===================================================================
RCS file: /cvsroot/selinux/nsa/linux-2.6/security/selinux/hooks.c,v
retrieving revision 1.15
diff -u -u -r1.15 hooks.c
--- security/selinux/hooks.c	27 Jul 2004 17:43:11 -0000	1.15
+++ security/selinux/hooks.c	22 Aug 2004 14:06:13 -0000
@@ -385,6 +385,14 @@
 				break;
 
 			case Opt_fscontext:
+				/* lkcl: allow fscontext on file systems with xattr
+				 *       in order to be able to mount an xattr-enabled tmpfs
+				 *       on /dev with a different fscontext.
+				 *       reason: shmfs and tmpfs are mapped to two types
+				 *       but we need a third (e.g. udevfs_t) in order to
+				 *       not interfere with / have-to-add-to either tmp_t
+				 *       or shmfs_t
+				 *
 				if (sbsec->behavior != SECURITY_FS_USE_XATTR) {
 					rc = -EINVAL;
 					printk(KERN_WARNING "SELinux:  "
@@ -392,6 +400,7 @@
 					       " this filesystem type\n");
 					goto out_free;
 				}
+				*/
 				if (seen & (Opt_context|Opt_fscontext)) {
 					rc = -EINVAL;
 					printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
-------------- next part --------------
Index: security/selinux/hooks.c
===================================================================
RCS file: /cvsroot/selinux/nsa/linux-2.6/security/selinux/hooks.c,v
retrieving revision 1.15
diff -u -u -r1.15 hooks.c
--- security/selinux/hooks.c	27 Jul 2004 17:43:11 -0000	1.15
+++ security/selinux/hooks.c	22 Aug 2004 14:01:46 -0000
@@ -385,6 +385,14 @@
 				break;
 
 			case Opt_fscontext:
+				/* lkcl: allow fscontext on file systems with xattr
+				 *       in order to be able to mount an xattr-enabled tmpfs
+				 *       on /dev with a different fscontext.
+				 *       reason: shmfs and tmpfs are mapped to two types
+				 *       but we need a third (e.g. udevfs_t) in order to
+				 *       not interfere with / have-to-add-to either tmp_t
+				 *       or shmfs_t
+				 *
 				if (sbsec->behavior != SECURITY_FS_USE_XATTR) {
 					rc = -EINVAL;
 					printk(KERN_WARNING "SELinux:  "
@@ -392,6 +400,7 @@
 					       " this filesystem type\n");
 					goto out_free;
 				}
+				*/
 				if (seen & (Opt_context|Opt_fscontext)) {
 					rc = -EINVAL;
 					printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
-------------- next part --------------
A non-text attachment was scrubbed...
Name: xattr.c
Type: text/x-csrc
Size: 4540 bytes
Desc: not available
URL: <http://listman.redhat.com/archives/fedora-selinux-list/attachments/20040822/606a2fe4/attachment.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: xattr_security.c
Type: text/x-csrc
Size: 971 bytes
Desc: not available
URL: <http://listman.redhat.com/archives/fedora-selinux-list/attachments/20040822/606a2fe4/attachment-0001.bin>
-------------- next part --------------
#!/bin/sh
#
# lkcl 2004aug08
#
# restore contexts on anything in /dev which has the default device_t
# file context.
#
# some things are meant to have device_t: hey, we set them too, makes
# no odds.
# 
# we pass all of the devs to restorecon on one line because restorecon
# caches the lookups of the filecontexts: doing a restorecon one at a
# time takes 1/4 sec per device/dir/symlink...

devs=''
#for x in `ls -altrZ /dev/ | grep -v initctl | grep device_t | grep -v "_device_t" | cut -c64-`; do
for x in `ls -altrZ /dev/ | grep device_t | grep -v "_device_t" | cut -c64-`; do
	echo $x
	devs="$devs /dev/$x"
done;
echo $devs
/sbin/restorecon $devs
-------------- next part --------------
--- udev-add.c.orig	2004-07-09 18:59:09.000000000 +0100
+++ udev-add.c	2004-08-03 16:21:59.000000000 +0100
@@ -50,6 +50,10 @@
 
 #define LOCAL_USER "$local"
 
+#ifdef WITH_SELINUX
+#include <selinux/selinux.h>
+#endif
+
 /* 
  * Right now the major/minor of a device is stored in a file called
  * "dev" in sysfs.
@@ -92,7 +96,31 @@
 			break;
 		*pos = 0x00;
 		if (stat(p, &stats)) {
+#ifdef WITH_SELINUX
+			int seretval = 0;
+			security_context_t scontext;
+		   if (is_selinux_enabled() > 0)
+		   {
+				seretval = matchpathcon(p, S_IFDIR, &scontext);
+				if (seretval < 0) {
+					dbg("matchpathcon(%s) failed\n", p);
+				} else {
+					seretval=setfscreatecon(scontext);
+					if (seretval < 0)
+						dbg("setfiles %s failed with error '%s'",
+					p, strerror(errno));
+				}
+			}
+#endif
 			retval = mkdir(p, 0755);
+#ifdef WITH_SELINUX
+			if (is_selinux_enabled() > 0)
+			{
+			   /* after mkdir, free the context */
+				freecon(scontext);
+			}
+#endif
+									
 			if (retval != 0) {
 				dbg("mkdir(%s) failed with error '%s'",
 				    p, strerror(errno));
@@ -109,6 +137,10 @@
 {
 	struct stat stats;
 	int retval = 0;
+	int seretval = 0;
+#ifdef WITH_SELINUX
+	security_context_t scontext;
+#endif
 
 	if (stat(file, &stats) != 0)
 		goto create;
@@ -117,6 +149,24 @@
 	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);
+#ifdef WITH_SELINUX
+		/* lkcl: maybe someone would like to do the same thing with se/linux
+		 * security contexts (check they are the same) but hey, not me!
+		 */
+	   if (is_selinux_enabled() > 0)
+	   {
+			retval = matchpathcon(file, mode, &scontext);
+			if (retval < 0) {
+				dbg("matchpathcon(%s) failed\n", file);
+			} else {
+				retval=setfilecon(scontext, file);
+				if (retval < 0)
+					dbg("setfiles %s failed with error '%s'",
+				file, strerror(errno));
+				freecon(scontext);
+			}
+		}
+#endif
 		goto perms;
 	}
 
@@ -126,6 +176,21 @@
 		dbg("already present file '%s' unlinked", file);
 
 create:
+#ifdef WITH_SELINUX
+   if (is_selinux_enabled() > 0)
+   {
+		seretval = matchpathcon(file, mode, &scontext);
+		if (seretval < 0) {
+			dbg("matchpathcon(%s) failed\n", file);
+		} else {
+			retval=setfscreatecon(scontext);
+			if (retval < 0)
+				dbg("setfiles %s failed with error '%s'",
+			file, strerror(errno));
+		}
+	}
+#endif
+						    
 	retval = mknod(file, mode, makedev(major, minor));
 	if (retval != 0) {
 		dbg("mknod(%s, %#o, %u, %u) failed with error '%s'",
@@ -133,6 +198,15 @@
 		goto exit;
 	}
 
+#ifdef WITH_SELINUX
+   if (is_selinux_enabled() > 0)
+   {
+	   /* after mknod, free the context */
+		if (seretval == 0)
+			freecon(scontext);
+	}
+#endif
+						    
 perms:
 	dbg("chmod(%s, %#o)", file, mode);
 	if (chmod(file, mode) != 0) {
@@ -150,7 +224,11 @@
 	}
 
 exit:
+#ifdef WITH_SELINUX
+	return retval < 0 ? retval : seretval;
+#else
 	return retval;
+#endif
 }
 
 /* get the local logged in user */
@@ -304,10 +382,36 @@
 
 		dbg("symlink(%s, %s)", linktarget, filename);
 		if (!fake) {
+#ifdef WITH_SELINUX
+			int seretval = 0;
+			security_context_t scontext;
+		   if (is_selinux_enabled() > 0)
+		   {
+				seretval = matchpathcon(filename, S_IFLNK, &scontext);
+				if (seretval < 0) {
+					dbg("matchpathcon(%s) failed\n", filename);
+				} else {
+					seretval=setfscreatecon(scontext);
+					if (seretval < 0)
+						dbg("setfiles %s failed with error '%s'",
+					filename, strerror(errno));
+				}
+			}
+#endif
+									
+
 			unlink(filename);
 			if (symlink(linktarget, filename) != 0)
 				dbg("symlink(%s, %s) failed with error '%s'",
 				    linktarget, filename, strerror(errno));
+#ifdef WITH_SELINUX
+		   if (is_selinux_enabled() > 0)
+		   {
+			   /* after symlink, free the context */
+				freecon(scontext);
+			}
+#endif
+									
 		}
 	}
 
@@ -403,6 +507,11 @@
 	char *pos;
 	int retval;
 
+#ifdef WITH_SELINUX
+	int seretval;
+	security_context_t prev_scontext;
+#endif
+
 	memset(&dev, 0x00, sizeof(dev));
 
 	dev.type = get_device_type(path, subsystem);
@@ -438,6 +547,23 @@
 
 	dbg("name='%s'", dev.name);
 
+#ifdef WITH_SELINUX
+	/* record the present security context, for file-creation
+	 * restoration creation purposes.
+	 *
+	 * we're going to assume that between now and the time that
+	 * this context is restored that the only filecreation of any
+	 * kind to occur will be mknod, symlink and mkdirs.
+	 */
+
+	if (is_selinux_enabled() > 0)
+	{
+		seretval = getfscreatecon(&prev_scontext);
+		if (seretval < 0) {
+			dbg("getfscreatecon failed\n");
+		}
+	}
+#endif
 	switch (dev.type) {
 	case 'b':
 	case 'c':
@@ -474,6 +600,16 @@
 		break;
 	}
 
+#ifdef WITH_SELINUX
+	if (is_selinux_enabled() > 0)
+	{
+	   /* reset the file create context to its former glory */
+		if (seretval == 0)
+			seretval=setfscreatecon(prev_scontext);
+		freecon(prev_scontext);
+	}
+#endif
+
 exit:
 	sysfs_close_class_device(class_dev);
 
--- Makefile.orig	2004-08-02 22:23:58.000000000 +0100
+++ Makefile	2004-08-02 22:24:01.000000000 +0100
@@ -25,6 +25,8 @@
 # Leave this set to `false' for production use.
 DEBUG = true
 
+# Set this to compile with Security-Enhanced Linux support.
+WITH_SELINUX = true
 
 ROOT =		udev
 DAEMON =	udevd
@@ -39,6 +41,7 @@
 LOCAL_CFG_DIR =	etc/udev
 HOTPLUG_EXEC =	$(ROOT)
 
+
 DESTDIR =
 
 KERNEL_DIR = /lib/modules/${shell uname -r}/build
@@ -172,6 +175,13 @@
 
 CFLAGS += -I$(PWD)/libsysfs
 
+ifeq ($(strip $(WITH_SELINUX)),true)
+	LIB_OBJS +=	\
+			-lselinux
+	CFLAGS += \
+		-DWITH_SELINUX
+endif
+
 all: $(ROOT) $(SENDER) $(DAEMON) $(INFO) $(TESTER) $(STARTER)
 	@extras="$(EXTRAS)" ; for target in $$extras ; do \
 		echo $$target ; \


More information about the fedora-selinux-list mailing list