diff -Nru a/include/linux/module.h b/include/linux/module.h
--- a/include/linux/module.h	2004-10-20 10:16:28 -07:00
+++ b/include/linux/module.h	2004-10-20 10:16:28 -07:00
@@ -308,6 +308,12 @@
 	/* Fake kernel param for refcnt. */
 	struct kernel_param refcnt_param;
 #endif
+	struct kernel_param author_param;
+	struct kernel_param version_param;
+	struct kernel_param license_param;
+	char *author;
+	char *version;
+	char *license;
 
 #ifdef CONFIG_KALLSYMS
 	/* We keep the symbol and string tables for kallsyms. */
diff -Nru a/kernel/module.c b/kernel/module.c
--- a/kernel/module.c	2004-10-20 10:16:28 -07:00
+++ b/kernel/module.c	2004-10-20 10:16:28 -07:00
@@ -1094,6 +1094,25 @@
 	.store = module_attr_store,
 };
 
+#define MOD_SYSFS(field)	\
+static int field##_get_fn(char *buffer, struct kernel_param *kp)		\
+{										\
+	struct module *mod = container_of(kp, struct module, field##_param);	\
+	return sprintf(buffer, "%s", mod->field);				\
+}										\
+static int sysfs_##field##_setup(struct module *mod)				\
+{										\
+	if (!mod->field)							\
+		return 0;							\
+	mod->field##_param.name = __stringify(field);				\
+	mod->field##_param.perm = 0444;						\
+	mod->field##_param.get = field##_get_fn;				\
+	return add_attribute(mod, &mod->field##_param);				\
+}
+MOD_SYSFS(author);
+MOD_SYSFS(version);
+MOD_SYSFS(license);
+
 static void module_kobj_release(struct kobject *kobj)
 {
 	kfree(container_of(kobj, struct module_kobject, kobj));
@@ -1114,7 +1133,7 @@
 
 	/* We overallocate: not every param is in sysfs, and maybe no refcnt */
 	mod->mkobj = kmalloc(sizeof(*mod->mkobj)
-			     + sizeof(mod->mkobj->attr[0]) * (num_params+1),
+			     + sizeof(mod->mkobj->attr[0]) * (num_params+4),
 			     GFP_KERNEL);
 	if (!mod->mkobj)
 		return -ENOMEM;
@@ -1140,6 +1159,15 @@
 	err = sysfs_unload_setup(mod);
 	if (err)
 		goto out_unreg;
+	err = sysfs_author_setup(mod);
+	if (err)
+		goto out_unreg;
+	err = sysfs_version_setup(mod);
+	if (err)
+		goto out_unreg;
+	err = sysfs_license_setup(mod);
+	if (err)
+		goto out_unreg;
 	return 0;
 
 out_unreg:
@@ -1160,6 +1188,9 @@
 		sysfs_remove_file(&mod->mkobj->kobj,&mod->mkobj->attr[i].attr);
 	/* Calls module_kobj_release */
 	kobject_unregister(&mod->mkobj->kobj);
+	kfree(mod->author);
+	kfree(mod->license);
+	kfree(mod->version);
 }
 
 /* Free a module, remove from lists, etc (must hold module mutex). */
@@ -1346,11 +1377,25 @@
 		|| strcmp(license, "Dual MPL/GPL") == 0);
 }
 
+static char *strdup(const char *str)
+{
+	char *s;
+
+	if (!str)
+		return NULL;
+	s = kmalloc(strlen(str)+1, GFP_KERNEL);
+	if (!s)
+		return NULL;
+	strcpy(s, str);
+	return s;
+}
+
 static void set_license(struct module *mod, const char *license)
 {
 	if (!license)
 		license = "unspecified";
 
+	mod->license = strdup(license);
 	mod->license_gplok = license_is_gpl_compatible(license);
 	if (!mod->license_gplok && !(tainted & TAINT_PROPRIETARY_MODULE)) {
 		printk(KERN_WARNING "%s: module license '%s' taints kernel.\n",
@@ -1696,6 +1741,9 @@
 
 	/* Set up license info based on the info section */
 	set_license(mod, get_modinfo(sechdrs, infoindex, "license"));
+
+	mod->author = strdup(get_modinfo(sechdrs, infoindex, "author"));
+	mod->version = strdup(get_modinfo(sechdrs, infoindex, "version"));
 
 	/* Fix up syms, so that st_value is a pointer to location. */
 	err = simplify_symbols(sechdrs, symindex, strtab, versindex, pcpuindex,
