summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/audit.c216
-rw-r--r--kernel/auditfilter.c9
-rw-r--r--kernel/auditsc.c40
-rw-r--r--kernel/kmod.c120
-rw-r--r--kernel/module.c47
-rw-r--r--kernel/params.c29
-rw-r--r--kernel/printk.c2
7 files changed, 367 insertions, 96 deletions
diff --git a/kernel/audit.c b/kernel/audit.c
index d9b690ac684..76c9a11b72d 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -2,7 +2,7 @@
* Gateway between the kernel (e.g., selinux) and the user-space audit daemon.
* System-call specific features have moved to auditsc.c
*
- * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina.
+ * Copyright 2003-2007 Red Hat Inc., Durham, North Carolina.
* All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -65,7 +65,9 @@
* (Initialization happens after skb_init is called.) */
static int audit_initialized;
-/* No syscall auditing will take place unless audit_enabled != 0. */
+/* 0 - no auditing
+ * 1 - auditing enabled
+ * 2 - auditing enabled and configuration is locked/unchangeable. */
int audit_enabled;
/* Default state when kernel boots without any parameters. */
@@ -239,102 +241,150 @@ void audit_log_lost(const char *message)
static int audit_set_rate_limit(int limit, uid_t loginuid, u32 sid)
{
- int old = audit_rate_limit;
+ int res, rc = 0, old = audit_rate_limit;
+
+ /* check if we are locked */
+ if (audit_enabled == 2)
+ res = 0;
+ else
+ res = 1;
if (sid) {
char *ctx = NULL;
u32 len;
- int rc;
- if ((rc = selinux_sid_to_string(sid, &ctx, &len)))
- return rc;
- else
+ if ((rc = selinux_sid_to_string(sid, &ctx, &len)) == 0) {
audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
- "audit_rate_limit=%d old=%d by auid=%u subj=%s",
- limit, old, loginuid, ctx);
- kfree(ctx);
- } else
- audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
- "audit_rate_limit=%d old=%d by auid=%u",
- limit, old, loginuid);
- audit_rate_limit = limit;
- return 0;
+ "audit_rate_limit=%d old=%d by auid=%u"
+ " subj=%s res=%d",
+ limit, old, loginuid, ctx, res);
+ kfree(ctx);
+ } else
+ res = 0; /* Something weird, deny request */
+ }
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+ "audit_rate_limit=%d old=%d by auid=%u res=%d",
+ limit, old, loginuid, res);
+
+ /* If we are allowed, make the change */
+ if (res == 1)
+ audit_rate_limit = limit;
+ /* Not allowed, update reason */
+ else if (rc == 0)
+ rc = -EPERM;
+ return rc;
}
static int audit_set_backlog_limit(int limit, uid_t loginuid, u32 sid)
{
- int old = audit_backlog_limit;
+ int res, rc = 0, old = audit_backlog_limit;
+
+ /* check if we are locked */
+ if (audit_enabled == 2)
+ res = 0;
+ else
+ res = 1;
if (sid) {
char *ctx = NULL;
u32 len;
- int rc;
- if ((rc = selinux_sid_to_string(sid, &ctx, &len)))
- return rc;
- else
+ if ((rc = selinux_sid_to_string(sid, &ctx, &len)) == 0) {
audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
- "audit_backlog_limit=%d old=%d by auid=%u subj=%s",
- limit, old, loginuid, ctx);
- kfree(ctx);
- } else
- audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
- "audit_backlog_limit=%d old=%d by auid=%u",
- limit, old, loginuid);
- audit_backlog_limit = limit;
- return 0;
+ "audit_backlog_limit=%d old=%d by auid=%u"
+ " subj=%s res=%d",
+ limit, old, loginuid, ctx, res);
+ kfree(ctx);
+ } else
+ res = 0; /* Something weird, deny request */
+ }
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+ "audit_backlog_limit=%d old=%d by auid=%u res=%d",
+ limit, old, loginuid, res);
+
+ /* If we are allowed, make the change */
+ if (res == 1)
+ audit_backlog_limit = limit;
+ /* Not allowed, update reason */
+ else if (rc == 0)
+ rc = -EPERM;
+ return rc;
}
static int audit_set_enabled(int state, uid_t loginuid, u32 sid)
{
- int old = audit_enabled;
+ int res, rc = 0, old = audit_enabled;
- if (state != 0 && state != 1)
+ if (state < 0 || state > 2)
return -EINVAL;
+ /* check if we are locked */
+ if (audit_enabled == 2)
+ res = 0;
+ else
+ res = 1;
+
if (sid) {
char *ctx = NULL;
u32 len;
- int rc;
- if ((rc = selinux_sid_to_string(sid, &ctx, &len)))
- return rc;
- else
+ if ((rc = selinux_sid_to_string(sid, &ctx, &len)) == 0) {
audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
- "audit_enabled=%d old=%d by auid=%u subj=%s",
- state, old, loginuid, ctx);
- kfree(ctx);
- } else
- audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
- "audit_enabled=%d old=%d by auid=%u",
- state, old, loginuid);
- audit_enabled = state;
- return 0;
+ "audit_enabled=%d old=%d by auid=%u"
+ " subj=%s res=%d",
+ state, old, loginuid, ctx, res);
+ kfree(ctx);
+ } else
+ res = 0; /* Something weird, deny request */
+ }
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+ "audit_enabled=%d old=%d by auid=%u res=%d",
+ state, old, loginuid, res);
+
+ /* If we are allowed, make the change */
+ if (res == 1)
+ audit_enabled = state;
+ /* Not allowed, update reason */
+ else if (rc == 0)
+ rc = -EPERM;
+ return rc;
}
static int audit_set_failure(int state, uid_t loginuid, u32 sid)
{
- int old = audit_failure;
+ int res, rc = 0, old = audit_failure;
if (state != AUDIT_FAIL_SILENT
&& state != AUDIT_FAIL_PRINTK
&& state != AUDIT_FAIL_PANIC)
return -EINVAL;
+ /* check if we are locked */
+ if (audit_enabled == 2)
+ res = 0;
+ else
+ res = 1;
+
if (sid) {
char *ctx = NULL;
u32 len;
- int rc;
- if ((rc = selinux_sid_to_string(sid, &ctx, &len)))
- return rc;
- else
+ if ((rc = selinux_sid_to_string(sid, &ctx, &len)) == 0) {
audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
- "audit_failure=%d old=%d by auid=%u subj=%s",
- state, old, loginuid, ctx);
- kfree(ctx);
- } else
- audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
- "audit_failure=%d old=%d by auid=%u",
- state, old, loginuid);
- audit_failure = state;
- return 0;
+ "audit_failure=%d old=%d by auid=%u"
+ " subj=%s res=%d",
+ state, old, loginuid, ctx, res);
+ kfree(ctx);
+ } else
+ res = 0; /* Something weird, deny request */
+ }
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+ "audit_failure=%d old=%d by auid=%u res=%d",
+ state, old, loginuid, res);
+
+ /* If we are allowed, make the change */
+ if (res == 1)
+ audit_failure = state;
+ /* Not allowed, update reason */
+ else if (rc == 0)
+ rc = -EPERM;
+ return rc;
}
static int kauditd_thread(void *dummy)
@@ -599,6 +649,30 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
case AUDIT_DEL:
if (nlmsg_len(nlh) < sizeof(struct audit_rule))
return -EINVAL;
+ if (audit_enabled == 2) {
+ ab = audit_log_start(NULL, GFP_KERNEL,
+ AUDIT_CONFIG_CHANGE);
+ if (ab) {
+ audit_log_format(ab,
+ "pid=%d uid=%u auid=%u",
+ pid, uid, loginuid);
+ if (sid) {
+ if (selinux_sid_to_string(
+ sid, &ctx, &len)) {
+ audit_log_format(ab,
+ " ssid=%u", sid);
+ /* Maybe call audit_panic? */
+ } else
+ audit_log_format(ab,
+ " subj=%s", ctx);
+ kfree(ctx);
+ }
+ audit_log_format(ab, " audit_enabled=%d res=0",
+ audit_enabled);
+ audit_log_end(ab);
+ }
+ return -EPERM;
+ }
/* fallthrough */
case AUDIT_LIST:
err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid,
@@ -609,6 +683,30 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
case AUDIT_DEL_RULE:
if (nlmsg_len(nlh) < sizeof(struct audit_rule_data))
return -EINVAL;
+ if (audit_enabled == 2) {
+ ab = audit_log_start(NULL, GFP_KERNEL,
+ AUDIT_CONFIG_CHANGE);
+ if (ab) {
+ audit_log_format(ab,
+ "pid=%d uid=%u auid=%u",
+ pid, uid, loginuid);
+ if (sid) {
+ if (selinux_sid_to_string(
+ sid, &ctx, &len)) {
+ audit_log_format(ab,
+ " ssid=%u", sid);
+ /* Maybe call audit_panic? */
+ } else
+ audit_log_format(ab,
+ " subj=%s", ctx);
+ kfree(ctx);
+ }
+ audit_log_format(ab, " audit_enabled=%d res=0",
+ audit_enabled);
+ audit_log_end(ab);
+ }
+ return -EPERM;
+ }
/* fallthrough */
case AUDIT_LIST_RULES:
err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid,
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index 87865f8b4ce..3749193aed8 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -937,9 +937,10 @@ static void audit_update_watch(struct audit_parent *parent,
}
ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
- audit_log_format(ab, "audit updated rules specifying path=");
+ audit_log_format(ab, "op=updated rules specifying path=");
audit_log_untrustedstring(ab, owatch->path);
audit_log_format(ab, " with dev=%u ino=%lu\n", dev, ino);
+ audit_log_format(ab, " list=%d res=1", r->listnr);
audit_log_end(ab);
audit_remove_watch(owatch);
@@ -969,14 +970,14 @@ static void audit_remove_parent_watches(struct audit_parent *parent)
e = container_of(r, struct audit_entry, rule);
ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
- audit_log_format(ab, "audit implicitly removed rule path=");
+ audit_log_format(ab, "op=remove rule path=");
audit_log_untrustedstring(ab, w->path);
if (r->filterkey) {
audit_log_format(ab, " key=");
audit_log_untrustedstring(ab, r->filterkey);
} else
audit_log_format(ab, " key=(null)");
- audit_log_format(ab, " list=%d", r->listnr);
+ audit_log_format(ab, " list=%d res=1", r->listnr);
audit_log_end(ab);
list_del(&r->rlist);
@@ -1410,7 +1411,7 @@ static void audit_log_rule_change(uid_t loginuid, u32 sid, char *action,
audit_log_format(ab, " subj=%s", ctx);
kfree(ctx);
}
- audit_log_format(ab, " %s rule key=", action);
+ audit_log_format(ab, " op=%s rule key=", action);
if (rule->filterkey)
audit_log_untrustedstring(ab, rule->filterkey);
else
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 298897559ca..359955800dd 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -170,6 +170,11 @@ struct audit_aux_data_sockaddr {
char a[0];
};
+struct audit_aux_data_fd_pair {
+ struct audit_aux_data d;
+ int fd[2];
+};
+
struct audit_aux_data_path {
struct audit_aux_data d;
struct dentry *dentry;
@@ -961,6 +966,11 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
audit_log_d_path(ab, "path=", axi->dentry, axi->mnt);
break; }
+ case AUDIT_FD_PAIR: {
+ struct audit_aux_data_fd_pair *axs = (void *)aux;
+ audit_log_format(ab, "fd0=%d fd1=%d", axs->fd[0], axs->fd[1]);
+ break; }
+
}
audit_log_end(ab);
}
@@ -1815,6 +1825,36 @@ int audit_socketcall(int nargs, unsigned long *args)
}
/**
+ * __audit_fd_pair - record audit data for pipe and socketpair
+ * @fd1: the first file descriptor
+ * @fd2: the second file descriptor
+ *
+ * Returns 0 for success or NULL context or < 0 on error.
+ */
+int __audit_fd_pair(int fd1, int fd2)
+{
+ struct audit_context *context = current->audit_context;
+ struct audit_aux_data_fd_pair *ax;
+
+ if (likely(!context)) {
+ return 0;
+ }
+
+ ax = kmalloc(sizeof(*ax), GFP_KERNEL);
+ if (!ax) {
+ return -ENOMEM;
+ }
+
+ ax->fd[0] = fd1;
+ ax->fd[1] = fd2;
+
+ ax->d.type = AUDIT_FD_PAIR;
+ ax->d.next = context->aux;
+ context->aux = (void *)ax;
+ return 0;
+}
+
+/**
* audit_sockaddr - record audit data for sys_bind, sys_connect, sys_sendto
* @len: data length in user space
* @a: data address in kernel space
diff --git a/kernel/kmod.c b/kernel/kmod.c
index 796276141e5..9f923f8ce6a 100644
--- a/kernel/kmod.c
+++ b/kernel/kmod.c
@@ -36,6 +36,8 @@
#include <linux/resource.h>
#include <asm/uaccess.h>
+extern int delete_module(const char *name, unsigned int flags);
+
extern int max_threads;
static struct workqueue_struct *khelper_wq;
@@ -46,6 +48,7 @@ static struct workqueue_struct *khelper_wq;
modprobe_path is set via /proc/sys.
*/
char modprobe_path[KMOD_PATH_LEN] = "/sbin/modprobe";
+struct module_kobject kmod_mk;
/**
* request_module - try to load a kernel module
@@ -75,6 +78,11 @@ int request_module(const char *fmt, ...)
static atomic_t kmod_concurrent = ATOMIC_INIT(0);
#define MAX_KMOD_CONCURRENT 50 /* Completely arbitrary value - KAO */
static int kmod_loop_msg;
+ char modalias[16 + MODULE_NAME_LEN] = "MODALIAS=";
+ char *uevent_envp[2] = {
+ modalias,
+ NULL
+ };
va_start(args, fmt);
ret = vsnprintf(module_name, MODULE_NAME_LEN, fmt, args);
@@ -82,6 +90,12 @@ int request_module(const char *fmt, ...)
if (ret >= MODULE_NAME_LEN)
return -ENAMETOOLONG;
+ strcpy(&modalias[strlen("MODALIAS=")], module_name);
+ kobject_uevent_env(&kmod_mk.kobj, KOBJ_CHANGE, uevent_envp);
+
+ if (modprobe_path[0] == '\0')
+ goto out;
+
/* If modprobe needs a service that is in a module, we get a recursive
* loop. Limit the number of running kmod threads to max_threads/2 or
* MAX_KMOD_CONCURRENT, whichever is the smaller. A cleaner method
@@ -108,9 +122,115 @@ int request_module(const char *fmt, ...)
ret = call_usermodehelper(modprobe_path, argv, envp, 1);
atomic_dec(&kmod_concurrent);
+out:
return ret;
}
EXPORT_SYMBOL(request_module);
+
+static ssize_t store_mod_request(struct module_attribute *mattr,
+ struct module *mod,
+ const char *buffer, size_t count)
+{
+ char name[MODULE_NAME_LEN];
+ int ret;
+
+ if (count < 1 || count+1 > MODULE_NAME_LEN)
+ return -EINVAL;
+ memcpy(name, buffer, count);
+ name[count] = '\0';
+ if (name[count-1] == '\n')
+ name[count-1] = '\0';
+
+ ret = request_module(name);
+ if (ret < 0)
+ return ret;
+ return count;
+}
+
+static struct module_attribute mod_request = {
+ .attr = { .name = "mod_request", .mode = S_IWUSR, .owner = THIS_MODULE },
+ .store = store_mod_request,
+};
+
+#ifdef CONFIG_MODULE_UNLOAD
+static ssize_t store_mod_unload(struct module_attribute *mattr,
+ struct module *mod,
+ const char *buffer, size_t count)
+{
+ char name[MODULE_NAME_LEN];
+ int ret;
+
+ if (count < 1 || count+1 > MODULE_NAME_LEN)
+ return -EINVAL;
+ memcpy(name, buffer, count);
+ name[count] = '\0';
+ if (name[count-1] == '\n')
+ name[count-1] = '\0';
+
+ ret = delete_module(name, O_NONBLOCK);
+ if (ret < 0)
+ return ret;
+ return count;
+}
+
+static struct module_attribute mod_unload = {
+ .attr = { .name = "mod_unload", .mode = S_IWUSR, .owner = THIS_MODULE },
+ .store = store_mod_unload,
+};
+#endif
+
+static ssize_t show_mod_request_helper(struct module_attribute *mattr,
+ struct module *mod,
+ char *buffer)
+{
+ return sprintf(buffer, "%s\n", modprobe_path);
+}
+
+static ssize_t store_mod_request_helper(struct module_attribute *mattr,
+ struct module *mod,
+ const char *buffer, size_t count)
+{
+ if (count < 1 || count+1 > KMOD_PATH_LEN)
+ return -EINVAL;
+ memcpy(modprobe_path, buffer, count);
+ modprobe_path[count] = '\0';
+ if (modprobe_path[count-1] == '\n')
+ modprobe_path[count-1] = '\0';
+ return count;
+}
+
+static struct module_attribute mod_request_helper = {
+ .attr = {
+ .name = "mod_request_helper",
+ .mode = S_IWUSR | S_IRUGO,
+ .owner = THIS_MODULE
+ },
+ .show = show_mod_request_helper,
+ .store = store_mod_request_helper,
+};
+
+void __init kmod_sysfs_init(void)
+{
+ int ret;
+
+ kmod_mk.mod = THIS_MODULE;
+ kobj_set_kset_s(&kmod_mk, module_subsys);
+ kobject_set_name(&kmod_mk.kobj, "kmod");
+ kobject_init(&kmod_mk.kobj);
+ ret = kobject_add(&kmod_mk.kobj);
+ if (ret < 0)
+ goto out;
+
+ ret = sysfs_create_file(&kmod_mk.kobj, &mod_request_helper.attr);
+ ret = sysfs_create_file(&kmod_mk.kobj, &mod_request.attr);
+#ifdef CONFIG_MODULE_UNLOAD
+ ret = sysfs_create_file(&kmod_mk.kobj, &mod_unload.attr);
+#endif
+
+ kobject_uevent(&kmod_mk.kobj, KOBJ_ADD);
+out:
+ return;
+}
#endif /* CONFIG_KMOD */
struct subprocess_info {
diff --git a/kernel/module.c b/kernel/module.c
index 8a94e054230..8c25b1a04fa 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -653,20 +653,11 @@ static void wait_for_zero_refcount(struct module *mod)
mutex_lock(&module_mutex);
}
-asmlinkage long
-sys_delete_module(const char __user *name_user, unsigned int flags)
+int delete_module(const char *name, unsigned int flags)
{
struct module *mod;
- char name[MODULE_NAME_LEN];
int ret, forced = 0;
- if (!capable(CAP_SYS_MODULE))
- return -EPERM;
-
- if (strncpy_from_user(name, name_user, MODULE_NAME_LEN-1) < 0)
- return -EFAULT;
- name[MODULE_NAME_LEN-1] = '\0';
-
if (mutex_lock_interruptible(&module_mutex) != 0)
return -EINTR;
@@ -727,6 +718,21 @@ sys_delete_module(const char __user *name_user, unsigned int flags)
return ret;
}
+asmlinkage long
+sys_delete_module(const char __user *name_user, unsigned int flags)
+{
+ char name[MODULE_NAME_LEN];
+
+ if (!capable(CAP_SYS_MODULE))
+ return -EPERM;
+
+ if (strncpy_from_user(name, name_user, MODULE_NAME_LEN-1) < 0)
+ return -EFAULT;
+ name[MODULE_NAME_LEN-1] = '\0';
+
+ return delete_module(name, flags);
+}
+
static void print_unload_info(struct seq_file *m, struct module *mod)
{
struct module_use *use;
@@ -1068,7 +1074,8 @@ static inline void remove_sect_attrs(struct module *mod)
}
#endif /* CONFIG_KALLSYMS */
-static int module_add_modinfo_attrs(struct module *mod)
+#ifdef CONFIG_SYSFS
+int module_add_modinfo_attrs(struct module *mod)
{
struct module_attribute *attr;
struct module_attribute *temp_attr;
@@ -1094,7 +1101,7 @@ static int module_add_modinfo_attrs(struct module *mod)
return error;
}
-static void module_remove_modinfo_attrs(struct module *mod)
+void module_remove_modinfo_attrs(struct module *mod)
{
struct module_attribute *attr;
int i;
@@ -1109,8 +1116,10 @@ static void module_remove_modinfo_attrs(struct module *mod)
}
kfree(mod->modinfo_attrs);
}
+#endif
-static int mod_sysfs_init(struct module *mod)
+#ifdef CONFIG_SYSFS
+int mod_sysfs_init(struct module *mod)
{
int err;
@@ -1133,7 +1142,7 @@ out:
return err;
}
-static int mod_sysfs_setup(struct module *mod,
+int mod_sysfs_setup(struct module *mod,
struct kernel_param *kparam,
unsigned int num_params)
{
@@ -1169,16 +1178,14 @@ out_unreg:
out:
return err;
}
+#endif
static void mod_kobject_remove(struct module *mod)
{
module_remove_modinfo_attrs(mod);
module_param_sysfs_remove(mod);
- if (mod->mkobj.drivers_dir)
- kobject_unregister(mod->mkobj.drivers_dir);
- if (mod->holders_dir)
- kobject_unregister(mod->holders_dir);
-
+ kobject_unregister(mod->mkobj.drivers_dir);
+ kobject_unregister(mod->holders_dir);
kobject_unregister(&mod->mkobj.kobj);
}
@@ -2345,6 +2352,7 @@ void print_modules(void)
printk("\n");
}
+#ifdef CONFIG_SYSFS
static char *make_driver_name(struct device_driver *drv)
{
char *driver_name;
@@ -2419,6 +2427,7 @@ void module_remove_driver(struct device_driver *drv)
}
}
EXPORT_SYMBOL(module_remove_driver);
+#endif
#ifdef CONFIG_MODVERSIONS
/* Generate the signature for struct module here, too, for modversions. */
diff --git a/kernel/params.c b/kernel/params.c
index 553cf7d6a4b..7a751570b56 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -30,8 +30,6 @@
#define DEBUGP(fmt, a...)
#endif
-static struct kobj_type module_ktype;
-
static inline char dash2underscore(char c)
{
if (c == '-')
@@ -391,6 +389,7 @@ struct module_param_attrs
struct param_attribute attrs[0];
};
+#ifdef CONFIG_SYSFS
#define to_param_attr(n) container_of(n, struct param_attribute, mattr);
static ssize_t param_attr_show(struct module_attribute *mattr,
@@ -426,6 +425,7 @@ static ssize_t param_attr_store(struct module_attribute *mattr,
return len;
return err;
}
+#endif
#ifdef CONFIG_MODULES
#define __modinit
@@ -433,6 +433,7 @@ static ssize_t param_attr_store(struct module_attribute *mattr,
#define __modinit __init
#endif
+#ifdef CONFIG_SYSFS
/*
* param_sysfs_setup - setup sysfs support for one module or KBUILD_MODNAME
* @mk: struct module_kobject (contains parent kobject)
@@ -500,9 +501,7 @@ param_sysfs_setup(struct module_kobject *mk,
return mp;
}
-
#ifdef CONFIG_MODULES
-
/*
* module_param_sysfs_setup - setup sysfs support for one module
* @mod: module
@@ -625,7 +624,6 @@ static void __init param_sysfs_builtin(void)
/* module-related sysfs stuff */
-#ifdef CONFIG_SYSFS
#define to_module_attr(n) container_of(n, struct module_attribute, attr);
#define to_module_kobject(n) container_of(n, struct module_kobject, kobj);
@@ -673,6 +671,8 @@ static struct sysfs_ops module_sysfs_ops = {
.store = module_attr_store,
};
+static struct kobj_type module_ktype;
+
static int uevent_filter(struct kset *kset, struct kobject *kobj)
{
struct kobj_type *ktype = get_ktype(kobj);
@@ -686,19 +686,12 @@ static struct kset_uevent_ops module_uevent_ops = {
.filter = uevent_filter,
};
-#else
-static struct sysfs_ops module_sysfs_ops = {
- .show = NULL,
- .store = NULL,
-};
-#endif
+decl_subsys(module, &module_ktype, &module_uevent_ops);
static struct kobj_type module_ktype = {
.sysfs_ops = &module_sysfs_ops,
};
-decl_subsys(module, &module_ktype, &module_uevent_ops);
-
/*
* param_sysfs_init - wrapper for built-in params support
*/
@@ -714,11 +707,21 @@ static int __init param_sysfs_init(void)
}
param_sysfs_builtin();
+ kmod_sysfs_init();
return 0;
}
subsys_initcall(param_sysfs_init);
+#else
+#if 0
+static struct sysfs_ops module_sysfs_ops = {
+ .show = NULL,
+ .store = NULL,
+};
+#endif
+#endif
+
EXPORT_SYMBOL(param_set_byte);
EXPORT_SYMBOL(param_get_byte);
EXPORT_SYMBOL(param_set_short);
diff --git a/kernel/printk.c b/kernel/printk.c
index 0c151877ff7..4b47e59248d 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -54,7 +54,7 @@ int console_printk[4] = {
};
/*
- * Low lever drivers may need that to know if they can schedule in
+ * Low level drivers may need that to know if they can schedule in
* their unblank() callback or not. So let's export it.
*/
int oops_in_progress;