diff --git a/msr_allowlist.c b/msr_allowlist.c index fb5936a..ea1abbc 100644 --- a/msr_allowlist.c +++ b/msr_allowlist.c @@ -361,15 +361,25 @@ static int parse_next_allowlist_entry(char *inbuf, char **nextinbuf, struct allo return *nextinbuf - inbuf; } -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,39) -static char *msr_allowlist_nodename(struct device *dev, mode_t *mode) -#else -#if LINUX_VERSION_CODE <= KERNEL_VERSION(6,2,0) -static char *msr_allowlist_nodename(struct device *dev, umode_t *mode) -#else -static char *msr_allowlist_nodename(const struct device *dev, umode_t *mode) -#endif -#endif + +#define msr_allowlist_nodename_selector _Generic(\ + (((struct class *)0)->devnode),\ + char* (*) (struct device *, mode_t *) : msr_allowlist_nodename1,\ + char* (*) (struct device *, umode_t *) : msr_allowlist_nodename2,\ + char* (*) (const struct device *, umode_t *) : msr_allowlist_nodename3 \ + ) + +static char *msr_allowlist_nodename1(struct device *dev, mode_t *mode) +{ + return kasprintf(GFP_KERNEL, "cpu/msr_allowlist"); +} + +static char *msr_allowlist_nodename2(struct device *dev, umode_t *mode) +{ + return kasprintf(GFP_KERNEL, "cpu/msr_allowlist"); +} + +static char *msr_allowlist_nodename3(const struct device *dev, umode_t *mode) { return kasprintf(GFP_KERNEL, "cpu/msr_allowlist"); } @@ -429,7 +439,7 @@ int msr_allowlist_init(int *majordev) } cdev_class_created = 1; - cdev_class->devnode = msr_allowlist_nodename; + cdev_class->devnode = msr_allowlist_nodename_selector; dev = device_create(cdev_class, NULL, MKDEV(*majordev, 0), NULL, "msr_allowlist"); if (IS_ERR(dev)) diff --git a/msr_batch.c b/msr_batch.c index dd46c27..3fc4082 100644 --- a/msr_batch.c +++ b/msr_batch.c @@ -179,15 +179,24 @@ void msrbatch_cleanup(int majordev) } } -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,39) -static char *msrbatch_nodename(struct device *dev, mode_t *mode) -#else -#if LINUX_VERSION_CODE <= KERNEL_VERSION(6,2,0) -static char *msrbatch_nodename(struct device *dev, umode_t *mode) -#else -static char *msrbatch_nodename(const struct device *dev, umode_t *mode) -#endif -#endif +#define msrbatch_nodename_selector _Generic(\ + (((struct class *)0)->devnode),\ + char* (*) ( struct device *, mode_t *) : msrbatch_nodename1,\ + char* (*) ( struct device *, umode_t *) : msrbatch_nodename2,\ + char* (*) (const struct device *, umode_t *) : msrbatch_nodename3 \ + ) + +static char *msrbatch_nodename1(struct device *dev, mode_t *mode) +{ + return kasprintf(GFP_KERNEL, "cpu/msr_batch"); +} + +static char *msrbatch_nodename2(struct device *dev, umode_t *mode) +{ + return kasprintf(GFP_KERNEL, "cpu/msr_batch"); +} + +static char *msrbatch_nodename3(const struct device *dev, umode_t *mode) { return kasprintf(GFP_KERNEL, "cpu/msr_batch"); } @@ -223,7 +232,7 @@ int msrbatch_init(int *majordev) } cdev_class_created = 1; - cdev_class->devnode = msrbatch_nodename; + cdev_class->devnode = msrbatch_nodename_selector; dev = device_create(cdev_class, NULL, MKDEV(*majordev, 0), NULL, "msr_batch"); if (IS_ERR(dev)) diff --git a/msr_entry.c b/msr_entry.c index 9e16803..94e8d86 100644 --- a/msr_entry.c +++ b/msr_entry.c @@ -254,15 +254,30 @@ static struct notifier_block __refdata msr_class_cpu_notifier = }; #endif -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,39) -static char *msr_devnode(struct device *dev, mode_t *mode) -#else -#if LINUX_VERSION_CODE <= KERNEL_VERSION(6,2,0) -static char *msr_devnode(struct device *dev, umode_t *mode) -#else -static char *msr_devnode(const struct device *dev, umode_t *mode) -#endif -#endif +/* The type of (((struct class *)0)->devnode) has changed at least + * twice in the mainline linux kernel. Trying to pin these changes + * to specific mainline kernel versions runs into the problem of + * distros backporting features to older kernels. Instead, we are + * now keying off of the change in the parameter types.*/ + +#define msr_devnode_selector _Generic(\ + (((struct class *)0)->devnode),\ + char * (*) (struct device *, mode_t *) : msr_devnode1,\ + char * (*) (struct device *, umode_t *) : msr_devnode2,\ + char * (*) (const struct device *, umode_t *) : msr_devnode3\ + ) + +static char *msr_devnode1(struct device *dev, mode_t *mode) +{ + return kasprintf(GFP_KERNEL, "cpu/%u/msr_safe", MINOR(dev->devt)); +} + +static char *msr_devnode2(struct device *dev, umode_t *mode) +{ + return kasprintf(GFP_KERNEL, "cpu/%u/msr_safe", MINOR(dev->devt)); +} + +static char *msr_devnode3(const struct device *dev, umode_t *mode) { return kasprintf(GFP_KERNEL, "cpu/%u/msr_safe", MINOR(dev->devt)); } @@ -329,7 +344,7 @@ static int __init msr_init(void) err = PTR_ERR(msr_class); goto out_chrdev; } - msr_class->devnode = msr_devnode; + msr_class->devnode = msr_devnode_selector; #if LINUX_VERSION_CODE < KERNEL_VERSION(4,10,0) i = 0; diff --git a/msr_version.c b/msr_version.c index bee1832..13cc451 100644 --- a/msr_version.c +++ b/msr_version.c @@ -52,15 +52,32 @@ static const struct file_operations fops = .open = open_version }; -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,39) -static char *msr_version_nodename(struct device *dev, mode_t *mode) -#else -#if LINUX_VERSION_CODE <= KERNEL_VERSION(6,2,0) -static char *msr_version_nodename(struct device *dev, umode_t *mode) -#else -static char *msr_version_nodename(const struct device *dev, umode_t *mode) -#endif -#endif +#define msr_version_nodename_selector _Generic(\ + (((struct class *)0)->devnode),\ + char * (*) ( struct device *, mode_t *) : msr_version_nodename1,\ + char * (*) ( struct device *, umode_t *) : msr_version_nodename2,\ + char * (*) (const struct device *, umode_t *) : msr_version_nodename3 \ + ) + +static char *msr_version_nodename1(struct device *dev, mode_t *mode) +{ + if (mode) + { + *mode = 0400; // read-only + } + return kasprintf(GFP_KERNEL, "cpu/msr_safe_version"); +} + +static char *msr_version_nodename2(struct device *dev, umode_t *mode) +{ + if (mode) + { + *mode = 0400; // read-only + } + return kasprintf(GFP_KERNEL, "cpu/msr_safe_version"); +} + +static char *msr_version_nodename3(const struct device *dev, umode_t *mode) { if (mode) { @@ -122,7 +139,7 @@ int msr_version_init(int *majordev) } cdev_class_created = 1; - cdev_class->devnode = msr_version_nodename; + cdev_class->devnode = msr_version_nodename_selector; dev = device_create(cdev_class, NULL, MKDEV(*majordev, 0), NULL, "msr_safe_version"); if (IS_ERR(dev))