sysfs: Reject with a warning invalid uses of tagged directories.
authorEric W. Biederman <ebiederm@xmission.com>
Wed, 12 Oct 2011 22:02:43 +0000 (22:02 +0000)
committerDavid S. Miller <davem@davemloft.net>
Wed, 19 Oct 2011 23:24:16 +0000 (19:24 -0400)
sysfs is a core piece of ifrastructure that many people use and
few people have all of the rules in their head on how to use
it correctly.  Add warnings for people using tagged directories
improperly to that any misuses can be caught and diagnosed quickly.

A single inexpensive test in sysfs_find_dirent is almost sufficient
to catch all possible misuses.  An additional warning is needed
in sysfs_add_dirent so that we actually fail when attempting to
add an untagged dirent in a tagged directory.

Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
Acked-by: Greg Kroah-Hartman <gregkh@suse.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
fs/sysfs/dir.c
fs/sysfs/file.c

index 352d26d98c0a1c1daa5341a50fbb27d1379f1be2..26f370a9b5ce910d82aeed949aae46f04ba9327d 100644 (file)
@@ -384,6 +384,13 @@ int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
 {
        struct sysfs_inode_attrs *ps_iattr;
 
+       if (!!sysfs_ns_type(acxt->parent_sd) != !!sd->s_ns) {
+               WARN(1, KERN_WARNING "sysfs: ns %s in '%s' for '%s'\n",
+                       sysfs_ns_type(acxt->parent_sd)? "required": "invalid",
+                       acxt->parent_sd->s_name, sd->s_name);
+               return -EINVAL;
+       }
+
        if (sysfs_find_dirent(acxt->parent_sd, sd->s_ns, sd->s_name))
                return -EEXIST;
 
@@ -542,6 +549,13 @@ struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd,
 {
        struct sysfs_dirent *sd;
 
+       if (!!sysfs_ns_type(parent_sd) != !!ns) {
+               WARN(1, KERN_WARNING "sysfs: ns %s in '%s' for '%s'\n",
+                       sysfs_ns_type(parent_sd)? "required": "invalid",
+                       parent_sd->s_name, name);
+               return NULL;
+       }
+
        for (sd = parent_sd->s_dir.children; sd; sd = sd->s_sibling) {
                if (sd->s_ns != ns)
                        continue;
index 07c1b4ec00dfdba56768f3987ce6f642c0b80f53..d4e6080b4b2053fae16fd451d01b6b20f813906f 100644 (file)
@@ -466,9 +466,6 @@ void sysfs_notify(struct kobject *k, const char *dir, const char *attr)
        mutex_lock(&sysfs_mutex);
 
        if (sd && dir)
-               /* Only directories are tagged, so no need to pass
-                * a tag explicitly.
-                */
                sd = sysfs_find_dirent(sd, NULL, dir);
        if (sd && attr)
                sd = sysfs_find_dirent(sd, NULL, attr);