From pjones@redhat.com Sat Jun 25 09:19:56 2005
Subject: /sys/block/hda/sample.sh
From: Peter Jones <pjones@redhat.com>
To: gregkh@suse.de
Date: Sat, 25 Jun 2005 11:57:46 -0400
Message-Id: <1119715067.22239.1.camel@localhost.localdomain>

Greg, here's a patch.  I'm thinking maybe the selinux context should be
a config option or a sysctl, but if distros care it's easy to patch it
to the right thing or just replace it at runtime.

From: Peter Jones <pjones@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>


---
 drivers/base/class.c   |   34 ++++++++++++++++++++++++++++++++++
 drivers/block/genhd.c  |   25 +++++++++++++++++++++++++
 fs/partitions/check.c  |   27 +++++++++++++++++++++++++++
 include/linux/device.h |    1 +
 4 files changed, 87 insertions(+)

--- gregkh-2.6.orig/drivers/block/genhd.c	2005-08-17 09:53:44.000000000 -0700
+++ gregkh-2.6/drivers/block/genhd.c	2005-08-17 09:59:14.000000000 -0700
@@ -15,6 +15,7 @@
 #include <linux/kmod.h>
 #include <linux/kobj_map.h>
 #include <linux/buffer_head.h>
+#include <linux/mount.h>
 
 #define MAX_PROBE_HASH 255	/* random */
 
@@ -382,6 +383,25 @@ static ssize_t disk_stats_read(struct ge
 		jiffies_to_msecs(disk_stat_read(disk, io_ticks)),
 		jiffies_to_msecs(disk_stat_read(disk, time_in_queue)));
 }
+static ssize_t disk_sample_read(struct gendisk * disk, char *page)
+{
+	char buf[BDEVNAME_SIZE];
+	const char * context = "system_u:object_r:fixed_disk_device_t";
+	struct vfsmount *mnt;
+	int n;
+
+	n = sprintf(page, "#!/bin/sh\nmknod ");
+
+	mnt = do_kern_mount("selinuxfs", 0, "selinuxfs", NULL);
+	if (!IS_ERR(mnt)) {
+		mntput(mnt);
+		n += sprintf(page+n, "-Z %s ", context);
+	}
+	n += sprintf(page+n, "/dev/%s b %d %d\n", disk_name(disk, 0, buf),
+		disk->major, disk->first_minor);
+
+	return n;
+}
 static struct disk_attribute disk_attr_dev = {
 	.attr = {.name = "dev", .mode = S_IRUGO },
 	.show	= disk_dev_read
@@ -402,6 +422,10 @@ static struct disk_attribute disk_attr_s
 	.attr = {.name = "stat", .mode = S_IRUGO },
 	.show	= disk_stats_read
 };
+static struct disk_attribute disk_attr_sample = {
+	.attr = {.name = "sample.sh", .mode = S_IRUSR | S_IXUSR | S_IRUGO },
+	.show	= disk_sample_read
+};
 
 static struct attribute * default_attrs[] = {
 	&disk_attr_dev.attr,
@@ -409,6 +433,7 @@ static struct attribute * default_attrs[
 	&disk_attr_removable.attr,
 	&disk_attr_size.attr,
 	&disk_attr_stat.attr,
+	&disk_attr_sample.attr,
 	NULL,
 };
 
--- gregkh-2.6.orig/fs/partitions/check.c	2005-08-17 09:53:44.000000000 -0700
+++ gregkh-2.6/fs/partitions/check.c	2005-08-17 09:59:14.000000000 -0700
@@ -36,6 +36,8 @@
 #include "ultrix.h"
 #include "efi.h"
 
+#include <linux/mount.h>
+
 #ifdef CONFIG_BLK_DEV_MD
 extern void md_autodetect_dev(dev_t dev);
 #endif
@@ -229,6 +231,26 @@ static ssize_t part_stat_read(struct hd_
 		       p->reads, (unsigned long long)p->read_sectors,
 		       p->writes, (unsigned long long)p->write_sectors);
 }
+static ssize_t part_sample_read(struct hd_struct * p, char *page)
+{
+	struct gendisk *disk = container_of(p->kobj.parent,struct gendisk,kobj);
+	char buf[BDEVNAME_SIZE];
+	const char * context = "system_u:object_r:fixed_disk_device_t";
+	struct vfsmount *mnt;
+	int n;
+
+	n = sprintf(page, "#!/bin/sh\nmknod ");
+
+	mnt = do_kern_mount("selinuxfs", 0, "selinuxfs", NULL);
+	if (!IS_ERR(mnt)) {
+		mntput(mnt);
+		n += sprintf(page+n, "-Z %s ", context);
+	}
+	n += sprintf(page+n, "/dev/%s b %d %d\n", disk_name(disk, p->partno, buf),
+		disk->major, disk->first_minor + p->partno);
+
+	return n;
+}
 static struct part_attribute part_attr_dev = {
 	.attr = {.name = "dev", .mode = S_IRUGO },
 	.show	= part_dev_read
@@ -245,12 +267,17 @@ static struct part_attribute part_attr_s
 	.attr = {.name = "stat", .mode = S_IRUGO },
 	.show	= part_stat_read
 };
+static struct part_attribute part_attr_sample = {
+	.attr = {.name = "sample.sh", .mode = S_IRUSR | S_IXUSR | S_IRUGO },
+	.show	= part_sample_read
+};
 
 static struct attribute * default_attrs[] = {
 	&part_attr_dev.attr,
 	&part_attr_start.attr,
 	&part_attr_size.attr,
 	&part_attr_stat.attr,
+	&part_attr_sample.attr,
 	NULL,
 };
 
--- gregkh-2.6.orig/drivers/base/class.c	2005-08-17 09:59:12.000000000 -0700
+++ gregkh-2.6/drivers/base/class.c	2005-08-17 09:59:14.000000000 -0700
@@ -17,6 +17,7 @@
 #include <linux/string.h>
 #include <linux/kdev_t.h>
 #include <linux/err.h>
+#include <linux/mount.h>
 #include "base.h"
 
 #define to_class_attr(_attr) container_of(_attr, struct class_attribute, attr)
@@ -445,6 +446,24 @@ static ssize_t show_dev(struct class_dev
 	return print_dev_t(buf, class_dev->devt);
 }
 
+static ssize_t show_sample(struct class_device *class_dev, char *buf)
+{
+	const char * context = "system_u:object_r:fixed_disk_device_t";
+	struct vfsmount *mnt;
+	int n;
+
+	n = sprintf(buf, "#!/bin/sh\nmknod ");
+
+	mnt = do_kern_mount("selinuxfs", 0, "selinuxfs", NULL);
+	if (!IS_ERR(mnt)) {
+		mntput(mnt);
+		n += sprintf(buf+n, "-Z %s ", context);
+	}
+	n += sprintf(buf+n, "/dev/%s c %d %d\n", kobject_name(&class_dev->kobj),
+		     MAJOR(class_dev->devt), MINOR(class_dev->devt));
+
+	return n;
+}
 void class_device_initialize(struct class_device *class_dev)
 {
 	kobj_set_kset_s(class_dev, class_obj_subsys);
@@ -497,6 +516,21 @@ int class_device_add(struct class_device
 		attr->store = NULL;
 		class_device_create_file(class_dev, attr);
 		class_dev->devt_attr = attr;
+
+		attr = kmalloc(sizeof(*attr), GFP_KERNEL);
+		if (!attr) {
+			error = -ENOMEM;
+			kobject_del(&class_dev->kobj);
+			goto register_done;
+		}
+		memset(attr, sizeof(*attr), 0x00);
+		attr->attr.name = "sample.sh";
+		attr->attr.mode = S_IRUSR | S_IXUSR | S_IRUGO;
+		attr->attr.owner = parent->owner;
+		attr->show = show_sample;
+		attr->store = NULL;
+		class_device_create_file(class_dev, attr);
+		class_dev->sample_attr = attr;
 	}
 
 	class_device_add_attrs(class_dev);
--- gregkh-2.6.orig/include/linux/device.h	2005-08-17 09:53:44.000000000 -0700
+++ gregkh-2.6/include/linux/device.h	2005-08-17 09:59:14.000000000 -0700
@@ -198,6 +198,7 @@ struct class_device {
 	struct class		* class;	/* required */
 	dev_t			devt;		/* dev_t, creates the sysfs "dev" */
 	struct class_device_attribute *devt_attr;
+	struct class_device_attribute *sample_attr;
 	struct device		* dev;		/* not necessary, but nice to have */
 	void			* class_data;	/* class-specific data */