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