[PATCH 3/9] Add a mode on the struct probe

Pavel Emelyanov
2008-03-05T17:42:34Z

The idea of the set is to make the dev_t to struct kobj map
be per-cgroup, and provide a permissions for this mapping.
This mode mask will operate with FMODE_xxx modes.

To achieve this, I add the mode_t mode on the struct probe,
which sets this mapping, and move the locked part of the
kobj_map() into a separate function, which also accepts the
mode to be set on the probe.

By default all the modes are provided for a map.

Signed-off-by: Pavel Emelyanov <xemul@openvz.org>

---
drivers/base/map.c | 31 ++++++++++++++++++++++++++-----
1 files changed, 26 insertions(+), 5 deletions(-)

diff --git a/drivers/base/map.c b/drivers/base/map.c
index 7de565f..c7e28a1 100644
--- a/drivers/base/map.c
+++ b/drivers/base/map.c
@@ -15,6 +15,7 @@
#include <linux/kdev_t.h>
#include <linux/kobject.h>
#include <linux/kobj_map.h>
+#include <linux/fs.h>

#define KOBJ_MAP_PROBES 255

@@ -22,6 +23,7 @@ struct kobj_map {
struct probe {
struct probe *next;
dev_t dev;
+ mode_t mode;
unsigned long range;
struct module *owner;
kobj_probe_t *get;
@@ -31,9 +33,9 @@ struct kobj_map {
struct mutex *lock;
};

-int kobj_map(struct kobj_map *domain, dev_t dev, unsigned long range,
- struct module *module, kobj_probe_t *probe,
- int (*lock)(dev_t, void *), void *data)
+static int __kobj_map(struct kobj_map *domain, dev_t dev, mode_t mode,
+ unsigned long range, struct module *module,
+ kobj_probe_t *probe, int (*lock)(dev_t, void *), void *data)
{
unsigned n = MAJOR(dev + range - 1) - MAJOR(dev) + 1;
unsigned index = MAJOR(dev);
@@ -55,8 +57,15 @@ int kobj_map(struct kobj_map *domain, dev_t dev, unsigned long range,
p->dev = dev;
p->range = range;
p->data = data;
+ /*
+ * When opening a device we want to (dis)allow only
+ * read or write. But sys_open() can provide more
+ * modes like lseek or pread. So, these FMODE-s are
+ * always 'on'.
+ */
+ p->mode = mode | FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE;
}
- mutex_lock(domain->lock);
+
for (i = 0, p -= n; i < n; i++, p++, index++) {
struct probe **s = &domain->probes[index % KOBJ_MAP_PROBES];
while (*s && (*s)->range < range)
@@ -64,10 +73,22 @@ int kobj_map(struct kobj_map *domain, dev_t dev, unsigned long range,
p->next = *s;
*s = p;
}
- mutex_unlock(domain->lock);
return 0;
}

+int kobj_map(struct kobj_map *domain, dev_t dev, unsigned long range,
+ struct module *module, kobj_probe_t *probe,
+ int (*lock)(dev_t, void *), void *data)
+{
+ int err;
+
+ mutex_lock(domain->lock);
+ err = __kobj_map(domain, dev, FMODE_READ | FMODE_WRITE, range,
+ module, probe, lock, data);
+ mutex_unlock(domain->lock);
+ return err;
+}
+
void kobj_unmap(struct kobj_map *domain, dev_t dev, unsigned long range)
{
unsigned n = MAJOR(dev + range - 1) - MAJOR(dev) + 1;
--
1.5.3.4