This patch fixes the behaviour of __register_chrdev_region.
Old implemention allowed registering a region which fully contains
an existing one. For example, if we made subseqent calls

  __register_chrdev_region(8,5,5,"a")
  __register_chrdev_region(8,0,15,"a")

both would have finished successfully, which is not supposed to happen.
---
 fs/char_dev.c | 18 ++++++------------
 1 file changed, 6 insertions(+), 12 deletions(-)

diff --git a/fs/char_dev.c b/fs/char_dev.c
index 687471d..93a28f2 100644
--- a/fs/char_dev.c
+++ b/fs/char_dev.c
@@ -118,19 +118,13 @@ __register_chrdev_region(unsigned int major, unsigned int 
baseminor,
 
        /* Check for overlapping minor ranges.  */
        if (*cp && (*cp)->major == major) {
-               int old_min = (*cp)->baseminor;
-               int old_max = (*cp)->baseminor + (*cp)->minorct - 1;
-               int new_min = baseminor;
-               int new_max = baseminor + minorct - 1;
+               int intersection_begin = max((*cp)->baseminor, baseminor);
+               int intersection_end = min(
+                       (*cp)->baseminor + (*cp)->minorct,
+                       baseminor + minorct);
 
-               /* New driver overlaps from the left.  */
-               if (new_max >= old_min && new_max <= old_max) {
-                       ret = -EBUSY;
-                       goto out;
-               }
-
-               /* New driver overlaps from the right.  */
-               if (new_min <= old_max && new_min >= old_min) {
+               /* Intersection is nonempty  */
+               if (intersection_begin < intersection_end) {
                        ret = -EBUSY;
                        goto out;
                }
-- 
2.9.0

Reply via email to