modules: increase MAXMODNAME and provide backward compat
With various firmware files used by graphics and wireless drivers we are exceeding the current 32 character module name (file path in kldxref) length. In order to overcome this issue bump it to the maximum path length for the next version. To be able to MFC provide backward compat support for another version of the struct as the offsets for the second half change due to the array size increase. MAXMODNAME being defined to MAXPATHLEN needs param.h to be included first. With only 7 modules (or LinuxKPI module.h) not doing that adjust them rather than including param.h in module.h [1]. Reported by: Greg V (greg unrelenting.technology) Sponsored by: The FreeBSD Foundation Suggested by: imp [1] MFC after: 10 days Reviewed by: imp (and others to different level) Differential Revision: https://reviews.freebsd.org/D32383
This commit is contained in:
parent
2cc5a480a6
commit
df38ada293
@ -33,6 +33,7 @@
|
|||||||
|
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <sys/param.h>
|
||||||
#include <sys/module.h>
|
#include <sys/module.h>
|
||||||
|
|
||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
|
@ -14,10 +14,10 @@
|
|||||||
__FBSDID("$FreeBSD$");
|
__FBSDID("$FreeBSD$");
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <sys/param.h> /* defines used in kernel.h and module.h */
|
||||||
#include <sys/module.h>
|
#include <sys/module.h>
|
||||||
#include <sys/systm.h> /* uprintf */
|
#include <sys/systm.h> /* uprintf */
|
||||||
#include <sys/errno.h>
|
#include <sys/errno.h>
|
||||||
#include <sys/param.h> /* defines used in kernel.h */
|
|
||||||
#include <sys/kernel.h> /* types used in module initialization */
|
#include <sys/kernel.h> /* types used in module initialization */
|
||||||
#include <sys/conf.h> /* cdevsw struct */
|
#include <sys/conf.h> /* cdevsw struct */
|
||||||
#include <sys/uio.h> /* uio struct */
|
#include <sys/uio.h> /* uio struct */
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
__FBSDID("$FreeBSD$");
|
__FBSDID("$FreeBSD$");
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <sys/param.h>
|
||||||
#include <sys/module.h>
|
#include <sys/module.h>
|
||||||
#include <dev/videomode/videomode.h>
|
#include <dev/videomode/videomode.h>
|
||||||
|
|
||||||
|
@ -64,6 +64,7 @@
|
|||||||
__FBSDID("$FreeBSD$");
|
__FBSDID("$FreeBSD$");
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <sys/param.h>
|
||||||
#include <sys/module.h>
|
#include <sys/module.h>
|
||||||
#include <sys/systm.h>
|
#include <sys/systm.h>
|
||||||
#include <sys/errno.h>
|
#include <sys/errno.h>
|
||||||
|
@ -64,6 +64,7 @@
|
|||||||
__FBSDID("$FreeBSD$");
|
__FBSDID("$FreeBSD$");
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <sys/param.h>
|
||||||
#include <sys/module.h>
|
#include <sys/module.h>
|
||||||
#include <sys/systm.h>
|
#include <sys/systm.h>
|
||||||
#include <sys/errno.h>
|
#include <sys/errno.h>
|
||||||
|
@ -64,6 +64,7 @@
|
|||||||
__FBSDID("$FreeBSD$");
|
__FBSDID("$FreeBSD$");
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <sys/param.h>
|
||||||
#include <sys/module.h>
|
#include <sys/module.h>
|
||||||
#include <sys/systm.h>
|
#include <sys/systm.h>
|
||||||
#include <sys/errno.h>
|
#include <sys/errno.h>
|
||||||
|
@ -361,11 +361,19 @@ sys_modfnext(struct thread *td, struct modfnext_args *uap)
|
|||||||
|
|
||||||
struct module_stat_v1 {
|
struct module_stat_v1 {
|
||||||
int version; /* set to sizeof(struct module_stat) */
|
int version; /* set to sizeof(struct module_stat) */
|
||||||
char name[MAXMODNAME];
|
char name[MAXMODNAMEV1V2];
|
||||||
int refs;
|
int refs;
|
||||||
int id;
|
int id;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct module_stat_v2 {
|
||||||
|
int version; /* set to sizeof(struct module_stat) */
|
||||||
|
char name[MAXMODNAMEV1V2];
|
||||||
|
int refs;
|
||||||
|
int id;
|
||||||
|
modspecific_t data;
|
||||||
|
};
|
||||||
|
|
||||||
int
|
int
|
||||||
sys_modstat(struct thread *td, struct modstat_args *uap)
|
sys_modstat(struct thread *td, struct modstat_args *uap)
|
||||||
{
|
{
|
||||||
@ -374,7 +382,9 @@ sys_modstat(struct thread *td, struct modstat_args *uap)
|
|||||||
int error = 0;
|
int error = 0;
|
||||||
int id, namelen, refs, version;
|
int id, namelen, refs, version;
|
||||||
struct module_stat *stat;
|
struct module_stat *stat;
|
||||||
|
struct module_stat_v2 *stat_v2;
|
||||||
char *name;
|
char *name;
|
||||||
|
bool is_v1v2;
|
||||||
|
|
||||||
MOD_SLOCK;
|
MOD_SLOCK;
|
||||||
mod = module_lookupbyid(uap->modid);
|
mod = module_lookupbyid(uap->modid);
|
||||||
@ -394,27 +404,44 @@ sys_modstat(struct thread *td, struct modstat_args *uap)
|
|||||||
*/
|
*/
|
||||||
if ((error = copyin(&stat->version, &version, sizeof(version))) != 0)
|
if ((error = copyin(&stat->version, &version, sizeof(version))) != 0)
|
||||||
return (error);
|
return (error);
|
||||||
if (version != sizeof(struct module_stat_v1)
|
is_v1v2 = (version == sizeof(struct module_stat_v1) ||
|
||||||
&& version != sizeof(struct module_stat))
|
version == sizeof(struct module_stat_v2));
|
||||||
|
if (!is_v1v2 && version != sizeof(struct module_stat))
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
namelen = strlen(mod->name) + 1;
|
namelen = strlen(mod->name) + 1;
|
||||||
if (namelen > MAXMODNAME)
|
if (is_v1v2 && namelen > MAXMODNAMEV1V2)
|
||||||
namelen = MAXMODNAME;
|
namelen = MAXMODNAMEV1V2;
|
||||||
|
else if (namelen > MAXMODNAMEV3)
|
||||||
|
namelen = MAXMODNAMEV3;
|
||||||
if ((error = copyout(name, &stat->name[0], namelen)) != 0)
|
if ((error = copyout(name, &stat->name[0], namelen)) != 0)
|
||||||
return (error);
|
return (error);
|
||||||
|
|
||||||
|
/* Extending MAXMODNAME gives an offset change for v3. */
|
||||||
|
if (is_v1v2) {
|
||||||
|
stat_v2 = (struct module_stat_v2 *)stat;
|
||||||
|
if ((error = copyout(&refs, &stat_v2->refs, sizeof(int))) != 0)
|
||||||
|
return (error);
|
||||||
|
if ((error = copyout(&id, &stat_v2->id, sizeof(int))) != 0)
|
||||||
|
return (error);
|
||||||
|
} else {
|
||||||
if ((error = copyout(&refs, &stat->refs, sizeof(int))) != 0)
|
if ((error = copyout(&refs, &stat->refs, sizeof(int))) != 0)
|
||||||
return (error);
|
return (error);
|
||||||
if ((error = copyout(&id, &stat->id, sizeof(int))) != 0)
|
if ((error = copyout(&id, &stat->id, sizeof(int))) != 0)
|
||||||
return (error);
|
return (error);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* >v1 stat includes module data.
|
* >v1 stat includes module data.
|
||||||
*/
|
*/
|
||||||
if (version == sizeof(struct module_stat))
|
if (version == sizeof(struct module_stat_v2)) {
|
||||||
|
if ((error = copyout(&data, &stat_v2->data,
|
||||||
|
sizeof(data))) != 0)
|
||||||
|
return (error);
|
||||||
|
} else if (version == sizeof(struct module_stat)) {
|
||||||
if ((error = copyout(&data, &stat->data,
|
if ((error = copyout(&data, &stat->data,
|
||||||
sizeof(data))) != 0)
|
sizeof(data))) != 0)
|
||||||
return (error);
|
return (error);
|
||||||
|
}
|
||||||
td->td_retval[0] = 0;
|
td->td_retval[0] = 0;
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
@ -423,7 +450,7 @@ int
|
|||||||
sys_modfind(struct thread *td, struct modfind_args *uap)
|
sys_modfind(struct thread *td, struct modfind_args *uap)
|
||||||
{
|
{
|
||||||
int error = 0;
|
int error = 0;
|
||||||
char name[MAXMODNAME];
|
char name[MAXMODNAMEV3];
|
||||||
module_t mod;
|
module_t mod;
|
||||||
|
|
||||||
if ((error = copyinstr(uap->name, name, sizeof name, 0)) != 0)
|
if ((error = copyinstr(uap->name, name, sizeof name, 0)) != 0)
|
||||||
@ -455,6 +482,14 @@ typedef union modspecific32 {
|
|||||||
uint32_t ulongval;
|
uint32_t ulongval;
|
||||||
} modspecific32_t;
|
} modspecific32_t;
|
||||||
|
|
||||||
|
struct module_stat32_v2 {
|
||||||
|
int version;
|
||||||
|
char name[MAXMODNAMEV1V2];
|
||||||
|
int refs;
|
||||||
|
int id;
|
||||||
|
modspecific32_t data;
|
||||||
|
};
|
||||||
|
|
||||||
struct module_stat32 {
|
struct module_stat32 {
|
||||||
int version;
|
int version;
|
||||||
char name[MAXMODNAME];
|
char name[MAXMODNAME];
|
||||||
@ -471,7 +506,9 @@ freebsd32_modstat(struct thread *td, struct freebsd32_modstat_args *uap)
|
|||||||
int error = 0;
|
int error = 0;
|
||||||
int id, namelen, refs, version;
|
int id, namelen, refs, version;
|
||||||
struct module_stat32 *stat32;
|
struct module_stat32 *stat32;
|
||||||
|
struct module_stat32_v2 *stat32_v2;
|
||||||
char *name;
|
char *name;
|
||||||
|
bool is_v1v2;
|
||||||
|
|
||||||
MOD_SLOCK;
|
MOD_SLOCK;
|
||||||
mod = module_lookupbyid(uap->modid);
|
mod = module_lookupbyid(uap->modid);
|
||||||
@ -492,27 +529,44 @@ freebsd32_modstat(struct thread *td, struct freebsd32_modstat_args *uap)
|
|||||||
|
|
||||||
if ((error = copyin(&stat32->version, &version, sizeof(version))) != 0)
|
if ((error = copyin(&stat32->version, &version, sizeof(version))) != 0)
|
||||||
return (error);
|
return (error);
|
||||||
if (version != sizeof(struct module_stat_v1)
|
is_v1v2 = (version == sizeof(struct module_stat_v1) ||
|
||||||
&& version != sizeof(struct module_stat32))
|
version == sizeof(struct module_stat32_v2));
|
||||||
|
if (!is_v1v2 && version != sizeof(struct module_stat32))
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
namelen = strlen(mod->name) + 1;
|
namelen = strlen(mod->name) + 1;
|
||||||
if (namelen > MAXMODNAME)
|
if (is_v1v2 && namelen > MAXMODNAMEV1V2)
|
||||||
namelen = MAXMODNAME;
|
namelen = MAXMODNAMEV1V2;
|
||||||
|
else if (namelen > MAXMODNAMEV3)
|
||||||
|
namelen = MAXMODNAMEV3;
|
||||||
if ((error = copyout(name, &stat32->name[0], namelen)) != 0)
|
if ((error = copyout(name, &stat32->name[0], namelen)) != 0)
|
||||||
return (error);
|
return (error);
|
||||||
|
|
||||||
|
/* Extending MAXMODNAME gives an offset change for v3. */
|
||||||
|
if (is_v1v2) {
|
||||||
|
stat32_v2 = (struct module_stat32_v2 *)stat32;
|
||||||
|
if ((error = copyout(&refs, &stat32_v2->refs, sizeof(int))) != 0)
|
||||||
|
return (error);
|
||||||
|
if ((error = copyout(&id, &stat32_v2->id, sizeof(int))) != 0)
|
||||||
|
return (error);
|
||||||
|
} else {
|
||||||
if ((error = copyout(&refs, &stat32->refs, sizeof(int))) != 0)
|
if ((error = copyout(&refs, &stat32->refs, sizeof(int))) != 0)
|
||||||
return (error);
|
return (error);
|
||||||
if ((error = copyout(&id, &stat32->id, sizeof(int))) != 0)
|
if ((error = copyout(&id, &stat32->id, sizeof(int))) != 0)
|
||||||
return (error);
|
return (error);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* >v1 stat includes module data.
|
* >v1 stat includes module data.
|
||||||
*/
|
*/
|
||||||
if (version == sizeof(struct module_stat32))
|
if (version == sizeof(struct module_stat32_v2)) {
|
||||||
|
if ((error = copyout(&data32, &stat32_v2->data,
|
||||||
|
sizeof(data32))) != 0)
|
||||||
|
return (error);
|
||||||
|
} else if (version == sizeof(struct module_stat32)) {
|
||||||
if ((error = copyout(&data32, &stat32->data,
|
if ((error = copyout(&data32, &stat32->data,
|
||||||
sizeof(data32))) != 0)
|
sizeof(data32))) != 0)
|
||||||
return (error);
|
return (error);
|
||||||
|
}
|
||||||
td->td_retval[0] = 0;
|
td->td_retval[0] = 0;
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
@ -253,7 +253,9 @@ extern int mod_debug;
|
|||||||
#endif
|
#endif
|
||||||
#endif /* _KERNEL */
|
#endif /* _KERNEL */
|
||||||
|
|
||||||
#define MAXMODNAME 32
|
#define MAXMODNAMEV1V2 32
|
||||||
|
#define MAXMODNAMEV3 MAXPATHLEN
|
||||||
|
#define MAXMODNAME MAXMODNAMEV3
|
||||||
|
|
||||||
struct module_stat {
|
struct module_stat {
|
||||||
int version; /* set to sizeof(struct module_stat) */
|
int version; /* set to sizeof(struct module_stat) */
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
__FBSDID("$FreeBSD$");
|
__FBSDID("$FreeBSD$");
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <sys/param.h>
|
||||||
#include <sys/sbuf.h>
|
#include <sys/sbuf.h>
|
||||||
#include <sys/module.h>
|
#include <sys/module.h>
|
||||||
#include <sys/systm.h>
|
#include <sys/systm.h>
|
||||||
|
Loading…
Reference in New Issue
Block a user