Skip to content

Commit 6d04d2b

Browse files
vimalagrawalgregkh
authored andcommitted
misc: misc_minor_alloc to use ida for all dynamic/misc dynamic minors
misc_minor_alloc was allocating id using ida for minor only in case of MISC_DYNAMIC_MINOR but misc_minor_free was always freeing ids using ida_free causing a mismatch and following warn: > > WARNING: CPU: 0 PID: 159 at lib/idr.c:525 ida_free+0x3e0/0x41f > > ida_free called for id=127 which is not allocated. > > <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ... > > [<60941eb4>] ida_free+0x3e0/0x41f > > [<605ac993>] misc_minor_free+0x3e/0xbc > > [<605acb82>] misc_deregister+0x171/0x1b3 misc_minor_alloc is changed to allocate id from ida for all minors falling in the range of dynamic/ misc dynamic minors Fixes: ab76079 ("char: misc: Increase the maximum number of dynamic misc devices to 1048448") Signed-off-by: Vimal Agrawal <vimal.agrawal@sophos.com> Reviewed-by: Dirk VanDerMerwe <dirk.vandermerwe@sophos.com> Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20241021133812.23703-1-vimal.agrawal@sophos.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 567a311 commit 6d04d2b

File tree

1 file changed

+30
-9
lines changed

1 file changed

+30
-9
lines changed

drivers/char/misc.c

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -63,16 +63,30 @@ static DEFINE_MUTEX(misc_mtx);
6363
#define DYNAMIC_MINORS 128 /* like dynamic majors */
6464
static DEFINE_IDA(misc_minors_ida);
6565

66-
static int misc_minor_alloc(void)
66+
static int misc_minor_alloc(int minor)
6767
{
68-
int ret;
69-
70-
ret = ida_alloc_max(&misc_minors_ida, DYNAMIC_MINORS - 1, GFP_KERNEL);
71-
if (ret >= 0) {
72-
ret = DYNAMIC_MINORS - ret - 1;
68+
int ret = 0;
69+
70+
if (minor == MISC_DYNAMIC_MINOR) {
71+
/* allocate free id */
72+
ret = ida_alloc_max(&misc_minors_ida, DYNAMIC_MINORS - 1, GFP_KERNEL);
73+
if (ret >= 0) {
74+
ret = DYNAMIC_MINORS - ret - 1;
75+
} else {
76+
ret = ida_alloc_range(&misc_minors_ida, MISC_DYNAMIC_MINOR + 1,
77+
MINORMASK, GFP_KERNEL);
78+
}
7379
} else {
74-
ret = ida_alloc_range(&misc_minors_ida, MISC_DYNAMIC_MINOR + 1,
75-
MINORMASK, GFP_KERNEL);
80+
/* specific minor, check if it is in dynamic or misc dynamic range */
81+
if (minor < DYNAMIC_MINORS) {
82+
minor = DYNAMIC_MINORS - minor - 1;
83+
ret = ida_alloc_range(&misc_minors_ida, minor, minor, GFP_KERNEL);
84+
} else if (minor > MISC_DYNAMIC_MINOR) {
85+
ret = ida_alloc_range(&misc_minors_ida, minor, minor, GFP_KERNEL);
86+
} else {
87+
/* case of non-dynamic minors, no need to allocate id */
88+
ret = 0;
89+
}
7690
}
7791
return ret;
7892
}
@@ -219,7 +233,7 @@ int misc_register(struct miscdevice *misc)
219233
mutex_lock(&misc_mtx);
220234

221235
if (is_dynamic) {
222-
int i = misc_minor_alloc();
236+
int i = misc_minor_alloc(misc->minor);
223237

224238
if (i < 0) {
225239
err = -EBUSY;
@@ -228,13 +242,20 @@ int misc_register(struct miscdevice *misc)
228242
misc->minor = i;
229243
} else {
230244
struct miscdevice *c;
245+
int i;
231246

232247
list_for_each_entry(c, &misc_list, list) {
233248
if (c->minor == misc->minor) {
234249
err = -EBUSY;
235250
goto out;
236251
}
237252
}
253+
254+
i = misc_minor_alloc(misc->minor);
255+
if (i < 0) {
256+
err = -EBUSY;
257+
goto out;
258+
}
238259
}
239260

240261
dev = MKDEV(MISC_MAJOR, misc->minor);

0 commit comments

Comments
 (0)